diff options
Diffstat (limited to 'src/devices/cpu/arm7')
-rw-r--r-- | src/devices/cpu/arm7/ap2010cpu.cpp | 45 | ||||
-rw-r--r-- | src/devices/cpu/arm7/ap2010cpu.h | 35 | ||||
-rw-r--r-- | src/devices/cpu/arm7/arm7.cpp | 1274 | ||||
-rw-r--r-- | src/devices/cpu/arm7/arm7.h | 282 | ||||
-rw-r--r-- | src/devices/cpu/arm7/arm7core.h | 129 | ||||
-rw-r--r-- | src/devices/cpu/arm7/arm7core.hxx | 14 | ||||
-rw-r--r-- | src/devices/cpu/arm7/arm7dasm.cpp | 1728 | ||||
-rw-r--r-- | src/devices/cpu/arm7/arm7dasm.h | 9 | ||||
-rw-r--r-- | src/devices/cpu/arm7/arm7drc.hxx | 102 | ||||
-rw-r--r-- | src/devices/cpu/arm7/arm7fe.hxx | 2 | ||||
-rw-r--r-- | src/devices/cpu/arm7/arm7help.h | 11 | ||||
-rw-r--r-- | src/devices/cpu/arm7/arm7ops.cpp | 309 | ||||
-rw-r--r-- | src/devices/cpu/arm7/arm7thmb.cpp | 49 | ||||
-rw-r--r-- | src/devices/cpu/arm7/cecalls.hxx | 1066 | ||||
-rw-r--r-- | src/devices/cpu/arm7/lpc210x.cpp | 66 | ||||
-rw-r--r-- | src/devices/cpu/arm7/lpc210x.h | 66 | ||||
-rw-r--r-- | src/devices/cpu/arm7/upd800468.cpp | 249 | ||||
-rw-r--r-- | src/devices/cpu/arm7/upd800468.h | 104 |
18 files changed, 3930 insertions, 1610 deletions
diff --git a/src/devices/cpu/arm7/ap2010cpu.cpp b/src/devices/cpu/arm7/ap2010cpu.cpp new file mode 100644 index 00000000000..0a2b1f97264 --- /dev/null +++ b/src/devices/cpu/arm7/ap2010cpu.cpp @@ -0,0 +1,45 @@ +// license:BSD-3-Clause +// copyright-holders:QUFB +/*************************************************************************** + + ARM7TDMI CPU component of the AP2010 LSI + +***************************************************************************/ + +#include "emu.h" +#include "ap2010cpu.h" + +#include "arm7core.h" + + +DEFINE_DEVICE_TYPE(AP2010CPU, ap2010cpu_device, "ap2010cpu", "AP2010 CPU") + +ap2010cpu_device::ap2010cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : arm7_cpu_device(mconfig, AP2010CPU, tag, owner, clock, 4, ARCHFLAG_T, ENDIANNESS_BIG) +{ } + +void ap2010cpu_device::add_hotspot(offs_t pc) +{ + if (m_hotspot_select < std::size(m_hotspot)) { + m_hotspot[m_hotspot_select] = pc; + m_hotspot_select++; + } +} + +void ap2010cpu_device::execute_run() +{ + for (size_t i = 0; i < ARM7_MAX_HOTSPOTS; i++) { + if (m_hotspot[i] == 0) { + break; + } + if (m_hotspot[i] == pc()) { + int32_t icount = *m_icountptr; + if (icount > 30) { + eat_cycles(icount - 30); + break; + } + } + } + + arm7_cpu_device::execute_run(); +} diff --git a/src/devices/cpu/arm7/ap2010cpu.h b/src/devices/cpu/arm7/ap2010cpu.h new file mode 100644 index 00000000000..3cf0a3c53dd --- /dev/null +++ b/src/devices/cpu/arm7/ap2010cpu.h @@ -0,0 +1,35 @@ +// license:BSD-3-Clause +// copyright-holders:QUFB +/*************************************************************************** + + ARM7TDMI CPU component of the AP2010 LSI + +***************************************************************************/ + +#ifndef MAME_CPU_ARM7_AP2010CPU_H +#define MAME_CPU_ARM7_AP2010CPU_H + +#pragma once + +#include "arm7.h" + +class ap2010cpu_device : public arm7_cpu_device +{ +public: + ap2010cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + void add_hotspot(offs_t pc); + +protected: + // device_execute_interface overrides + virtual void execute_run() override; + +private: + uint32_t m_hotspot_select = 0; + uint32_t m_hotspot[ARM7_MAX_HOTSPOTS]; +}; + +// device type definition +DECLARE_DEVICE_TYPE(AP2010CPU, ap2010cpu_device) + +#endif // MAME_CPU_ARM7_AP2010CPU_H diff --git a/src/devices/cpu/arm7/arm7.cpp b/src/devices/cpu/arm7/arm7.cpp index 4cf3b5fe351..46ffa46e41a 100644 --- a/src/devices/cpu/arm7/arm7.cpp +++ b/src/devices/cpu/arm7/arm7.cpp @@ -2,10 +2,10 @@ // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz /***************************************************************************** * - * arm7.c + * arm7.cpp * Portable CPU Emulator for 32-bit ARM v3/4/5/6 * - * Copyright Steve Ellenoff, all rights reserved. + * Copyright Steve Ellenoff * Thumb, DSP, and MMU support and many bugfixes by R. Belmont and Ryan Holtz. * * This work is based on: @@ -29,12 +29,33 @@ TODO: - Fix and finish the DRC code, or remove it entirely *****************************************************************************/ + #include "emu.h" -#include "debugger.h" #include "arm7.h" + #include "arm7core.h" //include arm7 core #include "arm7help.h" +#include "debug/debugcon.h" +#include "debugger.h" + +#include <cassert> + +#define LOG_MMU (1U << 1) +#define LOG_DSP (1U << 2) +#define LOG_COPRO_READS (1U << 3) +#define LOG_COPRO_WRITES (1U << 4) +#define LOG_COPRO_UNKNOWN (1U << 5) +#define LOG_COPRO_RESERVED (1U << 6) +#define LOG_TLB (1U << 7) +#define LOG_TLB_MISS (1U << 8) +#define LOG_PREFETCH (1U << 9) + +#define VERBOSE (0) // (LOG_COPRO_READS | LOG_COPRO_WRITES | LOG_COPRO_UNKNOWN | LOG_COPRO_RESERVED) +#include "logmacro.h" + +#define PRINT_HAPYFSH2 (0) +#define PRINT_CE_KERNEL (0) /* prototypes of coprocessor functions */ void arm7_dt_r_callback(arm_state *arm, uint32_t insn, uint32_t *prn, uint32_t (*read32)(arm_state *arm, uint32_t addr)); @@ -48,13 +69,17 @@ void (*arm7_coproc_dt_w_callback)(arm_state *arm, uint32_t insn, uint32_t *prn, DEFINE_DEVICE_TYPE(ARM7, arm7_cpu_device, "arm7_le", "ARM7 (little)") DEFINE_DEVICE_TYPE(ARM7_BE, arm7_be_cpu_device, "arm7_be", "ARM7 (big)") DEFINE_DEVICE_TYPE(ARM710A, arm710a_cpu_device, "arm710a", "ARM710a") +DEFINE_DEVICE_TYPE(ARM710T, arm710t_cpu_device, "arm710t", "ARM710T") DEFINE_DEVICE_TYPE(ARM7500, arm7500_cpu_device, "arm7500", "ARM7500") DEFINE_DEVICE_TYPE(ARM9, arm9_cpu_device, "arm9", "ARM9") DEFINE_DEVICE_TYPE(ARM920T, arm920t_cpu_device, "arm920t", "ARM920T") DEFINE_DEVICE_TYPE(ARM946ES, arm946es_cpu_device, "arm946es", "ARM946ES") DEFINE_DEVICE_TYPE(ARM11, arm11_cpu_device, "arm11", "ARM11") DEFINE_DEVICE_TYPE(ARM1176JZF_S, arm1176jzf_s_cpu_device, "arm1176jzf_s", "ARM1176JZF-S") +DEFINE_DEVICE_TYPE(PXA250, pxa250_cpu_device, "pxa250", "Intel XScale PXA250") DEFINE_DEVICE_TYPE(PXA255, pxa255_cpu_device, "pxa255", "Intel XScale PXA255") +DEFINE_DEVICE_TYPE(PXA270, pxa270_cpu_device, "pxa270", "Intel XScale PXA270") +DEFINE_DEVICE_TYPE(SA1100, sa1100_cpu_device, "sa1100", "Intel StrongARM SA-1100") DEFINE_DEVICE_TYPE(SA1110, sa1110_cpu_device, "sa1110", "Intel StrongARM SA-1110") DEFINE_DEVICE_TYPE(IGS036, igs036_cpu_device, "igs036", "IGS036") @@ -63,9 +88,17 @@ arm7_cpu_device::arm7_cpu_device(const machine_config &mconfig, const char *tag, { } -arm7_cpu_device::arm7_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint8_t archRev, uint32_t archFlags, endianness_t endianness) +arm7_cpu_device::arm7_cpu_device( + const machine_config &mconfig, + device_type type, + const char *tag, device_t *owner, + uint32_t clock, + uint8_t archRev, + uint32_t archFlags, + endianness_t endianness, + address_map_constructor internal_map) : cpu_device(mconfig, type, tag, owner, clock) - , m_program_config("program", endianness, 32, 32, 0) + , m_program_config("program", endianness, 32, 32, 0, internal_map) , m_prefetch_word0_shift(endianness == ENDIANNESS_LITTLE ? 0 : 16) , m_prefetch_word1_shift(endianness == ENDIANNESS_LITTLE ? 16 : 0) , m_endian(endianness) @@ -74,7 +107,7 @@ arm7_cpu_device::arm7_cpu_device(const machine_config &mconfig, device_type type , m_vectorbase(0) , m_pc(0) { - memset(m_r, 0x00, sizeof(m_r)); + std::fill(std::begin(m_r), std::end(m_r), 0); uint32_t arch = ARM9_COPRO_ID_ARCH_V4; if (m_archFlags & ARCHFLAG_T) arch = ARM9_COPRO_ID_ARCH_V4T; @@ -84,10 +117,17 @@ arm7_cpu_device::arm7_cpu_device(const machine_config &mconfig, device_type type // TODO[RH]: Default to 3-instruction prefetch for unknown ARM variants. Derived cores should set the appropriate value in their constructors. m_insn_prefetch_depth = 3; - memset(m_insn_prefetch_buffer, 0, sizeof(uint32_t) * 3); - memset(m_insn_prefetch_address, 0, sizeof(uint32_t) * 3); + std::fill_n(&m_insn_prefetch_buffer[0], 3, 0); + std::fill_n(&m_insn_prefetch_address[0], 3, 0); + std::fill_n(&m_insn_prefetch_valid[0], 3, false); m_insn_prefetch_count = 0; m_insn_prefetch_index = 0; + m_tlb_log = 0; + m_actual_log = 0; +} + +arm7_cpu_device::~arm7_cpu_device() +{ } @@ -106,6 +146,15 @@ arm710a_cpu_device::arm710a_cpu_device(const machine_config &mconfig, const char } +arm710t_cpu_device::arm710t_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : arm7_cpu_device(mconfig, ARM710T, tag, owner, clock, 4, ARCHFLAG_MODE26, ENDIANNESS_LITTLE) +{ + m_copro_id = ARM9_COPRO_ID_MFR_ARM + | ARM9_COPRO_ID_PART_ARM710 + | 0x00800000; +} + + arm7500_cpu_device::arm7500_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : arm7_cpu_device(mconfig, ARM7500, tag, owner, clock, 4, ARCHFLAG_MODE26, ENDIANNESS_LITTLE) { @@ -168,8 +217,8 @@ arm946es_cpu_device::arm946es_cpu_device(const machine_config &mconfig, device_t | ARM9_COPRO_ID_PART_ARM946 | ARM9_COPRO_ID_STEP_ARM946_A0; - memset(ITCM, 0, 0x8000); - memset(DTCM, 0, 0x4000); + std::fill_n(&ITCM[0], 0x8000, 0); + std::fill_n(&DTCM[0], 0x4000, 0); cp15_itcm_base = 0xffffffff; cp15_itcm_size = 0; @@ -215,16 +264,43 @@ igs036_cpu_device::igs036_cpu_device(const machine_config &mconfig, const char * { } +pxa250_cpu_device::pxa250_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : arm7_cpu_device(mconfig, PXA250, tag, owner, clock, 5, ARCHFLAG_T | ARCHFLAG_E | ARCHFLAG_XSCALE, ENDIANNESS_LITTLE) +{ + m_copro_id = ARM9_COPRO_ID_MFR_INTEL + | ARM9_COPRO_ID_ARCH_V5TE + | ARM9_COPRO_ID_PART_PXA250 + | ARM9_COPRO_ID_STEP_PXA255_A0; +} + pxa255_cpu_device::pxa255_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : arm7_cpu_device(mconfig, PXA255, tag, owner, clock, 5, ARCHFLAG_T | ARCHFLAG_E | ARCHFLAG_XSCALE, ENDIANNESS_LITTLE) { m_copro_id = ARM9_COPRO_ID_MFR_INTEL | ARM9_COPRO_ID_ARCH_V5TE - | ARM9_COPRO_ID_PXA255_CORE_GEN_XSCALE - | (3 << ARM9_COPRO_ID_PXA255_CORE_REV_SHIFT) + | ARM9_COPRO_ID_PART_PXA255 + | ARM9_COPRO_ID_STEP_PXA255_A0; +} + +pxa270_cpu_device::pxa270_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : arm7_cpu_device(mconfig, PXA270, tag, owner, clock, 5, ARCHFLAG_T | ARCHFLAG_E | ARCHFLAG_XSCALE, ENDIANNESS_LITTLE) +{ + m_copro_id = ARM9_COPRO_ID_MFR_INTEL + | ARM9_COPRO_ID_ARCH_V5TE + | ARM9_COPRO_ID_PART_PXA270 | ARM9_COPRO_ID_STEP_PXA255_A0; } +sa1100_cpu_device::sa1100_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : arm7_cpu_device(mconfig, SA1100, tag, owner, clock, 4, ARCHFLAG_SA, ENDIANNESS_LITTLE) + // has StrongARM, no Thumb, no Enhanced DSP +{ + m_copro_id = ARM9_COPRO_ID_MFR_DEC + | ARM9_COPRO_ID_ARCH_V4 + | ARM9_COPRO_ID_PART_SA1100 + | ARM9_COPRO_ID_STEP_SA1100_A; +} + sa1110_cpu_device::sa1110_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : arm7_cpu_device(mconfig, SA1110, tag, owner, clock, 4, ARCHFLAG_SA, ENDIANNESS_LITTLE) // has StrongARM, no Thumb, no Enhanced DSP @@ -232,7 +308,7 @@ sa1110_cpu_device::sa1110_cpu_device(const machine_config &mconfig, const char * m_copro_id = ARM9_COPRO_ID_MFR_INTEL | ARM9_COPRO_ID_ARCH_V4 | ARM9_COPRO_ID_PART_SA1110 - | ARM9_COPRO_ID_STEP_SA1110_A0; + | ARM9_COPRO_ID_STEP_SA1110_B4; } device_memory_interface::space_config_vector arm7_cpu_device::memory_space_config() const @@ -250,6 +326,7 @@ void arm7_cpu_device::update_reg_ptr() void arm7_cpu_device::set_cpsr(uint32_t val) { uint8_t old_mode = GET_CPSR & MODE_FLAG; + bool call_hook = false; if (m_archFlags & ARCHFLAG_MODE26) { if ((val & 0x10) != (m_r[eCPSR] & 0x10)) @@ -265,6 +342,7 @@ void arm7_cpu_device::set_cpsr(uint32_t val) // 32 -> 26 m_r[eR15] = (m_r[eR15] & 0x03FFFFFC) /* PC */ | (val & 0xF0000000) /* N Z C V */ | ((val & 0x000000C0) << (26 - 6)) /* I F */ | (val & 0x00000003) /* M1 M0 */; } + call_hook = true; } else { @@ -279,11 +357,17 @@ void arm7_cpu_device::set_cpsr(uint32_t val) { val |= 0x10; // force valid mode } + if ((val & T_MASK) != (m_r[eCPSR] & T_MASK)) + call_hook = true; m_r[eCPSR] = val; if ((GET_CPSR & MODE_FLAG) != old_mode) { + if ((GET_CPSR & MODE_FLAG) == eARM7_MODE_USER || old_mode == eARM7_MODE_USER) + call_hook = true; update_reg_ptr(); } + if (call_hook) + debugger_privilege_hook(); } @@ -306,7 +390,7 @@ enum // COARSE, desc_level1, vaddr -uint32_t arm7_cpu_device::arm7_tlb_get_second_level_descriptor( uint32_t granularity, uint32_t first_desc, uint32_t vaddr ) +uint32_t arm7_cpu_device::get_lvl2_desc_from_page_table( uint32_t granularity, uint32_t first_desc, uint32_t vaddr ) { uint32_t desc_lvl2 = vaddr; @@ -314,13 +398,17 @@ uint32_t arm7_cpu_device::arm7_tlb_get_second_level_descriptor( uint32_t granula { case TLB_COARSE: desc_lvl2 = (first_desc & COPRO_TLB_CFLD_ADDR_MASK) | ((vaddr & COPRO_TLB_VADDR_CSLTI_MASK) >> COPRO_TLB_VADDR_CSLTI_MASK_SHIFT); + if (m_tlb_log) + LOGMASKED(LOG_TLB, "%s: get_lvl2_desc_from_page_table: coarse descriptor, lvl2 address is %08x\n", machine().describe_context(), desc_lvl2); break; case TLB_FINE: desc_lvl2 = (first_desc & COPRO_TLB_FPTB_ADDR_MASK) | ((vaddr & COPRO_TLB_VADDR_FSLTI_MASK) >> COPRO_TLB_VADDR_FSLTI_MASK_SHIFT); + if (m_tlb_log) + LOGMASKED(LOG_TLB, "%s: get_lvl2_desc_from_page_table: fine descriptor, lvl2 address is %08x\n", machine().describe_context(), desc_lvl2); break; default: // We shouldn't be here - LOG( ( "ARM7: Attempting to get second-level TLB descriptor of invalid granularity (%d)\n", granularity ) ); + LOGMASKED(LOG_MMU, "ARM7: Attempting to get second-level TLB descriptor of invalid granularity (%d)\n", granularity); break; } @@ -403,182 +491,456 @@ int arm7_cpu_device::detect_fault(int desc_lvl1, int ap, int flags) return FAULT_NONE; } +arm7_cpu_device::tlb_entry *arm7_cpu_device::tlb_map_entry(const offs_t vaddr, const int flags) +{ + const uint32_t section = (vaddr >> (COPRO_TLB_VADDR_FLTI_MASK_SHIFT + 2)) & 0xFFF; + tlb_entry *entries = (flags & ARM7_TLB_ABORT_D) ? m_dtlb_entries : m_itlb_entries; + const uint32_t start = section << 1; + uint32_t index = (flags & ARM7_TLB_ABORT_D) ? m_dtlb_entry_index[section] : m_itlb_entry_index[section]; + + bool entry_found = false; + + for (uint32_t i = 0; i < 2; i++) + { + index = (index + 1) & 1; + if (!entries[start + index].valid) + { + entry_found = true; + break; + } + } + + if (!entry_found) + { + index = (index + 1) & 1; + } + + if (flags & ARM7_TLB_ABORT_D) + m_dtlb_entry_index[section] = index; + else + m_itlb_entry_index[section] = index; -bool arm7_cpu_device::arm7_tlb_translate(offs_t &addr, int flags, bool no_exception) + return &entries[start + index]; +} + +arm7_cpu_device::tlb_entry *arm7_cpu_device::tlb_probe(const offs_t vaddr, const int flags) { - if (addr < 0x2000000) + const uint32_t section = (vaddr >> (COPRO_TLB_VADDR_FLTI_MASK_SHIFT + 2)) & 0xFFF; + tlb_entry *entries = (flags & ARM7_TLB_ABORT_D) ? m_dtlb_entries : m_itlb_entries; + const uint32_t start = section << 1; + uint32_t index = (flags & ARM7_TLB_ABORT_D) ? m_dtlb_entry_index[section] : m_itlb_entry_index[section]; + + if (m_tlb_log) + LOGMASKED(LOG_TLB, "%s: tlb_probe: vaddr %08x, section %02x, start %02x, index %d\n", machine().describe_context(), vaddr, section, start, index); + + for (uint32_t i = 0; i < 2; i++) { - addr += m_pid_offset; + uint32_t position = start + index; + if (entries[position].valid) + { + switch (entries[position].type) + { + case COPRO_TLB_TYPE_SECTION: + if (entries[position].table_bits == (vaddr & COPRO_TLB_STABLE_MASK)) + return &entries[position]; + break; + case COPRO_TLB_TYPE_LARGE: + case COPRO_TLB_TYPE_SMALL: + if (entries[position].table_bits == (vaddr & COPRO_TLB_LSTABLE_MASK)) + return &entries[position]; + break; + case COPRO_TLB_TYPE_TINY: + if (entries[position].table_bits == (vaddr & COPRO_TLB_TTABLE_MASK)) + return &entries[position]; + break; + } + } + if (m_tlb_log) + { + LOGMASKED(LOG_TLB, "%s: tlb_probe: skipped due to mismatch (valid %d, domain %02x, access %d, table_bits %08x, base_addr %08x, type %d\n", + machine().describe_context(), entries[position].valid ? 1 : 0, entries[position].domain, entries[position].access, + entries[position].table_bits, entries[position].base_addr, entries[position].type); + } + + index = (index - 1) & 1; } - uint32_t desc_lvl1 = m_program->read_dword(m_tlb_base_mask | ((addr & COPRO_TLB_VADDR_FLTI_MASK) >> COPRO_TLB_VADDR_FLTI_MASK_SHIFT)); + return nullptr; +} -#if ARM7_MMU_ENABLE_HACK - if ((m_r[eR15] == (m_mmu_enable_addr + 4)) || (m_r[eR15] == (m_mmu_enable_addr + 8))) +uint32_t arm7_cpu_device::get_fault_from_permissions(const uint8_t access, const uint8_t domain, const uint8_t type, int flags) +{ + const uint8_t domain_bits = m_decoded_access_control[domain]; + switch (domain_bits) { - LOG( ( "ARM7: fetch flat, PC = %08x, vaddr = %08x\n", m_r[eR15], addr ) ); - return true; + case COPRO_DOMAIN_NO_ACCESS: + if (type == COPRO_TLB_TYPE_SECTION) + return (domain << 4) | COPRO_FAULT_DOMAIN_SECTION; + return (domain << 4) | COPRO_FAULT_DOMAIN_PAGE; + case COPRO_DOMAIN_CLIENT: + { + const uint32_t mode = GET_CPSR & 0xF; + switch (access) + { + case 0: // Check System/ROM bit + { + const uint32_t sr = (COPRO_CTRL >> COPRO_CTRL_SYSTEM_SHIFT) & 3; + switch (sr) + { + case 0: // No Access + if (type == COPRO_TLB_TYPE_SECTION) + return (domain << 4) | COPRO_FAULT_PERM_SECTION; + return (domain << 4) | COPRO_FAULT_PERM_PAGE; + case 1: // No User Access, Read-Only System Access + if (mode == 0 || (flags & ARM7_TLB_WRITE)) + { + if (type == COPRO_TLB_TYPE_SECTION) + return (domain << 4) | COPRO_FAULT_PERM_SECTION; + return (domain << 4) | COPRO_FAULT_PERM_PAGE; + } + return COPRO_FAULT_NONE; + case 2: // Read-Only Access + if (flags & ARM7_TLB_WRITE) + { + if (type == COPRO_TLB_TYPE_SECTION) + return (domain << 4) | COPRO_FAULT_PERM_SECTION; + return (domain << 4) | COPRO_FAULT_PERM_PAGE; + } + return COPRO_FAULT_NONE; + case 3: // Unpredictable Access + LOGMASKED(LOG_MMU, "%s: get_fault_from_permissions: Unpredictable access permissions (AP bits are 0, SR bits are 3).", machine().describe_context()); + return COPRO_FAULT_NONE; + } + return COPRO_FAULT_NONE; + } + case 1: // No User Access + if (mode != 0) + return COPRO_FAULT_NONE; + if (type == COPRO_TLB_TYPE_SECTION) + return (domain << 4) | COPRO_FAULT_PERM_SECTION; + return (domain << 4) | COPRO_FAULT_PERM_PAGE; + case 2: // Read-Only User Access + if (mode != 0 || (flags & ARM7_TLB_READ)) + return COPRO_FAULT_NONE; + if (type == COPRO_TLB_TYPE_SECTION) + return (domain << 4) | COPRO_FAULT_PERM_SECTION; + return (domain << 4) | COPRO_FAULT_PERM_PAGE; + case 3: // Full Access + return COPRO_FAULT_NONE; + } + return COPRO_FAULT_NONE; + } + case COPRO_DOMAIN_RESV: + LOGMASKED(LOG_MMU, "%s: get_fault_from_permissions: Domain type marked as Reserved.\n", machine().describe_context()); + return COPRO_FAULT_NONE; + default: + return COPRO_FAULT_NONE; } - else +} + +uint32_t arm7_cpu_device::tlb_check_permissions(tlb_entry *entry, const int flags) +{ + return get_fault_from_permissions(entry->access, entry->domain, entry->type, flags); +} + +offs_t arm7_cpu_device::tlb_translate(tlb_entry *entry, const offs_t vaddr) +{ + switch (entry->type) { - m_mmu_enable_addr = 1; + case COPRO_TLB_TYPE_SECTION: + return entry->base_addr | (vaddr & ~COPRO_TLB_SECTION_PAGE_MASK); + case COPRO_TLB_TYPE_LARGE: + return entry->base_addr | (vaddr & ~COPRO_TLB_LARGE_PAGE_MASK); + case COPRO_TLB_TYPE_SMALL: + return entry->base_addr | (vaddr & ~COPRO_TLB_SMALL_PAGE_MASK); + case COPRO_TLB_TYPE_TINY: + return entry->base_addr | (vaddr & ~COPRO_TLB_TINY_PAGE_MASK); + default: + return 0; } -#endif +} - uint8_t tlb_type = desc_lvl1 & 3; - if (tlb_type == COPRO_TLB_SECTION_TABLE) +bool arm7_cpu_device::page_table_finish_translation(offs_t &vaddr, const uint8_t type, const uint32_t lvl1, const uint32_t lvl2, const int flags, const uint32_t lvl1a, const uint32_t lvl2a) +{ + const uint8_t domain = (uint8_t)(lvl1 >> 5) & 0xF; + uint8_t access = 0; + uint32_t table_bits = 0; + switch (type) { - // Entry is a section - int fault = detect_fault(desc_lvl1, (desc_lvl1 >> 10) & 3, flags); - if (fault == FAULT_NONE) + case COPRO_TLB_TYPE_SECTION: + access = (uint8_t)((lvl2 >> 10) & 3); + table_bits = vaddr & COPRO_TLB_STABLE_MASK; + break; + case COPRO_TLB_TYPE_LARGE: { - addr = ( desc_lvl1 & COPRO_TLB_SECTION_PAGE_MASK ) | ( addr & ~COPRO_TLB_SECTION_PAGE_MASK ); + const uint8_t subpage_shift = 4 + (uint8_t)((vaddr >> 13) & 6); + access = (uint8_t)((lvl2 >> subpage_shift) & 3); + table_bits = vaddr & COPRO_TLB_LSTABLE_MASK; + break; } - else + + case COPRO_TLB_TYPE_SMALL: { - if (no_exception) - return false; + const uint8_t subpage_shift = 4 + (uint8_t)((vaddr >> 9) & 6); + access = (uint8_t)((lvl2 >> subpage_shift) & 3); + table_bits = vaddr & COPRO_TLB_LSTABLE_MASK; + break; + } + + case COPRO_TLB_TYPE_TINY: + access = (uint8_t)((lvl2 >> 4) & 3); + table_bits = vaddr & COPRO_TLB_TTABLE_MASK; + break; + } + + const uint32_t access_result = get_fault_from_permissions(access, domain, type, flags); + if (access_result != 0) + { + if (flags & ARM7_TLB_ABORT_P) + { + LOGMASKED(LOG_MMU, "ARM7: Page walk, Potential prefetch abort, vaddr = %08x, lvl1A = %08x, lvl1D = %08x, lvl2A = %08x, lvl2D = %08x\n", vaddr, lvl1a, lvl1, lvl2a, lvl2); + } + else if (flags & ARM7_TLB_ABORT_D) + { + LOGMASKED(LOG_MMU, "ARM7: Page walk, Data abort, vaddr = %08x, lvl1A = %08x, lvl1D = %08x, lvl2A = %08x, lvl2D = %08x\n", vaddr, lvl1a, lvl1, lvl2a, lvl2); + LOGMASKED(LOG_MMU, "access: %d, domain: %d, type: %d\n", access, domain, type); + m_faultStatus[0] = access_result; + m_faultAddress = vaddr; + m_pendingAbtD = true; + update_irq_state(); + } + return false; + } + static const uint32_t s_page_masks[4] = { COPRO_TLB_SECTION_PAGE_MASK, COPRO_TLB_LARGE_PAGE_MASK, COPRO_TLB_SMALL_PAGE_MASK, COPRO_TLB_TINY_PAGE_MASK }; + const uint32_t base_addr = lvl2 & s_page_masks[type]; + const uint32_t paddr = base_addr | (vaddr & ~s_page_masks[type]); + + if (flags) + { + tlb_entry *entry = tlb_map_entry(vaddr, flags); + + entry->valid = true; + entry->domain = domain; + entry->access = access; + entry->table_bits = table_bits; + entry->base_addr = base_addr; + entry->type = type; + } + + vaddr = paddr; + return true; +} + +bool arm7_cpu_device::page_table_translate(offs_t &vaddr, const int flags) +{ + const uint32_t lvl1_addr = m_tlb_base_mask | ((vaddr & COPRO_TLB_VADDR_FLTI_MASK) >> COPRO_TLB_VADDR_FLTI_MASK_SHIFT); + const uint32_t lvl1_desc = m_program->read_dword(lvl1_addr); + + LOGMASKED(LOG_MMU, "ARM7: Translating page table entry for %08x, lvl1_addr %08x, lvl1_desc %08x\n", vaddr, lvl1_addr, lvl1_desc); + + switch (lvl1_desc & 3) + { + case 0: // Unmapped + LOGMASKED(LOG_MMU, "ARM7: Translating page table entry for %08x, Unmapped, lvl1a %08x, lvl1d %08x\n", vaddr, lvl1_addr, lvl1_desc); if (flags & ARM7_TLB_ABORT_D) { - uint8_t domain = (desc_lvl1 >> 5) & 0xF; - LOG( ( "ARM7: Section Table, Section %s fault on virtual address, vaddr = %08x, PC = %08x\n", (fault == FAULT_DOMAIN) ? "domain" : "permission", addr, m_r[eR15] ) ); - m_faultStatus[0] = ((fault == FAULT_DOMAIN) ? (9 << 0) : (13 << 0)) | (domain << 4); // 9 = section domain fault, 13 = section permission fault - m_faultAddress = addr; + LOGMASKED(LOG_MMU, "ARM7: Page Table Translation failed (D), PC %08x, lvl1 unmapped, vaddr = %08x, lvl1A = %08x, lvl1D = %08x\n", m_r[eR15], vaddr, lvl1_addr, lvl1_desc); + m_faultStatus[0] = COPRO_FAULT_TRANSLATE_SECTION; + m_faultAddress = vaddr; m_pendingAbtD = true; update_irq_state(); - LOG( ( "vaddr %08X desc_lvl1 %08X domain %d permission %d ap %d s %d r %d mode %d read %d write %d\n", - addr, desc_lvl1, domain, (m_domainAccessControl >> ((desc_lvl1 >> 4) & 0x1e)) & 3, (desc_lvl1 >> 10) & 3, (m_control & COPRO_CTRL_SYSTEM) ? 1 : 0, (m_control & COPRO_CTRL_ROM) ? 1 : 0, - m_r[eCPSR] & MODE_FLAG, flags & ARM7_TLB_READ ? 1 : 0, flags & ARM7_TLB_WRITE ? 1 : 0) ); } else if (flags & ARM7_TLB_ABORT_P) { - LOG( ( "ARM7: Section Table, Section %s fault on virtual address, vaddr = %08x, PC = %08x\n", (fault == FAULT_DOMAIN) ? "domain" : "permission", addr, m_r[eR15] ) ); - m_pendingAbtP = true; - update_irq_state(); + LOGMASKED(LOG_MMU, "ARM7: Page Table Translation failed (P), PC %08x, lvl1 unmapped, vaddr = %08x, lvl1A = %08x, lvl1D = %08x\n", m_r[eR15], vaddr, lvl1_addr, lvl1_desc); + } + return false; + + case 1: // Coarse Table + { + const uint32_t lvl2_addr = (lvl1_desc & COPRO_TLB_CFLD_ADDR_MASK) | ((vaddr & COPRO_TLB_VADDR_CSLTI_MASK) >> COPRO_TLB_VADDR_CSLTI_MASK_SHIFT); + const uint32_t lvl2_desc = m_program->read_dword(lvl2_addr); + + LOGMASKED(LOG_MMU, "ARM7: Translating page table entry for %08x, Coarse, lvl1a %08x, lvl1d %08x, lvl2a %08x, lvl2d %08x\n", vaddr, lvl1_addr, lvl1_desc, lvl2_addr, lvl2_desc); + + switch (lvl2_desc & 3) + { + case 0: // Unmapped + if (flags & ARM7_TLB_ABORT_D) + { + LOGMASKED(LOG_MMU, "ARM7: Page Table Translation failed (D), coarse lvl2 unmapped, PC %08x, vaddr = %08x, lvl1A = %08x, lvl1D = %08x, lvl2A = %08x, lvl2D = %08x\n", m_r[eR15], vaddr, lvl1_addr, lvl1_desc, lvl2_addr, lvl2_desc); + m_faultStatus[0] = ((lvl1_desc >> 1) & 0xF0) | COPRO_FAULT_TRANSLATE_PAGE; + m_faultAddress = vaddr; + m_pendingAbtD = true; + update_irq_state(); + } + else if (flags & ARM7_TLB_ABORT_P) + { + LOGMASKED(LOG_MMU, "ARM7: Page Table Translation failed (P), coarse lvl2 unmapped, PC %08x, vaddr = %08x, lvl1A = %08x, lvl1D = %08x, lvl2A = %08x, lvl2D = %08x\n", m_r[eR15], vaddr, lvl1_addr, lvl1_desc, lvl2_addr, lvl2_desc); + } + return false; + + case 1: // Large Page + return page_table_finish_translation(vaddr, COPRO_TLB_TYPE_LARGE, lvl1_desc, lvl2_desc, flags, lvl1_addr, lvl2_addr); + + case 2: // Small Page + return page_table_finish_translation(vaddr, COPRO_TLB_TYPE_SMALL, lvl1_desc, lvl2_desc, flags, lvl1_addr, lvl2_addr); + + case 3: // Tiny Page (invalid) + LOGMASKED(LOG_MMU, "ARM7: Page Table Translation failed, tiny page present in coarse lvl2 table, PC %08x, vaddr = %08x, lvl1A = %08x, lvl1D = %08x, lvl2A = %08x, lvl2D = %08x\n", m_r[eR15], vaddr, lvl1_addr, lvl1_desc, lvl2_addr, lvl2_desc); + return false; + } + return false; + } + + case 2: // Section Descriptor + LOGMASKED(LOG_MMU, "ARM7: Translating page table entry for %08x, Section, lvl1a %08x, lvl1d %08x\n", vaddr, lvl1_addr, lvl1_desc); + return page_table_finish_translation(vaddr, COPRO_TLB_TYPE_SECTION, lvl1_desc, lvl1_desc, flags, lvl1_addr, lvl1_addr); + + case 3: // Fine Table + { + const uint32_t lvl2_addr = (lvl1_desc & COPRO_TLB_FPTB_ADDR_MASK) | ((vaddr & COPRO_TLB_VADDR_FSLTI_MASK) >> COPRO_TLB_VADDR_FSLTI_MASK_SHIFT); + const uint32_t lvl2_desc = m_program->read_dword(lvl2_addr); + + LOGMASKED(LOG_MMU, "ARM7: Translating page table entry for %08x, Fine, lvl1a %08x, lvl1d %08x, lvl2a %08x, lvl2d %08x\n", vaddr, lvl1_addr, lvl1_desc, lvl2_addr, lvl2_desc); + + switch (lvl2_desc & 3) + { + case 0: // Unmapped + if (flags & ARM7_TLB_ABORT_D) + { + LOGMASKED(LOG_MMU, "ARM7: Page Table Translation failed (D), fine lvl2 unmapped, PC %08x, vaddr = %08x, lvl1A = %08x, lvl1D = %08x, lvl2A = %08x, lvl2D = %08x\n", m_r[eR15], vaddr, lvl1_addr, lvl1_desc, lvl2_addr, lvl2_desc); + m_faultStatus[0] = ((lvl1_desc >> 1) & 0xF0) | COPRO_FAULT_TRANSLATE_PAGE; + m_faultAddress = vaddr; + m_pendingAbtD = true; + update_irq_state(); + } + else if (flags & ARM7_TLB_ABORT_P) + { + LOGMASKED(LOG_MMU, "ARM7: Page Table Translation failed (P), fine lvl2 unmapped, PC %08x, vaddr = %08x, lvl1A = %08x, lvl1D = %08x, lvl2A = %08x, lvl2D = %08x\n", m_r[eR15], vaddr, lvl1_addr, lvl1_desc, lvl2_addr, lvl2_desc); + } + return false; + + case 1: // Large Page + return page_table_finish_translation(vaddr, COPRO_TLB_TYPE_LARGE, lvl1_desc, lvl2_desc, flags, lvl1_addr, lvl2_addr); + + case 2: // Small Page + return page_table_finish_translation(vaddr, COPRO_TLB_TYPE_SMALL, lvl1_desc, lvl2_desc, flags, lvl1_addr, lvl2_addr); + + case 3: // Tiny Page + return page_table_finish_translation(vaddr, COPRO_TLB_TYPE_TINY, lvl1_desc, lvl2_desc, flags, lvl1_addr, lvl2_addr); } return false; } } - else if (tlb_type == COPRO_TLB_UNMAPPED) + + return false; +} + +bool arm7_cpu_device::translate_vaddr_to_paddr(offs_t &vaddr, const int flags) +{ + if (m_tlb_log) + LOGMASKED(LOG_TLB, "%s: translate_vaddr_to_paddr: vaddr %08x, flags %08x\n", machine().describe_context(), vaddr, flags); + + if (vaddr < 0x2000000) + { + vaddr += m_pid_offset; + if (m_tlb_log) + LOGMASKED(LOG_TLB, "%s: translate_vaddr_to_paddr: vaddr < 32M, adding PID (%08x) = %08x\n", machine().describe_context(), m_pid_offset, vaddr); + } + + tlb_entry *entry = tlb_probe(vaddr, flags); + + if (entry) { - if (no_exception) - return false; + if (m_tlb_log) + { + LOGMASKED(LOG_TLB, "%s: translate_vaddr_to_paddr: found entry (domain %02x, access %d, table_bits %08x, base_addr %08x, type %d\n", + machine().describe_context(), entry->domain, entry->access, entry->table_bits, entry->base_addr, entry->type); + } - // Unmapped, generate a translation fault - if (flags & ARM7_TLB_ABORT_D) + const uint32_t access_result = tlb_check_permissions(entry, flags); + if (access_result == 0) { - LOG( ( "ARM7: Translation fault on unmapped virtual address, PC = %08x, vaddr = %08x\n", m_r[eR15], addr ) ); - m_faultStatus[0] = (5 << 0); // 5 = section translation fault - m_faultAddress = addr; - m_pendingAbtD = true; - update_irq_state(); + vaddr = tlb_translate(entry, vaddr); + return true; } else if (flags & ARM7_TLB_ABORT_P) { - LOG( ( "ARM7: Translation fault on unmapped virtual address, PC = %08x, vaddr = %08x\n", m_r[eR15], addr ) ); - m_pendingAbtP = true; + LOGMASKED(LOG_MMU, "ARM7: TLB, Potential prefetch abort, vaddr = %08x\n", vaddr); + } + else if (flags & ARM7_TLB_ABORT_D) + { + LOGMASKED(LOG_MMU, "ARM7: TLB, Data abort, vaddr = %08x\n", vaddr); + m_faultStatus[0] = access_result; + m_faultAddress = vaddr; + m_pendingAbtD = true; update_irq_state(); } return false; } else { - // Entry is the physical address of a coarse second-level table - uint8_t permission = (m_domainAccessControl >> ((desc_lvl1 >> 4) & 0x1e)) & 3; - uint32_t desc_lvl2 = arm7_tlb_get_second_level_descriptor( (desc_lvl1 & 3) == COPRO_TLB_COARSE_TABLE ? TLB_COARSE : TLB_FINE, desc_lvl1, addr ); - if ((permission != 1) && (permission != 3)) - { - uint8_t domain = (desc_lvl1 >> 5) & 0xF; - fatalerror("ARM7: Not Yet Implemented: Coarse Table, Section Domain fault on virtual address, vaddr = %08x, domain = %08x, PC = %08x\n", addr, domain, m_r[eR15]); - } - - switch( desc_lvl2 & 3 ) - { - case COPRO_TLB_UNMAPPED: - if (no_exception) - return false; - - // Unmapped, generate a translation fault - if (flags & ARM7_TLB_ABORT_D) - { - uint8_t domain = (desc_lvl1 >> 5) & 0xF; - LOG( ( "ARM7: Translation fault on unmapped virtual address, vaddr = %08x, PC %08X\n", addr, m_r[eR15] ) ); - m_faultStatus[0] = (7 << 0) | (domain << 4); // 7 = page translation fault - m_faultAddress = addr; - m_pendingAbtD = true; - update_irq_state(); - } - else if (flags & ARM7_TLB_ABORT_P) - { - LOG( ( "ARM7: Translation fault on unmapped virtual address, vaddr = %08x, PC %08X\n", addr, m_r[eR15] ) ); - m_pendingAbtP = true; - update_irq_state(); - } - return false; - case COPRO_TLB_LARGE_PAGE: - // Large page descriptor - addr = ( desc_lvl2 & COPRO_TLB_LARGE_PAGE_MASK ) | ( addr & ~COPRO_TLB_LARGE_PAGE_MASK ); - break; - case COPRO_TLB_SMALL_PAGE: - // Small page descriptor - { - uint8_t ap = ((((desc_lvl2 >> 4) & 0xFF) >> (((addr >> 10) & 3) << 1)) & 3); - int fault = detect_fault(desc_lvl1, ap, flags); - if (fault == FAULT_NONE) - { - addr = ( desc_lvl2 & COPRO_TLB_SMALL_PAGE_MASK ) | ( addr & ~COPRO_TLB_SMALL_PAGE_MASK ); - } - else if (no_exception) - { - return false; - } - else - { - if (flags & ARM7_TLB_ABORT_D) - { - uint8_t domain = (desc_lvl1 >> 5) & 0xF; - // hapyfish expects a data abort when something tries to write to a read-only memory location from user mode - LOG( ( "ARM7: Page Table, Section %s fault on virtual address, vaddr = %08x, PC = %08x\n", (fault == FAULT_DOMAIN) ? "domain" : "permission", addr, m_r[eR15] ) ); - m_faultStatus[0] = ((fault == FAULT_DOMAIN) ? (11 << 0) : (15 << 0)) | (domain << 4); // 11 = page domain fault, 15 = page permission fault - m_faultAddress = addr; - m_pendingAbtD = true; - update_irq_state(); - LOG( ( "vaddr %08X desc_lvl2 %08X domain %d permission %d ap %d s %d r %d mode %d read %d write %d\n", - addr, desc_lvl2, domain, permission, ap, (m_control & COPRO_CTRL_SYSTEM) ? 1 : 0, (m_control & COPRO_CTRL_ROM) ? 1 : 0, - m_r[eCPSR] & MODE_FLAG, flags & ARM7_TLB_READ ? 1 : 0, flags & ARM7_TLB_WRITE ? 1 : 0) ); - } - else if (flags & ARM7_TLB_ABORT_P) - { - LOG( ( "ARM7: Page Table, Section %s fault on virtual address, vaddr = %08x, PC = %08x\n", (fault == FAULT_DOMAIN) ? "domain" : "permission", addr, m_r[eR15] ) ); - m_pendingAbtP = true; - update_irq_state(); - } - return false; - } - } - break; - case COPRO_TLB_TINY_PAGE: - // Tiny page descriptor - if( ( desc_lvl1 & 3 ) == 1 ) - { - LOG( ( "ARM7: It would appear that we're looking up a tiny page from a coarse TLB lookup. This is bad. vaddr = %08x\n", addr ) ); - } - addr = ( desc_lvl2 & COPRO_TLB_TINY_PAGE_MASK ) | ( addr & ~COPRO_TLB_TINY_PAGE_MASK ); - break; - } + if (m_tlb_log) + LOGMASKED(LOG_MMU, "No TLB entry for %08x yet, running page_table_translate\n", vaddr); + return page_table_translate(vaddr, flags); } +} - return true; +void arm7_cpu_device::translate_insn_command(const std::vector<std::string_view> ¶ms) +{ + translate_command(params, TR_FETCH); +} + +void arm7_cpu_device::translate_data_command(const std::vector<std::string_view> ¶ms) +{ + translate_command(params, TR_READ); } +void arm7_cpu_device::translate_command(const std::vector<std::string_view> ¶ms, int intention) +{ + uint64_t vaddr; + + if (!machine().debugger().console().validate_number_parameter(params[0], vaddr)) return; + + vaddr &= 0xffffffff; -bool arm7_cpu_device::memory_translate(int spacenum, int intention, offs_t &address) + offs_t paddr = (offs_t)vaddr; + address_space *space = nullptr; + bool can_translate = memory_translate(AS_PROGRAM, intention, paddr, space); + if (can_translate) + machine().debugger().console().printf("%s vaddr %08x => phys %08x\n", intention == TR_FETCH ? "instruction" : "data", (uint32_t)vaddr, paddr); + else + machine().debugger().console().printf("%s vaddr %08x => unmapped\n", intention == TR_FETCH ? "instruction" : "data"); +} + +bool arm7_cpu_device::memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) { + target_space = &space(spacenum); /* only applies to the program address space and only does something if the MMU's enabled */ - if( spacenum == AS_PROGRAM && ( m_control & COPRO_CTRL_MMU_EN ) ) + if (spacenum == AS_PROGRAM && (m_control & COPRO_CTRL_MMU_EN)) { - return arm7_tlb_translate(address, 0); + const int flags = intention == TR_FETCH ? ARM7_TLB_ABORT_P : ARM7_TLB_ABORT_D; + if (address < 0x2000000) + address += m_pid_offset; + + tlb_entry *entry = tlb_probe(address, flags); + + if (entry) + { + const uint32_t access_result = tlb_check_permissions(entry, flags); + if (access_result == 0) + { + address = tlb_translate(entry, address); + return true; + } + return false; + } + else + { + return page_table_translate(address, 0); + } } return true; } @@ -598,16 +960,18 @@ void arm7_cpu_device::postload() void arm7_cpu_device::device_start() { + init_ce_kernel_addrs(); + m_program = &space(AS_PROGRAM); if(m_program->endianness() == ENDIANNESS_LITTLE) { - auto cache = m_program->cache<2, 0, ENDIANNESS_LITTLE>(); - m_pr32 = [cache](offs_t address) -> u32 { return cache->read_dword(address); }; - m_prptr = [cache](offs_t address) -> const void * { return cache->read_ptr(address); }; + m_program->cache(m_cachele); + m_pr32 = [this](offs_t address) -> u32 { return m_cachele.read_dword(address); }; + m_prptr = [this](offs_t address) -> const void * { return m_cachele.read_ptr(address); }; } else { - auto cache = m_program->cache<2, 0, ENDIANNESS_BIG>(); - m_pr32 = [cache](offs_t address) -> u32 { return cache->read_dword(address); }; - m_prptr = [cache](offs_t address) -> const void * { return cache->read_ptr(address); }; + m_program->cache(m_cachebe); + m_pr32 = [this](offs_t address) -> u32 { return m_cachebe.read_dword(address); }; + m_prptr = [this](offs_t address) -> const void * { return m_cachebe.read_ptr(address); }; } save_item(NAME(m_insn_prefetch_depth)); @@ -615,6 +979,9 @@ void arm7_cpu_device::device_start() save_item(NAME(m_insn_prefetch_index)); save_item(NAME(m_insn_prefetch_buffer)); save_item(NAME(m_insn_prefetch_address)); + save_item(NAME(m_insn_prefetch_valid)); + save_item(NAME(m_tlb_log)); + save_item(NAME(m_actual_log)); save_item(NAME(m_r)); save_item(NAME(m_pendingIrq)); save_item(NAME(m_pendingFiq)); @@ -632,6 +999,20 @@ void arm7_cpu_device::device_start() save_item(NAME(m_pid_offset)); save_item(NAME(m_domainAccessControl)); save_item(NAME(m_decoded_access_control)); + save_item(STRUCT_MEMBER(m_dtlb_entries, valid)); + save_item(STRUCT_MEMBER(m_dtlb_entries, domain)); + save_item(STRUCT_MEMBER(m_dtlb_entries, access)); + save_item(STRUCT_MEMBER(m_dtlb_entries, table_bits)); + save_item(STRUCT_MEMBER(m_dtlb_entries, base_addr)); + save_item(STRUCT_MEMBER(m_dtlb_entries, type)); + save_item(STRUCT_MEMBER(m_itlb_entries, valid)); + save_item(STRUCT_MEMBER(m_itlb_entries, domain)); + save_item(STRUCT_MEMBER(m_itlb_entries, access)); + save_item(STRUCT_MEMBER(m_itlb_entries, table_bits)); + save_item(STRUCT_MEMBER(m_itlb_entries, base_addr)); + save_item(STRUCT_MEMBER(m_itlb_entries, type)); + save_item(NAME(m_dtlb_entry_index)); + save_item(NAME(m_itlb_entry_index)); machine().save().register_postload(save_prepost_delegate(FUNC(arm7_cpu_device::postload), this)); set_icountptr(m_icount); @@ -683,8 +1064,16 @@ void arm7_cpu_device::device_start() state_add( ARM7_UR13, "UR13", m_r[eR13_UND] ).formatstr("%08X"); state_add( ARM7_UR14, "UR14", m_r[eR14_UND] ).formatstr("%08X"); state_add( ARM7_USPSR, "UR16", m_r[eSPSR_UND]).formatstr("%08X"); + state_add( ARM7_LOGTLB, "LOGTLB", m_actual_log).formatstr("%01X"); state_add(STATE_GENFLAGS, "GENFLAGS", m_r[eCPSR]).formatstr("%13s").noshow(); + + if (debugger_enabled()) + { + using namespace std::placeholders; + machine().debugger().console().register_command("translate_insn", CMDFLAG_NONE, 1, 1, std::bind(&arm7_cpu_device::translate_insn_command, this, _1)); + machine().debugger().console().register_command("translate_data", CMDFLAG_NONE, 1, 1, std::bind(&arm7_cpu_device::translate_data_command, this, _1)); + } } @@ -705,7 +1094,6 @@ void arm946es_cpu_device::device_start() save_item(NAME(DTCM)); } - void arm7_cpu_device::state_export(const device_state_entry &entry) { switch (entry.index()) @@ -739,7 +1127,7 @@ void arm7_cpu_device::state_string_export(const device_state_entry &entry, std:: void arm7_cpu_device::device_reset() { - memset(m_r, 0, sizeof(m_r)); + std::fill(std::begin(m_r), std::end(m_r), 0); m_pendingIrq = false; m_pendingFiq = false; m_pendingAbtD = false; @@ -756,7 +1144,7 @@ void arm7_cpu_device::device_reset() m_fcsePID = 0; m_pid_offset = 0; m_domainAccessControl = 0; - memset(m_decoded_access_control, 0, sizeof(uint8_t) * 16); + std::fill_n(&m_decoded_access_control[0], 16, 0); /* start up in SVC mode with interrupts disabled. */ m_r[eCPSR] = I_MASK | F_MASK | 0x10; @@ -764,38 +1152,71 @@ void arm7_cpu_device::device_reset() m_r[eR15] = 0 | m_vectorbase; m_impstate.cache_dirty = true; -} + for (auto &entry : m_dtlb_entries) + { + entry.valid = false; + entry.domain = 0; + entry.access = 0; + entry.table_bits = 0; + entry.base_addr = 0; + entry.type = 0; + } + for (auto &entry : m_itlb_entries) + { + entry.valid = false; + entry.domain = 0; + entry.access = 0; + entry.table_bits = 0; + entry.base_addr = 0; + entry.type = 0; + } + std::fill(std::begin(m_dtlb_entry_index), std::end(m_dtlb_entry_index), 0); + std::fill(std::begin(m_itlb_entry_index), std::end(m_itlb_entry_index), 0); +} -#define UNEXECUTED() \ - m_r[eR15] += 4; \ - m_icount +=2; /* Any unexecuted instruction only takes 1 cycle (page 193) */ +void arm1176jzf_s_cpu_device::device_reset() +{ + arm7_cpu_device::device_reset(); + m_control = 0x00050078; +} void arm7_cpu_device::update_insn_prefetch(uint32_t curr_pc) { curr_pc &= ~3; if (m_insn_prefetch_address[m_insn_prefetch_index] != curr_pc) { + LOGMASKED(LOG_PREFETCH, "Prefetch addr %08x doesn't match curr_pc %08x, flushing prefetch buffer\n", m_insn_prefetch_address[m_insn_prefetch_index], curr_pc); m_insn_prefetch_count = 0; m_insn_prefetch_index = 0; } if (m_insn_prefetch_count == m_insn_prefetch_depth) + { + LOGMASKED(LOG_PREFETCH, "We have prefetched up to the max depth, bailing\n"); return; + } const uint32_t to_fetch = m_insn_prefetch_depth - m_insn_prefetch_count; const uint32_t start_index = (m_insn_prefetch_depth + (m_insn_prefetch_index - to_fetch)) % m_insn_prefetch_depth; //printf("need to prefetch %d instructions starting at index %d\n", to_fetch, start_index); + LOGMASKED(LOG_PREFETCH, "Need to fetch %d entries starting from index %d\n", to_fetch, start_index); uint32_t pc = curr_pc + m_insn_prefetch_count * 4; for (uint32_t i = 0; i < to_fetch; i++) { uint32_t index = (i + start_index) % m_insn_prefetch_depth; - if ((m_control & COPRO_CTRL_MMU_EN) && !arm7_tlb_translate(pc, ARM7_TLB_ABORT_P | ARM7_TLB_READ, true)) + LOGMASKED(LOG_PREFETCH, "About to get prefetch index %d from addr %08x\n", index, pc); + m_insn_prefetch_valid[index] = true; + offs_t physical_pc = pc; + if ((m_control & COPRO_CTRL_MMU_EN) && !translate_vaddr_to_paddr(physical_pc, ARM7_TLB_ABORT_P | ARM7_TLB_READ)) { + LOGMASKED(LOG_PREFETCH, "Unable to fetch, bailing\n"); + m_insn_prefetch_valid[index] = false; break; } - uint32_t op = m_pr32(pc); + uint32_t op = m_pr32(physical_pc); + LOGMASKED(LOG_PREFETCH, "Got op %08x\n", op); //printf("ipb[%d] <- %08x(%08x)\n", index, op, pc); m_insn_prefetch_buffer[index] = op; m_insn_prefetch_address[index] = pc; @@ -804,102 +1225,284 @@ void arm7_cpu_device::update_insn_prefetch(uint32_t curr_pc) } } -uint16_t arm7_cpu_device::insn_fetch_thumb(uint32_t pc) +bool arm7_cpu_device::insn_fetch_thumb(uint32_t pc, uint32_t &out_insn) { if (pc & 2) { - uint16_t insn = (uint16_t)(m_insn_prefetch_buffer[m_insn_prefetch_index] >> m_prefetch_word1_shift); - m_insn_prefetch_index = (m_insn_prefetch_index + 1) % m_insn_prefetch_count; + out_insn = (uint16_t)(m_insn_prefetch_buffer[m_insn_prefetch_index] >> m_prefetch_word1_shift); + bool valid = m_insn_prefetch_valid[m_insn_prefetch_index]; + m_insn_prefetch_index = (m_insn_prefetch_index + 1) % m_insn_prefetch_depth; m_insn_prefetch_count--; - return insn; + return valid; } - return (uint16_t)(m_insn_prefetch_buffer[m_insn_prefetch_index] >> m_prefetch_word0_shift); + out_insn = (uint16_t)(m_insn_prefetch_buffer[m_insn_prefetch_index] >> m_prefetch_word0_shift); + return m_insn_prefetch_valid[m_insn_prefetch_index]; } -uint32_t arm7_cpu_device::insn_fetch_arm(uint32_t pc) +bool arm7_cpu_device::insn_fetch_arm(uint32_t pc, uint32_t &out_insn) { //printf("ipb[%d] = %08x\n", m_insn_prefetch_index, m_insn_prefetch_buffer[m_insn_prefetch_index]); - uint32_t insn = m_insn_prefetch_buffer[m_insn_prefetch_index]; - m_insn_prefetch_index = (m_insn_prefetch_index + 1) % m_insn_prefetch_count; + out_insn = m_insn_prefetch_buffer[m_insn_prefetch_index]; + bool valid = m_insn_prefetch_valid[m_insn_prefetch_index]; + LOGMASKED(LOG_PREFETCH, "Fetched op %08x for PC %08x with %s entry from %08x\n", out_insn, pc, valid ? "valid" : "invalid", m_insn_prefetch_address[m_insn_prefetch_index]); + m_insn_prefetch_index = (m_insn_prefetch_index + 1) % m_insn_prefetch_depth; m_insn_prefetch_count--; - return insn; + return valid; } -int arm7_cpu_device::get_insn_prefetch_index(uint32_t address) +void arm7_cpu_device::add_ce_kernel_addr(offs_t addr, std::string value) { - address &= ~3; - for (uint32_t i = 0; i < m_insn_prefetch_depth; i++) - { - if (m_insn_prefetch_address[i] == address) - { - return (int)i; - } - } - return -1; + m_ce_kernel_addrs[addr - 0xf0000000] = value; + m_ce_kernel_addr_present[addr - 0xf0000000] = true; } +#include "cecalls.hxx" + void arm7_cpu_device::execute_run() { + auto const UNEXECUTED = [this] { m_r[eR15] += 4; m_icount += 2; }; // Any unexecuted instruction only takes 1 cycle (page 193) + + m_tlb_log = m_actual_log; + uint32_t insn; do { uint32_t pc = GET_PC; +#if PRINT_HAPYFSH2 + if (pc == 0xC0047374) + { + char substr_buf[4096]; + uint16_t substr_idx = 0; + bool zero_prepend = false; + uint8_t digit_count = 0; + uint32_t string_addr = (m_r[eR0] & 0x0fffffff) | 0x30000000; + uint8_t charval = 0; + uint32_t reg_idx = eR1; + do + { + charval = m_program->read_byte(string_addr); + string_addr++; + if (charval >= 0x20 && charval < 0x7f) + { + if (charval == '%') + { + bool still_processing = true; + uint8_t nextval = m_program->read_byte(string_addr); + string_addr++; + switch (nextval) + { + case 0: + printf("%%"); + charval = 0; + still_processing = false; + break; + case '%': + printf("%%"); + still_processing = false; + break; + case '0': + zero_prepend = true; + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + digit_count = nextval - '0'; + break; + case 'd': + printf("%d", (reg_idx >= eR4) ? m_program->read_dword(((m_r[eR13_SVC] & 0x0fffffff) | 0x30000000) + (reg_idx - eR4)) : m_r[reg_idx]); + still_processing = false; + reg_idx++; + break; + case 'l': + case 'u': + printf("%u", (reg_idx >= eR4) ? m_program->read_dword(((m_r[eR13_SVC] & 0x0fffffff) | 0x30000000) + (reg_idx - eR4)) : m_r[reg_idx]); + still_processing = false; + reg_idx++; + break; + case 'x': + case 'p': + printf("%x", (reg_idx >= eR4) ? m_program->read_dword(((m_r[eR13_SVC] & 0x0fffffff) | 0x30000000) + (reg_idx - eR4)) : m_r[reg_idx]); + still_processing = false; + reg_idx++; + break; + case 'o': + printf("%o", (reg_idx >= eR4) ? m_program->read_dword(((m_r[eR13_SVC] & 0x0fffffff) | 0x30000000) + (reg_idx - eR4)) : m_r[reg_idx]); + still_processing = false; + reg_idx++; + break; + case 's': + { + uint32_t val = (reg_idx >= eR4) ? m_program->read_dword(((m_r[eR13_SVC] & 0x0fffffff) | 0x30000000) + (reg_idx - eR4)) : m_r[reg_idx]; + uint32_t substring_addr = (val & 0x0fffffff) | 0x30000000; + reg_idx++; + bool end_found = false; + while (!end_found) + { + substr_buf[substr_idx] = m_program->read_byte(substring_addr); + if (substr_buf[substr_idx] == 0) + { + end_found = true; + } + substring_addr++; + substr_idx++; + } + substr_idx = 0; + printf("%s", substr_buf); + still_processing = false; + break; + } + } + while (still_processing) + { + uint8_t nextval2 = m_program->read_byte(string_addr); + string_addr++; + if (nextval2 == 0) + { + printf("%c%c", (char)charval, (char)nextval); + charval = 0; + break; + } + else if (nextval2 >= '1' && nextval2 <= '9') + { + digit_count = nextval2 - '0'; + } + else if (nextval2 == 'd') + { + uint32_t val = (reg_idx >= eR4) ? m_program->read_dword(((m_r[eR13_SVC] & 0x0fffffff) | 0x30000000) + (reg_idx - eR4)) : m_r[reg_idx]; + switch (digit_count) + { + case 1: if (zero_prepend) { printf("%01d", val); } else { printf("%1d", val); } break; + case 2: if (zero_prepend) { printf("%02d", val); } else { printf("%2d", val); } break; + case 3: if (zero_prepend) { printf("%03d", val); } else { printf("%3d", val); } break; + case 4: if (zero_prepend) { printf("%04d", val); } else { printf("%4d", val); } break; + case 5: if (zero_prepend) { printf("%05d", val); } else { printf("%5d", val); } break; + case 6: if (zero_prepend) { printf("%06d", val); } else { printf("%6d", val); } break; + case 7: if (zero_prepend) { printf("%07d", val); } else { printf("%7d", val); } break; + case 8: if (zero_prepend) { printf("%08d", val); } else { printf("%8d", val); } break; + case 9: if (zero_prepend) { printf("%09d", val); } else { printf("%9d", val); } break; + } + reg_idx++; + still_processing = false; + } + else if (nextval2 == 'u' || nextval2 == 'l') + { + uint32_t val = (reg_idx >= eR4) ? m_program->read_dword(((m_r[eR13_SVC] & 0x0fffffff) | 0x30000000) + (reg_idx - eR4)) : m_r[reg_idx]; + switch (digit_count) + { + case 1: if (zero_prepend) { printf("%01u", val); } else { printf("%1u", val); } break; + case 2: if (zero_prepend) { printf("%02u", val); } else { printf("%2u", val); } break; + case 3: if (zero_prepend) { printf("%03u", val); } else { printf("%3u", val); } break; + case 4: if (zero_prepend) { printf("%04u", val); } else { printf("%4u", val); } break; + case 5: if (zero_prepend) { printf("%05u", val); } else { printf("%5u", val); } break; + case 6: if (zero_prepend) { printf("%06u", val); } else { printf("%6u", val); } break; + case 7: if (zero_prepend) { printf("%07u", val); } else { printf("%7u", val); } break; + case 8: if (zero_prepend) { printf("%08u", val); } else { printf("%8u", val); } break; + case 9: if (zero_prepend) { printf("%09u", val); } else { printf("%9u", val); } break; + } + reg_idx++; + still_processing = false; + } + else if (nextval2 == 'x') + { + uint32_t val = (reg_idx >= eR4) ? m_program->read_dword(((m_r[eR13_SVC] & 0x0fffffff) | 0x30000000) + (reg_idx - eR4)) : m_r[reg_idx]; + switch (digit_count) + { + case 1: if (zero_prepend) { printf("%01x", val); } else { printf("%1x", val); } break; + case 2: if (zero_prepend) { printf("%02x", val); } else { printf("%2x", val); } break; + case 3: if (zero_prepend) { printf("%03x", val); } else { printf("%3x", val); } break; + case 4: if (zero_prepend) { printf("%04x", val); } else { printf("%4x", val); } break; + case 5: if (zero_prepend) { printf("%05x", val); } else { printf("%5x", val); } break; + case 6: if (zero_prepend) { printf("%06x", val); } else { printf("%6x", val); } break; + case 7: if (zero_prepend) { printf("%07x", val); } else { printf("%7x", val); } break; + case 8: if (zero_prepend) { printf("%08x", val); } else { printf("%8x", val); } break; + case 9: if (zero_prepend) { printf("%09x", val); } else { printf("%9x", val); } break; + } + reg_idx++; + still_processing = false; + } + else if (nextval2 == 'o') + { + uint32_t val = (reg_idx >= eR4) ? m_program->read_dword(((m_r[eR13_SVC] & 0x0fffffff) | 0x30000000) + (reg_idx - eR4)) : m_r[reg_idx]; + switch (digit_count) + { + case 1: if (zero_prepend) { printf("%01o", val); } else { printf("%1o", val); } break; + case 2: if (zero_prepend) { printf("%02o", val); } else { printf("%2o", val); } break; + case 3: if (zero_prepend) { printf("%03o", val); } else { printf("%3o", val); } break; + case 4: if (zero_prepend) { printf("%04o", val); } else { printf("%4o", val); } break; + case 5: if (zero_prepend) { printf("%05o", val); } else { printf("%5o", val); } break; + case 6: if (zero_prepend) { printf("%06o", val); } else { printf("%6o", val); } break; + case 7: if (zero_prepend) { printf("%07o", val); } else { printf("%7o", val); } break; + case 8: if (zero_prepend) { printf("%08o", val); } else { printf("%8o", val); } break; + case 9: if (zero_prepend) { printf("%09o", val); } else { printf("%9o", val); } break; + } + reg_idx++; + still_processing = false; + } + else + { + printf("%c%c", (char)charval, (char)nextval); + still_processing = false; + } + } + } + else + { + printf("%c", (char)charval); + } + } + } while (charval != 0); + printf("\n"); + } +#endif update_insn_prefetch(pc); + m_tlb_log = 0; debugger_instruction_hook(pc); + m_tlb_log = m_actual_log; /* handle Thumb instructions if active */ if (T_IS_SET(m_r[eCPSR])) { - offs_t raddr; - pc = m_r[eR15]; // "In Thumb state, bit [0] is undefined and must be ignored. Bits [31:1] contain the PC." - raddr = pc & (~1); + offs_t const raddr = pc & ~uint32_t(1); - if ( m_control & COPRO_CTRL_MMU_EN ) + if (!insn_fetch_thumb(raddr, insn)) { - if (!arm7_tlb_translate(raddr, ARM7_TLB_ABORT_P | ARM7_TLB_READ)) - { - goto skip_exec; - } + m_pendingAbtP = true; + update_irq_state(); + goto skip_exec; } - - insn = insn_fetch_thumb(raddr); (this->*thumb_handler[(insn & 0xffc0) >> 6])(pc, insn); - } else { - offs_t raddr; - /* load 32 bit instruction */ // "In ARM state, bits [1:0] of r15 are undefined and must be ignored. Bits [31:2] contain the PC." - raddr = pc & (~3); + offs_t const raddr = pc & ~uint32_t(3); - if ( m_control & COPRO_CTRL_MMU_EN ) + if (!insn_fetch_arm(raddr, insn)) { - if (!arm7_tlb_translate(raddr, ARM7_TLB_ABORT_P | ARM7_TLB_READ)) +#if PRINT_CE_KERNEL + if (raddr >= 0xf0000000) { - goto skip_exec; + print_ce_kernel_address(raddr - 0xf0000000); } - } - -#if 0 - if (MODE26) - { - uint32_t temp1, temp2; - temp1 = GET_CPSR & 0xF00000C3; - temp2 = (R15 & 0xF0000000) | ((R15 & 0x0C000000) >> (26 - 6)) | (R15 & 0x00000003); - if (temp1 != temp2) fatalerror( "%08X: 32-bit and 26-bit modes are out of sync (%08X %08X)\n", pc, temp1, temp2); - } #endif - - insn = insn_fetch_arm(raddr); + m_pendingAbtP = true; + update_irq_state(); + goto skip_exec; + } int op_offset = 0; /* process condition codes for this instruction */ @@ -984,29 +1587,32 @@ skip_exec: /* All instructions remove 3 cycles.. Others taking less / more will have adjusted this # prior to here */ m_icount -= 3; } while (m_icount > 0); + + m_tlb_log = 0; } void arm7_cpu_device::execute_set_input(int irqline, int state) { - switch (irqline) { - case ARM7_IRQ_LINE: /* IRQ */ - m_pendingIrq = state ? true : false; + switch (irqline) + { + case ARM7_IRQ_LINE: // IRQ + m_pendingIrq = state != 0; break; - case ARM7_FIRQ_LINE: /* FIRQ */ - m_pendingFiq = state ? true : false; + case ARM7_FIRQ_LINE: // FIQ + m_pendingFiq = state != 0; break; case ARM7_ABORT_EXCEPTION: - m_pendingAbtD = state ? true : false; + m_pendingAbtD = state != 0; break; case ARM7_ABORT_PREFETCH_EXCEPTION: - m_pendingAbtP = state ? true : false; + m_pendingAbtP = state != 0; break; case ARM7_UNDEFINE_EXCEPTION: - m_pendingUnd = state ? true : false; + m_pendingUnd = state != 0; break; } @@ -1015,6 +1621,24 @@ void arm7_cpu_device::execute_set_input(int irqline, int state) } +void arm7_cpu_device::set_irq(int state) +{ + assert((machine().scheduler().currently_executing() == static_cast<device_execute_interface *>(this)) || !machine().scheduler().currently_executing()); + m_pendingIrq = state != 0; + update_irq_state(); + arm7_check_irq_state(); +} + + +void arm7_cpu_device::set_fiq(int state) +{ + assert((machine().scheduler().currently_executing() == static_cast<device_execute_interface *>(this)) || !machine().scheduler().currently_executing()); + m_pendingFiq = state != 0; + update_irq_state(); + arm7_check_irq_state(); +} + + std::unique_ptr<util::disasm_interface> arm7_cpu_device::create_disassembler() { return std::make_unique<arm7_disassembler>(this); @@ -1028,13 +1652,13 @@ bool arm7_cpu_device::get_t_flag() const /* ARM system coprocessor support */ -WRITE32_MEMBER( arm7_cpu_device::arm7_do_callback ) +void arm7_cpu_device::arm7_do_callback(uint32_t data) { m_pendingUnd = true; update_irq_state(); } -READ32_MEMBER( arm7_cpu_device::arm7_rt_r_callback ) +uint32_t arm7_cpu_device::arm7_rt_r_callback(offs_t offset) { uint32_t opcode = offset; uint8_t cReg = ( opcode & INSN_COPRO_CREG ) >> INSN_COPRO_CREG_SHIFT; @@ -1072,7 +1696,7 @@ READ32_MEMBER( arm7_cpu_device::arm7_rt_r_callback ) } else { - LOG( ("ARM7: Unhandled coprocessor %d (archFlags %x)\n", cpnum, m_archFlags) ); + LOGMASKED(LOG_COPRO_UNKNOWN, "ARM7: Unhandled coprocessor %d (archFlags %x)\n", cpnum, m_archFlags); m_pendingUnd = true; update_irq_state(); return 0; @@ -1089,7 +1713,7 @@ READ32_MEMBER( arm7_cpu_device::arm7_rt_r_callback ) case 11: case 12: // RESERVED - LOG( ( "arm7_rt_r_callback CR%d, RESERVED\n", cReg ) ); + LOGMASKED(LOG_COPRO_RESERVED, "arm7_rt_r_callback CR%d, RESERVED\n", cReg); break; case 0: // ID switch(op2) @@ -1111,20 +1735,21 @@ READ32_MEMBER( arm7_cpu_device::arm7_rt_r_callback ) data = 0; break; } - LOG( ( "arm7_rt_r_callback, ID %02x (%02x) -> %08x (PC=%08x)\n",op2,m_archRev,data,GET_PC ) ); + LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, ID %02x (%02x) -> %08x (PC=%08x)\n",op2,m_archRev,data,GET_PC); break; case 1: // Control data = COPRO_CTRL | 0x70; // bits 4-6 always read back as "1" (bit 3 too in XScale) break; case 2: // Translation Table Base + LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, TLB Base, PC = %08x\n", m_r[eR15]); data = COPRO_TLB_BASE; break; case 3: // Domain Access Control - LOG( ( "arm7_rt_r_callback, Domain Access Control\n" ) ); + LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, Domain Access Control, PC = %08x\n", m_r[eR15]); data = COPRO_DOMAIN_ACCESS_CONTROL; break; case 5: // Fault Status - LOG( ( "arm7_rt_r_callback, Fault Status\n" ) ); + LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, Fault Status, PC = %08x, op3 %d, FSR0 = %08x, FSR1 = %08x\n", m_r[eR15], op3, COPRO_FAULT_STATUS_D, COPRO_FAULT_STATUS_P); switch (op3) { case 0: data = COPRO_FAULT_STATUS_D; break; @@ -1132,25 +1757,25 @@ READ32_MEMBER( arm7_cpu_device::arm7_rt_r_callback ) } break; case 6: // Fault Address - LOG( ( "arm7_rt_r_callback, Fault Address\n" ) ); + LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, Fault Address, PC = %08x, FAR = %08x\n", m_r[eR15], COPRO_FAULT_ADDRESS); data = COPRO_FAULT_ADDRESS; break; case 13: // Read Process ID (PID) - LOG( ( "arm7_rt_r_callback, Read PID\n" ) ); + LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, Read PID, PC = %08x\n", m_r[eR15]); data = COPRO_FCSE_PID; break; case 14: // Read Breakpoint - LOG( ( "arm7_rt_r_callback, Read Breakpoint\n" ) ); + LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, Read Breakpoint\n"); break; case 15: // Test, Clock, Idle - LOG( ( "arm7_rt_r_callback, Test / Clock / Idle \n" ) ); + LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, Test / Clock / Idle \n"); break; } return data; } -WRITE32_MEMBER( arm7_cpu_device::arm7_rt_w_callback ) +void arm7_cpu_device::arm7_rt_w_callback(offs_t offset, uint32_t data) { uint32_t opcode = offset; uint8_t cReg = ( opcode & INSN_COPRO_CREG ) >> INSN_COPRO_CREG_SHIFT; @@ -1163,19 +1788,19 @@ WRITE32_MEMBER( arm7_cpu_device::arm7_rt_w_callback ) { if (cpnum == 14) { - LOG( ("arm7_rt_w_callback: write %x to XScale CP14 reg %d\n", data, cReg) ); + LOGMASKED(LOG_COPRO_UNKNOWN, "arm7_rt_w_callback: write %x to XScale CP14 reg %d\n", data, cReg); return; } else { - LOG( ("ARM7: Unhandled coprocessor %d\n", cpnum) ); + LOGMASKED(LOG_COPRO_UNKNOWN, "ARM7: Unhandled coprocessor %d\n", cpnum); m_pendingUnd = true; update_irq_state(); return; } } - switch( cReg ) + switch (cReg) { case 0: case 4: @@ -1183,28 +1808,28 @@ WRITE32_MEMBER( arm7_cpu_device::arm7_rt_w_callback ) case 11: case 12: // RESERVED - LOG( ( "arm7_rt_w_callback CR%d, RESERVED = %08x\n", cReg, data) ); + LOGMASKED(LOG_COPRO_RESERVED, "arm7_rt_w_callback CR%d, RESERVED = %08x\n", cReg, data); break; case 1: // Control - LOG( ( "arm7_rt_w_callback Control = %08x (%d) (%d)\n", data, op2, op3 ) ); - LOG( ( " MMU:%d, Address Fault:%d, Data Cache:%d, Write Buffer:%d\n", + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Control = %08x (%d) (%d)\n", data, op2, op3); + LOGMASKED(LOG_COPRO_WRITES, " MMU:%d, Address Fault:%d, Data Cache:%d, Write Buffer:%d\n", data & COPRO_CTRL_MMU_EN, ( data & COPRO_CTRL_ADDRFAULT_EN ) >> COPRO_CTRL_ADDRFAULT_EN_SHIFT, ( data & COPRO_CTRL_DCACHE_EN ) >> COPRO_CTRL_DCACHE_EN_SHIFT, - ( data & COPRO_CTRL_WRITEBUF_EN ) >> COPRO_CTRL_WRITEBUF_EN_SHIFT ) ); - LOG( ( " Endianness:%d, System:%d, ROM:%d, Instruction Cache:%d\n", + ( data & COPRO_CTRL_WRITEBUF_EN ) >> COPRO_CTRL_WRITEBUF_EN_SHIFT); + LOGMASKED(LOG_COPRO_WRITES, " Endianness:%d, System:%d, ROM:%d, Instruction Cache:%d\n", ( data & COPRO_CTRL_ENDIAN ) >> COPRO_CTRL_ENDIAN_SHIFT, ( data & COPRO_CTRL_SYSTEM ) >> COPRO_CTRL_SYSTEM_SHIFT, ( data & COPRO_CTRL_ROM ) >> COPRO_CTRL_ROM_SHIFT, - ( data & COPRO_CTRL_ICACHE_EN ) >> COPRO_CTRL_ICACHE_EN_SHIFT ) ); - LOG( ( " Int Vector Adjust:%d\n", ( data & COPRO_CTRL_INTVEC_ADJUST ) >> COPRO_CTRL_INTVEC_ADJUST_SHIFT ) ); + ( data & COPRO_CTRL_ICACHE_EN ) >> COPRO_CTRL_ICACHE_EN_SHIFT); + LOGMASKED(LOG_COPRO_WRITES, " Int Vector Adjust:%d\n", ( data & COPRO_CTRL_INTVEC_ADJUST ) >> COPRO_CTRL_INTVEC_ADJUST_SHIFT); #if ARM7_MMU_ENABLE_HACK if (((data & COPRO_CTRL_MMU_EN) != 0) && ((COPRO_CTRL & COPRO_CTRL_MMU_EN) == 0)) { - >m_mmu_enable_addr = R15; + m_mmu_enable_addr = R15; } if (((data & COPRO_CTRL_MMU_EN) == 0) && ((COPRO_CTRL & COPRO_CTRL_MMU_EN) != 0)) { - if (!arm7_tlb_translate( R15, 0)) + if (!translate_vaddr_to_paddr( R15, 0)) { fatalerror("ARM7_MMU_ENABLE_HACK translate failed\n"); } @@ -1213,12 +1838,12 @@ WRITE32_MEMBER( arm7_cpu_device::arm7_rt_w_callback ) COPRO_CTRL = data & COPRO_CTRL_MASK; break; case 2: // Translation Table Base - LOG( ( "arm7_rt_w_callback TLB Base = %08x (%d) (%d)\n", data, op2, op3 ) ); + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback TLB Base = %08x (%d) (%d), PC = %08x\n", data, op2, op3, m_r[eR15]); COPRO_TLB_BASE = data; m_tlb_base_mask = data & COPRO_TLB_BASE_MASK; break; case 3: // Domain Access Control - LOG( ( "arm7_rt_w_callback Domain Access Control = %08x (%d) (%d)\n", data, op2, op3 ) ); + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Domain Access Control = %08x (%d) (%d), PC = %08x\n", data, op2, op3, m_r[eR15]); COPRO_DOMAIN_ACCESS_CONTROL = data; for (int i = 0; i < 32; i += 2) { @@ -1226,7 +1851,7 @@ WRITE32_MEMBER( arm7_cpu_device::arm7_rt_w_callback ) } break; case 5: // Fault Status - LOG( ( "arm7_rt_w_callback Fault Status = %08x (%d) (%d)\n", data, op2, op3 ) ); + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Fault Status = %08x (%d) (%d), PC = %08x\n", data, op2, op3, m_r[eR15]); switch (op3) { case 0: COPRO_FAULT_STATUS_D = data; break; @@ -1234,33 +1859,114 @@ WRITE32_MEMBER( arm7_cpu_device::arm7_rt_w_callback ) } break; case 6: // Fault Address - LOG( ( "arm7_rt_w_callback Fault Address = %08x (%d) (%d)\n", data, op2, op3 ) ); + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Fault Address = %08x (%d) (%d), PC = %08x\n", data, op2, op3, m_r[eR15]); COPRO_FAULT_ADDRESS = data; break; case 7: // Cache Operations -// LOG( ( "arm7_rt_w_callback Cache Ops = %08x (%d) (%d)\n", data, op2, op3 ) ); +// LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Cache Ops = %08x (%d) (%d)\n", data, op2, op3); break; case 8: // TLB Operations - LOG( ( "arm7_rt_w_callback TLB Ops = %08x (%d) (%d)\n", data, op2, op3 ) ); + LOGMASKED(LOG_COPRO_WRITES, "%s: arm7_rt_w_callback TLB Ops = %08x (%d) (%d), PC = %08x\n", machine().describe_context(), data, op2, op3, m_r[eR15]); + switch (op2) + { + case 0: + switch (op3) + { + case 5: + // Flush I + for (uint32_t i = 0; i < std::size(m_itlb_entries); i++) + { + m_itlb_entries[i].valid = false; + } + break; + case 6: + // Flush D + for (uint32_t i = 0; i < std::size(m_dtlb_entries); i++) + { + m_dtlb_entries[i].valid = false; + } + break; + case 7: + // Flush I+D + for (uint32_t i = 0; i < std::size(m_dtlb_entries); i++) + { + m_dtlb_entries[i].valid = false; + m_itlb_entries[i].valid = false; + } + break; + default: + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Unsupported TLB Op\n"); + break; + } + break; + case 1: + switch (op3) + { + case 5: + { + // Flush I single entry + tlb_entry *entry = tlb_probe(data, ARM7_TLB_ABORT_P); + if (entry) + { + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback TLB Ops: Successfully flushed I entry for %08x\n", data); + entry->valid = false; + } + break; + } + + case 6: + { + // Flush D single entry + tlb_entry *entry = tlb_probe(data, ARM7_TLB_ABORT_D); + if (entry) + { + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback TLB Ops: Successfully flushed D entry for %08x\n", data); + entry->valid = false; + } + break; + } + case 7: + { + // Flush unified single entry + tlb_entry *entry = tlb_probe(data, ARM7_TLB_ABORT_D); + if (entry) + { + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback TLB Ops: Successfully flushed D entry for %08x\n", data); + entry->valid = false; + } + entry = tlb_probe(data, ARM7_TLB_ABORT_P); + if (entry) + { + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback TLB Ops: Successfully flushed I entry for %08x\n", data); + entry->valid = false; + } + break; + } + default: + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Unsupported TLB Op\n"); + break; + } + break; + } break; case 9: // Read Buffer Operations - LOG( ( "arm7_rt_w_callback Read Buffer Ops = %08x (%d) (%d)\n", data, op2, op3 ) ); + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Read Buffer Ops = %08x (%d) (%d), PC = %08x\n", data, op2, op3, m_r[eR15]); break; case 13: // Write Process ID (PID) - LOG( ( "arm7_rt_w_callback Write PID = %08x (%d) (%d)\n", data, op2, op3 ) ); + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Write PID = %08x (%d) (%d), PC = %08x\n", data, op2, op3, m_r[eR15]); COPRO_FCSE_PID = data; m_pid_offset = (((COPRO_FCSE_PID >> 25) & 0x7F)) * 0x2000000; break; case 14: // Write Breakpoint - LOG( ( "arm7_rt_w_callback Write Breakpoint = %08x (%d) (%d)\n", data, op2, op3 ) ); + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Write Breakpoint = %08x (%d) (%d)\n", data, op2, op3); break; case 15: // Test, Clock, Idle - LOG( ( "arm7_rt_w_callback Test / Clock / Idle = %08x (%d) (%d)\n", data, op2, op3 ) ); + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Test / Clock / Idle = %08x (%d) (%d)\n", data, op2, op3); break; } } -READ32_MEMBER( arm946es_cpu_device::arm7_rt_r_callback ) +uint32_t arm946es_cpu_device::arm7_rt_r_callback(offs_t offset) { uint32_t opcode = offset; uint8_t cReg = ( opcode & INSN_COPRO_CREG ) >> INSN_COPRO_CREG_SHIFT; @@ -1314,7 +2020,7 @@ READ32_MEMBER( arm946es_cpu_device::arm7_rt_r_callback ) return data; } -WRITE32_MEMBER( arm946es_cpu_device::arm7_rt_w_callback ) +void arm946es_cpu_device::arm7_rt_w_callback(offs_t offset, uint32_t data) { uint32_t opcode = offset; uint8_t cReg = ( opcode & INSN_COPRO_CREG ) >> INSN_COPRO_CREG_SHIFT; @@ -1465,8 +2171,7 @@ uint32_t arm946es_cpu_device::arm7_cpu_read32(uint32_t addr) if (addr & 3) { uint32_t *wp = (uint32_t *)&ITCM[(addr & ~3)&0x7fff]; - result = *wp; - result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3)))); + result = rotr_32(*wp, 8 * (addr & 3)); } else { @@ -1479,8 +2184,7 @@ uint32_t arm946es_cpu_device::arm7_cpu_read32(uint32_t addr) if (addr & 3) { uint32_t *wp = (uint32_t *)&DTCM[(addr & ~3)&0x3fff]; - result = *wp; - result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3)))); + result = rotr_32(*wp, 8 * (addr & 3)); } else { @@ -1492,8 +2196,7 @@ uint32_t arm946es_cpu_device::arm7_cpu_read32(uint32_t addr) { if (addr & 3) { - result = m_program->read_dword(addr & ~3); - result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3)))); + result = rotr_32(m_program->read_dword(addr & ~3), 8 * (addr & 3)); } else { @@ -1541,7 +2244,7 @@ void arm7_cpu_device::arm7_dt_r_callback(uint32_t insn, uint32_t *prn) uint8_t cpn = (insn >> 8) & 0xF; if ((m_archFlags & ARCHFLAG_XSCALE) && (cpn == 0)) { - LOG( ( "arm7_dt_r_callback: DSP Coprocessor 0 (CP0) not yet emulated (PC %08x)\n", GET_PC ) ); + LOGMASKED(LOG_DSP, "arm7_dt_r_callback: DSP Coprocessor 0 (CP0) not yet emulated (PC %08x)\n", GET_PC); } else { @@ -1556,7 +2259,7 @@ void arm7_cpu_device::arm7_dt_w_callback(uint32_t insn, uint32_t *prn) uint8_t cpn = (insn >> 8) & 0xF; if ((m_archFlags & ARCHFLAG_XSCALE) && (cpn == 0)) { - LOG( ( "arm7_dt_w_callback: DSP Coprocessor 0 (CP0) not yet emulated (PC %08x)\n", GET_PC ) ); + LOGMASKED(LOG_DSP, "arm7_dt_w_callback: DSP Coprocessor 0 (CP0) not yet emulated (PC %08x)\n", GET_PC); } else { @@ -1565,6 +2268,44 @@ void arm7_cpu_device::arm7_dt_w_callback(uint32_t insn, uint32_t *prn) } } +uint32_t arm1176jzf_s_cpu_device::arm7_rt_r_callback(offs_t offset) +{ + uint32_t opcode = offset; + uint8_t crn = (opcode & INSN_COPRO_CREG) >> INSN_COPRO_CREG_SHIFT; + uint8_t op1 = (opcode & INSN_COPRO_OP1) >> INSN_COPRO_OP1_SHIFT; + uint8_t op2 = (opcode & INSN_COPRO_OP2) >> INSN_COPRO_OP2_SHIFT; + uint8_t crm = opcode & INSN_COPRO_OP3; + uint8_t cpnum = (opcode & INSN_COPRO_CPNUM) >> INSN_COPRO_CPNUM_SHIFT; + uint32_t data = 0; + +// printf("arm7946: copro %d write %x to cReg %d op2 %d op3 %d (mask %08x)\n", cpnum, data, cReg, op2, op3, mem_mask); + + if (cpnum == 15) + { + if(crn == 0 && op1 == 0 && crm == 0 && op2 == 0) data = 0x410FB767; //ARM1176JZF-S Main ID. + if(crn == 1 && op1 == 0 && crm == 0 && op2 == 0) data = m_control; + } + + return data; +} + +void arm1176jzf_s_cpu_device::arm7_rt_w_callback(offs_t offset, uint32_t data) +{ + uint32_t opcode = offset; + uint8_t crn = (opcode & INSN_COPRO_CREG) >> INSN_COPRO_CREG_SHIFT; + uint8_t op1 = (opcode & INSN_COPRO_OP1) >> INSN_COPRO_OP1_SHIFT; + uint8_t op2 = (opcode & INSN_COPRO_OP2) >> INSN_COPRO_OP2_SHIFT; + uint8_t crm = opcode & INSN_COPRO_OP3; + uint8_t cpnum = (opcode & INSN_COPRO_CPNUM) >> INSN_COPRO_CPNUM_SHIFT; + +// printf("arm7946: copro %d write %x to cReg %d op2 %d op3 %d (mask %08x)\n", cpnum, data, cReg, op2, op3, mem_mask); + + if (cpnum == 15) + { + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback: CP15 CRn %02x Op1 %02x CRm %02x Op2 %02x data %08x\n", crn, op1, crm, op2, data); + if(crn == 1 && op1 == 0 && crm == 0 && op2 == 0) m_control = data; + } +} /*************************************************************************** * Default Memory Handlers @@ -1573,7 +2314,7 @@ void arm7_cpu_device::arm7_cpu_write32(uint32_t addr, uint32_t data) { if( COPRO_CTRL & COPRO_CTRL_MMU_EN ) { - if (!arm7_tlb_translate( addr, ARM7_TLB_ABORT_D | ARM7_TLB_WRITE )) + if (!translate_vaddr_to_paddr( addr, ARM7_TLB_ABORT_D | ARM7_TLB_WRITE )) { return; } @@ -1588,7 +2329,7 @@ void arm7_cpu_device::arm7_cpu_write16(uint32_t addr, uint16_t data) { if( COPRO_CTRL & COPRO_CTRL_MMU_EN ) { - if (!arm7_tlb_translate( addr, ARM7_TLB_ABORT_D | ARM7_TLB_WRITE )) + if (!translate_vaddr_to_paddr( addr, ARM7_TLB_ABORT_D | ARM7_TLB_WRITE )) { return; } @@ -1602,7 +2343,7 @@ void arm7_cpu_device::arm7_cpu_write8(uint32_t addr, uint8_t data) { if( COPRO_CTRL & COPRO_CTRL_MMU_EN ) { - if (!arm7_tlb_translate( addr, ARM7_TLB_ABORT_D | ARM7_TLB_WRITE )) + if (!translate_vaddr_to_paddr( addr, ARM7_TLB_ABORT_D | ARM7_TLB_WRITE )) { return; } @@ -1617,7 +2358,7 @@ uint32_t arm7_cpu_device::arm7_cpu_read32(uint32_t addr) if( COPRO_CTRL & COPRO_CTRL_MMU_EN ) { - if (!arm7_tlb_translate( addr, ARM7_TLB_ABORT_D | ARM7_TLB_READ )) + if (!translate_vaddr_to_paddr( addr, ARM7_TLB_ABORT_D | ARM7_TLB_READ )) { return 0; } @@ -1625,8 +2366,7 @@ uint32_t arm7_cpu_device::arm7_cpu_read32(uint32_t addr) if (addr & 3) { - result = m_program->read_dword(addr & ~3); - result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3)))); + result = rotr_32(m_program->read_dword(addr & ~3), 8 * (addr & 3)); } else { @@ -1642,7 +2382,7 @@ uint32_t arm7_cpu_device::arm7_cpu_read16(uint32_t addr) if( COPRO_CTRL & COPRO_CTRL_MMU_EN ) { - if (!arm7_tlb_translate( addr, ARM7_TLB_ABORT_D | ARM7_TLB_READ )) + if (!translate_vaddr_to_paddr( addr, ARM7_TLB_ABORT_D | ARM7_TLB_READ )) { return 0; } @@ -1662,7 +2402,7 @@ uint8_t arm7_cpu_device::arm7_cpu_read8(uint32_t addr) { if( COPRO_CTRL & COPRO_CTRL_MMU_EN ) { - if (!arm7_tlb_translate( addr, ARM7_TLB_ABORT_D | ARM7_TLB_READ )) + if (!translate_vaddr_to_paddr( addr, ARM7_TLB_ABORT_D | ARM7_TLB_READ )) { return 0; } diff --git a/src/devices/cpu/arm7/arm7.h b/src/devices/cpu/arm7/arm7.h index 663a7564d5c..73cf8f44109 100644 --- a/src/devices/cpu/arm7/arm7.h +++ b/src/devices/cpu/arm7/arm7.h @@ -5,7 +5,7 @@ * arm7.h * Portable ARM7TDMI CPU Emulator * - * Copyright Steve Ellenoff, all rights reserved. + * Copyright Steve Ellenoff * * This work is based on: * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999' @@ -50,110 +50,118 @@ class arm7_cpu_device : public cpu_device, public arm7_disassembler::config { public: - // construction/destruction - arm7_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - void set_high_vectors() { m_vectorbase = 0xffff0000; } - -protected: enum { - ARCHFLAG_T = 1, // Thumb present - ARCHFLAG_E = 2, // extended DSP operations present (only for v5+) - ARCHFLAG_J = 4, // "Jazelle" (direct execution of Java bytecode) - ARCHFLAG_MMU = 8, // has on-board MMU (traditional ARM style like the SA1110) - ARCHFLAG_SA = 16, // StrongARM extensions (enhanced TLB) - ARCHFLAG_XSCALE = 32, // XScale extensions (CP14, enhanced TLB) - ARCHFLAG_MODE26 = 64, // supports 26-bit backwards compatibility mode - ARCHFLAG_K = 128, // enhanced MMU extensions present (only for v6) - ARCHFLAG_T2 = 256, //Thumb-2 present + ARM7_IRQ_LINE=0, ARM7_FIRQ_LINE, + ARM7_ABORT_EXCEPTION, ARM7_ABORT_PREFETCH_EXCEPTION, ARM7_UNDEFINE_EXCEPTION, + ARM7_NUM_LINES }; + // Really there's only 1 ABORT Line.. and cpu decides whether it's during data fetch or prefetch, but we let the user specify enum { - ARM9_COPRO_ID_STEP_SA1110_A0 = 0, - ARM9_COPRO_ID_STEP_SA1110_B0 = 4, - ARM9_COPRO_ID_STEP_SA1110_B1 = 5, - ARM9_COPRO_ID_STEP_SA1110_B2 = 6, - ARM9_COPRO_ID_STEP_SA1110_B4 = 8, - - ARM9_COPRO_ID_STEP_PXA255_A0 = 6, - - ARM9_COPRO_ID_STEP_ARM946_A0 = 1, - - ARM9_COPRO_ID_STEP_ARM1176JZF_S_R0P0 = 0, - ARM9_COPRO_ID_STEP_ARM1176JZF_S_R0P7 = 7, - - ARM9_COPRO_ID_PART_ARM1176JZF_S = 0xB76 << 4, - ARM9_COPRO_ID_PART_SA1110 = 0xB11 << 4, - ARM9_COPRO_ID_PART_ARM946 = 0x946 << 4, - ARM9_COPRO_ID_PART_ARM920 = 0x920 << 4, - ARM9_COPRO_ID_PART_ARM710 = 0x710 << 4, - ARM9_COPRO_ID_PART_GENERICARM7 = 0x700 << 4, - - ARM9_COPRO_ID_PXA255_CORE_REV_SHIFT = 10, - ARM9_COPRO_ID_PXA255_CORE_GEN_XSCALE = 0x01 << 13, - - ARM9_COPRO_ID_ARCH_V4 = 0x01 << 16, - ARM9_COPRO_ID_ARCH_V4T = 0x02 << 16, - ARM9_COPRO_ID_ARCH_V5 = 0x03 << 16, - ARM9_COPRO_ID_ARCH_V5T = 0x04 << 16, - ARM9_COPRO_ID_ARCH_V5TE = 0x05 << 16, - ARM9_COPRO_ID_ARCH_V5TEJ = 0x06 << 16, - ARM9_COPRO_ID_ARCH_V6 = 0x07 << 16, - ARM9_COPRO_ID_ARCH_CPUID = 0x0F << 16, - - ARM9_COPRO_ID_SPEC_REV0 = 0x00 << 20, - ARM9_COPRO_ID_SPEC_REV1 = 0x01 << 20, - - ARM9_COPRO_ID_MFR_ARM = 0x41 << 24, - ARM9_COPRO_ID_MFR_DEC = 0x44 << 24, - ARM9_COPRO_ID_MFR_INTEL = 0x69 << 24 + ARM7_PC = 0, + ARM7_R0, ARM7_R1, ARM7_R2, ARM7_R3, ARM7_R4, ARM7_R5, ARM7_R6, ARM7_R7, + ARM7_R8, ARM7_R9, ARM7_R10, ARM7_R11, ARM7_R12, ARM7_R13, ARM7_R14, ARM7_R15, + ARM7_FR8, ARM7_FR9, ARM7_FR10, ARM7_FR11, ARM7_FR12, ARM7_FR13, ARM7_FR14, + ARM7_IR13, ARM7_IR14, ARM7_SR13, ARM7_SR14, ARM7_FSPSR, ARM7_ISPSR, ARM7_SSPSR, + ARM7_CPSR, ARM7_AR13, ARM7_AR14, ARM7_ASPSR, ARM7_UR13, ARM7_UR14, ARM7_USPSR, ARM7_LOGTLB }; - arm7_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint8_t archRev, uint32_t archFlags, endianness_t endianness); + // construction/destruction + arm7_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + virtual ~arm7_cpu_device(); + + void set_high_vectors() { m_vectorbase = 0xffff0000; } + +protected: + enum arm_arch_flag : uint32_t; + enum arm_copro_id : uint32_t; + + arm7_cpu_device( + const machine_config &mconfig, + device_type type, + const char *tag, + device_t *owner, + uint32_t clock, + uint8_t archRev, + uint32_t archFlags, + endianness_t endianness, + address_map_constructor internal_map = address_map_constructor()); void postload(); - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; + // device_t implementation + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; - // device_execute_interface overrides - virtual uint32_t execute_min_cycles() const override { return 3; } - virtual uint32_t execute_max_cycles() const override { return 4; } - virtual uint32_t execute_input_lines() const override { return 4; } /* There are actually only 2 input lines: we use 3 variants of the ABORT line while there is only 1 real one */ + // device_execute_interface implementation + virtual uint32_t execute_min_cycles() const noexcept override { return 3; } + virtual uint32_t execute_max_cycles() const noexcept override { return 4; } virtual void execute_run() override; virtual void execute_set_input(int inputnum, int state) override; - // device_memory_interface overrides + // device_memory_interface implementation virtual space_config_vector memory_space_config() const override; - virtual bool memory_translate(int spacenum, int intention, offs_t &address) override; + virtual bool memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) override; - // device_state_interface overrides + // device_state_interface implementation virtual void state_export(const device_state_entry &entry) override; virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; - // device_disasm_interface overrides + // device_disasm_interface implementation virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; virtual bool get_t_flag() const override; + void translate_insn_command(const std::vector<std::string_view> ¶ms); + void translate_data_command(const std::vector<std::string_view> ¶ms); + void translate_command(const std::vector<std::string_view> ¶ms, int intention); + + void update_insn_prefetch(uint32_t curr_pc); + bool insn_fetch_thumb(uint32_t pc, uint32_t &out_insn); + bool insn_fetch_arm(uint32_t pc, uint32_t &out_insn); + + void add_ce_kernel_addr(offs_t addr, std::string value); + void init_ce_kernel_addrs(); + void print_ce_kernel_address(const offs_t addr); + + // for SoCs with onboard interrupt controllers - only call from scheduler or CPU's own context + void set_irq(int state); + void set_fiq(int state); + address_space_config m_program_config; + memory_access<32, 2, 0, ENDIANNESS_LITTLE>::cache m_cachele; + memory_access<32, 2, 0, ENDIANNESS_BIG>::cache m_cachebe; uint32_t m_r[/*NUM_REGS*/37]; - void update_insn_prefetch(uint32_t curr_pc); - virtual uint16_t insn_fetch_thumb(uint32_t pc); - uint32_t insn_fetch_arm(uint32_t pc); - int get_insn_prefetch_index(uint32_t address); + std::string m_ce_kernel_addrs[0x10400]; + bool m_ce_kernel_addr_present[0x10400]; uint32_t m_insn_prefetch_depth; uint32_t m_insn_prefetch_count; uint32_t m_insn_prefetch_index; uint32_t m_insn_prefetch_buffer[3]; uint32_t m_insn_prefetch_address[3]; + bool m_insn_prefetch_valid[3]; const uint32_t m_prefetch_word0_shift; const uint32_t m_prefetch_word1_shift; + int m_tlb_log; + int m_actual_log; + + struct tlb_entry + { + bool valid; + uint8_t domain; + uint8_t access; + uint32_t table_bits; + uint32_t base_addr; + uint8_t type; + }; + tlb_entry m_dtlb_entries[0x2000]; + tlb_entry m_itlb_entries[0x2000]; + uint8_t m_dtlb_entry_index[0x1000]; + uint8_t m_itlb_entry_index[0x1000]; bool m_pendingIrq; bool m_pendingFiq; @@ -179,7 +187,7 @@ protected: uint32_t m_domainAccessControl; uint8_t m_decoded_access_control[16]; - uint8_t m_archRev; // ARM architecture revision (3, 4, and 5 are valid) + uint8_t m_archRev; // ARM architecture revision (3, 4, 5, and 6 are valid) uint32_t m_archFlags; // architecture flags uint32_t m_vectorbase; @@ -231,8 +239,15 @@ protected: void arm9ops_e(uint32_t insn); void set_cpsr(uint32_t val); - bool arm7_tlb_translate(offs_t &addr, int flags, bool no_exception = false); - uint32_t arm7_tlb_get_second_level_descriptor( uint32_t granularity, uint32_t first_desc, uint32_t vaddr ); + bool translate_vaddr_to_paddr(offs_t &addr, const int flags); + bool page_table_finish_translation(offs_t &vaddr, const uint8_t type, const uint32_t lvl1, const uint32_t lvl2, const int flags, const uint32_t lvl1a, const uint32_t lvl2a); + bool page_table_translate(offs_t &vaddr, const int flags); + tlb_entry *tlb_map_entry(const offs_t vaddr, const int flags); + tlb_entry *tlb_probe(const offs_t vaddr, const int flags); + uint32_t get_fault_from_permissions(const uint8_t access, const uint8_t domain, const uint8_t type, const int flags); + uint32_t tlb_check_permissions(tlb_entry *entry, const int flags); + offs_t tlb_translate(tlb_entry *entry, const offs_t vaddr); + uint32_t get_lvl2_desc_from_page_table(uint32_t granularity, uint32_t first_desc, uint32_t vaddr); int detect_fault(int desc_lvl1, int ap, int flags); void arm7_check_irq_state(); void update_irq_state(); @@ -244,9 +259,9 @@ protected: virtual uint8_t arm7_cpu_read8(uint32_t addr); // Coprocessor support - DECLARE_WRITE32_MEMBER( arm7_do_callback ); - virtual DECLARE_READ32_MEMBER( arm7_rt_r_callback ); - virtual DECLARE_WRITE32_MEMBER( arm7_rt_w_callback ); + void arm7_do_callback(uint32_t data); + virtual uint32_t arm7_rt_r_callback(offs_t offset); + virtual void arm7_rt_w_callback(offs_t offset, uint32_t data); void arm7_dt_r_callback(uint32_t insn, uint32_t *prn); void arm7_dt_w_callback(uint32_t insn, uint32_t *prn); @@ -364,17 +379,17 @@ protected: /* fast RAM info */ struct fast_ram_info { - offs_t start; /* start of the RAM block */ - offs_t end; /* end of the RAM block */ - bool readonly; /* true if read-only */ - void * base; /* base in memory where the RAM lives */ + offs_t start = 0; /* start of the RAM block */ + offs_t end = 0; /* end of the RAM block */ + bool readonly = false; /* true if read-only */ + void * base = nullptr; /* base in memory where the RAM lives */ }; struct hotspot_info { - uint32_t pc; - uint32_t opcode; - uint32_t cycles; + uint32_t pc = 0; + uint32_t opcode = 0; + uint32_t cycles = 0; }; /* internal compiler state */ @@ -382,9 +397,9 @@ protected: { compiler_state &operator=(compiler_state const &) = delete; - uint32_t cycles; /* accumulated cycles */ - uint8_t checkints; /* need to check interrupts before next instruction */ - uint8_t checksoftints; /* need to check software interrupts before next instruction */ + uint32_t cycles = 0; /* accumulated cycles */ + uint8_t checkints = 0; /* need to check interrupts before next instruction */ + uint8_t checksoftints = 0; /* need to check software interrupts before next instruction */ uml::code_label labelnum; /* index for local labels */ }; @@ -392,45 +407,45 @@ protected: struct arm7imp_state { /* core state */ - drc_cache * cache; /* pointer to the DRC code cache */ - drcuml_state * drcuml; /* DRC UML generator state */ - //arm7_frontend * drcfe; /* pointer to the DRC front-end state */ - uint32_t drcoptions; /* configurable DRC options */ + std::unique_ptr<drc_cache> cache; /* pointer to the DRC code cache */ + std::unique_ptr<drcuml_state> drcuml; /* DRC UML generator state */ + //arm7_frontend * drcfe = nullptr; /* pointer to the DRC front-end state */ + uint32_t drcoptions = 0; /* configurable DRC options */ /* internal stuff */ - uint8_t cache_dirty; /* true if we need to flush the cache */ - uint32_t jmpdest; /* destination jump target */ + uint8_t cache_dirty = 0; /* true if we need to flush the cache */ + uint32_t jmpdest = 0; /* destination jump target */ /* parameters for subroutines */ - uint64_t numcycles; /* return value from gettotalcycles */ - uint32_t mode; /* current global mode */ - const char * format; /* format string for print_debug */ - uint32_t arg0; /* print_debug argument 1 */ - uint32_t arg1; /* print_debug argument 2 */ + uint64_t numcycles = 0; /* return value from gettotalcycles */ + uint32_t mode = 0; /* current global mode */ + const char * format = nullptr; /* format string for print_debug */ + uint32_t arg0 = 0; /* print_debug argument 1 */ + uint32_t arg1 = 0; /* print_debug argument 2 */ /* register mappings */ - uml::parameter regmap[/*NUM_REGS*/37]; /* parameter to register mappings for all 16 integer registers */ + uml::parameter regmap[/*NUM_REGS*/37]; /* parameter to register mappings for all 16 integer registers */ /* subroutines */ - uml::code_handle * entry; /* entry point */ - uml::code_handle * nocode; /* nocode exception handler */ - uml::code_handle * out_of_cycles; /* out of cycles exception handler */ - uml::code_handle * tlb_translate; /* tlb translation handler */ - uml::code_handle * detect_fault; /* tlb fault detection handler */ - uml::code_handle * check_irq; /* irq check handler */ - uml::code_handle * read8; /* read byte */ - uml::code_handle * write8; /* write byte */ - uml::code_handle * read16; /* read half */ - uml::code_handle * write16; /* write half */ - uml::code_handle * read32; /* read word */ - uml::code_handle * write32; /* write word */ + uml::code_handle * entry = nullptr; /* entry point */ + uml::code_handle * nocode = nullptr; /* nocode exception handler */ + uml::code_handle * out_of_cycles = nullptr; /* out of cycles exception handler */ + uml::code_handle * tlb_translate = nullptr; /* tlb translation handler */ + uml::code_handle * detect_fault = nullptr; /* tlb fault detection handler */ + uml::code_handle * check_irq = nullptr; /* irq check handler */ + uml::code_handle * read8 = nullptr; /* read byte */ + uml::code_handle * write8 = nullptr; /* write byte */ + uml::code_handle * read16 = nullptr; /* read half */ + uml::code_handle * write16 = nullptr; /* write half */ + uml::code_handle * read32 = nullptr; /* read word */ + uml::code_handle * write32 = nullptr; /* write word */ /* fast RAM */ - uint32_t fastram_select; + uint32_t fastram_select = 0; fast_ram_info fastram[ARM7_MAX_FASTRAM]; /* hotspots */ - uint32_t hotspot_select; + uint32_t hotspot_select = 0; hotspot_info hotspot[ARM7_MAX_HOTSPOTS]; } m_impstate; @@ -602,6 +617,13 @@ public: arm710a_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; +class arm710t_cpu_device : public arm7_cpu_device +{ +public: + // construction/destruction + arm710t_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + class arm9_cpu_device : public arm7_cpu_device { public: @@ -628,8 +650,8 @@ public: arm946es_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // 946E-S has Protection Unit instead of ARM MMU so CP15 is quite different - virtual DECLARE_READ32_MEMBER( arm7_rt_r_callback ) override; - virtual DECLARE_WRITE32_MEMBER( arm7_rt_w_callback ) override; + virtual uint32_t arm7_rt_r_callback(offs_t offset) override; + virtual void arm7_rt_w_callback(offs_t offset, uint32_t data) override; virtual void arm7_cpu_write32(uint32_t addr, uint32_t data) override; virtual void arm7_cpu_write16(uint32_t addr, uint16_t data) override; @@ -641,7 +663,7 @@ public: protected: arm946es_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - virtual void device_start() override; + virtual void device_start() override ATTR_COLD; private: uint32_t cp15_control, cp15_itcm_base, cp15_dtcm_base, cp15_itcm_size, cp15_dtcm_size; @@ -667,6 +689,12 @@ class arm1176jzf_s_cpu_device : public arm11_cpu_device public: // construction/destruction arm1176jzf_s_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual uint32_t arm7_rt_r_callback(offs_t offset) override; + virtual void arm7_rt_w_callback(offs_t offset, uint32_t data) override; + +protected: + virtual void device_reset() override ATTR_COLD; }; class igs036_cpu_device : public arm946es_cpu_device @@ -676,6 +704,13 @@ public: igs036_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; +class pxa250_cpu_device : public arm7_cpu_device +{ +public: + // construction/destruction + pxa250_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + class pxa255_cpu_device : public arm7_cpu_device { public: @@ -683,6 +718,19 @@ public: pxa255_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; +class pxa270_cpu_device : public arm7_cpu_device +{ +public: + // construction/destruction + pxa270_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + +class sa1100_cpu_device : public arm7_cpu_device +{ +public: + // construction/destruction + sa1100_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; class sa1110_cpu_device : public arm7_cpu_device { @@ -694,13 +742,17 @@ public: DECLARE_DEVICE_TYPE(ARM7, arm7_cpu_device) DECLARE_DEVICE_TYPE(ARM7_BE, arm7_be_cpu_device) DECLARE_DEVICE_TYPE(ARM710A, arm710a_cpu_device) +DECLARE_DEVICE_TYPE(ARM710T, arm710t_cpu_device) DECLARE_DEVICE_TYPE(ARM7500, arm7500_cpu_device) DECLARE_DEVICE_TYPE(ARM9, arm9_cpu_device) DECLARE_DEVICE_TYPE(ARM920T, arm920t_cpu_device) DECLARE_DEVICE_TYPE(ARM946ES, arm946es_cpu_device) DECLARE_DEVICE_TYPE(ARM11, arm11_cpu_device) DECLARE_DEVICE_TYPE(ARM1176JZF_S, arm1176jzf_s_cpu_device) +DECLARE_DEVICE_TYPE(PXA250, pxa250_cpu_device) DECLARE_DEVICE_TYPE(PXA255, pxa255_cpu_device) +DECLARE_DEVICE_TYPE(PXA270, pxa270_cpu_device) +DECLARE_DEVICE_TYPE(SA1100, sa1100_cpu_device) DECLARE_DEVICE_TYPE(SA1110, sa1110_cpu_device) DECLARE_DEVICE_TYPE(IGS036, igs036_cpu_device) diff --git a/src/devices/cpu/arm7/arm7core.h b/src/devices/cpu/arm7/arm7core.h index a6a7838bed4..64185a8aa28 100644 --- a/src/devices/cpu/arm7/arm7core.h +++ b/src/devices/cpu/arm7/arm7core.h @@ -5,7 +5,7 @@ * arm7core.h * Portable ARM7TDMI Core Emulator * - * Copyright Steve Ellenoff, all rights reserved. + * Copyright Steve Ellenoff * * This work is based on: * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999' @@ -18,38 +18,20 @@ ******************************************************************************/ +#ifndef MAME_CPU_ARM7_ARM7CORE_H +#define MAME_CPU_ARM7_ARM7CORE_H + #pragma once -#ifndef __ARM7CORE_H__ -#define __ARM7CORE_H__ +#include "arm7.h" #define ARM7_MMU_ENABLE_HACK 0 #define ARM7_DEBUG_CORE 0 /**************************************************************************************************** - * INTERRUPT LINES/EXCEPTIONS - ***************************************************************************************************/ -enum -{ - ARM7_IRQ_LINE=0, ARM7_FIRQ_LINE, - ARM7_ABORT_EXCEPTION, ARM7_ABORT_PREFETCH_EXCEPTION, ARM7_UNDEFINE_EXCEPTION, - ARM7_NUM_LINES -}; -// Really there's only 1 ABORT Line.. and cpu decides whether it's during data fetch or prefetch, but we let the user specify - -/**************************************************************************************************** * ARM7 CORE REGISTERS ***************************************************************************************************/ -enum -{ - ARM7_PC = 0, - ARM7_R0, ARM7_R1, ARM7_R2, ARM7_R3, ARM7_R4, ARM7_R5, ARM7_R6, ARM7_R7, - ARM7_R8, ARM7_R9, ARM7_R10, ARM7_R11, ARM7_R12, ARM7_R13, ARM7_R14, ARM7_R15, - ARM7_FR8, ARM7_FR9, ARM7_FR10, ARM7_FR11, ARM7_FR12, ARM7_FR13, ARM7_FR14, - ARM7_IR13, ARM7_IR14, ARM7_SR13, ARM7_SR14, ARM7_FSPSR, ARM7_ISPSR, ARM7_SSPSR, - ARM7_CPSR, ARM7_AR13, ARM7_AR14, ARM7_ASPSR, ARM7_UR13, ARM7_UR14, ARM7_USPSR -}; /* There are 36 Unique - 32 bit processor registers */ /* Each mode has 17 registers (except user & system, which have 16) */ @@ -83,6 +65,19 @@ enum }; /* Coprocessor-related macros */ +#define COPRO_DOMAIN_NO_ACCESS 0 +#define COPRO_DOMAIN_CLIENT 1 +#define COPRO_DOMAIN_RESV 2 +#define COPRO_DOMAIN_MANAGER 3 + +#define COPRO_FAULT_NONE 0 +#define COPRO_FAULT_TRANSLATE_SECTION 5 +#define COPRO_FAULT_TRANSLATE_PAGE 7 +#define COPRO_FAULT_DOMAIN_SECTION 9 +#define COPRO_FAULT_DOMAIN_PAGE 11 +#define COPRO_FAULT_PERM_SECTION 13 +#define COPRO_FAULT_PERM_PAGE 15 + #define COPRO_TLB_BASE m_tlbBase #define COPRO_TLB_BASE_MASK 0xffffc000 #define COPRO_TLB_VADDR_FLTI_MASK 0xfff00000 @@ -99,6 +94,9 @@ enum #define COPRO_TLB_LARGE_PAGE_MASK 0xffff0000 #define COPRO_TLB_SMALL_PAGE_MASK 0xfffff000 #define COPRO_TLB_TINY_PAGE_MASK 0xfffffc00 +#define COPRO_TLB_STABLE_MASK 0xfff00000 +#define COPRO_TLB_LSTABLE_MASK 0xfffff000 +#define COPRO_TLB_TTABLE_MASK 0xfffffc00 #define COPRO_TLB_UNMAPPED 0 #define COPRO_TLB_LARGE_PAGE 1 #define COPRO_TLB_SMALL_PAGE 2 @@ -106,6 +104,10 @@ enum #define COPRO_TLB_COARSE_TABLE 1 #define COPRO_TLB_SECTION_TABLE 2 #define COPRO_TLB_FINE_TABLE 3 +#define COPRO_TLB_TYPE_SECTION 0 +#define COPRO_TLB_TYPE_LARGE 1 +#define COPRO_TLB_TYPE_SMALL 2 +#define COPRO_TLB_TYPE_TINY 3 #define COPRO_CTRL m_control #define COPRO_CTRL_MMU_EN 0x00000001 @@ -187,6 +189,7 @@ struct arm_state /**************************************************************************************************** * VARIOUS INTERNAL STRUCS/DEFINES/ETC.. ***************************************************************************************************/ + // Mode values come from bit 4-0 of CPSR, but we are ignoring bit 4 here, since bit 4 always = 1 for valid modes enum { @@ -312,7 +315,7 @@ static const int sRegisterTable[ARM7_NUM_MODES][18] = #define T_IS_CLEAR(pc) (!T_IS_SET(pc)) /* Deconstructing an instruction */ -// todo: use these in all places (including dasm file) +// TODO: use these in all places (including dasm file) #define INSN_COND ((uint32_t)0xf0000000u) #define INSN_SDT_L ((uint32_t)0x00100000u) #define INSN_SDT_W ((uint32_t)0x00200000u) @@ -356,12 +359,14 @@ static const int sRegisterTable[ARM7_NUM_MODES][18] = #define INSN_RD_SHIFT 12 #define INSN_COND_SHIFT 28 +#define INSN_COPRO_OP1 ((uint32_t) 0x00e00000u) #define INSN_COPRO_N ((uint32_t) 0x00100000u) #define INSN_COPRO_CREG ((uint32_t) 0x000f0000u) #define INSN_COPRO_AREG ((uint32_t) 0x0000f000u) #define INSN_COPRO_CPNUM ((uint32_t) 0x00000f00u) #define INSN_COPRO_OP2 ((uint32_t) 0x000000e0u) #define INSN_COPRO_OP3 ((uint32_t) 0x0000000fu) +#define INSN_COPRO_OP1_SHIFT 21 #define INSN_COPRO_N_SHIFT 20 #define INSN_COPRO_CREG_SHIFT 16 #define INSN_COPRO_AREG_SHIFT 12 @@ -494,19 +499,69 @@ enum #define ARM7_TLB_WRITE (1 << 3) /* ARM flavors */ -enum arm_flavor +enum arm7_cpu_device::arm_arch_flag : uint32_t +{ + ARCHFLAG_T = 1U << 0, // Thumb present + ARCHFLAG_E = 1U << 1, // extended DSP operations present (only for v5+) + ARCHFLAG_J = 1U << 2, // "Jazelle" (direct execution of Java bytecode) + ARCHFLAG_MMU = 1U << 3, // has on-board MMU (traditional ARM style like the SA1110) + ARCHFLAG_SA = 1U << 4, // StrongARM extensions (enhanced TLB) + ARCHFLAG_XSCALE = 1U << 5, // XScale extensions (CP14, enhanced TLB) + ARCHFLAG_MODE26 = 1U << 6, // supports 26-bit backwards compatibility mode + ARCHFLAG_K = 1U << 7, // enhanced MMU extensions present (only for v6) + ARCHFLAG_T2 = 1U << 8, // Thumb-2 present +}; + +enum arm7_cpu_device::arm_copro_id : uint32_t { - /* ARM7 variants */ - ARM_TYPE_ARM7, - ARM_TYPE_ARM7BE, - ARM_TYPE_ARM7500, - ARM_TYPE_PXA255, - ARM_TYPE_SA1110, - - /* ARM9 variants */ - ARM_TYPE_ARM9, - ARM_TYPE_ARM920T, - ARM_TYPE_ARM946ES + ARM9_COPRO_ID_STEP_SA1100_A = 0, + ARM9_COPRO_ID_STEP_SA1100_B = 1, + ARM9_COPRO_ID_STEP_SA1100_C = 2, + ARM9_COPRO_ID_STEP_SA1100_D = 8, + ARM9_COPRO_ID_STEP_SA1100_E = 9, + ARM9_COPRO_ID_STEP_SA1100_G = 11, + + ARM9_COPRO_ID_STEP_SA1110_A0 = 0, + ARM9_COPRO_ID_STEP_SA1110_B0 = 4, + ARM9_COPRO_ID_STEP_SA1110_B1 = 5, + ARM9_COPRO_ID_STEP_SA1110_B2 = 6, + ARM9_COPRO_ID_STEP_SA1110_B4 = 8, + + ARM9_COPRO_ID_STEP_PXA255_A0 = 6, + + ARM9_COPRO_ID_STEP_ARM946_A0 = 1, + + ARM9_COPRO_ID_STEP_ARM1176JZF_S_R0P0 = 0, + ARM9_COPRO_ID_STEP_ARM1176JZF_S_R0P7 = 7, + + ARM9_COPRO_ID_PART_ARM1176JZF_S = 0xb76 << 4, + ARM9_COPRO_ID_PART_SA1100 = 0xa11 << 4, + ARM9_COPRO_ID_PART_SA1110 = 0xb11 << 4, + ARM9_COPRO_ID_PART_ARM946 = 0x946 << 4, + ARM9_COPRO_ID_PART_ARM920 = 0x920 << 4, + ARM9_COPRO_ID_PART_ARM710 = 0x710 << 4, + ARM9_COPRO_ID_PART_PXA250 = 0x200 << 4, + ARM9_COPRO_ID_PART_PXA255 = 0x2d0 << 4, + ARM9_COPRO_ID_PART_PXA270 = 0x411 << 4, + ARM9_COPRO_ID_PART_GENERICARM7 = 0x700 << 4, + + ARM9_COPRO_ID_PXA255_CORE_REV_SHIFT = 10, + + ARM9_COPRO_ID_ARCH_V4 = 0x01 << 16, + ARM9_COPRO_ID_ARCH_V4T = 0x02 << 16, + ARM9_COPRO_ID_ARCH_V5 = 0x03 << 16, + ARM9_COPRO_ID_ARCH_V5T = 0x04 << 16, + ARM9_COPRO_ID_ARCH_V5TE = 0x05 << 16, + ARM9_COPRO_ID_ARCH_V5TEJ = 0x06 << 16, + ARM9_COPRO_ID_ARCH_V6 = 0x07 << 16, + ARM9_COPRO_ID_ARCH_CPUID = 0x0f << 16, + + ARM9_COPRO_ID_SPEC_REV0 = 0x00 << 20, + ARM9_COPRO_ID_SPEC_REV1 = 0x01 << 20, + + ARM9_COPRO_ID_MFR_ARM = 0x41 << 24, + ARM9_COPRO_ID_MFR_DEC = 0x44 << 24, + ARM9_COPRO_ID_MFR_INTEL = 0x69 << 24 }; -#endif /* __ARM7CORE_H__ */ +#endif // MAME_CPU_ARM7_ARM7CORE_H diff --git a/src/devices/cpu/arm7/arm7core.hxx b/src/devices/cpu/arm7/arm7core.hxx index 8fba8e61b15..636019caa59 100644 --- a/src/devices/cpu/arm7/arm7core.hxx +++ b/src/devices/cpu/arm7/arm7core.hxx @@ -2,10 +2,10 @@ // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz /***************************************************************************** * - * arm7core.inc + * arm7core.hxx * Portable ARM7TDMI Core Emulator * - * Copyright Steve Ellenoff, all rights reserved. + * Copyright Steve Ellenoff * * This work is based on: * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999' @@ -113,7 +113,7 @@ void arm7_cpu_device::arm7_check_irq_state() // Data Abort if (m_pendingAbtD) { - if (MODE26) fatalerror( "ARM7: pendingAbtD (todo)\n"); + if (MODE26) fatalerror("ARM7: pendingAbtD (todo)\n"); SwitchMode(eARM7_MODE_ABT); /* Set ABT mode so PC is saved to correct R14 bank */ SetRegister(14, pc - 8 + 8); /* save PC to R14 */ SetRegister(SPSR, cpsr); /* Save current CPSR */ @@ -129,7 +129,8 @@ void arm7_cpu_device::arm7_check_irq_state() // FIQ if (m_pendingFiq && (cpsr & F_MASK) == 0) { - if (MODE26) fatalerror( "pendingFiq (todo)\n"); + standard_irq_callback(ARM7_FIRQ_LINE, pc); + if (MODE26) fatalerror("pendingFiq (todo)\n"); SwitchMode(eARM7_MODE_FIQ); /* Set FIQ mode so PC is saved to correct R14 bank */ SetRegister(14, pc - 4 + 4); /* save PC to R14 */ SetRegister(SPSR, cpsr); /* Save current CPSR */ @@ -144,6 +145,7 @@ void arm7_cpu_device::arm7_check_irq_state() // IRQ if (m_pendingIrq && (cpsr & I_MASK) == 0) { + standard_irq_callback(ARM7_IRQ_LINE, pc); SwitchMode(eARM7_MODE_IRQ); /* Set IRQ mode so PC is saved to correct R14 bank */ SetRegister(14, pc - 4 + 4); /* save PC to R14 */ if (MODE32) @@ -168,7 +170,7 @@ void arm7_cpu_device::arm7_check_irq_state() // Prefetch Abort if (m_pendingAbtP) { - if (MODE26) fatalerror( "pendingAbtP (todo)\n"); + if (MODE26) fatalerror("pendingAbtP (todo)\n"); SwitchMode(eARM7_MODE_ABT); /* Set ABT mode so PC is saved to correct R14 bank */ SetRegister(14, pc - 4 + 4); /* save PC to R14 */ SetRegister(SPSR, cpsr); /* Save current CPSR */ @@ -184,7 +186,7 @@ void arm7_cpu_device::arm7_check_irq_state() // Undefined instruction if (m_pendingUnd) { - if (MODE26) printf( "ARM7: pendingUnd (todo)\n"); + if (MODE26) printf("ARM7: pendingUnd (todo)\n"); SwitchMode(eARM7_MODE_UND); /* Set UND mode so PC is saved to correct R14 bank */ // compensate for prefetch (should this also be done for normal IRQ?) if (T_IS_SET(GET_CPSR)) diff --git a/src/devices/cpu/arm7/arm7dasm.cpp b/src/devices/cpu/arm7/arm7dasm.cpp index 61dbeada549..f597c5a58d3 100644 --- a/src/devices/cpu/arm7/arm7dasm.cpp +++ b/src/devices/cpu/arm7/arm7dasm.cpp @@ -2,10 +2,10 @@ // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz /***************************************************************************** * - * arm7dasm.c + * arm7dasm.cpp * Portable ARM7TDMI Core Emulator - Disassembler * - * Copyright Steve Ellenoff, all rights reserved. + * Copyright Steve Ellenoff * * This work is based on: * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999' @@ -38,14 +38,10 @@ void arm7_disassembler::DasmCoProc_RT(std::ostream &stream, uint32_t opcode, con /* co processor register transfer */ /* xxxx 1110 oooL nnnn dddd cccc ppp1 mmmm */ if( opcode&0x00100000 ) //Bit 20 = Load or Store - { - util::stream_format( stream, "MRC" ); - } + stream << "MRC"; else - { - util::stream_format( stream, "MCR" ); - } - util::stream_format( stream, "%s", pConditionCode ); + stream << "MCR"; + stream << pConditionCode; WritePadding(stream, start_position); util::stream_format( stream, "p%d, %d, R%d, c%d, c%d", (opcode>>8)&0xf, (opcode>>21)&7, (opcode>>12)&0xf, (opcode>>16)&0xf, opcode&0xf ); @@ -70,18 +66,24 @@ void arm7_disassembler::DasmCoProc_DT(std::ostream &stream, uint32_t opcode, con util::stream_format(stream, "[R%d%s",(opcode>>16)&0x0f,(opcode&0x1000000)?"":"]"); //If Bit 24 = 1, Pre-increment, otherwise, Post increment so close brace //immediate value ( 8 bit value is << 2 according to manual ) - if(opcode & 0xff) util::stream_format(stream, ",%s#$%x",(opcode&0x800000)?"":"-",(opcode & 0xff)<<2); + uint16_t imm = opcode & 0xff; + if(imm != 0) + util::stream_format(stream, ", #%s%s%X", (opcode&0x800000)?"":"-", (imm << 2) > 9 ? "0x" : "", imm << 2); //Pre-Inc brace & Write back - util::stream_format(stream, "%s%s",(opcode&0x1000000)?"]":"",(opcode&0x200000)?"{!}":""); + if(opcode&0x1000000) + { + stream << ']'; + if(opcode&0x200000) + stream << '!'; + } } void arm7_disassembler::DasmCoProc_DO(std::ostream &stream, uint32_t opcode, const char *pConditionCode, std::streampos start_position) { /* co processor data operation */ /* xxxx 1110 oooo nnnn dddd cccc ppp0 mmmm */ - util::stream_format( stream, "CDP" ); - util::stream_format( stream, "%s", pConditionCode ); + util::stream_format( stream, "CDP%s", pConditionCode ); WritePadding(stream, start_position); //p#,CPOpc,cd,cn,cm util::stream_format( stream, "p%d, %d, c%d, c%d, c%d", @@ -89,19 +91,29 @@ void arm7_disassembler::DasmCoProc_DO(std::ostream &stream, uint32_t opcode, con if((opcode>>5)&7) util::stream_format(stream, ", %d",(opcode>>5)&7); } -void arm7_disassembler::WriteImmediateOperand( std::ostream &stream, uint32_t opcode ) +uint32_t arm7_disassembler::ExtractImmediateOperand( uint32_t opcode ) { /* rrrrbbbbbbbb */ - uint32_t imm; - int r; + uint32_t imm = opcode&0xff; + int r = ((opcode>>8)&0xf)*2; + return rotr_32(imm, r); +} - imm = opcode&0xff; - r = ((opcode>>8)&0xf)*2; - imm = (imm>>r)|(r?(imm<<(32-r)):0); - util::stream_format( stream, ", #$%x", imm ); +void arm7_disassembler::WriteShiftCount( std::ostream &stream, uint32_t opcode ) +{ + if( opcode&0x10 ) /* Shift amount specified in bottom bits of RS */ + { + util::stream_format( stream, "R%d", (opcode>>8)&0xf ); + } + else /* Shift amount immediate 5 bit unsigned integer */ + { + int c=(opcode>>7)&0x1f; + if( c==0 ) c = 32; + util::stream_format( stream, "#%d", c ); + } } -void arm7_disassembler::WriteDataProcessingOperand( std::ostream &stream, uint32_t opcode, int printOp0, int printOp1, int printOp2 ) +void arm7_disassembler::WriteDataProcessingOperand( std::ostream &stream, uint32_t opcode, bool printOp0, bool printOp1 ) { /* ccccctttmmmm */ static const char *const pRegOp[4] = { "LSL","LSR","ASR","ROR" }; @@ -114,33 +126,25 @@ void arm7_disassembler::WriteDataProcessingOperand( std::ostream &stream, uint32 /* Immediate Op2 */ if (opcode & 0x02000000) { - stream.seekp(-2, std::ios_base::cur); - WriteImmediateOperand(stream, opcode); + uint32_t imm = ExtractImmediateOperand(opcode); + util::stream_format( stream, "#%s%X", imm > 9 ? "0x" : "", imm ); return; } /* Register Op2 */ - if (printOp2) -//SJE: pBuf += sprintf(pBuf,"R%d, ", (opcode>>0)&0xf); - util::stream_format(stream, "R%d ", (opcode>>0)&0xf); + util::stream_format(stream, "R%d", (opcode>>0)&0xf); //SJE: ignore if LSL#0 for register shift - if( ((opcode&0x2000000) == 0) && (((opcode>>4) & 0xff)==0) ) + if( ((opcode>>4) & 0xff)==0 ) return; - - util::stream_format(stream, ",%s ", pRegOp[(opcode>>5)&3]); - //SJE: pBuf += sprintf(pBuf, "%s ", pRegOp[(opcode>>5)&3] ); - - if( opcode&0x10 ) /* Shift amount specified in bottom bits of RS */ - { - util::stream_format( stream, "R%d", (opcode>>8)&0xf ); - } - else /* Shift amount immediate 5 bit unsigned integer */ + else if ( ((opcode>>4) & 0xff)==0x06 ) { - int c=(opcode>>7)&0x1f; - if( c==0 ) c = 32; - util::stream_format( stream, "#%d", c ); + stream << ", RRX"; + return; } + + util::stream_format(stream, ", %s ", pRegOp[(opcode>>5)&3]); + WriteShiftCount(stream, opcode); } void arm7_disassembler::WriteRegisterOperand1( std::ostream &stream, uint32_t opcode ) @@ -150,26 +154,23 @@ void arm7_disassembler::WriteRegisterOperand1( std::ostream &stream, uint32_t op util::stream_format( stream, - ", R%d", /* Operand 1 register, Operand 2 register, shift type */ + ", %sR%d", /* Operand 1 register, (optional) sign, Operand 2 register, shift type */ + (opcode&0x800000)?"":"-", (opcode >> 0) & 0xf); //check for LSL 0 - if ((((opcode >> 5) & 3) == 0) && (((opcode >> 7) & 0xf) == 0)) + if( ((opcode>>4) & 0xff)==0 ) return; - else - //Add rotation type - util::stream_format(stream, " %s ", pRegOp[(opcode >> 5) & 3]); - - if( opcode&0x10 ) /* Shift amount specified in bottom bits of RS */ + else if ( ((opcode>>4) & 0xff)==0x06 ) { - util::stream_format( stream, "R%d", (opcode>>7)&0xf ); - } - else /* Shift amount immediate 5 bit unsigned integer */ - { - int c=(opcode>>7)&0x1f; - if( c==0 ) c = 32; - util::stream_format( stream, "#%d", c ); + stream << ", RRX"; + return; } + + //Add rotation type + util::stream_format(stream, ", %s ", pRegOp[(opcode >> 5) & 3]); + + WriteShiftCount(stream, opcode); } /* WriteRegisterOperand */ @@ -180,24 +181,21 @@ void arm7_disassembler::WriteBranchAddress( std::ostream &stream, uint32_t pc, u { opcode |= 2; } - opcode &= 0x03fffffe; - if( opcode & 0x02000000 ) - { - opcode |= 0xfc000000; /* sign-extend */ - } + opcode = util::sext( opcode, 26 ); pc += 8+opcode; - util::stream_format( stream, "$%x", pc ); + util::stream_format( stream, "0x%08X", pc ); } /* WriteBranchAddress */ +static const char *const pConditionCodeTable[16] = +{ + "EQ","NE","CS","CC", + "MI","PL","VS","VC", + "HI","LS","GE","LT", + "GT","LE","","NV" +}; + u32 arm7_disassembler::arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t opcode ) { - static const char *const pConditionCodeTable[16] = - { - "EQ","NE","CS","CC", - "MI","PL","VS","VC", - "HI","LS","GE","LT", - "GT","LE","","NV" - }; static const char *const pOperation[16] = { "AND","EOR","SUB","RSB", @@ -205,12 +203,10 @@ u32 arm7_disassembler::arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t "TST","TEQ","CMP","CMN", "ORR","MOV","BIC","MVN" }; - const char *pConditionCode; + const char *pConditionCode = pConditionCodeTable[opcode>>28]; uint32_t dasmflags = 0; std::streampos start_position = stream.tellp(); - pConditionCode= pConditionCodeTable[opcode>>28]; - if( (opcode&0xfe000000)==0xfa000000 ) //bits 31-25 == 1111 101 (BLX - v5) { /* BLX(1) */ @@ -224,76 +220,63 @@ u32 arm7_disassembler::arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t else if( (opcode&0x0ff000f0)==0x01200030 ) // (BLX - v5) { /* BLX(2) */ - util::stream_format( stream, "BLX" ); + stream << "BLX"; dasmflags = STEP_OVER; + if (opcode < 0xe0000000) + dasmflags |= STEP_COND; WritePadding(stream, start_position); util::stream_format( stream, "R%d",(opcode&0xf)); } else if( (opcode&0x0ffffff0)==0x012fff10 ) //bits 27-4 == 000100101111111111110001 { /* Branch and Exchange (BX) */ - util::stream_format( stream, "B"); - util::stream_format( stream, "%sX", pConditionCode ); + util::stream_format( stream, "B%sX", pConditionCode ); WritePadding(stream, start_position); util::stream_format( stream, "R%d",(opcode&0xf)); if ((opcode & 0x0f) == 14) dasmflags = STEP_OUT; + if (opcode < 0xe0000000) + dasmflags |= STEP_COND; } else if ((opcode & 0x0ff000f0) == 0x01600010) // CLZ - v5 { - util::stream_format(stream, "CLZ"); + stream << "CLZ"; WritePadding(stream, start_position); util::stream_format(stream, "R%d, R%d", (opcode>>12)&0xf, opcode&0xf); } - else if ((opcode & 0x0ff000f0) == 0x01000050) // QADD - v5 - { - util::stream_format(stream, "QADD"); - WritePadding(stream, start_position); - util::stream_format(stream, "R%d, R%d, R%d", (opcode>>12)&0xf, opcode&0xf, (opcode>>16)&0xf); - } - else if ((opcode & 0x0ff000f0) == 0x01400050) // QDADD - v5 - { - util::stream_format(stream, "QDADD"); - WritePadding(stream, start_position); - util::stream_format(stream, "R%d, R%d, R%d", (opcode>>12)&0xf, opcode&0xf, (opcode>>16)&0xf); - } - else if ((opcode & 0x0ff000f0) == 0x01200050) // QSUB - v5 + else if ((opcode & 0x0f9000f0) == 0x01000050) // Q(D)ADD, Q(D)SUB - v5TE { - util::stream_format(stream, "QSUB"); + util::stream_format(stream, "Q%s%s", (opcode & 0x00400000) != 0 ? "D" : "", (opcode & 0x00200000) != 0 ? "SUB" : "ADD"); WritePadding(stream, start_position); - util::stream_format(stream, "R%d, R%d, R%d", (opcode>>12)&0xf, opcode&0xf, (opcode>>16)&0xf); + if (((opcode>>12)&0xf) != (opcode&0xf)) + util::stream_format(stream, "R%d, ", (opcode>>12)&0xf); + util::stream_format(stream, "R%d, R%d", opcode&0xf, (opcode>>16)&0xf); } - else if ((opcode & 0x0ff000f0) == 0x01600050) // QDSUB - v5 - { - util::stream_format(stream, "QDSUB"); - WritePadding(stream, start_position); - util::stream_format(stream, "R%d, R%d, R%d", (opcode>>12)&0xf, opcode&0xf, (opcode>>16)&0xf); - } - else if ((opcode & 0x0ff00090) == 0x01000080) // SMLAxy - v5 + else if ((opcode & 0x0ff00090) == 0x01000080) // SMLAxy - v5TE { util::stream_format(stream, "SMLA%c%c", (opcode&0x20) ? 'T' : 'B', (opcode&0x40) ? 'T' : 'B'); WritePadding(stream, start_position); util::stream_format(stream, "R%d, R%d, R%d, R%d", (opcode>>16)&0xf, (opcode>>12)&0xf, opcode&0xf, (opcode>>8)&0xf); } - else if ((opcode & 0x0ff00090) == 0x01400080) // SMLALxy - v5 + else if ((opcode & 0x0ff00090) == 0x01400080) // SMLALxy - v5TE { util::stream_format(stream, "SMLAL%c%c", (opcode&0x20) ? 'T' : 'B', (opcode&0x40) ? 'T' : 'B'); WritePadding(stream, start_position); util::stream_format(stream, "R%d, R%d, R%d, R%d", (opcode>>16)&0xf, (opcode>>12)&0xf, opcode&0xf, (opcode>>8)&0xf); } - else if ((opcode & 0x0ff00090) == 0x01600080) // SMULxy - v5 + else if ((opcode & 0x0ff00090) == 0x01600080) // SMULxy - v5TE { util::stream_format(stream, "SMUL%c%c", (opcode&0x20) ? 'T' : 'B', (opcode&0x40) ? 'T' : 'B'); WritePadding(stream, start_position); util::stream_format(stream, "R%d, R%d, R%d", (opcode>>16)&0xf, opcode&0xf, (opcode>>12)&0xf); } - else if ((opcode & 0x0ff000b0) == 0x012000a0) // SMULWy - v5 + else if ((opcode & 0x0ff000b0) == 0x012000a0) // SMULWy - v5TE { util::stream_format(stream, "SMULW%c", (opcode&0x40) ? 'T' : 'B'); WritePadding(stream, start_position); util::stream_format(stream, "R%d, R%d, R%d", (opcode>>16)&0xf, opcode&0xf, (opcode>>8)&0xf); } - else if ((opcode & 0x0ff000b0) == 0x01200080) // SMLAWy - v5 + else if ((opcode & 0x0ff000b0) == 0x01200080) // SMLAWy - v5TE { util::stream_format(stream, "SMLAW%c", (opcode&0x40) ? 'T' : 'B'); WritePadding(stream, start_position); @@ -305,56 +288,72 @@ u32 arm7_disassembler::arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t if(opcode&0x60) { //bits = 6-5 != 00 /* half word data transfer */ - if (((opcode & 0x60) == 0x40) && !(opcode & 0x100000)) // bit 20 = 0, bits 5&6 = 10 is ARMv5 LDRD + if (((opcode & 0x60) == 0x40) && !(opcode & 0x100000)) // bit 20 = 0, bits 5&6 = 10 is ARMv5TE LDRD { - util::stream_format(stream, "LDRD%s", pConditionCode); + stream << "LDRD"; } - else if (((opcode & 0x60) == 0x60) && !(opcode & 0x100000)) // bit 20 = 0, bits 5&6 = 11 is ARMv5 STRD + else if (((opcode & 0x60) == 0x60) && !(opcode & 0x100000)) // bit 20 = 0, bits 5&6 = 11 is ARMv5TE STRD { - util::stream_format(stream, "STRD%s", pConditionCode); + stream << "STRD"; } else { - util::stream_format(stream, "%s%s",(opcode&0x00100000)?"LDR":"STR",pConditionCode); //Bit 20 = 1 for Load, 0 for Store + //Bit 20 = 1 for Load, 0 for Store + if (opcode & 0x00100000) + stream << "LDR"; + else + stream << "STR"; //Signed? (if not, always unsigned half word) if(opcode&0x40) - { - util::stream_format(stream, "%s",(opcode&0x20)?"SH":"SB"); //Bit 5 = 1 for Half Word, 0 for Byte - } + util::stream_format(stream, "S%c", (opcode & 0x20) ? 'H' : 'B'); //Bit 5 = 1 for Half Word, 0 for Byte else - { - util::stream_format(stream, "H"); - } + stream << 'H'; } + stream << pConditionCode; WritePadding(stream, start_position); //Dest Register util::stream_format(stream, "R%d, ",(opcode>>12)&0x0f); //Base Register - util::stream_format(stream, "[R%d%s",(opcode>>16)&0x0f,(opcode&0x1000000)?"":"]"); //If Bit 24 = 1, Pre-increment, otherwise, Post increment so close brace - - //Immediate or Register Offset? - if(opcode&0x400000) { //Bit 22 - 1 = immediate, 0 = register - //immediate ( imm. value in high nibble (bits 8-11) and lo nibble (bit 0-3) ) - util::stream_format(stream, ",%s#$%x",(opcode&0x800000)?"":"-",( (((opcode>>8)&0x0f)<<4) | (opcode&0x0f))); + int rn = (opcode>>16)&0x0f; + if (rn == 15 && (opcode&0x1400000) == 0x1400000) { + uint8_t imm = ((opcode>>4)&0xf0) | (opcode&0x0f); + util::stream_format(stream, "0x%08X", uint32_t(pc + 8 + ((opcode&0x800000) ? imm : -imm))); } else { - //register - util::stream_format(stream, ",%sR%d",(opcode&0x800000)?"":"-",(opcode & 0x0f)); + util::stream_format(stream, "[R%d%s", rn, (opcode&0x1000000)?"":"]"); //If Bit 24 = 1, Pre-increment, otherwise, Post increment so close brace + + //Immediate or Register Offset? + if(opcode&0x400000) { //Bit 22 - 1 = immediate, 0 = register + //immediate ( imm. value in high nibble (bits 8-11) and lo nibble (bit 0-3) ) + uint8_t imm = ((opcode>>4)&0xf0) | (opcode&0x0f); + if(imm) + util::stream_format(stream, ", #%s%s%X", (opcode&0x800000)?"":"-", imm > 9 ? "0x" : "", imm); + } + else { + //register + util::stream_format(stream, ", %sR%d", (opcode&0x800000)?"":"-", opcode & 0x0f); + } } //Pre-Inc brace & Write back - util::stream_format(stream, "%s%s",(opcode&0x1000000)?"]":"",(opcode&0x200000)?"{!}":""); + if(opcode&0x1000000) + { + stream << ']'; + if(opcode&0x200000) + stream << '!'; + } } else { if(opcode&0x01000000) { //bit 24 = 1 /* swap */ //todo: Test on valid instructions /* xxxx 0001 0B00 nnnn dddd 0000 1001 mmmm */ - util::stream_format( stream, "SWP" ); - util::stream_format( stream, "%s%s", pConditionCode, (opcode & 0x400000)?"B":"" ); //Bit 22 = Byte/Word selection + util::stream_format( stream, "SWP%s%s", pConditionCode, (opcode & 0x400000)?"B":"" ); //Bit 22 = Byte/Word selection + WritePadding(stream, start_position); + //Rd, Rm, [Rn] util::stream_format( stream, "R%d, R%d, [R%d]", (opcode>>12)&0xf, opcode&0xf, (opcode>>16)&0xf ); @@ -369,20 +368,20 @@ u32 arm7_disassembler::arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t /* Signed? */ if( opcode&0x00400000 ) - util::stream_format( stream, "S" ); + stream << 'S'; else - util::stream_format( stream, "U" ); + stream << 'U'; /* Multiply & Accumulate? */ if( opcode&0x00200000 ) { - util::stream_format( stream, "MLAL" ); + stream << "MLAL"; } else { - util::stream_format( stream, "MULL" ); + stream << "MULL"; } - util::stream_format( stream, "%s", pConditionCode ); + stream << pConditionCode; /* Set Status Flags */ if( opcode&0x00100000 ) @@ -396,7 +395,7 @@ u32 arm7_disassembler::arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t "R%d, R%d, R%d, R%d", (opcode>>12)&0xf, (opcode>>16)&0xf, - (opcode&0xf), + opcode&0xf, (opcode>>8)&0xf); } else @@ -407,14 +406,14 @@ u32 arm7_disassembler::arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t /* Multiply & Accumulate? */ if( opcode&0x00200000 ) { - util::stream_format( stream, "MLA" ); + stream << "MLA"; } /* Multiply */ else { - util::stream_format( stream, "MUL" ); + stream << "MUL"; } - util::stream_format( stream, "%s", pConditionCode ); + stream << pConditionCode; if( opcode&0x00100000 ) { stream << 'S'; @@ -424,7 +423,7 @@ u32 arm7_disassembler::arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t util::stream_format(stream, "R%d, R%d, R%d", (opcode>>16)&0xf, - (opcode&0xf), + opcode&0xf, (opcode>>8)&0xf); if( opcode&0x00200000 ) @@ -440,24 +439,44 @@ u32 arm7_disassembler::arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t /* Data Processing OR PSR Transfer */ //SJE: check for MRS & MSR ( S bit must be clear, and bit 24,23 = 10 ) - if( ((opcode&0x00100000)==0) && ((opcode&0x01800000)==0x01000000) ) { - std::string strpsr = util::string_format("%s",(opcode&0x400000)?"SPSR":"CPSR"); - - //MSR ( bit 21 set ) - if( (opcode&0x00200000) ) { - util::stream_format(stream, "MSR%s",pConditionCode ); - //Flag Bits Only? (Bit 16 Clear) - if( (opcode&0x10000)==0) util::stream_format(stream, "F"); + if( ((opcode&0x00100000)==0) && ((opcode&0x01800000)==0x01000000) ) + { + if ((opcode & 0xf26000f0) == 0xe0200070) + { + stream << "BKPT"; // v5 WritePadding(stream, start_position); - util::stream_format(stream, "%s,", strpsr); - WriteDataProcessingOperand(stream, opcode, (opcode&0x02000000)?1:0, 0, 1); + util::stream_format(stream, "0x%04X", (opcode & 0xfff00) >> 4 | (opcode & 0xf)); + dasmflags = STEP_OVER; } - //MRS ( bit 21 clear ) - else { - util::stream_format(stream, "MRS%s", pConditionCode ); - WritePadding(stream, start_position); - util::stream_format(stream, "R%d,", (opcode>>12)&0x0f); - util::stream_format(stream, "%s", strpsr); + else + { + std::string strpsr = util::string_format("%cPSR", (opcode&0x400000) ? 'S' : 'C'); + + //MSR ( bit 21 set ) + if( (opcode&0x00200000) ) { + util::stream_format(stream, "MSR%s",pConditionCode ); + if( (opcode&0xf0000) != 0xf0000) + { + strpsr += '_'; + if (BIT(opcode, 19)) + strpsr += 'f'; + if (BIT(opcode, 18)) + strpsr += 'x'; + if (BIT(opcode, 17)) + strpsr += 's'; + if (BIT(opcode, 16)) + strpsr += 'c'; + } + WritePadding(stream, start_position); + util::stream_format(stream, "%s, ", strpsr); + WriteDataProcessingOperand(stream, opcode, false, false); + } + //MRS ( bit 21 clear ) + else { + util::stream_format(stream, "MRS%s", pConditionCode ); + WritePadding(stream, start_position); + util::stream_format(stream, "R%d, %s", (opcode>>12)&0x0f, strpsr); + } } } else { @@ -465,14 +484,41 @@ u32 arm7_disassembler::arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t /* xxxx001a aaaSnnnn ddddrrrr bbbbbbbb */ /* xxxx000a aaaSnnnn ddddcccc ctttmmmm */ int op=(opcode>>21)&0xf; - util::stream_format( - stream, "%s%s", - pOperation[op], - pConditionCode); + bool is_adr = (op == 0x02 || op == 0x04) && ((opcode >> 16) & 0x0f) == 15 && (opcode & 0x02000000) != 0; + bool is_shift = (op == 0x0d) && (opcode & 0x02000000) == 0 && (opcode & 0x00000fe0) != 0; + if( is_adr ) + stream << "ADR"; + else if( is_shift ) + { + switch( (opcode>>5) & 3 ) + { + case 0: + stream << "LSL"; + break; + + case 1: + stream << "LSR"; + break; + + case 2: + stream << "ASR"; + break; + + case 3: + if ( (opcode & 0x00000f90) == 0 ) + stream << "RRX"; + else + stream << "ROR"; + break; + } + } + else + stream << pOperation[op]; + stream << pConditionCode; //SJE: corrected S-Bit bug here //if( (opcode&0x01000000) ) - if( (opcode&0x0100000) ) + if( (opcode&0x0100000) && (op & 0x0c) != 0x08 ) { stream << 'S'; } @@ -480,108 +526,144 @@ u32 arm7_disassembler::arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t WritePadding(stream, start_position); switch (op) { + case 0x02: + // check for SUBS PC, LR, #imm + if (((opcode >> 12) & 0x0f) == 15) + { + if (((opcode >> 0) & 0x0f) == 14 && (opcode & 0x02100000) == 0x02100000) + dasmflags = STEP_OUT; + if (opcode < 0xe0000000) + dasmflags |= STEP_COND; + } + [[fallthrough]]; + case 0x04: + if (is_adr) + { + uint32_t adr = pc + 8; + if (op == 0x02) + adr -= ExtractImmediateOperand(opcode); + else + adr += ExtractImmediateOperand(opcode); + util::stream_format( stream, "R%d, 0x%08X", (opcode >> 12) & 0x0f, adr ); + break; + } + [[fallthrough]]; case 0x00: case 0x01: - case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: case 0x0c: case 0x0e: - WriteDataProcessingOperand(stream, opcode, 1, 1, 1); + WriteDataProcessingOperand(stream, opcode, ((opcode>>12)&0xf) != ((opcode>>16)&0xf), true); break; case 0x08: case 0x09: case 0x0a: case 0x0b: - WriteDataProcessingOperand(stream, opcode, 0, 1, 1); + WriteDataProcessingOperand(stream, opcode, false, true); break; case 0x0d: + if (is_shift) + { + uint8_t rd = (opcode >> 12) & 0x0f; + uint8_t rs = (opcode >> 0) & 0x0f; + if ( rd != rs ) + util::stream_format( stream, "R%d, ", rd ); + util::stream_format( stream, "R%d", rs ); + if ( (opcode & 0x00000ff0) != 0x00000060 ) + { + stream << ", "; + WriteShiftCount(stream, opcode); + } + break; + } /* look for mov pc,lr */ - if (((opcode >> 12) & 0x0f) == 15 && ((opcode >> 0) & 0x0f) == 14 && (opcode & 0x02000000) == 0) - dasmflags = STEP_OUT; + if (((opcode >> 12) & 0x0f) == 15) + { + if (((opcode >> 0) & 0x0f) == 14 && (opcode & 0x02000000) == 0) + dasmflags = STEP_OUT; + if (opcode < 0xe0000000) + dasmflags |= STEP_COND; + } + [[fallthrough]]; case 0x0f: - WriteDataProcessingOperand(stream, opcode, 1, 0, 1); + WriteDataProcessingOperand(stream, opcode, true, false); break; } } } else if( (opcode&0x0c000000)==0x04000000 ) //bits 27-26 == 01 { - uint32_t rn; - uint32_t rnv = 0; - /* Data Transfer */ /* xxxx010P UBWLnnnn ddddoooo oooooooo Immediate form */ /* xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register form */ - if( opcode&0x00100000 ) - { - util::stream_format( stream, "LDR" ); - } + if ((opcode & 0xf050f000) == 0xf050f000) + stream << "PLD"; // preload hint - v5TE else { - util::stream_format( stream, "STR" ); - } - util::stream_format( stream, "%s", pConditionCode ); - - if( opcode&0x00400000 ) - { - util::stream_format( stream, "B" ); - } + if( opcode&0x00100000 ) + stream << "LDR"; + else + stream << "STR"; + stream << pConditionCode; - if( opcode&0x00200000 ) - { - /* writeback addr */ - if( opcode&0x01000000 ) + if( opcode&0x00400000 ) { - /* pre-indexed addressing */ - util::stream_format( stream, "!" ); + stream << 'B'; } - else + if( (opcode&0x01200000) == 0x00200000 ) { - /* post-indexed addressing */ - util::stream_format( stream, "T" ); + stream << 'T'; } } WritePadding(stream, start_position); - util::stream_format( stream, "R%d, [R%d", - (opcode>>12)&0xf, (opcode>>16)&0xf ); - - //grab value of pc if used as base register - rn = (opcode>>16)&0xf; - if(rn==15) rnv = pc+8; + if ((opcode & 0xf050f000) != 0xf050f000) + util::stream_format( stream, "R%d, ", (opcode>>12)&0xf); + int rn = (opcode>>16)&0xf; if( opcode&0x02000000 ) { /* register form */ - util::stream_format( stream, "%s",(opcode&0x01000000)?"":"]" ); + util::stream_format( stream, "[R%d%s", rn, (opcode&0x01000000)?"":"]" ); WriteRegisterOperand1(stream, opcode); - util::stream_format( stream, "%s",(opcode&0x01000000)?"]":"" ); + if( opcode&0x01000000 ) + stream << ']'; + } + else if(rn==15) + { + uint32_t rnv = pc + 8; + if( opcode&0x00800000 ) + rnv += opcode&0xfff; + else + rnv -= opcode&0xfff; + util::stream_format( stream, "0x%08X", rnv); } else { /* immediate form */ - util::stream_format( stream, "%s",(opcode&0x01000000)?"":"]" ); + util::stream_format( stream, "[R%d%s", rn, (opcode&0x01000000)?"":"]" ); + //hide zero offsets if(opcode&0xfff) { - if( opcode&0x00800000 ) - { - util::stream_format( stream, ", #$%x", opcode&0xfff ); - rnv += (rnv)?opcode&0xfff:0; - } - else - { - util::stream_format( stream, ", -#$%x", opcode&0xfff ); - rnv -= (rnv)?opcode&0xfff:0; - } + stream << ", #"; + if( !(opcode&0x00800000 )) + stream << '-'; + if( (opcode&0xfff) > 9) + stream << "0x"; + util::stream_format( stream, "%X", opcode&0xfff ); } - util::stream_format( stream, "%s",(opcode&0x01000000)?"]":"" ); - //show where the read will occur if we found a value - if(rnv) util::stream_format( stream, " (%x)",rnv); + if( opcode&0x01000000 ) + stream << ']'; + } + + if ( (opcode&0x01200000) == 0x01200000 ) + { + /* writeback addr */ + stream << '!'; } } else if( (opcode&0x0e000000) == 0x08000000 ) //bits 27-25 == 100 @@ -589,59 +671,62 @@ u32 arm7_disassembler::arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t /* xxxx100P USWLnnnn llllllll llllllll */ /* Block Data Transfer */ + int rn = (opcode>>16)&0xf; if( opcode&0x00100000 ) { - util::stream_format( stream, "LDM" ); + util::stream_format( stream, "LDM%s", pConditionCode ); + if (rn == 13) + util::stream_format( stream, "%c%c", (opcode&0x01000000) ? 'E' : 'F', (opcode&0x00800000) ? 'D' : 'A'); + else + util::stream_format( stream, "%c%c", (opcode&0x00800000) ? 'I' : 'D', (opcode&0x01000000) ? 'B' : 'A'); } else { - util::stream_format( stream, "STM" ); - } - util::stream_format( stream, "%s", pConditionCode ); - - if( opcode&0x01000000 ) - { - util::stream_format( stream, "P" ); - } - if( opcode&0x00800000 ) - { - util::stream_format( stream, "U" ); - } - if( opcode&0x00400000 ) - { - util::stream_format( stream, "^" ); - } - if( opcode&0x00200000 ) - { - util::stream_format( stream, "W" ); + util::stream_format( stream, "STM%s", pConditionCode ); + if (rn == 13) + util::stream_format( stream, "%c%c", (opcode&0x01000000) ? 'F' : 'E', (opcode&0x00800000) ? 'A' : 'D'); + else + util::stream_format( stream, "%c%c", (opcode&0x00800000) ? 'I' : 'D', (opcode&0x01000000) ? 'B' : 'A'); } WritePadding(stream, start_position); - util::stream_format(stream, "[R%d], {",(opcode>>16)&0xf); + util::stream_format( stream, "R%d", rn ); + if( opcode&0x00200000 ) + stream << '!'; + stream << ", {"; { int j=0,last=0,found=0; for (j=0; j<16; j++) { if (opcode&(1<<j) && found==0) { + if (opcode&((1<<j)-1)) + stream << ", "; found=1; last=j; } else if ((opcode&(1<<j))==0 && found) { - if (last==j-1) - util::stream_format(stream, " R%d,",last); - else - util::stream_format(stream, " R%d-R%d,",last,j-1); + util::stream_format(stream, "R%d", last); + if (last!=j-1) + util::stream_format(stream, "-R%d", j-1); found=0; } } - if (found && last==15) - util::stream_format(stream, " R15,"); - else if (found) - util::stream_format(stream, " R%d-R%d,",last,15); + if (found) { + if (last != 15) + util::stream_format(stream, "R%d-", last); + stream << "R15"; + dasmflags = STEP_OUT; + if (opcode < 0xe0000000) + dasmflags |= STEP_COND; + } } - stream.seekp(-1, std::ios::cur); - util::stream_format(stream, " }"); + stream << '}'; + + if( opcode&0x00400000 ) + { + util::stream_format( stream, "^" ); + } } else if( (opcode&0x0e000000)==0x0a000000 ) //bits 27-25 == 101 { @@ -657,7 +742,9 @@ u32 arm7_disassembler::arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t util::stream_format( stream, "B" ); } - util::stream_format( stream, "%s", pConditionCode ); + stream << pConditionCode; + if (opcode < 0xe0000000) + dasmflags |= STEP_COND; WritePadding(stream, start_position); @@ -666,7 +753,10 @@ u32 arm7_disassembler::arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t else if( (opcode&0x0e000000)==0x0c000000 ) //bits 27-25 == 110 { /* co processor data transfer */ - DasmCoProc_DT(stream, opcode, (char*)pConditionCode, start_position); + if (opcode >= 0xf0000000) + DasmCoProc_DT(stream, opcode, "2", start_position); // LDC2, STC2 - v5 + else + DasmCoProc_DT(stream, opcode, pConditionCode, start_position); } else if( (opcode&0x0f000000)==0x0e000000 ) //bits 27-24 == 1110 { @@ -686,10 +776,12 @@ u32 arm7_disassembler::arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t else if( (opcode&0x0f000000) == 0x0f000000 ) //bits 27-24 == 1111 { /* Software Interrupt */ - util::stream_format( stream, "SWI%s $%x", - pConditionCode, - opcode&0x00ffffff ); + util::stream_format( stream, "SWI%s", pConditionCode ); + WritePadding(stream, start_position); + util::stream_format( stream, "0x%X", opcode&0x00ffffff ); dasmflags = STEP_OVER; + if (opcode < 0xe0000000) + dasmflags |= STEP_COND; } else { @@ -703,624 +795,592 @@ u32 arm7_disassembler::thumb_disasm(std::ostream &stream, uint32_t pc, uint16_t std::streampos start_position = stream.tellp(); uint32_t dasmflags = 0; -// uint32_t readword; - uint32_t addr; - uint32_t rm, rn, rs, rd, op2, imm;//, rrs; - int32_t offs; +// uint32_t readword; + uint32_t addr; + uint16_t rm, rn, rs, rd, imm;//, rrs; + int32_t offs; - WritePadding(stream, start_position); - - - switch( ( opcode & THUMB_INSN_TYPE ) >> THUMB_INSN_TYPE_SHIFT ) + switch( ( opcode & THUMB_INSN_TYPE ) >> THUMB_INSN_TYPE_SHIFT ) + { + case 0x0: /* Logical shifting */ + rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + offs = ( opcode & THUMB_SHIFT_AMT ) >> THUMB_SHIFT_AMT_SHIFT; + if( opcode & THUMB_SHIFT_R ) /* Shift right */ { - case 0x0: /* Logical shifting */ - if( opcode & THUMB_SHIFT_R ) /* Shift right */ - { - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - offs = ( opcode & THUMB_SHIFT_AMT ) >> THUMB_SHIFT_AMT_SHIFT; - util::stream_format( stream, "LSR R%d, R%d, %d", rd, rs, offs); - } - else /* Shift left */ - { - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - offs = ( opcode & THUMB_SHIFT_AMT ) >> THUMB_SHIFT_AMT_SHIFT; - util::stream_format( stream, "LSL R%d, R%d, %d", rd, rs, offs); - } - break; - case 0x1: /* Arithmetic */ - if( opcode & THUMB_INSN_ADDSUB ) - { - switch( ( opcode & THUMB_ADDSUB_TYPE ) >> THUMB_ADDSUB_TYPE_SHIFT ) - { - case 0x0: /* ADD Rd, Rs, Rn */ - rn = ( opcode & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT; - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "ADD R%d, R%d, R%d", rd, rs, rn ); - break; - case 0x1: /* SUB Rd, Rs, Rn */ - rn = ( opcode & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT; - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "SUB R%d, R%d, R%d", rd, rs, rn ); - break; - case 0x2: /* ADD Rd, Rs, #imm */ - imm = ( opcode & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT; - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "ADD R%d, R%d, #%d", rd, rs, imm ); - break; - case 0x3: /* SUB Rd, Rs, #imm */ - imm = ( opcode & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT; - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "SUB R%d, R%d, #%d", rd, rs, imm ); - break; - default: - util::stream_format(stream, "INVALID %04x", opcode); - break; - } - } - else - { - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - offs = ( opcode & THUMB_SHIFT_AMT ) >> THUMB_SHIFT_AMT_SHIFT; - util::stream_format( stream, "ASR R%d, R%d, %d", rd, rs, offs); - } - break; - case 0x2: /* CMP / MOV */ - if( opcode & THUMB_INSN_CMP ) - { - rn = ( opcode & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT; - op2 = ( opcode & THUMB_INSN_IMM ); - util::stream_format( stream, "CMP R%d, %02x", rn, op2 ); - } - else - { - rd = ( opcode & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT; - op2 = ( opcode & THUMB_INSN_IMM ); - util::stream_format( stream, "MOV R%d, %02x", rd, op2 ); - } - break; - case 0x3: /* ADD/SUB immediate */ - if( opcode & THUMB_INSN_SUB ) /* SUB Rd, #Offset8 */ - { - rn = ( opcode & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT; - op2 = ( opcode & THUMB_INSN_IMM ); - util::stream_format( stream, "SUB R%d, %02x", rn, op2 ); // fixed, rd -> rn - } - else /* ADD Rd, #Offset8 */ - { - rn = ( opcode & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT; - op2 = opcode & THUMB_INSN_IMM; - util::stream_format( stream, "ADD R%d, %02x", rn, op2 ); - } - break; - case 0x4: /* Rd & Rm instructions */ - switch( ( opcode & THUMB_GROUP4_TYPE ) >> THUMB_GROUP4_TYPE_SHIFT ) - { - case 0x0: - switch( ( opcode & THUMB_ALUOP_TYPE ) >> THUMB_ALUOP_TYPE_SHIFT ) - { - case 0x0: /* AND Rd, Rs */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "AND R%d, R%d", rd, rs ); - break; - case 0x1: /* EOR Rd, Rs */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "EOR R%d, R%d", rd, rs ); - break; - case 0x2: /* LSL Rd, Rs */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "LSL R%d, R%d", rd, rs ); - break; - case 0x3: /* LSR Rd, Rs */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "LSR R%d, R%d", rd, rs ); - break; - case 0x4: /* ASR Rd, Rs */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "ASR R%d, R%d", rd, rs ); - break; - case 0x5: /* ADC Rd, Rs */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "ADC R%d, R%d", rd, rs ); - break; - case 0x6: /* SBC Rd, Rs */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "SBC R%d, R%d", rd, rs ); - break; - case 0x7: /* ROR Rd, Rs */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "ROR R%d, R%d", rd, rs ); - break; - case 0x8: /* TST Rd, Rs */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "TST R%d, R%d", rd, rs ); - break; - case 0x9: /* NEG Rd, Rs */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "NEG R%d, R%d", rd, rs ); - break; - case 0xa: /* CMP Rd, Rs */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "CMP R%d, R%d", rd, rs ); - break; - case 0xb: /* CMN Rd, Rs - check flags, add dasm */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "CMN R%d, R%d", rd, rs ); - break; - case 0xc: /* ORR Rd, Rs */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "ORR R%d, R%d", rd, rs ); - break; - case 0xd: /* MUL Rd, Rs */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "MUL R%d, R%d", rd, rs ); - break; - case 0xe: /* MUL Rd, Rs */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "BIC R%d, R%d", rd, rs ); - break; - case 0xf: /* MVN Rd, Rs */ - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "MVN R%d, R%d", rd, rs ); - break; - default: - util::stream_format(stream, "INVALID %04x", opcode); - break; - } - break; - case 0x1: - switch( ( opcode & THUMB_HIREG_OP ) >> THUMB_HIREG_OP_SHIFT ) - { - case 0x0: /* ADD Rd, Rs */ - rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; - rd = opcode & THUMB_HIREG_RD; - switch( ( opcode & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT ) - { - case 0x1: /* ADD Rd, HRs */ - util::stream_format( stream, "ADD R%d, R%d", rd, rs + 8 ); - break; - case 0x2: /* ADD HRd, Rs */ - util::stream_format( stream, "ADD R%d, R%d", rd + 8, rs ); - break; - case 0x3: /* ADD HRd, HRs */ - util::stream_format( stream, "ADD R%d, R%d", rd + 8, rs + 8 ); - break; - default: - util::stream_format(stream, "INVALID %04x", opcode); - break; - } - break; - case 0x1: /* CMP */ - switch( ( opcode & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT ) - { - case 0x0: /* CMP Rd, Rs */ - rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; - rd = opcode & THUMB_HIREG_RD; - util::stream_format( stream, "CMP R%d, R%d", rd, rs ); - break; - case 0x1: /* CMP Rd, HRs */ - rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; - rd = opcode & THUMB_HIREG_RD; - util::stream_format( stream, "CMP R%d, R%d", rd, rs + 8 ); - break; - case 0x2: /* CMP Hd, Rs */ - rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; - rd = opcode & THUMB_HIREG_RD; - util::stream_format( stream, "CMP R%d, R%d", rd + 8, rs ); - break; - case 0x3: /* CMP Hd, Hs */ - rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; - rd = opcode & THUMB_HIREG_RD; - util::stream_format( stream, "CMP R%d, R%d", rd + 8, rs + 8 ); - break; - default: - util::stream_format(stream, "INVALID %04x", opcode); - break; - } - break; - case 0x2: /* MOV */ - switch( ( opcode & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT ) - { - case 0x0: - rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; - rd = opcode & THUMB_HIREG_RD; - util::stream_format( stream, "MOV R%d, R%d", rd, rs ); - break; - case 0x1: - rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; - rd = opcode & THUMB_HIREG_RD; - util::stream_format( stream, "MOV R%d, R%d", rd, rs + 8 ); - break; - case 0x2: - rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; - rd = opcode & THUMB_HIREG_RD; - util::stream_format( stream, "MOV R%d, R%d", rd + 8, rs ); - break; - case 0x3: - rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; - rd = opcode & THUMB_HIREG_RD; - util::stream_format( stream, "MOV R%d, R%d", rd + 8, rs + 8 ); - break; - default: - util::stream_format(stream, "INVALID %04x", opcode); - break; - } - break; - case 0x3: - switch( ( opcode & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT ) - { - case 0x0: - rd = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; - util::stream_format( stream, "BX R%d", rd ); - break; - case 0x1: - rd = ( ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT ) + 8; - util::stream_format( stream, "BX R%d", rd ); - if (rd == 14) - dasmflags = STEP_OUT; - break; - case 0x2: - rd = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; - util::stream_format( stream, "BLX R%d", rd ); - break; - default: - util::stream_format(stream, "INVALID %04x", opcode); - break; - } - break; - default: - util::stream_format(stream, "INVALID %04x", opcode); - break; - } - break; - case 0x2: - case 0x3: - rd = ( opcode & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT; - addr = ( opcode & THUMB_INSN_IMM ) << 2; - util::stream_format( stream, "LDR R%d, [PC, #%03x]", rd, addr ); - break; - default: - util::stream_format(stream, "INVALID %04x", opcode); - break; - } - break; - case 0x5: /* LDR* STR* */ - switch( ( opcode & THUMB_GROUP5_TYPE ) >> THUMB_GROUP5_TYPE_SHIFT ) - { - case 0x0: /* STR Rd, [Rn, Rm] */ - rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; - rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; - rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; - util::stream_format( stream, "STR R%d, [R%d, R%d]", rd, rn, rm ); - break; - case 0x1: /* STRH Rd, [Rn, Rm] */ - rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; - rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; - rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; - util::stream_format( stream, "STRH R%d, [R%d, R%d]", rd, rn, rm ); - break; - case 0x2: /* STRB Rd, [Rn, Rm] */ /* check */ - rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; - rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; - rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; - util::stream_format( stream, "STRB R%d, [R%d, R%d]", rd, rn, rm ); - break; - case 0x3: /* LDRSB Rd, [Rn, Rm] */ - rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; - rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; - rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; - util::stream_format( stream, "LDRSB R%d, [R%d, R%d]", rd, rn, rm ); - break; - case 0x4: /* LDR Rd, [Rn, Rm] */ /* check */ - rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; - rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; - rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; - util::stream_format( stream, "LDR R%d, [R%d, R%d]", rd, rn, rm ); - break; - case 0x5: /* LDRH Rd, [Rn, Rm] */ - rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; - rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; - rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; - util::stream_format( stream, "LDRH R%d, [R%d, R%d]", rd, rn, rm ); - break; - - case 0x6: /* LDRB Rd, [Rn, Rm] */ - rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; - rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; - rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; - util::stream_format( stream, "LDRB R%d, [R%d, R%d]", rd, rn, rm ); - break; - case 0x7: /* LDSH Rd, [Rn, Rm] */ - rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; - rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; - rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; - util::stream_format( stream, "LDSH R%d, [R%d, R%d]", rd, rn, rm ); - break; - default: - util::stream_format(stream, "INVALID %04x", opcode); - break; - } - break; - case 0x6: /* Word Store w/ Immediate Offset */ - if( opcode & THUMB_LSOP_L ) /* Load */ - { - rn = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = opcode & THUMB_ADDSUB_RD; - offs = ( ( opcode & THUMB_LSOP_OFFS ) >> THUMB_LSOP_OFFS_SHIFT ) << 2; - util::stream_format( stream, "LDR R%d [R%d + #%02x]", rd, rn, offs ); - } - else /* Store */ - { - rn = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = opcode & THUMB_ADDSUB_RD; - offs = ( ( opcode & THUMB_LSOP_OFFS ) >> THUMB_LSOP_OFFS_SHIFT ) << 2; - util::stream_format( stream, "STR R%d, [R%d + #%02x] ", rd, rn, offs ); - } + stream << "LSR"; + WritePadding(stream, start_position); + if( rd != rs ) + util::stream_format( stream, "R%d, ", rd); + util::stream_format( stream, "R%d, #%d", rs, (offs == 0) ? 32 : offs); + } + else /* Shift left */ + { + stream << "LSL"; + WritePadding(stream, start_position); + if( rd != rs ) + util::stream_format( stream, "R%d, ", rd); + util::stream_format( stream, "R%d, #%d", rs, offs); + } + break; + case 0x1: /* Arithmetic */ + rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + if( opcode & THUMB_INSN_ADDSUB ) + { + switch( ( opcode & THUMB_ADDSUB_TYPE ) >> THUMB_ADDSUB_TYPE_SHIFT ) + { + case 0x0: /* ADD Rd, Rs, Rn */ + rn = ( opcode & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT; + stream << "ADD"; + WritePadding(stream, start_position); + if( rd != rs ) + util::stream_format( stream, "R%d, ", rd ); + util::stream_format( stream, "R%d, R%d", rs, rn ); break; - case 0x7: /* Byte Store w/ Immeidate Offset */ - if( opcode & THUMB_LSOP_L ) /* Load */ - { - rn = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = opcode & THUMB_ADDSUB_RD; - offs = ( opcode & THUMB_LSOP_OFFS ) >> THUMB_LSOP_OFFS_SHIFT; - util::stream_format( stream, "LDRB R%d, [R%d + #%02x]", rd, rn, offs ); - } - else /* Store */ - { - rn = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = opcode & THUMB_ADDSUB_RD; - offs = ( opcode & THUMB_LSOP_OFFS ) >> THUMB_LSOP_OFFS_SHIFT; - util::stream_format( stream, "STRB R%d, [R%d + #%02x] ", rd, rn, offs ); - } + case 0x1: /* SUB Rd, Rs, Rn */ + rn = ( opcode & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT; + stream << "SUB"; + WritePadding(stream, start_position); + if( rd != rs ) + util::stream_format( stream, "R%d, ", rd ); + util::stream_format( stream, "R%d, R%d", rs, rn ); break; - case 0x8: /* Load/Store Halfword */ - if( opcode & THUMB_HALFOP_L ) /* Load */ - { - imm = ( opcode & THUMB_HALFOP_OFFS ) >> THUMB_HALFOP_OFFS_SHIFT; - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "LDRH R%d, [R%d, #%03x]", rd, rs, imm << 1 ); - } - else /* Store */ - { - imm = ( opcode & THUMB_HALFOP_OFFS ) >> THUMB_HALFOP_OFFS_SHIFT; - rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; - rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; - util::stream_format( stream, "STRH R%d, [R%d, #%03x]", rd, rs, imm << 1 ); - } + case 0x2: /* ADD Rd, Rs, #imm */ + imm = ( opcode & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT; + stream << "ADD"; + WritePadding(stream, start_position); + if( rd != rs ) + util::stream_format( stream, "R%d, ", rd ); + util::stream_format( stream, "R%d, #%d", rs, imm ); break; - case 0x9: /* Stack-Relative Load/Store */ - if( opcode & THUMB_STACKOP_L ) - { - rd = ( opcode & THUMB_STACKOP_RD ) >> THUMB_STACKOP_RD_SHIFT; - offs = (uint8_t)( opcode & THUMB_INSN_IMM ); - util::stream_format( stream, "LDR R%d, [SP, #%03x]", rd, offs << 2 ); - } - else - { - rd = ( opcode & THUMB_STACKOP_RD ) >> THUMB_STACKOP_RD_SHIFT; - offs = (uint8_t)( opcode & THUMB_INSN_IMM ); - util::stream_format( stream, "STR R%d, [SP, #%03x]", rd, offs << 2 ); - } + case 0x3: /* SUB Rd, Rs, #imm */ + imm = ( opcode & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT; + stream << "SUB"; + WritePadding(stream, start_position); + if( rd != rs ) + util::stream_format( stream, "R%d, ", rd ); + util::stream_format( stream, "R%d, #%d", rs, imm ); break; - case 0xa: /* Get relative address */ - if( opcode & THUMB_RELADDR_SP ) /* ADD Rd, SP, #nn */ - { - rd = ( opcode & THUMB_RELADDR_RD ) >> THUMB_RELADDR_RD_SHIFT; - offs = (uint8_t)( opcode & THUMB_INSN_IMM ) << 2; - util::stream_format( stream, "ADD R%d, SP, #%03x", rd, offs ); - } - else /* ADD Rd, PC, #nn */ - { - rd = ( opcode & THUMB_RELADDR_RD ) >> THUMB_RELADDR_RD_SHIFT; - offs = (uint8_t)( opcode & THUMB_INSN_IMM ) << 2; - util::stream_format( stream, "ADD R%d, PC, #%03x", rd, offs ); - } + default: + util::stream_format(stream, "INVALID %04x", opcode); break; - case 0xb: /* Stack-Related Opcodes */ - switch( ( opcode & THUMB_STACKOP_TYPE ) >> THUMB_STACKOP_TYPE_SHIFT ) + } + } + else + { + offs = ( opcode & THUMB_SHIFT_AMT ) >> THUMB_SHIFT_AMT_SHIFT; + stream << "ASR"; + WritePadding(stream, start_position); + if( rd != rs ) + util::stream_format( stream, "R%d, ", rd); + util::stream_format( stream, "R%d, #%d", rs, offs); + } + break; + case 0x2: /* CMP / MOV */ + rn = ( opcode & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT; + imm = ( opcode & THUMB_INSN_IMM ); + if( opcode & THUMB_INSN_CMP ) + stream << "CMP"; + else + stream << "MOV"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, #%s%X", rn, imm > 9 ? "0x" : "", imm ); + break; + case 0x3: /* ADD/SUB immediate */ + rn = ( opcode & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT; + imm = opcode & THUMB_INSN_IMM; + if( opcode & THUMB_INSN_SUB ) /* SUB Rd, #Offset8 */ + stream << "SUB"; + else + stream << "ADD"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, #%s%X", rn, imm > 9 ? "0x" : "", imm ); // fixed, rd -> rn + break; + case 0x4: /* Rd & Rm instructions */ + switch( ( opcode & THUMB_GROUP4_TYPE ) >> THUMB_GROUP4_TYPE_SHIFT ) + { + case 0x0: + rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + switch( ( opcode & THUMB_ALUOP_TYPE ) >> THUMB_ALUOP_TYPE_SHIFT ) + { + case 0x0: /* AND Rd, Rs */ + stream << "AND"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0x1: /* EOR Rd, Rs */ + stream << "EOR"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0x2: /* LSL Rd, Rs */ + stream << "LSL"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0x3: /* LSR Rd, Rs */ + stream << "LSR"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0x4: /* ASR Rd, Rs */ + stream << "ASR"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0x5: /* ADC Rd, Rs */ + stream << "ADC"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0x6: /* SBC Rd, Rs */ + stream << "SBC"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0x7: /* ROR Rd, Rs */ + stream << "ROR"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0x8: /* TST Rd, Rs */ + stream << "TST"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0x9: /* NEG Rd, Rs */ + stream << "NEG"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0xa: /* CMP Rd, Rs */ + stream << "CMP"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0xb: /* CMN Rd, Rs - check flags, add dasm */ + stream << "CMN"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0xc: /* ORR Rd, Rs */ + stream << "ORR"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0xd: /* MUL Rd, Rs */ + stream << "MUL"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0xe: /* BIC Rd, Rs */ + stream << "BIC"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0xf: /* MVN Rd, Rs */ + stream << "MVN"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + default: + util::stream_format(stream, "INVALID %04x", opcode); + break; + } + break; + case 0x1: + switch( ( opcode & THUMB_HIREG_OP ) >> THUMB_HIREG_OP_SHIFT ) + { + case 0x0: /* ADD Rd, Rs */ + rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; + rd = opcode & THUMB_HIREG_RD; + switch( ( opcode & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT ) { - case 0x0: /* ADD SP, #imm */ - addr = ( opcode & THUMB_INSN_IMM ); - addr &= ~THUMB_INSN_IMM_S; - util::stream_format( stream, "ADD SP, #"); - if( opcode & THUMB_INSN_IMM_S ) - { - util::stream_format( stream, "-"); - } - util::stream_format( stream, "%03x", addr << 2); - break; - case 0x5: /* PUSH {Rlist}{LR} */ - util::stream_format( stream, "PUSH {LR, "); - for( offs = 7; offs >= 0; offs-- ) - { - if( opcode & ( 1 << offs ) ) - { - util::stream_format( stream, "R%d, ", offs); - } - } - util::stream_format( stream, "}"); - break; - case 0x4: /* PUSH {Rlist} */ - util::stream_format( stream, "PUSH {"); - for( offs = 7; offs >= 0; offs-- ) - { - if( opcode & ( 1 << offs ) ) - { - util::stream_format( stream, "R%d, ", offs); - } - } - util::stream_format( stream, "}"); - break; - case 0xc: /* POP {Rlist} */ - util::stream_format( stream, "POP {"); - for( offs = 0; offs < 8; offs++ ) - { - if( opcode & ( 1 << offs ) ) - { - util::stream_format( stream, "R%d, ", offs); - } - } - util::stream_format( stream, "}"); - break; - case 0xd: /* POP {Rlist}{PC} */ - util::stream_format( stream, "POP {"); - for( offs = 0; offs < 8; offs++ ) - { - if( opcode & ( 1 << offs ) ) - { - util::stream_format( stream, "R%d, ", offs); - } - } - util::stream_format( stream, "PC}"); - break; - default: - util::stream_format(stream, "INVALID %04x", opcode); - break; + case 0x1: /* ADD Rd, HRs */ + stream << "ADD"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs + 8 ); + break; + case 0x2: /* ADD HRd, Rs */ + stream << "ADD"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd + 8, rs ); + break; + case 0x3: /* ADD HRd, HRs */ + stream << "ADD"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd + 8, rs + 8 ); + break; + default: + util::stream_format(stream, "INVALID %04x", opcode); + break; } break; - case 0xc: /* Multiple Load/Store */ - if( opcode & THUMB_MULTLS ) /* Load */ + case 0x1: /* CMP */ + rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; + rd = opcode & THUMB_HIREG_RD; + switch( ( opcode & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT ) { - rd = ( opcode & THUMB_MULTLS_BASE ) >> THUMB_MULTLS_BASE_SHIFT; - util::stream_format( stream, "LDMIA R%d!,{", rd); - for( offs = 0; offs < 8; offs++ ) - { - if( opcode & ( 1 << offs ) ) - { - util::stream_format( stream, "R%d, ", offs); - } - } - util::stream_format( stream, "}"); - } - else /* Store */ - { - rd = ( opcode & THUMB_MULTLS_BASE ) >> THUMB_MULTLS_BASE_SHIFT; - util::stream_format( stream, "STMIA R%d!,{", rd); - for( offs = 7; offs >= 0; offs-- ) - { - if( opcode & ( 1 << offs ) ) - { - util::stream_format( stream, "R%d, ", offs); - } - } - util::stream_format( stream, "}"); + case 0x0: /* CMP Rd, Rs */ + stream << "CMP"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0x1: /* CMP Rd, HRs */ + stream << "CMP"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs + 8 ); + break; + case 0x2: /* CMP Hd, Rs */ + stream << "CMP"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd + 8, rs ); + break; + case 0x3: /* CMP Hd, Hs */ + stream << "CMP"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd + 8, rs + 8 ); + break; + default: + util::stream_format(stream, "INVALID %04x", opcode); + break; } break; - case 0xd: /* Conditional Branch */ - offs = (int8_t)( opcode & THUMB_INSN_IMM ); - switch( ( opcode & THUMB_COND_TYPE ) >> THUMB_COND_TYPE_SHIFT ) + case 0x2: /* MOV */ + rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; + rd = opcode & THUMB_HIREG_RD; + switch( ( opcode & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT ) { - case COND_EQ: - util::stream_format( stream, "BEQ %08x (%02x)", pc + 4 + (offs << 1), offs << 1); - break; - case COND_NE: - util::stream_format( stream, "BNE %08x (%02x)", pc + 4 + (offs << 1), offs << 1); - break; - case COND_CS: - util::stream_format( stream, "BCS %08x (%02x)", pc + 4 + (offs << 1), offs << 1); - break; - case COND_CC: - util::stream_format( stream, "BCC %08x (%02x)", pc + 4 + (offs << 1), offs << 1); - break; - case COND_MI: - util::stream_format( stream, "BMI %08x (%02x)", pc + 4 + (offs << 1), offs << 1); - break; - case COND_PL: - util::stream_format( stream, "BPL %08x (%02x)", pc + 4 + (offs << 1), offs << 1); - break; - case COND_VS: - util::stream_format( stream, "BVS %08x (%02x)", pc + 4 + (offs << 1), offs << 1); - break; - case COND_VC: - util::stream_format( stream, "BVC %08x (%02x)", pc + 4 + (offs << 1), offs << 1); - break; - case COND_HI: - util::stream_format( stream, "BHI %08x (%02x)", pc + 4 + (offs << 1), offs << 1); - break; - case COND_LS: - util::stream_format( stream, "BLS %08x (%02x)", pc + 4 + (offs << 1), offs << 1); - break; - case COND_GE: - util::stream_format( stream, "BGE %08x (%02x)", pc + 4 + (offs << 1), offs << 1); - break; - case COND_LT: - util::stream_format( stream, "BLT %08x (%02x)", pc + 4 + (offs << 1), offs << 1); - break; - case COND_GT: - util::stream_format( stream, "BGT %08x (%02x)", pc + 4 + (offs << 1), offs << 1); - break; - case COND_LE: - util::stream_format( stream, "BLE %08x (%02x)", pc + 4 + (offs << 1), offs << 1); - break; - case COND_AL: - util::stream_format( stream, "INVALID"); - break; - case COND_NV: - util::stream_format( stream, "SWI %02x", opcode & 0xff); - break; + case 0x0: + stream << "MOV"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs ); + break; + case 0x1: + stream << "MOV"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd, rs + 8 ); + break; + case 0x2: + stream << "MOV"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd + 8, rs ); + break; + case 0x3: + stream << "MOV"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, R%d", rd + 8, rs + 8 ); + break; + default: + util::stream_format(stream, "INVALID %04x", opcode); + break; } break; - case 0xe: /* B #offs */ - if( opcode & THUMB_BLOP_LO ) + case 0x3: + switch( ( opcode & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT ) { - addr = ( ( opcode & THUMB_BLOP_OFFS ) << 1 ) & 0xfffc; - util::stream_format( stream, "BLX (LO) %08x", addr ); + case 0x0: + rd = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; + stream << "BX"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d", rd ); + break; + case 0x1: + rd = ( ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT ) + 8; + stream << "BX"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d", rd ); + if (rd == 14) + dasmflags = STEP_OUT; + break; + case 0x2: + rd = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT; + stream << "BLX"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d", rd ); dasmflags = STEP_OVER; - } - else - { - offs = ( opcode & THUMB_BRANCH_OFFS ) << 1; - if( offs & 0x00000800 ) - { - offs |= 0xfffff800; - } - util::stream_format( stream, "B #%08x (%08x)", offs, pc + 4 + offs); + break; + default: + util::stream_format(stream, "INVALID %04x", opcode); + break; } break; - case 0xf: /* BL */ - if( opcode & THUMB_BLOP_LO ) + default: + util::stream_format(stream, "INVALID %04x", opcode); + break; + } + break; + case 0x2: + case 0x3: + rd = ( opcode & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT; + addr = uint32_t( opcode & THUMB_INSN_IMM ) << 2; + stream << "LDR"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, 0x%08X", rd, (pc + 4 + addr) & 0xfffffffc ); + break; + default: + util::stream_format(stream, "INVALID %04x", opcode); + break; + } + break; + case 0x5: /* LDR* STR* */ + rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT; + rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT; + rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT; + switch( ( opcode & THUMB_GROUP5_TYPE ) >> THUMB_GROUP5_TYPE_SHIFT ) + { + case 0x0: /* STR Rd, [Rn, Rm] */ + stream << "STR"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, [R%d, R%d]", rd, rn, rm ); + break; + case 0x1: /* STRH Rd, [Rn, Rm] */ + stream << "STRH"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, [R%d, R%d]", rd, rn, rm ); + break; + case 0x2: /* STRB Rd, [Rn, Rm] */ /* check */ + stream << "STRB"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, [R%d, R%d]", rd, rn, rm ); + break; + case 0x3: /* LDRSB Rd, [Rn, Rm] */ + stream << "LDRSB"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, [R%d, R%d]", rd, rn, rm ); + break; + case 0x4: /* LDR Rd, [Rn, Rm] */ /* check */ + stream << "LDR"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, [R%d, R%d]", rd, rn, rm ); + break; + case 0x5: /* LDRH Rd, [Rn, Rm] */ + stream << "LDRH"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, [R%d, R%d]", rd, rn, rm ); + break; + case 0x6: /* LDRB Rd, [Rn, Rm] */ + stream << "LDRB"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, [R%d, R%d]", rd, rn, rm ); + break; + case 0x7: /* LDRSH Rd, [Rn, Rm] */ + stream << "LDRSH"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, [R%d, R%d]", rd, rn, rm ); + break; + default: + util::stream_format(stream, "INVALID %04x", opcode); + break; + } + break; + case 0x6: /* Word Store w/ Immediate Offset */ + rn = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = opcode & THUMB_ADDSUB_RD; + offs = ( ( opcode & THUMB_LSOP_OFFS ) >> THUMB_LSOP_OFFS_SHIFT ) << 2; + if( opcode & THUMB_LSOP_L ) /* Load */ + stream << "LDR"; + else /* Store */ + stream << "STR"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, [R%d", rd, rn ); + if ( offs != 0 ) + util::stream_format( stream, ", #%s%X", offs > 9 ? "0x" : "", offs ); + stream << ']'; + break; + case 0x7: /* Byte Store w/ Immeidate Offset */ + rn = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = opcode & THUMB_ADDSUB_RD; + offs = ( opcode & THUMB_LSOP_OFFS ) >> THUMB_LSOP_OFFS_SHIFT; + if( opcode & THUMB_LSOP_L ) /* Load */ + stream << "LDRB"; + else /* Store */ + stream << "STRB"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, [R%d", rd, rn ); + if ( offs != 0 ) + util::stream_format( stream, ", #%s%X", offs > 9 ? "0x" : "", offs ); + stream << ']'; + break; + case 0x8: /* Load/Store Halfword */ + imm = ( opcode & THUMB_HALFOP_OFFS ) >> THUMB_HALFOP_OFFS_SHIFT; + rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT; + rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT; + if( opcode & THUMB_HALFOP_L ) /* Load */ + stream << "LDRH"; + else /* Store */ + stream << "STRH"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, [R%d", rd, rs ); + if ( imm != 0 ) + util::stream_format( stream, ", #%s%X", (imm << 1) > 9 ? "0x" : "", imm << 1 ); + stream << ']'; + break; + case 0x9: /* Stack-Relative Load/Store */ + rd = ( opcode & THUMB_STACKOP_RD ) >> THUMB_STACKOP_RD_SHIFT; + offs = opcode & THUMB_INSN_IMM; + if( opcode & THUMB_STACKOP_L ) + stream << "LDR"; + else + stream << "STR"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, [SP", rd ); + if ( offs != 0 ) + util::stream_format( stream, ", #%s%X", (offs << 2) > 9 ? "0x" : "", offs << 2); + stream << ']'; + break; + case 0xa: /* Get relative address */ + rd = ( opcode & THUMB_RELADDR_RD ) >> THUMB_RELADDR_RD_SHIFT; + offs = uint32_t( opcode & THUMB_INSN_IMM ) << 2; + if( opcode & THUMB_RELADDR_SP ) /* ADD Rd, SP, #nn */ + { + stream << "ADD"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, SP, #%s%X", rd, (offs << 2) > 9 ? "0x" : "", offs ); + } + else /* ADD Rd, PC, #nn */ + { + stream << "ADR"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d, 0x%08X", rd, (pc + 4 + offs) & 0xfffffffc ); + } + break; + case 0xb: /* Stack-Related Opcodes */ + switch( ( opcode & THUMB_STACKOP_TYPE ) >> THUMB_STACKOP_TYPE_SHIFT ) + { + case 0x0: /* ADD SP, #imm */ + addr = ( opcode & THUMB_INSN_IMM ); + addr &= ~THUMB_INSN_IMM_S; + if( opcode & THUMB_INSN_IMM_S ) + stream << "SUB"; + else + stream << "ADD"; + WritePadding(stream, start_position); + util::stream_format( stream, "SP, #%s%X", (addr << 2) > 9 ? "0x" : "", addr << 2); + break; + case 0x4: /* PUSH {Rlist} */ + case 0x5: /* PUSH {Rlist}{LR} */ + stream << "PUSH"; + WritePadding(stream, start_position); + stream << '{'; + if (opcode & 0x100) + stream << "LR, "; + for( offs = 7; offs >= 0; offs-- ) + { + if( opcode & ( 1 << offs ) ) { - util::stream_format( stream, "BL (LO) %08x", ( opcode & THUMB_BLOP_OFFS ) << 1 ); - dasmflags = STEP_OVER; + util::stream_format(stream, "R%d", offs); + if( opcode & ( (1 << offs) - 1 ) ) + stream << ", "; } - else + } + util::stream_format( stream, "}"); + break; + case 0xc: /* POP {Rlist} */ + case 0xd: /* POP {Rlist}{PC} */ + stream << "POP"; + WritePadding(stream, start_position); + stream << '{'; + for( offs = 0; offs < 8; offs++ ) + { + if( opcode & ( 1 << offs ) ) { - addr = ( opcode & THUMB_BLOP_OFFS ) << 12; - if( addr & ( 1 << 22 ) ) - { - addr |= 0xff800000; - } - util::stream_format( stream, "BL (HI) %08x", addr ); - dasmflags = STEP_OVER; + if( opcode & ( (1 << offs) - 1 ) ) + stream << ", "; + util::stream_format(stream, "R%d", offs); } - break; - default: - util::stream_format(stream, "INVALID %04x", opcode); - break; + } + if (opcode & 0x100) + { + if ((opcode & 0xff) != 0) + stream << ", "; + stream << "PC"; + dasmflags = STEP_OUT; + } + stream << '}'; + break; + default: + util::stream_format(stream, "INVALID %04x", opcode); + break; + } + break; + case 0xc: /* Multiple Load/Store */ + rd = ( opcode & THUMB_MULTLS_BASE ) >> THUMB_MULTLS_BASE_SHIFT; + if( opcode & THUMB_MULTLS ) /* Load */ + stream << "LDMIA"; + else /* Store */ + stream << "STMIA"; + WritePadding(stream, start_position); + util::stream_format( stream, "R%d!, {", rd); + for( offs = 0; offs < 8; offs++ ) + { + if( opcode & ( 1 << offs ) ) + { + if( opcode & ((1 << offs) - 1) ) + stream << ", "; + util::stream_format(stream, "R%d", offs); + } } + stream << '}'; + break; + case 0xd: /* Conditional Branch */ + switch( ( opcode & THUMB_COND_TYPE ) >> THUMB_COND_TYPE_SHIFT ) + { + case COND_AL: + stream << "BKPT"; // v5 + WritePadding(stream, start_position); + util::stream_format( stream, "0x%02X", opcode & 0xff); + dasmflags = STEP_OVER; + break; + case COND_NV: + stream << "SWI"; + WritePadding(stream, start_position); + util::stream_format( stream, "0x%02X", opcode & 0xff); + dasmflags = STEP_OVER; + break; + default: + offs = (int8_t)( opcode & THUMB_INSN_IMM ); + util::stream_format( stream, "B%s", pConditionCodeTable[( opcode & THUMB_COND_TYPE ) >> THUMB_COND_TYPE_SHIFT]); + WritePadding(stream, start_position); + util::stream_format( stream, "0x%08X", pc + 4 + (offs << 1)); + dasmflags = STEP_COND; + break; + } + break; + case 0xe: /* B #offs */ + if( opcode & THUMB_BLOP_LO ) + { + addr = ( ( opcode & THUMB_BLOP_OFFS ) << 1 ) & 0xfffc; + util::stream_format( stream, "BLX (LO) 0x%X", addr ); + dasmflags = STEP_OVER; + } + else + { + offs = util::sext( ( opcode & THUMB_BRANCH_OFFS ) << 1, 12 ); + stream << "B"; + WritePadding(stream, start_position); + util::stream_format( stream, "0x%08X", uint32_t(pc + 4 + offs)); + } + break; + case 0xf: /* BL */ + if( opcode & THUMB_BLOP_LO ) + { + util::stream_format( stream, "BL (LO) 0x%X", ( opcode & THUMB_BLOP_OFFS ) << 1 ); + dasmflags = STEP_OVER; + } + else + { + addr = util::sext( ( opcode & THUMB_BLOP_OFFS ) << 12, 23 ); + util::stream_format( stream, "BL (HI) 0x%X", addr ); + dasmflags = STEP_OVER; + } + break; + default: + util::stream_format(stream, "INVALID %04x", opcode); + break; + } return 2 | dasmflags | SUPPORTED; } diff --git a/src/devices/cpu/arm7/arm7dasm.h b/src/devices/cpu/arm7/arm7dasm.h index 9f90b47308f..3c9514482bd 100644 --- a/src/devices/cpu/arm7/arm7dasm.h +++ b/src/devices/cpu/arm7/arm7dasm.h @@ -2,10 +2,10 @@ // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz /***************************************************************************** * - * arm7dasm.c + * arm7dasm.h * Portable ARM7TDMI Core Emulator - Disassembler * - * Copyright Steve Ellenoff, all rights reserved. + * Copyright Steve Ellenoff * * This work is based on: * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999' @@ -39,8 +39,9 @@ private: void DasmCoProc_RT(std::ostream &stream, u32 opcode, const char *pConditionCode, std::streampos start_position); void DasmCoProc_DT(std::ostream &stream, u32 opcode, const char *pConditionCode, std::streampos start_position); void DasmCoProc_DO(std::ostream &stream, u32 opcode, const char *pConditionCode, std::streampos start_position); - void WriteImmediateOperand( std::ostream &stream, u32 opcode ); - void WriteDataProcessingOperand( std::ostream &stream, u32 opcode, int printOp0, int printOp1, int printOp2 ); + static u32 ExtractImmediateOperand( u32 opcode ); + void WriteShiftCount( std::ostream &stream, u32 opcode ); + void WriteDataProcessingOperand( std::ostream &stream, u32 opcode, bool printOp0, bool printOp1 ); void WriteRegisterOperand1( std::ostream &stream, u32 opcode ); void WriteBranchAddress( std::ostream &stream, u32 pc, u32 opcode, bool h_bit ); u32 arm7_disasm( std::ostream &stream, u32 pc, u32 opcode ); diff --git a/src/devices/cpu/arm7/arm7drc.hxx b/src/devices/cpu/arm7/arm7drc.hxx index 621c0a7f0f8..9afdf5e7c88 100644 --- a/src/devices/cpu/arm7/arm7drc.hxx +++ b/src/devices/cpu/arm7/arm7drc.hxx @@ -2,10 +2,10 @@ // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz /***************************************************************************** * - * arm7drc.inc + * arm7drc.hxx * Portable CPU Emulator for 32-bit ARM v3/4/5/6 * - * Copyright Steve Ellenoff, all rights reserved. + * Copyright Steve Ellenoff * Thumb, DSP, and MMU support and many bugfixes by R. Belmont and Ryan Holtz. * Dyanmic Recompiler (DRC) / Just In Time Compiler (JIT) by Ryan Holtz. * @@ -95,7 +95,7 @@ void arm7_cpu_device::load_fast_iregs(drcuml_block &block) { int regnum; - for (regnum = 0; regnum < ARRAY_LENGTH(m_impstate.regmap); regnum++) + for (regnum = 0; regnum < std::size(m_impstate.regmap); regnum++) if (m_impstate.regmap[regnum].is_int_register()) UML_DMOV(block, uml::ireg(m_impstate.regmap[regnum].ireg() - uml::REG_I0), uml::mem(&m_r[regnum])); } @@ -110,7 +110,7 @@ void arm7_cpu_device::save_fast_iregs(drcuml_block &block) { int regnum; - for (regnum = 0; regnum < ARRAY_LENGTH(m_impstate.regmap); regnum++) + for (regnum = 0; regnum < std::size(m_impstate.regmap); regnum++) if (m_impstate.regmap[regnum].is_int_register()) UML_DMOV(block, uml::mem(&m_r[regnum]), uml::ireg(m_impstate.regmap[regnum].ireg() - uml::REG_I0)); } @@ -127,21 +127,18 @@ void arm7_cpu_device::save_fast_iregs(drcuml_block &block) void arm7_cpu_device::arm7_drc_init() { - drc_cache *cache; drcbe_info beinfo; uint32_t flags = 0; /* allocate enough space for the cache and the core */ - cache = auto_alloc(machine(), drc_cache(CACHE_SIZE)); - if (cache == nullptr) - fatalerror("Unable to allocate cache of size %d\n", (uint32_t)(CACHE_SIZE)); /* allocate the implementation-specific state from the full cache */ - memset(&m_impstate, 0, sizeof(m_impstate)); - m_impstate.cache = cache; + m_impstate = arm7imp_state(); + try { m_impstate.cache = std::make_unique<drc_cache>(CACHE_SIZE); } + catch (std::bad_alloc const &) { throw emu_fatalerror("Unable to allocate cache of size %d\n", (uint32_t)(CACHE_SIZE)); } /* initialize the UML generator */ - m_impstate.drcuml = new drcuml_state(*this, *cache, flags, 1, 32, 1); + m_impstate.drcuml = std::make_unique<drcuml_state>(*this, *m_impstate.cache, flags, 1, 32, 1); /* add symbols for our stuff */ m_impstate.drcuml->symbol_add(&m_icount, sizeof(m_icount), "icount"); @@ -158,7 +155,7 @@ void arm7_cpu_device::arm7_drc_init() //m_impstate.drcuml->symbol_add(&m_impstate.fpmode, sizeof(m_impstate.fpmode), "fpmode"); // TODO /* initialize the front-end helper */ - //m_impstate.drcfe = auto_alloc(machine(), arm7_frontend(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE)); + //m_impstate.drcfe = std::make_unique<arm7_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE); /* allocate memory for cache-local state and initialize it */ //memcpy(&m_impstate.fpmode, fpmode_source, sizeof(fpmode_source)); // TODO @@ -199,7 +196,7 @@ void arm7_cpu_device::arm7_drc_init() void arm7_cpu_device::execute_run_drc() { - drcuml_state *drcuml = m_impstate.drcuml; + drcuml_state &drcuml = *m_impstate.drcuml; int execute_result; /* reset the cache if dirty */ @@ -211,7 +208,7 @@ void arm7_cpu_device::execute_run_drc() do { /* run as much as we can */ - execute_result = drcuml->execute(*m_impstate.entry); + execute_result = drcuml.execute(*m_impstate.entry); /* if we need to recompile, do it */ if (execute_result == EXECUTE_MISSING_CODE) @@ -231,9 +228,9 @@ void arm7_cpu_device::execute_run_drc() void arm7_cpu_device::arm7_drc_exit() { /* clean up the DRC */ - //auto_free(machine(), m_impstate.drcfe); - delete m_impstate.drcuml; - auto_free(machine(), m_impstate.cache); + //m_impstate.drcfe.reset(); + m_impstate.drcuml.reset(); + m_impstate.cache.reset(); } @@ -254,7 +251,7 @@ void arm7_cpu_device::arm7drc_set_options(uint32_t options) void arm7_cpu_device::arm7drc_add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base) { - if (m_impstate.fastram_select < ARRAY_LENGTH(m_impstate.fastram)) + if (m_impstate.fastram_select < std::size(m_impstate.fastram)) { m_impstate.fastram[m_impstate.fastram_select].start = start; m_impstate.fastram[m_impstate.fastram_select].end = end; @@ -271,7 +268,7 @@ void arm7_cpu_device::arm7drc_add_fastram(offs_t start, offs_t end, uint8_t read void arm7_cpu_device::arm7drc_add_hotspot(offs_t pc, uint32_t opcode, uint32_t cycles) { - if (m_impstate.hotspot_select < ARRAY_LENGTH(m_impstate.hotspot)) + if (m_impstate.hotspot_select < std::size(m_impstate.hotspot)) { m_impstate.hotspot[m_impstate.hotspot_select].pc = pc; m_impstate.hotspot[m_impstate.hotspot_select].opcode = opcode; @@ -328,17 +325,17 @@ void arm7_cpu_device::code_flush_cache() void arm7_cpu_device::code_compile_block(uint8_t mode, offs_t pc) { - drcuml_state *drcuml = m_impstate.drcuml; + drcuml_state &drcuml = *m_impstate.drcuml; compiler_state compiler = { 0 }; const opcode_desc *seqlast; bool override = false; - g_profiler.start(PROFILER_DRC_COMPILE); + auto profile = g_profiler.start(PROFILER_DRC_COMPILE); /* get a description of this sequence */ // TODO FIXME const opcode_desc *desclist = nullptr; //m_impstate.drcfe->describe_code(pc); // TODO -// if (drcuml->logging() || drcuml->logging_native()) +// if (drcuml.logging() || drcuml.logging_native()) // log_opcode_desc(drcuml, desclist, 0); /* if we get an error back, flush the cache and try again */ @@ -348,7 +345,7 @@ void arm7_cpu_device::code_compile_block(uint8_t mode, offs_t pc) try { /* start the block */ - drcuml_block &block(drcuml->begin_block(4096)); + drcuml_block &block(drcuml.begin_block(4096)); /* loop until we get through all instruction sequences */ for (const opcode_desc *seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next()) @@ -357,7 +354,7 @@ void arm7_cpu_device::code_compile_block(uint8_t mode, offs_t pc) uint32_t nextpc; /* add a code log entry */ - if (drcuml->logging()) + if (drcuml.logging()) block.append_comment("-------------------------"); // comment /* determine the last instruction in this sequence */ @@ -367,7 +364,7 @@ void arm7_cpu_device::code_compile_block(uint8_t mode, offs_t pc) assert(seqlast != nullptr); /* if we don't have a hash for this mode/pc, or if we are overriding all, add one */ - if (override || !drcuml->hash_exists(mode, seqhead->pc)) + if (override || !drcuml.hash_exists(mode, seqhead->pc)) UML_HASH(block, mode, seqhead->pc); // hash mode,pc /* if we already have a hash, and this is the first sequence, assume that we */ @@ -421,7 +418,6 @@ void arm7_cpu_device::code_compile_block(uint8_t mode, offs_t pc) /* end the sequence */ block.end(); - g_profiler.stop(); succeeded = true; } catch (drcuml_block::abort_compilation &) @@ -470,17 +466,17 @@ void arm7_cpu_device::cfunc_unimplemented() void arm7_cpu_device::static_generate_entry_point() { - drcuml_state *drcuml = m_impstate.drcuml; + drcuml_state &drcuml = *m_impstate.drcuml; - drcuml_block &block(drcuml->begin_block(110)); + drcuml_block &block(drcuml.begin_block(110)); /* forward references */ - //alloc_handle(*drcuml, &m_impstate.exception_norecover[EXCEPTION_INTERRUPT], "interrupt_norecover"); - alloc_handle(*drcuml, m_impstate.nocode, "nocode"); - alloc_handle(*drcuml, m_impstate.detect_fault, "detect_fault"); - alloc_handle(*drcuml, m_impstate.tlb_translate, "tlb_translate"); + //alloc_handle(drcuml, &m_impstate.exception_norecover[EXCEPTION_INTERRUPT], "interrupt_norecover"); + alloc_handle(drcuml, m_impstate.nocode, "nocode"); + alloc_handle(drcuml, m_impstate.detect_fault, "detect_fault"); + alloc_handle(drcuml, m_impstate.tlb_translate, "tlb_translate"); - alloc_handle(*drcuml, m_impstate.entry, "entry"); + alloc_handle(drcuml, m_impstate.entry, "entry"); UML_HANDLE(block, *m_impstate.entry); // handle entry /* load fast integer registers */ @@ -501,7 +497,7 @@ void arm7_cpu_device::static_generate_entry_point() void arm7_cpu_device::static_generate_check_irq() { - drcuml_state *drcuml = m_impstate.drcuml; + drcuml_state &drcuml = *m_impstate.drcuml; uml::code_label noirq; int nodabt = 0; int nopabt = 0; @@ -513,10 +509,10 @@ void arm7_cpu_device::static_generate_check_irq() int label = 1; /* begin generating */ - drcuml_block &block(drcuml->begin_block(120)); + drcuml_block &block(drcuml.begin_block(120)); /* generate a hash jump via the current mode and PC */ - alloc_handle(*drcuml, m_impstate.check_irq, "check_irq"); + alloc_handle(drcuml, m_impstate.check_irq, "check_irq"); UML_HANDLE(block, *m_impstate.check_irq); // handle check_irq /* Exception priorities: @@ -669,13 +665,13 @@ void arm7_cpu_device::static_generate_check_irq() void arm7_cpu_device::static_generate_nocode_handler() { - drcuml_state *drcuml = m_impstate.drcuml; + drcuml_state &drcuml = *m_impstate.drcuml; /* begin generating */ - drcuml_block &block(drcuml->begin_block(10)); + drcuml_block &block(drcuml.begin_block(10)); /* generate a hash jump via the current mode and PC */ - alloc_handle(*drcuml, m_impstate.nocode, "nocode"); + alloc_handle(drcuml, m_impstate.nocode, "nocode"); UML_HANDLE(block, *m_impstate.nocode); // handle nocode UML_GETEXP(block, uml::I0); // getexp i0 UML_MOV(block, uml::mem(&R15), uml::I0); // mov [pc],i0 @@ -693,13 +689,13 @@ void arm7_cpu_device::static_generate_nocode_handler() void arm7_cpu_device::static_generate_out_of_cycles() { - drcuml_state *drcuml = m_impstate.drcuml; + drcuml_state &drcuml = *m_impstate.drcuml; /* begin generating */ - drcuml_block &block(drcuml->begin_block(10)); + drcuml_block &block(drcuml.begin_block(10)); /* generate a hash jump via the current mode and PC */ - alloc_handle(*drcuml, m_impstate.out_of_cycles, "out_of_cycles"); + alloc_handle(drcuml, m_impstate.out_of_cycles, "out_of_cycles"); UML_HANDLE(block, *m_impstate.out_of_cycles); // handle out_of_cycles UML_GETEXP(block, uml::I0); // getexp i0 UML_MOV(block, uml::mem(&R15), uml::I0); // mov <pc>,i0 @@ -718,16 +714,16 @@ void arm7_cpu_device::static_generate_detect_fault(uml::code_handle **handleptr) { /* on entry, flags are in I2, vaddr is in I3, desc_lvl1 is in I4, ap is in R5 */ /* on exit, fault result is in I6 */ - drcuml_state *drcuml = m_impstate.drcuml; + drcuml_state &drcuml = *m_impstate.drcuml; int donefault = 0; int checkuser = 0; int label = 1; /* begin generating */ - drcuml_block &block(drcuml->begin_block(1024)); + drcuml_block &block(drcuml.begin_block(1024)); /* add a global entry for this */ - alloc_handle(*drcuml, m_impstate.detect_fault, "detect_fault"); + alloc_handle(drcuml, m_impstate.detect_fault, "detect_fault"); UML_HANDLE(block, *m_impstate.detect_fault); // handle detect_fault UML_ROLAND(block, uml::I6, uml::I4, 32-4, 0x0f<<1); // roland i6, i4, 32-4, 0xf<<1 @@ -796,7 +792,7 @@ void arm7_cpu_device::static_generate_tlb_translate(uml::code_handle **handleptr /* on entry, address is in I0 and flags are in I2 */ /* on exit, translated address is in I0 and success/failure is in I2 */ /* routine trashes I4-I7 */ - drcuml_state *drcuml = m_impstate.drcuml; + drcuml_state &drcuml = *m_impstate.drcuml; uml::code_label smallfault; uml::code_label smallprefetch; int nopid = 0; @@ -815,9 +811,9 @@ void arm7_cpu_device::static_generate_tlb_translate(uml::code_handle **handleptr int label = 1; /* begin generating */ - drcuml_block &block(drcuml->begin_block(170)); + drcuml_block &block(drcuml.begin_block(170)); - alloc_handle(*drcuml, m_impstate.tlb_translate, "tlb_translate"); + alloc_handle(drcuml, m_impstate.tlb_translate, "tlb_translate"); UML_HANDLE(block, *m_impstate.tlb_translate); // handle tlb_translate // I3: vaddr @@ -1004,15 +1000,15 @@ void arm7_cpu_device::static_generate_memory_accessor(int size, bool istlb, bool /* on entry, address is in I0; data for writes is in I1, fetch type in I2 */ /* on exit, read result is in I0 */ /* routine trashes I0-I3 */ - drcuml_state *drcuml = m_impstate.drcuml; + drcuml_state &drcuml = *m_impstate.drcuml; //int tlbmiss = 0; int label = 1; /* begin generating */ - drcuml_block &block(drcuml->begin_block(1024)); + drcuml_block &block(drcuml.begin_block(1024)); /* add a global entry for this */ - alloc_handle(*drcuml, handleptr, name); + alloc_handle(drcuml, handleptr, name); UML_HANDLE(block, *handleptr); // handle *handleptr if (istlb) @@ -1031,7 +1027,7 @@ void arm7_cpu_device::static_generate_memory_accessor(int size, bool istlb, bool } /* general case: assume paging and perform a translation */ - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) == 0) + if (!debugger_enabled()) { for (int ramnum = 0; ramnum < ARM7_MAX_FASTRAM; ramnum++) { @@ -1270,7 +1266,7 @@ void arm7_cpu_device::generate_sequence_instruction(drcuml_block &block, compile UML_MAPVAR(block, MAPVAR_CYCLES, compiler.cycles); // mapvar CYCLES,compiler.cycles /* if we are debugging, call the debugger */ - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) + if (debugger_enabled()) { UML_MOV(block, uml::mem(&R15), desc->pc); // mov [pc],desc->pc save_fast_iregs(block); diff --git a/src/devices/cpu/arm7/arm7fe.hxx b/src/devices/cpu/arm7/arm7fe.hxx index 9fcb97776aa..9cefd6f0f81 100644 --- a/src/devices/cpu/arm7/arm7fe.hxx +++ b/src/devices/cpu/arm7/arm7fe.hxx @@ -2,7 +2,7 @@ // copyright-holders:Ryan Holtz /*************************************************************************** - arm7fe.c + arm7fe.hxx Front-end for ARM7 DRC diff --git a/src/devices/cpu/arm7/arm7help.h b/src/devices/cpu/arm7/arm7help.h index c006bfbf1af..544cbbbd269 100644 --- a/src/devices/cpu/arm7/arm7help.h +++ b/src/devices/cpu/arm7/arm7help.h @@ -7,12 +7,6 @@ #define ARM7_ICOUNT m_icount -#if 0 -#define LOG(x) osd_printf_debug x -#else -#define LOG(x) logerror x -#endif - /*************** * helper funcs ***************/ @@ -166,8 +160,3 @@ #define WRITE32(addr,data) arm7_cpu_write32(addr,data) #define PTR_READ32 &arm7_cpu_read32 #define PTR_WRITE32 &arm7_cpu_write32 - -#define LSL(v, s) ((v) << (s)) -#define LSR(v, s) ((v) >> (s)) -#define ROL(v, s) (LSL((v), (s)) | (LSR((v), 32u - (s)))) -#define ROR(v, s) (LSR((v), (s)) | (LSL((v), 32u - (s)))) diff --git a/src/devices/cpu/arm7/arm7ops.cpp b/src/devices/cpu/arm7/arm7ops.cpp index ab5bd9243aa..416789a1e19 100644 --- a/src/devices/cpu/arm7/arm7ops.cpp +++ b/src/devices/cpu/arm7/arm7ops.cpp @@ -5,6 +5,11 @@ #include "arm7core.h" #include "arm7help.h" +#define LOG_OPS (1U << 1) + +#define VERBOSE (0) +#include "logmacro.h" + int64_t arm7_cpu_device::saturate_qbit_overflow(int64_t res) { if (res > 2147483647) // INT32_MAX @@ -61,17 +66,17 @@ uint32_t arm7_cpu_device::decodeShift(uint32_t insn, uint32_t *pCarry) /* All shift types ending in 1 are Rk, not #k */ if (t & 1) { -// LOG(("%08x: RegShift %02x %02x\n", R15, k >> 1, GetRegister(k >> 1))); +// LOGMASKED(LOG_OPS, "%08x: RegShift %02x %02x\n", R15, k >> 1, GetRegister(k >> 1)); #if ARM7_DEBUG_CORE if ((insn & 0x80) == 0x80) - LOG(("%08x: RegShift ERROR (p36)\n", R15)); + LOGMASKED(LOG_OPS, "%08x: RegShift ERROR (p36)\n", R15); #endif // Keep only the bottom 8 bits for a Register Shift k = GetRegister(k >> 1) & 0xff; if (k == 0) /* Register shift by 0 is a no-op */ { -// LOG(("%08x: NO-OP Regshift\n", R15)); +// LOGMASKED(LOG_OPS, "%08x: NO-OP Regshift\n", R15); if (pCarry) *pCarry = GET_CPSR & C_MASK; return rm; @@ -97,7 +102,7 @@ uint32_t arm7_cpu_device::decodeShift(uint32_t insn, uint32_t *pCarry) // LSL (0,31) = Result shifted, least significant bit is in carry out *pCarry = k ? (rm & (1 << (32 - k))) : (GET_CPSR & C_MASK); } - return k ? LSL(rm, k) : rm; + return k ? (rm << k) : rm; } case 1: /* LSR */ @@ -117,7 +122,7 @@ uint32_t arm7_cpu_device::decodeShift(uint32_t insn, uint32_t *pCarry) { if (pCarry) *pCarry = (rm & (1 << (k - 1))); - return LSR(rm, k); + return rm >> k; } case 2: /* ASR */ @@ -131,9 +136,9 @@ uint32_t arm7_cpu_device::decodeShift(uint32_t insn, uint32_t *pCarry) else { if (rm & SIGN_BIT) - return LSR(rm, k) | (0xffffffffu << (32 - k)); + return (rm >> k) | (0xffffffffu << (32 - k)); else - return LSR(rm, k); + return rm >> k; } case 3: /* ROR and RRX */ @@ -144,7 +149,7 @@ uint32_t arm7_cpu_device::decodeShift(uint32_t insn, uint32_t *pCarry) { if (pCarry) *pCarry = rm & (1 << (k - 1)); - return ROR(rm, k); + return rotr_32(rm, k); } else { @@ -158,11 +163,11 @@ uint32_t arm7_cpu_device::decodeShift(uint32_t insn, uint32_t *pCarry) /* RRX */ if (pCarry) *pCarry = (rm & 1); - return LSR(rm, 1) | ((GET_CPSR & C_MASK) << 2); + return (rm >> 1) | ((GET_CPSR & C_MASK) << 2); } } - LOG(("%08x: Decodeshift error\n", R15)); + LOGMASKED(LOG_OPS, "%08x: Decodeshift error\n", R15); return 0; } /* decodeShift */ @@ -178,25 +183,24 @@ int arm7_cpu_device::loadInc(uint32_t pat, uint32_t rbv, uint32_t s, int mode) { if ((pat >> i) & 1) { - if (!m_pendingAbtD) // "Overwriting of registers stops when the abort happens." + data = READ32(rbv += 4); + if (m_pendingAbtD) // "Overwriting of registers stops when the abort happens." + return result; + if (i == 15) { - data = READ32(rbv += 4); - if (i == 15) - { - if (s) /* Pull full contents from stack */ - SetModeRegister(mode, 15, data); - else if (MODE32) /* Pull only address, preserve mode & status flags */ - SetModeRegister(mode, 15, data); - else - { - SetModeRegister(mode, 15, (GetModeRegister(mode, 15) & ~0x03FFFFFC) | (data & 0x03FFFFFC)); - } - } + if (s) /* Pull full contents from stack */ + SetModeRegister(mode, 15, data); + else if (MODE32) /* Pull only address, preserve mode & status flags */ + SetModeRegister(mode, 15, data); else { - SetModeRegister(mode, i, data); + SetModeRegister(mode, 15, (GetModeRegister(mode, 15) & ~0x03FFFFFC) | (data & 0x03FFFFFC)); } } + else + { + SetModeRegister(mode, i, data); + } result++; } } @@ -215,25 +219,24 @@ int arm7_cpu_device::loadDec(uint32_t pat, uint32_t rbv, uint32_t s, int mode) { if ((pat >> i) & 1) { - if (!m_pendingAbtD) // "Overwriting of registers stops when the abort happens." + data = READ32(rbv -= 4); + if (m_pendingAbtD) // "Overwriting of registers stops when the abort happens." + return result; + if (i == 15) { - data = READ32(rbv -= 4); - if (i == 15) - { - if (s) /* Pull full contents from stack */ - SetModeRegister(mode, 15, data); - else if (MODE32) /* Pull only address, preserve mode & status flags */ - SetModeRegister(mode, 15, data); - else - { - SetModeRegister(mode, 15, (GetModeRegister(mode, 15) & ~0x03FFFFFC) | (data & 0x03FFFFFC)); - } - } + if (s) /* Pull full contents from stack */ + SetModeRegister(mode, 15, data); + else if (MODE32) /* Pull only address, preserve mode & status flags */ + SetModeRegister(mode, 15, data); else { - SetModeRegister(mode, i, data); + SetModeRegister(mode, 15, (GetModeRegister(mode, 15) & ~0x03FFFFFC) | (data & 0x03FFFFFC)); } } + else + { + SetModeRegister(mode, i, data); + } result++; } } @@ -252,9 +255,11 @@ int arm7_cpu_device::storeInc(uint32_t pat, uint32_t rbv, int mode) { #if ARM7_DEBUG_CORE if (i == 15) /* R15 is plus 12 from address of STM */ - LOG(("%08x: StoreInc on R15\n", R15)); + LOGMASKED(LOG_OPS, "%08x: StoreInc on R15\n", R15); #endif WRITE32(rbv += 4, GetModeRegister(mode, i)); + if (m_pendingAbtD) + return result; result++; } } @@ -266,6 +271,7 @@ int arm7_cpu_device::storeDec(uint32_t pat, uint32_t rbv, int mode) { // pre-count the # of registers being stored int const result = population_count_32(pat & 0x0000ffff); + int actual_result = 0; // adjust starting address rbv -= (result << 2); @@ -276,10 +282,13 @@ int arm7_cpu_device::storeDec(uint32_t pat, uint32_t rbv, int mode) { #if ARM7_DEBUG_CORE if (i == 15) /* R15 is plus 12 from address of STM */ - LOG(("%08x: StoreDec on R15\n", R15)); + LOGMASKED(LOG_OPS, "%08x: StoreDec on R15\n", R15); #endif WRITE32(rbv, GetModeRegister(mode, i)); + if (m_pendingAbtD) + return actual_result; rbv += 4; + actual_result++; } } return result; @@ -294,7 +303,7 @@ int arm7_cpu_device::storeDec(uint32_t pat, uint32_t rbv, int mode) void arm7_cpu_device::HandleCoProcDO(uint32_t insn) { // This instruction simply instructs the co-processor to do something, no data is returned to ARM7 core - arm7_do_callback(*m_program, insn, 0, 0); // simply pass entire opcode to callback - since data format is actually dependent on co-proc implementation + arm7_do_callback(0); // simply pass entire opcode to callback - since data format is actually dependent on co-proc implementation } // Co-Processor Register Transfer - To/From Arm to Co-Proc @@ -305,7 +314,7 @@ void arm7_cpu_device::HandleCoProcRT(uint32_t insn) // Load (MRC) data from Co-Proc to ARM7 register if (insn & 0x00100000) // Bit 20 = Load or Store { - uint32_t res = arm7_rt_r_callback(*m_program, insn, 0); // RT Read handler must parse opcode & return appropriate result + uint32_t res = arm7_rt_r_callback(insn); // RT Read handler must parse opcode & return appropriate result if (!m_pendingUnd) { SetRegister((insn >> 12) & 0xf, res); @@ -314,7 +323,7 @@ void arm7_cpu_device::HandleCoProcRT(uint32_t insn) // Store (MCR) data from ARM7 to Co-Proc register else { - arm7_rt_w_callback(*m_program, insn, GetRegister((insn >> 12) & 0xf), 0); + arm7_rt_w_callback(insn, GetRegister((insn >> 12) & 0xf)); } } @@ -340,7 +349,7 @@ void arm7_cpu_device::HandleCoProcDT(uint32_t insn) #if ARM7_DEBUG_CORE if (((insn >> 16) & 0xf) == 15 && (insn & 0x200000)) - LOG(("%08x: Illegal use of R15 as base for write back value!\n", R15)); + LOGMASKED(LOG_OPS, "%08x: Illegal use of R15 as base for write back value!\n", R15); #endif // Pre-Increment base address (IF POST INCREMENT - CALL BACK FUNCTION MUST DO IT) @@ -387,20 +396,10 @@ void arm7_cpu_device::HandleBranch(uint32_t insn, bool h_bit) } /* Sign-extend the 24-bit offset in our calculations */ - if (off & 0x2000000u) - { - if (MODE32) - R15 -= ((~(off | 0xfc000000u)) + 1) - 8; - else - R15 = ((R15 - (((~(off | 0xfc000000u)) + 1) - 8)) & 0x03FFFFFC) | (R15 & ~0x03FFFFFC); - } + if (MODE32) + R15 += util::sext(off, 26) + 8; else - { - if (MODE32) - R15 += off + 8; - else - R15 = ((R15 + (off + 8)) & 0x03FFFFFC) | (R15 & ~0x03FFFFFC); - } + R15 = ((R15 + (util::sext(off, 26) + 8)) & 0x03FFFFFC) | (R15 & ~0x03FFFFFC); } void arm7_cpu_device::HandleMemSingle(uint32_t insn) @@ -513,8 +512,8 @@ void arm7_cpu_device::HandleMemSingle(uint32_t insn) if (insn & INSN_SDT_B) { #if ARM7_DEBUG_CORE - if (rd == eR15) - LOG(("Wrote R15 in byte mode\n")); + if (rd == eR15) + LOGMASKED(LOG_OPS, "Wrote R15 in byte mode\n"); #endif WRITE8(rnv, (uint8_t) GetRegister(rd) & 0xffu); @@ -522,8 +521,8 @@ void arm7_cpu_device::HandleMemSingle(uint32_t insn) else { #if ARM7_DEBUG_CORE - if (rd == eR15) - LOG(("Wrote R15 in 32bit mode\n")); + if (rd == eR15) + LOGMASKED(LOG_OPS, "Wrote R15 in 32bit mode\n"); #endif //WRITE32(rnv, rd == eR15 ? R15 + 8 : GetRegister(rd)); @@ -555,7 +554,7 @@ void arm7_cpu_device::HandleMemSingle(uint32_t insn) } else { if ((insn & INSN_SDT_W) != 0) - LOG(("%08x: RegisterWritebackIncrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0)); + LOGMASKED(LOG_OPS, "%08x: RegisterWritebackIncrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0); SetRegister(rn, (rnv + off)); } @@ -571,7 +570,7 @@ void arm7_cpu_device::HandleMemSingle(uint32_t insn) SetRegister(rn, (rnv - off)); if ((insn & INSN_SDT_W) != 0) - LOG(("%08x: RegisterWritebackDecrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0)); + LOGMASKED(LOG_OPS, "%08x: RegisterWritebackDecrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0); } } } @@ -768,7 +767,7 @@ void arm7_cpu_device::HandleHalfWordDT(uint32_t insn) } else { if ((insn & INSN_SDT_W) != 0) - LOG(("%08x: RegisterWritebackIncrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0)); + LOGMASKED(LOG_OPS, "%08x: RegisterWritebackIncrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0); SetRegister(rn, (rnv + off)); } @@ -784,7 +783,7 @@ void arm7_cpu_device::HandleHalfWordDT(uint32_t insn) SetRegister(rn, (rnv - off)); if ((insn & INSN_SDT_W) != 0) - LOG(("%08x: RegisterWritebackDecrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0)); + LOGMASKED(LOG_OPS, "%08x: RegisterWritebackDecrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0); } } } @@ -803,21 +802,27 @@ void arm7_cpu_device::HandleSwap(uint32_t insn) #if ARM7_DEBUG_CORE if (rn == 15 || rm == 15 || rd == 15) - LOG(("%08x: Illegal use of R15 in Swap Instruction\n", R15)); + LOGMASKED(LOG_OPS, "%08x: Illegal use of R15 in Swap Instruction\n", R15); #endif // can be byte or word if (insn & 0x400000) { tmp = READ8(rn); - WRITE8(rn, rm); - SetRegister(rd, tmp); + if (!m_pendingAbtD) + { + WRITE8(rn, rm); + SetRegister(rd, tmp); + } } else { tmp = READ32(rn); - WRITE32(rn, rm); - SetRegister(rd, tmp); + if (!m_pendingAbtD) + { + WRITE32(rn, rm); + SetRegister(rd, tmp); + } } R15 += 4; @@ -842,7 +847,7 @@ void arm7_cpu_device::HandlePSRTransfer(uint32_t insn) // Value can be specified for a Right Rotate, 2x the value specified. int by = (insn & INSN_OP2_ROTATE) >> INSN_OP2_ROTATE_SHIFT; if (by) - val = ROR(insn & INSN_OP2_IMM, by << 1); + val = rotr_32(insn & INSN_OP2_IMM, by << 1); else val = insn & INSN_OP2_IMM; } @@ -952,7 +957,7 @@ void arm7_cpu_device::HandleALU(uint32_t insn) by = (insn & INSN_OP2_ROTATE) >> INSN_OP2_ROTATE_SHIFT; if (by) { - op2 = ROR(insn & INSN_OP2_IMM, by << 1); + op2 = rotr_32(insn & INSN_OP2_IMM, by << 1); sc = op2 & SIGN_BIT; } else @@ -981,7 +986,7 @@ void arm7_cpu_device::HandleALU(uint32_t insn) if ((rn = (insn & INSN_RN) >> INSN_RN_SHIFT) == eR15) { #if ARM7_DEBUG_CORE - LOG(("%08x: Pipelined R15 (Shift %d)\n", R15, (insn & INSN_I ? 8 : insn & 0x10u ? 12 : 12))); + LOGMASKED(LOG_OPS, "%08x: Pipelined R15 (Shift %d)\n", R15, (insn & INSN_I ? 8 : insn & 0x10u ? 12 : 12)); #endif if (MODE32) rn = R15 + 8; @@ -1119,7 +1124,7 @@ void arm7_cpu_device::HandleALU(uint32_t insn) { if (insn & INSN_S) { #if ARM7_DEBUG_CORE - LOG(("%08x: TST class on R15 s bit set\n", R15)); + LOGMASKED(LOG_OPS, "%08x: TST class on R15 s bit set\n", R15); #endif if (MODE32) R15 = rd; @@ -1138,7 +1143,7 @@ void arm7_cpu_device::HandleALU(uint32_t insn) else { #if ARM7_DEBUG_CORE - LOG(("%08x: TST class on R15 no s bit set\n", R15)); + LOGMASKED(LOG_OPS, "%08x: TST class on R15 no s bit set\n", R15); #endif } // extra cycles (PC written) @@ -1169,7 +1174,7 @@ void arm7_cpu_device::HandleMul(uint32_t insn) if ((insn & INSN_MUL_RM) == 0xf || ((insn & INSN_MUL_RS) >> INSN_MUL_RS_SHIFT) == 0xf || ((insn & INSN_MUL_RN) >> INSN_MUL_RN_SHIFT) == 0xf) - LOG(("%08x: R15 used in mult\n", R15)); + LOGMASKED(LOG_OPS, "%08x: R15 used in mult\n", R15); #endif /* Add on Rn if this is a MLA */ @@ -1201,26 +1206,22 @@ void arm7_cpu_device::HandleMul(uint32_t insn) // todo: add proper cycle counts void arm7_cpu_device::HandleSMulLong(uint32_t insn) { - int32_t rm, rs; - uint32_t rhi, rlo; - int64_t res; - // MULL takes 1S + (m+1)I and MLAL 1S + (m+2)I cycles to execute, where m is the // number of 8 bit multiplier array cycles required to complete the multiply, which is // controlled by the value of the multiplier operand specified by Rs. - rm = (int32_t)GetRegister(insn & 0xf); - rs = (int32_t)GetRegister(((insn >> 8) & 0xf)); - rhi = (insn >> 16) & 0xf; - rlo = (insn >> 12) & 0xf; + int32_t rm = (int32_t)GetRegister(insn & 0xf); + int32_t rs = (int32_t)GetRegister(((insn >> 8) & 0xf)); + uint32_t rhi = (insn >> 16) & 0xf; + uint32_t rlo = (insn >> 12) & 0xf; #if ARM7_DEBUG_CORE if ((insn & 0xf) == 15 || ((insn >> 8) & 0xf) == 15 || ((insn >> 16) & 0xf) == 15 || ((insn >> 12) & 0xf) == 15) - LOG(("%08x: Illegal use of PC as a register in SMULL opcode\n", R15)); + LOGMASKED(LOG_OPS, "%08x: Illegal use of PC as a register in SMULL opcode\n", R15); #endif /* Perform the multiplication */ - res = (int64_t)rm * rs; + int64_t res = mul_32x32(rm, rs); /* Add on Rn if this is a MLA */ if (insn & INSN_MUL_A) @@ -1253,26 +1254,22 @@ void arm7_cpu_device::HandleSMulLong(uint32_t insn) // todo: add proper cycle counts void arm7_cpu_device::HandleUMulLong(uint32_t insn) { - uint32_t rm, rs; - uint32_t rhi, rlo; - uint64_t res; - // MULL takes 1S + (m+1)I and MLAL 1S + (m+2)I cycles to execute, where m is the // number of 8 bit multiplier array cycles required to complete the multiply, which is // controlled by the value of the multiplier operand specified by Rs. - rm = (int32_t)GetRegister(insn & 0xf); - rs = (int32_t)GetRegister(((insn >> 8) & 0xf)); - rhi = (insn >> 16) & 0xf; - rlo = (insn >> 12) & 0xf; + uint32_t rm = GetRegister(insn & 0xf); + uint32_t rs = GetRegister(((insn >> 8) & 0xf)); + uint32_t rhi = (insn >> 16) & 0xf; + uint32_t rlo = (insn >> 12) & 0xf; #if ARM7_DEBUG_CORE if (((insn & 0xf) == 15) || (((insn >> 8) & 0xf) == 15) || (((insn >> 16) & 0xf) == 15) || (((insn >> 12) & 0xf) == 15)) - LOG(("%08x: Illegal use of PC as a register in SMULL opcode\n", R15)); + LOGMASKED(LOG_OPS, "%08x: Illegal use of PC as a register in SMULL opcode\n", R15); #endif /* Perform the multiplication */ - res = (uint64_t)rm * rs; + uint64_t res = mulu_32x32(rm, rs); /* Add on Rn if this is a MLA */ if (insn & INSN_MUL_A) @@ -1309,7 +1306,7 @@ void arm7_cpu_device::HandleMemBlock(uint32_t insn) #if ARM7_DEBUG_CORE if (rbp & 3) - LOG(("%08x: Unaligned Mem Transfer @ %08x\n", R15, rbp)); + LOGMASKED(LOG_OPS, "%08x: Unaligned Mem Transfer @ %08x\n", R15, rbp); #endif // Normal LDM instructions take nS + 1N + 1I and LDM PC takes (n+1)S + 2N + 1I @@ -1335,7 +1332,7 @@ void arm7_cpu_device::HandleMemBlock(uint32_t insn) // set to user mode - then do the transfer, and set back //int curmode = GET_MODE; //SwitchMode(eARM7_MODE_USER); - LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15)); + LOGMASKED(LOG_OPS, "%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15); result = loadInc(insn & 0xffff, rbp, insn & INSN_BDT_S, eARM7_MODE_USER); // todo - not sure if Writeback occurs on User registers also.. //SwitchMode(curmode); @@ -1346,8 +1343,8 @@ void arm7_cpu_device::HandleMemBlock(uint32_t insn) if ((insn & INSN_BDT_W) && !m_pendingAbtD) { #if ARM7_DEBUG_CORE - if (rb == 15) - LOG(("%08x: Illegal LDRM writeback to r15\n", R15)); + if (rb == 15) + LOGMASKED(LOG_OPS, "%08x: Illegal LDRM writeback to r15\n", R15); #endif // "A LDM will always overwrite the updated base if the base is in the list." (also for a user bank transfer?) // GBA "V-Rally 3" expects R0 not to be overwritten with the updated base value [BP 8077B0C] @@ -1372,7 +1369,7 @@ void arm7_cpu_device::HandleMemBlock(uint32_t insn) else { uint32_t temp; -// LOG(("LDM + S | R15 %08X CPSR %08X\n", R15, GET_CPSR)); +// LOGMASKED(LOG_OPS, "LDM + S | R15 %08X CPSR %08X\n", R15, GET_CPSR); temp = (GET_CPSR & 0x0FFFFF20) | (R15 & 0xF0000000) /* N Z C V */ | ((R15 & 0x0C000000) >> (26 - 6)) /* I F */ | (R15 & 0x00000003) /* M1 M0 */; set_cpsr( temp); SwitchMode(temp & 3); @@ -1402,7 +1399,7 @@ void arm7_cpu_device::HandleMemBlock(uint32_t insn) // set to user mode - then do the transfer, and set back //int curmode = GET_MODE; //SwitchMode(eARM7_MODE_USER); - LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15)); + LOGMASKED(LOG_OPS, "%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15); result = loadDec(insn & 0xffff, rbp, insn & INSN_BDT_S, eARM7_MODE_USER); // todo - not sure if Writeback occurs on User registers also.. //SwitchMode(curmode); @@ -1413,7 +1410,7 @@ void arm7_cpu_device::HandleMemBlock(uint32_t insn) if ((insn & INSN_BDT_W) && !m_pendingAbtD) { if (rb == 0xf) - LOG(("%08x: Illegal LDRM writeback to r15\n", R15)); + LOGMASKED(LOG_OPS, "%08x: Illegal LDRM writeback to r15\n", R15); // "A LDM will always overwrite the updated base if the base is in the list." (also for a user bank transfer?) if (((insn >> rb) & 1) == 0) { @@ -1435,7 +1432,7 @@ void arm7_cpu_device::HandleMemBlock(uint32_t insn) else { uint32_t temp; -// LOG(("LDM + S | R15 %08X CPSR %08X\n", R15, GET_CPSR)); +// LOGMASKED(LOG_OPS, "LDM + S | R15 %08X CPSR %08X\n", R15, GET_CPSR); temp = (GET_CPSR & 0x0FFFFF20) /* N Z C V I F M4 M3 M2 M1 M0 */ | (R15 & 0xF0000000) /* N Z C V */ | ((R15 & 0x0C000000) >> (26 - 6)) /* I F */ | (R15 & 0x00000003) /* M1 M0 */; set_cpsr(temp); SwitchMode(temp & 3); @@ -1460,7 +1457,7 @@ void arm7_cpu_device::HandleMemBlock(uint32_t insn) if (insn & (1 << eR15)) { #if ARM7_DEBUG_CORE - LOG(("%08x: Writing R15 in strm\n", R15)); + LOGMASKED(LOG_OPS, "%08x: Writing R15 in strm\n", R15); #endif /* special case handling if writing to PC */ R15 += 12; @@ -1481,7 +1478,7 @@ void arm7_cpu_device::HandleMemBlock(uint32_t insn) // set to user mode - then do the transfer, and set back //int curmode = GET_MODE; //SwitchMode(eARM7_MODE_USER); - LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15)); + LOGMASKED(LOG_OPS, "%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15); result = storeInc(insn & 0xffff, rbp, eARM7_MODE_USER); // todo - not sure if Writeback occurs on User registers also.. //SwitchMode(curmode); @@ -1508,7 +1505,7 @@ void arm7_cpu_device::HandleMemBlock(uint32_t insn) // set to user mode - then do the transfer, and set back //int curmode = GET_MODE; //SwitchMode(eARM7_MODE_USER); - LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15)); + LOGMASKED(LOG_OPS, "%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15); result = storeDec(insn & 0xffff, rbp, eARM7_MODE_USER); // todo - not sure if Writeback occurs on User registers also.. //SwitchMode(curmode); @@ -1549,7 +1546,7 @@ const arm7_cpu_device::arm7ops_ophandler arm7_cpu_device::ops_handler[0x20] = void arm7_cpu_device::arm9ops_undef(uint32_t insn) { // unsupported instruction - LOG(("ARM7: Instruction %08X unsupported\n", insn)); + LOGMASKED(LOG_OPS, "ARM7: Instruction %08X unsupported\n", insn); } void arm7_cpu_device::arm9ops_1(uint32_t insn) @@ -1661,8 +1658,8 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn) R15 = GetRegister(insn & 0x0f); // If new PC address has A0 set, switch to Thumb mode if (R15 & 1) { - set_cpsr(GET_CPSR|T_MASK); R15--; + set_cpsr(GET_CPSR|T_MASK); } } else if ((insn & 0x0ff000f0) == 0x01200030) // BLX Rn - v5 @@ -1673,8 +1670,8 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn) R15 = GetRegister(insn & 0x0f); // If new PC address has A0 set, switch to Thumb mode if (R15 & 1) { - set_cpsr(GET_CPSR|T_MASK); R15--; + set_cpsr(GET_CPSR|T_MASK); } } else if ((insn & 0x0ff000f0) == 0x01600010) // CLZ - v5 @@ -1682,7 +1679,7 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn) uint32_t rm = insn&0xf; uint32_t rd = (insn>>12)&0xf; - SetRegister(rd, count_leading_zeros(GetRegister(rm))); + SetRegister(rd, count_leading_zeros_32(GetRegister(rm))); R15 += 4; } @@ -1690,9 +1687,8 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn) { int32_t src1 = GetRegister(insn&0xf); int32_t src2 = GetRegister((insn>>16)&0xf); - int64_t res; - res = saturate_qbit_overflow((int64_t)src1 + (int64_t)src2); + int64_t res = saturate_qbit_overflow((int64_t)src1 + (int64_t)src2); SetRegister((insn>>12)&0xf, (int32_t)res); R15 += 4; @@ -1701,10 +1697,9 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn) { int32_t src1 = GetRegister(insn&0xf); int32_t src2 = GetRegister((insn>>16)&0xf); - int64_t res; // check if doubling operation will overflow - res = (int64_t)src2 * 2; + int64_t res = (int64_t)src2 * 2; saturate_qbit_overflow(res); src2 *= 2; @@ -1717,9 +1712,8 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn) { int32_t src1 = GetRegister(insn&0xf); int32_t src2 = GetRegister((insn>>16)&0xf); - int64_t res; - res = saturate_qbit_overflow((int64_t)src1 - (int64_t)src2); + int64_t res = saturate_qbit_overflow((int64_t)src1 - (int64_t)src2); SetRegister((insn>>12)&0xf, (int32_t)res); R15 += 4; @@ -1728,10 +1722,9 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn) { int32_t src1 = GetRegister(insn&0xf); int32_t src2 = GetRegister((insn>>16)&0xf); - int64_t res; // check if doubling operation will overflow - res = (int64_t)src2 * 2; + int64_t res = (int64_t)src2 * 2; saturate_qbit_overflow(res); src2 *= 2; @@ -1748,26 +1741,14 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn) // select top and bottom halves of src1/src2 and sign extend if necessary if (insn & 0x20) - { src1 >>= 16; - } - - src1 &= 0xffff; - if (src1 & 0x8000) - { - src1 |= 0xffff0000; - } + else + src1 = util::sext(src1, 16); if (insn & 0x40) - { src2 >>= 16; - } - - src2 &= 0xffff; - if (src2 & 0x8000) - { - src2 |= 0xffff0000; - } + else + src2 = util::sext(src2, 16); // do the signed multiply res1 = src1 * src2; @@ -1781,13 +1762,12 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn) { int32_t src1 = GetRegister(insn&0xf); int32_t src2 = GetRegister((insn>>8)&0xf); - int64_t dst; - dst = (int64_t)GetRegister((insn>>12)&0xf); + int64_t dst = (int64_t)GetRegister((insn>>12)&0xf); dst |= (int64_t)GetRegister((insn>>16)&0xf)<<32; // do the multiply and accumulate - dst += (int64_t)src1 * (int64_t)src2; + dst += mul_32x32(src1, src2); // write back the result SetRegister((insn>>12)&0xf, (uint32_t)dst); @@ -1798,32 +1778,19 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn) { int32_t src1 = GetRegister(insn&0xf); int32_t src2 = GetRegister((insn>>8)&0xf); - int32_t res; // select top and bottom halves of src1/src2 and sign extend if necessary if (insn & 0x20) - { src1 >>= 16; - } - - src1 &= 0xffff; - if (src1 & 0x8000) - { - src1 |= 0xffff0000; - } + else + src1 = util::sext(src1, 16); if (insn & 0x40) - { src2 >>= 16; - } - - src2 &= 0xffff; - if (src2 & 0x8000) - { - src2 |= 0xffff0000; - } + else + src2 = util::sext(src2, 16); - res = src1 * src2; + int32_t res = src1 * src2; SetRegister((insn>>16)&0xf, res); R15 += 4; } @@ -1831,21 +1798,13 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn) { int32_t src1 = GetRegister(insn&0xf); int32_t src2 = GetRegister((insn>>8)&0xf); - int64_t res; if (insn & 0x40) - { src2 >>= 16; - } - - src2 &= 0xffff; - if (src2 & 0x8000) - { - src2 |= 0xffff0000; - } + else + src2 = util::sext(src2, 16); - res = (int64_t)src1 * (int64_t)src2; - res >>= 16; + int32_t res = mul_32x32_shift(src1, src2, 16); SetRegister((insn>>16)&0xf, (uint32_t)res); R15 += 4; } @@ -1854,27 +1813,19 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn) int32_t src1 = GetRegister(insn&0xf); int32_t src2 = GetRegister((insn>>8)&0xf); int32_t src3 = GetRegister((insn>>12)&0xf); - int64_t res; if (insn & 0x40) - { src2 >>= 16; - } - - src2 &= 0xffff; - if (src2 & 0x8000) - { - src2 |= 0xffff0000; - } + else + src2 = util::sext(src2, 16); - res = (int64_t)src1 * (int64_t)src2; - res >>= 16; + int32_t res = mul_32x32_shift(src1, src2, 16); // check for overflow and set the Q bit saturate_qbit_overflow((int64_t)src3 + res); // do the real accumulate - src3 += (int32_t)res; + src3 += res; // write the result back SetRegister((insn>>16)&0xf, (uint32_t)res); diff --git a/src/devices/cpu/arm7/arm7thmb.cpp b/src/devices/cpu/arm7/arm7thmb.cpp index 154e0b85095..467606aee84 100644 --- a/src/devices/cpu/arm7/arm7thmb.cpp +++ b/src/devices/cpu/arm7/arm7thmb.cpp @@ -654,18 +654,21 @@ void arm7_cpu_device::tg04_00_06(uint32_t pc, uint32_t op) /* SBC Rd, Rs */ void arm7_cpu_device::tg04_00_07(uint32_t pc, uint32_t op) /* ROR Rd, Rs */ { - uint32_t rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; - uint32_t rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; - uint32_t rrd = GetRegister(rd); - uint32_t imm = GetRegister(rs) & 0x0000001f; - SetRegister(rd, (rrd >> imm) | (rrd << (32 - imm))); - if (rrd & (1 << (imm - 1))) - { - set_cpsr(GET_CPSR | C_MASK); - } - else - { - set_cpsr(GET_CPSR & ~C_MASK); + const uint32_t rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + const uint32_t rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + const uint32_t rrd = GetRegister(rd); + const uint32_t imm = GetRegister(rs) & 0xff; + if (imm > 0) + { + SetRegister(rd, rotr_32(rrd, imm)); + if (rrd & (1 << ((imm - 1) & 0x1f))) + { + set_cpsr(GET_CPSR | C_MASK); + } + else + { + set_cpsr(GET_CPSR & ~C_MASK); + } } set_cpsr(GET_CPSR & ~(Z_MASK | N_MASK)); set_cpsr(GET_CPSR | HandleALUNZFlags(GetRegister(rd))); @@ -1001,18 +1004,14 @@ void arm7_cpu_device::tg05_2(uint32_t pc, uint32_t op) /* STRB Rd, [Rn, Rm] */ R15 += 2; } -void arm7_cpu_device::tg05_3(uint32_t pc, uint32_t op) /* LDSB Rd, [Rn, Rm] todo, add dasm */ +void arm7_cpu_device::tg05_3(uint32_t pc, uint32_t op) /* LDRSB Rd, [Rn, Rm] */ { uint32_t rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; uint32_t rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; uint32_t rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; uint32_t addr = GetRegister(rn) + GetRegister(rm); uint32_t op2 = READ8(addr); - if (op2 & 0x00000080) - { - op2 |= 0xffffff00; - } - SetRegister(rd, op2); + SetRegister(rd, util::sext(op2, 8)); R15 += 2; } @@ -1049,7 +1048,7 @@ void arm7_cpu_device::tg05_6(uint32_t pc, uint32_t op) /* LDRB Rd, [Rn, Rm] */ R15 += 2; } -void arm7_cpu_device::tg05_7(uint32_t pc, uint32_t op) /* LDSH Rd, [Rn, Rm] */ +void arm7_cpu_device::tg05_7(uint32_t pc, uint32_t op) /* LDRSH Rd, [Rn, Rm] */ { uint32_t rm = (op & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; uint32_t rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; @@ -1544,11 +1543,7 @@ void arm7_cpu_device::tg0d_f(uint32_t pc, uint32_t op) // COND_NV: // SWI (thi void arm7_cpu_device::tg0e_0(uint32_t pc, uint32_t op) { - int32_t offs = (op & THUMB_BRANCH_OFFS) << 1; - if (offs & 0x00000800) - { - offs |= 0xfffff800; - } + int32_t offs = util::sext((op & THUMB_BRANCH_OFFS) << 1, 12); R15 += 4 + offs; } @@ -1569,11 +1564,7 @@ void arm7_cpu_device::tg0f_0(uint32_t pc, uint32_t op) { /* BL (HI) */ - uint32_t addr = (op & THUMB_BLOP_OFFS) << 12; - if (addr & (1 << 22)) - { - addr |= 0xff800000; - } + uint32_t addr = util::sext((op & THUMB_BLOP_OFFS) << 12, 23); addr += R15 + 4; SetRegister(14, addr); R15 += 2; diff --git a/src/devices/cpu/arm7/cecalls.hxx b/src/devices/cpu/arm7/cecalls.hxx new file mode 100644 index 00000000000..839ae5633b2 --- /dev/null +++ b/src/devices/cpu/arm7/cecalls.hxx @@ -0,0 +1,1066 @@ +// license:BSD-3-Clause +// copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz +/***************************************************************************** + * + * cecalls.hxx + * + * Addresses of certain Windows CE kernel calls, for use in debugging + * the bring-up of ARM-based Windows CE systems, e.g. Jornada 7xx. + * + *****************************************************************************/ + +void arm7_cpu_device::init_ce_kernel_addrs() +{ + memset(m_ce_kernel_addr_present, 0, 0x10400); + + add_ce_kernel_addr(0xf0010000, "SH_AFS_Unmount"); + add_ce_kernel_addr(0xf0010000, "SH_AFS_CloseHandle"); + add_ce_kernel_addr(0xf0010008, "SH_AFS_CreateDirectoryW"); + add_ce_kernel_addr(0xf001000c, "SH_AFS_RemoveDirectoryW"); + add_ce_kernel_addr(0xf0010010, "SH_AFS_GetFileAttributesW"); + add_ce_kernel_addr(0xf0010014, "SH_AFS_SetFileAttributesW"); + add_ce_kernel_addr(0xf0010018, "SH_AFS_CreateFileW"); + add_ce_kernel_addr(0xf001001c, "SH_AFS_DeleteFileW"); + add_ce_kernel_addr(0xf0010020, "SH_AFS_MoveFileW"); + add_ce_kernel_addr(0xf0010024, "SH_AFS_FindFirstFileW"); + add_ce_kernel_addr(0xf0010030, "SH_AFS_PrestoChangoFileName"); + add_ce_kernel_addr(0xf0010034, "SH_AFS_CloseAllFileHandles"); + add_ce_kernel_addr(0xf0010038, "SH_AFS_GetDiskFreeSpace"); + add_ce_kernel_addr(0xf001003c, "SH_AFS_NotifyMountedFS"); + add_ce_kernel_addr(0xf0010040, "SH_AFS_RegisterFileSystemFunction"); + add_ce_kernel_addr(0xf0010044, "SH_AFS_FindFirstChangeNotificationW"); + add_ce_kernel_addr(0xf000fffc, "SH_WIN32_NotSupported"); + add_ce_kernel_addr(0xf000fff8, "SH_WIN32_CreateAPISet"); + add_ce_kernel_addr(0xf000fff4, "SH_WIN32_VirtualAlloc"); + add_ce_kernel_addr(0xf000fff0, "SH_WIN32_VirtualFree"); + add_ce_kernel_addr(0xf000ffec, "SH_WIN32_VirtualProtect"); + add_ce_kernel_addr(0xf000ffe8, "SH_WIN32_VirtualQuery"); + add_ce_kernel_addr(0xf000ffe4, "SH_WIN32_VirtualCopy"); + add_ce_kernel_addr(0xf000ffe0, "SH_WIN32_LoadLibraryW"); + add_ce_kernel_addr(0xf000ffdc, "SH_WIN32_FreeLibrary"); + add_ce_kernel_addr(0xf000ffd8, "SH_WIN32_GetProcAddressW"); + add_ce_kernel_addr(0xf000ffd4, "SH_WIN32_ThreadAttachOrDetach"); + add_ce_kernel_addr(0xf000ffd0, "SH_WIN32_ThreadDetachAllDLLs"); + add_ce_kernel_addr(0xf000ffcc, "SH_WIN32_GetTickCount"); + add_ce_kernel_addr(0xf000ffc8, "SH_WIN32_OutputDebugStringW"); + add_ce_kernel_addr(0xf000ffc4, "SH_WIN32_TlsCall"); + add_ce_kernel_addr(0xf000ffc0, "SH_WIN32_GetSystemInfo"); + add_ce_kernel_addr(0xf000ffbc, "SH_WIN32_U_ropen"); + add_ce_kernel_addr(0xf000ffb8, "SH_WIN32_U_rread"); + add_ce_kernel_addr(0xf000ffb4, "SH_WIN32_U_rwrite"); + add_ce_kernel_addr(0xf000ffb0, "SH_WIN32_U_rlseek"); + add_ce_kernel_addr(0xf000ffac, "SH_WIN32_U_rclose"); + add_ce_kernel_addr(0xf000ffa8, "SH_WIN32_RegisterDbgZones"); + add_ce_kernel_addr(0xf000ffa4, "SH_WIN32_NKvDbgPrintfW"); + add_ce_kernel_addr(0xf000ffa0, "SH_WIN32_ProfileSyscall"); + add_ce_kernel_addr(0xf000ff9c, "SH_WIN32_FindResourceW"); + add_ce_kernel_addr(0xf000ff98, "SH_WIN32_LoadResource"); + add_ce_kernel_addr(0xf000ff94, "SH_WIN32_SizeofResource"); + add_ce_kernel_addr(0xf000ff90, "SH_WIN32_GetRealTime"); + add_ce_kernel_addr(0xf000ff8c, "SH_WIN32_SetRealTime"); + add_ce_kernel_addr(0xf000ff88, "SH_WIN32_ProcessDetachAllDLLs"); + add_ce_kernel_addr(0xf000ff84, "SH_WIN32_ExtractResource"); + add_ce_kernel_addr(0xf000ff80, "SH_WIN32_GetRomFileInfo"); + add_ce_kernel_addr(0xf000ff7c, "SH_WIN32_GetRomFileBytes"); + add_ce_kernel_addr(0xf000ff78, "SH_WIN32_CacheRangeFlush"); + add_ce_kernel_addr(0xf000ff74, "SH_WIN32_AddTrackedItem"); + add_ce_kernel_addr(0xf000ff70, "SH_WIN32_DeleteTrackedItem"); + add_ce_kernel_addr(0xf000ff6c, "SH_WIN32_PrintTrackedItem"); + add_ce_kernel_addr(0xf000ff68, "SH_WIN32_GetKPhys"); + add_ce_kernel_addr(0xf000ff64, "SH_WIN32_GiveKPhys"); + add_ce_kernel_addr(0xf000ff60, "SH_WIN32_SetExceptionHandler"); + add_ce_kernel_addr(0xf000ff5c, "SH_WIN32_RegisterTrackedItem"); + add_ce_kernel_addr(0xf000ff58, "SH_WIN32_FilterTrackedItem"); + add_ce_kernel_addr(0xf000ff54, "SH_WIN32_SetKernelAlarm"); + add_ce_kernel_addr(0xf000ff50, "SH_WIN32_RefreshKernelAlarm"); + add_ce_kernel_addr(0xf000ff4c, "SH_WIN32_CeGetRandomSeed"); + add_ce_kernel_addr(0xf000ff48, "SH_WIN32_CloseProcOE"); + add_ce_kernel_addr(0xf000ff44, "SH_WIN32_SetGwesOOMEvent"); + add_ce_kernel_addr(0xf000ff40, "SH_WIN32_StringCompress"); + add_ce_kernel_addr(0xf000ff3c, "SH_WIN32_StringDecompress"); + add_ce_kernel_addr(0xf000ff38, "SH_WIN32_BinaryCompress"); + add_ce_kernel_addr(0xf000ff34, "SH_WIN32_BinaryDecompress"); + add_ce_kernel_addr(0xf000ff30, "SH_WIN32_CreateEventW"); + add_ce_kernel_addr(0xf000ff2c, "SH_WIN32_CreateProcessW"); + add_ce_kernel_addr(0xf000ff28, "SH_WIN32_CreateThread"); + add_ce_kernel_addr(0xf000ff24, "SH_WIN32_InputDebugCharW"); + add_ce_kernel_addr(0xf000ff20, "SH_WIN32_TakeCritSec"); + add_ce_kernel_addr(0xf000ff1c, "SH_WIN32_LeaveCritSec"); + add_ce_kernel_addr(0xf000ff18, "SH_WIN32_WaitForMultipleObjects"); + add_ce_kernel_addr(0xf000ff14, "SH_WIN32_MapPtrToProcess"); + add_ce_kernel_addr(0xf000ff10, "SH_WIN32_MapPtrUnsecure"); + add_ce_kernel_addr(0xf000ff0c, "SH_WIN32_GetProcFromPtr"); + add_ce_kernel_addr(0xf000ff08, "SH_WIN32_IsBadPtr"); + add_ce_kernel_addr(0xf000ff04, "SH_WIN32_GetProcAddrBits"); + add_ce_kernel_addr(0xf000ff00, "SH_WIN32_GetFSHeapInfo"); + add_ce_kernel_addr(0xf000fefc, "SH_WIN32_OtherThreadsRunning"); + add_ce_kernel_addr(0xf000fef8, "SH_WIN32_KillAllOtherThreads"); + add_ce_kernel_addr(0xf000fef4, "SH_WIN32_GetOwnerProcess"); + add_ce_kernel_addr(0xf000fef0, "SH_WIN32_GetCallerProcess"); + add_ce_kernel_addr(0xf000feec, "SH_WIN32_GetIdleTime"); + add_ce_kernel_addr(0xf000fee8, "SH_WIN32_SetLowestScheduledPriority"); + add_ce_kernel_addr(0xf000fee4, "SH_WIN32_IsPrimaryThread"); + add_ce_kernel_addr(0xf000fee0, "SH_WIN32_SetProcPermissions"); + add_ce_kernel_addr(0xf000fedc, "SH_WIN32_GetCurrentPermissions"); + add_ce_kernel_addr(0xf000fed4, "SH_WIN32_SetDaylightTime"); + add_ce_kernel_addr(0xf000fed0, "SH_WIN32_SetTimeZoneBias"); + add_ce_kernel_addr(0xf000fecc, "SH_WIN32_SetCleanRebootFlag"); + add_ce_kernel_addr(0xf000fec8, "SH_WIN32_CreateCrit"); + add_ce_kernel_addr(0xf000fec4, "SH_WIN32_PowerOffSystem"); + add_ce_kernel_addr(0xf000fec0, "SH_WIN32_CreateMutexW"); + add_ce_kernel_addr(0xf000febc, "SH_WIN32_SetDbgZone"); + add_ce_kernel_addr(0xf000feb8, "SH_WIN32_Sleep"); + add_ce_kernel_addr(0xf000feb4, "SH_WIN32_TurnOnProfiling"); + add_ce_kernel_addr(0xf000feb0, "SH_WIN32_TurnOffProfiling"); + add_ce_kernel_addr(0xf000feac, "SH_WIN32_CeGetCurrentTrust"); + add_ce_kernel_addr(0xf000fea8, "SH_WIN32_CeGetCallerTrust"); + add_ce_kernel_addr(0xf000fea4, "SH_WIN32_NKTerminateThread"); + add_ce_kernel_addr(0xf000fea0, "SH_WIN32_SetLastError"); + add_ce_kernel_addr(0xf000fe9c, "SH_WIN32_GetLastError"); + add_ce_kernel_addr(0xf000fe98, "SH_WIN32_GetProcName"); + add_ce_kernel_addr(0xf000fe94, "SH_WIN32_ExitProcess"); + add_ce_kernel_addr(0xf000fe90, "SH_WIN32_CloseAllHandles"); + add_ce_kernel_addr(0xf000fe8c, "SH_WIN32_SetHandleOwner"); + add_ce_kernel_addr(0xf000fe88, "SH_WIN32_LoadDriver"); + add_ce_kernel_addr(0xf000fe84, "SH_WIN32_CreateFileMappingW"); + add_ce_kernel_addr(0xf000fe80, "SH_WIN32_UnmapViewOfFile"); + add_ce_kernel_addr(0xf000fe7c, "SH_WIN32_FlushViewOfFile"); + add_ce_kernel_addr(0xf000fe78, "SH_WIN32_CreateFileForMappingW"); + add_ce_kernel_addr(0xf000fe74, "SH_WIN32_KernelIoControl"); + add_ce_kernel_addr(0xf000fe70, "SH_WIN32_GetCallStackSnapshot"); + add_ce_kernel_addr(0xf000fe6c, "SH_WIN32_PPSHRestart"); + add_ce_kernel_addr(0xf000fe64, "SH_WIN32_UpdateNLSInfoEx"); + add_ce_kernel_addr(0xf000fe60, "SH_WIN32_ConnectDebugger"); + add_ce_kernel_addr(0xf000fe5c, "SH_WIN32_InterruptInitialize"); + add_ce_kernel_addr(0xf000fe58, "SH_WIN32_InterruptDone"); + add_ce_kernel_addr(0xf000fe54, "SH_WIN32_InterruptDisable"); + add_ce_kernel_addr(0xf000fe50, "SH_WIN32_SetKMode"); + add_ce_kernel_addr(0xf000fe4c, "SH_WIN32_SetPowerOffHandler"); + add_ce_kernel_addr(0xf000fe48, "SH_WIN32_SetGwesPowerHandler"); + add_ce_kernel_addr(0xf000fe44, "SH_WIN32_SetHardwareWatch"); + add_ce_kernel_addr(0xf000fe40, "SH_WIN32_QueryAPISetID"); + add_ce_kernel_addr(0xf000fe3c, "SH_WIN32_PerformCallBack"); + add_ce_kernel_addr(0xf000fe38, "SH_WIN32_RaiseException"); + add_ce_kernel_addr(0xf000fe34, "SH_WIN32_GetCallerProcessIndex"); + add_ce_kernel_addr(0xf000fe30, "SH_WIN32_WaitForDebugEvent"); + add_ce_kernel_addr(0xf000fe2c, "SH_WIN32_ContinueDebugEvent"); + add_ce_kernel_addr(0xf000fe28, "SH_WIN32_DebugNotify"); + add_ce_kernel_addr(0xf000fe24, "SH_WIN32_OpenProcess"); + add_ce_kernel_addr(0xf000fe20, "SH_WIN32_THCreateSnapshot"); + add_ce_kernel_addr(0xf000fe1c, "SH_WIN32_THGrow"); + add_ce_kernel_addr(0xf000fe18, "SH_WIN32_NotifyForceCleanboot"); + add_ce_kernel_addr(0xf000fe14, "SH_WIN32_DumpKCallProfile"); + add_ce_kernel_addr(0xf000fe10, "SH_WIN32_GetProcessVersion"); + add_ce_kernel_addr(0xf000fe0c, "SH_WIN32_GetModuleFileNameW"); + add_ce_kernel_addr(0xf000fe08, "SH_WIN32_QueryPerformanceCounter"); + add_ce_kernel_addr(0xf000fe04, "SH_WIN32_QueryPerformanceFrequency"); + add_ce_kernel_addr(0xf000fe00, "SH_WIN32_KernExtractIcons"); + add_ce_kernel_addr(0xf000fdfc, "SH_WIN32_ForcePageout"); + add_ce_kernel_addr(0xf000fdf8, "SH_WIN32_GetThreadTimes"); + add_ce_kernel_addr(0xf000fdf4, "SH_WIN32_GetModuleHandleW"); + add_ce_kernel_addr(0xf000fdf0, "SH_WIN32_SetWDevicePowerHandler"); + add_ce_kernel_addr(0xf000fdec, "SH_WIN32_SetStdioPathW"); + add_ce_kernel_addr(0xf000fde8, "SH_WIN32_GetStdioPathW"); + add_ce_kernel_addr(0xf000fde4, "SH_WIN32_ReadRegistryFromOEM"); + add_ce_kernel_addr(0xf000fde0, "SH_WIN32_WriteRegistryToOEM"); + add_ce_kernel_addr(0xf000fddc, "SH_WIN32_WriteDebugLED"); + add_ce_kernel_addr(0xf000fdd8, "SH_WIN32_LockPages"); + add_ce_kernel_addr(0xf000fdd4, "SH_WIN32_UnlockPages"); + add_ce_kernel_addr(0xf000fdd0, "SH_WIN32_VirtualSetAttributes"); + add_ce_kernel_addr(0xf000fdcc, "SH_WIN32_SetRAMMode"); + add_ce_kernel_addr(0xf000fdc8, "SH_WIN32_SetStoreQueueBase"); + add_ce_kernel_addr(0xf000fdc4, "SH_WIN32_FlushViewOfFileMaybe"); + add_ce_kernel_addr(0xf000fdc0, "SH_WIN32_GetProcAddressA"); + add_ce_kernel_addr(0xf000fdbc, "SH_WIN32_GetCommandLineW"); + add_ce_kernel_addr(0xf000fdb8, "SH_WIN32_DisableThreadLibraryCalls"); + add_ce_kernel_addr(0xf000fdb4, "SH_WIN32_CreateSemaphoreW"); + add_ce_kernel_addr(0xf000fdb0, "SH_WIN32_LoadLibraryExW"); + add_ce_kernel_addr(0xf000fdac, "SH_WIN32_PerformCallForward"); + add_ce_kernel_addr(0xf000fda8, "SH_WIN32_CeMapArgumentArray"); + add_ce_kernel_addr(0xf000fda4, "SH_WIN32_KillThreadIfNeeded"); + add_ce_kernel_addr(0xf000fda0, "SH_WIN32_GetProcessIndexFromID"); + add_ce_kernel_addr(0xf000fd9c, "SH_WIN32_RegisterGwesHandler"); + add_ce_kernel_addr(0xf000fd98, "SH_WIN32_GetProfileBaseAddress"); + add_ce_kernel_addr(0xf000fd94, "SH_WIN32_SetProfilePortAddress"); + add_ce_kernel_addr(0xf000fd90, "SH_WIN32_CeLogData"); + add_ce_kernel_addr(0xf000fd8c, "SH_WIN32_CeLogSetZones"); + add_ce_kernel_addr(0xf000fd88, "SH_WIN32_CeModuleJit"); + add_ce_kernel_addr(0xf000fd84, "SH_WIN32_CeSetExtendedPdata"); + add_ce_kernel_addr(0xf000fd80, "SH_WIN32_VerQueryValueW"); + add_ce_kernel_addr(0xf000fd7c, "SH_WIN32_GetFileVersionInfoSizeW"); + add_ce_kernel_addr(0xf000fd78, "SH_WIN32_GetFileVersionInfoW"); + add_ce_kernel_addr(0xf000fd74, "SH_WIN32_CreateLocaleView"); + add_ce_kernel_addr(0xf000fd70, "SH_WIN32_CeLogReSync"); + add_ce_kernel_addr(0xf000fd6c, "SH_WIN32_LoadIntChainHandler"); + add_ce_kernel_addr(0xf000fd68, "SH_WIN32_FreeIntChainHandler"); + add_ce_kernel_addr(0xf000fd64, "SH_WIN32_LoadKernelLibrary"); + add_ce_kernel_addr(0xf000fd60, "SH_WIN32_AllocPhysMem"); + add_ce_kernel_addr(0xf000fd5c, "SH_WIN32_FreePhysMem"); + add_ce_kernel_addr(0xf000fd58, "SH_WIN32_KernelLibIoControl"); + add_ce_kernel_addr(0xf000fd54, "SH_WIN32_OpenEventW"); + add_ce_kernel_addr(0xf000fd50, "SH_WIN32_SleepTillTick"); + add_ce_kernel_addr(0xf000fd4c, "SH_WIN32_DuplicateHandle"); + add_ce_kernel_addr(0xf000fd48, "SH_WIN32_CreateStaticMapping"); + add_ce_kernel_addr(0xf000fd44, "SH_WIN32_MapCallerPtr"); + add_ce_kernel_addr(0xf000fd40, "SH_WIN32_MapPtrToProcWithSize"); + add_ce_kernel_addr(0xf000fd3c, "SH_WIN32_LoadStringW"); + add_ce_kernel_addr(0xf000fd38, "SH_WIN32_QueryInstructionSet"); + add_ce_kernel_addr(0xf000fd34, "SH_WIN32_CeLogGetZones"); + add_ce_kernel_addr(0xf000fd30, "SH_WIN32_GetProcessIDFromIndex"); + add_ce_kernel_addr(0xf000fd2c, "SH_WIN32_IsProcessorFeaturePresent"); + add_ce_kernel_addr(0xf000fd28, "SH_WIN32_DecompressBinaryBlock"); + add_ce_kernel_addr(0xf000fd24, "SH_WIN32_PageOutModule"); + add_ce_kernel_addr(0xf000fd20, "SH_WIN32_InterruptMask"); + add_ce_kernel_addr(0xf000fd1c, "SH_WIN32_GetProcModList"); + add_ce_kernel_addr(0xf000fd18, "SH_WIN32_FreeModFromCurrProc"); + add_ce_kernel_addr(0xf000fd14, "SH_WIN32_CeVirtualSharedAlloc"); + add_ce_kernel_addr(0xf000fd10, "SH_WIN32_NKDeleteStaticMapping"); + add_ce_kernel_addr(0xf000fd0c, "SH_WIN32_CreateToken"); + add_ce_kernel_addr(0xf000fd08, "SH_WIN32_RevertToSelf"); + add_ce_kernel_addr(0xf000fd04, "SH_WIN32_CeImpersonateCurrProc"); + add_ce_kernel_addr(0xf000fd00, "SH_WIN32_CeDuplicateToken"); + add_ce_kernel_addr(0xf000fcfc, "SH_WIN32_ConnectHdstub"); + add_ce_kernel_addr(0xf000fcf8, "SH_WIN32_ConnectOsAxsT0"); + add_ce_kernel_addr(0xf000fcf4, "SH_WIN32_IsNamedEventSignaled"); + add_ce_kernel_addr(0xf000fcf0, "SH_WIN32_ConnectOsAxsT1"); + add_ce_kernel_addr(0xf000fcec, "SH_WIN32_DebugSetProcessKillOnExit"); + add_ce_kernel_addr(0xf000fce8, "SH_WIN32_CeGetProcessTrust"); + add_ce_kernel_addr(0xf000fce4, "SH_WIN32_CeOpenFileHandle"); + + add_ce_kernel_addr(0xf000fbfc, "SH_CURTHREAD_ThreadCloseHandle"); + add_ce_kernel_addr(0xf000fbf8, "SH_CURTHREAD_SuspendThread"); + add_ce_kernel_addr(0xf000fbf4, "SH_CURTHREAD_ResumeThread"); + add_ce_kernel_addr(0xf000fbf0, "SH_CURTHREAD_SetThreadPriority"); + add_ce_kernel_addr(0xf000fbec, "SH_CURTHREAD_GetThreadPriority"); + add_ce_kernel_addr(0xf000fbe8, "SH_CURTHREAD_GetExitCodeThread"); + add_ce_kernel_addr(0xf000fbe4, "SH_CURTHREAD_GetThreadContext"); + add_ce_kernel_addr(0xf000fbe0, "SH_CURTHREAD_SetThreadContext"); + add_ce_kernel_addr(0xf000fbdc, "SH_CURTHREAD_TerminateThread"); + add_ce_kernel_addr(0xf000fbd8, "SH_CURTHREAD_CeGetThreadPriority"); + add_ce_kernel_addr(0xf000fbd4, "SH_CURTHREAD_CeSetThreadPriority"); + add_ce_kernel_addr(0xf000fbd0, "SH_CURTHREAD_CeGetThreadQuantum"); + add_ce_kernel_addr(0xf000fbcc, "SH_CURTHREAD_CeSetThreadQuantum"); + add_ce_kernel_addr(0xf000f800, "SH_CURPROC_ProcCloseHandle"); + add_ce_kernel_addr(0xf000f7f8, "SH_CURPROC_TerminateProcess"); + add_ce_kernel_addr(0xf000f7f4, "SH_CURPROC_GetExitCodeProcess"); + add_ce_kernel_addr(0xf000f7ec, "SH_CURPROC_FlushInstructionCache"); + add_ce_kernel_addr(0xf000f7e8, "SH_CURPROC_ReadProcessMemory"); + add_ce_kernel_addr(0xf000f7e4, "SH_CURPROC_WriteProcessMemory"); + add_ce_kernel_addr(0xf000f7e0, "SH_CURPROC_DebugActiveProcess"); + add_ce_kernel_addr(0xf000f7dc, "SH_CURPROC_GetModuleInformation"); + add_ce_kernel_addr(0xf000f7d8, "SH_CURPROC_CeSetProcessVersion"); + add_ce_kernel_addr(0xf000f7d4, "SH_CURPROC_DebugActiveProcessStop"); + add_ce_kernel_addr(0xf000f7d0, "SH_CURPROC_CeGetModuleInfo"); + add_ce_kernel_addr(0xf000f7cc, "SH_CURPROC_CheckRemoteDebuggerPresent"); + add_ce_kernel_addr(0xf000f000, "HT_EVENT_EventCloseHandle"); + add_ce_kernel_addr(0xf000eff8, "HT_EVENT_EventModify"); + add_ce_kernel_addr(0xf000eff4, "HT_EVENT_AddEventAccess"); + add_ce_kernel_addr(0xf000eff0, "HT_EVENT_EventGetData"); + add_ce_kernel_addr(0xf000efec, "HT_EVENT_EventSetData"); + add_ce_kernel_addr(0xf000ec00, "HT_MUTEX_MutexCloseHandle"); + add_ce_kernel_addr(0xf000ebf8, "HT_MUTEX_ReleaseMutex"); + add_ce_kernel_addr(0xf000e800, "HT_APISET_CloseAPISet"); + add_ce_kernel_addr(0xf000e7f8, "HT_APISET_RegisterAPISet"); + add_ce_kernel_addr(0xf000e7f4, "HT_APISET_CreateAPIHandle"); + add_ce_kernel_addr(0xf000e7f0, "HT_APISET_VerifyAPIHandle"); + add_ce_kernel_addr(0xf000e3fc, "HT_FILE_PSLGetStoreInfo"); + add_ce_kernel_addr(0xf000e3f8, "HT_FILE_PSLDismountStore"); + add_ce_kernel_addr(0xf000e3f8, "HT_FILE_ReadFile"); + add_ce_kernel_addr(0xf000e3f4, "HT_FILE_PSLFormatStore"); + add_ce_kernel_addr(0xf000e3f4, "HT_FILE_WriteFile"); + add_ce_kernel_addr(0xf000e3f0, "HT_FILE_GetFileSize"); + add_ce_kernel_addr(0xf000e3f0, "HT_FILE_PSLCreatePart"); + add_ce_kernel_addr(0xf000e3ec, "HT_FILE_PSLDeletePartition"); + add_ce_kernel_addr(0xf000e3ec, "HT_FILE_SetFilePointer"); + add_ce_kernel_addr(0xf000e3e8, "HT_FILE_GetFileInformationByHandle"); + add_ce_kernel_addr(0xf000e3e8, "HT_FILE_PSLOpenPartition"); + add_ce_kernel_addr(0xf000e3e4, "HT_FILE_FlushFileBuffers"); + add_ce_kernel_addr(0xf000e3e4, "HT_FILE_PSLMountPartition"); + add_ce_kernel_addr(0xf000e3e0, "HT_FILE_GetFileTime"); + add_ce_kernel_addr(0xf000e3e0, "HT_FILE_PSLDismountPartition"); + add_ce_kernel_addr(0xf000e3dc, "HT_FILE_PSLRenamePartition"); + add_ce_kernel_addr(0xf000e3dc, "HT_FILE_SetFileTime"); + add_ce_kernel_addr(0xf000e3d8, "HT_FILE_PSLSetPartitionAttributes"); + add_ce_kernel_addr(0xf000e3d8, "HT_FILE_SetEndOfFile"); + add_ce_kernel_addr(0xf000e3d4, "HT_FILE_DeviceIoControl"); + add_ce_kernel_addr(0xf000e3d0, "HT_FILE_PSLGetPartitionInfo"); + add_ce_kernel_addr(0xf000e3d0, "HT_FILE_ReadFileWithSeek"); + add_ce_kernel_addr(0xf000e3cc, "HT_FILE_PSLFormatPart"); + add_ce_kernel_addr(0xf000e3cc, "HT_FILE_WriteFileWithSeek"); + add_ce_kernel_addr(0xf000e3c8, "HT_FILE_PSLFindFirstPartition"); + add_ce_kernel_addr(0xf000e000, "HT_FIND_FindClose"); + //add_ce_kernel_addr(0xf000e000, "HT_FIND_PSLFindClosePartition"); + //add_ce_kernel_addr(0xf000e000, "HT_FIND_PSLFindCloseStore"); + add_ce_kernel_addr(0xf000dff8, "HT_FIND_FindNextFileW"); + //add_ce_kernel_addr(0xf000dff8, "HT_FIND_PSLFindNextPartition"); + //add_ce_kernel_addr(0xf000dff8, "HT_FIND_PSLFindNextStore"); + add_ce_kernel_addr(0xf000dbf8, "HT_DBFILE_CeSeekDatabaseEx"); + add_ce_kernel_addr(0xf000dbf4, "HT_DBFILE_CeDeleteRecord"); + add_ce_kernel_addr(0xf000dbf0, "HT_DBFILE_CeReadRecordPropsEx"); + add_ce_kernel_addr(0xf000dbec, "HT_DBFILE_CeWriteRecordProps"); + add_ce_kernel_addr(0xf000dbe8, "HT_DBFILE_CeGetDBInformationByHandle"); + add_ce_kernel_addr(0xf000d7f8, "HT_DBFIND_CeFindNextDatabaseEx"); + add_ce_kernel_addr(0xf000d400, "HT_SOCKET_AFDCloseSocket"); + add_ce_kernel_addr(0xf000d3f8, "HT_SOCKET_AFDAccept"); + add_ce_kernel_addr(0xf000d3f4, "HT_SOCKET_AFDBind"); + add_ce_kernel_addr(0xf000d3f0, "HT_SOCKET_AFDConnect"); + add_ce_kernel_addr(0xf000d3ec, "HT_SOCKET_AFDIoctl"); + add_ce_kernel_addr(0xf000d3e8, "HT_SOCKET_AFDListen"); + add_ce_kernel_addr(0xf000d3e4, "HT_SOCKET_AFDRecv"); + add_ce_kernel_addr(0xf000d3e0, "HT_SOCKET_AFDSend"); + add_ce_kernel_addr(0xf000d3dc, "HT_SOCKET_AFDShutdown"); + add_ce_kernel_addr(0xf000d3d8, "HT_SOCKET_AFDGetsockname"); + add_ce_kernel_addr(0xf000d3d4, "HT_SOCKET_AFDGetpeername"); + add_ce_kernel_addr(0xf000d3d0, "HT_SOCKET_AFDGetSockOpt"); + add_ce_kernel_addr(0xf000d3cc, "HT_SOCKET_AFDSetSockOpt"); + add_ce_kernel_addr(0xf000d3c8, "HT_SOCKET_AFDWakeup"); + add_ce_kernel_addr(0xf000d3c4, "HT_SOCKET_AFDGetOverlappedResult"); + add_ce_kernel_addr(0xf000d3c0, "HT_SOCKET_AFDEventSelect"); + add_ce_kernel_addr(0xf000d3bc, "HT_SOCKET_AFDEnumNetworkEvents"); + add_ce_kernel_addr(0xf000cc00, "HT_SEMAPHORE_SemaphoreCloseHandle"); + add_ce_kernel_addr(0xf000cbf8, "HT_SEMAPHORE_ReleaseSemaphore"); + add_ce_kernel_addr(0xf000c800, "HT_FSMAP_MapCloseHandle"); + add_ce_kernel_addr(0xf000c7f8, "HT_FSMAP_MapViewOfFile"); + add_ce_kernel_addr(0xf000c400, "HT_WNETENUM_WNetCloseEnum"); + add_ce_kernel_addr(0xf000c3f8, "HT_WNETENUM_WNetEnumResourceW"); + add_ce_kernel_addr(0xf000bff8, "SH_GDI_AddFontResourceW"); + add_ce_kernel_addr(0xf000bff4, "SH_GDI_BitBlt"); + add_ce_kernel_addr(0xf000bff0, "SH_GDI_CombineRgn"); + add_ce_kernel_addr(0xf000bfec, "SH_GDI_CreateCompatibleDC"); + add_ce_kernel_addr(0xf000bfe8, "SH_GDI_CreateDIBPatternBrushPt"); + add_ce_kernel_addr(0xF000BFE4, "SH_GDI_CreateDIBSection"); + add_ce_kernel_addr(0xf000bfe0, "SH_GDI_CreateFontIndirectW"); + add_ce_kernel_addr(0xf000bfdc, "SH_GDI_CreateRectRgnIndirect"); + add_ce_kernel_addr(0xf000bfd8, "SH_GDI_CreatePenIndirect"); + add_ce_kernel_addr(0xf000bfd4, "SH_GDI_CreateSolidBrush"); + add_ce_kernel_addr(0xf000bfd0, "SH_GDI_DeleteDC"); + add_ce_kernel_addr(0xf000bfcc, "SH_GDI_DeleteObject"); + add_ce_kernel_addr(0xf000bfc8, "SH_GDI_DrawEdge"); + add_ce_kernel_addr(0xf000bfc4, "SH_GDI_DrawFocusRect"); + add_ce_kernel_addr(0xf000bfc0, "SH_GDI_DrawTextW"); + add_ce_kernel_addr(0xf000bfbc, "SH_GDI_Ellipse"); + add_ce_kernel_addr(0xf000bfb8, "SH_GDI_EnumFontFamiliesW"); + add_ce_kernel_addr(0xF000BFB4, "SH_GDI_EnumFontsW"); + add_ce_kernel_addr(0xf000bfb0, "SH_GDI_ExcludeClipRect"); + add_ce_kernel_addr(0xf000bfac, "SH_GDI_ExtTextOutW"); + add_ce_kernel_addr(0xf000bfa8, "SH_GDI_FillRect"); + add_ce_kernel_addr(0xf000bfa0, "SH_GDI_GetBkColor"); + add_ce_kernel_addr(0xf000bf9c, "SH_GDI_GetBkMode"); + add_ce_kernel_addr(0xf000bf98, "SH_GDI_GetClipRgn"); + add_ce_kernel_addr(0xf000bf94, "SH_GDI_GetCurrentObject"); + add_ce_kernel_addr(0xf000bf90, "SH_GDI_GetDeviceCaps"); + add_ce_kernel_addr(0xf000bf8c, "SH_GDI_GetNearestColor"); + add_ce_kernel_addr(0xf000bf88, "SH_GDI_GetObjectW"); + add_ce_kernel_addr(0xf000bf84, "SH_GDI_GetObjectType"); + add_ce_kernel_addr(0xf000bf80, "SH_GDI_GetPixel"); + add_ce_kernel_addr(0xf000bf7c, "SH_GDI_GetRegionData"); + add_ce_kernel_addr(0xf000bf78, "SH_GDI_GetRgnBox"); + add_ce_kernel_addr(0xf000bf74, "SH_GDI_GetStockObject"); + add_ce_kernel_addr(0xf000bf70, "SH_GDI_PatBlt"); + add_ce_kernel_addr(0xf000bf6c, "SH_GDI_GetTextColor"); + add_ce_kernel_addr(0xf000bf68, "SH_GDI_GetTextExtentExPointW"); + add_ce_kernel_addr(0xf000bf64, "SH_GDI_GetTextFaceW"); + add_ce_kernel_addr(0xf000bf60, "SH_GDI_GetTextMetricsW"); + add_ce_kernel_addr(0xf000bf5c, "SH_GDI_MaskBlt"); + add_ce_kernel_addr(0xf000bf58, "SH_GDI_OffsetRgn"); + add_ce_kernel_addr(0xf000bf54, "SH_GDI_Polygon"); + add_ce_kernel_addr(0xf000bf50, "SH_GDI_Polyline"); + add_ce_kernel_addr(0xf000bf4c, "SH_GDI_PtInRegion"); + add_ce_kernel_addr(0xf000bf48, "SH_GDI_Rectangle"); + add_ce_kernel_addr(0xf000bf44, "SH_GDI_RectInRegion"); + add_ce_kernel_addr(0xf000bf40, "SH_GDI_RemoveFontResourceW"); + add_ce_kernel_addr(0xf000bf3c, "SH_GDI_RestoreDC"); + add_ce_kernel_addr(0xf000bf38, "SH_GDI_RoundRect"); + add_ce_kernel_addr(0xf000bf34, "SH_GDI_SaveDC"); + add_ce_kernel_addr(0xf000bf30, "SH_GDI_SelectClipRgn"); + add_ce_kernel_addr(0xf000bf2c, "SH_GDI_SelectObject"); + add_ce_kernel_addr(0xf000bf28, "SH_GDI_SetBkColor"); + add_ce_kernel_addr(0xf000bf24, "SH_GDI_SetBkMode"); + add_ce_kernel_addr(0xf000bf20, "SH_GDI_SetBrushOrgEx"); + add_ce_kernel_addr(0xf000bf1c, "SH_GDI_SetPixel"); + add_ce_kernel_addr(0xf000bf18, "SH_GDI_SetTextColor"); + add_ce_kernel_addr(0xf000bf14, "SH_GDI_StretchBlt"); + add_ce_kernel_addr(0xf000bf10, "SH_GDI_CreateBitmap"); + add_ce_kernel_addr(0xf000bf0c, "SH_GDI_CreateCompatibleBitmap"); + add_ce_kernel_addr(0xf000bf08, "SH_GDI_GetSysColorBrush"); + add_ce_kernel_addr(0xf000bf04, "SH_GDI_IntersectClipRect"); + add_ce_kernel_addr(0xf000bf00, "SH_GDI_GetClipBox"); + add_ce_kernel_addr(0xf000befc, "SH_GDI_CeRemoveFontResource"); + add_ce_kernel_addr(0xf000bef8, "SH_GDI_EnableEUDC"); + add_ce_kernel_addr(0xf000bef4, "SH_GDI_CloseEnhMetaFile"); + add_ce_kernel_addr(0xf000bef0, "SH_GDI_CreateEnhMetaFileW"); + add_ce_kernel_addr(0xf000beec, "SH_GDI_DeleteEnhMetaFile"); + add_ce_kernel_addr(0xf000bee8, "SH_GDI_PlayEnhMetaFile"); + add_ce_kernel_addr(0xf000bee4, "SH_GDI_CreatePalette"); + add_ce_kernel_addr(0xf000bee0, "SH_GDI_SelectPalette"); + add_ce_kernel_addr(0xf000bedc, "SH_GDI_RealizePalette"); + add_ce_kernel_addr(0xf000bed8, "SH_GDI_GetPaletteEntries"); + add_ce_kernel_addr(0xf000bed4, "SH_GDI_SetPaletteEntries"); + add_ce_kernel_addr(0xf000bed0, "SH_GDI_GetSystemPaletteEntries"); + add_ce_kernel_addr(0xf000becc, "SH_GDI_GetNearestPaletteIndex"); + add_ce_kernel_addr(0xf000bec8, "SH_GDI_CreatePen"); + add_ce_kernel_addr(0xf000bec4, "SH_GDI_StartDocW"); + add_ce_kernel_addr(0xf000bec0, "SH_GDI_EndDoc"); + add_ce_kernel_addr(0xf000bebc, "SH_GDI_StartPage"); + add_ce_kernel_addr(0xf000beb8, "SH_GDI_EndPage"); + add_ce_kernel_addr(0xf000beb4, "SH_GDI_AbortDoc"); + add_ce_kernel_addr(0xf000beb0, "SH_GDI_SetAbortProc"); + add_ce_kernel_addr(0xf000beac, "SH_GDI_CreateDCW"); + add_ce_kernel_addr(0xf000bea8, "SH_GDI_CreateRectRgn"); + add_ce_kernel_addr(0xf000bea4, "SH_GDI_FillRgn"); + add_ce_kernel_addr(0xf000bea0, "SH_GDI_SetROP2"); + add_ce_kernel_addr(0xf000be9c, "SH_GDI_SetRectRgn"); + add_ce_kernel_addr(0xf000be98, "SH_GDI_RectVisible"); + add_ce_kernel_addr(0xf000be94, "SH_GDI_CreatePatternBrush"); + add_ce_kernel_addr(0xf000be90, "SH_GDI_CreateBitmapFromPointer"); + add_ce_kernel_addr(0xf000be8c, "SH_GDI_SetViewportOrgEx"); + add_ce_kernel_addr(0xf000be88, "SH_GDI_TransparentImage"); + add_ce_kernel_addr(0xf000be84, "SH_GDI_SetObjectOwner"); + add_ce_kernel_addr(0xf000be80, "SH_GDI_TranslateCharsetInfo"); + add_ce_kernel_addr(0xf000be7c, "SH_GDI_ExtEscape"); + add_ce_kernel_addr(0xf000be78, "SH_GDI_SetWindowsHookExW_Trap"); + add_ce_kernel_addr(0xf000be74, "SH_GDI_UnhookWindowsHookEx_Trap"); + add_ce_kernel_addr(0xf000be70, "SH_GDI_GetForegroundInfo"); + add_ce_kernel_addr(0xf000be6c, "SH_GDI_CeGetUserNotificationPreferences"); + add_ce_kernel_addr(0xf000be68, "SH_GDI_CeSetUserNotificationEx"); + add_ce_kernel_addr(0xf000be64, "SH_GDI_CeClearUserNotification"); + add_ce_kernel_addr(0xf000be60, "SH_GDI_CeRunAppAtEvent"); + add_ce_kernel_addr(0xf000be5c, "SH_GDI_CeHandleAppNotifications"); + add_ce_kernel_addr(0xf000be58, "SH_GDI_CeGetUserNotificationHandles"); + add_ce_kernel_addr(0xf000be54, "SH_GDI_CeGetUserNotification"); + add_ce_kernel_addr(0xf000be50, "SH_GDI_CeEventHasOccurred"); + add_ce_kernel_addr(0xf000be4c, "SH_GDI_SetWindowRgn_Trap"); + add_ce_kernel_addr(0xf000be48, "SH_GDI_GetPrivateCallbacks_Trap"); + add_ce_kernel_addr(0xf000be44, "SH_GDI_GetWindowRgn_Trap"); + add_ce_kernel_addr(0xf000be40, "SH_GDI_CeRunAppAtTime"); + add_ce_kernel_addr(0xf000be3c, "SH_GDI_GetDesktopWindow_Trap"); + add_ce_kernel_addr(0xf000be38, "SH_GDI_InSendMessage_Trap"); + add_ce_kernel_addr(0xf000be34, "SH_GDI_GetQueueStatus_Trap"); + add_ce_kernel_addr(0xf000be30, "SH_GDI_AllKeys_Trap"); + add_ce_kernel_addr(0xf000be2c, "SH_GDI_LoadAnimatedCursor_Trap"); + add_ce_kernel_addr(0xf000be28, "SH_GDI_SendMessageTimeout"); + add_ce_kernel_addr(0xf000be24, "SH_GDI_SetProp_Trap"); + add_ce_kernel_addr(0xf000be20, "SH_GDI_GetProp_Trap"); + add_ce_kernel_addr(0xf000be1c, "SH_GDI_RemoveProp_Trap"); + add_ce_kernel_addr(0xf000be18, "SH_GDI_EnumPropsEx_Trap"); + add_ce_kernel_addr(0xf000be14, "SH_GDI_GetMessageQueueReadyTimeStamp"); + add_ce_kernel_addr(0xf000be10, "SH_GDI_RegisterTaskBarEx"); + add_ce_kernel_addr(0xf000be0c, "SH_GDI_RegisterDesktop"); + add_ce_kernel_addr(0xf000be08, "SH_GDI_GlobalAddAtomW"); + add_ce_kernel_addr(0xf000be04, "SH_GDI_GlobalDeleteAtom"); + add_ce_kernel_addr(0xf000be00, "SH_GDI_GlobalFindAtomW"); + add_ce_kernel_addr(0xf000bdfc, "SH_GDI_MonitorFromPoint_Trap"); + add_ce_kernel_addr(0xf000bdf8, "SH_GDI_MonitorFromRect_Trap"); + add_ce_kernel_addr(0xf000bdf4, "SH_GDI_MonitorFromWindow_Trap"); + add_ce_kernel_addr(0xf000bdf0, "SH_GDI_GetMonitorInfo_Trap"); + add_ce_kernel_addr(0xf000bdec, "SH_GDI_EnumDisplayMonitors_Trap"); + add_ce_kernel_addr(0xf000bde8, "SH_GDI_AccessibilitySoundSentryEvent_Trap"); + add_ce_kernel_addr(0xf000bde4, "SH_GDI_ChangeDisplaySettingsEx_Trap"); + add_ce_kernel_addr(0xf000bde0, "SH_GDI_InvalidateRgn_Trap"); + add_ce_kernel_addr(0xf000bddc, "SH_GDI_ValidateRgn_Trap"); + add_ce_kernel_addr(0xf000bdd8, "SH_GDI_ExtCreateRegion"); + add_ce_kernel_addr(0xf000bdd4, "SH_GDI_MoveToEx"); + add_ce_kernel_addr(0xf000bdd0, "SH_GDI_LineTo"); + add_ce_kernel_addr(0xf000bdcc, "SH_GDI_GetCurrentPositionEx"); + add_ce_kernel_addr(0xf000bdc8, "SH_GDI_SetTextAlign"); + add_ce_kernel_addr(0xf000bdc4, "SH_GDI_GetTextAlign"); + add_ce_kernel_addr(0xf000bdc0, "SH_GDI_GetCharWidth32"); + add_ce_kernel_addr(0xf000bdbc, "SH_GDI_GetDIBColorTable"); + add_ce_kernel_addr(0xf000bdb8, "SH_GDI_SetDIBColorTable"); + add_ce_kernel_addr(0xf000bdb4, "SH_GDI_StretchDIBits"); + add_ce_kernel_addr(0xf000bdb0, "SH_GDI_RedrawWindow_Trap"); + add_ce_kernel_addr(0xf000bdac, "SH_GDI_SetBitmapBits"); + add_ce_kernel_addr(0xf000bda8, "SH_GDI_SetDIBitsToDevice"); + add_ce_kernel_addr(0xf000bda4, "SH_GDI_GradientFill"); + add_ce_kernel_addr(0xf000bda0, "SH_GDI_InvertRect"); + add_ce_kernel_addr(0xf000bd9c, "SH_GDI_EnumDisplaySettings_Trap"); + add_ce_kernel_addr(0xf000bd98, "SH_GDI_EnumDisplayDevices_Trap"); + add_ce_kernel_addr(0xf000bd94, "SH_GDI_GetCharABCWidths"); + add_ce_kernel_addr(0xf000bd90, "SH_GDI_ShowStartupWindow_Trap"); + add_ce_kernel_addr(0xF000BD8C, "SH_GDI_GetGweApiSetTables"); + add_ce_kernel_addr(0xF000BD88, "SH_GDI_GetStretchBltMode"); + add_ce_kernel_addr(0xF000BD84, "SH_GDI_SetStretchBltMode"); + add_ce_kernel_addr(0xF000BD80, "SH_GDI_AlphaBlend"); + add_ce_kernel_addr(0xF000BD7C, "SH_GDI_GetIconInfo"); + add_ce_kernel_addr(0xF000BD78, "SH_GDI_EnumFontFamiliesExW"); + add_ce_kernel_addr(0xF000BD74, "SH_GDI_GetFontData"); + add_ce_kernel_addr(0xF000BD70, "SH_GDI_GetCharABCWidthsI"); + add_ce_kernel_addr(0xF000BD6C, "SH_GDI_GetOutlineTextMetricsW"); + add_ce_kernel_addr(0xF000BD68, "SH_GDI_SetLayout"); + add_ce_kernel_addr(0xF000BD64, "SH_GDI_GetLayout"); + add_ce_kernel_addr(0xF000BD60, "SH_GDI_SetTextCharacterExtra"); + add_ce_kernel_addr(0xF000BD5C, "SH_GDI_GetTextCharacterExtra"); + add_ce_kernel_addr(0xF000BD58, "SH_GDI_ImmGetKeyboardLayout"); + add_ce_kernel_addr(0xF000BD54, "SH_GDI_GetViewportOrgEx"); + add_ce_kernel_addr(0xF000BD50, "SH_GDI_GetViewportExtEx"); + add_ce_kernel_addr(0xF000BD4C, "SH_GDI_OffsetViewportOrgEx"); + add_ce_kernel_addr(0xF000BD48, "SH_GDI_GetROP2"); + add_ce_kernel_addr(0xF000BD44, "SH_GDI_SetWindowOrgEx"); + add_ce_kernel_addr(0xF000BD40, "SH_GDI_GetWindowOrgEx"); + add_ce_kernel_addr(0xF000BD3C, "SH_GDI_GetWindowExtEx"); + add_ce_kernel_addr(0xF000BD34, "SH_GDI_Gesture"); + add_ce_kernel_addr(0xF000BD30, "SH_GDI_GetWindowAutoGesture"); + add_ce_kernel_addr(0xF000BD2C, "SH_GDI_SetWindowAutoGesture"); + add_ce_kernel_addr(0xF000BD28, "SH_GDI_RegisterGesture"); + add_ce_kernel_addr(0xF000BD24, "SH_GDI_RegisterDefaultGestureHandler"); + add_ce_kernel_addr(0xF000BD20, "SH_GDI_SetLayeredWindowAttributes"); + add_ce_kernel_addr(0xF000BD1C, "SH_GDI_GetLayeredWindowAttributes"); + add_ce_kernel_addr(0xF000BD18, "SH_GDI_UpdateLayeredWindow"); + add_ce_kernel_addr(0xF000BD14, "SH_GDI_UpdateLayeredWindowIndirect"); + add_ce_kernel_addr(0xF000BD10, "SH_GDI_DrawThemePrimitive"); + add_ce_kernel_addr(0xF000BD0C, "SH_GDI_ThemePrimitiveExists"); + add_ce_kernel_addr(0xF000BD08, "SH_GDI_UpdateThemePrimitives"); + add_ce_kernel_addr(0xF000BD04, "SH_GDI_COREDLL_2872"); + + + add_ce_kernel_addr(0xf000bbf8, "SH_WMGR_RegisterClassWApiSetEntry_Trap"); + add_ce_kernel_addr(0xf000bbf4, "SH_WMGR_UnregisterClassW_Trap"); + add_ce_kernel_addr(0xf000bbf0, "SH_WMGR_CreateWindowExW_Trap"); + add_ce_kernel_addr(0xf000bbec, "SH_WMGR_PostMessageW"); + add_ce_kernel_addr(0xf000bbe8, "SH_WMGR_PostQuitMessage_Trap"); + add_ce_kernel_addr(0xf000bbe4, "SH_WMGR_SendMessageW"); + add_ce_kernel_addr(0xf000bbe0, "SH_WMGR_GetMessageW"); + add_ce_kernel_addr(0xf000bbdc, "SH_WMGR_TranslateMessage_Trap"); + add_ce_kernel_addr(0xf000bbd8, "SH_WMGR_DispatchMessageW"); + add_ce_kernel_addr(0xf000bbd4, "SH_WMGR_GetCapture_Trap"); + add_ce_kernel_addr(0xf000bbd0, "SH_WMGR_SetCapture_Trap"); + add_ce_kernel_addr(0xf000bbcc, "SH_WMGR_ReleaseCapture_Trap"); + add_ce_kernel_addr(0xf000bbc8, "SH_WMGR_SetWindowPos"); + add_ce_kernel_addr(0xf000bbc4, "SH_WMGR_GetWindowRect"); + add_ce_kernel_addr(0xf000bbc0, "SH_WMGR_GetClientRect"); + add_ce_kernel_addr(0xf000bbbc, "SH_WMGR_InvalidateRect"); + add_ce_kernel_addr(0xf000bbb8, "SH_WMGR_GetWindow"); + add_ce_kernel_addr(0xf000bbb4, "SH_WMGR_GetSystemMetrics"); + add_ce_kernel_addr(0xf000bbb0, "SH_WMGR_ImageList_GetDragImage"); + add_ce_kernel_addr(0xf000bbac, "SH_WMGR_ImageList_GetIconSize"); + add_ce_kernel_addr(0xf000bba8, "SH_WMGR_ImageList_SetIconSize"); + add_ce_kernel_addr(0xf000bba4, "SH_WMGR_ImageList_GetImageInfo"); + add_ce_kernel_addr(0xf000bba0, "SH_WMGR_ImageList_Merge"); + add_ce_kernel_addr(0xf000bb9c, "SH_WMGR_ShowCursor_Trap"); + add_ce_kernel_addr(0xf000bb98, "SH_WMGR_SetCursorPos_Trap"); + add_ce_kernel_addr(0xf000bb94, "SH_WMGR_ImageList_CopyDitherImage"); + add_ce_kernel_addr(0xf000bb90, "SH_WMGR_ImageList_DrawIndirect"); + add_ce_kernel_addr(0xf000bb8c, "SH_WMGR_ImageList_DragShowNolock"); + add_ce_kernel_addr(0xf000bb88, "SH_WMGR_WindowFromPoint_Trap"); + add_ce_kernel_addr(0xf000bb84, "SH_WMGR_ChildWindowFromPoint_Trap"); + add_ce_kernel_addr(0xf000bb80, "SH_WMGR_ClientToScreen"); + add_ce_kernel_addr(0xf000bb7c, "SH_WMGR_ScreenToClient_Trap"); + add_ce_kernel_addr(0xf000bb78, "SH_WMGR_SetWindowTextW_Trap"); + add_ce_kernel_addr(0xf000bb74, "SH_WMGR_GetWindowTextW_Trap"); + add_ce_kernel_addr(0xf000bb70, "SH_WMGR_SetWindowLongW"); + add_ce_kernel_addr(0xf000bb6c, "SH_WMGR_GetWindowLongW"); + add_ce_kernel_addr(0xf000bb68, "SH_WMGR_BeginPaint"); + add_ce_kernel_addr(0xf000bb64, "SH_WMGR_EndPaint"); + add_ce_kernel_addr(0xf000bb60, "SH_WMGR_GetDC"); + add_ce_kernel_addr(0xf000bb5c, "SH_WMGR_ReleaseDC"); + add_ce_kernel_addr(0xf000bb58, "SH_WMGR_DefWindowProcW"); + add_ce_kernel_addr(0xf000bb54, "SH_WMGR_GetClassLongW_Trap"); + add_ce_kernel_addr(0xf000bb50, "SH_WMGR_SetClassLongW_Trap"); + add_ce_kernel_addr(0xf000bb4c, "SH_WMGR_DestroyWindow_Trap"); + add_ce_kernel_addr(0xf000bb48, "SH_WMGR_ShowWindow_Trap"); + add_ce_kernel_addr(0xf000bb44, "SH_WMGR_UpdateWindow_Trap"); + add_ce_kernel_addr(0xf000bb40, "SH_WMGR_SetParent_Trap"); + add_ce_kernel_addr(0xf000bb3c, "SH_WMGR_GetParent"); + add_ce_kernel_addr(0xf000bb38, "SH_WMGR_MessageBoxW_Trap"); + add_ce_kernel_addr(0xf000bb34, "SH_WMGR_SetFocus_Trap"); + add_ce_kernel_addr(0xf000bb30, "SH_WMGR_GetFocus"); + add_ce_kernel_addr(0xf000bb2c, "SH_WMGR_GetActiveWindow_Trap"); + add_ce_kernel_addr(0xf000bb28, "SH_WMGR_GetWindowDC_Trap"); + add_ce_kernel_addr(0xf000bb24, "SH_WMGR_GetSysColor"); + add_ce_kernel_addr(0xf000bb20, "SH_WMGR_AdjustWindowRectEx_Trap"); + add_ce_kernel_addr(0xf000bb1c, "SH_WMGR_IsWindow"); + add_ce_kernel_addr(0xf000bb18, "SH_WMGR_CreatePopupMenu_Trap"); + add_ce_kernel_addr(0xf000bb14, "SH_WMGR_InsertMenuW_Trap"); + add_ce_kernel_addr(0xf000bb10, "SH_WMGR_AppendMenuW_Trap"); + add_ce_kernel_addr(0xf000bb0c, "SH_WMGR_RemoveMenu_Trap"); + add_ce_kernel_addr(0xf000bb08, "SH_WMGR_DestroyMenu_Trap"); + add_ce_kernel_addr(0xf000bb04, "SH_WMGR_TrackPopupMenuEx_Trap"); + add_ce_kernel_addr(0xf000bb00, "SH_WMGR_LoadMenuW_Trap"); + add_ce_kernel_addr(0xf000bafc, "SH_WMGR_EnableMenuItem_Trap"); + add_ce_kernel_addr(0xf000baf8, "SH_WMGR_MoveWindow_Trap"); + add_ce_kernel_addr(0xf000baf4, "SH_WMGR_GetUpdateRgn_Trap"); + add_ce_kernel_addr(0xf000baf0, "SH_WMGR_GetUpdateRect_Trap"); + add_ce_kernel_addr(0xf000baec, "SH_WMGR_BringWindowToTop_Trap"); + add_ce_kernel_addr(0xf000bae8, "SH_WMGR_GetWindowTextLengthW_Trap"); + add_ce_kernel_addr(0xf000bae4, "SH_WMGR_IsChild_Trap"); + add_ce_kernel_addr(0xf000bae0, "SH_WMGR_IsWindowVisible"); + add_ce_kernel_addr(0xf000badc, "SH_WMGR_ValidateRect_Trap"); + add_ce_kernel_addr(0xf000bad8, "SH_WMGR_LoadBitmapW_Trap"); + add_ce_kernel_addr(0xf000bad4, "SH_WMGR_CheckMenuItem_Trap"); + add_ce_kernel_addr(0xf000bad0, "SH_WMGR_CheckMenuRadioItem_Trap"); + add_ce_kernel_addr(0xf000bacc, "SH_WMGR_DeleteMenu"); + add_ce_kernel_addr(0xf000bac8, "SH_WMGR_LoadIconW_Trap"); + add_ce_kernel_addr(0xf000bac4, "SH_WMGR_DrawIconEx_Trap"); + add_ce_kernel_addr(0xf000bac0, "SH_WMGR_DestroyIcon_Trap"); + add_ce_kernel_addr(0xf000babc, "SH_WMGR_GetAsyncKeyState"); + add_ce_kernel_addr(0xf000bab8, "SH_WMGR_multitouch_event"); + add_ce_kernel_addr(0xf000bab4, "SH_WMGR_DialogBoxIndirectParamW"); + add_ce_kernel_addr(0xf000bab0, "SH_WMGR_EndDialog"); + add_ce_kernel_addr(0xf000baac, "SH_WMGR_GetDlgItem"); + add_ce_kernel_addr(0xf000baa8, "SH_WMGR_GetDlgCtrlID"); + add_ce_kernel_addr(0xf000baa4, "SH_WMGR_GetKeyState"); + add_ce_kernel_addr(0xf000baa0, "SH_WMGR_KeybdGetDeviceInfo"); + add_ce_kernel_addr(0xf000ba9c, "SH_WMGR_KeybdInitStates"); + add_ce_kernel_addr(0xf000ba98, "SH_WMGR_PostKeybdMessage"); + add_ce_kernel_addr(0xf000ba94, "SH_WMGR_KeybdVKeyToUnicode"); + add_ce_kernel_addr(0xf000ba90, "SH_WMGR_keybd_event"); + add_ce_kernel_addr(0xf000ba8c, "SH_WMGR_mouse_event"); + add_ce_kernel_addr(0xf000ba88, "SH_WMGR_SetScrollInfo"); + add_ce_kernel_addr(0xf000ba84, "SH_WMGR_SetScrollPos"); + add_ce_kernel_addr(0xf000ba80, "SH_WMGR_SetScrollRange"); + add_ce_kernel_addr(0xf000ba7c, "SH_WMGR_GetScrollInfo"); + add_ce_kernel_addr(0xf000ba78, "SH_WMGR_PeekMessageW"); + add_ce_kernel_addr(0xf000ba74, "SH_WMGR_MapVirtualKeyW"); + add_ce_kernel_addr(0xf000ba70, "SH_WMGR_GetMessageWNoWait"); + add_ce_kernel_addr(0xf000ba6c, "SH_WMGR_GetClassNameW"); + add_ce_kernel_addr(0xf000ba68, "SH_WMGR_MapWindowPoints"); + add_ce_kernel_addr(0xf000ba64, "SH_WMGR_LoadImageW"); + add_ce_kernel_addr(0xf000ba60, "SH_WMGR_GetForegroundWindow"); + add_ce_kernel_addr(0xf000ba5c, "SH_WMGR_SetForegroundWindow"); + add_ce_kernel_addr(0xf000ba58, "SH_WMGR_RegisterTaskBar"); + add_ce_kernel_addr(0xf000ba54, "SH_WMGR_SetActiveWindow"); + add_ce_kernel_addr(0xf000ba50, "SH_WMGR_CallWindowProcW_Trap"); + add_ce_kernel_addr(0xf000ba4c, "SH_WMGR_GetClassInfoW"); + add_ce_kernel_addr(0xf000ba48, "SH_WMGR_GetNextDlgTabItem"); + add_ce_kernel_addr(0xf000ba44, "SH_WMGR_CreateDialogIndirectParamW"); + add_ce_kernel_addr(0xf000ba40, "SH_WMGR_IsDialogMessageW"); + add_ce_kernel_addr(0xf000ba3c, "SH_WMGR_SetDlgItemInt"); + add_ce_kernel_addr(0xf000ba38, "SH_WMGR_GetDlgItemInt"); + add_ce_kernel_addr(0xf000ba34, "SH_WMGR_FindWindowW"); + add_ce_kernel_addr(0xf000ba30, "SH_WMGR_CreateCaret"); + add_ce_kernel_addr(0xf000ba2c, "SH_WMGR_DestroyCaret"); + add_ce_kernel_addr(0xf000ba28, "SH_WMGR_HideCaret"); + add_ce_kernel_addr(0xf000ba24, "SH_WMGR_ShowCaret"); + add_ce_kernel_addr(0xf000ba20, "SH_WMGR_SetCaretPos"); + add_ce_kernel_addr(0xf000ba1c, "SH_WMGR_GetCaretPos"); + add_ce_kernel_addr(0xf000ba18, "SH_WMGR_GetCursorPos_Trap"); + add_ce_kernel_addr(0xf000ba14, "SH_WMGR_ClipCursor"); + add_ce_kernel_addr(0xf000ba10, "SH_WMGR_GetClipCursor"); + add_ce_kernel_addr(0xf000ba0c, "SH_WMGR_GetCursor_Trap"); + add_ce_kernel_addr(0xf000ba08, "SH_WMGR_ExtractIconExW"); + add_ce_kernel_addr(0xf000ba04, "SH_WMGR_SetTimer_Trap"); + add_ce_kernel_addr(0xf000ba00, "SH_WMGR_KillTimer_Trap"); + add_ce_kernel_addr(0xf000b9fc, "SH_WMGR_GetNextDlgGroupItem"); + add_ce_kernel_addr(0xf000b9f8, "SH_WMGR_CheckRadioButton"); + add_ce_kernel_addr(0xf000b9f4, "SH_WMGR_EnableWindow"); + add_ce_kernel_addr(0xf000b9f0, "SH_WMGR_IsWindowEnabled"); + add_ce_kernel_addr(0xf000b9ec, "SH_WMGR_CreateMenu"); + add_ce_kernel_addr(0xf000b9e8, "SH_WMGR_GetSubMenu"); + add_ce_kernel_addr(0xf000b9e4, "SH_WMGR_DefDlgProcW"); + add_ce_kernel_addr(0xf000b9e0, "SH_WMGR_SendNotifyMessageW"); + add_ce_kernel_addr(0xf000b9dc, "SH_WMGR_PostThreadMessageW"); + add_ce_kernel_addr(0xf000b9d8, "SH_WMGR_TranslateAcceleratorW"); + add_ce_kernel_addr(0xf000b9d4, "SH_WMGR_GetKeyboardLayout"); + add_ce_kernel_addr(0xf000b9d0, "SH_WMGR_GetKeyboardLayoutList"); + add_ce_kernel_addr(0xf000b9cc, "SH_WMGR_GetKeyboardType"); + add_ce_kernel_addr(0xf000b9c8, "SH_WMGR_ImageList_Create"); + add_ce_kernel_addr(0xf000b9c4, "SH_WMGR_ImageList_Destroy"); + add_ce_kernel_addr(0xf000b9c0, "SH_WMGR_ImageList_GetImageCount"); + add_ce_kernel_addr(0xf000b9bc, "SH_WMGR_ImageList_Add"); + add_ce_kernel_addr(0xf000b9b8, "SH_WMGR_ImageList_ReplaceIcon"); + add_ce_kernel_addr(0xf000b9b4, "SH_WMGR_ImageList_SetBkColor"); + add_ce_kernel_addr(0xf000b9b0, "SH_WMGR_ImageList_GetBkColor"); + add_ce_kernel_addr(0xf000b9ac, "SH_WMGR_ImageList_SetOverlayImage"); + add_ce_kernel_addr(0xf000b9a8, "SH_WMGR_ImageList_Draw"); + add_ce_kernel_addr(0xf000b9a4, "SH_WMGR_ImageList_Replace"); + add_ce_kernel_addr(0xf000b9a0, "SH_WMGR_ImageList_AddMasked"); + add_ce_kernel_addr(0xf000b99c, "SH_WMGR_ImageList_DrawEx"); + add_ce_kernel_addr(0xf000b998, "SH_WMGR_ImageList_Remove"); + add_ce_kernel_addr(0xf000b994, "SH_WMGR_ImageList_GetIcon"); + add_ce_kernel_addr(0xf000b990, "SH_WMGR_ImageList_LoadImage"); + add_ce_kernel_addr(0xf000b98c, "SH_WMGR_ImageList_BeginDrag"); + add_ce_kernel_addr(0xf000b988, "SH_WMGR_ImageList_EndDrag"); + add_ce_kernel_addr(0xf000b984, "SH_WMGR_ImageList_DragEnter"); + add_ce_kernel_addr(0xf000b980, "SH_WMGR_ImageList_DragLeave"); + add_ce_kernel_addr(0xf000b97c, "SH_WMGR_ImageList_DragMove"); + add_ce_kernel_addr(0xf000b978, "SH_WMGR_ImageList_SetDragCursorImage"); + add_ce_kernel_addr(0xf000b974, "SH_WMGR_AudioUpdateFromRegistry"); + add_ce_kernel_addr(0xf000b970, "SH_WMGR_ScrollDC"); + add_ce_kernel_addr(0xf000b96c, "SH_WMGR_ScrollWindowEx"); + add_ce_kernel_addr(0xf000b968, "SH_WMGR_OpenClipboard"); + add_ce_kernel_addr(0xf000b964, "SH_WMGR_CloseClipboard"); + add_ce_kernel_addr(0xf000b960, "SH_WMGR_GetClipboardOwner"); + add_ce_kernel_addr(0xf000b95c, "SH_WMGR_SetClipboardData"); + add_ce_kernel_addr(0xf000b958, "SH_WMGR_GetClipboardDataGwe"); + add_ce_kernel_addr(0xf000b954, "SH_WMGR_RegisterClipboardFormatW"); + add_ce_kernel_addr(0xf000b950, "SH_WMGR_CountClipboardFormats"); + add_ce_kernel_addr(0xf000b94c, "SH_WMGR_EnumClipboardFormats"); + add_ce_kernel_addr(0xf000b948, "SH_WMGR_GetClipboardFormatNameW"); + add_ce_kernel_addr(0xf000b944, "SH_WMGR_EmptyClipboard"); + add_ce_kernel_addr(0xf000b940, "SH_WMGR_IsClipboardFormatAvailable"); + add_ce_kernel_addr(0xf000b93c, "SH_WMGR_GetPriorityClipboardFormat"); + add_ce_kernel_addr(0xf000b938, "SH_WMGR_GetOpenClipboardWindow"); + add_ce_kernel_addr(0xf000b934, "SH_WMGR_MessageBeep"); + add_ce_kernel_addr(0xf000b930, "SH_WMGR_SystemIdleTimerReset"); + add_ce_kernel_addr(0xf000b92c, "SH_WMGR_SystemIdleTimerUpdateMax"); + add_ce_kernel_addr(0xf000b928, "SH_WMGR_Unused182"); + add_ce_kernel_addr(0xf000b924, "SH_WMGR_SetKeyboardTarget"); + add_ce_kernel_addr(0xf000b920, "SH_WMGR_GetKeyboardTarget"); + add_ce_kernel_addr(0xf000b91c, "SH_WMGR_NotifyWinUserSystem"); + add_ce_kernel_addr(0xf000b918, "SH_WMGR_SetMenuItemInfoW"); + add_ce_kernel_addr(0xf000b914, "SH_WMGR_GetMenuItemInfoW"); + add_ce_kernel_addr(0xf000b910, "SH_WMGR_SetCaretBlinkTime"); + add_ce_kernel_addr(0xf000b90c, "SH_WMGR_GetCaretBlinkTime"); + add_ce_kernel_addr(0xf000b908, "SH_WMGR_GetMessagePos"); + add_ce_kernel_addr(0xf000b904, "SH_WMGR_QASetWindowsJournalHook"); + add_ce_kernel_addr(0xf000b900, "SH_WMGR_QAUnhookWindowsJournalHook"); + add_ce_kernel_addr(0xf000b8fc, "SH_WMGR_NLedGetDeviceInfo"); + add_ce_kernel_addr(0xf000b8f8, "SH_WMGR_NLedSetDevice"); + add_ce_kernel_addr(0xf000b8f4, "SH_WMGR_EnumWindows_Trap"); + add_ce_kernel_addr(0xf000b8f0, "SH_WMGR_RectangleAnimation"); + add_ce_kernel_addr(0xf000b8ec, "SH_WMGR_MapDialogRect"); + add_ce_kernel_addr(0xf000b8e8, "SH_WMGR_GetSystemPowerStatusEx"); + add_ce_kernel_addr(0xf000b8e4, "SH_WMGR_GetDialogBaseUnits"); + add_ce_kernel_addr(0xf000b8e0, "SH_WMGR_GetDoubleClickTime"); + add_ce_kernel_addr(0xf000b8dc, "SH_WMGR_GetWindowThreadProcessId"); + add_ce_kernel_addr(0xf000b8d8, "SH_WMGR_CreateIconIndirect"); + add_ce_kernel_addr(0xf000b8d4, "SH_WMGR_ShellModalEnd"); + add_ce_kernel_addr(0xf000b8d0, "SH_WMGR_TouchCalibrate"); + add_ce_kernel_addr(0xf000b8cc, "SH_WMGR_BatteryGetLifeTimeInfo"); + add_ce_kernel_addr(0xf000b8c8, "SH_WMGR_BatteryDrvrGetLevels"); + add_ce_kernel_addr(0xf000b8c4, "SH_WMGR_GwesPowerOffSystem"); + add_ce_kernel_addr(0xf000b8c0, "SH_WMGR_BatteryNotifyOfTimeChange"); + add_ce_kernel_addr(0xf000b8bc, "SH_WMGR_LoadCursorW_Trap"); + add_ce_kernel_addr(0xf000b8b8, "SH_WMGR_SetCursor"); + add_ce_kernel_addr(0xf000b8b4, "SH_WMGR_DestroyCursor_Trap"); + add_ce_kernel_addr(0xf000b8b0, "SH_WMGR_DisableCaretSystemWide"); + add_ce_kernel_addr(0xf000b8ac, "SH_WMGR_EnableCaretSystemWide"); + add_ce_kernel_addr(0xf000b8a8, "SH_WMGR_GetMouseMovePoints"); + add_ce_kernel_addr(0xf000b8a4, "SH_WMGR_BatteryDrvrSupportsChangeNotification"); + add_ce_kernel_addr(0xf000b8a0, "SH_WMGR_EnableHardwareKeyboard"); + add_ce_kernel_addr(0xf000b89c, "SH_WMGR_GetKeyboardStatus"); + add_ce_kernel_addr(0xf000b898, "SH_WMGR_RegisterSIPanel"); + add_ce_kernel_addr(0xf000b894, "SH_WMGR_GetAsyncShiftFlags"); + add_ce_kernel_addr(0xf000b890, "SH_WMGR_MsgWaitForMultipleObjectsEx"); + add_ce_kernel_addr(0xf000b88c, "SH_WMGR_SetAssociatedMenu"); + add_ce_kernel_addr(0xf000b888, "SH_WMGR_GetAssociatedMenu"); + add_ce_kernel_addr(0xf000b884, "SH_WMGR_DrawMenuBar"); + add_ce_kernel_addr(0xf000b880, "SH_WMGR_SetSysColors"); + add_ce_kernel_addr(0xf000b87c, "SH_WMGR_DrawFrameControl"); + add_ce_kernel_addr(0xf000b878, "SH_WMGR_CreateCursor_Trap"); + add_ce_kernel_addr(0xf000b874, "SH_WMGR_RegisterWindowMessageW"); + add_ce_kernel_addr(0xf000b870, "SH_WMGR_SystemParametersInfo_GWE_Trap"); + add_ce_kernel_addr(0xf000b86c, "SH_WMGR_SendInput"); + add_ce_kernel_addr(0xf000b868, "SH_WMGR_SendDlgItemMessageW"); + add_ce_kernel_addr(0xf000b864, "SH_WMGR_SetDlgItemTextW"); + add_ce_kernel_addr(0xf000b860, "SH_WMGR_GetDlgItemTextW"); + add_ce_kernel_addr(0xf000b85c, "SH_WMGR_GetMessageSource_Trap"); + add_ce_kernel_addr(0xf000b858, "SH_WMGR_RegisterHotKey_Trap"); + add_ce_kernel_addr(0xf000b854, "SH_WMGR_UnregisterHotKey_Trap"); + add_ce_kernel_addr(0xf000b850, "SH_WMGR_ImageList_Copy"); + add_ce_kernel_addr(0xf000b84c, "SH_WMGR_ImageList_Duplicate"); + add_ce_kernel_addr(0xf000b848, "SH_WMGR_ImageList_SetImageCount"); + add_ce_kernel_addr(0xf000b844, "SH_WMGR_UnregisterFunc1_Trap"); + add_ce_kernel_addr(0xf000b840, "SH_WMGR_ImmGetContextFromWindowGwe"); + add_ce_kernel_addr(0xf000b83c, "SH_WMGR_ImmAssociateContextWithWindowGwe"); + add_ce_kernel_addr(0xf000b838, "SH_WMGR_ImmSetHotKey"); + add_ce_kernel_addr(0xf000b834, "SH_WMGR_BeginDeferWindowPos_Trap"); + add_ce_kernel_addr(0xf000b830, "SH_WMGR_DeferWindowPos_Trap"); + add_ce_kernel_addr(0xf000b82c, "SH_WMGR_EndDeferWindowPos_Trap"); + add_ce_kernel_addr(0xf000b828, "SH_WMGR_ImmGetHotKey"); + add_ce_kernel_addr(0xf000b824, "SH_WMGR_GetDCEx_Trap"); + add_ce_kernel_addr(0xf000b820, "SH_WMGR_GwesPowerDown"); + add_ce_kernel_addr(0xf000b81c, "SH_WMGR_GwesPowerUp"); + add_ce_kernel_addr(0xf000b810, "SH_WMGR_LoadKeyboardLayoutW"); + add_ce_kernel_addr(0xf000b80c, "SH_WMGR_ActivateKeyboardLayout"); + add_ce_kernel_addr(0xf000b808, "SH_WMGR_GetSystemPowerStatusEx2"); + add_ce_kernel_addr(0xf000b804, "SH_WMGR_GetKeyboardLayoutNameW"); + add_ce_kernel_addr(0xf000b7fc, "SH_WNET_WNetAddConnection3W"); + add_ce_kernel_addr(0xf000b7f8, "SH_WNET_WNetCancelConnection2W"); + add_ce_kernel_addr(0xf000b7f4, "SH_WNET_WNetConnectionDialog1W"); + add_ce_kernel_addr(0xf000b7f0, "SH_WNET_WNetDisconnectDialog"); + add_ce_kernel_addr(0xf000b7ec, "SH_WNET_WNetDisconnectDialog1W"); + add_ce_kernel_addr(0xf000b7e8, "SH_WNET_WNetGetConnectionW"); + add_ce_kernel_addr(0xf000b7e4, "SH_WNET_WNetGetUniversalNameW"); + add_ce_kernel_addr(0xf000b7e0, "SH_WNET_WNetGetUserW"); + add_ce_kernel_addr(0xf000b7dc, "SH_WNET_WNetOpenEnumW"); + add_ce_kernel_addr(0xf000b3f8, "SH_COMM_AFDSocket"); + add_ce_kernel_addr(0xf000b3f4, "SH_COMM_AFDControl"); + add_ce_kernel_addr(0xf000b3f0, "SH_COMM_AFDEnumProtocolsW"); + add_ce_kernel_addr(0xf000b3ec, "SH_COMM_RasDial"); + add_ce_kernel_addr(0xf000b3e8, "SH_COMM_RasHangup"); + add_ce_kernel_addr(0xf000b3e4, "SH_COMM_AFDGetHostentByAttr"); + add_ce_kernel_addr(0xf000b3e0, "SH_COMM_AFDAddIPHostent"); + add_ce_kernel_addr(0xf000b3dc, "SH_COMM_RasIOControl"); + add_ce_kernel_addr(0xf000b3d8, "SH_COMM_AFDSelect"); + add_ce_kernel_addr(0xf000b3d4, "SH_COMM_RasEnumEntries"); + add_ce_kernel_addr(0xf000b3d0, "SH_COMM_RasGetEntryDialParams"); + add_ce_kernel_addr(0xf000b3cc, "SH_COMM_RasSetEntryDialParams"); + add_ce_kernel_addr(0xf000b3c8, "SH_COMM_RasGetEntryProperties"); + add_ce_kernel_addr(0xf000b3c4, "SH_COMM_RasSetEntryProperties"); + add_ce_kernel_addr(0xf000b3c0, "SH_COMM_RasValidateEntryName"); + add_ce_kernel_addr(0xf000b3bc, "SH_COMM_RasDeleteEntry"); + add_ce_kernel_addr(0xf000b3b8, "SH_COMM_RasRenameEntry"); + add_ce_kernel_addr(0xf000b3b4, "SH_COMM_AFDAddInterface"); + add_ce_kernel_addr(0xf000b3b0, "SH_COMM_RasEnumConnections"); + add_ce_kernel_addr(0xf000b3ac, "SH_COMM_RasGetConnectStatus"); + add_ce_kernel_addr(0xf000b3a8, "SH_COMM_RasGetEntryDevConfig"); + add_ce_kernel_addr(0xf000b3a4, "SH_COMM_RasSetEntryDevConfig"); + add_ce_kernel_addr(0xf000b3a0, "SH_COMM_NETbios"); + add_ce_kernel_addr(0xf000b398, "SH_COMM_PMInstallProvider"); + add_ce_kernel_addr(0xf000b394, "SH_COMM_PMEnumProtocols"); + add_ce_kernel_addr(0xf000b390, "SH_COMM_PMFindProvider"); + add_ce_kernel_addr(0xf000b38c, "SH_COMM_PMInstallNameSpace"); + add_ce_kernel_addr(0xf000b388, "SH_COMM_PMEnumNameSpaceProviders"); + add_ce_kernel_addr(0xf000b384, "SH_COMM_PMFindNameSpaces"); + add_ce_kernel_addr(0xf000b380, "SH_COMM_PMAddrConvert"); + add_ce_kernel_addr(0xf000aff8, "SH_FILESYS_APIS_CreateDirectoryW"); + add_ce_kernel_addr(0xf000aff4, "SH_FILESYS_APIS_RemoveDirectoryW"); + add_ce_kernel_addr(0xf000aff0, "SH_FILESYS_APIS_MoveFileW"); + add_ce_kernel_addr(0xf000afec, "SH_FILESYS_APIS_CopyFileW"); + add_ce_kernel_addr(0xf000afe8, "SH_FILESYS_APIS_DeleteFileW"); + add_ce_kernel_addr(0xf000afe4, "SH_FILESYS_APIS_GetFileAttributesW"); + add_ce_kernel_addr(0xf000afe0, "SH_FILESYS_APIS_FindFirstFileW"); + add_ce_kernel_addr(0xf000afdc, "SH_FILESYS_APIS_CreateFileW"); + add_ce_kernel_addr(0xf000afd8, "SH_FILESYS_APIS_CeRegisterFileSystemNotification"); + add_ce_kernel_addr(0xf000afd4, "SH_FILESYS_APIS_CeRegisterReplNotification"); + add_ce_kernel_addr(0xf000afd0, "SH_FILESYS_APIS_CeOidGetInfoEx2"); + add_ce_kernel_addr(0xf000afcc, "SH_FILESYS_APIS_CeFindFirstDatabaseEx"); + add_ce_kernel_addr(0xf000afc8, "SH_FILESYS_APIS_CeCreateDatabaseEx2"); + add_ce_kernel_addr(0xf000afc4, "SH_FILESYS_APIS_CeSetDatabaseInfoEx2"); + add_ce_kernel_addr(0xf000afc0, "SH_FILESYS_APIS_CeOpenDatabaseEx2"); + add_ce_kernel_addr(0xf000afbc, "SH_FILESYS_APIS_RegCloseKey"); + add_ce_kernel_addr(0xf000afb8, "SH_FILESYS_APIS_RegCreateKeyExW"); + add_ce_kernel_addr(0xf000afb4, "SH_FILESYS_APIS_RegDeleteKeyW"); + add_ce_kernel_addr(0xf000afb0, "SH_FILESYS_APIS_RegDeleteValueW"); + add_ce_kernel_addr(0xf000afac, "SH_FILESYS_APIS_RegEnumValueW"); + add_ce_kernel_addr(0xf000afa8, "SH_FILESYS_APIS_RegEnumKeyExW"); + add_ce_kernel_addr(0xf000afa4, "SH_FILESYS_APIS_RegOpenKeyExW"); + add_ce_kernel_addr(0xf000afa0, "SH_FILESYS_APIS_RegQueryInfoKeyW"); + add_ce_kernel_addr(0xf000af9c, "SH_FILESYS_APIS_RegQueryValueExW"); + add_ce_kernel_addr(0xf000af98, "SH_FILESYS_APIS_RegSetValueExW"); + add_ce_kernel_addr(0xf000af94, "SH_FILESYS_APIS_GetTempPathW"); + add_ce_kernel_addr(0xf000af90, "SH_FILESYS_APIS_CeDeleteDatabaseEx"); + add_ce_kernel_addr(0xf000af8c, "SH_FILESYS_APIS_CheckPassword"); + add_ce_kernel_addr(0xf000af88, "SH_FILESYS_APIS_SetPassword"); + add_ce_kernel_addr(0xf000af84, "SH_FILESYS_APIS_SetFileAttributesW"); + add_ce_kernel_addr(0xf000af80, "SH_FILESYS_APIS_GetStoreInformation"); + add_ce_kernel_addr(0xf000af7c, "SH_FILESYS_APIS_CeGetReplChangeMask"); + add_ce_kernel_addr(0xf000af78, "SH_FILESYS_APIS_CeSetReplChangeMask"); + add_ce_kernel_addr(0xf000af74, "SH_FILESYS_APIS_CeGetReplChangeBitsEx"); + add_ce_kernel_addr(0xf000af70, "SH_FILESYS_APIS_CeClearReplChangeBitsEx"); + add_ce_kernel_addr(0xf000af6c, "SH_FILESYS_APIS_CeGetReplOtherBitsEx"); + add_ce_kernel_addr(0xf000af68, "SH_FILESYS_APIS_CeSetReplOtherBitsEx"); + add_ce_kernel_addr(0xf000af64, "SH_FILESYS_APIS_GetSystemMemoryDivision"); + add_ce_kernel_addr(0xf000af60, "SH_FILESYS_APIS_SetSystemMemoryDivision"); + add_ce_kernel_addr(0xf000af5c, "SH_FILESYS_APIS_RegCopyFile"); + add_ce_kernel_addr(0xf000af58, "SH_FILESYS_APIS_CloseAllFileHandles"); + add_ce_kernel_addr(0xf000af54, "SH_FILESYS_APIS_DeleteAndRenameFile"); + add_ce_kernel_addr(0xf000af50, "SH_FILESYS_APIS_RegRestoreFile"); + add_ce_kernel_addr(0xf000af4c, "SH_FILESYS_APIS_RegisterAFSEx"); + add_ce_kernel_addr(0xf000af48, "SH_FILESYS_APIS_DeregisterAFS"); + add_ce_kernel_addr(0xf000af44, "SH_FILESYS_APIS_GetPasswordActive"); + add_ce_kernel_addr(0xf000af40, "SH_FILESYS_APIS_SetPasswordActive"); + add_ce_kernel_addr(0xf000af3c, "SH_FILESYS_APIS_RegFlushKey"); + add_ce_kernel_addr(0xf000af38, "SH_FILESYS_APIS_FileSystemPowerFunction"); + add_ce_kernel_addr(0xf000af34, "SH_FILESYS_APIS_CeSetReplChangeBitsEx"); + add_ce_kernel_addr(0xf000af30, "SH_FILESYS_APIS_RegisterAFSName"); + add_ce_kernel_addr(0xf000af2c, "SH_FILESYS_APIS_DeregisterAFSName"); + add_ce_kernel_addr(0xf000af28, "SH_FILESYS_APIS_GetDiskFreeSpaceExW"); + add_ce_kernel_addr(0xf000af24, "SH_FILESYS_APIS_IsSystemFile"); + add_ce_kernel_addr(0xf000af20, "SH_FILESYS_APIS_CeChangeDatabaseLCID"); + add_ce_kernel_addr(0xf000af1c, "SH_FILESYS_APIS_DumpFileSystemHeap"); + add_ce_kernel_addr(0xf000af18, "SH_FILESYS_APIS_CeMountDBVol"); + add_ce_kernel_addr(0xf000af14, "SH_FILESYS_APIS_CeEnumDBVolumes"); + add_ce_kernel_addr(0xf000af10, "SH_FILESYS_APIS_CeUnmountDBVol"); + add_ce_kernel_addr(0xf000af0c, "SH_FILESYS_APIS_CeFlushDBVol"); + add_ce_kernel_addr(0xf000af08, "SH_FILESYS_APIS_CeFreeNotification"); + add_ce_kernel_addr(0xf000af04, "SH_FILESYS_APIS_FindFirstFileExW"); + add_ce_kernel_addr(0xf000af00, "SH_FILESYS_APIS_RegSaveKey"); + add_ce_kernel_addr(0xf000aefc, "SH_FILESYS_APIS_RegReplaceKey"); + add_ce_kernel_addr(0xf000aef8, "SH_FILESYS_APIS_SignalStarted"); + add_ce_kernel_addr(0xf000aef4, "SH_FILESYS_APIS_SetCurrentUser"); + add_ce_kernel_addr(0xf000aef0, "SH_FILESYS_APIS_SetUserData"); + add_ce_kernel_addr(0xf000aeec, "SH_FILESYS_APIS_GetUserInformation"); + add_ce_kernel_addr(0xf000aee8, "SH_FILESYS_APIS_SetPasswordStatus"); + add_ce_kernel_addr(0xf000aee4, "SH_FILESYS_APIS_GetPasswordStatus"); + add_ce_kernel_addr(0xf000aee0, "SH_FILESYS_APIS_ReplOpenSync"); + add_ce_kernel_addr(0xf000aedc, "SH_FILESYS_APIS_ReplCheckpoint"); + add_ce_kernel_addr(0xf000aed8, "SH_FILESYS_APIS_ReplCloseSync"); + add_ce_kernel_addr(0xf000aed4, "SH_FILESYS_APIS_ReplGetSyncState"); + add_ce_kernel_addr(0xf000aed0, "SH_FILESYS_APIS_ReplChangeSyncSettings"); + add_ce_kernel_addr(0xf000aecc, "SH_FILESYS_APIS_ReplFindNextChange"); + add_ce_kernel_addr(0xf000aec8, "SH_FILESYS_APIS_ReplGetOidStatus"); + add_ce_kernel_addr(0xf000aec4, "SH_FILESYS_APIS_CreateMsgQueue"); + add_ce_kernel_addr(0xf000aec0, "SH_FILESYS_APIS_OpenMsgQueue"); + add_ce_kernel_addr(0xf000aebc, "SH_FILESYS_APIS_ReadMsgQueue"); + add_ce_kernel_addr(0xf000aeb8, "SH_FILESYS_APIS_WriteMsgQueue"); + add_ce_kernel_addr(0xf000aeb4, "SH_FILESYS_APIS_GetMsgQueueInfo"); + add_ce_kernel_addr(0xf000aeb0, "SH_FILESYS_APIS_CloseMsgQueue"); + add_ce_kernel_addr(0xf000aeac, "SH_FILESYS_APIS_CryptProtectData"); + add_ce_kernel_addr(0xf000aea8, "SH_FILESYS_APIS_CryptUnprotectData"); + add_ce_kernel_addr(0xf000aea4, "SH_FILESYS_APIS_GenRandom"); + add_ce_kernel_addr(0xf000aea0, "SH_FILESYS_APIS_FindFirstChangeNotificationW"); + add_ce_kernel_addr(0xf000ae9c, "SH_FILESYS_APIS_FindNextChangeNotification"); + add_ce_kernel_addr(0xf000ae98, "SH_FILESYS_APIS_FindCloseChangeNotification"); + add_ce_kernel_addr(0xf000ae94, "SH_FILESYS_APIS_CeGetFileNotificationInfo"); + add_ce_kernel_addr(0xf000abf4, "SH_SHELL_GetOpenFileNameW"); + add_ce_kernel_addr(0xf000abf0, "SH_SHELL_GetSaveFileNameW"); + add_ce_kernel_addr(0xf000abe8, "SH_SHELL_Shell_NotifyIcon"); + add_ce_kernel_addr(0xf000abe4, "SH_SHELL_SHAddToRecentDocs"); + add_ce_kernel_addr(0xf000abdc, "SH_SHELL_SHCreateExplorerInstance"); + add_ce_kernel_addr(0xf000ab94, "SH_SHELL_NotSystemParametersInfo_Trap"); + add_ce_kernel_addr(0xf000ab90, "SH_SHELL_SHGetAppKeyAssoc_Trap"); + add_ce_kernel_addr(0xf000ab8c, "SH_SHELL_SHSetAppKeyWndAssoc_Trap"); + add_ce_kernel_addr(0xf000ab78, "SH_SHELL_SHFileNotifyRemove_Trap"); + add_ce_kernel_addr(0xf000ab74, "SH_SHELL_SHFileNotifyFree_Trap"); + add_ce_kernel_addr(0xf000ab6c, "SH_SHELL_SHCloseApps_Trap"); + add_ce_kernel_addr(0xf000ab68, "SH_SHELL_SHSipPreference_Trap"); + add_ce_kernel_addr(0xf000ab5c, "SH_SHELL_SHSetNavBarText_Trap"); + add_ce_kernel_addr(0xf000ab58, "SH_SHELL_SHDoneButton_Trap"); + add_ce_kernel_addr(0xf000ab38, "SH_SHELL_SHChangeNotifyRegister_Trap"); + add_ce_kernel_addr(0xf000ab24, "SH_SHELL_SHNotificationAdd_Trap"); + add_ce_kernel_addr(0xf000ab20, "SH_SHELL_SHNotificationUpdate_Trap"); + add_ce_kernel_addr(0xf000ab1c, "SH_SHELL_SHNotificationRemove_Trap"); + add_ce_kernel_addr(0xf000ab18, "SH_SHELL_SHNotificationGetData_Trap"); + add_ce_kernel_addr(0xf000aadc, "SH_SHELL_SendChangeNotificationToWindow_Trap"); + add_ce_kernel_addr(0xf000a7f8, "SH_DEVMGR_APIS_RegisterDevice"); + add_ce_kernel_addr(0xf000a7f4, "SH_DEVMGR_APIS_DeregisterDevice"); + add_ce_kernel_addr(0xf000a7f0, "SH_DEVMGR_APIS_CloseAllDeviceHandles"); + add_ce_kernel_addr(0xf000a7ec, "SH_DEVMGR_APIS_CreateDeviceHandle"); + add_ce_kernel_addr(0xf000a7e8, "SH_DEVMGR_APIS_LoadFSD"); + add_ce_kernel_addr(0xf000a7e0, "SH_DEVMGR_APIS_DeactivateDevice"); + add_ce_kernel_addr(0xf000a7dc, "SH_DEVMGR_APIS_LoadFSDEx"); + add_ce_kernel_addr(0xf000a7d8, "SH_DEVMGR_APIS_GetDeviceByIndex"); + add_ce_kernel_addr(0xf000a7d4, "SH_DEVMGR_APIS_CeResyncFilesys"); + add_ce_kernel_addr(0xf000a7d0, "SH_DEVMGR_APIS_ActivateDeviceEx"); + add_ce_kernel_addr(0xf000a7cc, "SH_DEVMGR_APIS_RequestDeviceNotifications"); + add_ce_kernel_addr(0xf000a7c8, "SH_DEVMGR_APIS_StopDeviceNotifications"); + add_ce_kernel_addr(0xf000a7c4, "SH_DEVMGR_APIS__GetDevicePathFromPnp"); + add_ce_kernel_addr(0xf000a7c0, "SH_DEVMGR_APIS_ResourceCreateList"); + add_ce_kernel_addr(0xf000a7bc, "SH_DEVMGR_APIS_ResourceAdjust"); + add_ce_kernel_addr(0xf000a7b8, "SH_DEVMGR_APIS_GetSystemPowerState"); + add_ce_kernel_addr(0xf000a7b4, "SH_DEVMGR_APIS_SetSystemPowerState"); + add_ce_kernel_addr(0xf000a7b0, "SH_DEVMGR_APIS_SetPowerRequirement"); + add_ce_kernel_addr(0xf000a7ac, "SH_DEVMGR_APIS_ReleasePowerRequirement"); + add_ce_kernel_addr(0xf000a7a8, "SH_DEVMGR_APIS_RequestPowerNotifications"); + add_ce_kernel_addr(0xf000a7a4, "SH_DEVMGR_APIS_StopPowerNotifications"); + add_ce_kernel_addr(0xf000a79c, "SH_DEVMGR_APIS_DevicePowerNotify"); + add_ce_kernel_addr(0xf000a798, "SH_DEVMGR_APIS_RegisterPowerRelationship"); + add_ce_kernel_addr(0xf000a794, "SH_DEVMGR_APIS_ReleasePowerRelationship"); + add_ce_kernel_addr(0xf000a790, "SH_DEVMGR_APIS_SetDevicePower"); + add_ce_kernel_addr(0xf000a78c, "SH_DEVMGR_APIS_GetDevicePower"); + add_ce_kernel_addr(0xf000a788, "SH_DEVMGR_APIS_AdvertiseInterface"); + add_ce_kernel_addr(0xf000a3f8, "SH_TAPI_lineClose"); + add_ce_kernel_addr(0xf000a3f4, "SH_TAPI_lineConfigDialogEdit"); + add_ce_kernel_addr(0xf000a3f0, "SH_TAPI_lineDeallocateCall"); + add_ce_kernel_addr(0xf000a3ec, "SH_TAPI_lineDrop"); + add_ce_kernel_addr(0xf000a3e8, "SH_TAPI_lineGetDevCaps"); + add_ce_kernel_addr(0xf000a3e4, "SH_TAPI_lineGetDevConfig"); + add_ce_kernel_addr(0xf000a3e0, "SH_TAPI_lineGetTranslateCaps"); + add_ce_kernel_addr(0xf000a3dc, "SH_TAPI_TAPIlineInitialize"); + add_ce_kernel_addr(0xf000a3d8, "SH_TAPI_lineMakeCall"); + add_ce_kernel_addr(0xf000a3d4, "SH_TAPI_lineNegotiateAPIVersion"); + add_ce_kernel_addr(0xf000a3d0, "SH_TAPI_lineOpen"); + add_ce_kernel_addr(0xf000a3cc, "SH_TAPI_lineSetDevConfig"); + add_ce_kernel_addr(0xf000a3c8, "SH_TAPI_lineSetStatusMessages"); + add_ce_kernel_addr(0xf000a3c4, "SH_TAPI_TAPIlineShutdown"); + add_ce_kernel_addr(0xf000a3c0, "SH_TAPI_lineTranslateAddress"); + add_ce_kernel_addr(0xf000a3bc, "SH_TAPI_lineTranslateDialog"); + add_ce_kernel_addr(0xf000a3b8, "SH_TAPI_lineGetID"); + add_ce_kernel_addr(0xf000a3b4, "SH_TAPI_lineAddProvider"); + add_ce_kernel_addr(0xf000a3b0, "SH_TAPI_lineSetCurrentLocation"); + add_ce_kernel_addr(0xf000a3ac, "SH_TAPI_lineAccept"); + add_ce_kernel_addr(0xf000a3a8, "SH_TAPI_lineAddToConference"); + add_ce_kernel_addr(0xf000a3a4, "SH_TAPI_lineAnswer"); + add_ce_kernel_addr(0xf000a3a0, "SH_TAPI_lineBlindTransfer"); + add_ce_kernel_addr(0xf000a39c, "SH_TAPI_lineCompleteTransfer"); + add_ce_kernel_addr(0xf000a398, "SH_TAPI_lineDevSpecific"); + add_ce_kernel_addr(0xf000a394, "SH_TAPI_lineDial"); + add_ce_kernel_addr(0xf000a390, "SH_TAPI_lineForward"); + add_ce_kernel_addr(0xf000a38c, "SH_TAPI_lineGenerateDigits"); + add_ce_kernel_addr(0xf000a388, "SH_TAPI_lineGenerateTone"); + add_ce_kernel_addr(0xf000a384, "SH_TAPI_lineGetAddressCaps"); + add_ce_kernel_addr(0xf000a380, "SH_TAPI_lineGetAddressID"); + add_ce_kernel_addr(0xf000a37c, "SH_TAPI_lineGetAddressStatus"); + add_ce_kernel_addr(0xf000a378, "SH_TAPI_lineGetAppPriority"); + add_ce_kernel_addr(0xf000a374, "SH_TAPI_lineGetCallInfo"); + add_ce_kernel_addr(0xf000a370, "SH_TAPI_lineGetCallStatus"); + add_ce_kernel_addr(0xf000a36c, "SH_TAPI_lineGetConfRelatedCalls"); + add_ce_kernel_addr(0xf000a368, "SH_TAPI_lineGetIcon"); + add_ce_kernel_addr(0xf000a364, "SH_TAPI_lineGetLineDevStatus"); + add_ce_kernel_addr(0xf000a360, "SH_TAPI_lineGetMessage"); + add_ce_kernel_addr(0xf000a35c, "SH_TAPI_lineGetNewCalls"); + add_ce_kernel_addr(0xf000a358, "SH_TAPI_lineGetNumRings"); + add_ce_kernel_addr(0xf000a354, "SH_TAPI_lineGetProviderList"); + add_ce_kernel_addr(0xf000a350, "SH_TAPI_lineGetStatusMessages"); + add_ce_kernel_addr(0xf000a34c, "SH_TAPI_lineHandoff"); + add_ce_kernel_addr(0xf000a348, "SH_TAPI_lineHold"); + add_ce_kernel_addr(0xf000a344, "SH_TAPI_TAPIlineInitializeEx"); + add_ce_kernel_addr(0xf000a340, "SH_TAPI_lineMonitorDigits"); + add_ce_kernel_addr(0xf000a33c, "SH_TAPI_lineMonitorMedia"); + add_ce_kernel_addr(0xf000a338, "SH_TAPI_lineNegotiateExtVersion"); + add_ce_kernel_addr(0xf000a334, "SH_TAPI_linePickup"); + add_ce_kernel_addr(0xf000a330, "SH_TAPI_linePrepareAddToConference"); + add_ce_kernel_addr(0xf000a32c, "SH_TAPI_lineRedirect"); + add_ce_kernel_addr(0xf000a328, "SH_TAPI_lineReleaseUserUserInfo"); + add_ce_kernel_addr(0xf000a324, "SH_TAPI_lineRemoveFromConference"); + add_ce_kernel_addr(0xf000a320, "SH_TAPI_lineSendUserUserInfo"); + add_ce_kernel_addr(0xf000a31c, "SH_TAPI_lineSetAppPriority"); + add_ce_kernel_addr(0xf000a318, "SH_TAPI_lineSetCallParams"); + add_ce_kernel_addr(0xf000a314, "SH_TAPI_lineSetCallPrivilege"); + add_ce_kernel_addr(0xf000a310, "SH_TAPI_lineSetMediaMode"); + add_ce_kernel_addr(0xf000a30c, "SH_TAPI_lineSetNumRings"); + add_ce_kernel_addr(0xf000a308, "SH_TAPI_lineSetTerminal"); + add_ce_kernel_addr(0xf000a304, "SH_TAPI_lineSetTollList"); + add_ce_kernel_addr(0xf000a300, "SH_TAPI_lineSetupConference"); + add_ce_kernel_addr(0xf000a2fc, "SH_TAPI_lineSetupTransfer"); + add_ce_kernel_addr(0xf000a2f8, "SH_TAPI_lineSwapHold"); + add_ce_kernel_addr(0xf000a2f4, "SH_TAPI_lineUnhold"); + add_ce_kernel_addr(0xf000a2f0, "SH_TAPI_phoneClose"); + add_ce_kernel_addr(0xf000a2ec, "SH_TAPI_phoneConfigDialog"); + add_ce_kernel_addr(0xf000a2e8, "SH_TAPI_phoneDevSpecific"); + add_ce_kernel_addr(0xf000a2e4, "SH_TAPI_phoneGetDevCaps"); + add_ce_kernel_addr(0xf000a2e0, "SH_TAPI_phoneGetGain"); + add_ce_kernel_addr(0xf000a2dc, "SH_TAPI_phoneGetHookSwitch"); + add_ce_kernel_addr(0xf000a2d8, "SH_TAPI_phoneGetIcon"); + add_ce_kernel_addr(0xf000a2d4, "SH_TAPI_phoneGetID"); + add_ce_kernel_addr(0xf000a2d0, "SH_TAPI_phoneGetMessage"); + add_ce_kernel_addr(0xf000a2cc, "SH_TAPI_phoneGetRing"); + add_ce_kernel_addr(0xf000a2c8, "SH_TAPI_phoneGetStatus"); + add_ce_kernel_addr(0xf000a2c4, "SH_TAPI_phoneGetStatusMessages"); + add_ce_kernel_addr(0xf000a2c0, "SH_TAPI_phoneGetVolume"); + add_ce_kernel_addr(0xf000a2bc, "SH_TAPI_TAPIphoneInitializeEx"); + add_ce_kernel_addr(0xf000a2b8, "SH_TAPI_phoneNegotiateAPIVersion"); + add_ce_kernel_addr(0xf000a2b4, "SH_TAPI_phoneNegotiateExtVersion"); + add_ce_kernel_addr(0xf000a2b0, "SH_TAPI_phoneOpen"); + add_ce_kernel_addr(0xf000a2ac, "SH_TAPI_phoneSetGain"); + add_ce_kernel_addr(0xf000a2a8, "SH_TAPI_phoneSetHookSwitch"); + add_ce_kernel_addr(0xf000a2a4, "SH_TAPI_phoneSetRing"); + add_ce_kernel_addr(0xf000a2a0, "SH_TAPI_phoneSetStatusMessages"); + add_ce_kernel_addr(0xf000a29c, "SH_TAPI_phoneSetVolume"); + add_ce_kernel_addr(0xf000a298, "SH_TAPI_TAPIphoneShutdown"); + add_ce_kernel_addr(0xf0009ff8, "SH_PATCHER_PatchExe"); + add_ce_kernel_addr(0xf0009ff4, "SH_PATCHER_PatchDll"); + add_ce_kernel_addr(0xf0009ff0, "SH_PATCHER_FreeDllPatch"); + add_ce_kernel_addr(0xf00097f8, "SH_SERVICES_ActivateService"); + add_ce_kernel_addr(0xf00097f4, "SH_SERVICES_RegisterService"); + add_ce_kernel_addr(0xf00097f0, "SH_SERVICES_DeregisterService"); + add_ce_kernel_addr(0xf00097ec, "SH_SERVICES_CloseAllServiceHandles"); + add_ce_kernel_addr(0xf00097e8, "SH_SERVICES_CreateServiceHandle"); + add_ce_kernel_addr(0xf00097e4, "SH_SERVICES_GetServiceByIndex"); + add_ce_kernel_addr(0xf00097e0, "SH_SERVICES_ServiceIoControl"); + add_ce_kernel_addr(0xf00097dc, "SH_SERVICES_ServiceAddPort"); + add_ce_kernel_addr(0xf00097d8, "SH_SERVICES_ServiceUnbindPorts"); + add_ce_kernel_addr(0xf00097d4, "SH_SERVICES_EnumServices"); + add_ce_kernel_addr(0xf00097d0, "SH_SERVICES_GetServiceHandle"); + add_ce_kernel_addr(0xf00097cc, "SH_SERVICES_ServiceClosePort"); +} + +void arm7_cpu_device::print_ce_kernel_address(const offs_t addr) +{ + if (addr < 0x10400 && m_ce_kernel_addr_present[addr]) + { + printf("Kernel Call: %s\n", m_ce_kernel_addrs[addr].c_str()); + } + else if (addr == 0xFFFFCB80) + printf("Kernel Call: InterlockedPopList\n"); + else if (addr == 0xFFFFCB98) + printf("Kernel Call: InterlockedPushList\n"); + else if (addr == 0xFFFFCBAC) + printf("Kernel Call: InterlockedCompareExchange\n"); + else if (addr == 0xFFFFCBC0) + printf("Kernel Call: InterlockedExchangeAdd\n"); + else if (addr == 0xFFFFCBD4) + printf("Kernel Call: InterlockedExchange\n"); +} diff --git a/src/devices/cpu/arm7/lpc210x.cpp b/src/devices/cpu/arm7/lpc210x.cpp index d2964589e01..9e9c51c620a 100644 --- a/src/devices/cpu/arm7/lpc210x.cpp +++ b/src/devices/cpu/arm7/lpc210x.cpp @@ -15,6 +15,9 @@ #include "emu.h" #include "lpc210x.h" +#include "arm7core.h" + + DEFINE_DEVICE_TYPE(LPC2103, lpc210x_device, "lpc2103", "NXP LPC2103") void lpc210x_device::lpc2103_map(address_map &map) @@ -37,22 +40,23 @@ void lpc210x_device::lpc2103_map(address_map &map) map(0xE01FC100, 0xE01FC103).rw(FUNC(lpc210x_device::apbdiv_r), FUNC(lpc210x_device::apbdiv_w)); map(0xE01FC1a0, 0xE01FC1a3).rw(FUNC(lpc210x_device::scs_r), FUNC(lpc210x_device::scs_w)); - map(0xFFFFF000, 0xFFFFF2ff).rw(FUNC(lpc210x_device::vic_r), FUNC(lpc210x_device::vic_w)); // interrupt controller + map(0xfffff000, 0xffffffff).m(m_vic, FUNC(vic_pl190_device::map)); // interrupt controller } lpc210x_device::lpc210x_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : arm7_cpu_device(mconfig, LPC2103, tag, owner, clock, 4, ARCHFLAG_T, ENDIANNESS_LITTLE) , m_program_config("program", ENDIANNESS_LITTLE, 32, 32, 0, address_map_constructor(FUNC(lpc210x_device::lpc2103_map), this)) + , m_vic(*this, "vic") { } -READ32_MEMBER(lpc210x_device::arm_E01FC088_r) +uint32_t lpc210x_device::arm_E01FC088_r() { return 0xffffffff; } -READ32_MEMBER(lpc210x_device::flash_r) +uint32_t lpc210x_device::flash_r(offs_t offset) { uint32_t ret = (m_flash[offset * 4 + 3] << 24) | (m_flash[offset * 4 + 2] << 16) | @@ -61,7 +65,7 @@ READ32_MEMBER(lpc210x_device::flash_r) return ret; } -WRITE32_MEMBER(lpc210x_device::flash_w) +void lpc210x_device::flash_w(offs_t offset, uint32_t data) { // } @@ -98,32 +102,9 @@ void lpc210x_device::device_reset() m_TxPR[1] = 0; } -/* VIC (Vectored Interrupt Controller) */ - -READ32_MEMBER( lpc210x_device::vic_r ) -{ - switch (offset*4) - { - default: - logerror("%s unhandled read from VIC offset %08x mem_mask %08x\n", machine().describe_context(), offset * 4, mem_mask); - } - - return 0x00000000; -} - - -WRITE32_MEMBER( lpc210x_device::vic_w ) -{ - switch (offset * 4) - { - default: - logerror("%s unhandled write VIC offset %02x data %08x mem_mask %08x\n", machine().describe_context(), offset * 4, data, mem_mask); - } -} - /* PIN Select block */ -READ32_MEMBER( lpc210x_device::pin_r ) +uint32_t lpc210x_device::pin_r(offs_t offset, uint32_t mem_mask) { switch (offset*4) { @@ -135,7 +116,7 @@ READ32_MEMBER( lpc210x_device::pin_r ) } -WRITE32_MEMBER( lpc210x_device::pin_w ) +void lpc210x_device::pin_w(offs_t offset, uint32_t data, uint32_t mem_mask) { switch (offset * 4) { @@ -146,7 +127,7 @@ WRITE32_MEMBER( lpc210x_device::pin_w ) /* MAM block (memory conttroller) */ -READ32_MEMBER( lpc210x_device::mam_r ) +uint32_t lpc210x_device::mam_r(offs_t offset, uint32_t mem_mask) { switch (offset*4) { @@ -158,7 +139,7 @@ READ32_MEMBER( lpc210x_device::mam_r ) } -WRITE32_MEMBER( lpc210x_device::mam_w ) +void lpc210x_device::mam_w(offs_t offset, uint32_t data, uint32_t mem_mask) { switch (offset * 4) { @@ -169,7 +150,7 @@ WRITE32_MEMBER( lpc210x_device::mam_w ) /* FIO block */ -READ32_MEMBER( lpc210x_device::fio_r ) +uint32_t lpc210x_device::fio_r(offs_t offset, uint32_t mem_mask) { switch (offset*4) { @@ -181,7 +162,7 @@ READ32_MEMBER( lpc210x_device::fio_r ) } -WRITE32_MEMBER( lpc210x_device::fio_w ) +void lpc210x_device::fio_w(offs_t offset, uint32_t data, uint32_t mem_mask) { switch (offset * 4) { @@ -193,35 +174,35 @@ WRITE32_MEMBER( lpc210x_device::fio_w ) /* APB Divider */ -READ32_MEMBER( lpc210x_device::apbdiv_r ) +uint32_t lpc210x_device::apbdiv_r(offs_t offset, uint32_t mem_mask) { logerror("%s unhandled read from APBDIV offset %08x mem_mask %08x\n", machine().describe_context(), offset * 4, mem_mask); return 0x00000000; } -WRITE32_MEMBER( lpc210x_device::apbdiv_w ) +void lpc210x_device::apbdiv_w(offs_t offset, uint32_t data, uint32_t mem_mask) { logerror("%s unhandled write APBDIV offset %02x data %08x mem_mask %08x\n", machine().describe_context(),offset * 4, data, mem_mask); } /* Syscon misc registers */ -READ32_MEMBER( lpc210x_device::scs_r ) +uint32_t lpc210x_device::scs_r(offs_t offset, uint32_t mem_mask) { logerror("%s unhandled read from SCS offset %08x mem_mask %08x\n", machine().describe_context(),offset * 4, mem_mask); return 0x00000000; } -WRITE32_MEMBER( lpc210x_device::scs_w ) +void lpc210x_device::scs_w(offs_t offset, uint32_t data, uint32_t mem_mask) { logerror("%s unhandled write SCS offset %02x data %08x mem_mask %08x\n", machine().describe_context(),offset * 4, data, mem_mask); } /* PLL Phase Locked Loop */ -READ32_MEMBER( lpc210x_device::pll_r ) +uint32_t lpc210x_device::pll_r(offs_t offset, uint32_t mem_mask) { switch (offset*4) { @@ -233,7 +214,7 @@ READ32_MEMBER( lpc210x_device::pll_r ) } -WRITE32_MEMBER( lpc210x_device::pll_w ) +void lpc210x_device::pll_w(offs_t offset, uint32_t data, uint32_t mem_mask) { switch (offset * 4) { @@ -245,7 +226,7 @@ WRITE32_MEMBER( lpc210x_device::pll_w ) /* Timers */ -uint32_t lpc210x_device::read_timer(address_space &space, int timer, int offset, uint32_t mem_mask) +uint32_t lpc210x_device::read_timer(int timer, int offset, uint32_t mem_mask) { switch (offset*4) { @@ -260,7 +241,7 @@ uint32_t lpc210x_device::read_timer(address_space &space, int timer, int offset, } -void lpc210x_device::write_timer(address_space &space, int timer, int offset, uint32_t data, uint32_t mem_mask) +void lpc210x_device::write_timer(int timer, int offset, uint32_t data, uint32_t mem_mask) { switch (offset * 4) { @@ -278,4 +259,7 @@ void lpc210x_device::write_timer(address_space &space, int timer, int offset, ui void lpc210x_device::device_add_mconfig(machine_config &config) { + PL190_VIC(config, m_vic, 0); + m_vic->out_irq_cb().set_inputline(*this, ARM7_IRQ_LINE); + m_vic->out_fiq_cb().set_inputline(*this, ARM7_FIRQ_LINE); } diff --git a/src/devices/cpu/arm7/lpc210x.h b/src/devices/cpu/arm7/lpc210x.h index afcc4a57795..00bee60ef00 100644 --- a/src/devices/cpu/arm7/lpc210x.h +++ b/src/devices/cpu/arm7/lpc210x.h @@ -1,13 +1,15 @@ // license:BSD-3-Clause // copyright-holders:David Haywood -#ifndef MAME_CPU_ARM7_LPC2103_H -#define MAME_CPU_ARM7_LPC2103_H +#ifndef MAME_CPU_ARM7_LPC210X_H +#define MAME_CPU_ARM7_LPC210X_H #pragma once #include "arm7.h" -#include "arm7core.h" + +#include "machine/vic_pl192.h" + /*************************************************************************** DEVICE CONFIGURATION MACROS @@ -23,57 +25,53 @@ class lpc210x_device : public arm7_cpu_device public: lpc210x_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); - DECLARE_READ32_MEMBER(arm_E01FC088_r); - DECLARE_READ32_MEMBER(flash_r); - DECLARE_WRITE32_MEMBER(flash_w); + uint32_t arm_E01FC088_r(); + uint32_t flash_r(offs_t offset); + void flash_w(offs_t offset, uint32_t data); // timer 0 / 1 - DECLARE_READ32_MEMBER(timer0_r) { return read_timer(space, 0, offset, mem_mask); } - DECLARE_WRITE32_MEMBER(timer0_w) { write_timer(space, 0, offset, data, mem_mask); } + uint32_t timer0_r(offs_t offset, uint32_t mem_mask = ~0) { return read_timer(0, offset, mem_mask); } + void timer0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) { write_timer(0, offset, data, mem_mask); } - DECLARE_READ32_MEMBER(timer1_r) { return read_timer(space, 1, offset, mem_mask); } - DECLARE_WRITE32_MEMBER(timer1_w) { write_timer(space, 1, offset, data, mem_mask); } + uint32_t timer1_r(offs_t offset, uint32_t mem_mask = ~0) { return read_timer(1, offset, mem_mask); } + void timer1_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) { write_timer(1, offset, data, mem_mask); } - void write_timer(address_space &space, int timer, int offset, uint32_t data, uint32_t mem_mask); - uint32_t read_timer(address_space &space, int timer, int offset, uint32_t mem_mask); - - // VIC - DECLARE_READ32_MEMBER(vic_r); - DECLARE_WRITE32_MEMBER(vic_w); + void write_timer(int timer, int offset, uint32_t data, uint32_t mem_mask); + uint32_t read_timer(int timer, int offset, uint32_t mem_mask); // PIN select block - DECLARE_READ32_MEMBER(pin_r); - DECLARE_WRITE32_MEMBER(pin_w); + uint32_t pin_r(offs_t offset, uint32_t mem_mask = ~0); + void pin_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); //PLL Phase Locked Loop - DECLARE_READ32_MEMBER(pll_r); - DECLARE_WRITE32_MEMBER(pll_w); + uint32_t pll_r(offs_t offset, uint32_t mem_mask = ~0); + void pll_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); //MAM memory controller - DECLARE_READ32_MEMBER(mam_r); - DECLARE_WRITE32_MEMBER(mam_w); + uint32_t mam_r(offs_t offset, uint32_t mem_mask = ~0); + void mam_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); //APB divider - DECLARE_READ32_MEMBER(apbdiv_r); - DECLARE_WRITE32_MEMBER(apbdiv_w); + uint32_t apbdiv_r(offs_t offset, uint32_t mem_mask = ~0); + void apbdiv_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); //syscon misc - DECLARE_READ32_MEMBER(scs_r); - DECLARE_WRITE32_MEMBER(scs_w); + uint32_t scs_r(offs_t offset, uint32_t mem_mask = ~0); + void scs_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // fio - DECLARE_READ32_MEMBER(fio_r); - DECLARE_WRITE32_MEMBER(fio_w); + uint32_t fio_r(offs_t offset, uint32_t mem_mask = ~0); + void fio_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // todo, use an appropriate flash type instead uint8_t m_flash[0x8000]; // needs to be public because the harmony/melody device injects contents with memcpy, yuck - void lpc2103_map(address_map &map); + void lpc2103_map(address_map &map) ATTR_COLD; protected: // device-level overrides - virtual void device_add_mconfig(machine_config &config) override; - virtual void device_start() override; - virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; virtual space_config_vector memory_space_config() const override; @@ -81,10 +79,12 @@ protected: private: address_space_config m_program_config; + + required_device<vic_pl190_device> m_vic; }; // device type definition DECLARE_DEVICE_TYPE(LPC2103, lpc210x_device) -#endif // MAME_CPU_ARM7_LPC2103_H +#endif // MAME_CPU_ARM7_LPC210X_H diff --git a/src/devices/cpu/arm7/upd800468.cpp b/src/devices/cpu/arm7/upd800468.cpp new file mode 100644 index 00000000000..87dea88ad5c --- /dev/null +++ b/src/devices/cpu/arm7/upd800468.cpp @@ -0,0 +1,249 @@ +// license:BSD-3-Clause +// copyright-holders:Devin Acker +/*************************************************************************** + + NEC uPD800468 + ARM7TDMI core with internal peripherals and external ROM/flash + + Used in late 2000s/early 2010s Casio keyboards, like the CTK-2000 series. + +***************************************************************************/ + +#include "emu.h" +#include "upd800468.h" + +#include "arm7core.h" + + +DEFINE_DEVICE_TYPE(UPD800468_TIMER, upd800468_timer_device, "upd800468_timer", "NEC uPD800468 timer") + +upd800468_timer_device::upd800468_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, UPD800468_TIMER, tag, owner, clock) + , m_irq_cb(*this) +{ +} + +u32 upd800468_timer_device::rate_r() +{ + return m_rate; +} + +void upd800468_timer_device::rate_w(u32 data) +{ + m_rate = data; +} + +u8 upd800468_timer_device::control_r() +{ + return m_control; +} + +void upd800468_timer_device::control_w(u8 data) +{ + if (BIT(data, 1) != BIT(m_control, 1)) + { + if (BIT(data, 1)) + { + attotime period = clocks_to_attotime(m_rate); + m_timer->adjust(period, 0, period); + } + else + { + m_timer->adjust(attotime::never); + m_irq_cb(0); + } + } + + if (!BIT(data, 0)) + { + m_irq_cb(0); + } + + m_control = data; +} + +void upd800468_timer_device::device_start() +{ + m_timer = timer_alloc(FUNC(upd800468_timer_device::irq_timer_tick), this); + + save_item(NAME(m_rate)); + save_item(NAME(m_control)); +} + +void upd800468_timer_device::device_reset() +{ + m_rate = m_control = 0; +} + +TIMER_CALLBACK_MEMBER(upd800468_timer_device::irq_timer_tick) +{ + if (BIT(m_control, 0)) + m_irq_cb(1); +} + +DEFINE_DEVICE_TYPE(UPD800468, upd800468_device, "upd800468", "NEC uPD800468") + +void upd800468_device::upd800468_map(address_map &map) +{ + map(0x00000000, 0x0000ffff).view(m_ram_view); + m_ram_view[0](0x00000000, 0x0000ffff).ram(); + + // RAM used for storing user samples (TODO: is this actually supposed to be part of the main 64kb RAM?) + map(0x1ffe8400, 0x1ffedfff).ram(); + + map(0x1fff00a0, 0x1fff00a1).r(m_kbd, FUNC(gt913_kbd_hle_device::read)).umask32(0x0000ffff); + map(0x1fff00a2, 0x1fff00a3).r(m_kbd, FUNC(gt913_kbd_hle_device::status_r)).umask32(0xffff0000); + map(0x1fff00a4, 0x1fff00a5).w(m_kbd, FUNC(gt913_kbd_hle_device::status_w)).umask32(0x0000ffff); + + map(0x1fff00c0, 0x1fff00cf).r(FUNC(upd800468_device::adc_r)); + + map(0x1fff0141, 0x1fff0141).rw(FUNC(upd800468_device::port_ddr_r<0>), FUNC(upd800468_device::port_ddr_w<0>)).umask32(0x0000ff00); + map(0x1fff0142, 0x1fff0142).rw(FUNC(upd800468_device::port_r<0>), FUNC(upd800468_device::port_w<0>)).umask32(0x00ff0000); + map(0x1fff0145, 0x1fff0145).rw(FUNC(upd800468_device::port_ddr_r<1>), FUNC(upd800468_device::port_ddr_w<1>)).umask32(0x0000ff00); + map(0x1fff0146, 0x1fff0146).rw(FUNC(upd800468_device::port_r<1>), FUNC(upd800468_device::port_w<1>)).umask32(0x00ff0000); + map(0x1fff0149, 0x1fff0149).rw(FUNC(upd800468_device::port_ddr_r<2>), FUNC(upd800468_device::port_ddr_w<2>)).umask32(0x0000ff00); + map(0x1fff014a, 0x1fff014a).rw(FUNC(upd800468_device::port_r<2>), FUNC(upd800468_device::port_w<2>)).umask32(0x00ff0000); + map(0x1fff014d, 0x1fff014d).rw(FUNC(upd800468_device::port_ddr_r<3>), FUNC(upd800468_device::port_ddr_w<3>)).umask32(0x0000ff00); + map(0x1fff014e, 0x1fff014e).rw(FUNC(upd800468_device::port_r<3>), FUNC(upd800468_device::port_w<3>)).umask32(0x00ff0000); + + map(0x2a003504, 0x2a003507).rw(m_timer[0], FUNC(upd800468_timer_device::rate_r), FUNC(upd800468_timer_device::rate_w)); + map(0x2a003508, 0x2a003508).rw(m_timer[0], FUNC(upd800468_timer_device::control_r), FUNC(upd800468_timer_device::control_w)).umask32(0x000000ff); + map(0x2a003514, 0x2a003517).rw(m_timer[1], FUNC(upd800468_timer_device::rate_r), FUNC(upd800468_timer_device::rate_w)); + map(0x2a003518, 0x2a003518).rw(m_timer[1], FUNC(upd800468_timer_device::control_r), FUNC(upd800468_timer_device::control_w)).umask32(0x000000ff); + map(0x2a003524, 0x2a003527).rw(m_timer[2], FUNC(upd800468_timer_device::rate_r), FUNC(upd800468_timer_device::rate_w)); + map(0x2a003528, 0x2a003528).rw(m_timer[2], FUNC(upd800468_timer_device::control_r), FUNC(upd800468_timer_device::control_w)).umask32(0x000000ff); + + map(0x2a003e00, 0x2a003e03).rw(FUNC(upd800468_device::ram_enable_r), FUNC(upd800468_device::ram_enable_w)); + + // keep whatever this is from spamming the error log for now + map(0x50000070, 0x50000077).noprw(); + + // TODO: USB controller at 0x50000400 + + map(0xfffff000, 0xffffffff).m(m_vic, FUNC(vic_upd800468_device::map)); +} + +upd800468_device::upd800468_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : arm7_cpu_device(mconfig, UPD800468, tag, owner, clock, 4, ARCHFLAG_T, ENDIANNESS_LITTLE) + , m_program_config("program", ENDIANNESS_LITTLE, 32, 32, 0, address_map_constructor(FUNC(upd800468_device::upd800468_map), this)) + , m_vic(*this, "vic") + , m_timer(*this, "timer%u", 0) + , m_kbd(*this, "kbd") + , m_adc_cb(*this, 0x00), m_in_cb(*this, 0x00), m_out_cb(*this) + , m_ram_view(*this, "ramview") +{ +} + +device_memory_interface::space_config_vector upd800468_device::memory_space_config() const +{ + return space_config_vector{ + std::make_pair(AS_PROGRAM, &m_program_config) + }; +} + +void upd800468_device::device_add_mconfig(machine_config &config) +{ + UPD800468_VIC(config, m_vic, 0); + m_vic->out_irq_cb().set_inputline(*this, ARM7_IRQ_LINE); + m_vic->out_fiq_cb().set_inputline(*this, ARM7_FIRQ_LINE); + + // this is probably not 100% accurate timing-wise + // for the ctk2100 it works ok for e.g. MIDI tempo and the auto power off interval + // it's unclear if there's supposed to be a register for setting a divider for each timer + UPD800468_TIMER(config, m_timer[0], clock() >> 3); + UPD800468_TIMER(config, m_timer[1], clock() >> 3); + UPD800468_TIMER(config, m_timer[2], clock() >> 3); + m_timer[0]->irq_cb().set(m_vic, FUNC(vic_upd800468_device::irq_w<21>)); + m_timer[1]->irq_cb().set(m_vic, FUNC(vic_upd800468_device::irq_w<22>)); + m_timer[2]->irq_cb().set(m_vic, FUNC(vic_upd800468_device::irq_w<23>)); + + // key/button controller is compatible with the one from earlier keyboards + GT913_KBD_HLE(config, m_kbd, 0); + m_kbd->irq_cb().set(m_vic, FUNC(vic_upd800468_device::irq_w<31>)); +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void upd800468_device::device_start() +{ + arm7_cpu_device::device_start(); + + save_item(NAME(m_port_data)); + save_item(NAME(m_port_ddr)); + save_item(NAME(m_ram_enable)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void upd800468_device::device_reset() +{ + arm7_cpu_device::device_reset(); + + for (offs_t i = 0; i < 4; i++) + { + m_port_data[i] = 0; + m_port_ddr[i] = 0xff; + port_update(i); + } + + m_ram_enable = 0; + m_ram_view.disable(); +} + +u16 upd800468_device::adc_r(offs_t num) +{ + // TODO: verify strange-seeming ADC behavior + // ctk2100 reads a 10-bit value, then inverts the highest bit, and seemingly treats the result as unsigned + return m_adc_cb[num]() ^ 0x200; +} + +u8 upd800468_device::port_ddr_r(offs_t num) +{ + return m_port_ddr[num]; +} + +void upd800468_device::port_ddr_w(offs_t num, u8 data) +{ + m_port_ddr[num] = data; +// logerror("port %u ddr_w: %02x\n", num, data); + port_update(num); +} + +u8 upd800468_device::port_r(offs_t num) +{ + // port input seemingly does not use the ddr value + // (ctk2100 port 2 ddr lower 4 bits are always high, but the corresponding data bits + // are apparently expected to be bidirectional, otherwise reading LCD status fails) + return m_in_cb[num](); +} + +void upd800468_device::port_w(offs_t num, u8 data) +{ + m_port_data[num] = data; + port_update(num); +} + +void upd800468_device::port_update(offs_t num) +{ +// logerror("port %u out: %02x\n", num, m_port_data[num] & m_port_ddr[num]); + m_out_cb[num](m_port_data[num] & m_port_ddr[num]); +} + +u32 upd800468_device::ram_enable_r() +{ + return m_ram_enable; +} + +void upd800468_device::ram_enable_w(u32 data) +{ + m_ram_enable = data; + + if (BIT(m_ram_enable, 0)) + m_ram_view.select(0); + else + m_ram_view.disable(); +} diff --git a/src/devices/cpu/arm7/upd800468.h b/src/devices/cpu/arm7/upd800468.h new file mode 100644 index 00000000000..c3d62ad6572 --- /dev/null +++ b/src/devices/cpu/arm7/upd800468.h @@ -0,0 +1,104 @@ +// license:BSD-3-Clause +// copyright-holders:Devin Acker + +#ifndef MAME_CPU_ARM7_UPD800468_H +#define MAME_CPU_ARM7_UPD800468_H + +#pragma once + +#include "arm7.h" + +#include "machine/gt913_kbd.h" +#include "machine/vic_pl192.h" + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +class upd800468_timer_device : public device_t +{ +public: + upd800468_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + auto irq_cb() { return m_irq_cb.bind(); } + + u32 rate_r(); + void rate_w(u32); + + u8 control_r(); + void control_w(u8); + +protected: + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + TIMER_CALLBACK_MEMBER(irq_timer_tick); + +private: + devcb_write_line m_irq_cb; + + emu_timer *m_timer; + u32 m_rate; + u8 m_control; +}; + +class upd800468_device : public arm7_cpu_device +{ +public: + upd800468_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); + + void upd800468_map(address_map &map) ATTR_COLD; + + template<offs_t i> auto adc_cb() { return m_adc_cb[i].bind(); } + + template<offs_t i> auto port_in_cb() { return m_in_cb[i].bind(); } + template<offs_t i> auto port_out_cb() { return m_out_cb[i].bind(); } + + template<offs_t i> u8 port_ddr_r() { return port_ddr_r(i); } + template<offs_t i> void port_ddr_w(u8 data) { port_ddr_w(i, data); } + + template<offs_t i> u8 port_r() { return port_r(i); } + template<offs_t i> void port_w(u8 data) { port_w(i, data); } + + u32 ram_enable_r(); + void ram_enable_w(u32 data); + +protected: + u16 adc_r(offs_t); + + u8 port_ddr_r(offs_t); + void port_ddr_w(offs_t, u8); + + u8 port_r(offs_t); + void port_w(offs_t, u8); + void port_update(offs_t); + + // device-level overrides + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + virtual space_config_vector memory_space_config() const override; + +private: + address_space_config m_program_config; + + required_device<vic_upd800468_device> m_vic; + required_device_array<upd800468_timer_device, 3> m_timer; + required_device<gt913_kbd_hle_device> m_kbd; + + devcb_read16::array<8> m_adc_cb; + devcb_read8::array<4> m_in_cb; + devcb_write8::array<4> m_out_cb; + u8 m_port_ddr[4], m_port_data[4]; + + memory_view m_ram_view; + u32 m_ram_enable; +}; + +// device type +DECLARE_DEVICE_TYPE(UPD800468_TIMER, upd800468_timer_device) +DECLARE_DEVICE_TYPE(UPD800468, upd800468_device) + +#endif // MAME_CPU_ARM7_UPD800468_H |