diff options
Diffstat (limited to 'src/ARM_InstrInfo.h')
-rw-r--r-- | src/ARM_InstrInfo.h | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/src/ARM_InstrInfo.h b/src/ARM_InstrInfo.h new file mode 100644 index 0000000..a702435 --- /dev/null +++ b/src/ARM_InstrInfo.h @@ -0,0 +1,263 @@ +#ifndef ARMINSTRINFO_H +#define ARMINSTRINFO_H + +#include "types.h" + +namespace ARMInstrInfo +{ + +// Instruction kinds, for faster dispatch + +#define ak_ALU(n) \ + ak_##n##_REG_LSL_IMM, \ + ak_##n##_REG_LSR_IMM, \ + ak_##n##_REG_ASR_IMM, \ + ak_##n##_REG_ROR_IMM, \ + \ + ak_##n##_REG_LSL_REG, \ + ak_##n##_REG_LSR_REG, \ + ak_##n##_REG_ASR_REG, \ + ak_##n##_REG_ROR_REG, \ + \ + ak_##n##_IMM, \ + \ + ak_##n##_REG_LSL_IMM_S, \ + ak_##n##_REG_LSR_IMM_S, \ + ak_##n##_REG_ASR_IMM_S, \ + ak_##n##_REG_ROR_IMM_S, \ + \ + ak_##n##_REG_LSL_REG_S, \ + ak_##n##_REG_LSR_REG_S, \ + ak_##n##_REG_ASR_REG_S, \ + ak_##n##_REG_ROR_REG_S, \ + \ + ak_##n##_IMM_S \ + +#define ak_Test(n) \ + ak_##n##_REG_LSL_IMM, \ + ak_##n##_REG_LSR_IMM, \ + ak_##n##_REG_ASR_IMM, \ + ak_##n##_REG_ROR_IMM, \ + \ + ak_##n##_REG_LSL_REG, \ + ak_##n##_REG_LSR_REG, \ + ak_##n##_REG_ASR_REG, \ + ak_##n##_REG_ROR_REG, \ + \ + ak_##n##_IMM + +#define ak_WB_LDRSTR(n) \ + ak_##n##_REG_LSL, \ + ak_##n##_REG_LSR, \ + ak_##n##_REG_ASR, \ + ak_##n##_REG_ROR, \ + \ + ak_##n##_IMM, \ + \ + ak_##n##_POST_REG_LSL, \ + ak_##n##_POST_REG_LSR, \ + ak_##n##_POST_REG_ASR, \ + ak_##n##_POST_REG_ROR, \ + \ + ak_##n##_POST_IMM + +#define ak_HD_LDRSTR(n) \ + ak_##n##_REG, \ + ak_##n##_IMM, \ + \ + ak_##n##_POST_REG, \ + ak_##n##_POST_IMM + +enum +{ + ak_ALU(AND), + ak_ALU(EOR), + ak_ALU(SUB), + ak_ALU(RSB), + ak_ALU(ADD), + ak_ALU(ADC), + ak_ALU(SBC), + ak_ALU(RSC), + ak_ALU(ORR), + ak_ALU(MOV), + ak_ALU(BIC), + ak_ALU(MVN), + + ak_Test(TST), + ak_Test(TEQ), + ak_Test(CMP), + ak_Test(CMN), + + ak_MUL, + ak_MLA, + ak_UMULL, + ak_UMLAL, + ak_SMULL, + ak_SMLAL, + ak_SMLAxy, + ak_SMLAWy, + ak_SMULWy, + ak_SMLALxy, + ak_SMULxy, + + ak_CLZ, + + ak_QADD, + ak_QSUB, + ak_QDADD, + ak_QDSUB, + + ak_WB_LDRSTR(STR), + ak_WB_LDRSTR(STRB), + ak_WB_LDRSTR(LDR), + ak_WB_LDRSTR(LDRB), + + ak_HD_LDRSTR(STRH), + ak_HD_LDRSTR(LDRD), + ak_HD_LDRSTR(STRD), + ak_HD_LDRSTR(LDRH), + ak_HD_LDRSTR(LDRSB), + ak_HD_LDRSTR(LDRSH), + + ak_SWP, + ak_SWPB, + + ak_LDM, + ak_STM, + + ak_B, + ak_BL, + ak_BLX_IMM, + ak_BX, + ak_BLX_REG, + + ak_UNK, + ak_MSR_IMM, + ak_MSR_REG, + ak_MRS, + ak_MCR, + ak_MRC, + ak_SVC, + + ak_Nop, + + ak_Count, + + tk_LSL_IMM = 0, + tk_LSR_IMM, + tk_ASR_IMM, + + tk_ADD_REG_, + tk_SUB_REG_, + tk_ADD_IMM_, + tk_SUB_IMM_, + + tk_MOV_IMM, + tk_CMP_IMM, + tk_ADD_IMM, + tk_SUB_IMM, + + tk_AND_REG, + tk_EOR_REG, + tk_LSL_REG, + tk_LSR_REG, + tk_ASR_REG, + tk_ADC_REG, + tk_SBC_REG, + tk_ROR_REG, + tk_TST_REG, + tk_NEG_REG, + tk_CMP_REG, + tk_CMN_REG, + tk_ORR_REG, + tk_MUL_REG, + tk_BIC_REG, + tk_MVN_REG, + + tk_ADD_HIREG, + tk_CMP_HIREG, + tk_MOV_HIREG, + + tk_ADD_PCREL, + tk_ADD_SPREL, + tk_ADD_SP, + + tk_LDR_PCREL, + tk_STR_REG, + tk_STRB_REG, + tk_LDR_REG, + tk_LDRB_REG, + tk_STRH_REG, + tk_LDRSB_REG, + tk_LDRH_REG, + tk_LDRSH_REG, + tk_STR_IMM, + tk_LDR_IMM, + tk_STRB_IMM, + tk_LDRB_IMM, + tk_STRH_IMM, + tk_LDRH_IMM, + tk_STR_SPREL, + tk_LDR_SPREL, + + tk_PUSH, + tk_POP, + tk_LDMIA, + tk_STMIA, + + tk_BCOND, + tk_BX, + tk_BLX_REG, + tk_B, + tk_BL_LONG_1, + tk_BL_LONG_2, + tk_UNK, + tk_SVC, + + // not a real instruction + tk_BL_LONG, + + tk_Count +}; + +enum +{ + flag_N = 1 << 3, + flag_Z = 1 << 2, + flag_C = 1 << 1, + flag_V = 1 << 0, +}; + +enum +{ + special_NotSpecialAtAll = 0, + special_WriteMem, + special_LoadMem, + special_WaitForInterrupt, + special_LoadLiteral +}; + +struct Info +{ + u16 DstRegs, SrcRegs, NotStrictlyNeeded; + u16 Kind; + + u8 SpecialKind; + + u8 ReadFlags; + // lower 4 bits - set always + // upper 4 bits - might set flag + u8 WriteFlags; + + bool EndBlock; + bool Branches() const + { + return DstRegs & (1 << 15); + } +}; + +Info Decode(bool thumb, u32 num, u32 instr); + +} + +#endif
\ No newline at end of file |