diff --git a/.gitattributes b/.gitattributes index f73cd591ab2..52407ec347b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -241,6 +241,7 @@ src/emu/cpu/m68000/m68kcpu.h svneol=native#text/plain src/emu/cpu/m68000/m68kdasm.c svneol=native#text/plain src/emu/cpu/m68000/m68kfpu.c svneol=native#text/plain src/emu/cpu/m68000/m68kmake.c svneol=native#text/plain +src/emu/cpu/m68000/m68kmmu.h svneol=native#text/plain src/emu/cpu/m6805/6805dasm.c svneol=native#text/plain src/emu/cpu/m6805/6805ops.c svneol=native#text/plain src/emu/cpu/m6805/m6805.c svneol=native#text/plain diff --git a/src/emu/cpu/m68000/m68000.h b/src/emu/cpu/m68000/m68000.h index a28cef1e56f..a8682feee46 100644 --- a/src/emu/cpu/m68000/m68000.h +++ b/src/emu/cpu/m68000/m68000.h @@ -76,6 +76,7 @@ CPU_GET_INFO( m68008 ); CPU_GET_INFO( m68010 ); CPU_GET_INFO( m68ec020 ); CPU_GET_INFO( m68020 ); +CPU_GET_INFO( m68020pmmu ); CPU_GET_INFO( m68ec030 ); CPU_GET_INFO( m68030 ); CPU_GET_INFO( m68ec040 ); @@ -88,6 +89,7 @@ CPU_GET_INFO( scc68070 ); #define CPU_M68010 CPU_GET_INFO_NAME( m68010 ) #define CPU_M68EC020 CPU_GET_INFO_NAME( m68ec020 ) #define CPU_M68020 CPU_GET_INFO_NAME( m68020 ) +#define CPU_M68020_68851 CPU_GET_INFO_NAME( m68020pmmu ) #define CPU_M68EC030 CPU_GET_INFO_NAME( m68ec030 ) #define CPU_M68030 CPU_GET_INFO_NAME( m68030 ) #define CPU_M68EC040 CPU_GET_INFO_NAME( m68ec040 ) diff --git a/src/emu/cpu/m68000/m68k_in.c b/src/emu/cpu/m68000/m68k_in.c index db5d58d45d9..6002804a24a 100644 --- a/src/emu/cpu/m68000/m68k_in.c +++ b/src/emu/cpu/m68000/m68k_in.c @@ -8014,8 +8014,82 @@ M68KMAKE_OP(pmove, 32, ., .) { modes = m68ki_read_imm_16(m68k); ea = M68KMAKE_GET_EA_AY_32; + + if ((modes & 0xfde0) == 0x2000) // PLOAD + { + logerror("680x0: unhandled PLOAD\n"); + return; + } + + if ((modes & 0xe200) == 0x2000) // PFLUSHA + { + logerror("680x0: unhandled PFLUSHA\n"); + return; + } + + switch ((modes>>13) & 0x7) + { + case 0: // MC68030/040 form with FD bit + case 2: // MC68881 form, FD never set + if (modes & 0x200) + { + logerror("680x0: PMOVE from MMU not supported\n"); + } + else + { + switch ((modes>>10) & 7) + { + case 0: // translation control register + m68k->mmu_tc = memory_read_word_32be(m68k->program, ea)<<16; + m68k->mmu_tc |= memory_read_word_32be(m68k->program, ea+2); + + if (m68k->mmu_tc & 0x80000000) + { + m68k->pmmu_enabled = 1; + } + else + { + m68k->pmmu_enabled = 0; + } + break; + + case 2: // supervisor root pointer + m68k->mmu_srp_limit = memory_read_word_32be(m68k->program, ea)<<16; + m68k->mmu_srp_limit |= memory_read_word_32be(m68k->program, ea+2); + m68k->mmu_srp_aptr = memory_read_word_32be(m68k->program, ea+4)<<16; + m68k->mmu_srp_aptr |= memory_read_word_32be(m68k->program, ea+6); + break; + + case 3: // CPU root pointer + m68k->mmu_crp_limit = memory_read_word_32be(m68k->program, ea)<<16; + m68k->mmu_crp_limit |= memory_read_word_32be(m68k->program, ea+2); + m68k->mmu_crp_aptr = memory_read_word_32be(m68k->program, ea+4)<<16; + m68k->mmu_crp_aptr |= memory_read_word_32be(m68k->program, ea+6); + break; + + default: + logerror("680x0: PMOVE to unknown MMU register %x\n", (modes>>10) & 7); + break; + } + } + break; + + case 3: // MC68030 to/from status reg + if (modes & 0x200) + { + memory_write_word_32be(m68k->program, ea, m68k->mmu_sr); + } + else + { + m68k->mmu_sr = memory_read_word_32be(m68k->program, ea); + } + break; + + default: + logerror("680x0: unknown PMOVE mode %x (modes %04x) (PC %x)\n", (modes>>13) & 0x7, modes, m68k->pc); + break; + } - logerror("680x0: unhandled PMOVE modes %x ea %x\n", modes, ea); } else { diff --git a/src/emu/cpu/m68000/m68kcpu.c b/src/emu/cpu/m68000/m68kcpu.c index ee25c763a80..8ca8f6cb5ce 100644 --- a/src/emu/cpu/m68000/m68kcpu.c +++ b/src/emu/cpu/m68000/m68kcpu.c @@ -5,7 +5,7 @@ #if 0 static const char copyright_notice[] = "MUSASHI\n" -"Version 4.10 (2009-09-27)\n" +"Version 4.5 (2009-10-09)\n" "A portable Motorola M680x0 processor emulation engine.\n" "Copyright Karl Stenerud. All rights reserved.\n" "\n" @@ -38,6 +38,8 @@ static const char copyright_notice[] = #include "m68kfpu.c" #include "debugger.h" +#include "m68kmmu.h" + extern void m68040_fpu_op0(m68ki_cpu_core *m68k); extern void m68040_fpu_op1(m68ki_cpu_core *m68k); @@ -611,6 +613,21 @@ static void m68k_postload(running_machine *machine, void *param) m68ki_jump(m68k, REG_PC); } +/* translate logical to physical addresses */ +static CPU_TRANSLATE( m68k ) +{ + m68ki_cpu_core *m68k = get_safe_token(device); + + /* only applies to the program address space and only does something if the MMU's enabled */ + if (m68k) + { + if ((space == ADDRESS_SPACE_PROGRAM) && (m68k->pmmu_enabled)) + { + *address = pmmu_translate_addr(m68k, *address); + } + } + return TRUE; +} /* Execute some instructions until we use up cycles clock cycles */ static CPU_EXECUTE( m68k ) @@ -718,6 +735,9 @@ static CPU_RESET( m68k ) { m68ki_cpu_core *m68k = get_safe_token(device); + /* Disable the PMMU on reset */ + m68k->pmmu_enabled = 0; + /* Clear all stop levels and eat up all remaining cycles */ m68k->stopped = 0; if (m68k->remaining_cycles > 0) @@ -890,6 +910,7 @@ static CPU_GET_INFO( m68k ) case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m68k); break; case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(m68k); break; case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(m68k); break; + case CPUINFO_FCT_TRANSLATE: info->translate = CPU_TRANSLATE_NAME(m68k); break; /* --- the following bits of info are returned as pointers --- */ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &m68k->remaining_cycles; break; @@ -898,7 +919,7 @@ static CPU_GET_INFO( m68k ) /* --- the following bits of info are returned as NULL-terminated strings --- */ case DEVINFO_STR_NAME: /* set per-core */ break; case DEVINFO_STR_FAMILY: strcpy(info->s, "Motorola 68K"); break; - case DEVINFO_STR_VERSION: strcpy(info->s, "4.00"); break; + case DEVINFO_STR_VERSION: strcpy(info->s, "4.50"); break; case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Karl Stenerud. All rights reserved. (2.1 fixes HJB)"); break; @@ -1062,7 +1083,139 @@ static const m68k_memory_interface interface_d32 = writelong_d32 }; +/* interface for 32-bit data bus with PMMU (68EC020, 68020) */ +static UINT8 read_byte_32_mmu(const address_space *space, offs_t address) +{ + m68ki_cpu_core *m68k = get_safe_token(space->cpu); + + if (m68k->pmmu_enabled) + { + address = pmmu_translate_addr(m68k, address); + } + return memory_read_byte_32be(space, address); +} + +static void write_byte_32_mmu(const address_space *space, offs_t address, UINT8 data) +{ + m68ki_cpu_core *m68k = get_safe_token(space->cpu); + + if (m68k->pmmu_enabled) + { + address = pmmu_translate_addr(m68k, address); + } + + memory_write_byte_32be(space, address, data); +} + +static UINT16 read_immediate_16_mmu(const address_space *space, offs_t address) +{ + m68ki_cpu_core *m68k = get_safe_token(space->cpu); + + if (m68k->pmmu_enabled) + { + address = pmmu_translate_addr(m68k, address); + } + + return memory_decrypted_read_word(space, (address) ^ m68k->memory.opcode_xor); +} + +/* potentially misaligned 16-bit reads with a 32-bit data bus (and 24-bit address bus) */ +static UINT16 readword_d32_mmu(const address_space *space, offs_t address) +{ + m68ki_cpu_core *m68k = get_safe_token(space->cpu); + UINT16 result; + + if (m68k->pmmu_enabled) + { + address = pmmu_translate_addr(m68k, address); + } + + if (!(address & 1)) + return memory_read_word_32be(space, address); + result = memory_read_byte_32be(space, address) << 8; + return result | memory_read_byte_32be(space, address + 1); +} + +/* potentially misaligned 16-bit writes with a 32-bit data bus (and 24-bit address bus) */ +static void writeword_d32_mmu(const address_space *space, offs_t address, UINT16 data) +{ + m68ki_cpu_core *m68k = get_safe_token(space->cpu); + + if (m68k->pmmu_enabled) + { + address = pmmu_translate_addr(m68k, address); + } + + if (!(address & 1)) + { + memory_write_word_32be(space, address, data); + return; + } + memory_write_byte_32be(space, address, data >> 8); + memory_write_byte_32be(space, address + 1, data); +} + +/* potentially misaligned 32-bit reads with a 32-bit data bus (and 24-bit address bus) */ +static UINT32 readlong_d32_mmu(const address_space *space, offs_t address) +{ + m68ki_cpu_core *m68k = get_safe_token(space->cpu); + UINT32 result; + + if (m68k->pmmu_enabled) + { + address = pmmu_translate_addr(m68k, address); + } + + if (!(address & 3)) + return memory_read_dword_32be(space, address); + else if (!(address & 1)) + { + result = memory_read_word_32be(space, address) << 16; + return result | memory_read_word_32be(space, address + 2); + } + result = memory_read_byte_32be(space, address) << 24; + result |= memory_read_word_32be(space, address + 1) << 8; + return result | memory_read_byte_32be(space, address + 3); +} + +/* potentially misaligned 32-bit writes with a 32-bit data bus (and 24-bit address bus) */ +static void writelong_d32_mmu(const address_space *space, offs_t address, UINT32 data) +{ + m68ki_cpu_core *m68k = get_safe_token(space->cpu); + + if (m68k->pmmu_enabled) + { + address = pmmu_translate_addr(m68k, address); + } + + if (!(address & 3)) + { + memory_write_dword_32be(space, address, data); + return; + } + else if (!(address & 1)) + { + memory_write_word_32be(space, address, data >> 16); + memory_write_word_32be(space, address + 2, data); + return; + } + memory_write_byte_32be(space, address, data >> 24); + memory_write_word_32be(space, address + 1, data >> 8); + memory_write_byte_32be(space, address + 3, data); +} + +static const m68k_memory_interface interface_d32_mmu = +{ + WORD_XOR_BE(0), + read_immediate_16_mmu, + read_byte_32_mmu, + readword_d32_mmu, + readlong_d32_mmu, + write_byte_32_mmu, + writeword_d32_mmu, + writelong_d32_mmu +}; void m68k_set_reset_callback(const device_config *device, m68k_reset_func callback) @@ -1301,6 +1454,30 @@ CPU_GET_INFO( m68020 ) } } +// 68020 with 68851 PMMU +static CPU_INIT( m68020pmmu ) +{ + m68ki_cpu_core *m68k = get_safe_token(device); + + CPU_INIT_CALL(m68020); + + m68k->has_pmmu = 1; + m68k->memory = interface_d32_mmu; +} + +CPU_GET_INFO( m68020pmmu ) +{ + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68020pmmu); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "68020, 68851"); break; + + default: CPU_GET_INFO_CALL(m68020); break; + } +} /**************************************************************************** * M680EC20 section @@ -1361,7 +1538,7 @@ static CPU_INIT( m68030 ) m68k->cpu_type = CPU_TYPE_030; m68k->state.subtypemask = m68k->cpu_type; m68k->dasm_type = M68K_CPU_TYPE_68030; - m68k->memory = interface_d32; + m68k->memory = interface_d32_mmu; m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ m68k->cyc_instruction = m68ki_cycles[3]; m68k->cyc_exception = m68ki_exception_cycle_table[3]; @@ -1480,7 +1657,7 @@ static CPU_INIT( m68040 ) m68k->cpu_type = CPU_TYPE_040; m68k->state.subtypemask = m68k->cpu_type; m68k->dasm_type = M68K_CPU_TYPE_68040; - m68k->memory = interface_d32; + m68k->memory = interface_d32_mmu; m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ m68k->cyc_instruction = m68ki_cycles[4]; m68k->cyc_exception = m68ki_exception_cycle_table[4]; @@ -1568,7 +1745,7 @@ static CPU_INIT( m68ec040 ) m68k->cyc_movem_l = 2; m68k->cyc_shift = 0; m68k->cyc_reset = 518; - m68k->has_pmmu = 1; + m68k->has_pmmu = 0; } CPU_GET_INFO( m68ec040 ) diff --git a/src/emu/cpu/m68000/m68kcpu.h b/src/emu/cpu/m68000/m68kcpu.h index d074569906d..6f8245b937c 100644 --- a/src/emu/cpu/m68000/m68kcpu.h +++ b/src/emu/cpu/m68000/m68kcpu.h @@ -3,7 +3,7 @@ /* ======================================================================== */ /* * MUSASHI - * Version 4.00 + * Version 4.50 * * A portable Motorola M680x0 processor emulation engine. * Copyright Karl Stenerud. All rights reserved. @@ -581,6 +581,7 @@ struct _m68ki_cpu_core UINT32 instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */ UINT32 run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */ int has_pmmu; /* Indicates if a PMMU available (yes on 030, 040, no on EC030) */ + int pmmu_enabled; /* Indicates if the PMMU is enabled */ /* Clocks required for instructions / exceptions */ UINT32 cyc_bcc_notake_b; @@ -635,6 +636,12 @@ struct _m68ki_cpu_core UINT16 save_sr; UINT8 save_stopped; UINT8 save_halted; + + /* PMMU registers */ + UINT32 mmu_crp_aptr, mmu_crp_limit; + UINT32 mmu_srp_aptr, mmu_srp_limit; + UINT32 mmu_tc; + UINT16 mmu_sr; }; diff --git a/src/emu/cpu/m68000/m68kdasm.c b/src/emu/cpu/m68000/m68kdasm.c index ecb77953ffd..de8f34ba652 100644 --- a/src/emu/cpu/m68000/m68kdasm.c +++ b/src/emu/cpu/m68000/m68kdasm.c @@ -3027,6 +3027,32 @@ static void d68030_pmove(void) // do this after fetching the second PMOVE word so we properly get the 3rd if necessary str = get_ea_mode_str_32(g_cpu_ir); + if ((modes & 0xfde0) == 0x2000) // PLOAD + { + if (modes & 0x0200) + { + sprintf(g_dasm_str, "pload #%d, %s", (modes>>10)&7, str); + } + else + { + sprintf(g_dasm_str, "pload %s, #%d", str, (modes>>10)&7); + } + return; + } + + if ((modes & 0xe200) == 0x2000) // PFLUSHA + { + if (modes & 0x0200) + { + sprintf(g_dasm_str, "pflush %s, %s", g_mmuregs[(modes>>10)&7], str); + } + else + { + sprintf(g_dasm_str, "pflush %s, %s", str, g_mmuregs[(modes>>10)&7]); + } + return; + } + switch ((modes>>13) & 0x7) { case 0: // MC68030/040 form with FD bit @@ -3803,7 +3829,7 @@ CPU_DISASSEMBLE( m68040 ) return m68k_disassemble_raw(buffer, pc, oprom, opram, M68K_CPU_TYPE_68040); } - +// f028 2215 0008 /* ======================================================================== */ /* ============================== END OF FILE ============================= */ diff --git a/src/emu/cpu/m68000/m68kmmu.h b/src/emu/cpu/m68000/m68kmmu.h new file mode 100644 index 00000000000..63db4faad95 --- /dev/null +++ b/src/emu/cpu/m68000/m68kmmu.h @@ -0,0 +1,180 @@ +/* + m68kmmu.h - PMMU implementation for 68851/68030/68040 + + By R. Belmont + + Copyright Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. +*/ + +/* + pmmu_translate_addr: perform 68851/68030-style PMMU address translation +*/ +INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in) +{ + UINT32 addr_out, tbl_entry, tbl_entry2, tamode, tbmode; + UINT32 root_aptr, root_limit, tofs, is, abits, bbits, cbits; + UINT32 resolved, tptr, shift; + + resolved = 0; + addr_out = addr_in; + + // if SRP is enabled and we're in supervisor mode, use it + if ((m68k->mmu_tc & 0x02000000) && (m68ki_get_sr(m68k) & 0x2000)) + { + root_aptr = m68k->mmu_srp_aptr; + root_limit = m68k->mmu_srp_limit; + } + else // else use the CRP + { + root_aptr = m68k->mmu_crp_aptr; + root_limit = m68k->mmu_crp_limit; + } + + // get initial shift (# of top bits to ignore) + is = (m68k->mmu_tc>>16) & 0xf; + abits = (m68k->mmu_tc>>12)&0xf; + bbits = (m68k->mmu_tc>>8)&0xf; + cbits = (m68k->mmu_tc>>4)&0xf; + +// logerror("PMMU: tcr %08x limit %08x aptr %08x is %x abits %d bbits %d cbits %d\n", m68k->mmu_tc, root_limit, root_aptr, is, abits, bbits, cbits); + + // get table A offset + tofs = (addr_in<>(32-abits); + + // find out what format table A is + switch (root_limit & 3) + { + case 0: // invalid, should cause MMU exception + case 1: // page descriptor, should cause direct mapping + fatalerror("680x0 PMMU: Unhandled root mode\n"); + break; + + case 2: // valid 4 byte descriptors + tofs *= 4; +// logerror("PMMU: reading table A entry at %08x\n", tofs + (root_aptr & 0xfffffffc)); + tbl_entry = memory_read_dword_32be(m68k->program, tofs + (root_aptr & 0xfffffffc)); + tamode = tbl_entry & 3; +// logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs); + break; + + case 3: // valid 8 byte descriptors + tofs *= 8; +// logerror("PMMU: reading table A entries at %08x\n", tofs + (root_aptr & 0xfffffffc)); + tbl_entry2 = memory_read_dword_32be(m68k->program, tofs + (root_aptr & 0xfffffffc)); + tbl_entry = memory_read_dword_32be(m68k->program, tofs + (root_aptr & 0xfffffffc)+4); + tamode = tbl_entry2 & 3; +// logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs); + break; + } + + // get table B offset and pointer + tofs = (addr_in<<(is+abits))>>(32-bbits); + tptr = tbl_entry & 0xfffffff0; + + // find out what format table B is, if any + switch (tamode) + { + case 0: // invalid, should cause MMU exception + fatalerror("680x0 PMMU: Unhandled Table A mode %d (addr_in %08x)\n", tamode, addr_in); + break; + + case 2: // 4-byte table B descriptor + tofs *= 4; +// logerror("PMMU: reading table B entry at %08x\n", tofs + tptr); + tbl_entry = memory_read_dword_32be(m68k->program, tofs + tptr); + tbmode = tbl_entry & 3; +// logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs); + break; + + case 3: // 8-byte table B descriptor + tofs *= 8; +// logerror("PMMU: reading table B entries at %08x\n", tofs + tptr); + tbl_entry2 = memory_read_dword_32be(m68k->program, tofs + tptr); + tbl_entry = memory_read_dword_32be(m68k->program, tofs + tptr + 4); + tbmode = tbl_entry2 & 3; +// logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs); + break; + + case 1: // early termination descriptor + tbl_entry &= 0xffffff00; + + shift = is+abits; + addr_out = ((addr_in<>shift) + tbl_entry; + resolved = 1; + break; + } + + // if table A wasn't early-out, continue to process table B + if (!resolved) + { + switch (tbmode) + { + case 0: // invalid, should cause MMU exception + case 2: // 4-byte table C descriptor + case 3: // 8-byte table C descriptor + fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x)\n", tbmode, addr_in); + break; + + case 1: // early termination descriptor + tbl_entry &= 0xffffff00; + + shift = is+abits+bbits; + addr_out = ((addr_in<>shift) + tbl_entry; + resolved = 1; + break; + } + } + +// if ((addr_in < 0x40000000) || (addr_in > 0x4fffffff)) printf("PMMU: [%08x] => [%08x]\n", addr_in, addr_out); + + return addr_out; +} + +/* + +maincpu at 40804366: called unimplemented instruction f000 (cpgen) +PMMU: tcr 80f05570 limit 7fff0003 aptr 043ffcc0 is 0 +PMMU: reading table A entries at 043ffce0 +PMMU: addr 4080438a entry 00000000 entry2 7ffffc18 mode 0 aofs 20 +680x0 PMMU: Unhandled Table A mode 0 + +enable, PS = f + +tblA @ 043ffcc0: + +043ffcc0 0001fc0a 043ffcb0 => 00000019 04000019 +043ffcc8 7ffffc18 00000000 +043ffcd0 7ffffc18 00000000 +043ffcd8 7ffffc18 00000000 +043ffce0 7ffffc18 00000000 +043ffce8 7ffffc18 00000000 +043ffcf0 7ffffc18 00000000 +043ffcf8 7ffffc18 00000000 +043ffd00 7ffffc19 40000000 +043ffd08 7ffffc19 48000000 +043ffd10 7ffffc59 50000000 +043ffd18 7ffffc59 58000000 +043ffd20 7ffffc59 60000000 +043ffd28 7ffffc59 68000000 +043ffd30 7ffffc59 70000000 +043ffd38 7ffffc59 78000000 +043ffd40 7ffffc59 80000000 +043ffd48 7ffffc59 88000000 +043ffd50 7ffffc59 90000000 +043ffd58 7ffffc59 98000000 +043ffd60 7ffffc59 a0000000 +043ffd68 7ffffc59 a8000000 +043ffd70 7ffffc59 b0000000 +043ffd78 7ffffc59 b8000000 +043ffd80 7ffffc59 c0000000 +043ffd88 7ffffc59 c8000000 +043ffd90 7ffffc59 d0000000 +043ffd98 7ffffc59 d8000000 +043ffda0 7ffffc59 e0000000 +043ffda8 7ffffc59 e8000000 +043ffdb0 7ffffc59 f0000000 +043ffdb8 7ffffc59 f8000000 + +*/ +