|
|
1.1 root 1: /*
2: * CRIS emulation for qemu: main translation routines.
3: *
4: * Copyright (c) 2007 AXIS Communications AB
5: * Written by Edgar E. Iglesias.
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:
22: /*
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
26: *
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.
30: *
31: * For example the following CRIS code:
32: * add.d [$r0], $r1
33: *
34: * translates into:
35: *
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
39: *
40: * The actual names for the micro-code generators vary but the example
41: * illustrates the point.
42: */
43:
44: #include <stdarg.h>
45: #include <stdlib.h>
46: #include <stdio.h>
47: #include <string.h>
48: #include <inttypes.h>
49: #include <assert.h>
50:
51: #include "cpu.h"
52: #include "exec-all.h"
53: #include "disas.h"
54: #include "crisv32-decode.h"
55:
56: #define CRIS_STATS 0
57: #if CRIS_STATS
58: #define STATS(x) x
59: #else
60: #define STATS(x)
61: #endif
62:
63: #define DISAS_CRIS 0
64: #if DISAS_CRIS
65: #define DIS(x) x
66: #else
67: #define DIS(x)
68: #endif
69:
70: #ifdef USE_DIRECT_JUMP
71: #define TBPARAM(x)
72: #else
73: #define TBPARAM(x) (long)(x)
74: #endif
75:
76: #define BUG() (gen_BUG(dc, __FILE__, __LINE__))
77: #define BUG_ON(x) ({if (x) BUG();})
78:
79: /* Used by the decoder. */
80: #define EXTRACT_FIELD(src, start, end) \
81: (((src) >> start) & ((1 << (end - start + 1)) - 1))
82:
83: #define CC_MASK_NZ 0xc
84: #define CC_MASK_NZV 0xe
85: #define CC_MASK_NZVC 0xf
86: #define CC_MASK_RNZV 0x10e
87:
88: static uint16_t *gen_opc_ptr;
89: static uint32_t *gen_opparam_ptr;
90:
91: enum {
92: #define DEF(s, n, copy_size) INDEX_op_ ## s,
93: #include "opc.h"
94: #undef DEF
95: NB_OPS,
96: };
97: #include "gen-op.h"
98:
99: /* This is the state at translation time. */
100: typedef struct DisasContext {
101: CPUState *env;
102: target_ulong pc, insn_pc;
103:
104: /* Decoder. */
105: uint32_t ir;
106: uint32_t opcode;
107: unsigned int op1;
108: unsigned int op2;
109: unsigned int zsize, zzsize;
110: unsigned int mode;
111: unsigned int postinc;
112:
113:
114: struct
115: {
116: int op;
117: int size;
118: unsigned int mask;
119: } cc_state[3];
120: int cc_i;
121:
122: int update_cc;
123: int cc_op;
124: int cc_size;
125: uint32_t cc_mask;
126: int flags_live;
127: int flagx_live;
128: int flags_x;
129: uint32_t tb_entry_flags;
130:
131: int memidx; /* user or kernel mode. */
132: int is_jmp;
133: int dyn_jmp;
134:
135: uint32_t delayed_pc;
136: int delayed_branch;
137: int bcc;
138: uint32_t condlabel;
139:
140: struct TranslationBlock *tb;
141: int singlestep_enabled;
142: } DisasContext;
143:
144: void cris_prepare_jmp (DisasContext *dc, uint32_t dst);
145: static void gen_BUG(DisasContext *dc, char *file, int line)
146: {
147: printf ("BUG: pc=%x %s %d\n", dc->pc, file, line);
148: fprintf (logfile, "BUG: pc=%x %s %d\n", dc->pc, file, line);
149: cpu_dump_state (dc->env, stdout, fprintf, 0);
150: fflush(NULL);
151: cris_prepare_jmp (dc, 0x70000000 + line);
152: }
153:
154: /* Table to generate quick moves from T0 onto any register. */
155: static GenOpFunc *gen_movl_reg_T0[16] =
156: {
157: gen_op_movl_r0_T0, gen_op_movl_r1_T0,
158: gen_op_movl_r2_T0, gen_op_movl_r3_T0,
159: gen_op_movl_r4_T0, gen_op_movl_r5_T0,
160: gen_op_movl_r6_T0, gen_op_movl_r7_T0,
161: gen_op_movl_r8_T0, gen_op_movl_r9_T0,
162: gen_op_movl_r10_T0, gen_op_movl_r11_T0,
163: gen_op_movl_r12_T0, gen_op_movl_r13_T0,
164: gen_op_movl_r14_T0, gen_op_movl_r15_T0,
165: };
166: static GenOpFunc *gen_movl_T0_reg[16] =
167: {
168: gen_op_movl_T0_r0, gen_op_movl_T0_r1,
169: gen_op_movl_T0_r2, gen_op_movl_T0_r3,
170: gen_op_movl_T0_r4, gen_op_movl_T0_r5,
171: gen_op_movl_T0_r6, gen_op_movl_T0_r7,
172: gen_op_movl_T0_r8, gen_op_movl_T0_r9,
173: gen_op_movl_T0_r10, gen_op_movl_T0_r11,
174: gen_op_movl_T0_r12, gen_op_movl_T0_r13,
175: gen_op_movl_T0_r14, gen_op_movl_T0_r15,
176: };
177:
178: static void noop_write(void) {
179: /* nop. */
180: }
181:
182: static void gen_vr_read(void) {
183: gen_op_movl_T0_im(32);
184: }
185:
186: static void gen_ccs_read(void) {
187: gen_op_movl_T0_p13();
188: }
189:
190: static void gen_ccs_write(void) {
191: gen_op_movl_p13_T0();
192: }
193:
194: /* Table to generate quick moves from T0 onto any register. */
195: static GenOpFunc *gen_movl_preg_T0[16] =
196: {
197: noop_write, /* bz, not writeable. */
198: noop_write, /* vr, not writeable. */
199: gen_op_movl_p2_T0, gen_op_movl_p3_T0,
200: noop_write, /* wz, not writeable. */
201: gen_op_movl_p5_T0,
202: gen_op_movl_p6_T0, gen_op_movl_p7_T0,
203: noop_write, /* dz, not writeable. */
204: gen_op_movl_p9_T0,
205: gen_op_movl_p10_T0, gen_op_movl_p11_T0,
206: gen_op_movl_p12_T0,
207: gen_ccs_write, /* ccs needs special treatment. */
208: gen_op_movl_p14_T0, gen_op_movl_p15_T0,
209: };
210: static GenOpFunc *gen_movl_T0_preg[16] =
211: {
212: gen_op_movl_T0_p0,
213: gen_vr_read,
214: gen_op_movl_T0_p2, gen_op_movl_T0_p3,
215: gen_op_movl_T0_p4, gen_op_movl_T0_p5,
216: gen_op_movl_T0_p6, gen_op_movl_T0_p7,
217: gen_op_movl_T0_p8, gen_op_movl_T0_p9,
218: gen_op_movl_T0_p10, gen_op_movl_T0_p11,
219: gen_op_movl_T0_p12,
220: gen_ccs_read, /* ccs needs special treatment. */
221: gen_op_movl_T0_p14, gen_op_movl_T0_p15,
222: };
223:
224: /* We need this table to handle moves with implicit width. */
225: int preg_sizes[] = {
226: 1, /* bz. */
227: 1, /* vr. */
228: 4, /* pid. */
229: 1, /* srs. */
230: 2, /* wz. */
231: 4, 4, 4,
232: 4, 4, 4, 4,
233: 4, 4, 4, 4,
234: };
235:
236: #ifdef CONFIG_USER_ONLY
237: #define GEN_OP_LD(width, reg) \
238: void gen_op_ld##width##_T0_##reg (DisasContext *dc) { \
239: gen_op_ld##width##_T0_##reg##_raw(); \
240: }
241: #define GEN_OP_ST(width, reg) \
242: void gen_op_st##width##_##reg##_T1 (DisasContext *dc) { \
243: gen_op_st##width##_##reg##_T1_raw(); \
244: }
245: #else
246: #define GEN_OP_LD(width, reg) \
247: void gen_op_ld##width##_T0_##reg (DisasContext *dc) { \
248: if (dc->memidx) gen_op_ld##width##_T0_##reg##_kernel(); \
249: else gen_op_ld##width##_T0_##reg##_user();\
250: }
251: #define GEN_OP_ST(width, reg) \
252: void gen_op_st##width##_##reg##_T1 (DisasContext *dc) { \
253: if (dc->memidx) gen_op_st##width##_##reg##_T1_kernel(); \
254: else gen_op_st##width##_##reg##_T1_user();\
255: }
256: #endif
257:
258: GEN_OP_LD(ub, T0)
259: GEN_OP_LD(b, T0)
260: GEN_OP_ST(b, T0)
261: GEN_OP_LD(uw, T0)
262: GEN_OP_LD(w, T0)
263: GEN_OP_ST(w, T0)
264: GEN_OP_LD(l, T0)
265: GEN_OP_ST(l, T0)
266:
267: static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
268: {
269: TranslationBlock *tb;
270: tb = dc->tb;
271: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
272: if (n == 0)
273: gen_op_goto_tb0(TBPARAM(tb));
274: else
275: gen_op_goto_tb1(TBPARAM(tb));
276: gen_op_movl_T0_0();
277: } else {
278: gen_op_movl_T0_0();
279: }
280: gen_op_exit_tb();
281: }
282:
283: /* Sign extend at translation time. */
284: static int sign_extend(unsigned int val, unsigned int width)
285: {
286: int sval;
287:
288: /* LSL. */
289: val <<= 31 - width;
290: sval = val;
291: /* ASR. */
292: sval >>= 31 - width;
293: return sval;
294: }
295:
296: static void cris_evaluate_flags(DisasContext *dc)
297: {
298: if (!dc->flags_live) {
299:
300: switch (dc->cc_op)
301: {
302: case CC_OP_MCP:
303: gen_op_evaluate_flags_mcp ();
304: break;
305: case CC_OP_MULS:
306: gen_op_evaluate_flags_muls ();
307: break;
308: case CC_OP_MULU:
309: gen_op_evaluate_flags_mulu ();
310: break;
311: case CC_OP_MOVE:
312: switch (dc->cc_size)
313: {
314: case 4:
315: gen_op_evaluate_flags_move_4();
316: break;
317: case 2:
318: gen_op_evaluate_flags_move_2();
319: break;
320: default:
321: gen_op_evaluate_flags ();
322: break;
323: }
324: break;
325:
326: default:
327: {
328: switch (dc->cc_size)
329: {
330: case 4:
331: gen_op_evaluate_flags_alu_4 ();
332: break;
333: default:
334: gen_op_evaluate_flags ();
335: break;
336: }
337: }
338: break;
339: }
340: dc->flags_live = 1;
341: }
342: }
343:
344: static void cris_cc_mask(DisasContext *dc, unsigned int mask)
345: {
346: uint32_t ovl;
347:
348: ovl = (dc->cc_mask ^ mask) & ~mask;
349: if (ovl) {
350: /* TODO: optimize this case. It trigs all the time. */
351: cris_evaluate_flags (dc);
352: }
353: dc->cc_mask = mask;
354:
355: dc->update_cc = 1;
356: if (mask == 0)
357: dc->update_cc = 0;
358: else {
359: gen_op_update_cc_mask(mask);
360: dc->flags_live = 0;
361: }
362: }
363:
364: static void cris_update_cc_op(DisasContext *dc, int op)
365: {
366: dc->cc_op = op;
367: gen_op_update_cc_op(op);
368: dc->flags_live = 0;
369: }
370: static void cris_update_cc_size(DisasContext *dc, int size)
371: {
372: dc->cc_size = size;
373: gen_op_update_cc_size_im(size);
374: }
375:
376: /* op is the operation.
377: T0, T1 are the operands.
378: dst is the destination reg.
379: */
380: static void crisv32_alu_op(DisasContext *dc, int op, int rd, int size)
381: {
382: int writeback = 1;
383: if (dc->update_cc) {
384: cris_update_cc_op(dc, op);
385: cris_update_cc_size(dc, size);
386: gen_op_update_cc_x(dc->flagx_live, dc->flags_x);
387: gen_op_update_cc_dest_T0();
388: }
389:
390: /* Emit the ALU insns. */
391: switch (op)
392: {
393: case CC_OP_ADD:
394: gen_op_addl_T0_T1();
395: /* Extended arithmetics. */
396: if (!dc->flagx_live)
397: gen_op_addxl_T0_C();
398: else if (dc->flags_x)
399: gen_op_addxl_T0_C();
400: break;
401: case CC_OP_ADDC:
402: gen_op_addl_T0_T1();
403: gen_op_addl_T0_C();
404: break;
405: case CC_OP_MCP:
406: gen_op_addl_T0_T1();
407: gen_op_addl_T0_R();
408: break;
409: case CC_OP_SUB:
410: gen_op_negl_T1_T1();
411: gen_op_addl_T0_T1();
412: /* CRIS flag evaluation needs ~src. */
413: gen_op_negl_T1_T1();
414: gen_op_not_T1_T1();
415:
416: /* Extended arithmetics. */
417: if (!dc->flagx_live)
418: gen_op_subxl_T0_C();
419: else if (dc->flags_x)
420: gen_op_subxl_T0_C();
421: break;
422: case CC_OP_MOVE:
423: gen_op_movl_T0_T1();
424: break;
425: case CC_OP_OR:
426: gen_op_orl_T0_T1();
427: break;
428: case CC_OP_AND:
429: gen_op_andl_T0_T1();
430: break;
431: case CC_OP_XOR:
432: gen_op_xorl_T0_T1();
433: break;
434: case CC_OP_LSL:
435: gen_op_lsll_T0_T1();
436: break;
437: case CC_OP_LSR:
438: gen_op_lsrl_T0_T1();
439: break;
440: case CC_OP_ASR:
441: gen_op_asrl_T0_T1();
442: break;
443: case CC_OP_NEG:
444: gen_op_negl_T0_T1();
445: /* Extended arithmetics. */
446: gen_op_subxl_T0_C();
447: break;
448: case CC_OP_LZ:
449: gen_op_lz_T0_T1();
450: break;
451: case CC_OP_BTST:
452: gen_op_btst_T0_T1();
453: writeback = 0;
454: break;
455: case CC_OP_MULS:
456: gen_op_muls_T0_T1();
457: break;
458: case CC_OP_MULU:
459: gen_op_mulu_T0_T1();
460: break;
461: case CC_OP_DSTEP:
462: gen_op_dstep_T0_T1();
463: break;
464: case CC_OP_BOUND:
465: gen_op_bound_T0_T1();
466: break;
467: case CC_OP_CMP:
468: gen_op_negl_T1_T1();
469: gen_op_addl_T0_T1();
470: /* CRIS flag evaluation needs ~src. */
471: gen_op_negl_T1_T1();
472: gen_op_not_T1_T1();
473:
474: /* Extended arithmetics. */
475: gen_op_subxl_T0_C();
476: writeback = 0;
477: break;
478: default:
479: fprintf (logfile, "illegal ALU op.\n");
480: BUG();
481: break;
482: }
483:
484: if (dc->update_cc)
485: gen_op_update_cc_src_T1();
486:
487: if (size == 1)
488: gen_op_andl_T0_im(0xff);
489: else if (size == 2)
490: gen_op_andl_T0_im(0xffff);
491: /* Writeback. */
492: if (writeback) {
493: if (size == 4)
494: gen_movl_reg_T0[rd]();
495: else {
496: gen_op_movl_T1_T0();
497: gen_movl_T0_reg[rd]();
498: if (size == 1)
499: gen_op_andl_T0_im(~0xff);
500: else
501: gen_op_andl_T0_im(~0xffff);
502: gen_op_orl_T0_T1();
503: gen_movl_reg_T0[rd]();
504: gen_op_movl_T0_T1();
505: }
506: }
507: if (dc->update_cc)
508: gen_op_update_cc_result_T0();
509:
510: {
511: /* TODO: Optimize this. */
512: if (!dc->flagx_live)
513: cris_evaluate_flags(dc);
514: }
515: }
516:
517: static int arith_cc(DisasContext *dc)
518: {
519: if (dc->update_cc) {
520: switch (dc->cc_op) {
521: case CC_OP_ADD: return 1;
522: case CC_OP_SUB: return 1;
523: case CC_OP_LSL: return 1;
524: case CC_OP_LSR: return 1;
525: case CC_OP_ASR: return 1;
526: case CC_OP_CMP: return 1;
527: default:
528: return 0;
529: }
530: }
531: return 0;
532: }
533:
534: static void gen_tst_cc (DisasContext *dc, int cond)
535: {
536: int arith_opt;
537:
538: /* TODO: optimize more condition codes. */
539: arith_opt = arith_cc(dc) && !dc->flags_live;
540: switch (cond) {
541: case CC_EQ:
542: if (arith_opt)
543: gen_op_tst_cc_eq_fast ();
544: else {
545: cris_evaluate_flags(dc);
546: gen_op_tst_cc_eq ();
547: }
548: break;
549: case CC_NE:
550: if (arith_opt)
551: gen_op_tst_cc_ne_fast ();
552: else {
553: cris_evaluate_flags(dc);
554: gen_op_tst_cc_ne ();
555: }
556: break;
557: case CC_CS:
558: cris_evaluate_flags(dc);
559: gen_op_tst_cc_cs ();
560: break;
561: case CC_CC:
562: cris_evaluate_flags(dc);
563: gen_op_tst_cc_cc ();
564: break;
565: case CC_VS:
566: cris_evaluate_flags(dc);
567: gen_op_tst_cc_vs ();
568: break;
569: case CC_VC:
570: cris_evaluate_flags(dc);
571: gen_op_tst_cc_vc ();
572: break;
573: case CC_PL:
574: if (arith_opt)
575: gen_op_tst_cc_pl_fast ();
576: else {
577: cris_evaluate_flags(dc);
578: gen_op_tst_cc_pl ();
579: }
580: break;
581: case CC_MI:
582: if (arith_opt)
583: gen_op_tst_cc_mi_fast ();
584: else {
585: cris_evaluate_flags(dc);
586: gen_op_tst_cc_mi ();
587: }
588: break;
589: case CC_LS:
590: cris_evaluate_flags(dc);
591: gen_op_tst_cc_ls ();
592: break;
593: case CC_HI:
594: cris_evaluate_flags(dc);
595: gen_op_tst_cc_hi ();
596: break;
597: case CC_GE:
598: cris_evaluate_flags(dc);
599: gen_op_tst_cc_ge ();
600: break;
601: case CC_LT:
602: cris_evaluate_flags(dc);
603: gen_op_tst_cc_lt ();
604: break;
605: case CC_GT:
606: cris_evaluate_flags(dc);
607: gen_op_tst_cc_gt ();
608: break;
609: case CC_LE:
610: cris_evaluate_flags(dc);
611: gen_op_tst_cc_le ();
612: break;
613: case CC_P:
614: cris_evaluate_flags(dc);
615: gen_op_tst_cc_p ();
616: break;
617: case CC_A:
618: cris_evaluate_flags(dc);
619: gen_op_movl_T0_im (1);
620: break;
621: default:
622: BUG();
623: break;
624: };
625: }
626:
627: static void cris_prepare_cc_branch (DisasContext *dc, int offset, int cond)
628: {
629: /* This helps us re-schedule the micro-code to insns in delay-slots
630: before the actual jump. */
631: dc->delayed_branch = 2;
632: dc->delayed_pc = dc->pc + offset;
633: dc->bcc = cond;
634: if (cond != CC_A)
635: {
636: gen_tst_cc (dc, cond);
637: gen_op_evaluate_bcc ();
638: }
639: gen_op_movl_T0_im (dc->delayed_pc);
640: gen_op_movl_btarget_T0 ();
641: }
642:
643: /* Dynamic jumps, when the dest is in a live reg for example. */
644: void cris_prepare_dyn_jmp (DisasContext *dc)
645: {
646: /* This helps us re-schedule the micro-code to insns in delay-slots
647: before the actual jump. */
648: dc->delayed_branch = 2;
649: dc->dyn_jmp = 1;
650: dc->bcc = CC_A;
651: }
652:
653: void cris_prepare_jmp (DisasContext *dc, uint32_t dst)
654: {
655: /* This helps us re-schedule the micro-code to insns in delay-slots
656: before the actual jump. */
657: dc->delayed_branch = 2;
658: dc->delayed_pc = dst;
659: dc->dyn_jmp = 0;
660: dc->bcc = CC_A;
661: }
662:
663: void gen_load_T0_T0 (DisasContext *dc, unsigned int size, int sign)
664: {
665: if (size == 1) {
666: if (sign)
667: gen_op_ldb_T0_T0(dc);
668: else
669: gen_op_ldub_T0_T0(dc);
670: }
671: else if (size == 2) {
672: if (sign)
673: gen_op_ldw_T0_T0(dc);
674: else
675: gen_op_lduw_T0_T0(dc);
676: }
677: else {
678: gen_op_ldl_T0_T0(dc);
679: }
680: }
681:
682: void gen_store_T0_T1 (DisasContext *dc, unsigned int size)
683: {
684: /* Remember, operands are flipped. CRIS has reversed order. */
685: if (size == 1) {
686: gen_op_stb_T0_T1(dc);
687: }
688: else if (size == 2) {
689: gen_op_stw_T0_T1(dc);
690: }
691: else
692: gen_op_stl_T0_T1(dc);
693: }
694:
695: /* sign extend T1 according to size. */
696: static void gen_sext_T1_T0(int size)
697: {
698: if (size == 1)
699: gen_op_extb_T1_T0();
700: else if (size == 2)
701: gen_op_extw_T1_T0();
702: }
703:
704: static void gen_sext_T1_T1(int size)
705: {
706: if (size == 1)
707: gen_op_extb_T1_T1();
708: else if (size == 2)
709: gen_op_extw_T1_T1();
710: }
711:
712: static void gen_sext_T0_T0(int size)
713: {
714: if (size == 1)
715: gen_op_extb_T0_T0();
716: else if (size == 2)
717: gen_op_extw_T0_T0();
718: }
719:
720: static void gen_zext_T0_T0(int size)
721: {
722: if (size == 1)
723: gen_op_zextb_T0_T0();
724: else if (size == 2)
725: gen_op_zextw_T0_T0();
726: }
727:
728: static void gen_zext_T1_T0(int size)
729: {
730: if (size == 1)
731: gen_op_zextb_T1_T0();
732: else if (size == 2)
733: gen_op_zextw_T1_T0();
734: }
735:
736: static void gen_zext_T1_T1(int size)
737: {
738: if (size == 1)
739: gen_op_zextb_T1_T1();
740: else if (size == 2)
741: gen_op_zextw_T1_T1();
742: }
743:
744: #if DISAS_CRIS
745: static char memsize_char(int size)
746: {
747: switch (size)
748: {
749: case 1: return 'b'; break;
750: case 2: return 'w'; break;
751: case 4: return 'd'; break;
752: default:
753: return 'x';
754: break;
755: }
756: }
757: #endif
758:
759: static unsigned int memsize_z(DisasContext *dc)
760: {
761: return dc->zsize + 1;
762: }
763:
764: static unsigned int memsize_zz(DisasContext *dc)
765: {
766: switch (dc->zzsize)
767: {
768: case 0: return 1;
769: case 1: return 2;
770: default:
771: return 4;
772: }
773: }
774:
775: static void do_postinc (DisasContext *dc, int size)
776: {
777: if (!dc->postinc)
778: return;
779: gen_movl_T0_reg[dc->op1]();
780: gen_op_addl_T0_im(size);
781: gen_movl_reg_T0[dc->op1]();
782: }
783:
784:
785: static void dec_prep_move_r(DisasContext *dc, int rs, int rd,
786: int size, int s_ext)
787: {
788: gen_movl_T0_reg[rs]();
789: gen_op_movl_T1_T0();
790: if (s_ext)
791: gen_sext_T1_T1(size);
792: else
793: gen_zext_T1_T1(size);
794: }
795:
796: /* Prepare T0 and T1 for a register alu operation.
797: s_ext decides if the operand1 should be sign-extended or zero-extended when
798: needed. */
799: static void dec_prep_alu_r(DisasContext *dc, int rs, int rd,
800: int size, int s_ext)
801: {
802: dec_prep_move_r(dc, rs, rd, size, s_ext);
803:
804: gen_movl_T0_reg[rd]();
805: if (s_ext)
806: gen_sext_T0_T0(size);
807: else
808: gen_zext_T0_T0(size);
809: }
810:
811: /* Prepare T0 and T1 for a memory + alu operation.
812: s_ext decides if the operand1 should be sign-extended or zero-extended when
813: needed. */
814: static int dec_prep_alu_m(DisasContext *dc, int s_ext, int memsize)
815: {
816: unsigned int rs, rd;
817: uint32_t imm;
818: int is_imm;
819: int insn_len = 2;
820:
821: rs = dc->op1;
822: rd = dc->op2;
823: is_imm = rs == 15 && dc->postinc;
824:
825: /* Load [$rs] onto T1. */
826: if (is_imm) {
827: insn_len = 2 + memsize;
828: if (memsize == 1)
829: insn_len++;
830:
831: imm = ldl_code(dc->pc + 2);
832: if (memsize != 4) {
833: if (s_ext) {
834: imm = sign_extend(imm, (memsize * 8) - 1);
835: } else {
836: if (memsize == 1)
837: imm &= 0xff;
838: else
839: imm &= 0xffff;
840: }
841: }
842: DIS(fprintf (logfile, "imm=%x rd=%d sext=%d ms=%d\n",
843: imm, rd, s_ext, memsize));
844: gen_op_movl_T1_im (imm);
845: dc->postinc = 0;
846: } else {
847: gen_movl_T0_reg[rs]();
848: gen_load_T0_T0(dc, memsize, 0);
849: gen_op_movl_T1_T0();
850: if (s_ext)
851: gen_sext_T1_T1(memsize);
852: else
853: gen_zext_T1_T1(memsize);
854: }
855:
856: /* put dest in T0. */
857: gen_movl_T0_reg[rd]();
858: return insn_len;
859: }
860:
861: #if DISAS_CRIS
862: static const char *cc_name(int cc)
863: {
864: static char *cc_names[16] = {
865: "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi",
866: "ls", "hi", "ge", "lt", "gt", "le", "a", "p"
867: };
868: assert(cc < 16);
869: return cc_names[cc];
870: }
871: #endif
872:
873: static unsigned int dec_bccq(DisasContext *dc)
874: {
875: int32_t offset;
876: int sign;
877: uint32_t cond = dc->op2;
878: int tmp;
879:
880: offset = EXTRACT_FIELD (dc->ir, 1, 7);
881: sign = EXTRACT_FIELD(dc->ir, 0, 0);
882:
883: offset *= 2;
884: offset |= sign << 8;
885: tmp = offset;
886: offset = sign_extend(offset, 8);
887:
888: /* op2 holds the condition-code. */
889: cris_cc_mask(dc, 0);
890: cris_prepare_cc_branch (dc, offset, cond);
891: return 2;
892: }
893: static unsigned int dec_addoq(DisasContext *dc)
894: {
895: uint32_t imm;
896:
897: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 7);
898: imm = sign_extend(dc->op1, 7);
899:
900: DIS(fprintf (logfile, "addoq %d, $r%u\n", imm, dc->op2));
901: cris_cc_mask(dc, 0);
902: /* Fetch register operand, */
903: gen_movl_T0_reg[dc->op2]();
904: gen_op_movl_T1_im(imm);
905: crisv32_alu_op(dc, CC_OP_ADD, REG_ACR, 4);
906: return 2;
907: }
908: static unsigned int dec_addq(DisasContext *dc)
909: {
910: DIS(fprintf (logfile, "addq %u, $r%u\n", dc->op1, dc->op2));
911:
912: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
913:
914: cris_cc_mask(dc, CC_MASK_NZVC);
915: /* Fetch register operand, */
916: gen_movl_T0_reg[dc->op2]();
917: gen_op_movl_T1_im(dc->op1);
918: crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
919: return 2;
920: }
921: static unsigned int dec_moveq(DisasContext *dc)
922: {
923: uint32_t imm;
924:
925: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
926: imm = sign_extend(dc->op1, 5);
927: DIS(fprintf (logfile, "moveq %d, $r%u\n", imm, dc->op2));
928:
929: cris_cc_mask(dc, 0);
930: gen_op_movl_T1_im(imm);
931: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
932:
933: return 2;
934: }
935: static unsigned int dec_subq(DisasContext *dc)
936: {
937: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
938:
939: DIS(fprintf (logfile, "subq %u, $r%u\n", dc->op1, dc->op2));
940:
941: cris_cc_mask(dc, CC_MASK_NZVC);
942: /* Fetch register operand, */
943: gen_movl_T0_reg[dc->op2]();
944: gen_op_movl_T1_im(dc->op1);
945: crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
946: return 2;
947: }
948: static unsigned int dec_cmpq(DisasContext *dc)
949: {
950: uint32_t imm;
951: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
952: imm = sign_extend(dc->op1, 5);
953:
954: DIS(fprintf (logfile, "cmpq %d, $r%d\n", imm, dc->op2));
955: cris_cc_mask(dc, CC_MASK_NZVC);
956: gen_movl_T0_reg[dc->op2]();
957: gen_op_movl_T1_im(imm);
958: crisv32_alu_op(dc, CC_OP_CMP, dc->op2, 4);
959: return 2;
960: }
961: static unsigned int dec_andq(DisasContext *dc)
962: {
963: uint32_t imm;
964: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
965: imm = sign_extend(dc->op1, 5);
966:
967: DIS(fprintf (logfile, "andq %d, $r%d\n", imm, dc->op2));
968: cris_cc_mask(dc, CC_MASK_NZ);
969: gen_movl_T0_reg[dc->op2]();
970: gen_op_movl_T1_im(imm);
971: crisv32_alu_op(dc, CC_OP_AND, dc->op2, 4);
972: return 2;
973: }
974: static unsigned int dec_orq(DisasContext *dc)
975: {
976: uint32_t imm;
977: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
978: imm = sign_extend(dc->op1, 5);
979: DIS(fprintf (logfile, "orq %d, $r%d\n", imm, dc->op2));
980: cris_cc_mask(dc, CC_MASK_NZ);
981: gen_movl_T0_reg[dc->op2]();
982: gen_op_movl_T1_im(imm);
983: crisv32_alu_op(dc, CC_OP_OR, dc->op2, 4);
984: return 2;
985: }
986: static unsigned int dec_btstq(DisasContext *dc)
987: {
988: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
989: DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2));
990: cris_evaluate_flags(dc);
991: cris_cc_mask(dc, CC_MASK_NZ);
992: gen_movl_T0_reg[dc->op2]();
993: gen_op_movl_T1_im(dc->op1);
994: crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4);
995:
996: cris_update_cc_op(dc, CC_OP_FLAGS);
997: gen_op_movl_flags_T0();
998: dc->flags_live = 1;
999: return 2;
1000: }
1001: static unsigned int dec_asrq(DisasContext *dc)
1002: {
1003: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
1004: DIS(fprintf (logfile, "asrq %u, $r%d\n", dc->op1, dc->op2));
1005: cris_cc_mask(dc, CC_MASK_NZ);
1006: gen_movl_T0_reg[dc->op2]();
1007: gen_op_movl_T1_im(dc->op1);
1008: crisv32_alu_op(dc, CC_OP_ASR, dc->op2, 4);
1009: return 2;
1010: }
1011: static unsigned int dec_lslq(DisasContext *dc)
1012: {
1013: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
1014: DIS(fprintf (logfile, "lslq %u, $r%d\n", dc->op1, dc->op2));
1015:
1016: cris_cc_mask(dc, CC_MASK_NZ);
1017: gen_movl_T0_reg[dc->op2]();
1018: gen_op_movl_T1_im(dc->op1);
1019: crisv32_alu_op(dc, CC_OP_LSL, dc->op2, 4);
1020: return 2;
1021: }
1022: static unsigned int dec_lsrq(DisasContext *dc)
1023: {
1024: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
1025: DIS(fprintf (logfile, "lsrq %u, $r%d\n", dc->op1, dc->op2));
1026:
1027: cris_cc_mask(dc, CC_MASK_NZ);
1028: gen_movl_T0_reg[dc->op2]();
1029: gen_op_movl_T1_im(dc->op1);
1030: crisv32_alu_op(dc, CC_OP_LSR, dc->op2, 4);
1031: return 2;
1032: }
1033:
1034: static unsigned int dec_move_r(DisasContext *dc)
1035: {
1036: int size = memsize_zz(dc);
1037:
1038: DIS(fprintf (logfile, "move.%c $r%u, $r%u\n",
1039: memsize_char(size), dc->op1, dc->op2));
1040:
1041: cris_cc_mask(dc, CC_MASK_NZ);
1042: dec_prep_move_r(dc, dc->op1, dc->op2, size, 0);
1043: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, size);
1044: return 2;
1045: }
1046:
1047: static unsigned int dec_scc_r(DisasContext *dc)
1048: {
1049: int cond = dc->op2;
1050:
1051: DIS(fprintf (logfile, "s%s $r%u\n",
1052: cc_name(cond), dc->op1));
1053:
1054: if (cond != CC_A)
1055: {
1056: gen_tst_cc (dc, cond);
1057: gen_op_movl_T1_T0();
1058: }
1059: else
1060: gen_op_movl_T1_im(1);
1061:
1062: cris_cc_mask(dc, 0);
1063: crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4);
1064: return 2;
1065: }
1066:
1067: static unsigned int dec_and_r(DisasContext *dc)
1068: {
1069: int size = memsize_zz(dc);
1070:
1071: DIS(fprintf (logfile, "and.%c $r%u, $r%u\n",
1072: memsize_char(size), dc->op1, dc->op2));
1073: cris_cc_mask(dc, CC_MASK_NZ);
1074: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1075: crisv32_alu_op(dc, CC_OP_AND, dc->op2, size);
1076: return 2;
1077: }
1078:
1079: static unsigned int dec_lz_r(DisasContext *dc)
1080: {
1081: DIS(fprintf (logfile, "lz $r%u, $r%u\n",
1082: dc->op1, dc->op2));
1083: cris_cc_mask(dc, CC_MASK_NZ);
1084: dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1085: crisv32_alu_op(dc, CC_OP_LZ, dc->op2, 4);
1086: return 2;
1087: }
1088:
1089: static unsigned int dec_lsl_r(DisasContext *dc)
1090: {
1091: int size = memsize_zz(dc);
1092:
1093: DIS(fprintf (logfile, "lsl.%c $r%u, $r%u\n",
1094: memsize_char(size), dc->op1, dc->op2));
1095: cris_cc_mask(dc, CC_MASK_NZ);
1096: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1097: gen_op_andl_T1_im(63);
1098: crisv32_alu_op(dc, CC_OP_LSL, dc->op2, size);
1099: return 2;
1100: }
1101:
1102: static unsigned int dec_lsr_r(DisasContext *dc)
1103: {
1104: int size = memsize_zz(dc);
1105:
1106: DIS(fprintf (logfile, "lsr.%c $r%u, $r%u\n",
1107: memsize_char(size), dc->op1, dc->op2));
1108: cris_cc_mask(dc, CC_MASK_NZ);
1109: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1110: gen_op_andl_T1_im(63);
1111: crisv32_alu_op(dc, CC_OP_LSR, dc->op2, size);
1112: return 2;
1113: }
1114:
1115: static unsigned int dec_asr_r(DisasContext *dc)
1116: {
1117: int size = memsize_zz(dc);
1118:
1119: DIS(fprintf (logfile, "asr.%c $r%u, $r%u\n",
1120: memsize_char(size), dc->op1, dc->op2));
1121: cris_cc_mask(dc, CC_MASK_NZ);
1122: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1);
1123: gen_op_andl_T1_im(63);
1124: crisv32_alu_op(dc, CC_OP_ASR, dc->op2, size);
1125: return 2;
1126: }
1127:
1128: static unsigned int dec_muls_r(DisasContext *dc)
1129: {
1130: int size = memsize_zz(dc);
1131:
1132: DIS(fprintf (logfile, "muls.%c $r%u, $r%u\n",
1133: memsize_char(size), dc->op1, dc->op2));
1134: cris_cc_mask(dc, CC_MASK_NZV);
1135: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1);
1136: gen_sext_T0_T0(size);
1137: crisv32_alu_op(dc, CC_OP_MULS, dc->op2, 4);
1138: return 2;
1139: }
1140:
1141: static unsigned int dec_mulu_r(DisasContext *dc)
1142: {
1143: int size = memsize_zz(dc);
1144:
1145: DIS(fprintf (logfile, "mulu.%c $r%u, $r%u\n",
1146: memsize_char(size), dc->op1, dc->op2));
1147: cris_cc_mask(dc, CC_MASK_NZV);
1148: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1149: gen_zext_T0_T0(size);
1150: crisv32_alu_op(dc, CC_OP_MULU, dc->op2, 4);
1151: return 2;
1152: }
1153:
1154:
1155: static unsigned int dec_dstep_r(DisasContext *dc)
1156: {
1157: DIS(fprintf (logfile, "dstep $r%u, $r%u\n", dc->op1, dc->op2));
1158: cris_cc_mask(dc, CC_MASK_NZ);
1159: gen_movl_T0_reg[dc->op1]();
1160: gen_op_movl_T1_T0();
1161: gen_movl_T0_reg[dc->op2]();
1162: crisv32_alu_op(dc, CC_OP_DSTEP, dc->op2, 4);
1163: return 2;
1164: }
1165:
1166: static unsigned int dec_xor_r(DisasContext *dc)
1167: {
1168: int size = memsize_zz(dc);
1169: DIS(fprintf (logfile, "xor.%c $r%u, $r%u\n",
1170: memsize_char(size), dc->op1, dc->op2));
1171: BUG_ON(size != 4); /* xor is dword. */
1172: cris_cc_mask(dc, CC_MASK_NZ);
1173: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1174: crisv32_alu_op(dc, CC_OP_XOR, dc->op2, 4);
1175: return 2;
1176: }
1177:
1178: static unsigned int dec_bound_r(DisasContext *dc)
1179: {
1180: int size = memsize_zz(dc);
1181: DIS(fprintf (logfile, "bound.%c $r%u, $r%u\n",
1182: memsize_char(size), dc->op1, dc->op2));
1183: cris_cc_mask(dc, CC_MASK_NZ);
1184: /* TODO: needs optmimization. */
1185: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1186: /* rd should be 4. */
1187: gen_movl_T0_reg[dc->op2]();
1188: crisv32_alu_op(dc, CC_OP_BOUND, dc->op2, 4);
1189: return 2;
1190: }
1191:
1192: static unsigned int dec_cmp_r(DisasContext *dc)
1193: {
1194: int size = memsize_zz(dc);
1195: DIS(fprintf (logfile, "cmp.%c $r%u, $r%u\n",
1196: memsize_char(size), dc->op1, dc->op2));
1197: cris_cc_mask(dc, CC_MASK_NZVC);
1198: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1199: crisv32_alu_op(dc, CC_OP_CMP, dc->op2, size);
1200: return 2;
1201: }
1202:
1203: static unsigned int dec_abs_r(DisasContext *dc)
1204: {
1205: DIS(fprintf (logfile, "abs $r%u, $r%u\n",
1206: dc->op1, dc->op2));
1207: cris_cc_mask(dc, CC_MASK_NZ);
1208: dec_prep_move_r(dc, dc->op1, dc->op2, 4, 0);
1209: gen_op_absl_T1_T1();
1210: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1211: return 2;
1212: }
1213:
1214: static unsigned int dec_add_r(DisasContext *dc)
1215: {
1216: int size = memsize_zz(dc);
1217: DIS(fprintf (logfile, "add.%c $r%u, $r%u\n",
1218: memsize_char(size), dc->op1, dc->op2));
1219: cris_cc_mask(dc, CC_MASK_NZVC);
1220: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1221: crisv32_alu_op(dc, CC_OP_ADD, dc->op2, size);
1222: return 2;
1223: }
1224:
1225: static unsigned int dec_addc_r(DisasContext *dc)
1226: {
1227: DIS(fprintf (logfile, "addc $r%u, $r%u\n",
1228: dc->op1, dc->op2));
1229: cris_evaluate_flags(dc);
1230: cris_cc_mask(dc, CC_MASK_NZVC);
1231: dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1232: crisv32_alu_op(dc, CC_OP_ADDC, dc->op2, 4);
1233: return 2;
1234: }
1235:
1236: static unsigned int dec_mcp_r(DisasContext *dc)
1237: {
1238: DIS(fprintf (logfile, "mcp $p%u, $r%u\n",
1239: dc->op2, dc->op1));
1240: cris_evaluate_flags(dc);
1241: cris_cc_mask(dc, CC_MASK_RNZV);
1242: gen_movl_T0_preg[dc->op2]();
1243: gen_op_movl_T1_T0();
1244: gen_movl_T0_reg[dc->op1]();
1245: crisv32_alu_op(dc, CC_OP_MCP, dc->op1, 4);
1246: return 2;
1247: }
1248:
1249: #if DISAS_CRIS
1250: static char * swapmode_name(int mode, char *modename) {
1251: int i = 0;
1252: if (mode & 8)
1253: modename[i++] = 'n';
1254: if (mode & 4)
1255: modename[i++] = 'w';
1256: if (mode & 2)
1257: modename[i++] = 'b';
1258: if (mode & 1)
1259: modename[i++] = 'r';
1260: modename[i++] = 0;
1261: return modename;
1262: }
1263: #endif
1264:
1265: static unsigned int dec_swap_r(DisasContext *dc)
1266: {
1267: DIS(char modename[4]);
1268: DIS(fprintf (logfile, "swap%s $r%u\n",
1269: swapmode_name(dc->op2, modename), dc->op1));
1270:
1271: cris_cc_mask(dc, CC_MASK_NZ);
1272: gen_movl_T0_reg[dc->op1]();
1273: if (dc->op2 & 8)
1274: gen_op_not_T0_T0();
1275: if (dc->op2 & 4)
1276: gen_op_swapw_T0_T0();
1277: if (dc->op2 & 2)
1278: gen_op_swapb_T0_T0();
1279: if (dc->op2 & 1)
1280: gen_op_swapr_T0_T0();
1281: gen_op_movl_T1_T0();
1282: crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4);
1283: return 2;
1284: }
1285:
1286: static unsigned int dec_or_r(DisasContext *dc)
1287: {
1288: int size = memsize_zz(dc);
1289: DIS(fprintf (logfile, "or.%c $r%u, $r%u\n",
1290: memsize_char(size), dc->op1, dc->op2));
1291: cris_cc_mask(dc, CC_MASK_NZ);
1292: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1293: crisv32_alu_op(dc, CC_OP_OR, dc->op2, size);
1294: return 2;
1295: }
1296:
1297: static unsigned int dec_addi_r(DisasContext *dc)
1298: {
1299: DIS(fprintf (logfile, "addi.%c $r%u, $r%u\n",
1300: memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
1301: cris_cc_mask(dc, 0);
1302: dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1303: gen_op_lsll_T0_im(dc->zzsize);
1304: gen_op_addl_T0_T1();
1305: gen_movl_reg_T0[dc->op1]();
1306: return 2;
1307: }
1308:
1309: static unsigned int dec_addi_acr(DisasContext *dc)
1310: {
1311: DIS(fprintf (logfile, "addi.%c $r%u, $r%u, $acr\n",
1312: memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
1313: cris_cc_mask(dc, 0);
1314: dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1315: gen_op_lsll_T0_im(dc->zzsize);
1316: gen_op_addl_T0_T1();
1317: gen_movl_reg_T0[REG_ACR]();
1318: return 2;
1319: }
1320:
1321: static unsigned int dec_neg_r(DisasContext *dc)
1322: {
1323: int size = memsize_zz(dc);
1324: DIS(fprintf (logfile, "neg.%c $r%u, $r%u\n",
1325: memsize_char(size), dc->op1, dc->op2));
1326: cris_cc_mask(dc, CC_MASK_NZVC);
1327: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1328: crisv32_alu_op(dc, CC_OP_NEG, dc->op2, size);
1329: return 2;
1330: }
1331:
1332: static unsigned int dec_btst_r(DisasContext *dc)
1333: {
1334: DIS(fprintf (logfile, "btst $r%u, $r%u\n",
1335: dc->op1, dc->op2));
1336: cris_evaluate_flags(dc);
1337: cris_cc_mask(dc, CC_MASK_NZ);
1338: dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
1339: crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4);
1340:
1341: cris_update_cc_op(dc, CC_OP_FLAGS);
1342: gen_op_movl_flags_T0();
1343: dc->flags_live = 1;
1344: return 2;
1345: }
1346:
1347: static unsigned int dec_sub_r(DisasContext *dc)
1348: {
1349: int size = memsize_zz(dc);
1350: DIS(fprintf (logfile, "sub.%c $r%u, $r%u\n",
1351: memsize_char(size), dc->op1, dc->op2));
1352: cris_cc_mask(dc, CC_MASK_NZVC);
1353: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
1354: crisv32_alu_op(dc, CC_OP_SUB, dc->op2, size);
1355: return 2;
1356: }
1357:
1358: /* Zero extension. From size to dword. */
1359: static unsigned int dec_movu_r(DisasContext *dc)
1360: {
1361: int size = memsize_z(dc);
1362: DIS(fprintf (logfile, "movu.%c $r%u, $r%u\n",
1363: memsize_char(size),
1364: dc->op1, dc->op2));
1365:
1366: cris_cc_mask(dc, CC_MASK_NZ);
1367: dec_prep_move_r(dc, dc->op1, dc->op2, size, 0);
1368: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1369: return 2;
1370: }
1371:
1372: /* Sign extension. From size to dword. */
1373: static unsigned int dec_movs_r(DisasContext *dc)
1374: {
1375: int size = memsize_z(dc);
1376: DIS(fprintf (logfile, "movs.%c $r%u, $r%u\n",
1377: memsize_char(size),
1378: dc->op1, dc->op2));
1379:
1380: cris_cc_mask(dc, CC_MASK_NZ);
1381: gen_movl_T0_reg[dc->op1]();
1382: /* Size can only be qi or hi. */
1383: gen_sext_T1_T0(size);
1384: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1385: return 2;
1386: }
1387:
1388: /* zero extension. From size to dword. */
1389: static unsigned int dec_addu_r(DisasContext *dc)
1390: {
1391: int size = memsize_z(dc);
1392: DIS(fprintf (logfile, "addu.%c $r%u, $r%u\n",
1393: memsize_char(size),
1394: dc->op1, dc->op2));
1395:
1396: cris_cc_mask(dc, CC_MASK_NZVC);
1397: gen_movl_T0_reg[dc->op1]();
1398: /* Size can only be qi or hi. */
1399: gen_zext_T1_T0(size);
1400: gen_movl_T0_reg[dc->op2]();
1401: crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
1402: return 2;
1403: }
1404: /* Sign extension. From size to dword. */
1405: static unsigned int dec_adds_r(DisasContext *dc)
1406: {
1407: int size = memsize_z(dc);
1408: DIS(fprintf (logfile, "adds.%c $r%u, $r%u\n",
1409: memsize_char(size),
1410: dc->op1, dc->op2));
1411:
1412: cris_cc_mask(dc, CC_MASK_NZVC);
1413: gen_movl_T0_reg[dc->op1]();
1414: /* Size can only be qi or hi. */
1415: gen_sext_T1_T0(size);
1416: gen_movl_T0_reg[dc->op2]();
1417: crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
1418: return 2;
1419: }
1420:
1421: /* Zero extension. From size to dword. */
1422: static unsigned int dec_subu_r(DisasContext *dc)
1423: {
1424: int size = memsize_z(dc);
1425: DIS(fprintf (logfile, "subu.%c $r%u, $r%u\n",
1426: memsize_char(size),
1427: dc->op1, dc->op2));
1428:
1429: cris_cc_mask(dc, CC_MASK_NZVC);
1430: gen_movl_T0_reg[dc->op1]();
1431: /* Size can only be qi or hi. */
1432: gen_zext_T1_T0(size);
1433: gen_movl_T0_reg[dc->op2]();
1434: crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
1435: return 2;
1436: }
1437:
1438: /* Sign extension. From size to dword. */
1439: static unsigned int dec_subs_r(DisasContext *dc)
1440: {
1441: int size = memsize_z(dc);
1442: DIS(fprintf (logfile, "subs.%c $r%u, $r%u\n",
1443: memsize_char(size),
1444: dc->op1, dc->op2));
1445:
1446: cris_cc_mask(dc, CC_MASK_NZVC);
1447: gen_movl_T0_reg[dc->op1]();
1448: /* Size can only be qi or hi. */
1449: gen_sext_T1_T0(size);
1450: gen_movl_T0_reg[dc->op2]();
1451: crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
1452: return 2;
1453: }
1454:
1455: static unsigned int dec_setclrf(DisasContext *dc)
1456: {
1457: uint32_t flags;
1458: int set = (~dc->opcode >> 2) & 1;
1459:
1460: flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4)
1461: | EXTRACT_FIELD(dc->ir, 0, 3);
1462: DIS(fprintf (logfile, "set=%d flags=%x\n", set, flags));
1463: if (set && flags == 0)
1464: DIS(fprintf (logfile, "nop\n"));
1465: else if (!set && (flags & 0x20))
1466: DIS(fprintf (logfile, "di\n"));
1467: else
1468: DIS(fprintf (logfile, "%sf %x\n",
1469: set ? "set" : "clr",
1470: flags));
1471:
1472: if (set && (flags & X_FLAG)) {
1473: dc->flagx_live = 1;
1474: dc->flags_x = 1;
1475: }
1476:
1477: /* Simply decode the flags. */
1478: cris_evaluate_flags (dc);
1479: cris_update_cc_op(dc, CC_OP_FLAGS);
1480: if (set)
1481: gen_op_setf (flags);
1482: else
1483: gen_op_clrf (flags);
1484: dc->flags_live = 1;
1485: return 2;
1486: }
1487:
1488: static unsigned int dec_move_rs(DisasContext *dc)
1489: {
1490: DIS(fprintf (logfile, "move $r%u, $s%u\n", dc->op1, dc->op2));
1491: cris_cc_mask(dc, 0);
1492: gen_movl_T0_reg[dc->op1]();
1493: gen_op_movl_sreg_T0(dc->op2);
1494:
1495: if (dc->op2 == 5) /* srs is checked at runtime. */
1496: gen_op_movl_tlb_lo_T0();
1497: return 2;
1498: }
1499: static unsigned int dec_move_sr(DisasContext *dc)
1500: {
1501: DIS(fprintf (logfile, "move $s%u, $r%u\n", dc->op1, dc->op2));
1502: cris_cc_mask(dc, 0);
1503: gen_op_movl_T0_sreg(dc->op1);
1504: gen_op_movl_T1_T0();
1505: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1506: return 2;
1507: }
1508: static unsigned int dec_move_rp(DisasContext *dc)
1509: {
1510: DIS(fprintf (logfile, "move $r%u, $p%u\n", dc->op1, dc->op2));
1511: cris_cc_mask(dc, 0);
1512: gen_movl_T0_reg[dc->op1]();
1513: gen_op_movl_T1_T0();
1514: gen_movl_preg_T0[dc->op2]();
1515: return 2;
1516: }
1517: static unsigned int dec_move_pr(DisasContext *dc)
1518: {
1519: DIS(fprintf (logfile, "move $p%u, $r%u\n", dc->op1, dc->op2));
1520: cris_cc_mask(dc, 0);
1521: gen_movl_T0_preg[dc->op2]();
1522: gen_op_movl_T1_T0();
1523: crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, preg_sizes[dc->op2]);
1524: return 2;
1525: }
1526:
1527: static unsigned int dec_move_mr(DisasContext *dc)
1528: {
1529: int memsize = memsize_zz(dc);
1530: int insn_len;
1531: DIS(fprintf (logfile, "move.%c [$r%u%s, $r%u\n",
1532: memsize_char(memsize),
1533: dc->op1, dc->postinc ? "+]" : "]",
1534: dc->op2));
1535:
1536: cris_cc_mask(dc, CC_MASK_NZ);
1537: insn_len = dec_prep_alu_m(dc, 0, memsize);
1538: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, memsize);
1539: do_postinc(dc, memsize);
1540: return insn_len;
1541: }
1542:
1543: static unsigned int dec_movs_m(DisasContext *dc)
1544: {
1545: int memsize = memsize_z(dc);
1546: int insn_len;
1547: DIS(fprintf (logfile, "movs.%c [$r%u%s, $r%u\n",
1548: memsize_char(memsize),
1549: dc->op1, dc->postinc ? "+]" : "]",
1550: dc->op2));
1551:
1552: /* sign extend. */
1553: cris_cc_mask(dc, CC_MASK_NZ);
1554: insn_len = dec_prep_alu_m(dc, 1, memsize);
1555: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1556: do_postinc(dc, memsize);
1557: return insn_len;
1558: }
1559:
1560: static unsigned int dec_addu_m(DisasContext *dc)
1561: {
1562: int memsize = memsize_z(dc);
1563: int insn_len;
1564: DIS(fprintf (logfile, "addu.%c [$r%u%s, $r%u\n",
1565: memsize_char(memsize),
1566: dc->op1, dc->postinc ? "+]" : "]",
1567: dc->op2));
1568:
1569: /* sign extend. */
1570: cris_cc_mask(dc, CC_MASK_NZVC);
1571: insn_len = dec_prep_alu_m(dc, 0, memsize);
1572: crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
1573: do_postinc(dc, memsize);
1574: return insn_len;
1575: }
1576:
1577: static unsigned int dec_adds_m(DisasContext *dc)
1578: {
1579: int memsize = memsize_z(dc);
1580: int insn_len;
1581: DIS(fprintf (logfile, "adds.%c [$r%u%s, $r%u\n",
1582: memsize_char(memsize),
1583: dc->op1, dc->postinc ? "+]" : "]",
1584: dc->op2));
1585:
1586: /* sign extend. */
1587: cris_cc_mask(dc, CC_MASK_NZVC);
1588: insn_len = dec_prep_alu_m(dc, 1, memsize);
1589: crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
1590: do_postinc(dc, memsize);
1591: return insn_len;
1592: }
1593:
1594: static unsigned int dec_subu_m(DisasContext *dc)
1595: {
1596: int memsize = memsize_z(dc);
1597: int insn_len;
1598: DIS(fprintf (logfile, "subu.%c [$r%u%s, $r%u\n",
1599: memsize_char(memsize),
1600: dc->op1, dc->postinc ? "+]" : "]",
1601: dc->op2));
1602:
1603: /* sign extend. */
1604: cris_cc_mask(dc, CC_MASK_NZVC);
1605: insn_len = dec_prep_alu_m(dc, 0, memsize);
1606: crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
1607: do_postinc(dc, memsize);
1608: return insn_len;
1609: }
1610:
1611: static unsigned int dec_subs_m(DisasContext *dc)
1612: {
1613: int memsize = memsize_z(dc);
1614: int insn_len;
1615: DIS(fprintf (logfile, "subs.%c [$r%u%s, $r%u\n",
1616: memsize_char(memsize),
1617: dc->op1, dc->postinc ? "+]" : "]",
1618: dc->op2));
1619:
1620: /* sign extend. */
1621: cris_cc_mask(dc, CC_MASK_NZVC);
1622: insn_len = dec_prep_alu_m(dc, 1, memsize);
1623: crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
1624: do_postinc(dc, memsize);
1625: return insn_len;
1626: }
1627:
1628: static unsigned int dec_movu_m(DisasContext *dc)
1629: {
1630: int memsize = memsize_z(dc);
1631: int insn_len;
1632:
1633: DIS(fprintf (logfile, "movu.%c [$r%u%s, $r%u\n",
1634: memsize_char(memsize),
1635: dc->op1, dc->postinc ? "+]" : "]",
1636: dc->op2));
1637:
1638: cris_cc_mask(dc, CC_MASK_NZ);
1639: insn_len = dec_prep_alu_m(dc, 0, memsize);
1640: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1641: do_postinc(dc, memsize);
1642: return insn_len;
1643: }
1644:
1645: static unsigned int dec_cmpu_m(DisasContext *dc)
1646: {
1647: int memsize = memsize_z(dc);
1648: int insn_len;
1649: DIS(fprintf (logfile, "cmpu.%c [$r%u%s, $r%u\n",
1650: memsize_char(memsize),
1651: dc->op1, dc->postinc ? "+]" : "]",
1652: dc->op2));
1653:
1654: cris_cc_mask(dc, CC_MASK_NZVC);
1655: insn_len = dec_prep_alu_m(dc, 0, memsize);
1656: crisv32_alu_op(dc, CC_OP_CMP, dc->op2, 4);
1657: do_postinc(dc, memsize);
1658: return insn_len;
1659: }
1660:
1661: static unsigned int dec_cmps_m(DisasContext *dc)
1662: {
1663: int memsize = memsize_z(dc);
1664: int insn_len;
1665: DIS(fprintf (logfile, "cmps.%c [$r%u%s, $r%u\n",
1666: memsize_char(memsize),
1667: dc->op1, dc->postinc ? "+]" : "]",
1668: dc->op2));
1669:
1670: cris_cc_mask(dc, CC_MASK_NZVC);
1671: insn_len = dec_prep_alu_m(dc, 1, memsize);
1672: crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc));
1673: do_postinc(dc, memsize);
1674: return insn_len;
1675: }
1676:
1677: static unsigned int dec_cmp_m(DisasContext *dc)
1678: {
1679: int memsize = memsize_zz(dc);
1680: int insn_len;
1681: DIS(fprintf (logfile, "cmp.%c [$r%u%s, $r%u\n",
1682: memsize_char(memsize),
1683: dc->op1, dc->postinc ? "+]" : "]",
1684: dc->op2));
1685:
1686: cris_cc_mask(dc, CC_MASK_NZVC);
1687: insn_len = dec_prep_alu_m(dc, 0, memsize);
1688: crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc));
1689: do_postinc(dc, memsize);
1690: return insn_len;
1691: }
1692:
1693: static unsigned int dec_test_m(DisasContext *dc)
1694: {
1695: int memsize = memsize_zz(dc);
1696: int insn_len;
1697: DIS(fprintf (logfile, "test.%d [$r%u%s] op2=%x\n",
1698: memsize_char(memsize),
1699: dc->op1, dc->postinc ? "+]" : "]",
1700: dc->op2));
1701:
1702: cris_cc_mask(dc, CC_MASK_NZ);
1703: gen_op_clrf(3);
1704: insn_len = dec_prep_alu_m(dc, 0, memsize);
1705: gen_op_swp_T0_T1();
1706: gen_op_movl_T1_im(0);
1707: crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc));
1708: do_postinc(dc, memsize);
1709: return insn_len;
1710: }
1711:
1712: static unsigned int dec_and_m(DisasContext *dc)
1713: {
1714: int memsize = memsize_zz(dc);
1715: int insn_len;
1716: DIS(fprintf (logfile, "and.%d [$r%u%s, $r%u\n",
1717: memsize_char(memsize),
1718: dc->op1, dc->postinc ? "+]" : "]",
1719: dc->op2));
1720:
1721: cris_cc_mask(dc, CC_MASK_NZ);
1722: insn_len = dec_prep_alu_m(dc, 0, memsize);
1723: crisv32_alu_op(dc, CC_OP_AND, dc->op2, memsize_zz(dc));
1724: do_postinc(dc, memsize);
1725: return insn_len;
1726: }
1727:
1728: static unsigned int dec_add_m(DisasContext *dc)
1729: {
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));
1736:
1737: cris_cc_mask(dc, CC_MASK_NZVC);
1738: insn_len = dec_prep_alu_m(dc, 0, memsize);
1739: crisv32_alu_op(dc, CC_OP_ADD, dc->op2, memsize_zz(dc));
1740: do_postinc(dc, memsize);
1741: return insn_len;
1742: }
1743:
1744: static unsigned int dec_addo_m(DisasContext *dc)
1745: {
1746: int memsize = memsize_zz(dc);
1747: int insn_len;
1748: DIS(fprintf (logfile, "add.%d [$r%u%s, $r%u\n",
1749: memsize_char(memsize),
1750: dc->op1, dc->postinc ? "+]" : "]",
1751: dc->op2));
1752:
1753: cris_cc_mask(dc, 0);
1754: insn_len = dec_prep_alu_m(dc, 1, memsize);
1755: crisv32_alu_op(dc, CC_OP_ADD, REG_ACR, 4);
1756: do_postinc(dc, memsize);
1757: return insn_len;
1758: }
1759:
1760: static unsigned int dec_bound_m(DisasContext *dc)
1761: {
1762: int memsize = memsize_zz(dc);
1763: int insn_len;
1764: DIS(fprintf (logfile, "bound.%d [$r%u%s, $r%u\n",
1765: memsize_char(memsize),
1766: dc->op1, dc->postinc ? "+]" : "]",
1767: dc->op2));
1768:
1769: cris_cc_mask(dc, CC_MASK_NZ);
1770: insn_len = dec_prep_alu_m(dc, 0, memsize);
1771: crisv32_alu_op(dc, CC_OP_BOUND, dc->op2, 4);
1772: do_postinc(dc, memsize);
1773: return insn_len;
1774: }
1775:
1776: static unsigned int dec_addc_mr(DisasContext *dc)
1777: {
1778: int insn_len = 2;
1779: DIS(fprintf (logfile, "addc [$r%u%s, $r%u\n",
1780: dc->op1, dc->postinc ? "+]" : "]",
1781: dc->op2));
1782:
1783: cris_evaluate_flags(dc);
1784: cris_cc_mask(dc, CC_MASK_NZVC);
1785: insn_len = dec_prep_alu_m(dc, 0, 4);
1786: crisv32_alu_op(dc, CC_OP_ADDC, dc->op2, 4);
1787: do_postinc(dc, 4);
1788: return insn_len;
1789: }
1790:
1791: static unsigned int dec_sub_m(DisasContext *dc)
1792: {
1793: int memsize = memsize_zz(dc);
1794: int insn_len;
1795: DIS(fprintf (logfile, "sub.%c [$r%u%s, $r%u ir=%x zz=%x\n",
1796: memsize_char(memsize),
1797: dc->op1, dc->postinc ? "+]" : "]",
1798: dc->op2, dc->ir, dc->zzsize));
1799:
1800: cris_cc_mask(dc, CC_MASK_NZVC);
1801: insn_len = dec_prep_alu_m(dc, 0, memsize);
1802: crisv32_alu_op(dc, CC_OP_SUB, dc->op2, memsize);
1803: do_postinc(dc, memsize);
1804: return insn_len;
1805: }
1806:
1807: static unsigned int dec_or_m(DisasContext *dc)
1808: {
1809: int memsize = memsize_zz(dc);
1810: int insn_len;
1811: DIS(fprintf (logfile, "or.%d [$r%u%s, $r%u pc=%x\n",
1812: memsize_char(memsize),
1813: dc->op1, dc->postinc ? "+]" : "]",
1814: dc->op2, dc->pc));
1815:
1816: cris_cc_mask(dc, CC_MASK_NZ);
1817: insn_len = dec_prep_alu_m(dc, 0, memsize);
1818: crisv32_alu_op(dc, CC_OP_OR, dc->op2, memsize_zz(dc));
1819: do_postinc(dc, memsize);
1820: return insn_len;
1821: }
1822:
1823: static unsigned int dec_move_mp(DisasContext *dc)
1824: {
1825: int memsize = memsize_zz(dc);
1826: int insn_len = 2;
1827:
1828: DIS(fprintf (logfile, "move.%c [$r%u%s, $p%u\n",
1829: memsize_char(memsize),
1830: dc->op1,
1831: dc->postinc ? "+]" : "]",
1832: dc->op2));
1833:
1834: cris_cc_mask(dc, 0);
1835: insn_len = dec_prep_alu_m(dc, 0, memsize);
1836: gen_op_movl_T0_T1();
1837: gen_movl_preg_T0[dc->op2]();
1838:
1839: do_postinc(dc, memsize);
1840: return insn_len;
1841: }
1842:
1843: static unsigned int dec_move_pm(DisasContext *dc)
1844: {
1845: int memsize;
1846:
1847: memsize = preg_sizes[dc->op2];
1848:
1849: DIS(fprintf (logfile, "move.%d $p%u, [$r%u%s\n",
1850: memsize, dc->op2, dc->op1, dc->postinc ? "+]" : "]"));
1851:
1852: cris_cc_mask(dc, 0);
1853: /* prepare store. */
1854: gen_movl_T0_preg[dc->op2]();
1855: gen_op_movl_T1_T0();
1856: gen_movl_T0_reg[dc->op1]();
1857: gen_store_T0_T1(dc, memsize);
1858: if (dc->postinc)
1859: {
1860: gen_op_addl_T0_im(memsize);
1861: gen_movl_reg_T0[dc->op1]();
1862: }
1863: return 2;
1864: }
1865:
1866: static unsigned int dec_movem_mr(DisasContext *dc)
1867: {
1868: int i;
1869:
1870: DIS(fprintf (logfile, "movem [$r%u%s, $r%u\n", dc->op1,
1871: dc->postinc ? "+]" : "]", dc->op2));
1872:
1873: cris_cc_mask(dc, 0);
1874: /* fetch the address into T1. */
1875: gen_movl_T0_reg[dc->op1]();
1876: gen_op_movl_T1_T0();
1877: for (i = 0; i <= dc->op2; i++) {
1878: /* Perform the load onto regnum i. Always dword wide. */
1879: gen_load_T0_T0(dc, 4, 0);
1880: gen_movl_reg_T0[i]();
1881: /* Update the address. */
1882: gen_op_addl_T1_im(4);
1883: gen_op_movl_T0_T1();
1884: }
1885: if (dc->postinc) {
1886: /* writeback the updated pointer value. */
1887: gen_movl_reg_T0[dc->op1]();
1888: }
1889: return 2;
1890: }
1891:
1892: static unsigned int dec_movem_rm(DisasContext *dc)
1893: {
1894: int i;
1895:
1896: DIS(fprintf (logfile, "movem $r%u, [$r%u%s\n", dc->op2, dc->op1,
1897: dc->postinc ? "+]" : "]"));
1898:
1899: cris_cc_mask(dc, 0);
1900: for (i = 0; i <= dc->op2; i++) {
1901: /* Fetch register i into T1. */
1902: gen_movl_T0_reg[i]();
1903: gen_op_movl_T1_T0();
1904:
1905: /* Fetch the address into T0. */
1906: gen_movl_T0_reg[dc->op1]();
1907: /* Displace it. */
1908: gen_op_addl_T0_im(i * 4);
1909:
1910: /* Perform the store. */
1911: gen_store_T0_T1(dc, 4);
1912: }
1913: if (dc->postinc) {
1914: /* Update the address. */
1915: gen_op_addl_T0_im(4);
1916: /* writeback the updated pointer value. */
1917: gen_movl_reg_T0[dc->op1]();
1918: }
1919: return 2;
1920: }
1921:
1922: static unsigned int dec_move_rm(DisasContext *dc)
1923: {
1924: int memsize;
1925:
1926: memsize = memsize_zz(dc);
1927:
1928: DIS(fprintf (logfile, "move.%d $r%u, [$r%u]\n",
1929: memsize, dc->op2, dc->op1));
1930:
1931: cris_cc_mask(dc, 0);
1932: /* prepare store. */
1933: gen_movl_T0_reg[dc->op2]();
1934: gen_op_movl_T1_T0();
1935: gen_movl_T0_reg[dc->op1]();
1936: gen_store_T0_T1(dc, memsize);
1937: if (dc->postinc)
1938: {
1939: gen_op_addl_T0_im(memsize);
1940: gen_movl_reg_T0[dc->op1]();
1941: }
1942: return 2;
1943: }
1944:
1945:
1946: static unsigned int dec_lapcq(DisasContext *dc)
1947: {
1948: DIS(fprintf (logfile, "lapcq %x, $r%u\n",
1949: dc->pc + dc->op1*2, dc->op2));
1950: cris_cc_mask(dc, 0);
1951: gen_op_movl_T1_im(dc->pc + dc->op1*2);
1952: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
1953: return 2;
1954: }
1955:
1956: static unsigned int dec_lapc_im(DisasContext *dc)
1957: {
1958: unsigned int rd;
1959: int32_t imm;
1960: int insn_len = 6;
1961:
1962: rd = dc->op2;
1963:
1964: cris_cc_mask(dc, 0);
1965: imm = ldl_code(dc->pc + 2);
1966: DIS(fprintf (logfile, "lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2));
1967: gen_op_movl_T0_im (dc->pc + imm);
1968: gen_movl_reg_T0[rd] ();
1969: return insn_len;
1970: }
1971:
1972: /* Jump to special reg. */
1973: static unsigned int dec_jump_p(DisasContext *dc)
1974: {
1975: DIS(fprintf (logfile, "jump $p%u\n", dc->op2));
1976: cris_cc_mask(dc, 0);
1977: /* Store the return address in Pd. */
1978: gen_movl_T0_preg[dc->op2]();
1979: gen_op_movl_btarget_T0();
1980: cris_prepare_dyn_jmp(dc);
1981: return 2;
1982: }
1983:
1984: /* Jump and save. */
1985: static unsigned int dec_jas_r(DisasContext *dc)
1986: {
1987: DIS(fprintf (logfile, "jas $r%u, $p%u\n", dc->op1, dc->op2));
1988: cris_cc_mask(dc, 0);
1989: /* Stor the return address in Pd. */
1990: gen_movl_T0_reg[dc->op1]();
1991: gen_op_movl_btarget_T0();
1992: gen_op_movl_T0_im(dc->pc + 4);
1993: gen_movl_preg_T0[dc->op2]();
1994: cris_prepare_dyn_jmp(dc);
1995: return 2;
1996: }
1997:
1998: static unsigned int dec_jas_im(DisasContext *dc)
1999: {
2000: uint32_t imm;
2001:
2002: imm = ldl_code(dc->pc + 2);
2003:
2004: DIS(fprintf (logfile, "jas 0x%x\n", imm));
2005: cris_cc_mask(dc, 0);
2006: /* Stor the return address in Pd. */
2007: gen_op_movl_T0_im(imm);
2008: gen_op_movl_btarget_T0();
2009: gen_op_movl_T0_im(dc->pc + 8);
2010: gen_movl_preg_T0[dc->op2]();
2011: cris_prepare_dyn_jmp(dc);
2012: return 6;
2013: }
2014:
2015: static unsigned int dec_jasc_im(DisasContext *dc)
2016: {
2017: uint32_t imm;
2018:
2019: imm = ldl_code(dc->pc + 2);
2020:
2021: DIS(fprintf (logfile, "jasc 0x%x\n", imm));
2022: cris_cc_mask(dc, 0);
2023: /* Stor the return address in Pd. */
2024: gen_op_movl_T0_im(imm);
2025: gen_op_movl_btarget_T0();
2026: gen_op_movl_T0_im(dc->pc + 8 + 4);
2027: gen_movl_preg_T0[dc->op2]();
2028: cris_prepare_dyn_jmp(dc);
2029: return 6;
2030: }
2031:
2032: static unsigned int dec_jasc_r(DisasContext *dc)
2033: {
2034: DIS(fprintf (logfile, "jasc_r $r%u, $p%u\n", dc->op1, dc->op2));
2035: cris_cc_mask(dc, 0);
2036: /* Stor the return address in Pd. */
2037: gen_movl_T0_reg[dc->op1]();
2038: gen_op_movl_btarget_T0();
2039: gen_op_movl_T0_im(dc->pc + 4 + 4);
2040: gen_movl_preg_T0[dc->op2]();
2041: cris_prepare_dyn_jmp(dc);
2042: return 2;
2043: }
2044:
2045: static unsigned int dec_bcc_im(DisasContext *dc)
2046: {
2047: int32_t offset;
2048: uint32_t cond = dc->op2;
2049:
2050: offset = ldl_code(dc->pc + 2);
2051: offset = sign_extend(offset, 15);
2052:
2053: DIS(fprintf (logfile, "b%s %d pc=%x dst=%x\n",
2054: cc_name(cond), offset,
2055: dc->pc, dc->pc + offset));
2056:
2057: cris_cc_mask(dc, 0);
2058: /* op2 holds the condition-code. */
2059: cris_prepare_cc_branch (dc, offset, cond);
2060: return 4;
2061: }
2062:
2063: static unsigned int dec_bas_im(DisasContext *dc)
2064: {
2065: int32_t simm;
2066:
2067:
2068: simm = ldl_code(dc->pc + 2);
2069:
2070: DIS(fprintf (logfile, "bas 0x%x, $p%u\n", dc->pc + simm, dc->op2));
2071: cris_cc_mask(dc, 0);
2072: /* Stor the return address in Pd. */
2073: gen_op_movl_T0_im(dc->pc + simm);
2074: gen_op_movl_btarget_T0();
2075: gen_op_movl_T0_im(dc->pc + 8);
2076: gen_movl_preg_T0[dc->op2]();
2077: cris_prepare_dyn_jmp(dc);
2078: return 6;
2079: }
2080:
2081: static unsigned int dec_basc_im(DisasContext *dc)
2082: {
2083: int32_t simm;
2084: simm = ldl_code(dc->pc + 2);
2085:
2086: DIS(fprintf (logfile, "basc 0x%x, $p%u\n", dc->pc + simm, dc->op2));
2087: cris_cc_mask(dc, 0);
2088: /* Stor the return address in Pd. */
2089: gen_op_movl_T0_im(dc->pc + simm);
2090: gen_op_movl_btarget_T0();
2091: gen_op_movl_T0_im(dc->pc + 12);
2092: gen_movl_preg_T0[dc->op2]();
2093: cris_prepare_dyn_jmp(dc);
2094: return 6;
2095: }
2096:
2097: static unsigned int dec_rfe_etc(DisasContext *dc)
2098: {
2099: DIS(fprintf (logfile, "rfe_etc opc=%x pc=0x%x op1=%d op2=%d\n",
2100: dc->opcode, dc->pc, dc->op1, dc->op2));
2101:
2102: cris_cc_mask(dc, 0);
2103:
2104: if (dc->op2 == 15) /* ignore halt. */
2105: goto done;
2106:
2107: switch (dc->op2 & 7) {
2108: case 2:
2109: /* rfe. */
2110: cris_evaluate_flags(dc);
2111: gen_op_ccs_rshift();
2112: break;
2113: case 5:
2114: /* rfn. */
2115: BUG();
2116: break;
2117: case 6:
2118: /* break. */
2119: gen_op_movl_T0_im(dc->pc);
2120: gen_op_movl_pc_T0();
2121: /* Breaks start at 16 in the exception vector. */
2122: gen_op_break_im(dc->op1 + 16);
2123: break;
2124: default:
2125: printf ("op2=%x\n", dc->op2);
2126: BUG();
2127: break;
2128:
2129: }
2130: done:
2131: return 2;
2132: }
2133:
2134: static unsigned int dec_null(DisasContext *dc)
2135: {
2136: printf ("unknown insn pc=%x opc=%x op1=%x op2=%x\n",
2137: dc->pc, dc->opcode, dc->op1, dc->op2);
2138: fflush(NULL);
2139: BUG();
2140: return 2;
2141: }
2142:
2143: struct decoder_info {
2144: struct {
2145: uint32_t bits;
2146: uint32_t mask;
2147: };
2148: unsigned int (*dec)(DisasContext *dc);
2149: } decinfo[] = {
2150: /* Order matters here. */
2151: {DEC_MOVEQ, dec_moveq},
2152: {DEC_BTSTQ, dec_btstq},
2153: {DEC_CMPQ, dec_cmpq},
2154: {DEC_ADDOQ, dec_addoq},
2155: {DEC_ADDQ, dec_addq},
2156: {DEC_SUBQ, dec_subq},
2157: {DEC_ANDQ, dec_andq},
2158: {DEC_ORQ, dec_orq},
2159: {DEC_ASRQ, dec_asrq},
2160: {DEC_LSLQ, dec_lslq},
2161: {DEC_LSRQ, dec_lsrq},
2162: {DEC_BCCQ, dec_bccq},
2163:
2164: {DEC_BCC_IM, dec_bcc_im},
2165: {DEC_JAS_IM, dec_jas_im},
2166: {DEC_JAS_R, dec_jas_r},
2167: {DEC_JASC_IM, dec_jasc_im},
2168: {DEC_JASC_R, dec_jasc_r},
2169: {DEC_BAS_IM, dec_bas_im},
2170: {DEC_BASC_IM, dec_basc_im},
2171: {DEC_JUMP_P, dec_jump_p},
2172: {DEC_LAPC_IM, dec_lapc_im},
2173: {DEC_LAPCQ, dec_lapcq},
2174:
2175: {DEC_RFE_ETC, dec_rfe_etc},
2176: {DEC_ADDC_MR, dec_addc_mr},
2177:
2178: {DEC_MOVE_MP, dec_move_mp},
2179: {DEC_MOVE_PM, dec_move_pm},
2180: {DEC_MOVEM_MR, dec_movem_mr},
2181: {DEC_MOVEM_RM, dec_movem_rm},
2182: {DEC_MOVE_PR, dec_move_pr},
2183: {DEC_SCC_R, dec_scc_r},
2184: {DEC_SETF, dec_setclrf},
2185: {DEC_CLEARF, dec_setclrf},
2186:
2187: {DEC_MOVE_SR, dec_move_sr},
2188: {DEC_MOVE_RP, dec_move_rp},
2189: {DEC_SWAP_R, dec_swap_r},
2190: {DEC_ABS_R, dec_abs_r},
2191: {DEC_LZ_R, dec_lz_r},
2192: {DEC_MOVE_RS, dec_move_rs},
2193: {DEC_BTST_R, dec_btst_r},
2194: {DEC_ADDC_R, dec_addc_r},
2195:
2196: {DEC_DSTEP_R, dec_dstep_r},
2197: {DEC_XOR_R, dec_xor_r},
2198: {DEC_MCP_R, dec_mcp_r},
2199: {DEC_CMP_R, dec_cmp_r},
2200:
2201: {DEC_ADDI_R, dec_addi_r},
2202: {DEC_ADDI_ACR, dec_addi_acr},
2203:
2204: {DEC_ADD_R, dec_add_r},
2205: {DEC_SUB_R, dec_sub_r},
2206:
2207: {DEC_ADDU_R, dec_addu_r},
2208: {DEC_ADDS_R, dec_adds_r},
2209: {DEC_SUBU_R, dec_subu_r},
2210: {DEC_SUBS_R, dec_subs_r},
2211: {DEC_LSL_R, dec_lsl_r},
2212:
2213: {DEC_AND_R, dec_and_r},
2214: {DEC_OR_R, dec_or_r},
2215: {DEC_BOUND_R, dec_bound_r},
2216: {DEC_ASR_R, dec_asr_r},
2217: {DEC_LSR_R, dec_lsr_r},
2218:
2219: {DEC_MOVU_R, dec_movu_r},
2220: {DEC_MOVS_R, dec_movs_r},
2221: {DEC_NEG_R, dec_neg_r},
2222: {DEC_MOVE_R, dec_move_r},
2223:
2224: /* ftag_fidx_i_m. */
2225: /* ftag_fidx_d_m. */
2226:
2227: {DEC_MULS_R, dec_muls_r},
2228: {DEC_MULU_R, dec_mulu_r},
2229:
2230: {DEC_ADDU_M, dec_addu_m},
2231: {DEC_ADDS_M, dec_adds_m},
2232: {DEC_SUBU_M, dec_subu_m},
2233: {DEC_SUBS_M, dec_subs_m},
2234:
2235: {DEC_CMPU_M, dec_cmpu_m},
2236: {DEC_CMPS_M, dec_cmps_m},
2237: {DEC_MOVU_M, dec_movu_m},
2238: {DEC_MOVS_M, dec_movs_m},
2239:
2240: {DEC_CMP_M, dec_cmp_m},
2241: {DEC_ADDO_M, dec_addo_m},
2242: {DEC_BOUND_M, dec_bound_m},
2243: {DEC_ADD_M, dec_add_m},
2244: {DEC_SUB_M, dec_sub_m},
2245: {DEC_AND_M, dec_and_m},
2246: {DEC_OR_M, dec_or_m},
2247: {DEC_MOVE_RM, dec_move_rm},
2248: {DEC_TEST_M, dec_test_m},
2249: {DEC_MOVE_MR, dec_move_mr},
2250:
2251: {{0, 0}, dec_null}
2252: };
2253:
2254: static inline unsigned int
2255: cris_decoder(DisasContext *dc)
2256: {
2257: unsigned int insn_len = 2;
2258: uint32_t tmp;
2259: int i;
2260:
2261: /* Load a halfword onto the instruction register. */
2262: tmp = ldl_code(dc->pc);
2263: dc->ir = tmp & 0xffff;
2264:
2265: /* Now decode it. */
2266: dc->opcode = EXTRACT_FIELD(dc->ir, 4, 11);
2267: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 3);
2268: dc->op2 = EXTRACT_FIELD(dc->ir, 12, 15);
2269: dc->zsize = EXTRACT_FIELD(dc->ir, 4, 4);
2270: dc->zzsize = EXTRACT_FIELD(dc->ir, 4, 5);
2271: dc->postinc = EXTRACT_FIELD(dc->ir, 10, 10);
2272:
2273: /* Large switch for all insns. */
2274: for (i = 0; i < sizeof decinfo / sizeof decinfo[0]; i++) {
2275: if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits)
2276: {
2277: insn_len = decinfo[i].dec(dc);
2278: break;
2279: }
2280: }
2281:
2282: return insn_len;
2283: }
2284:
2285: static void check_breakpoint(CPUState *env, DisasContext *dc)
2286: {
2287: int j;
2288: if (env->nb_breakpoints > 0) {
2289: for(j = 0; j < env->nb_breakpoints; j++) {
2290: if (env->breakpoints[j] == dc->pc) {
2291: cris_evaluate_flags (dc);
2292: gen_op_movl_T0_im((long)dc->pc);
2293: gen_op_movl_pc_T0();
2294: gen_op_debug();
2295: dc->is_jmp = DISAS_UPDATE;
2296: }
2297: }
2298: }
2299: }
2300:
2301:
2302: /* generate intermediate code for basic block 'tb'. */
2303: struct DisasContext ctx;
2304: static int
2305: gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
2306: int search_pc)
2307: {
2308: uint16_t *gen_opc_end;
2309: uint32_t pc_start;
2310: unsigned int insn_len;
2311: int j, lj;
2312: struct DisasContext *dc = &ctx;
2313: uint32_t next_page_start;
2314:
2315: pc_start = tb->pc;
2316: dc->env = env;
2317: dc->tb = tb;
2318:
2319: gen_opc_ptr = gen_opc_buf;
2320: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2321: gen_opparam_ptr = gen_opparam_buf;
2322:
2323: dc->is_jmp = DISAS_NEXT;
2324: dc->pc = pc_start;
2325: dc->singlestep_enabled = env->singlestep_enabled;
2326: dc->flagx_live = 0;
2327: dc->flags_x = 0;
2328: next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
2329: lj = -1;
2330: do
2331: {
2332: check_breakpoint(env, dc);
2333: if (dc->is_jmp == DISAS_JUMP)
2334: goto done;
2335:
2336: if (search_pc) {
2337: j = gen_opc_ptr - gen_opc_buf;
2338: if (lj < j) {
2339: lj++;
2340: while (lj < j)
2341: gen_opc_instr_start[lj++] = 0;
2342: }
2343: gen_opc_pc[lj] = dc->pc;
2344: gen_opc_instr_start[lj] = 1;
2345: }
2346:
2347: insn_len = cris_decoder(dc);
2348: STATS(gen_op_exec_insn());
2349: dc->pc += insn_len;
2350: if (!dc->flagx_live
2351: || (dc->flagx_live &&
2352: !(dc->cc_op == CC_OP_FLAGS && dc->flags_x))) {
2353: gen_movl_T0_preg[SR_CCS]();
2354: gen_op_andl_T0_im(~X_FLAG);
2355: gen_movl_preg_T0[SR_CCS]();
2356: dc->flagx_live = 1;
2357: dc->flags_x = 0;
2358: }
2359:
2360: /* Check for delayed branches here. If we do it before
2361: actually genereating any host code, the simulator will just
2362: loop doing nothing for on this program location. */
2363: if (dc->delayed_branch) {
2364: dc->delayed_branch--;
2365: if (dc->delayed_branch == 0)
2366: {
2367: if (dc->bcc == CC_A) {
2368: gen_op_jmp ();
2369: dc->is_jmp = DISAS_UPDATE;
2370: }
2371: else {
2372: /* Conditional jmp. */
2373: gen_op_cc_jmp (dc->delayed_pc, dc->pc);
2374: dc->is_jmp = DISAS_UPDATE;
2375: }
2376: }
2377: }
2378:
2379: if (env->singlestep_enabled)
2380: break;
2381: } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end
2382: && dc->pc < next_page_start);
2383:
2384: if (!dc->is_jmp) {
2385: gen_op_movl_T0_im((long)dc->pc);
2386: gen_op_movl_pc_T0();
2387: }
2388:
2389: cris_evaluate_flags (dc);
2390: done:
2391: if (__builtin_expect(env->singlestep_enabled, 0)) {
2392: gen_op_debug();
2393: } else {
2394: switch(dc->is_jmp) {
2395: case DISAS_NEXT:
2396: gen_goto_tb(dc, 1, dc->pc);
2397: break;
2398: default:
2399: case DISAS_JUMP:
2400: case DISAS_UPDATE:
2401: /* indicate that the hash table must be used
2402: to find the next TB */
2403: /* T0 is used to index the jmp tables. */
2404: gen_op_movl_T0_0();
2405: gen_op_exit_tb();
2406: break;
2407: case DISAS_TB_JUMP:
2408: /* nothing more to generate */
2409: break;
2410: }
2411: }
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;
2420: }
2421:
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");
2428: if (loglevel & CPU_LOG_TB_OP) {
2429: fprintf(logfile, "OP:\n");
2430: dump_ops(gen_opc_buf, gen_opparam_buf);
2431: fprintf(logfile, "\n");
2432: }
2433: }
2434: #endif
2435: return 0;
2436: }
2437:
2438: int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
2439: {
2440: return gen_intermediate_code_internal(env, tb, 0);
2441: }
2442:
2443: int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
2444: {
2445: return gen_intermediate_code_internal(env, tb, 1);
2446: }
2447:
2448: void cpu_dump_state (CPUState *env, FILE *f,
2449: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2450: int flags)
2451: {
2452: int i;
2453: uint32_t srs;
2454:
2455: if (!env || !f)
2456: return;
2457:
2458: cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
2459: "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n"
2460: "debug=%x %x %x\n",
2461: env->pc, env->pregs[SR_CCS], env->btaken, env->btarget,
2462: env->cc_op,
2463: env->cc_src, env->cc_dest, env->cc_result, env->cc_mask,
2464: env->debug1, env->debug2, env->debug3);
2465:
2466: for (i = 0; i < 16; i++) {
2467: cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
2468: if ((i + 1) % 4 == 0)
2469: cpu_fprintf(f, "\n");
2470: }
2471: cpu_fprintf(f, "\nspecial regs:\n");
2472: for (i = 0; i < 16; i++) {
2473: cpu_fprintf(f, "p%2.2d=%8.8x ", i, env->pregs[i]);
2474: if ((i + 1) % 4 == 0)
2475: cpu_fprintf(f, "\n");
2476: }
2477: srs = env->pregs[SR_SRS];
2478: cpu_fprintf(f, "\nsupport function regs bank %d:\n", srs);
2479: if (srs < 256) {
2480: for (i = 0; i < 16; i++) {
2481: cpu_fprintf(f, "s%2.2d=%8.8x ",
2482: i, env->sregs[srs][i]);
2483: if ((i + 1) % 4 == 0)
2484: cpu_fprintf(f, "\n");
2485: }
2486: }
2487: cpu_fprintf(f, "\n\n");
2488:
2489: }
2490:
2491: CPUCRISState *cpu_cris_init (const char *cpu_model)
2492: {
2493: CPUCRISState *env;
2494:
2495: env = qemu_mallocz(sizeof(CPUCRISState));
2496: if (!env)
2497: return NULL;
2498: cpu_exec_init(env);
2499: cpu_reset(env);
2500: return env;
2501: }
2502:
2503: void cpu_reset (CPUCRISState *env)
2504: {
2505: memset(env, 0, offsetof(CPUCRISState, breakpoints));
2506: tlb_flush(env, 1);
2507: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.