ARM9: Implement BLX (2) Thumb
Jeffrey Pfau jeffrey@endrift.com
Tue, 03 Jan 2017 22:39:37 -0800
4 files changed,
30 insertions(+),
2 deletions(-)
M
include/mgba/internal/arm/emitter-thumb.h
→
include/mgba/internal/arm/emitter-thumb.h
@@ -50,8 +50,8 @@ DECLARE_INSTRUCTION_WITH_HIGH_THUMB(EMITTER, CMP3), \
DECLARE_INSTRUCTION_WITH_HIGH_THUMB(EMITTER, MOV3), \ DECLARE_INSTRUCTION_THUMB(EMITTER, BX), \ DECLARE_INSTRUCTION_THUMB(EMITTER, BX), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, ILL), \ - DECLARE_INSTRUCTION_THUMB(EMITTER, ILL), \ + MIN_V(DECLARE_INSTRUCTION_THUMB(EMITTER, BLX2), DECLARE_INSTRUCTION_THUMB(EMITTER, ILL), V >= 5), \ + MIN_V(DECLARE_INSTRUCTION_THUMB(EMITTER, BLX2), DECLARE_INSTRUCTION_THUMB(EMITTER, ILL), V >= 5), \ DO_8(DO_4(DECLARE_INSTRUCTION_THUMB(EMITTER, LDR3))), \ DO_8(DECLARE_INSTRUCTION_THUMB(EMITTER, STR2)), \ DO_8(DECLARE_INSTRUCTION_THUMB(EMITTER, STRH2)), \
M
src/arm/decoder-thumb.c
→
src/arm/decoder-thumb.c
@@ -290,6 +290,12 @@ info->operandFormat = ARM_OPERAND_REGISTER_1 | ARM_OPERAND_AFFECTED_1 |
ARM_OPERAND_REGISTER_2 | ARM_OPERAND_IMMEDIATE_3; info->branchType = ARM_BRANCH_LINKED;) +DEFINE_THUMB_DECODER(BLX2, BLX, + info->op1.reg = (opcode >> 3) & 0xF; + info->op2.reg = ARM_LR; + info->operandFormat = ARM_OPERAND_REGISTER_1 | ARM_OPERAND_REGISTER_2 | ARM_OPERAND_AFFECTED_2; + info->branchType = ARM_BRANCH_INDIRECT;) + DEFINE_THUMB_DECODER(BX, BX, info->op1.reg = (opcode >> 3) & 0xF; info->operandFormat = ARM_OPERAND_REGISTER_1;
M
src/arm/decoder.c
→
src/arm/decoder.c
@@ -393,6 +393,13 @@ case ARM_MN_BLX:
if (info->operandFormat & ARM_OPERAND_IMMEDIATE_1) { written = _decodePCRelative(info->op1.immediate, pc, buffer, blen); ADVANCE(written); + } else if (info->operandFormat & ARM_OPERAND_REGISTER_1) { + written = _decodeRegister(info->op1.reg, buffer, blen); + ADVANCE(written); + if (info->op1.reg > ARM_PC) { + written = _decodePSR(info->op1.psrBits, buffer, blen); + ADVANCE(written); + } } break; default:
M
src/arm/isa-thumb.c
→
src/arm/isa-thumb.c
@@ -404,6 +404,21 @@ } else {
ARM_WRITE_PC; }) +DEFINE_INSTRUCTION_THUMB(BLX2, + int rm = (opcode >> 3) & 0xF; + _ARMSetMode(cpu, cpu->gprs[rm] & 0x00000001); + int misalign = 0; + if (rm == ARM_PC) { + misalign = cpu->gprs[rm] & 0x00000002; + } + cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - 1; + cpu->gprs[ARM_PC] = (cpu->gprs[rm] & 0xFFFFFFFE) - misalign; + if (cpu->executionMode == MODE_THUMB) { + THUMB_WRITE_PC; + } else { + ARM_WRITE_PC; + }) + DEFINE_INSTRUCTION_THUMB(SWI, cpu->irqh.swi16(cpu, opcode & 0xFF)) const ThumbInstruction _thumbv4Table[0x400] = {