melonDS/src/ARM_InstrInfo.h
2023-11-04 00:21:46 +01:00

282 lines
4.6 KiB
C++

/*
Copyright 2016-2023 melonDS team
This file is part of melonDS.
melonDS is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with melonDS. If not, see http://www.gnu.org/licenses/.
*/
#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