summaryrefslogtreecommitdiffstats
path: root/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/arm/dyncom/arm_dyncom_interpreter.cpp')
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp4578
1 files changed, 0 insertions, 4578 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
deleted file mode 100644
index fc2d6aabc..000000000
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ /dev/null
@@ -1,4578 +0,0 @@
-// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#define CITRA_IGNORE_EXIT(x)
-
-#include <algorithm>
-#include <cinttypes>
-#include <cstdio>
-#include "common/common_types.h"
-#include "common/logging/log.h"
-#include "common/microprofile.h"
-#include "core/arm/dyncom/arm_dyncom_dec.h"
-#include "core/arm/dyncom/arm_dyncom_interpreter.h"
-#include "core/arm/dyncom/arm_dyncom_run.h"
-#include "core/arm/dyncom/arm_dyncom_thumb.h"
-#include "core/arm/dyncom/arm_dyncom_trans.h"
-#include "core/arm/skyeye_common/armstate.h"
-#include "core/arm/skyeye_common/armsupp.h"
-#include "core/arm/skyeye_common/vfp/vfp.h"
-#include "core/gdbstub/gdbstub.h"
-#include "core/hle/svc.h"
-#include "core/memory.h"
-
-#define RM BITS(sht_oper, 0, 3)
-#define RS BITS(sht_oper, 8, 11)
-
-#define glue(x, y) x##y
-#define DPO(s) glue(DataProcessingOperands, s)
-#define ROTATE_RIGHT(n, i, l) ((n << (l - i)) | (n >> i))
-#define ROTATE_LEFT(n, i, l) ((n >> (l - i)) | (n << i))
-#define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32)
-#define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32)
-
-static bool CondPassed(const ARMul_State* cpu, unsigned int cond) {
- const bool n_flag = cpu->NFlag != 0;
- const bool z_flag = cpu->ZFlag != 0;
- const bool c_flag = cpu->CFlag != 0;
- const bool v_flag = cpu->VFlag != 0;
-
- switch (cond) {
- case ConditionCode::EQ:
- return z_flag;
- case ConditionCode::NE:
- return !z_flag;
- case ConditionCode::CS:
- return c_flag;
- case ConditionCode::CC:
- return !c_flag;
- case ConditionCode::MI:
- return n_flag;
- case ConditionCode::PL:
- return !n_flag;
- case ConditionCode::VS:
- return v_flag;
- case ConditionCode::VC:
- return !v_flag;
- case ConditionCode::HI:
- return (c_flag && !z_flag);
- case ConditionCode::LS:
- return (!c_flag || z_flag);
- case ConditionCode::GE:
- return (n_flag == v_flag);
- case ConditionCode::LT:
- return (n_flag != v_flag);
- case ConditionCode::GT:
- return (!z_flag && (n_flag == v_flag));
- case ConditionCode::LE:
- return (z_flag || (n_flag != v_flag));
- case ConditionCode::AL:
- case ConditionCode::NV: // Unconditional
- return true;
- }
-
- return false;
-}
-
-static unsigned int DPO(Immediate)(ARMul_State* cpu, unsigned int sht_oper) {
- unsigned int immed_8 = BITS(sht_oper, 0, 7);
- unsigned int rotate_imm = BITS(sht_oper, 8, 11);
- unsigned int shifter_operand = ROTATE_RIGHT_32(immed_8, rotate_imm * 2);
- if (rotate_imm == 0)
- cpu->shifter_carry_out = cpu->CFlag;
- else
- cpu->shifter_carry_out = BIT(shifter_operand, 31);
- return shifter_operand;
-}
-
-static unsigned int DPO(Register)(ARMul_State* cpu, unsigned int sht_oper) {
- unsigned int rm = CHECK_READ_REG15(cpu, RM);
- unsigned int shifter_operand = rm;
- cpu->shifter_carry_out = cpu->CFlag;
- return shifter_operand;
-}
-
-static unsigned int DPO(LogicalShiftLeftByImmediate)(ARMul_State* cpu, unsigned int sht_oper) {
- int shift_imm = BITS(sht_oper, 7, 11);
- unsigned int rm = CHECK_READ_REG15(cpu, RM);
- unsigned int shifter_operand;
- if (shift_imm == 0) {
- shifter_operand = rm;
- cpu->shifter_carry_out = cpu->CFlag;
- } else {
- shifter_operand = rm << shift_imm;
- cpu->shifter_carry_out = BIT(rm, 32 - shift_imm);
- }
- return shifter_operand;
-}
-
-static unsigned int DPO(LogicalShiftLeftByRegister)(ARMul_State* cpu, unsigned int sht_oper) {
- int shifter_operand;
- unsigned int rm = CHECK_READ_REG15(cpu, RM);
- unsigned int rs = CHECK_READ_REG15(cpu, RS);
- if (BITS(rs, 0, 7) == 0) {
- shifter_operand = rm;
- cpu->shifter_carry_out = cpu->CFlag;
- } else if (BITS(rs, 0, 7) < 32) {
- shifter_operand = rm << BITS(rs, 0, 7);
- cpu->shifter_carry_out = BIT(rm, 32 - BITS(rs, 0, 7));
- } else if (BITS(rs, 0, 7) == 32) {
- shifter_operand = 0;
- cpu->shifter_carry_out = BIT(rm, 0);
- } else {
- shifter_operand = 0;
- cpu->shifter_carry_out = 0;
- }
- return shifter_operand;
-}
-
-static unsigned int DPO(LogicalShiftRightByImmediate)(ARMul_State* cpu, unsigned int sht_oper) {
- unsigned int rm = CHECK_READ_REG15(cpu, RM);
- unsigned int shifter_operand;
- int shift_imm = BITS(sht_oper, 7, 11);
- if (shift_imm == 0) {
- shifter_operand = 0;
- cpu->shifter_carry_out = BIT(rm, 31);
- } else {
- shifter_operand = rm >> shift_imm;
- cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
- }
- return shifter_operand;
-}
-
-static unsigned int DPO(LogicalShiftRightByRegister)(ARMul_State* cpu, unsigned int sht_oper) {
- unsigned int rs = CHECK_READ_REG15(cpu, RS);
- unsigned int rm = CHECK_READ_REG15(cpu, RM);
- unsigned int shifter_operand;
- if (BITS(rs, 0, 7) == 0) {
- shifter_operand = rm;
- cpu->shifter_carry_out = cpu->CFlag;
- } else if (BITS(rs, 0, 7) < 32) {
- shifter_operand = rm >> BITS(rs, 0, 7);
- cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 7) - 1);
- } else if (BITS(rs, 0, 7) == 32) {
- shifter_operand = 0;
- cpu->shifter_carry_out = BIT(rm, 31);
- } else {
- shifter_operand = 0;
- cpu->shifter_carry_out = 0;
- }
- return shifter_operand;
-}
-
-static unsigned int DPO(ArithmeticShiftRightByImmediate)(ARMul_State* cpu, unsigned int sht_oper) {
- unsigned int rm = CHECK_READ_REG15(cpu, RM);
- unsigned int shifter_operand;
- int shift_imm = BITS(sht_oper, 7, 11);
- if (shift_imm == 0) {
- if (BIT(rm, 31) == 0)
- shifter_operand = 0;
- else
- shifter_operand = 0xFFFFFFFF;
- cpu->shifter_carry_out = BIT(rm, 31);
- } else {
- shifter_operand = static_cast<int>(rm) >> shift_imm;
- cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
- }
- return shifter_operand;
-}
-
-static unsigned int DPO(ArithmeticShiftRightByRegister)(ARMul_State* cpu, unsigned int sht_oper) {
- unsigned int rs = CHECK_READ_REG15(cpu, RS);
- unsigned int rm = CHECK_READ_REG15(cpu, RM);
- unsigned int shifter_operand;
- if (BITS(rs, 0, 7) == 0) {
- shifter_operand = rm;
- cpu->shifter_carry_out = cpu->CFlag;
- } else if (BITS(rs, 0, 7) < 32) {
- shifter_operand = static_cast<int>(rm) >> BITS(rs, 0, 7);
- cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 7) - 1);
- } else {
- if (BIT(rm, 31) == 0)
- shifter_operand = 0;
- else
- shifter_operand = 0xffffffff;
- cpu->shifter_carry_out = BIT(rm, 31);
- }
- return shifter_operand;
-}
-
-static unsigned int DPO(RotateRightByImmediate)(ARMul_State* cpu, unsigned int sht_oper) {
- unsigned int shifter_operand;
- unsigned int rm = CHECK_READ_REG15(cpu, RM);
- int shift_imm = BITS(sht_oper, 7, 11);
- if (shift_imm == 0) {
- shifter_operand = (cpu->CFlag << 31) | (rm >> 1);
- cpu->shifter_carry_out = BIT(rm, 0);
- } else {
- shifter_operand = ROTATE_RIGHT_32(rm, shift_imm);
- cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
- }
- return shifter_operand;
-}
-
-static unsigned int DPO(RotateRightByRegister)(ARMul_State* cpu, unsigned int sht_oper) {
- unsigned int rm = CHECK_READ_REG15(cpu, RM);
- unsigned int rs = CHECK_READ_REG15(cpu, RS);
- unsigned int shifter_operand;
- if (BITS(rs, 0, 7) == 0) {
- shifter_operand = rm;
- cpu->shifter_carry_out = cpu->CFlag;
- } else if (BITS(rs, 0, 4) == 0) {
- shifter_operand = rm;
- cpu->shifter_carry_out = BIT(rm, 31);
- } else {
- shifter_operand = ROTATE_RIGHT_32(rm, BITS(rs, 0, 4));
- cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 4) - 1);
- }
- return shifter_operand;
-}
-
-#define DEBUG_MSG \
- LOG_DEBUG(Core_ARM, "inst is %x", inst); \
- CITRA_IGNORE_EXIT(0)
-
-#define LnSWoUB(s) glue(LnSWoUB, s)
-#define MLnS(s) glue(MLnS, s)
-#define LdnStM(s) glue(LdnStM, s)
-
-#define W_BIT BIT(inst, 21)
-#define U_BIT BIT(inst, 23)
-#define I_BIT BIT(inst, 25)
-#define P_BIT BIT(inst, 24)
-#define OFFSET_12 BITS(inst, 0, 11)
-
-static void LnSWoUB(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int addr;
-
- if (U_BIT)
- addr = CHECK_READ_REG15_WA(cpu, Rn) + OFFSET_12;
- else
- addr = CHECK_READ_REG15_WA(cpu, Rn) - OFFSET_12;
-
- virt_addr = addr;
-}
-
-static void LnSWoUB(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int Rm = BITS(inst, 0, 3);
- unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
- unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
- unsigned int addr;
-
- if (U_BIT)
- addr = rn + rm;
- else
- addr = rn - rm;
-
- virt_addr = addr;
-}
-
-static void LnSWoUB(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst,
- unsigned int& virt_addr) {
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn);
-
- if (U_BIT)
- cpu->Reg[Rn] += OFFSET_12;
- else
- cpu->Reg[Rn] -= OFFSET_12;
-
- virt_addr = addr;
-}
-
-static void LnSWoUB(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst,
- unsigned int& virt_addr) {
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int addr;
-
- if (U_BIT)
- addr = CHECK_READ_REG15_WA(cpu, Rn) + OFFSET_12;
- else
- addr = CHECK_READ_REG15_WA(cpu, Rn) - OFFSET_12;
-
- virt_addr = addr;
-
- if (CondPassed(cpu, BITS(inst, 28, 31)))
- cpu->Reg[Rn] = addr;
-}
-
-static void MLnS(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
- unsigned int addr;
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int Rm = BITS(inst, 0, 3);
- unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
- unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
-
- if (U_BIT)
- addr = rn + rm;
- else
- addr = rn - rm;
-
- virt_addr = addr;
-
- if (CondPassed(cpu, BITS(inst, 28, 31)))
- cpu->Reg[Rn] = addr;
-}
-
-static void LnSWoUB(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst,
- unsigned int& virt_addr) {
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int Rm = BITS(inst, 0, 3);
- unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
- unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
- unsigned int addr;
-
- if (U_BIT)
- addr = rn + rm;
- else
- addr = rn - rm;
-
- virt_addr = addr;
-
- if (CondPassed(cpu, BITS(inst, 28, 31))) {
- cpu->Reg[Rn] = addr;
- }
-}
-
-static void LnSWoUB(ScaledRegisterPreIndexed)(ARMul_State* cpu, unsigned int inst,
- unsigned int& virt_addr) {
- unsigned int shift = BITS(inst, 5, 6);
- unsigned int shift_imm = BITS(inst, 7, 11);
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int Rm = BITS(inst, 0, 3);
- unsigned int index = 0;
- unsigned int addr;
- unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
- unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
-
- switch (shift) {
- case 0:
- index = rm << shift_imm;
- break;
- case 1:
- if (shift_imm == 0) {
- index = 0;
- } else {
- index = rm >> shift_imm;
- }
- break;
- case 2:
- if (shift_imm == 0) { // ASR #32
- if (BIT(rm, 31) == 1)
- index = 0xFFFFFFFF;
- else
- index = 0;
- } else {
- index = static_cast<int>(rm) >> shift_imm;
- }
- break;
- case 3:
- if (shift_imm == 0) {
- index = (cpu->CFlag << 31) | (rm >> 1);
- } else {
- index = ROTATE_RIGHT_32(rm, shift_imm);
- }
- break;
- }
-
- if (U_BIT)
- addr = rn + index;
- else
- addr = rn - index;
-
- virt_addr = addr;
-
- if (CondPassed(cpu, BITS(inst, 28, 31)))
- cpu->Reg[Rn] = addr;
-}
-
-static void LnSWoUB(ScaledRegisterPostIndexed)(ARMul_State* cpu, unsigned int inst,
- unsigned int& virt_addr) {
- unsigned int shift = BITS(inst, 5, 6);
- unsigned int shift_imm = BITS(inst, 7, 11);
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int Rm = BITS(inst, 0, 3);
- unsigned int index = 0;
- unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn);
- unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
-
- switch (shift) {
- case 0:
- index = rm << shift_imm;
- break;
- case 1:
- if (shift_imm == 0) {
- index = 0;
- } else {
- index = rm >> shift_imm;
- }
- break;
- case 2:
- if (shift_imm == 0) { // ASR #32
- if (BIT(rm, 31) == 1)
- index = 0xFFFFFFFF;
- else
- index = 0;
- } else {
- index = static_cast<int>(rm) >> shift_imm;
- }
- break;
- case 3:
- if (shift_imm == 0) {
- index = (cpu->CFlag << 31) | (rm >> 1);
- } else {
- index = ROTATE_RIGHT_32(rm, shift_imm);
- }
- break;
- }
-
- virt_addr = addr;
-
- if (CondPassed(cpu, BITS(inst, 28, 31))) {
- if (U_BIT)
- cpu->Reg[Rn] += index;
- else
- cpu->Reg[Rn] -= index;
- }
-}
-
-static void LnSWoUB(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst,
- unsigned int& virt_addr) {
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int Rm = BITS(inst, 0, 3);
- unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
-
- virt_addr = CHECK_READ_REG15_WA(cpu, Rn);
-
- if (CondPassed(cpu, BITS(inst, 28, 31))) {
- if (U_BIT) {
- cpu->Reg[Rn] += rm;
- } else {
- cpu->Reg[Rn] -= rm;
- }
- }
-}
-
-static void MLnS(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
- unsigned int immedL = BITS(inst, 0, 3);
- unsigned int immedH = BITS(inst, 8, 11);
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int addr;
-
- unsigned int offset_8 = (immedH << 4) | immedL;
-
- if (U_BIT)
- addr = CHECK_READ_REG15_WA(cpu, Rn) + offset_8;
- else
- addr = CHECK_READ_REG15_WA(cpu, Rn) - offset_8;
-
- virt_addr = addr;
-}
-
-static void MLnS(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
- unsigned int addr;
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int Rm = BITS(inst, 0, 3);
- unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
- unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
-
- if (U_BIT)
- addr = rn + rm;
- else
- addr = rn - rm;
-
- virt_addr = addr;
-}
-
-static void MLnS(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst,
- unsigned int& virt_addr) {
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int immedH = BITS(inst, 8, 11);
- unsigned int immedL = BITS(inst, 0, 3);
- unsigned int addr;
- unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
- unsigned int offset_8 = (immedH << 4) | immedL;
-
- if (U_BIT)
- addr = rn + offset_8;
- else
- addr = rn - offset_8;
-
- virt_addr = addr;
-
- if (CondPassed(cpu, BITS(inst, 28, 31)))
- cpu->Reg[Rn] = addr;
-}
-
-static void MLnS(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst,
- unsigned int& virt_addr) {
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int immedH = BITS(inst, 8, 11);
- unsigned int immedL = BITS(inst, 0, 3);
- unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
-
- virt_addr = rn;
-
- if (CondPassed(cpu, BITS(inst, 28, 31))) {
- unsigned int offset_8 = (immedH << 4) | immedL;
- if (U_BIT)
- rn += offset_8;
- else
- rn -= offset_8;
-
- cpu->Reg[Rn] = rn;
- }
-}
-
-static void MLnS(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst,
- unsigned int& virt_addr) {
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int Rm = BITS(inst, 0, 3);
- unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
-
- virt_addr = CHECK_READ_REG15_WA(cpu, Rn);
-
- if (CondPassed(cpu, BITS(inst, 28, 31))) {
- if (U_BIT)
- cpu->Reg[Rn] += rm;
- else
- cpu->Reg[Rn] -= rm;
- }
-}
-
-static void LdnStM(DecrementBefore)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int i = BITS(inst, 0, 15);
- int count = 0;
-
- while (i) {
- if (i & 1)
- count++;
- i = i >> 1;
- }
-
- virt_addr = CHECK_READ_REG15_WA(cpu, Rn) - count * 4;
-
- if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21))
- cpu->Reg[Rn] -= count * 4;
-}
-
-static void LdnStM(IncrementBefore)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int i = BITS(inst, 0, 15);
- int count = 0;
-
- while (i) {
- if (i & 1)
- count++;
- i = i >> 1;
- }
-
- virt_addr = CHECK_READ_REG15_WA(cpu, Rn) + 4;
-
- if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21))
- cpu->Reg[Rn] += count * 4;
-}
-
-static void LdnStM(IncrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int i = BITS(inst, 0, 15);
- int count = 0;
-
- while (i) {
- if (i & 1)
- count++;
- i = i >> 1;
- }
-
- virt_addr = CHECK_READ_REG15_WA(cpu, Rn);
-
- if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21))
- cpu->Reg[Rn] += count * 4;
-}
-
-static void LdnStM(DecrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int i = BITS(inst, 0, 15);
- int count = 0;
- while (i) {
- if (i & 1)
- count++;
- i = i >> 1;
- }
- unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
- unsigned int start_addr = rn - count * 4 + 4;
-
- virt_addr = start_addr;
-
- if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
- cpu->Reg[Rn] -= count * 4;
- }
-}
-
-static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst,
- unsigned int& virt_addr) {
- unsigned int shift = BITS(inst, 5, 6);
- unsigned int shift_imm = BITS(inst, 7, 11);
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int Rm = BITS(inst, 0, 3);
- unsigned int index = 0;
- unsigned int addr;
- unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
- unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
-
- switch (shift) {
- case 0:
- index = rm << shift_imm;
- break;
- case 1:
- if (shift_imm == 0) {
- index = 0;
- } else {
- index = rm >> shift_imm;
- }
- break;
- case 2:
- if (shift_imm == 0) { // ASR #32
- if (BIT(rm, 31) == 1)
- index = 0xFFFFFFFF;
- else
- index = 0;
- } else {
- index = static_cast<int>(rm) >> shift_imm;
- }
- break;
- case 3:
- if (shift_imm == 0) {
- index = (cpu->CFlag << 31) | (rm >> 1);
- } else {
- index = ROTATE_RIGHT_32(rm, shift_imm);
- }
- break;
- }
-
- if (U_BIT) {
- addr = rn + index;
- } else
- addr = rn - index;
-
- virt_addr = addr;
-}
-
-shtop_fp_t GetShifterOp(unsigned int inst) {
- if (BIT(inst, 25)) {
- return DPO(Immediate);
- } else if (BITS(inst, 4, 11) == 0) {
- return DPO(Register);
- } else if (BITS(inst, 4, 6) == 0) {
- return DPO(LogicalShiftLeftByImmediate);
- } else if (BITS(inst, 4, 7) == 1) {
- return DPO(LogicalShiftLeftByRegister);
- } else if (BITS(inst, 4, 6) == 2) {
- return DPO(LogicalShiftRightByImmediate);
- } else if (BITS(inst, 4, 7) == 3) {
- return DPO(LogicalShiftRightByRegister);
- } else if (BITS(inst, 4, 6) == 4) {
- return DPO(ArithmeticShiftRightByImmediate);
- } else if (BITS(inst, 4, 7) == 5) {
- return DPO(ArithmeticShiftRightByRegister);
- } else if (BITS(inst, 4, 6) == 6) {
- return DPO(RotateRightByImmediate);
- } else if (BITS(inst, 4, 7) == 7) {
- return DPO(RotateRightByRegister);
- }
- return nullptr;
-}
-
-get_addr_fp_t GetAddressingOp(unsigned int inst) {
- if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 0) {
- return LnSWoUB(ImmediateOffset);
- } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) {
- return LnSWoUB(RegisterOffset);
- } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) {
- return LnSWoUB(ScaledRegisterOffset);
- } else if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 1) {
- return LnSWoUB(ImmediatePreIndexed);
- } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 1 && BITS(inst, 4, 11) == 0) {
- return LnSWoUB(RegisterPreIndexed);
- } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 1 && BIT(inst, 4) == 0) {
- return LnSWoUB(ScaledRegisterPreIndexed);
- } else if (BITS(inst, 24, 27) == 4 && BIT(inst, 21) == 0) {
- return LnSWoUB(ImmediatePostIndexed);
- } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) {
- return LnSWoUB(RegisterPostIndexed);
- } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) {
- return LnSWoUB(ScaledRegisterPostIndexed);
- } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 &&
- BIT(inst, 4) == 1) {
- return MLnS(ImmediateOffset);
- } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 &&
- BIT(inst, 4) == 1) {
- return MLnS(RegisterOffset);
- } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 3 && BIT(inst, 7) == 1 &&
- BIT(inst, 4) == 1) {
- return MLnS(ImmediatePreIndexed);
- } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 1 && BIT(inst, 7) == 1 &&
- BIT(inst, 4) == 1) {
- return MLnS(RegisterPreIndexed);
- } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 &&
- BIT(inst, 4) == 1) {
- return MLnS(ImmediatePostIndexed);
- } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 &&
- BIT(inst, 4) == 1) {
- return MLnS(RegisterPostIndexed);
- } else if (BITS(inst, 23, 27) == 0x11) {
- return LdnStM(IncrementAfter);
- } else if (BITS(inst, 23, 27) == 0x13) {
- return LdnStM(IncrementBefore);
- } else if (BITS(inst, 23, 27) == 0x10) {
- return LdnStM(DecrementAfter);
- } else if (BITS(inst, 23, 27) == 0x12) {
- return LdnStM(DecrementBefore);
- }
- return nullptr;
-}
-
-// Specialized for LDRT, LDRBT, STRT, and STRBT, which have specific addressing mode requirements
-get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst) {
- if (BITS(inst, 25, 27) == 2) {
- return LnSWoUB(ImmediatePostIndexed);
- } else if (BITS(inst, 25, 27) == 3) {
- return LnSWoUB(ScaledRegisterPostIndexed);
- }
- // Reaching this would indicate the thumb version
- // of this instruction, however the 3DS CPU doesn't
- // support this variant (the 3DS CPU is only ARMv6K,
- // while this variant is added in ARMv6T2).
- // So it's sufficient for citra to not implement this.
- return nullptr;
-}
-
-enum { FETCH_SUCCESS, FETCH_FAILURE };
-
-static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_inst, u32* inst_size,
- ARM_INST_PTR* ptr_inst_base) {
- // Check if in Thumb mode
- ThumbDecodeStatus ret = TranslateThumbInstruction(addr, inst, arm_inst, inst_size);
- if (ret == ThumbDecodeStatus::BRANCH) {
- int inst_index;
- int table_length = static_cast<int>(arm_instruction_trans_len);
- u32 tinstr = GetThumbInstruction(inst, addr);
-
- switch ((tinstr & 0xF800) >> 11) {
- case 26:
- case 27:
- if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)) {
- inst_index = table_length - 4;
- *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
- } else {
- LOG_ERROR(Core_ARM, "thumb decoder error");
- }
- break;
- case 28:
- // Branch 2, unconditional branch
- inst_index = table_length - 5;
- *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
- break;
-
- case 8:
- case 29:
- // For BLX 1 thumb instruction
- inst_index = table_length - 1;
- *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
- break;
- case 30:
- // For BL 1 thumb instruction
- inst_index = table_length - 3;
- *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
- break;
- case 31:
- // For BL 2 thumb instruction
- inst_index = table_length - 2;
- *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
- break;
- default:
- ret = ThumbDecodeStatus::UNDEFINED;
- break;
- }
- }
- return ret;
-}
-
-enum { KEEP_GOING, FETCH_EXCEPTION };
-
-MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64));
-
-static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr,
- ARM_INST_PTR& inst_base) {
- u32 inst_size = 4;
- u32 inst = Memory::Read32(phys_addr & 0xFFFFFFFC);
-
- // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM
- // instruction
- if (cpu->TFlag) {
- u32 arm_inst;
- ThumbDecodeStatus state =
- DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base);
-
- // We have translated the Thumb branch instruction in the Thumb decoder
- if (state == ThumbDecodeStatus::BRANCH) {
- return inst_size;
- }
- inst = arm_inst;
- }
-
- int idx;
- if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) {
- LOG_ERROR(Core_ARM, "Decode failure.\tPC: [0x%08" PRIX32 "]\tInstruction: %08" PRIX32,
- phys_addr, inst);
- LOG_ERROR(Core_ARM, "cpsr=0x%" PRIX32 ", cpu->TFlag=%d, r15=0x%08" PRIX32, cpu->Cpsr,
- cpu->TFlag, cpu->Reg[15]);
- CITRA_IGNORE_EXIT(-1);
- }
- inst_base = arm_instruction_trans[idx](inst, idx);
-
- return inst_size;
-}
-
-static int InterpreterTranslateBlock(ARMul_State* cpu, std::size_t& bb_start, u32 addr) {
- MICROPROFILE_SCOPE(DynCom_Decode);
-
- // Decode instruction, get index
- // Allocate memory and init InsCream
- // Go on next, until terminal instruction
- // Save start addr of basicblock in CreamCache
- ARM_INST_PTR inst_base = nullptr;
- TransExtData ret = TransExtData::NON_BRANCH;
- int size = 0; // instruction size of basic block
- bb_start = trans_cache_buf_top;
-
- u32 phys_addr = addr;
- u32 pc_start = cpu->Reg[15];
-
- while (ret == TransExtData::NON_BRANCH) {
- unsigned int inst_size = InterpreterTranslateInstruction(cpu, phys_addr, inst_base);
-
- size++;
-
- phys_addr += inst_size;
-
- if ((phys_addr & 0xfff) == 0) {
- inst_base->br = TransExtData::END_OF_PAGE;
- }
- ret = inst_base->br;
- };
-
- cpu->instruction_cache[pc_start] = bb_start;
-
- return KEEP_GOING;
-}
-
-static int InterpreterTranslateSingle(ARMul_State* cpu, std::size_t& bb_start, u32 addr) {
- MICROPROFILE_SCOPE(DynCom_Decode);
-
- ARM_INST_PTR inst_base = nullptr;
- bb_start = trans_cache_buf_top;
-
- u32 phys_addr = addr;
- u32 pc_start = cpu->Reg[15];
-
- InterpreterTranslateInstruction(cpu, phys_addr, inst_base);
-
- if (inst_base->br == TransExtData::NON_BRANCH) {
- inst_base->br = TransExtData::SINGLE_STEP;
- }
-
- cpu->instruction_cache[pc_start] = bb_start;
-
- return KEEP_GOING;
-}
-
-static int clz(unsigned int x) {
- int n;
- if (x == 0)
- return (32);
- n = 1;
- if ((x >> 16) == 0) {
- n = n + 16;
- x = x << 16;
- }
- if ((x >> 24) == 0) {
- n = n + 8;
- x = x << 8;
- }
- if ((x >> 28) == 0) {
- n = n + 4;
- x = x << 4;
- }
- if ((x >> 30) == 0) {
- n = n + 2;
- x = x << 2;
- }
- n = n - (x >> 31);
- return n;
-}
-
-MICROPROFILE_DEFINE(DynCom_Execute, "DynCom", "Execute", MP_RGB(255, 0, 0));
-
-unsigned InterpreterMainLoop(ARMul_State* cpu) {
- MICROPROFILE_SCOPE(DynCom_Execute);
-
- GDBStub::BreakpointAddress breakpoint_data;
-
-#undef RM
-#undef RS
-
-#define CRn inst_cream->crn
-#define OPCODE_1 inst_cream->opcode_1
-#define OPCODE_2 inst_cream->opcode_2
-#define CRm inst_cream->crm
-#define RD cpu->Reg[inst_cream->Rd]
-#define RD2 cpu->Reg[inst_cream->Rd + 1]
-#define RN cpu->Reg[inst_cream->Rn]
-#define RM cpu->Reg[inst_cream->Rm]
-#define RS cpu->Reg[inst_cream->Rs]
-#define RDHI cpu->Reg[inst_cream->RdHi]
-#define RDLO cpu->Reg[inst_cream->RdLo]
-#define LINK_RTN_ADDR (cpu->Reg[14] = cpu->Reg[15] + 4)
-#define SET_PC (cpu->Reg[15] = cpu->Reg[15] + 8 + inst_cream->signed_immed_24)
-#define SHIFTER_OPERAND inst_cream->shtop_func(cpu, inst_cream->shifter_operand)
-
-#define FETCH_INST \
- if (inst_base->br != TransExtData::NON_BRANCH) \
- goto DISPATCH; \
- inst_base = (arm_inst*)&trans_cache_buf[ptr]
-
-#define INC_PC(l) ptr += sizeof(arm_inst) + l
-#define INC_PC_STUB ptr += sizeof(arm_inst)
-
-#define GDB_BP_CHECK \
- cpu->Cpsr &= ~(1 << 5); \
- cpu->Cpsr |= cpu->TFlag << 5; \
- if (GDBStub::IsServerEnabled()) { \
- if (GDBStub::IsMemoryBreak() || (breakpoint_data.type != GDBStub::BreakpointType::None && \
- PC == breakpoint_data.address)) { \
- GDBStub::Break(); \
- goto END; \
- } \
- }
-
-// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a
-// clunky switch statement.
-#if defined __GNUC__ || defined __clang__
-#define GOTO_NEXT_INST \
- GDB_BP_CHECK; \
- if (num_instrs >= cpu->NumInstrsToExecute) \
- goto END; \
- num_instrs++; \
- goto* InstLabel[inst_base->idx]
-#else
-#define GOTO_NEXT_INST \
- GDB_BP_CHECK; \
- if (num_instrs >= cpu->NumInstrsToExecute) \
- goto END; \
- num_instrs++; \
- switch (inst_base->idx) { \
- case 0: \
- goto VMLA_INST; \
- case 1: \
- goto VMLS_INST; \
- case 2: \
- goto VNMLA_INST; \
- case 3: \
- goto VNMLS_INST; \
- case 4: \
- goto VNMUL_INST; \
- case 5: \
- goto VMUL_INST; \
- case 6: \
- goto VADD_INST; \
- case 7: \
- goto VSUB_INST; \
- case 8: \
- goto VDIV_INST; \
- case 9: \
- goto VMOVI_INST; \
- case 10: \
- goto VMOVR_INST; \
- case 11: \
- goto VABS_INST; \
- case 12: \
- goto VNEG_INST; \
- case 13: \
- goto VSQRT_INST; \
- case 14: \
- goto VCMP_INST; \
- case 15: \
- goto VCMP2_INST; \
- case 16: \
- goto VCVTBDS_INST; \
- case 17: \
- goto VCVTBFF_INST; \
- case 18: \
- goto VCVTBFI_INST; \
- case 19: \
- goto VMOVBRS_INST; \
- case 20: \
- goto VMSR_INST; \
- case 21: \
- goto VMOVBRC_INST; \
- case 22: \
- goto VMRS_INST; \
- case 23: \
- goto VMOVBCR_INST; \
- case 24: \
- goto VMOVBRRSS_INST; \
- case 25: \
- goto VMOVBRRD_INST; \
- case 26: \
- goto VSTR_INST; \
- case 27: \
- goto VPUSH_INST; \
- case 28: \
- goto VSTM_INST; \
- case 29: \
- goto VPOP_INST; \
- case 30: \
- goto VLDR_INST; \
- case 31: \
- goto VLDM_INST; \
- case 32: \
- goto SRS_INST; \
- case 33: \
- goto RFE_INST; \
- case 34: \
- goto BKPT_INST; \
- case 35: \
- goto BLX_INST; \
- case 36: \
- goto CPS_INST; \
- case 37: \
- goto PLD_INST; \
- case 38: \
- goto SETEND_INST; \
- case 39: \
- goto CLREX_INST; \
- case 40: \
- goto REV16_INST; \
- case 41: \
- goto USAD8_INST; \
- case 42: \
- goto SXTB_INST; \
- case 43: \
- goto UXTB_INST; \
- case 44: \
- goto SXTH_INST; \
- case 45: \
- goto SXTB16_INST; \
- case 46: \
- goto UXTH_INST; \
- case 47: \
- goto UXTB16_INST; \
- case 48: \
- goto CPY_INST; \
- case 49: \
- goto UXTAB_INST; \
- case 50: \
- goto SSUB8_INST; \
- case 51: \
- goto SHSUB8_INST; \
- case 52: \
- goto SSUBADDX_INST; \
- case 53: \
- goto STREX_INST; \
- case 54: \
- goto STREXB_INST; \
- case 55: \
- goto SWP_INST; \
- case 56: \
- goto SWPB_INST; \
- case 57: \
- goto SSUB16_INST; \
- case 58: \
- goto SSAT16_INST; \
- case 59: \
- goto SHSUBADDX_INST; \
- case 60: \
- goto QSUBADDX_INST; \
- case 61: \
- goto SHADDSUBX_INST; \
- case 62: \
- goto SHADD8_INST; \
- case 63: \
- goto SHADD16_INST; \
- case 64: \
- goto SEL_INST; \
- case 65: \
- goto SADDSUBX_INST; \
- case 66: \
- goto SADD8_INST; \
- case 67: \
- goto SADD16_INST; \
- case 68: \
- goto SHSUB16_INST; \
- case 69: \
- goto UMAAL_INST; \
- case 70: \
- goto UXTAB16_INST; \
- case 71: \
- goto USUBADDX_INST; \
- case 72: \
- goto USUB8_INST; \
- case 73: \
- goto USUB16_INST; \
- case 74: \
- goto USAT16_INST; \
- case 75: \
- goto USADA8_INST; \
- case 76: \
- goto UQSUBADDX_INST; \
- case 77: \
- goto UQSUB8_INST; \
- case 78: \
- goto UQSUB16_INST; \
- case 79: \
- goto UQADDSUBX_INST; \
- case 80: \
- goto UQADD8_INST; \
- case 81: \
- goto UQADD16_INST; \
- case 82: \
- goto SXTAB_INST; \
- case 83: \
- goto UHSUBADDX_INST; \
- case 84: \
- goto UHSUB8_INST; \
- case 85: \
- goto UHSUB16_INST; \
- case 86: \
- goto UHADDSUBX_INST; \
- case 87: \
- goto UHADD8_INST; \
- case 88: \
- goto UHADD16_INST; \
- case 89: \
- goto UADDSUBX_INST; \
- case 90: \
- goto UADD8_INST; \
- case 91: \
- goto UADD16_INST; \
- case 92: \
- goto SXTAH_INST; \
- case 93: \
- goto SXTAB16_INST; \
- case 94: \
- goto QADD8_INST; \
- case 95: \
- goto BXJ_INST; \
- case 96: \
- goto CLZ_INST; \
- case 97: \
- goto UXTAH_INST; \
- case 98: \
- goto BX_INST; \
- case 99: \
- goto REV_INST; \
- case 100: \
- goto BLX_INST; \
- case 101: \
- goto REVSH_INST; \
- case 102: \
- goto QADD_INST; \
- case 103: \
- goto QADD16_INST; \
- case 104: \
- goto QADDSUBX_INST; \
- case 105: \
- goto LDREX_INST; \
- case 106: \
- goto QDADD_INST; \
- case 107: \
- goto QDSUB_INST; \
- case 108: \
- goto QSUB_INST; \
- case 109: \
- goto LDREXB_INST; \
- case 110: \
- goto QSUB8_INST; \
- case 111: \
- goto QSUB16_INST; \
- case 112: \
- goto SMUAD_INST; \
- case 113: \
- goto SMMUL_INST; \
- case 114: \
- goto SMUSD_INST; \
- case 115: \
- goto SMLSD_INST; \
- case 116: \
- goto SMLSLD_INST; \
- case 117: \
- goto SMMLA_INST; \
- case 118: \
- goto SMMLS_INST; \
- case 119: \
- goto SMLALD_INST; \
- case 120: \
- goto SMLAD_INST; \
- case 121: \
- goto SMLAW_INST; \
- case 122: \
- goto SMULW_INST; \
- case 123: \
- goto PKHTB_INST; \
- case 124: \
- goto PKHBT_INST; \
- case 125: \
- goto SMUL_INST; \
- case 126: \
- goto SMLALXY_INST; \
- case 127: \
- goto SMLA_INST; \
- case 128: \
- goto MCRR_INST; \
- case 129: \
- goto MRRC_INST; \
- case 130: \
- goto CMP_INST; \
- case 131: \
- goto TST_INST; \
- case 132: \
- goto TEQ_INST; \
- case 133: \
- goto CMN_INST; \
- case 134: \
- goto SMULL_INST; \
- case 135: \
- goto UMULL_INST; \
- case 136: \
- goto UMLAL_INST; \
- case 137: \
- goto SMLAL_INST; \
- case 138: \
- goto MUL_INST; \
- case 139: \
- goto MLA_INST; \
- case 140: \
- goto SSAT_INST; \
- case 141: \
- goto USAT_INST; \
- case 142: \
- goto MRS_INST; \
- case 143: \
- goto MSR_INST; \
- case 144: \
- goto AND_INST; \
- case 145: \
- goto BIC_INST; \
- case 146: \
- goto LDM_INST; \
- case 147: \
- goto EOR_INST; \
- case 148: \
- goto ADD_INST; \
- case 149: \
- goto RSB_INST; \
- case 150: \
- goto RSC_INST; \
- case 151: \
- goto SBC_INST; \
- case 152: \
- goto ADC_INST; \
- case 153: \
- goto SUB_INST; \
- case 154: \
- goto ORR_INST; \
- case 155: \
- goto MVN_INST; \
- case 156: \
- goto MOV_INST; \
- case 157: \
- goto STM_INST; \
- case 158: \
- goto LDM_INST; \
- case 159: \
- goto LDRSH_INST; \
- case 160: \
- goto STM_INST; \
- case 161: \
- goto LDM_INST; \
- case 162: \
- goto LDRSB_INST; \
- case 163: \
- goto STRD_INST; \
- case 164: \
- goto LDRH_INST; \
- case 165: \
- goto STRH_INST; \
- case 166: \
- goto LDRD_INST; \
- case 167: \
- goto STRT_INST; \
- case 168: \
- goto STRBT_INST; \
- case 169: \
- goto LDRBT_INST; \
- case 170: \
- goto LDRT_INST; \
- case 171: \
- goto MRC_INST; \
- case 172: \
- goto MCR_INST; \
- case 173: \
- goto MSR_INST; \
- case 174: \
- goto MSR_INST; \
- case 175: \
- goto MSR_INST; \
- case 176: \
- goto MSR_INST; \
- case 177: \
- goto MSR_INST; \
- case 178: \
- goto LDRB_INST; \
- case 179: \
- goto STRB_INST; \
- case 180: \
- goto LDR_INST; \
- case 181: \
- goto LDRCOND_INST; \
- case 182: \
- goto STR_INST; \
- case 183: \
- goto CDP_INST; \
- case 184: \
- goto STC_INST; \
- case 185: \
- goto LDC_INST; \
- case 186: \
- goto LDREXD_INST; \
- case 187: \
- goto STREXD_INST; \
- case 188: \
- goto LDREXH_INST; \
- case 189: \
- goto STREXH_INST; \
- case 190: \
- goto NOP_INST; \
- case 191: \
- goto YIELD_INST; \
- case 192: \
- goto WFE_INST; \
- case 193: \
- goto WFI_INST; \
- case 194: \
- goto SEV_INST; \
- case 195: \
- goto SWI_INST; \
- case 196: \
- goto BBL_INST; \
- case 197: \
- goto B_2_THUMB; \
- case 198: \
- goto B_COND_THUMB; \
- case 199: \
- goto BL_1_THUMB; \
- case 200: \
- goto BL_2_THUMB; \
- case 201: \
- goto BLX_1_THUMB; \
- case 202: \
- goto DISPATCH; \
- case 203: \
- goto INIT_INST_LENGTH; \
- case 204: \
- goto END; \
- }
-#endif
-
-#define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0)
-#define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1)
-#define UPDATE_CFLAG_WITH_SC (cpu->CFlag = cpu->shifter_carry_out)
-
-#define SAVE_NZCVT \
- cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) | (cpu->NFlag << 31) | (cpu->ZFlag << 30) | \
- (cpu->CFlag << 29) | (cpu->VFlag << 28) | (cpu->TFlag << 5)
-#define LOAD_NZCVT \
- cpu->NFlag = (cpu->Cpsr >> 31); \
- cpu->ZFlag = (cpu->Cpsr >> 30) & 1; \
- cpu->CFlag = (cpu->Cpsr >> 29) & 1; \
- cpu->VFlag = (cpu->Cpsr >> 28) & 1; \
- cpu->TFlag = (cpu->Cpsr >> 5) & 1;
-
-#define CurrentModeHasSPSR (cpu->Mode != SYSTEM32MODE) && (cpu->Mode != USER32MODE)
-#define PC (cpu->Reg[15])
-
-// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback
-// to a clunky switch statement.
-#if defined __GNUC__ || defined __clang__
- void* InstLabel[] = {&&VMLA_INST,
- &&VMLS_INST,
- &&VNMLA_INST,
- &&VNMLS_INST,
- &&VNMUL_INST,
- &&VMUL_INST,
- &&VADD_INST,
- &&VSUB_INST,
- &&VDIV_INST,
- &&VMOVI_INST,
- &&VMOVR_INST,
- &&VABS_INST,
- &&VNEG_INST,
- &&VSQRT_INST,
- &&VCMP_INST,
- &&VCMP2_INST,
- &&VCVTBDS_INST,
- &&VCVTBFF_INST,
- &&VCVTBFI_INST,
- &&VMOVBRS_INST,
- &&VMSR_INST,
- &&VMOVBRC_INST,
- &&VMRS_INST,
- &&VMOVBCR_INST,
- &&VMOVBRRSS_INST,
- &&VMOVBRRD_INST,
- &&VSTR_INST,
- &&VPUSH_INST,
- &&VSTM_INST,
- &&VPOP_INST,
- &&VLDR_INST,
- &&VLDM_INST,
-
- &&SRS_INST,
- &&RFE_INST,
- &&BKPT_INST,
- &&BLX_INST,
- &&CPS_INST,
- &&PLD_INST,
- &&SETEND_INST,
- &&CLREX_INST,
- &&REV16_INST,
- &&USAD8_INST,
- &&SXTB_INST,
- &&UXTB_INST,
- &&SXTH_INST,
- &&SXTB16_INST,
- &&UXTH_INST,
- &&UXTB16_INST,
- &&CPY_INST,
- &&UXTAB_INST,
- &&SSUB8_INST,
- &&SHSUB8_INST,
- &&SSUBADDX_INST,
- &&STREX_INST,
- &&STREXB_INST,
- &&SWP_INST,
- &&SWPB_INST,
- &&SSUB16_INST,
- &&SSAT16_INST,
- &&SHSUBADDX_INST,
- &&QSUBADDX_INST,
- &&SHADDSUBX_INST,
- &&SHADD8_INST,
- &&SHADD16_INST,
- &&SEL_INST,
- &&SADDSUBX_INST,
- &&SADD8_INST,
- &&SADD16_INST,
- &&SHSUB16_INST,
- &&UMAAL_INST,
- &&UXTAB16_INST,
- &&USUBADDX_INST,
- &&USUB8_INST,
- &&USUB16_INST,
- &&USAT16_INST,
- &&USADA8_INST,
- &&UQSUBADDX_INST,
- &&UQSUB8_INST,
- &&UQSUB16_INST,
- &&UQADDSUBX_INST,
- &&UQADD8_INST,
- &&UQADD16_INST,
- &&SXTAB_INST,
- &&UHSUBADDX_INST,
- &&UHSUB8_INST,
- &&UHSUB16_INST,
- &&UHADDSUBX_INST,
- &&UHADD8_INST,
- &&UHADD16_INST,
- &&UADDSUBX_INST,
- &&UADD8_INST,
- &&UADD16_INST,
- &&SXTAH_INST,
- &&SXTAB16_INST,
- &&QADD8_INST,
- &&BXJ_INST,
- &&CLZ_INST,
- &&UXTAH_INST,
- &&BX_INST,
- &&REV_INST,
- &&BLX_INST,
- &&REVSH_INST,
- &&QADD_INST,
- &&QADD16_INST,
- &&QADDSUBX_INST,
- &&LDREX_INST,
- &&QDADD_INST,
- &&QDSUB_INST,
- &&QSUB_INST,
- &&LDREXB_INST,
- &&QSUB8_INST,
- &&QSUB16_INST,
- &&SMUAD_INST,
- &&SMMUL_INST,
- &&SMUSD_INST,
- &&SMLSD_INST,
- &&SMLSLD_INST,
- &&SMMLA_INST,
- &&SMMLS_INST,
- &&SMLALD_INST,
- &&SMLAD_INST,
- &&SMLAW_INST,
- &&SMULW_INST,
- &&PKHTB_INST,
- &&PKHBT_INST,
- &&SMUL_INST,
- &&SMLALXY_INST,
- &&SMLA_INST,
- &&MCRR_INST,
- &&MRRC_INST,
- &&CMP_INST,
- &&TST_INST,
- &&TEQ_INST,
- &&CMN_INST,
- &&SMULL_INST,
- &&UMULL_INST,
- &&UMLAL_INST,
- &&SMLAL_INST,
- &&MUL_INST,
- &&MLA_INST,
- &&SSAT_INST,
- &&USAT_INST,
- &&MRS_INST,
- &&MSR_INST,
- &&AND_INST,
- &&BIC_INST,
- &&LDM_INST,
- &&EOR_INST,
- &&ADD_INST,
- &&RSB_INST,
- &&RSC_INST,
- &&SBC_INST,
- &&ADC_INST,
- &&SUB_INST,
- &&ORR_INST,
- &&MVN_INST,
- &&MOV_INST,
- &&STM_INST,
- &&LDM_INST,
- &&LDRSH_INST,
- &&STM_INST,
- &&LDM_INST,
- &&LDRSB_INST,
- &&STRD_INST,
- &&LDRH_INST,
- &&STRH_INST,
- &&LDRD_INST,
- &&STRT_INST,
- &&STRBT_INST,
- &&LDRBT_INST,
- &&LDRT_INST,
- &&MRC_INST,
- &&MCR_INST,
- &&MSR_INST,
- &&MSR_INST,
- &&MSR_INST,
- &&MSR_INST,
- &&MSR_INST,
- &&LDRB_INST,
- &&STRB_INST,
- &&LDR_INST,
- &&LDRCOND_INST,
- &&STR_INST,
- &&CDP_INST,
- &&STC_INST,
- &&LDC_INST,
- &&LDREXD_INST,
- &&STREXD_INST,
- &&LDREXH_INST,
- &&STREXH_INST,
- &&NOP_INST,
- &&YIELD_INST,
- &&WFE_INST,
- &&WFI_INST,
- &&SEV_INST,
- &&SWI_INST,
- &&BBL_INST,
- &&B_2_THUMB,
- &&B_COND_THUMB,
- &&BL_1_THUMB,
- &&BL_2_THUMB,
- &&BLX_1_THUMB,
- &&DISPATCH,
- &&INIT_INST_LENGTH,
- &&END};
-#endif
- arm_inst* inst_base;
- unsigned int addr;
- unsigned int num_instrs = 0;
-
- std::size_t ptr;
-
- LOAD_NZCVT;
-DISPATCH : {
- if (!cpu->NirqSig) {
- if (!(cpu->Cpsr & 0x80)) {
- goto END;
- }
- }
-
- if (cpu->TFlag)
- cpu->Reg[15] &= 0xfffffffe;
- else
- cpu->Reg[15] &= 0xfffffffc;
-
- // Find the cached instruction cream, otherwise translate it...
- auto itr = cpu->instruction_cache.find(cpu->Reg[15]);
- if (itr != cpu->instruction_cache.end()) {
- ptr = itr->second;
- } else if (cpu->NumInstrsToExecute != 1) {
- if (InterpreterTranslateBlock(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
- goto END;
- } else {
- if (InterpreterTranslateSingle(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
- goto END;
- }
-
- // Find breakpoint if one exists within the block
- if (GDBStub::IsConnected()) {
- breakpoint_data =
- GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute);
- }
-
- inst_base = (arm_inst*)&trans_cache_buf[ptr];
- GOTO_NEXT_INST;
-}
-ADC_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- adc_inst* const inst_cream = (adc_inst*)inst_base->component;
-
- u32 rn_val = RN;
- if (inst_cream->Rn == 15)
- rn_val += 2 * cpu->GetInstructionSize();
-
- bool carry;
- bool overflow;
- RD = AddWithCarry(rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
-
- if (inst_cream->S && (inst_cream->Rd == 15)) {
- if (CurrentModeHasSPSR) {
- cpu->Cpsr = cpu->Spsr_copy;
- cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
- LOAD_NZCVT;
- }
- } else if (inst_cream->S) {
- UPDATE_NFLAG(RD);
- UPDATE_ZFLAG(RD);
- cpu->CFlag = carry;
- cpu->VFlag = overflow;
- }
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(adc_inst));
- goto DISPATCH;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(adc_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-ADD_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- add_inst* const inst_cream = (add_inst*)inst_base->component;
-
- u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn);
-
- bool carry;
- bool overflow;
- RD = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
-
- if (inst_cream->S && (inst_cream->Rd == 15)) {
- if (CurrentModeHasSPSR) {
- cpu->Cpsr = cpu->Spsr_copy;
- cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
- LOAD_NZCVT;
- }
- } else if (inst_cream->S) {
- UPDATE_NFLAG(RD);
- UPDATE_ZFLAG(RD);
- cpu->CFlag = carry;
- cpu->VFlag = overflow;
- }
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(add_inst));
- goto DISPATCH;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(add_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-AND_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- and_inst* const inst_cream = (and_inst*)inst_base->component;
-
- u32 lop = RN;
- u32 rop = SHIFTER_OPERAND;
-
- if (inst_cream->Rn == 15)
- lop += 2 * cpu->GetInstructionSize();
-
- RD = lop & rop;
-
- if (inst_cream->S && (inst_cream->Rd == 15)) {
- if (CurrentModeHasSPSR) {
- cpu->Cpsr = cpu->Spsr_copy;
- cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
- LOAD_NZCVT;
- }
- } else if (inst_cream->S) {
- UPDATE_NFLAG(RD);
- UPDATE_ZFLAG(RD);
- UPDATE_CFLAG_WITH_SC;
- }
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(and_inst));
- goto DISPATCH;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(and_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-BBL_INST : {
- if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
- bbl_inst* inst_cream = (bbl_inst*)inst_base->component;
- if (inst_cream->L) {
- LINK_RTN_ADDR;
- }
- SET_PC;
- INC_PC(sizeof(bbl_inst));
- goto DISPATCH;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(bbl_inst));
- goto DISPATCH;
-}
-BIC_INST : {
- bic_inst* inst_cream = (bic_inst*)inst_base->component;
- if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
- u32 lop = RN;
- if (inst_cream->Rn == 15) {
- lop += 2 * cpu->GetInstructionSize();
- }
- u32 rop = SHIFTER_OPERAND;
- RD = lop & (~rop);
- if ((inst_cream->S) && (inst_cream->Rd == 15)) {
- if (CurrentModeHasSPSR) {
- cpu->Cpsr = cpu->Spsr_copy;
- cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
- LOAD_NZCVT;
- }
- } else if (inst_cream->S) {
- UPDATE_NFLAG(RD);
- UPDATE_ZFLAG(RD);
- UPDATE_CFLAG_WITH_SC;
- }
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(bic_inst));
- goto DISPATCH;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(bic_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-BKPT_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component;
- LOG_DEBUG(Core_ARM, "Breakpoint instruction hit. Immediate: 0x%08X", inst_cream->imm);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(bkpt_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-BLX_INST : {
- blx_inst* inst_cream = (blx_inst*)inst_base->component;
- if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
- unsigned int inst = inst_cream->inst;
- if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
- const u32 jump_address = cpu->Reg[inst_cream->val.Rm];
- cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
- if (cpu->TFlag)
- cpu->Reg[14] |= 0x1;
- cpu->Reg[15] = jump_address & 0xfffffffe;
- cpu->TFlag = jump_address & 0x1;
- } else {
- cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
- cpu->TFlag = 0x1;
- int signed_int = inst_cream->val.signed_immed_24;
- signed_int = (signed_int & 0x800000) ? (0x3F000000 | signed_int) : signed_int;
- signed_int = signed_int << 2;
- cpu->Reg[15] = cpu->Reg[15] + 8 + signed_int + (BIT(inst, 24) << 1);
- }
- INC_PC(sizeof(blx_inst));
- goto DISPATCH;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(blx_inst));
- goto DISPATCH;
-}
-
-BX_INST:
-BXJ_INST : {
- // Note that only the 'fail' case of BXJ is emulated. This is because
- // the facilities for Jazelle emulation are not implemented.
- //
- // According to the ARM documentation on BXJ, if setting the J bit in the APSR
- // fails, then BXJ functions identically like a regular BX instruction.
- //
- // This is sufficient for citra, as the CPU for the 3DS does not implement Jazelle.
-
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- bx_inst* const inst_cream = (bx_inst*)inst_base->component;
-
- u32 address = RM;
-
- if (inst_cream->Rm == 15)
- address += 2 * cpu->GetInstructionSize();
-
- cpu->TFlag = address & 1;
- cpu->Reg[15] = address & 0xfffffffe;
- INC_PC(sizeof(bx_inst));
- goto DISPATCH;
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(bx_inst));
- goto DISPATCH;
-}
-
-CDP_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- // Undefined instruction here
- cpu->NumInstrsToExecute = 0;
- return num_instrs;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(cdp_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-CLREX_INST : {
- cpu->UnsetExclusiveMemoryAddress();
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(clrex_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-CLZ_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- clz_inst* inst_cream = (clz_inst*)inst_base->component;
- RD = clz(RM);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(clz_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-CMN_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- cmn_inst* const inst_cream = (cmn_inst*)inst_base->component;
-
- u32 rn_val = RN;
- if (inst_cream->Rn == 15)
- rn_val += 2 * cpu->GetInstructionSize();
-
- bool carry;
- bool overflow;
- u32 result = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
-
- UPDATE_NFLAG(result);
- UPDATE_ZFLAG(result);
- cpu->CFlag = carry;
- cpu->VFlag = overflow;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(cmn_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-CMP_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- cmp_inst* const inst_cream = (cmp_inst*)inst_base->component;
-
- u32 rn_val = RN;
- if (inst_cream->Rn == 15)
- rn_val += 2 * cpu->GetInstructionSize();
-
- bool carry;
- bool overflow;
- u32 result = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
-
- UPDATE_NFLAG(result);
- UPDATE_ZFLAG(result);
- cpu->CFlag = carry;
- cpu->VFlag = overflow;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(cmp_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-CPS_INST : {
- cps_inst* inst_cream = (cps_inst*)inst_base->component;
- u32 aif_val = 0;
- u32 aif_mask = 0;
- if (cpu->InAPrivilegedMode()) {
- if (inst_cream->imod1) {
- if (inst_cream->A) {
- aif_val |= (inst_cream->imod0 << 8);
- aif_mask |= 1 << 8;
- }
- if (inst_cream->I) {
- aif_val |= (inst_cream->imod0 << 7);
- aif_mask |= 1 << 7;
- }
- if (inst_cream->F) {
- aif_val |= (inst_cream->imod0 << 6);
- aif_mask |= 1 << 6;
- }
- aif_mask = ~aif_mask;
- cpu->Cpsr = (cpu->Cpsr & aif_mask) | aif_val;
- }
- if (inst_cream->mmod) {
- cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode;
- cpu->ChangePrivilegeMode(inst_cream->mode);
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(cps_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-CPY_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- mov_inst* inst_cream = (mov_inst*)inst_base->component;
-
- RD = SHIFTER_OPERAND;
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(mov_inst));
- goto DISPATCH;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(mov_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-EOR_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- eor_inst* inst_cream = (eor_inst*)inst_base->component;
-
- u32 lop = RN;
- if (inst_cream->Rn == 15) {
- lop += 2 * cpu->GetInstructionSize();
- }
- u32 rop = SHIFTER_OPERAND;
- RD = lop ^ rop;
- if (inst_cream->S && (inst_cream->Rd == 15)) {
- if (CurrentModeHasSPSR) {
- cpu->Cpsr = cpu->Spsr_copy;
- cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
- LOAD_NZCVT;
- }
- } else if (inst_cream->S) {
- UPDATE_NFLAG(RD);
- UPDATE_ZFLAG(RD);
- UPDATE_CFLAG_WITH_SC;
- }
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(eor_inst));
- goto DISPATCH;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(eor_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-LDC_INST : {
- // Instruction not implemented
- // LOG_CRITICAL(Core_ARM, "unimplemented instruction");
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldc_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-LDM_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
-
- unsigned int inst = inst_cream->inst;
- if (BIT(inst, 22) && !BIT(inst, 15)) {
- for (int i = 0; i < 13; i++) {
- if (BIT(inst, i)) {
- cpu->Reg[i] = cpu->ReadMemory32(addr);
- addr += 4;
- }
- }
- if (BIT(inst, 13)) {
- if (cpu->Mode == USER32MODE)
- cpu->Reg[13] = cpu->ReadMemory32(addr);
- else
- cpu->Reg_usr[0] = cpu->ReadMemory32(addr);
-
- addr += 4;
- }
- if (BIT(inst, 14)) {
- if (cpu->Mode == USER32MODE)
- cpu->Reg[14] = cpu->ReadMemory32(addr);
- else
- cpu->Reg_usr[1] = cpu->ReadMemory32(addr);
-
- addr += 4;
- }
- } else if (!BIT(inst, 22)) {
- for (int i = 0; i < 16; i++) {
- if (BIT(inst, i)) {
- unsigned int ret = cpu->ReadMemory32(addr);
-
- // For armv5t, should enter thumb when bits[0] is non-zero.
- if (i == 15) {
- cpu->TFlag = ret & 0x1;
- ret &= 0xFFFFFFFE;
- }
-
- cpu->Reg[i] = ret;
- addr += 4;
- }
- }
- } else if (BIT(inst, 22) && BIT(inst, 15)) {
- for (int i = 0; i < 15; i++) {
- if (BIT(inst, i)) {
- cpu->Reg[i] = cpu->ReadMemory32(addr);
- addr += 4;
- }
- }
-
- if (CurrentModeHasSPSR) {
- cpu->Cpsr = cpu->Spsr_copy;
- cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
- LOAD_NZCVT;
- }
-
- cpu->Reg[15] = cpu->ReadMemory32(addr);
- }
-
- if (BIT(inst, 15)) {
- INC_PC(sizeof(ldst_inst));
- goto DISPATCH;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-SXTH_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- sxth_inst* inst_cream = (sxth_inst*)inst_base->component;
-
- unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate);
- if (BIT(operand2, 15)) {
- operand2 |= 0xffff0000;
- } else {
- operand2 &= 0xffff;
- }
- RD = operand2;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(sxth_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-LDR_INST : {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
-
- unsigned int value = cpu->ReadMemory32(addr);
- cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
-
- if (BITS(inst_cream->inst, 12, 15) == 15) {
- // For armv5t, should enter thumb when bits[0] is non-zero.
- cpu->TFlag = value & 0x1;
- cpu->Reg[15] &= 0xFFFFFFFE;
- INC_PC(sizeof(ldst_inst));
- goto DISPATCH;
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-LDRCOND_INST : {
- if (CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
-
- unsigned int value = cpu->ReadMemory32(addr);
- cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
-
- if (BITS(inst_cream->inst, 12, 15) == 15) {
- // For armv5t, should enter thumb when bits[0] is non-zero.
- cpu->TFlag = value & 0x1;
- cpu->Reg[15] &= 0xFFFFFFFE;
- INC_PC(sizeof(ldst_inst));
- goto DISPATCH;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-UXTH_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- uxth_inst* inst_cream = (uxth_inst*)inst_base->component;
- RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(uxth_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-UXTAH_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- uxtah_inst* inst_cream = (uxtah_inst*)inst_base->component;
- unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
-
- RD = RN + operand2;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(uxtah_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-LDRB_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
-
- cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory8(addr);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-LDRBT_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
-
- const u32 dest_index = BITS(inst_cream->inst, 12, 15);
- const u32 previous_mode = cpu->Mode;
-
- cpu->ChangePrivilegeMode(USER32MODE);
- const u8 value = cpu->ReadMemory8(addr);
- cpu->ChangePrivilegeMode(previous_mode);
-
- cpu->Reg[dest_index] = value;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-LDRD_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 ||
- // addr[2] == 0)
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
-
- // The 3DS doesn't have LPAE (Large Physical Access Extension), so it
- // wouldn't do this as a single read.
- cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = cpu->ReadMemory32(addr);
- cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = cpu->ReadMemory32(addr + 4);
-
- // No dispatch since this operation should not modify R15
- }
- cpu->Reg[15] += 4;
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-LDREX_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
- unsigned int read_addr = RN;
-
- cpu->SetExclusiveMemoryAddress(read_addr);
-
- RD = cpu->ReadMemory32(read_addr);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-LDREXB_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
- unsigned int read_addr = RN;
-
- cpu->SetExclusiveMemoryAddress(read_addr);
-
- RD = cpu->ReadMemory8(read_addr);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-LDREXH_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
- unsigned int read_addr = RN;
-
- cpu->SetExclusiveMemoryAddress(read_addr);
-
- RD = cpu->ReadMemory16(read_addr);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-LDREXD_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
- unsigned int read_addr = RN;
-
- cpu->SetExclusiveMemoryAddress(read_addr);
-
- RD = cpu->ReadMemory32(read_addr);
- RD2 = cpu->ReadMemory32(read_addr + 4);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-LDRH_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
-
- cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory16(addr);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-LDRSB_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
- unsigned int value = cpu->ReadMemory8(addr);
- if (BIT(value, 7)) {
- value |= 0xffffff00;
- }
- cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-LDRSH_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
-
- unsigned int value = cpu->ReadMemory16(addr);
- if (BIT(value, 15)) {
- value |= 0xffff0000;
- }
- cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-LDRT_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
-
- const u32 dest_index = BITS(inst_cream->inst, 12, 15);
- const u32 previous_mode = cpu->Mode;
-
- cpu->ChangePrivilegeMode(USER32MODE);
- const u32 value = cpu->ReadMemory32(addr);
- cpu->ChangePrivilegeMode(previous_mode);
-
- cpu->Reg[dest_index] = value;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-MCR_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- mcr_inst* inst_cream = (mcr_inst*)inst_base->component;
-
- unsigned int inst = inst_cream->inst;
- if (inst_cream->Rd == 15) {
- DEBUG_MSG;
- } else {
- if (inst_cream->cp_num == 15)
- cpu->WriteCP15Register(RD, CRn, OPCODE_1, CRm, OPCODE_2);
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(mcr_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-MCRR_INST : {
- // Stubbed, as the MPCore doesn't have any registers that are accessible
- // through this instruction.
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
-
- LOG_ERROR(Core_ARM, "MCRR executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u",
- inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt,
- inst_cream->rt2);
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(mcrr_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-MLA_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- mla_inst* inst_cream = (mla_inst*)inst_base->component;
-
- u64 rm = RM;
- u64 rs = RS;
- u64 rn = RN;
-
- RD = static_cast<u32>((rm * rs + rn) & 0xffffffff);
- if (inst_cream->S) {
- UPDATE_NFLAG(RD);
- UPDATE_ZFLAG(RD);
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(mla_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-MOV_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- mov_inst* inst_cream = (mov_inst*)inst_base->component;
-
- RD = SHIFTER_OPERAND;
- if (inst_cream->S && (inst_cream->Rd == 15)) {
- if (CurrentModeHasSPSR) {
- cpu->Cpsr = cpu->Spsr_copy;
- cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
- LOAD_NZCVT;
- }
- } else if (inst_cream->S) {
- UPDATE_NFLAG(RD);
- UPDATE_ZFLAG(RD);
- UPDATE_CFLAG_WITH_SC;
- }
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(mov_inst));
- goto DISPATCH;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(mov_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-MRC_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- mrc_inst* inst_cream = (mrc_inst*)inst_base->component;
-
- if (inst_cream->cp_num == 15) {
- const uint32_t value = cpu->ReadCP15Register(CRn, OPCODE_1, CRm, OPCODE_2);
-
- if (inst_cream->Rd == 15) {
- cpu->Cpsr = (cpu->Cpsr & ~0xF0000000) | (value & 0xF0000000);
- LOAD_NZCVT;
- } else {
- RD = value;
- }
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(mrc_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-MRRC_INST : {
- // Stubbed, as the MPCore doesn't have any registers that are accessible
- // through this instruction.
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
-
- LOG_ERROR(Core_ARM, "MRRC executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u",
- inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt,
- inst_cream->rt2);
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(mcrr_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-MRS_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- mrs_inst* inst_cream = (mrs_inst*)inst_base->component;
-
- if (inst_cream->R) {
- RD = cpu->Spsr_copy;
- } else {
- SAVE_NZCVT;
- RD = cpu->Cpsr;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(mrs_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-MSR_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- msr_inst* inst_cream = (msr_inst*)inst_base->component;
- const u32 UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020;
- unsigned int inst = inst_cream->inst;
- unsigned int operand;
-
- if (BIT(inst, 25)) {
- int rot_imm = BITS(inst, 8, 11) * 2;
- operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm);
- } else {
- operand = cpu->Reg[BITS(inst, 0, 3)];
- }
- u32 byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) |
- (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
- u32 mask = 0;
- if (!inst_cream->R) {
- if (cpu->InAPrivilegedMode()) {
- if ((operand & StateMask) != 0) {
- /// UNPREDICTABLE
- DEBUG_MSG;
- } else
- mask = byte_mask & (UserMask | PrivMask);
- } else {
- mask = byte_mask & UserMask;
- }
- SAVE_NZCVT;
-
- cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask);
- cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
- LOAD_NZCVT;
- } else {
- if (CurrentModeHasSPSR) {
- mask = byte_mask & (UserMask | PrivMask | StateMask);
- cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask);
- }
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(msr_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-MUL_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- mul_inst* inst_cream = (mul_inst*)inst_base->component;
-
- u64 rm = RM;
- u64 rs = RS;
- RD = static_cast<u32>((rm * rs) & 0xffffffff);
- if (inst_cream->S) {
- UPDATE_NFLAG(RD);
- UPDATE_ZFLAG(RD);
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(mul_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-MVN_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- mvn_inst* const inst_cream = (mvn_inst*)inst_base->component;
-
- RD = ~SHIFTER_OPERAND;
-
- if (inst_cream->S && (inst_cream->Rd == 15)) {
- if (CurrentModeHasSPSR) {
- cpu->Cpsr = cpu->Spsr_copy;
- cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
- LOAD_NZCVT;
- }
- } else if (inst_cream->S) {
- UPDATE_NFLAG(RD);
- UPDATE_ZFLAG(RD);
- UPDATE_CFLAG_WITH_SC;
- }
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(mvn_inst));
- goto DISPATCH;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(mvn_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-ORR_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- orr_inst* const inst_cream = (orr_inst*)inst_base->component;
-
- u32 lop = RN;
- u32 rop = SHIFTER_OPERAND;
-
- if (inst_cream->Rn == 15)
- lop += 2 * cpu->GetInstructionSize();
-
- RD = lop | rop;
-
- if (inst_cream->S && (inst_cream->Rd == 15)) {
- if (CurrentModeHasSPSR) {
- cpu->Cpsr = cpu->Spsr_copy;
- cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
- LOAD_NZCVT;
- }
- } else if (inst_cream->S) {
- UPDATE_NFLAG(RD);
- UPDATE_ZFLAG(RD);
- UPDATE_CFLAG_WITH_SC;
- }
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(orr_inst));
- goto DISPATCH;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(orr_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-NOP_INST : {
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC_STUB;
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-PKHBT_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- pkh_inst* inst_cream = (pkh_inst*)inst_base->component;
- RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(pkh_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-PKHTB_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- pkh_inst* inst_cream = (pkh_inst*)inst_base->component;
- int shift_imm = inst_cream->imm ? inst_cream->imm : 31;
- RD = ((static_cast<s32>(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(pkh_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-PLD_INST : {
- // Not implemented. PLD is a hint instruction, so it's optional.
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(pld_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-QADD_INST:
-QDADD_INST:
-QDSUB_INST:
-QSUB_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
- const u8 op1 = inst_cream->op1;
- const u32 rm_val = RM;
- const u32 rn_val = RN;
-
- u32 result = 0;
-
- // QADD
- if (op1 == 0x00) {
- result = rm_val + rn_val;
-
- if (AddOverflow(rm_val, rn_val, result)) {
- result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
- cpu->Cpsr |= (1 << 27);
- }
- }
- // QSUB
- else if (op1 == 0x01) {
- result = rm_val - rn_val;
-
- if (SubOverflow(rm_val, rn_val, result)) {
- result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
- cpu->Cpsr |= (1 << 27);
- }
- }
- // QDADD
- else if (op1 == 0x02) {
- u32 mul = (rn_val * 2);
-
- if (AddOverflow(rn_val, rn_val, rn_val * 2)) {
- mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF;
- cpu->Cpsr |= (1 << 27);
- }
-
- result = mul + rm_val;
-
- if (AddOverflow(rm_val, mul, result)) {
- result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
- cpu->Cpsr |= (1 << 27);
- }
- }
- // QDSUB
- else if (op1 == 0x03) {
- u32 mul = (rn_val * 2);
-
- if (AddOverflow(rn_val, rn_val, mul)) {
- mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF;
- cpu->Cpsr |= (1 << 27);
- }
-
- result = rm_val - mul;
-
- if (SubOverflow(rm_val, mul, result)) {
- result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
- cpu->Cpsr |= (1 << 27);
- }
- }
-
- RD = result;
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-QADD8_INST:
-QADD16_INST:
-QADDSUBX_INST:
-QSUB8_INST:
-QSUB16_INST:
-QSUBADDX_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
- const u16 rm_lo = (RM & 0xFFFF);
- const u16 rm_hi = ((RM >> 16) & 0xFFFF);
- const u16 rn_lo = (RN & 0xFFFF);
- const u16 rn_hi = ((RN >> 16) & 0xFFFF);
- const u8 op2 = inst_cream->op2;
-
- u16 lo_result = 0;
- u16 hi_result = 0;
-
- // QADD16
- if (op2 == 0x00) {
- lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo);
- hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi);
- }
- // QASX
- else if (op2 == 0x01) {
- lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi);
- hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo);
- }
- // QSAX
- else if (op2 == 0x02) {
- lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi);
- hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo);
- }
- // QSUB16
- else if (op2 == 0x03) {
- lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo);
- hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi);
- }
- // QADD8
- else if (op2 == 0x04) {
- lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) |
- ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8;
- hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) |
- ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8;
- }
- // QSUB8
- else if (op2 == 0x07) {
- lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) |
- ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8;
- hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) |
- ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8;
- }
-
- RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-REV_INST:
-REV16_INST:
-REVSH_INST : {
-
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- rev_inst* const inst_cream = (rev_inst*)inst_base->component;
-
- const u8 op1 = inst_cream->op1;
- const u8 op2 = inst_cream->op2;
-
- // REV
- if (op1 == 0x03 && op2 == 0x01) {
- RD = ((RM & 0xFF) << 24) | (((RM >> 8) & 0xFF) << 16) | (((RM >> 16) & 0xFF) << 8) |
- ((RM >> 24) & 0xFF);
- }
- // REV16
- else if (op1 == 0x03 && op2 == 0x05) {
- RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8) | ((RM & 0xFF0000) << 8) |
- ((RM & 0xFF000000) >> 8);
- }
- // REVSH
- else if (op1 == 0x07 && op2 == 0x05) {
- RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8);
- if (RD & 0x8000)
- RD |= 0xffff0000;
- }
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(rev_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-RFE_INST : {
- // RFE is unconditional
- ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
-
- u32 address = 0;
- inst_cream->get_addr(cpu, inst_cream->inst, address);
-
- cpu->Cpsr = cpu->ReadMemory32(address);
- cpu->Reg[15] = cpu->ReadMemory32(address + 4);
-
- INC_PC(sizeof(ldst_inst));
- goto DISPATCH;
-}
-
-RSB_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- rsb_inst* const inst_cream = (rsb_inst*)inst_base->component;
-
- u32 rn_val = RN;
- if (inst_cream->Rn == 15)
- rn_val += 2 * cpu->GetInstructionSize();
-
- bool carry;
- bool overflow;
- RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, 1, &carry, &overflow);
-
- if (inst_cream->S && (inst_cream->Rd == 15)) {
- if (CurrentModeHasSPSR) {
- cpu->Cpsr = cpu->Spsr_copy;
- cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
- LOAD_NZCVT;
- }
- } else if (inst_cream->S) {
- UPDATE_NFLAG(RD);
- UPDATE_ZFLAG(RD);
- cpu->CFlag = carry;
- cpu->VFlag = overflow;
- }
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(rsb_inst));
- goto DISPATCH;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(rsb_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-RSC_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- rsc_inst* const inst_cream = (rsc_inst*)inst_base->component;
-
- u32 rn_val = RN;
- if (inst_cream->Rn == 15)
- rn_val += 2 * cpu->GetInstructionSize();
-
- bool carry;
- bool overflow;
- RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
-
- if (inst_cream->S && (inst_cream->Rd == 15)) {
- if (CurrentModeHasSPSR) {
- cpu->Cpsr = cpu->Spsr_copy;
- cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
- LOAD_NZCVT;
- }
- } else if (inst_cream->S) {
- UPDATE_NFLAG(RD);
- UPDATE_ZFLAG(RD);
- cpu->CFlag = carry;
- cpu->VFlag = overflow;
- }
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(rsc_inst));
- goto DISPATCH;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(rsc_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SADD8_INST:
-SSUB8_INST:
-SADD16_INST:
-SADDSUBX_INST:
-SSUBADDX_INST:
-SSUB16_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
- const u8 op2 = inst_cream->op2;
-
- if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
- const s16 rn_lo = (RN & 0xFFFF);
- const s16 rn_hi = ((RN >> 16) & 0xFFFF);
- const s16 rm_lo = (RM & 0xFFFF);
- const s16 rm_hi = ((RM >> 16) & 0xFFFF);
-
- s32 lo_result = 0;
- s32 hi_result = 0;
-
- // SADD16
- if (inst_cream->op2 == 0x00) {
- lo_result = (rn_lo + rm_lo);
- hi_result = (rn_hi + rm_hi);
- }
- // SASX
- else if (op2 == 0x01) {
- lo_result = (rn_lo - rm_hi);
- hi_result = (rn_hi + rm_lo);
- }
- // SSAX
- else if (op2 == 0x02) {
- lo_result = (rn_lo + rm_hi);
- hi_result = (rn_hi - rm_lo);
- }
- // SSUB16
- else if (op2 == 0x03) {
- lo_result = (rn_lo - rm_lo);
- hi_result = (rn_hi - rm_hi);
- }
-
- RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
-
- if (lo_result >= 0) {
- cpu->Cpsr |= (1 << 16);
- cpu->Cpsr |= (1 << 17);
- } else {
- cpu->Cpsr &= ~(1 << 16);
- cpu->Cpsr &= ~(1 << 17);
- }
-
- if (hi_result >= 0) {
- cpu->Cpsr |= (1 << 18);
- cpu->Cpsr |= (1 << 19);
- } else {
- cpu->Cpsr &= ~(1 << 18);
- cpu->Cpsr &= ~(1 << 19);
- }
- } else if (op2 == 0x04 || op2 == 0x07) {
- s32 lo_val1, lo_val2;
- s32 hi_val1, hi_val2;
-
- // SADD8
- if (op2 == 0x04) {
- lo_val1 = (s32)(s8)(RN & 0xFF) + (s32)(s8)(RM & 0xFF);
- lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) + (s32)(s8)((RM >> 8) & 0xFF);
- hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) + (s32)(s8)((RM >> 16) & 0xFF);
- hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) + (s32)(s8)((RM >> 24) & 0xFF);
- }
- // SSUB8
- else {
- lo_val1 = (s32)(s8)(RN & 0xFF) - (s32)(s8)(RM & 0xFF);
- lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) - (s32)(s8)((RM >> 8) & 0xFF);
- hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) - (s32)(s8)((RM >> 16) & 0xFF);
- hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) - (s32)(s8)((RM >> 24) & 0xFF);
- }
-
- RD = ((lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) |
- ((hi_val2 & 0xFF) << 24));
-
- if (lo_val1 >= 0)
- cpu->Cpsr |= (1 << 16);
- else
- cpu->Cpsr &= ~(1 << 16);
-
- if (lo_val2 >= 0)
- cpu->Cpsr |= (1 << 17);
- else
- cpu->Cpsr &= ~(1 << 17);
-
- if (hi_val1 >= 0)
- cpu->Cpsr |= (1 << 18);
- else
- cpu->Cpsr &= ~(1 << 18);
-
- if (hi_val2 >= 0)
- cpu->Cpsr |= (1 << 19);
- else
- cpu->Cpsr &= ~(1 << 19);
- }
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SBC_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- sbc_inst* const inst_cream = (sbc_inst*)inst_base->component;
-
- u32 rn_val = RN;
- if (inst_cream->Rn == 15)
- rn_val += 2 * cpu->GetInstructionSize();
-
- bool carry;
- bool overflow;
- RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
-
- if (inst_cream->S && (inst_cream->Rd == 15)) {
- if (CurrentModeHasSPSR) {
- cpu->Cpsr = cpu->Spsr_copy;
- cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
- LOAD_NZCVT;
- }
- } else if (inst_cream->S) {
- UPDATE_NFLAG(RD);
- UPDATE_ZFLAG(RD);
- cpu->CFlag = carry;
- cpu->VFlag = overflow;
- }
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(sbc_inst));
- goto DISPATCH;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(sbc_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SEL_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
-
- const u32 to = RM;
- const u32 from = RN;
- const u32 cpsr = cpu->Cpsr;
-
- u32 result;
- if (cpsr & (1 << 16))
- result = from & 0xff;
- else
- result = to & 0xff;
-
- if (cpsr & (1 << 17))
- result |= from & 0x0000ff00;
- else
- result |= to & 0x0000ff00;
-
- if (cpsr & (1 << 18))
- result |= from & 0x00ff0000;
- else
- result |= to & 0x00ff0000;
-
- if (cpsr & (1 << 19))
- result |= from & 0xff000000;
- else
- result |= to & 0xff000000;
-
- RD = result;
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SETEND_INST : {
- // SETEND is unconditional
- setend_inst* const inst_cream = (setend_inst*)inst_base->component;
- const bool big_endian = (inst_cream->set_bigend == 1);
-
- if (big_endian)
- cpu->Cpsr |= (1 << 9);
- else
- cpu->Cpsr &= ~(1 << 9);
-
- LOG_WARNING(Core_ARM, "SETEND %s executed", big_endian ? "BE" : "LE");
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(setend_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SEV_INST : {
- // Stubbed, as SEV is a hint instruction.
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- LOG_TRACE(Core_ARM, "SEV executed.");
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC_STUB;
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SHADD8_INST:
-SHADD16_INST:
-SHADDSUBX_INST:
-SHSUB8_INST:
-SHSUB16_INST:
-SHSUBADDX_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
-
- const u8 op2 = inst_cream->op2;
- const u32 rm_val = RM;
- const u32 rn_val = RN;
-
- if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
- s32 lo_result = 0;
- s32 hi_result = 0;
-
- // SHADD16
- if (op2 == 0x00) {
- lo_result = ((s16)(rn_val & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1;
- hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
- }
- // SHASX
- else if (op2 == 0x01) {
- lo_result = ((s16)(rn_val & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
- hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1;
- }
- // SHSAX
- else if (op2 == 0x02) {
- lo_result = ((s16)(rn_val & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
- hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1;
- }
- // SHSUB16
- else if (op2 == 0x03) {
- lo_result = ((s16)(rn_val & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1;
- hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
- }
-
- RD = ((lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16));
- } else if (op2 == 0x04 || op2 == 0x07) {
- s16 lo_val1, lo_val2;
- s16 hi_val1, hi_val2;
-
- // SHADD8
- if (op2 == 0x04) {
- lo_val1 = ((s8)(rn_val & 0xFF) + (s8)(rm_val & 0xFF)) >> 1;
- lo_val2 = ((s8)((rn_val >> 8) & 0xFF) + (s8)((rm_val >> 8) & 0xFF)) >> 1;
-
- hi_val1 = ((s8)((rn_val >> 16) & 0xFF) + (s8)((rm_val >> 16) & 0xFF)) >> 1;
- hi_val2 = ((s8)((rn_val >> 24) & 0xFF) + (s8)((rm_val >> 24) & 0xFF)) >> 1;
- }
- // SHSUB8
- else {
- lo_val1 = ((s8)(rn_val & 0xFF) - (s8)(rm_val & 0xFF)) >> 1;
- lo_val2 = ((s8)((rn_val >> 8) & 0xFF) - (s8)((rm_val >> 8) & 0xFF)) >> 1;
-
- hi_val1 = ((s8)((rn_val >> 16) & 0xFF) - (s8)((rm_val >> 16) & 0xFF)) >> 1;
- hi_val2 = ((s8)((rn_val >> 24) & 0xFF) - (s8)((rm_val >> 24) & 0xFF)) >> 1;
- }
-
- RD = (lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) |
- ((hi_val2 & 0xFF) << 24);
- }
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SMLA_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- smla_inst* inst_cream = (smla_inst*)inst_base->component;
- s32 operand1, operand2;
- if (inst_cream->x == 0)
- operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
- else
- operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
-
- if (inst_cream->y == 0)
- operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15);
- else
- operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
-
- u32 product = operand1 * operand2;
- u32 result = product + RN;
- if (AddOverflow(product, RN, result))
- cpu->Cpsr |= (1 << 27);
- RD = result;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(smla_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SMLAD_INST:
-SMLSD_INST:
-SMUAD_INST:
-SMUSD_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
- const u8 op2 = inst_cream->op2;
-
- u32 rm_val = cpu->Reg[inst_cream->Rm];
- const u32 rn_val = cpu->Reg[inst_cream->Rn];
-
- if (inst_cream->m)
- rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
-
- const s16 rm_lo = (rm_val & 0xFFFF);
- const s16 rm_hi = ((rm_val >> 16) & 0xFFFF);
- const s16 rn_lo = (rn_val & 0xFFFF);
- const s16 rn_hi = ((rn_val >> 16) & 0xFFFF);
-
- const u32 product1 = (rn_lo * rm_lo);
- const u32 product2 = (rn_hi * rm_hi);
-
- // SMUAD and SMLAD
- if (BIT(op2, 1) == 0) {
- u32 rd_val = (product1 + product2);
-
- if (inst_cream->Ra != 15) {
- rd_val += cpu->Reg[inst_cream->Ra];
-
- if (ARMul_AddOverflowQ(product1 + product2, cpu->Reg[inst_cream->Ra]))
- cpu->Cpsr |= (1 << 27);
- }
-
- RD = rd_val;
-
- if (ARMul_AddOverflowQ(product1, product2))
- cpu->Cpsr |= (1 << 27);
- }
- // SMUSD and SMLSD
- else {
- u32 rd_val = (product1 - product2);
-
- if (inst_cream->Ra != 15) {
- rd_val += cpu->Reg[inst_cream->Ra];
-
- if (ARMul_AddOverflowQ(product1 - product2, cpu->Reg[inst_cream->Ra]))
- cpu->Cpsr |= (1 << 27);
- }
-
- RD = rd_val;
- }
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(smlad_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SMLAL_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
- long long int rm = RM;
- long long int rs = RS;
- if (BIT(rm, 31)) {
- rm |= 0xffffffff00000000LL;
- }
- if (BIT(rs, 31)) {
- rs |= 0xffffffff00000000LL;
- }
- long long int rst = rm * rs;
- long long int rdhi32 = RDHI;
- long long int hilo = (rdhi32 << 32) + RDLO;
- rst += hilo;
- RDLO = BITS(rst, 0, 31);
- RDHI = BITS(rst, 32, 63);
- if (inst_cream->S) {
- cpu->NFlag = BIT(RDHI, 31);
- cpu->ZFlag = (RDHI == 0 && RDLO == 0);
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(umlal_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SMLALXY_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component;
-
- u64 operand1 = RN;
- u64 operand2 = RM;
-
- if (inst_cream->x != 0)
- operand1 >>= 16;
- if (inst_cream->y != 0)
- operand2 >>= 16;
- operand1 &= 0xFFFF;
- if (operand1 & 0x8000)
- operand1 -= 65536;
- operand2 &= 0xFFFF;
- if (operand2 & 0x8000)
- operand2 -= 65536;
-
- u64 dest = ((u64)RDHI << 32 | RDLO) + (operand1 * operand2);
- RDLO = (dest & 0xFFFFFFFF);
- RDHI = ((dest >> 32) & 0xFFFFFFFF);
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(smlalxy_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SMLAW_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
-
- const u32 rm_val = RM;
- const u32 rn_val = RN;
- const u32 ra_val = cpu->Reg[inst_cream->Ra];
- const bool high = (inst_cream->m == 1);
-
- const s16 operand2 = (high) ? ((rm_val >> 16) & 0xFFFF) : (rm_val & 0xFFFF);
- const s64 result = (s64)(s32)rn_val * (s64)(s32)operand2 + ((s64)(s32)ra_val << 16);
-
- RD = BITS(result, 16, 47);
-
- if ((result >> 16) != (s32)RD)
- cpu->Cpsr |= (1 << 27);
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(smlad_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SMLALD_INST:
-SMLSLD_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- smlald_inst* const inst_cream = (smlald_inst*)inst_base->component;
-
- const bool do_swap = (inst_cream->swap == 1);
- const u32 rdlo_val = RDLO;
- const u32 rdhi_val = RDHI;
- const u32 rn_val = RN;
- u32 rm_val = RM;
-
- if (do_swap)
- rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
-
- const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF);
- const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF);
- s64 result;
-
- // SMLALD
- if (BIT(inst_cream->op2, 1) == 0) {
- result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
- }
- // SMLSLD
- else {
- result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
- }
-
- RDLO = (result & 0xFFFFFFFF);
- RDHI = ((result >> 32) & 0xFFFFFFFF);
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(smlald_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SMMLA_INST:
-SMMLS_INST:
-SMMUL_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
-
- const u32 rm_val = RM;
- const u32 rn_val = RN;
- const bool do_round = (inst_cream->m == 1);
-
- // Assume SMMUL by default.
- s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val;
-
- if (inst_cream->Ra != 15) {
- const u32 ra_val = cpu->Reg[inst_cream->Ra];
-
- // SMMLA, otherwise SMMLS
- if (BIT(inst_cream->op2, 1) == 0)
- result += ((s64)ra_val << 32);
- else
- result = ((s64)ra_val << 32) - result;
- }
-
- if (do_round)
- result += 0x80000000;
-
- RD = ((result >> 32) & 0xFFFFFFFF);
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(smlad_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SMUL_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- smul_inst* inst_cream = (smul_inst*)inst_base->component;
- u32 operand1, operand2;
- if (inst_cream->x == 0)
- operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
- else
- operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
-
- if (inst_cream->y == 0)
- operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15);
- else
- operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
- RD = operand1 * operand2;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(smul_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-SMULL_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- umull_inst* inst_cream = (umull_inst*)inst_base->component;
- s64 rm = RM;
- s64 rs = RS;
- if (BIT(rm, 31)) {
- rm |= 0xffffffff00000000LL;
- }
- if (BIT(rs, 31)) {
- rs |= 0xffffffff00000000LL;
- }
- s64 rst = rm * rs;
- RDHI = BITS(rst, 32, 63);
- RDLO = BITS(rst, 0, 31);
-
- if (inst_cream->S) {
- cpu->NFlag = BIT(RDHI, 31);
- cpu->ZFlag = (RDHI == 0 && RDLO == 0);
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(umull_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SMULW_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
-
- s16 rm = (inst_cream->m == 1) ? ((RM >> 16) & 0xFFFF) : (RM & 0xFFFF);
-
- s64 result = (s64)rm * (s64)(s32)RN;
- RD = BITS(result, 16, 47);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(smlad_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SRS_INST : {
- // SRS is unconditional
- ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
-
- u32 address = 0;
- inst_cream->get_addr(cpu, inst_cream->inst, address);
-
- cpu->WriteMemory32(address + 0, cpu->Reg[14]);
- cpu->WriteMemory32(address + 4, cpu->Spsr_copy);
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SSAT_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
-
- u8 shift_type = inst_cream->shift_type;
- u8 shift_amount = inst_cream->imm5;
- u32 rn_val = RN;
-
- // 32-bit ASR is encoded as an amount of 0.
- if (shift_type == 1 && shift_amount == 0)
- shift_amount = 31;
-
- if (shift_type == 0)
- rn_val <<= shift_amount;
- else if (shift_type == 1)
- rn_val = ((s32)rn_val >> shift_amount);
-
- bool saturated = false;
- rn_val = ARMul_SignedSatQ(rn_val, inst_cream->sat_imm, &saturated);
-
- if (saturated)
- cpu->Cpsr |= (1 << 27);
-
- RD = rn_val;
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ssat_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SSAT16_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
- const u8 saturate_to = inst_cream->sat_imm;
-
- bool sat1 = false;
- bool sat2 = false;
-
- RD = (ARMul_SignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) |
- ARMul_SignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16;
-
- if (sat1 || sat2)
- cpu->Cpsr |= (1 << 27);
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ssat_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-STC_INST : {
- // Instruction not implemented
- // LOG_CRITICAL(Core_ARM, "unimplemented instruction");
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(stc_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-STM_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- unsigned int inst = inst_cream->inst;
-
- unsigned int Rn = BITS(inst, 16, 19);
- unsigned int old_RN = cpu->Reg[Rn];
-
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
- if (BIT(inst_cream->inst, 22) == 1) {
- for (int i = 0; i < 13; i++) {
- if (BIT(inst_cream->inst, i)) {
- cpu->WriteMemory32(addr, cpu->Reg[i]);
- addr += 4;
- }
- }
- if (BIT(inst_cream->inst, 13)) {
- if (cpu->Mode == USER32MODE)
- cpu->WriteMemory32(addr, cpu->Reg[13]);
- else
- cpu->WriteMemory32(addr, cpu->Reg_usr[0]);
-
- addr += 4;
- }
- if (BIT(inst_cream->inst, 14)) {
- if (cpu->Mode == USER32MODE)
- cpu->WriteMemory32(addr, cpu->Reg[14]);
- else
- cpu->WriteMemory32(addr, cpu->Reg_usr[1]);
-
- addr += 4;
- }
- if (BIT(inst_cream->inst, 15)) {
- cpu->WriteMemory32(addr, cpu->Reg[15] + 8);
- }
- } else {
- for (int i = 0; i < 15; i++) {
- if (BIT(inst_cream->inst, i)) {
- if (i == Rn)
- cpu->WriteMemory32(addr, old_RN);
- else
- cpu->WriteMemory32(addr, cpu->Reg[i]);
-
- addr += 4;
- }
- }
-
- // Check PC reg
- if (BIT(inst_cream->inst, 15)) {
- cpu->WriteMemory32(addr, cpu->Reg[15] + 8);
- }
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-SXTB_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component;
-
- unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate);
- if (BIT(operand2, 7)) {
- operand2 |= 0xffffff00;
- } else {
- operand2 &= 0xff;
- }
- RD = operand2;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(sxtb_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-STR_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
-
- unsigned int reg = BITS(inst_cream->inst, 12, 15);
- unsigned int value = cpu->Reg[reg];
-
- if (reg == 15)
- value += 2 * cpu->GetInstructionSize();
-
- cpu->WriteMemory32(addr, value);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-UXTB_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- uxtb_inst* inst_cream = (uxtb_inst*)inst_base->component;
- RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(uxtb_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-UXTAB_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- uxtab_inst* inst_cream = (uxtab_inst*)inst_base->component;
-
- unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
- RD = RN + operand2;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(uxtab_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-STRB_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
- unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
- cpu->WriteMemory8(addr, value);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-STRBT_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
-
- const u32 previous_mode = cpu->Mode;
- const u32 value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
-
- cpu->ChangePrivilegeMode(USER32MODE);
- cpu->WriteMemory8(addr, value);
- cpu->ChangePrivilegeMode(previous_mode);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-STRD_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
-
- // The 3DS doesn't have the Large Physical Access Extension (LPAE)
- // so STRD wouldn't store these as a single write.
- cpu->WriteMemory32(addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]);
- cpu->WriteMemory32(addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-STREX_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
- unsigned int write_addr = cpu->Reg[inst_cream->Rn];
-
- if (cpu->IsExclusiveMemoryAccess(write_addr)) {
- cpu->UnsetExclusiveMemoryAddress();
- cpu->WriteMemory32(write_addr, RM);
- RD = 0;
- } else {
- // Failed to write due to mutex access
- RD = 1;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-STREXB_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
- unsigned int write_addr = cpu->Reg[inst_cream->Rn];
-
- if (cpu->IsExclusiveMemoryAccess(write_addr)) {
- cpu->UnsetExclusiveMemoryAddress();
- cpu->WriteMemory8(write_addr, cpu->Reg[inst_cream->Rm]);
- RD = 0;
- } else {
- // Failed to write due to mutex access
- RD = 1;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-STREXD_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
- unsigned int write_addr = cpu->Reg[inst_cream->Rn];
-
- if (cpu->IsExclusiveMemoryAccess(write_addr)) {
- cpu->UnsetExclusiveMemoryAddress();
-
- const u32 rt = cpu->Reg[inst_cream->Rm + 0];
- const u32 rt2 = cpu->Reg[inst_cream->Rm + 1];
- u64 value;
-
- if (cpu->InBigEndianMode())
- value = (((u64)rt << 32) | rt2);
- else
- value = (((u64)rt2 << 32) | rt);
-
- cpu->WriteMemory64(write_addr, value);
- RD = 0;
- } else {
- // Failed to write due to mutex access
- RD = 1;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-STREXH_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
- unsigned int write_addr = cpu->Reg[inst_cream->Rn];
-
- if (cpu->IsExclusiveMemoryAccess(write_addr)) {
- cpu->UnsetExclusiveMemoryAddress();
- cpu->WriteMemory16(write_addr, RM);
- RD = 0;
- } else {
- // Failed to write due to mutex access
- RD = 1;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-STRH_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
-
- unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff;
- cpu->WriteMemory16(addr, value);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-STRT_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
- inst_cream->get_addr(cpu, inst_cream->inst, addr);
-
- const u32 previous_mode = cpu->Mode;
- const u32 rt_index = BITS(inst_cream->inst, 12, 15);
-
- u32 value = cpu->Reg[rt_index];
- if (rt_index == 15)
- value += 2 * cpu->GetInstructionSize();
-
- cpu->ChangePrivilegeMode(USER32MODE);
- cpu->WriteMemory32(addr, value);
- cpu->ChangePrivilegeMode(previous_mode);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ldst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-SUB_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- sub_inst* const inst_cream = (sub_inst*)inst_base->component;
-
- u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn);
-
- bool carry;
- bool overflow;
- RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
-
- if (inst_cream->S && (inst_cream->Rd == 15)) {
- if (CurrentModeHasSPSR) {
- cpu->Cpsr = cpu->Spsr_copy;
- cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
- LOAD_NZCVT;
- }
- } else if (inst_cream->S) {
- UPDATE_NFLAG(RD);
- UPDATE_ZFLAG(RD);
- cpu->CFlag = carry;
- cpu->VFlag = overflow;
- }
- if (inst_cream->Rd == 15) {
- INC_PC(sizeof(sub_inst));
- goto DISPATCH;
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(sub_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-SWI_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- swi_inst* const inst_cream = (swi_inst*)inst_base->component;
- SVC::CallSVC(inst_cream->num & 0xFFFF);
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(swi_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-SWP_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- swp_inst* inst_cream = (swp_inst*)inst_base->component;
-
- addr = RN;
- unsigned int value = cpu->ReadMemory32(addr);
- cpu->WriteMemory32(addr, RM);
-
- RD = value;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(swp_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-SWPB_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- swp_inst* inst_cream = (swp_inst*)inst_base->component;
- addr = RN;
- unsigned int value = cpu->ReadMemory8(addr);
- cpu->WriteMemory8(addr, (RM & 0xFF));
- RD = value;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(swp_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-SXTAB_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- sxtab_inst* inst_cream = (sxtab_inst*)inst_base->component;
-
- unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
-
- // Sign extend for byte
- operand2 = (0x80 & operand2) ? (0xFFFFFF00 | operand2) : operand2;
- RD = RN + operand2;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(uxtab_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SXTAB16_INST:
-SXTB16_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component;
-
- const u8 rotation = inst_cream->rotate * 8;
- u32 rm_val = RM;
- u32 rn_val = RN;
-
- if (rotation)
- rm_val = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
-
- // SXTB16
- if (inst_cream->Rn == 15) {
- u32 lo = (u32)(s8)rm_val;
- u32 hi = (u32)(s8)(rm_val >> 16);
- RD = (lo & 0xFFFF) | (hi << 16);
- }
- // SXTAB16
- else {
- u32 lo = rn_val + (u32)(s8)(rm_val & 0xFF);
- u32 hi = (rn_val >> 16) + (u32)(s8)((rm_val >> 16) & 0xFF);
- RD = (lo & 0xFFFF) | (hi << 16);
- }
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(sxtab_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-SXTAH_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- sxtah_inst* inst_cream = (sxtah_inst*)inst_base->component;
-
- unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
- // Sign extend for half
- operand2 = (0x8000 & operand2) ? (0xFFFF0000 | operand2) : operand2;
- RD = RN + operand2;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(sxtah_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-TEQ_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- teq_inst* const inst_cream = (teq_inst*)inst_base->component;
-
- u32 lop = RN;
- u32 rop = SHIFTER_OPERAND;
-
- if (inst_cream->Rn == 15)
- lop += cpu->GetInstructionSize() * 2;
-
- u32 result = lop ^ rop;
-
- UPDATE_NFLAG(result);
- UPDATE_ZFLAG(result);
- UPDATE_CFLAG_WITH_SC;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(teq_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-TST_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- tst_inst* const inst_cream = (tst_inst*)inst_base->component;
-
- u32 lop = RN;
- u32 rop = SHIFTER_OPERAND;
-
- if (inst_cream->Rn == 15)
- lop += cpu->GetInstructionSize() * 2;
-
- u32 result = lop & rop;
-
- UPDATE_NFLAG(result);
- UPDATE_ZFLAG(result);
- UPDATE_CFLAG_WITH_SC;
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(tst_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-UADD8_INST:
-UADD16_INST:
-UADDSUBX_INST:
-USUB8_INST:
-USUB16_INST:
-USUBADDX_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
-
- const u8 op2 = inst_cream->op2;
- const u32 rm_val = RM;
- const u32 rn_val = RN;
-
- s32 lo_result = 0;
- s32 hi_result = 0;
-
- // UADD16
- if (op2 == 0x00) {
- lo_result = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
- hi_result = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
-
- if (lo_result & 0xFFFF0000) {
- cpu->Cpsr |= (1 << 16);
- cpu->Cpsr |= (1 << 17);
- } else {
- cpu->Cpsr &= ~(1 << 16);
- cpu->Cpsr &= ~(1 << 17);
- }
-
- if (hi_result & 0xFFFF0000) {
- cpu->Cpsr |= (1 << 18);
- cpu->Cpsr |= (1 << 19);
- } else {
- cpu->Cpsr &= ~(1 << 18);
- cpu->Cpsr &= ~(1 << 19);
- }
- }
- // UASX
- else if (op2 == 0x01) {
- lo_result = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
- hi_result = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
-
- if (lo_result >= 0) {
- cpu->Cpsr |= (1 << 16);
- cpu->Cpsr |= (1 << 17);
- } else {
- cpu->Cpsr &= ~(1 << 16);
- cpu->Cpsr &= ~(1 << 17);
- }
-
- if (hi_result >= 0x10000) {
- cpu->Cpsr |= (1 << 18);
- cpu->Cpsr |= (1 << 19);
- } else {
- cpu->Cpsr &= ~(1 << 18);
- cpu->Cpsr &= ~(1 << 19);
- }
- }
- // USAX
- else if (op2 == 0x02) {
- lo_result = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
- hi_result = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
-
- if (lo_result >= 0x10000) {
- cpu->Cpsr |= (1 << 16);
- cpu->Cpsr |= (1 << 17);
- } else {
- cpu->Cpsr &= ~(1 << 16);
- cpu->Cpsr &= ~(1 << 17);
- }
-
- if (hi_result >= 0) {
- cpu->Cpsr |= (1 << 18);
- cpu->Cpsr |= (1 << 19);
- } else {
- cpu->Cpsr &= ~(1 << 18);
- cpu->Cpsr &= ~(1 << 19);
- }
- }
- // USUB16
- else if (op2 == 0x03) {
- lo_result = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
- hi_result = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
-
- if ((lo_result & 0xFFFF0000) == 0) {
- cpu->Cpsr |= (1 << 16);
- cpu->Cpsr |= (1 << 17);
- } else {
- cpu->Cpsr &= ~(1 << 16);
- cpu->Cpsr &= ~(1 << 17);
- }
-
- if ((hi_result & 0xFFFF0000) == 0) {
- cpu->Cpsr |= (1 << 18);
- cpu->Cpsr |= (1 << 19);
- } else {
- cpu->Cpsr &= ~(1 << 18);
- cpu->Cpsr &= ~(1 << 19);
- }
- }
- // UADD8
- else if (op2 == 0x04) {
- s16 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
- s16 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
- s16 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
- s16 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
-
- if (sum1 >= 0x100)
- cpu->Cpsr |= (1 << 16);
- else
- cpu->Cpsr &= ~(1 << 16);
-
- if (sum2 >= 0x100)
- cpu->Cpsr |= (1 << 17);
- else
- cpu->Cpsr &= ~(1 << 17);
-
- if (sum3 >= 0x100)
- cpu->Cpsr |= (1 << 18);
- else
- cpu->Cpsr &= ~(1 << 18);
-
- if (sum4 >= 0x100)
- cpu->Cpsr |= (1 << 19);
- else
- cpu->Cpsr &= ~(1 << 19);
-
- lo_result = ((sum1 & 0xFF) | (sum2 & 0xFF) << 8);
- hi_result = ((sum3 & 0xFF) | (sum4 & 0xFF) << 8);
- }
- // USUB8
- else if (op2 == 0x07) {
- s16 diff1 = (rn_val & 0xFF) - (rm_val & 0xFF);
- s16 diff2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
- s16 diff3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
- s16 diff4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
-
- if (diff1 >= 0)
- cpu->Cpsr |= (1 << 16);
- else
- cpu->Cpsr &= ~(1 << 16);
-
- if (diff2 >= 0)
- cpu->Cpsr |= (1 << 17);
- else
- cpu->Cpsr &= ~(1 << 17);
-
- if (diff3 >= 0)
- cpu->Cpsr |= (1 << 18);
- else
- cpu->Cpsr &= ~(1 << 18);
-
- if (diff4 >= 0)
- cpu->Cpsr |= (1 << 19);
- else
- cpu->Cpsr &= ~(1 << 19);
-
- lo_result = (diff1 & 0xFF) | ((diff2 & 0xFF) << 8);
- hi_result = (diff3 & 0xFF) | ((diff4 & 0xFF) << 8);
- }
-
- RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-UHADD8_INST:
-UHADD16_INST:
-UHADDSUBX_INST:
-UHSUBADDX_INST:
-UHSUB8_INST:
-UHSUB16_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
- const u32 rm_val = RM;
- const u32 rn_val = RN;
- const u8 op2 = inst_cream->op2;
-
- if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
- u32 lo_val = 0;
- u32 hi_val = 0;
-
- // UHADD16
- if (op2 == 0x00) {
- lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
- hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
- }
- // UHASX
- else if (op2 == 0x01) {
- lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
- hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
- }
- // UHSAX
- else if (op2 == 0x02) {
- lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
- hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
- }
- // UHSUB16
- else if (op2 == 0x03) {
- lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
- hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
- }
-
- lo_val >>= 1;
- hi_val >>= 1;
-
- RD = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16);
- } else if (op2 == 0x04 || op2 == 0x07) {
- u32 sum1;
- u32 sum2;
- u32 sum3;
- u32 sum4;
-
- // UHADD8
- if (op2 == 0x04) {
- sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
- sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
- sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
- sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
- }
- // UHSUB8
- else {
- sum1 = (rn_val & 0xFF) - (rm_val & 0xFF);
- sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
- sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
- sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
- }
-
- sum1 >>= 1;
- sum2 >>= 1;
- sum3 >>= 1;
- sum4 >>= 1;
-
- RD = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) |
- ((sum4 & 0xFF) << 24);
- }
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-UMAAL_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
- const u64 rm = RM;
- const u64 rn = RN;
- const u64 rd_lo = RDLO;
- const u64 rd_hi = RDHI;
- const u64 result = (rm * rn) + rd_lo + rd_hi;
-
- RDLO = (result & 0xFFFFFFFF);
- RDHI = ((result >> 32) & 0xFFFFFFFF);
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(umaal_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-UMLAL_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
- unsigned long long int rm = RM;
- unsigned long long int rs = RS;
- unsigned long long int rst = rm * rs;
- unsigned long long int add = ((unsigned long long)RDHI) << 32;
- add += RDLO;
- rst += add;
- RDLO = BITS(rst, 0, 31);
- RDHI = BITS(rst, 32, 63);
-
- if (inst_cream->S) {
- cpu->NFlag = BIT(RDHI, 31);
- cpu->ZFlag = (RDHI == 0 && RDLO == 0);
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(umlal_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-UMULL_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- umull_inst* inst_cream = (umull_inst*)inst_base->component;
- unsigned long long int rm = RM;
- unsigned long long int rs = RS;
- unsigned long long int rst = rm * rs;
- RDHI = BITS(rst, 32, 63);
- RDLO = BITS(rst, 0, 31);
-
- if (inst_cream->S) {
- cpu->NFlag = BIT(RDHI, 31);
- cpu->ZFlag = (RDHI == 0 && RDLO == 0);
- }
- }
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(umull_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-B_2_THUMB : {
- b_2_thumb* inst_cream = (b_2_thumb*)inst_base->component;
- cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm;
- INC_PC(sizeof(b_2_thumb));
- goto DISPATCH;
-}
-B_COND_THUMB : {
- b_cond_thumb* inst_cream = (b_cond_thumb*)inst_base->component;
-
- if (CondPassed(cpu, inst_cream->cond))
- cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm;
- else
- cpu->Reg[15] += 2;
-
- INC_PC(sizeof(b_cond_thumb));
- goto DISPATCH;
-}
-BL_1_THUMB : {
- bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component;
- cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm;
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(bl_1_thumb));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-BL_2_THUMB : {
- bl_2_thumb* inst_cream = (bl_2_thumb*)inst_base->component;
- int tmp = ((cpu->Reg[15] + 2) | 1);
- cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm);
- cpu->Reg[14] = tmp;
- INC_PC(sizeof(bl_2_thumb));
- goto DISPATCH;
-}
-BLX_1_THUMB : {
- // BLX 1 for armv5t and above
- u32 tmp = cpu->Reg[15];
- blx_1_thumb* inst_cream = (blx_1_thumb*)inst_base->component;
- cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm) & 0xFFFFFFFC;
- cpu->Reg[14] = ((tmp + 2) | 1);
- cpu->TFlag = 0;
- INC_PC(sizeof(blx_1_thumb));
- goto DISPATCH;
-}
-
-UQADD8_INST:
-UQADD16_INST:
-UQADDSUBX_INST:
-UQSUB8_INST:
-UQSUB16_INST:
-UQSUBADDX_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
-
- const u8 op2 = inst_cream->op2;
- const u32 rm_val = RM;
- const u32 rn_val = RN;
-
- u16 lo_val = 0;
- u16 hi_val = 0;
-
- // UQADD16
- if (op2 == 0x00) {
- lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF);
- hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
- }
- // UQASX
- else if (op2 == 0x01) {
- lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
- hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
- }
- // UQSAX
- else if (op2 == 0x02) {
- lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
- hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
- }
- // UQSUB16
- else if (op2 == 0x03) {
- lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF);
- hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
- }
- // UQADD8
- else if (op2 == 0x04) {
- lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) |
- ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8;
- hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) |
- ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8;
- }
- // UQSUB8
- else {
- lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) |
- ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8;
- hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) |
- ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8;
- }
-
- RD = ((lo_val & 0xFFFF) | hi_val << 16);
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-USAD8_INST:
-USADA8_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
-
- const u8 ra_idx = inst_cream->Ra;
- const u32 rm_val = RM;
- const u32 rn_val = RN;
-
- const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF);
- const u8 diff2 =
- ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF);
- const u8 diff3 =
- ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF);
- const u8 diff4 =
- ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF);
-
- u32 finalDif = (diff1 + diff2 + diff3 + diff4);
-
- // Op is USADA8 if true.
- if (ra_idx != 15)
- finalDif += cpu->Reg[ra_idx];
-
- RD = finalDif;
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(generic_arm_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-USAT_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
-
- u8 shift_type = inst_cream->shift_type;
- u8 shift_amount = inst_cream->imm5;
- u32 rn_val = RN;
-
- // 32-bit ASR is encoded as an amount of 0.
- if (shift_type == 1 && shift_amount == 0)
- shift_amount = 31;
-
- if (shift_type == 0)
- rn_val <<= shift_amount;
- else if (shift_type == 1)
- rn_val = ((s32)rn_val >> shift_amount);
-
- bool saturated = false;
- rn_val = ARMul_UnsignedSatQ(rn_val, inst_cream->sat_imm, &saturated);
-
- if (saturated)
- cpu->Cpsr |= (1 << 27);
-
- RD = rn_val;
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ssat_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-USAT16_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
- const u8 saturate_to = inst_cream->sat_imm;
-
- bool sat1 = false;
- bool sat2 = false;
-
- RD = (ARMul_UnsignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) |
- ARMul_UnsignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16;
-
- if (sat1 || sat2)
- cpu->Cpsr |= (1 << 27);
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(ssat_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-UXTAB16_INST:
-UXTB16_INST : {
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
-
- const u8 rn_idx = inst_cream->Rn;
- const u32 rm_val = RM;
- const u32 rotation = inst_cream->rotate * 8;
- const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
-
- // UXTB16, otherwise UXTAB16
- if (rn_idx == 15) {
- RD = rotated_rm & 0x00FF00FF;
- } else {
- const u32 rn_val = RN;
- const u8 lo_rotated = (rotated_rm & 0xFF);
- const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated;
- const u8 hi_rotated = (rotated_rm >> 16) & 0xFF;
- const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated;
-
- RD = ((hi_result << 16) | (lo_result & 0xFFFF));
- }
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC(sizeof(uxtab_inst));
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-WFE_INST : {
- // Stubbed, as WFE is a hint instruction.
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- LOG_TRACE(Core_ARM, "WFE executed.");
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC_STUB;
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-WFI_INST : {
- // Stubbed, as WFI is a hint instruction.
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- LOG_TRACE(Core_ARM, "WFI executed.");
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC_STUB;
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-YIELD_INST : {
- // Stubbed, as YIELD is a hint instruction.
- if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
- LOG_TRACE(Core_ARM, "YIELD executed.");
- }
-
- cpu->Reg[15] += cpu->GetInstructionSize();
- INC_PC_STUB;
- FETCH_INST;
- GOTO_NEXT_INST;
-}
-
-#define VFP_INTERPRETER_IMPL
-#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
-#undef VFP_INTERPRETER_IMPL
-
-END : {
- SAVE_NZCVT;
- cpu->NumInstrsToExecute = 0;
- return num_instrs;
-}
-INIT_INST_LENGTH : {
- cpu->NumInstrsToExecute = 0;
- return num_instrs;
-}
-}