ARM7: Decode MCR/MRC

This commit is contained in:
Jeffrey Pfau 2016-06-01 21:30:36 -07:00
parent 2006f27d6d
commit 5939af0a2b
5 changed files with 66 additions and 9 deletions

View File

@ -45,6 +45,7 @@ Bugfixes:
- 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

View File

@ -355,11 +355,24 @@ DEFINE_DECODER_ARM(BX, BX,
// 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

View File

@ -251,15 +251,19 @@ static const char* _armMnemonicStrings[] = {
"bkpt",
"bl",
"bx",
"cdp",
"cmn",
"cmp",
"eor",
"ldc",
"ldm",
"ldr",
"lsl",
"lsr",
"mcr",
"mla",
"mov",
"mrc",
"mrs",
"msr",
"mul",
@ -272,6 +276,7 @@ static const char* _armMnemonicStrings[] = {
"sbc",
"smlal",
"smull",
"stc",
"stm",
"str",
"sub",
@ -388,6 +393,10 @@ int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, i
}
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 @@ int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, i
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 @@ int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, i
} 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 @@ int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, i
} 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,6 +481,9 @@ int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, i
} 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);
@ -472,6 +492,10 @@ int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, i
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;
}
buffer[blen - 1] = '\0';

View File

@ -14,6 +14,7 @@
// 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_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_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_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_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 @@ union ARMOperand {
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 @@ enum ARMMnemonic {
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 @@ enum ARMMnemonic {
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 @@ struct ARMInstructionInfo {
unsigned nInstructionCycles : 4;
unsigned sDataCycles : 10;
unsigned nDataCycles : 10;
struct ARMCoprocessor cp;
};
void ARMDecodeARM(uint32_t opcode, struct ARMInstructionInfo* info);

View File

@ -67,8 +67,10 @@
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, 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