summaryrefslogtreecommitdiff
path: root/src/core/arm/dyncom
diff options
context:
space:
mode:
authorGravatar bunnei2018-01-02 22:24:12 -0500
committerGravatar bunnei2018-01-02 22:24:12 -0500
commitb172f0d770486d4367fbea22906a5e908ef621e8 (patch)
tree6a564c23ed8f52c16c50942803f4a69fd0047f6c /src/core/arm/dyncom
parentvm_manager: Use a more reasonable MAX_ADDRESS size. (diff)
downloadyuzu-b172f0d770486d4367fbea22906a5e908ef621e8.tar.gz
yuzu-b172f0d770486d4367fbea22906a5e908ef621e8.tar.xz
yuzu-b172f0d770486d4367fbea22906a5e908ef621e8.zip
arm: Remove SkyEye/Dyncom code that is ARMv6-only.
Diffstat (limited to 'src/core/arm/dyncom')
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp132
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h46
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.cpp478
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.h36
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp4578
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.h9
-rw-r--r--src/core/arm/dyncom/arm_dyncom_run.h48
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.cpp390
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.h49
-rw-r--r--src/core/arm/dyncom/arm_dyncom_trans.cpp1887
-rw-r--r--src/core/arm/dyncom/arm_dyncom_trans.h494
11 files changed, 0 insertions, 8147 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
deleted file mode 100644
index 5ebf7a2f1..000000000
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cstring>
6#include <memory>
7#include "core/arm/dyncom/arm_dyncom.h"
8#include "core/arm/dyncom/arm_dyncom_interpreter.h"
9#include "core/arm/dyncom/arm_dyncom_run.h"
10#include "core/arm/dyncom/arm_dyncom_trans.h"
11#include "core/arm/skyeye_common/armstate.h"
12#include "core/arm/skyeye_common/armsupp.h"
13#include "core/arm/skyeye_common/vfp/vfp.h"
14#include "core/core.h"
15#include "core/core_timing.h"
16
17ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) {
18 state = std::make_unique<ARMul_State>(initial_mode);
19}
20
21ARM_DynCom::~ARM_DynCom() {}
22
23void ARM_DynCom::ClearInstructionCache() {
24 state->instruction_cache.clear();
25 trans_cache_buf_top = 0;
26}
27
28void ARM_DynCom::SetPC(u64 pc) {
29 state->Reg[15] = pc;
30}
31
32void ARM_DynCom::PageTableChanged() {
33 ClearInstructionCache();
34}
35
36u64 ARM_DynCom::GetPC() const {
37 return state->Reg[15];
38}
39
40u64 ARM_DynCom::GetReg(int index) const {
41 return state->Reg[index];
42}
43
44void ARM_DynCom::SetReg(int index, u64 value) {
45 state->Reg[index] = value;
46}
47
48const u128& ARM_DynCom::GetExtReg(int index) const {
49 return {};
50}
51
52void ARM_DynCom::SetExtReg(int index, u128& value) {
53}
54
55u32 ARM_DynCom::GetVFPReg(int index) const {
56 return state->ExtReg[index];
57}
58
59void ARM_DynCom::SetVFPReg(int index, u32 value) {
60 state->ExtReg[index] = value;
61}
62
63u32 ARM_DynCom::GetVFPSystemReg(VFPSystemRegister reg) const {
64 return state->VFP[reg];
65}
66
67void ARM_DynCom::SetVFPSystemReg(VFPSystemRegister reg, u32 value) {
68 state->VFP[reg] = value;
69}
70
71u32 ARM_DynCom::GetCPSR() const {
72 return state->Cpsr;
73}
74
75void ARM_DynCom::SetCPSR(u32 cpsr) {
76 state->Cpsr = cpsr;
77}
78
79u32 ARM_DynCom::GetCP15Register(CP15Register reg) {
80 return state->CP15[reg];
81}
82
83void ARM_DynCom::SetCP15Register(CP15Register reg, u32 value) {
84 state->CP15[reg] = value;
85}
86
87VAddr ARM_DynCom::GetTlsAddress() const {
88 return {};
89}
90
91void ARM_DynCom::SetTlsAddress(VAddr /*address*/) {
92}
93
94void ARM_DynCom::ExecuteInstructions(int num_instructions) {
95 state->NumInstrsToExecute = num_instructions;
96
97 // Dyncom only breaks on instruction dispatch. This only happens on every instruction when
98 // executing one instruction at a time. Otherwise, if a block is being executed, more
99 // instructions may actually be executed than specified.
100 unsigned ticks_executed = InterpreterMainLoop(state.get());
101 CoreTiming::AddTicks(ticks_executed);
102}
103
104void ARM_DynCom::SaveContext(ThreadContext& ctx) {
105 memcpy(ctx.cpu_registers, state->Reg.data(), sizeof(ctx.cpu_registers));
106 memcpy(ctx.fpu_registers, state->ExtReg.data(), sizeof(ctx.fpu_registers));
107
108 ctx.sp = state->Reg[13];
109 ctx.lr = state->Reg[14];
110 ctx.pc = state->Reg[15];
111 ctx.cpsr = state->Cpsr;
112
113 ctx.fpscr = state->VFP[VFP_FPSCR];
114 ctx.fpexc = state->VFP[VFP_FPEXC];
115}
116
117void ARM_DynCom::LoadContext(const ThreadContext& ctx) {
118 memcpy(state->Reg.data(), ctx.cpu_registers, sizeof(ctx.cpu_registers));
119 memcpy(state->ExtReg.data(), ctx.fpu_registers, sizeof(ctx.fpu_registers));
120
121 state->Reg[13] = ctx.sp;
122 state->Reg[14] = ctx.lr;
123 state->Reg[15] = ctx.pc;
124 state->Cpsr = ctx.cpsr;
125
126 state->VFP[VFP_FPSCR] = ctx.fpscr;
127 state->VFP[VFP_FPEXC] = ctx.fpexc;
128}
129
130void ARM_DynCom::PrepareReschedule() {
131 state->NumInstrsToExecute = 0;
132}
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
deleted file mode 100644
index cc3c0f3da..000000000
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ /dev/null
@@ -1,46 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include "common/common_types.h"
9#include "core/arm/arm_interface.h"
10#include "core/arm/skyeye_common/arm_regformat.h"
11#include "core/arm/skyeye_common/armstate.h"
12
13class ARM_DynCom final : public ARM_Interface {
14public:
15 ARM_DynCom(PrivilegeMode initial_mode);
16 ~ARM_DynCom();
17
18 void ClearInstructionCache() override;
19 void PageTableChanged() override;
20
21 void SetPC(u64 pc) override;
22 u64 GetPC() const override;
23 u64 GetReg(int index) const override;
24 void SetReg(int index, u64 value) override;
25 const u128& GetExtReg(int index) const override;
26 void SetExtReg(int index, u128& value) override;
27 u32 GetVFPReg(int index) const override;
28 void SetVFPReg(int index, u32 value) override;
29 u32 GetVFPSystemReg(VFPSystemRegister reg) const override;
30 void SetVFPSystemReg(VFPSystemRegister reg, u32 value) override;
31 u32 GetCPSR() const override;
32 void SetCPSR(u32 cpsr) override;
33 u32 GetCP15Register(CP15Register reg) override;
34 void SetCP15Register(CP15Register reg, u32 value) override;
35 VAddr GetTlsAddress() const override;
36 void SetTlsAddress(VAddr address) override;
37
38 void SaveContext(ThreadContext& ctx) override;
39 void LoadContext(const ThreadContext& ctx) override;
40
41 void PrepareReschedule() override;
42 void ExecuteInstructions(int num_instructions) override;
43
44private:
45 std::unique_ptr<ARMul_State> state;
46};
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp
deleted file mode 100644
index dcfcd6561..000000000
--- a/src/core/arm/dyncom/arm_dyncom_dec.cpp
+++ /dev/null
@@ -1,478 +0,0 @@
1// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/arm/dyncom/arm_dyncom_dec.h"
6#include "core/arm/skyeye_common/armsupp.h"
7
8// clang-format off
9const InstructionSetEncodingItem arm_instruction[] = {
10 { "vmla", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }},
11 { "vmls", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
12 { "vnmla", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
13 { "vnmls", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }},
14 { "vnmul", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
15 { "vmul", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }},
16 { "vadd", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }},
17 { "vsub", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
18 { "vdiv", 5, ARMVFP2, { 23, 27, 0x1D, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }},
19 { "vmov(i)", 4, ARMVFP3, { 23, 27, 0x1D, 20, 21, 0x3, 9, 11, 0x5, 4, 7, 0 }},
20 { "vmov(r)", 5, ARMVFP3, { 23, 27, 0x1D, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 1, 4, 4, 0 }},
21 { "vabs", 5, ARMVFP2, { 23, 27, 0x1D, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 3, 4, 4, 0 }},
22 { "vneg", 5, ARMVFP2, { 23, 27, 0x1D, 17, 21, 0x18, 9, 11, 0x5, 6, 7, 1, 4, 4, 0 }},
23 { "vsqrt", 5, ARMVFP2, { 23, 27, 0x1D, 16, 21, 0x31, 9, 11, 0x5, 6, 7, 3, 4, 4, 0 }},
24 { "vcmp", 5, ARMVFP2, { 23, 27, 0x1D, 16, 21, 0x34, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
25 { "vcmp2", 5, ARMVFP2, { 23, 27, 0x1D, 16, 21, 0x35, 9, 11, 0x5, 0, 6, 0x40 }},
26 { "vcvt(bds)", 5, ARMVFP2, { 23, 27, 0x1D, 16, 21, 0x37, 9, 11, 0x5, 6, 7, 3, 4, 4, 0 }},
27 { "vcvt(bff)", 6, ARMVFP3, { 23, 27, 0x1D, 19, 21, 0x7, 17, 17, 0x1, 9, 11, 5, 6, 6, 1 }},
28 { "vcvt(bfi)", 5, ARMVFP2, { 23, 27, 0x1D, 19, 21, 0x7, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
29 { "vmovbrs", 3, ARMVFP2, { 21, 27, 0x70, 8, 11, 0xA, 0, 6, 0x10 }},
30 { "vmsr", 2, ARMVFP2, { 20, 27, 0xEE, 0, 11, 0xA10 }},
31 { "vmovbrc", 4, ARMVFP2, { 23, 27, 0x1C, 20, 20, 0x0, 8, 11, 0xB, 0, 4, 0x10 }},
32 { "vmrs", 2, ARMVFP2, { 20, 27, 0xEF, 0, 11, 0xA10 }},
33 { "vmovbcr", 4, ARMVFP2, { 24, 27, 0xE, 20, 20, 1, 8, 11, 0xB, 0, 4, 0x10 }},
34 { "vmovbrrss", 3, ARMVFP2, { 21, 27, 0x62, 8, 11, 0xA, 4, 4, 1 }},
35 { "vmovbrrd", 3, ARMVFP2, { 21, 27, 0x62, 6, 11, 0x2C, 4, 4, 1 }},
36 { "vstr", 3, ARMVFP2, { 24, 27, 0xD, 20, 21, 0, 9, 11, 5 }},
37 { "vpush", 3, ARMVFP2, { 23, 27, 0x1A, 16, 21, 0x2D, 9, 11, 5 }},
38 { "vstm", 3, ARMVFP2, { 25, 27, 0x6, 20, 20, 0, 9, 11, 5 }},
39 { "vpop", 3, ARMVFP2, { 23, 27, 0x19, 16, 21, 0x3D, 9, 11, 5 }},
40 { "vldr", 3, ARMVFP2, { 24, 27, 0xD, 20, 21, 1, 9, 11, 5 }},
41 { "vldm", 3, ARMVFP2, { 25, 27, 0x6, 20, 20, 1, 9, 11, 5 }},
42
43 { "srs", 4, 6, { 25, 31, 0x0000007c, 22, 22, 0x00000001, 16, 20, 0x0000000d, 8, 11, 0x00000005 }},
44 { "rfe", 4, 6, { 25, 31, 0x0000007c, 22, 22, 0x00000000, 20, 20, 0x00000001, 8, 11, 0x0000000a }},
45 { "bkpt", 2, 3, { 20, 27, 0x00000012, 4, 7, 0x00000007 }},
46 { "blx", 1, 3, { 25, 31, 0x0000007d }},
47 { "cps", 3, 6, { 20, 31, 0x00000f10, 16, 16, 0x00000000, 5, 5, 0x00000000 }},
48 { "pld", 4, 4, { 26, 31, 0x0000003d, 24, 24, 0x00000001, 20, 22, 0x00000005, 12, 15, 0x0000000f }},
49 { "setend", 2, 6, { 16, 31, 0x0000f101, 4, 7, 0x00000000 }},
50 { "clrex", 1, 6, { 0, 31, 0xf57ff01f }},
51 { "rev16", 2, 6, { 16, 27, 0x000006bf, 4, 11, 0x000000fb }},
52 { "usad8", 3, 6, { 20, 27, 0x00000078, 12, 15, 0x0000000f, 4, 7, 0x00000001 }},
53 { "sxtb", 2, 6, { 16, 27, 0x000006af, 4, 7, 0x00000007 }},
54 { "uxtb", 2, 6, { 16, 27, 0x000006ef, 4, 7, 0x00000007 }},
55 { "sxth", 2, 6, { 16, 27, 0x000006bf, 4, 7, 0x00000007 }},
56 { "sxtb16", 2, 6, { 16, 27, 0x0000068f, 4, 7, 0x00000007 }},
57 { "uxth", 2, 6, { 16, 27, 0x000006ff, 4, 7, 0x00000007 }},
58 { "uxtb16", 2, 6, { 16, 27, 0x000006cf, 4, 7, 0x00000007 }},
59 { "cpy", 2, 6, { 20, 27, 0x0000001a, 4, 11, 0x00000000 }},
60 { "uxtab", 2, 6, { 20, 27, 0x0000006e, 4, 9, 0x00000007 }},
61 { "ssub8", 2, 6, { 20, 27, 0x00000061, 4, 7, 0x0000000f }},
62 { "shsub8", 2, 6, { 20, 27, 0x00000063, 4, 7, 0x0000000f }},
63 { "ssubaddx", 2, 6, { 20, 27, 0x00000061, 4, 7, 0x00000005 }},
64 { "strex", 2, 6, { 20, 27, 0x00000018, 4, 7, 0x00000009 }},
65 { "strexb", 2, 7, { 20, 27, 0x0000001c, 4, 7, 0x00000009 }},
66 { "swp", 2, 0, { 20, 27, 0x00000010, 4, 7, 0x00000009 }},
67 { "swpb", 2, 0, { 20, 27, 0x00000014, 4, 7, 0x00000009 }},
68 { "ssub16", 2, 6, { 20, 27, 0x00000061, 4, 7, 0x00000007 }},
69 { "ssat16", 2, 6, { 20, 27, 0x0000006a, 4, 7, 0x00000003 }},
70 { "shsubaddx", 2, 6, { 20, 27, 0x00000063, 4, 7, 0x00000005 }},
71 { "qsubaddx", 2, 6, { 20, 27, 0x00000062, 4, 7, 0x00000005 }},
72 { "shaddsubx", 2, 6, { 20, 27, 0x00000063, 4, 7, 0x00000003 }},
73 { "shadd8", 2, 6, { 20, 27, 0x00000063, 4, 7, 0x00000009 }},
74 { "shadd16", 2, 6, { 20, 27, 0x00000063, 4, 7, 0x00000001 }},
75 { "sel", 2, 6, { 20, 27, 0x00000068, 4, 7, 0x0000000b }},
76 { "saddsubx", 2, 6, { 20, 27, 0x00000061, 4, 7, 0x00000003 }},
77 { "sadd8", 2, 6, { 20, 27, 0x00000061, 4, 7, 0x00000009 }},
78 { "sadd16", 2, 6, { 20, 27, 0x00000061, 4, 7, 0x00000001 }},
79 { "shsub16", 2, 6, { 20, 27, 0x00000063, 4, 7, 0x00000007 }},
80 { "umaal", 2, 6, { 20, 27, 0x00000004, 4, 7, 0x00000009 }},
81 { "uxtab16", 2, 6, { 20, 27, 0x0000006c, 4, 7, 0x00000007 }},
82 { "usubaddx", 2, 6, { 20, 27, 0x00000065, 4, 7, 0x00000005 }},
83 { "usub8", 2, 6, { 20, 27, 0x00000065, 4, 7, 0x0000000f }},
84 { "usub16", 2, 6, { 20, 27, 0x00000065, 4, 7, 0x00000007 }},
85 { "usat16", 2, 6, { 20, 27, 0x0000006e, 4, 7, 0x00000003 }},
86 { "usada8", 2, 6, { 20, 27, 0x00000078, 4, 7, 0x00000001 }},
87 { "uqsubaddx", 2, 6, { 20, 27, 0x00000066, 4, 7, 0x00000005 }},
88 { "uqsub8", 2, 6, { 20, 27, 0x00000066, 4, 7, 0x0000000f }},
89 { "uqsub16", 2, 6, { 20, 27, 0x00000066, 4, 7, 0x00000007 }},
90 { "uqaddsubx", 2, 6, { 20, 27, 0x00000066, 4, 7, 0x00000003 }},
91 { "uqadd8", 2, 6, { 20, 27, 0x00000066, 4, 7, 0x00000009 }},
92 { "uqadd16", 2, 6, { 20, 27, 0x00000066, 4, 7, 0x00000001 }},
93 { "sxtab", 2, 6, { 20, 27, 0x0000006a, 4, 7, 0x00000007 }},
94 { "uhsubaddx", 2, 6, { 20, 27, 0x00000067, 4, 7, 0x00000005 }},
95 { "uhsub8", 2, 6, { 20, 27, 0x00000067, 4, 7, 0x0000000f }},
96 { "uhsub16", 2, 6, { 20, 27, 0x00000067, 4, 7, 0x00000007 }},
97 { "uhaddsubx", 2, 6, { 20, 27, 0x00000067, 4, 7, 0x00000003 }},
98 { "uhadd8", 2, 6, { 20, 27, 0x00000067, 4, 7, 0x00000009 }},
99 { "uhadd16", 2, 6, { 20, 27, 0x00000067, 4, 7, 0x00000001 }},
100 { "uaddsubx", 2, 6, { 20, 27, 0x00000065, 4, 7, 0x00000003 }},
101 { "uadd8", 2, 6, { 20, 27, 0x00000065, 4, 7, 0x00000009 }},
102 { "uadd16", 2, 6, { 20, 27, 0x00000065, 4, 7, 0x00000001 }},
103 { "sxtah", 2, 6, { 20, 27, 0x0000006b, 4, 7, 0x00000007 }},
104 { "sxtab16", 2, 6, { 20, 27, 0x00000068, 4, 7, 0x00000007 }},
105 { "qadd8", 2, 6, { 20, 27, 0x00000062, 4, 7, 0x00000009 }},
106 { "bxj", 2, 5, { 20, 27, 0x00000012, 4, 7, 0x00000002 }},
107 { "clz", 2, 3, { 20, 27, 0x00000016, 4, 7, 0x00000001 }},
108 { "uxtah", 2, 6, { 20, 27, 0x0000006f, 4, 7, 0x00000007 }},
109 { "bx", 2, 2, { 20, 27, 0x00000012, 4, 7, 0x00000001 }},
110 { "rev", 2, 6, { 20, 27, 0x0000006b, 4, 7, 0x00000003 }},
111 { "blx", 2, 3, { 20, 27, 0x00000012, 4, 7, 0x00000003 }},
112 { "revsh", 2, 6, { 20, 27, 0x0000006f, 4, 7, 0x0000000b }},
113 { "qadd", 2, 4, { 20, 27, 0x00000010, 4, 7, 0x00000005 }},
114 { "qadd16", 2, 6, { 20, 27, 0x00000062, 4, 7, 0x00000001 }},
115 { "qaddsubx", 2, 6, { 20, 27, 0x00000062, 4, 7, 0x00000003 }},
116 { "ldrex", 2, 0, { 20, 27, 0x00000019, 4, 7, 0x00000009 }},
117 { "qdadd", 2, 4, { 20, 27, 0x00000014, 4, 7, 0x00000005 }},
118 { "qdsub", 2, 4, { 20, 27, 0x00000016, 4, 7, 0x00000005 }},
119 { "qsub", 2, 4, { 20, 27, 0x00000012, 4, 7, 0x00000005 }},
120 { "ldrexb", 2, 7, { 20, 27, 0x0000001d, 4, 7, 0x00000009 }},
121 { "qsub8", 2, 6, { 20, 27, 0x00000062, 4, 7, 0x0000000f }},
122 { "qsub16", 2, 6, { 20, 27, 0x00000062, 4, 7, 0x00000007 }},
123 { "smuad", 4, 6, { 20, 27, 0x00000070, 12, 15, 0x0000000f, 6, 7, 0x00000000, 4, 4, 0x00000001 }},
124 { "smmul", 4, 6, { 20, 27, 0x00000075, 12, 15, 0x0000000f, 6, 7, 0x00000000, 4, 4, 0x00000001 }},
125 { "smusd", 4, 6, { 20, 27, 0x00000070, 12, 15, 0x0000000f, 6, 7, 0x00000001, 4, 4, 0x00000001 }},
126 { "smlsd", 3, 6, { 20, 27, 0x00000070, 6, 7, 0x00000001, 4, 4, 0x00000001 }},
127 { "smlsld", 3, 6, { 20, 27, 0x00000074, 6, 7, 0x00000001, 4, 4, 0x00000001 }},
128 { "smmla", 3, 6, { 20, 27, 0x00000075, 6, 7, 0x00000000, 4, 4, 0x00000001 }},
129 { "smmls", 3, 6, { 20, 27, 0x00000075, 6, 7, 0x00000003, 4, 4, 0x00000001 }},
130 { "smlald", 3, 6, { 20, 27, 0x00000074, 6, 7, 0x00000000, 4, 4, 0x00000001 }},
131 { "smlad", 3, 6, { 20, 27, 0x00000070, 6, 7, 0x00000000, 4, 4, 0x00000001 }},
132 { "smlaw", 3, 4, { 20, 27, 0x00000012, 7, 7, 0x00000001, 4, 5, 0x00000000 }},
133 { "smulw", 3, 4, { 20, 27, 0x00000012, 7, 7, 0x00000001, 4, 5, 0x00000002 }},
134 { "pkhtb", 2, 6, { 20, 27, 0x00000068, 4, 6, 0x00000005 }},
135 { "pkhbt", 2, 6, { 20, 27, 0x00000068, 4, 6, 0x00000001 }},
136 { "smul", 3, 4, { 20, 27, 0x00000016, 7, 7, 0x00000001, 4, 4, 0x00000000 }},
137 { "smlalxy", 3, 4, { 20, 27, 0x00000014, 7, 7, 0x00000001, 4, 4, 0x00000000 }},
138 { "smla", 3, 4, { 20, 27, 0x00000010, 7, 7, 0x00000001, 4, 4, 0x00000000 }},
139 { "mcrr", 1, 6, { 20, 27, 0x000000c4 }},
140 { "mrrc", 1, 6, { 20, 27, 0x000000c5 }},
141 { "cmp", 2, 0, { 26, 27, 0x00000000, 20, 24, 0x00000015 }},
142 { "tst", 2, 0, { 26, 27, 0x00000000, 20, 24, 0x00000011 }},
143 { "teq", 2, 0, { 26, 27, 0x00000000, 20, 24, 0x00000013 }},
144 { "cmn", 2, 0, { 26, 27, 0x00000000, 20, 24, 0x00000017 }},
145 { "smull", 2, 0, { 21, 27, 0x00000006, 4, 7, 0x00000009 }},
146 { "umull", 2, 0, { 21, 27, 0x00000004, 4, 7, 0x00000009 }},
147 { "umlal", 2, 0, { 21, 27, 0x00000005, 4, 7, 0x00000009 }},
148 { "smlal", 2, 0, { 21, 27, 0x00000007, 4, 7, 0x00000009 }},
149 { "mul", 2, 0, { 21, 27, 0x00000000, 4, 7, 0x00000009 }},
150 { "mla", 2, 0, { 21, 27, 0x00000001, 4, 7, 0x00000009 }},
151 { "ssat", 2, 6, { 21, 27, 0x00000035, 4, 5, 0x00000001 }},
152 { "usat", 2, 6, { 21, 27, 0x00000037, 4, 5, 0x00000001 }},
153 { "mrs", 4, 0, { 23, 27, 0x00000002, 20, 21, 0x00000000, 16, 19, 0x0000000f, 0, 11, 0x00000000 }},
154 { "msr", 3, 0, { 23, 27, 0x00000002, 20, 21, 0x00000002, 4, 7, 0x00000000 }},
155 { "and", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000000 }},
156 { "bic", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x0000000e }},
157 { "ldm", 3, 0, { 25, 27, 0x00000004, 20, 22, 0x00000005, 15, 15, 0x00000000 }},
158 { "eor", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000001 }},
159 { "add", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000004 }},
160 { "rsb", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000003 }},
161 { "rsc", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000007 }},
162 { "sbc", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000006 }},
163 { "adc", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000005 }},
164 { "sub", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000002 }},
165 { "orr", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x0000000c }},
166 { "mvn", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x0000000f }},
167 { "mov", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x0000000d }},
168 { "stm", 2, 0, { 25, 27, 0x00000004, 20, 22, 0x00000004 }},
169 { "ldm", 4, 0, { 25, 27, 0x00000004, 22, 22, 0x00000001, 20, 20, 0x00000001, 15, 15, 0x00000001 }},
170 { "ldrsh", 3, 2, { 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000f }},
171 { "stm", 3, 0, { 25, 27, 0x00000004, 22, 22, 0x00000000, 20, 20, 0x00000000 }},
172 { "ldm", 3, 0, { 25, 27, 0x00000004, 22, 22, 0x00000000, 20, 20, 0x00000001 }},
173 { "ldrsb", 3, 2, { 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000d }},
174 { "strd", 3, 4, { 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000f }},
175 { "ldrh", 3, 0, { 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000b }},
176 { "strh", 3, 0, { 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000b }},
177 { "ldrd", 3, 4, { 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000d }},
178 { "strt", 3, 0, { 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000002 }},
179 { "strbt", 3, 0, { 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000006 }},
180 { "ldrbt", 3, 0, { 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000007 }},
181 { "ldrt", 3, 0, { 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000003 }},
182 { "mrc", 3, 6, { 24, 27, 0x0000000e, 20, 20, 0x00000001, 4, 4, 0x00000001 }},
183 { "mcr", 3, 0, { 24, 27, 0x0000000e, 20, 20, 0x00000000, 4, 4, 0x00000001 }},
184 { "msr", 3, 0, { 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000001 }},
185 { "msr", 4, 0, { 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 16, 19, 0x00000004 }},
186 { "msr", 5, 0, { 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 19, 19, 0x00000001, 16, 17, 0x00000000 }},
187 { "msr", 4, 0, { 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 16, 17, 0x00000001 }},
188 { "msr", 4, 0, { 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 17, 17, 0x00000001 }},
189 { "ldrb", 3, 0, { 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000001 }},
190 { "strb", 3, 0, { 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000000 }},
191 { "ldr", 4, 0, { 28, 31, 0x0000000e, 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000001 }},
192 { "ldrcond", 3, 0, { 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000001 }},
193 { "str", 3, 0, { 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000000 }},
194 { "cdp", 2, 0, { 24, 27, 0x0000000e, 4, 4, 0x00000000 }},
195 { "stc", 2, 0, { 25, 27, 0x00000006, 20, 20, 0x00000000 }},
196 { "ldc", 2, 0, { 25, 27, 0x00000006, 20, 20, 0x00000001 }},
197 { "ldrexd", 2, ARMV6K, { 20, 27, 0x0000001B, 4, 7, 0x00000009 }},
198 { "strexd", 2, ARMV6K, { 20, 27, 0x0000001A, 4, 7, 0x00000009 }},
199 { "ldrexh", 2, ARMV6K, { 20, 27, 0x0000001F, 4, 7, 0x00000009 }},
200 { "strexh", 2, ARMV6K, { 20, 27, 0x0000001E, 4, 7, 0x00000009 }},
201 { "nop", 5, ARMV6K, { 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000000 }},
202 { "yield", 5, ARMV6K, { 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000001 }},
203 { "wfe", 5, ARMV6K, { 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000002 }},
204 { "wfi", 5, ARMV6K, { 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000003 }},
205 { "sev", 5, ARMV6K, { 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000004 }},
206 { "swi", 1, 0, { 24, 27, 0x0000000f }},
207 { "bbl", 1, 0, { 25, 27, 0x00000005 }},
208};
209
210
211const InstructionSetEncodingItem arm_exclusion_code[] = {
212 { "vmla", 0, ARMVFP2, { 0 }},
213 { "vmls", 0, ARMVFP2, { 0 }},
214 { "vnmla", 0, ARMVFP2, { 0 }},
215 { "vnmls", 0, ARMVFP2, { 0 }},
216 { "vnmul", 0, ARMVFP2, { 0 }},
217 { "vmul", 0, ARMVFP2, { 0 }},
218 { "vadd", 0, ARMVFP2, { 0 }},
219 { "vsub", 0, ARMVFP2, { 0 }},
220 { "vdiv", 0, ARMVFP2, { 0 }},
221 { "vmov(i)", 0, ARMVFP3, { 0 }},
222 { "vmov(r)", 0, ARMVFP3, { 0 }},
223 { "vabs", 0, ARMVFP2, { 0 }},
224 { "vneg", 0, ARMVFP2, { 0 }},
225 { "vsqrt", 0, ARMVFP2, { 0 }},
226 { "vcmp", 0, ARMVFP2, { 0 }},
227 { "vcmp2", 0, ARMVFP2, { 0 }},
228 { "vcvt(bff)", 0, ARMVFP3, { 4, 4, 1 }},
229 { "vcvt(bds)", 0, ARMVFP2, { 0 }},
230 { "vcvt(bfi)", 0, ARMVFP2, { 0 }},
231 { "vmovbrs", 0, ARMVFP2, { 0 }},
232 { "vmsr", 0, ARMVFP2, { 0 }},
233 { "vmovbrc", 0, ARMVFP2, { 0 }},
234 { "vmrs", 0, ARMVFP2, { 0 }},
235 { "vmovbcr", 0, ARMVFP2, { 0 }},
236 { "vmovbrrss", 0, ARMVFP2, { 0 }},
237 { "vmovbrrd", 0, ARMVFP2, { 0 }},
238 { "vstr", 0, ARMVFP2, { 0 }},
239 { "vpush", 0, ARMVFP2, { 0 }},
240 { "vstm", 0, ARMVFP2, { 0 }},
241 { "vpop", 0, ARMVFP2, { 0 }},
242 { "vldr", 0, ARMVFP2, { 0 }},
243 { "vldm", 0, ARMVFP2, { 0 }},
244
245 { "srs", 0, 6, { 0 }},
246 { "rfe", 0, 6, { 0 }},
247 { "bkpt", 0, 3, { 0 }},
248 { "blx", 0, 3, { 0 }},
249 { "cps", 0, 6, { 0 }},
250 { "pld", 0, 4, { 0 }},
251 { "setend", 0, 6, { 0 }},
252 { "clrex", 0, 6, { 0 }},
253 { "rev16", 0, 6, { 0 }},
254 { "usad8", 0, 6, { 0 }},
255 { "sxtb", 0, 6, { 0 }},
256 { "uxtb", 0, 6, { 0 }},
257 { "sxth", 0, 6, { 0 }},
258 { "sxtb16", 0, 6, { 0 }},
259 { "uxth", 0, 6, { 0 }},
260 { "uxtb16", 0, 6, { 0 }},
261 { "cpy", 0, 6, { 0 }},
262 { "uxtab", 0, 6, { 0 }},
263 { "ssub8", 0, 6, { 0 }},
264 { "shsub8", 0, 6, { 0 }},
265 { "ssubaddx", 0, 6, { 0 }},
266 { "strex", 0, 6, { 0 }},
267 { "strexb", 0, 7, { 0 }},
268 { "swp", 0, 0, { 0 }},
269 { "swpb", 0, 0, { 0 }},
270 { "ssub16", 0, 6, { 0 }},
271 { "ssat16", 0, 6, { 0 }},
272 { "shsubaddx", 0, 6, { 0 }},
273 { "qsubaddx", 0, 6, { 0 }},
274 { "shaddsubx", 0, 6, { 0 }},
275 { "shadd8", 0, 6, { 0 }},
276 { "shadd16", 0, 6, { 0 }},
277 { "sel", 0, 6, { 0 }},
278 { "saddsubx", 0, 6, { 0 }},
279 { "sadd8", 0, 6, { 0 }},
280 { "sadd16", 0, 6, { 0 }},
281 { "shsub16", 0, 6, { 0 }},
282 { "umaal", 0, 6, { 0 }},
283 { "uxtab16", 0, 6, { 0 }},
284 { "usubaddx", 0, 6, { 0 }},
285 { "usub8", 0, 6, { 0 }},
286 { "usub16", 0, 6, { 0 }},
287 { "usat16", 0, 6, { 0 }},
288 { "usada8", 0, 6, { 0 }},
289 { "uqsubaddx", 0, 6, { 0 }},
290 { "uqsub8", 0, 6, { 0 }},
291 { "uqsub16", 0, 6, { 0 }},
292 { "uqaddsubx", 0, 6, { 0 }},
293 { "uqadd8", 0, 6, { 0 }},
294 { "uqadd16", 0, 6, { 0 }},
295 { "sxtab", 0, 6, { 0 }},
296 { "uhsubaddx", 0, 6, { 0 }},
297 { "uhsub8", 0, 6, { 0 }},
298 { "uhsub16", 0, 6, { 0 }},
299 { "uhaddsubx", 0, 6, { 0 }},
300 { "uhadd8", 0, 6, { 0 }},
301 { "uhadd16", 0, 6, { 0 }},
302 { "uaddsubx", 0, 6, { 0 }},
303 { "uadd8", 0, 6, { 0 }},
304 { "uadd16", 0, 6, { 0 }},
305 { "sxtah", 0, 6, { 0 }},
306 { "sxtab16", 0, 6, { 0 }},
307 { "qadd8", 0, 6, { 0 }},
308 { "bxj", 0, 5, { 0 }},
309 { "clz", 0, 3, { 0 }},
310 { "uxtah", 0, 6, { 0 }},
311 { "bx", 0, 2, { 0 }},
312 { "rev", 0, 6, { 0 }},
313 { "blx", 0, 3, { 0 }},
314 { "revsh", 0, 6, { 0 }},
315 { "qadd", 0, 4, { 0 }},
316 { "qadd16", 0, 6, { 0 }},
317 { "qaddsubx", 0, 6, { 0 }},
318 { "ldrex", 0, 0, { 0 }},
319 { "qdadd", 0, 4, { 0 }},
320 { "qdsub", 0, 4, { 0 }},
321 { "qsub", 0, 4, { 0 }},
322 { "ldrexb", 0, 7, { 0 }},
323 { "qsub8", 0, 6, { 0 }},
324 { "qsub16", 0, 6, { 0 }},
325 { "smuad", 0, 6, { 0 }},
326 { "smmul", 0, 6, { 0 }},
327 { "smusd", 0, 6, { 0 }},
328 { "smlsd", 0, 6, { 0 }},
329 { "smlsld", 0, 6, { 0 }},
330 { "smmla", 0, 6, { 0 }},
331 { "smmls", 0, 6, { 0 }},
332 { "smlald", 0, 6, { 0 }},
333 { "smlad", 0, 6, { 0 }},
334 { "smlaw", 0, 4, { 0 }},
335 { "smulw", 0, 4, { 0 }},
336 { "pkhtb", 0, 6, { 0 }},
337 { "pkhbt", 0, 6, { 0 }},
338 { "smul", 0, 4, { 0 }},
339 { "smlal", 0, 4, { 0 }},
340 { "smla", 0, 4, { 0 }},
341 { "mcrr", 0, 6, { 0 }},
342 { "mrrc", 0, 6, { 0 }},
343 { "cmp", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
344 { "tst", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
345 { "teq", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
346 { "cmn", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
347 { "smull", 0, 0, { 0 }},
348 { "umull", 0, 0, { 0 }},
349 { "umlal", 0, 0, { 0 }},
350 { "smlal", 0, 0, { 0 }},
351 { "mul", 0, 0, { 0 }},
352 { "mla", 0, 0, { 0 }},
353 { "ssat", 0, 6, { 0 }},
354 { "usat", 0, 6, { 0 }},
355 { "mrs", 0, 0, { 0 }},
356 { "msr", 0, 0, { 0 }},
357 { "and", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
358 { "bic", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
359 { "ldm", 0, 0, { 0 }},
360 { "eor", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
361 { "add", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
362 { "rsb", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
363 { "rsc", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
364 { "sbc", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
365 { "adc", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
366 { "sub", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
367 { "orr", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
368 { "mvn", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
369 { "mov", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }},
370 { "stm", 0, 0, { 0 }},
371 { "ldm", 0, 0, { 0 }},
372 { "ldrsh", 0, 2, { 0 }},
373 { "stm", 0, 0, { 0 }},
374 { "ldm", 0, 0, { 0 }},
375 { "ldrsb", 0, 2, { 0 }},
376 { "strd", 0, 4, { 0 }},
377 { "ldrh", 0, 0, { 0 }},
378 { "strh", 0, 0, { 0 }},
379 { "ldrd", 0, 4, { 0 }},
380 { "strt", 0, 0, { 0 }},
381 { "strbt", 0, 0, { 0 }},
382 { "ldrbt", 0, 0, { 0 }},
383 { "ldrt", 0, 0, { 0 }},
384 { "mrc", 0, 6, { 0 }},
385 { "mcr", 0, 0, { 0 }},
386 { "msr", 0, 0, { 0 }},
387 { "msr", 0, 0, { 0 }},
388 { "msr", 0, 0, { 0 }},
389 { "msr", 0, 0, { 0 }},
390 { "msr", 0, 0, { 0 }},
391 { "ldrb", 0, 0, { 0 }},
392 { "strb", 0, 0, { 0 }},
393 { "ldr", 0, 0, { 0 }},
394 { "ldrcond", 1, 0, { 28, 31, 0x0000000e }},
395 { "str", 0, 0, { 0 }},
396 { "cdp", 0, 0, { 0 }},
397 { "stc", 0, 0, { 0 }},
398 { "ldc", 0, 0, { 0 }},
399 { "ldrexd", 0, ARMV6K, { 0 }},
400 { "strexd", 0, ARMV6K, { 0 }},
401 { "ldrexh", 0, ARMV6K, { 0 }},
402 { "strexh", 0, ARMV6K, { 0 }},
403 { "nop", 0, ARMV6K, { 0 }},
404 { "yield", 0, ARMV6K, { 0 }},
405 { "wfe", 0, ARMV6K, { 0 }},
406 { "wfi", 0, ARMV6K, { 0 }},
407 { "sev", 0, ARMV6K, { 0 }},
408 { "swi", 0, 0, { 0 }},
409 { "bbl", 0, 0, { 0 }},
410
411 { "bl_1_thumb", 0, INVALID, { 0 }}, // Should be table[-4]
412 { "bl_2_thumb", 0, INVALID, { 0 }}, // Should be located at the end of the table[-3]
413 { "blx_1_thumb", 0, INVALID, { 0 }}, // Should be located at table[-2]
414 { "invalid", 0, INVALID, { 0 }}
415};
416// clang-format on
417
418ARMDecodeStatus DecodeARMInstruction(u32 instr, int* idx) {
419 int n = 0;
420 int base = 0;
421 int instr_slots = sizeof(arm_instruction) / sizeof(InstructionSetEncodingItem);
422 ARMDecodeStatus ret = ARMDecodeStatus::FAILURE;
423
424 for (int i = 0; i < instr_slots; i++) {
425 n = arm_instruction[i].attribute_value;
426 base = 0;
427
428 // 3DS has no VFP3 support
429 if (arm_instruction[i].version == ARMVFP3)
430 continue;
431
432 while (n) {
433 if (arm_instruction[i].content[base + 1] == 31 &&
434 arm_instruction[i].content[base] == 0) {
435 // clrex
436 if (instr != arm_instruction[i].content[base + 2]) {
437 break;
438 }
439 } else if (BITS(instr, arm_instruction[i].content[base],
440 arm_instruction[i].content[base + 1]) !=
441 arm_instruction[i].content[base + 2]) {
442 break;
443 }
444 base += 3;
445 n--;
446 }
447
448 // All conditions are satisfied.
449 if (n == 0)
450 ret = ARMDecodeStatus::SUCCESS;
451
452 if (ret == ARMDecodeStatus::SUCCESS) {
453 n = arm_exclusion_code[i].attribute_value;
454 if (n != 0) {
455 base = 0;
456 while (n) {
457 if (BITS(instr, arm_exclusion_code[i].content[base],
458 arm_exclusion_code[i].content[base + 1]) !=
459 arm_exclusion_code[i].content[base + 2]) {
460 break;
461 }
462 base += 3;
463 n--;
464 }
465
466 // All conditions are satisfied.
467 if (n == 0)
468 ret = ARMDecodeStatus::FAILURE;
469 }
470 }
471
472 if (ret == ARMDecodeStatus::SUCCESS) {
473 *idx = i;
474 return ret;
475 }
476 }
477 return ret;
478}
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.h b/src/core/arm/dyncom/arm_dyncom_dec.h
deleted file mode 100644
index 1dcf7ecd1..000000000
--- a/src/core/arm/dyncom/arm_dyncom_dec.h
+++ /dev/null
@@ -1,36 +0,0 @@
1// Copyright 2012 Michael Kang, 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8
9enum class ARMDecodeStatus { SUCCESS, FAILURE };
10
11ARMDecodeStatus DecodeARMInstruction(u32 instr, int* idx);
12
13struct InstructionSetEncodingItem {
14 const char* name;
15 int attribute_value;
16 int version;
17 u32 content[21];
18};
19
20// ARM versions
21enum {
22 INVALID = 0,
23 ARMALL,
24 ARMV4,
25 ARMV4T,
26 ARMV5T,
27 ARMV5TE,
28 ARMV5TEJ,
29 ARMV6,
30 ARM1176JZF_S,
31 ARMVFP2,
32 ARMVFP3,
33 ARMV6K,
34};
35
36extern const InstructionSetEncodingItem arm_instruction[];
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 @@
1// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#define CITRA_IGNORE_EXIT(x)
6
7#include <algorithm>
8#include <cinttypes>
9#include <cstdio>
10#include "common/common_types.h"
11#include "common/logging/log.h"
12#include "common/microprofile.h"
13#include "core/arm/dyncom/arm_dyncom_dec.h"
14#include "core/arm/dyncom/arm_dyncom_interpreter.h"
15#include "core/arm/dyncom/arm_dyncom_run.h"
16#include "core/arm/dyncom/arm_dyncom_thumb.h"
17#include "core/arm/dyncom/arm_dyncom_trans.h"
18#include "core/arm/skyeye_common/armstate.h"
19#include "core/arm/skyeye_common/armsupp.h"
20#include "core/arm/skyeye_common/vfp/vfp.h"
21#include "core/gdbstub/gdbstub.h"
22#include "core/hle/svc.h"
23#include "core/memory.h"
24
25#define RM BITS(sht_oper, 0, 3)
26#define RS BITS(sht_oper, 8, 11)
27
28#define glue(x, y) x##y
29#define DPO(s) glue(DataProcessingOperands, s)
30#define ROTATE_RIGHT(n, i, l) ((n << (l - i)) | (n >> i))
31#define ROTATE_LEFT(n, i, l) ((n >> (l - i)) | (n << i))
32#define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32)
33#define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32)
34
35static bool CondPassed(const ARMul_State* cpu, unsigned int cond) {
36 const bool n_flag = cpu->NFlag != 0;
37 const bool z_flag = cpu->ZFlag != 0;
38 const bool c_flag = cpu->CFlag != 0;
39 const bool v_flag = cpu->VFlag != 0;
40
41 switch (cond) {
42 case ConditionCode::EQ:
43 return z_flag;
44 case ConditionCode::NE:
45 return !z_flag;
46 case ConditionCode::CS:
47 return c_flag;
48 case ConditionCode::CC:
49 return !c_flag;
50 case ConditionCode::MI:
51 return n_flag;
52 case ConditionCode::PL:
53 return !n_flag;
54 case ConditionCode::VS:
55 return v_flag;
56 case ConditionCode::VC:
57 return !v_flag;
58 case ConditionCode::HI:
59 return (c_flag && !z_flag);
60 case ConditionCode::LS:
61 return (!c_flag || z_flag);
62 case ConditionCode::GE:
63 return (n_flag == v_flag);
64 case ConditionCode::LT:
65 return (n_flag != v_flag);
66 case ConditionCode::GT:
67 return (!z_flag && (n_flag == v_flag));
68 case ConditionCode::LE:
69 return (z_flag || (n_flag != v_flag));
70 case ConditionCode::AL:
71 case ConditionCode::NV: // Unconditional
72 return true;
73 }
74
75 return false;
76}
77
78static unsigned int DPO(Immediate)(ARMul_State* cpu, unsigned int sht_oper) {
79 unsigned int immed_8 = BITS(sht_oper, 0, 7);
80 unsigned int rotate_imm = BITS(sht_oper, 8, 11);
81 unsigned int shifter_operand = ROTATE_RIGHT_32(immed_8, rotate_imm * 2);
82 if (rotate_imm == 0)
83 cpu->shifter_carry_out = cpu->CFlag;
84 else
85 cpu->shifter_carry_out = BIT(shifter_operand, 31);
86 return shifter_operand;
87}
88
89static unsigned int DPO(Register)(ARMul_State* cpu, unsigned int sht_oper) {
90 unsigned int rm = CHECK_READ_REG15(cpu, RM);
91 unsigned int shifter_operand = rm;
92 cpu->shifter_carry_out = cpu->CFlag;
93 return shifter_operand;
94}
95
96static unsigned int DPO(LogicalShiftLeftByImmediate)(ARMul_State* cpu, unsigned int sht_oper) {
97 int shift_imm = BITS(sht_oper, 7, 11);
98 unsigned int rm = CHECK_READ_REG15(cpu, RM);
99 unsigned int shifter_operand;
100 if (shift_imm == 0) {
101 shifter_operand = rm;
102 cpu->shifter_carry_out = cpu->CFlag;
103 } else {
104 shifter_operand = rm << shift_imm;
105 cpu->shifter_carry_out = BIT(rm, 32 - shift_imm);
106 }
107 return shifter_operand;
108}
109
110static unsigned int DPO(LogicalShiftLeftByRegister)(ARMul_State* cpu, unsigned int sht_oper) {
111 int shifter_operand;
112 unsigned int rm = CHECK_READ_REG15(cpu, RM);
113 unsigned int rs = CHECK_READ_REG15(cpu, RS);
114 if (BITS(rs, 0, 7) == 0) {
115 shifter_operand = rm;
116 cpu->shifter_carry_out = cpu->CFlag;
117 } else if (BITS(rs, 0, 7) < 32) {
118 shifter_operand = rm << BITS(rs, 0, 7);
119 cpu->shifter_carry_out = BIT(rm, 32 - BITS(rs, 0, 7));
120 } else if (BITS(rs, 0, 7) == 32) {
121 shifter_operand = 0;
122 cpu->shifter_carry_out = BIT(rm, 0);
123 } else {
124 shifter_operand = 0;
125 cpu->shifter_carry_out = 0;
126 }
127 return shifter_operand;
128}
129
130static unsigned int DPO(LogicalShiftRightByImmediate)(ARMul_State* cpu, unsigned int sht_oper) {
131 unsigned int rm = CHECK_READ_REG15(cpu, RM);
132 unsigned int shifter_operand;
133 int shift_imm = BITS(sht_oper, 7, 11);
134 if (shift_imm == 0) {
135 shifter_operand = 0;
136 cpu->shifter_carry_out = BIT(rm, 31);
137 } else {
138 shifter_operand = rm >> shift_imm;
139 cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
140 }
141 return shifter_operand;
142}
143
144static unsigned int DPO(LogicalShiftRightByRegister)(ARMul_State* cpu, unsigned int sht_oper) {
145 unsigned int rs = CHECK_READ_REG15(cpu, RS);
146 unsigned int rm = CHECK_READ_REG15(cpu, RM);
147 unsigned int shifter_operand;
148 if (BITS(rs, 0, 7) == 0) {
149 shifter_operand = rm;
150 cpu->shifter_carry_out = cpu->CFlag;
151 } else if (BITS(rs, 0, 7) < 32) {
152 shifter_operand = rm >> BITS(rs, 0, 7);
153 cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 7) - 1);
154 } else if (BITS(rs, 0, 7) == 32) {
155 shifter_operand = 0;
156 cpu->shifter_carry_out = BIT(rm, 31);
157 } else {
158 shifter_operand = 0;
159 cpu->shifter_carry_out = 0;
160 }
161 return shifter_operand;
162}
163
164static unsigned int DPO(ArithmeticShiftRightByImmediate)(ARMul_State* cpu, unsigned int sht_oper) {
165 unsigned int rm = CHECK_READ_REG15(cpu, RM);
166 unsigned int shifter_operand;
167 int shift_imm = BITS(sht_oper, 7, 11);
168 if (shift_imm == 0) {
169 if (BIT(rm, 31) == 0)
170 shifter_operand = 0;
171 else
172 shifter_operand = 0xFFFFFFFF;
173 cpu->shifter_carry_out = BIT(rm, 31);
174 } else {
175 shifter_operand = static_cast<int>(rm) >> shift_imm;
176 cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
177 }
178 return shifter_operand;
179}
180
181static unsigned int DPO(ArithmeticShiftRightByRegister)(ARMul_State* cpu, unsigned int sht_oper) {
182 unsigned int rs = CHECK_READ_REG15(cpu, RS);
183 unsigned int rm = CHECK_READ_REG15(cpu, RM);
184 unsigned int shifter_operand;
185 if (BITS(rs, 0, 7) == 0) {
186 shifter_operand = rm;
187 cpu->shifter_carry_out = cpu->CFlag;
188 } else if (BITS(rs, 0, 7) < 32) {
189 shifter_operand = static_cast<int>(rm) >> BITS(rs, 0, 7);
190 cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 7) - 1);
191 } else {
192 if (BIT(rm, 31) == 0)
193 shifter_operand = 0;
194 else
195 shifter_operand = 0xffffffff;
196 cpu->shifter_carry_out = BIT(rm, 31);
197 }
198 return shifter_operand;
199}
200
201static unsigned int DPO(RotateRightByImmediate)(ARMul_State* cpu, unsigned int sht_oper) {
202 unsigned int shifter_operand;
203 unsigned int rm = CHECK_READ_REG15(cpu, RM);
204 int shift_imm = BITS(sht_oper, 7, 11);
205 if (shift_imm == 0) {
206 shifter_operand = (cpu->CFlag << 31) | (rm >> 1);
207 cpu->shifter_carry_out = BIT(rm, 0);
208 } else {
209 shifter_operand = ROTATE_RIGHT_32(rm, shift_imm);
210 cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
211 }
212 return shifter_operand;
213}
214
215static unsigned int DPO(RotateRightByRegister)(ARMul_State* cpu, unsigned int sht_oper) {
216 unsigned int rm = CHECK_READ_REG15(cpu, RM);
217 unsigned int rs = CHECK_READ_REG15(cpu, RS);
218 unsigned int shifter_operand;
219 if (BITS(rs, 0, 7) == 0) {
220 shifter_operand = rm;
221 cpu->shifter_carry_out = cpu->CFlag;
222 } else if (BITS(rs, 0, 4) == 0) {
223 shifter_operand = rm;
224 cpu->shifter_carry_out = BIT(rm, 31);
225 } else {
226 shifter_operand = ROTATE_RIGHT_32(rm, BITS(rs, 0, 4));
227 cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 4) - 1);
228 }
229 return shifter_operand;
230}
231
232#define DEBUG_MSG \
233 LOG_DEBUG(Core_ARM, "inst is %x", inst); \
234 CITRA_IGNORE_EXIT(0)
235
236#define LnSWoUB(s) glue(LnSWoUB, s)
237#define MLnS(s) glue(MLnS, s)
238#define LdnStM(s) glue(LdnStM, s)
239
240#define W_BIT BIT(inst, 21)
241#define U_BIT BIT(inst, 23)
242#define I_BIT BIT(inst, 25)
243#define P_BIT BIT(inst, 24)
244#define OFFSET_12 BITS(inst, 0, 11)
245
246static void LnSWoUB(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
247 unsigned int Rn = BITS(inst, 16, 19);
248 unsigned int addr;
249
250 if (U_BIT)
251 addr = CHECK_READ_REG15_WA(cpu, Rn) + OFFSET_12;
252 else
253 addr = CHECK_READ_REG15_WA(cpu, Rn) - OFFSET_12;
254
255 virt_addr = addr;
256}
257
258static void LnSWoUB(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
259 unsigned int Rn = BITS(inst, 16, 19);
260 unsigned int Rm = BITS(inst, 0, 3);
261 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
262 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
263 unsigned int addr;
264
265 if (U_BIT)
266 addr = rn + rm;
267 else
268 addr = rn - rm;
269
270 virt_addr = addr;
271}
272
273static void LnSWoUB(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst,
274 unsigned int& virt_addr) {
275 unsigned int Rn = BITS(inst, 16, 19);
276 unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn);
277
278 if (U_BIT)
279 cpu->Reg[Rn] += OFFSET_12;
280 else
281 cpu->Reg[Rn] -= OFFSET_12;
282
283 virt_addr = addr;
284}
285
286static void LnSWoUB(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst,
287 unsigned int& virt_addr) {
288 unsigned int Rn = BITS(inst, 16, 19);
289 unsigned int addr;
290
291 if (U_BIT)
292 addr = CHECK_READ_REG15_WA(cpu, Rn) + OFFSET_12;
293 else
294 addr = CHECK_READ_REG15_WA(cpu, Rn) - OFFSET_12;
295
296 virt_addr = addr;
297
298 if (CondPassed(cpu, BITS(inst, 28, 31)))
299 cpu->Reg[Rn] = addr;
300}
301
302static void MLnS(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
303 unsigned int addr;
304 unsigned int Rn = BITS(inst, 16, 19);
305 unsigned int Rm = BITS(inst, 0, 3);
306 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
307 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
308
309 if (U_BIT)
310 addr = rn + rm;
311 else
312 addr = rn - rm;
313
314 virt_addr = addr;
315
316 if (CondPassed(cpu, BITS(inst, 28, 31)))
317 cpu->Reg[Rn] = addr;
318}
319
320static void LnSWoUB(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst,
321 unsigned int& virt_addr) {
322 unsigned int Rn = BITS(inst, 16, 19);
323 unsigned int Rm = BITS(inst, 0, 3);
324 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
325 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
326 unsigned int addr;
327
328 if (U_BIT)
329 addr = rn + rm;
330 else
331 addr = rn - rm;
332
333 virt_addr = addr;
334
335 if (CondPassed(cpu, BITS(inst, 28, 31))) {
336 cpu->Reg[Rn] = addr;
337 }
338}
339
340static void LnSWoUB(ScaledRegisterPreIndexed)(ARMul_State* cpu, unsigned int inst,
341 unsigned int& virt_addr) {
342 unsigned int shift = BITS(inst, 5, 6);
343 unsigned int shift_imm = BITS(inst, 7, 11);
344 unsigned int Rn = BITS(inst, 16, 19);
345 unsigned int Rm = BITS(inst, 0, 3);
346 unsigned int index = 0;
347 unsigned int addr;
348 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
349 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
350
351 switch (shift) {
352 case 0:
353 index = rm << shift_imm;
354 break;
355 case 1:
356 if (shift_imm == 0) {
357 index = 0;
358 } else {
359 index = rm >> shift_imm;
360 }
361 break;
362 case 2:
363 if (shift_imm == 0) { // ASR #32
364 if (BIT(rm, 31) == 1)
365 index = 0xFFFFFFFF;
366 else
367 index = 0;
368 } else {
369 index = static_cast<int>(rm) >> shift_imm;
370 }
371 break;
372 case 3:
373 if (shift_imm == 0) {
374 index = (cpu->CFlag << 31) | (rm >> 1);
375 } else {
376 index = ROTATE_RIGHT_32(rm, shift_imm);
377 }
378 break;
379 }
380
381 if (U_BIT)
382 addr = rn + index;
383 else
384 addr = rn - index;
385
386 virt_addr = addr;
387
388 if (CondPassed(cpu, BITS(inst, 28, 31)))
389 cpu->Reg[Rn] = addr;
390}
391
392static void LnSWoUB(ScaledRegisterPostIndexed)(ARMul_State* cpu, unsigned int inst,
393 unsigned int& virt_addr) {
394 unsigned int shift = BITS(inst, 5, 6);
395 unsigned int shift_imm = BITS(inst, 7, 11);
396 unsigned int Rn = BITS(inst, 16, 19);
397 unsigned int Rm = BITS(inst, 0, 3);
398 unsigned int index = 0;
399 unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn);
400 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
401
402 switch (shift) {
403 case 0:
404 index = rm << shift_imm;
405 break;
406 case 1:
407 if (shift_imm == 0) {
408 index = 0;
409 } else {
410 index = rm >> shift_imm;
411 }
412 break;
413 case 2:
414 if (shift_imm == 0) { // ASR #32
415 if (BIT(rm, 31) == 1)
416 index = 0xFFFFFFFF;
417 else
418 index = 0;
419 } else {
420 index = static_cast<int>(rm) >> shift_imm;
421 }
422 break;
423 case 3:
424 if (shift_imm == 0) {
425 index = (cpu->CFlag << 31) | (rm >> 1);
426 } else {
427 index = ROTATE_RIGHT_32(rm, shift_imm);
428 }
429 break;
430 }
431
432 virt_addr = addr;
433
434 if (CondPassed(cpu, BITS(inst, 28, 31))) {
435 if (U_BIT)
436 cpu->Reg[Rn] += index;
437 else
438 cpu->Reg[Rn] -= index;
439 }
440}
441
442static void LnSWoUB(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst,
443 unsigned int& virt_addr) {
444 unsigned int Rn = BITS(inst, 16, 19);
445 unsigned int Rm = BITS(inst, 0, 3);
446 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
447
448 virt_addr = CHECK_READ_REG15_WA(cpu, Rn);
449
450 if (CondPassed(cpu, BITS(inst, 28, 31))) {
451 if (U_BIT) {
452 cpu->Reg[Rn] += rm;
453 } else {
454 cpu->Reg[Rn] -= rm;
455 }
456 }
457}
458
459static void MLnS(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
460 unsigned int immedL = BITS(inst, 0, 3);
461 unsigned int immedH = BITS(inst, 8, 11);
462 unsigned int Rn = BITS(inst, 16, 19);
463 unsigned int addr;
464
465 unsigned int offset_8 = (immedH << 4) | immedL;
466
467 if (U_BIT)
468 addr = CHECK_READ_REG15_WA(cpu, Rn) + offset_8;
469 else
470 addr = CHECK_READ_REG15_WA(cpu, Rn) - offset_8;
471
472 virt_addr = addr;
473}
474
475static void MLnS(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
476 unsigned int addr;
477 unsigned int Rn = BITS(inst, 16, 19);
478 unsigned int Rm = BITS(inst, 0, 3);
479 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
480 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
481
482 if (U_BIT)
483 addr = rn + rm;
484 else
485 addr = rn - rm;
486
487 virt_addr = addr;
488}
489
490static void MLnS(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst,
491 unsigned int& virt_addr) {
492 unsigned int Rn = BITS(inst, 16, 19);
493 unsigned int immedH = BITS(inst, 8, 11);
494 unsigned int immedL = BITS(inst, 0, 3);
495 unsigned int addr;
496 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
497 unsigned int offset_8 = (immedH << 4) | immedL;
498
499 if (U_BIT)
500 addr = rn + offset_8;
501 else
502 addr = rn - offset_8;
503
504 virt_addr = addr;
505
506 if (CondPassed(cpu, BITS(inst, 28, 31)))
507 cpu->Reg[Rn] = addr;
508}
509
510static void MLnS(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst,
511 unsigned int& virt_addr) {
512 unsigned int Rn = BITS(inst, 16, 19);
513 unsigned int immedH = BITS(inst, 8, 11);
514 unsigned int immedL = BITS(inst, 0, 3);
515 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
516
517 virt_addr = rn;
518
519 if (CondPassed(cpu, BITS(inst, 28, 31))) {
520 unsigned int offset_8 = (immedH << 4) | immedL;
521 if (U_BIT)
522 rn += offset_8;
523 else
524 rn -= offset_8;
525
526 cpu->Reg[Rn] = rn;
527 }
528}
529
530static void MLnS(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst,
531 unsigned int& virt_addr) {
532 unsigned int Rn = BITS(inst, 16, 19);
533 unsigned int Rm = BITS(inst, 0, 3);
534 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
535
536 virt_addr = CHECK_READ_REG15_WA(cpu, Rn);
537
538 if (CondPassed(cpu, BITS(inst, 28, 31))) {
539 if (U_BIT)
540 cpu->Reg[Rn] += rm;
541 else
542 cpu->Reg[Rn] -= rm;
543 }
544}
545
546static void LdnStM(DecrementBefore)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
547 unsigned int Rn = BITS(inst, 16, 19);
548 unsigned int i = BITS(inst, 0, 15);
549 int count = 0;
550
551 while (i) {
552 if (i & 1)
553 count++;
554 i = i >> 1;
555 }
556
557 virt_addr = CHECK_READ_REG15_WA(cpu, Rn) - count * 4;
558
559 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21))
560 cpu->Reg[Rn] -= count * 4;
561}
562
563static void LdnStM(IncrementBefore)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
564 unsigned int Rn = BITS(inst, 16, 19);
565 unsigned int i = BITS(inst, 0, 15);
566 int count = 0;
567
568 while (i) {
569 if (i & 1)
570 count++;
571 i = i >> 1;
572 }
573
574 virt_addr = CHECK_READ_REG15_WA(cpu, Rn) + 4;
575
576 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21))
577 cpu->Reg[Rn] += count * 4;
578}
579
580static void LdnStM(IncrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
581 unsigned int Rn = BITS(inst, 16, 19);
582 unsigned int i = BITS(inst, 0, 15);
583 int count = 0;
584
585 while (i) {
586 if (i & 1)
587 count++;
588 i = i >> 1;
589 }
590
591 virt_addr = CHECK_READ_REG15_WA(cpu, Rn);
592
593 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21))
594 cpu->Reg[Rn] += count * 4;
595}
596
597static void LdnStM(DecrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
598 unsigned int Rn = BITS(inst, 16, 19);
599 unsigned int i = BITS(inst, 0, 15);
600 int count = 0;
601 while (i) {
602 if (i & 1)
603 count++;
604 i = i >> 1;
605 }
606 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
607 unsigned int start_addr = rn - count * 4 + 4;
608
609 virt_addr = start_addr;
610
611 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
612 cpu->Reg[Rn] -= count * 4;
613 }
614}
615
616static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst,
617 unsigned int& virt_addr) {
618 unsigned int shift = BITS(inst, 5, 6);
619 unsigned int shift_imm = BITS(inst, 7, 11);
620 unsigned int Rn = BITS(inst, 16, 19);
621 unsigned int Rm = BITS(inst, 0, 3);
622 unsigned int index = 0;
623 unsigned int addr;
624 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
625 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
626
627 switch (shift) {
628 case 0:
629 index = rm << shift_imm;
630 break;
631 case 1:
632 if (shift_imm == 0) {
633 index = 0;
634 } else {
635 index = rm >> shift_imm;
636 }
637 break;
638 case 2:
639 if (shift_imm == 0) { // ASR #32
640 if (BIT(rm, 31) == 1)
641 index = 0xFFFFFFFF;
642 else
643 index = 0;
644 } else {
645 index = static_cast<int>(rm) >> shift_imm;
646 }
647 break;
648 case 3:
649 if (shift_imm == 0) {
650 index = (cpu->CFlag << 31) | (rm >> 1);
651 } else {
652 index = ROTATE_RIGHT_32(rm, shift_imm);
653 }
654 break;
655 }
656
657 if (U_BIT) {
658 addr = rn + index;
659 } else
660 addr = rn - index;
661
662 virt_addr = addr;
663}
664
665shtop_fp_t GetShifterOp(unsigned int inst) {
666 if (BIT(inst, 25)) {
667 return DPO(Immediate);
668 } else if (BITS(inst, 4, 11) == 0) {
669 return DPO(Register);
670 } else if (BITS(inst, 4, 6) == 0) {
671 return DPO(LogicalShiftLeftByImmediate);
672 } else if (BITS(inst, 4, 7) == 1) {
673 return DPO(LogicalShiftLeftByRegister);
674 } else if (BITS(inst, 4, 6) == 2) {
675 return DPO(LogicalShiftRightByImmediate);
676 } else if (BITS(inst, 4, 7) == 3) {
677 return DPO(LogicalShiftRightByRegister);
678 } else if (BITS(inst, 4, 6) == 4) {
679 return DPO(ArithmeticShiftRightByImmediate);
680 } else if (BITS(inst, 4, 7) == 5) {
681 return DPO(ArithmeticShiftRightByRegister);
682 } else if (BITS(inst, 4, 6) == 6) {
683 return DPO(RotateRightByImmediate);
684 } else if (BITS(inst, 4, 7) == 7) {
685 return DPO(RotateRightByRegister);
686 }
687 return nullptr;
688}
689
690get_addr_fp_t GetAddressingOp(unsigned int inst) {
691 if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 0) {
692 return LnSWoUB(ImmediateOffset);
693 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) {
694 return LnSWoUB(RegisterOffset);
695 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) {
696 return LnSWoUB(ScaledRegisterOffset);
697 } else if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 1) {
698 return LnSWoUB(ImmediatePreIndexed);
699 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 1 && BITS(inst, 4, 11) == 0) {
700 return LnSWoUB(RegisterPreIndexed);
701 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 1 && BIT(inst, 4) == 0) {
702 return LnSWoUB(ScaledRegisterPreIndexed);
703 } else if (BITS(inst, 24, 27) == 4 && BIT(inst, 21) == 0) {
704 return LnSWoUB(ImmediatePostIndexed);
705 } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) {
706 return LnSWoUB(RegisterPostIndexed);
707 } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) {
708 return LnSWoUB(ScaledRegisterPostIndexed);
709 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 &&
710 BIT(inst, 4) == 1) {
711 return MLnS(ImmediateOffset);
712 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 &&
713 BIT(inst, 4) == 1) {
714 return MLnS(RegisterOffset);
715 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 3 && BIT(inst, 7) == 1 &&
716 BIT(inst, 4) == 1) {
717 return MLnS(ImmediatePreIndexed);
718 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 1 && BIT(inst, 7) == 1 &&
719 BIT(inst, 4) == 1) {
720 return MLnS(RegisterPreIndexed);
721 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 &&
722 BIT(inst, 4) == 1) {
723 return MLnS(ImmediatePostIndexed);
724 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 &&
725 BIT(inst, 4) == 1) {
726 return MLnS(RegisterPostIndexed);
727 } else if (BITS(inst, 23, 27) == 0x11) {
728 return LdnStM(IncrementAfter);
729 } else if (BITS(inst, 23, 27) == 0x13) {
730 return LdnStM(IncrementBefore);
731 } else if (BITS(inst, 23, 27) == 0x10) {
732 return LdnStM(DecrementAfter);
733 } else if (BITS(inst, 23, 27) == 0x12) {
734 return LdnStM(DecrementBefore);
735 }
736 return nullptr;
737}
738
739// Specialized for LDRT, LDRBT, STRT, and STRBT, which have specific addressing mode requirements
740get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst) {
741 if (BITS(inst, 25, 27) == 2) {
742 return LnSWoUB(ImmediatePostIndexed);
743 } else if (BITS(inst, 25, 27) == 3) {
744 return LnSWoUB(ScaledRegisterPostIndexed);
745 }
746 // Reaching this would indicate the thumb version
747 // of this instruction, however the 3DS CPU doesn't
748 // support this variant (the 3DS CPU is only ARMv6K,
749 // while this variant is added in ARMv6T2).
750 // So it's sufficient for citra to not implement this.
751 return nullptr;
752}
753
754enum { FETCH_SUCCESS, FETCH_FAILURE };
755
756static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_inst, u32* inst_size,
757 ARM_INST_PTR* ptr_inst_base) {
758 // Check if in Thumb mode
759 ThumbDecodeStatus ret = TranslateThumbInstruction(addr, inst, arm_inst, inst_size);
760 if (ret == ThumbDecodeStatus::BRANCH) {
761 int inst_index;
762 int table_length = static_cast<int>(arm_instruction_trans_len);
763 u32 tinstr = GetThumbInstruction(inst, addr);
764
765 switch ((tinstr & 0xF800) >> 11) {
766 case 26:
767 case 27:
768 if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)) {
769 inst_index = table_length - 4;
770 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
771 } else {
772 LOG_ERROR(Core_ARM, "thumb decoder error");
773 }
774 break;
775 case 28:
776 // Branch 2, unconditional branch
777 inst_index = table_length - 5;
778 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
779 break;
780
781 case 8:
782 case 29:
783 // For BLX 1 thumb instruction
784 inst_index = table_length - 1;
785 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
786 break;
787 case 30:
788 // For BL 1 thumb instruction
789 inst_index = table_length - 3;
790 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
791 break;
792 case 31:
793 // For BL 2 thumb instruction
794 inst_index = table_length - 2;
795 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
796 break;
797 default:
798 ret = ThumbDecodeStatus::UNDEFINED;
799 break;
800 }
801 }
802 return ret;
803}
804
805enum { KEEP_GOING, FETCH_EXCEPTION };
806
807MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64));
808
809static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr,
810 ARM_INST_PTR& inst_base) {
811 u32 inst_size = 4;
812 u32 inst = Memory::Read32(phys_addr & 0xFFFFFFFC);
813
814 // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM
815 // instruction
816 if (cpu->TFlag) {
817 u32 arm_inst;
818 ThumbDecodeStatus state =
819 DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base);
820
821 // We have translated the Thumb branch instruction in the Thumb decoder
822 if (state == ThumbDecodeStatus::BRANCH) {
823 return inst_size;
824 }
825 inst = arm_inst;
826 }
827
828 int idx;
829 if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) {
830 LOG_ERROR(Core_ARM, "Decode failure.\tPC: [0x%08" PRIX32 "]\tInstruction: %08" PRIX32,
831 phys_addr, inst);
832 LOG_ERROR(Core_ARM, "cpsr=0x%" PRIX32 ", cpu->TFlag=%d, r15=0x%08" PRIX32, cpu->Cpsr,
833 cpu->TFlag, cpu->Reg[15]);
834 CITRA_IGNORE_EXIT(-1);
835 }
836 inst_base = arm_instruction_trans[idx](inst, idx);
837
838 return inst_size;
839}
840
841static int InterpreterTranslateBlock(ARMul_State* cpu, std::size_t& bb_start, u32 addr) {
842 MICROPROFILE_SCOPE(DynCom_Decode);
843
844 // Decode instruction, get index
845 // Allocate memory and init InsCream
846 // Go on next, until terminal instruction
847 // Save start addr of basicblock in CreamCache
848 ARM_INST_PTR inst_base = nullptr;
849 TransExtData ret = TransExtData::NON_BRANCH;
850 int size = 0; // instruction size of basic block
851 bb_start = trans_cache_buf_top;
852
853 u32 phys_addr = addr;
854 u32 pc_start = cpu->Reg[15];
855
856 while (ret == TransExtData::NON_BRANCH) {
857 unsigned int inst_size = InterpreterTranslateInstruction(cpu, phys_addr, inst_base);
858
859 size++;
860
861 phys_addr += inst_size;
862
863 if ((phys_addr & 0xfff) == 0) {
864 inst_base->br = TransExtData::END_OF_PAGE;
865 }
866 ret = inst_base->br;
867 };
868
869 cpu->instruction_cache[pc_start] = bb_start;
870
871 return KEEP_GOING;
872}
873
874static int InterpreterTranslateSingle(ARMul_State* cpu, std::size_t& bb_start, u32 addr) {
875 MICROPROFILE_SCOPE(DynCom_Decode);
876
877 ARM_INST_PTR inst_base = nullptr;
878 bb_start = trans_cache_buf_top;
879
880 u32 phys_addr = addr;
881 u32 pc_start = cpu->Reg[15];
882
883 InterpreterTranslateInstruction(cpu, phys_addr, inst_base);
884
885 if (inst_base->br == TransExtData::NON_BRANCH) {
886 inst_base->br = TransExtData::SINGLE_STEP;
887 }
888
889 cpu->instruction_cache[pc_start] = bb_start;
890
891 return KEEP_GOING;
892}
893
894static int clz(unsigned int x) {
895 int n;
896 if (x == 0)
897 return (32);
898 n = 1;
899 if ((x >> 16) == 0) {
900 n = n + 16;
901 x = x << 16;
902 }
903 if ((x >> 24) == 0) {
904 n = n + 8;
905 x = x << 8;
906 }
907 if ((x >> 28) == 0) {
908 n = n + 4;
909 x = x << 4;
910 }
911 if ((x >> 30) == 0) {
912 n = n + 2;
913 x = x << 2;
914 }
915 n = n - (x >> 31);
916 return n;
917}
918
919MICROPROFILE_DEFINE(DynCom_Execute, "DynCom", "Execute", MP_RGB(255, 0, 0));
920
921unsigned InterpreterMainLoop(ARMul_State* cpu) {
922 MICROPROFILE_SCOPE(DynCom_Execute);
923
924 GDBStub::BreakpointAddress breakpoint_data;
925
926#undef RM
927#undef RS
928
929#define CRn inst_cream->crn
930#define OPCODE_1 inst_cream->opcode_1
931#define OPCODE_2 inst_cream->opcode_2
932#define CRm inst_cream->crm
933#define RD cpu->Reg[inst_cream->Rd]
934#define RD2 cpu->Reg[inst_cream->Rd + 1]
935#define RN cpu->Reg[inst_cream->Rn]
936#define RM cpu->Reg[inst_cream->Rm]
937#define RS cpu->Reg[inst_cream->Rs]
938#define RDHI cpu->Reg[inst_cream->RdHi]
939#define RDLO cpu->Reg[inst_cream->RdLo]
940#define LINK_RTN_ADDR (cpu->Reg[14] = cpu->Reg[15] + 4)
941#define SET_PC (cpu->Reg[15] = cpu->Reg[15] + 8 + inst_cream->signed_immed_24)
942#define SHIFTER_OPERAND inst_cream->shtop_func(cpu, inst_cream->shifter_operand)
943
944#define FETCH_INST \
945 if (inst_base->br != TransExtData::NON_BRANCH) \
946 goto DISPATCH; \
947 inst_base = (arm_inst*)&trans_cache_buf[ptr]
948
949#define INC_PC(l) ptr += sizeof(arm_inst) + l
950#define INC_PC_STUB ptr += sizeof(arm_inst)
951
952#define GDB_BP_CHECK \
953 cpu->Cpsr &= ~(1 << 5); \
954 cpu->Cpsr |= cpu->TFlag << 5; \
955 if (GDBStub::IsServerEnabled()) { \
956 if (GDBStub::IsMemoryBreak() || (breakpoint_data.type != GDBStub::BreakpointType::None && \
957 PC == breakpoint_data.address)) { \
958 GDBStub::Break(); \
959 goto END; \
960 } \
961 }
962
963// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a
964// clunky switch statement.
965#if defined __GNUC__ || defined __clang__
966#define GOTO_NEXT_INST \
967 GDB_BP_CHECK; \
968 if (num_instrs >= cpu->NumInstrsToExecute) \
969 goto END; \
970 num_instrs++; \
971 goto* InstLabel[inst_base->idx]
972#else
973#define GOTO_NEXT_INST \
974 GDB_BP_CHECK; \
975 if (num_instrs >= cpu->NumInstrsToExecute) \
976 goto END; \
977 num_instrs++; \
978 switch (inst_base->idx) { \
979 case 0: \
980 goto VMLA_INST; \
981 case 1: \
982 goto VMLS_INST; \
983 case 2: \
984 goto VNMLA_INST; \
985 case 3: \
986 goto VNMLS_INST; \
987 case 4: \
988 goto VNMUL_INST; \
989 case 5: \
990 goto VMUL_INST; \
991 case 6: \
992 goto VADD_INST; \
993 case 7: \
994 goto VSUB_INST; \
995 case 8: \
996 goto VDIV_INST; \
997 case 9: \
998 goto VMOVI_INST; \
999 case 10: \
1000 goto VMOVR_INST; \
1001 case 11: \
1002 goto VABS_INST; \
1003 case 12: \
1004 goto VNEG_INST; \
1005 case 13: \
1006 goto VSQRT_INST; \
1007 case 14: \
1008 goto VCMP_INST; \
1009 case 15: \
1010 goto VCMP2_INST; \
1011 case 16: \
1012 goto VCVTBDS_INST; \
1013 case 17: \
1014 goto VCVTBFF_INST; \
1015 case 18: \
1016 goto VCVTBFI_INST; \
1017 case 19: \
1018 goto VMOVBRS_INST; \
1019 case 20: \
1020 goto VMSR_INST; \
1021 case 21: \
1022 goto VMOVBRC_INST; \
1023 case 22: \
1024 goto VMRS_INST; \
1025 case 23: \
1026 goto VMOVBCR_INST; \
1027 case 24: \
1028 goto VMOVBRRSS_INST; \
1029 case 25: \
1030 goto VMOVBRRD_INST; \
1031 case 26: \
1032 goto VSTR_INST; \
1033 case 27: \
1034 goto VPUSH_INST; \
1035 case 28: \
1036 goto VSTM_INST; \
1037 case 29: \
1038 goto VPOP_INST; \
1039 case 30: \
1040 goto VLDR_INST; \
1041 case 31: \
1042 goto VLDM_INST; \
1043 case 32: \
1044 goto SRS_INST; \
1045 case 33: \
1046 goto RFE_INST; \
1047 case 34: \
1048 goto BKPT_INST; \
1049 case 35: \
1050 goto BLX_INST; \
1051 case 36: \
1052 goto CPS_INST; \
1053 case 37: \
1054 goto PLD_INST; \
1055 case 38: \
1056 goto SETEND_INST; \
1057 case 39: \
1058 goto CLREX_INST; \
1059 case 40: \
1060 goto REV16_INST; \
1061 case 41: \
1062 goto USAD8_INST; \
1063 case 42: \
1064 goto SXTB_INST; \
1065 case 43: \
1066 goto UXTB_INST; \
1067 case 44: \
1068 goto SXTH_INST; \
1069 case 45: \
1070 goto SXTB16_INST; \
1071 case 46: \
1072 goto UXTH_INST; \
1073 case 47: \
1074 goto UXTB16_INST; \
1075 case 48: \
1076 goto CPY_INST; \
1077 case 49: \
1078 goto UXTAB_INST; \
1079 case 50: \
1080 goto SSUB8_INST; \
1081 case 51: \
1082 goto SHSUB8_INST; \
1083 case 52: \
1084 goto SSUBADDX_INST; \
1085 case 53: \
1086 goto STREX_INST; \
1087 case 54: \
1088 goto STREXB_INST; \
1089 case 55: \
1090 goto SWP_INST; \
1091 case 56: \
1092 goto SWPB_INST; \
1093 case 57: \
1094 goto SSUB16_INST; \
1095 case 58: \
1096 goto SSAT16_INST; \
1097 case 59: \
1098 goto SHSUBADDX_INST; \
1099 case 60: \
1100 goto QSUBADDX_INST; \
1101 case 61: \
1102 goto SHADDSUBX_INST; \
1103 case 62: \
1104 goto SHADD8_INST; \
1105 case 63: \
1106 goto SHADD16_INST; \
1107 case 64: \
1108 goto SEL_INST; \
1109 case 65: \
1110 goto SADDSUBX_INST; \
1111 case 66: \
1112 goto SADD8_INST; \
1113 case 67: \
1114 goto SADD16_INST; \
1115 case 68: \
1116 goto SHSUB16_INST; \
1117 case 69: \
1118 goto UMAAL_INST; \
1119 case 70: \
1120 goto UXTAB16_INST; \
1121 case 71: \
1122 goto USUBADDX_INST; \
1123 case 72: \
1124 goto USUB8_INST; \
1125 case 73: \
1126 goto USUB16_INST; \
1127 case 74: \
1128 goto USAT16_INST; \
1129 case 75: \
1130 goto USADA8_INST; \
1131 case 76: \
1132 goto UQSUBADDX_INST; \
1133 case 77: \
1134 goto UQSUB8_INST; \
1135 case 78: \
1136 goto UQSUB16_INST; \
1137 case 79: \
1138 goto UQADDSUBX_INST; \
1139 case 80: \
1140 goto UQADD8_INST; \
1141 case 81: \
1142 goto UQADD16_INST; \
1143 case 82: \
1144 goto SXTAB_INST; \
1145 case 83: \
1146 goto UHSUBADDX_INST; \
1147 case 84: \
1148 goto UHSUB8_INST; \
1149 case 85: \
1150 goto UHSUB16_INST; \
1151 case 86: \
1152 goto UHADDSUBX_INST; \
1153 case 87: \
1154 goto UHADD8_INST; \
1155 case 88: \
1156 goto UHADD16_INST; \
1157 case 89: \
1158 goto UADDSUBX_INST; \
1159 case 90: \
1160 goto UADD8_INST; \
1161 case 91: \
1162 goto UADD16_INST; \
1163 case 92: \
1164 goto SXTAH_INST; \
1165 case 93: \
1166 goto SXTAB16_INST; \
1167 case 94: \
1168 goto QADD8_INST; \
1169 case 95: \
1170 goto BXJ_INST; \
1171 case 96: \
1172 goto CLZ_INST; \
1173 case 97: \
1174 goto UXTAH_INST; \
1175 case 98: \
1176 goto BX_INST; \
1177 case 99: \
1178 goto REV_INST; \
1179 case 100: \
1180 goto BLX_INST; \
1181 case 101: \
1182 goto REVSH_INST; \
1183 case 102: \
1184 goto QADD_INST; \
1185 case 103: \
1186 goto QADD16_INST; \
1187 case 104: \
1188 goto QADDSUBX_INST; \
1189 case 105: \
1190 goto LDREX_INST; \
1191 case 106: \
1192 goto QDADD_INST; \
1193 case 107: \
1194 goto QDSUB_INST; \
1195 case 108: \
1196 goto QSUB_INST; \
1197 case 109: \
1198 goto LDREXB_INST; \
1199 case 110: \
1200 goto QSUB8_INST; \
1201 case 111: \
1202 goto QSUB16_INST; \
1203 case 112: \
1204 goto SMUAD_INST; \
1205 case 113: \
1206 goto SMMUL_INST; \
1207 case 114: \
1208 goto SMUSD_INST; \
1209 case 115: \
1210 goto SMLSD_INST; \
1211 case 116: \
1212 goto SMLSLD_INST; \
1213 case 117: \
1214 goto SMMLA_INST; \
1215 case 118: \
1216 goto SMMLS_INST; \
1217 case 119: \
1218 goto SMLALD_INST; \
1219 case 120: \
1220 goto SMLAD_INST; \
1221 case 121: \
1222 goto SMLAW_INST; \
1223 case 122: \
1224 goto SMULW_INST; \
1225 case 123: \
1226 goto PKHTB_INST; \
1227 case 124: \
1228 goto PKHBT_INST; \
1229 case 125: \
1230 goto SMUL_INST; \
1231 case 126: \
1232 goto SMLALXY_INST; \
1233 case 127: \
1234 goto SMLA_INST; \
1235 case 128: \
1236 goto MCRR_INST; \
1237 case 129: \
1238 goto MRRC_INST; \
1239 case 130: \
1240 goto CMP_INST; \
1241 case 131: \
1242 goto TST_INST; \
1243 case 132: \
1244 goto TEQ_INST; \
1245 case 133: \
1246 goto CMN_INST; \
1247 case 134: \
1248 goto SMULL_INST; \
1249 case 135: \
1250 goto UMULL_INST; \
1251 case 136: \
1252 goto UMLAL_INST; \
1253 case 137: \
1254 goto SMLAL_INST; \
1255 case 138: \
1256 goto MUL_INST; \
1257 case 139: \
1258 goto MLA_INST; \
1259 case 140: \
1260 goto SSAT_INST; \
1261 case 141: \
1262 goto USAT_INST; \
1263 case 142: \
1264 goto MRS_INST; \
1265 case 143: \
1266 goto MSR_INST; \
1267 case 144: \
1268 goto AND_INST; \
1269 case 145: \
1270 goto BIC_INST; \
1271 case 146: \
1272 goto LDM_INST; \
1273 case 147: \
1274 goto EOR_INST; \
1275 case 148: \
1276 goto ADD_INST; \
1277 case 149: \
1278 goto RSB_INST; \
1279 case 150: \
1280 goto RSC_INST; \
1281 case 151: \
1282 goto SBC_INST; \
1283 case 152: \
1284 goto ADC_INST; \
1285 case 153: \
1286 goto SUB_INST; \
1287 case 154: \
1288 goto ORR_INST; \
1289 case 155: \
1290 goto MVN_INST; \
1291 case 156: \
1292 goto MOV_INST; \
1293 case 157: \
1294 goto STM_INST; \
1295 case 158: \
1296 goto LDM_INST; \
1297 case 159: \
1298 goto LDRSH_INST; \
1299 case 160: \
1300 goto STM_INST; \
1301 case 161: \
1302 goto LDM_INST; \
1303 case 162: \
1304 goto LDRSB_INST; \
1305 case 163: \
1306 goto STRD_INST; \
1307 case 164: \
1308 goto LDRH_INST; \
1309 case 165: \
1310 goto STRH_INST; \
1311 case 166: \
1312 goto LDRD_INST; \
1313 case 167: \
1314 goto STRT_INST; \
1315 case 168: \
1316 goto STRBT_INST; \
1317 case 169: \
1318 goto LDRBT_INST; \
1319 case 170: \
1320 goto LDRT_INST; \
1321 case 171: \
1322 goto MRC_INST; \
1323 case 172: \
1324 goto MCR_INST; \
1325 case 173: \
1326 goto MSR_INST; \
1327 case 174: \
1328 goto MSR_INST; \
1329 case 175: \
1330 goto MSR_INST; \
1331 case 176: \
1332 goto MSR_INST; \
1333 case 177: \
1334 goto MSR_INST; \
1335 case 178: \
1336 goto LDRB_INST; \
1337 case 179: \
1338 goto STRB_INST; \
1339 case 180: \
1340 goto LDR_INST; \
1341 case 181: \
1342 goto LDRCOND_INST; \
1343 case 182: \
1344 goto STR_INST; \
1345 case 183: \
1346 goto CDP_INST; \
1347 case 184: \
1348 goto STC_INST; \
1349 case 185: \
1350 goto LDC_INST; \
1351 case 186: \
1352 goto LDREXD_INST; \
1353 case 187: \
1354 goto STREXD_INST; \
1355 case 188: \
1356 goto LDREXH_INST; \
1357 case 189: \
1358 goto STREXH_INST; \
1359 case 190: \
1360 goto NOP_INST; \
1361 case 191: \
1362 goto YIELD_INST; \
1363 case 192: \
1364 goto WFE_INST; \
1365 case 193: \
1366 goto WFI_INST; \
1367 case 194: \
1368 goto SEV_INST; \
1369 case 195: \
1370 goto SWI_INST; \
1371 case 196: \
1372 goto BBL_INST; \
1373 case 197: \
1374 goto B_2_THUMB; \
1375 case 198: \
1376 goto B_COND_THUMB; \
1377 case 199: \
1378 goto BL_1_THUMB; \
1379 case 200: \
1380 goto BL_2_THUMB; \
1381 case 201: \
1382 goto BLX_1_THUMB; \
1383 case 202: \
1384 goto DISPATCH; \
1385 case 203: \
1386 goto INIT_INST_LENGTH; \
1387 case 204: \
1388 goto END; \
1389 }
1390#endif
1391
1392#define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0)
1393#define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1)
1394#define UPDATE_CFLAG_WITH_SC (cpu->CFlag = cpu->shifter_carry_out)
1395
1396#define SAVE_NZCVT \
1397 cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) | (cpu->NFlag << 31) | (cpu->ZFlag << 30) | \
1398 (cpu->CFlag << 29) | (cpu->VFlag << 28) | (cpu->TFlag << 5)
1399#define LOAD_NZCVT \
1400 cpu->NFlag = (cpu->Cpsr >> 31); \
1401 cpu->ZFlag = (cpu->Cpsr >> 30) & 1; \
1402 cpu->CFlag = (cpu->Cpsr >> 29) & 1; \
1403 cpu->VFlag = (cpu->Cpsr >> 28) & 1; \
1404 cpu->TFlag = (cpu->Cpsr >> 5) & 1;
1405
1406#define CurrentModeHasSPSR (cpu->Mode != SYSTEM32MODE) && (cpu->Mode != USER32MODE)
1407#define PC (cpu->Reg[15])
1408
1409// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback
1410// to a clunky switch statement.
1411#if defined __GNUC__ || defined __clang__
1412 void* InstLabel[] = {&&VMLA_INST,
1413 &&VMLS_INST,
1414 &&VNMLA_INST,
1415 &&VNMLS_INST,
1416 &&VNMUL_INST,
1417 &&VMUL_INST,
1418 &&VADD_INST,
1419 &&VSUB_INST,
1420 &&VDIV_INST,
1421 &&VMOVI_INST,
1422 &&VMOVR_INST,
1423 &&VABS_INST,
1424 &&VNEG_INST,
1425 &&VSQRT_INST,
1426 &&VCMP_INST,
1427 &&VCMP2_INST,
1428 &&VCVTBDS_INST,
1429 &&VCVTBFF_INST,
1430 &&VCVTBFI_INST,
1431 &&VMOVBRS_INST,
1432 &&VMSR_INST,
1433 &&VMOVBRC_INST,
1434 &&VMRS_INST,
1435 &&VMOVBCR_INST,
1436 &&VMOVBRRSS_INST,
1437 &&VMOVBRRD_INST,
1438 &&VSTR_INST,
1439 &&VPUSH_INST,
1440 &&VSTM_INST,
1441 &&VPOP_INST,
1442 &&VLDR_INST,
1443 &&VLDM_INST,
1444
1445 &&SRS_INST,
1446 &&RFE_INST,
1447 &&BKPT_INST,
1448 &&BLX_INST,
1449 &&CPS_INST,
1450 &&PLD_INST,
1451 &&SETEND_INST,
1452 &&CLREX_INST,
1453 &&REV16_INST,
1454 &&USAD8_INST,
1455 &&SXTB_INST,
1456 &&UXTB_INST,
1457 &&SXTH_INST,
1458 &&SXTB16_INST,
1459 &&UXTH_INST,
1460 &&UXTB16_INST,
1461 &&CPY_INST,
1462 &&UXTAB_INST,
1463 &&SSUB8_INST,
1464 &&SHSUB8_INST,
1465 &&SSUBADDX_INST,
1466 &&STREX_INST,
1467 &&STREXB_INST,
1468 &&SWP_INST,
1469 &&SWPB_INST,
1470 &&SSUB16_INST,
1471 &&SSAT16_INST,
1472 &&SHSUBADDX_INST,
1473 &&QSUBADDX_INST,
1474 &&SHADDSUBX_INST,
1475 &&SHADD8_INST,
1476 &&SHADD16_INST,
1477 &&SEL_INST,
1478 &&SADDSUBX_INST,
1479 &&SADD8_INST,
1480 &&SADD16_INST,
1481 &&SHSUB16_INST,
1482 &&UMAAL_INST,
1483 &&UXTAB16_INST,
1484 &&USUBADDX_INST,
1485 &&USUB8_INST,
1486 &&USUB16_INST,
1487 &&USAT16_INST,
1488 &&USADA8_INST,
1489 &&UQSUBADDX_INST,
1490 &&UQSUB8_INST,
1491 &&UQSUB16_INST,
1492 &&UQADDSUBX_INST,
1493 &&UQADD8_INST,
1494 &&UQADD16_INST,
1495 &&SXTAB_INST,
1496 &&UHSUBADDX_INST,
1497 &&UHSUB8_INST,
1498 &&UHSUB16_INST,
1499 &&UHADDSUBX_INST,
1500 &&UHADD8_INST,
1501 &&UHADD16_INST,
1502 &&UADDSUBX_INST,
1503 &&UADD8_INST,
1504 &&UADD16_INST,
1505 &&SXTAH_INST,
1506 &&SXTAB16_INST,
1507 &&QADD8_INST,
1508 &&BXJ_INST,
1509 &&CLZ_INST,
1510 &&UXTAH_INST,
1511 &&BX_INST,
1512 &&REV_INST,
1513 &&BLX_INST,
1514 &&REVSH_INST,
1515 &&QADD_INST,
1516 &&QADD16_INST,
1517 &&QADDSUBX_INST,
1518 &&LDREX_INST,
1519 &&QDADD_INST,
1520 &&QDSUB_INST,
1521 &&QSUB_INST,
1522 &&LDREXB_INST,
1523 &&QSUB8_INST,
1524 &&QSUB16_INST,
1525 &&SMUAD_INST,
1526 &&SMMUL_INST,
1527 &&SMUSD_INST,
1528 &&SMLSD_INST,
1529 &&SMLSLD_INST,
1530 &&SMMLA_INST,
1531 &&SMMLS_INST,
1532 &&SMLALD_INST,
1533 &&SMLAD_INST,
1534 &&SMLAW_INST,
1535 &&SMULW_INST,
1536 &&PKHTB_INST,
1537 &&PKHBT_INST,
1538 &&SMUL_INST,
1539 &&SMLALXY_INST,
1540 &&SMLA_INST,
1541 &&MCRR_INST,
1542 &&MRRC_INST,
1543 &&CMP_INST,
1544 &&TST_INST,
1545 &&TEQ_INST,
1546 &&CMN_INST,
1547 &&SMULL_INST,
1548 &&UMULL_INST,
1549 &&UMLAL_INST,
1550 &&SMLAL_INST,
1551 &&MUL_INST,
1552 &&MLA_INST,
1553 &&SSAT_INST,
1554 &&USAT_INST,
1555 &&MRS_INST,
1556 &&MSR_INST,
1557 &&AND_INST,
1558 &&BIC_INST,
1559 &&LDM_INST,
1560 &&EOR_INST,
1561 &&ADD_INST,
1562 &&RSB_INST,
1563 &&RSC_INST,
1564 &&SBC_INST,
1565 &&ADC_INST,
1566 &&SUB_INST,
1567 &&ORR_INST,
1568 &&MVN_INST,
1569 &&MOV_INST,
1570 &&STM_INST,
1571 &&LDM_INST,
1572 &&LDRSH_INST,
1573 &&STM_INST,
1574 &&LDM_INST,
1575 &&LDRSB_INST,
1576 &&STRD_INST,
1577 &&LDRH_INST,
1578 &&STRH_INST,
1579 &&LDRD_INST,
1580 &&STRT_INST,
1581 &&STRBT_INST,
1582 &&LDRBT_INST,
1583 &&LDRT_INST,
1584 &&MRC_INST,
1585 &&MCR_INST,
1586 &&MSR_INST,
1587 &&MSR_INST,
1588 &&MSR_INST,
1589 &&MSR_INST,
1590 &&MSR_INST,
1591 &&LDRB_INST,
1592 &&STRB_INST,
1593 &&LDR_INST,
1594 &&LDRCOND_INST,
1595 &&STR_INST,
1596 &&CDP_INST,
1597 &&STC_INST,
1598 &&LDC_INST,
1599 &&LDREXD_INST,
1600 &&STREXD_INST,
1601 &&LDREXH_INST,
1602 &&STREXH_INST,
1603 &&NOP_INST,
1604 &&YIELD_INST,
1605 &&WFE_INST,
1606 &&WFI_INST,
1607 &&SEV_INST,
1608 &&SWI_INST,
1609 &&BBL_INST,
1610 &&B_2_THUMB,
1611 &&B_COND_THUMB,
1612 &&BL_1_THUMB,
1613 &&BL_2_THUMB,
1614 &&BLX_1_THUMB,
1615 &&DISPATCH,
1616 &&INIT_INST_LENGTH,
1617 &&END};
1618#endif
1619 arm_inst* inst_base;
1620 unsigned int addr;
1621 unsigned int num_instrs = 0;
1622
1623 std::size_t ptr;
1624
1625 LOAD_NZCVT;
1626DISPATCH : {
1627 if (!cpu->NirqSig) {
1628 if (!(cpu->Cpsr & 0x80)) {
1629 goto END;
1630 }
1631 }
1632
1633 if (cpu->TFlag)
1634 cpu->Reg[15] &= 0xfffffffe;
1635 else
1636 cpu->Reg[15] &= 0xfffffffc;
1637
1638 // Find the cached instruction cream, otherwise translate it...
1639 auto itr = cpu->instruction_cache.find(cpu->Reg[15]);
1640 if (itr != cpu->instruction_cache.end()) {
1641 ptr = itr->second;
1642 } else if (cpu->NumInstrsToExecute != 1) {
1643 if (InterpreterTranslateBlock(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
1644 goto END;
1645 } else {
1646 if (InterpreterTranslateSingle(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
1647 goto END;
1648 }
1649
1650 // Find breakpoint if one exists within the block
1651 if (GDBStub::IsConnected()) {
1652 breakpoint_data =
1653 GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute);
1654 }
1655
1656 inst_base = (arm_inst*)&trans_cache_buf[ptr];
1657 GOTO_NEXT_INST;
1658}
1659ADC_INST : {
1660 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1661 adc_inst* const inst_cream = (adc_inst*)inst_base->component;
1662
1663 u32 rn_val = RN;
1664 if (inst_cream->Rn == 15)
1665 rn_val += 2 * cpu->GetInstructionSize();
1666
1667 bool carry;
1668 bool overflow;
1669 RD = AddWithCarry(rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
1670
1671 if (inst_cream->S && (inst_cream->Rd == 15)) {
1672 if (CurrentModeHasSPSR) {
1673 cpu->Cpsr = cpu->Spsr_copy;
1674 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
1675 LOAD_NZCVT;
1676 }
1677 } else if (inst_cream->S) {
1678 UPDATE_NFLAG(RD);
1679 UPDATE_ZFLAG(RD);
1680 cpu->CFlag = carry;
1681 cpu->VFlag = overflow;
1682 }
1683 if (inst_cream->Rd == 15) {
1684 INC_PC(sizeof(adc_inst));
1685 goto DISPATCH;
1686 }
1687 }
1688 cpu->Reg[15] += cpu->GetInstructionSize();
1689 INC_PC(sizeof(adc_inst));
1690 FETCH_INST;
1691 GOTO_NEXT_INST;
1692}
1693ADD_INST : {
1694 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1695 add_inst* const inst_cream = (add_inst*)inst_base->component;
1696
1697 u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn);
1698
1699 bool carry;
1700 bool overflow;
1701 RD = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
1702
1703 if (inst_cream->S && (inst_cream->Rd == 15)) {
1704 if (CurrentModeHasSPSR) {
1705 cpu->Cpsr = cpu->Spsr_copy;
1706 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
1707 LOAD_NZCVT;
1708 }
1709 } else if (inst_cream->S) {
1710 UPDATE_NFLAG(RD);
1711 UPDATE_ZFLAG(RD);
1712 cpu->CFlag = carry;
1713 cpu->VFlag = overflow;
1714 }
1715 if (inst_cream->Rd == 15) {
1716 INC_PC(sizeof(add_inst));
1717 goto DISPATCH;
1718 }
1719 }
1720 cpu->Reg[15] += cpu->GetInstructionSize();
1721 INC_PC(sizeof(add_inst));
1722 FETCH_INST;
1723 GOTO_NEXT_INST;
1724}
1725AND_INST : {
1726 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1727 and_inst* const inst_cream = (and_inst*)inst_base->component;
1728
1729 u32 lop = RN;
1730 u32 rop = SHIFTER_OPERAND;
1731
1732 if (inst_cream->Rn == 15)
1733 lop += 2 * cpu->GetInstructionSize();
1734
1735 RD = lop & rop;
1736
1737 if (inst_cream->S && (inst_cream->Rd == 15)) {
1738 if (CurrentModeHasSPSR) {
1739 cpu->Cpsr = cpu->Spsr_copy;
1740 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
1741 LOAD_NZCVT;
1742 }
1743 } else if (inst_cream->S) {
1744 UPDATE_NFLAG(RD);
1745 UPDATE_ZFLAG(RD);
1746 UPDATE_CFLAG_WITH_SC;
1747 }
1748 if (inst_cream->Rd == 15) {
1749 INC_PC(sizeof(and_inst));
1750 goto DISPATCH;
1751 }
1752 }
1753 cpu->Reg[15] += cpu->GetInstructionSize();
1754 INC_PC(sizeof(and_inst));
1755 FETCH_INST;
1756 GOTO_NEXT_INST;
1757}
1758BBL_INST : {
1759 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1760 bbl_inst* inst_cream = (bbl_inst*)inst_base->component;
1761 if (inst_cream->L) {
1762 LINK_RTN_ADDR;
1763 }
1764 SET_PC;
1765 INC_PC(sizeof(bbl_inst));
1766 goto DISPATCH;
1767 }
1768 cpu->Reg[15] += cpu->GetInstructionSize();
1769 INC_PC(sizeof(bbl_inst));
1770 goto DISPATCH;
1771}
1772BIC_INST : {
1773 bic_inst* inst_cream = (bic_inst*)inst_base->component;
1774 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1775 u32 lop = RN;
1776 if (inst_cream->Rn == 15) {
1777 lop += 2 * cpu->GetInstructionSize();
1778 }
1779 u32 rop = SHIFTER_OPERAND;
1780 RD = lop & (~rop);
1781 if ((inst_cream->S) && (inst_cream->Rd == 15)) {
1782 if (CurrentModeHasSPSR) {
1783 cpu->Cpsr = cpu->Spsr_copy;
1784 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
1785 LOAD_NZCVT;
1786 }
1787 } else if (inst_cream->S) {
1788 UPDATE_NFLAG(RD);
1789 UPDATE_ZFLAG(RD);
1790 UPDATE_CFLAG_WITH_SC;
1791 }
1792 if (inst_cream->Rd == 15) {
1793 INC_PC(sizeof(bic_inst));
1794 goto DISPATCH;
1795 }
1796 }
1797 cpu->Reg[15] += cpu->GetInstructionSize();
1798 INC_PC(sizeof(bic_inst));
1799 FETCH_INST;
1800 GOTO_NEXT_INST;
1801}
1802BKPT_INST : {
1803 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1804 bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component;
1805 LOG_DEBUG(Core_ARM, "Breakpoint instruction hit. Immediate: 0x%08X", inst_cream->imm);
1806 }
1807 cpu->Reg[15] += cpu->GetInstructionSize();
1808 INC_PC(sizeof(bkpt_inst));
1809 FETCH_INST;
1810 GOTO_NEXT_INST;
1811}
1812BLX_INST : {
1813 blx_inst* inst_cream = (blx_inst*)inst_base->component;
1814 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1815 unsigned int inst = inst_cream->inst;
1816 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
1817 const u32 jump_address = cpu->Reg[inst_cream->val.Rm];
1818 cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
1819 if (cpu->TFlag)
1820 cpu->Reg[14] |= 0x1;
1821 cpu->Reg[15] = jump_address & 0xfffffffe;
1822 cpu->TFlag = jump_address & 0x1;
1823 } else {
1824 cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
1825 cpu->TFlag = 0x1;
1826 int signed_int = inst_cream->val.signed_immed_24;
1827 signed_int = (signed_int & 0x800000) ? (0x3F000000 | signed_int) : signed_int;
1828 signed_int = signed_int << 2;
1829 cpu->Reg[15] = cpu->Reg[15] + 8 + signed_int + (BIT(inst, 24) << 1);
1830 }
1831 INC_PC(sizeof(blx_inst));
1832 goto DISPATCH;
1833 }
1834 cpu->Reg[15] += cpu->GetInstructionSize();
1835 INC_PC(sizeof(blx_inst));
1836 goto DISPATCH;
1837}
1838
1839BX_INST:
1840BXJ_INST : {
1841 // Note that only the 'fail' case of BXJ is emulated. This is because
1842 // the facilities for Jazelle emulation are not implemented.
1843 //
1844 // According to the ARM documentation on BXJ, if setting the J bit in the APSR
1845 // fails, then BXJ functions identically like a regular BX instruction.
1846 //
1847 // This is sufficient for citra, as the CPU for the 3DS does not implement Jazelle.
1848
1849 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1850 bx_inst* const inst_cream = (bx_inst*)inst_base->component;
1851
1852 u32 address = RM;
1853
1854 if (inst_cream->Rm == 15)
1855 address += 2 * cpu->GetInstructionSize();
1856
1857 cpu->TFlag = address & 1;
1858 cpu->Reg[15] = address & 0xfffffffe;
1859 INC_PC(sizeof(bx_inst));
1860 goto DISPATCH;
1861 }
1862
1863 cpu->Reg[15] += cpu->GetInstructionSize();
1864 INC_PC(sizeof(bx_inst));
1865 goto DISPATCH;
1866}
1867
1868CDP_INST : {
1869 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1870 // Undefined instruction here
1871 cpu->NumInstrsToExecute = 0;
1872 return num_instrs;
1873 }
1874 cpu->Reg[15] += cpu->GetInstructionSize();
1875 INC_PC(sizeof(cdp_inst));
1876 FETCH_INST;
1877 GOTO_NEXT_INST;
1878}
1879
1880CLREX_INST : {
1881 cpu->UnsetExclusiveMemoryAddress();
1882 cpu->Reg[15] += cpu->GetInstructionSize();
1883 INC_PC(sizeof(clrex_inst));
1884 FETCH_INST;
1885 GOTO_NEXT_INST;
1886}
1887CLZ_INST : {
1888 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1889 clz_inst* inst_cream = (clz_inst*)inst_base->component;
1890 RD = clz(RM);
1891 }
1892 cpu->Reg[15] += cpu->GetInstructionSize();
1893 INC_PC(sizeof(clz_inst));
1894 FETCH_INST;
1895 GOTO_NEXT_INST;
1896}
1897CMN_INST : {
1898 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1899 cmn_inst* const inst_cream = (cmn_inst*)inst_base->component;
1900
1901 u32 rn_val = RN;
1902 if (inst_cream->Rn == 15)
1903 rn_val += 2 * cpu->GetInstructionSize();
1904
1905 bool carry;
1906 bool overflow;
1907 u32 result = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
1908
1909 UPDATE_NFLAG(result);
1910 UPDATE_ZFLAG(result);
1911 cpu->CFlag = carry;
1912 cpu->VFlag = overflow;
1913 }
1914 cpu->Reg[15] += cpu->GetInstructionSize();
1915 INC_PC(sizeof(cmn_inst));
1916 FETCH_INST;
1917 GOTO_NEXT_INST;
1918}
1919CMP_INST : {
1920 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1921 cmp_inst* const inst_cream = (cmp_inst*)inst_base->component;
1922
1923 u32 rn_val = RN;
1924 if (inst_cream->Rn == 15)
1925 rn_val += 2 * cpu->GetInstructionSize();
1926
1927 bool carry;
1928 bool overflow;
1929 u32 result = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
1930
1931 UPDATE_NFLAG(result);
1932 UPDATE_ZFLAG(result);
1933 cpu->CFlag = carry;
1934 cpu->VFlag = overflow;
1935 }
1936 cpu->Reg[15] += cpu->GetInstructionSize();
1937 INC_PC(sizeof(cmp_inst));
1938 FETCH_INST;
1939 GOTO_NEXT_INST;
1940}
1941CPS_INST : {
1942 cps_inst* inst_cream = (cps_inst*)inst_base->component;
1943 u32 aif_val = 0;
1944 u32 aif_mask = 0;
1945 if (cpu->InAPrivilegedMode()) {
1946 if (inst_cream->imod1) {
1947 if (inst_cream->A) {
1948 aif_val |= (inst_cream->imod0 << 8);
1949 aif_mask |= 1 << 8;
1950 }
1951 if (inst_cream->I) {
1952 aif_val |= (inst_cream->imod0 << 7);
1953 aif_mask |= 1 << 7;
1954 }
1955 if (inst_cream->F) {
1956 aif_val |= (inst_cream->imod0 << 6);
1957 aif_mask |= 1 << 6;
1958 }
1959 aif_mask = ~aif_mask;
1960 cpu->Cpsr = (cpu->Cpsr & aif_mask) | aif_val;
1961 }
1962 if (inst_cream->mmod) {
1963 cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode;
1964 cpu->ChangePrivilegeMode(inst_cream->mode);
1965 }
1966 }
1967 cpu->Reg[15] += cpu->GetInstructionSize();
1968 INC_PC(sizeof(cps_inst));
1969 FETCH_INST;
1970 GOTO_NEXT_INST;
1971}
1972CPY_INST : {
1973 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1974 mov_inst* inst_cream = (mov_inst*)inst_base->component;
1975
1976 RD = SHIFTER_OPERAND;
1977 if (inst_cream->Rd == 15) {
1978 INC_PC(sizeof(mov_inst));
1979 goto DISPATCH;
1980 }
1981 }
1982 cpu->Reg[15] += cpu->GetInstructionSize();
1983 INC_PC(sizeof(mov_inst));
1984 FETCH_INST;
1985 GOTO_NEXT_INST;
1986}
1987EOR_INST : {
1988 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1989 eor_inst* inst_cream = (eor_inst*)inst_base->component;
1990
1991 u32 lop = RN;
1992 if (inst_cream->Rn == 15) {
1993 lop += 2 * cpu->GetInstructionSize();
1994 }
1995 u32 rop = SHIFTER_OPERAND;
1996 RD = lop ^ rop;
1997 if (inst_cream->S && (inst_cream->Rd == 15)) {
1998 if (CurrentModeHasSPSR) {
1999 cpu->Cpsr = cpu->Spsr_copy;
2000 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2001 LOAD_NZCVT;
2002 }
2003 } else if (inst_cream->S) {
2004 UPDATE_NFLAG(RD);
2005 UPDATE_ZFLAG(RD);
2006 UPDATE_CFLAG_WITH_SC;
2007 }
2008 if (inst_cream->Rd == 15) {
2009 INC_PC(sizeof(eor_inst));
2010 goto DISPATCH;
2011 }
2012 }
2013 cpu->Reg[15] += cpu->GetInstructionSize();
2014 INC_PC(sizeof(eor_inst));
2015 FETCH_INST;
2016 GOTO_NEXT_INST;
2017}
2018LDC_INST : {
2019 // Instruction not implemented
2020 // LOG_CRITICAL(Core_ARM, "unimplemented instruction");
2021 cpu->Reg[15] += cpu->GetInstructionSize();
2022 INC_PC(sizeof(ldc_inst));
2023 FETCH_INST;
2024 GOTO_NEXT_INST;
2025}
2026LDM_INST : {
2027 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2028 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2029 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2030
2031 unsigned int inst = inst_cream->inst;
2032 if (BIT(inst, 22) && !BIT(inst, 15)) {
2033 for (int i = 0; i < 13; i++) {
2034 if (BIT(inst, i)) {
2035 cpu->Reg[i] = cpu->ReadMemory32(addr);
2036 addr += 4;
2037 }
2038 }
2039 if (BIT(inst, 13)) {
2040 if (cpu->Mode == USER32MODE)
2041 cpu->Reg[13] = cpu->ReadMemory32(addr);
2042 else
2043 cpu->Reg_usr[0] = cpu->ReadMemory32(addr);
2044
2045 addr += 4;
2046 }
2047 if (BIT(inst, 14)) {
2048 if (cpu->Mode == USER32MODE)
2049 cpu->Reg[14] = cpu->ReadMemory32(addr);
2050 else
2051 cpu->Reg_usr[1] = cpu->ReadMemory32(addr);
2052
2053 addr += 4;
2054 }
2055 } else if (!BIT(inst, 22)) {
2056 for (int i = 0; i < 16; i++) {
2057 if (BIT(inst, i)) {
2058 unsigned int ret = cpu->ReadMemory32(addr);
2059
2060 // For armv5t, should enter thumb when bits[0] is non-zero.
2061 if (i == 15) {
2062 cpu->TFlag = ret & 0x1;
2063 ret &= 0xFFFFFFFE;
2064 }
2065
2066 cpu->Reg[i] = ret;
2067 addr += 4;
2068 }
2069 }
2070 } else if (BIT(inst, 22) && BIT(inst, 15)) {
2071 for (int i = 0; i < 15; i++) {
2072 if (BIT(inst, i)) {
2073 cpu->Reg[i] = cpu->ReadMemory32(addr);
2074 addr += 4;
2075 }
2076 }
2077
2078 if (CurrentModeHasSPSR) {
2079 cpu->Cpsr = cpu->Spsr_copy;
2080 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
2081 LOAD_NZCVT;
2082 }
2083
2084 cpu->Reg[15] = cpu->ReadMemory32(addr);
2085 }
2086
2087 if (BIT(inst, 15)) {
2088 INC_PC(sizeof(ldst_inst));
2089 goto DISPATCH;
2090 }
2091 }
2092 cpu->Reg[15] += cpu->GetInstructionSize();
2093 INC_PC(sizeof(ldst_inst));
2094 FETCH_INST;
2095 GOTO_NEXT_INST;
2096}
2097SXTH_INST : {
2098 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2099 sxth_inst* inst_cream = (sxth_inst*)inst_base->component;
2100
2101 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate);
2102 if (BIT(operand2, 15)) {
2103 operand2 |= 0xffff0000;
2104 } else {
2105 operand2 &= 0xffff;
2106 }
2107 RD = operand2;
2108 }
2109 cpu->Reg[15] += cpu->GetInstructionSize();
2110 INC_PC(sizeof(sxth_inst));
2111 FETCH_INST;
2112 GOTO_NEXT_INST;
2113}
2114LDR_INST : {
2115 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2116 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2117
2118 unsigned int value = cpu->ReadMemory32(addr);
2119 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
2120
2121 if (BITS(inst_cream->inst, 12, 15) == 15) {
2122 // For armv5t, should enter thumb when bits[0] is non-zero.
2123 cpu->TFlag = value & 0x1;
2124 cpu->Reg[15] &= 0xFFFFFFFE;
2125 INC_PC(sizeof(ldst_inst));
2126 goto DISPATCH;
2127 }
2128
2129 cpu->Reg[15] += cpu->GetInstructionSize();
2130 INC_PC(sizeof(ldst_inst));
2131 FETCH_INST;
2132 GOTO_NEXT_INST;
2133}
2134LDRCOND_INST : {
2135 if (CondPassed(cpu, inst_base->cond)) {
2136 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2137 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2138
2139 unsigned int value = cpu->ReadMemory32(addr);
2140 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
2141
2142 if (BITS(inst_cream->inst, 12, 15) == 15) {
2143 // For armv5t, should enter thumb when bits[0] is non-zero.
2144 cpu->TFlag = value & 0x1;
2145 cpu->Reg[15] &= 0xFFFFFFFE;
2146 INC_PC(sizeof(ldst_inst));
2147 goto DISPATCH;
2148 }
2149 }
2150 cpu->Reg[15] += cpu->GetInstructionSize();
2151 INC_PC(sizeof(ldst_inst));
2152 FETCH_INST;
2153 GOTO_NEXT_INST;
2154}
2155UXTH_INST : {
2156 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2157 uxth_inst* inst_cream = (uxth_inst*)inst_base->component;
2158 RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
2159 }
2160 cpu->Reg[15] += cpu->GetInstructionSize();
2161 INC_PC(sizeof(uxth_inst));
2162 FETCH_INST;
2163 GOTO_NEXT_INST;
2164}
2165UXTAH_INST : {
2166 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2167 uxtah_inst* inst_cream = (uxtah_inst*)inst_base->component;
2168 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
2169
2170 RD = RN + operand2;
2171 }
2172 cpu->Reg[15] += cpu->GetInstructionSize();
2173 INC_PC(sizeof(uxtah_inst));
2174 FETCH_INST;
2175 GOTO_NEXT_INST;
2176}
2177LDRB_INST : {
2178 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2179 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2180 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2181
2182 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory8(addr);
2183 }
2184 cpu->Reg[15] += cpu->GetInstructionSize();
2185 INC_PC(sizeof(ldst_inst));
2186 FETCH_INST;
2187 GOTO_NEXT_INST;
2188}
2189LDRBT_INST : {
2190 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2191 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2192 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2193
2194 const u32 dest_index = BITS(inst_cream->inst, 12, 15);
2195 const u32 previous_mode = cpu->Mode;
2196
2197 cpu->ChangePrivilegeMode(USER32MODE);
2198 const u8 value = cpu->ReadMemory8(addr);
2199 cpu->ChangePrivilegeMode(previous_mode);
2200
2201 cpu->Reg[dest_index] = value;
2202 }
2203 cpu->Reg[15] += cpu->GetInstructionSize();
2204 INC_PC(sizeof(ldst_inst));
2205 FETCH_INST;
2206 GOTO_NEXT_INST;
2207}
2208LDRD_INST : {
2209 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2210 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2211 // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 ||
2212 // addr[2] == 0)
2213 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2214
2215 // The 3DS doesn't have LPAE (Large Physical Access Extension), so it
2216 // wouldn't do this as a single read.
2217 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = cpu->ReadMemory32(addr);
2218 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = cpu->ReadMemory32(addr + 4);
2219
2220 // No dispatch since this operation should not modify R15
2221 }
2222 cpu->Reg[15] += 4;
2223 INC_PC(sizeof(ldst_inst));
2224 FETCH_INST;
2225 GOTO_NEXT_INST;
2226}
2227
2228LDREX_INST : {
2229 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2230 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2231 unsigned int read_addr = RN;
2232
2233 cpu->SetExclusiveMemoryAddress(read_addr);
2234
2235 RD = cpu->ReadMemory32(read_addr);
2236 }
2237 cpu->Reg[15] += cpu->GetInstructionSize();
2238 INC_PC(sizeof(generic_arm_inst));
2239 FETCH_INST;
2240 GOTO_NEXT_INST;
2241}
2242LDREXB_INST : {
2243 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2244 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2245 unsigned int read_addr = RN;
2246
2247 cpu->SetExclusiveMemoryAddress(read_addr);
2248
2249 RD = cpu->ReadMemory8(read_addr);
2250 }
2251 cpu->Reg[15] += cpu->GetInstructionSize();
2252 INC_PC(sizeof(generic_arm_inst));
2253 FETCH_INST;
2254 GOTO_NEXT_INST;
2255}
2256LDREXH_INST : {
2257 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2258 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2259 unsigned int read_addr = RN;
2260
2261 cpu->SetExclusiveMemoryAddress(read_addr);
2262
2263 RD = cpu->ReadMemory16(read_addr);
2264 }
2265 cpu->Reg[15] += cpu->GetInstructionSize();
2266 INC_PC(sizeof(generic_arm_inst));
2267 FETCH_INST;
2268 GOTO_NEXT_INST;
2269}
2270LDREXD_INST : {
2271 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2272 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2273 unsigned int read_addr = RN;
2274
2275 cpu->SetExclusiveMemoryAddress(read_addr);
2276
2277 RD = cpu->ReadMemory32(read_addr);
2278 RD2 = cpu->ReadMemory32(read_addr + 4);
2279 }
2280 cpu->Reg[15] += cpu->GetInstructionSize();
2281 INC_PC(sizeof(generic_arm_inst));
2282 FETCH_INST;
2283 GOTO_NEXT_INST;
2284}
2285LDRH_INST : {
2286 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2287 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2288 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2289
2290 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory16(addr);
2291 }
2292 cpu->Reg[15] += cpu->GetInstructionSize();
2293 INC_PC(sizeof(ldst_inst));
2294 FETCH_INST;
2295 GOTO_NEXT_INST;
2296}
2297LDRSB_INST : {
2298 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2299 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2300 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2301 unsigned int value = cpu->ReadMemory8(addr);
2302 if (BIT(value, 7)) {
2303 value |= 0xffffff00;
2304 }
2305 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
2306 }
2307 cpu->Reg[15] += cpu->GetInstructionSize();
2308 INC_PC(sizeof(ldst_inst));
2309 FETCH_INST;
2310 GOTO_NEXT_INST;
2311}
2312LDRSH_INST : {
2313 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2314 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2315 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2316
2317 unsigned int value = cpu->ReadMemory16(addr);
2318 if (BIT(value, 15)) {
2319 value |= 0xffff0000;
2320 }
2321 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
2322 }
2323 cpu->Reg[15] += cpu->GetInstructionSize();
2324 INC_PC(sizeof(ldst_inst));
2325 FETCH_INST;
2326 GOTO_NEXT_INST;
2327}
2328LDRT_INST : {
2329 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2330 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2331 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2332
2333 const u32 dest_index = BITS(inst_cream->inst, 12, 15);
2334 const u32 previous_mode = cpu->Mode;
2335
2336 cpu->ChangePrivilegeMode(USER32MODE);
2337 const u32 value = cpu->ReadMemory32(addr);
2338 cpu->ChangePrivilegeMode(previous_mode);
2339
2340 cpu->Reg[dest_index] = value;
2341 }
2342 cpu->Reg[15] += cpu->GetInstructionSize();
2343 INC_PC(sizeof(ldst_inst));
2344 FETCH_INST;
2345 GOTO_NEXT_INST;
2346}
2347MCR_INST : {
2348 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2349 mcr_inst* inst_cream = (mcr_inst*)inst_base->component;
2350
2351 unsigned int inst = inst_cream->inst;
2352 if (inst_cream->Rd == 15) {
2353 DEBUG_MSG;
2354 } else {
2355 if (inst_cream->cp_num == 15)
2356 cpu->WriteCP15Register(RD, CRn, OPCODE_1, CRm, OPCODE_2);
2357 }
2358 }
2359 cpu->Reg[15] += cpu->GetInstructionSize();
2360 INC_PC(sizeof(mcr_inst));
2361 FETCH_INST;
2362 GOTO_NEXT_INST;
2363}
2364
2365MCRR_INST : {
2366 // Stubbed, as the MPCore doesn't have any registers that are accessible
2367 // through this instruction.
2368 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2369 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
2370
2371 LOG_ERROR(Core_ARM, "MCRR executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u",
2372 inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt,
2373 inst_cream->rt2);
2374 }
2375
2376 cpu->Reg[15] += cpu->GetInstructionSize();
2377 INC_PC(sizeof(mcrr_inst));
2378 FETCH_INST;
2379 GOTO_NEXT_INST;
2380}
2381
2382MLA_INST : {
2383 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2384 mla_inst* inst_cream = (mla_inst*)inst_base->component;
2385
2386 u64 rm = RM;
2387 u64 rs = RS;
2388 u64 rn = RN;
2389
2390 RD = static_cast<u32>((rm * rs + rn) & 0xffffffff);
2391 if (inst_cream->S) {
2392 UPDATE_NFLAG(RD);
2393 UPDATE_ZFLAG(RD);
2394 }
2395 }
2396 cpu->Reg[15] += cpu->GetInstructionSize();
2397 INC_PC(sizeof(mla_inst));
2398 FETCH_INST;
2399 GOTO_NEXT_INST;
2400}
2401MOV_INST : {
2402 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2403 mov_inst* inst_cream = (mov_inst*)inst_base->component;
2404
2405 RD = SHIFTER_OPERAND;
2406 if (inst_cream->S && (inst_cream->Rd == 15)) {
2407 if (CurrentModeHasSPSR) {
2408 cpu->Cpsr = cpu->Spsr_copy;
2409 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2410 LOAD_NZCVT;
2411 }
2412 } else if (inst_cream->S) {
2413 UPDATE_NFLAG(RD);
2414 UPDATE_ZFLAG(RD);
2415 UPDATE_CFLAG_WITH_SC;
2416 }
2417 if (inst_cream->Rd == 15) {
2418 INC_PC(sizeof(mov_inst));
2419 goto DISPATCH;
2420 }
2421 }
2422 cpu->Reg[15] += cpu->GetInstructionSize();
2423 INC_PC(sizeof(mov_inst));
2424 FETCH_INST;
2425 GOTO_NEXT_INST;
2426}
2427MRC_INST : {
2428 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2429 mrc_inst* inst_cream = (mrc_inst*)inst_base->component;
2430
2431 if (inst_cream->cp_num == 15) {
2432 const uint32_t value = cpu->ReadCP15Register(CRn, OPCODE_1, CRm, OPCODE_2);
2433
2434 if (inst_cream->Rd == 15) {
2435 cpu->Cpsr = (cpu->Cpsr & ~0xF0000000) | (value & 0xF0000000);
2436 LOAD_NZCVT;
2437 } else {
2438 RD = value;
2439 }
2440 }
2441 }
2442 cpu->Reg[15] += cpu->GetInstructionSize();
2443 INC_PC(sizeof(mrc_inst));
2444 FETCH_INST;
2445 GOTO_NEXT_INST;
2446}
2447
2448MRRC_INST : {
2449 // Stubbed, as the MPCore doesn't have any registers that are accessible
2450 // through this instruction.
2451 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2452 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
2453
2454 LOG_ERROR(Core_ARM, "MRRC executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u",
2455 inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt,
2456 inst_cream->rt2);
2457 }
2458
2459 cpu->Reg[15] += cpu->GetInstructionSize();
2460 INC_PC(sizeof(mcrr_inst));
2461 FETCH_INST;
2462 GOTO_NEXT_INST;
2463}
2464
2465MRS_INST : {
2466 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2467 mrs_inst* inst_cream = (mrs_inst*)inst_base->component;
2468
2469 if (inst_cream->R) {
2470 RD = cpu->Spsr_copy;
2471 } else {
2472 SAVE_NZCVT;
2473 RD = cpu->Cpsr;
2474 }
2475 }
2476 cpu->Reg[15] += cpu->GetInstructionSize();
2477 INC_PC(sizeof(mrs_inst));
2478 FETCH_INST;
2479 GOTO_NEXT_INST;
2480}
2481MSR_INST : {
2482 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2483 msr_inst* inst_cream = (msr_inst*)inst_base->component;
2484 const u32 UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020;
2485 unsigned int inst = inst_cream->inst;
2486 unsigned int operand;
2487
2488 if (BIT(inst, 25)) {
2489 int rot_imm = BITS(inst, 8, 11) * 2;
2490 operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm);
2491 } else {
2492 operand = cpu->Reg[BITS(inst, 0, 3)];
2493 }
2494 u32 byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) |
2495 (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
2496 u32 mask = 0;
2497 if (!inst_cream->R) {
2498 if (cpu->InAPrivilegedMode()) {
2499 if ((operand & StateMask) != 0) {
2500 /// UNPREDICTABLE
2501 DEBUG_MSG;
2502 } else
2503 mask = byte_mask & (UserMask | PrivMask);
2504 } else {
2505 mask = byte_mask & UserMask;
2506 }
2507 SAVE_NZCVT;
2508
2509 cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask);
2510 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
2511 LOAD_NZCVT;
2512 } else {
2513 if (CurrentModeHasSPSR) {
2514 mask = byte_mask & (UserMask | PrivMask | StateMask);
2515 cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask);
2516 }
2517 }
2518 }
2519 cpu->Reg[15] += cpu->GetInstructionSize();
2520 INC_PC(sizeof(msr_inst));
2521 FETCH_INST;
2522 GOTO_NEXT_INST;
2523}
2524MUL_INST : {
2525 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2526 mul_inst* inst_cream = (mul_inst*)inst_base->component;
2527
2528 u64 rm = RM;
2529 u64 rs = RS;
2530 RD = static_cast<u32>((rm * rs) & 0xffffffff);
2531 if (inst_cream->S) {
2532 UPDATE_NFLAG(RD);
2533 UPDATE_ZFLAG(RD);
2534 }
2535 }
2536 cpu->Reg[15] += cpu->GetInstructionSize();
2537 INC_PC(sizeof(mul_inst));
2538 FETCH_INST;
2539 GOTO_NEXT_INST;
2540}
2541MVN_INST : {
2542 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2543 mvn_inst* const inst_cream = (mvn_inst*)inst_base->component;
2544
2545 RD = ~SHIFTER_OPERAND;
2546
2547 if (inst_cream->S && (inst_cream->Rd == 15)) {
2548 if (CurrentModeHasSPSR) {
2549 cpu->Cpsr = cpu->Spsr_copy;
2550 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2551 LOAD_NZCVT;
2552 }
2553 } else if (inst_cream->S) {
2554 UPDATE_NFLAG(RD);
2555 UPDATE_ZFLAG(RD);
2556 UPDATE_CFLAG_WITH_SC;
2557 }
2558 if (inst_cream->Rd == 15) {
2559 INC_PC(sizeof(mvn_inst));
2560 goto DISPATCH;
2561 }
2562 }
2563 cpu->Reg[15] += cpu->GetInstructionSize();
2564 INC_PC(sizeof(mvn_inst));
2565 FETCH_INST;
2566 GOTO_NEXT_INST;
2567}
2568ORR_INST : {
2569 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2570 orr_inst* const inst_cream = (orr_inst*)inst_base->component;
2571
2572 u32 lop = RN;
2573 u32 rop = SHIFTER_OPERAND;
2574
2575 if (inst_cream->Rn == 15)
2576 lop += 2 * cpu->GetInstructionSize();
2577
2578 RD = lop | rop;
2579
2580 if (inst_cream->S && (inst_cream->Rd == 15)) {
2581 if (CurrentModeHasSPSR) {
2582 cpu->Cpsr = cpu->Spsr_copy;
2583 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2584 LOAD_NZCVT;
2585 }
2586 } else if (inst_cream->S) {
2587 UPDATE_NFLAG(RD);
2588 UPDATE_ZFLAG(RD);
2589 UPDATE_CFLAG_WITH_SC;
2590 }
2591 if (inst_cream->Rd == 15) {
2592 INC_PC(sizeof(orr_inst));
2593 goto DISPATCH;
2594 }
2595 }
2596 cpu->Reg[15] += cpu->GetInstructionSize();
2597 INC_PC(sizeof(orr_inst));
2598 FETCH_INST;
2599 GOTO_NEXT_INST;
2600}
2601
2602NOP_INST : {
2603 cpu->Reg[15] += cpu->GetInstructionSize();
2604 INC_PC_STUB;
2605 FETCH_INST;
2606 GOTO_NEXT_INST;
2607}
2608
2609PKHBT_INST : {
2610 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2611 pkh_inst* inst_cream = (pkh_inst*)inst_base->component;
2612 RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000);
2613 }
2614 cpu->Reg[15] += cpu->GetInstructionSize();
2615 INC_PC(sizeof(pkh_inst));
2616 FETCH_INST;
2617 GOTO_NEXT_INST;
2618}
2619
2620PKHTB_INST : {
2621 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2622 pkh_inst* inst_cream = (pkh_inst*)inst_base->component;
2623 int shift_imm = inst_cream->imm ? inst_cream->imm : 31;
2624 RD = ((static_cast<s32>(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000);
2625 }
2626 cpu->Reg[15] += cpu->GetInstructionSize();
2627 INC_PC(sizeof(pkh_inst));
2628 FETCH_INST;
2629 GOTO_NEXT_INST;
2630}
2631
2632PLD_INST : {
2633 // Not implemented. PLD is a hint instruction, so it's optional.
2634
2635 cpu->Reg[15] += cpu->GetInstructionSize();
2636 INC_PC(sizeof(pld_inst));
2637 FETCH_INST;
2638 GOTO_NEXT_INST;
2639}
2640
2641QADD_INST:
2642QDADD_INST:
2643QDSUB_INST:
2644QSUB_INST : {
2645 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2646 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2647 const u8 op1 = inst_cream->op1;
2648 const u32 rm_val = RM;
2649 const u32 rn_val = RN;
2650
2651 u32 result = 0;
2652
2653 // QADD
2654 if (op1 == 0x00) {
2655 result = rm_val + rn_val;
2656
2657 if (AddOverflow(rm_val, rn_val, result)) {
2658 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2659 cpu->Cpsr |= (1 << 27);
2660 }
2661 }
2662 // QSUB
2663 else if (op1 == 0x01) {
2664 result = rm_val - rn_val;
2665
2666 if (SubOverflow(rm_val, rn_val, result)) {
2667 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2668 cpu->Cpsr |= (1 << 27);
2669 }
2670 }
2671 // QDADD
2672 else if (op1 == 0x02) {
2673 u32 mul = (rn_val * 2);
2674
2675 if (AddOverflow(rn_val, rn_val, rn_val * 2)) {
2676 mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF;
2677 cpu->Cpsr |= (1 << 27);
2678 }
2679
2680 result = mul + rm_val;
2681
2682 if (AddOverflow(rm_val, mul, result)) {
2683 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2684 cpu->Cpsr |= (1 << 27);
2685 }
2686 }
2687 // QDSUB
2688 else if (op1 == 0x03) {
2689 u32 mul = (rn_val * 2);
2690
2691 if (AddOverflow(rn_val, rn_val, mul)) {
2692 mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF;
2693 cpu->Cpsr |= (1 << 27);
2694 }
2695
2696 result = rm_val - mul;
2697
2698 if (SubOverflow(rm_val, mul, result)) {
2699 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2700 cpu->Cpsr |= (1 << 27);
2701 }
2702 }
2703
2704 RD = result;
2705 }
2706
2707 cpu->Reg[15] += cpu->GetInstructionSize();
2708 INC_PC(sizeof(generic_arm_inst));
2709 FETCH_INST;
2710 GOTO_NEXT_INST;
2711}
2712
2713QADD8_INST:
2714QADD16_INST:
2715QADDSUBX_INST:
2716QSUB8_INST:
2717QSUB16_INST:
2718QSUBADDX_INST : {
2719 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2720 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2721 const u16 rm_lo = (RM & 0xFFFF);
2722 const u16 rm_hi = ((RM >> 16) & 0xFFFF);
2723 const u16 rn_lo = (RN & 0xFFFF);
2724 const u16 rn_hi = ((RN >> 16) & 0xFFFF);
2725 const u8 op2 = inst_cream->op2;
2726
2727 u16 lo_result = 0;
2728 u16 hi_result = 0;
2729
2730 // QADD16
2731 if (op2 == 0x00) {
2732 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo);
2733 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi);
2734 }
2735 // QASX
2736 else if (op2 == 0x01) {
2737 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi);
2738 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo);
2739 }
2740 // QSAX
2741 else if (op2 == 0x02) {
2742 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi);
2743 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo);
2744 }
2745 // QSUB16
2746 else if (op2 == 0x03) {
2747 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo);
2748 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi);
2749 }
2750 // QADD8
2751 else if (op2 == 0x04) {
2752 lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) |
2753 ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8;
2754 hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) |
2755 ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8;
2756 }
2757 // QSUB8
2758 else if (op2 == 0x07) {
2759 lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) |
2760 ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8;
2761 hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) |
2762 ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8;
2763 }
2764
2765 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
2766 }
2767
2768 cpu->Reg[15] += cpu->GetInstructionSize();
2769 INC_PC(sizeof(generic_arm_inst));
2770 FETCH_INST;
2771 GOTO_NEXT_INST;
2772}
2773
2774REV_INST:
2775REV16_INST:
2776REVSH_INST : {
2777
2778 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2779 rev_inst* const inst_cream = (rev_inst*)inst_base->component;
2780
2781 const u8 op1 = inst_cream->op1;
2782 const u8 op2 = inst_cream->op2;
2783
2784 // REV
2785 if (op1 == 0x03 && op2 == 0x01) {
2786 RD = ((RM & 0xFF) << 24) | (((RM >> 8) & 0xFF) << 16) | (((RM >> 16) & 0xFF) << 8) |
2787 ((RM >> 24) & 0xFF);
2788 }
2789 // REV16
2790 else if (op1 == 0x03 && op2 == 0x05) {
2791 RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8) | ((RM & 0xFF0000) << 8) |
2792 ((RM & 0xFF000000) >> 8);
2793 }
2794 // REVSH
2795 else if (op1 == 0x07 && op2 == 0x05) {
2796 RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8);
2797 if (RD & 0x8000)
2798 RD |= 0xffff0000;
2799 }
2800 }
2801
2802 cpu->Reg[15] += cpu->GetInstructionSize();
2803 INC_PC(sizeof(rev_inst));
2804 FETCH_INST;
2805 GOTO_NEXT_INST;
2806}
2807
2808RFE_INST : {
2809 // RFE is unconditional
2810 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
2811
2812 u32 address = 0;
2813 inst_cream->get_addr(cpu, inst_cream->inst, address);
2814
2815 cpu->Cpsr = cpu->ReadMemory32(address);
2816 cpu->Reg[15] = cpu->ReadMemory32(address + 4);
2817
2818 INC_PC(sizeof(ldst_inst));
2819 goto DISPATCH;
2820}
2821
2822RSB_INST : {
2823 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2824 rsb_inst* const inst_cream = (rsb_inst*)inst_base->component;
2825
2826 u32 rn_val = RN;
2827 if (inst_cream->Rn == 15)
2828 rn_val += 2 * cpu->GetInstructionSize();
2829
2830 bool carry;
2831 bool overflow;
2832 RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, 1, &carry, &overflow);
2833
2834 if (inst_cream->S && (inst_cream->Rd == 15)) {
2835 if (CurrentModeHasSPSR) {
2836 cpu->Cpsr = cpu->Spsr_copy;
2837 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2838 LOAD_NZCVT;
2839 }
2840 } else if (inst_cream->S) {
2841 UPDATE_NFLAG(RD);
2842 UPDATE_ZFLAG(RD);
2843 cpu->CFlag = carry;
2844 cpu->VFlag = overflow;
2845 }
2846 if (inst_cream->Rd == 15) {
2847 INC_PC(sizeof(rsb_inst));
2848 goto DISPATCH;
2849 }
2850 }
2851 cpu->Reg[15] += cpu->GetInstructionSize();
2852 INC_PC(sizeof(rsb_inst));
2853 FETCH_INST;
2854 GOTO_NEXT_INST;
2855}
2856RSC_INST : {
2857 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2858 rsc_inst* const inst_cream = (rsc_inst*)inst_base->component;
2859
2860 u32 rn_val = RN;
2861 if (inst_cream->Rn == 15)
2862 rn_val += 2 * cpu->GetInstructionSize();
2863
2864 bool carry;
2865 bool overflow;
2866 RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
2867
2868 if (inst_cream->S && (inst_cream->Rd == 15)) {
2869 if (CurrentModeHasSPSR) {
2870 cpu->Cpsr = cpu->Spsr_copy;
2871 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2872 LOAD_NZCVT;
2873 }
2874 } else if (inst_cream->S) {
2875 UPDATE_NFLAG(RD);
2876 UPDATE_ZFLAG(RD);
2877 cpu->CFlag = carry;
2878 cpu->VFlag = overflow;
2879 }
2880 if (inst_cream->Rd == 15) {
2881 INC_PC(sizeof(rsc_inst));
2882 goto DISPATCH;
2883 }
2884 }
2885 cpu->Reg[15] += cpu->GetInstructionSize();
2886 INC_PC(sizeof(rsc_inst));
2887 FETCH_INST;
2888 GOTO_NEXT_INST;
2889}
2890
2891SADD8_INST:
2892SSUB8_INST:
2893SADD16_INST:
2894SADDSUBX_INST:
2895SSUBADDX_INST:
2896SSUB16_INST : {
2897 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2898 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2899 const u8 op2 = inst_cream->op2;
2900
2901 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
2902 const s16 rn_lo = (RN & 0xFFFF);
2903 const s16 rn_hi = ((RN >> 16) & 0xFFFF);
2904 const s16 rm_lo = (RM & 0xFFFF);
2905 const s16 rm_hi = ((RM >> 16) & 0xFFFF);
2906
2907 s32 lo_result = 0;
2908 s32 hi_result = 0;
2909
2910 // SADD16
2911 if (inst_cream->op2 == 0x00) {
2912 lo_result = (rn_lo + rm_lo);
2913 hi_result = (rn_hi + rm_hi);
2914 }
2915 // SASX
2916 else if (op2 == 0x01) {
2917 lo_result = (rn_lo - rm_hi);
2918 hi_result = (rn_hi + rm_lo);
2919 }
2920 // SSAX
2921 else if (op2 == 0x02) {
2922 lo_result = (rn_lo + rm_hi);
2923 hi_result = (rn_hi - rm_lo);
2924 }
2925 // SSUB16
2926 else if (op2 == 0x03) {
2927 lo_result = (rn_lo - rm_lo);
2928 hi_result = (rn_hi - rm_hi);
2929 }
2930
2931 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
2932
2933 if (lo_result >= 0) {
2934 cpu->Cpsr |= (1 << 16);
2935 cpu->Cpsr |= (1 << 17);
2936 } else {
2937 cpu->Cpsr &= ~(1 << 16);
2938 cpu->Cpsr &= ~(1 << 17);
2939 }
2940
2941 if (hi_result >= 0) {
2942 cpu->Cpsr |= (1 << 18);
2943 cpu->Cpsr |= (1 << 19);
2944 } else {
2945 cpu->Cpsr &= ~(1 << 18);
2946 cpu->Cpsr &= ~(1 << 19);
2947 }
2948 } else if (op2 == 0x04 || op2 == 0x07) {
2949 s32 lo_val1, lo_val2;
2950 s32 hi_val1, hi_val2;
2951
2952 // SADD8
2953 if (op2 == 0x04) {
2954 lo_val1 = (s32)(s8)(RN & 0xFF) + (s32)(s8)(RM & 0xFF);
2955 lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) + (s32)(s8)((RM >> 8) & 0xFF);
2956 hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) + (s32)(s8)((RM >> 16) & 0xFF);
2957 hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) + (s32)(s8)((RM >> 24) & 0xFF);
2958 }
2959 // SSUB8
2960 else {
2961 lo_val1 = (s32)(s8)(RN & 0xFF) - (s32)(s8)(RM & 0xFF);
2962 lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) - (s32)(s8)((RM >> 8) & 0xFF);
2963 hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) - (s32)(s8)((RM >> 16) & 0xFF);
2964 hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) - (s32)(s8)((RM >> 24) & 0xFF);
2965 }
2966
2967 RD = ((lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) |
2968 ((hi_val2 & 0xFF) << 24));
2969
2970 if (lo_val1 >= 0)
2971 cpu->Cpsr |= (1 << 16);
2972 else
2973 cpu->Cpsr &= ~(1 << 16);
2974
2975 if (lo_val2 >= 0)
2976 cpu->Cpsr |= (1 << 17);
2977 else
2978 cpu->Cpsr &= ~(1 << 17);
2979
2980 if (hi_val1 >= 0)
2981 cpu->Cpsr |= (1 << 18);
2982 else
2983 cpu->Cpsr &= ~(1 << 18);
2984
2985 if (hi_val2 >= 0)
2986 cpu->Cpsr |= (1 << 19);
2987 else
2988 cpu->Cpsr &= ~(1 << 19);
2989 }
2990 }
2991
2992 cpu->Reg[15] += cpu->GetInstructionSize();
2993 INC_PC(sizeof(generic_arm_inst));
2994 FETCH_INST;
2995 GOTO_NEXT_INST;
2996}
2997
2998SBC_INST : {
2999 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3000 sbc_inst* const inst_cream = (sbc_inst*)inst_base->component;
3001
3002 u32 rn_val = RN;
3003 if (inst_cream->Rn == 15)
3004 rn_val += 2 * cpu->GetInstructionSize();
3005
3006 bool carry;
3007 bool overflow;
3008 RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
3009
3010 if (inst_cream->S && (inst_cream->Rd == 15)) {
3011 if (CurrentModeHasSPSR) {
3012 cpu->Cpsr = cpu->Spsr_copy;
3013 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
3014 LOAD_NZCVT;
3015 }
3016 } else if (inst_cream->S) {
3017 UPDATE_NFLAG(RD);
3018 UPDATE_ZFLAG(RD);
3019 cpu->CFlag = carry;
3020 cpu->VFlag = overflow;
3021 }
3022 if (inst_cream->Rd == 15) {
3023 INC_PC(sizeof(sbc_inst));
3024 goto DISPATCH;
3025 }
3026 }
3027 cpu->Reg[15] += cpu->GetInstructionSize();
3028 INC_PC(sizeof(sbc_inst));
3029 FETCH_INST;
3030 GOTO_NEXT_INST;
3031}
3032
3033SEL_INST : {
3034 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3035 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
3036
3037 const u32 to = RM;
3038 const u32 from = RN;
3039 const u32 cpsr = cpu->Cpsr;
3040
3041 u32 result;
3042 if (cpsr & (1 << 16))
3043 result = from & 0xff;
3044 else
3045 result = to & 0xff;
3046
3047 if (cpsr & (1 << 17))
3048 result |= from & 0x0000ff00;
3049 else
3050 result |= to & 0x0000ff00;
3051
3052 if (cpsr & (1 << 18))
3053 result |= from & 0x00ff0000;
3054 else
3055 result |= to & 0x00ff0000;
3056
3057 if (cpsr & (1 << 19))
3058 result |= from & 0xff000000;
3059 else
3060 result |= to & 0xff000000;
3061
3062 RD = result;
3063 }
3064
3065 cpu->Reg[15] += cpu->GetInstructionSize();
3066 INC_PC(sizeof(generic_arm_inst));
3067 FETCH_INST;
3068 GOTO_NEXT_INST;
3069}
3070
3071SETEND_INST : {
3072 // SETEND is unconditional
3073 setend_inst* const inst_cream = (setend_inst*)inst_base->component;
3074 const bool big_endian = (inst_cream->set_bigend == 1);
3075
3076 if (big_endian)
3077 cpu->Cpsr |= (1 << 9);
3078 else
3079 cpu->Cpsr &= ~(1 << 9);
3080
3081 LOG_WARNING(Core_ARM, "SETEND %s executed", big_endian ? "BE" : "LE");
3082
3083 cpu->Reg[15] += cpu->GetInstructionSize();
3084 INC_PC(sizeof(setend_inst));
3085 FETCH_INST;
3086 GOTO_NEXT_INST;
3087}
3088
3089SEV_INST : {
3090 // Stubbed, as SEV is a hint instruction.
3091 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3092 LOG_TRACE(Core_ARM, "SEV executed.");
3093 }
3094
3095 cpu->Reg[15] += cpu->GetInstructionSize();
3096 INC_PC_STUB;
3097 FETCH_INST;
3098 GOTO_NEXT_INST;
3099}
3100
3101SHADD8_INST:
3102SHADD16_INST:
3103SHADDSUBX_INST:
3104SHSUB8_INST:
3105SHSUB16_INST:
3106SHSUBADDX_INST : {
3107 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3108 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
3109
3110 const u8 op2 = inst_cream->op2;
3111 const u32 rm_val = RM;
3112 const u32 rn_val = RN;
3113
3114 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
3115 s32 lo_result = 0;
3116 s32 hi_result = 0;
3117
3118 // SHADD16
3119 if (op2 == 0x00) {
3120 lo_result = ((s16)(rn_val & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1;
3121 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
3122 }
3123 // SHASX
3124 else if (op2 == 0x01) {
3125 lo_result = ((s16)(rn_val & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
3126 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1;
3127 }
3128 // SHSAX
3129 else if (op2 == 0x02) {
3130 lo_result = ((s16)(rn_val & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
3131 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1;
3132 }
3133 // SHSUB16
3134 else if (op2 == 0x03) {
3135 lo_result = ((s16)(rn_val & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1;
3136 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
3137 }
3138
3139 RD = ((lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16));
3140 } else if (op2 == 0x04 || op2 == 0x07) {
3141 s16 lo_val1, lo_val2;
3142 s16 hi_val1, hi_val2;
3143
3144 // SHADD8
3145 if (op2 == 0x04) {
3146 lo_val1 = ((s8)(rn_val & 0xFF) + (s8)(rm_val & 0xFF)) >> 1;
3147 lo_val2 = ((s8)((rn_val >> 8) & 0xFF) + (s8)((rm_val >> 8) & 0xFF)) >> 1;
3148
3149 hi_val1 = ((s8)((rn_val >> 16) & 0xFF) + (s8)((rm_val >> 16) & 0xFF)) >> 1;
3150 hi_val2 = ((s8)((rn_val >> 24) & 0xFF) + (s8)((rm_val >> 24) & 0xFF)) >> 1;
3151 }
3152 // SHSUB8
3153 else {
3154 lo_val1 = ((s8)(rn_val & 0xFF) - (s8)(rm_val & 0xFF)) >> 1;
3155 lo_val2 = ((s8)((rn_val >> 8) & 0xFF) - (s8)((rm_val >> 8) & 0xFF)) >> 1;
3156
3157 hi_val1 = ((s8)((rn_val >> 16) & 0xFF) - (s8)((rm_val >> 16) & 0xFF)) >> 1;
3158 hi_val2 = ((s8)((rn_val >> 24) & 0xFF) - (s8)((rm_val >> 24) & 0xFF)) >> 1;
3159 }
3160
3161 RD = (lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) |
3162 ((hi_val2 & 0xFF) << 24);
3163 }
3164 }
3165
3166 cpu->Reg[15] += cpu->GetInstructionSize();
3167 INC_PC(sizeof(generic_arm_inst));
3168 FETCH_INST;
3169 GOTO_NEXT_INST;
3170}
3171
3172SMLA_INST : {
3173 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3174 smla_inst* inst_cream = (smla_inst*)inst_base->component;
3175 s32 operand1, operand2;
3176 if (inst_cream->x == 0)
3177 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
3178 else
3179 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
3180
3181 if (inst_cream->y == 0)
3182 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15);
3183 else
3184 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
3185
3186 u32 product = operand1 * operand2;
3187 u32 result = product + RN;
3188 if (AddOverflow(product, RN, result))
3189 cpu->Cpsr |= (1 << 27);
3190 RD = result;
3191 }
3192 cpu->Reg[15] += cpu->GetInstructionSize();
3193 INC_PC(sizeof(smla_inst));
3194 FETCH_INST;
3195 GOTO_NEXT_INST;
3196}
3197
3198SMLAD_INST:
3199SMLSD_INST:
3200SMUAD_INST:
3201SMUSD_INST : {
3202 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3203 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3204 const u8 op2 = inst_cream->op2;
3205
3206 u32 rm_val = cpu->Reg[inst_cream->Rm];
3207 const u32 rn_val = cpu->Reg[inst_cream->Rn];
3208
3209 if (inst_cream->m)
3210 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
3211
3212 const s16 rm_lo = (rm_val & 0xFFFF);
3213 const s16 rm_hi = ((rm_val >> 16) & 0xFFFF);
3214 const s16 rn_lo = (rn_val & 0xFFFF);
3215 const s16 rn_hi = ((rn_val >> 16) & 0xFFFF);
3216
3217 const u32 product1 = (rn_lo * rm_lo);
3218 const u32 product2 = (rn_hi * rm_hi);
3219
3220 // SMUAD and SMLAD
3221 if (BIT(op2, 1) == 0) {
3222 u32 rd_val = (product1 + product2);
3223
3224 if (inst_cream->Ra != 15) {
3225 rd_val += cpu->Reg[inst_cream->Ra];
3226
3227 if (ARMul_AddOverflowQ(product1 + product2, cpu->Reg[inst_cream->Ra]))
3228 cpu->Cpsr |= (1 << 27);
3229 }
3230
3231 RD = rd_val;
3232
3233 if (ARMul_AddOverflowQ(product1, product2))
3234 cpu->Cpsr |= (1 << 27);
3235 }
3236 // SMUSD and SMLSD
3237 else {
3238 u32 rd_val = (product1 - product2);
3239
3240 if (inst_cream->Ra != 15) {
3241 rd_val += cpu->Reg[inst_cream->Ra];
3242
3243 if (ARMul_AddOverflowQ(product1 - product2, cpu->Reg[inst_cream->Ra]))
3244 cpu->Cpsr |= (1 << 27);
3245 }
3246
3247 RD = rd_val;
3248 }
3249 }
3250
3251 cpu->Reg[15] += cpu->GetInstructionSize();
3252 INC_PC(sizeof(smlad_inst));
3253 FETCH_INST;
3254 GOTO_NEXT_INST;
3255}
3256
3257SMLAL_INST : {
3258 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3259 umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
3260 long long int rm = RM;
3261 long long int rs = RS;
3262 if (BIT(rm, 31)) {
3263 rm |= 0xffffffff00000000LL;
3264 }
3265 if (BIT(rs, 31)) {
3266 rs |= 0xffffffff00000000LL;
3267 }
3268 long long int rst = rm * rs;
3269 long long int rdhi32 = RDHI;
3270 long long int hilo = (rdhi32 << 32) + RDLO;
3271 rst += hilo;
3272 RDLO = BITS(rst, 0, 31);
3273 RDHI = BITS(rst, 32, 63);
3274 if (inst_cream->S) {
3275 cpu->NFlag = BIT(RDHI, 31);
3276 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
3277 }
3278 }
3279 cpu->Reg[15] += cpu->GetInstructionSize();
3280 INC_PC(sizeof(umlal_inst));
3281 FETCH_INST;
3282 GOTO_NEXT_INST;
3283}
3284
3285SMLALXY_INST : {
3286 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3287 smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component;
3288
3289 u64 operand1 = RN;
3290 u64 operand2 = RM;
3291
3292 if (inst_cream->x != 0)
3293 operand1 >>= 16;
3294 if (inst_cream->y != 0)
3295 operand2 >>= 16;
3296 operand1 &= 0xFFFF;
3297 if (operand1 & 0x8000)
3298 operand1 -= 65536;
3299 operand2 &= 0xFFFF;
3300 if (operand2 & 0x8000)
3301 operand2 -= 65536;
3302
3303 u64 dest = ((u64)RDHI << 32 | RDLO) + (operand1 * operand2);
3304 RDLO = (dest & 0xFFFFFFFF);
3305 RDHI = ((dest >> 32) & 0xFFFFFFFF);
3306 }
3307
3308 cpu->Reg[15] += cpu->GetInstructionSize();
3309 INC_PC(sizeof(smlalxy_inst));
3310 FETCH_INST;
3311 GOTO_NEXT_INST;
3312}
3313
3314SMLAW_INST : {
3315 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3316 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3317
3318 const u32 rm_val = RM;
3319 const u32 rn_val = RN;
3320 const u32 ra_val = cpu->Reg[inst_cream->Ra];
3321 const bool high = (inst_cream->m == 1);
3322
3323 const s16 operand2 = (high) ? ((rm_val >> 16) & 0xFFFF) : (rm_val & 0xFFFF);
3324 const s64 result = (s64)(s32)rn_val * (s64)(s32)operand2 + ((s64)(s32)ra_val << 16);
3325
3326 RD = BITS(result, 16, 47);
3327
3328 if ((result >> 16) != (s32)RD)
3329 cpu->Cpsr |= (1 << 27);
3330 }
3331
3332 cpu->Reg[15] += cpu->GetInstructionSize();
3333 INC_PC(sizeof(smlad_inst));
3334 FETCH_INST;
3335 GOTO_NEXT_INST;
3336}
3337
3338SMLALD_INST:
3339SMLSLD_INST : {
3340 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3341 smlald_inst* const inst_cream = (smlald_inst*)inst_base->component;
3342
3343 const bool do_swap = (inst_cream->swap == 1);
3344 const u32 rdlo_val = RDLO;
3345 const u32 rdhi_val = RDHI;
3346 const u32 rn_val = RN;
3347 u32 rm_val = RM;
3348
3349 if (do_swap)
3350 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
3351
3352 const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF);
3353 const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF);
3354 s64 result;
3355
3356 // SMLALD
3357 if (BIT(inst_cream->op2, 1) == 0) {
3358 result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
3359 }
3360 // SMLSLD
3361 else {
3362 result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
3363 }
3364
3365 RDLO = (result & 0xFFFFFFFF);
3366 RDHI = ((result >> 32) & 0xFFFFFFFF);
3367 }
3368
3369 cpu->Reg[15] += cpu->GetInstructionSize();
3370 INC_PC(sizeof(smlald_inst));
3371 FETCH_INST;
3372 GOTO_NEXT_INST;
3373}
3374
3375SMMLA_INST:
3376SMMLS_INST:
3377SMMUL_INST : {
3378 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3379 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3380
3381 const u32 rm_val = RM;
3382 const u32 rn_val = RN;
3383 const bool do_round = (inst_cream->m == 1);
3384
3385 // Assume SMMUL by default.
3386 s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val;
3387
3388 if (inst_cream->Ra != 15) {
3389 const u32 ra_val = cpu->Reg[inst_cream->Ra];
3390
3391 // SMMLA, otherwise SMMLS
3392 if (BIT(inst_cream->op2, 1) == 0)
3393 result += ((s64)ra_val << 32);
3394 else
3395 result = ((s64)ra_val << 32) - result;
3396 }
3397
3398 if (do_round)
3399 result += 0x80000000;
3400
3401 RD = ((result >> 32) & 0xFFFFFFFF);
3402 }
3403
3404 cpu->Reg[15] += cpu->GetInstructionSize();
3405 INC_PC(sizeof(smlad_inst));
3406 FETCH_INST;
3407 GOTO_NEXT_INST;
3408}
3409
3410SMUL_INST : {
3411 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3412 smul_inst* inst_cream = (smul_inst*)inst_base->component;
3413 u32 operand1, operand2;
3414 if (inst_cream->x == 0)
3415 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
3416 else
3417 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
3418
3419 if (inst_cream->y == 0)
3420 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15);
3421 else
3422 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
3423 RD = operand1 * operand2;
3424 }
3425 cpu->Reg[15] += cpu->GetInstructionSize();
3426 INC_PC(sizeof(smul_inst));
3427 FETCH_INST;
3428 GOTO_NEXT_INST;
3429}
3430SMULL_INST : {
3431 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3432 umull_inst* inst_cream = (umull_inst*)inst_base->component;
3433 s64 rm = RM;
3434 s64 rs = RS;
3435 if (BIT(rm, 31)) {
3436 rm |= 0xffffffff00000000LL;
3437 }
3438 if (BIT(rs, 31)) {
3439 rs |= 0xffffffff00000000LL;
3440 }
3441 s64 rst = rm * rs;
3442 RDHI = BITS(rst, 32, 63);
3443 RDLO = BITS(rst, 0, 31);
3444
3445 if (inst_cream->S) {
3446 cpu->NFlag = BIT(RDHI, 31);
3447 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
3448 }
3449 }
3450 cpu->Reg[15] += cpu->GetInstructionSize();
3451 INC_PC(sizeof(umull_inst));
3452 FETCH_INST;
3453 GOTO_NEXT_INST;
3454}
3455
3456SMULW_INST : {
3457 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3458 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3459
3460 s16 rm = (inst_cream->m == 1) ? ((RM >> 16) & 0xFFFF) : (RM & 0xFFFF);
3461
3462 s64 result = (s64)rm * (s64)(s32)RN;
3463 RD = BITS(result, 16, 47);
3464 }
3465 cpu->Reg[15] += cpu->GetInstructionSize();
3466 INC_PC(sizeof(smlad_inst));
3467 FETCH_INST;
3468 GOTO_NEXT_INST;
3469}
3470
3471SRS_INST : {
3472 // SRS is unconditional
3473 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
3474
3475 u32 address = 0;
3476 inst_cream->get_addr(cpu, inst_cream->inst, address);
3477
3478 cpu->WriteMemory32(address + 0, cpu->Reg[14]);
3479 cpu->WriteMemory32(address + 4, cpu->Spsr_copy);
3480
3481 cpu->Reg[15] += cpu->GetInstructionSize();
3482 INC_PC(sizeof(ldst_inst));
3483 FETCH_INST;
3484 GOTO_NEXT_INST;
3485}
3486
3487SSAT_INST : {
3488 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3489 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
3490
3491 u8 shift_type = inst_cream->shift_type;
3492 u8 shift_amount = inst_cream->imm5;
3493 u32 rn_val = RN;
3494
3495 // 32-bit ASR is encoded as an amount of 0.
3496 if (shift_type == 1 && shift_amount == 0)
3497 shift_amount = 31;
3498
3499 if (shift_type == 0)
3500 rn_val <<= shift_amount;
3501 else if (shift_type == 1)
3502 rn_val = ((s32)rn_val >> shift_amount);
3503
3504 bool saturated = false;
3505 rn_val = ARMul_SignedSatQ(rn_val, inst_cream->sat_imm, &saturated);
3506
3507 if (saturated)
3508 cpu->Cpsr |= (1 << 27);
3509
3510 RD = rn_val;
3511 }
3512
3513 cpu->Reg[15] += cpu->GetInstructionSize();
3514 INC_PC(sizeof(ssat_inst));
3515 FETCH_INST;
3516 GOTO_NEXT_INST;
3517}
3518
3519SSAT16_INST : {
3520 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3521 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
3522 const u8 saturate_to = inst_cream->sat_imm;
3523
3524 bool sat1 = false;
3525 bool sat2 = false;
3526
3527 RD = (ARMul_SignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) |
3528 ARMul_SignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16;
3529
3530 if (sat1 || sat2)
3531 cpu->Cpsr |= (1 << 27);
3532 }
3533
3534 cpu->Reg[15] += cpu->GetInstructionSize();
3535 INC_PC(sizeof(ssat_inst));
3536 FETCH_INST;
3537 GOTO_NEXT_INST;
3538}
3539
3540STC_INST : {
3541 // Instruction not implemented
3542 // LOG_CRITICAL(Core_ARM, "unimplemented instruction");
3543 cpu->Reg[15] += cpu->GetInstructionSize();
3544 INC_PC(sizeof(stc_inst));
3545 FETCH_INST;
3546 GOTO_NEXT_INST;
3547}
3548STM_INST : {
3549 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3550 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3551 unsigned int inst = inst_cream->inst;
3552
3553 unsigned int Rn = BITS(inst, 16, 19);
3554 unsigned int old_RN = cpu->Reg[Rn];
3555
3556 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3557 if (BIT(inst_cream->inst, 22) == 1) {
3558 for (int i = 0; i < 13; i++) {
3559 if (BIT(inst_cream->inst, i)) {
3560 cpu->WriteMemory32(addr, cpu->Reg[i]);
3561 addr += 4;
3562 }
3563 }
3564 if (BIT(inst_cream->inst, 13)) {
3565 if (cpu->Mode == USER32MODE)
3566 cpu->WriteMemory32(addr, cpu->Reg[13]);
3567 else
3568 cpu->WriteMemory32(addr, cpu->Reg_usr[0]);
3569
3570 addr += 4;
3571 }
3572 if (BIT(inst_cream->inst, 14)) {
3573 if (cpu->Mode == USER32MODE)
3574 cpu->WriteMemory32(addr, cpu->Reg[14]);
3575 else
3576 cpu->WriteMemory32(addr, cpu->Reg_usr[1]);
3577
3578 addr += 4;
3579 }
3580 if (BIT(inst_cream->inst, 15)) {
3581 cpu->WriteMemory32(addr, cpu->Reg[15] + 8);
3582 }
3583 } else {
3584 for (int i = 0; i < 15; i++) {
3585 if (BIT(inst_cream->inst, i)) {
3586 if (i == Rn)
3587 cpu->WriteMemory32(addr, old_RN);
3588 else
3589 cpu->WriteMemory32(addr, cpu->Reg[i]);
3590
3591 addr += 4;
3592 }
3593 }
3594
3595 // Check PC reg
3596 if (BIT(inst_cream->inst, 15)) {
3597 cpu->WriteMemory32(addr, cpu->Reg[15] + 8);
3598 }
3599 }
3600 }
3601 cpu->Reg[15] += cpu->GetInstructionSize();
3602 INC_PC(sizeof(ldst_inst));
3603 FETCH_INST;
3604 GOTO_NEXT_INST;
3605}
3606SXTB_INST : {
3607 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3608 sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component;
3609
3610 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate);
3611 if (BIT(operand2, 7)) {
3612 operand2 |= 0xffffff00;
3613 } else {
3614 operand2 &= 0xff;
3615 }
3616 RD = operand2;
3617 }
3618 cpu->Reg[15] += cpu->GetInstructionSize();
3619 INC_PC(sizeof(sxtb_inst));
3620 FETCH_INST;
3621 GOTO_NEXT_INST;
3622}
3623STR_INST : {
3624 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3625 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3626 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3627
3628 unsigned int reg = BITS(inst_cream->inst, 12, 15);
3629 unsigned int value = cpu->Reg[reg];
3630
3631 if (reg == 15)
3632 value += 2 * cpu->GetInstructionSize();
3633
3634 cpu->WriteMemory32(addr, value);
3635 }
3636 cpu->Reg[15] += cpu->GetInstructionSize();
3637 INC_PC(sizeof(ldst_inst));
3638 FETCH_INST;
3639 GOTO_NEXT_INST;
3640}
3641UXTB_INST : {
3642 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3643 uxtb_inst* inst_cream = (uxtb_inst*)inst_base->component;
3644 RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
3645 }
3646 cpu->Reg[15] += cpu->GetInstructionSize();
3647 INC_PC(sizeof(uxtb_inst));
3648 FETCH_INST;
3649 GOTO_NEXT_INST;
3650}
3651UXTAB_INST : {
3652 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3653 uxtab_inst* inst_cream = (uxtab_inst*)inst_base->component;
3654
3655 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
3656 RD = RN + operand2;
3657 }
3658 cpu->Reg[15] += cpu->GetInstructionSize();
3659 INC_PC(sizeof(uxtab_inst));
3660 FETCH_INST;
3661 GOTO_NEXT_INST;
3662}
3663STRB_INST : {
3664 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3665 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3666 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3667 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
3668 cpu->WriteMemory8(addr, value);
3669 }
3670 cpu->Reg[15] += cpu->GetInstructionSize();
3671 INC_PC(sizeof(ldst_inst));
3672 FETCH_INST;
3673 GOTO_NEXT_INST;
3674}
3675STRBT_INST : {
3676 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3677 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3678 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3679
3680 const u32 previous_mode = cpu->Mode;
3681 const u32 value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
3682
3683 cpu->ChangePrivilegeMode(USER32MODE);
3684 cpu->WriteMemory8(addr, value);
3685 cpu->ChangePrivilegeMode(previous_mode);
3686 }
3687 cpu->Reg[15] += cpu->GetInstructionSize();
3688 INC_PC(sizeof(ldst_inst));
3689 FETCH_INST;
3690 GOTO_NEXT_INST;
3691}
3692STRD_INST : {
3693 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3694 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3695 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3696
3697 // The 3DS doesn't have the Large Physical Access Extension (LPAE)
3698 // so STRD wouldn't store these as a single write.
3699 cpu->WriteMemory32(addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]);
3700 cpu->WriteMemory32(addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]);
3701 }
3702 cpu->Reg[15] += cpu->GetInstructionSize();
3703 INC_PC(sizeof(ldst_inst));
3704 FETCH_INST;
3705 GOTO_NEXT_INST;
3706}
3707STREX_INST : {
3708 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3709 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3710 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3711
3712 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3713 cpu->UnsetExclusiveMemoryAddress();
3714 cpu->WriteMemory32(write_addr, RM);
3715 RD = 0;
3716 } else {
3717 // Failed to write due to mutex access
3718 RD = 1;
3719 }
3720 }
3721 cpu->Reg[15] += cpu->GetInstructionSize();
3722 INC_PC(sizeof(generic_arm_inst));
3723 FETCH_INST;
3724 GOTO_NEXT_INST;
3725}
3726STREXB_INST : {
3727 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3728 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3729 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3730
3731 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3732 cpu->UnsetExclusiveMemoryAddress();
3733 cpu->WriteMemory8(write_addr, cpu->Reg[inst_cream->Rm]);
3734 RD = 0;
3735 } else {
3736 // Failed to write due to mutex access
3737 RD = 1;
3738 }
3739 }
3740 cpu->Reg[15] += cpu->GetInstructionSize();
3741 INC_PC(sizeof(generic_arm_inst));
3742 FETCH_INST;
3743 GOTO_NEXT_INST;
3744}
3745STREXD_INST : {
3746 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3747 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3748 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3749
3750 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3751 cpu->UnsetExclusiveMemoryAddress();
3752
3753 const u32 rt = cpu->Reg[inst_cream->Rm + 0];
3754 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1];
3755 u64 value;
3756
3757 if (cpu->InBigEndianMode())
3758 value = (((u64)rt << 32) | rt2);
3759 else
3760 value = (((u64)rt2 << 32) | rt);
3761
3762 cpu->WriteMemory64(write_addr, value);
3763 RD = 0;
3764 } else {
3765 // Failed to write due to mutex access
3766 RD = 1;
3767 }
3768 }
3769 cpu->Reg[15] += cpu->GetInstructionSize();
3770 INC_PC(sizeof(generic_arm_inst));
3771 FETCH_INST;
3772 GOTO_NEXT_INST;
3773}
3774STREXH_INST : {
3775 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3776 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3777 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3778
3779 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3780 cpu->UnsetExclusiveMemoryAddress();
3781 cpu->WriteMemory16(write_addr, RM);
3782 RD = 0;
3783 } else {
3784 // Failed to write due to mutex access
3785 RD = 1;
3786 }
3787 }
3788 cpu->Reg[15] += cpu->GetInstructionSize();
3789 INC_PC(sizeof(generic_arm_inst));
3790 FETCH_INST;
3791 GOTO_NEXT_INST;
3792}
3793STRH_INST : {
3794 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3795 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3796 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3797
3798 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff;
3799 cpu->WriteMemory16(addr, value);
3800 }
3801 cpu->Reg[15] += cpu->GetInstructionSize();
3802 INC_PC(sizeof(ldst_inst));
3803 FETCH_INST;
3804 GOTO_NEXT_INST;
3805}
3806STRT_INST : {
3807 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3808 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3809 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3810
3811 const u32 previous_mode = cpu->Mode;
3812 const u32 rt_index = BITS(inst_cream->inst, 12, 15);
3813
3814 u32 value = cpu->Reg[rt_index];
3815 if (rt_index == 15)
3816 value += 2 * cpu->GetInstructionSize();
3817
3818 cpu->ChangePrivilegeMode(USER32MODE);
3819 cpu->WriteMemory32(addr, value);
3820 cpu->ChangePrivilegeMode(previous_mode);
3821 }
3822 cpu->Reg[15] += cpu->GetInstructionSize();
3823 INC_PC(sizeof(ldst_inst));
3824 FETCH_INST;
3825 GOTO_NEXT_INST;
3826}
3827SUB_INST : {
3828 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3829 sub_inst* const inst_cream = (sub_inst*)inst_base->component;
3830
3831 u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn);
3832
3833 bool carry;
3834 bool overflow;
3835 RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
3836
3837 if (inst_cream->S && (inst_cream->Rd == 15)) {
3838 if (CurrentModeHasSPSR) {
3839 cpu->Cpsr = cpu->Spsr_copy;
3840 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
3841 LOAD_NZCVT;
3842 }
3843 } else if (inst_cream->S) {
3844 UPDATE_NFLAG(RD);
3845 UPDATE_ZFLAG(RD);
3846 cpu->CFlag = carry;
3847 cpu->VFlag = overflow;
3848 }
3849 if (inst_cream->Rd == 15) {
3850 INC_PC(sizeof(sub_inst));
3851 goto DISPATCH;
3852 }
3853 }
3854 cpu->Reg[15] += cpu->GetInstructionSize();
3855 INC_PC(sizeof(sub_inst));
3856 FETCH_INST;
3857 GOTO_NEXT_INST;
3858}
3859SWI_INST : {
3860 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3861 swi_inst* const inst_cream = (swi_inst*)inst_base->component;
3862 SVC::CallSVC(inst_cream->num & 0xFFFF);
3863 }
3864
3865 cpu->Reg[15] += cpu->GetInstructionSize();
3866 INC_PC(sizeof(swi_inst));
3867 FETCH_INST;
3868 GOTO_NEXT_INST;
3869}
3870SWP_INST : {
3871 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3872 swp_inst* inst_cream = (swp_inst*)inst_base->component;
3873
3874 addr = RN;
3875 unsigned int value = cpu->ReadMemory32(addr);
3876 cpu->WriteMemory32(addr, RM);
3877
3878 RD = value;
3879 }
3880 cpu->Reg[15] += cpu->GetInstructionSize();
3881 INC_PC(sizeof(swp_inst));
3882 FETCH_INST;
3883 GOTO_NEXT_INST;
3884}
3885SWPB_INST : {
3886 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3887 swp_inst* inst_cream = (swp_inst*)inst_base->component;
3888 addr = RN;
3889 unsigned int value = cpu->ReadMemory8(addr);
3890 cpu->WriteMemory8(addr, (RM & 0xFF));
3891 RD = value;
3892 }
3893 cpu->Reg[15] += cpu->GetInstructionSize();
3894 INC_PC(sizeof(swp_inst));
3895 FETCH_INST;
3896 GOTO_NEXT_INST;
3897}
3898SXTAB_INST : {
3899 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3900 sxtab_inst* inst_cream = (sxtab_inst*)inst_base->component;
3901
3902 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
3903
3904 // Sign extend for byte
3905 operand2 = (0x80 & operand2) ? (0xFFFFFF00 | operand2) : operand2;
3906 RD = RN + operand2;
3907 }
3908 cpu->Reg[15] += cpu->GetInstructionSize();
3909 INC_PC(sizeof(uxtab_inst));
3910 FETCH_INST;
3911 GOTO_NEXT_INST;
3912}
3913
3914SXTAB16_INST:
3915SXTB16_INST : {
3916 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3917 sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component;
3918
3919 const u8 rotation = inst_cream->rotate * 8;
3920 u32 rm_val = RM;
3921 u32 rn_val = RN;
3922
3923 if (rotation)
3924 rm_val = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
3925
3926 // SXTB16
3927 if (inst_cream->Rn == 15) {
3928 u32 lo = (u32)(s8)rm_val;
3929 u32 hi = (u32)(s8)(rm_val >> 16);
3930 RD = (lo & 0xFFFF) | (hi << 16);
3931 }
3932 // SXTAB16
3933 else {
3934 u32 lo = rn_val + (u32)(s8)(rm_val & 0xFF);
3935 u32 hi = (rn_val >> 16) + (u32)(s8)((rm_val >> 16) & 0xFF);
3936 RD = (lo & 0xFFFF) | (hi << 16);
3937 }
3938 }
3939
3940 cpu->Reg[15] += cpu->GetInstructionSize();
3941 INC_PC(sizeof(sxtab_inst));
3942 FETCH_INST;
3943 GOTO_NEXT_INST;
3944}
3945
3946SXTAH_INST : {
3947 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3948 sxtah_inst* inst_cream = (sxtah_inst*)inst_base->component;
3949
3950 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
3951 // Sign extend for half
3952 operand2 = (0x8000 & operand2) ? (0xFFFF0000 | operand2) : operand2;
3953 RD = RN + operand2;
3954 }
3955 cpu->Reg[15] += cpu->GetInstructionSize();
3956 INC_PC(sizeof(sxtah_inst));
3957 FETCH_INST;
3958 GOTO_NEXT_INST;
3959}
3960
3961TEQ_INST : {
3962 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3963 teq_inst* const inst_cream = (teq_inst*)inst_base->component;
3964
3965 u32 lop = RN;
3966 u32 rop = SHIFTER_OPERAND;
3967
3968 if (inst_cream->Rn == 15)
3969 lop += cpu->GetInstructionSize() * 2;
3970
3971 u32 result = lop ^ rop;
3972
3973 UPDATE_NFLAG(result);
3974 UPDATE_ZFLAG(result);
3975 UPDATE_CFLAG_WITH_SC;
3976 }
3977 cpu->Reg[15] += cpu->GetInstructionSize();
3978 INC_PC(sizeof(teq_inst));
3979 FETCH_INST;
3980 GOTO_NEXT_INST;
3981}
3982TST_INST : {
3983 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3984 tst_inst* const inst_cream = (tst_inst*)inst_base->component;
3985
3986 u32 lop = RN;
3987 u32 rop = SHIFTER_OPERAND;
3988
3989 if (inst_cream->Rn == 15)
3990 lop += cpu->GetInstructionSize() * 2;
3991
3992 u32 result = lop & rop;
3993
3994 UPDATE_NFLAG(result);
3995 UPDATE_ZFLAG(result);
3996 UPDATE_CFLAG_WITH_SC;
3997 }
3998 cpu->Reg[15] += cpu->GetInstructionSize();
3999 INC_PC(sizeof(tst_inst));
4000 FETCH_INST;
4001 GOTO_NEXT_INST;
4002}
4003
4004UADD8_INST:
4005UADD16_INST:
4006UADDSUBX_INST:
4007USUB8_INST:
4008USUB16_INST:
4009USUBADDX_INST : {
4010 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4011 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
4012
4013 const u8 op2 = inst_cream->op2;
4014 const u32 rm_val = RM;
4015 const u32 rn_val = RN;
4016
4017 s32 lo_result = 0;
4018 s32 hi_result = 0;
4019
4020 // UADD16
4021 if (op2 == 0x00) {
4022 lo_result = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
4023 hi_result = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
4024
4025 if (lo_result & 0xFFFF0000) {
4026 cpu->Cpsr |= (1 << 16);
4027 cpu->Cpsr |= (1 << 17);
4028 } else {
4029 cpu->Cpsr &= ~(1 << 16);
4030 cpu->Cpsr &= ~(1 << 17);
4031 }
4032
4033 if (hi_result & 0xFFFF0000) {
4034 cpu->Cpsr |= (1 << 18);
4035 cpu->Cpsr |= (1 << 19);
4036 } else {
4037 cpu->Cpsr &= ~(1 << 18);
4038 cpu->Cpsr &= ~(1 << 19);
4039 }
4040 }
4041 // UASX
4042 else if (op2 == 0x01) {
4043 lo_result = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4044 hi_result = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
4045
4046 if (lo_result >= 0) {
4047 cpu->Cpsr |= (1 << 16);
4048 cpu->Cpsr |= (1 << 17);
4049 } else {
4050 cpu->Cpsr &= ~(1 << 16);
4051 cpu->Cpsr &= ~(1 << 17);
4052 }
4053
4054 if (hi_result >= 0x10000) {
4055 cpu->Cpsr |= (1 << 18);
4056 cpu->Cpsr |= (1 << 19);
4057 } else {
4058 cpu->Cpsr &= ~(1 << 18);
4059 cpu->Cpsr &= ~(1 << 19);
4060 }
4061 }
4062 // USAX
4063 else if (op2 == 0x02) {
4064 lo_result = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
4065 hi_result = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
4066
4067 if (lo_result >= 0x10000) {
4068 cpu->Cpsr |= (1 << 16);
4069 cpu->Cpsr |= (1 << 17);
4070 } else {
4071 cpu->Cpsr &= ~(1 << 16);
4072 cpu->Cpsr &= ~(1 << 17);
4073 }
4074
4075 if (hi_result >= 0) {
4076 cpu->Cpsr |= (1 << 18);
4077 cpu->Cpsr |= (1 << 19);
4078 } else {
4079 cpu->Cpsr &= ~(1 << 18);
4080 cpu->Cpsr &= ~(1 << 19);
4081 }
4082 }
4083 // USUB16
4084 else if (op2 == 0x03) {
4085 lo_result = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
4086 hi_result = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4087
4088 if ((lo_result & 0xFFFF0000) == 0) {
4089 cpu->Cpsr |= (1 << 16);
4090 cpu->Cpsr |= (1 << 17);
4091 } else {
4092 cpu->Cpsr &= ~(1 << 16);
4093 cpu->Cpsr &= ~(1 << 17);
4094 }
4095
4096 if ((hi_result & 0xFFFF0000) == 0) {
4097 cpu->Cpsr |= (1 << 18);
4098 cpu->Cpsr |= (1 << 19);
4099 } else {
4100 cpu->Cpsr &= ~(1 << 18);
4101 cpu->Cpsr &= ~(1 << 19);
4102 }
4103 }
4104 // UADD8
4105 else if (op2 == 0x04) {
4106 s16 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
4107 s16 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
4108 s16 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
4109 s16 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
4110
4111 if (sum1 >= 0x100)
4112 cpu->Cpsr |= (1 << 16);
4113 else
4114 cpu->Cpsr &= ~(1 << 16);
4115
4116 if (sum2 >= 0x100)
4117 cpu->Cpsr |= (1 << 17);
4118 else
4119 cpu->Cpsr &= ~(1 << 17);
4120
4121 if (sum3 >= 0x100)
4122 cpu->Cpsr |= (1 << 18);
4123 else
4124 cpu->Cpsr &= ~(1 << 18);
4125
4126 if (sum4 >= 0x100)
4127 cpu->Cpsr |= (1 << 19);
4128 else
4129 cpu->Cpsr &= ~(1 << 19);
4130
4131 lo_result = ((sum1 & 0xFF) | (sum2 & 0xFF) << 8);
4132 hi_result = ((sum3 & 0xFF) | (sum4 & 0xFF) << 8);
4133 }
4134 // USUB8
4135 else if (op2 == 0x07) {
4136 s16 diff1 = (rn_val & 0xFF) - (rm_val & 0xFF);
4137 s16 diff2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
4138 s16 diff3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
4139 s16 diff4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
4140
4141 if (diff1 >= 0)
4142 cpu->Cpsr |= (1 << 16);
4143 else
4144 cpu->Cpsr &= ~(1 << 16);
4145
4146 if (diff2 >= 0)
4147 cpu->Cpsr |= (1 << 17);
4148 else
4149 cpu->Cpsr &= ~(1 << 17);
4150
4151 if (diff3 >= 0)
4152 cpu->Cpsr |= (1 << 18);
4153 else
4154 cpu->Cpsr &= ~(1 << 18);
4155
4156 if (diff4 >= 0)
4157 cpu->Cpsr |= (1 << 19);
4158 else
4159 cpu->Cpsr &= ~(1 << 19);
4160
4161 lo_result = (diff1 & 0xFF) | ((diff2 & 0xFF) << 8);
4162 hi_result = (diff3 & 0xFF) | ((diff4 & 0xFF) << 8);
4163 }
4164
4165 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
4166 }
4167
4168 cpu->Reg[15] += cpu->GetInstructionSize();
4169 INC_PC(sizeof(generic_arm_inst));
4170 FETCH_INST;
4171 GOTO_NEXT_INST;
4172}
4173
4174UHADD8_INST:
4175UHADD16_INST:
4176UHADDSUBX_INST:
4177UHSUBADDX_INST:
4178UHSUB8_INST:
4179UHSUB16_INST : {
4180 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4181 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
4182 const u32 rm_val = RM;
4183 const u32 rn_val = RN;
4184 const u8 op2 = inst_cream->op2;
4185
4186 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
4187 u32 lo_val = 0;
4188 u32 hi_val = 0;
4189
4190 // UHADD16
4191 if (op2 == 0x00) {
4192 lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
4193 hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
4194 }
4195 // UHASX
4196 else if (op2 == 0x01) {
4197 lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4198 hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
4199 }
4200 // UHSAX
4201 else if (op2 == 0x02) {
4202 lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
4203 hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
4204 }
4205 // UHSUB16
4206 else if (op2 == 0x03) {
4207 lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
4208 hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4209 }
4210
4211 lo_val >>= 1;
4212 hi_val >>= 1;
4213
4214 RD = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16);
4215 } else if (op2 == 0x04 || op2 == 0x07) {
4216 u32 sum1;
4217 u32 sum2;
4218 u32 sum3;
4219 u32 sum4;
4220
4221 // UHADD8
4222 if (op2 == 0x04) {
4223 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
4224 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
4225 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
4226 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
4227 }
4228 // UHSUB8
4229 else {
4230 sum1 = (rn_val & 0xFF) - (rm_val & 0xFF);
4231 sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
4232 sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
4233 sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
4234 }
4235
4236 sum1 >>= 1;
4237 sum2 >>= 1;
4238 sum3 >>= 1;
4239 sum4 >>= 1;
4240
4241 RD = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) |
4242 ((sum4 & 0xFF) << 24);
4243 }
4244 }
4245
4246 cpu->Reg[15] += cpu->GetInstructionSize();
4247 INC_PC(sizeof(generic_arm_inst));
4248 FETCH_INST;
4249 GOTO_NEXT_INST;
4250}
4251
4252UMAAL_INST : {
4253 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4254 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
4255 const u64 rm = RM;
4256 const u64 rn = RN;
4257 const u64 rd_lo = RDLO;
4258 const u64 rd_hi = RDHI;
4259 const u64 result = (rm * rn) + rd_lo + rd_hi;
4260
4261 RDLO = (result & 0xFFFFFFFF);
4262 RDHI = ((result >> 32) & 0xFFFFFFFF);
4263 }
4264 cpu->Reg[15] += cpu->GetInstructionSize();
4265 INC_PC(sizeof(umaal_inst));
4266 FETCH_INST;
4267 GOTO_NEXT_INST;
4268}
4269UMLAL_INST : {
4270 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4271 umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
4272 unsigned long long int rm = RM;
4273 unsigned long long int rs = RS;
4274 unsigned long long int rst = rm * rs;
4275 unsigned long long int add = ((unsigned long long)RDHI) << 32;
4276 add += RDLO;
4277 rst += add;
4278 RDLO = BITS(rst, 0, 31);
4279 RDHI = BITS(rst, 32, 63);
4280
4281 if (inst_cream->S) {
4282 cpu->NFlag = BIT(RDHI, 31);
4283 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
4284 }
4285 }
4286 cpu->Reg[15] += cpu->GetInstructionSize();
4287 INC_PC(sizeof(umlal_inst));
4288 FETCH_INST;
4289 GOTO_NEXT_INST;
4290}
4291UMULL_INST : {
4292 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4293 umull_inst* inst_cream = (umull_inst*)inst_base->component;
4294 unsigned long long int rm = RM;
4295 unsigned long long int rs = RS;
4296 unsigned long long int rst = rm * rs;
4297 RDHI = BITS(rst, 32, 63);
4298 RDLO = BITS(rst, 0, 31);
4299
4300 if (inst_cream->S) {
4301 cpu->NFlag = BIT(RDHI, 31);
4302 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
4303 }
4304 }
4305 cpu->Reg[15] += cpu->GetInstructionSize();
4306 INC_PC(sizeof(umull_inst));
4307 FETCH_INST;
4308 GOTO_NEXT_INST;
4309}
4310B_2_THUMB : {
4311 b_2_thumb* inst_cream = (b_2_thumb*)inst_base->component;
4312 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm;
4313 INC_PC(sizeof(b_2_thumb));
4314 goto DISPATCH;
4315}
4316B_COND_THUMB : {
4317 b_cond_thumb* inst_cream = (b_cond_thumb*)inst_base->component;
4318
4319 if (CondPassed(cpu, inst_cream->cond))
4320 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm;
4321 else
4322 cpu->Reg[15] += 2;
4323
4324 INC_PC(sizeof(b_cond_thumb));
4325 goto DISPATCH;
4326}
4327BL_1_THUMB : {
4328 bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component;
4329 cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm;
4330 cpu->Reg[15] += cpu->GetInstructionSize();
4331 INC_PC(sizeof(bl_1_thumb));
4332 FETCH_INST;
4333 GOTO_NEXT_INST;
4334}
4335BL_2_THUMB : {
4336 bl_2_thumb* inst_cream = (bl_2_thumb*)inst_base->component;
4337 int tmp = ((cpu->Reg[15] + 2) | 1);
4338 cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm);
4339 cpu->Reg[14] = tmp;
4340 INC_PC(sizeof(bl_2_thumb));
4341 goto DISPATCH;
4342}
4343BLX_1_THUMB : {
4344 // BLX 1 for armv5t and above
4345 u32 tmp = cpu->Reg[15];
4346 blx_1_thumb* inst_cream = (blx_1_thumb*)inst_base->component;
4347 cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm) & 0xFFFFFFFC;
4348 cpu->Reg[14] = ((tmp + 2) | 1);
4349 cpu->TFlag = 0;
4350 INC_PC(sizeof(blx_1_thumb));
4351 goto DISPATCH;
4352}
4353
4354UQADD8_INST:
4355UQADD16_INST:
4356UQADDSUBX_INST:
4357UQSUB8_INST:
4358UQSUB16_INST:
4359UQSUBADDX_INST : {
4360 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4361 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
4362
4363 const u8 op2 = inst_cream->op2;
4364 const u32 rm_val = RM;
4365 const u32 rn_val = RN;
4366
4367 u16 lo_val = 0;
4368 u16 hi_val = 0;
4369
4370 // UQADD16
4371 if (op2 == 0x00) {
4372 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF);
4373 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4374 }
4375 // UQASX
4376 else if (op2 == 0x01) {
4377 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4378 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
4379 }
4380 // UQSAX
4381 else if (op2 == 0x02) {
4382 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4383 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
4384 }
4385 // UQSUB16
4386 else if (op2 == 0x03) {
4387 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF);
4388 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4389 }
4390 // UQADD8
4391 else if (op2 == 0x04) {
4392 lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) |
4393 ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8;
4394 hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) |
4395 ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8;
4396 }
4397 // UQSUB8
4398 else {
4399 lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) |
4400 ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8;
4401 hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) |
4402 ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8;
4403 }
4404
4405 RD = ((lo_val & 0xFFFF) | hi_val << 16);
4406 }
4407
4408 cpu->Reg[15] += cpu->GetInstructionSize();
4409 INC_PC(sizeof(generic_arm_inst));
4410 FETCH_INST;
4411 GOTO_NEXT_INST;
4412}
4413
4414USAD8_INST:
4415USADA8_INST : {
4416 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4417 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4418
4419 const u8 ra_idx = inst_cream->Ra;
4420 const u32 rm_val = RM;
4421 const u32 rn_val = RN;
4422
4423 const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF);
4424 const u8 diff2 =
4425 ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF);
4426 const u8 diff3 =
4427 ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF);
4428 const u8 diff4 =
4429 ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF);
4430
4431 u32 finalDif = (diff1 + diff2 + diff3 + diff4);
4432
4433 // Op is USADA8 if true.
4434 if (ra_idx != 15)
4435 finalDif += cpu->Reg[ra_idx];
4436
4437 RD = finalDif;
4438 }
4439
4440 cpu->Reg[15] += cpu->GetInstructionSize();
4441 INC_PC(sizeof(generic_arm_inst));
4442 FETCH_INST;
4443 GOTO_NEXT_INST;
4444}
4445
4446USAT_INST : {
4447 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4448 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
4449
4450 u8 shift_type = inst_cream->shift_type;
4451 u8 shift_amount = inst_cream->imm5;
4452 u32 rn_val = RN;
4453
4454 // 32-bit ASR is encoded as an amount of 0.
4455 if (shift_type == 1 && shift_amount == 0)
4456 shift_amount = 31;
4457
4458 if (shift_type == 0)
4459 rn_val <<= shift_amount;
4460 else if (shift_type == 1)
4461 rn_val = ((s32)rn_val >> shift_amount);
4462
4463 bool saturated = false;
4464 rn_val = ARMul_UnsignedSatQ(rn_val, inst_cream->sat_imm, &saturated);
4465
4466 if (saturated)
4467 cpu->Cpsr |= (1 << 27);
4468
4469 RD = rn_val;
4470 }
4471
4472 cpu->Reg[15] += cpu->GetInstructionSize();
4473 INC_PC(sizeof(ssat_inst));
4474 FETCH_INST;
4475 GOTO_NEXT_INST;
4476}
4477
4478USAT16_INST : {
4479 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4480 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
4481 const u8 saturate_to = inst_cream->sat_imm;
4482
4483 bool sat1 = false;
4484 bool sat2 = false;
4485
4486 RD = (ARMul_UnsignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) |
4487 ARMul_UnsignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16;
4488
4489 if (sat1 || sat2)
4490 cpu->Cpsr |= (1 << 27);
4491 }
4492
4493 cpu->Reg[15] += cpu->GetInstructionSize();
4494 INC_PC(sizeof(ssat_inst));
4495 FETCH_INST;
4496 GOTO_NEXT_INST;
4497}
4498
4499UXTAB16_INST:
4500UXTB16_INST : {
4501 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4502 uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
4503
4504 const u8 rn_idx = inst_cream->Rn;
4505 const u32 rm_val = RM;
4506 const u32 rotation = inst_cream->rotate * 8;
4507 const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
4508
4509 // UXTB16, otherwise UXTAB16
4510 if (rn_idx == 15) {
4511 RD = rotated_rm & 0x00FF00FF;
4512 } else {
4513 const u32 rn_val = RN;
4514 const u8 lo_rotated = (rotated_rm & 0xFF);
4515 const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated;
4516 const u8 hi_rotated = (rotated_rm >> 16) & 0xFF;
4517 const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated;
4518
4519 RD = ((hi_result << 16) | (lo_result & 0xFFFF));
4520 }
4521 }
4522
4523 cpu->Reg[15] += cpu->GetInstructionSize();
4524 INC_PC(sizeof(uxtab_inst));
4525 FETCH_INST;
4526 GOTO_NEXT_INST;
4527}
4528
4529WFE_INST : {
4530 // Stubbed, as WFE is a hint instruction.
4531 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4532 LOG_TRACE(Core_ARM, "WFE executed.");
4533 }
4534
4535 cpu->Reg[15] += cpu->GetInstructionSize();
4536 INC_PC_STUB;
4537 FETCH_INST;
4538 GOTO_NEXT_INST;
4539}
4540
4541WFI_INST : {
4542 // Stubbed, as WFI is a hint instruction.
4543 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4544 LOG_TRACE(Core_ARM, "WFI executed.");
4545 }
4546
4547 cpu->Reg[15] += cpu->GetInstructionSize();
4548 INC_PC_STUB;
4549 FETCH_INST;
4550 GOTO_NEXT_INST;
4551}
4552
4553YIELD_INST : {
4554 // Stubbed, as YIELD is a hint instruction.
4555 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4556 LOG_TRACE(Core_ARM, "YIELD executed.");
4557 }
4558
4559 cpu->Reg[15] += cpu->GetInstructionSize();
4560 INC_PC_STUB;
4561 FETCH_INST;
4562 GOTO_NEXT_INST;
4563}
4564
4565#define VFP_INTERPRETER_IMPL
4566#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
4567#undef VFP_INTERPRETER_IMPL
4568
4569END : {
4570 SAVE_NZCVT;
4571 cpu->NumInstrsToExecute = 0;
4572 return num_instrs;
4573}
4574INIT_INST_LENGTH : {
4575 cpu->NumInstrsToExecute = 0;
4576 return num_instrs;
4577}
4578}
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.h b/src/core/arm/dyncom/arm_dyncom_interpreter.h
deleted file mode 100644
index 7a46dcc94..000000000
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.h
+++ /dev/null
@@ -1,9 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7struct ARMul_State;
8
9unsigned InterpreterMainLoop(ARMul_State* state);
diff --git a/src/core/arm/dyncom/arm_dyncom_run.h b/src/core/arm/dyncom/arm_dyncom_run.h
deleted file mode 100644
index 8eb694fee..000000000
--- a/src/core/arm/dyncom/arm_dyncom_run.h
+++ /dev/null
@@ -1,48 +0,0 @@
1/* Copyright (C)
2* 2011 - Michael.Kang blackfin.kang@gmail.com
3* This program is free software; you can redistribute it and/or
4* modify it under the terms of the GNU General Public License
5* as published by the Free Software Foundation; either version 2
6* of the License, or (at your option) any later version.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program; if not, write to the Free Software
15* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16*
17*/
18
19#pragma once
20
21#include "core/arm/skyeye_common/armstate.h"
22
23/**
24 * Checks if the PC is being read, and if so, word-aligns it.
25 * Used with address calculations.
26 *
27 * @param cpu The ARM CPU state instance.
28 * @param Rn The register being read.
29 *
30 * @return If the PC is being read, then the word-aligned PC value is returned.
31 * If the PC is not being read, then the value stored in the register is returned.
32 */
33inline u32 CHECK_READ_REG15_WA(const ARMul_State* cpu, int Rn) {
34 return (Rn == 15) ? ((cpu->Reg[15] & ~0x3) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn];
35}
36
37/**
38 * Reads the PC. Used for data processing operations that use the PC.
39 *
40 * @param cpu The ARM CPU state instance.
41 * @param Rn The register being read.
42 *
43 * @return If the PC is being read, then the incremented PC value is returned.
44 * If the PC is not being read, then the values stored in the register is returned.
45 */
46inline u32 CHECK_READ_REG15(const ARMul_State* cpu, int Rn) {
47 return (Rn == 15) ? ((cpu->Reg[15] & ~0x1) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn];
48}
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
deleted file mode 100644
index 2a3dd0f53..000000000
--- a/src/core/arm/dyncom/arm_dyncom_thumb.cpp
+++ /dev/null
@@ -1,390 +0,0 @@
1// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cstddef>
6
7// We can provide simple Thumb simulation by decoding the Thumb instruction into its corresponding
8// ARM instruction, and using the existing ARM simulator.
9
10#include "core/arm/dyncom/arm_dyncom_thumb.h"
11#include "core/arm/skyeye_common/armsupp.h"
12
13// Decode a 16bit Thumb instruction. The instruction is in the low 16-bits of the tinstr field,
14// with the following Thumb instruction held in the high 16-bits. Passing in two Thumb instructions
15// allows easier simulation of the special dual BL instruction.
16
17ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
18 ThumbDecodeStatus valid = ThumbDecodeStatus::UNINITIALIZED;
19 u32 tinstr = GetThumbInstruction(instr, addr);
20
21 *ainstr = 0xDEADC0DE; // Debugging to catch non updates
22
23 switch ((tinstr & 0xF800) >> 11) {
24 case 0: // LSL
25 case 1: // LSR
26 case 2: // ASR
27 *ainstr = 0xE1B00000 // base opcode
28 | ((tinstr & 0x1800) >> (11 - 5)) // shift type
29 | ((tinstr & 0x07C0) << (7 - 6)) // imm5
30 | ((tinstr & 0x0038) >> 3) // Rs
31 | ((tinstr & 0x0007) << 12); // Rd
32 break;
33
34 case 3: // ADD/SUB
35 {
36 static const u32 subset[4] = {
37 0xE0900000, // ADDS Rd,Rs,Rn
38 0xE0500000, // SUBS Rd,Rs,Rn
39 0xE2900000, // ADDS Rd,Rs,#imm3
40 0xE2500000 // SUBS Rd,Rs,#imm3
41 };
42 // It is quicker indexing into a table, than performing switch or conditionals:
43 *ainstr = subset[(tinstr & 0x0600) >> 9] // base opcode
44 | ((tinstr & 0x01C0) >> 6) // Rn or imm3
45 | ((tinstr & 0x0038) << (16 - 3)) // Rs
46 | ((tinstr & 0x0007) << (12 - 0)); // Rd
47 } break;
48
49 case 4: // MOV
50 case 5: // CMP
51 case 6: // ADD
52 case 7: // SUB
53 {
54 static const u32 subset[4] = {
55 0xE3B00000, // MOVS Rd,#imm8
56 0xE3500000, // CMP Rd,#imm8
57 0xE2900000, // ADDS Rd,Rd,#imm8
58 0xE2500000, // SUBS Rd,Rd,#imm8
59 };
60
61 *ainstr = subset[(tinstr & 0x1800) >> 11] // base opcode
62 | ((tinstr & 0x00FF) >> 0) // imm8
63 | ((tinstr & 0x0700) << (16 - 8)) // Rn
64 | ((tinstr & 0x0700) << (12 - 8)); // Rd
65 } break;
66
67 case 8: // Arithmetic and high register transfers
68
69 // TODO: Since the subsets for both Format 4 and Format 5 instructions are made up of
70 // different ARM encodings, we could save the following conditional, and just have one
71 // large subset
72
73 if ((tinstr & (1 << 10)) == 0) {
74 enum otype { t_norm, t_shift, t_neg, t_mul };
75
76 static const struct {
77 u32 opcode;
78 otype type;
79 } subset[16] = {
80 {0xE0100000, t_norm}, // ANDS Rd,Rd,Rs
81 {0xE0300000, t_norm}, // EORS Rd,Rd,Rs
82 {0xE1B00010, t_shift}, // MOVS Rd,Rd,LSL Rs
83 {0xE1B00030, t_shift}, // MOVS Rd,Rd,LSR Rs
84 {0xE1B00050, t_shift}, // MOVS Rd,Rd,ASR Rs
85 {0xE0B00000, t_norm}, // ADCS Rd,Rd,Rs
86 {0xE0D00000, t_norm}, // SBCS Rd,Rd,Rs
87 {0xE1B00070, t_shift}, // MOVS Rd,Rd,ROR Rs
88 {0xE1100000, t_norm}, // TST Rd,Rs
89 {0xE2700000, t_neg}, // RSBS Rd,Rs,#0
90 {0xE1500000, t_norm}, // CMP Rd,Rs
91 {0xE1700000, t_norm}, // CMN Rd,Rs
92 {0xE1900000, t_norm}, // ORRS Rd,Rd,Rs
93 {0xE0100090, t_mul}, // MULS Rd,Rd,Rs
94 {0xE1D00000, t_norm}, // BICS Rd,Rd,Rs
95 {0xE1F00000, t_norm} // MVNS Rd,Rs
96 };
97
98 *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode; // base
99
100 switch (subset[(tinstr & 0x03C0) >> 6].type) {
101 case t_norm:
102 *ainstr |= ((tinstr & 0x0007) << 16) // Rn
103 | ((tinstr & 0x0007) << 12) // Rd
104 | ((tinstr & 0x0038) >> 3); // Rs
105 break;
106 case t_shift:
107 *ainstr |= ((tinstr & 0x0007) << 12) // Rd
108 | ((tinstr & 0x0007) >> 0) // Rm
109 | ((tinstr & 0x0038) << (8 - 3)); // Rs
110 break;
111 case t_neg:
112 *ainstr |= ((tinstr & 0x0007) << 12) // Rd
113 | ((tinstr & 0x0038) << (16 - 3)); // Rn
114 break;
115 case t_mul:
116 *ainstr |= ((tinstr & 0x0007) << 16) // Rd
117 | ((tinstr & 0x0007) << 8) // Rs
118 | ((tinstr & 0x0038) >> 3); // Rm
119 break;
120 }
121 } else {
122 u32 Rd = ((tinstr & 0x0007) >> 0);
123 u32 Rs = ((tinstr & 0x0078) >> 3);
124
125 if (tinstr & (1 << 7))
126 Rd += 8;
127
128 switch ((tinstr & 0x03C0) >> 6) {
129 case 0x0: // ADD Rd,Rd,Rs
130 case 0x1: // ADD Rd,Rd,Hs
131 case 0x2: // ADD Hd,Hd,Rs
132 case 0x3: // ADD Hd,Hd,Hs
133 *ainstr = 0xE0800000 // base
134 | (Rd << 16) // Rn
135 | (Rd << 12) // Rd
136 | (Rs << 0); // Rm
137 break;
138 case 0x4: // CMP Rd,Rs
139 case 0x5: // CMP Rd,Hs
140 case 0x6: // CMP Hd,Rs
141 case 0x7: // CMP Hd,Hs
142 *ainstr = 0xE1500000 // base
143 | (Rd << 16) // Rn
144 | (Rs << 0); // Rm
145 break;
146 case 0x8: // MOV Rd,Rs
147 case 0x9: // MOV Rd,Hs
148 case 0xA: // MOV Hd,Rs
149 case 0xB: // MOV Hd,Hs
150 *ainstr = 0xE1A00000 // base
151 | (Rd << 12) // Rd
152 | (Rs << 0); // Rm
153 break;
154 case 0xC: // BX Rs
155 case 0xD: // BX Hs
156 *ainstr = 0xE12FFF10 // base
157 | ((tinstr & 0x0078) >> 3); // Rd
158 break;
159 case 0xE: // BLX
160 case 0xF: // BLX
161 *ainstr = 0xE1200030 // base
162 | (Rs << 0); // Rm
163 break;
164 }
165 }
166 break;
167
168 case 9: // LDR Rd,[PC,#imm8]
169 *ainstr = 0xE59F0000 // base
170 | ((tinstr & 0x0700) << (12 - 8)) // Rd
171 | ((tinstr & 0x00FF) << (2 - 0)); // off8
172 break;
173
174 case 10:
175 case 11: {
176 static const u32 subset[8] = {
177 0xE7800000, // STR Rd,[Rb,Ro]
178 0xE18000B0, // STRH Rd,[Rb,Ro]
179 0xE7C00000, // STRB Rd,[Rb,Ro]
180 0xE19000D0, // LDRSB Rd,[Rb,Ro]
181 0xE7900000, // LDR Rd,[Rb,Ro]
182 0xE19000B0, // LDRH Rd,[Rb,Ro]
183 0xE7D00000, // LDRB Rd,[Rb,Ro]
184 0xE19000F0 // LDRSH Rd,[Rb,Ro]
185 };
186
187 *ainstr = subset[(tinstr & 0xE00) >> 9] // base
188 | ((tinstr & 0x0007) << (12 - 0)) // Rd
189 | ((tinstr & 0x0038) << (16 - 3)) // Rb
190 | ((tinstr & 0x01C0) >> 6); // Ro
191 } break;
192
193 case 12: // STR Rd,[Rb,#imm5]
194 case 13: // LDR Rd,[Rb,#imm5]
195 case 14: // STRB Rd,[Rb,#imm5]
196 case 15: // LDRB Rd,[Rb,#imm5]
197 {
198 static const u32 subset[4] = {
199 0xE5800000, // STR Rd,[Rb,#imm5]
200 0xE5900000, // LDR Rd,[Rb,#imm5]
201 0xE5C00000, // STRB Rd,[Rb,#imm5]
202 0xE5D00000 // LDRB Rd,[Rb,#imm5]
203 };
204 // The offset range defends on whether we are transferring a byte or word value:
205 *ainstr = subset[(tinstr & 0x1800) >> 11] // base
206 | ((tinstr & 0x0007) << (12 - 0)) // Rd
207 | ((tinstr & 0x0038) << (16 - 3)) // Rb
208 | ((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); // off5
209 } break;
210
211 case 16: // STRH Rd,[Rb,#imm5]
212 case 17: // LDRH Rd,[Rb,#imm5]
213 *ainstr = ((tinstr & (1 << 11)) // base
214 ? 0xE1D000B0 // LDRH
215 : 0xE1C000B0) // STRH
216 | ((tinstr & 0x0007) << (12 - 0)) // Rd
217 | ((tinstr & 0x0038) << (16 - 3)) // Rb
218 | ((tinstr & 0x01C0) >> (6 - 1)) // off5, low nibble
219 | ((tinstr & 0x0600) >> (9 - 8)); // off5, high nibble
220 break;
221
222 case 18: // STR Rd,[SP,#imm8]
223 case 19: // LDR Rd,[SP,#imm8]
224 *ainstr = ((tinstr & (1 << 11)) // base
225 ? 0xE59D0000 // LDR
226 : 0xE58D0000) // STR
227 | ((tinstr & 0x0700) << (12 - 8)) // Rd
228 | ((tinstr & 0x00FF) << 2); // off8
229 break;
230
231 case 20: // ADD Rd,PC,#imm8
232 case 21: // ADD Rd,SP,#imm8
233
234 if ((tinstr & (1 << 11)) == 0) {
235
236 // NOTE: The PC value used here should by word aligned. We encode shift-left-by-2 in the
237 // rotate immediate field, so no shift of off8 is needed.
238
239 *ainstr = 0xE28F0F00 // base
240 | ((tinstr & 0x0700) << (12 - 8)) // Rd
241 | (tinstr & 0x00FF); // off8
242 } else {
243 // We encode shift-left-by-2 in the rotate immediate field, so no shift of off8 is
244 // needed.
245 *ainstr = 0xE28D0F00 // base
246 | ((tinstr & 0x0700) << (12 - 8)) // Rd
247 | (tinstr & 0x00FF); // off8
248 }
249 break;
250
251 case 22:
252 case 23:
253 if ((tinstr & 0x0F00) == 0x0000) {
254 // NOTE: The instruction contains a shift left of 2 equivalent (implemented as ROR #30):
255 *ainstr = ((tinstr & (1 << 7)) // base
256 ? 0xE24DDF00 // SUB
257 : 0xE28DDF00) // ADD
258 | (tinstr & 0x007F); // off7
259 } else if ((tinstr & 0x0F00) == 0x0e00) {
260 // BKPT
261 *ainstr = 0xEF000000 // base
262 | BITS(tinstr, 0, 3) // imm4 field;
263 | (BITS(tinstr, 4, 7) << 8); // beginning 4 bits of imm12
264 } else if ((tinstr & 0x0F00) == 0x0200) {
265 static const u32 subset[4] = {
266 0xE6BF0070, // SXTH
267 0xE6AF0070, // SXTB
268 0xE6FF0070, // UXTH
269 0xE6EF0070, // UXTB
270 };
271
272 *ainstr = subset[BITS(tinstr, 6, 7)] // base
273 | (BITS(tinstr, 0, 2) << 12) // Rd
274 | BITS(tinstr, 3, 5); // Rm
275 } else if ((tinstr & 0x0F00) == 0x600) {
276 if (BIT(tinstr, 5) == 0) {
277 // SETEND
278 *ainstr = 0xF1010000 // base
279 | (BIT(tinstr, 3) << 9); // endian specifier
280 } else {
281 // CPS
282 *ainstr = 0xF1080000 // base
283 | (BIT(tinstr, 0) << 6) // fiq bit
284 | (BIT(tinstr, 1) << 7) // irq bit
285 | (BIT(tinstr, 2) << 8) // abort bit
286 | (BIT(tinstr, 4) << 18); // enable bit
287 }
288 } else if ((tinstr & 0x0F00) == 0x0a00) {
289 static const u32 subset[4] = {
290 0xE6BF0F30, // REV
291 0xE6BF0FB0, // REV16
292 0, // undefined
293 0xE6FF0FB0, // REVSH
294 };
295
296 size_t subset_index = BITS(tinstr, 6, 7);
297
298 if (subset_index == 2) {
299 valid = ThumbDecodeStatus::UNDEFINED;
300 } else {
301 *ainstr = subset[subset_index] // base
302 | (BITS(tinstr, 0, 2) << 12) // Rd
303 | BITS(tinstr, 3, 5); // Rm
304 }
305 } else {
306 static const u32 subset[4] = {
307 0xE92D0000, // STMDB sp!,{rlist}
308 0xE92D4000, // STMDB sp!,{rlist,lr}
309 0xE8BD0000, // LDMIA sp!,{rlist}
310 0xE8BD8000 // LDMIA sp!,{rlist,pc}
311 };
312 *ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] // base
313 | (tinstr & 0x00FF); // mask8
314 }
315 break;
316
317 case 24: // STMIA
318 case 25: // LDMIA
319 if (tinstr & (1 << 11)) {
320 unsigned int base = 0xE8900000;
321 unsigned int rn = BITS(tinstr, 8, 10);
322
323 // Writeback
324 if ((tinstr & (1 << rn)) == 0)
325 base |= (1 << 21);
326
327 *ainstr = base // base (LDMIA)
328 | (rn << 16) // Rn
329 | (tinstr & 0x00FF); // Register list
330 } else {
331 *ainstr = 0xE8A00000 // base (STMIA)
332 | (BITS(tinstr, 8, 10) << 16) // Rn
333 | (tinstr & 0x00FF); // Register list
334 }
335 break;
336
337 case 26: // Bcc
338 case 27: // Bcc/SWI
339 if ((tinstr & 0x0F00) == 0x0F00) {
340 // Format 17 : SWI
341 *ainstr = 0xEF000000;
342 // Breakpoint must be handled specially.
343 if ((tinstr & 0x00FF) == 0x18)
344 *ainstr |= ((tinstr & 0x00FF) << 16);
345 // New breakpoint value. See gdb/arm-tdep.c
346 else if ((tinstr & 0x00FF) == 0xFE)
347 *ainstr |= 0x180000; // base |= BKPT mask
348 else
349 *ainstr |= (tinstr & 0x00FF);
350 } else if ((tinstr & 0x0F00) != 0x0E00)
351 valid = ThumbDecodeStatus::BRANCH;
352 else // UNDEFINED : cc=1110(AL) uses different format
353 valid = ThumbDecodeStatus::UNDEFINED;
354
355 break;
356
357 case 28: // B
358 valid = ThumbDecodeStatus::BRANCH;
359 break;
360
361 case 29:
362 if (tinstr & 0x1)
363 valid = ThumbDecodeStatus::UNDEFINED;
364 else
365 valid = ThumbDecodeStatus::BRANCH;
366 break;
367
368 case 30: // BL instruction 1
369
370 // There is no single ARM instruction equivalent for this Thumb instruction. To keep the
371 // simulation simple (from the user perspective) we check if the following instruction is
372 // the second half of this BL, and if it is we simulate it immediately
373
374 valid = ThumbDecodeStatus::BRANCH;
375 break;
376
377 case 31: // BL instruction 2
378
379 // There is no single ARM instruction equivalent for this instruction. Also, it should only
380 // ever be matched with the fmt19 "BL instruction 1" instruction. However, we do allow the
381 // simulation of it on its own, with undefined results if r14 is not suitably initialised.
382
383 valid = ThumbDecodeStatus::BRANCH;
384 break;
385 }
386
387 *inst_size = 2;
388
389 return valid;
390}
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.h b/src/core/arm/dyncom/arm_dyncom_thumb.h
deleted file mode 100644
index 231e48aa4..000000000
--- a/src/core/arm/dyncom/arm_dyncom_thumb.h
+++ /dev/null
@@ -1,49 +0,0 @@
1/* Copyright (C)
2* 2011 - Michael.Kang blackfin.kang@gmail.com
3* This program is free software; you can redistribute it and/or
4* modify it under the terms of the GNU General Public License
5* as published by the Free Software Foundation; either version 2
6* of the License, or (at your option) any later version.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program; if not, write to the Free Software
15* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16*
17*/
18
19/**
20* @file arm_dyncom_thumb.h
21* @brief The thumb dyncom
22* @author Michael.Kang blackfin.kang@gmail.com
23* @version 78.77
24* @date 2011-11-07
25*/
26
27#pragma once
28
29#include "common/common_types.h"
30
31enum class ThumbDecodeStatus {
32 UNDEFINED, // Undefined Thumb instruction
33 DECODED, // Instruction decoded to ARM equivalent
34 BRANCH, // Thumb branch (already processed)
35 UNINITIALIZED,
36};
37
38// Translates a Thumb mode instruction into its ARM equivalent.
39ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size);
40
41inline u32 GetThumbInstruction(u32 instr, u32 address) {
42 // Normally you would need to handle instruction endianness,
43 // however, it is fixed to little-endian on the MPCore, so
44 // there's no need to check for this beforehand.
45 if ((address & 0x3) != 0)
46 return instr >> 16;
47
48 return instr & 0xFFFF;
49}
diff --git a/src/core/arm/dyncom/arm_dyncom_trans.cpp b/src/core/arm/dyncom/arm_dyncom_trans.cpp
deleted file mode 100644
index 9cd6c0dea..000000000
--- a/src/core/arm/dyncom/arm_dyncom_trans.cpp
+++ /dev/null
@@ -1,1887 +0,0 @@
1#include <cstdlib>
2#include "common/assert.h"
3#include "common/common_types.h"
4#include "core/arm/dyncom/arm_dyncom_interpreter.h"
5#include "core/arm/dyncom/arm_dyncom_trans.h"
6#include "core/arm/skyeye_common/armstate.h"
7#include "core/arm/skyeye_common/armsupp.h"
8#include "core/arm/skyeye_common/vfp/vfp.h"
9
10char trans_cache_buf[TRANS_CACHE_SIZE];
11size_t trans_cache_buf_top = 0;
12
13static void* AllocBuffer(size_t size) {
14 size_t start = trans_cache_buf_top;
15 trans_cache_buf_top += size;
16 ASSERT_MSG(trans_cache_buf_top <= TRANS_CACHE_SIZE, "Translation cache is full!");
17 return static_cast<void*>(&trans_cache_buf[start]);
18}
19
20#define glue(x, y) x##y
21#define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s)
22
23shtop_fp_t GetShifterOp(unsigned int inst);
24get_addr_fp_t GetAddressingOp(unsigned int inst);
25get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst);
26
27static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index) {
28 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst));
29 adc_inst* inst_cream = (adc_inst*)inst_base->component;
30
31 inst_base->cond = BITS(inst, 28, 31);
32 inst_base->idx = index;
33 inst_base->br = TransExtData::NON_BRANCH;
34
35 inst_cream->I = BIT(inst, 25);
36 inst_cream->S = BIT(inst, 20);
37 inst_cream->Rn = BITS(inst, 16, 19);
38 inst_cream->Rd = BITS(inst, 12, 15);
39 inst_cream->shifter_operand = BITS(inst, 0, 11);
40 inst_cream->shtop_func = GetShifterOp(inst);
41
42 if (inst_cream->Rd == 15)
43 inst_base->br = TransExtData::INDIRECT_BRANCH;
44
45 return inst_base;
46}
47static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index) {
48 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(add_inst));
49 add_inst* inst_cream = (add_inst*)inst_base->component;
50
51 inst_base->cond = BITS(inst, 28, 31);
52 inst_base->idx = index;
53 inst_base->br = TransExtData::NON_BRANCH;
54
55 inst_cream->I = BIT(inst, 25);
56 inst_cream->S = BIT(inst, 20);
57 inst_cream->Rn = BITS(inst, 16, 19);
58 inst_cream->Rd = BITS(inst, 12, 15);
59 inst_cream->shifter_operand = BITS(inst, 0, 11);
60 inst_cream->shtop_func = GetShifterOp(inst);
61
62 if (inst_cream->Rd == 15)
63 inst_base->br = TransExtData::INDIRECT_BRANCH;
64
65 return inst_base;
66}
67static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index) {
68 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(and_inst));
69 and_inst* inst_cream = (and_inst*)inst_base->component;
70
71 inst_base->cond = BITS(inst, 28, 31);
72 inst_base->idx = index;
73 inst_base->br = TransExtData::NON_BRANCH;
74
75 inst_cream->I = BIT(inst, 25);
76 inst_cream->S = BIT(inst, 20);
77 inst_cream->Rn = BITS(inst, 16, 19);
78 inst_cream->Rd = BITS(inst, 12, 15);
79 inst_cream->shifter_operand = BITS(inst, 0, 11);
80 inst_cream->shtop_func = GetShifterOp(inst);
81
82 if (inst_cream->Rd == 15)
83 inst_base->br = TransExtData::INDIRECT_BRANCH;
84
85 return inst_base;
86}
87static ARM_INST_PTR INTERPRETER_TRANSLATE(bbl)(unsigned int inst, int index) {
88#define POSBRANCH ((inst & 0x7fffff) << 2)
89#define NEGBRANCH ((0xff000000 | (inst & 0xffffff)) << 2)
90
91 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bbl_inst));
92 bbl_inst* inst_cream = (bbl_inst*)inst_base->component;
93
94 inst_base->cond = BITS(inst, 28, 31);
95 inst_base->idx = index;
96 inst_base->br = TransExtData::DIRECT_BRANCH;
97
98 if (BIT(inst, 24))
99 inst_base->br = TransExtData::CALL;
100
101 inst_cream->L = BIT(inst, 24);
102 inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH;
103
104 return inst_base;
105}
106static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index) {
107 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bic_inst));
108 bic_inst* inst_cream = (bic_inst*)inst_base->component;
109
110 inst_base->cond = BITS(inst, 28, 31);
111 inst_base->idx = index;
112 inst_base->br = TransExtData::NON_BRANCH;
113
114 inst_cream->I = BIT(inst, 25);
115 inst_cream->S = BIT(inst, 20);
116 inst_cream->Rn = BITS(inst, 16, 19);
117 inst_cream->Rd = BITS(inst, 12, 15);
118 inst_cream->shifter_operand = BITS(inst, 0, 11);
119 inst_cream->shtop_func = GetShifterOp(inst);
120
121 if (inst_cream->Rd == 15)
122 inst_base->br = TransExtData::INDIRECT_BRANCH;
123 return inst_base;
124}
125
126static ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index) {
127 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bkpt_inst));
128 bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component;
129
130 inst_base->cond = BITS(inst, 28, 31);
131 inst_base->idx = index;
132 inst_base->br = TransExtData::NON_BRANCH;
133
134 inst_cream->imm = (BITS(inst, 8, 19) << 4) | BITS(inst, 0, 3);
135
136 return inst_base;
137}
138
139static ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index) {
140 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(blx_inst));
141 blx_inst* inst_cream = (blx_inst*)inst_base->component;
142
143 inst_base->cond = BITS(inst, 28, 31);
144 inst_base->idx = index;
145 inst_base->br = TransExtData::INDIRECT_BRANCH;
146
147 inst_cream->inst = inst;
148 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
149 inst_cream->val.Rm = BITS(inst, 0, 3);
150 } else {
151 inst_cream->val.signed_immed_24 = BITS(inst, 0, 23);
152 }
153
154 return inst_base;
155}
156static ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index) {
157 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst));
158 bx_inst* inst_cream = (bx_inst*)inst_base->component;
159
160 inst_base->cond = BITS(inst, 28, 31);
161 inst_base->idx = index;
162 inst_base->br = TransExtData::INDIRECT_BRANCH;
163
164 inst_cream->Rm = BITS(inst, 0, 3);
165
166 return inst_base;
167}
168static ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) {
169 return INTERPRETER_TRANSLATE(bx)(inst, index);
170}
171
172static ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index) {
173 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst));
174 cdp_inst* inst_cream = (cdp_inst*)inst_base->component;
175
176 inst_base->cond = BITS(inst, 28, 31);
177 inst_base->idx = index;
178 inst_base->br = TransExtData::NON_BRANCH;
179
180 inst_cream->CRm = BITS(inst, 0, 3);
181 inst_cream->CRd = BITS(inst, 12, 15);
182 inst_cream->CRn = BITS(inst, 16, 19);
183 inst_cream->cp_num = BITS(inst, 8, 11);
184 inst_cream->opcode_2 = BITS(inst, 5, 7);
185 inst_cream->opcode_1 = BITS(inst, 20, 23);
186 inst_cream->inst = inst;
187
188 LOG_TRACE(Core_ARM, "inst %x index %x", inst, index);
189 return inst_base;
190}
191static ARM_INST_PTR INTERPRETER_TRANSLATE(clrex)(unsigned int inst, int index) {
192 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(clrex_inst));
193 inst_base->cond = BITS(inst, 28, 31);
194 inst_base->idx = index;
195 inst_base->br = TransExtData::NON_BRANCH;
196
197 return inst_base;
198}
199static ARM_INST_PTR INTERPRETER_TRANSLATE(clz)(unsigned int inst, int index) {
200 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(clz_inst));
201 clz_inst* inst_cream = (clz_inst*)inst_base->component;
202
203 inst_base->cond = BITS(inst, 28, 31);
204 inst_base->idx = index;
205 inst_base->br = TransExtData::NON_BRANCH;
206
207 inst_cream->Rm = BITS(inst, 0, 3);
208 inst_cream->Rd = BITS(inst, 12, 15);
209
210 return inst_base;
211}
212static ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index) {
213 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(cmn_inst));
214 cmn_inst* inst_cream = (cmn_inst*)inst_base->component;
215
216 inst_base->cond = BITS(inst, 28, 31);
217 inst_base->idx = index;
218 inst_base->br = TransExtData::NON_BRANCH;
219
220 inst_cream->I = BIT(inst, 25);
221 inst_cream->Rn = BITS(inst, 16, 19);
222 inst_cream->shifter_operand = BITS(inst, 0, 11);
223 inst_cream->shtop_func = GetShifterOp(inst);
224
225 return inst_base;
226}
227static ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index) {
228 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(cmp_inst));
229 cmp_inst* inst_cream = (cmp_inst*)inst_base->component;
230
231 inst_base->cond = BITS(inst, 28, 31);
232 inst_base->idx = index;
233 inst_base->br = TransExtData::NON_BRANCH;
234
235 inst_cream->I = BIT(inst, 25);
236 inst_cream->Rn = BITS(inst, 16, 19);
237 inst_cream->shifter_operand = BITS(inst, 0, 11);
238 inst_cream->shtop_func = GetShifterOp(inst);
239
240 return inst_base;
241}
242static ARM_INST_PTR INTERPRETER_TRANSLATE(cps)(unsigned int inst, int index) {
243 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(cps_inst));
244 cps_inst* inst_cream = (cps_inst*)inst_base->component;
245
246 inst_base->cond = BITS(inst, 28, 31);
247 inst_base->idx = index;
248 inst_base->br = TransExtData::NON_BRANCH;
249
250 inst_cream->imod0 = BIT(inst, 18);
251 inst_cream->imod1 = BIT(inst, 19);
252 inst_cream->mmod = BIT(inst, 17);
253 inst_cream->A = BIT(inst, 8);
254 inst_cream->I = BIT(inst, 7);
255 inst_cream->F = BIT(inst, 6);
256 inst_cream->mode = BITS(inst, 0, 4);
257
258 return inst_base;
259}
260static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index) {
261 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst));
262 mov_inst* inst_cream = (mov_inst*)inst_base->component;
263
264 inst_base->cond = BITS(inst, 28, 31);
265 inst_base->idx = index;
266 inst_base->br = TransExtData::NON_BRANCH;
267
268 inst_cream->I = BIT(inst, 25);
269 inst_cream->S = BIT(inst, 20);
270 inst_cream->Rd = BITS(inst, 12, 15);
271 inst_cream->shifter_operand = BITS(inst, 0, 11);
272 inst_cream->shtop_func = GetShifterOp(inst);
273
274 if (inst_cream->Rd == 15) {
275 inst_base->br = TransExtData::INDIRECT_BRANCH;
276 }
277 return inst_base;
278}
279static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index) {
280 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(eor_inst));
281 eor_inst* inst_cream = (eor_inst*)inst_base->component;
282
283 inst_base->cond = BITS(inst, 28, 31);
284 inst_base->idx = index;
285 inst_base->br = TransExtData::NON_BRANCH;
286
287 inst_cream->I = BIT(inst, 25);
288 inst_cream->S = BIT(inst, 20);
289 inst_cream->Rn = BITS(inst, 16, 19);
290 inst_cream->Rd = BITS(inst, 12, 15);
291 inst_cream->shifter_operand = BITS(inst, 0, 11);
292 inst_cream->shtop_func = GetShifterOp(inst);
293
294 if (inst_cream->Rd == 15)
295 inst_base->br = TransExtData::INDIRECT_BRANCH;
296
297 return inst_base;
298}
299static ARM_INST_PTR INTERPRETER_TRANSLATE(ldc)(unsigned int inst, int index) {
300 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldc_inst));
301 inst_base->cond = BITS(inst, 28, 31);
302 inst_base->idx = index;
303 inst_base->br = TransExtData::NON_BRANCH;
304
305 return inst_base;
306}
307static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index) {
308 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
309 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
310
311 inst_base->cond = BITS(inst, 28, 31);
312 inst_base->idx = index;
313 inst_base->br = TransExtData::NON_BRANCH;
314
315 inst_cream->inst = inst;
316 inst_cream->get_addr = GetAddressingOp(inst);
317
318 if (BIT(inst, 15)) {
319 inst_base->br = TransExtData::INDIRECT_BRANCH;
320 }
321 return inst_base;
322}
323static ARM_INST_PTR INTERPRETER_TRANSLATE(sxth)(unsigned int inst, int index) {
324 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst));
325 sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component;
326
327 inst_base->cond = BITS(inst, 28, 31);
328 inst_base->idx = index;
329 inst_base->br = TransExtData::NON_BRANCH;
330
331 inst_cream->Rd = BITS(inst, 12, 15);
332 inst_cream->Rm = BITS(inst, 0, 3);
333 inst_cream->rotate = BITS(inst, 10, 11);
334
335 return inst_base;
336}
337static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index) {
338 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
339 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
340
341 inst_base->cond = BITS(inst, 28, 31);
342 inst_base->idx = index;
343 inst_base->br = TransExtData::NON_BRANCH;
344
345 inst_cream->inst = inst;
346 inst_cream->get_addr = GetAddressingOp(inst);
347
348 if (BITS(inst, 12, 15) == 15)
349 inst_base->br = TransExtData::INDIRECT_BRANCH;
350
351 return inst_base;
352}
353
354static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index) {
355 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
356 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
357
358 inst_base->cond = BITS(inst, 28, 31);
359 inst_base->idx = index;
360 inst_base->br = TransExtData::NON_BRANCH;
361
362 inst_cream->inst = inst;
363 inst_cream->get_addr = GetAddressingOp(inst);
364
365 if (BITS(inst, 12, 15) == 15)
366 inst_base->br = TransExtData::INDIRECT_BRANCH;
367
368 return inst_base;
369}
370
371static ARM_INST_PTR INTERPRETER_TRANSLATE(uxth)(unsigned int inst, int index) {
372 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst));
373 uxth_inst* inst_cream = (uxth_inst*)inst_base->component;
374
375 inst_base->cond = BITS(inst, 28, 31);
376 inst_base->idx = index;
377 inst_base->br = TransExtData::NON_BRANCH;
378
379 inst_cream->Rd = BITS(inst, 12, 15);
380 inst_cream->rotate = BITS(inst, 10, 11);
381 inst_cream->Rm = BITS(inst, 0, 3);
382
383 return inst_base;
384}
385static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtah)(unsigned int inst, int index) {
386 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtah_inst));
387 uxtah_inst* inst_cream = (uxtah_inst*)inst_base->component;
388
389 inst_base->cond = BITS(inst, 28, 31);
390 inst_base->idx = index;
391 inst_base->br = TransExtData::NON_BRANCH;
392
393 inst_cream->Rn = BITS(inst, 16, 19);
394 inst_cream->Rd = BITS(inst, 12, 15);
395 inst_cream->rotate = BITS(inst, 10, 11);
396 inst_cream->Rm = BITS(inst, 0, 3);
397
398 return inst_base;
399}
400static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index) {
401 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
402 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
403
404 inst_base->cond = BITS(inst, 28, 31);
405 inst_base->idx = index;
406 inst_base->br = TransExtData::NON_BRANCH;
407
408 inst_cream->inst = inst;
409 inst_cream->get_addr = GetAddressingOp(inst);
410
411 return inst_base;
412}
413static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index) {
414 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
415 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
416
417 inst_base->cond = BITS(inst, 28, 31);
418 inst_base->idx = index;
419 inst_base->br = TransExtData::NON_BRANCH;
420
421 inst_cream->inst = inst;
422 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
423
424 return inst_base;
425}
426static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index) {
427 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
428 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
429
430 inst_base->cond = BITS(inst, 28, 31);
431 inst_base->idx = index;
432 inst_base->br = TransExtData::NON_BRANCH;
433
434 inst_cream->inst = inst;
435 inst_cream->get_addr = GetAddressingOp(inst);
436
437 return inst_base;
438}
439static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index) {
440 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
441 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
442
443 inst_base->cond = BITS(inst, 28, 31);
444 inst_base->idx = index;
445 inst_base->br = (BITS(inst, 12, 15) == 15) ? TransExtData::INDIRECT_BRANCH
446 : TransExtData::NON_BRANCH; // Branch if dest is R15
447
448 inst_cream->Rn = BITS(inst, 16, 19);
449 inst_cream->Rd = BITS(inst, 12, 15);
450
451 return inst_base;
452}
453static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index) {
454 return INTERPRETER_TRANSLATE(ldrex)(inst, index);
455}
456static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexh)(unsigned int inst, int index) {
457 return INTERPRETER_TRANSLATE(ldrex)(inst, index);
458}
459static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexd)(unsigned int inst, int index) {
460 return INTERPRETER_TRANSLATE(ldrex)(inst, index);
461}
462static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index) {
463 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
464 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
465
466 inst_base->cond = BITS(inst, 28, 31);
467 inst_base->idx = index;
468 inst_base->br = TransExtData::NON_BRANCH;
469
470 inst_cream->inst = inst;
471 inst_cream->get_addr = GetAddressingOp(inst);
472
473 return inst_base;
474}
475static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index) {
476 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
477 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
478
479 inst_base->cond = BITS(inst, 28, 31);
480 inst_base->idx = index;
481 inst_base->br = TransExtData::NON_BRANCH;
482
483 inst_cream->inst = inst;
484 inst_cream->get_addr = GetAddressingOp(inst);
485
486 return inst_base;
487}
488static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index) {
489 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
490 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
491
492 inst_base->cond = BITS(inst, 28, 31);
493 inst_base->idx = index;
494 inst_base->br = TransExtData::NON_BRANCH;
495
496 inst_cream->inst = inst;
497 inst_cream->get_addr = GetAddressingOp(inst);
498
499 return inst_base;
500}
501static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index) {
502 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
503 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
504
505 inst_base->cond = BITS(inst, 28, 31);
506 inst_base->idx = index;
507 inst_base->br = TransExtData::NON_BRANCH;
508
509 inst_cream->inst = inst;
510 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
511
512 if (BITS(inst, 12, 15) == 15) {
513 inst_base->br = TransExtData::INDIRECT_BRANCH;
514 }
515 return inst_base;
516}
517static ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index) {
518 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mcr_inst));
519 mcr_inst* inst_cream = (mcr_inst*)inst_base->component;
520 inst_base->cond = BITS(inst, 28, 31);
521 inst_base->idx = index;
522 inst_base->br = TransExtData::NON_BRANCH;
523
524 inst_cream->crn = BITS(inst, 16, 19);
525 inst_cream->crm = BITS(inst, 0, 3);
526 inst_cream->opcode_1 = BITS(inst, 21, 23);
527 inst_cream->opcode_2 = BITS(inst, 5, 7);
528 inst_cream->Rd = BITS(inst, 12, 15);
529 inst_cream->cp_num = BITS(inst, 8, 11);
530 inst_cream->inst = inst;
531 return inst_base;
532}
533
534static ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index) {
535 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mcrr_inst));
536 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
537
538 inst_base->cond = BITS(inst, 28, 31);
539 inst_base->idx = index;
540 inst_base->br = TransExtData::NON_BRANCH;
541
542 inst_cream->crm = BITS(inst, 0, 3);
543 inst_cream->opcode_1 = BITS(inst, 4, 7);
544 inst_cream->cp_num = BITS(inst, 8, 11);
545 inst_cream->rt = BITS(inst, 12, 15);
546 inst_cream->rt2 = BITS(inst, 16, 19);
547
548 return inst_base;
549}
550
551static ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index) {
552 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst));
553 mla_inst* inst_cream = (mla_inst*)inst_base->component;
554
555 inst_base->cond = BITS(inst, 28, 31);
556 inst_base->idx = index;
557 inst_base->br = TransExtData::NON_BRANCH;
558
559 inst_cream->S = BIT(inst, 20);
560 inst_cream->Rn = BITS(inst, 12, 15);
561 inst_cream->Rd = BITS(inst, 16, 19);
562 inst_cream->Rs = BITS(inst, 8, 11);
563 inst_cream->Rm = BITS(inst, 0, 3);
564
565 return inst_base;
566}
567static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index) {
568 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst));
569 mov_inst* inst_cream = (mov_inst*)inst_base->component;
570
571 inst_base->cond = BITS(inst, 28, 31);
572 inst_base->idx = index;
573 inst_base->br = TransExtData::NON_BRANCH;
574
575 inst_cream->I = BIT(inst, 25);
576 inst_cream->S = BIT(inst, 20);
577 inst_cream->Rd = BITS(inst, 12, 15);
578 inst_cream->shifter_operand = BITS(inst, 0, 11);
579 inst_cream->shtop_func = GetShifterOp(inst);
580
581 if (inst_cream->Rd == 15) {
582 inst_base->br = TransExtData::INDIRECT_BRANCH;
583 }
584 return inst_base;
585}
586static ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index) {
587 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mrc_inst));
588 mrc_inst* inst_cream = (mrc_inst*)inst_base->component;
589 inst_base->cond = BITS(inst, 28, 31);
590 inst_base->idx = index;
591 inst_base->br = TransExtData::NON_BRANCH;
592
593 inst_cream->crn = BITS(inst, 16, 19);
594 inst_cream->crm = BITS(inst, 0, 3);
595 inst_cream->opcode_1 = BITS(inst, 21, 23);
596 inst_cream->opcode_2 = BITS(inst, 5, 7);
597 inst_cream->Rd = BITS(inst, 12, 15);
598 inst_cream->cp_num = BITS(inst, 8, 11);
599 inst_cream->inst = inst;
600 return inst_base;
601}
602
603static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index) {
604 return INTERPRETER_TRANSLATE(mcrr)(inst, index);
605}
606
607static ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index) {
608 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst));
609 mrs_inst* inst_cream = (mrs_inst*)inst_base->component;
610
611 inst_base->cond = BITS(inst, 28, 31);
612 inst_base->idx = index;
613 inst_base->br = TransExtData::NON_BRANCH;
614
615 inst_cream->Rd = BITS(inst, 12, 15);
616 inst_cream->R = BIT(inst, 22);
617
618 return inst_base;
619}
620static ARM_INST_PTR INTERPRETER_TRANSLATE(msr)(unsigned int inst, int index) {
621 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(msr_inst));
622 msr_inst* inst_cream = (msr_inst*)inst_base->component;
623
624 inst_base->cond = BITS(inst, 28, 31);
625 inst_base->idx = index;
626 inst_base->br = TransExtData::NON_BRANCH;
627
628 inst_cream->field_mask = BITS(inst, 16, 19);
629 inst_cream->R = BIT(inst, 22);
630 inst_cream->inst = inst;
631
632 return inst_base;
633}
634static ARM_INST_PTR INTERPRETER_TRANSLATE(mul)(unsigned int inst, int index) {
635 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mul_inst));
636 mul_inst* inst_cream = (mul_inst*)inst_base->component;
637
638 inst_base->cond = BITS(inst, 28, 31);
639 inst_base->idx = index;
640 inst_base->br = TransExtData::NON_BRANCH;
641
642 inst_cream->S = BIT(inst, 20);
643 inst_cream->Rm = BITS(inst, 0, 3);
644 inst_cream->Rs = BITS(inst, 8, 11);
645 inst_cream->Rd = BITS(inst, 16, 19);
646
647 return inst_base;
648}
649static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index) {
650 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mvn_inst));
651 mvn_inst* inst_cream = (mvn_inst*)inst_base->component;
652
653 inst_base->cond = BITS(inst, 28, 31);
654 inst_base->idx = index;
655 inst_base->br = TransExtData::NON_BRANCH;
656
657 inst_cream->I = BIT(inst, 25);
658 inst_cream->S = BIT(inst, 20);
659 inst_cream->Rd = BITS(inst, 12, 15);
660 inst_cream->shifter_operand = BITS(inst, 0, 11);
661 inst_cream->shtop_func = GetShifterOp(inst);
662
663 if (inst_cream->Rd == 15) {
664 inst_base->br = TransExtData::INDIRECT_BRANCH;
665 }
666 return inst_base;
667}
668static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index) {
669 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(orr_inst));
670 orr_inst* inst_cream = (orr_inst*)inst_base->component;
671
672 inst_base->cond = BITS(inst, 28, 31);
673 inst_base->idx = index;
674 inst_base->br = TransExtData::NON_BRANCH;
675
676 inst_cream->I = BIT(inst, 25);
677 inst_cream->S = BIT(inst, 20);
678 inst_cream->Rd = BITS(inst, 12, 15);
679 inst_cream->Rn = BITS(inst, 16, 19);
680 inst_cream->shifter_operand = BITS(inst, 0, 11);
681 inst_cream->shtop_func = GetShifterOp(inst);
682
683 if (inst_cream->Rd == 15)
684 inst_base->br = TransExtData::INDIRECT_BRANCH;
685
686 return inst_base;
687}
688
689// NOP introduced in ARMv6K.
690static ARM_INST_PTR INTERPRETER_TRANSLATE(nop)(unsigned int inst, int index) {
691 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
692
693 inst_base->cond = BITS(inst, 28, 31);
694 inst_base->idx = index;
695 inst_base->br = TransExtData::NON_BRANCH;
696
697 return inst_base;
698}
699
700static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index) {
701 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(pkh_inst));
702 pkh_inst* inst_cream = (pkh_inst*)inst_base->component;
703
704 inst_base->cond = BITS(inst, 28, 31);
705 inst_base->idx = index;
706 inst_base->br = TransExtData::NON_BRANCH;
707
708 inst_cream->Rd = BITS(inst, 12, 15);
709 inst_cream->Rn = BITS(inst, 16, 19);
710 inst_cream->Rm = BITS(inst, 0, 3);
711 inst_cream->imm = BITS(inst, 7, 11);
712
713 return inst_base;
714}
715
716static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index) {
717 return INTERPRETER_TRANSLATE(pkhbt)(inst, index);
718}
719
720static ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index) {
721 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst));
722
723 inst_base->cond = BITS(inst, 28, 31);
724 inst_base->idx = index;
725 inst_base->br = TransExtData::NON_BRANCH;
726
727 return inst_base;
728}
729
730static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) {
731 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
732 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
733
734 inst_base->cond = BITS(inst, 28, 31);
735 inst_base->idx = index;
736 inst_base->br = TransExtData::NON_BRANCH;
737
738 inst_cream->op1 = BITS(inst, 21, 22);
739 inst_cream->Rm = BITS(inst, 0, 3);
740 inst_cream->Rn = BITS(inst, 16, 19);
741 inst_cream->Rd = BITS(inst, 12, 15);
742
743 return inst_base;
744}
745static ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) {
746 return INTERPRETER_TRANSLATE(qadd)(inst, index);
747}
748static ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) {
749 return INTERPRETER_TRANSLATE(qadd)(inst, index);
750}
751static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) {
752 return INTERPRETER_TRANSLATE(qadd)(inst, index);
753}
754
755static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) {
756 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
757 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
758
759 inst_base->cond = BITS(inst, 28, 31);
760 inst_base->idx = index;
761 inst_base->br = TransExtData::NON_BRANCH;
762
763 inst_cream->Rm = BITS(inst, 0, 3);
764 inst_cream->Rn = BITS(inst, 16, 19);
765 inst_cream->Rd = BITS(inst, 12, 15);
766 inst_cream->op1 = BITS(inst, 20, 21);
767 inst_cream->op2 = BITS(inst, 5, 7);
768
769 return inst_base;
770}
771static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index) {
772 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
773}
774static ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) {
775 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
776}
777static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) {
778 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
779}
780static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) {
781 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
782}
783static ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) {
784 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
785}
786
787static ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index) {
788 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst));
789 rev_inst* const inst_cream = (rev_inst*)inst_base->component;
790
791 inst_base->cond = BITS(inst, 28, 31);
792 inst_base->idx = index;
793 inst_base->br = TransExtData::NON_BRANCH;
794
795 inst_cream->Rm = BITS(inst, 0, 3);
796 inst_cream->Rd = BITS(inst, 12, 15);
797 inst_cream->op1 = BITS(inst, 20, 22);
798 inst_cream->op2 = BITS(inst, 5, 7);
799
800 return inst_base;
801}
802static ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index) {
803 return INTERPRETER_TRANSLATE(rev)(inst, index);
804}
805static ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index) {
806 return INTERPRETER_TRANSLATE(rev)(inst, index);
807}
808
809static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index) {
810 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
811 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
812
813 inst_base->cond = AL;
814 inst_base->idx = index;
815 inst_base->br = TransExtData::INDIRECT_BRANCH;
816
817 inst_cream->inst = inst;
818 inst_cream->get_addr = GetAddressingOp(inst);
819
820 return inst_base;
821}
822
823static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index) {
824 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rsb_inst));
825 rsb_inst* inst_cream = (rsb_inst*)inst_base->component;
826
827 inst_base->cond = BITS(inst, 28, 31);
828 inst_base->idx = index;
829 inst_base->br = TransExtData::NON_BRANCH;
830
831 inst_cream->I = BIT(inst, 25);
832 inst_cream->S = BIT(inst, 20);
833 inst_cream->Rn = BITS(inst, 16, 19);
834 inst_cream->Rd = BITS(inst, 12, 15);
835 inst_cream->shifter_operand = BITS(inst, 0, 11);
836 inst_cream->shtop_func = GetShifterOp(inst);
837
838 if (inst_cream->Rd == 15)
839 inst_base->br = TransExtData::INDIRECT_BRANCH;
840
841 return inst_base;
842}
843static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index) {
844 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rsc_inst));
845 rsc_inst* inst_cream = (rsc_inst*)inst_base->component;
846
847 inst_base->cond = BITS(inst, 28, 31);
848 inst_base->idx = index;
849 inst_base->br = TransExtData::NON_BRANCH;
850
851 inst_cream->I = BIT(inst, 25);
852 inst_cream->S = BIT(inst, 20);
853 inst_cream->Rn = BITS(inst, 16, 19);
854 inst_cream->Rd = BITS(inst, 12, 15);
855 inst_cream->shifter_operand = BITS(inst, 0, 11);
856 inst_cream->shtop_func = GetShifterOp(inst);
857
858 if (inst_cream->Rd == 15)
859 inst_base->br = TransExtData::INDIRECT_BRANCH;
860
861 return inst_base;
862}
863static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd8)(unsigned int inst, int index) {
864 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
865 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
866
867 inst_base->cond = BITS(inst, 28, 31);
868 inst_base->idx = index;
869 inst_base->br = TransExtData::NON_BRANCH;
870
871 inst_cream->Rm = BITS(inst, 0, 3);
872 inst_cream->Rn = BITS(inst, 16, 19);
873 inst_cream->Rd = BITS(inst, 12, 15);
874 inst_cream->op1 = BITS(inst, 20, 21);
875 inst_cream->op2 = BITS(inst, 5, 7);
876
877 return inst_base;
878}
879static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index) {
880 return INTERPRETER_TRANSLATE(sadd8)(inst, index);
881}
882static ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index) {
883 return INTERPRETER_TRANSLATE(sadd8)(inst, index);
884}
885static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index) {
886 return INTERPRETER_TRANSLATE(sadd8)(inst, index);
887}
888static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index) {
889 return INTERPRETER_TRANSLATE(sadd8)(inst, index);
890}
891static ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index) {
892 return INTERPRETER_TRANSLATE(sadd8)(inst, index);
893}
894
895static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index) {
896 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sbc_inst));
897 sbc_inst* inst_cream = (sbc_inst*)inst_base->component;
898
899 inst_base->cond = BITS(inst, 28, 31);
900 inst_base->idx = index;
901 inst_base->br = TransExtData::NON_BRANCH;
902
903 inst_cream->I = BIT(inst, 25);
904 inst_cream->S = BIT(inst, 20);
905 inst_cream->Rn = BITS(inst, 16, 19);
906 inst_cream->Rd = BITS(inst, 12, 15);
907 inst_cream->shifter_operand = BITS(inst, 0, 11);
908 inst_cream->shtop_func = GetShifterOp(inst);
909
910 if (inst_cream->Rd == 15)
911 inst_base->br = TransExtData::INDIRECT_BRANCH;
912
913 return inst_base;
914}
915static ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index) {
916 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
917 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
918
919 inst_base->cond = BITS(inst, 28, 31);
920 inst_base->idx = index;
921 inst_base->br = TransExtData::NON_BRANCH;
922
923 inst_cream->Rm = BITS(inst, 0, 3);
924 inst_cream->Rn = BITS(inst, 16, 19);
925 inst_cream->Rd = BITS(inst, 12, 15);
926 inst_cream->op1 = BITS(inst, 20, 22);
927 inst_cream->op2 = BITS(inst, 5, 7);
928
929 return inst_base;
930}
931
932static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) {
933 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(setend_inst));
934 setend_inst* const inst_cream = (setend_inst*)inst_base->component;
935
936 inst_base->cond = AL;
937 inst_base->idx = index;
938 inst_base->br = TransExtData::NON_BRANCH;
939
940 inst_cream->set_bigend = BIT(inst, 9);
941
942 return inst_base;
943}
944
945static ARM_INST_PTR INTERPRETER_TRANSLATE(sev)(unsigned int inst, int index) {
946 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
947
948 inst_base->cond = BITS(inst, 28, 31);
949 inst_base->idx = index;
950 inst_base->br = TransExtData::NON_BRANCH;
951
952 return inst_base;
953}
954
955static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) {
956 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
957 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
958
959 inst_base->cond = BITS(inst, 28, 31);
960 inst_base->idx = index;
961 inst_base->br = TransExtData::NON_BRANCH;
962
963 inst_cream->op1 = BITS(inst, 20, 21);
964 inst_cream->op2 = BITS(inst, 5, 7);
965 inst_cream->Rm = BITS(inst, 0, 3);
966 inst_cream->Rn = BITS(inst, 16, 19);
967 inst_cream->Rd = BITS(inst, 12, 15);
968
969 return inst_base;
970}
971static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index) {
972 return INTERPRETER_TRANSLATE(shadd8)(inst, index);
973}
974static ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index) {
975 return INTERPRETER_TRANSLATE(shadd8)(inst, index);
976}
977static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index) {
978 return INTERPRETER_TRANSLATE(shadd8)(inst, index);
979}
980static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index) {
981 return INTERPRETER_TRANSLATE(shadd8)(inst, index);
982}
983static ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index) {
984 return INTERPRETER_TRANSLATE(shadd8)(inst, index);
985}
986
987static ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index) {
988 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smla_inst));
989 smla_inst* inst_cream = (smla_inst*)inst_base->component;
990
991 inst_base->cond = BITS(inst, 28, 31);
992 inst_base->idx = index;
993 inst_base->br = TransExtData::NON_BRANCH;
994
995 inst_cream->x = BIT(inst, 5);
996 inst_cream->y = BIT(inst, 6);
997 inst_cream->Rm = BITS(inst, 0, 3);
998 inst_cream->Rs = BITS(inst, 8, 11);
999 inst_cream->Rd = BITS(inst, 16, 19);
1000 inst_cream->Rn = BITS(inst, 12, 15);
1001
1002 return inst_base;
1003}
1004
1005static ARM_INST_PTR INTERPRETER_TRANSLATE(smlad)(unsigned int inst, int index) {
1006 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
1007 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
1008
1009 inst_base->cond = BITS(inst, 28, 31);
1010 inst_base->idx = index;
1011 inst_base->br = TransExtData::NON_BRANCH;
1012
1013 inst_cream->m = BIT(inst, 5);
1014 inst_cream->Rn = BITS(inst, 0, 3);
1015 inst_cream->Rm = BITS(inst, 8, 11);
1016 inst_cream->Rd = BITS(inst, 16, 19);
1017 inst_cream->Ra = BITS(inst, 12, 15);
1018 inst_cream->op1 = BITS(inst, 20, 22);
1019 inst_cream->op2 = BITS(inst, 5, 7);
1020
1021 return inst_base;
1022}
1023static ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index) {
1024 return INTERPRETER_TRANSLATE(smlad)(inst, index);
1025}
1026static ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index) {
1027 return INTERPRETER_TRANSLATE(smlad)(inst, index);
1028}
1029static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsd)(unsigned int inst, int index) {
1030 return INTERPRETER_TRANSLATE(smlad)(inst, index);
1031}
1032
1033static ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index) {
1034 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst));
1035 umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
1036
1037 inst_base->cond = BITS(inst, 28, 31);
1038 inst_base->idx = index;
1039 inst_base->br = TransExtData::NON_BRANCH;
1040
1041 inst_cream->S = BIT(inst, 20);
1042 inst_cream->Rm = BITS(inst, 0, 3);
1043 inst_cream->Rs = BITS(inst, 8, 11);
1044 inst_cream->RdHi = BITS(inst, 16, 19);
1045 inst_cream->RdLo = BITS(inst, 12, 15);
1046
1047 return inst_base;
1048}
1049
1050static ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) {
1051 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlalxy_inst));
1052 smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component;
1053
1054 inst_base->cond = BITS(inst, 28, 31);
1055 inst_base->idx = index;
1056 inst_base->br = TransExtData::NON_BRANCH;
1057
1058 inst_cream->x = BIT(inst, 5);
1059 inst_cream->y = BIT(inst, 6);
1060 inst_cream->RdLo = BITS(inst, 12, 15);
1061 inst_cream->RdHi = BITS(inst, 16, 19);
1062 inst_cream->Rn = BITS(inst, 0, 4);
1063 inst_cream->Rm = BITS(inst, 8, 11);
1064
1065 return inst_base;
1066}
1067
1068static ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) {
1069 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
1070 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
1071
1072 inst_base->cond = BITS(inst, 28, 31);
1073 inst_base->idx = index;
1074 inst_base->br = TransExtData::NON_BRANCH;
1075
1076 inst_cream->Ra = BITS(inst, 12, 15);
1077 inst_cream->Rm = BITS(inst, 8, 11);
1078 inst_cream->Rn = BITS(inst, 0, 3);
1079 inst_cream->Rd = BITS(inst, 16, 19);
1080 inst_cream->m = BIT(inst, 6);
1081
1082 return inst_base;
1083}
1084
1085static ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) {
1086 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlald_inst));
1087 smlald_inst* const inst_cream = (smlald_inst*)inst_base->component;
1088
1089 inst_base->cond = BITS(inst, 28, 31);
1090 inst_base->idx = index;
1091 inst_base->br = TransExtData::NON_BRANCH;
1092
1093 inst_cream->Rm = BITS(inst, 8, 11);
1094 inst_cream->Rn = BITS(inst, 0, 3);
1095 inst_cream->RdLo = BITS(inst, 12, 15);
1096 inst_cream->RdHi = BITS(inst, 16, 19);
1097 inst_cream->swap = BIT(inst, 5);
1098 inst_cream->op1 = BITS(inst, 20, 22);
1099 inst_cream->op2 = BITS(inst, 5, 7);
1100
1101 return inst_base;
1102}
1103static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index) {
1104 return INTERPRETER_TRANSLATE(smlald)(inst, index);
1105}
1106
1107static ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index) {
1108 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
1109 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
1110
1111 inst_base->cond = BITS(inst, 28, 31);
1112 inst_base->idx = index;
1113 inst_base->br = TransExtData::NON_BRANCH;
1114
1115 inst_cream->m = BIT(inst, 5);
1116 inst_cream->Ra = BITS(inst, 12, 15);
1117 inst_cream->Rm = BITS(inst, 8, 11);
1118 inst_cream->Rn = BITS(inst, 0, 3);
1119 inst_cream->Rd = BITS(inst, 16, 19);
1120 inst_cream->op1 = BITS(inst, 20, 22);
1121 inst_cream->op2 = BITS(inst, 5, 7);
1122
1123 return inst_base;
1124}
1125static ARM_INST_PTR INTERPRETER_TRANSLATE(smmls)(unsigned int inst, int index) {
1126 return INTERPRETER_TRANSLATE(smmla)(inst, index);
1127}
1128static ARM_INST_PTR INTERPRETER_TRANSLATE(smmul)(unsigned int inst, int index) {
1129 return INTERPRETER_TRANSLATE(smmla)(inst, index);
1130}
1131
1132static ARM_INST_PTR INTERPRETER_TRANSLATE(smul)(unsigned int inst, int index) {
1133 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smul_inst));
1134 smul_inst* inst_cream = (smul_inst*)inst_base->component;
1135
1136 inst_base->cond = BITS(inst, 28, 31);
1137 inst_base->idx = index;
1138 inst_base->br = TransExtData::NON_BRANCH;
1139
1140 inst_cream->Rd = BITS(inst, 16, 19);
1141 inst_cream->Rs = BITS(inst, 8, 11);
1142 inst_cream->Rm = BITS(inst, 0, 3);
1143
1144 inst_cream->x = BIT(inst, 5);
1145 inst_cream->y = BIT(inst, 6);
1146
1147 return inst_base;
1148}
1149static ARM_INST_PTR INTERPRETER_TRANSLATE(smull)(unsigned int inst, int index) {
1150 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst));
1151 umull_inst* inst_cream = (umull_inst*)inst_base->component;
1152
1153 inst_base->cond = BITS(inst, 28, 31);
1154 inst_base->idx = index;
1155 inst_base->br = TransExtData::NON_BRANCH;
1156
1157 inst_cream->S = BIT(inst, 20);
1158 inst_cream->Rm = BITS(inst, 0, 3);
1159 inst_cream->Rs = BITS(inst, 8, 11);
1160 inst_cream->RdHi = BITS(inst, 16, 19);
1161 inst_cream->RdLo = BITS(inst, 12, 15);
1162
1163 return inst_base;
1164}
1165
1166static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index) {
1167 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
1168 smlad_inst* inst_cream = (smlad_inst*)inst_base->component;
1169
1170 inst_base->cond = BITS(inst, 28, 31);
1171 inst_base->idx = index;
1172 inst_base->br = TransExtData::NON_BRANCH;
1173
1174 inst_cream->m = BIT(inst, 6);
1175 inst_cream->Rm = BITS(inst, 8, 11);
1176 inst_cream->Rn = BITS(inst, 0, 3);
1177 inst_cream->Rd = BITS(inst, 16, 19);
1178
1179 return inst_base;
1180}
1181
1182static ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index) {
1183 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1184 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
1185
1186 inst_base->cond = AL;
1187 inst_base->idx = index;
1188 inst_base->br = TransExtData::NON_BRANCH;
1189
1190 inst_cream->inst = inst;
1191 inst_cream->get_addr = GetAddressingOp(inst);
1192
1193 return inst_base;
1194}
1195
1196static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index) {
1197 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst));
1198 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
1199
1200 inst_base->cond = BITS(inst, 28, 31);
1201 inst_base->idx = index;
1202 inst_base->br = TransExtData::NON_BRANCH;
1203
1204 inst_cream->Rn = BITS(inst, 0, 3);
1205 inst_cream->Rd = BITS(inst, 12, 15);
1206 inst_cream->imm5 = BITS(inst, 7, 11);
1207 inst_cream->sat_imm = BITS(inst, 16, 20);
1208 inst_cream->shift_type = BIT(inst, 6);
1209
1210 return inst_base;
1211}
1212static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index) {
1213 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst));
1214 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
1215
1216 inst_base->cond = BITS(inst, 28, 31);
1217 inst_base->idx = index;
1218 inst_base->br = TransExtData::NON_BRANCH;
1219
1220 inst_cream->Rn = BITS(inst, 0, 3);
1221 inst_cream->Rd = BITS(inst, 12, 15);
1222 inst_cream->sat_imm = BITS(inst, 16, 19);
1223
1224 return inst_base;
1225}
1226
1227static ARM_INST_PTR INTERPRETER_TRANSLATE(stc)(unsigned int inst, int index) {
1228 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(stc_inst));
1229 inst_base->cond = BITS(inst, 28, 31);
1230 inst_base->idx = index;
1231 inst_base->br = TransExtData::NON_BRANCH;
1232
1233 return inst_base;
1234}
1235static ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index) {
1236 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1237 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1238
1239 inst_base->cond = BITS(inst, 28, 31);
1240 inst_base->idx = index;
1241 inst_base->br = TransExtData::NON_BRANCH;
1242
1243 inst_cream->inst = inst;
1244 inst_cream->get_addr = GetAddressingOp(inst);
1245 return inst_base;
1246}
1247static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index) {
1248 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst));
1249 sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component;
1250
1251 inst_base->cond = BITS(inst, 28, 31);
1252 inst_base->idx = index;
1253 inst_base->br = TransExtData::NON_BRANCH;
1254
1255 inst_cream->Rd = BITS(inst, 12, 15);
1256 inst_cream->Rm = BITS(inst, 0, 3);
1257 inst_cream->rotate = BITS(inst, 10, 11);
1258
1259 return inst_base;
1260}
1261static ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index) {
1262 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1263 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1264
1265 inst_base->cond = BITS(inst, 28, 31);
1266 inst_base->idx = index;
1267 inst_base->br = TransExtData::NON_BRANCH;
1268
1269 inst_cream->inst = inst;
1270 inst_cream->get_addr = GetAddressingOp(inst);
1271
1272 return inst_base;
1273}
1274static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index) {
1275 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst));
1276 uxth_inst* inst_cream = (uxth_inst*)inst_base->component;
1277
1278 inst_base->cond = BITS(inst, 28, 31);
1279 inst_base->idx = index;
1280 inst_base->br = TransExtData::NON_BRANCH;
1281
1282 inst_cream->Rd = BITS(inst, 12, 15);
1283 inst_cream->rotate = BITS(inst, 10, 11);
1284 inst_cream->Rm = BITS(inst, 0, 3);
1285
1286 return inst_base;
1287}
1288static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab)(unsigned int inst, int index) {
1289 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst));
1290 uxtab_inst* inst_cream = (uxtab_inst*)inst_base->component;
1291
1292 inst_base->cond = BITS(inst, 28, 31);
1293 inst_base->idx = index;
1294 inst_base->br = TransExtData::NON_BRANCH;
1295
1296 inst_cream->Rd = BITS(inst, 12, 15);
1297 inst_cream->rotate = BITS(inst, 10, 11);
1298 inst_cream->Rm = BITS(inst, 0, 3);
1299 inst_cream->Rn = BITS(inst, 16, 19);
1300
1301 return inst_base;
1302}
1303static ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index) {
1304 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1305 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1306
1307 inst_base->cond = BITS(inst, 28, 31);
1308 inst_base->idx = index;
1309 inst_base->br = TransExtData::NON_BRANCH;
1310
1311 inst_cream->inst = inst;
1312 inst_cream->get_addr = GetAddressingOp(inst);
1313
1314 return inst_base;
1315}
1316static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index) {
1317 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1318 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1319
1320 inst_base->cond = BITS(inst, 28, 31);
1321 inst_base->idx = index;
1322 inst_base->br = TransExtData::NON_BRANCH;
1323
1324 inst_cream->inst = inst;
1325 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
1326
1327 return inst_base;
1328}
1329static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index) {
1330 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1331 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1332
1333 inst_base->cond = BITS(inst, 28, 31);
1334 inst_base->idx = index;
1335 inst_base->br = TransExtData::NON_BRANCH;
1336
1337 inst_cream->inst = inst;
1338 inst_cream->get_addr = GetAddressingOp(inst);
1339
1340 return inst_base;
1341}
1342static ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index) {
1343 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
1344 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
1345
1346 inst_base->cond = BITS(inst, 28, 31);
1347 inst_base->idx = index;
1348 inst_base->br = TransExtData::NON_BRANCH;
1349
1350 inst_cream->Rn = BITS(inst, 16, 19);
1351 inst_cream->Rd = BITS(inst, 12, 15);
1352 inst_cream->Rm = BITS(inst, 0, 3);
1353
1354 return inst_base;
1355}
1356static ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index) {
1357 return INTERPRETER_TRANSLATE(strex)(inst, index);
1358}
1359static ARM_INST_PTR INTERPRETER_TRANSLATE(strexh)(unsigned int inst, int index) {
1360 return INTERPRETER_TRANSLATE(strex)(inst, index);
1361}
1362static ARM_INST_PTR INTERPRETER_TRANSLATE(strexd)(unsigned int inst, int index) {
1363 return INTERPRETER_TRANSLATE(strex)(inst, index);
1364}
1365static ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) {
1366 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1367 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1368
1369 inst_base->cond = BITS(inst, 28, 31);
1370 inst_base->idx = index;
1371 inst_base->br = TransExtData::NON_BRANCH;
1372
1373 inst_cream->inst = inst;
1374 inst_cream->get_addr = GetAddressingOp(inst);
1375
1376 return inst_base;
1377}
1378static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index) {
1379 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1380 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1381
1382 inst_base->cond = BITS(inst, 28, 31);
1383 inst_base->idx = index;
1384 inst_base->br = TransExtData::NON_BRANCH;
1385
1386 inst_cream->inst = inst;
1387 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
1388
1389 return inst_base;
1390}
1391static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index) {
1392 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sub_inst));
1393 sub_inst* inst_cream = (sub_inst*)inst_base->component;
1394
1395 inst_base->cond = BITS(inst, 28, 31);
1396 inst_base->idx = index;
1397 inst_base->br = TransExtData::NON_BRANCH;
1398
1399 inst_cream->I = BIT(inst, 25);
1400 inst_cream->S = BIT(inst, 20);
1401 inst_cream->Rn = BITS(inst, 16, 19);
1402 inst_cream->Rd = BITS(inst, 12, 15);
1403 inst_cream->shifter_operand = BITS(inst, 0, 11);
1404 inst_cream->shtop_func = GetShifterOp(inst);
1405
1406 if (inst_cream->Rd == 15)
1407 inst_base->br = TransExtData::INDIRECT_BRANCH;
1408
1409 return inst_base;
1410}
1411static ARM_INST_PTR INTERPRETER_TRANSLATE(swi)(unsigned int inst, int index) {
1412 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(swi_inst));
1413 swi_inst* inst_cream = (swi_inst*)inst_base->component;
1414
1415 inst_base->cond = BITS(inst, 28, 31);
1416 inst_base->idx = index;
1417 inst_base->br = TransExtData::NON_BRANCH;
1418
1419 inst_cream->num = BITS(inst, 0, 23);
1420 return inst_base;
1421}
1422static ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index) {
1423 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst));
1424 swp_inst* inst_cream = (swp_inst*)inst_base->component;
1425
1426 inst_base->cond = BITS(inst, 28, 31);
1427 inst_base->idx = index;
1428 inst_base->br = TransExtData::NON_BRANCH;
1429
1430 inst_cream->Rn = BITS(inst, 16, 19);
1431 inst_cream->Rd = BITS(inst, 12, 15);
1432 inst_cream->Rm = BITS(inst, 0, 3);
1433
1434 return inst_base;
1435}
1436static ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index) {
1437 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst));
1438 swp_inst* inst_cream = (swp_inst*)inst_base->component;
1439
1440 inst_base->cond = BITS(inst, 28, 31);
1441 inst_base->idx = index;
1442 inst_base->br = TransExtData::NON_BRANCH;
1443
1444 inst_cream->Rn = BITS(inst, 16, 19);
1445 inst_cream->Rd = BITS(inst, 12, 15);
1446 inst_cream->Rm = BITS(inst, 0, 3);
1447
1448 return inst_base;
1449}
1450static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index) {
1451 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst));
1452 sxtab_inst* inst_cream = (sxtab_inst*)inst_base->component;
1453
1454 inst_base->cond = BITS(inst, 28, 31);
1455 inst_base->idx = index;
1456 inst_base->br = TransExtData::NON_BRANCH;
1457
1458 inst_cream->Rd = BITS(inst, 12, 15);
1459 inst_cream->rotate = BITS(inst, 10, 11);
1460 inst_cream->Rm = BITS(inst, 0, 3);
1461 inst_cream->Rn = BITS(inst, 16, 19);
1462
1463 return inst_base;
1464}
1465
1466static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index) {
1467 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst));
1468 sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component;
1469
1470 inst_base->cond = BITS(inst, 28, 31);
1471 inst_base->idx = index;
1472 inst_base->br = TransExtData::NON_BRANCH;
1473
1474 inst_cream->Rm = BITS(inst, 0, 3);
1475 inst_cream->Rn = BITS(inst, 16, 19);
1476 inst_cream->Rd = BITS(inst, 12, 15);
1477 inst_cream->rotate = BITS(inst, 10, 11);
1478
1479 return inst_base;
1480}
1481static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index) {
1482 return INTERPRETER_TRANSLATE(sxtab16)(inst, index);
1483}
1484
1485static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtah)(unsigned int inst, int index) {
1486 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtah_inst));
1487 sxtah_inst* inst_cream = (sxtah_inst*)inst_base->component;
1488
1489 inst_base->cond = BITS(inst, 28, 31);
1490 inst_base->idx = index;
1491 inst_base->br = TransExtData::NON_BRANCH;
1492
1493 inst_cream->Rd = BITS(inst, 12, 15);
1494 inst_cream->rotate = BITS(inst, 10, 11);
1495 inst_cream->Rm = BITS(inst, 0, 3);
1496 inst_cream->Rn = BITS(inst, 16, 19);
1497
1498 return inst_base;
1499}
1500
1501static ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index) {
1502 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(teq_inst));
1503 teq_inst* inst_cream = (teq_inst*)inst_base->component;
1504
1505 inst_base->cond = BITS(inst, 28, 31);
1506 inst_base->idx = index;
1507 inst_base->br = TransExtData::NON_BRANCH;
1508
1509 inst_cream->I = BIT(inst, 25);
1510 inst_cream->Rn = BITS(inst, 16, 19);
1511 inst_cream->shifter_operand = BITS(inst, 0, 11);
1512 inst_cream->shtop_func = GetShifterOp(inst);
1513
1514 return inst_base;
1515}
1516static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index) {
1517 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(tst_inst));
1518 tst_inst* inst_cream = (tst_inst*)inst_base->component;
1519
1520 inst_base->cond = BITS(inst, 28, 31);
1521 inst_base->idx = index;
1522 inst_base->br = TransExtData::NON_BRANCH;
1523
1524 inst_cream->I = BIT(inst, 25);
1525 inst_cream->S = BIT(inst, 20);
1526 inst_cream->Rn = BITS(inst, 16, 19);
1527 inst_cream->Rd = BITS(inst, 12, 15);
1528 inst_cream->shifter_operand = BITS(inst, 0, 11);
1529 inst_cream->shtop_func = GetShifterOp(inst);
1530
1531 return inst_base;
1532}
1533
1534static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index) {
1535 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
1536 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
1537
1538 inst_base->cond = BITS(inst, 28, 31);
1539 inst_base->idx = index;
1540 inst_base->br = TransExtData::NON_BRANCH;
1541
1542 inst_cream->op1 = BITS(inst, 20, 21);
1543 inst_cream->op2 = BITS(inst, 5, 7);
1544 inst_cream->Rm = BITS(inst, 0, 3);
1545 inst_cream->Rn = BITS(inst, 16, 19);
1546 inst_cream->Rd = BITS(inst, 12, 15);
1547
1548 return inst_base;
1549}
1550static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) {
1551 return INTERPRETER_TRANSLATE(uadd8)(inst, index);
1552}
1553static ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index) {
1554 return INTERPRETER_TRANSLATE(uadd8)(inst, index);
1555}
1556static ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) {
1557 return INTERPRETER_TRANSLATE(uadd8)(inst, index);
1558}
1559static ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) {
1560 return INTERPRETER_TRANSLATE(uadd8)(inst, index);
1561}
1562static ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index) {
1563 return INTERPRETER_TRANSLATE(uadd8)(inst, index);
1564}
1565
1566static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index) {
1567 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
1568 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
1569
1570 inst_base->cond = BITS(inst, 28, 31);
1571 inst_base->idx = index;
1572 inst_base->br = TransExtData::NON_BRANCH;
1573
1574 inst_cream->op1 = BITS(inst, 20, 21);
1575 inst_cream->op2 = BITS(inst, 5, 7);
1576 inst_cream->Rm = BITS(inst, 0, 3);
1577 inst_cream->Rn = BITS(inst, 16, 19);
1578 inst_cream->Rd = BITS(inst, 12, 15);
1579
1580 return inst_base;
1581}
1582static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index) {
1583 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
1584}
1585static ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index) {
1586 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
1587}
1588static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) {
1589 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
1590}
1591static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) {
1592 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
1593}
1594static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) {
1595 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
1596}
1597static ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index) {
1598 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst));
1599 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
1600
1601 inst_base->cond = BITS(inst, 28, 31);
1602 inst_base->idx = index;
1603 inst_base->br = TransExtData::NON_BRANCH;
1604
1605 inst_cream->Rm = BITS(inst, 8, 11);
1606 inst_cream->Rn = BITS(inst, 0, 3);
1607 inst_cream->RdLo = BITS(inst, 12, 15);
1608 inst_cream->RdHi = BITS(inst, 16, 19);
1609
1610 return inst_base;
1611}
1612static ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index) {
1613 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst));
1614 umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
1615
1616 inst_base->cond = BITS(inst, 28, 31);
1617 inst_base->idx = index;
1618 inst_base->br = TransExtData::NON_BRANCH;
1619
1620 inst_cream->S = BIT(inst, 20);
1621 inst_cream->Rm = BITS(inst, 0, 3);
1622 inst_cream->Rs = BITS(inst, 8, 11);
1623 inst_cream->RdHi = BITS(inst, 16, 19);
1624 inst_cream->RdLo = BITS(inst, 12, 15);
1625
1626 return inst_base;
1627}
1628static ARM_INST_PTR INTERPRETER_TRANSLATE(umull)(unsigned int inst, int index) {
1629 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst));
1630 umull_inst* inst_cream = (umull_inst*)inst_base->component;
1631
1632 inst_base->cond = BITS(inst, 28, 31);
1633 inst_base->idx = index;
1634 inst_base->br = TransExtData::NON_BRANCH;
1635
1636 inst_cream->S = BIT(inst, 20);
1637 inst_cream->Rm = BITS(inst, 0, 3);
1638 inst_cream->Rs = BITS(inst, 8, 11);
1639 inst_cream->RdHi = BITS(inst, 16, 19);
1640 inst_cream->RdLo = BITS(inst, 12, 15);
1641
1642 return inst_base;
1643}
1644
1645static ARM_INST_PTR INTERPRETER_TRANSLATE(b_2_thumb)(unsigned int tinst, int index) {
1646 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(b_2_thumb));
1647 b_2_thumb* inst_cream = (b_2_thumb*)inst_base->component;
1648
1649 inst_cream->imm = ((tinst & 0x3FF) << 1) | ((tinst & (1 << 10)) ? 0xFFFFF800 : 0);
1650
1651 inst_base->idx = index;
1652 inst_base->br = TransExtData::DIRECT_BRANCH;
1653
1654 return inst_base;
1655}
1656
1657static ARM_INST_PTR INTERPRETER_TRANSLATE(b_cond_thumb)(unsigned int tinst, int index) {
1658 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(b_cond_thumb));
1659 b_cond_thumb* inst_cream = (b_cond_thumb*)inst_base->component;
1660
1661 inst_cream->imm = (((tinst & 0x7F) << 1) | ((tinst & (1 << 7)) ? 0xFFFFFF00 : 0));
1662 inst_cream->cond = ((tinst >> 8) & 0xf);
1663 inst_base->idx = index;
1664 inst_base->br = TransExtData::DIRECT_BRANCH;
1665
1666 return inst_base;
1667}
1668
1669static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_1_thumb)(unsigned int tinst, int index) {
1670 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bl_1_thumb));
1671 bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component;
1672
1673 inst_cream->imm = (((tinst & 0x07FF) << 12) | ((tinst & (1 << 10)) ? 0xFF800000 : 0));
1674
1675 inst_base->idx = index;
1676 inst_base->br = TransExtData::NON_BRANCH;
1677 return inst_base;
1678}
1679static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_2_thumb)(unsigned int tinst, int index) {
1680 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bl_2_thumb));
1681 bl_2_thumb* inst_cream = (bl_2_thumb*)inst_base->component;
1682
1683 inst_cream->imm = (tinst & 0x07FF) << 1;
1684
1685 inst_base->idx = index;
1686 inst_base->br = TransExtData::DIRECT_BRANCH;
1687 return inst_base;
1688}
1689static ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index) {
1690 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(blx_1_thumb));
1691 blx_1_thumb* inst_cream = (blx_1_thumb*)inst_base->component;
1692
1693 inst_cream->imm = (tinst & 0x07FF) << 1;
1694 inst_cream->instr = tinst;
1695
1696 inst_base->idx = index;
1697 inst_base->br = TransExtData::DIRECT_BRANCH;
1698 return inst_base;
1699}
1700
1701static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index) {
1702 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
1703 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
1704
1705 inst_base->cond = BITS(inst, 28, 31);
1706 inst_base->idx = index;
1707 inst_base->br = TransExtData::NON_BRANCH;
1708
1709 inst_cream->Rm = BITS(inst, 0, 3);
1710 inst_cream->Rn = BITS(inst, 16, 19);
1711 inst_cream->Rd = BITS(inst, 12, 15);
1712 inst_cream->op1 = BITS(inst, 20, 21);
1713 inst_cream->op2 = BITS(inst, 5, 7);
1714
1715 return inst_base;
1716}
1717static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index) {
1718 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
1719}
1720static ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index) {
1721 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
1722}
1723static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index) {
1724 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
1725}
1726static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index) {
1727 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
1728}
1729static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index) {
1730 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
1731}
1732static ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index) {
1733 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
1734 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
1735
1736 inst_base->cond = BITS(inst, 28, 31);
1737 inst_base->idx = index;
1738 inst_base->br = TransExtData::NON_BRANCH;
1739
1740 inst_cream->op1 = BITS(inst, 20, 24);
1741 inst_cream->op2 = BITS(inst, 5, 7);
1742 inst_cream->Rd = BITS(inst, 16, 19);
1743 inst_cream->Rm = BITS(inst, 8, 11);
1744 inst_cream->Rn = BITS(inst, 0, 3);
1745 inst_cream->Ra = BITS(inst, 12, 15);
1746
1747 return inst_base;
1748}
1749static ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index) {
1750 return INTERPRETER_TRANSLATE(usada8)(inst, index);
1751}
1752static ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) {
1753 return INTERPRETER_TRANSLATE(ssat)(inst, index);
1754}
1755static ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) {
1756 return INTERPRETER_TRANSLATE(ssat16)(inst, index);
1757}
1758
1759static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index) {
1760 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst));
1761 uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
1762
1763 inst_base->cond = BITS(inst, 28, 31);
1764 inst_base->idx = index;
1765 inst_base->br = TransExtData::NON_BRANCH;
1766
1767 inst_cream->Rm = BITS(inst, 0, 3);
1768 inst_cream->Rn = BITS(inst, 16, 19);
1769 inst_cream->Rd = BITS(inst, 12, 15);
1770 inst_cream->rotate = BITS(inst, 10, 11);
1771
1772 return inst_base;
1773}
1774static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) {
1775 return INTERPRETER_TRANSLATE(uxtab16)(inst, index);
1776}
1777
1778static ARM_INST_PTR INTERPRETER_TRANSLATE(wfe)(unsigned int inst, int index) {
1779 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
1780
1781 inst_base->cond = BITS(inst, 28, 31);
1782 inst_base->idx = index;
1783 inst_base->br = TransExtData::NON_BRANCH;
1784
1785 return inst_base;
1786}
1787static ARM_INST_PTR INTERPRETER_TRANSLATE(wfi)(unsigned int inst, int index) {
1788 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
1789
1790 inst_base->cond = BITS(inst, 28, 31);
1791 inst_base->idx = index;
1792 inst_base->br = TransExtData::NON_BRANCH;
1793
1794 return inst_base;
1795}
1796static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index) {
1797 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
1798
1799 inst_base->cond = BITS(inst, 28, 31);
1800 inst_base->idx = index;
1801 inst_base->br = TransExtData::NON_BRANCH;
1802
1803 return inst_base;
1804}
1805
1806// Floating point VFPv3 instructions
1807#define VFP_INTERPRETER_TRANS
1808#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
1809#undef VFP_INTERPRETER_TRANS
1810
1811const transop_fp_t arm_instruction_trans[] = {
1812 INTERPRETER_TRANSLATE(vmla), INTERPRETER_TRANSLATE(vmls), INTERPRETER_TRANSLATE(vnmla),
1813 INTERPRETER_TRANSLATE(vnmls), INTERPRETER_TRANSLATE(vnmul), INTERPRETER_TRANSLATE(vmul),
1814 INTERPRETER_TRANSLATE(vadd), INTERPRETER_TRANSLATE(vsub), INTERPRETER_TRANSLATE(vdiv),
1815 INTERPRETER_TRANSLATE(vmovi), INTERPRETER_TRANSLATE(vmovr), INTERPRETER_TRANSLATE(vabs),
1816 INTERPRETER_TRANSLATE(vneg), INTERPRETER_TRANSLATE(vsqrt), INTERPRETER_TRANSLATE(vcmp),
1817 INTERPRETER_TRANSLATE(vcmp2), INTERPRETER_TRANSLATE(vcvtbds), INTERPRETER_TRANSLATE(vcvtbff),
1818 INTERPRETER_TRANSLATE(vcvtbfi), INTERPRETER_TRANSLATE(vmovbrs), INTERPRETER_TRANSLATE(vmsr),
1819 INTERPRETER_TRANSLATE(vmovbrc), INTERPRETER_TRANSLATE(vmrs), INTERPRETER_TRANSLATE(vmovbcr),
1820 INTERPRETER_TRANSLATE(vmovbrrss), INTERPRETER_TRANSLATE(vmovbrrd), INTERPRETER_TRANSLATE(vstr),
1821 INTERPRETER_TRANSLATE(vpush), INTERPRETER_TRANSLATE(vstm), INTERPRETER_TRANSLATE(vpop),
1822 INTERPRETER_TRANSLATE(vldr), INTERPRETER_TRANSLATE(vldm),
1823
1824 INTERPRETER_TRANSLATE(srs), INTERPRETER_TRANSLATE(rfe), INTERPRETER_TRANSLATE(bkpt),
1825 INTERPRETER_TRANSLATE(blx), INTERPRETER_TRANSLATE(cps), INTERPRETER_TRANSLATE(pld),
1826 INTERPRETER_TRANSLATE(setend), INTERPRETER_TRANSLATE(clrex), INTERPRETER_TRANSLATE(rev16),
1827 INTERPRETER_TRANSLATE(usad8), INTERPRETER_TRANSLATE(sxtb), INTERPRETER_TRANSLATE(uxtb),
1828 INTERPRETER_TRANSLATE(sxth), INTERPRETER_TRANSLATE(sxtb16), INTERPRETER_TRANSLATE(uxth),
1829 INTERPRETER_TRANSLATE(uxtb16), INTERPRETER_TRANSLATE(cpy), INTERPRETER_TRANSLATE(uxtab),
1830 INTERPRETER_TRANSLATE(ssub8), INTERPRETER_TRANSLATE(shsub8), INTERPRETER_TRANSLATE(ssubaddx),
1831 INTERPRETER_TRANSLATE(strex), INTERPRETER_TRANSLATE(strexb), INTERPRETER_TRANSLATE(swp),
1832 INTERPRETER_TRANSLATE(swpb), INTERPRETER_TRANSLATE(ssub16), INTERPRETER_TRANSLATE(ssat16),
1833 INTERPRETER_TRANSLATE(shsubaddx), INTERPRETER_TRANSLATE(qsubaddx),
1834 INTERPRETER_TRANSLATE(shaddsubx), INTERPRETER_TRANSLATE(shadd8), INTERPRETER_TRANSLATE(shadd16),
1835 INTERPRETER_TRANSLATE(sel), INTERPRETER_TRANSLATE(saddsubx), INTERPRETER_TRANSLATE(sadd8),
1836 INTERPRETER_TRANSLATE(sadd16), INTERPRETER_TRANSLATE(shsub16), INTERPRETER_TRANSLATE(umaal),
1837 INTERPRETER_TRANSLATE(uxtab16), INTERPRETER_TRANSLATE(usubaddx), INTERPRETER_TRANSLATE(usub8),
1838 INTERPRETER_TRANSLATE(usub16), INTERPRETER_TRANSLATE(usat16), INTERPRETER_TRANSLATE(usada8),
1839 INTERPRETER_TRANSLATE(uqsubaddx), INTERPRETER_TRANSLATE(uqsub8), INTERPRETER_TRANSLATE(uqsub16),
1840 INTERPRETER_TRANSLATE(uqaddsubx), INTERPRETER_TRANSLATE(uqadd8), INTERPRETER_TRANSLATE(uqadd16),
1841 INTERPRETER_TRANSLATE(sxtab), INTERPRETER_TRANSLATE(uhsubaddx), INTERPRETER_TRANSLATE(uhsub8),
1842 INTERPRETER_TRANSLATE(uhsub16), INTERPRETER_TRANSLATE(uhaddsubx), INTERPRETER_TRANSLATE(uhadd8),
1843 INTERPRETER_TRANSLATE(uhadd16), INTERPRETER_TRANSLATE(uaddsubx), INTERPRETER_TRANSLATE(uadd8),
1844 INTERPRETER_TRANSLATE(uadd16), INTERPRETER_TRANSLATE(sxtah), INTERPRETER_TRANSLATE(sxtab16),
1845 INTERPRETER_TRANSLATE(qadd8), INTERPRETER_TRANSLATE(bxj), INTERPRETER_TRANSLATE(clz),
1846 INTERPRETER_TRANSLATE(uxtah), INTERPRETER_TRANSLATE(bx), INTERPRETER_TRANSLATE(rev),
1847 INTERPRETER_TRANSLATE(blx), INTERPRETER_TRANSLATE(revsh), INTERPRETER_TRANSLATE(qadd),
1848 INTERPRETER_TRANSLATE(qadd16), INTERPRETER_TRANSLATE(qaddsubx), INTERPRETER_TRANSLATE(ldrex),
1849 INTERPRETER_TRANSLATE(qdadd), INTERPRETER_TRANSLATE(qdsub), INTERPRETER_TRANSLATE(qsub),
1850 INTERPRETER_TRANSLATE(ldrexb), INTERPRETER_TRANSLATE(qsub8), INTERPRETER_TRANSLATE(qsub16),
1851 INTERPRETER_TRANSLATE(smuad), INTERPRETER_TRANSLATE(smmul), INTERPRETER_TRANSLATE(smusd),
1852 INTERPRETER_TRANSLATE(smlsd), INTERPRETER_TRANSLATE(smlsld), INTERPRETER_TRANSLATE(smmla),
1853 INTERPRETER_TRANSLATE(smmls), INTERPRETER_TRANSLATE(smlald), INTERPRETER_TRANSLATE(smlad),
1854 INTERPRETER_TRANSLATE(smlaw), INTERPRETER_TRANSLATE(smulw), INTERPRETER_TRANSLATE(pkhtb),
1855 INTERPRETER_TRANSLATE(pkhbt), INTERPRETER_TRANSLATE(smul), INTERPRETER_TRANSLATE(smlalxy),
1856 INTERPRETER_TRANSLATE(smla), INTERPRETER_TRANSLATE(mcrr), INTERPRETER_TRANSLATE(mrrc),
1857 INTERPRETER_TRANSLATE(cmp), INTERPRETER_TRANSLATE(tst), INTERPRETER_TRANSLATE(teq),
1858 INTERPRETER_TRANSLATE(cmn), INTERPRETER_TRANSLATE(smull), INTERPRETER_TRANSLATE(umull),
1859 INTERPRETER_TRANSLATE(umlal), INTERPRETER_TRANSLATE(smlal), INTERPRETER_TRANSLATE(mul),
1860 INTERPRETER_TRANSLATE(mla), INTERPRETER_TRANSLATE(ssat), INTERPRETER_TRANSLATE(usat),
1861 INTERPRETER_TRANSLATE(mrs), INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(and),
1862 INTERPRETER_TRANSLATE(bic), INTERPRETER_TRANSLATE(ldm), INTERPRETER_TRANSLATE(eor),
1863 INTERPRETER_TRANSLATE(add), INTERPRETER_TRANSLATE(rsb), INTERPRETER_TRANSLATE(rsc),
1864 INTERPRETER_TRANSLATE(sbc), INTERPRETER_TRANSLATE(adc), INTERPRETER_TRANSLATE(sub),
1865 INTERPRETER_TRANSLATE(orr), INTERPRETER_TRANSLATE(mvn), INTERPRETER_TRANSLATE(mov),
1866 INTERPRETER_TRANSLATE(stm), INTERPRETER_TRANSLATE(ldm), INTERPRETER_TRANSLATE(ldrsh),
1867 INTERPRETER_TRANSLATE(stm), INTERPRETER_TRANSLATE(ldm), INTERPRETER_TRANSLATE(ldrsb),
1868 INTERPRETER_TRANSLATE(strd), INTERPRETER_TRANSLATE(ldrh), INTERPRETER_TRANSLATE(strh),
1869 INTERPRETER_TRANSLATE(ldrd), INTERPRETER_TRANSLATE(strt), INTERPRETER_TRANSLATE(strbt),
1870 INTERPRETER_TRANSLATE(ldrbt), INTERPRETER_TRANSLATE(ldrt), INTERPRETER_TRANSLATE(mrc),
1871 INTERPRETER_TRANSLATE(mcr), INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(msr),
1872 INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(msr),
1873 INTERPRETER_TRANSLATE(ldrb), INTERPRETER_TRANSLATE(strb), INTERPRETER_TRANSLATE(ldr),
1874 INTERPRETER_TRANSLATE(ldrcond), INTERPRETER_TRANSLATE(str), INTERPRETER_TRANSLATE(cdp),
1875 INTERPRETER_TRANSLATE(stc), INTERPRETER_TRANSLATE(ldc), INTERPRETER_TRANSLATE(ldrexd),
1876 INTERPRETER_TRANSLATE(strexd), INTERPRETER_TRANSLATE(ldrexh), INTERPRETER_TRANSLATE(strexh),
1877 INTERPRETER_TRANSLATE(nop), INTERPRETER_TRANSLATE(yield), INTERPRETER_TRANSLATE(wfe),
1878 INTERPRETER_TRANSLATE(wfi), INTERPRETER_TRANSLATE(sev), INTERPRETER_TRANSLATE(swi),
1879 INTERPRETER_TRANSLATE(bbl),
1880
1881 // All the thumb instructions should be placed the end of table
1882 INTERPRETER_TRANSLATE(b_2_thumb), INTERPRETER_TRANSLATE(b_cond_thumb),
1883 INTERPRETER_TRANSLATE(bl_1_thumb), INTERPRETER_TRANSLATE(bl_2_thumb),
1884 INTERPRETER_TRANSLATE(blx_1_thumb),
1885};
1886
1887const size_t arm_instruction_trans_len = sizeof(arm_instruction_trans) / sizeof(transop_fp_t);
diff --git a/src/core/arm/dyncom/arm_dyncom_trans.h b/src/core/arm/dyncom/arm_dyncom_trans.h
deleted file mode 100644
index 632ff2cd6..000000000
--- a/src/core/arm/dyncom/arm_dyncom_trans.h
+++ /dev/null
@@ -1,494 +0,0 @@
1#pragma once
2
3#include <cstddef>
4#include "common/common_types.h"
5
6struct ARMul_State;
7typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper);
8
9enum class TransExtData {
10 COND = (1 << 0),
11 NON_BRANCH = (1 << 1),
12 DIRECT_BRANCH = (1 << 2),
13 INDIRECT_BRANCH = (1 << 3),
14 CALL = (1 << 4),
15 RET = (1 << 5),
16 END_OF_PAGE = (1 << 6),
17 THUMB = (1 << 7),
18 SINGLE_STEP = (1 << 8)
19};
20
21struct arm_inst {
22 unsigned int idx;
23 unsigned int cond;
24 TransExtData br;
25 char component[0];
26};
27
28struct generic_arm_inst {
29 u32 Ra;
30 u32 Rm;
31 u32 Rn;
32 u32 Rd;
33 u8 op1;
34 u8 op2;
35};
36
37struct adc_inst {
38 unsigned int I;
39 unsigned int S;
40 unsigned int Rn;
41 unsigned int Rd;
42 unsigned int shifter_operand;
43 shtop_fp_t shtop_func;
44};
45
46struct add_inst {
47 unsigned int I;
48 unsigned int S;
49 unsigned int Rn;
50 unsigned int Rd;
51 unsigned int shifter_operand;
52 shtop_fp_t shtop_func;
53};
54
55struct orr_inst {
56 unsigned int I;
57 unsigned int S;
58 unsigned int Rn;
59 unsigned int Rd;
60 unsigned int shifter_operand;
61 shtop_fp_t shtop_func;
62};
63
64struct and_inst {
65 unsigned int I;
66 unsigned int S;
67 unsigned int Rn;
68 unsigned int Rd;
69 unsigned int shifter_operand;
70 shtop_fp_t shtop_func;
71};
72
73struct eor_inst {
74 unsigned int I;
75 unsigned int S;
76 unsigned int Rn;
77 unsigned int Rd;
78 unsigned int shifter_operand;
79 shtop_fp_t shtop_func;
80};
81
82struct bbl_inst {
83 unsigned int L;
84 int signed_immed_24;
85 unsigned int next_addr;
86 unsigned int jmp_addr;
87};
88
89struct bx_inst {
90 unsigned int Rm;
91};
92
93struct blx_inst {
94 union {
95 s32 signed_immed_24;
96 u32 Rm;
97 } val;
98 unsigned int inst;
99};
100
101struct clz_inst {
102 unsigned int Rm;
103 unsigned int Rd;
104};
105
106struct cps_inst {
107 unsigned int imod0;
108 unsigned int imod1;
109 unsigned int mmod;
110 unsigned int A, I, F;
111 unsigned int mode;
112};
113
114struct clrex_inst {};
115
116struct cpy_inst {
117 unsigned int Rm;
118 unsigned int Rd;
119};
120
121struct bic_inst {
122 unsigned int I;
123 unsigned int S;
124 unsigned int Rn;
125 unsigned int Rd;
126 unsigned int shifter_operand;
127 shtop_fp_t shtop_func;
128};
129
130struct sub_inst {
131 unsigned int I;
132 unsigned int S;
133 unsigned int Rn;
134 unsigned int Rd;
135 unsigned int shifter_operand;
136 shtop_fp_t shtop_func;
137};
138
139struct tst_inst {
140 unsigned int I;
141 unsigned int S;
142 unsigned int Rn;
143 unsigned int Rd;
144 unsigned int shifter_operand;
145 shtop_fp_t shtop_func;
146};
147
148struct cmn_inst {
149 unsigned int I;
150 unsigned int Rn;
151 unsigned int shifter_operand;
152 shtop_fp_t shtop_func;
153};
154
155struct teq_inst {
156 unsigned int I;
157 unsigned int Rn;
158 unsigned int shifter_operand;
159 shtop_fp_t shtop_func;
160};
161
162struct stm_inst {
163 unsigned int inst;
164};
165
166struct bkpt_inst {
167 u32 imm;
168};
169
170struct stc_inst {};
171
172struct ldc_inst {};
173
174struct swi_inst {
175 unsigned int num;
176};
177
178struct cmp_inst {
179 unsigned int I;
180 unsigned int Rn;
181 unsigned int shifter_operand;
182 shtop_fp_t shtop_func;
183};
184
185struct mov_inst {
186 unsigned int I;
187 unsigned int S;
188 unsigned int Rd;
189 unsigned int shifter_operand;
190 shtop_fp_t shtop_func;
191};
192
193struct mvn_inst {
194 unsigned int I;
195 unsigned int S;
196 unsigned int Rd;
197 unsigned int shifter_operand;
198 shtop_fp_t shtop_func;
199};
200
201struct rev_inst {
202 unsigned int Rd;
203 unsigned int Rm;
204 unsigned int op1;
205 unsigned int op2;
206};
207
208struct rsb_inst {
209 unsigned int I;
210 unsigned int S;
211 unsigned int Rn;
212 unsigned int Rd;
213 unsigned int shifter_operand;
214 shtop_fp_t shtop_func;
215};
216
217struct rsc_inst {
218 unsigned int I;
219 unsigned int S;
220 unsigned int Rn;
221 unsigned int Rd;
222 unsigned int shifter_operand;
223 shtop_fp_t shtop_func;
224};
225
226struct sbc_inst {
227 unsigned int I;
228 unsigned int S;
229 unsigned int Rn;
230 unsigned int Rd;
231 unsigned int shifter_operand;
232 shtop_fp_t shtop_func;
233};
234
235struct mul_inst {
236 unsigned int S;
237 unsigned int Rd;
238 unsigned int Rs;
239 unsigned int Rm;
240};
241
242struct smul_inst {
243 unsigned int Rd;
244 unsigned int Rs;
245 unsigned int Rm;
246 unsigned int x;
247 unsigned int y;
248};
249
250struct umull_inst {
251 unsigned int S;
252 unsigned int RdHi;
253 unsigned int RdLo;
254 unsigned int Rs;
255 unsigned int Rm;
256};
257
258struct smlad_inst {
259 unsigned int m;
260 unsigned int Rm;
261 unsigned int Rd;
262 unsigned int Ra;
263 unsigned int Rn;
264 unsigned int op1;
265 unsigned int op2;
266};
267
268struct smla_inst {
269 unsigned int x;
270 unsigned int y;
271 unsigned int Rm;
272 unsigned int Rd;
273 unsigned int Rs;
274 unsigned int Rn;
275};
276
277struct smlalxy_inst {
278 unsigned int x;
279 unsigned int y;
280 unsigned int RdLo;
281 unsigned int RdHi;
282 unsigned int Rm;
283 unsigned int Rn;
284};
285
286struct ssat_inst {
287 unsigned int Rn;
288 unsigned int Rd;
289 unsigned int imm5;
290 unsigned int sat_imm;
291 unsigned int shift_type;
292};
293
294struct umaal_inst {
295 unsigned int Rn;
296 unsigned int Rm;
297 unsigned int RdHi;
298 unsigned int RdLo;
299};
300
301struct umlal_inst {
302 unsigned int S;
303 unsigned int Rm;
304 unsigned int Rs;
305 unsigned int RdHi;
306 unsigned int RdLo;
307};
308
309struct smlal_inst {
310 unsigned int S;
311 unsigned int Rm;
312 unsigned int Rs;
313 unsigned int RdHi;
314 unsigned int RdLo;
315};
316
317struct smlald_inst {
318 unsigned int RdLo;
319 unsigned int RdHi;
320 unsigned int Rm;
321 unsigned int Rn;
322 unsigned int swap;
323 unsigned int op1;
324 unsigned int op2;
325};
326
327struct mla_inst {
328 unsigned int S;
329 unsigned int Rn;
330 unsigned int Rd;
331 unsigned int Rs;
332 unsigned int Rm;
333};
334
335struct mrc_inst {
336 unsigned int opcode_1;
337 unsigned int opcode_2;
338 unsigned int cp_num;
339 unsigned int crn;
340 unsigned int crm;
341 unsigned int Rd;
342 unsigned int inst;
343};
344
345struct mcr_inst {
346 unsigned int opcode_1;
347 unsigned int opcode_2;
348 unsigned int cp_num;
349 unsigned int crn;
350 unsigned int crm;
351 unsigned int Rd;
352 unsigned int inst;
353};
354
355struct mcrr_inst {
356 unsigned int opcode_1;
357 unsigned int cp_num;
358 unsigned int crm;
359 unsigned int rt;
360 unsigned int rt2;
361};
362
363struct mrs_inst {
364 unsigned int R;
365 unsigned int Rd;
366};
367
368struct msr_inst {
369 unsigned int field_mask;
370 unsigned int R;
371 unsigned int inst;
372};
373
374struct pld_inst {};
375
376struct sxtb_inst {
377 unsigned int Rd;
378 unsigned int Rm;
379 unsigned int rotate;
380};
381
382struct sxtab_inst {
383 unsigned int Rd;
384 unsigned int Rn;
385 unsigned int Rm;
386 unsigned rotate;
387};
388
389struct sxtah_inst {
390 unsigned int Rd;
391 unsigned int Rn;
392 unsigned int Rm;
393 unsigned int rotate;
394};
395
396struct sxth_inst {
397 unsigned int Rd;
398 unsigned int Rm;
399 unsigned int rotate;
400};
401
402struct uxtab_inst {
403 unsigned int Rn;
404 unsigned int Rd;
405 unsigned int rotate;
406 unsigned int Rm;
407};
408
409struct uxtah_inst {
410 unsigned int Rn;
411 unsigned int Rd;
412 unsigned int rotate;
413 unsigned int Rm;
414};
415
416struct uxth_inst {
417 unsigned int Rd;
418 unsigned int Rm;
419 unsigned int rotate;
420};
421
422struct cdp_inst {
423 unsigned int opcode_1;
424 unsigned int CRn;
425 unsigned int CRd;
426 unsigned int cp_num;
427 unsigned int opcode_2;
428 unsigned int CRm;
429 unsigned int inst;
430};
431
432struct uxtb_inst {
433 unsigned int Rd;
434 unsigned int Rm;
435 unsigned int rotate;
436};
437
438struct swp_inst {
439 unsigned int Rn;
440 unsigned int Rd;
441 unsigned int Rm;
442};
443
444struct setend_inst {
445 unsigned int set_bigend;
446};
447
448struct b_2_thumb {
449 unsigned int imm;
450};
451struct b_cond_thumb {
452 unsigned int imm;
453 unsigned int cond;
454};
455
456struct bl_1_thumb {
457 unsigned int imm;
458};
459struct bl_2_thumb {
460 unsigned int imm;
461};
462struct blx_1_thumb {
463 unsigned int imm;
464 unsigned int instr;
465};
466
467struct pkh_inst {
468 unsigned int Rm;
469 unsigned int Rn;
470 unsigned int Rd;
471 unsigned char imm;
472};
473
474// Floating point VFPv3 structures
475#define VFP_INTERPRETER_STRUCT
476#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
477#undef VFP_INTERPRETER_STRUCT
478
479typedef void (*get_addr_fp_t)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr);
480
481struct ldst_inst {
482 unsigned int inst;
483 get_addr_fp_t get_addr;
484};
485
486typedef arm_inst* ARM_INST_PTR;
487typedef ARM_INST_PTR (*transop_fp_t)(unsigned int, int);
488
489extern const transop_fp_t arm_instruction_trans[];
490extern const size_t arm_instruction_trans_len;
491
492#define TRANS_CACHE_SIZE (64 * 1024 * 2000)
493extern char trans_cache_buf[TRANS_CACHE_SIZE];
494extern size_t trans_cache_buf_top;