1 /* This file is part of the dynarmic project.
2 * Copyright (c) 2016 MerryMage
3 * SPDX-License-Identifier: 0BSD
4 */
5
6 #include "frontend/A32/translate/impl/translate_arm.h"
7
8 namespace Dynarmic::A32 {
9
Rotate(A32::IREmitter & ir,Reg m,SignExtendRotation rotate)10 static IR::U32 Rotate(A32::IREmitter& ir, Reg m, SignExtendRotation rotate) {
11 const u8 rotate_by = static_cast<u8>(static_cast<size_t>(rotate) * 8);
12 return ir.RotateRight(ir.GetRegister(m), ir.Imm8(rotate_by), ir.Imm1(0)).result;
13 }
14
15 // SXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
arm_SXTAB(Cond cond,Reg n,Reg d,SignExtendRotation rotate,Reg m)16 bool ArmTranslatorVisitor::arm_SXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
17 if (d == Reg::PC || m == Reg::PC) {
18 return UnpredictableInstruction();
19 }
20
21 if (!ConditionPassed(cond)) {
22 return true;
23 }
24
25 const auto rotated = Rotate(ir, m, rotate);
26 const auto reg_n = ir.GetRegister(n);
27 const auto result = ir.Add(reg_n, ir.SignExtendByteToWord(ir.LeastSignificantByte(rotated)));
28
29 ir.SetRegister(d, result);
30 return true;
31 }
32
33 // SXTAB16<c> <Rd>, <Rn>, <Rm>{, <rotation>}
arm_SXTAB16(Cond cond,Reg n,Reg d,SignExtendRotation rotate,Reg m)34 bool ArmTranslatorVisitor::arm_SXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
35 if (d == Reg::PC || m == Reg::PC) {
36 return UnpredictableInstruction();
37 }
38
39 if (!ConditionPassed(cond)) {
40 return true;
41 }
42
43 const auto rotated = Rotate(ir, m, rotate);
44 const auto low_byte = ir.And(rotated, ir.Imm32(0x00FF00FF));
45 const auto sign_bit = ir.And(rotated, ir.Imm32(0x00800080));
46 const auto addend = ir.Or(low_byte, ir.Mul(sign_bit, ir.Imm32(0x1FE)));
47 const auto result = ir.PackedAddU16(addend, ir.GetRegister(n)).result;
48
49 ir.SetRegister(d, result);
50 return true;
51 }
52
53 // SXTAH<c> <Rd>, <Rn>, <Rm>{, <rotation>}
arm_SXTAH(Cond cond,Reg n,Reg d,SignExtendRotation rotate,Reg m)54 bool ArmTranslatorVisitor::arm_SXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
55 if (d == Reg::PC || m == Reg::PC) {
56 return UnpredictableInstruction();
57 }
58
59 if (!ConditionPassed(cond)) {
60 return true;
61 }
62
63 const auto rotated = Rotate(ir, m, rotate);
64 const auto reg_n = ir.GetRegister(n);
65 const auto result = ir.Add(reg_n, ir.SignExtendHalfToWord(ir.LeastSignificantHalf(rotated)));
66
67 ir.SetRegister(d, result);
68 return true;
69 }
70
71 // SXTB<c> <Rd>, <Rm>{, <rotation>}
arm_SXTB(Cond cond,Reg d,SignExtendRotation rotate,Reg m)72 bool ArmTranslatorVisitor::arm_SXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
73 if (d == Reg::PC || m == Reg::PC) {
74 return UnpredictableInstruction();
75 }
76
77 if (!ConditionPassed(cond)) {
78 return true;
79 }
80
81 const auto rotated = Rotate(ir, m, rotate);
82 const auto result = ir.SignExtendByteToWord(ir.LeastSignificantByte(rotated));
83
84 ir.SetRegister(d, result);
85 return true;
86 }
87
88 // SXTB16<c> <Rd>, <Rm>{, <rotation>}
arm_SXTB16(Cond cond,Reg d,SignExtendRotation rotate,Reg m)89 bool ArmTranslatorVisitor::arm_SXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
90 if (d == Reg::PC || m == Reg::PC) {
91 return UnpredictableInstruction();
92 }
93
94 if (!ConditionPassed(cond)) {
95 return true;
96 }
97
98 const auto rotated = Rotate(ir, m, rotate);
99 const auto low_byte = ir.And(rotated, ir.Imm32(0x00FF00FF));
100 const auto sign_bit = ir.And(rotated, ir.Imm32(0x00800080));
101 const auto result = ir.Or(low_byte, ir.Mul(sign_bit, ir.Imm32(0x1FE)));
102
103 ir.SetRegister(d, result);
104 return true;
105 }
106
107 // SXTH<c> <Rd>, <Rm>{, <rotation>}
arm_SXTH(Cond cond,Reg d,SignExtendRotation rotate,Reg m)108 bool ArmTranslatorVisitor::arm_SXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
109 if (d == Reg::PC || m == Reg::PC) {
110 return UnpredictableInstruction();
111 }
112
113 if (!ConditionPassed(cond)) {
114 return true;
115 }
116
117 const auto rotated = Rotate(ir, m, rotate);
118 const auto result = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(rotated));
119
120 ir.SetRegister(d, result);
121 return true;
122 }
123
124 // UXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
arm_UXTAB(Cond cond,Reg n,Reg d,SignExtendRotation rotate,Reg m)125 bool ArmTranslatorVisitor::arm_UXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
126 if (d == Reg::PC || m == Reg::PC) {
127 return UnpredictableInstruction();
128 }
129
130 if (!ConditionPassed(cond)) {
131 return true;
132 }
133
134 const auto rotated = Rotate(ir, m, rotate);
135 const auto reg_n = ir.GetRegister(n);
136 const auto result = ir.Add(reg_n, ir.ZeroExtendByteToWord(ir.LeastSignificantByte(rotated)));
137
138 ir.SetRegister(d, result);
139 return true;
140 }
141
142 // UXTAB16<c> <Rd>, <Rn>, <Rm>{, <rotation>}
arm_UXTAB16(Cond cond,Reg n,Reg d,SignExtendRotation rotate,Reg m)143 bool ArmTranslatorVisitor::arm_UXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
144 if (d == Reg::PC || m == Reg::PC || n == Reg::PC) {
145 return UnpredictableInstruction();
146 }
147
148 if (!ConditionPassed(cond)) {
149 return true;
150 }
151
152 const auto rotated = Rotate(ir, m, rotate);
153 auto result = ir.And(rotated, ir.Imm32(0x00FF00FF));
154 const auto reg_n = ir.GetRegister(n);
155 result = ir.PackedAddU16(reg_n, result).result;
156
157 ir.SetRegister(d, result);
158 return true;
159 }
160
161 // UXTAH<c> <Rd>, <Rn>, <Rm>{, <rotation>}
arm_UXTAH(Cond cond,Reg n,Reg d,SignExtendRotation rotate,Reg m)162 bool ArmTranslatorVisitor::arm_UXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
163 if (d == Reg::PC || m == Reg::PC) {
164 return UnpredictableInstruction();
165 }
166
167 if (!ConditionPassed(cond)) {
168 return true;
169 }
170
171 const auto rotated = Rotate(ir, m, rotate);
172 const auto reg_n = ir.GetRegister(n);
173 const auto result = ir.Add(reg_n, ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(rotated)));
174
175 ir.SetRegister(d, result);
176 return true;
177 }
178
179 // UXTB<c> <Rd>, <Rm>{, <rotation>}
arm_UXTB(Cond cond,Reg d,SignExtendRotation rotate,Reg m)180 bool ArmTranslatorVisitor::arm_UXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
181 if (d == Reg::PC || m == Reg::PC) {
182 return UnpredictableInstruction();
183 }
184
185 if (!ConditionPassed(cond)) {
186 return true;
187 }
188
189 const auto rotated = Rotate(ir, m, rotate);
190 const auto result = ir.ZeroExtendByteToWord(ir.LeastSignificantByte(rotated));
191 ir.SetRegister(d, result);
192 return true;
193 }
194
195 // UXTB16<c> <Rd>, <Rm>{, <rotation>}
arm_UXTB16(Cond cond,Reg d,SignExtendRotation rotate,Reg m)196 bool ArmTranslatorVisitor::arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
197 if (d == Reg::PC || m == Reg::PC) {
198 return UnpredictableInstruction();
199 }
200
201 if (!ConditionPassed(cond)) {
202 return true;
203 }
204
205 const auto rotated = Rotate(ir, m, rotate);
206 const auto result = ir.And(rotated, ir.Imm32(0x00FF00FF));
207
208 ir.SetRegister(d, result);
209 return true;
210 }
211
212 // UXTH<c> <Rd>, <Rm>{, <rotation>}
arm_UXTH(Cond cond,Reg d,SignExtendRotation rotate,Reg m)213 bool ArmTranslatorVisitor::arm_UXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
214 if (d == Reg::PC || m == Reg::PC) {
215 return UnpredictableInstruction();
216 }
217
218 if (!ConditionPassed(cond)) {
219 return true;
220 }
221
222 const auto rotated = Rotate(ir, m, rotate);
223 const auto result = ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(rotated));
224
225 ir.SetRegister(d, result);
226 return true;
227 }
228
229 } // namespace Dynarmic::A32
230