mirror of https://github.com/mgba-emu/mgba.git
ARM Dynarec: Code cleanup
This commit is contained in:
parent
af27f79c1c
commit
ef3d47ff45
|
@ -28,6 +28,10 @@
|
||||||
#define COND_LE 0xD0000000
|
#define COND_LE 0xD0000000
|
||||||
#define COND_AL 0xE0000000
|
#define COND_AL 0xE0000000
|
||||||
|
|
||||||
|
#define EMIT(DEST, OPCODE, COND, ...) \
|
||||||
|
*DEST = emit ## OPCODE (__VA_ARGS__) | COND_ ## COND; \
|
||||||
|
++DEST;
|
||||||
|
|
||||||
static uint32_t calculateAddrMode1(unsigned imm) {
|
static uint32_t calculateAddrMode1(unsigned imm) {
|
||||||
if (imm < 0x100) {
|
if (imm < 0x100) {
|
||||||
return imm;
|
return imm;
|
||||||
|
@ -116,37 +120,35 @@ static uint32_t emitSUBS(unsigned dst, unsigned src1, unsigned src2) {
|
||||||
return OP_SUBS | (dst << 12) | (src1 << 16) | src2;
|
return OP_SUBS | (dst << 12) | (src1 << 16) | src2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define EMIT_IMM(DEST, COND, REG, VALUE) \
|
||||||
|
EMIT(DEST, MOVW, COND, REG, VALUE); \
|
||||||
|
if (VALUE >= 0x10000) { \
|
||||||
|
EMIT(DEST, MOVT, COND, REG, (VALUE) >> 16); \
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t* updatePC(uint32_t* code, uint32_t address) {
|
static uint32_t* updatePC(uint32_t* code, uint32_t address) {
|
||||||
*code++ = emitMOVW(5, address) | COND_AL;
|
EMIT_IMM(code, AL, 5, address);
|
||||||
*code++ = emitMOVT(5, address >> 16) | COND_AL;
|
EMIT(code, STRI, AL, 5, 4, ARM_PC * sizeof(uint32_t));
|
||||||
*code++ = emitSTRI(5, 4, ARM_PC * sizeof(uint32_t)) | COND_AL;
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t* updateEvents(uint32_t* code, struct ARMCore* cpu) {
|
static uint32_t* updateEvents(uint32_t* code, struct ARMCore* cpu) {
|
||||||
*code++ = emitADDI(0, 4, offsetof(struct ARMCore, cycles)) | COND_AL;
|
EMIT(code, ADDI, AL, 0, 4, offsetof(struct ARMCore, cycles));
|
||||||
*code++ = emitLDMIA(0, 6) | COND_AL;
|
EMIT(code, LDMIA, AL, 0, 6);
|
||||||
*code++ = emitSUBS(0, 2, 1) | COND_AL;
|
EMIT(code, SUBS, AL, 0, 2, 1);
|
||||||
*code++ = emitMOV(0, 4) | COND_AL;
|
EMIT(code, MOV, AL, 0, 4);
|
||||||
*code = emitBL(code, cpu->irqh.processEvents) | COND_LE;
|
EMIT(code, BL, LE, code, cpu->irqh.processEvents);
|
||||||
++code;
|
EMIT(code, LDRI, AL, 1, 4, ARM_PC * sizeof(uint32_t));
|
||||||
*code++ = emitLDRI(1, 4, ARM_PC * sizeof(uint32_t)) | COND_AL;
|
EMIT(code, CMP, AL, 1, 5);
|
||||||
*code++ = emitCMP(1, 5) | COND_AL;
|
EMIT(code, POP, NE, 0x8030);
|
||||||
*code++ = emitPOP(0x8030) | COND_NE;
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t* flushPrefetch(uint32_t* code, uint32_t op0, uint32_t op1) {
|
static uint32_t* flushPrefetch(uint32_t* code, uint32_t op0, uint32_t op1) {
|
||||||
*code++ = emitMOVW(1, op0) | COND_AL;
|
EMIT_IMM(code, AL, 1, op0);
|
||||||
if (op0 >= 0x10000) {
|
EMIT_IMM(code, AL, 2, op1);
|
||||||
*code++ = emitMOVT(1, op0 >> 16) | COND_AL;
|
EMIT(code, ADDI, AL, 0, 4, offsetof(struct ARMCore, prefetch));
|
||||||
}
|
EMIT(code, STMIA, AL, 0, 6);
|
||||||
*code++ = emitMOVW(2, op1) | COND_AL;
|
|
||||||
if (op1 >= 0x10000) {
|
|
||||||
*code++ = emitMOVT(2, op1 >> 16) | COND_AL;
|
|
||||||
}
|
|
||||||
*code++ = emitADDI(0, 4, offsetof(struct ARMCore, prefetch)) | COND_AL;
|
|
||||||
*code++ = emitSTMIA(0, 6) | COND_AL;
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,9 +235,9 @@ void ARMDynarecRecompileTrace(struct ARMCore* cpu, struct ARMDynarecTrace* trace
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
trace->entry = (void (*)(struct ARMCore*)) code;
|
trace->entry = (void (*)(struct ARMCore*)) code;
|
||||||
*code++ = emitPUSH(0x4030) | COND_AL;
|
EMIT(code, PUSH, AL, 0x4030);
|
||||||
*code++ = emitMOV(4, 0) | COND_AL;
|
EMIT(code, MOV, AL, 4, 0);
|
||||||
*code++ = emitLDRI(5, 0, ARM_PC * sizeof(uint32_t)) | COND_AL;
|
EMIT(code, LDRI, AL, 5, 0, ARM_PC * sizeof(uint32_t));
|
||||||
struct ARMInstructionInfo info;
|
struct ARMInstructionInfo info;
|
||||||
while (true) {
|
while (true) {
|
||||||
uint16_t instruction = cpu->memory.load16(cpu, address, 0);
|
uint16_t instruction = cpu->memory.load16(cpu, address, 0);
|
||||||
|
@ -250,10 +252,9 @@ void ARMDynarecRecompileTrace(struct ARMCore* cpu, struct ARMDynarecTrace* trace
|
||||||
if (needsUpdatePrefetch(&info)) {
|
if (needsUpdatePrefetch(&info)) {
|
||||||
code = flushPrefetch(code, cpu->memory.load16(cpu, address, 0), cpu->memory.load16(cpu, address + WORD_SIZE_THUMB, 0));
|
code = flushPrefetch(code, cpu->memory.load16(cpu, address, 0), cpu->memory.load16(cpu, address + WORD_SIZE_THUMB, 0));
|
||||||
}
|
}
|
||||||
*code++ = emitMOVW(1, instruction) | COND_AL;
|
EMIT(code, MOVW, AL, 1, instruction);
|
||||||
*code++ = emitMOV(0, 4) | COND_AL;
|
EMIT(code, MOV, AL, 0, 4);
|
||||||
*code = emitBL(code, _thumbTable[instruction >> 6]) | COND_AL;
|
EMIT(code, BL, AL, code, _thumbTable[instruction >> 6]);
|
||||||
++code;
|
|
||||||
if (info.branchType == ARM_BRANCH) {
|
if (info.branchType == ARM_BRANCH) {
|
||||||
struct Label* label = NULL;
|
struct Label* label = NULL;
|
||||||
uint32_t base = address + info.op1.immediate + WORD_SIZE_THUMB;
|
uint32_t base = address + info.op1.immediate + WORD_SIZE_THUMB;
|
||||||
|
@ -267,20 +268,19 @@ void ARMDynarecRecompileTrace(struct ARMCore* cpu, struct ARMDynarecTrace* trace
|
||||||
code = updateEvents(code, cpu);
|
code = updateEvents(code, cpu);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*code++ = emitMOVW(5, address + WORD_SIZE_THUMB) | COND_AL;
|
EMIT(code, MOVW, AL, 5, address + WORD_SIZE_THUMB);
|
||||||
*code++ = emitMOVT(5, (address + WORD_SIZE_THUMB) >> 16) | COND_AL;
|
EMIT(code, MOVT, AL, 5, (address + WORD_SIZE_THUMB) >> 16);
|
||||||
*code++ = emitLDRI(1, 4, ARM_PC * sizeof(uint32_t)) | COND_AL;
|
EMIT(code, LDRI, AL, 1, 4, ARM_PC * sizeof(uint32_t));
|
||||||
*code++ = emitCMP(1, 5) | COND_AL;
|
EMIT(code, CMP, AL, 1, 5);
|
||||||
if (!label || !label->code) {
|
if (!label || !label->code) {
|
||||||
*code++ = emitPOP(0x8030) | COND_NE;
|
EMIT(code, POP, NE, 0x8030);
|
||||||
} else {
|
} else {
|
||||||
uint32_t* l2 = code;
|
uint32_t* l2 = code;
|
||||||
++code;
|
++code;
|
||||||
*code++ = emitMOV(5, 1) | COND_AL;
|
EMIT(code, MOV, AL, 5, 1);
|
||||||
code = updateEvents(code, cpu);
|
code = updateEvents(code, cpu);
|
||||||
*code = emitB(code, label->code) | COND_AL;
|
EMIT(code, B, AL, code, label->code);
|
||||||
++code;
|
EMIT(l2, B, EQ, l2, code);
|
||||||
*l2 = emitB(l2, code) | COND_EQ;
|
|
||||||
}
|
}
|
||||||
} else if (needsUpdateEvents(&info)) {
|
} else if (needsUpdateEvents(&info)) {
|
||||||
code = updateEvents(code, cpu);
|
code = updateEvents(code, cpu);
|
||||||
|
@ -291,7 +291,7 @@ void ARMDynarecRecompileTrace(struct ARMCore* cpu, struct ARMDynarecTrace* trace
|
||||||
}
|
}
|
||||||
memset(labels, 0, sizeof(struct Label) * ((address - trace->start) >> 1));
|
memset(labels, 0, sizeof(struct Label) * ((address - trace->start) >> 1));
|
||||||
code = flushPrefetch(code, cpu->memory.load16(cpu, address, 0), cpu->memory.load16(cpu, address + WORD_SIZE_THUMB, 0));
|
code = flushPrefetch(code, cpu->memory.load16(cpu, address, 0), cpu->memory.load16(cpu, address + WORD_SIZE_THUMB, 0));
|
||||||
*code++ = emitPOP(0x8030) | COND_AL;
|
EMIT(code, POP, AL, 0x8030);
|
||||||
}
|
}
|
||||||
__clear_cache(trace->entry, code);
|
__clear_cache(trace->entry, code);
|
||||||
cpu->dynarec.buffer = code;
|
cpu->dynarec.buffer = code;
|
||||||
|
|
Loading…
Reference in New Issue