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