all repos — mgba @ 64cc5ada8684b93a0e1835c8e63d0a018aa430d5

mGBA Game Boy Advance Emulator

Merge Thumb mnemonics into ARM mnemonics in preparation for ARM decoder
Jeffrey Pfau jeffrey@endrift.com
Thu, 10 Jul 2014 03:30:59 -0700
commit

64cc5ada8684b93a0e1835c8e63d0a018aa430d5

parent

a22c89fedbf6f7d66b2ddd2d3963b5ead6c9cfcd

2 files changed, 131 insertions(+), 91 deletions(-)

jump to
M src/arm/decoder-thumb.csrc/arm/decoder-thumb.c

@@ -9,9 +9,9 @@ #include <stdio.h>

#include <string.h> #define DEFINE_THUMB_DECODER(NAME, MNEMONIC, BODY) \ - static void _ThumbDecode ## NAME (uint16_t opcode, struct ThumbInstructionInfo* info) { \ + static void _ThumbDecode ## NAME (uint16_t opcode, struct ARMInstructionInfo* info) { \ UNUSED(opcode); \ - info->mnemonic = THUMB_MN_ ## MNEMONIC; \ + info->mnemonic = ARM_MN_ ## MNEMONIC; \ BODY; \ }

@@ -31,6 +31,7 @@ DEFINE_THUMB_DECODER(NAME, MNEMONIC, \

info->op1.reg = opcode & 0x0007; \ info->memory.baseReg = (opcode >> 3) & 0x0007; \ info->memory.offset.immediate = IMMEDIATE * WIDTH; \ + info->memory.width = (enum ARMMemoryAccessType) WIDTH; \ info->operandFormat = ARM_OPERAND_REGISTER_1 | \ ARM_OPERAND_AFFECTED_1 | \ ARM_OPERAND_MEMORY_2; \

@@ -51,11 +52,11 @@ DEFINE_IMMEDIATE_5_DECODER_THUMB(LSL1, LSL, DATA,)

DEFINE_IMMEDIATE_5_DECODER_THUMB(LSR1, LSR, DATA,) DEFINE_IMMEDIATE_5_DECODER_THUMB(ASR1, ASR, DATA,) DEFINE_IMMEDIATE_5_DECODER_THUMB(LDR1, LDR, MEM_LOAD, 4) -DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRB1, LDRB, MEM_LOAD, 1) -DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRH1, LDRH, MEM_LOAD, 2) +DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRB1, LDR, MEM_LOAD, 1) +DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRH1, LDR, MEM_LOAD, 2) DEFINE_IMMEDIATE_5_DECODER_THUMB(STR1, STR, MEM_STORE, 4) -DEFINE_IMMEDIATE_5_DECODER_THUMB(STRB1, STRB, MEM_STORE, 1) -DEFINE_IMMEDIATE_5_DECODER_THUMB(STRH1, STRH, MEM_STORE, 2) +DEFINE_IMMEDIATE_5_DECODER_THUMB(STRB1, STR, MEM_STORE, 1) +DEFINE_IMMEDIATE_5_DECODER_THUMB(STRH1, STR, MEM_STORE, 2) #define DEFINE_DATA_FORM_1_DECODER_EX_THUMB(NAME, RM, MNEMONIC) \ DEFINE_THUMB_DECODER(NAME, MNEMONIC, \

@@ -170,6 +171,7 @@ DEFINE_THUMB_DECODER(NAME, MNEMONIC, \

info->op1.reg = RD; \ info->memory.baseReg = REG; \ info->memory.offset.immediate = (opcode & 0x00FF) << 2; \ + info->memory.width = ARM_ACCESS_WORD; \ info->operandFormat = ARM_OPERAND_REGISTER_1 | \ ARM_OPERAND_AFFECTED_1 | \ ARM_OPERAND_MEMORY_2; \

@@ -193,11 +195,12 @@

DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD5, ADD, DATA, ARM_PC) DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD6, ADD, DATA, ARM_SP) -#define DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB(NAME, RM, MNEMONIC, CYCLES) \ +#define DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB(NAME, RM, MNEMONIC, CYCLES, TYPE) \ DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ info->memory.offset.reg = RM; \ info->op1.reg = opcode & 0x0007; \ info->memory.baseReg = (opcode >> 3) & 0x0007; \ + info->memory.width = TYPE; \ info->operandFormat = ARM_OPERAND_REGISTER_1 | \ ARM_OPERAND_AFFECTED_1 | \ ARM_OPERAND_MEMORY_2; \

@@ -205,32 +208,33 @@ info->memory.format = ARM_MEMORY_REGISTER_BASE | \

ARM_MEMORY_REGISTER_OFFSET; \ CYCLES;) -#define DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(NAME, MNEMONIC, CYCLES) \ - COUNT_3(DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB, NAME ## _R, MNEMONIC, CYCLES) +#define DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(NAME, MNEMONIC, CYCLES, TYPE) \ + COUNT_3(DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB, NAME ## _R, MNEMONIC, CYCLES, TYPE) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDR2, LDR, LOAD_CYCLES) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRB2, LDRB, LOAD_CYCLES) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRH2, LDRH, LOAD_CYCLES) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSB, LDRSB, LOAD_CYCLES) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSH, LDRSH, LOAD_CYCLES) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, STR, STORE_CYCLES) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, STRB, STORE_CYCLES) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, STRH, STORE_CYCLES) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDR2, LDR, LOAD_CYCLES, ARM_ACCESS_WORD) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRB2, LDR, LOAD_CYCLES, ARM_ACCESS_BYTE) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRH2, LDR, LOAD_CYCLES, ARM_ACCESS_HALFWORD) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSB, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_BYTE) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSH, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_HALFWORD) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, STR, STORE_CYCLES, ARM_ACCESS_WORD) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, STR, STORE_CYCLES, ARM_ACCESS_BYTE) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, STR, STORE_CYCLES, ARM_ACCESS_HALFWORD) -#define DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME, RN, MNEMONIC, SPECIAL_REG, ADDITIONAL_REG) \ +#define DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME, RN, MNEMONIC, DIRECTION, ADDITIONAL_REG) \ DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ info->memory.baseReg = RN; \ info->op1.immediate = (opcode & 0xFF) | ADDITIONAL_REG; \ info->branches = info->op1.immediate & (1 << ARM_PC); \ info->operandFormat = ARM_OPERAND_MEMORY_1; \ + info->memory.direction = DIRECTION; \ info->memory.format = ARM_MEMORY_REGISTER_BASE | \ ARM_MEMORY_POST_INCREMENT;) #define DEFINE_LOAD_STORE_MULTIPLE_THUMB(NAME) \ - COUNT_3(DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB, NAME ## _R, NAME, 0, 0) + COUNT_3(DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB, NAME ## IA_R, NAME, ARM_INCREMENT_AFTER, 0) -DEFINE_LOAD_STORE_MULTIPLE_THUMB(LDMIA) -DEFINE_LOAD_STORE_MULTIPLE_THUMB(STMIA) +DEFINE_LOAD_STORE_MULTIPLE_THUMB(LDM) +DEFINE_LOAD_STORE_MULTIPLE_THUMB(STM) #define DEFINE_CONDITIONAL_BRANCH_THUMB(COND) \ DEFINE_THUMB_DECODER(B ## COND, B, \

@@ -266,10 +270,10 @@

DEFINE_SP_MODIFY_THUMB(ADD7, ADD) DEFINE_SP_MODIFY_THUMB(SUB4, SUB) -DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POP, ARM_SP, POP, 1, 0) -DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPR, ARM_SP, POP, 1, 1 << ARM_PC) -DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSH, ARM_SP, PUSH, 1, 0) -DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSHR, ARM_SP, PUSH, 1, 1 << ARM_LR) +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POP, ARM_SP, LDM, ARM_INCREMENT_AFTER, 0) +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPR, ARM_SP, LDM, ARM_INCREMENT_AFTER, 1 << ARM_PC) +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSH, ARM_SP, STM, ARM_DECREMENT_BEFORE, 0) +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSHR, ARM_SP, STM, ARM_DECREMENT_BEFORE, 1 << ARM_LR) DEFINE_THUMB_DECODER(ILL, ILL, info->traps = 1;) DEFINE_THUMB_DECODER(BKPT, BKPT, info->traps = 1;)

@@ -300,13 +304,13 @@ info->op1.immediate = opcode & 0xFF;

info->operandFormat = ARM_OPERAND_IMMEDIATE_1; info->traps = 1;) -typedef void (*ThumbDecoder)(uint16_t opcode, struct ThumbInstructionInfo* info); +typedef void (*ThumbDecoder)(uint16_t opcode, struct ARMInstructionInfo* info); static const ThumbDecoder _thumbDecoderTable[0x400] = { DECLARE_THUMB_EMITTER_BLOCK(_ThumbDecode) }; -void ARMDecodeThumb(uint16_t opcode, struct ThumbInstructionInfo* info) { +void ARMDecodeThumb(uint16_t opcode, struct ARMInstructionInfo* info) { info->opcode = opcode; info->branches = 0; info->traps = 0;

@@ -322,7 +326,7 @@ ThumbDecoder decoder = _thumbDecoderTable[opcode >> 6];

decoder(opcode, info); } -const char* thumbMnemonicStrings[] = { +const char* armMnemonicStrings[] = { "ill", "adc", "add",

@@ -337,12 +341,8 @@ "bx",

"cmn", "cmp", "eor", - "ldmia", + "ldm", "ldr", - "ldrb", - "ldrh", - "ldrsb", - "ldrsh", "lsl", "lsr", "mov",

@@ -350,46 +350,75 @@ "mul",

"mvn", "neg", "orr", - "pop", - "push", "ror", "sbc", - "stmia", + "stm", "str", - "strb", - "strh", "sub", "swi", "tst" }; +const char* armDirectionStrings[] = { + "da", + "ia", + "db", + "da" +}; + +const char* armAccessTypeStrings[] = { + "", + "b", + "h", + "", + "", + "", + "", + "", + "", + "sb", + "sh", + "" + "" +}; + int ARMDisassembleThumb(uint16_t opcode, uint32_t pc, char* buffer, int blen) { - struct ThumbInstructionInfo info; + struct ARMInstructionInfo info; ARMDecodeThumb(opcode, &info); - const char* mnemonic = thumbMnemonicStrings[info.mnemonic]; + const char* mnemonic = armMnemonicStrings[info.mnemonic]; int written; int total = 0; const char* cond = ""; if (info.condition != ARM_CONDITION_AL && info.condition < ARM_CONDITION_NV) { cond = _armConditions[info.condition]; } - written = snprintf(buffer, blen, "%s%s ", mnemonic, cond); + const char* flags = ""; + switch (info.mnemonic) { + case ARM_MN_LDM: + case ARM_MN_STM: + flags = armDirectionStrings[info.memory.direction]; + break; + case ARM_MN_LDR: + case ARM_MN_STR: + flags = armAccessTypeStrings[info.memory.direction]; + break; + default: + break; + } + written = snprintf(buffer, blen - 1, "%s%s%s ", mnemonic, flags, cond); ADVANCE(written); switch (info.mnemonic) { - case THUMB_MN_LDMIA: - case THUMB_MN_STMIA: + case ARM_MN_LDM: + case ARM_MN_STM: written = _decodeRegister(info.memory.baseReg, buffer, blen); ADVANCE(written); strncpy(buffer, "!, ", blen); ADVANCE(3); - // Fall through - case THUMB_MN_POP: - case THUMB_MN_PUSH: written = _decodeRegisterList(info.op1.immediate, buffer, blen); ADVANCE(written); break; - case THUMB_MN_B: + case ARM_MN_B: written = _decodePCRelative(info.op1.immediate, pc, buffer, blen); ADVANCE(written); break;
M src/arm/decoder.hsrc/arm/decoder.h

@@ -77,58 +77,69 @@ };

int32_t immediate; }; +enum ARMMultipleDirection { + ARM_DECREMENT_AFTER = 0, + ARM_INCREMENT_AFTER = 1, + ARM_DECREMENT_BEFORE = 2, + ARM_INCREMENT_BEFORE = 3, +}; + +enum ARMMemoryAccessType { + ARM_ACCESS_WORD = 4, + ARM_ACCESS_HALFWORD = 2, + ARM_ACCESS_SIGNED_HALFWORD = 10, + ARM_ACCESS_BYTE = 1, + ARM_ACCESS_SIGNED_BYTE = 9 +}; + struct ARMMemoryAccess { uint8_t baseReg; uint16_t format; union ARMOperand offset; + union { + enum ARMMultipleDirection direction; + enum ARMMemoryAccessType width; + }; }; -enum ThumbMnemonic { - THUMB_MN_ILL = 0, - THUMB_MN_ADC, - THUMB_MN_ADD, - THUMB_MN_AND, - THUMB_MN_ASR, - THUMB_MN_B, - THUMB_MN_BIC, - THUMB_MN_BKPT, - THUMB_MN_BL, - THUMB_MN_BLH, - THUMB_MN_BX, - THUMB_MN_CMN, - THUMB_MN_CMP, - THUMB_MN_EOR, - THUMB_MN_LDMIA, - THUMB_MN_LDR, - THUMB_MN_LDRB, - THUMB_MN_LDRH, - THUMB_MN_LDRSB, - THUMB_MN_LDRSH, - THUMB_MN_LSL, - THUMB_MN_LSR, - THUMB_MN_MOV, - THUMB_MN_MUL, - THUMB_MN_MVN, - THUMB_MN_NEG, - THUMB_MN_ORR, - THUMB_MN_POP, - THUMB_MN_PUSH, - THUMB_MN_ROR, - THUMB_MN_SBC, - THUMB_MN_STMIA, - THUMB_MN_STR, - THUMB_MN_STRB, - THUMB_MN_STRH, - THUMB_MN_SUB, - THUMB_MN_SWI, - THUMB_MN_TST, +enum ARMMnemonic { + ARM_MN_ILL = 0, + ARM_MN_ADC, + ARM_MN_ADD, + ARM_MN_AND, + ARM_MN_ASR, + ARM_MN_B, + ARM_MN_BIC, + ARM_MN_BKPT, + ARM_MN_BL, + ARM_MN_BLH, + ARM_MN_BX, + ARM_MN_CMN, + ARM_MN_CMP, + ARM_MN_EOR, + ARM_MN_LDM, + ARM_MN_LDR, + ARM_MN_LSL, + ARM_MN_LSR, + ARM_MN_MOV, + ARM_MN_MUL, + ARM_MN_MVN, + ARM_MN_NEG, + ARM_MN_ORR, + ARM_MN_ROR, + ARM_MN_SBC, + ARM_MN_STM, + ARM_MN_STR, + ARM_MN_SUB, + ARM_MN_SWI, + ARM_MN_TST, - THUMB_MN_MAX + ARM_MN_MAX }; -struct ThumbInstructionInfo { - uint16_t opcode; - enum ThumbMnemonic mnemonic; +struct ARMInstructionInfo { + uint32_t opcode; + enum ARMMnemonic mnemonic; union ARMOperand op1; union ARMOperand op2; union ARMOperand op3;

@@ -146,7 +157,7 @@ int iCycles;

int cCycles; }; -void ARMDecodeThumb(uint16_t opcode, struct ThumbInstructionInfo* info); +void ARMDecodeThumb(uint16_t opcode, struct ARMInstructionInfo* info); int ARMDisassembleThumb(uint16_t opcode, uint32_t pc, char* buffer, int blen); #endif