1 // Copyright 2012 Michael Kang, 2015 Citra Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4 
5 /* Notice: this file should not be compiled as is, and is meant to be
6    included in other files only. */
7 
8 /* ----------------------------------------------------------------------- */
9 /* CDP instructions */
10 /* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */
11 
12 /* ----------------------------------------------------------------------- */
13 /* VMLA */
14 /* cond 1110 0D00 Vn-- Vd-- 101X N0M0 Vm-- */
15 #ifdef VFP_INTERPRETER_STRUCT
16 struct vmla_inst {
17     unsigned int instr;
18     unsigned int dp_operation;
19 };
20 #endif
21 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vmla)22 static ARM_INST_PTR INTERPRETER_TRANSLATE(vmla)(unsigned int inst, int index) {
23     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmla_inst));
24     vmla_inst* inst_cream = (vmla_inst*)inst_base->component;
25 
26     inst_base->cond = BITS(inst, 28, 31);
27     inst_base->idx = index;
28     inst_base->br = TransExtData::NON_BRANCH;
29 
30     inst_cream->dp_operation = BIT(inst, 8);
31     inst_cream->instr = inst;
32 
33     return inst_base;
34 }
35 #endif
36 #ifdef VFP_INTERPRETER_IMPL
37 VMLA_INST : {
38     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
39         CHECK_VFP_ENABLED;
40 
41         vmla_inst* inst_cream = (vmla_inst*)inst_base->component;
42 
43         int ret;
44 
45         if (inst_cream->dp_operation)
46             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
47         else
48             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
49 
50         CHECK_VFP_CDP_RET;
51     }
52     cpu->Reg[15] += cpu->GetInstructionSize();
53     INC_PC(sizeof(vmla_inst));
54     FETCH_INST;
55     GOTO_NEXT_INST;
56 }
57 #endif
58 
59 /* ----------------------------------------------------------------------- */
60 /* VNMLS */
61 /* cond 1110 0D00 Vn-- Vd-- 101X N1M0 Vm-- */
62 #ifdef VFP_INTERPRETER_STRUCT
63 struct vmls_inst {
64     unsigned int instr;
65     unsigned int dp_operation;
66 };
67 #endif
68 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vmls)69 static ARM_INST_PTR INTERPRETER_TRANSLATE(vmls)(unsigned int inst, int index) {
70     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmls_inst));
71     vmls_inst* inst_cream = (vmls_inst*)inst_base->component;
72 
73     inst_base->cond = BITS(inst, 28, 31);
74     inst_base->idx = index;
75     inst_base->br = TransExtData::NON_BRANCH;
76 
77     inst_cream->dp_operation = BIT(inst, 8);
78     inst_cream->instr = inst;
79 
80     return inst_base;
81 }
82 #endif
83 #ifdef VFP_INTERPRETER_IMPL
84 VMLS_INST : {
85     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
86         CHECK_VFP_ENABLED;
87 
88         vmls_inst* inst_cream = (vmls_inst*)inst_base->component;
89 
90         int ret;
91 
92         if (inst_cream->dp_operation)
93             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
94         else
95             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
96 
97         CHECK_VFP_CDP_RET;
98     }
99     cpu->Reg[15] += cpu->GetInstructionSize();
100     INC_PC(sizeof(vmls_inst));
101     FETCH_INST;
102     GOTO_NEXT_INST;
103 }
104 #endif
105 
106 /* ----------------------------------------------------------------------- */
107 /* VNMLA */
108 /* cond 1110 0D01 Vn-- Vd-- 101X N1M0 Vm-- */
109 #ifdef VFP_INTERPRETER_STRUCT
110 struct vnmla_inst {
111     unsigned int instr;
112     unsigned int dp_operation;
113 };
114 #endif
115 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vnmla)116 static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmla)(unsigned int inst, int index) {
117     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vnmla_inst));
118     vnmla_inst* inst_cream = (vnmla_inst*)inst_base->component;
119 
120     inst_base->cond = BITS(inst, 28, 31);
121     inst_base->idx = index;
122     inst_base->br = TransExtData::NON_BRANCH;
123 
124     inst_cream->dp_operation = BIT(inst, 8);
125     inst_cream->instr = inst;
126 
127     return inst_base;
128 }
129 #endif
130 #ifdef VFP_INTERPRETER_IMPL
131 VNMLA_INST : {
132     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
133         CHECK_VFP_ENABLED;
134 
135         vnmla_inst* inst_cream = (vnmla_inst*)inst_base->component;
136 
137         int ret;
138 
139         if (inst_cream->dp_operation)
140             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
141         else
142             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
143 
144         CHECK_VFP_CDP_RET;
145     }
146     cpu->Reg[15] += cpu->GetInstructionSize();
147     INC_PC(sizeof(vnmla_inst));
148     FETCH_INST;
149     GOTO_NEXT_INST;
150 }
151 #endif
152 
153 /* ----------------------------------------------------------------------- */
154 /* VNMLS */
155 /* cond 1110 0D01 Vn-- Vd-- 101X N0M0 Vm-- */
156 
157 #ifdef VFP_INTERPRETER_STRUCT
158 struct vnmls_inst {
159     unsigned int instr;
160     unsigned int dp_operation;
161 };
162 #endif
163 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vnmls)164 static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmls)(unsigned int inst, int index) {
165     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vnmls_inst));
166     vnmls_inst* inst_cream = (vnmls_inst*)inst_base->component;
167 
168     inst_base->cond = BITS(inst, 28, 31);
169     inst_base->idx = index;
170     inst_base->br = TransExtData::NON_BRANCH;
171 
172     inst_cream->dp_operation = BIT(inst, 8);
173     inst_cream->instr = inst;
174 
175     return inst_base;
176 }
177 #endif
178 #ifdef VFP_INTERPRETER_IMPL
179 VNMLS_INST : {
180     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
181         CHECK_VFP_ENABLED;
182 
183         vnmls_inst* inst_cream = (vnmls_inst*)inst_base->component;
184 
185         int ret;
186 
187         if (inst_cream->dp_operation)
188             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
189         else
190             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
191 
192         CHECK_VFP_CDP_RET;
193     }
194     cpu->Reg[15] += cpu->GetInstructionSize();
195     INC_PC(sizeof(vnmls_inst));
196     FETCH_INST;
197     GOTO_NEXT_INST;
198 }
199 #endif
200 
201 /* ----------------------------------------------------------------------- */
202 /* VNMUL */
203 /* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */
204 #ifdef VFP_INTERPRETER_STRUCT
205 struct vnmul_inst {
206     unsigned int instr;
207     unsigned int dp_operation;
208 };
209 #endif
210 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vnmul)211 static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmul)(unsigned int inst, int index) {
212     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vnmul_inst));
213     vnmul_inst* inst_cream = (vnmul_inst*)inst_base->component;
214 
215     inst_base->cond = BITS(inst, 28, 31);
216     inst_base->idx = index;
217     inst_base->br = TransExtData::NON_BRANCH;
218 
219     inst_cream->dp_operation = BIT(inst, 8);
220     inst_cream->instr = inst;
221 
222     return inst_base;
223 }
224 #endif
225 #ifdef VFP_INTERPRETER_IMPL
226 VNMUL_INST : {
227     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
228         CHECK_VFP_ENABLED;
229 
230         vnmul_inst* inst_cream = (vnmul_inst*)inst_base->component;
231 
232         int ret;
233 
234         if (inst_cream->dp_operation)
235             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
236         else
237             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
238 
239         CHECK_VFP_CDP_RET;
240     }
241     cpu->Reg[15] += cpu->GetInstructionSize();
242     INC_PC(sizeof(vnmul_inst));
243     FETCH_INST;
244     GOTO_NEXT_INST;
245 }
246 #endif
247 
248 /* ----------------------------------------------------------------------- */
249 /* VMUL */
250 /* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */
251 #ifdef VFP_INTERPRETER_STRUCT
252 struct vmul_inst {
253     unsigned int instr;
254     unsigned int dp_operation;
255 };
256 #endif
257 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vmul)258 static ARM_INST_PTR INTERPRETER_TRANSLATE(vmul)(unsigned int inst, int index) {
259     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmul_inst));
260     vmul_inst* inst_cream = (vmul_inst*)inst_base->component;
261 
262     inst_base->cond = BITS(inst, 28, 31);
263     inst_base->idx = index;
264     inst_base->br = TransExtData::NON_BRANCH;
265 
266     inst_cream->dp_operation = BIT(inst, 8);
267     inst_cream->instr = inst;
268 
269     return inst_base;
270 }
271 #endif
272 #ifdef VFP_INTERPRETER_IMPL
273 VMUL_INST : {
274     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
275         CHECK_VFP_ENABLED;
276 
277         vmul_inst* inst_cream = (vmul_inst*)inst_base->component;
278 
279         int ret;
280 
281         if (inst_cream->dp_operation)
282             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
283         else
284             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
285 
286         CHECK_VFP_CDP_RET;
287     }
288     cpu->Reg[15] += cpu->GetInstructionSize();
289     INC_PC(sizeof(vmul_inst));
290     FETCH_INST;
291     GOTO_NEXT_INST;
292 }
293 #endif
294 
295 /* ----------------------------------------------------------------------- */
296 /* VADD */
297 /* cond 1110 0D11 Vn-- Vd-- 101X N0M0 Vm-- */
298 #ifdef VFP_INTERPRETER_STRUCT
299 struct vadd_inst {
300     unsigned int instr;
301     unsigned int dp_operation;
302 };
303 #endif
304 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vadd)305 static ARM_INST_PTR INTERPRETER_TRANSLATE(vadd)(unsigned int inst, int index) {
306     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vadd_inst));
307     vadd_inst* inst_cream = (vadd_inst*)inst_base->component;
308 
309     inst_base->cond = BITS(inst, 28, 31);
310     inst_base->idx = index;
311     inst_base->br = TransExtData::NON_BRANCH;
312 
313     inst_cream->dp_operation = BIT(inst, 8);
314     inst_cream->instr = inst;
315 
316     return inst_base;
317 }
318 #endif
319 #ifdef VFP_INTERPRETER_IMPL
320 VADD_INST : {
321     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
322         CHECK_VFP_ENABLED;
323 
324         vadd_inst* inst_cream = (vadd_inst*)inst_base->component;
325 
326         int ret;
327 
328         if (inst_cream->dp_operation)
329             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
330         else
331             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
332 
333         CHECK_VFP_CDP_RET;
334     }
335     cpu->Reg[15] += cpu->GetInstructionSize();
336     INC_PC(sizeof(vadd_inst));
337     FETCH_INST;
338     GOTO_NEXT_INST;
339 }
340 #endif
341 
342 /* ----------------------------------------------------------------------- */
343 /* VSUB */
344 /* cond 1110 0D11 Vn-- Vd-- 101X N1M0 Vm-- */
345 #ifdef VFP_INTERPRETER_STRUCT
346 struct vsub_inst {
347     unsigned int instr;
348     unsigned int dp_operation;
349 };
350 #endif
351 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vsub)352 static ARM_INST_PTR INTERPRETER_TRANSLATE(vsub)(unsigned int inst, int index) {
353     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vsub_inst));
354     vsub_inst* inst_cream = (vsub_inst*)inst_base->component;
355 
356     inst_base->cond = BITS(inst, 28, 31);
357     inst_base->idx = index;
358     inst_base->br = TransExtData::NON_BRANCH;
359 
360     inst_cream->dp_operation = BIT(inst, 8);
361     inst_cream->instr = inst;
362 
363     return inst_base;
364 }
365 #endif
366 #ifdef VFP_INTERPRETER_IMPL
367 VSUB_INST : {
368     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
369         CHECK_VFP_ENABLED;
370 
371         vsub_inst* inst_cream = (vsub_inst*)inst_base->component;
372 
373         int ret;
374 
375         if (inst_cream->dp_operation)
376             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
377         else
378             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
379 
380         CHECK_VFP_CDP_RET;
381     }
382     cpu->Reg[15] += cpu->GetInstructionSize();
383     INC_PC(sizeof(vsub_inst));
384     FETCH_INST;
385     GOTO_NEXT_INST;
386 }
387 #endif
388 
389 /* ----------------------------------------------------------------------- */
390 /* VDIV */
391 /* cond 1110 1D00 Vn-- Vd-- 101X N0M0 Vm-- */
392 #ifdef VFP_INTERPRETER_STRUCT
393 struct vdiv_inst {
394     unsigned int instr;
395     unsigned int dp_operation;
396 };
397 #endif
398 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vdiv)399 static ARM_INST_PTR INTERPRETER_TRANSLATE(vdiv)(unsigned int inst, int index) {
400     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vdiv_inst));
401     vdiv_inst* inst_cream = (vdiv_inst*)inst_base->component;
402 
403     inst_base->cond = BITS(inst, 28, 31);
404     inst_base->idx = index;
405     inst_base->br = TransExtData::NON_BRANCH;
406 
407     inst_cream->dp_operation = BIT(inst, 8);
408     inst_cream->instr = inst;
409 
410     return inst_base;
411 }
412 #endif
413 #ifdef VFP_INTERPRETER_IMPL
414 VDIV_INST : {
415     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
416         CHECK_VFP_ENABLED;
417 
418         vdiv_inst* inst_cream = (vdiv_inst*)inst_base->component;
419 
420         int ret;
421 
422         if (inst_cream->dp_operation)
423             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
424         else
425             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
426 
427         CHECK_VFP_CDP_RET;
428     }
429     cpu->Reg[15] += cpu->GetInstructionSize();
430     INC_PC(sizeof(vdiv_inst));
431     FETCH_INST;
432     GOTO_NEXT_INST;
433 }
434 #endif
435 
436 /* ----------------------------------------------------------------------- */
437 /* VMOVI move immediate */
438 /* cond 1110 1D11 im4H Vd-- 101X 0000 im4L */
439 /* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */
440 #ifdef VFP_INTERPRETER_STRUCT
441 struct vmovi_inst {
442     unsigned int single;
443     unsigned int d;
444     unsigned int imm;
445 };
446 #endif
447 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vmovi)448 static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovi)(unsigned int inst, int index) {
449     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovi_inst));
450     vmovi_inst* inst_cream = (vmovi_inst*)inst_base->component;
451 
452     inst_base->cond = BITS(inst, 28, 31);
453     inst_base->idx = index;
454     inst_base->br = TransExtData::NON_BRANCH;
455 
456     inst_cream->single = BIT(inst, 8) == 0;
457     inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22)
458                                         : BITS(inst, 12, 15) | BIT(inst, 22) << 4);
459     unsigned int imm8 = BITS(inst, 16, 19) << 4 | BITS(inst, 0, 3);
460     if (inst_cream->single)
461         inst_cream->imm = BIT(imm8, 7) << 31 | (BIT(imm8, 6) == 0) << 30 |
462                           (BIT(imm8, 6) ? 0x1f : 0) << 25 | BITS(imm8, 0, 5) << 19;
463     else
464         inst_cream->imm = BIT(imm8, 7) << 31 | (BIT(imm8, 6) == 0) << 30 |
465                           (BIT(imm8, 6) ? 0xff : 0) << 22 | BITS(imm8, 0, 5) << 16;
466     return inst_base;
467 }
468 #endif
469 #ifdef VFP_INTERPRETER_IMPL
470 VMOVI_INST : {
471     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
472         CHECK_VFP_ENABLED;
473 
474         vmovi_inst* inst_cream = (vmovi_inst*)inst_base->component;
475 
476         VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm);
477     }
478     cpu->Reg[15] += cpu->GetInstructionSize();
479     INC_PC(sizeof(vmovi_inst));
480     FETCH_INST;
481     GOTO_NEXT_INST;
482 }
483 #endif
484 
485 /* ----------------------------------------------------------------------- */
486 /* VMOVR move register */
487 /* cond 1110 1D11 0000 Vd-- 101X 01M0 Vm-- */
488 /* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */
489 #ifdef VFP_INTERPRETER_STRUCT
490 struct vmovr_inst {
491     unsigned int single;
492     unsigned int d;
493     unsigned int m;
494 };
495 #endif
496 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vmovr)497 static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovr)(unsigned int inst, int index) {
498     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovr_inst));
499     vmovr_inst* inst_cream = (vmovr_inst*)inst_base->component;
500 
501     inst_base->cond = BITS(inst, 28, 31);
502     inst_base->idx = index;
503     inst_base->br = TransExtData::NON_BRANCH;
504 
505     inst_cream->single = BIT(inst, 8) == 0;
506     inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22)
507                                         : BITS(inst, 12, 15) | BIT(inst, 22) << 4);
508     inst_cream->m = (inst_cream->single ? BITS(inst, 0, 3) << 1 | BIT(inst, 5)
509                                         : BITS(inst, 0, 3) | BIT(inst, 5) << 4);
510     return inst_base;
511 }
512 #endif
513 #ifdef VFP_INTERPRETER_IMPL
514 VMOVR_INST : {
515     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
516         CHECK_VFP_ENABLED;
517 
518         vmovr_inst* inst_cream = (vmovr_inst*)inst_base->component;
519 
520         VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m);
521     }
522     cpu->Reg[15] += cpu->GetInstructionSize();
523     INC_PC(sizeof(vmovr_inst));
524     FETCH_INST;
525     GOTO_NEXT_INST;
526 }
527 #endif
528 
529 /* ----------------------------------------------------------------------- */
530 /* VABS */
531 /* cond 1110 1D11 0000 Vd-- 101X 11M0 Vm-- */
532 #ifdef VFP_INTERPRETER_STRUCT
533 typedef struct _vabs_inst {
534     unsigned int instr;
535     unsigned int dp_operation;
536 } vabs_inst;
537 #endif
538 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vabs)539 static ARM_INST_PTR INTERPRETER_TRANSLATE(vabs)(unsigned int inst, int index) {
540     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vabs_inst));
541     vabs_inst* inst_cream = (vabs_inst*)inst_base->component;
542 
543     inst_base->cond = BITS(inst, 28, 31);
544     inst_base->idx = index;
545     inst_base->br = TransExtData::NON_BRANCH;
546 
547     inst_cream->dp_operation = BIT(inst, 8);
548     inst_cream->instr = inst;
549 
550     return inst_base;
551 }
552 #endif
553 #ifdef VFP_INTERPRETER_IMPL
554 VABS_INST : {
555     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
556         CHECK_VFP_ENABLED;
557 
558         vabs_inst* inst_cream = (vabs_inst*)inst_base->component;
559 
560         int ret;
561 
562         if (inst_cream->dp_operation)
563             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
564         else
565             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
566 
567         CHECK_VFP_CDP_RET;
568     }
569     cpu->Reg[15] += cpu->GetInstructionSize();
570     INC_PC(sizeof(vabs_inst));
571     FETCH_INST;
572     GOTO_NEXT_INST;
573 }
574 #endif
575 
576 /* ----------------------------------------------------------------------- */
577 /* VNEG */
578 /* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */
579 
580 #ifdef VFP_INTERPRETER_STRUCT
581 struct vneg_inst {
582     unsigned int instr;
583     unsigned int dp_operation;
584 };
585 #endif
586 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vneg)587 static ARM_INST_PTR INTERPRETER_TRANSLATE(vneg)(unsigned int inst, int index) {
588     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vneg_inst));
589     vneg_inst* inst_cream = (vneg_inst*)inst_base->component;
590 
591     inst_base->cond = BITS(inst, 28, 31);
592     inst_base->idx = index;
593     inst_base->br = TransExtData::NON_BRANCH;
594 
595     inst_cream->dp_operation = BIT(inst, 8);
596     inst_cream->instr = inst;
597 
598     return inst_base;
599 }
600 #endif
601 #ifdef VFP_INTERPRETER_IMPL
602 VNEG_INST : {
603     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
604         CHECK_VFP_ENABLED;
605 
606         vneg_inst* inst_cream = (vneg_inst*)inst_base->component;
607 
608         int ret;
609 
610         if (inst_cream->dp_operation)
611             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
612         else
613             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
614 
615         CHECK_VFP_CDP_RET;
616     }
617     cpu->Reg[15] += cpu->GetInstructionSize();
618     INC_PC(sizeof(vneg_inst));
619     FETCH_INST;
620     GOTO_NEXT_INST;
621 }
622 #endif
623 
624 /* ----------------------------------------------------------------------- */
625 /* VSQRT */
626 /* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */
627 #ifdef VFP_INTERPRETER_STRUCT
628 struct vsqrt_inst {
629     unsigned int instr;
630     unsigned int dp_operation;
631 };
632 #endif
633 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vsqrt)634 static ARM_INST_PTR INTERPRETER_TRANSLATE(vsqrt)(unsigned int inst, int index) {
635     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vsqrt_inst));
636     vsqrt_inst* inst_cream = (vsqrt_inst*)inst_base->component;
637 
638     inst_base->cond = BITS(inst, 28, 31);
639     inst_base->idx = index;
640     inst_base->br = TransExtData::NON_BRANCH;
641 
642     inst_cream->dp_operation = BIT(inst, 8);
643     inst_cream->instr = inst;
644 
645     return inst_base;
646 }
647 #endif
648 #ifdef VFP_INTERPRETER_IMPL
649 VSQRT_INST : {
650     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
651         CHECK_VFP_ENABLED;
652 
653         vsqrt_inst* inst_cream = (vsqrt_inst*)inst_base->component;
654 
655         int ret;
656 
657         if (inst_cream->dp_operation)
658             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
659         else
660             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
661 
662         CHECK_VFP_CDP_RET;
663     }
664     cpu->Reg[15] += cpu->GetInstructionSize();
665     INC_PC(sizeof(vsqrt_inst));
666     FETCH_INST;
667     GOTO_NEXT_INST;
668 }
669 #endif
670 
671 /* ----------------------------------------------------------------------- */
672 /* VCMP VCMPE */
673 /* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 1 */
674 #ifdef VFP_INTERPRETER_STRUCT
675 struct vcmp_inst {
676     unsigned int instr;
677     unsigned int dp_operation;
678 };
679 #endif
680 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vcmp)681 static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp)(unsigned int inst, int index) {
682     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp_inst));
683     vcmp_inst* inst_cream = (vcmp_inst*)inst_base->component;
684 
685     inst_base->cond = BITS(inst, 28, 31);
686     inst_base->idx = index;
687     inst_base->br = TransExtData::NON_BRANCH;
688 
689     inst_cream->dp_operation = BIT(inst, 8);
690     inst_cream->instr = inst;
691 
692     return inst_base;
693 }
694 #endif
695 #ifdef VFP_INTERPRETER_IMPL
696 VCMP_INST : {
697     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
698         CHECK_VFP_ENABLED;
699 
700         vcmp_inst* inst_cream = (vcmp_inst*)inst_base->component;
701 
702         int ret;
703 
704         if (inst_cream->dp_operation)
705             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
706         else
707             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
708 
709         CHECK_VFP_CDP_RET;
710     }
711     cpu->Reg[15] += cpu->GetInstructionSize();
712     INC_PC(sizeof(vcmp_inst));
713     FETCH_INST;
714     GOTO_NEXT_INST;
715 }
716 #endif
717 
718 /* ----------------------------------------------------------------------- */
719 /* VCMP VCMPE */
720 /* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 2 */
721 #ifdef VFP_INTERPRETER_STRUCT
722 struct vcmp2_inst {
723     unsigned int instr;
724     unsigned int dp_operation;
725 };
726 #endif
727 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vcmp2)728 static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp2)(unsigned int inst, int index) {
729     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp2_inst));
730     vcmp2_inst* inst_cream = (vcmp2_inst*)inst_base->component;
731 
732     inst_base->cond = BITS(inst, 28, 31);
733     inst_base->idx = index;
734     inst_base->br = TransExtData::NON_BRANCH;
735 
736     inst_cream->dp_operation = BIT(inst, 8);
737     inst_cream->instr = inst;
738 
739     return inst_base;
740 }
741 #endif
742 #ifdef VFP_INTERPRETER_IMPL
743 VCMP2_INST : {
744     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
745         CHECK_VFP_ENABLED;
746 
747         vcmp2_inst* inst_cream = (vcmp2_inst*)inst_base->component;
748 
749         int ret;
750 
751         if (inst_cream->dp_operation)
752             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
753         else
754             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
755 
756         CHECK_VFP_CDP_RET;
757     }
758     cpu->Reg[15] += cpu->GetInstructionSize();
759     INC_PC(sizeof(vcmp2_inst));
760     FETCH_INST;
761     GOTO_NEXT_INST;
762 }
763 #endif
764 
765 /* ----------------------------------------------------------------------- */
766 /* VCVTBDS between double and single */
767 /* cond 1110 1D11 0111 Vd-- 101X 11M0 Vm-- */
768 #ifdef VFP_INTERPRETER_STRUCT
769 struct vcvtbds_inst {
770     unsigned int instr;
771     unsigned int dp_operation;
772 };
773 #endif
774 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vcvtbds)775 static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbds)(unsigned int inst, int index) {
776     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbds_inst));
777     vcvtbds_inst* inst_cream = (vcvtbds_inst*)inst_base->component;
778 
779     inst_base->cond = BITS(inst, 28, 31);
780     inst_base->idx = index;
781     inst_base->br = TransExtData::NON_BRANCH;
782 
783     inst_cream->dp_operation = BIT(inst, 8);
784     inst_cream->instr = inst;
785 
786     return inst_base;
787 }
788 #endif
789 #ifdef VFP_INTERPRETER_IMPL
790 VCVTBDS_INST : {
791     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
792         CHECK_VFP_ENABLED;
793 
794         vcvtbds_inst* inst_cream = (vcvtbds_inst*)inst_base->component;
795 
796         int ret;
797 
798         if (inst_cream->dp_operation)
799             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
800         else
801             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
802 
803         CHECK_VFP_CDP_RET;
804     }
805     cpu->Reg[15] += cpu->GetInstructionSize();
806     INC_PC(sizeof(vcvtbds_inst));
807     FETCH_INST;
808     GOTO_NEXT_INST;
809 }
810 #endif
811 
812 /* ----------------------------------------------------------------------- */
813 /* VCVTBFF between floating point and fixed point */
814 /* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */
815 #ifdef VFP_INTERPRETER_STRUCT
816 struct vcvtbff_inst {
817     unsigned int instr;
818     unsigned int dp_operation;
819 };
820 #endif
821 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vcvtbff)822 static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbff)(unsigned int inst, int index) {
823     VFP_DEBUG_UNTESTED(VCVTBFF);
824 
825     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbff_inst));
826     vcvtbff_inst* inst_cream = (vcvtbff_inst*)inst_base->component;
827 
828     inst_base->cond = BITS(inst, 28, 31);
829     inst_base->idx = index;
830     inst_base->br = TransExtData::NON_BRANCH;
831 
832     inst_cream->dp_operation = BIT(inst, 8);
833     inst_cream->instr = inst;
834 
835     return inst_base;
836 }
837 #endif
838 #ifdef VFP_INTERPRETER_IMPL
839 VCVTBFF_INST : {
840     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
841         CHECK_VFP_ENABLED;
842 
843         vcvtbff_inst* inst_cream = (vcvtbff_inst*)inst_base->component;
844 
845         int ret;
846 
847         if (inst_cream->dp_operation)
848             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
849         else
850             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
851 
852         CHECK_VFP_CDP_RET;
853     }
854     cpu->Reg[15] += cpu->GetInstructionSize();
855     INC_PC(sizeof(vcvtbff_inst));
856     FETCH_INST;
857     GOTO_NEXT_INST;
858 }
859 #endif
860 
861 /* ----------------------------------------------------------------------- */
862 /* VCVTBFI between floating point and integer */
863 /* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */
864 #ifdef VFP_INTERPRETER_STRUCT
865 struct vcvtbfi_inst {
866     unsigned int instr;
867     unsigned int dp_operation;
868 };
869 #endif
870 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vcvtbfi)871 static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbfi)(unsigned int inst, int index) {
872     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbfi_inst));
873     vcvtbfi_inst* inst_cream = (vcvtbfi_inst*)inst_base->component;
874 
875     inst_base->cond = BITS(inst, 28, 31);
876     inst_base->idx = index;
877     inst_base->br = TransExtData::NON_BRANCH;
878 
879     inst_cream->dp_operation = BIT(inst, 8);
880     inst_cream->instr = inst;
881 
882     return inst_base;
883 }
884 #endif
885 #ifdef VFP_INTERPRETER_IMPL
886 VCVTBFI_INST : {
887     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
888         CHECK_VFP_ENABLED;
889 
890         vcvtbfi_inst* inst_cream = (vcvtbfi_inst*)inst_base->component;
891 
892         int ret;
893 
894         if (inst_cream->dp_operation)
895             ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
896         else
897             ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
898 
899         CHECK_VFP_CDP_RET;
900     }
901     cpu->Reg[15] += cpu->GetInstructionSize();
902     INC_PC(sizeof(vcvtbfi_inst));
903     FETCH_INST;
904     GOTO_NEXT_INST;
905 }
906 #endif
907 
908 /* ----------------------------------------------------------------------- */
909 /* MRC / MCR instructions */
910 /* cond 1110 AAAL XXXX XXXX 101C XBB1 XXXX */
911 /* cond 1110 op11 CRn- Rt-- copr op21 CRm- */
912 
913 /* ----------------------------------------------------------------------- */
914 /* VMOVBRS between register and single precision */
915 /* cond 1110 000o Vn-- Rt-- 1010 N001 0000 */
916 /* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */
917 #ifdef VFP_INTERPRETER_STRUCT
918 struct vmovbrs_inst {
919     unsigned int to_arm;
920     unsigned int t;
921     unsigned int n;
922 };
923 #endif
924 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vmovbrs)925 static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrs)(unsigned int inst, int index) {
926     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrs_inst));
927     vmovbrs_inst* inst_cream = (vmovbrs_inst*)inst_base->component;
928 
929     inst_base->cond = BITS(inst, 28, 31);
930     inst_base->idx = index;
931     inst_base->br = TransExtData::NON_BRANCH;
932 
933     inst_cream->to_arm = BIT(inst, 20) == 1;
934     inst_cream->t = BITS(inst, 12, 15);
935     inst_cream->n = BIT(inst, 7) | BITS(inst, 16, 19) << 1;
936 
937     return inst_base;
938 }
939 #endif
940 #ifdef VFP_INTERPRETER_IMPL
941 VMOVBRS_INST : {
942     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
943         CHECK_VFP_ENABLED;
944 
945         vmovbrs_inst* inst_cream = (vmovbrs_inst*)inst_base->component;
946 
947         VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t]));
948     }
949     cpu->Reg[15] += cpu->GetInstructionSize();
950     INC_PC(sizeof(vmovbrs_inst));
951     FETCH_INST;
952     GOTO_NEXT_INST;
953 }
954 #endif
955 
956 /* ----------------------------------------------------------------------- */
957 /* VMSR */
958 /* cond 1110 1110 reg- Rt-- 1010 0001 0000 */
959 /* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */
960 #ifdef VFP_INTERPRETER_STRUCT
961 struct vmsr_inst {
962     unsigned int reg;
963     unsigned int Rt;
964 };
965 #endif
966 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vmsr)967 static ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index) {
968     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmsr_inst));
969     vmsr_inst* inst_cream = (vmsr_inst*)inst_base->component;
970 
971     inst_base->cond = BITS(inst, 28, 31);
972     inst_base->idx = index;
973     inst_base->br = TransExtData::NON_BRANCH;
974 
975     inst_cream->reg = BITS(inst, 16, 19);
976     inst_cream->Rt = BITS(inst, 12, 15);
977 
978     return inst_base;
979 }
980 #endif
981 #ifdef VFP_INTERPRETER_IMPL
982 VMSR_INST : {
983     if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
984         /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled ,
985            and in privileged mode */
986         /* Exceptions must be checked, according to v7 ref manual */
987         CHECK_VFP_ENABLED;
988 
989         vmsr_inst* const inst_cream = (vmsr_inst*)inst_base->component;
990 
991         unsigned int reg = inst_cream->reg;
992         unsigned int rt = inst_cream->Rt;
993 
994         if (reg == 1) {
995             cpu->VFP[VFP_FPSCR] = cpu->Reg[rt];
996         } else if (cpu->InAPrivilegedMode()) {
997             if (reg == 8)
998                 cpu->VFP[VFP_FPEXC] = cpu->Reg[rt];
999             else if (reg == 9)
1000                 cpu->VFP[VFP_FPINST] = cpu->Reg[rt];
1001             else if (reg == 10)
1002                 cpu->VFP[VFP_FPINST2] = cpu->Reg[rt];
1003         }
1004     }
1005     cpu->Reg[15] += cpu->GetInstructionSize();
1006     INC_PC(sizeof(vmsr_inst));
1007     FETCH_INST;
1008     GOTO_NEXT_INST;
1009 }
1010 #endif
1011 
1012 /* ----------------------------------------------------------------------- */
1013 /* VMOVBRC register to scalar */
1014 /* cond 1110 0XX0 Vd-- Rt-- 1011 DXX1 0000 */
1015 /* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */
1016 #ifdef VFP_INTERPRETER_STRUCT
1017 struct vmovbrc_inst {
1018     unsigned int esize;
1019     unsigned int index;
1020     unsigned int d;
1021     unsigned int t;
1022 };
1023 #endif
1024 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vmovbrc)1025 static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index) {
1026     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrc_inst));
1027     vmovbrc_inst* inst_cream = (vmovbrc_inst*)inst_base->component;
1028 
1029     inst_base->cond = BITS(inst, 28, 31);
1030     inst_base->idx = index;
1031     inst_base->br = TransExtData::NON_BRANCH;
1032 
1033     inst_cream->d = BITS(inst, 16, 19) | BIT(inst, 7) << 4;
1034     inst_cream->t = BITS(inst, 12, 15);
1035     /* VFP variant of instruction */
1036     inst_cream->esize = 32;
1037     inst_cream->index = BIT(inst, 21);
1038 
1039     return inst_base;
1040 }
1041 #endif
1042 #ifdef VFP_INTERPRETER_IMPL
1043 VMOVBRC_INST : {
1044     if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1045         CHECK_VFP_ENABLED;
1046 
1047         vmovbrc_inst* const inst_cream = (vmovbrc_inst*)inst_base->component;
1048 
1049         cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index] = cpu->Reg[inst_cream->t];
1050     }
1051     cpu->Reg[15] += cpu->GetInstructionSize();
1052     INC_PC(sizeof(vmovbrc_inst));
1053     FETCH_INST;
1054     GOTO_NEXT_INST;
1055 }
1056 #endif
1057 
1058 /* ----------------------------------------------------------------------- */
1059 /* VMRS */
1060 /* cond 1110 1111 CRn- Rt-- 1010 0001 0000 */
1061 /* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */
1062 #ifdef VFP_INTERPRETER_STRUCT
1063 struct vmrs_inst {
1064     unsigned int reg;
1065     unsigned int Rt;
1066 };
1067 #endif
1068 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vmrs)1069 static ARM_INST_PTR INTERPRETER_TRANSLATE(vmrs)(unsigned int inst, int index) {
1070     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmrs_inst));
1071     vmrs_inst* inst_cream = (vmrs_inst*)inst_base->component;
1072 
1073     inst_base->cond = BITS(inst, 28, 31);
1074     inst_base->idx = index;
1075     inst_base->br = TransExtData::NON_BRANCH;
1076 
1077     inst_cream->reg = BITS(inst, 16, 19);
1078     inst_cream->Rt = BITS(inst, 12, 15);
1079 
1080     return inst_base;
1081 }
1082 #endif
1083 #ifdef VFP_INTERPRETER_IMPL
1084 VMRS_INST : {
1085     if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1086         /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled,
1087            and in privileged mode */
1088         /* Exceptions must be checked, according to v7 ref manual */
1089         CHECK_VFP_ENABLED;
1090 
1091         vmrs_inst* const inst_cream = (vmrs_inst*)inst_base->component;
1092 
1093         unsigned int reg = inst_cream->reg;
1094         unsigned int rt = inst_cream->Rt;
1095 
1096         if (reg == 1) // FPSCR
1097         {
1098             if (rt != 15) {
1099                 cpu->Reg[rt] = cpu->VFP[VFP_FPSCR];
1100             } else {
1101                 cpu->NFlag = (cpu->VFP[VFP_FPSCR] >> 31) & 1;
1102                 cpu->ZFlag = (cpu->VFP[VFP_FPSCR] >> 30) & 1;
1103                 cpu->CFlag = (cpu->VFP[VFP_FPSCR] >> 29) & 1;
1104                 cpu->VFlag = (cpu->VFP[VFP_FPSCR] >> 28) & 1;
1105             }
1106         } else if (reg == 0) {
1107             cpu->Reg[rt] = cpu->VFP[VFP_FPSID];
1108         } else if (reg == 6) {
1109             cpu->Reg[rt] = cpu->VFP[VFP_MVFR1];
1110         } else if (reg == 7) {
1111             cpu->Reg[rt] = cpu->VFP[VFP_MVFR0];
1112         } else if (cpu->InAPrivilegedMode()) {
1113             if (reg == 8)
1114                 cpu->Reg[rt] = cpu->VFP[VFP_FPEXC];
1115             else if (reg == 9)
1116                 cpu->Reg[rt] = cpu->VFP[VFP_FPINST];
1117             else if (reg == 10)
1118                 cpu->Reg[rt] = cpu->VFP[VFP_FPINST2];
1119         }
1120     }
1121     cpu->Reg[15] += cpu->GetInstructionSize();
1122     INC_PC(sizeof(vmrs_inst));
1123     FETCH_INST;
1124     GOTO_NEXT_INST;
1125 }
1126 #endif
1127 
1128 /* ----------------------------------------------------------------------- */
1129 /* VMOVBCR scalar to register */
1130 /* cond 1110 XXX1 Vd-- Rt-- 1011 NXX1 0000 */
1131 /* cond 1110 op11 CRn- Rt-- copr op21 CRm- MCR */
1132 #ifdef VFP_INTERPRETER_STRUCT
1133 struct vmovbcr_inst {
1134     unsigned int esize;
1135     unsigned int index;
1136     unsigned int d;
1137     unsigned int t;
1138 };
1139 #endif
1140 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vmovbcr)1141 static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index) {
1142     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbcr_inst));
1143     vmovbcr_inst* inst_cream = (vmovbcr_inst*)inst_base->component;
1144 
1145     inst_base->cond = BITS(inst, 28, 31);
1146     inst_base->idx = index;
1147     inst_base->br = TransExtData::NON_BRANCH;
1148 
1149     inst_cream->d = BITS(inst, 16, 19) | BIT(inst, 7) << 4;
1150     inst_cream->t = BITS(inst, 12, 15);
1151     /* VFP variant of instruction */
1152     inst_cream->esize = 32;
1153     inst_cream->index = BIT(inst, 21);
1154 
1155     return inst_base;
1156 }
1157 #endif
1158 #ifdef VFP_INTERPRETER_IMPL
1159 VMOVBCR_INST : {
1160     if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1161         CHECK_VFP_ENABLED;
1162 
1163         vmovbcr_inst* const inst_cream = (vmovbcr_inst*)inst_base->component;
1164 
1165         cpu->Reg[inst_cream->t] = cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index];
1166     }
1167     cpu->Reg[15] += cpu->GetInstructionSize();
1168     INC_PC(sizeof(vmovbcr_inst));
1169     FETCH_INST;
1170     GOTO_NEXT_INST;
1171 }
1172 #endif
1173 
1174 /* ----------------------------------------------------------------------- */
1175 /* MRRC / MCRR instructions */
1176 /* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */
1177 /* cond 1100 0100 Rt2- Rt-- copr opc1 CRm- MCRR */
1178 
1179 /* ----------------------------------------------------------------------- */
1180 /* VMOVBRRSS between 2 registers to 2 singles */
1181 /* cond 1100 010X Rt2- Rt-- 1010 00X1 Vm-- */
1182 /* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */
1183 #ifdef VFP_INTERPRETER_STRUCT
1184 struct vmovbrrss_inst {
1185     unsigned int to_arm;
1186     unsigned int t;
1187     unsigned int t2;
1188     unsigned int m;
1189 };
1190 #endif
1191 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vmovbrrss)1192 static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrss)(unsigned int inst, int index) {
1193     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrss_inst));
1194     vmovbrrss_inst* inst_cream = (vmovbrrss_inst*)inst_base->component;
1195 
1196     inst_base->cond = BITS(inst, 28, 31);
1197     inst_base->idx = index;
1198     inst_base->br = TransExtData::NON_BRANCH;
1199 
1200     inst_cream->to_arm = BIT(inst, 20) == 1;
1201     inst_cream->t = BITS(inst, 12, 15);
1202     inst_cream->t2 = BITS(inst, 16, 19);
1203     inst_cream->m = BITS(inst, 0, 3) << 1 | BIT(inst, 5);
1204 
1205     return inst_base;
1206 }
1207 #endif
1208 #ifdef VFP_INTERPRETER_IMPL
1209 VMOVBRRSS_INST : {
1210     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1211         CHECK_VFP_ENABLED;
1212 
1213         vmovbrrss_inst* const inst_cream = (vmovbrrss_inst*)inst_base->component;
1214 
1215         VMOVBRRSS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m,
1216                   &cpu->Reg[inst_cream->t], &cpu->Reg[inst_cream->t2]);
1217     }
1218     cpu->Reg[15] += cpu->GetInstructionSize();
1219     INC_PC(sizeof(vmovbrrss_inst));
1220     FETCH_INST;
1221     GOTO_NEXT_INST;
1222 }
1223 #endif
1224 
1225 /* ----------------------------------------------------------------------- */
1226 /* VMOVBRRD between 2 registers and 1 double */
1227 /* cond 1100 010X Rt2- Rt-- 1011 00X1 Vm-- */
1228 /* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */
1229 #ifdef VFP_INTERPRETER_STRUCT
1230 struct vmovbrrd_inst {
1231     unsigned int to_arm;
1232     unsigned int t;
1233     unsigned int t2;
1234     unsigned int m;
1235 };
1236 #endif
1237 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vmovbrrd)1238 static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrd)(unsigned int inst, int index) {
1239     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrd_inst));
1240     vmovbrrd_inst* inst_cream = (vmovbrrd_inst*)inst_base->component;
1241 
1242     inst_base->cond = BITS(inst, 28, 31);
1243     inst_base->idx = index;
1244     inst_base->br = TransExtData::NON_BRANCH;
1245 
1246     inst_cream->to_arm = BIT(inst, 20) == 1;
1247     inst_cream->t = BITS(inst, 12, 15);
1248     inst_cream->t2 = BITS(inst, 16, 19);
1249     inst_cream->m = BIT(inst, 5) << 4 | BITS(inst, 0, 3);
1250 
1251     return inst_base;
1252 }
1253 #endif
1254 #ifdef VFP_INTERPRETER_IMPL
1255 VMOVBRRD_INST : {
1256     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1257         CHECK_VFP_ENABLED;
1258 
1259         vmovbrrd_inst* inst_cream = (vmovbrrd_inst*)inst_base->component;
1260 
1261         VMOVBRRD(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m,
1262                  &(cpu->Reg[inst_cream->t]), &(cpu->Reg[inst_cream->t2]));
1263     }
1264     cpu->Reg[15] += cpu->GetInstructionSize();
1265     INC_PC(sizeof(vmovbrrd_inst));
1266     FETCH_INST;
1267     GOTO_NEXT_INST;
1268 }
1269 #endif
1270 
1271 /* ----------------------------------------------------------------------- */
1272 /* LDC/STC between 2 registers and 1 double */
1273 /* cond 110X XXX1 Rn-- CRd- copr imm- imm- LDC */
1274 /* cond 110X XXX0 Rn-- CRd- copr imm8 imm8 STC */
1275 
1276 /* ----------------------------------------------------------------------- */
1277 /* VSTR */
1278 /* cond 1101 UD00 Rn-- Vd-- 101X imm8 imm8 */
1279 #ifdef VFP_INTERPRETER_STRUCT
1280 struct vstr_inst {
1281     unsigned int single;
1282     unsigned int n;
1283     unsigned int d;
1284     unsigned int imm32;
1285     unsigned int add;
1286 };
1287 #endif
1288 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vstr)1289 static ARM_INST_PTR INTERPRETER_TRANSLATE(vstr)(unsigned int inst, int index) {
1290     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vstr_inst));
1291     vstr_inst* inst_cream = (vstr_inst*)inst_base->component;
1292 
1293     inst_base->cond = BITS(inst, 28, 31);
1294     inst_base->idx = index;
1295     inst_base->br = TransExtData::NON_BRANCH;
1296 
1297     inst_cream->single = BIT(inst, 8) == 0;
1298     inst_cream->add = BIT(inst, 23);
1299     inst_cream->imm32 = BITS(inst, 0, 7) << 2;
1300     inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22)
1301                                         : BITS(inst, 12, 15) | BIT(inst, 22) << 4);
1302     inst_cream->n = BITS(inst, 16, 19);
1303 
1304     return inst_base;
1305 }
1306 #endif
1307 #ifdef VFP_INTERPRETER_IMPL
1308 VSTR_INST : {
1309     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1310         CHECK_VFP_ENABLED;
1311 
1312         vstr_inst* inst_cream = (vstr_inst*)inst_base->component;
1313 
1314         unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8
1315                                                  : cpu->Reg[inst_cream->n]);
1316         addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32);
1317 
1318         if (inst_cream->single) {
1319             cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d]);
1320         } else {
1321             const u32 word1 = cpu->ExtReg[inst_cream->d * 2 + 0];
1322             const u32 word2 = cpu->ExtReg[inst_cream->d * 2 + 1];
1323 
1324             if (cpu->InBigEndianMode()) {
1325                 cpu->WriteMemory32(addr + 0, word2);
1326                 cpu->WriteMemory32(addr + 4, word1);
1327             } else {
1328                 cpu->WriteMemory32(addr + 0, word1);
1329                 cpu->WriteMemory32(addr + 4, word2);
1330             }
1331         }
1332     }
1333     cpu->Reg[15] += cpu->GetInstructionSize();
1334     INC_PC(sizeof(vstr_inst));
1335     FETCH_INST;
1336     GOTO_NEXT_INST;
1337 }
1338 #endif
1339 
1340 /* ----------------------------------------------------------------------- */
1341 /* VPUSH */
1342 /* cond 1101 0D10 1101 Vd-- 101X imm8 imm8 */
1343 #ifdef VFP_INTERPRETER_STRUCT
1344 struct vpush_inst {
1345     unsigned int single;
1346     unsigned int d;
1347     unsigned int imm32;
1348     unsigned int regs;
1349 };
1350 #endif
1351 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vpush)1352 static ARM_INST_PTR INTERPRETER_TRANSLATE(vpush)(unsigned int inst, int index) {
1353     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vpush_inst));
1354     vpush_inst* inst_cream = (vpush_inst*)inst_base->component;
1355 
1356     inst_base->cond = BITS(inst, 28, 31);
1357     inst_base->idx = index;
1358     inst_base->br = TransExtData::NON_BRANCH;
1359 
1360     inst_cream->single = BIT(inst, 8) == 0;
1361     inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22)
1362                                         : BITS(inst, 12, 15) | BIT(inst, 22) << 4);
1363     inst_cream->imm32 = BITS(inst, 0, 7) << 2;
1364     inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7));
1365 
1366     return inst_base;
1367 }
1368 #endif
1369 #ifdef VFP_INTERPRETER_IMPL
1370 VPUSH_INST : {
1371     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1372         CHECK_VFP_ENABLED;
1373 
1374         vpush_inst* inst_cream = (vpush_inst*)inst_base->component;
1375 
1376         addr = cpu->Reg[R13] - inst_cream->imm32;
1377 
1378         for (unsigned int i = 0; i < inst_cream->regs; i++) {
1379             if (inst_cream->single) {
1380                 cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d + i]);
1381                 addr += 4;
1382             } else {
1383                 const u32 word1 = cpu->ExtReg[(inst_cream->d + i) * 2 + 0];
1384                 const u32 word2 = cpu->ExtReg[(inst_cream->d + i) * 2 + 1];
1385 
1386                 if (cpu->InBigEndianMode()) {
1387                     cpu->WriteMemory32(addr + 0, word2);
1388                     cpu->WriteMemory32(addr + 4, word1);
1389                 } else {
1390                     cpu->WriteMemory32(addr + 0, word1);
1391                     cpu->WriteMemory32(addr + 4, word2);
1392                 }
1393 
1394                 addr += 8;
1395             }
1396         }
1397 
1398         cpu->Reg[R13] -= inst_cream->imm32;
1399     }
1400     cpu->Reg[15] += cpu->GetInstructionSize();
1401     INC_PC(sizeof(vpush_inst));
1402     FETCH_INST;
1403     GOTO_NEXT_INST;
1404 }
1405 #endif
1406 
1407 /* ----------------------------------------------------------------------- */
1408 /* VSTM */
1409 /* cond 110P UDW0 Rn-- Vd-- 101X imm8 imm8 */
1410 #ifdef VFP_INTERPRETER_STRUCT
1411 struct vstm_inst {
1412     unsigned int single;
1413     unsigned int add;
1414     unsigned int wback;
1415     unsigned int d;
1416     unsigned int n;
1417     unsigned int imm32;
1418     unsigned int regs;
1419 };
1420 #endif
1421 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vstm)1422 static ARM_INST_PTR INTERPRETER_TRANSLATE(vstm)(unsigned int inst, int index) {
1423     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vstm_inst));
1424     vstm_inst* inst_cream = (vstm_inst*)inst_base->component;
1425 
1426     inst_base->cond = BITS(inst, 28, 31);
1427     inst_base->idx = index;
1428     inst_base->br = TransExtData::NON_BRANCH;
1429 
1430     inst_cream->single = BIT(inst, 8) == 0;
1431     inst_cream->add = BIT(inst, 23);
1432     inst_cream->wback = BIT(inst, 21);
1433     inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22)
1434                                         : BITS(inst, 12, 15) | BIT(inst, 22) << 4);
1435     inst_cream->n = BITS(inst, 16, 19);
1436     inst_cream->imm32 = BITS(inst, 0, 7) << 2;
1437     inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7));
1438 
1439     return inst_base;
1440 }
1441 #endif
1442 #ifdef VFP_INTERPRETER_IMPL
1443 VSTM_INST : /* encoding 1 */
1444 {
1445     if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1446         CHECK_VFP_ENABLED;
1447 
1448         vstm_inst* inst_cream = (vstm_inst*)inst_base->component;
1449 
1450         u32 address = cpu->Reg[inst_cream->n];
1451 
1452         // Only possible in ARM mode, where PC accesses have an 8 byte offset.
1453         if (inst_cream->n == 15)
1454             address += 8;
1455 
1456         if (inst_cream->add == 0)
1457             address -= inst_cream->imm32;
1458 
1459         for (unsigned int i = 0; i < inst_cream->regs; i++) {
1460             if (inst_cream->single) {
1461                 cpu->WriteMemory32(address, cpu->ExtReg[inst_cream->d + i]);
1462                 address += 4;
1463             } else {
1464                 const u32 word1 = cpu->ExtReg[(inst_cream->d + i) * 2 + 0];
1465                 const u32 word2 = cpu->ExtReg[(inst_cream->d + i) * 2 + 1];
1466 
1467                 if (cpu->InBigEndianMode()) {
1468                     cpu->WriteMemory32(address + 0, word2);
1469                     cpu->WriteMemory32(address + 4, word1);
1470                 } else {
1471                     cpu->WriteMemory32(address + 0, word1);
1472                     cpu->WriteMemory32(address + 4, word2);
1473                 }
1474 
1475                 address += 8;
1476             }
1477         }
1478         if (inst_cream->wback) {
1479             cpu->Reg[inst_cream->n] =
1480                 (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32
1481                                  : cpu->Reg[inst_cream->n] - inst_cream->imm32);
1482         }
1483     }
1484     cpu->Reg[15] += 4;
1485     INC_PC(sizeof(vstm_inst));
1486 
1487     FETCH_INST;
1488     GOTO_NEXT_INST;
1489 }
1490 #endif
1491 
1492 /* ----------------------------------------------------------------------- */
1493 /* VPOP */
1494 /* cond 1100 1D11 1101 Vd-- 101X imm8 imm8 */
1495 #ifdef VFP_INTERPRETER_STRUCT
1496 struct vpop_inst {
1497     unsigned int single;
1498     unsigned int d;
1499     unsigned int imm32;
1500     unsigned int regs;
1501 };
1502 #endif
1503 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vpop)1504 static ARM_INST_PTR INTERPRETER_TRANSLATE(vpop)(unsigned int inst, int index) {
1505     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vpop_inst));
1506     vpop_inst* inst_cream = (vpop_inst*)inst_base->component;
1507 
1508     inst_base->cond = BITS(inst, 28, 31);
1509     inst_base->idx = index;
1510     inst_base->br = TransExtData::NON_BRANCH;
1511 
1512     inst_cream->single = BIT(inst, 8) == 0;
1513     inst_cream->d = (inst_cream->single ? (BITS(inst, 12, 15) << 1) | BIT(inst, 22)
1514                                         : BITS(inst, 12, 15) | (BIT(inst, 22) << 4));
1515     inst_cream->imm32 = BITS(inst, 0, 7) << 2;
1516     inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7));
1517 
1518     return inst_base;
1519 }
1520 #endif
1521 #ifdef VFP_INTERPRETER_IMPL
1522 VPOP_INST : {
1523     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1524         CHECK_VFP_ENABLED;
1525 
1526         vpop_inst* inst_cream = (vpop_inst*)inst_base->component;
1527 
1528         addr = cpu->Reg[R13];
1529 
1530         for (unsigned int i = 0; i < inst_cream->regs; i++) {
1531             if (inst_cream->single) {
1532                 cpu->ExtReg[inst_cream->d + i] = cpu->ReadMemory32(addr);
1533                 addr += 4;
1534             } else {
1535                 const u32 word1 = cpu->ReadMemory32(addr + 0);
1536                 const u32 word2 = cpu->ReadMemory32(addr + 4);
1537 
1538                 if (cpu->InBigEndianMode()) {
1539                     cpu->ExtReg[(inst_cream->d + i) * 2 + 0] = word2;
1540                     cpu->ExtReg[(inst_cream->d + i) * 2 + 1] = word1;
1541                 } else {
1542                     cpu->ExtReg[(inst_cream->d + i) * 2 + 0] = word1;
1543                     cpu->ExtReg[(inst_cream->d + i) * 2 + 1] = word2;
1544                 }
1545 
1546                 addr += 8;
1547             }
1548         }
1549         cpu->Reg[R13] += inst_cream->imm32;
1550     }
1551     cpu->Reg[15] += cpu->GetInstructionSize();
1552     INC_PC(sizeof(vpop_inst));
1553     FETCH_INST;
1554     GOTO_NEXT_INST;
1555 }
1556 #endif
1557 
1558 /* ----------------------------------------------------------------------- */
1559 /* VLDR */
1560 /* cond 1101 UD01 Rn-- Vd-- 101X imm8 imm8 */
1561 #ifdef VFP_INTERPRETER_STRUCT
1562 struct vldr_inst {
1563     unsigned int single;
1564     unsigned int n;
1565     unsigned int d;
1566     unsigned int imm32;
1567     unsigned int add;
1568 };
1569 #endif
1570 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vldr)1571 static ARM_INST_PTR INTERPRETER_TRANSLATE(vldr)(unsigned int inst, int index) {
1572     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vldr_inst));
1573     vldr_inst* inst_cream = (vldr_inst*)inst_base->component;
1574 
1575     inst_base->cond = BITS(inst, 28, 31);
1576     inst_base->idx = index;
1577     inst_base->br = TransExtData::NON_BRANCH;
1578 
1579     inst_cream->single = BIT(inst, 8) == 0;
1580     inst_cream->add = BIT(inst, 23);
1581     inst_cream->imm32 = BITS(inst, 0, 7) << 2;
1582     inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22)
1583                                         : BITS(inst, 12, 15) | BIT(inst, 22) << 4);
1584     inst_cream->n = BITS(inst, 16, 19);
1585 
1586     return inst_base;
1587 }
1588 #endif
1589 #ifdef VFP_INTERPRETER_IMPL
1590 VLDR_INST : {
1591     if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1592         CHECK_VFP_ENABLED;
1593 
1594         vldr_inst* inst_cream = (vldr_inst*)inst_base->component;
1595 
1596         unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8
1597                                                  : cpu->Reg[inst_cream->n]);
1598         addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32);
1599 
1600         if (inst_cream->single) {
1601             cpu->ExtReg[inst_cream->d] = cpu->ReadMemory32(addr);
1602         } else {
1603             const u32 word1 = cpu->ReadMemory32(addr + 0);
1604             const u32 word2 = cpu->ReadMemory32(addr + 4);
1605 
1606             if (cpu->InBigEndianMode()) {
1607                 cpu->ExtReg[inst_cream->d * 2 + 0] = word2;
1608                 cpu->ExtReg[inst_cream->d * 2 + 1] = word1;
1609             } else {
1610                 cpu->ExtReg[inst_cream->d * 2 + 0] = word1;
1611                 cpu->ExtReg[inst_cream->d * 2 + 1] = word2;
1612             }
1613         }
1614     }
1615     cpu->Reg[15] += cpu->GetInstructionSize();
1616     INC_PC(sizeof(vldr_inst));
1617     FETCH_INST;
1618     GOTO_NEXT_INST;
1619 }
1620 #endif
1621 
1622 /* ----------------------------------------------------------------------- */
1623 /* VLDM */
1624 /* cond 110P UDW1 Rn-- Vd-- 101X imm8 imm8 */
1625 #ifdef VFP_INTERPRETER_STRUCT
1626 struct vldm_inst {
1627     unsigned int single;
1628     unsigned int add;
1629     unsigned int wback;
1630     unsigned int d;
1631     unsigned int n;
1632     unsigned int imm32;
1633     unsigned int regs;
1634 };
1635 #endif
1636 #ifdef VFP_INTERPRETER_TRANS
INTERPRETER_TRANSLATE(vldm)1637 static ARM_INST_PTR INTERPRETER_TRANSLATE(vldm)(unsigned int inst, int index) {
1638     arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vldm_inst));
1639     vldm_inst* inst_cream = (vldm_inst*)inst_base->component;
1640 
1641     inst_base->cond = BITS(inst, 28, 31);
1642     inst_base->idx = index;
1643     inst_base->br = TransExtData::NON_BRANCH;
1644 
1645     inst_cream->single = BIT(inst, 8) == 0;
1646     inst_cream->add = BIT(inst, 23);
1647     inst_cream->wback = BIT(inst, 21);
1648     inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22)
1649                                         : BITS(inst, 12, 15) | BIT(inst, 22) << 4);
1650     inst_cream->n = BITS(inst, 16, 19);
1651     inst_cream->imm32 = BITS(inst, 0, 7) << 2;
1652     inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7));
1653 
1654     return inst_base;
1655 }
1656 #endif
1657 #ifdef VFP_INTERPRETER_IMPL
1658 VLDM_INST : {
1659     if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1660         CHECK_VFP_ENABLED;
1661 
1662         vldm_inst* inst_cream = (vldm_inst*)inst_base->component;
1663 
1664         u32 address = cpu->Reg[inst_cream->n];
1665 
1666         // Only possible in ARM mode, where PC accesses have an 8 byte offset.
1667         if (inst_cream->n == 15)
1668             address += 8;
1669 
1670         if (inst_cream->add == 0)
1671             address -= inst_cream->imm32;
1672 
1673         for (unsigned int i = 0; i < inst_cream->regs; i++) {
1674             if (inst_cream->single) {
1675                 cpu->ExtReg[inst_cream->d + i] = cpu->ReadMemory32(address);
1676                 address += 4;
1677             } else {
1678                 const u32 word1 = cpu->ReadMemory32(address + 0);
1679                 const u32 word2 = cpu->ReadMemory32(address + 4);
1680 
1681                 if (cpu->InBigEndianMode()) {
1682                     cpu->ExtReg[(inst_cream->d + i) * 2 + 0] = word2;
1683                     cpu->ExtReg[(inst_cream->d + i) * 2 + 1] = word1;
1684                 } else {
1685                     cpu->ExtReg[(inst_cream->d + i) * 2 + 0] = word1;
1686                     cpu->ExtReg[(inst_cream->d + i) * 2 + 1] = word2;
1687                 }
1688 
1689                 address += 8;
1690             }
1691         }
1692         if (inst_cream->wback) {
1693             cpu->Reg[inst_cream->n] =
1694                 (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32
1695                                  : cpu->Reg[inst_cream->n] - inst_cream->imm32);
1696         }
1697     }
1698     cpu->Reg[15] += cpu->GetInstructionSize();
1699     INC_PC(sizeof(vldm_inst));
1700     FETCH_INST;
1701     GOTO_NEXT_INST;
1702 }
1703 #endif
1704