ARM9: Implement STRD/LDRD

This commit is contained in:
Vicki Pfau 2017-04-11 18:12:08 -07:00
parent 5efacfa097
commit d4134c8227
5 changed files with 56 additions and 28 deletions

View File

@ -12,8 +12,9 @@ Bugfixes:
Misc:
- DS: Set boot complete bit in RAM on boot (fixes mgba.io/i/576, mgba.io/i/580, mgba.io/i/586)
- DS Memory: Ensure DS9 I/O is 8-byte aligned
- ARM9: Implement SMLAW and SMULW
- ARM9: Implement SMLAW<y> and SMULW<y>
- Qt: Add .nds files to the extension list in Info.plist
- ARM9: Implement STRD/LDRD
0.6.0: (Future)
Features:

View File

@ -135,7 +135,8 @@ enum ARMMemoryAccessType {
ARM_ACCESS_BYTE = 1,
ARM_ACCESS_SIGNED_BYTE = 9,
ARM_ACCESS_TRANSLATED_WORD = 20,
ARM_ACCESS_TRANSLATED_BYTE = 17
ARM_ACCESS_TRANSLATED_BYTE = 17,
ARM_ACCESS_DUALWORD = 32,
};
enum ARMBranchType {

View File

@ -33,6 +33,24 @@
DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ROR), \
DECLARE_INSTRUCTION_ARM(EMITTER, EX4)
#define DECLARE_ARM_ALU_BLOCKv5(EMITTER, ALU, EX1, EX2, EX3, EX4, V) \
DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSL), \
DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSL), \
DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSR), \
DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSR), \
DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ASR), \
DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ASR), \
DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ROR), \
DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ROR), \
DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSL), \
DECLARE_INSTRUCTION_ARM(EMITTER, EX1), \
DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSR), \
DECLARE_INSTRUCTION_ARM(EMITTER, EX2), \
DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ASR), \
MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, EX3), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ROR), \
MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, EX4), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5)
#define DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, NAME, P, U, W) \
DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## I ## P ## U ## W)), \
DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## I ## P ## U ## W))
@ -102,19 +120,19 @@
DO_256(DECLARE_INSTRUCTION_ARM(EMITTER, SWI))
#define DECLARE_ARM_EMITTER_BLOCK(EMITTER, V) \
/* -00---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, AND, MUL, STRH, ILL, ILL), \
/* -00---X- */ DECLARE_ARM_ALU_BLOCKv5(EMITTER, AND, MUL, STRH, LDRD, STRD, V), \
/* -01---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, ANDS, MULS, LDRH, LDRSB, LDRSH), \
/* -02---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, EOR, MLA, STRH, ILL, ILL), \
/* -03---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, EORS, MLAS, LDRH, LDRSB, LDRSH), \
/* -04---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, SUB, ILL, STRHI, ILL, ILL), \
/* -04---X- */ DECLARE_ARM_ALU_BLOCKv5(EMITTER, SUB, ILL, STRHI, LDRDI, STRDI, V), \
/* -05---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, SUBS, ILL, LDRHI, LDRSBI, LDRSHI), \
/* -06---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, RSB, ILL, STRHI, ILL, ILL), \
/* -07---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, RSBS, ILL, LDRHI, LDRSBI, LDRSHI), \
/* -08---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, ADD, UMULL, STRHU, ILL, ILL), \
/* -08---X- */ DECLARE_ARM_ALU_BLOCKv5(EMITTER, ADD, UMULL, STRHU, LDRDU, STRDU, V), \
/* -09---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, ADDS, UMULLS, LDRHU, LDRSBU, LDRSHU), \
/* -0A---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, ADC, UMLAL, STRHU, ILL, ILL), \
/* -0B---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, ADCS, UMLALS, LDRHU, LDRSBU, LDRSHU), \
/* -0C---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, SBC, SMULL, STRHIU, ILL, ILL), \
/* -0C---X- */ DECLARE_ARM_ALU_BLOCKv5(EMITTER, SBC, SMULL, STRHIU, LDRDIU, STRDIU, V), \
/* -0D---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, SBCS, SMULLS, LDRHIU, LDRSBIU, LDRSHIU), \
/* -0E---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, RSC, SMLAL, STRHIU, ILL, ILL), \
/* -0F---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, RSCS, SMLALS, LDRHIU, LDRSBIU, LDRSHIU), \
@ -123,7 +141,7 @@
/* -10---2- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -10---3- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -10---4- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -10---5- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -10---5- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL /* QADD */), \
/* -10---6- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -10---7- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -10---8- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMLABB), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
@ -131,16 +149,16 @@
/* -10---A- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMLATB), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -10---B- */ DECLARE_INSTRUCTION_ARM(EMITTER, STRHP), \
/* -10---C- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMLABT), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -10---D- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -10---D- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, LDRDP), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -10---E- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMLATT), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -10---F- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -10---F- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, STRDP), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -11---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, TST, ILL, LDRHP, LDRSBP, LDRSHP), \
/* -12---0- */ DECLARE_INSTRUCTION_ARM(EMITTER, MSR), \
/* -12---1- */ DECLARE_INSTRUCTION_ARM(EMITTER, BX), \
/* -12---2- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -12---2- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL /* BXJ */), \
/* -12---3- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, BLX2), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -12---4- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -12---5- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -12---5- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL /* QSUB */), \
/* -12---6- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -12---7- */ DECLARE_INSTRUCTION_ARM(EMITTER, BKPT), \
/* -12---8- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMLAWB), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
@ -148,16 +166,16 @@
/* -12---A- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMULWB), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -12---B- */ DECLARE_INSTRUCTION_ARM(EMITTER, STRHPW), \
/* -12---C- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMLAWT), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -12---D- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -12---D- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, LDRDPW), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -12---E- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMULWT), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -12---F- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -12---F- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, STRDPW), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -13---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, TEQ, ILL, LDRHPW, LDRSBPW, LDRSHPW), \
/* -14---0- */ DECLARE_INSTRUCTION_ARM(EMITTER, MRSR), \
/* -14---1- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -14---2- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -14---3- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -14---4- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -14---5- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -14---5- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL /* QDADD */), \
/* -14---6- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -14---7- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -14---8- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMLABB), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
@ -165,16 +183,16 @@
/* -14---A- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMLATB), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -14---B- */ DECLARE_INSTRUCTION_ARM(EMITTER, STRHIP), \
/* -14---C- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMLABT), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -14---D- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -14---D- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, LDRDIP), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -14---E- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMLATT), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -14---F- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -14---F- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, STRDIP), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -15---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, CMP, ILL, LDRHIP, LDRSBIP, LDRSHIP), \
/* -16---0- */ DECLARE_INSTRUCTION_ARM(EMITTER, MSRR), \
/* -16---1- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, CLZ), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -16---2- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -16---3- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -16---4- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -16---5- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -16---5- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL /* QDSUB */), \
/* -16---6- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -16---7- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -16---8- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMULBB), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
@ -182,17 +200,17 @@
/* -16---A- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMULTB), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -16---B- */ DECLARE_INSTRUCTION_ARM(EMITTER, STRHIPW), \
/* -16---C- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMULBT), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -16---D- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -16---D- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, LDRDIPW), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -16---E- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, SMULTT), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -16---F- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
/* -16---F- */ MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, STRDIPW), DECLARE_INSTRUCTION_ARM(EMITTER, ILL), V >= 5), \
/* -17---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, CMN, ILL, LDRHIPW, LDRSBIPW, LDRSHIPW), \
/* -18---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, ORR, SMLAL, STRHPU, ILL, ILL), \
/* -18---X- */ DECLARE_ARM_ALU_BLOCKv5(EMITTER, ORR, SMLAL, STRHPU, LDRDPU, STRDPU, V), \
/* -19---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, ORRS, SMLALS, LDRHPU, LDRSBPU, LDRSHPU), \
/* -1A---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, MOV, SMLAL, STRHPUW, ILL, ILL), \
/* -1A---X- */ DECLARE_ARM_ALU_BLOCKv5(EMITTER, MOV, SMLAL, STRHPUW, LDRDPUW, STRDPUW, V), \
/* -1B---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, MOVS, SMLALS, LDRHPUW, LDRSBPUW, LDRSHPUW), \
/* -1C---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, BIC, SMLAL, STRHIPU, ILL, ILL), \
/* -1C---X- */ DECLARE_ARM_ALU_BLOCKv5(EMITTER, BIC, SMLAL, STRHIPU, LDRDIPU, STRDIPU, V), \
/* -1D---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, BICS, SMLALS, LDRHIPU, LDRSBIPU, LDRSHIPU), \
/* -1E---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, MVN, SMLAL, STRHIPUW, ILL, ILL), \
/* -1E---X- */ DECLARE_ARM_ALU_BLOCKv5(EMITTER, MVN, SMLAL, STRHIPUW, LDRDIPUW, STRDIPUW, V), \
/* -1F---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, MVNS, SMLALS, LDRHIPUW, LDRSBIPUW, LDRSHIPUW), \
/* -20---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, AND), \
/* -21---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ANDS), \

View File

@ -330,11 +330,13 @@ DEFINE_MULTIPLY_DECODER_EX_ARM(SMULWT, SMULWT, 0, 0)
DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(LDR, LDR, LOAD_CYCLES, ARM_ACCESS_WORD)
DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(LDRv5, LDR, LOAD_CYCLES, ARM_ACCESS_WORD)
DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(LDRB, LDR, LOAD_CYCLES, ARM_ACCESS_BYTE)
DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRD, LDR, LOAD_CYCLES, ARM_ACCESS_DUALWORD)
DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRH, LDR, LOAD_CYCLES, ARM_ACCESS_HALFWORD)
DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRSB, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_BYTE)
DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRSH, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_HALFWORD)
DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(STR, STR, STORE_CYCLES, ARM_ACCESS_WORD)
DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(STRB, STR, STORE_CYCLES, ARM_ACCESS_BYTE)
DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(STRD, STR, STORE_CYCLES, ARM_ACCESS_DUALWORD)
DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(STRH, STR, STORE_CYCLES, ARM_ACCESS_HALFWORD)
DEFINE_LOAD_STORE_T_DECODER_ARM(LDRBT, LDR, LOAD_CYCLES, ARM_ACCESS_TRANSLATED_BYTE)

View File

@ -256,6 +256,7 @@ static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) {
#define ADDR_MODE_3_IMMEDIATE (((opcode & 0x00000F00) >> 4) | (opcode & 0x0000000F))
#define ADDR_MODE_3_INDEX(U_OP, M) ADDR_MODE_2_INDEX(U_OP, M)
#define ADDR_MODE_3_WRITEBACK(ADDR) ADDR_MODE_2_WRITEBACK(ADDR)
#define ADDR_MODE_3_WRITEBACK_64(ADDR) ADDR_MODE_2_WRITEBACK(ADDR + 4)
#define ADDR_MODE_4_WRITEBACK_LDM \
if (!((1 << rn) & rs)) { \
@ -442,20 +443,23 @@ static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) {
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPU, ADDR_MODE_2_INDEX(+, ADDR_MODE_2_IMMEDIATE), , BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPUW, ADDR_MODE_2_INDEX(+, ADDR_MODE_2_IMMEDIATE), ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_ADDRESS), BODY) \
#define DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(NAME, BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME, ADDR_MODE_3_RN, ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_INDEX(-, ADDR_MODE_3_RM)), BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## U, ADDR_MODE_3_RN, ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_INDEX(+, ADDR_MODE_3_RM)), BODY) \
#define DEFINE_LOAD_STORE_MODE_3_WRITEBACK_WIDTH_INSTRUCTION_ARM(NAME, BODY, WRITEBACK) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME, ADDR_MODE_3_RN, WRITEBACK(ADDR_MODE_3_INDEX(-, ADDR_MODE_3_RM)), BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## U, ADDR_MODE_3_RN, WRITEBACK(ADDR_MODE_3_INDEX(+, ADDR_MODE_3_RM)), BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## P, ADDR_MODE_3_INDEX(-, ADDR_MODE_3_RM), , BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## PW, ADDR_MODE_3_INDEX(-, ADDR_MODE_3_RM), ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_ADDRESS), BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## PU, ADDR_MODE_3_INDEX(+, ADDR_MODE_3_RM), , BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## PUW, ADDR_MODE_3_INDEX(+, ADDR_MODE_3_RM), ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_ADDRESS), BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## I, ADDR_MODE_3_RN, ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_INDEX(-, ADDR_MODE_3_IMMEDIATE)), BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IU, ADDR_MODE_3_RN, ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_INDEX(+, ADDR_MODE_3_IMMEDIATE)), BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## I, ADDR_MODE_3_RN, WRITEBACK(ADDR_MODE_3_INDEX(-, ADDR_MODE_3_IMMEDIATE)), BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IU, ADDR_MODE_3_RN, WRITEBACK(ADDR_MODE_3_INDEX(+, ADDR_MODE_3_IMMEDIATE)), BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IP, ADDR_MODE_3_INDEX(-, ADDR_MODE_3_IMMEDIATE), , BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPW, ADDR_MODE_3_INDEX(-, ADDR_MODE_3_IMMEDIATE), ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_ADDRESS), BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPU, ADDR_MODE_3_INDEX(+, ADDR_MODE_3_IMMEDIATE), , BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IPUW, ADDR_MODE_3_INDEX(+, ADDR_MODE_3_IMMEDIATE), ADDR_MODE_3_WRITEBACK(ADDR_MODE_3_ADDRESS), BODY) \
#define DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(NAME, BODY) DEFINE_LOAD_STORE_MODE_3_WRITEBACK_WIDTH_INSTRUCTION_ARM(NAME, BODY, ADDR_MODE_3_WRITEBACK)
#define DEFINE_LOAD_STORE_MODE_3_DOUBLE_INSTRUCTION_ARM(NAME, BODY) DEFINE_LOAD_STORE_MODE_3_WRITEBACK_WIDTH_INSTRUCTION_ARM(NAME, BODY, ADDR_MODE_3_WRITEBACK_64)
#define DEFINE_LOAD_STORE_T_INSTRUCTION_SHIFTER_ARM(NAME, SHIFTER, BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME, SHIFTER, ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_INDEX(-, ADDR_MODE_2_RM)), BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## U, SHIFTER, ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_INDEX(+, ADDR_MODE_2_RM)), BODY) \
@ -621,11 +625,13 @@ DEFINE_MULTIPLY_INSTRUCTION_2_ARM(UMULL,
DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDR, cpu->gprs[rd] = cpu->memory.load32(cpu, address, &currentCycles); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDRv5, cpu->gprs[rd] = cpu->memory.load32(cpu, address, &currentCycles); ARM_LOAD_POST_BODY_v5;)
DEFINE_LOAD_STORE_INSTRUCTION_ARM(LDRB, cpu->gprs[rd] = cpu->memory.load8(cpu, address, &currentCycles); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_MODE_3_DOUBLE_INSTRUCTION_ARM(LDRD, cpu->gprs[rd & ~1] = cpu->memory.load32(cpu, address, &currentCycles); cpu->gprs[rd | 1] = cpu->memory.load32(cpu, address + 4, &currentCycles); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRH, cpu->gprs[rd] = cpu->memory.load16(cpu, address, &currentCycles); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRSB, cpu->gprs[rd] = ARM_SXT_8(cpu->memory.load8(cpu, address, &currentCycles)); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(LDRSH, cpu->gprs[rd] = address & 1 ? ARM_SXT_8(cpu->memory.load16(cpu, address, &currentCycles)) : ARM_SXT_16(cpu->memory.load16(cpu, address, &currentCycles)); ARM_LOAD_POST_BODY;)
DEFINE_LOAD_STORE_INSTRUCTION_ARM(STR, cpu->memory.store32(cpu, address, cpu->gprs[rd], &currentCycles); ARM_STORE_POST_BODY;)
DEFINE_LOAD_STORE_INSTRUCTION_ARM(STRB, cpu->memory.store8(cpu, address, cpu->gprs[rd], &currentCycles); ARM_STORE_POST_BODY;)
DEFINE_LOAD_STORE_MODE_3_DOUBLE_INSTRUCTION_ARM(STRD, cpu->memory.store32(cpu, address, cpu->gprs[rd & ~1], &currentCycles); cpu->memory.store32(cpu, address + 4, cpu->gprs[rd | 1], &currentCycles); ARM_STORE_POST_BODY;)
DEFINE_LOAD_STORE_MODE_3_INSTRUCTION_ARM(STRH, cpu->memory.store16(cpu, address, cpu->gprs[rd], &currentCycles); ARM_STORE_POST_BODY;)
DEFINE_LOAD_STORE_T_INSTRUCTION_ARM(LDRBT,