]> git.proxmox.com Git - qemu.git/blob - target-arm/translate.c
sparc update
[qemu.git] / target-arm / translate.c
1 /*
2 * ARM translation
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005 CodeSourcery, LLC
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <inttypes.h>
26
27 #include "cpu.h"
28 #include "exec-all.h"
29 #include "disas.h"
30
31 /* internal defines */
32 typedef struct DisasContext {
33 target_ulong pc;
34 int is_jmp;
35 struct TranslationBlock *tb;
36 } DisasContext;
37
38 #define DISAS_JUMP_NEXT 4
39
40 /* XXX: move that elsewhere */
41 static uint16_t *gen_opc_ptr;
42 static uint32_t *gen_opparam_ptr;
43 extern FILE *logfile;
44 extern int loglevel;
45
46 enum {
47 #define DEF(s, n, copy_size) INDEX_op_ ## s,
48 #include "opc.h"
49 #undef DEF
50 NB_OPS,
51 };
52
53 #include "gen-op.h"
54
55 static GenOpFunc2 *gen_test_cc[14] = {
56 gen_op_test_eq,
57 gen_op_test_ne,
58 gen_op_test_cs,
59 gen_op_test_cc,
60 gen_op_test_mi,
61 gen_op_test_pl,
62 gen_op_test_vs,
63 gen_op_test_vc,
64 gen_op_test_hi,
65 gen_op_test_ls,
66 gen_op_test_ge,
67 gen_op_test_lt,
68 gen_op_test_gt,
69 gen_op_test_le,
70 };
71
72 const uint8_t table_logic_cc[16] = {
73 1, /* and */
74 1, /* xor */
75 0, /* sub */
76 0, /* rsb */
77 0, /* add */
78 0, /* adc */
79 0, /* sbc */
80 0, /* rsc */
81 1, /* andl */
82 1, /* xorl */
83 0, /* cmp */
84 0, /* cmn */
85 1, /* orr */
86 1, /* mov */
87 1, /* bic */
88 1, /* mvn */
89 };
90
91 static GenOpFunc1 *gen_shift_T1_im[4] = {
92 gen_op_shll_T1_im,
93 gen_op_shrl_T1_im,
94 gen_op_sarl_T1_im,
95 gen_op_rorl_T1_im,
96 };
97
98 static GenOpFunc *gen_shift_T1_0[4] = {
99 NULL,
100 gen_op_shrl_T1_0,
101 gen_op_sarl_T1_0,
102 gen_op_rrxl_T1,
103 };
104
105 static GenOpFunc1 *gen_shift_T2_im[4] = {
106 gen_op_shll_T2_im,
107 gen_op_shrl_T2_im,
108 gen_op_sarl_T2_im,
109 gen_op_rorl_T2_im,
110 };
111
112 static GenOpFunc *gen_shift_T2_0[4] = {
113 NULL,
114 gen_op_shrl_T2_0,
115 gen_op_sarl_T2_0,
116 gen_op_rrxl_T2,
117 };
118
119 static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
120 gen_op_shll_T1_im_cc,
121 gen_op_shrl_T1_im_cc,
122 gen_op_sarl_T1_im_cc,
123 gen_op_rorl_T1_im_cc,
124 };
125
126 static GenOpFunc *gen_shift_T1_0_cc[4] = {
127 NULL,
128 gen_op_shrl_T1_0_cc,
129 gen_op_sarl_T1_0_cc,
130 gen_op_rrxl_T1_cc,
131 };
132
133 static GenOpFunc *gen_shift_T1_T0[4] = {
134 gen_op_shll_T1_T0,
135 gen_op_shrl_T1_T0,
136 gen_op_sarl_T1_T0,
137 gen_op_rorl_T1_T0,
138 };
139
140 static GenOpFunc *gen_shift_T1_T0_cc[4] = {
141 gen_op_shll_T1_T0_cc,
142 gen_op_shrl_T1_T0_cc,
143 gen_op_sarl_T1_T0_cc,
144 gen_op_rorl_T1_T0_cc,
145 };
146
147 static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
148 {
149 gen_op_movl_T0_r0,
150 gen_op_movl_T0_r1,
151 gen_op_movl_T0_r2,
152 gen_op_movl_T0_r3,
153 gen_op_movl_T0_r4,
154 gen_op_movl_T0_r5,
155 gen_op_movl_T0_r6,
156 gen_op_movl_T0_r7,
157 gen_op_movl_T0_r8,
158 gen_op_movl_T0_r9,
159 gen_op_movl_T0_r10,
160 gen_op_movl_T0_r11,
161 gen_op_movl_T0_r12,
162 gen_op_movl_T0_r13,
163 gen_op_movl_T0_r14,
164 gen_op_movl_T0_r15,
165 },
166 {
167 gen_op_movl_T1_r0,
168 gen_op_movl_T1_r1,
169 gen_op_movl_T1_r2,
170 gen_op_movl_T1_r3,
171 gen_op_movl_T1_r4,
172 gen_op_movl_T1_r5,
173 gen_op_movl_T1_r6,
174 gen_op_movl_T1_r7,
175 gen_op_movl_T1_r8,
176 gen_op_movl_T1_r9,
177 gen_op_movl_T1_r10,
178 gen_op_movl_T1_r11,
179 gen_op_movl_T1_r12,
180 gen_op_movl_T1_r13,
181 gen_op_movl_T1_r14,
182 gen_op_movl_T1_r15,
183 },
184 {
185 gen_op_movl_T2_r0,
186 gen_op_movl_T2_r1,
187 gen_op_movl_T2_r2,
188 gen_op_movl_T2_r3,
189 gen_op_movl_T2_r4,
190 gen_op_movl_T2_r5,
191 gen_op_movl_T2_r6,
192 gen_op_movl_T2_r7,
193 gen_op_movl_T2_r8,
194 gen_op_movl_T2_r9,
195 gen_op_movl_T2_r10,
196 gen_op_movl_T2_r11,
197 gen_op_movl_T2_r12,
198 gen_op_movl_T2_r13,
199 gen_op_movl_T2_r14,
200 gen_op_movl_T2_r15,
201 },
202 };
203
204 static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
205 {
206 gen_op_movl_r0_T0,
207 gen_op_movl_r1_T0,
208 gen_op_movl_r2_T0,
209 gen_op_movl_r3_T0,
210 gen_op_movl_r4_T0,
211 gen_op_movl_r5_T0,
212 gen_op_movl_r6_T0,
213 gen_op_movl_r7_T0,
214 gen_op_movl_r8_T0,
215 gen_op_movl_r9_T0,
216 gen_op_movl_r10_T0,
217 gen_op_movl_r11_T0,
218 gen_op_movl_r12_T0,
219 gen_op_movl_r13_T0,
220 gen_op_movl_r14_T0,
221 gen_op_movl_r15_T0,
222 },
223 {
224 gen_op_movl_r0_T1,
225 gen_op_movl_r1_T1,
226 gen_op_movl_r2_T1,
227 gen_op_movl_r3_T1,
228 gen_op_movl_r4_T1,
229 gen_op_movl_r5_T1,
230 gen_op_movl_r6_T1,
231 gen_op_movl_r7_T1,
232 gen_op_movl_r8_T1,
233 gen_op_movl_r9_T1,
234 gen_op_movl_r10_T1,
235 gen_op_movl_r11_T1,
236 gen_op_movl_r12_T1,
237 gen_op_movl_r13_T1,
238 gen_op_movl_r14_T1,
239 gen_op_movl_r15_T1,
240 },
241 };
242
243 static GenOpFunc1 *gen_op_movl_TN_im[3] = {
244 gen_op_movl_T0_im,
245 gen_op_movl_T1_im,
246 gen_op_movl_T2_im,
247 };
248
249 static GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
250 gen_op_shll_T0_im_thumb,
251 gen_op_shrl_T0_im_thumb,
252 gen_op_sarl_T0_im_thumb,
253 };
254
255 static inline void gen_bx(DisasContext *s)
256 {
257 s->is_jmp = DISAS_UPDATE;
258 gen_op_bx_T0();
259 }
260
261 static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
262 {
263 int val;
264
265 if (reg == 15) {
266 /* normaly, since we updated PC, we need only to add 4 */
267 val = (long)s->pc + 4;
268 gen_op_movl_TN_im[t](val);
269 } else {
270 gen_op_movl_TN_reg[t][reg]();
271 }
272 }
273
274 static inline void gen_movl_T0_reg(DisasContext *s, int reg)
275 {
276 gen_movl_TN_reg(s, reg, 0);
277 }
278
279 static inline void gen_movl_T1_reg(DisasContext *s, int reg)
280 {
281 gen_movl_TN_reg(s, reg, 1);
282 }
283
284 static inline void gen_movl_T2_reg(DisasContext *s, int reg)
285 {
286 gen_movl_TN_reg(s, reg, 2);
287 }
288
289 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
290 {
291 gen_op_movl_reg_TN[t][reg]();
292 if (reg == 15) {
293 s->is_jmp = DISAS_JUMP;
294 }
295 }
296
297 static inline void gen_movl_reg_T0(DisasContext *s, int reg)
298 {
299 gen_movl_reg_TN(s, reg, 0);
300 }
301
302 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
303 {
304 gen_movl_reg_TN(s, reg, 1);
305 }
306
307 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
308 {
309 int val, rm, shift, shiftop;
310
311 if (!(insn & (1 << 25))) {
312 /* immediate */
313 val = insn & 0xfff;
314 if (!(insn & (1 << 23)))
315 val = -val;
316 if (val != 0)
317 gen_op_addl_T1_im(val);
318 } else {
319 /* shift/register */
320 rm = (insn) & 0xf;
321 shift = (insn >> 7) & 0x1f;
322 gen_movl_T2_reg(s, rm);
323 shiftop = (insn >> 5) & 3;
324 if (shift != 0) {
325 gen_shift_T2_im[shiftop](shift);
326 } else if (shiftop != 0) {
327 gen_shift_T2_0[shiftop]();
328 }
329 if (!(insn & (1 << 23)))
330 gen_op_subl_T1_T2();
331 else
332 gen_op_addl_T1_T2();
333 }
334 }
335
336 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
337 {
338 int val, rm;
339
340 if (insn & (1 << 22)) {
341 /* immediate */
342 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
343 if (!(insn & (1 << 23)))
344 val = -val;
345 if (val != 0)
346 gen_op_addl_T1_im(val);
347 } else {
348 /* register */
349 rm = (insn) & 0xf;
350 gen_movl_T2_reg(s, rm);
351 if (!(insn & (1 << 23)))
352 gen_op_subl_T1_T2();
353 else
354 gen_op_addl_T1_T2();
355 }
356 }
357
358 #define VFP_OP(name) \
359 static inline void gen_vfp_##name(int dp) \
360 { \
361 if (dp) \
362 gen_op_vfp_##name##d(); \
363 else \
364 gen_op_vfp_##name##s(); \
365 }
366
367 VFP_OP(add)
368 VFP_OP(sub)
369 VFP_OP(mul)
370 VFP_OP(div)
371 VFP_OP(neg)
372 VFP_OP(abs)
373 VFP_OP(sqrt)
374 VFP_OP(cmp)
375 VFP_OP(cmpe)
376 VFP_OP(F1_ld0)
377 VFP_OP(uito)
378 VFP_OP(sito)
379 VFP_OP(toui)
380 VFP_OP(touiz)
381 VFP_OP(tosi)
382 VFP_OP(tosiz)
383 VFP_OP(ld)
384 VFP_OP(st)
385
386 #undef VFP_OP
387
388 static inline void gen_mov_F0_vreg(int dp, int reg)
389 {
390 if (dp)
391 gen_op_vfp_getreg_F0d(offsetof(CPUARMState, vfp.regs.d[reg]));
392 else
393 gen_op_vfp_getreg_F0s(offsetof(CPUARMState, vfp.regs.s[reg]));
394 }
395
396 static inline void gen_mov_F1_vreg(int dp, int reg)
397 {
398 if (dp)
399 gen_op_vfp_getreg_F1d(offsetof(CPUARMState, vfp.regs.d[reg]));
400 else
401 gen_op_vfp_getreg_F1s(offsetof(CPUARMState, vfp.regs.s[reg]));
402 }
403
404 static inline void gen_mov_vreg_F0(int dp, int reg)
405 {
406 if (dp)
407 gen_op_vfp_setreg_F0d(offsetof(CPUARMState, vfp.regs.d[reg]));
408 else
409 gen_op_vfp_setreg_F0s(offsetof(CPUARMState, vfp.regs.s[reg]));
410 }
411
412 /* Disassemble a VFP instruction. Returns nonzero if an error occured
413 (ie. an undefined instruction). */
414 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
415 {
416 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
417 int dp, veclen;
418
419 dp = ((insn & 0xf00) == 0xb00);
420 switch ((insn >> 24) & 0xf) {
421 case 0xe:
422 if (insn & (1 << 4)) {
423 /* single register transfer */
424 if ((insn & 0x6f) != 0x00)
425 return 1;
426 rd = (insn >> 12) & 0xf;
427 if (dp) {
428 if (insn & 0x80)
429 return 1;
430 rn = (insn >> 16) & 0xf;
431 /* Get the existing value even for arm->vfp moves because
432 we only set half the register. */
433 gen_mov_F0_vreg(1, rn);
434 gen_op_vfp_mrrd();
435 if (insn & (1 << 20)) {
436 /* vfp->arm */
437 if (insn & (1 << 21))
438 gen_movl_reg_T1(s, rd);
439 else
440 gen_movl_reg_T0(s, rd);
441 } else {
442 /* arm->vfp */
443 if (insn & (1 << 21))
444 gen_movl_T1_reg(s, rd);
445 else
446 gen_movl_T0_reg(s, rd);
447 gen_op_vfp_mdrr();
448 gen_mov_vreg_F0(dp, rn);
449 }
450 } else {
451 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
452 if (insn & (1 << 20)) {
453 /* vfp->arm */
454 if (insn & (1 << 21)) {
455 /* system register */
456 switch (rn) {
457 case 0: /* fpsid */
458 n = 0x0091A0000;
459 break;
460 case 2: /* fpscr */
461 if (rd == 15)
462 gen_op_vfp_movl_T0_fpscr_flags();
463 else
464 gen_op_vfp_movl_T0_fpscr();
465 break;
466 default:
467 return 1;
468 }
469 } else {
470 gen_mov_F0_vreg(0, rn);
471 gen_op_vfp_mrs();
472 }
473 if (rd == 15) {
474 /* This will only set the 4 flag bits */
475 gen_op_movl_psr_T0();
476 } else
477 gen_movl_reg_T0(s, rd);
478 } else {
479 /* arm->vfp */
480 gen_movl_T0_reg(s, rd);
481 if (insn & (1 << 21)) {
482 /* system register */
483 switch (rn) {
484 case 0: /* fpsid */
485 /* Writes are ignored. */
486 break;
487 case 2: /* fpscr */
488 gen_op_vfp_movl_fpscr_T0();
489 /* This could change vector settings, so jump to
490 the next instuction. */
491 gen_op_movl_T0_im(s->pc);
492 gen_movl_reg_T0(s, 15);
493 s->is_jmp = DISAS_UPDATE;
494 break;
495 default:
496 return 1;
497 }
498 } else {
499 gen_op_vfp_msr();
500 gen_mov_vreg_F0(0, rn);
501 }
502 }
503 }
504 } else {
505 /* data processing */
506 /* The opcode is in bits 23, 21, 20 and 6. */
507 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
508 if (dp) {
509 if (op == 15) {
510 /* rn is opcode */
511 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
512 } else {
513 /* rn is register number */
514 if (insn & (1 << 7))
515 return 1;
516 rn = (insn >> 16) & 0xf;
517 }
518
519 if (op == 15 && (rn == 15 || rn > 17)) {
520 /* Integer or single precision destination. */
521 rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
522 } else {
523 if (insn & (1 << 22))
524 return 1;
525 rd = (insn >> 12) & 0xf;
526 }
527
528 if (op == 15 && (rn == 16 || rn == 17)) {
529 /* Integer source. */
530 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
531 } else {
532 if (insn & (1 << 5))
533 return 1;
534 rm = insn & 0xf;
535 }
536 } else {
537 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
538 if (op == 15 && rn == 15) {
539 /* Double precision destination. */
540 if (insn & (1 << 22))
541 return 1;
542 rd = (insn >> 12) & 0xf;
543 } else
544 rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
545 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
546 }
547
548 veclen = env->vfp.vec_len;
549 if (op == 15 && rn > 3)
550 veclen = 0;
551
552 /* Shut up compiler warnings. */
553 delta_m = 0;
554 delta_d = 0;
555 bank_mask = 0;
556
557 if (veclen > 0) {
558 if (dp)
559 bank_mask = 0xc;
560 else
561 bank_mask = 0x18;
562
563 /* Figure out what type of vector operation this is. */
564 if ((rd & bank_mask) == 0) {
565 /* scalar */
566 veclen = 0;
567 } else {
568 if (dp)
569 delta_d = (env->vfp.vec_stride >> 1) + 1;
570 else
571 delta_d = env->vfp.vec_stride + 1;
572
573 if ((rm & bank_mask) == 0) {
574 /* mixed scalar/vector */
575 delta_m = 0;
576 } else {
577 /* vector */
578 delta_m = delta_d;
579 }
580 }
581 }
582
583 /* Load the initial operands. */
584 if (op == 15) {
585 switch (rn) {
586 case 16:
587 case 17:
588 /* Integer source */
589 gen_mov_F0_vreg(0, rm);
590 break;
591 case 8:
592 case 9:
593 /* Compare */
594 gen_mov_F0_vreg(dp, rd);
595 gen_mov_F1_vreg(dp, rm);
596 break;
597 case 10:
598 case 11:
599 /* Compare with zero */
600 gen_mov_F0_vreg(dp, rd);
601 gen_vfp_F1_ld0(dp);
602 break;
603 default:
604 /* One source operand. */
605 gen_mov_F0_vreg(dp, rm);
606 }
607 } else {
608 /* Two source operands. */
609 gen_mov_F0_vreg(dp, rn);
610 gen_mov_F1_vreg(dp, rm);
611 }
612
613 for (;;) {
614 /* Perform the calculation. */
615 switch (op) {
616 case 0: /* mac: fd + (fn * fm) */
617 gen_vfp_mul(dp);
618 gen_mov_F1_vreg(dp, rd);
619 gen_vfp_add(dp);
620 break;
621 case 1: /* nmac: fd - (fn * fm) */
622 gen_vfp_mul(dp);
623 gen_vfp_neg(dp);
624 gen_mov_F1_vreg(dp, rd);
625 gen_vfp_add(dp);
626 break;
627 case 2: /* msc: -fd + (fn * fm) */
628 gen_vfp_mul(dp);
629 gen_mov_F1_vreg(dp, rd);
630 gen_vfp_sub(dp);
631 break;
632 case 3: /* nmsc: -fd - (fn * fm) */
633 gen_vfp_mul(dp);
634 gen_mov_F1_vreg(dp, rd);
635 gen_vfp_add(dp);
636 gen_vfp_neg(dp);
637 break;
638 case 4: /* mul: fn * fm */
639 gen_vfp_mul(dp);
640 break;
641 case 5: /* nmul: -(fn * fm) */
642 gen_vfp_mul(dp);
643 gen_vfp_neg(dp);
644 break;
645 case 6: /* add: fn + fm */
646 gen_vfp_add(dp);
647 break;
648 case 7: /* sub: fn - fm */
649 gen_vfp_sub(dp);
650 break;
651 case 8: /* div: fn / fm */
652 gen_vfp_div(dp);
653 break;
654 case 15: /* extension space */
655 switch (rn) {
656 case 0: /* cpy */
657 /* no-op */
658 break;
659 case 1: /* abs */
660 gen_vfp_abs(dp);
661 break;
662 case 2: /* neg */
663 gen_vfp_neg(dp);
664 break;
665 case 3: /* sqrt */
666 gen_vfp_sqrt(dp);
667 break;
668 case 8: /* cmp */
669 gen_vfp_cmp(dp);
670 break;
671 case 9: /* cmpe */
672 gen_vfp_cmpe(dp);
673 break;
674 case 10: /* cmpz */
675 gen_vfp_cmp(dp);
676 break;
677 case 11: /* cmpez */
678 gen_vfp_F1_ld0(dp);
679 gen_vfp_cmpe(dp);
680 break;
681 case 15: /* single<->double conversion */
682 if (dp)
683 gen_op_vfp_fcvtsd();
684 else
685 gen_op_vfp_fcvtds();
686 break;
687 case 16: /* fuito */
688 gen_vfp_uito(dp);
689 break;
690 case 17: /* fsito */
691 gen_vfp_sito(dp);
692 break;
693 case 24: /* ftoui */
694 gen_vfp_toui(dp);
695 break;
696 case 25: /* ftouiz */
697 gen_vfp_touiz(dp);
698 break;
699 case 26: /* ftosi */
700 gen_vfp_tosi(dp);
701 break;
702 case 27: /* ftosiz */
703 gen_vfp_tosiz(dp);
704 break;
705 default: /* undefined */
706 printf ("rn:%d\n", rn);
707 return 1;
708 }
709 break;
710 default: /* undefined */
711 printf ("op:%d\n", op);
712 return 1;
713 }
714
715 /* Write back the result. */
716 if (op == 15 && (rn >= 8 && rn <= 11))
717 ; /* Comparison, do nothing. */
718 else if (op == 15 && rn > 17)
719 /* Integer result. */
720 gen_mov_vreg_F0(0, rd);
721 else if (op == 15 && rn == 15)
722 /* conversion */
723 gen_mov_vreg_F0(!dp, rd);
724 else
725 gen_mov_vreg_F0(dp, rd);
726
727 /* break out of the loop if we have finished */
728 if (veclen == 0)
729 break;
730
731 if (op == 15 && delta_m == 0) {
732 /* single source one-many */
733 while (veclen--) {
734 rd = ((rd + delta_d) & (bank_mask - 1))
735 | (rd & bank_mask);
736 gen_mov_vreg_F0(dp, rd);
737 }
738 break;
739 }
740 /* Setup the next operands. */
741 veclen--;
742 rd = ((rd + delta_d) & (bank_mask - 1))
743 | (rd & bank_mask);
744
745 if (op == 15) {
746 /* One source operand. */
747 rm = ((rm + delta_m) & (bank_mask - 1))
748 | (rm & bank_mask);
749 gen_mov_F0_vreg(dp, rm);
750 } else {
751 /* Two source operands. */
752 rn = ((rn + delta_d) & (bank_mask - 1))
753 | (rn & bank_mask);
754 gen_mov_F0_vreg(dp, rn);
755 if (delta_m) {
756 rm = ((rm + delta_m) & (bank_mask - 1))
757 | (rm & bank_mask);
758 gen_mov_F1_vreg(dp, rm);
759 }
760 }
761 }
762 }
763 break;
764 case 0xc:
765 case 0xd:
766 if (dp && (insn & (1 << 22))) {
767 /* two-register transfer */
768 rn = (insn >> 16) & 0xf;
769 rd = (insn >> 12) & 0xf;
770 if (dp) {
771 if (insn & (1 << 5))
772 return 1;
773 rm = insn & 0xf;
774 } else
775 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
776
777 if (insn & (1 << 20)) {
778 /* vfp->arm */
779 if (dp) {
780 gen_mov_F0_vreg(1, rm);
781 gen_op_vfp_mrrd();
782 gen_movl_reg_T0(s, rd);
783 gen_movl_reg_T1(s, rn);
784 } else {
785 gen_mov_F0_vreg(0, rm);
786 gen_op_vfp_mrs();
787 gen_movl_reg_T0(s, rn);
788 gen_mov_F0_vreg(0, rm + 1);
789 gen_op_vfp_mrs();
790 gen_movl_reg_T0(s, rd);
791 }
792 } else {
793 /* arm->vfp */
794 if (dp) {
795 gen_movl_T0_reg(s, rd);
796 gen_movl_T1_reg(s, rn);
797 gen_op_vfp_mdrr();
798 gen_mov_vreg_F0(1, rm);
799 } else {
800 gen_movl_T0_reg(s, rn);
801 gen_op_vfp_msr();
802 gen_mov_vreg_F0(0, rm);
803 gen_movl_T0_reg(s, rd);
804 gen_op_vfp_msr();
805 gen_mov_vreg_F0(0, rm + 1);
806 }
807 }
808 } else {
809 /* Load/store */
810 rn = (insn >> 16) & 0xf;
811 if (dp)
812 rd = (insn >> 12) & 0xf;
813 else
814 rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
815 gen_movl_T1_reg(s, rn);
816 if ((insn & 0x01200000) == 0x01000000) {
817 /* Single load/store */
818 offset = (insn & 0xff) << 2;
819 if ((insn & (1 << 23)) == 0)
820 offset = -offset;
821 gen_op_addl_T1_im(offset);
822 if (insn & (1 << 20)) {
823 gen_vfp_ld(dp);
824 gen_mov_vreg_F0(dp, rd);
825 } else {
826 gen_mov_F0_vreg(dp, rd);
827 gen_vfp_st(dp);
828 }
829 } else {
830 /* load/store multiple */
831 if (dp)
832 n = (insn >> 1) & 0x7f;
833 else
834 n = insn & 0xff;
835
836 if (insn & (1 << 24)) /* pre-decrement */
837 gen_op_addl_T1_im(-((insn & 0xff) << 2));
838
839 if (dp)
840 offset = 8;
841 else
842 offset = 4;
843 for (i = 0; i < n; i++) {
844 if (insn & (1 << 20)) {
845 /* load */
846 gen_vfp_ld(dp);
847 gen_mov_vreg_F0(dp, rd + i);
848 } else {
849 /* store */
850 gen_mov_F0_vreg(dp, rd + i);
851 gen_vfp_st(dp);
852 }
853 gen_op_addl_T1_im(offset);
854 }
855 if (insn & (1 << 21)) {
856 /* writeback */
857 if (insn & (1 << 24))
858 offset = -offset * n;
859 else if (dp && (insn & 1))
860 offset = 4;
861 else
862 offset = 0;
863
864 if (offset != 0)
865 gen_op_addl_T1_im(offset);
866 gen_movl_reg_T1(s, rn);
867 }
868 }
869 }
870 break;
871 default:
872 /* Should never happen. */
873 return 1;
874 }
875 return 0;
876 }
877
878 static void disas_arm_insn(CPUState * env, DisasContext *s)
879 {
880 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
881
882 insn = ldl(s->pc);
883 s->pc += 4;
884
885 cond = insn >> 28;
886 if (cond == 0xf){
887 /* Unconditional instructions. */
888 if ((insn & 0x0d70f000) == 0x0550f000)
889 return; /* PLD */
890 else if ((insn & 0x0e000000) == 0x0a000000) {
891 /* branch link and change to thumb (blx <offset>) */
892 int32_t offset;
893
894 val = (uint32_t)s->pc;
895 gen_op_movl_T0_im(val);
896 gen_movl_reg_T0(s, 14);
897 /* Sign-extend the 24-bit offset */
898 offset = (((int32_t)insn) << 8) >> 8;
899 /* offset * 4 + bit24 * 2 + (thumb bit) */
900 val += (offset << 2) | ((insn >> 23) & 2) | 1;
901 /* pipeline offset */
902 val += 4;
903 gen_op_movl_T0_im(val);
904 gen_bx(s);
905 return;
906 } else if ((insn & 0x0fe00000) == 0x0c400000) {
907 /* Coprocessor double register transfer. */
908 } else if ((insn & 0x0f000010) == 0x0e000010) {
909 /* Additional coprocessor register transfer. */
910 }
911 goto illegal_op;
912 }
913 if (cond != 0xe) {
914 /* if not always execute, we generate a conditional jump to
915 next instruction */
916 gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
917 s->is_jmp = DISAS_JUMP_NEXT;
918 }
919 if ((insn & 0x0f900000) == 0x03000000) {
920 if ((insn & 0x0ff0f000) != 0x0360f000)
921 goto illegal_op;
922 /* CPSR = immediate */
923 val = insn & 0xff;
924 shift = ((insn >> 8) & 0xf) * 2;
925 if (shift)
926 val = (val >> shift) | (val << (32 - shift));
927 gen_op_movl_T0_im(val);
928 if (insn & (1 << 19))
929 gen_op_movl_psr_T0();
930 } else if ((insn & 0x0f900000) == 0x01000000
931 && (insn & 0x00000090) != 0x00000090) {
932 /* miscellaneous instructions */
933 op1 = (insn >> 21) & 3;
934 sh = (insn >> 4) & 0xf;
935 rm = insn & 0xf;
936 switch (sh) {
937 case 0x0: /* move program status register */
938 if (op1 & 2) {
939 /* SPSR not accessible in user mode */
940 goto illegal_op;
941 }
942 if (op1 & 1) {
943 /* CPSR = reg */
944 gen_movl_T0_reg(s, rm);
945 if (insn & (1 << 19))
946 gen_op_movl_psr_T0();
947 } else {
948 /* reg = CPSR */
949 rd = (insn >> 12) & 0xf;
950 gen_op_movl_T0_psr();
951 gen_movl_reg_T0(s, rd);
952 }
953 break;
954 case 0x1:
955 if (op1 == 1) {
956 /* branch/exchange thumb (bx). */
957 gen_movl_T0_reg(s, rm);
958 gen_bx(s);
959 } else if (op1 == 3) {
960 /* clz */
961 rd = (insn >> 12) & 0xf;
962 gen_movl_T0_reg(s, rm);
963 gen_op_clz_T0();
964 gen_movl_reg_T0(s, rd);
965 } else {
966 goto illegal_op;
967 }
968 break;
969 case 0x3:
970 if (op1 != 1)
971 goto illegal_op;
972
973 /* branch link/exchange thumb (blx) */
974 val = (uint32_t)s->pc;
975 gen_op_movl_T0_im(val);
976 gen_movl_reg_T0(s, 14);
977 gen_movl_T0_reg(s, rm);
978 gen_bx(s);
979 break;
980 case 0x5: /* saturating add/subtract */
981 rd = (insn >> 12) & 0xf;
982 rn = (insn >> 16) & 0xf;
983 gen_movl_T0_reg(s, rn);
984 if (op1 & 2) {
985 gen_movl_T1_reg(s, rn);
986 if (op1 & 1)
987 gen_op_subl_T0_T1_saturate();
988 else
989 gen_op_addl_T0_T1_saturate();
990 }
991 gen_movl_T1_reg(s, rm);
992 if (op1 & 1)
993 gen_op_subl_T0_T1_saturate();
994 else
995 gen_op_addl_T0_T1_saturate();
996 gen_movl_reg_T0(s, rn);
997 break;
998 case 0x8: /* signed multiply */
999 case 0xa:
1000 case 0xc:
1001 case 0xe:
1002 rs = (insn >> 8) & 0xf;
1003 rn = (insn >> 12) & 0xf;
1004 rd = (insn >> 16) & 0xf;
1005 if (op1 == 1) {
1006 /* (32 * 16) >> 16 */
1007 gen_movl_T0_reg(s, rm);
1008 gen_movl_T1_reg(s, rs);
1009 if (sh & 4)
1010 gen_op_sarl_T1_im(16);
1011 else
1012 gen_op_sxl_T1();
1013 gen_op_imulw_T0_T1();
1014 if ((sh & 2) == 0) {
1015 gen_movl_T1_reg(s, rn);
1016 gen_op_addl_T0_T1_setq();
1017 }
1018 gen_movl_reg_T0(s, rd);
1019 } else {
1020 /* 16 * 16 */
1021 gen_movl_T0_reg(s, rm);
1022 if (sh & 2)
1023 gen_op_sarl_T0_im(16);
1024 else
1025 gen_op_sxl_T0();
1026 gen_movl_T1_reg(s, rs);
1027 if (sh & 4)
1028 gen_op_sarl_T1_im(16);
1029 else
1030 gen_op_sxl_T1();
1031 if (op1 == 2) {
1032 gen_op_imull_T0_T1();
1033 gen_op_addq_T0_T1(rn, rd);
1034 gen_movl_reg_T0(s, rn);
1035 gen_movl_reg_T1(s, rd);
1036 } else {
1037 gen_op_mul_T0_T1();
1038 if (op1 == 0) {
1039 gen_movl_T1_reg(s, rn);
1040 gen_op_addl_T0_T1_setq();
1041 }
1042 gen_movl_reg_T0(s, rd);
1043 }
1044 }
1045 break;
1046 default:
1047 goto illegal_op;
1048 }
1049 } else if (((insn & 0x0e000000) == 0 &&
1050 (insn & 0x00000090) != 0x90) ||
1051 ((insn & 0x0e000000) == (1 << 25))) {
1052 int set_cc, logic_cc, shiftop;
1053
1054 op1 = (insn >> 21) & 0xf;
1055 set_cc = (insn >> 20) & 1;
1056 logic_cc = table_logic_cc[op1] & set_cc;
1057
1058 /* data processing instruction */
1059 if (insn & (1 << 25)) {
1060 /* immediate operand */
1061 val = insn & 0xff;
1062 shift = ((insn >> 8) & 0xf) * 2;
1063 if (shift)
1064 val = (val >> shift) | (val << (32 - shift));
1065 gen_op_movl_T1_im(val);
1066 if (logic_cc && shift)
1067 gen_op_mov_CF_T1();
1068 } else {
1069 /* register */
1070 rm = (insn) & 0xf;
1071 gen_movl_T1_reg(s, rm);
1072 shiftop = (insn >> 5) & 3;
1073 if (!(insn & (1 << 4))) {
1074 shift = (insn >> 7) & 0x1f;
1075 if (shift != 0) {
1076 if (logic_cc) {
1077 gen_shift_T1_im_cc[shiftop](shift);
1078 } else {
1079 gen_shift_T1_im[shiftop](shift);
1080 }
1081 } else if (shiftop != 0) {
1082 if (logic_cc) {
1083 gen_shift_T1_0_cc[shiftop]();
1084 } else {
1085 gen_shift_T1_0[shiftop]();
1086 }
1087 }
1088 } else {
1089 rs = (insn >> 8) & 0xf;
1090 gen_movl_T0_reg(s, rs);
1091 if (logic_cc) {
1092 gen_shift_T1_T0_cc[shiftop]();
1093 } else {
1094 gen_shift_T1_T0[shiftop]();
1095 }
1096 }
1097 }
1098 if (op1 != 0x0f && op1 != 0x0d) {
1099 rn = (insn >> 16) & 0xf;
1100 gen_movl_T0_reg(s, rn);
1101 }
1102 rd = (insn >> 12) & 0xf;
1103 switch(op1) {
1104 case 0x00:
1105 gen_op_andl_T0_T1();
1106 gen_movl_reg_T0(s, rd);
1107 if (logic_cc)
1108 gen_op_logic_T0_cc();
1109 break;
1110 case 0x01:
1111 gen_op_xorl_T0_T1();
1112 gen_movl_reg_T0(s, rd);
1113 if (logic_cc)
1114 gen_op_logic_T0_cc();
1115 break;
1116 case 0x02:
1117 if (set_cc)
1118 gen_op_subl_T0_T1_cc();
1119 else
1120 gen_op_subl_T0_T1();
1121 gen_movl_reg_T0(s, rd);
1122 break;
1123 case 0x03:
1124 if (set_cc)
1125 gen_op_rsbl_T0_T1_cc();
1126 else
1127 gen_op_rsbl_T0_T1();
1128 gen_movl_reg_T0(s, rd);
1129 break;
1130 case 0x04:
1131 if (set_cc)
1132 gen_op_addl_T0_T1_cc();
1133 else
1134 gen_op_addl_T0_T1();
1135 gen_movl_reg_T0(s, rd);
1136 break;
1137 case 0x05:
1138 if (set_cc)
1139 gen_op_adcl_T0_T1_cc();
1140 else
1141 gen_op_adcl_T0_T1();
1142 gen_movl_reg_T0(s, rd);
1143 break;
1144 case 0x06:
1145 if (set_cc)
1146 gen_op_sbcl_T0_T1_cc();
1147 else
1148 gen_op_sbcl_T0_T1();
1149 gen_movl_reg_T0(s, rd);
1150 break;
1151 case 0x07:
1152 if (set_cc)
1153 gen_op_rscl_T0_T1_cc();
1154 else
1155 gen_op_rscl_T0_T1();
1156 gen_movl_reg_T0(s, rd);
1157 break;
1158 case 0x08:
1159 if (set_cc) {
1160 gen_op_andl_T0_T1();
1161 gen_op_logic_T0_cc();
1162 }
1163 break;
1164 case 0x09:
1165 if (set_cc) {
1166 gen_op_xorl_T0_T1();
1167 gen_op_logic_T0_cc();
1168 }
1169 break;
1170 case 0x0a:
1171 if (set_cc) {
1172 gen_op_subl_T0_T1_cc();
1173 }
1174 break;
1175 case 0x0b:
1176 if (set_cc) {
1177 gen_op_addl_T0_T1_cc();
1178 }
1179 break;
1180 case 0x0c:
1181 gen_op_orl_T0_T1();
1182 gen_movl_reg_T0(s, rd);
1183 if (logic_cc)
1184 gen_op_logic_T0_cc();
1185 break;
1186 case 0x0d:
1187 gen_movl_reg_T1(s, rd);
1188 if (logic_cc)
1189 gen_op_logic_T1_cc();
1190 break;
1191 case 0x0e:
1192 gen_op_bicl_T0_T1();
1193 gen_movl_reg_T0(s, rd);
1194 if (logic_cc)
1195 gen_op_logic_T0_cc();
1196 break;
1197 default:
1198 case 0x0f:
1199 gen_op_notl_T1();
1200 gen_movl_reg_T1(s, rd);
1201 if (logic_cc)
1202 gen_op_logic_T1_cc();
1203 break;
1204 }
1205 } else {
1206 /* other instructions */
1207 op1 = (insn >> 24) & 0xf;
1208 switch(op1) {
1209 case 0x0:
1210 case 0x1:
1211 /* multiplies, extra load/stores */
1212 sh = (insn >> 5) & 3;
1213 if (sh == 0) {
1214 if (op1 == 0x0) {
1215 rd = (insn >> 16) & 0xf;
1216 rn = (insn >> 12) & 0xf;
1217 rs = (insn >> 8) & 0xf;
1218 rm = (insn) & 0xf;
1219 if (((insn >> 22) & 3) == 0) {
1220 /* 32 bit mul */
1221 gen_movl_T0_reg(s, rs);
1222 gen_movl_T1_reg(s, rm);
1223 gen_op_mul_T0_T1();
1224 if (insn & (1 << 21)) {
1225 gen_movl_T1_reg(s, rn);
1226 gen_op_addl_T0_T1();
1227 }
1228 if (insn & (1 << 20))
1229 gen_op_logic_T0_cc();
1230 gen_movl_reg_T0(s, rd);
1231 } else {
1232 /* 64 bit mul */
1233 gen_movl_T0_reg(s, rs);
1234 gen_movl_T1_reg(s, rm);
1235 if (insn & (1 << 22))
1236 gen_op_imull_T0_T1();
1237 else
1238 gen_op_mull_T0_T1();
1239 if (insn & (1 << 21)) /* mult accumulate */
1240 gen_op_addq_T0_T1(rn, rd);
1241 if (!(insn & (1 << 23))) { /* double accumulate */
1242 gen_op_addq_lo_T0_T1(rn);
1243 gen_op_addq_lo_T0_T1(rd);
1244 }
1245 if (insn & (1 << 20))
1246 gen_op_logicq_cc();
1247 gen_movl_reg_T0(s, rn);
1248 gen_movl_reg_T1(s, rd);
1249 }
1250 } else {
1251 rn = (insn >> 16) & 0xf;
1252 rd = (insn >> 12) & 0xf;
1253 if (insn & (1 << 23)) {
1254 /* load/store exclusive */
1255 goto illegal_op;
1256 } else {
1257 /* SWP instruction */
1258 rm = (insn) & 0xf;
1259
1260 gen_movl_T0_reg(s, rm);
1261 gen_movl_T1_reg(s, rn);
1262 if (insn & (1 << 22)) {
1263 gen_op_swpb_T0_T1();
1264 } else {
1265 gen_op_swpl_T0_T1();
1266 }
1267 gen_movl_reg_T0(s, rd);
1268 }
1269 }
1270 } else {
1271 /* Misc load/store */
1272 rn = (insn >> 16) & 0xf;
1273 rd = (insn >> 12) & 0xf;
1274 gen_movl_T1_reg(s, rn);
1275 if (insn & (1 << 24))
1276 gen_add_datah_offset(s, insn);
1277 if (insn & (1 << 20)) {
1278 /* load */
1279 switch(sh) {
1280 case 1:
1281 gen_op_lduw_T0_T1();
1282 break;
1283 case 2:
1284 gen_op_ldsb_T0_T1();
1285 break;
1286 default:
1287 case 3:
1288 gen_op_ldsw_T0_T1();
1289 break;
1290 }
1291 gen_movl_reg_T0(s, rd);
1292 } else if (sh & 2) {
1293 /* doubleword */
1294 if (sh & 1) {
1295 /* store */
1296 gen_movl_T0_reg(s, rd);
1297 gen_op_stl_T0_T1();
1298 gen_op_addl_T1_im(4);
1299 gen_movl_T0_reg(s, rd + 1);
1300 gen_op_stl_T0_T1();
1301 if ((insn & (1 << 24)) || (insn & (1 << 20)))
1302 gen_op_addl_T1_im(-4);
1303 } else {
1304 /* load */
1305 gen_op_ldl_T0_T1();
1306 gen_movl_reg_T0(s, rd);
1307 gen_op_addl_T1_im(4);
1308 gen_op_ldl_T0_T1();
1309 gen_movl_reg_T0(s, rd + 1);
1310 if ((insn & (1 << 24)) || (insn & (1 << 20)))
1311 gen_op_addl_T1_im(-4);
1312 }
1313 } else {
1314 /* store */
1315 gen_movl_T0_reg(s, rd);
1316 gen_op_stw_T0_T1();
1317 }
1318 if (!(insn & (1 << 24))) {
1319 gen_add_datah_offset(s, insn);
1320 gen_movl_reg_T1(s, rn);
1321 } else if (insn & (1 << 21)) {
1322 gen_movl_reg_T1(s, rn);
1323 }
1324 }
1325 break;
1326 case 0x4:
1327 case 0x5:
1328 case 0x6:
1329 case 0x7:
1330 /* load/store byte/word */
1331 rn = (insn >> 16) & 0xf;
1332 rd = (insn >> 12) & 0xf;
1333 gen_movl_T1_reg(s, rn);
1334 if (insn & (1 << 24))
1335 gen_add_data_offset(s, insn);
1336 if (insn & (1 << 20)) {
1337 /* load */
1338 if (insn & (1 << 22))
1339 gen_op_ldub_T0_T1();
1340 else
1341 gen_op_ldl_T0_T1();
1342 if (rd == 15)
1343 gen_bx(s);
1344 else
1345 gen_movl_reg_T0(s, rd);
1346 } else {
1347 /* store */
1348 gen_movl_T0_reg(s, rd);
1349 if (insn & (1 << 22))
1350 gen_op_stb_T0_T1();
1351 else
1352 gen_op_stl_T0_T1();
1353 }
1354 if (!(insn & (1 << 24))) {
1355 gen_add_data_offset(s, insn);
1356 gen_movl_reg_T1(s, rn);
1357 } else if (insn & (1 << 21))
1358 gen_movl_reg_T1(s, rn); {
1359 }
1360 break;
1361 case 0x08:
1362 case 0x09:
1363 {
1364 int j, n;
1365 /* load/store multiple words */
1366 /* XXX: store correct base if write back */
1367 if (insn & (1 << 22))
1368 goto illegal_op; /* only usable in supervisor mode */
1369 rn = (insn >> 16) & 0xf;
1370 gen_movl_T1_reg(s, rn);
1371
1372 /* compute total size */
1373 n = 0;
1374 for(i=0;i<16;i++) {
1375 if (insn & (1 << i))
1376 n++;
1377 }
1378 /* XXX: test invalid n == 0 case ? */
1379 if (insn & (1 << 23)) {
1380 if (insn & (1 << 24)) {
1381 /* pre increment */
1382 gen_op_addl_T1_im(4);
1383 } else {
1384 /* post increment */
1385 }
1386 } else {
1387 if (insn & (1 << 24)) {
1388 /* pre decrement */
1389 gen_op_addl_T1_im(-(n * 4));
1390 } else {
1391 /* post decrement */
1392 if (n != 1)
1393 gen_op_addl_T1_im(-((n - 1) * 4));
1394 }
1395 }
1396 j = 0;
1397 for(i=0;i<16;i++) {
1398 if (insn & (1 << i)) {
1399 if (insn & (1 << 20)) {
1400 /* load */
1401 gen_op_ldl_T0_T1();
1402 if (i == 15)
1403 gen_bx(s);
1404 else
1405 gen_movl_reg_T0(s, i);
1406 } else {
1407 /* store */
1408 if (i == 15) {
1409 /* special case: r15 = PC + 12 */
1410 val = (long)s->pc + 8;
1411 gen_op_movl_TN_im[0](val);
1412 } else {
1413 gen_movl_T0_reg(s, i);
1414 }
1415 gen_op_stl_T0_T1();
1416 }
1417 j++;
1418 /* no need to add after the last transfer */
1419 if (j != n)
1420 gen_op_addl_T1_im(4);
1421 }
1422 }
1423 if (insn & (1 << 21)) {
1424 /* write back */
1425 if (insn & (1 << 23)) {
1426 if (insn & (1 << 24)) {
1427 /* pre increment */
1428 } else {
1429 /* post increment */
1430 gen_op_addl_T1_im(4);
1431 }
1432 } else {
1433 if (insn & (1 << 24)) {
1434 /* pre decrement */
1435 if (n != 1)
1436 gen_op_addl_T1_im(-((n - 1) * 4));
1437 } else {
1438 /* post decrement */
1439 gen_op_addl_T1_im(-(n * 4));
1440 }
1441 }
1442 gen_movl_reg_T1(s, rn);
1443 }
1444 }
1445 break;
1446 case 0xa:
1447 case 0xb:
1448 {
1449 int32_t offset;
1450
1451 /* branch (and link) */
1452 val = (int32_t)s->pc;
1453 if (insn & (1 << 24)) {
1454 gen_op_movl_T0_im(val);
1455 gen_op_movl_reg_TN[0][14]();
1456 }
1457 offset = (((int32_t)insn << 8) >> 8);
1458 val += (offset << 2) + 4;
1459 gen_op_jmp((long)s->tb, val);
1460 s->is_jmp = DISAS_TB_JUMP;
1461 }
1462 break;
1463 case 0xc:
1464 case 0xd:
1465 case 0xe:
1466 /* Coprocessor. */
1467 op1 = (insn >> 8) & 0xf;
1468 switch (op1) {
1469 case 10:
1470 case 11:
1471 if (disas_vfp_insn (env, s, insn))
1472 goto illegal_op;
1473 break;
1474 default:
1475 /* unknown coprocessor. */
1476 goto illegal_op;
1477 }
1478 break;
1479 case 0xf:
1480 /* swi */
1481 gen_op_movl_T0_im((long)s->pc);
1482 gen_op_movl_reg_TN[0][15]();
1483 gen_op_swi();
1484 s->is_jmp = DISAS_JUMP;
1485 break;
1486 default:
1487 illegal_op:
1488 gen_op_movl_T0_im((long)s->pc - 4);
1489 gen_op_movl_reg_TN[0][15]();
1490 gen_op_undef_insn();
1491 s->is_jmp = DISAS_JUMP;
1492 break;
1493 }
1494 }
1495 }
1496
1497 static void disas_thumb_insn(DisasContext *s)
1498 {
1499 uint32_t val, insn, op, rm, rn, rd, shift, cond;
1500 int32_t offset;
1501 int i;
1502
1503 insn = lduw(s->pc);
1504 s->pc += 2;
1505
1506 switch (insn >> 12) {
1507 case 0: case 1:
1508 rd = insn & 7;
1509 op = (insn >> 11) & 3;
1510 if (op == 3) {
1511 /* add/subtract */
1512 rn = (insn >> 3) & 7;
1513 gen_movl_T0_reg(s, rn);
1514 if (insn & (1 << 10)) {
1515 /* immediate */
1516 gen_op_movl_T1_im((insn >> 6) & 7);
1517 } else {
1518 /* reg */
1519 rm = (insn >> 6) & 7;
1520 gen_movl_T1_reg(s, rm);
1521 }
1522 if (insn & (1 << 9))
1523 gen_op_addl_T0_T1_cc();
1524 else
1525 gen_op_addl_T0_T1_cc();
1526 gen_movl_reg_T0(s, rd);
1527 } else {
1528 /* shift immediate */
1529 rm = (insn >> 3) & 7;
1530 shift = (insn >> 6) & 0x1f;
1531 gen_movl_T0_reg(s, rm);
1532 gen_shift_T0_im_thumb[op](shift);
1533 gen_movl_reg_T0(s, rd);
1534 }
1535 break;
1536 case 2: case 3:
1537 /* arithmetic large immediate */
1538 op = (insn >> 11) & 3;
1539 rd = (insn >> 8) & 0x7;
1540 if (op == 0) {
1541 gen_op_movl_T0_im(insn & 0xff);
1542 } else {
1543 gen_movl_T0_reg(s, rd);
1544 gen_op_movl_T1_im(insn & 0xff);
1545 }
1546 switch (op) {
1547 case 0: /* mov */
1548 gen_op_logic_T0_cc();
1549 break;
1550 case 1: /* cmp */
1551 gen_op_subl_T0_T1_cc();
1552 break;
1553 case 2: /* add */
1554 gen_op_addl_T0_T1_cc();
1555 break;
1556 case 3: /* sub */
1557 gen_op_subl_T0_T1_cc();
1558 break;
1559 }
1560 if (op != 1)
1561 gen_movl_reg_T0(s, rd);
1562 break;
1563 case 4:
1564 if (insn & (1 << 11)) {
1565 rd = (insn >> 8) & 7;
1566 /* load pc-relative */
1567 val = (insn & 0xff) * 4;
1568 gen_op_movl_T1_im(val);
1569 gen_movl_T2_reg(s, 15);
1570 gen_op_addl_T1_T2();
1571 gen_op_ldl_T0_T1();
1572 gen_movl_reg_T0(s, rd);
1573 break;
1574 }
1575 if (insn & (1 << 10)) {
1576 /* data processing extended or blx */
1577 rd = (insn & 7) | ((insn >> 4) & 8);
1578 rm = (insn >> 3) & 0xf;
1579 op = (insn >> 8) & 3;
1580 switch (op) {
1581 case 0: /* add */
1582 gen_movl_T0_reg(s, rd);
1583 gen_movl_T1_reg(s, rm);
1584 gen_op_addl_T0_T1();
1585 gen_movl_reg_T0(s, rd);
1586 break;
1587 case 1: /* cmp */
1588 gen_movl_T0_reg(s, rd);
1589 gen_movl_T1_reg(s, rm);
1590 gen_op_subl_T0_T1_cc();
1591 break;
1592 case 2: /* mov/cpy */
1593 gen_movl_T0_reg(s, rm);
1594 gen_movl_reg_T0(s, rd);
1595 break;
1596 case 3:/* branch [and link] exchange thumb register */
1597 if (insn & (1 << 7)) {
1598 val = (uint32_t)s->pc | 1;
1599 gen_op_movl_T1_im(val);
1600 gen_movl_reg_T1(s, 14);
1601 }
1602 gen_movl_T0_reg(s, rm);
1603 gen_bx(s);
1604 break;
1605 }
1606 break;
1607 }
1608
1609 /* data processing register */
1610 rd = insn & 7;
1611 rm = (insn >> 3) & 7;
1612 op = (insn >> 6) & 0xf;
1613 if (op == 2 || op == 3 || op == 4 || op == 7) {
1614 /* the shift/rotate ops want the operands backwards */
1615 val = rm;
1616 rm = rd;
1617 rd = val;
1618 val = 1;
1619 } else {
1620 val = 0;
1621 }
1622
1623 if (op == 9) /* neg */
1624 gen_op_movl_T0_im(0);
1625 else if (op != 0xf) /* mvn doesn't read its first operand */
1626 gen_movl_T0_reg(s, rd);
1627
1628 gen_movl_T1_reg(s, rm);
1629 switch (insn >> 6) {
1630 case 0x0: /* and */
1631 gen_op_andl_T0_T1();
1632 gen_op_logic_T0_cc();
1633 break;
1634 case 0x1: /* eor */
1635 gen_op_xorl_T0_T1();
1636 gen_op_logic_T0_cc();
1637 break;
1638 case 0x2: /* lsl */
1639 gen_op_shll_T1_T0_cc();
1640 break;
1641 case 0x3: /* lsr */
1642 gen_op_shrl_T1_T0_cc();
1643 break;
1644 case 0x4: /* asr */
1645 gen_op_sarl_T1_T0_cc();
1646 break;
1647 case 0x5: /* adc */
1648 gen_op_adcl_T0_T1_cc();
1649 break;
1650 case 0x6: /* sbc */
1651 gen_op_sbcl_T0_T1_cc();
1652 break;
1653 case 0x7: /* ror */
1654 gen_op_rorl_T1_T0_cc();
1655 break;
1656 case 0x8: /* tst */
1657 gen_op_andl_T0_T1();
1658 gen_op_logic_T0_cc();
1659 rd = 16;
1660 case 0x9: /* neg */
1661 gen_op_rsbl_T0_T1_cc();
1662 break;
1663 case 0xa: /* cmp */
1664 gen_op_subl_T0_T1_cc();
1665 rd = 16;
1666 break;
1667 case 0xb: /* cmn */
1668 gen_op_addl_T0_T1_cc();
1669 rd = 16;
1670 break;
1671 case 0xc: /* orr */
1672 gen_op_orl_T0_T1();
1673 gen_op_logic_T0_cc();
1674 break;
1675 case 0xd: /* mul */
1676 gen_op_mull_T0_T1();
1677 gen_op_logic_T0_cc();
1678 break;
1679 case 0xe: /* bic */
1680 gen_op_bicl_T0_T1();
1681 gen_op_logic_T0_cc();
1682 break;
1683 case 0xf: /* mvn */
1684 gen_op_notl_T1();
1685 gen_op_logic_T1_cc();
1686 val = 1;
1687 break;
1688 }
1689 if (rd != 16) {
1690 if (val)
1691 gen_movl_reg_T1(s, rd);
1692 else
1693 gen_movl_reg_T0(s, rd);
1694 }
1695 break;
1696
1697 case 5:
1698 /* load/store register offset. */
1699 rd = insn & 7;
1700 rn = (insn >> 3) & 7;
1701 rm = (insn >> 6) & 7;
1702 op = (insn >> 9) & 7;
1703 gen_movl_T1_reg(s, rn);
1704 gen_movl_T2_reg(s, rm);
1705 gen_op_addl_T1_T2();
1706
1707 if (op < 3) /* store */
1708 gen_movl_T0_reg(s, rd);
1709
1710 switch (op) {
1711 case 0: /* str */
1712 gen_op_stl_T0_T1();
1713 break;
1714 case 1: /* strh */
1715 gen_op_stw_T0_T1();
1716 break;
1717 case 2: /* strb */
1718 gen_op_stb_T0_T1();
1719 break;
1720 case 3: /* ldrsb */
1721 gen_op_ldsb_T0_T1();
1722 break;
1723 case 4: /* ldr */
1724 gen_op_ldl_T0_T1();
1725 break;
1726 case 5: /* ldrh */
1727 gen_op_ldsw_T0_T1();
1728 break;
1729 case 6: /* ldrb */
1730 gen_op_ldub_T0_T1();
1731 break;
1732 case 7: /* ldrsh */
1733 gen_op_ldsw_T0_T1();
1734 break;
1735 }
1736 if (op >= 3) /* load */
1737 gen_movl_reg_T0(s, rd);
1738 break;
1739
1740 case 6:
1741 /* load/store word immediate offset */
1742 rd = insn & 7;
1743 rn = (insn >> 3) & 7;
1744 gen_movl_T1_reg(s, rn);
1745 val = (insn >> 4) & 0x7c;
1746 gen_op_movl_T2_im(val);
1747 gen_op_addl_T1_T2();
1748
1749 if (insn & (1 << 11)) {
1750 /* load */
1751 gen_op_ldl_T0_T1();
1752 gen_movl_reg_T0(s, rd);
1753 } else {
1754 /* store */
1755 gen_movl_T0_reg(s, rd);
1756 gen_op_stl_T0_T1();
1757 }
1758 break;
1759
1760 case 7:
1761 /* load/store byte immediate offset */
1762 rd = insn & 7;
1763 rn = (insn >> 3) & 7;
1764 gen_movl_T1_reg(s, rn);
1765 val = (insn >> 6) & 0x1f;
1766 gen_op_movl_T2_im(val);
1767 gen_op_addl_T1_T2();
1768
1769 if (insn & (1 << 11)) {
1770 /* load */
1771 gen_op_ldub_T0_T1();
1772 gen_movl_reg_T0(s, rd);
1773 } else {
1774 /* store */
1775 gen_movl_T0_reg(s, rd);
1776 gen_op_stb_T0_T1();
1777 }
1778 break;
1779
1780 case 8:
1781 /* load/store halfword immediate offset */
1782 rd = insn & 7;
1783 rn = (insn >> 3) & 7;
1784 gen_movl_T1_reg(s, rn);
1785 val = (insn >> 5) & 0x3e;
1786 gen_op_movl_T2_im(val);
1787 gen_op_addl_T1_T2();
1788
1789 if (insn & (1 << 11)) {
1790 /* load */
1791 gen_op_lduw_T0_T1();
1792 gen_movl_reg_T0(s, rd);
1793 } else {
1794 /* store */
1795 gen_movl_T0_reg(s, rd);
1796 gen_op_stw_T0_T1();
1797 }
1798 break;
1799
1800 case 9:
1801 /* load/store from stack */
1802 rd = (insn >> 8) & 7;
1803 gen_movl_T1_reg(s, 13);
1804 val = (insn & 0xff) * 4;
1805 gen_op_movl_T2_im(val);
1806 gen_op_addl_T1_T2();
1807
1808 if (insn & (1 << 11)) {
1809 /* load */
1810 gen_op_ldl_T0_T1();
1811 gen_movl_reg_T0(s, rd);
1812 } else {
1813 /* store */
1814 gen_movl_T0_reg(s, rd);
1815 gen_op_stl_T0_T1();
1816 }
1817 break;
1818
1819 case 10:
1820 /* add to high reg */
1821 rd = (insn >> 8) & 7;
1822 if (insn & (1 << 11))
1823 rm = 13; /* sp */
1824 else
1825 rm = 15; /* pc */
1826 gen_movl_T0_reg(s, rm);
1827 val = (insn & 0xff) * 4;
1828 gen_op_movl_T1_im(val);
1829 gen_op_addl_T0_T1();
1830 gen_movl_reg_T0(s, rd);
1831 break;
1832
1833 case 11:
1834 /* misc */
1835 op = (insn >> 8) & 0xf;
1836 switch (op) {
1837 case 0:
1838 /* adjust stack pointer */
1839 gen_movl_T1_reg(s, 13);
1840 val = (insn & 0x7f) * 4;
1841 if (insn & (1 << 7))
1842 val = -(int32_t)val;
1843 gen_op_movl_T2_im(val);
1844 gen_op_addl_T1_T2();
1845 gen_movl_reg_T1(s, 13);
1846 break;
1847
1848 case 4: case 5: case 0xc: case 0xd:
1849 /* push/pop */
1850 gen_movl_T1_reg(s, 13);
1851 if (insn & (1 << 11))
1852 val = 4;
1853 else
1854 val = -4;
1855 gen_op_movl_T2_im(val);
1856 for (i = 0; i < 8; i++) {
1857 if (insn & (1 << i)) {
1858 if (insn & (1 << 11)) {
1859 /* pop */
1860 gen_op_ldl_T0_T1();
1861 gen_movl_reg_T0(s, i);
1862 } else {
1863 /* push */
1864 gen_movl_T0_reg(s, i);
1865 gen_op_stl_T0_T1();
1866 }
1867 /* move to the next address */
1868 gen_op_addl_T1_T2();
1869 }
1870 }
1871 if (insn & (1 << 8)) {
1872 if (insn & (1 << 11)) {
1873 /* pop pc */
1874 gen_op_ldl_T0_T1();
1875 /* don't set the pc until the rest of the instruction
1876 has completed */
1877 } else {
1878 /* push lr */
1879 gen_movl_T0_reg(s, 14);
1880 gen_op_stl_T0_T1();
1881 }
1882 gen_op_addl_T1_T2();
1883 }
1884
1885 /* write back the new stack pointer */
1886 gen_movl_reg_T1(s, 13);
1887 /* set the new PC value */
1888 if ((insn & 0x0900) == 0x0900)
1889 gen_bx(s);
1890 break;
1891
1892 default:
1893 goto undef;
1894 }
1895 break;
1896
1897 case 12:
1898 /* load/store multiple */
1899 rn = (insn >> 8) & 0x7;
1900 gen_movl_T1_reg(s, rn);
1901 gen_op_movl_T2_im(4);
1902 val = 0;
1903 for (i = 0; i < 8; i++) {
1904 if (insn & (1 << i)) {
1905 /* advance to the next address */
1906 if (val)
1907 gen_op_addl_T1_T2();
1908 else
1909 val = 1;
1910 if (insn & (1 << 11)) {
1911 /* load */
1912 gen_op_ldl_T0_T1();
1913 gen_movl_reg_T0(s, i);
1914 } else {
1915 /* store */
1916 gen_movl_T0_reg(s, i);
1917 gen_op_stl_T0_T1();
1918 }
1919 }
1920 }
1921 break;
1922
1923 case 13:
1924 /* conditional branch or swi */
1925 cond = (insn >> 8) & 0xf;
1926 if (cond == 0xe)
1927 goto undef;
1928
1929 if (cond == 0xf) {
1930 /* swi */
1931 gen_op_movl_T0_im((long)s->pc | 1);
1932 /* Don't set r15. */
1933 gen_op_movl_reg_TN[0][15]();
1934 gen_op_swi();
1935 s->is_jmp = DISAS_JUMP;
1936 break;
1937 }
1938 /* generate a conditional jump to next instruction */
1939 gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
1940 s->is_jmp = DISAS_JUMP_NEXT;
1941 gen_movl_T1_reg(s, 15);
1942
1943 /* jump to the offset */
1944 val = (uint32_t)s->pc;
1945 offset = ((int32_t)insn << 24) >> 24;
1946 val += (offset << 1) + 2;
1947 gen_op_jmp((long)s->tb, val);
1948 s->is_jmp = DISAS_TB_JUMP;
1949 break;
1950
1951 case 14:
1952 /* unconditional branch */
1953 if (insn & (1 << 11))
1954 goto undef; /* Second half of a blx */
1955 val = (uint32_t)s->pc;
1956 offset = ((int32_t)insn << 21) >> 21;
1957 val += (offset << 1) + 2;
1958 gen_op_jmp((long)s->tb, val);
1959 s->is_jmp = DISAS_TB_JUMP;
1960 break;
1961
1962 case 15:
1963 /* branch and link [and switch to arm] */
1964 offset = ((int32_t)insn << 21) >> 10;
1965 insn = lduw(s->pc);
1966 offset |= insn & 0x7ff;
1967
1968 val = (uint32_t)s->pc + 2;
1969 gen_op_movl_T1_im(val | 1);
1970 gen_movl_reg_T1(s, 14);
1971
1972 val += offset;
1973 if (insn & (1 << 11)) {
1974 /* bl */
1975 gen_op_jmp((long)s->tb, val);
1976 s->is_jmp = DISAS_TB_JUMP;
1977 } else {
1978 /* blx */
1979 gen_op_movl_T0_im(val);
1980 gen_bx(s);
1981 }
1982 }
1983 return;
1984 undef:
1985 gen_op_movl_T0_im((long)s->pc - 4);
1986 gen_op_movl_reg_TN[0][15]();
1987 gen_op_undef_insn();
1988 s->is_jmp = DISAS_JUMP;
1989 }
1990
1991 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
1992 basic block 'tb'. If search_pc is TRUE, also generate PC
1993 information for each intermediate instruction. */
1994 static inline int gen_intermediate_code_internal(CPUState *env,
1995 TranslationBlock *tb,
1996 int search_pc)
1997 {
1998 DisasContext dc1, *dc = &dc1;
1999 uint16_t *gen_opc_end;
2000 int j, lj;
2001 target_ulong pc_start;
2002
2003 /* generate intermediate code */
2004 pc_start = tb->pc;
2005
2006 dc->tb = tb;
2007
2008 gen_opc_ptr = gen_opc_buf;
2009 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2010 gen_opparam_ptr = gen_opparam_buf;
2011
2012 dc->is_jmp = DISAS_NEXT;
2013 dc->pc = pc_start;
2014 lj = -1;
2015 do {
2016 if (search_pc) {
2017 j = gen_opc_ptr - gen_opc_buf;
2018 if (lj < j) {
2019 lj++;
2020 while (lj < j)
2021 gen_opc_instr_start[lj++] = 0;
2022 }
2023 gen_opc_pc[lj] = dc->pc;
2024 gen_opc_instr_start[lj] = 1;
2025 }
2026 if (env->thumb)
2027 disas_thumb_insn(dc);
2028 else
2029 disas_arm_insn(env, dc);
2030 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
2031 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
2032 switch(dc->is_jmp) {
2033 case DISAS_JUMP_NEXT:
2034 case DISAS_NEXT:
2035 gen_op_jmp((long)dc->tb, (long)dc->pc);
2036 break;
2037 default:
2038 case DISAS_JUMP:
2039 case DISAS_UPDATE:
2040 /* indicate that the hash table must be used to find the next TB */
2041 gen_op_movl_T0_0();
2042 gen_op_exit_tb();
2043 break;
2044 case DISAS_TB_JUMP:
2045 /* nothing more to generate */
2046 break;
2047 }
2048 *gen_opc_ptr = INDEX_op_end;
2049
2050 #ifdef DEBUG_DISAS
2051 if (loglevel & CPU_LOG_TB_IN_ASM) {
2052 fprintf(logfile, "----------------\n");
2053 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2054 target_disas(logfile, pc_start, dc->pc - pc_start, 0);
2055 fprintf(logfile, "\n");
2056 if (loglevel & (CPU_LOG_TB_OP)) {
2057 fprintf(logfile, "OP:\n");
2058 dump_ops(gen_opc_buf, gen_opparam_buf);
2059 fprintf(logfile, "\n");
2060 }
2061 }
2062 #endif
2063 if (!search_pc)
2064 tb->size = dc->pc - pc_start;
2065 return 0;
2066 }
2067
2068 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
2069 {
2070 return gen_intermediate_code_internal(env, tb, 0);
2071 }
2072
2073 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2074 {
2075 return gen_intermediate_code_internal(env, tb, 1);
2076 }
2077
2078 CPUARMState *cpu_arm_init(void)
2079 {
2080 CPUARMState *env;
2081
2082 cpu_exec_init();
2083
2084 env = malloc(sizeof(CPUARMState));
2085 if (!env)
2086 return NULL;
2087 memset(env, 0, sizeof(CPUARMState));
2088 cpu_single_env = env;
2089 return env;
2090 }
2091
2092 void cpu_arm_close(CPUARMState *env)
2093 {
2094 free(env);
2095 }
2096
2097 void cpu_dump_state(CPUState *env, FILE *f,
2098 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2099 int flags)
2100 {
2101 int i;
2102 struct {
2103 uint32_t i;
2104 float s;
2105 } s0, s1;
2106 CPU_DoubleU d;
2107
2108 for(i=0;i<16;i++) {
2109 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2110 if ((i % 4) == 3)
2111 cpu_fprintf(f, "\n");
2112 else
2113 cpu_fprintf(f, " ");
2114 }
2115 cpu_fprintf(f, "PSR=%08x %c%c%c%c\n",
2116 env->cpsr,
2117 env->cpsr & (1 << 31) ? 'N' : '-',
2118 env->cpsr & (1 << 30) ? 'Z' : '-',
2119 env->cpsr & (1 << 29) ? 'C' : '-',
2120 env->cpsr & (1 << 28) ? 'V' : '-');
2121
2122 for (i = 0; i < 16; i++) {
2123 s0.s = env->vfp.regs.s[i * 2];
2124 s1.s = env->vfp.regs.s[i * 2 + 1];
2125 d.d = env->vfp.regs.d[i];
2126 cpu_fprintf(f, "s%02d=%08x(%8f) s%02d=%08x(%8f) d%02d=%08x%08x(%8f)\n",
2127 i * 2, (int)s0.i, s0.s,
2128 i * 2 + 1, (int)s0.i, s0.s,
2129 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
2130 d.d);
2131 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.fpscr);
2132 }
2133 }
2134
2135 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2136 {
2137 return addr;
2138 }
2139
2140 #if defined(CONFIG_USER_ONLY)
2141
2142 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
2143 int is_user, int is_softmmu)
2144 {
2145 env->cp15_6 = address;
2146 if (rw == 2) {
2147 env->exception_index = EXCP_PREFETCH_ABORT;
2148 } else {
2149 env->exception_index = EXCP_DATA_ABORT;
2150 }
2151 return 1;
2152 }
2153
2154 #else
2155
2156 #error not implemented
2157
2158 #endif