summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/arm7
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/arm7')
-rw-r--r--src/devices/cpu/arm7/ap2010cpu.cpp45
-rw-r--r--src/devices/cpu/arm7/ap2010cpu.h35
-rw-r--r--src/devices/cpu/arm7/arm7.cpp1274
-rw-r--r--src/devices/cpu/arm7/arm7.h282
-rw-r--r--src/devices/cpu/arm7/arm7core.h129
-rw-r--r--src/devices/cpu/arm7/arm7core.hxx14
-rw-r--r--src/devices/cpu/arm7/arm7dasm.cpp1728
-rw-r--r--src/devices/cpu/arm7/arm7dasm.h9
-rw-r--r--src/devices/cpu/arm7/arm7drc.hxx102
-rw-r--r--src/devices/cpu/arm7/arm7fe.hxx2
-rw-r--r--src/devices/cpu/arm7/arm7help.h11
-rw-r--r--src/devices/cpu/arm7/arm7ops.cpp309
-rw-r--r--src/devices/cpu/arm7/arm7thmb.cpp49
-rw-r--r--src/devices/cpu/arm7/cecalls.hxx1066
-rw-r--r--src/devices/cpu/arm7/lpc210x.cpp66
-rw-r--r--src/devices/cpu/arm7/lpc210x.h66
-rw-r--r--src/devices/cpu/arm7/upd800468.cpp249
-rw-r--r--src/devices/cpu/arm7/upd800468.h104
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> &params)
+{
+ translate_command(params, TR_FETCH);
+}
+
+void arm7_cpu_device::translate_data_command(const std::vector<std::string_view> &params)
+{
+ translate_command(params, TR_READ);
}
+void arm7_cpu_device::translate_command(const std::vector<std::string_view> &params, 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> &params);
+ void translate_data_command(const std::vector<std::string_view> &params);
+ void translate_command(const std::vector<std::string_view> &params, 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