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
10 // ADC{S}<c> <Rd>, <Rn>, #<imm>
arm_ADC_imm(Cond cond,bool S,Reg n,Reg d,int rotate,Imm<8> imm8)11 bool ArmTranslatorVisitor::arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
12 if (!ConditionPassed(cond)) {
13 return true;
14 }
15
16 const u32 imm32 = ArmExpandImm(rotate, imm8);
17 const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.GetCFlag());
18 if (d == Reg::PC) {
19 if (S) {
20 // This is UNPREDICTABLE when in user-mode.
21 return UnpredictableInstruction();
22 }
23
24 ir.ALUWritePC(result.result);
25 ir.SetTerm(IR::Term::ReturnToDispatch{});
26 return false;
27 }
28
29 ir.SetRegister(d, result.result);
30 if (S) {
31 ir.SetNFlag(ir.MostSignificantBit(result.result));
32 ir.SetZFlag(ir.IsZero(result.result));
33 ir.SetCFlag(result.carry);
34 ir.SetVFlag(result.overflow);
35 }
36 return true;
37 }
38
39 // ADC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
arm_ADC_reg(Cond cond,bool S,Reg n,Reg d,Imm<5> imm5,ShiftType shift,Reg m)40 bool ArmTranslatorVisitor::arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
41 if (!ConditionPassed(cond)) {
42 return true;
43 }
44
45 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
46 const auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.GetCFlag());
47 if (d == Reg::PC) {
48 if (S) {
49 // This is UNPREDICTABLE when in user-mode.
50 return UnpredictableInstruction();
51 }
52
53 ir.ALUWritePC(result.result);
54 ir.SetTerm(IR::Term::ReturnToDispatch{});
55 return false;
56 }
57
58 ir.SetRegister(d, result.result);
59 if (S) {
60 ir.SetNFlag(ir.MostSignificantBit(result.result));
61 ir.SetZFlag(ir.IsZero(result.result));
62 ir.SetCFlag(result.carry);
63 ir.SetVFlag(result.overflow);
64 }
65
66 return true;
67 }
68
69 // ADC{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
arm_ADC_rsr(Cond cond,bool S,Reg n,Reg d,Reg s,ShiftType shift,Reg m)70 bool ArmTranslatorVisitor::arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
71 if (d == Reg::PC || n == Reg::PC || m == Reg::PC || s == Reg::PC) {
72 return UnpredictableInstruction();
73 }
74
75 if (!ConditionPassed(cond)) {
76 return true;
77 }
78
79 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
80 const auto carry_in = ir.GetCFlag();
81 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
82 const auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.GetCFlag());
83
84 ir.SetRegister(d, result.result);
85 if (S) {
86 ir.SetNFlag(ir.MostSignificantBit(result.result));
87 ir.SetZFlag(ir.IsZero(result.result));
88 ir.SetCFlag(result.carry);
89 ir.SetVFlag(result.overflow);
90 }
91
92 return true;
93 }
94
95 // ADD{S}<c> <Rd>, <Rn>, #<const>
arm_ADD_imm(Cond cond,bool S,Reg n,Reg d,int rotate,Imm<8> imm8)96 bool ArmTranslatorVisitor::arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
97 if (!ConditionPassed(cond)) {
98 return true;
99 }
100
101 const u32 imm32 = ArmExpandImm(rotate, imm8);
102 const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0));
103 if (d == Reg::PC) {
104 if (S) {
105 // This is UNPREDICTABLE when in user-mode.
106 return UnpredictableInstruction();
107 }
108
109 ir.ALUWritePC(result.result);
110 ir.SetTerm(IR::Term::ReturnToDispatch{});
111 return false;
112 }
113
114 ir.SetRegister(d, result.result);
115 if (S) {
116 ir.SetNFlag(ir.MostSignificantBit(result.result));
117 ir.SetZFlag(ir.IsZero(result.result));
118 ir.SetCFlag(result.carry);
119 ir.SetVFlag(result.overflow);
120 }
121
122 return true;
123 }
124
125 // ADD{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
arm_ADD_reg(Cond cond,bool S,Reg n,Reg d,Imm<5> imm5,ShiftType shift,Reg m)126 bool ArmTranslatorVisitor::arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
127 if (!ConditionPassed(cond)) {
128 return true;
129 }
130
131 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
132 const auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(0));
133 if (d == Reg::PC) {
134 if (S) {
135 // This is UNPREDICTABLE when in user-mode.
136 return UnpredictableInstruction();
137 }
138
139 ir.ALUWritePC(result.result);
140 ir.SetTerm(IR::Term::ReturnToDispatch{});
141 return false;
142 }
143
144 ir.SetRegister(d, result.result);
145 if (S) {
146 ir.SetNFlag(ir.MostSignificantBit(result.result));
147 ir.SetZFlag(ir.IsZero(result.result));
148 ir.SetCFlag(result.carry);
149 ir.SetVFlag(result.overflow);
150 }
151
152 return true;
153 }
154
155 // ADD{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
arm_ADD_rsr(Cond cond,bool S,Reg n,Reg d,Reg s,ShiftType shift,Reg m)156 bool ArmTranslatorVisitor::arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
157 if (d == Reg::PC || n == Reg::PC || m == Reg::PC || s == Reg::PC) {
158 return UnpredictableInstruction();
159 }
160
161 if (!ConditionPassed(cond)) {
162 return true;
163 }
164
165 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
166 const auto carry_in = ir.GetCFlag();
167 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
168 const auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(0));
169
170 ir.SetRegister(d, result.result);
171 if (S) {
172 ir.SetNFlag(ir.MostSignificantBit(result.result));
173 ir.SetZFlag(ir.IsZero(result.result));
174 ir.SetCFlag(result.carry);
175 ir.SetVFlag(result.overflow);
176 }
177
178 return true;
179 }
180
181 // AND{S}<c> <Rd>, <Rn>, #<const>
arm_AND_imm(Cond cond,bool S,Reg n,Reg d,int rotate,Imm<8> imm8)182 bool ArmTranslatorVisitor::arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
183 if (!ConditionPassed(cond)) {
184 return true;
185 }
186
187 const auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
188 const auto result = ir.And(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
189 if (d == Reg::PC) {
190 if (S) {
191 // This is UNPREDICTABLE when in user-mode.
192 return UnpredictableInstruction();
193 }
194
195 ir.ALUWritePC(result);
196 ir.SetTerm(IR::Term::ReturnToDispatch{});
197 return false;
198 }
199
200 ir.SetRegister(d, result);
201 if (S) {
202 ir.SetNFlag(ir.MostSignificantBit(result));
203 ir.SetZFlag(ir.IsZero(result));
204 ir.SetCFlag(imm_carry.carry);
205 }
206
207 return true;
208 }
209
210 // AND{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
arm_AND_reg(Cond cond,bool S,Reg n,Reg d,Imm<5> imm5,ShiftType shift,Reg m)211 bool ArmTranslatorVisitor::arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
212 if (!ConditionPassed(cond)) {
213 return true;
214 }
215
216 const auto carry_in = ir.GetCFlag();
217 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
218 const auto result = ir.And(ir.GetRegister(n), shifted.result);
219 if (d == Reg::PC) {
220 if (S) {
221 // This is UNPREDICTABLE when in user-mode.
222 return UnpredictableInstruction();
223 }
224
225 ir.ALUWritePC(result);
226 ir.SetTerm(IR::Term::ReturnToDispatch{});
227 return false;
228 }
229 ir.SetRegister(d, result);
230 if (S) {
231 ir.SetNFlag(ir.MostSignificantBit(result));
232 ir.SetZFlag(ir.IsZero(result));
233 ir.SetCFlag(shifted.carry);
234 }
235
236 return true;
237 }
238
239 // AND{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
arm_AND_rsr(Cond cond,bool S,Reg n,Reg d,Reg s,ShiftType shift,Reg m)240 bool ArmTranslatorVisitor::arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
241 if (d == Reg::PC || n == Reg::PC || m == Reg::PC || s == Reg::PC) {
242 return UnpredictableInstruction();
243 }
244
245 if (!ConditionPassed(cond)) {
246 return true;
247 }
248
249 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
250 const auto carry_in = ir.GetCFlag();
251 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
252 const auto result = ir.And(ir.GetRegister(n), shifted.result);
253
254 ir.SetRegister(d, result);
255 if (S) {
256 ir.SetNFlag(ir.MostSignificantBit(result));
257 ir.SetZFlag(ir.IsZero(result));
258 ir.SetCFlag(shifted.carry);
259 }
260
261 return true;
262 }
263
264 // BIC{S}<c> <Rd>, <Rn>, #<const>
arm_BIC_imm(Cond cond,bool S,Reg n,Reg d,int rotate,Imm<8> imm8)265 bool ArmTranslatorVisitor::arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
266 if (!ConditionPassed(cond)) {
267 return true;
268 }
269
270 const auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
271 const auto result = ir.And(ir.GetRegister(n), ir.Not(ir.Imm32(imm_carry.imm32)));
272 if (d == Reg::PC) {
273 if (S) {
274 // This is UNPREDICTABLE when in user-mode.
275 return UnpredictableInstruction();
276 }
277
278 ir.ALUWritePC(result);
279 ir.SetTerm(IR::Term::ReturnToDispatch{});
280 return false;
281 }
282
283 ir.SetRegister(d, result);
284 if (S) {
285 ir.SetNFlag(ir.MostSignificantBit(result));
286 ir.SetZFlag(ir.IsZero(result));
287 ir.SetCFlag(imm_carry.carry);
288 }
289
290 return true;
291 }
292
293 // BIC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
arm_BIC_reg(Cond cond,bool S,Reg n,Reg d,Imm<5> imm5,ShiftType shift,Reg m)294 bool ArmTranslatorVisitor::arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
295 if (!ConditionPassed(cond)) {
296 return true;
297 }
298
299 const auto carry_in = ir.GetCFlag();
300 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
301 const auto result = ir.And(ir.GetRegister(n), ir.Not(shifted.result));
302 if (d == Reg::PC) {
303 if (S) {
304 // This is UNPREDICTABLE when in user-mode.
305 return UnpredictableInstruction();
306 }
307
308 ir.ALUWritePC(result);
309 ir.SetTerm(IR::Term::ReturnToDispatch{});
310 return false;
311 }
312
313 ir.SetRegister(d, result);
314 if (S) {
315 ir.SetNFlag(ir.MostSignificantBit(result));
316 ir.SetZFlag(ir.IsZero(result));
317 ir.SetCFlag(shifted.carry);
318 }
319
320 return true;
321 }
322
323 // BIC{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
arm_BIC_rsr(Cond cond,bool S,Reg n,Reg d,Reg s,ShiftType shift,Reg m)324 bool ArmTranslatorVisitor::arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
325 if (d == Reg::PC || n == Reg::PC || m == Reg::PC || s == Reg::PC) {
326 return UnpredictableInstruction();
327 }
328
329 if (!ConditionPassed(cond)) {
330 return true;
331 }
332
333 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
334 const auto carry_in = ir.GetCFlag();
335 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
336 const auto result = ir.And(ir.GetRegister(n), ir.Not(shifted.result));
337
338 ir.SetRegister(d, result);
339 if (S) {
340 ir.SetNFlag(ir.MostSignificantBit(result));
341 ir.SetZFlag(ir.IsZero(result));
342 ir.SetCFlag(shifted.carry);
343 }
344
345 return true;
346 }
347
348 // CMN<c> <Rn>, #<const>
arm_CMN_imm(Cond cond,Reg n,int rotate,Imm<8> imm8)349 bool ArmTranslatorVisitor::arm_CMN_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
350 if (!ConditionPassed(cond)) {
351 return true;
352 }
353
354 const u32 imm32 = ArmExpandImm(rotate, imm8);
355 const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0));
356
357 ir.SetNFlag(ir.MostSignificantBit(result.result));
358 ir.SetZFlag(ir.IsZero(result.result));
359 ir.SetCFlag(result.carry);
360 ir.SetVFlag(result.overflow);
361 return true;
362 }
363
364 // CMN<c> <Rn>, <Rm>{, <shift>}
arm_CMN_reg(Cond cond,Reg n,Imm<5> imm5,ShiftType shift,Reg m)365 bool ArmTranslatorVisitor::arm_CMN_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
366 if (!ConditionPassed(cond)) {
367 return true;
368 }
369
370 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
371 const auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(0));
372
373 ir.SetNFlag(ir.MostSignificantBit(result.result));
374 ir.SetZFlag(ir.IsZero(result.result));
375 ir.SetCFlag(result.carry);
376 ir.SetVFlag(result.overflow);
377 return true;
378 }
379
380 // CMN<c> <Rn>, <Rm>, <type> <Rs>
arm_CMN_rsr(Cond cond,Reg n,Reg s,ShiftType shift,Reg m)381 bool ArmTranslatorVisitor::arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
382 if (n == Reg::PC || m == Reg::PC || s == Reg::PC) {
383 return UnpredictableInstruction();
384 }
385
386 if (!ConditionPassed(cond)) {
387 return true;
388 }
389
390 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
391 const auto carry_in = ir.GetCFlag();
392 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
393 const auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(0));
394
395 ir.SetNFlag(ir.MostSignificantBit(result.result));
396 ir.SetZFlag(ir.IsZero(result.result));
397 ir.SetCFlag(result.carry);
398 ir.SetVFlag(result.overflow);
399 return true;
400 }
401
402 // CMP<c> <Rn>, #<imm>
arm_CMP_imm(Cond cond,Reg n,int rotate,Imm<8> imm8)403 bool ArmTranslatorVisitor::arm_CMP_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
404 if (!ConditionPassed(cond)) {
405 return true;
406 }
407
408 const u32 imm32 = ArmExpandImm(rotate, imm8);
409 const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
410
411 ir.SetNFlag(ir.MostSignificantBit(result.result));
412 ir.SetZFlag(ir.IsZero(result.result));
413 ir.SetCFlag(result.carry);
414 ir.SetVFlag(result.overflow);
415 return true;
416 }
417
418 // CMP<c> <Rn>, <Rm>{, <shift>}
arm_CMP_reg(Cond cond,Reg n,Imm<5> imm5,ShiftType shift,Reg m)419 bool ArmTranslatorVisitor::arm_CMP_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
420 if (!ConditionPassed(cond)) {
421 return true;
422 }
423
424 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
425 const auto result = ir.SubWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(1));
426
427 ir.SetNFlag(ir.MostSignificantBit(result.result));
428 ir.SetZFlag(ir.IsZero(result.result));
429 ir.SetCFlag(result.carry);
430 ir.SetVFlag(result.overflow);
431 return true;
432 }
433
434 // CMP<c> <Rn>, <Rm>, <type> <Rs>
arm_CMP_rsr(Cond cond,Reg n,Reg s,ShiftType shift,Reg m)435 bool ArmTranslatorVisitor::arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
436 if (n == Reg::PC || m == Reg::PC || s == Reg::PC) {
437 return UnpredictableInstruction();
438 }
439
440 if (!ConditionPassed(cond)) {
441 return true;
442 }
443
444 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
445 const auto carry_in = ir.GetCFlag();
446 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
447 const auto result = ir.SubWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(1));
448
449 ir.SetNFlag(ir.MostSignificantBit(result.result));
450 ir.SetZFlag(ir.IsZero(result.result));
451 ir.SetCFlag(result.carry);
452 ir.SetVFlag(result.overflow);
453 return true;
454 }
455
456 // EOR{S}<c> <Rd>, <Rn>, #<const>
arm_EOR_imm(Cond cond,bool S,Reg n,Reg d,int rotate,Imm<8> imm8)457 bool ArmTranslatorVisitor::arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
458 if (!ConditionPassed(cond)) {
459 return true;
460 }
461
462 const auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
463 const auto result = ir.Eor(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
464 if (d == Reg::PC) {
465 if (S) {
466 // This is UNPREDICTABLE when in user-mode.
467 return UnpredictableInstruction();
468 }
469
470 ir.ALUWritePC(result);
471 ir.SetTerm(IR::Term::ReturnToDispatch{});
472 return false;
473 }
474
475 ir.SetRegister(d, result);
476 if (S) {
477 ir.SetNFlag(ir.MostSignificantBit(result));
478 ir.SetZFlag(ir.IsZero(result));
479 ir.SetCFlag(imm_carry.carry);
480 }
481
482 return true;
483 }
484
485 // EOR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
arm_EOR_reg(Cond cond,bool S,Reg n,Reg d,Imm<5> imm5,ShiftType shift,Reg m)486 bool ArmTranslatorVisitor::arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
487 if (!ConditionPassed(cond)) {
488 return true;
489 }
490
491 const auto carry_in = ir.GetCFlag();
492 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
493 const auto result = ir.Eor(ir.GetRegister(n), shifted.result);
494 if (d == Reg::PC) {
495 if (S) {
496 // This is UNPREDICTABLE when in user-mode.
497 return UnpredictableInstruction();
498 }
499
500 ir.ALUWritePC(result);
501 ir.SetTerm(IR::Term::ReturnToDispatch{});
502 return false;
503 }
504
505 ir.SetRegister(d, result);
506 if (S) {
507 ir.SetNFlag(ir.MostSignificantBit(result));
508 ir.SetZFlag(ir.IsZero(result));
509 ir.SetCFlag(shifted.carry);
510 }
511
512 return true;
513 }
514
515 // EOR{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
arm_EOR_rsr(Cond cond,bool S,Reg n,Reg d,Reg s,ShiftType shift,Reg m)516 bool ArmTranslatorVisitor::arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
517 if (d == Reg::PC || n == Reg::PC || m == Reg::PC || s == Reg::PC) {
518 return UnpredictableInstruction();
519 }
520
521 if (!ConditionPassed(cond)) {
522 return true;
523 }
524
525 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
526 const auto carry_in = ir.GetCFlag();
527 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
528 const auto result = ir.Eor(ir.GetRegister(n), shifted.result);
529
530 ir.SetRegister(d, result);
531 if (S) {
532 ir.SetNFlag(ir.MostSignificantBit(result));
533 ir.SetZFlag(ir.IsZero(result));
534 ir.SetCFlag(shifted.carry);
535 }
536
537 return true;
538 }
539
540 // MOV{S}<c> <Rd>, #<const>
arm_MOV_imm(Cond cond,bool S,Reg d,int rotate,Imm<8> imm8)541 bool ArmTranslatorVisitor::arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8) {
542 if (!ConditionPassed(cond)) {
543 return true;
544 }
545
546 const auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
547 const auto result = ir.Imm32(imm_carry.imm32);
548 if (d == Reg::PC) {
549 if (S) {
550 // This is UNPREDICTABLE when in user-mode.
551 return UnpredictableInstruction();
552 }
553
554 ir.ALUWritePC(result);
555 ir.SetTerm(IR::Term::ReturnToDispatch{});
556 return false;
557 }
558
559 ir.SetRegister(d, result);
560 if (S) {
561 ir.SetNFlag(ir.MostSignificantBit(result));
562 ir.SetZFlag(ir.IsZero(result));
563 ir.SetCFlag(imm_carry.carry);
564 }
565
566 return true;
567 }
568
569 // MOV{S}<c> <Rd>, <Rm>
arm_MOV_reg(Cond cond,bool S,Reg d,Imm<5> imm5,ShiftType shift,Reg m)570 bool ArmTranslatorVisitor::arm_MOV_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
571 if (!ConditionPassed(cond)) {
572 return true;
573 }
574
575 const auto carry_in = ir.GetCFlag();
576 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
577 const auto result = shifted.result;
578 if (d == Reg::PC) {
579 if (S) {
580 // This is UNPREDICTABLE when in user-mode.
581 return UnpredictableInstruction();
582 }
583
584 ir.ALUWritePC(result);
585 ir.SetTerm(IR::Term::ReturnToDispatch{});
586 return false;
587 }
588
589 ir.SetRegister(d, result);
590 if (S) {
591 ir.SetNFlag(ir.MostSignificantBit(result));
592 ir.SetZFlag(ir.IsZero(result));
593 ir.SetCFlag(shifted.carry);
594 }
595
596 return true;
597 }
598
arm_MOV_rsr(Cond cond,bool S,Reg d,Reg s,ShiftType shift,Reg m)599 bool ArmTranslatorVisitor::arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) {
600 if (d == Reg::PC || m == Reg::PC || s == Reg::PC) {
601 return UnpredictableInstruction();
602 }
603
604 if (!ConditionPassed(cond)) {
605 return true;
606 }
607
608 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
609 const auto carry_in = ir.GetCFlag();
610 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
611 const auto result = shifted.result;
612 ir.SetRegister(d, result);
613 if (S) {
614 ir.SetNFlag(ir.MostSignificantBit(result));
615 ir.SetZFlag(ir.IsZero(result));
616 ir.SetCFlag(shifted.carry);
617 }
618
619 return true;
620 }
621
622 // MVN{S}<c> <Rd>, #<const>
arm_MVN_imm(Cond cond,bool S,Reg d,int rotate,Imm<8> imm8)623 bool ArmTranslatorVisitor::arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8) {
624 if (!ConditionPassed(cond)) {
625 return true;
626 }
627
628 const auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
629 const auto result = ir.Not(ir.Imm32(imm_carry.imm32));
630 if (d == Reg::PC) {
631 if (S) {
632 // This is UNPREDICTABLE when in user-mode.
633 return UnpredictableInstruction();
634 }
635
636 ir.ALUWritePC(result);
637 ir.SetTerm(IR::Term::ReturnToDispatch{});
638 return false;
639 }
640
641 ir.SetRegister(d, result);
642 if (S) {
643 ir.SetNFlag(ir.MostSignificantBit(result));
644 ir.SetZFlag(ir.IsZero(result));
645 ir.SetCFlag(imm_carry.carry);
646 }
647
648 return true;
649 }
650
651 // MVN{S}<c> <Rd>, <Rm>{, <shift>}
arm_MVN_reg(Cond cond,bool S,Reg d,Imm<5> imm5,ShiftType shift,Reg m)652 bool ArmTranslatorVisitor::arm_MVN_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
653 if (!ConditionPassed(cond)) {
654 return true;
655 }
656
657 const auto carry_in = ir.GetCFlag();
658 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
659 const auto result = ir.Not(shifted.result);
660 if (d == Reg::PC) {
661 if (S) {
662 // This is UNPREDICTABLE when in user-mode.
663 return UnpredictableInstruction();
664 }
665
666 ir.ALUWritePC(result);
667 ir.SetTerm(IR::Term::ReturnToDispatch{});
668 return false;
669 }
670
671 ir.SetRegister(d, result);
672 if (S) {
673 ir.SetNFlag(ir.MostSignificantBit(result));
674 ir.SetZFlag(ir.IsZero(result));
675 ir.SetCFlag(shifted.carry);
676 }
677
678 return true;
679 }
680
681 // MVN{S}<c> <Rd>, <Rm>, <type> <Rs>
arm_MVN_rsr(Cond cond,bool S,Reg d,Reg s,ShiftType shift,Reg m)682 bool ArmTranslatorVisitor::arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) {
683 if (d == Reg::PC || m == Reg::PC || s == Reg::PC) {
684 return UnpredictableInstruction();
685 }
686
687 if (!ConditionPassed(cond)) {
688 return true;
689 }
690
691 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
692 const auto carry_in = ir.GetCFlag();
693 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
694 const auto result = ir.Not(shifted.result);
695
696 ir.SetRegister(d, result);
697 if (S) {
698 ir.SetNFlag(ir.MostSignificantBit(result));
699 ir.SetZFlag(ir.IsZero(result));
700 ir.SetCFlag(shifted.carry);
701 }
702
703 return true;
704 }
705
706 // ORR{S}<c> <Rd>, <Rn>, #<const>
arm_ORR_imm(Cond cond,bool S,Reg n,Reg d,int rotate,Imm<8> imm8)707 bool ArmTranslatorVisitor::arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
708 if (!ConditionPassed(cond)) {
709 return true;
710 }
711
712 const auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
713 const auto result = ir.Or(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
714 if (d == Reg::PC) {
715 if (S) {
716 // This is UNPREDICTABLE when in user-mode.
717 return UnpredictableInstruction();
718 }
719
720 ir.ALUWritePC(result);
721 ir.SetTerm(IR::Term::ReturnToDispatch{});
722 return false;
723 }
724
725 ir.SetRegister(d, result);
726 if (S) {
727 ir.SetNFlag(ir.MostSignificantBit(result));
728 ir.SetZFlag(ir.IsZero(result));
729 ir.SetCFlag(imm_carry.carry);
730 }
731
732 return true;
733 }
734
735 // ORR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
arm_ORR_reg(Cond cond,bool S,Reg n,Reg d,Imm<5> imm5,ShiftType shift,Reg m)736 bool ArmTranslatorVisitor::arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
737 if (!ConditionPassed(cond)) {
738 return true;
739 }
740
741 const auto carry_in = ir.GetCFlag();
742 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
743 const auto result = ir.Or(ir.GetRegister(n), shifted.result);
744 if (d == Reg::PC) {
745 if (S) {
746 // This is UNPREDICTABLE when in user-mode.
747 return UnpredictableInstruction();
748 }
749
750 ir.ALUWritePC(result);
751 ir.SetTerm(IR::Term::ReturnToDispatch{});
752 return false;
753 }
754
755 ir.SetRegister(d, result);
756 if (S) {
757 ir.SetNFlag(ir.MostSignificantBit(result));
758 ir.SetZFlag(ir.IsZero(result));
759 ir.SetCFlag(shifted.carry);
760 }
761
762 return true;
763 }
764
765 // ORR{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
arm_ORR_rsr(Cond cond,bool S,Reg n,Reg d,Reg s,ShiftType shift,Reg m)766 bool ArmTranslatorVisitor::arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
767 if (n == Reg::PC || m == Reg::PC || s == Reg::PC || d == Reg::PC) {
768 return UnpredictableInstruction();
769 }
770
771 if (!ConditionPassed(cond)) {
772 return true;
773 }
774
775 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
776 const auto carry_in = ir.GetCFlag();
777 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
778 const auto result = ir.Or(ir.GetRegister(n), shifted.result);
779
780 ir.SetRegister(d, result);
781 if (S) {
782 ir.SetNFlag(ir.MostSignificantBit(result));
783 ir.SetZFlag(ir.IsZero(result));
784 ir.SetCFlag(shifted.carry);
785 }
786
787 return true;
788 }
789
790 // RSB{S}<c> <Rd>, <Rn>, #<const>
arm_RSB_imm(Cond cond,bool S,Reg n,Reg d,int rotate,Imm<8> imm8)791 bool ArmTranslatorVisitor::arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
792 if (!ConditionPassed(cond)) {
793 return true;
794 }
795
796 const u32 imm32 = ArmExpandImm(rotate, imm8);
797 const auto result = ir.SubWithCarry(ir.Imm32(imm32), ir.GetRegister(n), ir.Imm1(1));
798 if (d == Reg::PC) {
799 if (S) {
800 // This is UNPREDICTABLE when in user-mode.
801 return UnpredictableInstruction();
802 }
803
804 ir.ALUWritePC(result.result);
805 ir.SetTerm(IR::Term::ReturnToDispatch{});
806 return false;
807 }
808
809 ir.SetRegister(d, result.result);
810 if (S) {
811 ir.SetNFlag(ir.MostSignificantBit(result.result));
812 ir.SetZFlag(ir.IsZero(result.result));
813 ir.SetCFlag(result.carry);
814 ir.SetVFlag(result.overflow);
815 }
816
817 return true;
818 }
819
820 // RSB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
arm_RSB_reg(Cond cond,bool S,Reg n,Reg d,Imm<5> imm5,ShiftType shift,Reg m)821 bool ArmTranslatorVisitor::arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
822 if (!ConditionPassed(cond)) {
823 return true;
824 }
825
826 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
827 const auto result = ir.SubWithCarry(shifted.result, ir.GetRegister(n), ir.Imm1(1));
828 if (d == Reg::PC) {
829 if (S) {
830 // This is UNPREDICTABLE when in user-mode.
831 return UnpredictableInstruction();
832 }
833
834 ir.ALUWritePC(result.result);
835 ir.SetTerm(IR::Term::ReturnToDispatch{});
836 return false;
837 }
838
839 ir.SetRegister(d, result.result);
840 if (S) {
841 ir.SetNFlag(ir.MostSignificantBit(result.result));
842 ir.SetZFlag(ir.IsZero(result.result));
843 ir.SetCFlag(result.carry);
844 ir.SetVFlag(result.overflow);
845 }
846
847 return true;
848 }
849
850 // RSB{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
arm_RSB_rsr(Cond cond,bool S,Reg n,Reg d,Reg s,ShiftType shift,Reg m)851 bool ArmTranslatorVisitor::arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
852 if (n == Reg::PC || m == Reg::PC || s == Reg::PC || d == Reg::PC) {
853 return UnpredictableInstruction();
854 }
855
856 if (!ConditionPassed(cond)) {
857 return true;
858 }
859
860 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
861 const auto carry_in = ir.GetCFlag();
862 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
863 const auto result = ir.SubWithCarry(shifted.result, ir.GetRegister(n), ir.Imm1(1));
864
865 ir.SetRegister(d, result.result);
866 if (S) {
867 ir.SetNFlag(ir.MostSignificantBit(result.result));
868 ir.SetZFlag(ir.IsZero(result.result));
869 ir.SetCFlag(result.carry);
870 ir.SetVFlag(result.overflow);
871 }
872
873 return true;
874 }
875
876 // RSC{S}<c> <Rd>, <Rn>, #<const>
arm_RSC_imm(Cond cond,bool S,Reg n,Reg d,int rotate,Imm<8> imm8)877 bool ArmTranslatorVisitor::arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
878 if (!ConditionPassed(cond)) {
879 return true;
880 }
881
882 const u32 imm32 = ArmExpandImm(rotate, imm8);
883 const auto result = ir.SubWithCarry(ir.Imm32(imm32), ir.GetRegister(n), ir.GetCFlag());
884 if (d == Reg::PC) {
885 if (S) {
886 // This is UNPREDICTABLE when in user-mode.
887 return UnpredictableInstruction();
888 }
889
890 ir.ALUWritePC(result.result);
891 ir.SetTerm(IR::Term::ReturnToDispatch{});
892 return false;
893 }
894
895 ir.SetRegister(d, result.result);
896 if (S) {
897 ir.SetNFlag(ir.MostSignificantBit(result.result));
898 ir.SetZFlag(ir.IsZero(result.result));
899 ir.SetCFlag(result.carry);
900 ir.SetVFlag(result.overflow);
901 }
902
903 return true;
904 }
905
arm_RSC_reg(Cond cond,bool S,Reg n,Reg d,Imm<5> imm5,ShiftType shift,Reg m)906 bool ArmTranslatorVisitor::arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
907 if (!ConditionPassed(cond)) {
908 return true;
909 }
910
911 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
912 const auto result = ir.SubWithCarry(shifted.result, ir.GetRegister(n), ir.GetCFlag());
913 if (d == Reg::PC) {
914 if (S) {
915 // This is UNPREDICTABLE when in user-mode.
916 return UnpredictableInstruction();
917 }
918
919 ir.ALUWritePC(result.result);
920 ir.SetTerm(IR::Term::ReturnToDispatch{});
921 return false;
922 }
923
924 ir.SetRegister(d, result.result);
925 if (S) {
926 ir.SetNFlag(ir.MostSignificantBit(result.result));
927 ir.SetZFlag(ir.IsZero(result.result));
928 ir.SetCFlag(result.carry);
929 ir.SetVFlag(result.overflow);
930 }
931
932 return true;
933 }
934
935 // RSC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
arm_RSC_rsr(Cond cond,bool S,Reg n,Reg d,Reg s,ShiftType shift,Reg m)936 bool ArmTranslatorVisitor::arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
937 if (n == Reg::PC || m == Reg::PC || s == Reg::PC || d == Reg::PC) {
938 return UnpredictableInstruction();
939 }
940
941 if (!ConditionPassed(cond)) {
942 return true;
943 }
944
945 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
946 const auto carry_in = ir.GetCFlag();
947 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
948 const auto result = ir.SubWithCarry(shifted.result, ir.GetRegister(n), ir.GetCFlag());
949
950 ir.SetRegister(d, result.result);
951 if (S) {
952 ir.SetNFlag(ir.MostSignificantBit(result.result));
953 ir.SetZFlag(ir.IsZero(result.result));
954 ir.SetCFlag(result.carry);
955 ir.SetVFlag(result.overflow);
956 }
957
958 return true;
959 }
960
961 // SBC{S}<c> <Rd>, <Rn>, #<const>
arm_SBC_imm(Cond cond,bool S,Reg n,Reg d,int rotate,Imm<8> imm8)962 bool ArmTranslatorVisitor::arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
963 if (!ConditionPassed(cond)) {
964 return true;
965 }
966
967 const u32 imm32 = ArmExpandImm(rotate, imm8);
968 const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.GetCFlag());
969 if (d == Reg::PC) {
970 if (S) {
971 // This is UNPREDICTABLE when in user-mode.
972 return UnpredictableInstruction();
973 }
974
975 ir.ALUWritePC(result.result);
976 ir.SetTerm(IR::Term::ReturnToDispatch{});
977 return false;
978 }
979
980 ir.SetRegister(d, result.result);
981 if (S) {
982 ir.SetNFlag(ir.MostSignificantBit(result.result));
983 ir.SetZFlag(ir.IsZero(result.result));
984 ir.SetCFlag(result.carry);
985 ir.SetVFlag(result.overflow);
986 }
987
988 return true;
989 }
990
991 // SBC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
arm_SBC_reg(Cond cond,bool S,Reg n,Reg d,Imm<5> imm5,ShiftType shift,Reg m)992 bool ArmTranslatorVisitor::arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
993 if (!ConditionPassed(cond)) {
994 return true;
995 }
996
997 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
998 const auto result = ir.SubWithCarry(ir.GetRegister(n), shifted.result, ir.GetCFlag());
999 if (d == Reg::PC) {
1000 if (S) {
1001 // This is UNPREDICTABLE when in user-mode.
1002 return UnpredictableInstruction();
1003 }
1004
1005 ir.ALUWritePC(result.result);
1006 ir.SetTerm(IR::Term::ReturnToDispatch{});
1007 return false;
1008 }
1009
1010 ir.SetRegister(d, result.result);
1011 if (S) {
1012 ir.SetNFlag(ir.MostSignificantBit(result.result));
1013 ir.SetZFlag(ir.IsZero(result.result));
1014 ir.SetCFlag(result.carry);
1015 ir.SetVFlag(result.overflow);
1016 }
1017
1018 return true;
1019 }
1020
1021 // SBC{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
arm_SBC_rsr(Cond cond,bool S,Reg n,Reg d,Reg s,ShiftType shift,Reg m)1022 bool ArmTranslatorVisitor::arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
1023 if (n == Reg::PC || m == Reg::PC || s == Reg::PC || d == Reg::PC) {
1024 return UnpredictableInstruction();
1025 }
1026
1027 if (!ConditionPassed(cond)) {
1028 return true;
1029 }
1030
1031 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
1032 const auto carry_in = ir.GetCFlag();
1033 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
1034 const auto result = ir.SubWithCarry(ir.GetRegister(n), shifted.result, ir.GetCFlag());
1035
1036 ir.SetRegister(d, result.result);
1037 if (S) {
1038 ir.SetNFlag(ir.MostSignificantBit(result.result));
1039 ir.SetZFlag(ir.IsZero(result.result));
1040 ir.SetCFlag(result.carry);
1041 ir.SetVFlag(result.overflow);
1042 }
1043
1044 return true;
1045 }
1046
1047 // SUB{S}<c> <Rd>, <Rn>, #<const>
arm_SUB_imm(Cond cond,bool S,Reg n,Reg d,int rotate,Imm<8> imm8)1048 bool ArmTranslatorVisitor::arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8) {
1049 if (!ConditionPassed(cond)) {
1050 return true;
1051 }
1052
1053 const u32 imm32 = ArmExpandImm(rotate, imm8);
1054 const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
1055 if (d == Reg::PC) {
1056 if (S) {
1057 // This is UNPREDICTABLE when in user-mode.
1058 return UnpredictableInstruction();
1059 }
1060
1061 ir.ALUWritePC(result.result);
1062 ir.SetTerm(IR::Term::ReturnToDispatch{});
1063 return false;
1064 }
1065
1066 ir.SetRegister(d, result.result);
1067 if (S) {
1068 ir.SetNFlag(ir.MostSignificantBit(result.result));
1069 ir.SetZFlag(ir.IsZero(result.result));
1070 ir.SetCFlag(result.carry);
1071 ir.SetVFlag(result.overflow);
1072 }
1073
1074 return true;
1075 }
1076
1077 // SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
arm_SUB_reg(Cond cond,bool S,Reg n,Reg d,Imm<5> imm5,ShiftType shift,Reg m)1078 bool ArmTranslatorVisitor::arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m) {
1079 if (!ConditionPassed(cond)) {
1080 return true;
1081 }
1082
1083 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
1084 const auto result = ir.SubWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(1));
1085 if (d == Reg::PC) {
1086 if (S) {
1087 // This is UNPREDICTABLE when in user-mode.
1088 return UnpredictableInstruction();
1089 }
1090
1091 ir.ALUWritePC(result.result);
1092 ir.SetTerm(IR::Term::ReturnToDispatch{});
1093 return false;
1094 }
1095
1096 ir.SetRegister(d, result.result);
1097 if (S) {
1098 ir.SetNFlag(ir.MostSignificantBit(result.result));
1099 ir.SetZFlag(ir.IsZero(result.result));
1100 ir.SetCFlag(result.carry);
1101 ir.SetVFlag(result.overflow);
1102 }
1103
1104 return true;
1105 }
1106
arm_SUB_rsr(Cond cond,bool S,Reg n,Reg d,Reg s,ShiftType shift,Reg m)1107 bool ArmTranslatorVisitor::arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
1108 if (n == Reg::PC || m == Reg::PC || s == Reg::PC || d == Reg::PC) {
1109 return UnpredictableInstruction();
1110 }
1111
1112 if (!ConditionPassed(cond)) {
1113 return true;
1114 }
1115
1116 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
1117 const auto carry_in = ir.GetCFlag();
1118 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
1119 const auto result = ir.SubWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(1));
1120
1121 ir.SetRegister(d, result.result);
1122 if (S) {
1123 ir.SetNFlag(ir.MostSignificantBit(result.result));
1124 ir.SetZFlag(ir.IsZero(result.result));
1125 ir.SetCFlag(result.carry);
1126 ir.SetVFlag(result.overflow);
1127 }
1128
1129 return true;
1130 }
1131
1132 // TEQ<c> <Rn>, #<const>
arm_TEQ_imm(Cond cond,Reg n,int rotate,Imm<8> imm8)1133 bool ArmTranslatorVisitor::arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
1134 if (!ConditionPassed(cond)) {
1135 return true;
1136 }
1137
1138 const auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
1139 const auto result = ir.Eor(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
1140
1141 ir.SetNFlag(ir.MostSignificantBit(result));
1142 ir.SetZFlag(ir.IsZero(result));
1143 ir.SetCFlag(imm_carry.carry);
1144 return true;
1145 }
1146
1147 // TEQ<c> <Rn>, <Rm>{, <shift>}
arm_TEQ_reg(Cond cond,Reg n,Imm<5> imm5,ShiftType shift,Reg m)1148 bool ArmTranslatorVisitor::arm_TEQ_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
1149 if (!ConditionPassed(cond)) {
1150 return true;
1151 }
1152
1153 const auto carry_in = ir.GetCFlag();
1154 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
1155 const auto result = ir.Eor(ir.GetRegister(n), shifted.result);
1156
1157 ir.SetNFlag(ir.MostSignificantBit(result));
1158 ir.SetZFlag(ir.IsZero(result));
1159 ir.SetCFlag(shifted.carry);
1160 return true;
1161 }
1162
1163 // TEQ<c> <Rn>, <Rm>, <type> <Rs>
arm_TEQ_rsr(Cond cond,Reg n,Reg s,ShiftType shift,Reg m)1164 bool ArmTranslatorVisitor::arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
1165 if (n == Reg::PC || m == Reg::PC || s == Reg::PC) {
1166 return UnpredictableInstruction();
1167 }
1168
1169 if (!ConditionPassed(cond)) {
1170 return true;
1171 }
1172
1173 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
1174 const auto carry_in = ir.GetCFlag();
1175 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
1176 const auto result = ir.Eor(ir.GetRegister(n), shifted.result);
1177
1178 ir.SetNFlag(ir.MostSignificantBit(result));
1179 ir.SetZFlag(ir.IsZero(result));
1180 ir.SetCFlag(shifted.carry);
1181 return true;
1182 }
1183
1184 // TST<c> <Rn>, #<const>
arm_TST_imm(Cond cond,Reg n,int rotate,Imm<8> imm8)1185 bool ArmTranslatorVisitor::arm_TST_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) {
1186 if (!ConditionPassed(cond)) {
1187 return true;
1188 }
1189
1190 const auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
1191 const auto result = ir.And(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
1192
1193 ir.SetNFlag(ir.MostSignificantBit(result));
1194 ir.SetZFlag(ir.IsZero(result));
1195 ir.SetCFlag(imm_carry.carry);
1196 return true;
1197 }
1198
1199 // TST<c> <Rn>, <Rm>{, <shift>}
arm_TST_reg(Cond cond,Reg n,Imm<5> imm5,ShiftType shift,Reg m)1200 bool ArmTranslatorVisitor::arm_TST_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m) {
1201 if (!ConditionPassed(cond)) {
1202 return true;
1203 }
1204
1205 const auto carry_in = ir.GetCFlag();
1206 const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
1207 const auto result = ir.And(ir.GetRegister(n), shifted.result);
1208
1209 ir.SetNFlag(ir.MostSignificantBit(result));
1210 ir.SetZFlag(ir.IsZero(result));
1211 ir.SetCFlag(shifted.carry);
1212 return true;
1213 }
1214
1215 // TST<c> <Rn>, <Rm>, <type> <Rs>
arm_TST_rsr(Cond cond,Reg n,Reg s,ShiftType shift,Reg m)1216 bool ArmTranslatorVisitor::arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
1217 if (n == Reg::PC || m == Reg::PC || s == Reg::PC) {
1218 return UnpredictableInstruction();
1219 }
1220
1221 if (!ConditionPassed(cond)) {
1222 return true;
1223 }
1224
1225 const auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
1226 const auto carry_in = ir.GetCFlag();
1227 const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
1228 const auto result = ir.And(ir.GetRegister(n), shifted.result);
1229
1230 ir.SetNFlag(ir.MostSignificantBit(result));
1231 ir.SetZFlag(ir.IsZero(result));
1232 ir.SetCFlag(shifted.carry);
1233 return true;
1234 }
1235
1236 } // namespace Dynarmic::A32
1237