More consistent naming for CRIS register-number macros.
[qemu/malc.git] / target-cris / translate.c
blob4150737f82111dfa25ca83882fd29e9f4227a99d
1 /*
2 * CRIS emulation for qemu: main translation routines.
4 * Copyright (c) 2007 AXIS Communications AB
5 * Written by Edgar E. Iglesias.
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
23 * This file implements a CRIS decoder-stage in SW. The decoder translates the
24 * guest (CRIS) machine-code into host machine code via dyngen using the
25 * micro-operations described in op.c
27 * The micro-operations for CRIS translation implement a RISC style ISA.
28 * Note that the micro-operations typically order their operands
29 * starting with the dst. CRIS asm, does the opposite.
31 * For example the following CRIS code:
32 * add.d [$r0], $r1
34 * translates into:
36 * gen_movl_T0_reg(0); // Fetch $r0 into T0
37 * gen_load_T0_T0(); // Load T0, @T0
38 * gen_movl_reg_T0(1); // Writeback T0 into $r1
40 * The actual names for the micro-code generators vary but the example
41 * illustrates the point.
44 #include <stdarg.h>
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <inttypes.h>
49 #include <assert.h>
51 #include "cpu.h"
52 #include "exec-all.h"
53 #include "disas.h"
54 #include "tcg-op.h"
55 #include "crisv32-decode.h"
57 #define CRIS_STATS 0
58 #if CRIS_STATS
59 #define STATS(x) x
60 #else
61 #define STATS(x)
62 #endif
64 #define DISAS_CRIS 0
65 #if DISAS_CRIS
66 #define DIS(x) x
67 #else
68 #define DIS(x)
69 #endif
71 #define BUG() (gen_BUG(dc, __FILE__, __LINE__))
72 #define BUG_ON(x) ({if (x) BUG();})
74 /* Used by the decoder. */
75 #define EXTRACT_FIELD(src, start, end) \
76 (((src) >> start) & ((1 << (end - start + 1)) - 1))
78 #define CC_MASK_NZ 0xc
79 #define CC_MASK_NZV 0xe
80 #define CC_MASK_NZVC 0xf
81 #define CC_MASK_RNZV 0x10e
83 /* This is the state at translation time. */
84 typedef struct DisasContext {
85 CPUState *env;
86 target_ulong pc, insn_pc;
88 /* Decoder. */
89 uint32_t ir;
90 uint32_t opcode;
91 unsigned int op1;
92 unsigned int op2;
93 unsigned int zsize, zzsize;
94 unsigned int mode;
95 unsigned int postinc;
97 int update_cc;
98 int cc_op;
99 int cc_size;
100 uint32_t cc_mask;
101 int flags_live;
102 int flagx_live;
103 int flags_x;
104 uint32_t tb_entry_flags;
106 int memidx; /* user or kernel mode. */
107 int is_jmp;
108 int dyn_jmp;
110 uint32_t delayed_pc;
111 int delayed_branch;
112 int bcc;
113 uint32_t condlabel;
115 struct TranslationBlock *tb;
116 int singlestep_enabled;
117 } DisasContext;
119 void cris_prepare_jmp (DisasContext *dc, uint32_t dst);
120 static void gen_BUG(DisasContext *dc, char *file, int line)
122 printf ("BUG: pc=%x %s %d\n", dc->pc, file, line);
123 fprintf (logfile, "BUG: pc=%x %s %d\n", dc->pc, file, line);
124 cpu_dump_state (dc->env, stdout, fprintf, 0);
125 fflush(NULL);
126 cris_prepare_jmp (dc, 0x70000000 + line);
129 /* Table to generate quick moves from T0 onto any register. */
130 static GenOpFunc *gen_movl_reg_T0[16] =
132 gen_op_movl_r0_T0, gen_op_movl_r1_T0,
133 gen_op_movl_r2_T0, gen_op_movl_r3_T0,
134 gen_op_movl_r4_T0, gen_op_movl_r5_T0,
135 gen_op_movl_r6_T0, gen_op_movl_r7_T0,
136 gen_op_movl_r8_T0, gen_op_movl_r9_T0,
137 gen_op_movl_r10_T0, gen_op_movl_r11_T0,
138 gen_op_movl_r12_T0, gen_op_movl_r13_T0,
139 gen_op_movl_r14_T0, gen_op_movl_r15_T0,
141 static GenOpFunc *gen_movl_T0_reg[16] =
143 gen_op_movl_T0_r0, gen_op_movl_T0_r1,
144 gen_op_movl_T0_r2, gen_op_movl_T0_r3,
145 gen_op_movl_T0_r4, gen_op_movl_T0_r5,
146 gen_op_movl_T0_r6, gen_op_movl_T0_r7,
147 gen_op_movl_T0_r8, gen_op_movl_T0_r9,
148 gen_op_movl_T0_r10, gen_op_movl_T0_r11,
149 gen_op_movl_T0_r12, gen_op_movl_T0_r13,
150 gen_op_movl_T0_r14, gen_op_movl_T0_r15,
153 static void noop_write(void) {
154 /* nop. */
157 static void gen_vr_read(void) {
158 gen_op_movl_T0_im(32);
161 static void gen_movl_T0_p0(void) {
162 gen_op_movl_T0_im(0);
165 static void gen_ccs_read(void) {
166 gen_op_movl_T0_p13();
169 static void gen_ccs_write(void) {
170 gen_op_movl_p13_T0();
173 /* Table to generate quick moves from T0 onto any register. */
174 static GenOpFunc *gen_movl_preg_T0[16] =
176 noop_write, /* bz, not writeable. */
177 noop_write, /* vr, not writeable. */
178 gen_op_movl_p2_T0, gen_op_movl_p3_T0,
179 noop_write, /* wz, not writeable. */
180 gen_op_movl_p5_T0,
181 gen_op_movl_p6_T0, gen_op_movl_p7_T0,
182 noop_write, /* dz, not writeable. */
183 gen_op_movl_p9_T0,
184 gen_op_movl_p10_T0, gen_op_movl_p11_T0,
185 gen_op_movl_p12_T0,
186 gen_ccs_write, /* ccs needs special treatment. */
187 gen_op_movl_p14_T0, gen_op_movl_p15_T0,
189 static GenOpFunc *gen_movl_T0_preg[16] =
191 gen_movl_T0_p0,
192 gen_vr_read,
193 gen_op_movl_T0_p2, gen_op_movl_T0_p3,
194 gen_op_movl_T0_p4, gen_op_movl_T0_p5,
195 gen_op_movl_T0_p6, gen_op_movl_T0_p7,
196 gen_op_movl_T0_p8, gen_op_movl_T0_p9,
197 gen_op_movl_T0_p10, gen_op_movl_T0_p11,
198 gen_op_movl_T0_p12,
199 gen_ccs_read, /* ccs needs special treatment. */
200 gen_op_movl_T0_p14, gen_op_movl_T0_p15,
203 /* We need this table to handle moves with implicit width. */
204 int preg_sizes[] = {
205 1, /* bz. */
206 1, /* vr. */
207 4, /* pid. */
208 1, /* srs. */
209 2, /* wz. */
210 4, 4, 4,
211 4, 4, 4, 4,
212 4, 4, 4, 4,
215 #ifdef CONFIG_USER_ONLY
216 #define GEN_OP_LD(width, reg) \
217 void gen_op_ld##width##_T0_##reg (DisasContext *dc) { \
218 gen_op_ld##width##_T0_##reg##_raw(); \
220 #define GEN_OP_ST(width, reg) \
221 void gen_op_st##width##_##reg##_T1 (DisasContext *dc) { \
222 gen_op_st##width##_##reg##_T1_raw(); \
224 #else
225 #define GEN_OP_LD(width, reg) \
226 void gen_op_ld##width##_T0_##reg (DisasContext *dc) { \
227 if (dc->memidx) gen_op_ld##width##_T0_##reg##_kernel(); \
228 else gen_op_ld##width##_T0_##reg##_user();\
230 #define GEN_OP_ST(width, reg) \
231 void gen_op_st##width##_##reg##_T1 (DisasContext *dc) { \
232 if (dc->memidx) gen_op_st##width##_##reg##_T1_kernel(); \
233 else gen_op_st##width##_##reg##_T1_user();\
235 #endif
237 GEN_OP_LD(ub, T0)
238 GEN_OP_LD(b, T0)
239 GEN_OP_ST(b, T0)
240 GEN_OP_LD(uw, T0)
241 GEN_OP_LD(w, T0)
242 GEN_OP_ST(w, T0)
243 GEN_OP_LD(l, T0)
244 GEN_OP_ST(l, T0)
246 static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
248 TranslationBlock *tb;
249 tb = dc->tb;
250 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
251 #if 0
252 /* XXX: this code is not finished */
253 tcg_gen_goto_tb(n);
254 #endif
255 tcg_gen_exit_tb(0);
256 } else {
257 tcg_gen_exit_tb(0);
261 /* Sign extend at translation time. */
262 static int sign_extend(unsigned int val, unsigned int width)
264 int sval;
266 /* LSL. */
267 val <<= 31 - width;
268 sval = val;
269 /* ASR. */
270 sval >>= 31 - width;
271 return sval;
274 static void cris_evaluate_flags(DisasContext *dc)
276 if (!dc->flags_live) {
278 switch (dc->cc_op)
280 case CC_OP_MCP:
281 gen_op_evaluate_flags_mcp ();
282 break;
283 case CC_OP_MULS:
284 gen_op_evaluate_flags_muls ();
285 break;
286 case CC_OP_MULU:
287 gen_op_evaluate_flags_mulu ();
288 break;
289 case CC_OP_MOVE:
290 switch (dc->cc_size)
292 case 4:
293 gen_op_evaluate_flags_move_4();
294 break;
295 case 2:
296 gen_op_evaluate_flags_move_2();
297 break;
298 default:
299 gen_op_evaluate_flags ();
300 break;
302 break;
304 default:
306 switch (dc->cc_size)
308 case 4:
309 gen_op_evaluate_flags_alu_4 ();
310 break;
311 default:
312 gen_op_evaluate_flags ();
313 break;
316 break;
318 dc->flags_live = 1;
322 static void cris_cc_mask(DisasContext *dc, unsigned int mask)
324 uint32_t ovl;
326 /* Check if we need to evaluate the condition codes due to
327 CC overlaying. */
328 ovl = (dc->cc_mask ^ mask) & ~mask;
329 if (ovl) {
330 /* TODO: optimize this case. It trigs all the time. */
331 cris_evaluate_flags (dc);
333 dc->cc_mask = mask;
335 dc->update_cc = 1;
336 if (mask == 0)
337 dc->update_cc = 0;
338 else {
339 gen_op_update_cc_mask(mask);
340 dc->flags_live = 0;
344 static void cris_update_cc_op(DisasContext *dc, int op)
346 dc->cc_op = op;
347 gen_op_update_cc_op(op);
348 dc->flags_live = 0;
350 static void cris_update_cc_size(DisasContext *dc, int size)
352 dc->cc_size = size;
353 gen_op_update_cc_size_im(size);
356 /* op is the operation.
357 T0, T1 are the operands.
358 dst is the destination reg.
360 static void crisv32_alu_op(DisasContext *dc, int op, int rd, int size)
362 int writeback = 1;
363 if (dc->update_cc) {
364 cris_update_cc_op(dc, op);
365 cris_update_cc_size(dc, size);
366 gen_op_update_cc_x(dc->flagx_live, dc->flags_x);
367 gen_op_update_cc_dest_T0();
370 /* Emit the ALU insns. */
371 switch (op)
373 case CC_OP_ADD:
374 gen_op_addl_T0_T1();
375 /* Extended arithmetics. */
376 if (!dc->flagx_live)
377 gen_op_addxl_T0_C();
378 else if (dc->flags_x)
379 gen_op_addxl_T0_C();
380 break;
381 case CC_OP_ADDC:
382 gen_op_addl_T0_T1();
383 gen_op_addl_T0_C();
384 break;
385 case CC_OP_MCP:
386 gen_op_addl_T0_T1();
387 gen_op_addl_T0_R();
388 break;
389 case CC_OP_SUB:
390 gen_op_negl_T1_T1();
391 gen_op_addl_T0_T1();
392 /* CRIS flag evaluation needs ~src. */
393 gen_op_negl_T1_T1();
394 gen_op_not_T1_T1();
396 /* Extended arithmetics. */
397 if (!dc->flagx_live)
398 gen_op_subxl_T0_C();
399 else if (dc->flags_x)
400 gen_op_subxl_T0_C();
401 break;
402 case CC_OP_MOVE:
403 gen_op_movl_T0_T1();
404 break;
405 case CC_OP_OR:
406 gen_op_orl_T0_T1();
407 break;
408 case CC_OP_AND:
409 gen_op_andl_T0_T1();
410 break;
411 case CC_OP_XOR:
412 gen_op_xorl_T0_T1();
413 break;
414 case CC_OP_LSL:
415 gen_op_lsll_T0_T1();
416 break;
417 case CC_OP_LSR:
418 gen_op_lsrl_T0_T1();
419 break;
420 case CC_OP_ASR:
421 gen_op_asrl_T0_T1();
422 break;
423 case CC_OP_NEG:
424 gen_op_negl_T0_T1();
425 /* Extended arithmetics. */
426 gen_op_subxl_T0_C();
427 break;
428 case CC_OP_LZ:
429 gen_op_lz_T0_T1();
430 break;
431 case CC_OP_BTST:
432 gen_op_btst_T0_T1();
433 writeback = 0;
434 break;
435 case CC_OP_MULS:
436 gen_op_muls_T0_T1();
437 break;
438 case CC_OP_MULU:
439 gen_op_mulu_T0_T1();
440 break;
441 case CC_OP_DSTEP:
442 gen_op_dstep_T0_T1();
443 break;
444 case CC_OP_BOUND:
445 gen_op_bound_T0_T1();
446 break;
447 case CC_OP_CMP:
448 gen_op_negl_T1_T1();
449 gen_op_addl_T0_T1();
450 /* CRIS flag evaluation needs ~src. */
451 gen_op_negl_T1_T1();
452 gen_op_not_T1_T1();
454 /* Extended arithmetics. */
455 gen_op_subxl_T0_C();
456 writeback = 0;
457 break;
458 default:
459 fprintf (logfile, "illegal ALU op.\n");
460 BUG();
461 break;
464 if (dc->update_cc)
465 gen_op_update_cc_src_T1();
467 if (size == 1)
468 gen_op_andl_T0_im(0xff);
469 else if (size == 2)
470 gen_op_andl_T0_im(0xffff);
471 /* Writeback. */
472 if (writeback) {
473 if (size == 4)
474 gen_movl_reg_T0[rd]();
475 else {
476 gen_op_movl_T1_T0();
477 gen_movl_T0_reg[rd]();
478 if (size == 1)
479 gen_op_andl_T0_im(~0xff);
480 else
481 gen_op_andl_T0_im(~0xffff);
482 gen_op_orl_T0_T1();
483 gen_movl_reg_T0[rd]();
484 gen_op_movl_T0_T1();
487 if (dc->update_cc)
488 gen_op_update_cc_result_T0();
491 /* TODO: Optimize this. */
492 if (!dc->flagx_live)
493 cris_evaluate_flags(dc);
497 static int arith_cc(DisasContext *dc)
499 if (dc->update_cc) {
500 switch (dc->cc_op) {
501 case CC_OP_ADD: return 1;
502 case CC_OP_SUB: return 1;
503 case CC_OP_LSL: return 1;
504 case CC_OP_LSR: return 1;
505 case CC_OP_ASR: return 1;
506 case CC_OP_CMP: return 1;
507 default:
508 return 0;
511 return 0;
514 static void gen_tst_cc (DisasContext *dc, int cond)
516 int arith_opt;
518 /* TODO: optimize more condition codes. */
519 arith_opt = arith_cc(dc) && !dc->flags_live;
520 switch (cond) {
521 case CC_EQ:
522 if (arith_opt)
523 gen_op_tst_cc_eq_fast ();
524 else {
525 cris_evaluate_flags(dc);
526 gen_op_tst_cc_eq ();
528 break;
529 case CC_NE:
530 if (arith_opt)
531 gen_op_tst_cc_ne_fast ();
532 else {
533 cris_evaluate_flags(dc);
534 gen_op_tst_cc_ne ();
536 break;
537 case CC_CS:
538 cris_evaluate_flags(dc);
539 gen_op_tst_cc_cs ();
540 break;
541 case CC_CC:
542 cris_evaluate_flags(dc);
543 gen_op_tst_cc_cc ();
544 break;
545 case CC_VS:
546 cris_evaluate_flags(dc);
547 gen_op_tst_cc_vs ();
548 break;
549 case CC_VC:
550 cris_evaluate_flags(dc);
551 gen_op_tst_cc_vc ();
552 break;
553 case CC_PL:
554 if (arith_opt)
555 gen_op_tst_cc_pl_fast ();
556 else {
557 cris_evaluate_flags(dc);
558 gen_op_tst_cc_pl ();
560 break;
561 case CC_MI:
562 if (arith_opt)
563 gen_op_tst_cc_mi_fast ();
564 else {
565 cris_evaluate_flags(dc);
566 gen_op_tst_cc_mi ();
568 break;
569 case CC_LS:
570 cris_evaluate_flags(dc);
571 gen_op_tst_cc_ls ();
572 break;
573 case CC_HI:
574 cris_evaluate_flags(dc);
575 gen_op_tst_cc_hi ();
576 break;
577 case CC_GE:
578 cris_evaluate_flags(dc);
579 gen_op_tst_cc_ge ();
580 break;
581 case CC_LT:
582 cris_evaluate_flags(dc);
583 gen_op_tst_cc_lt ();
584 break;
585 case CC_GT:
586 cris_evaluate_flags(dc);
587 gen_op_tst_cc_gt ();
588 break;
589 case CC_LE:
590 cris_evaluate_flags(dc);
591 gen_op_tst_cc_le ();
592 break;
593 case CC_P:
594 cris_evaluate_flags(dc);
595 gen_op_tst_cc_p ();
596 break;
597 case CC_A:
598 cris_evaluate_flags(dc);
599 gen_op_movl_T0_im (1);
600 break;
601 default:
602 BUG();
603 break;
607 static void cris_prepare_cc_branch (DisasContext *dc, int offset, int cond)
609 /* This helps us re-schedule the micro-code to insns in delay-slots
610 before the actual jump. */
611 dc->delayed_branch = 2;
612 dc->delayed_pc = dc->pc + offset;
613 dc->bcc = cond;
614 if (cond != CC_A)
616 gen_tst_cc (dc, cond);
617 gen_op_evaluate_bcc ();
619 gen_op_movl_T0_im (dc->delayed_pc);
620 gen_op_movl_btarget_T0 ();
623 /* Dynamic jumps, when the dest is in a live reg for example. */
624 void cris_prepare_dyn_jmp (DisasContext *dc)
626 /* This helps us re-schedule the micro-code to insns in delay-slots
627 before the actual jump. */
628 dc->delayed_branch = 2;
629 dc->dyn_jmp = 1;
630 dc->bcc = CC_A;
633 void cris_prepare_jmp (DisasContext *dc, uint32_t dst)
635 /* This helps us re-schedule the micro-code to insns in delay-slots
636 before the actual jump. */
637 dc->delayed_branch = 2;
638 dc->delayed_pc = dst;
639 dc->dyn_jmp = 0;
640 dc->bcc = CC_A;
643 void gen_load_T0_T0 (DisasContext *dc, unsigned int size, int sign)
645 if (size == 1) {
646 if (sign)
647 gen_op_ldb_T0_T0(dc);
648 else
649 gen_op_ldub_T0_T0(dc);
651 else if (size == 2) {
652 if (sign)
653 gen_op_ldw_T0_T0(dc);
654 else
655 gen_op_lduw_T0_T0(dc);
657 else {
658 gen_op_ldl_T0_T0(dc);
662 void gen_store_T0_T1 (DisasContext *dc, unsigned int size)
664 /* Remember, operands are flipped. CRIS has reversed order. */
665 if (size == 1) {
666 gen_op_stb_T0_T1(dc);
668 else if (size == 2) {
669 gen_op_stw_T0_T1(dc);
671 else
672 gen_op_stl_T0_T1(dc);
675 /* sign extend T1 according to size. */
676 static void gen_sext_T1_T0(int size)
678 if (size == 1)
679 gen_op_extb_T1_T0();
680 else if (size == 2)
681 gen_op_extw_T1_T0();
684 static void gen_sext_T1_T1(int size)
686 if (size == 1)
687 gen_op_extb_T1_T1();
688 else if (size == 2)
689 gen_op_extw_T1_T1();
692 static void gen_sext_T0_T0(int size)
694 if (size == 1)
695 gen_op_extb_T0_T0();
696 else if (size == 2)
697 gen_op_extw_T0_T0();
700 static void gen_zext_T0_T0(int size)
702 if (size == 1)
703 gen_op_zextb_T0_T0();
704 else if (size == 2)
705 gen_op_zextw_T0_T0();
708 static void gen_zext_T1_T0(int size)
710 if (size == 1)
711 gen_op_zextb_T1_T0();
712 else if (size == 2)
713 gen_op_zextw_T1_T0();
716 static void gen_zext_T1_T1(int size)
718 if (size == 1)
719 gen_op_zextb_T1_T1();
720 else if (size == 2)
721 gen_op_zextw_T1_T1();
724 #if DISAS_CRIS
725 static char memsize_char(int size)
727 switch (size)
729 case 1: return 'b'; break;
730 case 2: return 'w'; break;
731 case 4: return 'd'; break;
732 default:
733 return 'x';
734 break;
737 #endif
739 static unsigned int memsize_z(DisasContext *dc)
741 return dc->zsize + 1;
744 static unsigned int memsize_zz(DisasContext *dc)
746 switch (dc->zzsize)
748 case 0: return 1;
749 case 1: return 2;
750 default:
751 return 4;
755 static void do_postinc (DisasContext *dc, int size)
757 if (!dc->postinc)
758 return;
759 gen_movl_T0_reg[dc->op1]();
760 gen_op_addl_T0_im(size);
761 gen_movl_reg_T0[dc->op1]();
765 static void dec_prep_move_r(DisasContext *dc, int rs, int rd,
766 int size, int s_ext)
768 gen_movl_T0_reg[rs]();
769 gen_op_movl_T1_T0();
770 if (s_ext)
771 gen_sext_T1_T1(size);
772 else
773 gen_zext_T1_T1(size);
776 /* Prepare T0 and T1 for a register alu operation.
777 s_ext decides if the operand1 should be sign-extended or zero-extended when
778 needed. */
779 static void dec_prep_alu_r(DisasContext *dc, int rs, int rd,
780 int size, int s_ext)
782 dec_prep_move_r(dc, rs, rd, size, s_ext);
784 gen_movl_T0_reg[rd]();
785 if (s_ext)
786 gen_sext_T0_T0(size);
787 else
788 gen_zext_T0_T0(size);
791 /* Prepare T0 and T1 for a memory + alu operation.
792 s_ext decides if the operand1 should be sign-extended or zero-extended when
793 needed. */
794 static int dec_prep_alu_m(DisasContext *dc, int s_ext, int memsize)
796 unsigned int rs, rd;
797 uint32_t imm;
798 int is_imm;
799 int insn_len = 2;
801 rs = dc->op1;
802 rd = dc->op2;
803 is_imm = rs == 15 && dc->postinc;
805 /* Load [$rs] onto T1. */
806 if (is_imm) {
807 insn_len = 2 + memsize;
808 if (memsize == 1)
809 insn_len++;
811 imm = ldl_code(dc->pc + 2);
812 if (memsize != 4) {
813 if (s_ext) {
814 imm = sign_extend(imm, (memsize * 8) - 1);
815 } else {
816 if (memsize == 1)
817 imm &= 0xff;
818 else
819 imm &= 0xffff;
822 DIS(fprintf (logfile, "imm=%x rd=%d sext=%d ms=%d\n",
823 imm, rd, s_ext, memsize));
824 gen_op_movl_T1_im (imm);
825 dc->postinc = 0;
826 } else {
827 gen_movl_T0_reg[rs]();
828 gen_load_T0_T0(dc, memsize, 0);
829 gen_op_movl_T1_T0();
830 if (s_ext)
831 gen_sext_T1_T1(memsize);
832 else
833 gen_zext_T1_T1(memsize);
836 /* put dest in T0. */
837 gen_movl_T0_reg[rd]();
838 return insn_len;
841 #if DISAS_CRIS
842 static const char *cc_name(int cc)
844 static char *cc_names[16] = {
845 "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi",
846 "ls", "hi", "ge", "lt", "gt", "le", "a", "p"
848 assert(cc < 16);
849 return cc_names[cc];
851 #endif
853 static unsigned int dec_bccq(DisasContext *dc)
855 int32_t offset;
856 int sign;
857 uint32_t cond = dc->op2;
858 int tmp;
860 offset = EXTRACT_FIELD (dc->ir, 1, 7);
861 sign = EXTRACT_FIELD(dc->ir, 0, 0);
863 offset *= 2;
864 offset |= sign << 8;
865 tmp = offset;
866 offset = sign_extend(offset, 8);
868 /* op2 holds the condition-code. */
869 cris_cc_mask(dc, 0);
870 cris_prepare_cc_branch (dc, offset, cond);
871 return 2;
873 static unsigned int dec_addoq(DisasContext *dc)
875 uint32_t imm;
877 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 7);
878 imm = sign_extend(dc->op1, 7);
880 DIS(fprintf (logfile, "addoq %d, $r%u\n", imm, dc->op2));
881 cris_cc_mask(dc, 0);
882 /* Fetch register operand, */
883 gen_movl_T0_reg[dc->op2]();
884 gen_op_movl_T1_im(imm);
885 crisv32_alu_op(dc, CC_OP_ADD, R_ACR, 4);
886 return 2;
888 static unsigned int dec_addq(DisasContext *dc)
890 DIS(fprintf (logfile, "addq %u, $r%u\n", dc->op1, dc->op2));
892 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
894 cris_cc_mask(dc, CC_MASK_NZVC);
895 /* Fetch register operand, */
896 gen_movl_T0_reg[dc->op2]();
897 gen_op_movl_T1_im(dc->op1);
898 crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
899 return 2;
901 static unsigned int dec_moveq(DisasContext *dc)
903 uint32_t imm;
905 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
906 imm = sign_extend(dc->op1, 5);
907 DIS(fprintf (logfile, "moveq %d, $r%u\n", imm, dc->op2));
909 cris_cc_mask(dc, 0);
910 gen_op_movl_T1_im(imm);
911 crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
913 return 2;
915 static unsigned int dec_subq(DisasContext *dc)
917 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
919 DIS(fprintf (logfile, "subq %u, $r%u\n", dc->op1, dc->op2));
921 cris_cc_mask(dc, CC_MASK_NZVC);
922 /* Fetch register operand, */
923 gen_movl_T0_reg[dc->op2]();
924 gen_op_movl_T1_im(dc->op1);
925 crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
926 return 2;
928 static unsigned int dec_cmpq(DisasContext *dc)
930 uint32_t imm;
931 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
932 imm = sign_extend(dc->op1, 5);
934 DIS(fprintf (logfile, "cmpq %d, $r%d\n", imm, dc->op2));
935 cris_cc_mask(dc, CC_MASK_NZVC);
936 gen_movl_T0_reg[dc->op2]();
937 gen_op_movl_T1_im(imm);
938 crisv32_alu_op(dc, CC_OP_CMP, dc->op2, 4);
939 return 2;
941 static unsigned int dec_andq(DisasContext *dc)
943 uint32_t imm;
944 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
945 imm = sign_extend(dc->op1, 5);
947 DIS(fprintf (logfile, "andq %d, $r%d\n", imm, dc->op2));
948 cris_cc_mask(dc, CC_MASK_NZ);
949 gen_movl_T0_reg[dc->op2]();
950 gen_op_movl_T1_im(imm);
951 crisv32_alu_op(dc, CC_OP_AND, dc->op2, 4);
952 return 2;
954 static unsigned int dec_orq(DisasContext *dc)
956 uint32_t imm;
957 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
958 imm = sign_extend(dc->op1, 5);
959 DIS(fprintf (logfile, "orq %d, $r%d\n", imm, dc->op2));
960 cris_cc_mask(dc, CC_MASK_NZ);
961 gen_movl_T0_reg[dc->op2]();
962 gen_op_movl_T1_im(imm);
963 crisv32_alu_op(dc, CC_OP_OR, dc->op2, 4);
964 return 2;
966 static unsigned int dec_btstq(DisasContext *dc)
968 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
969 DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2));
970 cris_cc_mask(dc, CC_MASK_NZ);
971 gen_movl_T0_reg[dc->op2]();
972 gen_op_movl_T1_im(dc->op1);
973 crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4);
975 cris_update_cc_op(dc, CC_OP_FLAGS);
976 gen_op_movl_flags_T0();
977 dc->flags_live = 1;
978 return 2;
980 static unsigned int dec_asrq(DisasContext *dc)
982 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
983 DIS(fprintf (logfile, "asrq %u, $r%d\n", dc->op1, dc->op2));
984 cris_cc_mask(dc, CC_MASK_NZ);
985 gen_movl_T0_reg[dc->op2]();
986 gen_op_movl_T1_im(dc->op1);
987 crisv32_alu_op(dc, CC_OP_ASR, dc->op2, 4);
988 return 2;
990 static unsigned int dec_lslq(DisasContext *dc)
992 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
993 DIS(fprintf (logfile, "lslq %u, $r%d\n", dc->op1, dc->op2));
995 cris_cc_mask(dc, CC_MASK_NZ);
996 gen_movl_T0_reg[dc->op2]();
997 gen_op_movl_T1_im(dc->op1);
998 crisv32_alu_op(dc, CC_OP_LSL, dc->op2, 4);
999 return 2;
1001 static unsigned int dec_lsrq(DisasContext *dc)
1003 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
1004 DIS(fprintf (logfile, "lsrq %u, $r%d\n", dc->op1, dc->op2));
1006 cris_cc_mask(dc, CC_MASK_NZ);
1007 gen_movl_T0_reg[dc->op2]();
1008 gen_op_movl_T1_im(dc->op1);
1009 crisv32_alu_op(dc, CC_OP_LSR, dc->op2, 4);
1010 return 2;
1013 static unsigned int dec_move_r(DisasContext *dc)
1015 int size = memsize_zz(dc);
1017 DIS(fprintf (logfile, "move.%c $r%u, $r%u\n",
1018 memsize_char(size), dc->op1, dc->op2));
1020 cris_cc_mask(dc, CC_MASK_NZ);
1021 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0);
1022 crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, size);
1023 return 2;
1026 static unsigned int dec_scc_r(DisasContext *dc)
1028 int cond = dc->op2;
1030 DIS(fprintf (logfile, "s%s $r%u\n",
1031 cc_name(cond), dc->op1));
1033 if (cond != CC_A)
1035 gen_tst_cc (dc, cond);
1036 gen_op_movl_T1_T0();
1038 else
1039 gen_op_movl_T1_im(1);
1041 cris_cc_mask(dc, 0);
1042 crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4);
1043 return 2;
1046 static unsigned int dec_and_r(DisasContext *dc)
1048 int size = memsize_zz(dc);
1050 DIS(fprintf (logfile, "and.%c $r%u, $r%u\n",
1051 memsize_char(size), dc->op1, dc->op2));
1052 cris_cc_mask(dc, CC_MASK_NZ);
1053 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1054 crisv32_alu_op(dc, CC_OP_AND, dc->op2, size);
1055 return 2;
1058 static unsigned int dec_lz_r(DisasContext *dc)
1060 DIS(fprintf (logfile, "lz $r%u, $r%u\n",
1061 dc->op1, dc->op2));
1062 cris_cc_mask(dc, CC_MASK_NZ);
1063 dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1064 crisv32_alu_op(dc, CC_OP_LZ, dc->op2, 4);
1065 return 2;
1068 static unsigned int dec_lsl_r(DisasContext *dc)
1070 int size = memsize_zz(dc);
1072 DIS(fprintf (logfile, "lsl.%c $r%u, $r%u\n",
1073 memsize_char(size), dc->op1, dc->op2));
1074 cris_cc_mask(dc, CC_MASK_NZ);
1075 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1076 gen_op_andl_T1_im(63);
1077 crisv32_alu_op(dc, CC_OP_LSL, dc->op2, size);
1078 return 2;
1081 static unsigned int dec_lsr_r(DisasContext *dc)
1083 int size = memsize_zz(dc);
1085 DIS(fprintf (logfile, "lsr.%c $r%u, $r%u\n",
1086 memsize_char(size), dc->op1, dc->op2));
1087 cris_cc_mask(dc, CC_MASK_NZ);
1088 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1089 gen_op_andl_T1_im(63);
1090 crisv32_alu_op(dc, CC_OP_LSR, dc->op2, size);
1091 return 2;
1094 static unsigned int dec_asr_r(DisasContext *dc)
1096 int size = memsize_zz(dc);
1098 DIS(fprintf (logfile, "asr.%c $r%u, $r%u\n",
1099 memsize_char(size), dc->op1, dc->op2));
1100 cris_cc_mask(dc, CC_MASK_NZ);
1101 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1);
1102 gen_op_andl_T1_im(63);
1103 crisv32_alu_op(dc, CC_OP_ASR, dc->op2, size);
1104 return 2;
1107 static unsigned int dec_muls_r(DisasContext *dc)
1109 int size = memsize_zz(dc);
1111 DIS(fprintf (logfile, "muls.%c $r%u, $r%u\n",
1112 memsize_char(size), dc->op1, dc->op2));
1113 cris_cc_mask(dc, CC_MASK_NZV);
1114 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1);
1115 gen_sext_T0_T0(size);
1116 crisv32_alu_op(dc, CC_OP_MULS, dc->op2, 4);
1117 return 2;
1120 static unsigned int dec_mulu_r(DisasContext *dc)
1122 int size = memsize_zz(dc);
1124 DIS(fprintf (logfile, "mulu.%c $r%u, $r%u\n",
1125 memsize_char(size), dc->op1, dc->op2));
1126 cris_cc_mask(dc, CC_MASK_NZV);
1127 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1128 gen_zext_T0_T0(size);
1129 crisv32_alu_op(dc, CC_OP_MULU, dc->op2, 4);
1130 return 2;
1134 static unsigned int dec_dstep_r(DisasContext *dc)
1136 DIS(fprintf (logfile, "dstep $r%u, $r%u\n", dc->op1, dc->op2));
1137 cris_cc_mask(dc, CC_MASK_NZ);
1138 gen_movl_T0_reg[dc->op1]();
1139 gen_op_movl_T1_T0();
1140 gen_movl_T0_reg[dc->op2]();
1141 crisv32_alu_op(dc, CC_OP_DSTEP, dc->op2, 4);
1142 return 2;
1145 static unsigned int dec_xor_r(DisasContext *dc)
1147 int size = memsize_zz(dc);
1148 DIS(fprintf (logfile, "xor.%c $r%u, $r%u\n",
1149 memsize_char(size), dc->op1, dc->op2));
1150 BUG_ON(size != 4); /* xor is dword. */
1151 cris_cc_mask(dc, CC_MASK_NZ);
1152 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1153 crisv32_alu_op(dc, CC_OP_XOR, dc->op2, 4);
1154 return 2;
1157 static unsigned int dec_bound_r(DisasContext *dc)
1159 int size = memsize_zz(dc);
1160 DIS(fprintf (logfile, "bound.%c $r%u, $r%u\n",
1161 memsize_char(size), dc->op1, dc->op2));
1162 cris_cc_mask(dc, CC_MASK_NZ);
1163 /* TODO: needs optmimization. */
1164 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1165 /* rd should be 4. */
1166 gen_movl_T0_reg[dc->op2]();
1167 crisv32_alu_op(dc, CC_OP_BOUND, dc->op2, 4);
1168 return 2;
1171 static unsigned int dec_cmp_r(DisasContext *dc)
1173 int size = memsize_zz(dc);
1174 DIS(fprintf (logfile, "cmp.%c $r%u, $r%u\n",
1175 memsize_char(size), dc->op1, dc->op2));
1176 cris_cc_mask(dc, CC_MASK_NZVC);
1177 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1178 crisv32_alu_op(dc, CC_OP_CMP, dc->op2, size);
1179 return 2;
1182 static unsigned int dec_abs_r(DisasContext *dc)
1184 DIS(fprintf (logfile, "abs $r%u, $r%u\n",
1185 dc->op1, dc->op2));
1186 cris_cc_mask(dc, CC_MASK_NZ);
1187 dec_prep_move_r(dc, dc->op1, dc->op2, 4, 0);
1188 gen_op_absl_T1_T1();
1189 crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1190 return 2;
1193 static unsigned int dec_add_r(DisasContext *dc)
1195 int size = memsize_zz(dc);
1196 DIS(fprintf (logfile, "add.%c $r%u, $r%u\n",
1197 memsize_char(size), dc->op1, dc->op2));
1198 cris_cc_mask(dc, CC_MASK_NZVC);
1199 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1200 crisv32_alu_op(dc, CC_OP_ADD, dc->op2, size);
1201 return 2;
1204 static unsigned int dec_addc_r(DisasContext *dc)
1206 DIS(fprintf (logfile, "addc $r%u, $r%u\n",
1207 dc->op1, dc->op2));
1208 cris_evaluate_flags(dc);
1209 cris_cc_mask(dc, CC_MASK_NZVC);
1210 dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1211 crisv32_alu_op(dc, CC_OP_ADDC, dc->op2, 4);
1212 return 2;
1215 static unsigned int dec_mcp_r(DisasContext *dc)
1217 DIS(fprintf (logfile, "mcp $p%u, $r%u\n",
1218 dc->op2, dc->op1));
1219 cris_evaluate_flags(dc);
1220 cris_cc_mask(dc, CC_MASK_RNZV);
1221 gen_movl_T0_preg[dc->op2]();
1222 gen_op_movl_T1_T0();
1223 gen_movl_T0_reg[dc->op1]();
1224 crisv32_alu_op(dc, CC_OP_MCP, dc->op1, 4);
1225 return 2;
1228 #if DISAS_CRIS
1229 static char * swapmode_name(int mode, char *modename) {
1230 int i = 0;
1231 if (mode & 8)
1232 modename[i++] = 'n';
1233 if (mode & 4)
1234 modename[i++] = 'w';
1235 if (mode & 2)
1236 modename[i++] = 'b';
1237 if (mode & 1)
1238 modename[i++] = 'r';
1239 modename[i++] = 0;
1240 return modename;
1242 #endif
1244 static unsigned int dec_swap_r(DisasContext *dc)
1246 DIS(char modename[4]);
1247 DIS(fprintf (logfile, "swap%s $r%u\n",
1248 swapmode_name(dc->op2, modename), dc->op1));
1250 cris_cc_mask(dc, CC_MASK_NZ);
1251 gen_movl_T0_reg[dc->op1]();
1252 if (dc->op2 & 8)
1253 gen_op_not_T0_T0();
1254 if (dc->op2 & 4)
1255 gen_op_swapw_T0_T0();
1256 if (dc->op2 & 2)
1257 gen_op_swapb_T0_T0();
1258 if (dc->op2 & 1)
1259 gen_op_swapr_T0_T0();
1260 gen_op_movl_T1_T0();
1261 crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4);
1262 return 2;
1265 static unsigned int dec_or_r(DisasContext *dc)
1267 int size = memsize_zz(dc);
1268 DIS(fprintf (logfile, "or.%c $r%u, $r%u\n",
1269 memsize_char(size), dc->op1, dc->op2));
1270 cris_cc_mask(dc, CC_MASK_NZ);
1271 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1272 crisv32_alu_op(dc, CC_OP_OR, dc->op2, size);
1273 return 2;
1276 static unsigned int dec_addi_r(DisasContext *dc)
1278 DIS(fprintf (logfile, "addi.%c $r%u, $r%u\n",
1279 memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
1280 cris_cc_mask(dc, 0);
1281 dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1282 gen_op_lsll_T0_im(dc->zzsize);
1283 gen_op_addl_T0_T1();
1284 gen_movl_reg_T0[dc->op1]();
1285 return 2;
1288 static unsigned int dec_addi_acr(DisasContext *dc)
1290 DIS(fprintf (logfile, "addi.%c $r%u, $r%u, $acr\n",
1291 memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
1292 cris_cc_mask(dc, 0);
1293 dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1294 gen_op_lsll_T0_im(dc->zzsize);
1295 gen_op_addl_T0_T1();
1296 gen_movl_reg_T0[R_ACR]();
1297 return 2;
1300 static unsigned int dec_neg_r(DisasContext *dc)
1302 int size = memsize_zz(dc);
1303 DIS(fprintf (logfile, "neg.%c $r%u, $r%u\n",
1304 memsize_char(size), dc->op1, dc->op2));
1305 cris_cc_mask(dc, CC_MASK_NZVC);
1306 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1307 crisv32_alu_op(dc, CC_OP_NEG, dc->op2, size);
1308 return 2;
1311 static unsigned int dec_btst_r(DisasContext *dc)
1313 DIS(fprintf (logfile, "btst $r%u, $r%u\n",
1314 dc->op1, dc->op2));
1315 cris_cc_mask(dc, CC_MASK_NZ);
1316 dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1317 crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4);
1319 cris_update_cc_op(dc, CC_OP_FLAGS);
1320 gen_op_movl_flags_T0();
1321 dc->flags_live = 1;
1322 return 2;
1325 static unsigned int dec_sub_r(DisasContext *dc)
1327 int size = memsize_zz(dc);
1328 DIS(fprintf (logfile, "sub.%c $r%u, $r%u\n",
1329 memsize_char(size), dc->op1, dc->op2));
1330 cris_cc_mask(dc, CC_MASK_NZVC);
1331 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1332 crisv32_alu_op(dc, CC_OP_SUB, dc->op2, size);
1333 return 2;
1336 /* Zero extension. From size to dword. */
1337 static unsigned int dec_movu_r(DisasContext *dc)
1339 int size = memsize_z(dc);
1340 DIS(fprintf (logfile, "movu.%c $r%u, $r%u\n",
1341 memsize_char(size),
1342 dc->op1, dc->op2));
1344 cris_cc_mask(dc, CC_MASK_NZ);
1345 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0);
1346 crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1347 return 2;
1350 /* Sign extension. From size to dword. */
1351 static unsigned int dec_movs_r(DisasContext *dc)
1353 int size = memsize_z(dc);
1354 DIS(fprintf (logfile, "movs.%c $r%u, $r%u\n",
1355 memsize_char(size),
1356 dc->op1, dc->op2));
1358 cris_cc_mask(dc, CC_MASK_NZ);
1359 gen_movl_T0_reg[dc->op1]();
1360 /* Size can only be qi or hi. */
1361 gen_sext_T1_T0(size);
1362 crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1363 return 2;
1366 /* zero extension. From size to dword. */
1367 static unsigned int dec_addu_r(DisasContext *dc)
1369 int size = memsize_z(dc);
1370 DIS(fprintf (logfile, "addu.%c $r%u, $r%u\n",
1371 memsize_char(size),
1372 dc->op1, dc->op2));
1374 cris_cc_mask(dc, CC_MASK_NZVC);
1375 gen_movl_T0_reg[dc->op1]();
1376 /* Size can only be qi or hi. */
1377 gen_zext_T1_T0(size);
1378 gen_movl_T0_reg[dc->op2]();
1379 crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
1380 return 2;
1382 /* Sign extension. From size to dword. */
1383 static unsigned int dec_adds_r(DisasContext *dc)
1385 int size = memsize_z(dc);
1386 DIS(fprintf (logfile, "adds.%c $r%u, $r%u\n",
1387 memsize_char(size),
1388 dc->op1, dc->op2));
1390 cris_cc_mask(dc, CC_MASK_NZVC);
1391 gen_movl_T0_reg[dc->op1]();
1392 /* Size can only be qi or hi. */
1393 gen_sext_T1_T0(size);
1394 gen_movl_T0_reg[dc->op2]();
1395 crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
1396 return 2;
1399 /* Zero extension. From size to dword. */
1400 static unsigned int dec_subu_r(DisasContext *dc)
1402 int size = memsize_z(dc);
1403 DIS(fprintf (logfile, "subu.%c $r%u, $r%u\n",
1404 memsize_char(size),
1405 dc->op1, dc->op2));
1407 cris_cc_mask(dc, CC_MASK_NZVC);
1408 gen_movl_T0_reg[dc->op1]();
1409 /* Size can only be qi or hi. */
1410 gen_zext_T1_T0(size);
1411 gen_movl_T0_reg[dc->op2]();
1412 crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
1413 return 2;
1416 /* Sign extension. From size to dword. */
1417 static unsigned int dec_subs_r(DisasContext *dc)
1419 int size = memsize_z(dc);
1420 DIS(fprintf (logfile, "subs.%c $r%u, $r%u\n",
1421 memsize_char(size),
1422 dc->op1, dc->op2));
1424 cris_cc_mask(dc, CC_MASK_NZVC);
1425 gen_movl_T0_reg[dc->op1]();
1426 /* Size can only be qi or hi. */
1427 gen_sext_T1_T0(size);
1428 gen_movl_T0_reg[dc->op2]();
1429 crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
1430 return 2;
1433 static unsigned int dec_setclrf(DisasContext *dc)
1435 uint32_t flags;
1436 int set = (~dc->opcode >> 2) & 1;
1438 flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4)
1439 | EXTRACT_FIELD(dc->ir, 0, 3);
1440 DIS(fprintf (logfile, "set=%d flags=%x\n", set, flags));
1441 if (set && flags == 0)
1442 DIS(fprintf (logfile, "nop\n"));
1443 else if (!set && (flags & 0x20))
1444 DIS(fprintf (logfile, "di\n"));
1445 else
1446 DIS(fprintf (logfile, "%sf %x\n",
1447 set ? "set" : "clr",
1448 flags));
1450 if (set && (flags & X_FLAG)) {
1451 dc->flagx_live = 1;
1452 dc->flags_x = 1;
1455 /* Simply decode the flags. */
1456 cris_evaluate_flags (dc);
1457 cris_update_cc_op(dc, CC_OP_FLAGS);
1458 if (set)
1459 gen_op_setf (flags);
1460 else
1461 gen_op_clrf (flags);
1462 dc->flags_live = 1;
1463 return 2;
1466 static unsigned int dec_move_rs(DisasContext *dc)
1468 DIS(fprintf (logfile, "move $r%u, $s%u\n", dc->op1, dc->op2));
1469 cris_cc_mask(dc, 0);
1470 gen_movl_T0_reg[dc->op1]();
1471 gen_op_movl_sreg_T0(dc->op2);
1473 if (dc->op2 == 5) /* srs is checked at runtime. */
1474 gen_op_movl_tlb_lo_T0();
1475 return 2;
1477 static unsigned int dec_move_sr(DisasContext *dc)
1479 DIS(fprintf (logfile, "move $s%u, $r%u\n", dc->op1, dc->op2));
1480 cris_cc_mask(dc, 0);
1481 gen_op_movl_T0_sreg(dc->op1);
1482 gen_op_movl_T1_T0();
1483 crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1484 return 2;
1486 static unsigned int dec_move_rp(DisasContext *dc)
1488 DIS(fprintf (logfile, "move $r%u, $p%u\n", dc->op1, dc->op2));
1489 cris_cc_mask(dc, 0);
1490 gen_movl_T0_reg[dc->op1]();
1491 gen_op_movl_T1_T0();
1492 gen_movl_preg_T0[dc->op2]();
1493 return 2;
1495 static unsigned int dec_move_pr(DisasContext *dc)
1497 DIS(fprintf (logfile, "move $p%u, $r%u\n", dc->op1, dc->op2));
1498 cris_cc_mask(dc, 0);
1499 /* Support register 0 is hardwired to zero.
1500 Treat it specially. */
1501 if (dc->op2 == 0)
1502 gen_op_movl_T1_im(0);
1503 else {
1504 gen_movl_T0_preg[dc->op2]();
1505 gen_op_movl_T1_T0();
1507 crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, preg_sizes[dc->op2]);
1508 return 2;
1511 static unsigned int dec_move_mr(DisasContext *dc)
1513 int memsize = memsize_zz(dc);
1514 int insn_len;
1515 DIS(fprintf (logfile, "move.%c [$r%u%s, $r%u\n",
1516 memsize_char(memsize),
1517 dc->op1, dc->postinc ? "+]" : "]",
1518 dc->op2));
1520 cris_cc_mask(dc, CC_MASK_NZ);
1521 insn_len = dec_prep_alu_m(dc, 0, memsize);
1522 crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, memsize);
1523 do_postinc(dc, memsize);
1524 return insn_len;
1527 static unsigned int dec_movs_m(DisasContext *dc)
1529 int memsize = memsize_z(dc);
1530 int insn_len;
1531 DIS(fprintf (logfile, "movs.%c [$r%u%s, $r%u\n",
1532 memsize_char(memsize),
1533 dc->op1, dc->postinc ? "+]" : "]",
1534 dc->op2));
1536 /* sign extend. */
1537 cris_cc_mask(dc, CC_MASK_NZ);
1538 insn_len = dec_prep_alu_m(dc, 1, memsize);
1539 crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1540 do_postinc(dc, memsize);
1541 return insn_len;
1544 static unsigned int dec_addu_m(DisasContext *dc)
1546 int memsize = memsize_z(dc);
1547 int insn_len;
1548 DIS(fprintf (logfile, "addu.%c [$r%u%s, $r%u\n",
1549 memsize_char(memsize),
1550 dc->op1, dc->postinc ? "+]" : "]",
1551 dc->op2));
1553 /* sign extend. */
1554 cris_cc_mask(dc, CC_MASK_NZVC);
1555 insn_len = dec_prep_alu_m(dc, 0, memsize);
1556 crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
1557 do_postinc(dc, memsize);
1558 return insn_len;
1561 static unsigned int dec_adds_m(DisasContext *dc)
1563 int memsize = memsize_z(dc);
1564 int insn_len;
1565 DIS(fprintf (logfile, "adds.%c [$r%u%s, $r%u\n",
1566 memsize_char(memsize),
1567 dc->op1, dc->postinc ? "+]" : "]",
1568 dc->op2));
1570 /* sign extend. */
1571 cris_cc_mask(dc, CC_MASK_NZVC);
1572 insn_len = dec_prep_alu_m(dc, 1, memsize);
1573 crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
1574 do_postinc(dc, memsize);
1575 return insn_len;
1578 static unsigned int dec_subu_m(DisasContext *dc)
1580 int memsize = memsize_z(dc);
1581 int insn_len;
1582 DIS(fprintf (logfile, "subu.%c [$r%u%s, $r%u\n",
1583 memsize_char(memsize),
1584 dc->op1, dc->postinc ? "+]" : "]",
1585 dc->op2));
1587 /* sign extend. */
1588 cris_cc_mask(dc, CC_MASK_NZVC);
1589 insn_len = dec_prep_alu_m(dc, 0, memsize);
1590 crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
1591 do_postinc(dc, memsize);
1592 return insn_len;
1595 static unsigned int dec_subs_m(DisasContext *dc)
1597 int memsize = memsize_z(dc);
1598 int insn_len;
1599 DIS(fprintf (logfile, "subs.%c [$r%u%s, $r%u\n",
1600 memsize_char(memsize),
1601 dc->op1, dc->postinc ? "+]" : "]",
1602 dc->op2));
1604 /* sign extend. */
1605 cris_cc_mask(dc, CC_MASK_NZVC);
1606 insn_len = dec_prep_alu_m(dc, 1, memsize);
1607 crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
1608 do_postinc(dc, memsize);
1609 return insn_len;
1612 static unsigned int dec_movu_m(DisasContext *dc)
1614 int memsize = memsize_z(dc);
1615 int insn_len;
1617 DIS(fprintf (logfile, "movu.%c [$r%u%s, $r%u\n",
1618 memsize_char(memsize),
1619 dc->op1, dc->postinc ? "+]" : "]",
1620 dc->op2));
1622 cris_cc_mask(dc, CC_MASK_NZ);
1623 insn_len = dec_prep_alu_m(dc, 0, memsize);
1624 crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1625 do_postinc(dc, memsize);
1626 return insn_len;
1629 static unsigned int dec_cmpu_m(DisasContext *dc)
1631 int memsize = memsize_z(dc);
1632 int insn_len;
1633 DIS(fprintf (logfile, "cmpu.%c [$r%u%s, $r%u\n",
1634 memsize_char(memsize),
1635 dc->op1, dc->postinc ? "+]" : "]",
1636 dc->op2));
1638 cris_cc_mask(dc, CC_MASK_NZVC);
1639 insn_len = dec_prep_alu_m(dc, 0, memsize);
1640 crisv32_alu_op(dc, CC_OP_CMP, dc->op2, 4);
1641 do_postinc(dc, memsize);
1642 return insn_len;
1645 static unsigned int dec_cmps_m(DisasContext *dc)
1647 int memsize = memsize_z(dc);
1648 int insn_len;
1649 DIS(fprintf (logfile, "cmps.%c [$r%u%s, $r%u\n",
1650 memsize_char(memsize),
1651 dc->op1, dc->postinc ? "+]" : "]",
1652 dc->op2));
1654 cris_cc_mask(dc, CC_MASK_NZVC);
1655 insn_len = dec_prep_alu_m(dc, 1, memsize);
1656 crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc));
1657 do_postinc(dc, memsize);
1658 return insn_len;
1661 static unsigned int dec_cmp_m(DisasContext *dc)
1663 int memsize = memsize_zz(dc);
1664 int insn_len;
1665 DIS(fprintf (logfile, "cmp.%c [$r%u%s, $r%u\n",
1666 memsize_char(memsize),
1667 dc->op1, dc->postinc ? "+]" : "]",
1668 dc->op2));
1670 cris_cc_mask(dc, CC_MASK_NZVC);
1671 insn_len = dec_prep_alu_m(dc, 0, memsize);
1672 crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc));
1673 do_postinc(dc, memsize);
1674 return insn_len;
1677 static unsigned int dec_test_m(DisasContext *dc)
1679 int memsize = memsize_zz(dc);
1680 int insn_len;
1681 DIS(fprintf (logfile, "test.%d [$r%u%s] op2=%x\n",
1682 memsize_char(memsize),
1683 dc->op1, dc->postinc ? "+]" : "]",
1684 dc->op2));
1686 cris_cc_mask(dc, CC_MASK_NZ);
1687 gen_op_clrf(3);
1688 insn_len = dec_prep_alu_m(dc, 0, memsize);
1689 gen_op_swp_T0_T1();
1690 gen_op_movl_T1_im(0);
1691 crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc));
1692 do_postinc(dc, memsize);
1693 return insn_len;
1696 static unsigned int dec_and_m(DisasContext *dc)
1698 int memsize = memsize_zz(dc);
1699 int insn_len;
1700 DIS(fprintf (logfile, "and.%d [$r%u%s, $r%u\n",
1701 memsize_char(memsize),
1702 dc->op1, dc->postinc ? "+]" : "]",
1703 dc->op2));
1705 cris_cc_mask(dc, CC_MASK_NZ);
1706 insn_len = dec_prep_alu_m(dc, 0, memsize);
1707 crisv32_alu_op(dc, CC_OP_AND, dc->op2, memsize_zz(dc));
1708 do_postinc(dc, memsize);
1709 return insn_len;
1712 static unsigned int dec_add_m(DisasContext *dc)
1714 int memsize = memsize_zz(dc);
1715 int insn_len;
1716 DIS(fprintf (logfile, "add.%d [$r%u%s, $r%u\n",
1717 memsize_char(memsize),
1718 dc->op1, dc->postinc ? "+]" : "]",
1719 dc->op2));
1721 cris_cc_mask(dc, CC_MASK_NZVC);
1722 insn_len = dec_prep_alu_m(dc, 0, memsize);
1723 crisv32_alu_op(dc, CC_OP_ADD, dc->op2, memsize_zz(dc));
1724 do_postinc(dc, memsize);
1725 return insn_len;
1728 static unsigned int dec_addo_m(DisasContext *dc)
1730 int memsize = memsize_zz(dc);
1731 int insn_len;
1732 DIS(fprintf (logfile, "add.%d [$r%u%s, $r%u\n",
1733 memsize_char(memsize),
1734 dc->op1, dc->postinc ? "+]" : "]",
1735 dc->op2));
1737 cris_cc_mask(dc, 0);
1738 insn_len = dec_prep_alu_m(dc, 1, memsize);
1739 crisv32_alu_op(dc, CC_OP_ADD, R_ACR, 4);
1740 do_postinc(dc, memsize);
1741 return insn_len;
1744 static unsigned int dec_bound_m(DisasContext *dc)
1746 int memsize = memsize_zz(dc);
1747 int insn_len;
1748 DIS(fprintf (logfile, "bound.%d [$r%u%s, $r%u\n",
1749 memsize_char(memsize),
1750 dc->op1, dc->postinc ? "+]" : "]",
1751 dc->op2));
1753 cris_cc_mask(dc, CC_MASK_NZ);
1754 insn_len = dec_prep_alu_m(dc, 0, memsize);
1755 crisv32_alu_op(dc, CC_OP_BOUND, dc->op2, 4);
1756 do_postinc(dc, memsize);
1757 return insn_len;
1760 static unsigned int dec_addc_mr(DisasContext *dc)
1762 int insn_len = 2;
1763 DIS(fprintf (logfile, "addc [$r%u%s, $r%u\n",
1764 dc->op1, dc->postinc ? "+]" : "]",
1765 dc->op2));
1767 cris_evaluate_flags(dc);
1768 cris_cc_mask(dc, CC_MASK_NZVC);
1769 insn_len = dec_prep_alu_m(dc, 0, 4);
1770 crisv32_alu_op(dc, CC_OP_ADDC, dc->op2, 4);
1771 do_postinc(dc, 4);
1772 return insn_len;
1775 static unsigned int dec_sub_m(DisasContext *dc)
1777 int memsize = memsize_zz(dc);
1778 int insn_len;
1779 DIS(fprintf (logfile, "sub.%c [$r%u%s, $r%u ir=%x zz=%x\n",
1780 memsize_char(memsize),
1781 dc->op1, dc->postinc ? "+]" : "]",
1782 dc->op2, dc->ir, dc->zzsize));
1784 cris_cc_mask(dc, CC_MASK_NZVC);
1785 insn_len = dec_prep_alu_m(dc, 0, memsize);
1786 crisv32_alu_op(dc, CC_OP_SUB, dc->op2, memsize);
1787 do_postinc(dc, memsize);
1788 return insn_len;
1791 static unsigned int dec_or_m(DisasContext *dc)
1793 int memsize = memsize_zz(dc);
1794 int insn_len;
1795 DIS(fprintf (logfile, "or.%d [$r%u%s, $r%u pc=%x\n",
1796 memsize_char(memsize),
1797 dc->op1, dc->postinc ? "+]" : "]",
1798 dc->op2, dc->pc));
1800 cris_cc_mask(dc, CC_MASK_NZ);
1801 insn_len = dec_prep_alu_m(dc, 0, memsize);
1802 crisv32_alu_op(dc, CC_OP_OR, dc->op2, memsize_zz(dc));
1803 do_postinc(dc, memsize);
1804 return insn_len;
1807 static unsigned int dec_move_mp(DisasContext *dc)
1809 int memsize = memsize_zz(dc);
1810 int insn_len = 2;
1812 DIS(fprintf (logfile, "move.%c [$r%u%s, $p%u\n",
1813 memsize_char(memsize),
1814 dc->op1,
1815 dc->postinc ? "+]" : "]",
1816 dc->op2));
1818 cris_cc_mask(dc, 0);
1819 insn_len = dec_prep_alu_m(dc, 0, memsize);
1820 gen_op_movl_T0_T1();
1821 gen_movl_preg_T0[dc->op2]();
1823 do_postinc(dc, memsize);
1824 return insn_len;
1827 static unsigned int dec_move_pm(DisasContext *dc)
1829 int memsize;
1831 memsize = preg_sizes[dc->op2];
1833 DIS(fprintf (logfile, "move.%c $p%u, [$r%u%s\n",
1834 memsize_char(memsize),
1835 dc->op2, dc->op1, dc->postinc ? "+]" : "]"));
1837 cris_cc_mask(dc, 0);
1838 /* prepare store. Address in T0, value in T1. */
1839 /* Support register 0 is hardwired to zero.
1840 Treat it specially. */
1841 if (dc->op2 == 0)
1842 gen_op_movl_T1_im(0);
1843 else
1845 gen_movl_T0_preg[dc->op2]();
1846 gen_op_movl_T1_T0();
1848 gen_movl_T0_reg[dc->op1]();
1849 gen_store_T0_T1(dc, memsize);
1850 if (dc->postinc)
1852 gen_op_addl_T0_im(memsize);
1853 gen_movl_reg_T0[dc->op1]();
1855 return 2;
1858 static unsigned int dec_movem_mr(DisasContext *dc)
1860 int i;
1862 DIS(fprintf (logfile, "movem [$r%u%s, $r%u\n", dc->op1,
1863 dc->postinc ? "+]" : "]", dc->op2));
1865 cris_cc_mask(dc, 0);
1866 /* fetch the address into T1. */
1867 gen_movl_T0_reg[dc->op1]();
1868 gen_op_movl_T1_T0();
1869 for (i = 0; i <= dc->op2; i++) {
1870 /* Perform the load onto regnum i. Always dword wide. */
1871 gen_load_T0_T0(dc, 4, 0);
1872 gen_movl_reg_T0[i]();
1873 /* Update the address. */
1874 gen_op_addl_T1_im(4);
1875 gen_op_movl_T0_T1();
1877 if (dc->postinc) {
1878 /* writeback the updated pointer value. */
1879 gen_movl_reg_T0[dc->op1]();
1881 return 2;
1884 static unsigned int dec_movem_rm(DisasContext *dc)
1886 int i;
1888 DIS(fprintf (logfile, "movem $r%u, [$r%u%s\n", dc->op2, dc->op1,
1889 dc->postinc ? "+]" : "]"));
1891 cris_cc_mask(dc, 0);
1892 for (i = 0; i <= dc->op2; i++) {
1893 /* Fetch register i into T1. */
1894 gen_movl_T0_reg[i]();
1895 gen_op_movl_T1_T0();
1897 /* Fetch the address into T0. */
1898 gen_movl_T0_reg[dc->op1]();
1899 /* Displace it. */
1900 gen_op_addl_T0_im(i * 4);
1902 /* Perform the store. */
1903 gen_store_T0_T1(dc, 4);
1905 if (dc->postinc) {
1906 /* Update the address. */
1907 gen_op_addl_T0_im(4);
1908 /* writeback the updated pointer value. */
1909 gen_movl_reg_T0[dc->op1]();
1911 return 2;
1914 static unsigned int dec_move_rm(DisasContext *dc)
1916 int memsize;
1918 memsize = memsize_zz(dc);
1920 DIS(fprintf (logfile, "move.%d $r%u, [$r%u]\n",
1921 memsize, dc->op2, dc->op1));
1923 cris_cc_mask(dc, 0);
1924 /* prepare store. */
1925 gen_movl_T0_reg[dc->op2]();
1926 gen_op_movl_T1_T0();
1927 gen_movl_T0_reg[dc->op1]();
1928 gen_store_T0_T1(dc, memsize);
1929 if (dc->postinc)
1931 gen_op_addl_T0_im(memsize);
1932 gen_movl_reg_T0[dc->op1]();
1934 return 2;
1938 static unsigned int dec_lapcq(DisasContext *dc)
1940 DIS(fprintf (logfile, "lapcq %x, $r%u\n",
1941 dc->pc + dc->op1*2, dc->op2));
1942 cris_cc_mask(dc, 0);
1943 gen_op_movl_T1_im(dc->pc + dc->op1*2);
1944 crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1945 return 2;
1948 static unsigned int dec_lapc_im(DisasContext *dc)
1950 unsigned int rd;
1951 int32_t imm;
1952 int insn_len = 6;
1954 rd = dc->op2;
1956 cris_cc_mask(dc, 0);
1957 imm = ldl_code(dc->pc + 2);
1958 DIS(fprintf (logfile, "lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2));
1959 gen_op_movl_T0_im (dc->pc + imm);
1960 gen_movl_reg_T0[rd] ();
1961 return insn_len;
1964 /* Jump to special reg. */
1965 static unsigned int dec_jump_p(DisasContext *dc)
1967 DIS(fprintf (logfile, "jump $p%u\n", dc->op2));
1968 cris_cc_mask(dc, 0);
1969 /* Store the return address in Pd. */
1970 gen_movl_T0_preg[dc->op2]();
1971 gen_op_movl_btarget_T0();
1972 cris_prepare_dyn_jmp(dc);
1973 return 2;
1976 /* Jump and save. */
1977 static unsigned int dec_jas_r(DisasContext *dc)
1979 DIS(fprintf (logfile, "jas $r%u, $p%u\n", dc->op1, dc->op2));
1980 cris_cc_mask(dc, 0);
1981 /* Stor the return address in Pd. */
1982 gen_movl_T0_reg[dc->op1]();
1983 gen_op_movl_btarget_T0();
1984 gen_op_movl_T0_im(dc->pc + 4);
1985 gen_movl_preg_T0[dc->op2]();
1986 cris_prepare_dyn_jmp(dc);
1987 return 2;
1990 static unsigned int dec_jas_im(DisasContext *dc)
1992 uint32_t imm;
1994 imm = ldl_code(dc->pc + 2);
1996 DIS(fprintf (logfile, "jas 0x%x\n", imm));
1997 cris_cc_mask(dc, 0);
1998 /* Stor the return address in Pd. */
1999 gen_op_movl_T0_im(imm);
2000 gen_op_movl_btarget_T0();
2001 gen_op_movl_T0_im(dc->pc + 8);
2002 gen_movl_preg_T0[dc->op2]();
2003 cris_prepare_dyn_jmp(dc);
2004 return 6;
2007 static unsigned int dec_jasc_im(DisasContext *dc)
2009 uint32_t imm;
2011 imm = ldl_code(dc->pc + 2);
2013 DIS(fprintf (logfile, "jasc 0x%x\n", imm));
2014 cris_cc_mask(dc, 0);
2015 /* Stor the return address in Pd. */
2016 gen_op_movl_T0_im(imm);
2017 gen_op_movl_btarget_T0();
2018 gen_op_movl_T0_im(dc->pc + 8 + 4);
2019 gen_movl_preg_T0[dc->op2]();
2020 cris_prepare_dyn_jmp(dc);
2021 return 6;
2024 static unsigned int dec_jasc_r(DisasContext *dc)
2026 DIS(fprintf (logfile, "jasc_r $r%u, $p%u\n", dc->op1, dc->op2));
2027 cris_cc_mask(dc, 0);
2028 /* Stor the return address in Pd. */
2029 gen_movl_T0_reg[dc->op1]();
2030 gen_op_movl_btarget_T0();
2031 gen_op_movl_T0_im(dc->pc + 4 + 4);
2032 gen_movl_preg_T0[dc->op2]();
2033 cris_prepare_dyn_jmp(dc);
2034 return 2;
2037 static unsigned int dec_bcc_im(DisasContext *dc)
2039 int32_t offset;
2040 uint32_t cond = dc->op2;
2042 offset = ldl_code(dc->pc + 2);
2043 offset = sign_extend(offset, 15);
2045 DIS(fprintf (logfile, "b%s %d pc=%x dst=%x\n",
2046 cc_name(cond), offset,
2047 dc->pc, dc->pc + offset));
2049 cris_cc_mask(dc, 0);
2050 /* op2 holds the condition-code. */
2051 cris_prepare_cc_branch (dc, offset, cond);
2052 return 4;
2055 static unsigned int dec_bas_im(DisasContext *dc)
2057 int32_t simm;
2060 simm = ldl_code(dc->pc + 2);
2062 DIS(fprintf (logfile, "bas 0x%x, $p%u\n", dc->pc + simm, dc->op2));
2063 cris_cc_mask(dc, 0);
2064 /* Stor the return address in Pd. */
2065 gen_op_movl_T0_im(dc->pc + simm);
2066 gen_op_movl_btarget_T0();
2067 gen_op_movl_T0_im(dc->pc + 8);
2068 gen_movl_preg_T0[dc->op2]();
2069 cris_prepare_dyn_jmp(dc);
2070 return 6;
2073 static unsigned int dec_basc_im(DisasContext *dc)
2075 int32_t simm;
2076 simm = ldl_code(dc->pc + 2);
2078 DIS(fprintf (logfile, "basc 0x%x, $p%u\n", dc->pc + simm, dc->op2));
2079 cris_cc_mask(dc, 0);
2080 /* Stor the return address in Pd. */
2081 gen_op_movl_T0_im(dc->pc + simm);
2082 gen_op_movl_btarget_T0();
2083 gen_op_movl_T0_im(dc->pc + 12);
2084 gen_movl_preg_T0[dc->op2]();
2085 cris_prepare_dyn_jmp(dc);
2086 return 6;
2089 static unsigned int dec_rfe_etc(DisasContext *dc)
2091 DIS(fprintf (logfile, "rfe_etc opc=%x pc=0x%x op1=%d op2=%d\n",
2092 dc->opcode, dc->pc, dc->op1, dc->op2));
2094 cris_cc_mask(dc, 0);
2096 if (dc->op2 == 15) /* ignore halt. */
2097 goto done;
2099 switch (dc->op2 & 7) {
2100 case 2:
2101 /* rfe. */
2102 cris_evaluate_flags(dc);
2103 gen_op_ccs_rshift();
2104 break;
2105 case 5:
2106 /* rfn. */
2107 BUG();
2108 break;
2109 case 6:
2110 /* break. */
2111 gen_op_movl_T0_im(dc->pc);
2112 gen_op_movl_pc_T0();
2113 /* Breaks start at 16 in the exception vector. */
2114 gen_op_break_im(dc->op1 + 16);
2115 break;
2116 default:
2117 printf ("op2=%x\n", dc->op2);
2118 BUG();
2119 break;
2122 done:
2123 return 2;
2126 static unsigned int dec_ftag_fidx_d_m(DisasContext *dc)
2128 /* Ignore D-cache flushes. */
2129 return 2;
2132 static unsigned int dec_ftag_fidx_i_m(DisasContext *dc)
2134 /* Ignore I-cache flushes. */
2135 return 2;
2138 static unsigned int dec_null(DisasContext *dc)
2140 printf ("unknown insn pc=%x opc=%x op1=%x op2=%x\n",
2141 dc->pc, dc->opcode, dc->op1, dc->op2);
2142 fflush(NULL);
2143 BUG();
2144 return 2;
2147 struct decoder_info {
2148 struct {
2149 uint32_t bits;
2150 uint32_t mask;
2152 unsigned int (*dec)(DisasContext *dc);
2153 } decinfo[] = {
2154 /* Order matters here. */
2155 {DEC_MOVEQ, dec_moveq},
2156 {DEC_BTSTQ, dec_btstq},
2157 {DEC_CMPQ, dec_cmpq},
2158 {DEC_ADDOQ, dec_addoq},
2159 {DEC_ADDQ, dec_addq},
2160 {DEC_SUBQ, dec_subq},
2161 {DEC_ANDQ, dec_andq},
2162 {DEC_ORQ, dec_orq},
2163 {DEC_ASRQ, dec_asrq},
2164 {DEC_LSLQ, dec_lslq},
2165 {DEC_LSRQ, dec_lsrq},
2166 {DEC_BCCQ, dec_bccq},
2168 {DEC_BCC_IM, dec_bcc_im},
2169 {DEC_JAS_IM, dec_jas_im},
2170 {DEC_JAS_R, dec_jas_r},
2171 {DEC_JASC_IM, dec_jasc_im},
2172 {DEC_JASC_R, dec_jasc_r},
2173 {DEC_BAS_IM, dec_bas_im},
2174 {DEC_BASC_IM, dec_basc_im},
2175 {DEC_JUMP_P, dec_jump_p},
2176 {DEC_LAPC_IM, dec_lapc_im},
2177 {DEC_LAPCQ, dec_lapcq},
2179 {DEC_RFE_ETC, dec_rfe_etc},
2180 {DEC_ADDC_MR, dec_addc_mr},
2182 {DEC_MOVE_MP, dec_move_mp},
2183 {DEC_MOVE_PM, dec_move_pm},
2184 {DEC_MOVEM_MR, dec_movem_mr},
2185 {DEC_MOVEM_RM, dec_movem_rm},
2186 {DEC_MOVE_PR, dec_move_pr},
2187 {DEC_SCC_R, dec_scc_r},
2188 {DEC_SETF, dec_setclrf},
2189 {DEC_CLEARF, dec_setclrf},
2191 {DEC_MOVE_SR, dec_move_sr},
2192 {DEC_MOVE_RP, dec_move_rp},
2193 {DEC_SWAP_R, dec_swap_r},
2194 {DEC_ABS_R, dec_abs_r},
2195 {DEC_LZ_R, dec_lz_r},
2196 {DEC_MOVE_RS, dec_move_rs},
2197 {DEC_BTST_R, dec_btst_r},
2198 {DEC_ADDC_R, dec_addc_r},
2200 {DEC_DSTEP_R, dec_dstep_r},
2201 {DEC_XOR_R, dec_xor_r},
2202 {DEC_MCP_R, dec_mcp_r},
2203 {DEC_CMP_R, dec_cmp_r},
2205 {DEC_ADDI_R, dec_addi_r},
2206 {DEC_ADDI_ACR, dec_addi_acr},
2208 {DEC_ADD_R, dec_add_r},
2209 {DEC_SUB_R, dec_sub_r},
2211 {DEC_ADDU_R, dec_addu_r},
2212 {DEC_ADDS_R, dec_adds_r},
2213 {DEC_SUBU_R, dec_subu_r},
2214 {DEC_SUBS_R, dec_subs_r},
2215 {DEC_LSL_R, dec_lsl_r},
2217 {DEC_AND_R, dec_and_r},
2218 {DEC_OR_R, dec_or_r},
2219 {DEC_BOUND_R, dec_bound_r},
2220 {DEC_ASR_R, dec_asr_r},
2221 {DEC_LSR_R, dec_lsr_r},
2223 {DEC_MOVU_R, dec_movu_r},
2224 {DEC_MOVS_R, dec_movs_r},
2225 {DEC_NEG_R, dec_neg_r},
2226 {DEC_MOVE_R, dec_move_r},
2228 {DEC_FTAG_FIDX_I_M, dec_ftag_fidx_i_m},
2229 {DEC_FTAG_FIDX_D_M, dec_ftag_fidx_d_m},
2231 {DEC_MULS_R, dec_muls_r},
2232 {DEC_MULU_R, dec_mulu_r},
2234 {DEC_ADDU_M, dec_addu_m},
2235 {DEC_ADDS_M, dec_adds_m},
2236 {DEC_SUBU_M, dec_subu_m},
2237 {DEC_SUBS_M, dec_subs_m},
2239 {DEC_CMPU_M, dec_cmpu_m},
2240 {DEC_CMPS_M, dec_cmps_m},
2241 {DEC_MOVU_M, dec_movu_m},
2242 {DEC_MOVS_M, dec_movs_m},
2244 {DEC_CMP_M, dec_cmp_m},
2245 {DEC_ADDO_M, dec_addo_m},
2246 {DEC_BOUND_M, dec_bound_m},
2247 {DEC_ADD_M, dec_add_m},
2248 {DEC_SUB_M, dec_sub_m},
2249 {DEC_AND_M, dec_and_m},
2250 {DEC_OR_M, dec_or_m},
2251 {DEC_MOVE_RM, dec_move_rm},
2252 {DEC_TEST_M, dec_test_m},
2253 {DEC_MOVE_MR, dec_move_mr},
2255 {{0, 0}, dec_null}
2258 static inline unsigned int
2259 cris_decoder(DisasContext *dc)
2261 unsigned int insn_len = 2;
2262 uint32_t tmp;
2263 int i;
2265 /* Load a halfword onto the instruction register. */
2266 tmp = ldl_code(dc->pc);
2267 dc->ir = tmp & 0xffff;
2269 /* Now decode it. */
2270 dc->opcode = EXTRACT_FIELD(dc->ir, 4, 11);
2271 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 3);
2272 dc->op2 = EXTRACT_FIELD(dc->ir, 12, 15);
2273 dc->zsize = EXTRACT_FIELD(dc->ir, 4, 4);
2274 dc->zzsize = EXTRACT_FIELD(dc->ir, 4, 5);
2275 dc->postinc = EXTRACT_FIELD(dc->ir, 10, 10);
2277 /* Large switch for all insns. */
2278 for (i = 0; i < sizeof decinfo / sizeof decinfo[0]; i++) {
2279 if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits)
2281 insn_len = decinfo[i].dec(dc);
2282 break;
2286 return insn_len;
2289 static void check_breakpoint(CPUState *env, DisasContext *dc)
2291 int j;
2292 if (env->nb_breakpoints > 0) {
2293 for(j = 0; j < env->nb_breakpoints; j++) {
2294 if (env->breakpoints[j] == dc->pc) {
2295 cris_evaluate_flags (dc);
2296 gen_op_movl_T0_im((long)dc->pc);
2297 gen_op_movl_pc_T0();
2298 gen_op_debug();
2299 dc->is_jmp = DISAS_UPDATE;
2306 /* generate intermediate code for basic block 'tb'. */
2307 struct DisasContext ctx;
2308 static int
2309 gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
2310 int search_pc)
2312 uint16_t *gen_opc_end;
2313 uint32_t pc_start;
2314 unsigned int insn_len;
2315 int j, lj;
2316 struct DisasContext *dc = &ctx;
2317 uint32_t next_page_start;
2319 pc_start = tb->pc;
2320 dc->env = env;
2321 dc->tb = tb;
2323 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2325 dc->is_jmp = DISAS_NEXT;
2326 dc->pc = pc_start;
2327 dc->singlestep_enabled = env->singlestep_enabled;
2328 dc->flagx_live = 0;
2329 dc->flags_x = 0;
2330 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
2331 lj = -1;
2334 check_breakpoint(env, dc);
2335 if (dc->is_jmp == DISAS_JUMP)
2336 goto done;
2338 if (search_pc) {
2339 j = gen_opc_ptr - gen_opc_buf;
2340 if (lj < j) {
2341 lj++;
2342 while (lj < j)
2343 gen_opc_instr_start[lj++] = 0;
2345 gen_opc_pc[lj] = dc->pc;
2346 gen_opc_instr_start[lj] = 1;
2349 insn_len = cris_decoder(dc);
2350 STATS(gen_op_exec_insn());
2351 dc->pc += insn_len;
2352 if (!dc->flagx_live
2353 || (dc->flagx_live &&
2354 !(dc->cc_op == CC_OP_FLAGS && dc->flags_x))) {
2355 gen_movl_T0_preg[PR_CCS]();
2356 gen_op_andl_T0_im(~X_FLAG);
2357 gen_movl_preg_T0[PR_CCS]();
2358 dc->flagx_live = 1;
2359 dc->flags_x = 0;
2362 /* Check for delayed branches here. If we do it before
2363 actually genereating any host code, the simulator will just
2364 loop doing nothing for on this program location. */
2365 if (dc->delayed_branch) {
2366 dc->delayed_branch--;
2367 if (dc->delayed_branch == 0)
2369 if (dc->bcc == CC_A) {
2370 gen_op_jmp1 ();
2371 dc->is_jmp = DISAS_UPDATE;
2373 else {
2374 /* Conditional jmp. */
2375 gen_op_cc_jmp (dc->delayed_pc, dc->pc);
2376 dc->is_jmp = DISAS_UPDATE;
2381 if (env->singlestep_enabled)
2382 break;
2383 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end
2384 && dc->pc < next_page_start);
2386 if (!dc->is_jmp) {
2387 gen_op_movl_T0_im((long)dc->pc);
2388 gen_op_movl_pc_T0();
2391 cris_evaluate_flags (dc);
2392 done:
2393 if (__builtin_expect(env->singlestep_enabled, 0)) {
2394 gen_op_debug();
2395 } else {
2396 switch(dc->is_jmp) {
2397 case DISAS_NEXT:
2398 gen_goto_tb(dc, 1, dc->pc);
2399 break;
2400 default:
2401 case DISAS_JUMP:
2402 case DISAS_UPDATE:
2403 /* indicate that the hash table must be used
2404 to find the next TB */
2405 tcg_gen_exit_tb(0);
2406 break;
2407 case DISAS_TB_JUMP:
2408 /* nothing more to generate */
2409 break;
2412 *gen_opc_ptr = INDEX_op_end;
2413 if (search_pc) {
2414 j = gen_opc_ptr - gen_opc_buf;
2415 lj++;
2416 while (lj <= j)
2417 gen_opc_instr_start[lj++] = 0;
2418 } else {
2419 tb->size = dc->pc - pc_start;
2422 #ifdef DEBUG_DISAS
2423 if (loglevel & CPU_LOG_TB_IN_ASM) {
2424 fprintf(logfile, "--------------\n");
2425 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2426 target_disas(logfile, pc_start, dc->pc + 4 - pc_start, 0);
2427 fprintf(logfile, "\n");
2429 #endif
2430 return 0;
2433 int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
2435 return gen_intermediate_code_internal(env, tb, 0);
2438 int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
2440 return gen_intermediate_code_internal(env, tb, 1);
2443 void cpu_dump_state (CPUState *env, FILE *f,
2444 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2445 int flags)
2447 int i;
2448 uint32_t srs;
2450 if (!env || !f)
2451 return;
2453 cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
2454 "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n"
2455 "debug=%x %x %x\n",
2456 env->pc, env->pregs[PR_CCS], env->btaken, env->btarget,
2457 env->cc_op,
2458 env->cc_src, env->cc_dest, env->cc_result, env->cc_mask,
2459 env->debug1, env->debug2, env->debug3);
2461 for (i = 0; i < 16; i++) {
2462 cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
2463 if ((i + 1) % 4 == 0)
2464 cpu_fprintf(f, "\n");
2466 cpu_fprintf(f, "\nspecial regs:\n");
2467 for (i = 0; i < 16; i++) {
2468 cpu_fprintf(f, "p%2.2d=%8.8x ", i, env->pregs[i]);
2469 if ((i + 1) % 4 == 0)
2470 cpu_fprintf(f, "\n");
2472 srs = env->pregs[PR_SRS];
2473 cpu_fprintf(f, "\nsupport function regs bank %d:\n", srs);
2474 if (srs < 256) {
2475 for (i = 0; i < 16; i++) {
2476 cpu_fprintf(f, "s%2.2d=%8.8x ",
2477 i, env->sregs[srs][i]);
2478 if ((i + 1) % 4 == 0)
2479 cpu_fprintf(f, "\n");
2482 cpu_fprintf(f, "\n\n");
2486 CPUCRISState *cpu_cris_init (const char *cpu_model)
2488 CPUCRISState *env;
2490 env = qemu_mallocz(sizeof(CPUCRISState));
2491 if (!env)
2492 return NULL;
2493 cpu_exec_init(env);
2494 cpu_reset(env);
2495 return env;
2498 void cpu_reset (CPUCRISState *env)
2500 memset(env, 0, offsetof(CPUCRISState, breakpoints));
2501 tlb_flush(env, 1);