mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-12 08:49:43 -06:00

fixes Dragon Quest IX move code with side effects out of assert, fixes release build (thanks to m4wx for this one) also remove some leftovers of jit pipelining
484 lines
20 KiB
C++
484 lines
20 KiB
C++
#include "ARM_InstrInfo.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
namespace ARMInstrInfo
|
|
{
|
|
|
|
#define ak(x) ((x) << 22)
|
|
|
|
enum {
|
|
A_Read0 = 1 << 0,
|
|
A_Read16 = 1 << 1,
|
|
A_Read8 = 1 << 2,
|
|
A_Read12 = 1 << 3,
|
|
|
|
A_Write12 = 1 << 4,
|
|
A_Write16 = 1 << 5,
|
|
A_MemWriteback = 1 << 6,
|
|
|
|
A_BranchAlways = 1 << 7,
|
|
|
|
// for STRD/LDRD
|
|
A_Read12Double = 1 << 8,
|
|
A_Write12Double = 1 << 9,
|
|
|
|
A_Link = 1 << 10,
|
|
|
|
A_UnkOnARM7 = 1 << 11,
|
|
|
|
A_SetNZ = 1 << 12,
|
|
A_SetCV = 1 << 13,
|
|
A_SetMaybeC = 1 << 14,
|
|
A_MulFlags = 1 << 15,
|
|
A_ReadC = 1 << 16,
|
|
A_RRXReadC = 1 << 17,
|
|
A_StaticShiftSetC = 1 << 18,
|
|
A_SetC = 1 << 19,
|
|
|
|
A_WriteMem = 1 << 20,
|
|
A_LoadMem = 1 << 21
|
|
};
|
|
|
|
#define A_BIOP A_Read16
|
|
#define A_MONOOP 0
|
|
|
|
#define A_ARITH_LSL_IMM A_SetCV
|
|
#define A_LOGIC_LSL_IMM A_StaticShiftSetC
|
|
#define A_ARITH_SHIFT_IMM A_SetCV
|
|
#define A_LOGIC_SHIFT_IMM A_SetC
|
|
#define A_ARITH_SHIFT_REG A_SetCV
|
|
#define A_LOGIC_SHIFT_REG A_SetMaybeC
|
|
#define A_ARITH_IMM A_SetCV
|
|
#define A_LOGIC_IMM 0
|
|
|
|
#define A_IMPLEMENT_ALU_OP(x,k,a,c) \
|
|
const u32 A_##x##_IMM = A_Write12 | c | A_##k | ak(ak_##x##_IMM); \
|
|
const u32 A_##x##_REG_LSL_IMM = A_Write12 | c | A_##k | A_Read0 | ak(ak_##x##_REG_LSL_IMM); \
|
|
const u32 A_##x##_REG_LSR_IMM = A_Write12 | c | A_##k | A_Read0 | ak(ak_##x##_REG_LSR_IMM); \
|
|
const u32 A_##x##_REG_ASR_IMM = A_Write12 | c | A_##k | A_Read0 | ak(ak_##x##_REG_ASR_IMM); \
|
|
const u32 A_##x##_REG_ROR_IMM = A_RRXReadC | A_Write12 | c | A_##k | A_Read0 | ak(ak_##x##_REG_ROR_IMM); \
|
|
const u32 A_##x##_REG_LSL_REG = A_Write12 | c | A_##k | A_Read0 | A_Read8 | ak(ak_##x##_REG_LSL_REG); \
|
|
const u32 A_##x##_REG_LSR_REG = A_Write12 | c | A_##k | A_Read0 | A_Read8 | ak(ak_##x##_REG_LSR_REG); \
|
|
const u32 A_##x##_REG_ASR_REG = A_Write12 | c | A_##k | A_Read0 | A_Read8 | ak(ak_##x##_REG_ASR_REG); \
|
|
const u32 A_##x##_REG_ROR_REG = A_Write12 | c | A_##k | A_Read0 | A_Read8 | ak(ak_##x##_REG_ROR_REG); \
|
|
\
|
|
const u32 A_##x##_IMM_S = A_SetNZ | c | A_##a##_IMM | A_Write12 | A_##k | ak(ak_##x##_IMM_S); \
|
|
const u32 A_##x##_REG_LSL_IMM_S = A_SetNZ | c | A_##a##_LSL_IMM | A_Write12 | A_##k | A_Read0 | ak(ak_##x##_REG_LSL_IMM_S); \
|
|
const u32 A_##x##_REG_LSR_IMM_S = A_SetNZ | c | A_##a##_SHIFT_IMM | A_Write12 | A_##k | A_Read0 | ak(ak_##x##_REG_LSR_IMM_S); \
|
|
const u32 A_##x##_REG_ASR_IMM_S = A_SetNZ | c | A_##a##_SHIFT_IMM | A_Write12 | A_##k | A_Read0 | ak(ak_##x##_REG_ASR_IMM_S); \
|
|
const u32 A_##x##_REG_ROR_IMM_S = A_RRXReadC | A_SetNZ | c | A_##a##_SHIFT_IMM | A_Write12 | A_##k | A_Read0 | ak(ak_##x##_REG_ROR_IMM_S); \
|
|
const u32 A_##x##_REG_LSL_REG_S = A_SetNZ | c | A_##a##_SHIFT_REG | A_Write12 | A_##k | A_Read0 | A_Read8 | ak(ak_##x##_REG_LSL_REG_S); \
|
|
const u32 A_##x##_REG_LSR_REG_S = A_SetNZ | c | A_##a##_SHIFT_REG | A_Write12 | A_##k | A_Read0 | A_Read8 | ak(ak_##x##_REG_LSR_REG_S); \
|
|
const u32 A_##x##_REG_ASR_REG_S = A_SetNZ | c | A_##a##_SHIFT_REG | A_Write12 | A_##k | A_Read0 | A_Read8 | ak(ak_##x##_REG_ASR_REG_S); \
|
|
const u32 A_##x##_REG_ROR_REG_S = A_SetNZ | c | A_##a##_SHIFT_REG | A_Write12 | A_##k | A_Read0 | A_Read8 | ak(ak_##x##_REG_ROR_REG_S);
|
|
|
|
A_IMPLEMENT_ALU_OP(AND,BIOP,LOGIC,0)
|
|
A_IMPLEMENT_ALU_OP(EOR,BIOP,LOGIC,0)
|
|
A_IMPLEMENT_ALU_OP(SUB,BIOP,ARITH,0)
|
|
A_IMPLEMENT_ALU_OP(RSB,BIOP,ARITH,0)
|
|
A_IMPLEMENT_ALU_OP(ADD,BIOP,ARITH,0)
|
|
A_IMPLEMENT_ALU_OP(ADC,BIOP,ARITH,A_ReadC)
|
|
A_IMPLEMENT_ALU_OP(SBC,BIOP,ARITH,A_ReadC)
|
|
A_IMPLEMENT_ALU_OP(RSC,BIOP,ARITH,A_ReadC)
|
|
A_IMPLEMENT_ALU_OP(ORR,BIOP,LOGIC,0)
|
|
A_IMPLEMENT_ALU_OP(MOV,MONOOP,LOGIC,0)
|
|
A_IMPLEMENT_ALU_OP(BIC,BIOP,LOGIC,0)
|
|
A_IMPLEMENT_ALU_OP(MVN,MONOOP,LOGIC,0)
|
|
|
|
const u32 A_MOV_REG_LSL_IMM_DBG = A_MOV_REG_LSL_IMM;
|
|
|
|
#define A_IMPLEMENT_ALU_TEST(x,a) \
|
|
const u32 A_##x##_IMM = A_SetNZ | A_Read16 | A_##a##_IMM | ak(ak_##x##_IMM); \
|
|
const u32 A_##x##_REG_LSL_IMM = A_SetNZ | A_Read16 | A_##a##_LSL_IMM | A_Read0 | ak(ak_##x##_REG_LSL_IMM); \
|
|
const u32 A_##x##_REG_LSR_IMM = A_SetNZ | A_Read16 | A_##a##_SHIFT_IMM | A_Read0 | ak(ak_##x##_REG_LSR_IMM); \
|
|
const u32 A_##x##_REG_ASR_IMM = A_SetNZ | A_Read16 | A_##a##_SHIFT_IMM | A_Read0 | ak(ak_##x##_REG_ASR_IMM); \
|
|
const u32 A_##x##_REG_ROR_IMM = A_RRXReadC | A_SetNZ | A_Read16 | A_##a##_SHIFT_IMM | A_Read0 | ak(ak_##x##_REG_ROR_IMM); \
|
|
const u32 A_##x##_REG_LSL_REG = A_SetNZ | A_Read16 | A_##a##_SHIFT_REG | A_Read0 | A_Read8 | ak(ak_##x##_REG_LSL_REG); \
|
|
const u32 A_##x##_REG_LSR_REG = A_SetNZ | A_Read16 | A_##a##_SHIFT_REG | A_Read0 | A_Read8 | ak(ak_##x##_REG_LSR_REG); \
|
|
const u32 A_##x##_REG_ASR_REG = A_SetNZ | A_Read16 | A_##a##_SHIFT_REG | A_Read0 | A_Read8 | ak(ak_##x##_REG_ASR_REG); \
|
|
const u32 A_##x##_REG_ROR_REG = A_SetNZ | A_Read16 | A_##a##_SHIFT_REG | A_Read0 | A_Read8 | ak(ak_##x##_REG_ROR_REG);
|
|
|
|
A_IMPLEMENT_ALU_TEST(TST,LOGIC)
|
|
A_IMPLEMENT_ALU_TEST(TEQ,LOGIC)
|
|
A_IMPLEMENT_ALU_TEST(CMP,ARITH)
|
|
A_IMPLEMENT_ALU_TEST(CMN,ARITH)
|
|
|
|
const u32 A_MUL = A_MulFlags | A_Write16 | A_Read0 | A_Read8 | ak(ak_MUL);
|
|
const u32 A_MLA = A_MulFlags | A_Write16 | A_Read0 | A_Read8 | A_Read12 | ak(ak_MLA);
|
|
const u32 A_UMULL = A_MulFlags | A_Write16 | A_Write12 | A_Read0 | A_Read8 | ak(ak_UMULL);
|
|
const u32 A_UMLAL = A_MulFlags | A_Write16 | A_Write12 | A_Read16 | A_Read12 | A_Read0 | A_Read8 | ak(ak_UMLAL);
|
|
const u32 A_SMULL = A_MulFlags | A_Write16 | A_Write12 | A_Read0 | A_Read8 | ak(ak_SMULL);
|
|
const u32 A_SMLAL = A_MulFlags | A_Write16 | A_Write12 | A_Read16 | A_Read12 | A_Read0 | A_Read8 | ak(ak_SMLAL);
|
|
const u32 A_SMLAxy = A_Write16 | A_Read0 | A_Read8 | A_Read12 | ak(ak_SMLAxy);
|
|
const u32 A_SMLAWy = A_Write16 | A_Read0 | A_Read8 | A_Read12 | ak(ak_SMLAWy);
|
|
const u32 A_SMULWy = A_Write16 | A_Read0 | A_Read8 | ak(ak_SMULWy);
|
|
const u32 A_SMLALxy = A_Write16 | A_Write12 | A_Read16 | A_Read12 | A_Read0 | A_Read8 | ak(ak_SMLALxy);
|
|
const u32 A_SMULxy = A_Write16 | A_Read0 | A_Read8 | ak(ak_SMULxy);
|
|
|
|
const u32 A_CLZ = A_Write12 | A_Read0 | A_UnkOnARM7 | ak(ak_CLZ);
|
|
|
|
const u32 A_QADD = A_Write12 | A_Read0 | A_Read16 | A_UnkOnARM7 | ak(ak_QADD);
|
|
const u32 A_QSUB = A_Write12 | A_Read0 | A_Read16 | A_UnkOnARM7 | ak(ak_QSUB);
|
|
const u32 A_QDADD = A_Write12 | A_Read0 | A_Read16 | A_UnkOnARM7 | ak(ak_QDADD);
|
|
const u32 A_QDSUB = A_Write12 | A_Read0 | A_Read16 | A_UnkOnARM7 | ak(ak_QDSUB);
|
|
|
|
#define A_LDR A_Write12 | A_LoadMem
|
|
#define A_STR A_Read12 | A_WriteMem
|
|
|
|
#define A_IMPLEMENT_WB_LDRSTR(x,k) \
|
|
const u32 A_##x##_IMM = A_##k | A_Read16 | A_MemWriteback | ak(ak_##x##_IMM); \
|
|
const u32 A_##x##_REG_LSL = A_##k | A_Read16 | A_MemWriteback | A_Read0 | ak(ak_##x##_REG_LSL); \
|
|
const u32 A_##x##_REG_LSR = A_##k | A_Read16 | A_MemWriteback | A_Read0 | ak(ak_##x##_REG_LSR); \
|
|
const u32 A_##x##_REG_ASR = A_##k | A_Read16 | A_MemWriteback | A_Read0 | ak(ak_##x##_REG_ASR); \
|
|
const u32 A_##x##_REG_ROR = A_##k | A_RRXReadC | A_Read16 | A_MemWriteback | A_Read0 | ak(ak_##x##_REG_ROR); \
|
|
\
|
|
const u32 A_##x##_POST_IMM = A_##k | A_Read16 | A_Write16 | ak(ak_##x##_POST_IMM); \
|
|
const u32 A_##x##_POST_REG_LSL = A_##k | A_Read16 | A_Write16 | A_Read0 | ak(ak_##x##_POST_REG_LSL); \
|
|
const u32 A_##x##_POST_REG_LSR = A_##k | A_Read16 | A_Write16 | A_Read0 | ak(ak_##x##_POST_REG_LSR); \
|
|
const u32 A_##x##_POST_REG_ASR = A_##k | A_Read16 | A_Write16 | A_Read0 | ak(ak_##x##_POST_REG_ASR); \
|
|
const u32 A_##x##_POST_REG_ROR = A_##k | A_RRXReadC | A_Read16 | A_Write16 | A_Read0 | ak(ak_##x##_POST_REG_ROR);
|
|
|
|
A_IMPLEMENT_WB_LDRSTR(STR,STR)
|
|
A_IMPLEMENT_WB_LDRSTR(STRB,STR)
|
|
A_IMPLEMENT_WB_LDRSTR(LDR,LDR)
|
|
A_IMPLEMENT_WB_LDRSTR(LDRB,LDR)
|
|
|
|
#define A_LDRD A_Write12Double | A_LoadMem
|
|
#define A_STRD A_Read12Double | A_WriteMem
|
|
|
|
#define A_IMPLEMENT_HD_LDRSTR(x,k) \
|
|
const u32 A_##x##_IMM = A_##k | A_Read16 | A_MemWriteback | ak(ak_##x##_IMM); \
|
|
const u32 A_##x##_REG = A_##k | A_Read16 | A_MemWriteback | A_Read0 | ak(ak_##x##_REG); \
|
|
const u32 A_##x##_POST_IMM = A_##k | A_Read16 | A_Write16 | ak(ak_##x##_POST_IMM); \
|
|
const u32 A_##x##_POST_REG = A_##k | A_Read16 | A_Write16 | A_Read0 | ak(ak_##x##_POST_REG);
|
|
|
|
A_IMPLEMENT_HD_LDRSTR(STRH,STR)
|
|
A_IMPLEMENT_HD_LDRSTR(LDRD,LDRD)
|
|
A_IMPLEMENT_HD_LDRSTR(STRD,STRD)
|
|
A_IMPLEMENT_HD_LDRSTR(LDRH,LDR)
|
|
A_IMPLEMENT_HD_LDRSTR(LDRSB,LDR)
|
|
A_IMPLEMENT_HD_LDRSTR(LDRSH,LDR)
|
|
|
|
const u32 A_SWP = A_Write12 | A_Read16 | A_Read0 | A_LoadMem | A_WriteMem | ak(ak_SWP);
|
|
const u32 A_SWPB = A_Write12 | A_Read16 | A_Read0 | A_LoadMem | A_WriteMem | ak(ak_SWPB);
|
|
|
|
const u32 A_LDM = A_Read16 | A_MemWriteback | A_LoadMem | ak(ak_LDM);
|
|
const u32 A_STM = A_Read16 | A_MemWriteback | A_WriteMem | ak(ak_STM);
|
|
|
|
const u32 A_B = A_BranchAlways | ak(ak_B);
|
|
const u32 A_BL = A_BranchAlways | A_Link | ak(ak_BL);
|
|
const u32 A_BLX_IMM = A_BranchAlways | A_Link | ak(ak_BLX_IMM);
|
|
const u32 A_BX = A_BranchAlways | A_Read0 | ak(ak_BX);
|
|
const u32 A_BLX_REG = A_BranchAlways | A_Link | A_Read0 | ak(ak_BLX_REG);
|
|
|
|
const u32 A_UNK = A_BranchAlways | A_Link | ak(ak_UNK);
|
|
const u32 A_MSR_IMM = ak(ak_MSR_IMM);
|
|
const u32 A_MSR_REG = A_Read0 | ak(ak_MSR_REG);
|
|
const u32 A_MRS = A_Write12 | ak(ak_MRS);
|
|
const u32 A_MCR = A_Read12 | ak(ak_MCR);
|
|
const u32 A_MRC = A_Write12 | ak(ak_MRC);
|
|
const u32 A_SVC = A_BranchAlways | A_Link | ak(ak_SVC);
|
|
|
|
// THUMB
|
|
|
|
#define tk(x) ((x) << 22)
|
|
|
|
enum {
|
|
T_Read0 = 1 << 0,
|
|
T_Read3 = 1 << 1,
|
|
T_Read6 = 1 << 2,
|
|
T_Read8 = 1 << 3,
|
|
|
|
T_Write0 = 1 << 4,
|
|
T_Write8 = 1 << 5,
|
|
|
|
T_ReadHi0 = 1 << 6,
|
|
T_ReadHi3 = 1 << 7,
|
|
T_WriteHi0 = 1 << 8,
|
|
|
|
T_ReadR13 = 1 << 9,
|
|
T_WriteR13 = 1 << 10,
|
|
|
|
T_BranchAlways = 1 << 12,
|
|
T_ReadR14 = 1 << 13,
|
|
T_WriteR14 = 1 << 14,
|
|
|
|
T_PopPC = 1 << 15,
|
|
|
|
T_SetNZ = 1 << 16,
|
|
T_SetCV = 1 << 17,
|
|
T_SetMaybeC = 1 << 18,
|
|
T_ReadC = 1 << 19,
|
|
T_SetC = 1 << 20,
|
|
|
|
T_WriteMem = 1 << 21,
|
|
};
|
|
|
|
const u32 T_LSL_IMM = T_SetNZ | T_SetMaybeC | T_Write0 | T_Read3 | tk(tk_LSL_IMM);
|
|
const u32 T_LSR_IMM = T_SetNZ | T_SetC | T_Write0 | T_Read3 | tk(tk_LSR_IMM);
|
|
const u32 T_ASR_IMM = T_SetNZ | T_SetC | T_Write0 | T_Read3 | tk(tk_ASR_IMM);
|
|
|
|
const u32 T_ADD_REG_ = T_SetNZ | T_SetCV | T_Write0 | T_Read3 | T_Read6 | tk(tk_ADD_REG_);
|
|
const u32 T_SUB_REG_ = T_SetNZ | T_SetCV | T_Write0 | T_Read3 | T_Read6 | tk(tk_SUB_REG_);
|
|
const u32 T_ADD_IMM_ = T_SetNZ | T_SetCV | T_Write0 | T_Read3 | tk(tk_ADD_IMM_);
|
|
const u32 T_SUB_IMM_ = T_SetNZ | T_SetCV | T_Write0 | T_Read3 | tk(tk_SUB_IMM_);
|
|
|
|
const u32 T_MOV_IMM = T_SetNZ | T_Write8 | tk(tk_MOV_IMM);
|
|
const u32 T_CMP_IMM = T_SetNZ | T_SetCV | T_Read8 | tk(tk_CMP_IMM);
|
|
const u32 T_ADD_IMM = T_SetNZ | T_SetCV | T_Write8 | T_Read8 | tk(tk_ADD_IMM);
|
|
const u32 T_SUB_IMM = T_SetNZ | T_SetCV | T_Write8 | T_Read8 | tk(tk_SUB_IMM);
|
|
|
|
const u32 T_AND_REG = T_SetNZ | T_Write0 | T_Read0 | T_Read3 | tk(tk_AND_REG);
|
|
const u32 T_EOR_REG = T_SetNZ | T_Write0 | T_Read0 | T_Read3 | tk(tk_EOR_REG);
|
|
const u32 T_LSL_REG = T_SetNZ | T_SetMaybeC | T_Write0 | T_Read0 | T_Read3 | tk(tk_LSL_REG);
|
|
const u32 T_LSR_REG = T_SetNZ | T_SetMaybeC | T_Write0 | T_Read0 | T_Read3 | tk(tk_LSR_REG);
|
|
const u32 T_ASR_REG = T_SetNZ | T_SetMaybeC | T_Write0 | T_Read0 | T_Read3 | tk(tk_ASR_REG);
|
|
const u32 T_ADC_REG = T_ReadC | T_SetNZ | T_SetCV | T_Write0 | T_Read0 | T_Read3 | tk(tk_ADC_REG);
|
|
const u32 T_SBC_REG = T_ReadC | T_SetNZ | T_SetCV | T_Write0 | T_Read0 | T_Read3 | tk(tk_SBC_REG);
|
|
const u32 T_ROR_REG = T_SetNZ | T_SetMaybeC | T_Write0 | T_Read0 | T_Read3 | tk(tk_ROR_REG);
|
|
const u32 T_TST_REG = T_SetNZ | T_Read0 | T_Read3 | tk(tk_TST_REG);
|
|
const u32 T_NEG_REG = T_SetNZ | T_SetCV | T_Write0 | T_Read3 | tk(tk_NEG_REG);
|
|
const u32 T_CMP_REG = T_SetNZ | T_SetCV | T_Read0 | T_Read3 | tk(tk_CMP_REG);
|
|
const u32 T_CMN_REG = T_SetNZ | T_SetCV | T_Read0 | T_Read3 | tk(tk_CMN_REG);
|
|
const u32 T_ORR_REG = T_SetNZ | T_Write0 | T_Read0 | T_Read3 | tk(tk_ORR_REG);
|
|
const u32 T_MUL_REG = T_SetNZ | T_Write0 | T_Read0 | T_Read3 | tk(tk_MUL_REG);
|
|
const u32 T_BIC_REG = T_SetNZ | T_Write0 | T_Read0 | T_Read3 | tk(tk_BIC_REG);
|
|
const u32 T_MVN_REG = T_SetNZ | T_Write0 | T_Read3 | tk(tk_MVN_REG);
|
|
|
|
const u32 T_ADD_HIREG = T_WriteHi0 | T_ReadHi0 | T_ReadHi3 | tk(tk_ADD_HIREG);
|
|
const u32 T_CMP_HIREG = T_SetNZ | T_SetCV | T_ReadHi0 | T_ReadHi3 | tk(tk_CMP_HIREG);
|
|
const u32 T_MOV_HIREG = T_WriteHi0 | T_ReadHi3 | tk(tk_MOV_HIREG);
|
|
|
|
const u32 T_ADD_PCREL = T_Write8 | tk(tk_ADD_PCREL);
|
|
const u32 T_ADD_SPREL = T_Write8 | T_ReadR13 | tk(tk_ADD_SPREL);
|
|
const u32 T_ADD_SP = T_WriteR13 | T_ReadR13 | tk(tk_ADD_SP);
|
|
|
|
const u32 T_LDR_PCREL = T_Write8 | tk(tk_LDR_PCREL);
|
|
|
|
const u32 T_STR_REG = T_Read0 | T_Read3 | T_Read6 | T_WriteMem | tk(tk_STR_REG);
|
|
const u32 T_STRB_REG = T_Read0 | T_Read3 | T_Read6 | T_WriteMem | tk(tk_STRB_REG);
|
|
const u32 T_LDR_REG = T_Write0 | T_Read3 | T_Read6 | tk(tk_LDR_REG);
|
|
const u32 T_LDRB_REG = T_Write0 | T_Read3 | T_Read6 | tk(tk_LDRB_REG);
|
|
const u32 T_STRH_REG = T_Read0 | T_Read3 | T_Read6 | T_WriteMem | tk(tk_STRH_REG);
|
|
const u32 T_LDRSB_REG = T_Write0 | T_Read3 | T_Read6 | tk(tk_LDRSB_REG);
|
|
const u32 T_LDRH_REG = T_Write0 | T_Read3 | T_Read6 | tk(tk_LDRH_REG);
|
|
const u32 T_LDRSH_REG = T_Write0 | T_Read3 | T_Read6 | tk(tk_LDRSH_REG);
|
|
|
|
const u32 T_STR_IMM = T_Read0 | T_Read3 | T_WriteMem | tk(tk_STR_IMM);
|
|
const u32 T_LDR_IMM = T_Write0 | T_Read3 | tk(tk_LDR_IMM);
|
|
const u32 T_STRB_IMM = T_Read0 | T_Read3 | T_WriteMem | tk(tk_STRB_IMM);
|
|
const u32 T_LDRB_IMM = T_Write0 | T_Read3 | tk(tk_LDRB_IMM);
|
|
const u32 T_STRH_IMM = T_Read0 | T_Read3 | T_WriteMem | tk(tk_STRH_IMM);
|
|
const u32 T_LDRH_IMM = T_Write0 | T_Read3 | tk(tk_LDRH_IMM);
|
|
|
|
const u32 T_STR_SPREL = T_Read8 | T_ReadR13 | T_WriteMem | tk(tk_STR_SPREL);
|
|
const u32 T_LDR_SPREL = T_Write8 | T_ReadR13 | tk(tk_LDR_SPREL);
|
|
|
|
const u32 T_PUSH = T_ReadR13 | T_WriteR13 | T_WriteMem | tk(tk_PUSH);
|
|
const u32 T_POP = T_PopPC | T_ReadR13 | T_WriteR13 | tk(tk_POP);
|
|
|
|
const u32 T_LDMIA = T_Read8 | T_Write8 | tk(tk_LDMIA);
|
|
const u32 T_STMIA = T_Read8 | T_Write8 | T_WriteMem | tk(tk_STMIA);
|
|
|
|
const u32 T_BCOND = T_BranchAlways | tk(tk_BCOND);
|
|
const u32 T_BX = T_BranchAlways | T_ReadHi3 | tk(tk_BX);
|
|
const u32 T_BLX_REG = T_BranchAlways | T_WriteR14 | T_ReadHi3 | tk(tk_BLX_REG);
|
|
const u32 T_B = T_BranchAlways | tk(tk_B);
|
|
const u32 T_BL_LONG_1 = T_WriteR14 | tk(tk_BL_LONG_1);
|
|
const u32 T_BL_LONG_2 = T_BranchAlways | T_ReadR14 | T_WriteR14 | tk(tk_BL_LONG_2);
|
|
|
|
const u32 T_UNK = T_BranchAlways | T_WriteR14 | tk(tk_UNK);
|
|
const u32 T_SVC = T_BranchAlways | T_WriteR14 | tk(tk_SVC);
|
|
|
|
#define INSTRFUNC_PROTO(x) u32 x
|
|
#include "ARM_InstrTable.h"
|
|
#undef INSTRFUNC_PROTO
|
|
|
|
Info Decode(bool thumb, u32 num, u32 instr)
|
|
{
|
|
const u8 FlagsReadPerCond[7] = {
|
|
flag_Z,
|
|
flag_C,
|
|
flag_N,
|
|
flag_V,
|
|
flag_C | flag_Z,
|
|
flag_N | flag_V,
|
|
flag_Z | flag_N | flag_V};
|
|
|
|
Info res = {0};
|
|
if (thumb)
|
|
{
|
|
u32 data = THUMBInstrTable[(instr >> 6) & 0x3FF];
|
|
res.Kind = (data >> 22) & 0x3F;
|
|
|
|
if (data & T_Read0)
|
|
res.SrcRegs |= 1 << (instr & 0x7);
|
|
if (data & T_Read3)
|
|
res.SrcRegs |= 1 << ((instr >> 3) & 0x7);
|
|
if (data & T_Read6)
|
|
res.SrcRegs |= 1 << ((instr >> 6) & 0x7);
|
|
if (data & T_Read8)
|
|
res.SrcRegs |= 1 << ((instr >> 8) & 0x7);
|
|
|
|
if (data & T_Write0)
|
|
res.DstRegs |= 1 << (instr & 0x7);
|
|
if (data & T_Write8)
|
|
res.DstRegs |= 1 << ((instr >> 8) & 0x7);
|
|
|
|
if (data & T_ReadHi0)
|
|
res.SrcRegs |= 1 << ((instr & 0x7) | ((instr >> 4) & 0x8));
|
|
if (data & T_ReadHi3)
|
|
res.SrcRegs |= 1 << ((instr >> 3) & 0xF);
|
|
if (data & T_WriteHi0)
|
|
res.DstRegs |= 1 << ((instr & 0x7) | ((instr >> 4) & 0x8));
|
|
|
|
if (data & T_ReadR13)
|
|
res.SrcRegs |= (1 << 13);
|
|
if (data & T_WriteR13)
|
|
res.DstRegs |= (1 << 13);
|
|
if (data & T_WriteR14)
|
|
res.DstRegs |= (1 << 14);
|
|
if (data & T_ReadR14)
|
|
res.SrcRegs |= (1 << 14);
|
|
|
|
if (data & T_BranchAlways)
|
|
res.DstRegs |= (1 << 15);
|
|
|
|
if (data & T_PopPC && instr & (1 << 8))
|
|
res.DstRegs |= 1 << 15;
|
|
|
|
if (data & T_SetNZ)
|
|
res.WriteFlags |= flag_N | flag_Z;
|
|
if (data & T_SetCV)
|
|
res.WriteFlags |= flag_C | flag_V;
|
|
if (data & T_SetMaybeC)
|
|
res.WriteFlags |= flag_C << 4;
|
|
if (data & T_ReadC)
|
|
res.ReadFlags |= flag_C;
|
|
if (data & T_SetC)
|
|
res.WriteFlags |= flag_C;
|
|
|
|
if (data & T_WriteMem)
|
|
res.SpecialKind = special_WriteMem;
|
|
|
|
if (res.Kind == ARMInstrInfo::tk_LDR_PCREL)
|
|
res.SpecialKind = special_LoadLiteral;
|
|
|
|
res.EndBlock |= res.Branches();
|
|
|
|
if (res.Kind == tk_BCOND)
|
|
res.ReadFlags |= FlagsReadPerCond[(instr >> 9) & 0x7];
|
|
|
|
return res;
|
|
}
|
|
else
|
|
{
|
|
u32 data = ARMInstrTable[((instr >> 4) & 0xF) | ((instr >> 16) & 0xFF0)];
|
|
if (num == 0 && (instr & 0xFE000000) == 0xFA000000)
|
|
data = A_BLX_IMM;
|
|
|
|
if (data & A_UnkOnARM7 && num != 0)
|
|
data = A_UNK;
|
|
|
|
res.Kind = (data >> 22) & 0x1FF;
|
|
|
|
if (res.Kind == ak_MCR)
|
|
{
|
|
u32 cn = (instr >> 16) & 0xF;
|
|
u32 cm = instr & 0xF;
|
|
u32 cpinfo = (instr >> 5) & 0x7;
|
|
u32 id = (cn<<8)|(cm<<4)|cpinfo;
|
|
if (id == 0x704 || id == 0x782 || id == 0x750 || id == 0x751 || id == 0x752)
|
|
res.EndBlock |= true;
|
|
|
|
if (id == 0x704 || id == 0x782)
|
|
res.SpecialKind = special_WaitForInterrupt;
|
|
}
|
|
if (res.Kind == ak_MCR || res.Kind == ak_MRC)
|
|
{
|
|
u32 cp = ((instr >> 8) & 0xF);
|
|
if ((num == 0 && cp != 15) || (num == 1 && cp != 14))
|
|
{
|
|
printf("happens\n");
|
|
data = A_UNK;
|
|
res.Kind = ak_UNK;
|
|
}
|
|
}
|
|
|
|
if (data & A_Read0)
|
|
res.SrcRegs |= 1 << (instr & 0xF);
|
|
if (data & A_Read16)
|
|
res.SrcRegs |= 1 << ((instr >> 16) & 0xF);
|
|
if (data & A_Read8)
|
|
res.SrcRegs |= 1 << ((instr >> 8) & 0xF);
|
|
if (data & A_Read12)
|
|
res.SrcRegs |= 1 << ((instr >> 12) & 0xF);
|
|
|
|
if (data & A_Write12)
|
|
res.DstRegs |= 1 << ((instr >> 12) & 0xF);
|
|
if (data & A_Write16)
|
|
res.DstRegs |= 1 << ((instr >> 16) & 0xF);
|
|
|
|
if (data & A_MemWriteback && instr & (1 << 21))
|
|
res.DstRegs |= 1 << ((instr >> 16) & 0xF);
|
|
|
|
if (data & A_BranchAlways)
|
|
res.DstRegs |= 1 << 15;
|
|
|
|
if (data & A_Read12Double)
|
|
{
|
|
res.SrcRegs |= 1 << ((instr >> 12) & 0xF);
|
|
res.SrcRegs |= 1 << (((instr >> 12) & 0xF) + 1);
|
|
}
|
|
if (data & A_Write12Double)
|
|
{
|
|
res.DstRegs |= 1 << ((instr >> 12) & 0xF);
|
|
res.DstRegs |= 1 << (((instr >> 12) & 0xF) + 1);
|
|
}
|
|
|
|
if (data & A_Link)
|
|
res.DstRegs |= 1 << 14;
|
|
|
|
if (res.Kind == ak_LDM)
|
|
res.DstRegs |= instr & (1 << 15); // this is right
|
|
|
|
if (res.Kind == ak_STM)
|
|
res.SrcRegs |= instr & (1 << 15);
|
|
|
|
if (data & A_SetNZ)
|
|
res.WriteFlags |= flag_N | flag_Z;
|
|
if (data & A_SetCV)
|
|
res.WriteFlags |= flag_C | flag_V;
|
|
if (data & A_SetMaybeC)
|
|
res.WriteFlags |= flag_C << 4;
|
|
if ((data & A_MulFlags) && (instr & (1 << 20)))
|
|
res.WriteFlags |= flag_N | flag_Z;
|
|
if (data & A_ReadC)
|
|
res.ReadFlags |= flag_C;
|
|
if ((data & A_RRXReadC) && !((instr >> 7) & 0x1F))
|
|
res.ReadFlags |= flag_C;
|
|
if ((data & A_SetC) || ((data & A_StaticShiftSetC) && ((instr >> 7) & 0x1F)))
|
|
res.WriteFlags |= flag_C;
|
|
|
|
if (data & A_WriteMem)
|
|
res.SpecialKind = special_WriteMem;
|
|
|
|
if ((data & A_LoadMem) && res.SrcRegs == (1 << 15))
|
|
res.SpecialKind = special_LoadLiteral;
|
|
|
|
if ((instr >> 28) < 0xE)
|
|
{
|
|
// make non conditional flag sets conditional
|
|
res.WriteFlags = (res.WriteFlags | (res.WriteFlags << 4)) & 0xF0;
|
|
res.ReadFlags |= FlagsReadPerCond[instr >> 29];
|
|
}
|
|
|
|
res.EndBlock |= res.Branches();
|
|
|
|
return res;
|
|
}
|
|
}
|
|
|
|
}
|