Descriptions of all opcodes
Jeffrey Pfau jeffrey@endrift.com
Fri, 01 Nov 2013 00:47:12 -0700
2 files changed,
352 insertions(+),
18 deletions(-)
M
src/arm/decompiler.c
→
src/arm/decompiler.c
@@ -1,6 +1,303 @@
#include "decompiler.h" +#include "arm.h" +#include "emitter-thumb.h" +#include "isa-inlines.h" + +#define DEFINE_THUMB_DECODER(NAME, MNEMONIC, BODY) \ + static void _ThumbDecode ## NAME (uint16_t opcode, struct ThumbInstructionInfo* info) { \ + UNUSED(opcode); \ + info->mnemonic = THUMB_MN_ ## MNEMONIC; \ + BODY; \ + } + +#define DEFINE_IMMEDIATE_5_DECODER_DATA_THUMB(NAME, IMMEDIATE, MNEMONIC) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op3.immediate = IMMEDIATE; \ + info->op1.reg = opcode & 0x0007; \ + info->op2.reg = (opcode >> 3) & 0x0007; \ + info->affectsCPSR = 1; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + ARM_OPERAND_AFFECTED_1 | \ + ARM_OPERAND_REGISTER_2 | \ + ARM_OPERAND_IMMEDIATE_3;) + +#define DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, IMMEDIATE, MNEMONIC) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = opcode & 0x0007; \ + info->memory.baseReg = (opcode >> 3) & 0x0007; \ + info->memory.offset.shifterReg = IMMEDIATE << 2; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + ARM_OPERAND_AFFECTED_1 | \ + ARM_OPERAND_MEMORY_2; \ + info->memory.format = ARM_MEMORY_REGISTER_BASE | \ + ARM_MEMORY_IMMEDIATE_OFFSET;) + +#define DEFINE_IMMEDIATE_5_DECODER_THUMB(NAME, MNEMONIC, TYPE) \ + COUNT_5(DEFINE_IMMEDIATE_5_DECODER_ ## TYPE ## _THUMB, NAME ## _, MNEMONIC) + +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) +DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRB1, LDRB, MEM) +DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRH1, LDRH, MEM) +DEFINE_IMMEDIATE_5_DECODER_THUMB(STR1, STR, MEM) +DEFINE_IMMEDIATE_5_DECODER_THUMB(STRB1, STRB, MEM) +DEFINE_IMMEDIATE_5_DECODER_THUMB(STRH1, STRH, MEM) + +#define DEFINE_DATA_FORM_1_DECODER_EX_THUMB(NAME, RM, MNEMONIC) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = opcode & 0x0007; \ + info->op2.reg = (opcode >> 3) & 0x0007; \ + info->op3.reg = RM; \ + info->affectsCPSR = 1; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + ARM_OPERAND_AFFECTED_1 | \ + ARM_OPERAND_REGISTER_2 | \ + ARM_OPERAND_REGISTER_3;) + +#define DEFINE_DATA_FORM_1_DECODER_THUMB(NAME) \ + COUNT_3(DEFINE_DATA_FORM_1_DECODER_EX_THUMB, NAME ## 3_R, NAME) + +DEFINE_DATA_FORM_1_DECODER_THUMB(ADD) +DEFINE_DATA_FORM_1_DECODER_THUMB(SUB) + +#define DEFINE_DATA_FORM_2_DECODER_EX_THUMB(NAME, IMMEDIATE, MNEMONIC) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = opcode & 0x0007; \ + info->op2.reg = (opcode >> 3) & 0x0007; \ + info->op3.immediate = IMMEDIATE; \ + info->affectsCPSR = 1; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + ARM_OPERAND_AFFECTED_1 | \ + ARM_OPERAND_REGISTER_2 | \ + ARM_OPERAND_IMMEDIATE_3;) + +#define DEFINE_DATA_FORM_2_DECODER_THUMB(NAME) \ + COUNT_3(DEFINE_DATA_FORM_2_DECODER_EX_THUMB, NAME ## 1_, NAME) + +DEFINE_DATA_FORM_2_DECODER_THUMB(ADD) +DEFINE_DATA_FORM_2_DECODER_THUMB(SUB) + +#define DEFINE_DATA_FORM_3_DECODER_EX_THUMB(NAME, RD, MNEMONIC, AFFECTED) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = RD; \ + info->op2.immediate = opcode & 0x00FF; \ + info->affectsCPSR = 1; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + AFFECTED | \ + ARM_OPERAND_IMMEDIATE_2;) + +#define DEFINE_DATA_FORM_3_DECODER_THUMB(NAME, MNEMONIC, AFFECTED) \ + COUNT_3(DEFINE_DATA_FORM_3_DECODER_EX_THUMB, NAME ## _R, MNEMONIC, AFFECTED) + +DEFINE_DATA_FORM_3_DECODER_THUMB(ADD2, ADD, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_3_DECODER_THUMB(CMP1, CMP, ARM_OPERAND_NONE) +DEFINE_DATA_FORM_3_DECODER_THUMB(MOV1, MOV, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_3_DECODER_THUMB(SUB2, SUB, ARM_OPERAND_AFFECTED_1) + +#define DEFINE_DATA_FORM_5_DECODER_THUMB(NAME, MNEMONIC, AFFECTED) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = opcode & 0x0007; \ + info->op2.reg = (opcode >> 3) & 0x0007; \ + info->affectsCPSR = 1; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + AFFECTED | \ + ARM_OPERAND_REGISTER_2;) + +DEFINE_DATA_FORM_5_DECODER_THUMB(AND, AND, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(EOR, EOR, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(LSL2, LSL, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(LSR2, LSR, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(ASR2, ASR, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(ADC, ADC, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(SBC, SBC, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(ROR, ROR, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(TST, TST, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(NEG, NEG, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(CMP2, CMP, ARM_OPERAND_NONE) +DEFINE_DATA_FORM_5_DECODER_THUMB(CMN, CMN, ARM_OPERAND_NONE) +DEFINE_DATA_FORM_5_DECODER_THUMB(ORR, ORR, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(MUL, MUL, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(BIC, BIC, ARM_OPERAND_AFFECTED_1) +DEFINE_DATA_FORM_5_DECODER_THUMB(MVN, MVN, ARM_OPERAND_AFFECTED_1) + +#define DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME, H1, H2, MNEMONIC, AFFECTED, CPSR) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = (opcode & 0x0007) | H1; \ + info->op2.reg = ((opcode >> 3) & 0x0007) | H2; \ + info->accessesSpecialRegisters = info->op1.reg > 12 || info->op2.reg > 12; \ + info->affectsCPSR = CPSR; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + AFFECTED | \ + ARM_OPERAND_REGISTER_2;) + + +#define DEFINE_DECODER_WITH_HIGH_THUMB(NAME, MNEMONIC, AFFECTED, CPSR) \ + DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 00, 0, 0, MNEMONIC, AFFECTED, CPSR) \ + DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 01, 0, 8, MNEMONIC, AFFECTED, CPSR) \ + DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 10, 8, 0, MNEMONIC, AFFECTED, CPSR) \ + DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 11, 8, 8, MNEMONIC, AFFECTED, CPSR) + +DEFINE_DECODER_WITH_HIGH_THUMB(ADD4, ADD, ARM_OPERAND_AFFECTED_1, 0) +DEFINE_DECODER_WITH_HIGH_THUMB(CMP3, CMP, ARM_OPERAND_NONE, 1) +DEFINE_DECODER_WITH_HIGH_THUMB(MOV3, MOV, ARM_OPERAND_AFFECTED_1, 0) + +#define DEFINE_IMMEDIATE_WITH_REGISTER_DATA_THUMB(NAME, RD, MNEMONIC, REG) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = RD; \ + info->op2.reg = REG; \ + info->op3.immediate = (opcode & 0x00FF) << 2; \ + info->accessesSpecialRegisters = 1; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + ARM_OPERAND_AFFECTED_1 | \ + ARM_OPERAND_REGISTER_2 | \ + ARM_OPERAND_IMMEDIATE_3;) + +#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = RD; \ + info->memory.baseReg = REG; \ + info->memory.offset.immediate = (opcode & 0x00FF) << 2; \ + info->accessesSpecialRegisters = 1; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + ARM_OPERAND_AFFECTED_1 | \ + ARM_OPERAND_MEMORY_2; \ + info->memory.format = ARM_MEMORY_REGISTER_BASE | \ + ARM_MEMORY_IMMEDIATE_OFFSET;) + +#define DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(NAME, MNEMONIC, TYPE, REG) \ + COUNT_3(DEFINE_IMMEDIATE_WITH_REGISTER_ ## TYPE ## _THUMB, NAME ## _R, MNEMONIC, REG) + +DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR3, LDR, MEM, ARM_PC) +DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR4, LDR, MEM, ARM_SP) +DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(STR3, STR, MEM, ARM_SP) + +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) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->memory.offset.reg = RM; \ + info->op1.reg = opcode & 0x0007; \ + info->memory.baseReg = (opcode >> 3) & 0x0007; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + ARM_OPERAND_AFFECTED_1 | \ + ARM_OPERAND_MEMORY_2; \ + info->memory.format = ARM_MEMORY_REGISTER_BASE | \ + ARM_MEMORY_REGISTER_OFFSET;) + +#define DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(NAME, MNEMONIC) \ + COUNT_3(DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB, NAME ## _R, MNEMONIC) + +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDR2, LDR) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRB2, LDRB) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRH2, LDRH) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSB, LDRSB) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSH, LDRSH) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, STR) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, STRB) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, STRH) + +#define DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME, RN, MNEMONIC, SPECIAL_REG) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->memory.baseReg = RN; \ + info->accessesSpecialRegisters = SPECIAL_REG; \ + info->op1.immediate = opcode & 0xFF; \ + info->operandFormat = ARM_OPERAND_IMMEDIATE_1 | \ + ARM_OPERAND_AFFECTED_1; \ + 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) + +DEFINE_LOAD_STORE_MULTIPLE_THUMB(LDMIA) +DEFINE_LOAD_STORE_MULTIPLE_THUMB(STMIA) + +#define DEFINE_CONDITIONAL_BRANCH_THUMB(COND) \ + DEFINE_THUMB_DECODER(B ## COND, B, \ + int8_t immediate = opcode; \ + info->op1.immediate += immediate << 1; \ + info->branches = 1; \ + info->operandFormat = ARM_OPERAND_IMMEDIATE_1;) + +DEFINE_CONDITIONAL_BRANCH_THUMB(EQ) +DEFINE_CONDITIONAL_BRANCH_THUMB(NE) +DEFINE_CONDITIONAL_BRANCH_THUMB(CS) +DEFINE_CONDITIONAL_BRANCH_THUMB(CC) +DEFINE_CONDITIONAL_BRANCH_THUMB(MI) +DEFINE_CONDITIONAL_BRANCH_THUMB(PL) +DEFINE_CONDITIONAL_BRANCH_THUMB(VS) +DEFINE_CONDITIONAL_BRANCH_THUMB(VC) +DEFINE_CONDITIONAL_BRANCH_THUMB(LS) +DEFINE_CONDITIONAL_BRANCH_THUMB(HI) +DEFINE_CONDITIONAL_BRANCH_THUMB(GE) +DEFINE_CONDITIONAL_BRANCH_THUMB(LT) +DEFINE_CONDITIONAL_BRANCH_THUMB(GT) +DEFINE_CONDITIONAL_BRANCH_THUMB(LE) + +#define DEFINE_SP_MODIFY_THUMB(NAME, MNEMONIC) \ + DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ + info->op1.reg = ARM_SP; \ + info->op2.immediate = (opcode & 0x7F) << 2; \ + info->accessesSpecialRegisters = 1; \ + info->operandFormat = ARM_OPERAND_REGISTER_1 | \ + ARM_OPERAND_AFFECTED_1 | \ + ARM_OPERAND_IMMEDIATE_2;) + +DEFINE_SP_MODIFY_THUMB(ADD7, ADD) +DEFINE_SP_MODIFY_THUMB(SUB4, SUB) + +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POP, ARM_SP, POP, 1) +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPR, ARM_SP, POP, 1) +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSH, ARM_SP, PUSH, 1) +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSHR, ARM_SP, PUSH, 1) + +DEFINE_THUMB_DECODER(ILL, ILL, info->traps = 1;) +DEFINE_THUMB_DECODER(BKPT, BKPT, info->traps = 1;) + +DEFINE_THUMB_DECODER(B, B, + int16_t immediate = (opcode & 0x07FF) << 5; + info->op1.immediate = (((int32_t) immediate) >> 4); + info->operandFormat = ARM_OPERAND_IMMEDIATE_1; + info->branches = 1;) + +DEFINE_THUMB_DECODER(BL1, BLH, + int16_t immediate = (opcode & 0x07FF) << 5; + info->op1.immediate = (((int32_t) immediate) << 7); + info->operandFormat = ARM_OPERAND_IMMEDIATE_1; + info->accessesSpecialRegisters = 1;) + +DEFINE_THUMB_DECODER(BL2, BL, + info->op1.immediate = (opcode & 0x07FF) << 1; + info->operandFormat = ARM_OPERAND_IMMEDIATE_1; + info->accessesSpecialRegisters = 1; + info->branches = 1;) + +DEFINE_THUMB_DECODER(BX, BX, + info->op1.reg = (opcode >> 3) & 0xF; + info->operandFormat = ARM_OPERAND_REGISTER_1; + info->branches = 1;) + +DEFINE_THUMB_DECODER(SWI, SWI, + info->op1.immediate = opcode & 0xFF; + info->operandFormat = ARM_OPERAND_IMMEDIATE_1; + info->traps = 1;) + +typedef void (*ThumbDecoder)(uint16_t opcode, struct ThumbInstructionInfo* info); + +static const ThumbDecoder _thumbDecoderTable[0x400] = { + DECLARE_THUMB_EMITTER_BLOCK(_ThumbDecode) +}; + void ARMDecodeThumb(uint16_t opcode, struct ThumbInstructionInfo* info) { - // TODO info->opcode = opcode; + info->branches = 0; + info->traps = 0; + info->accessesSpecialRegisters = 0; + info->affectsCPSR = 0; + ThumbDecoder decoder = _thumbDecoderTable[opcode >> 6]; + decoder(opcode, info); }
M
src/arm/decompiler.h
→
src/arm/decompiler.h
@@ -3,28 +3,64 @@ #define ARM_DECOMPILER_H
#include <stdint.h> +// Bit 0: a register is involved with this operand +// Bit 1: an immediate is invovled with this operand +// 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: this operand is added or subtracted to the base register +enum ARMOperandFormat { + ARM_OPERAND_NONE = 0x00000000, + ARM_OPERAND_REGISTER_1 = 0x00000001, + ARM_OPERAND_IMMEDIATE_1 = 0x00000002, + ARM_OPERAND_MEMORY_1 = 0x00000004, + ARM_OPERAND_AFFECTED_1 = 0x00000008, + ARM_OPERAND_SHIFT_REGISTER_1 = 0x00000010, + ARM_OPERAND_SHIFT_IMMEDIATE_1 = 0x00000020, + + ARM_OPERAND_REGISTER_2 = 0x00000100, + ARM_OPERAND_IMMEDIATE_2 = 0x00000200, + ARM_OPERAND_MEMORY_2 = 0x00000400, + ARM_OPERAND_AFFECTED_2 = 0x00000800, + ARM_OPERAND_SHIFT_REGISTER_2 = 0x00001000, + ARM_OPERAND_SHIFT_IMMEDIATE_2 = 0x00002000, + + ARM_OPERAND_REGISTER_3 = 0x00010000, + ARM_OPERAND_IMMEDIATE_3 = 0x00020000, + ARM_OPERAND_MEMORY_3 = 0x00040000, + ARM_OPERAND_AFFECTED_3 = 0x00080000, + ARM_OPERAND_SHIFT_REGISTER_3 = 0x00100000, + ARM_OPERAND_SHIFT_IMMEDIATE_3 = 0x00200000 +}; + +enum ARMMemoryFormat { + ARM_MEMORY_REGISTER_BASE = 0x0001, + ARM_MEMORY_IMMEDIATE_OFFSET = 0x0002, + ARM_MEMORY_REGISTER_OFFSET = 0x0004, + ARM_MEMORY_SHIFTED_OFFSET = 0x0008, + ARM_MEMORY_PRE_INCREMENT = 0x0010, + ARM_MEMORY_POST_INCREMENT = 0x0020 +}; + union ARMOperand { - uint8_t reg; + struct { + uint8_t reg; + uint8_t shifterOp; + union { + uint8_t shifterReg; + uint8_t shifterImm; + }; + }; int32_t immediate; }; struct ARMMemoryAccess { - uint8_t baseRegister; + uint8_t baseReg; + uint16_t format; union ARMOperand offset; }; -enum ARMOperandFormat { - ARM_OPERAND_NONE = 0x00000000, - ARM_OPERAND_REGISTER_1 = 0x00000001, - ARM_OPERAND_IMMEDIATE_1 = 0x00000002, - ARM_OPERAND_MEMORY_REGISTER_1 = 0x00000005, - ARM_OPERAND_MEMORY_IMMEDIATE_1 = 0x00000006, - ARM_OPERAND_MEMORY_OFFSET_1 = 0x00000007, - ARM_OPERAND_AFFECTED_1 = 0x00000080, - ARM_OPERAND_MEMORY_POST_INCR_1 = 0x00000097, - ARM_OPERAND_MEMORY_PRE_INCR_1 = 0x000000A7, -}; - enum ThumbMnemonic { THUMB_MN_ILL = 0, THUMB_MN_ADC,@@ -33,6 +69,7 @@ THUMB_MN_AND,
THUMB_MN_ASR, THUMB_MN_B, THUMB_MN_BIC, + THUMB_MN_BKPT, THUMB_MN_BL, THUMB_MN_BLH, THUMB_MN_BX,@@ -72,11 +109,11 @@ union ARMOperand op1;
union ARMOperand op2; union ARMOperand op3; struct ARMMemoryAccess memory; - int immediateFormat; int operandFormat; int branches; - int accessesMemory; - int accessesHighRegisters; + int traps; + int accessesSpecialRegisters; + int affectsCPSR; }; void ARMDecodeThumb(uint16_t opcode, struct ThumbInstructionInfo* info);