From e091544bec3b47df7f554b5392c344c7215c987e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 12 Oct 2018 14:51:45 -0700 Subject: [PATCH] ARM: Unify barrel shifter instructions --- include/mgba/internal/arm/emitter-arm.h | 24 +-- src/arm/decoder-arm.c | 55 +++--- src/arm/isa-arm.c | 248 ++++++++++-------------- 3 files changed, 141 insertions(+), 186 deletions(-) diff --git a/include/mgba/internal/arm/emitter-arm.h b/include/mgba/internal/arm/emitter-arm.h index e99a1b7ee..5374318b3 100644 --- a/include/mgba/internal/arm/emitter-arm.h +++ b/include/mgba/internal/arm/emitter-arm.h @@ -16,21 +16,21 @@ DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## I)) #define DECLARE_ARM_ALU_BLOCK(EMITTER, ALU, EX1, EX2, EX3, EX4) \ - 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, ALU), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ DECLARE_INSTRUCTION_ARM(EMITTER, EX1), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ DECLARE_INSTRUCTION_ARM(EMITTER, EX2), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ASR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ DECLARE_INSTRUCTION_ARM(EMITTER, EX3), \ - DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ROR), \ + DECLARE_INSTRUCTION_ARM(EMITTER, ALU), \ DECLARE_INSTRUCTION_ARM(EMITTER, EX4) #define DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, NAME, P, U, W) \ diff --git a/src/arm/decoder-arm.c b/src/arm/decoder-arm.c index bfbf65365..dbf6df44f 100644 --- a/src/arm/decoder-arm.c +++ b/src/arm/decoder-arm.c @@ -9,9 +9,22 @@ #include #include -#define ADDR_MODE_1_SHIFT(OP) \ +#define ADDR_MODE_1_SHIFT \ info->op3.reg = opcode & 0x0000000F; \ - info->op3.shifterOp = ARM_SHIFT_ ## OP; \ + switch (opcode & 0x00000060) { \ + case 0x00000000: \ + info->op3.shifterOp = ARM_SHIFT_LSL; \ + break; \ + case 0x00000020: \ + info->op3.shifterOp = ARM_SHIFT_LSR; \ + break; \ + case 0x00000040: \ + info->op3.shifterOp = ARM_SHIFT_ASR; \ + break; \ + case 0x00000060: \ + info->op3.shifterOp = ARM_SHIFT_ROR; \ + break; \ + } \ info->operandFormat |= ARM_OPERAND_REGISTER_3; \ if (opcode & 0x00000010) { \ info->op3.shifterReg = (opcode >> 8) & 0xF; \ @@ -20,21 +33,14 @@ } else { \ info->op3.shifterImm = (opcode >> 7) & 0x1F; \ info->operandFormat |= ARM_OPERAND_SHIFT_IMMEDIATE_3; \ - } - -#define ADDR_MODE_1_LSL \ - ADDR_MODE_1_SHIFT(LSL) \ - if (!info->op3.shifterImm) { \ - info->operandFormat &= ~ARM_OPERAND_SHIFT_IMMEDIATE_3; \ - info->op3.shifterOp = ARM_SHIFT_NONE; \ - } - -#define ADDR_MODE_1_LSR ADDR_MODE_1_SHIFT(LSR) -#define ADDR_MODE_1_ASR ADDR_MODE_1_SHIFT(ASR) -#define ADDR_MODE_1_ROR \ - ADDR_MODE_1_SHIFT(ROR) \ - if (!info->op3.shifterImm) { \ - info->op3.shifterOp = ARM_SHIFT_RRX; \ + if (!info->op3.shifterImm) { \ + if (info->op3.shifterOp == ARM_SHIFT_LSL) { \ + info->operandFormat &= ~ARM_OPERAND_SHIFT_IMMEDIATE_3; \ + info->op3.shifterOp = ARM_SHIFT_NONE; \ + } else if (info->op3.shifterOp == ARM_SHIFT_ROR) { \ + info->op3.shifterOp = ARM_SHIFT_RRX; \ + } \ + } \ } #define ADDR_MODE_1_IMM \ @@ -114,22 +120,13 @@ }) #define DEFINE_ALU_DECODER_ARM(NAME, SKIPPED) \ - DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSL, NAME, 0, ADDR_MODE_1_LSL, ARM_OPERAND_AFFECTED_1, SKIPPED) \ - DEFINE_ALU_DECODER_EX_ARM(NAME ## S_LSL, NAME, 1, ADDR_MODE_1_LSL, ARM_OPERAND_AFFECTED_1, SKIPPED) \ - DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSR, NAME, 0, ADDR_MODE_1_LSR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ - DEFINE_ALU_DECODER_EX_ARM(NAME ## S_LSR, NAME, 1, ADDR_MODE_1_LSR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ - DEFINE_ALU_DECODER_EX_ARM(NAME ## _ASR, NAME, 0, ADDR_MODE_1_ASR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ - DEFINE_ALU_DECODER_EX_ARM(NAME ## S_ASR, NAME, 1, ADDR_MODE_1_ASR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ - DEFINE_ALU_DECODER_EX_ARM(NAME ## _ROR, NAME, 0, ADDR_MODE_1_ROR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ - DEFINE_ALU_DECODER_EX_ARM(NAME ## S_ROR, NAME, 1, ADDR_MODE_1_ROR, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME, NAME, 0, ADDR_MODE_1_SHIFT, ARM_OPERAND_AFFECTED_1, SKIPPED) \ + DEFINE_ALU_DECODER_EX_ARM(NAME ## S, NAME, 1, ADDR_MODE_1_SHIFT, ARM_OPERAND_AFFECTED_1, SKIPPED) \ DEFINE_ALU_DECODER_EX_ARM(NAME ## I, NAME, 0, ADDR_MODE_1_IMM, ARM_OPERAND_AFFECTED_1, SKIPPED) \ DEFINE_ALU_DECODER_EX_ARM(NAME ## SI, NAME, 1, ADDR_MODE_1_IMM, ARM_OPERAND_AFFECTED_1, SKIPPED) #define DEFINE_ALU_DECODER_S_ONLY_ARM(NAME) \ - DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSL, NAME, 1, ADDR_MODE_1_LSL, ARM_OPERAND_NONE, 1) \ - DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSR, NAME, 1, ADDR_MODE_1_LSR, ARM_OPERAND_NONE, 1) \ - DEFINE_ALU_DECODER_EX_ARM(NAME ## _ASR, NAME, 1, ADDR_MODE_1_ASR, ARM_OPERAND_NONE, 1) \ - DEFINE_ALU_DECODER_EX_ARM(NAME ## _ROR, NAME, 1, ADDR_MODE_1_ROR, ARM_OPERAND_NONE, 1) \ + DEFINE_ALU_DECODER_EX_ARM(NAME, NAME, 1, ADDR_MODE_1_SHIFT, ARM_OPERAND_NONE, 1) \ DEFINE_ALU_DECODER_EX_ARM(NAME ## I, NAME, 1, ADDR_MODE_1_IMM, ARM_OPERAND_NONE, 1) #define DEFINE_MULTIPLY_DECODER_EX_ARM(NAME, MNEMONIC, S, OTHER_AFFECTED) \ diff --git a/src/arm/isa-arm.c b/src/arm/isa-arm.c index 901174b75..22b2ab6dd 100644 --- a/src/arm/isa-arm.c +++ b/src/arm/isa-arm.c @@ -14,157 +14,124 @@ #define PSR_STATE_MASK 0x00000020 // Addressing mode 1 -static inline void _shiftLSL(struct ARMCore* cpu, uint32_t opcode) { +static void _shift(struct ARMCore* cpu, uint32_t opcode) { int rm = opcode & 0x0000000F; - if (opcode & 0x00000010) { - int rs = (opcode >> 8) & 0x0000000F; - ++cpu->cycles; - int shift = cpu->gprs[rs]; - if (rs == ARM_PC) { - shift += 4; - } - shift &= 0xFF; - int32_t shiftVal = cpu->gprs[rm]; - if (rm == ARM_PC) { - shiftVal += 4; - } - if (!shift) { - cpu->shifterOperand = shiftVal; - cpu->shifterCarryOut = cpu->cpsr.c; - } else if (shift < 32) { - cpu->shifterOperand = shiftVal << shift; - cpu->shifterCarryOut = (shiftVal >> (32 - shift)) & 1; - } else if (shift == 32) { - cpu->shifterOperand = 0; - cpu->shifterCarryOut = shiftVal & 1; - } else { - cpu->shifterOperand = 0; - cpu->shifterCarryOut = 0; - } - } else { - int immediate = (opcode & 0x00000F80) >> 7; - if (!immediate) { - cpu->shifterOperand = cpu->gprs[rm]; - cpu->shifterCarryOut = cpu->cpsr.c; - } else { - cpu->shifterOperand = cpu->gprs[rm] << immediate; - cpu->shifterCarryOut = (cpu->gprs[rm] >> (32 - immediate)) & 1; - } - } -} -static inline void _shiftLSR(struct ARMCore* cpu, uint32_t opcode) { - int rm = opcode & 0x0000000F; if (opcode & 0x00000010) { - int rs = (opcode >> 8) & 0x0000000F; ++cpu->cycles; - int shift = cpu->gprs[rs]; + int rs = (opcode >> 8) & 0x0000000F; + uint8_t shift = cpu->gprs[rs]; if (rs == ARM_PC) { shift += 4; } - shift &= 0xFF; uint32_t shiftVal = cpu->gprs[rm]; if (rm == ARM_PC) { shiftVal += 4; } - if (!shift) { - cpu->shifterOperand = shiftVal; - cpu->shifterCarryOut = cpu->cpsr.c; - } else if (shift < 32) { - cpu->shifterOperand = shiftVal >> shift; - cpu->shifterCarryOut = (shiftVal >> (shift - 1)) & 1; - } else if (shift == 32) { - cpu->shifterOperand = 0; - cpu->shifterCarryOut = shiftVal >> 31; - } else { - cpu->shifterOperand = 0; - cpu->shifterCarryOut = 0; - } - } else { - int immediate = (opcode & 0x00000F80) >> 7; - if (immediate) { - cpu->shifterOperand = ((uint32_t) cpu->gprs[rm]) >> immediate; - cpu->shifterCarryOut = (cpu->gprs[rm] >> (immediate - 1)) & 1; - } else { - cpu->shifterOperand = 0; - cpu->shifterCarryOut = ARM_SIGN(cpu->gprs[rm]); - } - } -} -static inline void _shiftASR(struct ARMCore* cpu, uint32_t opcode) { - int rm = opcode & 0x0000000F; - if (opcode & 0x00000010) { - int rs = (opcode >> 8) & 0x0000000F; - ++cpu->cycles; - int shift = cpu->gprs[rs]; - if (rs == ARM_PC) { - shift += 4; - } - shift &= 0xFF; - int shiftVal = cpu->gprs[rm]; - if (rm == ARM_PC) { - shiftVal += 4; - } if (!shift) { cpu->shifterOperand = shiftVal; cpu->shifterCarryOut = cpu->cpsr.c; - } else if (shift < 32) { - cpu->shifterOperand = shiftVal >> shift; - cpu->shifterCarryOut = (shiftVal >> (shift - 1)) & 1; - } else if (cpu->gprs[rm] >> 31) { - cpu->shifterOperand = 0xFFFFFFFF; - cpu->shifterCarryOut = 1; - } else { - cpu->shifterOperand = 0; - cpu->shifterCarryOut = 0; + return; + } + switch (opcode & 0x00000060) { + // LSL + case 0x00000000: + if (shift < 32) { + cpu->shifterOperand = shiftVal << shift; + cpu->shifterCarryOut = (shiftVal >> (32 - shift)) & 1; + } else if (shift == 32) { + cpu->shifterOperand = 0; + cpu->shifterCarryOut = shiftVal & 1; + } else { + cpu->shifterOperand = 0; + cpu->shifterCarryOut = 0; + } + break; + // LSR + case 0x00000020: + if (shift < 32) { + cpu->shifterOperand = shiftVal >> shift; + cpu->shifterCarryOut = (shiftVal >> (shift - 1)) & 1; + } else if (shift == 32) { + cpu->shifterOperand = 0; + cpu->shifterCarryOut = shiftVal >> 31; + } else { + cpu->shifterOperand = 0; + cpu->shifterCarryOut = 0; + } + break; + // ASR + case 0x00000040: + if (shift < 32) { + cpu->shifterOperand = (int32_t) shiftVal >> shift; + cpu->shifterCarryOut = ((int32_t) shiftVal >> (shift - 1)) & 1; + } else if (cpu->gprs[rm] >> 31) { + cpu->shifterOperand = 0xFFFFFFFF; + cpu->shifterCarryOut = 1; + } else { + cpu->shifterOperand = 0; + cpu->shifterCarryOut = 0; + } + break; + // ROR + case 0x00000060: + { + int rotate = shift & 0x1F; + if (rotate) { + cpu->shifterOperand = ROR(shiftVal, rotate); + cpu->shifterCarryOut = (shiftVal >> (rotate - 1)) & 1; + } else { + cpu->shifterOperand = shiftVal; + cpu->shifterCarryOut = ARM_SIGN(shiftVal); + } + } + break; } } else { int immediate = (opcode & 0x00000F80) >> 7; - if (immediate) { - cpu->shifterOperand = cpu->gprs[rm] >> immediate; - cpu->shifterCarryOut = (cpu->gprs[rm] >> (immediate - 1)) & 1; - } else { - cpu->shifterCarryOut = ARM_SIGN(cpu->gprs[rm]); - cpu->shifterOperand = cpu->shifterCarryOut; - } - } -} - -static inline void _shiftROR(struct ARMCore* cpu, uint32_t opcode) { - int rm = opcode & 0x0000000F; - if (opcode & 0x00000010) { - int rs = (opcode >> 8) & 0x0000000F; - ++cpu->cycles; - int shift = cpu->gprs[rs]; - if (rs == ARM_PC) { - shift += 4; - } - shift &= 0xFF; - int shiftVal = cpu->gprs[rm]; - if (rm == ARM_PC) { - shiftVal += 4; - } - int rotate = shift & 0x1F; - if (!shift) { - cpu->shifterOperand = shiftVal; - cpu->shifterCarryOut = cpu->cpsr.c; - } else if (rotate) { - cpu->shifterOperand = ROR(shiftVal, rotate); - cpu->shifterCarryOut = (shiftVal >> (rotate - 1)) & 1; - } else { - cpu->shifterOperand = shiftVal; - cpu->shifterCarryOut = ARM_SIGN(shiftVal); - } - } else { - int immediate = (opcode & 0x00000F80) >> 7; - if (immediate) { - cpu->shifterOperand = ROR(cpu->gprs[rm], immediate); - cpu->shifterCarryOut = (cpu->gprs[rm] >> (immediate - 1)) & 1; - } else { - // RRX - cpu->shifterOperand = (cpu->cpsr.c << 31) | (((uint32_t) cpu->gprs[rm]) >> 1); - cpu->shifterCarryOut = cpu->gprs[rm] & 0x00000001; + switch (opcode & 0x00000060) { + // LSL + case 0x00000000: + if (!immediate) { + cpu->shifterOperand = cpu->gprs[rm]; + cpu->shifterCarryOut = cpu->cpsr.c; + } else { + cpu->shifterOperand = cpu->gprs[rm] << immediate; + cpu->shifterCarryOut = (cpu->gprs[rm] >> (32 - immediate)) & 1; + } + break; + // LSR + case 0x00000020: + if (immediate) { + cpu->shifterOperand = ((uint32_t) cpu->gprs[rm]) >> immediate; + cpu->shifterCarryOut = (cpu->gprs[rm] >> (immediate - 1)) & 1; + } else { + cpu->shifterOperand = 0; + cpu->shifterCarryOut = ARM_SIGN(cpu->gprs[rm]); + } + break; + // ASR + case 0x00000040: + if (immediate) { + cpu->shifterOperand = cpu->gprs[rm] >> immediate; + cpu->shifterCarryOut = (cpu->gprs[rm] >> (immediate - 1)) & 1; + } else { + cpu->shifterCarryOut = ARM_SIGN(cpu->gprs[rm]); + cpu->shifterOperand = cpu->shifterCarryOut; + } + break; + // ROR + case 0x00000060: + if (immediate) { + cpu->shifterOperand = ROR(cpu->gprs[rm], immediate); + cpu->shifterCarryOut = (cpu->gprs[rm] >> (immediate - 1)) & 1; + } else { + // RRX + cpu->shifterOperand = (cpu->cpsr.c << 31) | (((uint32_t) cpu->gprs[rm]) >> 1); + cpu->shifterCarryOut = cpu->gprs[rm] & 0x00000001; + } + break; } } } @@ -308,22 +275,13 @@ ATTRIBUTE_NOINLINE static void _neutralS(struct ARMCore* cpu, int32_t d) { }) #define DEFINE_ALU_INSTRUCTION_ARM(NAME, S_BODY, BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## _LSL, , _shiftLSL, BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## S_LSL, S_BODY, _shiftLSL, BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## _LSR, , _shiftLSR, BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## S_LSR, S_BODY, _shiftLSR, BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## _ASR, , _shiftASR, BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## S_ASR, S_BODY, _shiftASR, BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## _ROR, , _shiftROR, BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## S_ROR, S_BODY, _shiftROR, BODY) \ + DEFINE_ALU_INSTRUCTION_EX_ARM(NAME, , _shift, BODY) \ + DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## S, S_BODY, _shift, BODY) \ DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## I, , _immediate, BODY) \ DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## SI, S_BODY, _immediate, BODY) #define DEFINE_ALU_INSTRUCTION_S_ONLY_ARM(NAME, S_BODY, BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## _LSL, S_BODY, _shiftLSL, BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## _LSR, S_BODY, _shiftLSR, BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## _ASR, S_BODY, _shiftASR, BODY) \ - DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## _ROR, S_BODY, _shiftROR, BODY) \ + DEFINE_ALU_INSTRUCTION_EX_ARM(NAME, S_BODY, _shift, BODY) \ DEFINE_ALU_INSTRUCTION_EX_ARM(NAME ## I, S_BODY, _immediate, BODY) #define DEFINE_MULTIPLY_INSTRUCTION_EX_ARM(NAME, BODY, S_BODY) \