ARM7: Decode MCR/MRC
@@ -45,6 +45,7 @@ - GB Memory: Fix HDMA5 value after DMA completes
- GB Video: Hblank IRQs should mask LYC=LY IRQs - GB Audio: Reset envelope timer when reseting sound channel - SDL: Prevent crash on cores with no audio + - ARM7: Decode MCR/MRC Misc: - SDL: Remove scancode key input - GBA Video: Clean up unused timers
@@ -355,11 +355,24 @@ // End branch definitions
// Begin coprocessor definitions -DEFINE_DECODER_ARM(CDP, ILL, info->operandFormat = ARM_OPERAND_NONE;) -DEFINE_DECODER_ARM(LDC, ILL, info->operandFormat = ARM_OPERAND_NONE;) -DEFINE_DECODER_ARM(STC, ILL, info->operandFormat = ARM_OPERAND_NONE;) -DEFINE_DECODER_ARM(MCR, ILL, info->operandFormat = ARM_OPERAND_NONE;) -DEFINE_DECODER_ARM(MRC, ILL, info->operandFormat = ARM_OPERAND_NONE;) +#define DEFINE_DECODER_COPROCESSOR(NAME, FORMAT) \ + DEFINE_DECODER_ARM(NAME, NAME, \ + info->cp.op1 = (opcode >> 21) & 7; \ + info->cp.op2 = (opcode >> 5) & 7; \ + info->op1.reg = (opcode >> 12) & 0xF; \ + info->cp.cp = (opcode >> 8) & 0xF; \ + info->op2.reg = (opcode >> 16) & 0xF; \ + info->op3.reg = opcode & 0xF; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 |\ + ARM_OPERAND_COPROCESSOR_REG_2 | \ + ARM_OPERAND_COPROCESSOR_REG_3 | \ + (FORMAT);) + +DEFINE_DECODER_ARM(CDP, CDP, info->operandFormat = ARM_OPERAND_NONE;) +DEFINE_DECODER_ARM(LDC, LDC, info->operandFormat = ARM_OPERAND_NONE;) +DEFINE_DECODER_ARM(STC, STC, info->operandFormat = ARM_OPERAND_NONE;) +DEFINE_DECODER_COPROCESSOR(MCR, ARM_OPERAND_AFFECTED_2 | ARM_OPERAND_AFFECTED_3) +DEFINE_DECODER_COPROCESSOR(MRC, ARM_OPERAND_AFFECTED_1) // Begin miscellaneous definitions
@@ -251,15 +251,19 @@ "bic",
"bkpt", "bl", "bx", + "cdp", "cmn", "cmp", "eor", + "ldc", "ldm", "ldr", "lsl", "lsr", + "mcr", "mla", "mov", + "mrc", "mrs", "msr", "mul",@@ -272,6 +276,7 @@ "rsc",
"sbc", "smlal", "smull", + "stc", "stm", "str", "sub",@@ -388,6 +393,10 @@ ADVANCE(written);
} break; default: + if (info->operandFormat & ARM_OPERAND_COPROCESSOR) { + written = snprintf(buffer, blen - 1, "p%i, %i, ", info->cp.cp, info->cp.op1); + ADVANCE(written); + } if (info->operandFormat & ARM_OPERAND_IMMEDIATE_1) { written = snprintf(buffer, blen - 1, "#%i", info->op1.immediate); ADVANCE(written);@@ -401,6 +410,8 @@ if (info->op1.reg > ARM_PC) {
written = _decodePSR(info->op1.psrBits, buffer, blen); ADVANCE(written); } + } else if (info->operandFormat & ARM_OPERAND_COPROCESSOR_REG_1) { + written = snprintf(buffer, blen - 1, "c%i", info->op1.reg); } if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_1) { written = _decodeShift(info->op1, true, buffer, blen);@@ -422,6 +433,9 @@ ADVANCE(written);
} else if (info->operandFormat & ARM_OPERAND_REGISTER_2) { written = _decodeRegister(info->op2.reg, buffer, blen); ADVANCE(written); + } else if (info->operandFormat & ARM_OPERAND_COPROCESSOR_REG_2) { + written = snprintf(buffer, blen - 1, "c%i", info->op2.reg); + ADVANCE(written); } if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_2) { written = _decodeShift(info->op2, true, buffer, blen);@@ -443,6 +457,9 @@ ADVANCE(written);
} else if (info->operandFormat & ARM_OPERAND_REGISTER_3) { written = _decodeRegister(info->op3.reg, buffer, blen); ADVANCE(written); + } else if (info->operandFormat & ARM_OPERAND_COPROCESSOR_REG_3) { + written = snprintf(buffer, blen - 1, "c%i", info->op3.reg); + ADVANCE(written); } if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_3) { written = _decodeShift(info->op3, true, buffer, blen);@@ -464,12 +481,19 @@ ADVANCE(written);
} else if (info->operandFormat & ARM_OPERAND_REGISTER_4) { written = _decodeRegister(info->op4.reg, buffer, blen); ADVANCE(written); + } else if (info->operandFormat & ARM_OPERAND_COPROCESSOR_REG_4) { + written = snprintf(buffer, blen - 1, "c%i", info->op4.reg); + ADVANCE(written); } if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_4) { written = _decodeShift(info->op4, true, buffer, blen); ADVANCE(written); } else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_4) { written = _decodeShift(info->op4, false, buffer, blen); + ADVANCE(written); + } + if (info->cp.op2) { + written = snprintf(buffer, blen - 1, ", %i", info->cp.op2); ADVANCE(written); } break;
@@ -14,6 +14,7 @@ // Bit 2: a memory access is invovled with this operand
// Bit 3: the destination of this operand is affected by this opcode // Bit 4: this operand is shifted by a register // Bit 5: this operand is shifted by an immediate +// Bit 6: a coprocessor register is involved with this command #define ARM_OPERAND_NONE 0x00000000 #define ARM_OPERAND_REGISTER_1 0x00000001 #define ARM_OPERAND_IMMEDIATE_1 0x00000002@@ -21,6 +22,7 @@ #define ARM_OPERAND_MEMORY_1 0x00000004
#define ARM_OPERAND_AFFECTED_1 0x00000008 #define ARM_OPERAND_SHIFT_REGISTER_1 0x00000010 #define ARM_OPERAND_SHIFT_IMMEDIATE_1 0x00000020 +#define ARM_OPERAND_COPROCESSOR_REG_1 0x00000040 #define ARM_OPERAND_1 0x000000FF #define ARM_OPERAND_REGISTER_2 0x00000100@@ -29,6 +31,7 @@ #define ARM_OPERAND_MEMORY_2 0x00000400
#define ARM_OPERAND_AFFECTED_2 0x00000800 #define ARM_OPERAND_SHIFT_REGISTER_2 0x00001000 #define ARM_OPERAND_SHIFT_IMMEDIATE_2 0x00002000 +#define ARM_OPERAND_COPROCESSOR_REG_2 0x00004000 #define ARM_OPERAND_2 0x0000FF00 #define ARM_OPERAND_REGISTER_3 0x00010000@@ -37,6 +40,7 @@ #define ARM_OPERAND_MEMORY_3 0x00040000
#define ARM_OPERAND_AFFECTED_3 0x00080000 #define ARM_OPERAND_SHIFT_REGISTER_3 0x00100000 #define ARM_OPERAND_SHIFT_IMMEDIATE_3 0x00200000 +#define ARM_OPERAND_COPROCESSOR_REG_3 0x00400000 #define ARM_OPERAND_3 0x00FF0000 #define ARM_OPERAND_REGISTER_4 0x01000000@@ -45,9 +49,11 @@ #define ARM_OPERAND_MEMORY_4 0x04000000
#define ARM_OPERAND_AFFECTED_4 0x08000000 #define ARM_OPERAND_SHIFT_REGISTER_4 0x10000000 #define ARM_OPERAND_SHIFT_IMMEDIATE_4 0x20000000 +#define ARM_OPERAND_COPROCESSOR_REG_4 0x40000000 #define ARM_OPERAND_4 0xFF000000 #define ARM_OPERAND_MEMORY (ARM_OPERAND_MEMORY_1 | ARM_OPERAND_MEMORY_2 | ARM_OPERAND_MEMORY_3 | ARM_OPERAND_MEMORY_4) +#define ARM_OPERAND_COPROCESSOR (ARM_OPERAND_COPROCESSOR_REG_1 | ARM_OPERAND_COPROCESSOR_REG_2 | ARM_OPERAND_COPROCESSOR_REG_3 | ARM_OPERAND_COPROCESSOR_REG_4) #define ARM_MEMORY_REGISTER_BASE 0x0001 #define ARM_MEMORY_IMMEDIATE_OFFSET 0x0002@@ -112,6 +118,12 @@ };
int32_t immediate; }; +struct ARMCoprocessor { + uint8_t cp : 4; + uint8_t op1 : 4; + uint8_t op2 : 3; +}; + enum ARMMemoryAccessType { ARM_ACCESS_WORD = 4, ARM_ACCESS_HALFWORD = 2,@@ -147,15 +159,19 @@ ARM_MN_BIC,
ARM_MN_BKPT, ARM_MN_BL, ARM_MN_BX, + ARM_MN_CDP, ARM_MN_CMN, ARM_MN_CMP, ARM_MN_EOR, + ARM_MN_LDC, ARM_MN_LDM, ARM_MN_LDR, ARM_MN_LSL, ARM_MN_LSR, + ARM_MN_MCR, ARM_MN_MLA, ARM_MN_MOV, + ARM_MN_MRC, ARM_MN_MRS, ARM_MN_MSR, ARM_MN_MUL,@@ -168,6 +184,7 @@ ARM_MN_RSC,
ARM_MN_SBC, ARM_MN_SMLAL, ARM_MN_SMULL, + ARM_MN_STC, ARM_MN_STM, ARM_MN_STR, ARM_MN_SUB,@@ -206,6 +223,7 @@ unsigned sInstructionCycles : 4;
unsigned nInstructionCycles : 4; unsigned sDataCycles : 10; unsigned nDataCycles : 10; + struct ARMCoprocessor cp; }; void ARMDecodeARM(uint32_t opcode, struct ARMInstructionInfo* info);
@@ -67,8 +67,10 @@ #define DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, NAME, P, U, N, W) \
DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME)), \ DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME)) -#define DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, NAME1, NAME2) \ - DO_8(DO_8(DO_INTERLACE(DECLARE_INSTRUCTION_ARM(EMITTER, NAME1), DECLARE_INSTRUCTION_ARM(EMITTER, NAME2)))) +#define DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, NAME1, NAME2, NAME3) \ + DO_8(DO_INTERLACE( \ + DO_8(DO_INTERLACE(DECLARE_INSTRUCTION_ARM(EMITTER, NAME1), DECLARE_INSTRUCTION_ARM(EMITTER, NAME2))), \ + DO_8(DO_INTERLACE(DECLARE_INSTRUCTION_ARM(EMITTER, NAME1), DECLARE_INSTRUCTION_ARM(EMITTER, NAME3))))) #define DECLARE_ARM_SWI_BLOCK(EMITTER) \ DO_256(DECLARE_INSTRUCTION_ARM(EMITTER, SWI))@@ -328,8 +330,7 @@ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, ), \
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, ), \ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, W), \ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, W), \ - DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, CDP, MCR), \ - DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, CDP, MRC), \ + DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, CDP, MCR, MRC), \ DECLARE_ARM_SWI_BLOCK(EMITTER) #endif