]> git.proxmox.com Git - qemu.git/blame - translate-arm.c
added nop test for exception
[qemu.git] / translate-arm.c
CommitLineData
5898e816
FB
1/*
2 * ARM translation
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <stdarg.h>
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include <inttypes.h>
25
26#include "cpu-arm.h"
27#include "exec.h"
28#include "disas.h"
29
30/* internal defines */
31typedef struct DisasContext {
32 uint8_t *pc;
33 int is_jmp;
34 struct TranslationBlock *tb;
35} DisasContext;
36
6e295807
FB
37#define DISAS_JUMP_NEXT 4
38
5898e816
FB
39/* XXX: move that elsewhere */
40static uint16_t *gen_opc_ptr;
41static uint32_t *gen_opparam_ptr;
42extern FILE *logfile;
43extern int loglevel;
44
45enum {
46#define DEF(s, n, copy_size) INDEX_op_ ## s,
47#include "opc-arm.h"
48#undef DEF
49 NB_OPS,
50};
51
52#include "gen-op-arm.h"
53
54typedef void (GenOpFunc)(void);
55typedef void (GenOpFunc1)(long);
56typedef void (GenOpFunc2)(long, long);
57typedef void (GenOpFunc3)(long, long, long);
58
59static GenOpFunc2 *gen_test_cc[14] = {
60 gen_op_test_eq,
61 gen_op_test_ne,
62 gen_op_test_cs,
63 gen_op_test_cc,
64 gen_op_test_mi,
65 gen_op_test_pl,
66 gen_op_test_vs,
67 gen_op_test_vc,
68 gen_op_test_hi,
69 gen_op_test_ls,
70 gen_op_test_ge,
71 gen_op_test_lt,
72 gen_op_test_gt,
73 gen_op_test_le,
74};
75
76const uint8_t table_logic_cc[16] = {
77 1, /* and */
78 1, /* xor */
79 0, /* sub */
80 0, /* rsb */
81 0, /* add */
82 0, /* adc */
83 0, /* sbc */
84 0, /* rsc */
85 1, /* andl */
86 1, /* xorl */
87 0, /* cmp */
88 0, /* cmn */
89 1, /* orr */
90 1, /* mov */
91 1, /* bic */
92 1, /* mvn */
93};
94
95static GenOpFunc1 *gen_shift_T1_im[4] = {
96 gen_op_shll_T1_im,
97 gen_op_shrl_T1_im,
98 gen_op_sarl_T1_im,
99 gen_op_rorl_T1_im,
100};
101
102static GenOpFunc1 *gen_shift_T2_im[4] = {
103 gen_op_shll_T2_im,
104 gen_op_shrl_T2_im,
105 gen_op_sarl_T2_im,
106 gen_op_rorl_T2_im,
107};
108
109static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
110 gen_op_shll_T1_im_cc,
111 gen_op_shrl_T1_im_cc,
112 gen_op_sarl_T1_im_cc,
113 gen_op_rorl_T1_im_cc,
114};
115
116static GenOpFunc *gen_shift_T1_T0[4] = {
117 gen_op_shll_T1_T0,
118 gen_op_shrl_T1_T0,
119 gen_op_sarl_T1_T0,
120 gen_op_rorl_T1_T0,
121};
122
123static GenOpFunc *gen_shift_T1_T0_cc[4] = {
124 gen_op_shll_T1_T0_cc,
125 gen_op_shrl_T1_T0_cc,
126 gen_op_sarl_T1_T0_cc,
127 gen_op_rorl_T1_T0_cc,
128};
129
130static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
131 {
132 gen_op_movl_T0_r0,
133 gen_op_movl_T0_r1,
134 gen_op_movl_T0_r2,
135 gen_op_movl_T0_r3,
136 gen_op_movl_T0_r4,
137 gen_op_movl_T0_r5,
138 gen_op_movl_T0_r6,
139 gen_op_movl_T0_r7,
140 gen_op_movl_T0_r8,
141 gen_op_movl_T0_r9,
142 gen_op_movl_T0_r10,
143 gen_op_movl_T0_r11,
144 gen_op_movl_T0_r12,
145 gen_op_movl_T0_r13,
146 gen_op_movl_T0_r14,
147 gen_op_movl_T0_r15,
148 },
149 {
150 gen_op_movl_T1_r0,
151 gen_op_movl_T1_r1,
152 gen_op_movl_T1_r2,
153 gen_op_movl_T1_r3,
154 gen_op_movl_T1_r4,
155 gen_op_movl_T1_r5,
156 gen_op_movl_T1_r6,
157 gen_op_movl_T1_r7,
158 gen_op_movl_T1_r8,
159 gen_op_movl_T1_r9,
160 gen_op_movl_T1_r10,
161 gen_op_movl_T1_r11,
162 gen_op_movl_T1_r12,
163 gen_op_movl_T1_r13,
164 gen_op_movl_T1_r14,
165 gen_op_movl_T1_r15,
166 },
167 {
168 gen_op_movl_T2_r0,
169 gen_op_movl_T2_r1,
170 gen_op_movl_T2_r2,
171 gen_op_movl_T2_r3,
172 gen_op_movl_T2_r4,
173 gen_op_movl_T2_r5,
174 gen_op_movl_T2_r6,
175 gen_op_movl_T2_r7,
176 gen_op_movl_T2_r8,
177 gen_op_movl_T2_r9,
178 gen_op_movl_T2_r10,
179 gen_op_movl_T2_r11,
180 gen_op_movl_T2_r12,
181 gen_op_movl_T2_r13,
182 gen_op_movl_T2_r14,
183 gen_op_movl_T2_r15,
184 },
185};
186
187static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
188 {
189 gen_op_movl_r0_T0,
190 gen_op_movl_r1_T0,
191 gen_op_movl_r2_T0,
192 gen_op_movl_r3_T0,
193 gen_op_movl_r4_T0,
194 gen_op_movl_r5_T0,
195 gen_op_movl_r6_T0,
196 gen_op_movl_r7_T0,
197 gen_op_movl_r8_T0,
198 gen_op_movl_r9_T0,
199 gen_op_movl_r10_T0,
200 gen_op_movl_r11_T0,
201 gen_op_movl_r12_T0,
202 gen_op_movl_r13_T0,
203 gen_op_movl_r14_T0,
204 gen_op_movl_r15_T0,
205 },
206 {
207 gen_op_movl_r0_T1,
208 gen_op_movl_r1_T1,
209 gen_op_movl_r2_T1,
210 gen_op_movl_r3_T1,
211 gen_op_movl_r4_T1,
212 gen_op_movl_r5_T1,
213 gen_op_movl_r6_T1,
214 gen_op_movl_r7_T1,
215 gen_op_movl_r8_T1,
216 gen_op_movl_r9_T1,
217 gen_op_movl_r10_T1,
218 gen_op_movl_r11_T1,
219 gen_op_movl_r12_T1,
220 gen_op_movl_r13_T1,
221 gen_op_movl_r14_T1,
222 gen_op_movl_r15_T1,
223 },
224};
225
226static GenOpFunc1 *gen_op_movl_TN_im[3] = {
227 gen_op_movl_T0_im,
228 gen_op_movl_T1_im,
229 gen_op_movl_T2_im,
230};
231
232static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
233{
234 int val;
235
236 if (reg == 15) {
237 /* normaly, since we updated PC, we need only to add 4 */
238 val = (long)s->pc + 4;
239 gen_op_movl_TN_im[t](val);
240 } else {
241 gen_op_movl_TN_reg[t][reg]();
242 }
243}
244
245static inline void gen_movl_T0_reg(DisasContext *s, int reg)
246{
247 gen_movl_TN_reg(s, reg, 0);
248}
249
250static inline void gen_movl_T1_reg(DisasContext *s, int reg)
251{
252 gen_movl_TN_reg(s, reg, 1);
253}
254
255static inline void gen_movl_T2_reg(DisasContext *s, int reg)
256{
257 gen_movl_TN_reg(s, reg, 2);
258}
259
260static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
261{
262 gen_op_movl_reg_TN[t][reg]();
263 if (reg == 15) {
264 s->is_jmp = DISAS_JUMP;
265 }
266}
267
268static inline void gen_movl_reg_T0(DisasContext *s, int reg)
269{
270 gen_movl_reg_TN(s, reg, 0);
271}
272
273static inline void gen_movl_reg_T1(DisasContext *s, int reg)
274{
275 gen_movl_reg_TN(s, reg, 1);
276}
277
278static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
279{
280 int val, rm, shift;
281
282 if (!(insn & (1 << 25))) {
283 /* immediate */
284 val = insn & 0xfff;
285 if (!(insn & (1 << 23)))
286 val = -val;
287 gen_op_addl_T1_im(val);
288 } else {
289 /* shift/register */
290 rm = (insn) & 0xf;
291 shift = (insn >> 7) & 0x1f;
292 gen_movl_T2_reg(s, rm);
293 if (shift != 0) {
294 gen_shift_T2_im[(insn >> 5) & 3](shift);
295 }
296 if (!(insn & (1 << 23)))
297 gen_op_subl_T1_T2();
298 else
299 gen_op_addl_T1_T2();
300 }
301}
302
303static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
304{
305 int val, rm;
306
307 if (insn & (1 << 22)) {
308 /* immediate */
309 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
310 if (!(insn & (1 << 23)))
311 val = -val;
312 gen_op_addl_T1_im(val);
313 } else {
314 /* register */
315 rm = (insn) & 0xf;
316 gen_movl_T2_reg(s, rm);
317 if (!(insn & (1 << 23)))
318 gen_op_subl_T1_T2();
319 else
320 gen_op_addl_T1_T2();
321 }
322}
323
324static void disas_arm_insn(DisasContext *s)
325{
326 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
327
328 insn = ldl(s->pc);
329 s->pc += 4;
330
331 cond = insn >> 28;
332 if (cond == 0xf)
333 goto illegal_op;
334 if (cond != 0xe) {
335 /* if not always execute, we generate a conditional jump to
336 next instruction */
337 gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
6e295807 338 s->is_jmp = DISAS_JUMP_NEXT;
5898e816 339 }
6e295807
FB
340 if (((insn & 0x0e000000) == 0 &&
341 (insn & 0x00000090) != 0x90) ||
342 ((insn & 0x0e000000) == (1 << 25))) {
5898e816
FB
343 int set_cc, logic_cc, shiftop;
344
345 op1 = (insn >> 21) & 0xf;
346 set_cc = (insn >> 20) & 1;
347 logic_cc = table_logic_cc[op1] & set_cc;
348
349 /* data processing instruction */
350 if (insn & (1 << 25)) {
351 /* immediate operand */
352 val = insn & 0xff;
353 shift = ((insn >> 8) & 0xf) * 2;
354 if (shift)
355 val = (val >> shift) | (val << (32 - shift));
356 gen_op_movl_T1_im(val);
357 /* XXX: is CF modified ? */
358 } else {
359 /* register */
360 rm = (insn) & 0xf;
361 gen_movl_T1_reg(s, rm);
362 shiftop = (insn >> 5) & 3;
363 if (!(insn & (1 << 4))) {
364 shift = (insn >> 7) & 0x1f;
365 if (shift != 0) {
366 if (logic_cc) {
367 gen_shift_T1_im_cc[shiftop](shift);
368 } else {
369 gen_shift_T1_im[shiftop](shift);
370 }
371 }
372 } else {
6e295807 373 rs = (insn >> 8) & 0xf;
5898e816
FB
374 gen_movl_T0_reg(s, rs);
375 if (logic_cc) {
376 gen_shift_T1_T0_cc[shiftop]();
377 } else {
378 gen_shift_T1_T0[shiftop]();
379 }
380 }
381 }
382 if (op1 != 0x0f && op1 != 0x0d) {
383 rn = (insn >> 16) & 0xf;
384 gen_movl_T0_reg(s, rn);
385 }
386 rd = (insn >> 12) & 0xf;
387 switch(op1) {
388 case 0x00:
389 gen_op_andl_T0_T1();
390 gen_movl_reg_T0(s, rd);
6e295807
FB
391 if (logic_cc)
392 gen_op_logic_T0_cc();
5898e816
FB
393 break;
394 case 0x01:
395 gen_op_xorl_T0_T1();
396 gen_movl_reg_T0(s, rd);
6e295807
FB
397 if (logic_cc)
398 gen_op_logic_T0_cc();
5898e816
FB
399 break;
400 case 0x02:
401 if (set_cc)
402 gen_op_subl_T0_T1_cc();
403 else
404 gen_op_subl_T0_T1();
405 gen_movl_reg_T0(s, rd);
406 break;
407 case 0x03:
408 if (set_cc)
409 gen_op_rsbl_T0_T1_cc();
410 else
411 gen_op_rsbl_T0_T1();
412 gen_movl_reg_T0(s, rd);
413 break;
414 case 0x04:
415 if (set_cc)
416 gen_op_addl_T0_T1_cc();
417 else
418 gen_op_addl_T0_T1();
419 gen_movl_reg_T0(s, rd);
420 break;
421 case 0x05:
422 if (set_cc)
423 gen_op_adcl_T0_T1_cc();
424 else
425 gen_op_adcl_T0_T1();
426 gen_movl_reg_T0(s, rd);
427 break;
428 case 0x06:
429 if (set_cc)
430 gen_op_sbcl_T0_T1_cc();
431 else
432 gen_op_sbcl_T0_T1();
433 gen_movl_reg_T0(s, rd);
434 break;
435 case 0x07:
436 if (set_cc)
437 gen_op_rscl_T0_T1_cc();
438 else
439 gen_op_rscl_T0_T1();
440 gen_movl_reg_T0(s, rd);
441 break;
442 case 0x08:
443 if (set_cc) {
444 gen_op_andl_T0_T1();
6e295807 445 gen_op_logic_T0_cc();
5898e816
FB
446 }
447 break;
448 case 0x09:
449 if (set_cc) {
450 gen_op_xorl_T0_T1();
6e295807 451 gen_op_logic_T0_cc();
5898e816
FB
452 }
453 break;
454 case 0x0a:
455 if (set_cc) {
456 gen_op_subl_T0_T1_cc();
457 }
458 break;
459 case 0x0b:
460 if (set_cc) {
461 gen_op_addl_T0_T1_cc();
462 }
463 break;
464 case 0x0c:
465 gen_op_orl_T0_T1();
466 gen_movl_reg_T0(s, rd);
6e295807
FB
467 if (logic_cc)
468 gen_op_logic_T0_cc();
5898e816
FB
469 break;
470 case 0x0d:
471 gen_movl_reg_T1(s, rd);
6e295807
FB
472 if (logic_cc)
473 gen_op_logic_T1_cc();
5898e816
FB
474 break;
475 case 0x0e:
476 gen_op_bicl_T0_T1();
477 gen_movl_reg_T0(s, rd);
6e295807
FB
478 if (logic_cc)
479 gen_op_logic_T0_cc();
5898e816
FB
480 break;
481 default:
482 case 0x0f:
483 gen_op_notl_T1();
484 gen_movl_reg_T1(s, rd);
6e295807
FB
485 if (logic_cc)
486 gen_op_logic_T1_cc();
5898e816
FB
487 break;
488 }
5898e816
FB
489 } else {
490 /* other instructions */
491 op1 = (insn >> 24) & 0xf;
492 switch(op1) {
493 case 0x0:
494 case 0x1:
495 sh = (insn >> 5) & 3;
496 if (sh == 0) {
497 if (op1 == 0x0) {
498 rd = (insn >> 16) & 0xf;
499 rn = (insn >> 12) & 0xf;
500 rs = (insn >> 8) & 0xf;
501 rm = (insn) & 0xf;
502 if (!(insn & (1 << 23))) {
503 /* 32 bit mul */
504 gen_movl_T0_reg(s, rs);
505 gen_movl_T1_reg(s, rm);
506 gen_op_mul_T0_T1();
507 if (insn & (1 << 21)) {
508 gen_movl_T1_reg(s, rn);
509 gen_op_addl_T0_T1();
510 }
511 if (insn & (1 << 20))
6e295807 512 gen_op_logic_T0_cc();
5898e816
FB
513 gen_movl_reg_T0(s, rd);
514 } else {
515 /* 64 bit mul */
516 gen_movl_T0_reg(s, rs);
517 gen_movl_T1_reg(s, rm);
518 if (insn & (1 << 22))
519 gen_op_mull_T0_T1();
520 else
521 gen_op_imull_T0_T1();
522 if (insn & (1 << 21))
523 gen_op_addq_T0_T1(rn, rd);
524 if (insn & (1 << 20))
525 gen_op_logicq_cc();
526 gen_movl_reg_T0(s, rn);
527 gen_movl_reg_T1(s, rd);
528 }
529 } else {
530 /* SWP instruction */
531 rn = (insn >> 16) & 0xf;
532 rd = (insn >> 12) & 0xf;
533 rm = (insn) & 0xf;
534
535 gen_movl_T0_reg(s, rm);
536 gen_movl_T1_reg(s, rn);
537 if (insn & (1 << 22)) {
538 gen_op_swpb_T0_T1();
539 } else {
540 gen_op_swpl_T0_T1();
541 }
542 gen_movl_reg_T0(s, rd);
543 }
544 } else {
545 /* load/store half word */
546 rn = (insn >> 16) & 0xf;
547 rd = (insn >> 12) & 0xf;
548 gen_movl_T1_reg(s, rn);
549 if (insn & (1 << 25))
550 gen_add_datah_offset(s, insn);
551 if (insn & (1 << 20)) {
552 /* load */
553 switch(sh) {
554 case 1:
555 gen_op_lduw_T0_T1();
556 break;
557 case 2:
558 gen_op_ldsb_T0_T1();
559 break;
560 default:
561 case 3:
562 gen_op_ldsw_T0_T1();
563 break;
564 }
565 } else {
566 /* store */
567 gen_op_stw_T0_T1();
568 }
6e295807 569 if (!(insn & (1 << 24))) {
5898e816 570 gen_add_datah_offset(s, insn);
5898e816 571 gen_movl_reg_T1(s, rn);
6e295807
FB
572 } else if (insn & (1 << 21)) {
573 gen_movl_reg_T1(s, rn);
574 }
5898e816
FB
575 }
576 break;
577 case 0x4:
578 case 0x5:
579 case 0x6:
580 case 0x7:
581 /* load/store byte/word */
582 rn = (insn >> 16) & 0xf;
583 rd = (insn >> 12) & 0xf;
584 gen_movl_T1_reg(s, rn);
585 if (insn & (1 << 24))
586 gen_add_data_offset(s, insn);
587 if (insn & (1 << 20)) {
588 /* load */
589 if (insn & (1 << 22))
590 gen_op_ldub_T0_T1();
591 else
592 gen_op_ldl_T0_T1();
593 gen_movl_reg_T0(s, rd);
594 } else {
595 /* store */
596 gen_movl_T0_reg(s, rd);
597 if (insn & (1 << 22))
598 gen_op_stb_T0_T1();
599 else
600 gen_op_stl_T0_T1();
601 }
6e295807 602 if (!(insn & (1 << 24))) {
5898e816 603 gen_add_data_offset(s, insn);
5898e816 604 gen_movl_reg_T1(s, rn);
6e295807
FB
605 } else if (insn & (1 << 21))
606 gen_movl_reg_T1(s, rn); {
607 }
5898e816
FB
608 break;
609 case 0x08:
610 case 0x09:
6e295807
FB
611 {
612 int j, n;
613 /* load/store multiple words */
614 /* XXX: store correct base if write back */
615 if (insn & (1 << 22))
616 goto illegal_op; /* only usable in supervisor mode */
617 rn = (insn >> 16) & 0xf;
618 gen_movl_T1_reg(s, rn);
619
620 /* compute total size */
621 n = 0;
622 for(i=0;i<16;i++) {
623 if (insn & (1 << i))
624 n++;
625 }
626 /* XXX: test invalid n == 0 case ? */
627 if (insn & (1 << 23)) {
628 if (insn & (1 << 24)) {
629 /* pre increment */
630 gen_op_addl_T1_im(4);
5898e816 631 } else {
6e295807
FB
632 /* post increment */
633 }
634 } else {
635 if (insn & (1 << 24)) {
636 /* pre decrement */
637 gen_op_addl_T1_im(-(n * 4));
638 } else {
639 /* post decrement */
640 if (n != 1)
641 gen_op_addl_T1_im(-((n - 1) * 4));
642 }
643 }
644 j = 0;
645 for(i=0;i<16;i++) {
646 if (insn & (1 << i)) {
647 if (insn & (1 << 20)) {
648 /* load */
649 gen_op_ldl_T0_T1();
650 gen_movl_reg_T0(s, i);
651 } else {
652 /* store */
653 if (i == 15) {
654 /* special case: r15 = PC + 12 */
655 val = (long)s->pc + 8;
656 gen_op_movl_TN_im[0](val);
657 } else {
658 gen_movl_T0_reg(s, i);
659 }
660 gen_op_stl_T0_T1();
661 }
662 j++;
663 /* no need to add after the last transfer */
664 if (j != n)
665 gen_op_addl_T1_im(4);
5898e816 666 }
6e295807
FB
667 }
668 if (insn & (1 << 21)) {
669 /* write back */
670 if (insn & (1 << 23)) {
671 if (insn & (1 << 24)) {
672 /* pre increment */
673 } else {
674 /* post increment */
675 gen_op_addl_T1_im(4);
676 }
677 } else {
678 if (insn & (1 << 24)) {
679 /* pre decrement */
680 if (n != 1)
681 gen_op_addl_T1_im(-((n - 1) * 4));
682 } else {
683 /* post decrement */
684 gen_op_addl_T1_im(-(n * 4));
685 }
686 }
687 gen_movl_reg_T1(s, rn);
5898e816
FB
688 }
689 }
5898e816
FB
690 break;
691 case 0xa:
692 case 0xb:
693 {
694 int offset;
695
696 /* branch (and link) */
697 val = (int)s->pc;
698 if (insn & (1 << 24)) {
699 gen_op_movl_T0_im(val);
700 gen_op_movl_reg_TN[0][14]();
701 }
702 offset = (((int)insn << 8) >> 8);
703 val += (offset << 2) + 4;
704 gen_op_jmp((long)s->tb, val);
705 s->is_jmp = DISAS_TB_JUMP;
706 }
707 break;
708 case 0xf:
709 /* swi */
710 gen_op_movl_T0_im((long)s->pc);
711 gen_op_movl_reg_TN[0][15]();
712 gen_op_swi();
713 s->is_jmp = DISAS_JUMP;
714 break;
6e295807
FB
715 case 0xc:
716 case 0xd:
717 rd = (insn >> 12) & 0x7;
718 rn = (insn >> 16) & 0xf;
719 gen_movl_T1_reg(s, rn);
720 val = (insn) & 0xff;
721 if (!(insn & (1 << 23)))
722 val = -val;
723 switch((insn >> 8) & 0xf) {
724 case 0x1:
725 /* load/store */
726 if ((insn & (1 << 24)))
727 gen_op_addl_T1_im(val);
728 /* XXX: do it */
729 if (!(insn & (1 << 24)))
730 gen_op_addl_T1_im(val);
731 if (insn & (1 << 21))
732 gen_movl_reg_T1(s, rn);
733 break;
734 case 0x2:
735 {
736 int n, i;
737 /* load store multiple */
738 if ((insn & (1 << 24)))
739 gen_op_addl_T1_im(val);
740 switch(insn & 0x00408000) {
741 case 0x00008000: n = 1; break;
742 case 0x00400000: n = 2; break;
743 case 0x00408000: n = 3; break;
744 default: n = 4; break;
745 }
746 for(i = 0;i < n; i++) {
747 /* XXX: do it */
748 }
749 if (!(insn & (1 << 24)))
750 gen_op_addl_T1_im(val);
751 if (insn & (1 << 21))
752 gen_movl_reg_T1(s, rn);
753 }
754 break;
755 default:
756 goto illegal_op;
757 }
758 break;
759 case 0x0e:
760 /* float ops */
761 /* XXX: do it */
762 switch((insn >> 20) & 0xf) {
763 case 0x2: /* wfs */
764 break;
765 case 0x3: /* rfs */
766 break;
767 case 0x4: /* wfc */
768 break;
769 case 0x5: /* rfc */
770 break;
771 default:
772 goto illegal_op;
773 }
774 break;
5898e816
FB
775 default:
776 illegal_op:
777 gen_op_movl_T0_im((long)s->pc - 4);
778 gen_op_movl_reg_TN[0][15]();
779 gen_op_undef_insn();
780 s->is_jmp = DISAS_JUMP;
781 break;
782 }
783 }
784}
785
786/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
787 basic block 'tb'. If search_pc is TRUE, also generate PC
788 information for each intermediate instruction. */
7d83131c 789static inline int gen_intermediate_code_internal(TranslationBlock *tb, int search_pc)
5898e816
FB
790{
791 DisasContext dc1, *dc = &dc1;
792 uint16_t *gen_opc_end;
793 int j, lj;
794 uint8_t *pc_start;
795
796 /* generate intermediate code */
797 pc_start = (uint8_t *)tb->pc;
798
799 dc->tb = tb;
800
801 gen_opc_ptr = gen_opc_buf;
802 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
803 gen_opparam_ptr = gen_opparam_buf;
804
805 dc->is_jmp = DISAS_NEXT;
806 dc->pc = pc_start;
807 lj = -1;
808 do {
809 if (search_pc) {
810 j = gen_opc_ptr - gen_opc_buf;
811 if (lj < j) {
812 lj++;
813 while (lj < j)
814 gen_opc_instr_start[lj++] = 0;
5898e816 815 }
7739f36e
FB
816 gen_opc_pc[lj] = (uint32_t)dc->pc;
817 gen_opc_instr_start[lj] = 1;
5898e816
FB
818 }
819 disas_arm_insn(dc);
820 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
821 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
6e295807
FB
822 switch(dc->is_jmp) {
823 case DISAS_JUMP_NEXT:
824 case DISAS_NEXT:
825 gen_op_jmp((long)dc->tb, (long)dc->pc);
826 break;
827 default:
828 case DISAS_JUMP:
5898e816
FB
829 /* indicate that the hash table must be used to find the next TB */
830 gen_op_movl_T0_0();
6e295807
FB
831 break;
832 case DISAS_TB_JUMP:
833 /* nothing more to generate */
834 break;
5898e816
FB
835 }
836 *gen_opc_ptr = INDEX_op_end;
837
838#ifdef DEBUG_DISAS
839 if (loglevel) {
840 fprintf(logfile, "----------------\n");
841 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
842 disas(logfile, pc_start, dc->pc - pc_start, 0, 0);
843 fprintf(logfile, "\n");
844
845 fprintf(logfile, "OP:\n");
846 dump_ops(gen_opc_buf, gen_opparam_buf);
847 fprintf(logfile, "\n");
848 }
849#endif
850 if (!search_pc)
851 tb->size = dc->pc - pc_start;
852 return 0;
853}
854
7d83131c
FB
855int gen_intermediate_code(TranslationBlock *tb)
856{
857 return gen_intermediate_code_internal(tb, 0);
858}
859
860int gen_intermediate_code_pc(TranslationBlock *tb)
861{
862 return gen_intermediate_code_internal(tb, 1);
863}
864
5898e816
FB
865CPUARMState *cpu_arm_init(void)
866{
867 CPUARMState *env;
868
869 cpu_exec_init();
870
871 env = malloc(sizeof(CPUARMState));
872 if (!env)
873 return NULL;
874 memset(env, 0, sizeof(CPUARMState));
875 return env;
876}
877
878void cpu_arm_close(CPUARMState *env)
879{
880 free(env);
881}
882
883void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags)
884{
885 int i;
886
887 for(i=0;i<16;i++) {
888 fprintf(f, "R%02d=%08x", i, env->regs[i]);
889 if ((i % 4) == 3)
890 fprintf(f, "\n");
891 else
892 fprintf(f, " ");
893 }
6e295807
FB
894 fprintf(f, "PSR=%08x %c%c%c%c\n",
895 env->cpsr,
896 env->cpsr & (1 << 31) ? 'N' : '-',
897 env->cpsr & (1 << 30) ? 'Z' : '-',
898 env->cpsr & (1 << 29) ? 'C' : '-',
899 env->cpsr & (1 << 28) ? 'V' : '-');
5898e816 900}