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