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