]> git.proxmox.com Git - qemu.git/blame - target-cris/translate.c
More consistent naming for CRIS register-number macros.
[qemu.git] / target-cris / translate.c
CommitLineData
8170028d
TS
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"
57fec1fe 54#include "tcg-op.h"
8170028d
TS
55#include "crisv32-decode.h"
56
57#define CRIS_STATS 0
58#if CRIS_STATS
59#define STATS(x) x
60#else
61#define STATS(x)
62#endif
63
64#define DISAS_CRIS 0
65#if DISAS_CRIS
66#define DIS(x) x
67#else
68#define DIS(x)
69#endif
70
8170028d
TS
71#define BUG() (gen_BUG(dc, __FILE__, __LINE__))
72#define BUG_ON(x) ({if (x) BUG();})
73
74/* Used by the decoder. */
75#define EXTRACT_FIELD(src, start, end) \
76 (((src) >> start) & ((1 << (end - start + 1)) - 1))
77
78#define CC_MASK_NZ 0xc
79#define CC_MASK_NZV 0xe
80#define CC_MASK_NZVC 0xf
81#define CC_MASK_RNZV 0x10e
82
8170028d
TS
83/* This is the state at translation time. */
84typedef struct DisasContext {
85 CPUState *env;
86 target_ulong pc, insn_pc;
87
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;
96
8170028d
TS
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;
105
106 int memidx; /* user or kernel mode. */
107 int is_jmp;
108 int dyn_jmp;
109
110 uint32_t delayed_pc;
111 int delayed_branch;
112 int bcc;
113 uint32_t condlabel;
114
115 struct TranslationBlock *tb;
116 int singlestep_enabled;
117} DisasContext;
118
119void cris_prepare_jmp (DisasContext *dc, uint32_t dst);
120static void gen_BUG(DisasContext *dc, char *file, int line)
121{
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);
127}
128
129/* Table to generate quick moves from T0 onto any register. */
130static GenOpFunc *gen_movl_reg_T0[16] =
131{
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,
140};
141static GenOpFunc *gen_movl_T0_reg[16] =
142{
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,
151};
152
153static void noop_write(void) {
154 /* nop. */
155}
156
157static void gen_vr_read(void) {
158 gen_op_movl_T0_im(32);
159}
160
fd56059f
AZ
161static void gen_movl_T0_p0(void) {
162 gen_op_movl_T0_im(0);
163}
164
8170028d
TS
165static void gen_ccs_read(void) {
166 gen_op_movl_T0_p13();
167}
168
169static void gen_ccs_write(void) {
170 gen_op_movl_p13_T0();
171}
172
173/* Table to generate quick moves from T0 onto any register. */
174static GenOpFunc *gen_movl_preg_T0[16] =
175{
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,
188};
189static GenOpFunc *gen_movl_T0_preg[16] =
190{
fd56059f 191 gen_movl_T0_p0,
8170028d
TS
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,
201};
202
203/* We need this table to handle moves with implicit width. */
204int 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,
213};
214
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(); \
219 }
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(); \
223 }
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();\
229 }
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();\
234 }
235#endif
236
237GEN_OP_LD(ub, T0)
238GEN_OP_LD(b, T0)
239GEN_OP_ST(b, T0)
240GEN_OP_LD(uw, T0)
241GEN_OP_LD(w, T0)
242GEN_OP_ST(w, T0)
243GEN_OP_LD(l, T0)
244GEN_OP_ST(l, T0)
245
246static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
247{
248 TranslationBlock *tb;
249 tb = dc->tb;
250 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
57fec1fe
FB
251#if 0
252 /* XXX: this code is not finished */
253 tcg_gen_goto_tb(n);
254#endif
255 tcg_gen_exit_tb(0);
8170028d 256 } else {
57fec1fe 257 tcg_gen_exit_tb(0);
8170028d 258 }
8170028d
TS
259}
260
261/* Sign extend at translation time. */
262static int sign_extend(unsigned int val, unsigned int width)
263{
264 int sval;
265
266 /* LSL. */
267 val <<= 31 - width;
268 sval = val;
269 /* ASR. */
270 sval >>= 31 - width;
271 return sval;
272}
273
274static void cris_evaluate_flags(DisasContext *dc)
275{
276 if (!dc->flags_live) {
277
278 switch (dc->cc_op)
279 {
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)
291 {
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;
301 }
302 break;
303
304 default:
305 {
306 switch (dc->cc_size)
307 {
308 case 4:
309 gen_op_evaluate_flags_alu_4 ();
310 break;
311 default:
312 gen_op_evaluate_flags ();
313 break;
314 }
315 }
316 break;
317 }
318 dc->flags_live = 1;
319 }
320}
321
322static void cris_cc_mask(DisasContext *dc, unsigned int mask)
323{
324 uint32_t ovl;
325
fd56059f
AZ
326 /* Check if we need to evaluate the condition codes due to
327 CC overlaying. */
8170028d
TS
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);
332 }
333 dc->cc_mask = mask;
334
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;
341 }
342}
343
344static void cris_update_cc_op(DisasContext *dc, int op)
345{
346 dc->cc_op = op;
347 gen_op_update_cc_op(op);
348 dc->flags_live = 0;
349}
350static void cris_update_cc_size(DisasContext *dc, int size)
351{
352 dc->cc_size = size;
353 gen_op_update_cc_size_im(size);
354}
355
356/* op is the operation.
357 T0, T1 are the operands.
358 dst is the destination reg.
359*/
360static void crisv32_alu_op(DisasContext *dc, int op, int rd, int size)
361{
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();
368 }
369
370 /* Emit the ALU insns. */
371 switch (op)
372 {
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();
395
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();
453
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;
462 }
463
464 if (dc->update_cc)
465 gen_op_update_cc_src_T1();
466
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();
485 }
486 }
487 if (dc->update_cc)
488 gen_op_update_cc_result_T0();
489
490 {
491 /* TODO: Optimize this. */
492 if (!dc->flagx_live)
493 cris_evaluate_flags(dc);
494 }
495}
496
497static int arith_cc(DisasContext *dc)
498{
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;
509 }
510 }
511 return 0;
512}
513
514static void gen_tst_cc (DisasContext *dc, int cond)
515{
516 int arith_opt;
517
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 ();
527 }
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 ();
535 }
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 ();
559 }
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 ();
567 }
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;
604 };
605}
606
607static void cris_prepare_cc_branch (DisasContext *dc, int offset, int cond)
608{
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)
615 {
616 gen_tst_cc (dc, cond);
617 gen_op_evaluate_bcc ();
618 }
619 gen_op_movl_T0_im (dc->delayed_pc);
620 gen_op_movl_btarget_T0 ();
621}
622
623/* Dynamic jumps, when the dest is in a live reg for example. */
624void cris_prepare_dyn_jmp (DisasContext *dc)
625{
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;
631}
632
633void cris_prepare_jmp (DisasContext *dc, uint32_t dst)
634{
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;
641}
642
643void gen_load_T0_T0 (DisasContext *dc, unsigned int size, int sign)
644{
645 if (size == 1) {
646 if (sign)
647 gen_op_ldb_T0_T0(dc);
648 else
649 gen_op_ldub_T0_T0(dc);
650 }
651 else if (size == 2) {
652 if (sign)
653 gen_op_ldw_T0_T0(dc);
654 else
655 gen_op_lduw_T0_T0(dc);
656 }
657 else {
658 gen_op_ldl_T0_T0(dc);
659 }
660}
661
662void gen_store_T0_T1 (DisasContext *dc, unsigned int size)
663{
664 /* Remember, operands are flipped. CRIS has reversed order. */
665 if (size == 1) {
666 gen_op_stb_T0_T1(dc);
667 }
668 else if (size == 2) {
669 gen_op_stw_T0_T1(dc);
670 }
671 else
672 gen_op_stl_T0_T1(dc);
673}
674
675/* sign extend T1 according to size. */
676static void gen_sext_T1_T0(int size)
677{
678 if (size == 1)
679 gen_op_extb_T1_T0();
680 else if (size == 2)
681 gen_op_extw_T1_T0();
682}
683
684static void gen_sext_T1_T1(int size)
685{
686 if (size == 1)
687 gen_op_extb_T1_T1();
688 else if (size == 2)
689 gen_op_extw_T1_T1();
690}
691
692static void gen_sext_T0_T0(int size)
693{
694 if (size == 1)
695 gen_op_extb_T0_T0();
696 else if (size == 2)
697 gen_op_extw_T0_T0();
698}
699
700static void gen_zext_T0_T0(int size)
701{
702 if (size == 1)
703 gen_op_zextb_T0_T0();
704 else if (size == 2)
705 gen_op_zextw_T0_T0();
706}
707
708static void gen_zext_T1_T0(int size)
709{
710 if (size == 1)
711 gen_op_zextb_T1_T0();
712 else if (size == 2)
713 gen_op_zextw_T1_T0();
714}
715
716static void gen_zext_T1_T1(int size)
717{
718 if (size == 1)
719 gen_op_zextb_T1_T1();
720 else if (size == 2)
721 gen_op_zextw_T1_T1();
722}
723
724#if DISAS_CRIS
725static char memsize_char(int size)
726{
727 switch (size)
728 {
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;
735 }
736}
737#endif
738
739static unsigned int memsize_z(DisasContext *dc)
740{
741 return dc->zsize + 1;
742}
743
744static unsigned int memsize_zz(DisasContext *dc)
745{
746 switch (dc->zzsize)
747 {
748 case 0: return 1;
749 case 1: return 2;
750 default:
751 return 4;
752 }
753}
754
755static void do_postinc (DisasContext *dc, int size)
756{
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]();
762}
763
764
765static void dec_prep_move_r(DisasContext *dc, int rs, int rd,
766 int size, int s_ext)
767{
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);
774}
775
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. */
779static void dec_prep_alu_r(DisasContext *dc, int rs, int rd,
780 int size, int s_ext)
781{
782 dec_prep_move_r(dc, rs, rd, size, s_ext);
783
784 gen_movl_T0_reg[rd]();
785 if (s_ext)
786 gen_sext_T0_T0(size);
787 else
788 gen_zext_T0_T0(size);
789}
790
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. */
794static int dec_prep_alu_m(DisasContext *dc, int s_ext, int memsize)
795{
796 unsigned int rs, rd;
797 uint32_t imm;
798 int is_imm;
799 int insn_len = 2;
800
801 rs = dc->op1;
802 rd = dc->op2;
803 is_imm = rs == 15 && dc->postinc;
804
805 /* Load [$rs] onto T1. */
806 if (is_imm) {
807 insn_len = 2 + memsize;
808 if (memsize == 1)
809 insn_len++;
810
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;
820 }
821 }
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);
834 }
835
836 /* put dest in T0. */
837 gen_movl_T0_reg[rd]();
838 return insn_len;
839}
840
841#if DISAS_CRIS
842static const char *cc_name(int cc)
843{
844 static char *cc_names[16] = {
845 "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi",
846 "ls", "hi", "ge", "lt", "gt", "le", "a", "p"
847 };
848 assert(cc < 16);
849 return cc_names[cc];
850}
851#endif
852
853static unsigned int dec_bccq(DisasContext *dc)
854{
855 int32_t offset;
856 int sign;
857 uint32_t cond = dc->op2;
858 int tmp;
859
860 offset = EXTRACT_FIELD (dc->ir, 1, 7);
861 sign = EXTRACT_FIELD(dc->ir, 0, 0);
862
863 offset *= 2;
864 offset |= sign << 8;
865 tmp = offset;
866 offset = sign_extend(offset, 8);
867
868 /* op2 holds the condition-code. */
869 cris_cc_mask(dc, 0);
870 cris_prepare_cc_branch (dc, offset, cond);
871 return 2;
872}
873static unsigned int dec_addoq(DisasContext *dc)
874{
875 uint32_t imm;
876
877 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 7);
878 imm = sign_extend(dc->op1, 7);
879
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);
9004627f 885 crisv32_alu_op(dc, CC_OP_ADD, R_ACR, 4);
8170028d
TS
886 return 2;
887}
888static unsigned int dec_addq(DisasContext *dc)
889{
890 DIS(fprintf (logfile, "addq %u, $r%u\n", dc->op1, dc->op2));
891
892 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
893
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;
900}
901static unsigned int dec_moveq(DisasContext *dc)
902{
903 uint32_t imm;
904
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));
908
909 cris_cc_mask(dc, 0);
910 gen_op_movl_T1_im(imm);
911 crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
912
913 return 2;
914}
915static unsigned int dec_subq(DisasContext *dc)
916{
917 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
918
919 DIS(fprintf (logfile, "subq %u, $r%u\n", dc->op1, dc->op2));
920
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;
927}
928static unsigned int dec_cmpq(DisasContext *dc)
929{
930 uint32_t imm;
931 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
932 imm = sign_extend(dc->op1, 5);
933
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;
940}
941static unsigned int dec_andq(DisasContext *dc)
942{
943 uint32_t imm;
944 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
945 imm = sign_extend(dc->op1, 5);
946
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;
953}
954static unsigned int dec_orq(DisasContext *dc)
955{
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;
965}
966static unsigned int dec_btstq(DisasContext *dc)
967{
968 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
969 DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2));
8170028d
TS
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);
974
975 cris_update_cc_op(dc, CC_OP_FLAGS);
976 gen_op_movl_flags_T0();
977 dc->flags_live = 1;
978 return 2;
979}
980static unsigned int dec_asrq(DisasContext *dc)
981{
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;
989}
990static unsigned int dec_lslq(DisasContext *dc)
991{
992 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
993 DIS(fprintf (logfile, "lslq %u, $r%d\n", dc->op1, dc->op2));
994
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;
1000}
1001static unsigned int dec_lsrq(DisasContext *dc)
1002{
1003 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
1004 DIS(fprintf (logfile, "lsrq %u, $r%d\n", dc->op1, dc->op2));
1005
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;
1011}
1012
1013static unsigned int dec_move_r(DisasContext *dc)
1014{
1015 int size = memsize_zz(dc);
1016
1017 DIS(fprintf (logfile, "move.%c $r%u, $r%u\n",
1018 memsize_char(size), dc->op1, dc->op2));
1019
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;
1024}
1025
1026static unsigned int dec_scc_r(DisasContext *dc)
1027{
1028 int cond = dc->op2;
1029
1030 DIS(fprintf (logfile, "s%s $r%u\n",
1031 cc_name(cond), dc->op1));
1032
1033 if (cond != CC_A)
1034 {
1035 gen_tst_cc (dc, cond);
1036 gen_op_movl_T1_T0();
1037 }
1038 else
1039 gen_op_movl_T1_im(1);
1040
1041 cris_cc_mask(dc, 0);
1042 crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4);
1043 return 2;
1044}
1045
1046static unsigned int dec_and_r(DisasContext *dc)
1047{
1048 int size = memsize_zz(dc);
1049
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;
1056}
1057
1058static unsigned int dec_lz_r(DisasContext *dc)
1059{
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;
1066}
1067
1068static unsigned int dec_lsl_r(DisasContext *dc)
1069{
1070 int size = memsize_zz(dc);
1071
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;
1079}
1080
1081static unsigned int dec_lsr_r(DisasContext *dc)
1082{
1083 int size = memsize_zz(dc);
1084
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;
1092}
1093
1094static unsigned int dec_asr_r(DisasContext *dc)
1095{
1096 int size = memsize_zz(dc);
1097
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;
1105}
1106
1107static unsigned int dec_muls_r(DisasContext *dc)
1108{
1109 int size = memsize_zz(dc);
1110
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;
1118}
1119
1120static unsigned int dec_mulu_r(DisasContext *dc)
1121{
1122 int size = memsize_zz(dc);
1123
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;
1131}
1132
1133
1134static unsigned int dec_dstep_r(DisasContext *dc)
1135{
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;
1143}
1144
1145static unsigned int dec_xor_r(DisasContext *dc)
1146{
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;
1155}
1156
1157static unsigned int dec_bound_r(DisasContext *dc)
1158{
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;
1169}
1170
1171static unsigned int dec_cmp_r(DisasContext *dc)
1172{
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;
1180}
1181
1182static unsigned int dec_abs_r(DisasContext *dc)
1183{
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;
1191}
1192
1193static unsigned int dec_add_r(DisasContext *dc)
1194{
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;
1202}
1203
1204static unsigned int dec_addc_r(DisasContext *dc)
1205{
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;
1213}
1214
1215static unsigned int dec_mcp_r(DisasContext *dc)
1216{
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;
1226}
1227
1228#if DISAS_CRIS
1229static 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;
1241}
1242#endif
1243
1244static unsigned int dec_swap_r(DisasContext *dc)
1245{
1246 DIS(char modename[4]);
1247 DIS(fprintf (logfile, "swap%s $r%u\n",
1248 swapmode_name(dc->op2, modename), dc->op1));
1249
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;
1263}
1264
1265static unsigned int dec_or_r(DisasContext *dc)
1266{
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;
1274}
1275
1276static unsigned int dec_addi_r(DisasContext *dc)
1277{
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;
1286}
1287
1288static unsigned int dec_addi_acr(DisasContext *dc)
1289{
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();
9004627f 1296 gen_movl_reg_T0[R_ACR]();
8170028d
TS
1297 return 2;
1298}
1299
1300static unsigned int dec_neg_r(DisasContext *dc)
1301{
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;
1309}
1310
1311static unsigned int dec_btst_r(DisasContext *dc)
1312{
1313 DIS(fprintf (logfile, "btst $r%u, $r%u\n",
1314 dc->op1, dc->op2));
8170028d
TS
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);
1318
1319 cris_update_cc_op(dc, CC_OP_FLAGS);
1320 gen_op_movl_flags_T0();
1321 dc->flags_live = 1;
1322 return 2;
1323}
1324
1325static unsigned int dec_sub_r(DisasContext *dc)
1326{
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;
1334}
1335
1336/* Zero extension. From size to dword. */
1337static unsigned int dec_movu_r(DisasContext *dc)
1338{
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));
1343
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;
1348}
1349
1350/* Sign extension. From size to dword. */
1351static unsigned int dec_movs_r(DisasContext *dc)
1352{
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));
1357
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;
1364}
1365
1366/* zero extension. From size to dword. */
1367static unsigned int dec_addu_r(DisasContext *dc)
1368{
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));
1373
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;
1381}
1382/* Sign extension. From size to dword. */
1383static unsigned int dec_adds_r(DisasContext *dc)
1384{
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));
1389
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;
1397}
1398
1399/* Zero extension. From size to dword. */
1400static unsigned int dec_subu_r(DisasContext *dc)
1401{
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));
1406
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;
1414}
1415
1416/* Sign extension. From size to dword. */
1417static unsigned int dec_subs_r(DisasContext *dc)
1418{
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));
1423
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;
1431}
1432
1433static unsigned int dec_setclrf(DisasContext *dc)
1434{
1435 uint32_t flags;
1436 int set = (~dc->opcode >> 2) & 1;
1437
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));
1449
1450 if (set && (flags & X_FLAG)) {
1451 dc->flagx_live = 1;
1452 dc->flags_x = 1;
1453 }
1454
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;
1464}
1465
1466static unsigned int dec_move_rs(DisasContext *dc)
1467{
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);
1472
1473 if (dc->op2 == 5) /* srs is checked at runtime. */
1474 gen_op_movl_tlb_lo_T0();
1475 return 2;
1476}
1477static unsigned int dec_move_sr(DisasContext *dc)
1478{
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;
1485}
1486static unsigned int dec_move_rp(DisasContext *dc)
1487{
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;
1494}
1495static unsigned int dec_move_pr(DisasContext *dc)
1496{
1497 DIS(fprintf (logfile, "move $p%u, $r%u\n", dc->op1, dc->op2));
1498 cris_cc_mask(dc, 0);
fd56059f
AZ
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();
1506 }
8170028d
TS
1507 crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, preg_sizes[dc->op2]);
1508 return 2;
1509}
1510
1511static unsigned int dec_move_mr(DisasContext *dc)
1512{
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));
1519
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;
1525}
1526
1527static unsigned int dec_movs_m(DisasContext *dc)
1528{
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));
1535
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;
1542}
1543
1544static unsigned int dec_addu_m(DisasContext *dc)
1545{
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));
1552
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;
1559}
1560
1561static unsigned int dec_adds_m(DisasContext *dc)
1562{
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));
1569
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;
1576}
1577
1578static unsigned int dec_subu_m(DisasContext *dc)
1579{
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));
1586
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;
1593}
1594
1595static unsigned int dec_subs_m(DisasContext *dc)
1596{
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));
1603
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;
1610}
1611
1612static unsigned int dec_movu_m(DisasContext *dc)
1613{
1614 int memsize = memsize_z(dc);
1615 int insn_len;
1616
1617 DIS(fprintf (logfile, "movu.%c [$r%u%s, $r%u\n",
1618 memsize_char(memsize),
1619 dc->op1, dc->postinc ? "+]" : "]",
1620 dc->op2));
1621
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;
1627}
1628
1629static unsigned int dec_cmpu_m(DisasContext *dc)
1630{
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));
1637
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;
1643}
1644
1645static unsigned int dec_cmps_m(DisasContext *dc)
1646{
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));
1653
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;
1659}
1660
1661static unsigned int dec_cmp_m(DisasContext *dc)
1662{
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));
1669
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;
1675}
1676
1677static unsigned int dec_test_m(DisasContext *dc)
1678{
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));
1685
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;
1694}
1695
1696static unsigned int dec_and_m(DisasContext *dc)
1697{
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));
1704
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;
1710}
1711
1712static unsigned int dec_add_m(DisasContext *dc)
1713{
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));
1720
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;
1726}
1727
1728static unsigned int dec_addo_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, 0);
1738 insn_len = dec_prep_alu_m(dc, 1, memsize);
9004627f 1739 crisv32_alu_op(dc, CC_OP_ADD, R_ACR, 4);
8170028d
TS
1740 do_postinc(dc, memsize);
1741 return insn_len;
1742}
1743
1744static unsigned int dec_bound_m(DisasContext *dc)
1745{
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));
1752
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;
1758}
1759
1760static unsigned int dec_addc_mr(DisasContext *dc)
1761{
1762 int insn_len = 2;
1763 DIS(fprintf (logfile, "addc [$r%u%s, $r%u\n",
1764 dc->op1, dc->postinc ? "+]" : "]",
1765 dc->op2));
1766
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;
1773}
1774
1775static unsigned int dec_sub_m(DisasContext *dc)
1776{
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));
1783
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;
1789}
1790
1791static unsigned int dec_or_m(DisasContext *dc)
1792{
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));
1799
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;
1805}
1806
1807static unsigned int dec_move_mp(DisasContext *dc)
1808{
1809 int memsize = memsize_zz(dc);
1810 int insn_len = 2;
1811
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));
1817
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]();
1822
1823 do_postinc(dc, memsize);
1824 return insn_len;
1825}
1826
1827static unsigned int dec_move_pm(DisasContext *dc)
1828{
1829 int memsize;
1830
1831 memsize = preg_sizes[dc->op2];
1832
fd56059f
AZ
1833 DIS(fprintf (logfile, "move.%c $p%u, [$r%u%s\n",
1834 memsize_char(memsize),
1835 dc->op2, dc->op1, dc->postinc ? "+]" : "]"));
8170028d
TS
1836
1837 cris_cc_mask(dc, 0);
fd56059f
AZ
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
1844 {
1845 gen_movl_T0_preg[dc->op2]();
1846 gen_op_movl_T1_T0();
1847 }
8170028d
TS
1848 gen_movl_T0_reg[dc->op1]();
1849 gen_store_T0_T1(dc, memsize);
1850 if (dc->postinc)
1851 {
1852 gen_op_addl_T0_im(memsize);
1853 gen_movl_reg_T0[dc->op1]();
1854 }
1855 return 2;
1856}
1857
1858static unsigned int dec_movem_mr(DisasContext *dc)
1859{
1860 int i;
1861
1862 DIS(fprintf (logfile, "movem [$r%u%s, $r%u\n", dc->op1,
1863 dc->postinc ? "+]" : "]", dc->op2));
1864
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();
1876 }
1877 if (dc->postinc) {
1878 /* writeback the updated pointer value. */
1879 gen_movl_reg_T0[dc->op1]();
1880 }
1881 return 2;
1882}
1883
1884static unsigned int dec_movem_rm(DisasContext *dc)
1885{
1886 int i;
1887
1888 DIS(fprintf (logfile, "movem $r%u, [$r%u%s\n", dc->op2, dc->op1,
1889 dc->postinc ? "+]" : "]"));
1890
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();
1896
1897 /* Fetch the address into T0. */
1898 gen_movl_T0_reg[dc->op1]();
1899 /* Displace it. */
1900 gen_op_addl_T0_im(i * 4);
1901
1902 /* Perform the store. */
1903 gen_store_T0_T1(dc, 4);
1904 }
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]();
1910 }
1911 return 2;
1912}
1913
1914static unsigned int dec_move_rm(DisasContext *dc)
1915{
1916 int memsize;
1917
1918 memsize = memsize_zz(dc);
1919
1920 DIS(fprintf (logfile, "move.%d $r%u, [$r%u]\n",
1921 memsize, dc->op2, dc->op1));
1922
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)
1930 {
1931 gen_op_addl_T0_im(memsize);
1932 gen_movl_reg_T0[dc->op1]();
1933 }
1934 return 2;
1935}
1936
1937
1938static unsigned int dec_lapcq(DisasContext *dc)
1939{
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;
1946}
1947
1948static unsigned int dec_lapc_im(DisasContext *dc)
1949{
1950 unsigned int rd;
1951 int32_t imm;
1952 int insn_len = 6;
1953
1954 rd = dc->op2;
1955
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;
1962}
1963
1964/* Jump to special reg. */
1965static unsigned int dec_jump_p(DisasContext *dc)
1966{
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;
1974}
1975
1976/* Jump and save. */
1977static unsigned int dec_jas_r(DisasContext *dc)
1978{
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;
1988}
1989
1990static unsigned int dec_jas_im(DisasContext *dc)
1991{
1992 uint32_t imm;
1993
1994 imm = ldl_code(dc->pc + 2);
1995
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;
2005}
2006
2007static unsigned int dec_jasc_im(DisasContext *dc)
2008{
2009 uint32_t imm;
2010
2011 imm = ldl_code(dc->pc + 2);
2012
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;
2022}
2023
2024static unsigned int dec_jasc_r(DisasContext *dc)
2025{
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;
2035}
2036
2037static unsigned int dec_bcc_im(DisasContext *dc)
2038{
2039 int32_t offset;
2040 uint32_t cond = dc->op2;
2041
2042 offset = ldl_code(dc->pc + 2);
2043 offset = sign_extend(offset, 15);
2044
2045 DIS(fprintf (logfile, "b%s %d pc=%x dst=%x\n",
2046 cc_name(cond), offset,
2047 dc->pc, dc->pc + offset));
2048
2049 cris_cc_mask(dc, 0);
2050 /* op2 holds the condition-code. */
2051 cris_prepare_cc_branch (dc, offset, cond);
2052 return 4;
2053}
2054
2055static unsigned int dec_bas_im(DisasContext *dc)
2056{
2057 int32_t simm;
2058
2059
2060 simm = ldl_code(dc->pc + 2);
2061
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;
2071}
2072
2073static unsigned int dec_basc_im(DisasContext *dc)
2074{
2075 int32_t simm;
2076 simm = ldl_code(dc->pc + 2);
2077
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;
2087}
2088
2089static unsigned int dec_rfe_etc(DisasContext *dc)
2090{
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));
2093
2094 cris_cc_mask(dc, 0);
2095
2096 if (dc->op2 == 15) /* ignore halt. */
2097 goto done;
2098
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;
2120
2121 }
2122 done:
2123 return 2;
2124}
2125
5d4a534d
EI
2126static unsigned int dec_ftag_fidx_d_m(DisasContext *dc)
2127{
2128 /* Ignore D-cache flushes. */
2129 return 2;
2130}
2131
2132static unsigned int dec_ftag_fidx_i_m(DisasContext *dc)
2133{
2134 /* Ignore I-cache flushes. */
2135 return 2;
2136}
2137
8170028d
TS
2138static unsigned int dec_null(DisasContext *dc)
2139{
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;
2145}
2146
2147struct decoder_info {
2148 struct {
2149 uint32_t bits;
2150 uint32_t mask;
2151 };
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},
2167
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},
2178
2179 {DEC_RFE_ETC, dec_rfe_etc},
2180 {DEC_ADDC_MR, dec_addc_mr},
2181
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},
2190
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},
2199
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},
2204
2205 {DEC_ADDI_R, dec_addi_r},
2206 {DEC_ADDI_ACR, dec_addi_acr},
2207
2208 {DEC_ADD_R, dec_add_r},
2209 {DEC_SUB_R, dec_sub_r},
2210
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},
2216
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},
2222
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},
2227
5d4a534d
EI
2228 {DEC_FTAG_FIDX_I_M, dec_ftag_fidx_i_m},
2229 {DEC_FTAG_FIDX_D_M, dec_ftag_fidx_d_m},
8170028d
TS
2230
2231 {DEC_MULS_R, dec_muls_r},
2232 {DEC_MULU_R, dec_mulu_r},
2233
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},
2238
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},
2243
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},
2254
2255 {{0, 0}, dec_null}
2256};
2257
2258static inline unsigned int
2259cris_decoder(DisasContext *dc)
2260{
2261 unsigned int insn_len = 2;
2262 uint32_t tmp;
2263 int i;
2264
2265 /* Load a halfword onto the instruction register. */
2266 tmp = ldl_code(dc->pc);
2267 dc->ir = tmp & 0xffff;
2268
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);
2276
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)
2280 {
2281 insn_len = decinfo[i].dec(dc);
2282 break;
2283 }
2284 }
2285
2286 return insn_len;
2287}
2288
2289static void check_breakpoint(CPUState *env, DisasContext *dc)
2290{
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;
2300 }
2301 }
2302 }
2303}
2304
2305
2306/* generate intermediate code for basic block 'tb'. */
2307struct DisasContext ctx;
2308static int
2309gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
2310 int search_pc)
2311{
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;
2318
2319 pc_start = tb->pc;
2320 dc->env = env;
2321 dc->tb = tb;
2322
8170028d 2323 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8170028d
TS
2324
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;
2332 do
2333 {
2334 check_breakpoint(env, dc);
2335 if (dc->is_jmp == DISAS_JUMP)
2336 goto done;
2337
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;
2344 }
2345 gen_opc_pc[lj] = dc->pc;
2346 gen_opc_instr_start[lj] = 1;
2347 }
2348
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))) {
9004627f 2355 gen_movl_T0_preg[PR_CCS]();
8170028d 2356 gen_op_andl_T0_im(~X_FLAG);
9004627f 2357 gen_movl_preg_T0[PR_CCS]();
8170028d
TS
2358 dc->flagx_live = 1;
2359 dc->flags_x = 0;
2360 }
2361
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)
2368 {
2369 if (dc->bcc == CC_A) {
57fec1fe 2370 gen_op_jmp1 ();
8170028d
TS
2371 dc->is_jmp = DISAS_UPDATE;
2372 }
2373 else {
2374 /* Conditional jmp. */
2375 gen_op_cc_jmp (dc->delayed_pc, dc->pc);
2376 dc->is_jmp = DISAS_UPDATE;
2377 }
2378 }
2379 }
2380
2381 if (env->singlestep_enabled)
2382 break;
2383 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end
2384 && dc->pc < next_page_start);
2385
2386 if (!dc->is_jmp) {
2387 gen_op_movl_T0_im((long)dc->pc);
2388 gen_op_movl_pc_T0();
2389 }
2390
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 */
57fec1fe 2405 tcg_gen_exit_tb(0);
8170028d
TS
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");
8170028d
TS
2428 }
2429#endif
2430 return 0;
2431}
2432
2433int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
2434{
2435 return gen_intermediate_code_internal(env, tb, 0);
2436}
2437
2438int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
2439{
2440 return gen_intermediate_code_internal(env, tb, 1);
2441}
2442
2443void cpu_dump_state (CPUState *env, FILE *f,
2444 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2445 int flags)
2446{
2447 int i;
2448 uint32_t srs;
2449
2450 if (!env || !f)
2451 return;
2452
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",
9004627f 2456 env->pc, env->pregs[PR_CCS], env->btaken, env->btarget,
8170028d
TS
2457 env->cc_op,
2458 env->cc_src, env->cc_dest, env->cc_result, env->cc_mask,
2459 env->debug1, env->debug2, env->debug3);
2460
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");
2465 }
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");
2471 }
9004627f 2472 srs = env->pregs[PR_SRS];
8170028d
TS
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");
2480 }
2481 }
2482 cpu_fprintf(f, "\n\n");
2483
2484}
2485
aaed909a 2486CPUCRISState *cpu_cris_init (const char *cpu_model)
8170028d
TS
2487{
2488 CPUCRISState *env;
2489
2490 env = qemu_mallocz(sizeof(CPUCRISState));
2491 if (!env)
2492 return NULL;
2493 cpu_exec_init(env);
2494 cpu_reset(env);
2495 return env;
2496}
2497
2498void cpu_reset (CPUCRISState *env)
2499{
2500 memset(env, 0, offsetof(CPUCRISState, breakpoints));
2501 tlb_flush(env, 1);
2502}