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