mirror of https://github.com/mgba-emu/mgba.git
ARM7: Decode MCR/MRC
This commit is contained in:
parent
2006f27d6d
commit
5939af0a2b
1
CHANGES
1
CHANGES
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue