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 // SADD8<c> <Rd>, <Rn>, <Rm>
arm_SADD8(Cond cond,Reg n,Reg d,Reg m)11 bool ArmTranslatorVisitor::arm_SADD8(Cond cond, Reg n, Reg d, Reg m) {
12 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
13 return UnpredictableInstruction();
14 }
15
16 if (!ConditionPassed(cond)) {
17 return true;
18 }
19
20 const auto result = ir.PackedAddS8(ir.GetRegister(n), ir.GetRegister(m));
21 ir.SetRegister(d, result.result);
22 ir.SetGEFlags(result.ge);
23 return true;
24 }
25
26 // SADD16<c> <Rd>, <Rn>, <Rm>
arm_SADD16(Cond cond,Reg n,Reg d,Reg m)27 bool ArmTranslatorVisitor::arm_SADD16(Cond cond, Reg n, Reg d, Reg m) {
28 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
29 return UnpredictableInstruction();
30 }
31
32 if (!ConditionPassed(cond)) {
33 return true;
34 }
35
36 const auto result = ir.PackedAddS16(ir.GetRegister(n), ir.GetRegister(m));
37 ir.SetRegister(d, result.result);
38 ir.SetGEFlags(result.ge);
39 return true;
40 }
41
42 // SASX<c> <Rd>, <Rn>, <Rm>
arm_SASX(Cond cond,Reg n,Reg d,Reg m)43 bool ArmTranslatorVisitor::arm_SASX(Cond cond, Reg n, Reg d, Reg m) {
44 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
45 return UnpredictableInstruction();
46 }
47
48 if (!ConditionPassed(cond)) {
49 return true;
50 }
51
52 const auto result = ir.PackedAddSubS16(ir.GetRegister(n), ir.GetRegister(m));
53 ir.SetRegister(d, result.result);
54 ir.SetGEFlags(result.ge);
55 return true;
56 }
57
58 // SSAX<c> <Rd>, <Rn>, <Rm>
arm_SSAX(Cond cond,Reg n,Reg d,Reg m)59 bool ArmTranslatorVisitor::arm_SSAX(Cond cond, Reg n, Reg d, Reg m) {
60 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
61 return UnpredictableInstruction();
62 }
63
64 if (!ConditionPassed(cond)) {
65 return true;
66 }
67
68 const auto result = ir.PackedSubAddS16(ir.GetRegister(n), ir.GetRegister(m));
69 ir.SetRegister(d, result.result);
70 ir.SetGEFlags(result.ge);
71 return true;
72 }
73
74 // SSUB8<c> <Rd>, <Rn>, <Rm>
arm_SSUB8(Cond cond,Reg n,Reg d,Reg m)75 bool ArmTranslatorVisitor::arm_SSUB8(Cond cond, Reg n, Reg d, Reg m) {
76 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
77 return UnpredictableInstruction();
78 }
79
80 if (!ConditionPassed(cond)) {
81 return true;
82 }
83
84 const auto result = ir.PackedSubS8(ir.GetRegister(n), ir.GetRegister(m));
85 ir.SetRegister(d, result.result);
86 ir.SetGEFlags(result.ge);
87 return true;
88 }
89
90 // SSUB16<c> <Rd>, <Rn>, <Rm>
arm_SSUB16(Cond cond,Reg n,Reg d,Reg m)91 bool ArmTranslatorVisitor::arm_SSUB16(Cond cond, Reg n, Reg d, Reg m) {
92 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
93 return UnpredictableInstruction();
94 }
95
96 if (!ConditionPassed(cond)) {
97 return true;
98 }
99
100 const auto result = ir.PackedSubS16(ir.GetRegister(n), ir.GetRegister(m));
101 ir.SetRegister(d, result.result);
102 ir.SetGEFlags(result.ge);
103 return true;
104 }
105
106 // UADD8<c> <Rd>, <Rn>, <Rm>
arm_UADD8(Cond cond,Reg n,Reg d,Reg m)107 bool ArmTranslatorVisitor::arm_UADD8(Cond cond, Reg n, Reg d, Reg m) {
108 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
109 return UnpredictableInstruction();
110 }
111
112 if (!ConditionPassed(cond)) {
113 return true;
114 }
115
116 const auto result = ir.PackedAddU8(ir.GetRegister(n), ir.GetRegister(m));
117 ir.SetRegister(d, result.result);
118 ir.SetGEFlags(result.ge);
119 return true;
120 }
121
122 // UADD16<c> <Rd>, <Rn>, <Rm>
arm_UADD16(Cond cond,Reg n,Reg d,Reg m)123 bool ArmTranslatorVisitor::arm_UADD16(Cond cond, Reg n, Reg d, Reg m) {
124 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
125 return UnpredictableInstruction();
126 }
127
128 if (!ConditionPassed(cond)) {
129 return true;
130 }
131
132 const auto result = ir.PackedAddU16(ir.GetRegister(n), ir.GetRegister(m));
133 ir.SetRegister(d, result.result);
134 ir.SetGEFlags(result.ge);
135 return true;
136 }
137
138 // UASX<c> <Rd>, <Rn>, <Rm>
arm_UASX(Cond cond,Reg n,Reg d,Reg m)139 bool ArmTranslatorVisitor::arm_UASX(Cond cond, Reg n, Reg d, Reg m) {
140 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
141 return UnpredictableInstruction();
142 }
143
144 if (!ConditionPassed(cond)) {
145 return true;
146 }
147
148 const auto result = ir.PackedAddSubU16(ir.GetRegister(n), ir.GetRegister(m));
149 ir.SetRegister(d, result.result);
150 ir.SetGEFlags(result.ge);
151 return true;
152 }
153
154 // USAX<c> <Rd>, <Rn>, <Rm>
arm_USAX(Cond cond,Reg n,Reg d,Reg m)155 bool ArmTranslatorVisitor::arm_USAX(Cond cond, Reg n, Reg d, Reg m) {
156 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
157 return UnpredictableInstruction();
158 }
159
160 if (!ConditionPassed(cond)) {
161 return true;
162 }
163
164 const auto result = ir.PackedSubAddU16(ir.GetRegister(n), ir.GetRegister(m));
165 ir.SetRegister(d, result.result);
166 ir.SetGEFlags(result.ge);
167 return true;
168 }
169
170 // USAD8<c> <Rd>, <Rn>, <Rm>
arm_USAD8(Cond cond,Reg d,Reg m,Reg n)171 bool ArmTranslatorVisitor::arm_USAD8(Cond cond, Reg d, Reg m, Reg n) {
172 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
173 return UnpredictableInstruction();
174 }
175
176 if (!ConditionPassed(cond)) {
177 return true;
178 }
179
180 const auto result = ir.PackedAbsDiffSumS8(ir.GetRegister(n), ir.GetRegister(m));
181 ir.SetRegister(d, result);
182 return true;
183 }
184
185 // USADA8<c> <Rd>, <Rn>, <Rm>, <Ra>
arm_USADA8(Cond cond,Reg d,Reg a,Reg m,Reg n)186 bool ArmTranslatorVisitor::arm_USADA8(Cond cond, Reg d, Reg a, Reg m, Reg n){
187 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
188 return UnpredictableInstruction();
189 }
190
191 if (!ConditionPassed(cond)) {
192 return true;
193 }
194
195 const auto tmp = ir.PackedAbsDiffSumS8(ir.GetRegister(n), ir.GetRegister(m));
196 const auto result = ir.AddWithCarry(ir.GetRegister(a), tmp, ir.Imm1(0));
197 ir.SetRegister(d, result.result);
198 return true;
199 }
200
201 // USUB8<c> <Rd>, <Rn>, <Rm>
arm_USUB8(Cond cond,Reg n,Reg d,Reg m)202 bool ArmTranslatorVisitor::arm_USUB8(Cond cond, Reg n, Reg d, Reg m) {
203 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
204 return UnpredictableInstruction();
205 }
206
207 if (!ConditionPassed(cond)) {
208 return true;
209 }
210
211 const auto result = ir.PackedSubU8(ir.GetRegister(n), ir.GetRegister(m));
212 ir.SetRegister(d, result.result);
213 ir.SetGEFlags(result.ge);
214 return true;
215 }
216
217 // USUB16<c> <Rd>, <Rn>, <Rm>
arm_USUB16(Cond cond,Reg n,Reg d,Reg m)218 bool ArmTranslatorVisitor::arm_USUB16(Cond cond, Reg n, Reg d, Reg m) {
219 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
220 return UnpredictableInstruction();
221 }
222
223 if (!ConditionPassed(cond)) {
224 return true;
225 }
226
227 const auto result = ir.PackedSubU16(ir.GetRegister(n), ir.GetRegister(m));
228 ir.SetRegister(d, result.result);
229 ir.SetGEFlags(result.ge);
230 return true;
231 }
232
233 // Parallel Add/Subtract (Saturating) instructions
234
235 // QADD8<c> <Rd>, <Rn>, <Rm>
arm_QADD8(Cond cond,Reg n,Reg d,Reg m)236 bool ArmTranslatorVisitor::arm_QADD8(Cond cond, Reg n, Reg d, Reg m) {
237 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
238 return UnpredictableInstruction();
239 }
240
241 if (!ConditionPassed(cond)) {
242 return true;
243 }
244
245 const auto result = ir.PackedSaturatedAddS8(ir.GetRegister(n), ir.GetRegister(m));
246 ir.SetRegister(d, result);
247 return true;
248 }
249
250 // QADD16<c> <Rd>, <Rn>, <Rm>
arm_QADD16(Cond cond,Reg n,Reg d,Reg m)251 bool ArmTranslatorVisitor::arm_QADD16(Cond cond, Reg n, Reg d, Reg m) {
252 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
253 return UnpredictableInstruction();
254 }
255
256 if (!ConditionPassed(cond)) {
257 return true;
258 }
259
260 const auto result = ir.PackedSaturatedAddS16(ir.GetRegister(n), ir.GetRegister(m));
261 ir.SetRegister(d, result);
262 return true;
263 }
264
265 // QSUB8<c> <Rd>, <Rn>, <Rm>
arm_QSUB8(Cond cond,Reg n,Reg d,Reg m)266 bool ArmTranslatorVisitor::arm_QSUB8(Cond cond, Reg n, Reg d, Reg m) {
267 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
268 return UnpredictableInstruction();
269 }
270
271 if (!ConditionPassed(cond)) {
272 return true;
273 }
274
275 const auto result = ir.PackedSaturatedSubS8(ir.GetRegister(n), ir.GetRegister(m));
276 ir.SetRegister(d, result);
277 return true;
278 }
279
280 // QSUB16<c> <Rd>, <Rn>, <Rm>
arm_QSUB16(Cond cond,Reg n,Reg d,Reg m)281 bool ArmTranslatorVisitor::arm_QSUB16(Cond cond, Reg n, Reg d, Reg m) {
282 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
283 return UnpredictableInstruction();
284 }
285
286 if (!ConditionPassed(cond)) {
287 return true;
288 }
289
290 const auto result = ir.PackedSaturatedSubS16(ir.GetRegister(n), ir.GetRegister(m));
291 ir.SetRegister(d, result);
292 return true;
293 }
294
295 // UQADD8<c> <Rd>, <Rn>, <Rm>
arm_UQADD8(Cond cond,Reg n,Reg d,Reg m)296 bool ArmTranslatorVisitor::arm_UQADD8(Cond cond, Reg n, Reg d, Reg m) {
297 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
298 return UnpredictableInstruction();
299 }
300
301 if (!ConditionPassed(cond)) {
302 return true;
303 }
304
305 const auto result = ir.PackedSaturatedAddU8(ir.GetRegister(n), ir.GetRegister(m));
306 ir.SetRegister(d, result);
307 return true;
308 }
309
310 // UQADD16<c> <Rd>, <Rn>, <Rm>
arm_UQADD16(Cond cond,Reg n,Reg d,Reg m)311 bool ArmTranslatorVisitor::arm_UQADD16(Cond cond, Reg n, Reg d, Reg m) {
312 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
313 return UnpredictableInstruction();
314 }
315
316 if (!ConditionPassed(cond)) {
317 return true;
318 }
319
320 const auto result = ir.PackedSaturatedAddU16(ir.GetRegister(n), ir.GetRegister(m));
321 ir.SetRegister(d, result);
322 return true;
323 }
324
325 // UQSUB8<c> <Rd>, <Rn>, <Rm>
arm_UQSUB8(Cond cond,Reg n,Reg d,Reg m)326 bool ArmTranslatorVisitor::arm_UQSUB8(Cond cond, Reg n, Reg d, Reg m) {
327 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
328 return UnpredictableInstruction();
329 }
330
331 if (!ConditionPassed(cond)) {
332 return true;
333 }
334
335 const auto result = ir.PackedSaturatedSubU8(ir.GetRegister(n), ir.GetRegister(m));
336 ir.SetRegister(d, result);
337 return true;
338 }
339
340 // UQSUB16<c> <Rd>, <Rn>, <Rm>
arm_UQSUB16(Cond cond,Reg n,Reg d,Reg m)341 bool ArmTranslatorVisitor::arm_UQSUB16(Cond cond, Reg n, Reg d, Reg m) {
342 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
343 return UnpredictableInstruction();
344 }
345
346 if (!ConditionPassed(cond)) {
347 return true;
348 }
349
350 const auto result = ir.PackedSaturatedSubU16(ir.GetRegister(n), ir.GetRegister(m));
351 ir.SetRegister(d, result);
352 return true;
353 }
354
355 // Parallel Add/Subtract (Halving) instructions
356
357 // SHADD8<c> <Rd>, <Rn>, <Rm>
arm_SHADD8(Cond cond,Reg n,Reg d,Reg m)358 bool ArmTranslatorVisitor::arm_SHADD8(Cond cond, Reg n, Reg d, Reg m) {
359 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
360 return UnpredictableInstruction();
361 }
362
363 if (!ConditionPassed(cond)) {
364 return true;
365 }
366
367 const auto result = ir.PackedHalvingAddS8(ir.GetRegister(n), ir.GetRegister(m));
368 ir.SetRegister(d, result);
369 return true;
370 }
371
372 // SHADD16<c> <Rd>, <Rn>, <Rm>
arm_SHADD16(Cond cond,Reg n,Reg d,Reg m)373 bool ArmTranslatorVisitor::arm_SHADD16(Cond cond, Reg n, Reg d, Reg m) {
374 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
375 return UnpredictableInstruction();
376 }
377
378 if (!ConditionPassed(cond)) {
379 return true;
380 }
381
382 const auto result = ir.PackedHalvingAddS16(ir.GetRegister(n), ir.GetRegister(m));
383 ir.SetRegister(d, result);
384 return true;
385 }
386
387 // SHASX<c> <Rd>, <Rn>, <Rm>
arm_SHASX(Cond cond,Reg n,Reg d,Reg m)388 bool ArmTranslatorVisitor::arm_SHASX(Cond cond, Reg n, Reg d, Reg m) {
389 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
390 return UnpredictableInstruction();
391 }
392
393 if (!ConditionPassed(cond)) {
394 return true;
395 }
396
397 const auto result = ir.PackedHalvingAddSubS16(ir.GetRegister(n), ir.GetRegister(m));
398 ir.SetRegister(d, result);
399 return true;
400 }
401
402 // SHSAX<c> <Rd>, <Rn>, <Rm>
arm_SHSAX(Cond cond,Reg n,Reg d,Reg m)403 bool ArmTranslatorVisitor::arm_SHSAX(Cond cond, Reg n, Reg d, Reg m) {
404 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
405 return UnpredictableInstruction();
406 }
407
408 if (!ConditionPassed(cond)) {
409 return true;
410 }
411
412 const auto result = ir.PackedHalvingSubAddS16(ir.GetRegister(n), ir.GetRegister(m));
413 ir.SetRegister(d, result);
414 return true;
415 }
416
417 // SHSUB8<c> <Rd>, <Rn>, <Rm>
arm_SHSUB8(Cond cond,Reg n,Reg d,Reg m)418 bool ArmTranslatorVisitor::arm_SHSUB8(Cond cond, Reg n, Reg d, Reg m) {
419 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
420 return UnpredictableInstruction();
421 }
422
423 if (!ConditionPassed(cond)) {
424 return true;
425 }
426
427 const auto result = ir.PackedHalvingSubS8(ir.GetRegister(n), ir.GetRegister(m));
428 ir.SetRegister(d, result);
429 return true;
430 }
431
432 // SHSUB16<c> <Rd>, <Rn>, <Rm>
arm_SHSUB16(Cond cond,Reg n,Reg d,Reg m)433 bool ArmTranslatorVisitor::arm_SHSUB16(Cond cond, Reg n, Reg d, Reg m) {
434 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
435 return UnpredictableInstruction();
436 }
437
438 if (!ConditionPassed(cond)) {
439 return true;
440 }
441
442 const auto result = ir.PackedHalvingSubS16(ir.GetRegister(n), ir.GetRegister(m));
443 ir.SetRegister(d, result);
444 return true;
445 }
446
447 // UHADD8<c> <Rd>, <Rn>, <Rm>
arm_UHADD8(Cond cond,Reg n,Reg d,Reg m)448 bool ArmTranslatorVisitor::arm_UHADD8(Cond cond, Reg n, Reg d, Reg m) {
449 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
450 return UnpredictableInstruction();
451 }
452
453 if (!ConditionPassed(cond)) {
454 return true;
455 }
456
457 const auto result = ir.PackedHalvingAddU8(ir.GetRegister(n), ir.GetRegister(m));
458 ir.SetRegister(d, result);
459 return true;
460 }
461
462 // UHADD16<c> <Rd>, <Rn>, <Rm>
arm_UHADD16(Cond cond,Reg n,Reg d,Reg m)463 bool ArmTranslatorVisitor::arm_UHADD16(Cond cond, Reg n, Reg d, Reg m) {
464 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
465 return UnpredictableInstruction();
466 }
467
468 if (!ConditionPassed(cond)) {
469 return true;
470 }
471
472 const auto result = ir.PackedHalvingAddU16(ir.GetRegister(n), ir.GetRegister(m));
473 ir.SetRegister(d, result);
474 return true;
475 }
476
477 // UHASX<c> <Rd>, <Rn>, <Rm>
arm_UHASX(Cond cond,Reg n,Reg d,Reg m)478 bool ArmTranslatorVisitor::arm_UHASX(Cond cond, Reg n, Reg d, Reg m) {
479 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
480 return UnpredictableInstruction();
481 }
482
483 if (!ConditionPassed(cond)) {
484 return true;
485 }
486
487 const auto result = ir.PackedHalvingAddSubU16(ir.GetRegister(n), ir.GetRegister(m));
488 ir.SetRegister(d, result);
489 return true;
490 }
491
492 // UHSAX<c> <Rd>, <Rn>, <Rm>
arm_UHSAX(Cond cond,Reg n,Reg d,Reg m)493 bool ArmTranslatorVisitor::arm_UHSAX(Cond cond, Reg n, Reg d, Reg m) {
494 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
495 return UnpredictableInstruction();
496 }
497
498 if (!ConditionPassed(cond)) {
499 return true;
500 }
501
502 const auto result = ir.PackedHalvingSubAddU16(ir.GetRegister(n), ir.GetRegister(m));
503 ir.SetRegister(d, result);
504 return true;
505 }
506
507 // UHSUB8<c> <Rd>, <Rn>, <Rm>
arm_UHSUB8(Cond cond,Reg n,Reg d,Reg m)508 bool ArmTranslatorVisitor::arm_UHSUB8(Cond cond, Reg n, Reg d, Reg m) {
509 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
510 return UnpredictableInstruction();
511 }
512
513 if (!ConditionPassed(cond)) {
514 return true;
515 }
516
517 const auto result = ir.PackedHalvingSubU8(ir.GetRegister(n), ir.GetRegister(m));
518 ir.SetRegister(d, result);
519 return true;
520 }
521
522 // UHSUB16<c> <Rd>, <Rn>, <Rm>
arm_UHSUB16(Cond cond,Reg n,Reg d,Reg m)523 bool ArmTranslatorVisitor::arm_UHSUB16(Cond cond, Reg n, Reg d, Reg m) {
524 if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
525 return UnpredictableInstruction();
526 }
527
528 if (!ConditionPassed(cond)) {
529 return true;
530 }
531
532 const auto result = ir.PackedHalvingSubU16(ir.GetRegister(n), ir.GetRegister(m));
533 ir.SetRegister(d, result);
534 return true;
535 }
536
537 } // namespace Dynarmic::A32
538