diff --git a/include/mgba/internal/arm/emitter-arm.h b/include/mgba/internal/arm/emitter-arm.h index b8e801537..9090c4611 100644 --- a/include/mgba/internal/arm/emitter-arm.h +++ b/include/mgba/internal/arm/emitter-arm.h @@ -59,6 +59,10 @@ DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## MODE ## W)), \ DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## MODE ## W)) +#define DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCKv5(EMITTER, NAME, MODE, W, V) \ + DO_8(MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## v5 ## MODE ## W), DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## MODE ## W), V >= 5)), \ + DO_8(MIN_V(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## v5 ## MODE ## W), DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## MODE ## W), V >= 5)) + #define DECLARE_ARM_BRANCH_BLOCK(EMITTER, NAME) \ DO_256(DECLARE_INSTRUCTION_ARM(EMITTER, NAME)) @@ -265,33 +269,33 @@ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, U, W), \ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, U, W), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DA, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DA, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCKv5(EMITTER, LDM, DA, , V), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DA, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DA, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCKv5(EMITTER, LDM, DA, W, V), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DA, ), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DA, ), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DA, W), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DA, W), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IA, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IA, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCKv5(EMITTER, LDM, IA, , V), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IA, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IA, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCKv5(EMITTER, LDM, IA, W, V), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IA, ), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IA, ), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IA, W), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IA, W), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DB, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DB, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCKv5(EMITTER, LDM, DB, , V), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DB, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DB, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCKv5(EMITTER, LDM, DB, W, V), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DB, ), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DB, ), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DB, W), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DB, W), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IB, ), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IB, ), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCKv5(EMITTER, LDM, IB, , V), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IB, W), \ - DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IB, W), \ + DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCKv5(EMITTER, LDM, IB, W, V), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IB, ), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IB, ), \ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IB, W), \ diff --git a/include/mgba/internal/arm/emitter-thumb.h b/include/mgba/internal/arm/emitter-thumb.h index 670b8cde7..59a8a631a 100644 --- a/include/mgba/internal/arm/emitter-thumb.h +++ b/include/mgba/internal/arm/emitter-thumb.h @@ -84,7 +84,7 @@ DO_8(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ DO_8(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, POP)), \ - DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, POPR)), \ + DO_4(MIN_V(DECLARE_INSTRUCTION_THUMB(EMITTER, POPR), DECLARE_INSTRUCTION_THUMB(EMITTER, POPRv4), V >= 5)), \ DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, BKPT)), \ DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, ILL)), \ DO_8(DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, STMIA))), \ diff --git a/src/arm/decoder-arm.c b/src/arm/decoder-arm.c index ea15ca27b..2d62eef7b 100644 --- a/src/arm/decoder-arm.c +++ b/src/arm/decoder-arm.c @@ -252,15 +252,18 @@ ARM_MEMORY_ ## DIRECTION;) +#define DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM_NO_S(NAME, SUFFIX) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SUFFIX ## DA, NAME, DECREMENT_AFTER, 0) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SUFFIX ## DAW, NAME, DECREMENT_AFTER, ARM_MEMORY_WRITEBACK) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SUFFIX ## DB, NAME, DECREMENT_BEFORE, 0) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SUFFIX ## DBW, NAME, DECREMENT_BEFORE, ARM_MEMORY_WRITEBACK) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SUFFIX ## IA, NAME, INCREMENT_AFTER, 0) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SUFFIX ## IAW, NAME, INCREMENT_AFTER, ARM_MEMORY_WRITEBACK) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SUFFIX ## IB, NAME, INCREMENT_BEFORE, 0) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SUFFIX ## IBW, NAME, INCREMENT_BEFORE, ARM_MEMORY_WRITEBACK) \ + #define DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(NAME) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DA, NAME, DECREMENT_AFTER, 0) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DAW, NAME, DECREMENT_AFTER, ARM_MEMORY_WRITEBACK) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DB, NAME, DECREMENT_BEFORE, 0) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DBW, NAME, DECREMENT_BEFORE, ARM_MEMORY_WRITEBACK) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IA, NAME, INCREMENT_AFTER, 0) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IAW, NAME, INCREMENT_AFTER, ARM_MEMORY_WRITEBACK) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IB, NAME, INCREMENT_BEFORE, 0) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IBW, NAME, INCREMENT_BEFORE, ARM_MEMORY_WRITEBACK) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM_NO_S(NAME, ) \ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDA, NAME, DECREMENT_AFTER, ARM_MEMORY_SPSR_SWAP) \ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDAW, NAME, DECREMENT_AFTER, ARM_MEMORY_WRITEBACK | ARM_MEMORY_SPSR_SWAP) \ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDB, NAME, DECREMENT_BEFORE, ARM_MEMORY_SPSR_SWAP) \ @@ -325,6 +328,7 @@ DEFINE_LOAD_STORE_T_DECODER_ARM(STRBT, STR, STORE_CYCLES, ARM_ACCESS_TRANSLATED_ DEFINE_LOAD_STORE_T_DECODER_ARM(STRT, STR, STORE_CYCLES, ARM_ACCESS_TRANSLATED_WORD) DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(LDM) +DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM_NO_S(LDM, v5) DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(STM) DEFINE_SWP_DECODER_ARM(SWP, ARM_ACCESS_WORD) diff --git a/src/arm/decoder-thumb.c b/src/arm/decoder-thumb.c index 40ae39ed4..2bea4192c 100644 --- a/src/arm/decoder-thumb.c +++ b/src/arm/decoder-thumb.c @@ -248,6 +248,7 @@ DEFINE_SP_MODIFY_THUMB(SUB4, SUB) DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POP, ARM_SP, LDM, ARM_MEMORY_INCREMENT_AFTER, 0) DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPR, ARM_SP, LDM, ARM_MEMORY_INCREMENT_AFTER, 1 << ARM_PC) +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPRv4, ARM_SP, LDM, ARM_MEMORY_INCREMENT_AFTER, 1 << ARM_PC) DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSH, ARM_SP, STM, ARM_MEMORY_DECREMENT_BEFORE, 0) DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSHR, ARM_SP, STM, ARM_MEMORY_DECREMENT_BEFORE, 1 << ARM_LR) diff --git a/src/arm/isa-arm.c b/src/arm/isa-arm.c index 88797b08c..0433f81ab 100644 --- a/src/arm/isa-arm.c +++ b/src/arm/isa-arm.c @@ -287,6 +287,8 @@ static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) { cpu->gprs[rn] = address; \ } +#define ADDR_MODE_4_WRITEBACK_LDMv5 ADDR_MODE_4_WRITEBACK_LDM + #define ADDR_MODE_4_WRITEBACK_STM cpu->gprs[rn] = address; #define ARM_LOAD_POST_BODY \ @@ -450,7 +452,7 @@ static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) { WRITEBACK;) -#define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(NAME, LS, POST_BODY) \ +#define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM_NO_S(NAME, LS, POST_BODY) \ DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DA, LS, , , , DA, POST_BODY) \ DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, , , DA, POST_BODY) \ DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DB, LS, , , , DB, POST_BODY) \ @@ -459,6 +461,9 @@ static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) { DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, , , IA, POST_BODY) \ DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IB, LS, , , , IB, POST_BODY) \ DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IBW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, , , IB, POST_BODY) \ + +#define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(NAME, LS, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM_NO_S(NAME, LS, POST_BODY) \ DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDA, LS, , ARM_MS_PRE, ARM_MS_POST, DA, POST_BODY) \ DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE, ARM_MS_POST, DA, POST_BODY) \ DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDB, LS, , ARM_MS_PRE, ARM_MS_POST, DB, POST_BODY) \ @@ -611,6 +616,20 @@ DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(LDM, ARM_WRITE_PC; }) +DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM_NO_S(LDMv5, + load, + currentCycles += cpu->memory.activeNonseqCycles32 - cpu->memory.activeSeqCycles32; + if (rs & 0x8000) { + _ARMSetMode(cpu, cpu->gprs[ARM_PC] & 0x00000001); + cpu->gprs[ARM_PC] &= 0xFFFFFFFE; + if (cpu->executionMode == MODE_THUMB) { + THUMB_WRITE_PC; + } else { + ARM_WRITE_PC; + + } + }) + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(STM, store, ARM_STORE_POST_BODY;) diff --git a/src/arm/isa-thumb.c b/src/arm/isa-thumb.c index 33adf3239..88b3bf1ac 100644 --- a/src/arm/isa-thumb.c +++ b/src/arm/isa-thumb.c @@ -361,7 +361,7 @@ DEFINE_LOAD_STORE_MULTIPLE_THUMB(POP, THUMB_LOAD_POST_BODY; cpu->gprs[ARM_SP] = address) -DEFINE_LOAD_STORE_MULTIPLE_THUMB(POPR, +DEFINE_LOAD_STORE_MULTIPLE_THUMB(POPRv4, ARM_SP, load, IA, @@ -370,6 +370,22 @@ DEFINE_LOAD_STORE_MULTIPLE_THUMB(POPR, cpu->gprs[ARM_SP] = address; THUMB_WRITE_PC;) +DEFINE_LOAD_STORE_MULTIPLE_THUMB(POPR, + ARM_SP, + load, + IA, + rs |= 1 << ARM_PC, + THUMB_LOAD_POST_BODY; + cpu->gprs[ARM_SP] = address; + _ARMSetMode(cpu, cpu->gprs[ARM_PC] & 0x00000001); + cpu->gprs[ARM_PC] &= 0xFFFFFFFE; + if (cpu->executionMode == MODE_THUMB) { + THUMB_WRITE_PC; + } else { + ARM_WRITE_PC; + + }) + DEFINE_LOAD_STORE_MULTIPLE_THUMB(PUSH, ARM_SP, store,