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