]> git.proxmox.com Git - qemu.git/blame - target-cris/translate.c
cris: Centralize fetching
[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
8167ee88 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
8170028d
TS
19 */
20
b41f7df0
EI
21/*
22 * FIXME:
cf1d97f0 23 * The condition code translation is in need of attention.
b41f7df0
EI
24 */
25
8170028d
TS
26#include <stdarg.h>
27#include <stdlib.h>
28#include <stdio.h>
29#include <string.h>
30#include <inttypes.h>
8170028d
TS
31
32#include "cpu.h"
33#include "exec-all.h"
34#include "disas.h"
57fec1fe 35#include "tcg-op.h"
05ba7d5f 36#include "helper.h"
52819664 37#include "mmu.h"
8170028d 38#include "crisv32-decode.h"
ca10f867 39#include "qemu-common.h"
8170028d 40
a7812ae4
PB
41#define GEN_HELPER 1
42#include "helper.h"
43
8170028d
TS
44#define DISAS_CRIS 0
45#if DISAS_CRIS
93fcfe39 46# define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
8170028d 47#else
d12d51d5 48# define LOG_DIS(...) do { } while (0)
8170028d
TS
49#endif
50
b41f7df0 51#define D(x)
8170028d
TS
52#define BUG() (gen_BUG(dc, __FILE__, __LINE__))
53#define BUG_ON(x) ({if (x) BUG();})
54
4f400ab5
EI
55#define DISAS_SWI 5
56
8170028d
TS
57/* Used by the decoder. */
58#define EXTRACT_FIELD(src, start, end) \
59 (((src) >> start) & ((1 << (end - start + 1)) - 1))
60
61#define CC_MASK_NZ 0xc
62#define CC_MASK_NZV 0xe
63#define CC_MASK_NZVC 0xf
64#define CC_MASK_RNZV 0x10e
65
a7812ae4 66static TCGv_ptr cpu_env;
9b32fbf8
EI
67static TCGv cpu_R[16];
68static TCGv cpu_PR[16];
69static TCGv cc_x;
70static TCGv cc_src;
71static TCGv cc_dest;
72static TCGv cc_result;
73static TCGv cc_op;
74static TCGv cc_size;
75static TCGv cc_mask;
76
77static TCGv env_btaken;
78static TCGv env_btarget;
79static TCGv env_pc;
b41f7df0 80
2e70f6ef
PB
81#include "gen-icount.h"
82
8170028d
TS
83/* This is the state at translation time. */
84typedef struct DisasContext {
85 CPUState *env;
b41f7df0 86 target_ulong pc, ppc;
8170028d
TS
87
88 /* Decoder. */
40e9eddd 89 unsigned int (*decoder)(struct DisasContext *dc);
8170028d
TS
90 uint32_t ir;
91 uint32_t opcode;
92 unsigned int op1;
93 unsigned int op2;
94 unsigned int zsize, zzsize;
95 unsigned int mode;
96 unsigned int postinc;
97
40e9eddd
EI
98 unsigned int size;
99 unsigned int src;
100 unsigned int dst;
101 unsigned int cond;
102
8170028d
TS
103 int update_cc;
104 int cc_op;
105 int cc_size;
106 uint32_t cc_mask;
30abcfc7
EI
107
108 int cc_size_uptodate; /* -1 invalid or last written value. */
109
110 int cc_x_uptodate; /* 1 - ccs, 2 - known | X_FLAG. 0 not uptodate. */
111 int flags_uptodate; /* Wether or not $ccs is uptodate. */
112 int flagx_known; /* Wether or not flags_x has the x flag known at
113 translation time. */
8170028d 114 int flags_x;
8170028d 115
30abcfc7 116 int clear_x; /* Clear x after this insn? */
40e9eddd
EI
117 int clear_prefix; /* Clear prefix after this insn? */
118 int clear_locked_irq; /* Clear the irq lockout. */
2a44f7f1
EI
119 int cpustate_changed;
120 unsigned int tb_flags; /* tb dependent flags. */
8170028d 121 int is_jmp;
8170028d 122
2a44f7f1
EI
123#define JMP_NOJMP 0
124#define JMP_DIRECT 1
125#define JMP_INDIRECT 2
126 int jmp; /* 0=nojmp, 1=direct, 2=indirect. */
127 uint32_t jmp_pc;
128
8170028d 129 int delayed_branch;
8170028d
TS
130
131 struct TranslationBlock *tb;
132 int singlestep_enabled;
133} DisasContext;
134
7ccfb2eb 135static void gen_BUG(DisasContext *dc, const char *file, int line)
8170028d
TS
136{
137 printf ("BUG: pc=%x %s %d\n", dc->pc, file, line);
93fcfe39 138 qemu_log("BUG: pc=%x %s %d\n", dc->pc, file, line);
cf1d97f0 139 cpu_abort(dc->env, "%s:%d\n", file, line);
8170028d
TS
140}
141
9b32fbf8 142static const char *regnames[] =
a825e703
EI
143{
144 "$r0", "$r1", "$r2", "$r3",
145 "$r4", "$r5", "$r6", "$r7",
146 "$r8", "$r9", "$r10", "$r11",
147 "$r12", "$r13", "$sp", "$acr",
148};
9b32fbf8 149static const char *pregnames[] =
a825e703
EI
150{
151 "$bz", "$vr", "$pid", "$srs",
152 "$wz", "$exs", "$eda", "$mof",
153 "$dz", "$ebp", "$erp", "$srp",
154 "$nrp", "$ccs", "$usp", "$spc",
155};
156
05ba7d5f 157/* We need this table to handle preg-moves with implicit width. */
9b32fbf8 158static int preg_sizes[] = {
05ba7d5f
EI
159 1, /* bz. */
160 1, /* vr. */
161 4, /* pid. */
162 1, /* srs. */
163 2, /* wz. */
164 4, 4, 4,
165 4, 4, 4, 4,
166 4, 4, 4, 4,
167};
168
169#define t_gen_mov_TN_env(tn, member) \
3157a0a9 170 _t_gen_mov_TN_env((tn), offsetof(CPUState, member))
05ba7d5f 171#define t_gen_mov_env_TN(member, tn) \
3157a0a9 172 _t_gen_mov_env_TN(offsetof(CPUState, member), (tn))
05ba7d5f 173
b41f7df0
EI
174static inline void t_gen_mov_TN_reg(TCGv tn, int r)
175{
176 if (r < 0 || r > 15)
177 fprintf(stderr, "wrong register read $r%d\n", r);
178 tcg_gen_mov_tl(tn, cpu_R[r]);
179}
180static inline void t_gen_mov_reg_TN(int r, TCGv tn)
181{
182 if (r < 0 || r > 15)
183 fprintf(stderr, "wrong register write $r%d\n", r);
184 tcg_gen_mov_tl(cpu_R[r], tn);
185}
05ba7d5f
EI
186
187static inline void _t_gen_mov_TN_env(TCGv tn, int offset)
188{
b41f7df0
EI
189 if (offset > sizeof (CPUState))
190 fprintf(stderr, "wrong load from env from off=%d\n", offset);
05ba7d5f
EI
191 tcg_gen_ld_tl(tn, cpu_env, offset);
192}
193static inline void _t_gen_mov_env_TN(int offset, TCGv tn)
194{
b41f7df0
EI
195 if (offset > sizeof (CPUState))
196 fprintf(stderr, "wrong store to env at off=%d\n", offset);
05ba7d5f
EI
197 tcg_gen_st_tl(tn, cpu_env, offset);
198}
199
200static inline void t_gen_mov_TN_preg(TCGv tn, int r)
201{
b41f7df0
EI
202 if (r < 0 || r > 15)
203 fprintf(stderr, "wrong register read $p%d\n", r);
05ba7d5f 204 if (r == PR_BZ || r == PR_WZ || r == PR_DZ)
3157a0a9 205 tcg_gen_mov_tl(tn, tcg_const_tl(0));
05ba7d5f 206 else if (r == PR_VR)
3157a0a9 207 tcg_gen_mov_tl(tn, tcg_const_tl(32));
05ba7d5f 208 else
a825e703 209 tcg_gen_mov_tl(tn, cpu_PR[r]);
05ba7d5f 210}
cf1d97f0 211static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn)
05ba7d5f 212{
b41f7df0
EI
213 if (r < 0 || r > 15)
214 fprintf(stderr, "wrong register write $p%d\n", r);
05ba7d5f
EI
215 if (r == PR_BZ || r == PR_WZ || r == PR_DZ)
216 return;
b41f7df0
EI
217 else if (r == PR_SRS)
218 tcg_gen_andi_tl(cpu_PR[r], tn, 3);
219 else {
2a44f7f1 220 if (r == PR_PID)
a7812ae4 221 gen_helper_tlb_flush_pid(tn);
a1aebcb8 222 if (dc->tb_flags & S_FLAG && r == PR_SPC)
a7812ae4 223 gen_helper_spc_write(tn);
2a44f7f1
EI
224 else if (r == PR_CCS)
225 dc->cpustate_changed = 1;
28de16da 226 tcg_gen_mov_tl(cpu_PR[r], tn);
b41f7df0 227 }
05ba7d5f
EI
228}
229
7de141cb
EI
230static int cris_fetch(DisasContext *dc, uint32_t addr,
231 unsigned int size, unsigned int sign)
232{
233 int r;
234
235 switch (size) {
236 case 4:
237 {
238 r = ldl_code(addr);
239 break;
240 }
241 case 2:
242 {
243 if (sign) {
244 r = ldsw_code(addr);
245 } else {
246 r = lduw_code(addr);
247 }
248 break;
249 }
250 case 1:
251 {
252 if (sign) {
253 r = ldsb_code(addr);
254 } else {
255 r = ldub_code(addr);
256 }
257 break;
258 }
259 default:
260 cpu_abort(dc->env, "Invalid fetch size %d\n", size);
261 break;
262 }
263 return r;
264}
265
40e9eddd
EI
266static void cris_lock_irq(DisasContext *dc)
267{
268 dc->clear_locked_irq = 0;
269 t_gen_mov_env_TN(locked_irq, tcg_const_tl(1));
270}
271
dceaf394 272static inline void t_gen_raise_exception(uint32_t index)
05ba7d5f 273{
a7812ae4
PB
274 TCGv_i32 tmp = tcg_const_i32(index);
275 gen_helper_raise_exception(tmp);
276 tcg_temp_free_i32(tmp);
05ba7d5f
EI
277}
278
279static void t_gen_lsl(TCGv d, TCGv a, TCGv b)
280{
7dcfb089 281 TCGv t0, t_31;
05ba7d5f 282
a7812ae4 283 t0 = tcg_temp_new();
44696296 284 t_31 = tcg_const_tl(31);
05ba7d5f 285 tcg_gen_shl_tl(d, a, b);
7dcfb089 286
7dcfb089
EI
287 tcg_gen_sub_tl(t0, t_31, b);
288 tcg_gen_sar_tl(t0, t0, t_31);
289 tcg_gen_and_tl(t0, t0, d);
290 tcg_gen_xor_tl(d, d, t0);
291 tcg_temp_free(t0);
292 tcg_temp_free(t_31);
05ba7d5f
EI
293}
294
295static void t_gen_lsr(TCGv d, TCGv a, TCGv b)
296{
7dcfb089 297 TCGv t0, t_31;
05ba7d5f 298
a7812ae4
PB
299 t0 = tcg_temp_new();
300 t_31 = tcg_temp_new();
05ba7d5f 301 tcg_gen_shr_tl(d, a, b);
7dcfb089
EI
302
303 tcg_gen_movi_tl(t_31, 31);
304 tcg_gen_sub_tl(t0, t_31, b);
305 tcg_gen_sar_tl(t0, t0, t_31);
306 tcg_gen_and_tl(t0, t0, d);
307 tcg_gen_xor_tl(d, d, t0);
308 tcg_temp_free(t0);
309 tcg_temp_free(t_31);
05ba7d5f
EI
310}
311
312static void t_gen_asr(TCGv d, TCGv a, TCGv b)
313{
7dcfb089 314 TCGv t0, t_31;
05ba7d5f 315
a7812ae4
PB
316 t0 = tcg_temp_new();
317 t_31 = tcg_temp_new();
05ba7d5f 318 tcg_gen_sar_tl(d, a, b);
7dcfb089
EI
319
320 tcg_gen_movi_tl(t_31, 31);
321 tcg_gen_sub_tl(t0, t_31, b);
322 tcg_gen_sar_tl(t0, t0, t_31);
323 tcg_gen_or_tl(d, d, t0);
324 tcg_temp_free(t0);
325 tcg_temp_free(t_31);
05ba7d5f
EI
326}
327
3157a0a9
EI
328/* 64-bit signed mul, lower result in d and upper in d2. */
329static void t_gen_muls(TCGv d, TCGv d2, TCGv a, TCGv b)
330{
a7812ae4 331 TCGv_i64 t0, t1;
3157a0a9 332
a7812ae4
PB
333 t0 = tcg_temp_new_i64();
334 t1 = tcg_temp_new_i64();
3157a0a9 335
a7812ae4
PB
336 tcg_gen_ext_i32_i64(t0, a);
337 tcg_gen_ext_i32_i64(t1, b);
3157a0a9
EI
338 tcg_gen_mul_i64(t0, t0, t1);
339
340 tcg_gen_trunc_i64_i32(d, t0);
341 tcg_gen_shri_i64(t0, t0, 32);
342 tcg_gen_trunc_i64_i32(d2, t0);
b41f7df0 343
a7812ae4
PB
344 tcg_temp_free_i64(t0);
345 tcg_temp_free_i64(t1);
3157a0a9
EI
346}
347
348/* 64-bit unsigned muls, lower result in d and upper in d2. */
349static void t_gen_mulu(TCGv d, TCGv d2, TCGv a, TCGv b)
350{
a7812ae4 351 TCGv_i64 t0, t1;
3157a0a9 352
a7812ae4
PB
353 t0 = tcg_temp_new_i64();
354 t1 = tcg_temp_new_i64();
3157a0a9
EI
355
356 tcg_gen_extu_i32_i64(t0, a);
357 tcg_gen_extu_i32_i64(t1, b);
358 tcg_gen_mul_i64(t0, t0, t1);
359
360 tcg_gen_trunc_i64_i32(d, t0);
361 tcg_gen_shri_i64(t0, t0, 32);
362 tcg_gen_trunc_i64_i32(d2, t0);
b41f7df0 363
a7812ae4
PB
364 tcg_temp_free_i64(t0);
365 tcg_temp_free_i64(t1);
3157a0a9
EI
366}
367
30abcfc7 368static void t_gen_cris_dstep(TCGv d, TCGv a, TCGv b)
aae6b32a
EI
369{
370 int l1;
371
372 l1 = gen_new_label();
373
374 /*
375 * d <<= 1
376 * if (d >= s)
377 * d -= s;
378 */
30abcfc7
EI
379 tcg_gen_shli_tl(d, a, 1);
380 tcg_gen_brcond_tl(TCG_COND_LTU, d, b, l1);
381 tcg_gen_sub_tl(d, d, b);
aae6b32a
EI
382 gen_set_label(l1);
383}
384
40e9eddd
EI
385static void t_gen_cris_mstep(TCGv d, TCGv a, TCGv b, TCGv ccs)
386{
387 TCGv t;
388
389 /*
390 * d <<= 1
391 * if (n)
392 * d += s;
393 */
394 t = tcg_temp_new();
395 tcg_gen_shli_tl(d, a, 1);
396 tcg_gen_shli_tl(t, ccs, 31 - 3);
397 tcg_gen_sari_tl(t, t, 31);
398 tcg_gen_and_tl(t, t, b);
399 tcg_gen_add_tl(d, d, t);
400 tcg_temp_free(t);
401}
402
3157a0a9
EI
403/* Extended arithmetics on CRIS. */
404static inline void t_gen_add_flag(TCGv d, int flag)
405{
406 TCGv c;
407
a7812ae4 408 c = tcg_temp_new();
3157a0a9
EI
409 t_gen_mov_TN_preg(c, PR_CCS);
410 /* Propagate carry into d. */
411 tcg_gen_andi_tl(c, c, 1 << flag);
412 if (flag)
413 tcg_gen_shri_tl(c, c, flag);
414 tcg_gen_add_tl(d, d, c);
30abcfc7 415 tcg_temp_free(c);
3157a0a9
EI
416}
417
30abcfc7 418static inline void t_gen_addx_carry(DisasContext *dc, TCGv d)
3157a0a9 419{
30abcfc7
EI
420 if (dc->flagx_known) {
421 if (dc->flags_x) {
422 TCGv c;
423
a7812ae4 424 c = tcg_temp_new();
30abcfc7
EI
425 t_gen_mov_TN_preg(c, PR_CCS);
426 /* C flag is already at bit 0. */
427 tcg_gen_andi_tl(c, c, C_FLAG);
428 tcg_gen_add_tl(d, d, c);
429 tcg_temp_free(c);
430 }
431 } else {
432 TCGv x, c;
3157a0a9 433
a7812ae4
PB
434 x = tcg_temp_new();
435 c = tcg_temp_new();
30abcfc7
EI
436 t_gen_mov_TN_preg(x, PR_CCS);
437 tcg_gen_mov_tl(c, x);
3157a0a9 438
30abcfc7
EI
439 /* Propagate carry into d if X is set. Branch free. */
440 tcg_gen_andi_tl(c, c, C_FLAG);
441 tcg_gen_andi_tl(x, x, X_FLAG);
442 tcg_gen_shri_tl(x, x, 4);
3157a0a9 443
30abcfc7
EI
444 tcg_gen_and_tl(x, x, c);
445 tcg_gen_add_tl(d, d, x);
446 tcg_temp_free(x);
447 tcg_temp_free(c);
448 }
3157a0a9
EI
449}
450
a39f8f3a 451static inline void t_gen_subx_carry(DisasContext *dc, TCGv d)
3157a0a9 452{
30abcfc7
EI
453 if (dc->flagx_known) {
454 if (dc->flags_x) {
455 TCGv c;
456
a7812ae4 457 c = tcg_temp_new();
30abcfc7
EI
458 t_gen_mov_TN_preg(c, PR_CCS);
459 /* C flag is already at bit 0. */
460 tcg_gen_andi_tl(c, c, C_FLAG);
461 tcg_gen_sub_tl(d, d, c);
462 tcg_temp_free(c);
463 }
464 } else {
a39f8f3a
EI
465 TCGv x, c;
466
a7812ae4
PB
467 x = tcg_temp_new();
468 c = tcg_temp_new();
a39f8f3a
EI
469 t_gen_mov_TN_preg(x, PR_CCS);
470 tcg_gen_mov_tl(c, x);
471
472 /* Propagate carry into d if X is set. Branch free. */
473 tcg_gen_andi_tl(c, c, C_FLAG);
474 tcg_gen_andi_tl(x, x, X_FLAG);
475 tcg_gen_shri_tl(x, x, 4);
476
477 tcg_gen_and_tl(x, x, c);
478 tcg_gen_sub_tl(d, d, x);
30abcfc7
EI
479 tcg_temp_free(x);
480 tcg_temp_free(c);
a39f8f3a 481 }
3157a0a9
EI
482}
483
484/* Swap the two bytes within each half word of the s operand.
485 T0 = ((T0 << 8) & 0xff00ff00) | ((T0 >> 8) & 0x00ff00ff) */
486static inline void t_gen_swapb(TCGv d, TCGv s)
487{
488 TCGv t, org_s;
489
a7812ae4
PB
490 t = tcg_temp_new();
491 org_s = tcg_temp_new();
3157a0a9
EI
492
493 /* d and s may refer to the same object. */
494 tcg_gen_mov_tl(org_s, s);
495 tcg_gen_shli_tl(t, org_s, 8);
496 tcg_gen_andi_tl(d, t, 0xff00ff00);
497 tcg_gen_shri_tl(t, org_s, 8);
498 tcg_gen_andi_tl(t, t, 0x00ff00ff);
499 tcg_gen_or_tl(d, d, t);
30abcfc7
EI
500 tcg_temp_free(t);
501 tcg_temp_free(org_s);
3157a0a9
EI
502}
503
504/* Swap the halfwords of the s operand. */
505static inline void t_gen_swapw(TCGv d, TCGv s)
506{
507 TCGv t;
508 /* d and s refer the same object. */
a7812ae4 509 t = tcg_temp_new();
3157a0a9
EI
510 tcg_gen_mov_tl(t, s);
511 tcg_gen_shli_tl(d, t, 16);
512 tcg_gen_shri_tl(t, t, 16);
513 tcg_gen_or_tl(d, d, t);
30abcfc7 514 tcg_temp_free(t);
3157a0a9
EI
515}
516
517/* Reverse the within each byte.
518 T0 = (((T0 << 7) & 0x80808080) |
519 ((T0 << 5) & 0x40404040) |
520 ((T0 << 3) & 0x20202020) |
521 ((T0 << 1) & 0x10101010) |
522 ((T0 >> 1) & 0x08080808) |
523 ((T0 >> 3) & 0x04040404) |
524 ((T0 >> 5) & 0x02020202) |
525 ((T0 >> 7) & 0x01010101));
526 */
527static inline void t_gen_swapr(TCGv d, TCGv s)
528{
529 struct {
530 int shift; /* LSL when positive, LSR when negative. */
531 uint32_t mask;
532 } bitrev [] = {
533 {7, 0x80808080},
534 {5, 0x40404040},
535 {3, 0x20202020},
536 {1, 0x10101010},
537 {-1, 0x08080808},
538 {-3, 0x04040404},
539 {-5, 0x02020202},
540 {-7, 0x01010101}
541 };
542 int i;
543 TCGv t, org_s;
544
545 /* d and s refer the same object. */
a7812ae4
PB
546 t = tcg_temp_new();
547 org_s = tcg_temp_new();
3157a0a9
EI
548 tcg_gen_mov_tl(org_s, s);
549
550 tcg_gen_shli_tl(t, org_s, bitrev[0].shift);
551 tcg_gen_andi_tl(d, t, bitrev[0].mask);
b1503cda 552 for (i = 1; i < ARRAY_SIZE(bitrev); i++) {
3157a0a9
EI
553 if (bitrev[i].shift >= 0) {
554 tcg_gen_shli_tl(t, org_s, bitrev[i].shift);
555 } else {
556 tcg_gen_shri_tl(t, org_s, -bitrev[i].shift);
557 }
558 tcg_gen_andi_tl(t, t, bitrev[i].mask);
559 tcg_gen_or_tl(d, d, t);
560 }
30abcfc7
EI
561 tcg_temp_free(t);
562 tcg_temp_free(org_s);
3157a0a9
EI
563}
564
cf1d97f0 565static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false)
17ac9754
EI
566{
567 TCGv btaken;
568 int l1;
569
570 l1 = gen_new_label();
a7812ae4 571 btaken = tcg_temp_new();
17ac9754
EI
572
573 /* Conditional jmp. */
2a44f7f1 574 tcg_gen_mov_tl(btaken, env_btaken);
cf1d97f0 575 tcg_gen_mov_tl(env_pc, pc_false);
cb63669a 576 tcg_gen_brcondi_tl(TCG_COND_EQ, btaken, 0, l1);
cf1d97f0 577 tcg_gen_mov_tl(env_pc, pc_true);
17ac9754
EI
578 gen_set_label(l1);
579
30abcfc7 580 tcg_temp_free(btaken);
17ac9754
EI
581}
582
8170028d
TS
583static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
584{
585 TranslationBlock *tb;
586 tb = dc->tb;
587 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
05ba7d5f 588 tcg_gen_goto_tb(n);
50cfa95c 589 tcg_gen_movi_tl(env_pc, dest);
05ba7d5f 590 tcg_gen_exit_tb((long)tb + n);
8170028d 591 } else {
2a44f7f1 592 tcg_gen_movi_tl(env_pc, dest);
05ba7d5f 593 tcg_gen_exit_tb(0);
8170028d 594 }
8170028d
TS
595}
596
597/* Sign extend at translation time. */
598static int sign_extend(unsigned int val, unsigned int width)
599{
600 int sval;
601
602 /* LSL. */
603 val <<= 31 - width;
604 sval = val;
605 /* ASR. */
606 sval >>= 31 - width;
607 return sval;
608}
609
05ba7d5f
EI
610static inline void cris_clear_x_flag(DisasContext *dc)
611{
2a44f7f1
EI
612 if (dc->flagx_known && dc->flags_x)
613 dc->flags_uptodate = 0;
614
30abcfc7 615 dc->flagx_known = 1;
b41f7df0 616 dc->flags_x = 0;
05ba7d5f
EI
617}
618
30abcfc7 619static void cris_flush_cc_state(DisasContext *dc)
8170028d 620{
30abcfc7 621 if (dc->cc_size_uptodate != dc->cc_size) {
b41f7df0 622 tcg_gen_movi_tl(cc_size, dc->cc_size);
30abcfc7
EI
623 dc->cc_size_uptodate = dc->cc_size;
624 }
625 tcg_gen_movi_tl(cc_op, dc->cc_op);
626 tcg_gen_movi_tl(cc_mask, dc->cc_mask);
627}
628
629static void cris_evaluate_flags(DisasContext *dc)
630{
6231868b
EI
631 if (dc->flags_uptodate)
632 return;
b41f7df0 633
6231868b
EI
634 cris_flush_cc_state(dc);
635
636 switch (dc->cc_op)
637 {
638 case CC_OP_MCP:
639 gen_helper_evaluate_flags_mcp(cpu_PR[PR_CCS],
640 cpu_PR[PR_CCS], cc_src,
641 cc_dest, cc_result);
642 break;
643 case CC_OP_MULS:
644 gen_helper_evaluate_flags_muls(cpu_PR[PR_CCS],
645 cpu_PR[PR_CCS], cc_result,
646 cpu_PR[PR_MOF]);
647 break;
648 case CC_OP_MULU:
649 gen_helper_evaluate_flags_mulu(cpu_PR[PR_CCS],
650 cpu_PR[PR_CCS], cc_result,
651 cpu_PR[PR_MOF]);
652 break;
653 case CC_OP_MOVE:
654 case CC_OP_AND:
655 case CC_OP_OR:
656 case CC_OP_XOR:
657 case CC_OP_ASR:
658 case CC_OP_LSR:
659 case CC_OP_LSL:
660 switch (dc->cc_size)
8170028d 661 {
6231868b
EI
662 case 4:
663 gen_helper_evaluate_flags_move_4(cpu_PR[PR_CCS],
664 cpu_PR[PR_CCS], cc_result);
665 break;
666 case 2:
667 gen_helper_evaluate_flags_move_2(cpu_PR[PR_CCS],
668 cpu_PR[PR_CCS], cc_result);
669 break;
670 default:
671 gen_helper_evaluate_flags();
672 break;
673 }
674 break;
675 case CC_OP_FLAGS:
676 /* live. */
677 break;
678 case CC_OP_SUB:
679 case CC_OP_CMP:
680 if (dc->cc_size == 4)
681 gen_helper_evaluate_flags_sub_4(cpu_PR[PR_CCS],
682 cpu_PR[PR_CCS], cc_src, cc_dest, cc_result);
683 else
684 gen_helper_evaluate_flags();
685
686 break;
687 default:
688 switch (dc->cc_size)
689 {
690 case 4:
691 gen_helper_evaluate_flags_alu_4(cpu_PR[PR_CCS],
692 cpu_PR[PR_CCS], cc_src, cc_dest, cc_result);
a8cf66bb 693 break;
8170028d 694 default:
6231868b
EI
695 gen_helper_evaluate_flags();
696 break;
8170028d 697 }
6231868b 698 break;
8170028d 699 }
6231868b
EI
700
701 if (dc->flagx_known) {
702 if (dc->flags_x)
703 tcg_gen_ori_tl(cpu_PR[PR_CCS],
704 cpu_PR[PR_CCS], X_FLAG);
40e9eddd 705 else if (dc->cc_op == CC_OP_FLAGS)
6231868b
EI
706 tcg_gen_andi_tl(cpu_PR[PR_CCS],
707 cpu_PR[PR_CCS], ~X_FLAG);
708 }
709 dc->flags_uptodate = 1;
8170028d
TS
710}
711
712static void cris_cc_mask(DisasContext *dc, unsigned int mask)
713{
714 uint32_t ovl;
715
2a44f7f1
EI
716 if (!mask) {
717 dc->update_cc = 0;
718 return;
719 }
720
fd56059f
AZ
721 /* Check if we need to evaluate the condition codes due to
722 CC overlaying. */
8170028d
TS
723 ovl = (dc->cc_mask ^ mask) & ~mask;
724 if (ovl) {
725 /* TODO: optimize this case. It trigs all the time. */
726 cris_evaluate_flags (dc);
727 }
728 dc->cc_mask = mask;
8170028d 729 dc->update_cc = 1;
8170028d
TS
730}
731
b41f7df0 732static void cris_update_cc_op(DisasContext *dc, int op, int size)
8170028d
TS
733{
734 dc->cc_op = op;
8170028d 735 dc->cc_size = size;
30abcfc7 736 dc->flags_uptodate = 0;
8170028d
TS
737}
738
30abcfc7
EI
739static inline void cris_update_cc_x(DisasContext *dc)
740{
741 /* Save the x flag state at the time of the cc snapshot. */
742 if (dc->flagx_known) {
743 if (dc->cc_x_uptodate == (2 | dc->flags_x))
744 return;
745 tcg_gen_movi_tl(cc_x, dc->flags_x);
746 dc->cc_x_uptodate = 2 | dc->flags_x;
747 }
748 else {
749 tcg_gen_andi_tl(cc_x, cpu_PR[PR_CCS], X_FLAG);
750 dc->cc_x_uptodate = 1;
751 }
752}
753
754/* Update cc prior to executing ALU op. Needs source operands untouched. */
755static void cris_pre_alu_update_cc(DisasContext *dc, int op,
756 TCGv dst, TCGv src, int size)
8170028d 757{
8170028d 758 if (dc->update_cc) {
b41f7df0 759 cris_update_cc_op(dc, op, size);
30abcfc7
EI
760 tcg_gen_mov_tl(cc_src, src);
761
762 if (op != CC_OP_MOVE
763 && op != CC_OP_AND
764 && op != CC_OP_OR
765 && op != CC_OP_XOR
766 && op != CC_OP_ASR
767 && op != CC_OP_LSR
768 && op != CC_OP_LSL)
769 tcg_gen_mov_tl(cc_dest, dst);
770
771 cris_update_cc_x(dc);
772 }
773}
3157a0a9 774
30abcfc7
EI
775/* Update cc after executing ALU op. needs the result. */
776static inline void cris_update_result(DisasContext *dc, TCGv res)
777{
a8cf66bb 778 if (dc->update_cc)
30abcfc7 779 tcg_gen_mov_tl(cc_result, res);
30abcfc7 780}
8170028d 781
30abcfc7
EI
782/* Returns one if the write back stage should execute. */
783static void cris_alu_op_exec(DisasContext *dc, int op,
784 TCGv dst, TCGv a, TCGv b, int size)
785{
8170028d
TS
786 /* Emit the ALU insns. */
787 switch (op)
788 {
789 case CC_OP_ADD:
30abcfc7 790 tcg_gen_add_tl(dst, a, b);
8170028d 791 /* Extended arithmetics. */
30abcfc7 792 t_gen_addx_carry(dc, dst);
8170028d
TS
793 break;
794 case CC_OP_ADDC:
30abcfc7
EI
795 tcg_gen_add_tl(dst, a, b);
796 t_gen_add_flag(dst, 0); /* C_FLAG. */
8170028d
TS
797 break;
798 case CC_OP_MCP:
30abcfc7
EI
799 tcg_gen_add_tl(dst, a, b);
800 t_gen_add_flag(dst, 8); /* R_FLAG. */
8170028d
TS
801 break;
802 case CC_OP_SUB:
30abcfc7 803 tcg_gen_sub_tl(dst, a, b);
8170028d 804 /* Extended arithmetics. */
30abcfc7 805 t_gen_subx_carry(dc, dst);
8170028d
TS
806 break;
807 case CC_OP_MOVE:
30abcfc7 808 tcg_gen_mov_tl(dst, b);
8170028d
TS
809 break;
810 case CC_OP_OR:
30abcfc7 811 tcg_gen_or_tl(dst, a, b);
8170028d
TS
812 break;
813 case CC_OP_AND:
30abcfc7 814 tcg_gen_and_tl(dst, a, b);
8170028d
TS
815 break;
816 case CC_OP_XOR:
30abcfc7 817 tcg_gen_xor_tl(dst, a, b);
8170028d
TS
818 break;
819 case CC_OP_LSL:
30abcfc7 820 t_gen_lsl(dst, a, b);
8170028d
TS
821 break;
822 case CC_OP_LSR:
30abcfc7 823 t_gen_lsr(dst, a, b);
8170028d
TS
824 break;
825 case CC_OP_ASR:
30abcfc7 826 t_gen_asr(dst, a, b);
8170028d
TS
827 break;
828 case CC_OP_NEG:
30abcfc7 829 tcg_gen_neg_tl(dst, b);
8170028d 830 /* Extended arithmetics. */
30abcfc7 831 t_gen_subx_carry(dc, dst);
8170028d
TS
832 break;
833 case CC_OP_LZ:
c38ac98d 834 gen_helper_lz(dst, b);
8170028d 835 break;
8170028d 836 case CC_OP_MULS:
30abcfc7
EI
837 t_gen_muls(dst, cpu_PR[PR_MOF], a, b);
838 break;
8170028d 839 case CC_OP_MULU:
30abcfc7
EI
840 t_gen_mulu(dst, cpu_PR[PR_MOF], a, b);
841 break;
8170028d 842 case CC_OP_DSTEP:
30abcfc7 843 t_gen_cris_dstep(dst, a, b);
8170028d 844 break;
40e9eddd
EI
845 case CC_OP_MSTEP:
846 t_gen_cris_mstep(dst, a, b, cpu_PR[PR_CCS]);
847 break;
8170028d 848 case CC_OP_BOUND:
3157a0a9
EI
849 {
850 int l1;
851 l1 = gen_new_label();
30abcfc7
EI
852 tcg_gen_mov_tl(dst, a);
853 tcg_gen_brcond_tl(TCG_COND_LEU, a, b, l1);
854 tcg_gen_mov_tl(dst, b);
3157a0a9
EI
855 gen_set_label(l1);
856 }
857 break;
8170028d 858 case CC_OP_CMP:
30abcfc7 859 tcg_gen_sub_tl(dst, a, b);
8170028d 860 /* Extended arithmetics. */
30abcfc7 861 t_gen_subx_carry(dc, dst);
8170028d
TS
862 break;
863 default:
93fcfe39 864 qemu_log("illegal ALU op.\n");
8170028d
TS
865 BUG();
866 break;
867 }
868
8170028d 869 if (size == 1)
30abcfc7 870 tcg_gen_andi_tl(dst, dst, 0xff);
8170028d 871 else if (size == 2)
30abcfc7
EI
872 tcg_gen_andi_tl(dst, dst, 0xffff);
873}
874
875static void cris_alu(DisasContext *dc, int op,
876 TCGv d, TCGv op_a, TCGv op_b, int size)
877{
878 TCGv tmp;
879 int writeback;
880
881 writeback = 1;
31c18d87 882
31c18d87 883 if (op == CC_OP_CMP) {
a7812ae4 884 tmp = tcg_temp_new();
30abcfc7 885 writeback = 0;
31c18d87 886 } else if (size == 4) {
30abcfc7
EI
887 tmp = d;
888 writeback = 0;
44696296 889 } else
a7812ae4 890 tmp = tcg_temp_new();
44696296 891
30abcfc7
EI
892
893 cris_pre_alu_update_cc(dc, op, op_a, op_b, size);
894 cris_alu_op_exec(dc, op, tmp, op_a, op_b, size);
895 cris_update_result(dc, tmp);
05ba7d5f 896
8170028d
TS
897 /* Writeback. */
898 if (writeback) {
30abcfc7
EI
899 if (size == 1)
900 tcg_gen_andi_tl(d, d, ~0xff);
901 else
902 tcg_gen_andi_tl(d, d, ~0xffff);
903 tcg_gen_or_tl(d, d, tmp);
8170028d 904 }
a7812ae4 905 if (!TCGV_EQUAL(tmp, d))
31c18d87 906 tcg_temp_free(tmp);
8170028d
TS
907}
908
909static int arith_cc(DisasContext *dc)
910{
911 if (dc->update_cc) {
912 switch (dc->cc_op) {
30abcfc7 913 case CC_OP_ADDC: return 1;
8170028d
TS
914 case CC_OP_ADD: return 1;
915 case CC_OP_SUB: return 1;
30abcfc7 916 case CC_OP_DSTEP: return 1;
8170028d
TS
917 case CC_OP_LSL: return 1;
918 case CC_OP_LSR: return 1;
919 case CC_OP_ASR: return 1;
920 case CC_OP_CMP: return 1;
30abcfc7
EI
921 case CC_OP_NEG: return 1;
922 case CC_OP_OR: return 1;
459e5185 923 case CC_OP_AND: return 1;
30abcfc7
EI
924 case CC_OP_XOR: return 1;
925 case CC_OP_MULU: return 1;
926 case CC_OP_MULS: return 1;
8170028d
TS
927 default:
928 return 0;
929 }
930 }
931 return 0;
932}
933
c5631f48 934static void gen_tst_cc (DisasContext *dc, TCGv cc, int cond)
8170028d 935{
2a44f7f1 936 int arith_opt, move_opt;
8170028d
TS
937
938 /* TODO: optimize more condition codes. */
dceaf394
EI
939
940 /*
941 * If the flags are live, we've gotta look into the bits of CCS.
942 * Otherwise, if we just did an arithmetic operation we try to
943 * evaluate the condition code faster.
944 *
945 * When this function is done, T0 should be non-zero if the condition
946 * code is true.
947 */
30abcfc7 948 arith_opt = arith_cc(dc) && !dc->flags_uptodate;
459e5185 949 move_opt = (dc->cc_op == CC_OP_MOVE);
8170028d
TS
950 switch (cond) {
951 case CC_EQ:
40e9eddd
EI
952 if ((arith_opt || move_opt)
953 && dc->cc_x_uptodate != (2 | X_FLAG)) {
dceaf394
EI
954 /* If cc_result is zero, T0 should be
955 non-zero otherwise T0 should be zero. */
956 int l1;
957 l1 = gen_new_label();
c5631f48 958 tcg_gen_movi_tl(cc, 0);
cb63669a
PB
959 tcg_gen_brcondi_tl(TCG_COND_NE, cc_result,
960 0, l1);
c5631f48 961 tcg_gen_movi_tl(cc, 1);
dceaf394
EI
962 gen_set_label(l1);
963 }
8170028d
TS
964 else {
965 cris_evaluate_flags(dc);
c5631f48 966 tcg_gen_andi_tl(cc,
dceaf394 967 cpu_PR[PR_CCS], Z_FLAG);
8170028d
TS
968 }
969 break;
970 case CC_NE:
40e9eddd
EI
971 if ((arith_opt || move_opt)
972 && dc->cc_x_uptodate != (2 | X_FLAG)) {
c5631f48 973 tcg_gen_mov_tl(cc, cc_result);
40e9eddd 974 } else {
8170028d 975 cris_evaluate_flags(dc);
c5631f48 976 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
dceaf394 977 Z_FLAG);
c5631f48 978 tcg_gen_andi_tl(cc, cc, Z_FLAG);
8170028d
TS
979 }
980 break;
981 case CC_CS:
982 cris_evaluate_flags(dc);
c5631f48 983 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], C_FLAG);
8170028d
TS
984 break;
985 case CC_CC:
986 cris_evaluate_flags(dc);
c5631f48
EI
987 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS], C_FLAG);
988 tcg_gen_andi_tl(cc, cc, C_FLAG);
8170028d
TS
989 break;
990 case CC_VS:
991 cris_evaluate_flags(dc);
c5631f48 992 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], V_FLAG);
8170028d
TS
993 break;
994 case CC_VC:
995 cris_evaluate_flags(dc);
c5631f48 996 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
dceaf394 997 V_FLAG);
c5631f48 998 tcg_gen_andi_tl(cc, cc, V_FLAG);
8170028d
TS
999 break;
1000 case CC_PL:
2a44f7f1
EI
1001 if (arith_opt || move_opt) {
1002 int bits = 31;
1003
1004 if (dc->cc_size == 1)
1005 bits = 7;
1006 else if (dc->cc_size == 2)
1007 bits = 15;
1008
c5631f48
EI
1009 tcg_gen_shri_tl(cc, cc_result, bits);
1010 tcg_gen_xori_tl(cc, cc, 1);
2a44f7f1 1011 } else {
8170028d 1012 cris_evaluate_flags(dc);
c5631f48 1013 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
dceaf394 1014 N_FLAG);
c5631f48 1015 tcg_gen_andi_tl(cc, cc, N_FLAG);
8170028d
TS
1016 }
1017 break;
1018 case CC_MI:
2a44f7f1
EI
1019 if (arith_opt || move_opt) {
1020 int bits = 31;
1021
1022 if (dc->cc_size == 1)
1023 bits = 7;
1024 else if (dc->cc_size == 2)
1025 bits = 15;
1026
f3bc5238
EI
1027 tcg_gen_shri_tl(cc, cc_result, bits);
1028 tcg_gen_andi_tl(cc, cc, 1);
dceaf394 1029 }
8170028d
TS
1030 else {
1031 cris_evaluate_flags(dc);
c5631f48 1032 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS],
dceaf394 1033 N_FLAG);
8170028d
TS
1034 }
1035 break;
1036 case CC_LS:
1037 cris_evaluate_flags(dc);
c5631f48 1038 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS],
dceaf394 1039 C_FLAG | Z_FLAG);
8170028d
TS
1040 break;
1041 case CC_HI:
1042 cris_evaluate_flags(dc);
dceaf394
EI
1043 {
1044 TCGv tmp;
1045
a7812ae4 1046 tmp = tcg_temp_new();
dceaf394
EI
1047 tcg_gen_xori_tl(tmp, cpu_PR[PR_CCS],
1048 C_FLAG | Z_FLAG);
1049 /* Overlay the C flag on top of the Z. */
c5631f48
EI
1050 tcg_gen_shli_tl(cc, tmp, 2);
1051 tcg_gen_and_tl(cc, tmp, cc);
1052 tcg_gen_andi_tl(cc, cc, Z_FLAG);
dceaf394 1053
30abcfc7 1054 tcg_temp_free(tmp);
dceaf394 1055 }
8170028d
TS
1056 break;
1057 case CC_GE:
1058 cris_evaluate_flags(dc);
dceaf394 1059 /* Overlay the V flag on top of the N. */
c5631f48
EI
1060 tcg_gen_shli_tl(cc, cpu_PR[PR_CCS], 2);
1061 tcg_gen_xor_tl(cc,
1062 cpu_PR[PR_CCS], cc);
1063 tcg_gen_andi_tl(cc, cc, N_FLAG);
1064 tcg_gen_xori_tl(cc, cc, N_FLAG);
8170028d
TS
1065 break;
1066 case CC_LT:
1067 cris_evaluate_flags(dc);
dceaf394 1068 /* Overlay the V flag on top of the N. */
c5631f48
EI
1069 tcg_gen_shli_tl(cc, cpu_PR[PR_CCS], 2);
1070 tcg_gen_xor_tl(cc,
1071 cpu_PR[PR_CCS], cc);
1072 tcg_gen_andi_tl(cc, cc, N_FLAG);
8170028d
TS
1073 break;
1074 case CC_GT:
1075 cris_evaluate_flags(dc);
dceaf394
EI
1076 {
1077 TCGv n, z;
1078
a7812ae4
PB
1079 n = tcg_temp_new();
1080 z = tcg_temp_new();
dceaf394
EI
1081
1082 /* To avoid a shift we overlay everything on
1083 the V flag. */
1084 tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2);
1085 tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1);
1086 /* invert Z. */
1087 tcg_gen_xori_tl(z, z, 2);
1088
1089 tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]);
1090 tcg_gen_xori_tl(n, n, 2);
c5631f48
EI
1091 tcg_gen_and_tl(cc, z, n);
1092 tcg_gen_andi_tl(cc, cc, 2);
dceaf394 1093
30abcfc7
EI
1094 tcg_temp_free(n);
1095 tcg_temp_free(z);
dceaf394 1096 }
8170028d
TS
1097 break;
1098 case CC_LE:
1099 cris_evaluate_flags(dc);
dceaf394
EI
1100 {
1101 TCGv n, z;
1102
a7812ae4
PB
1103 n = tcg_temp_new();
1104 z = tcg_temp_new();
dceaf394
EI
1105
1106 /* To avoid a shift we overlay everything on
1107 the V flag. */
1108 tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2);
1109 tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1);
1110
1111 tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]);
c5631f48
EI
1112 tcg_gen_or_tl(cc, z, n);
1113 tcg_gen_andi_tl(cc, cc, 2);
dceaf394 1114
30abcfc7
EI
1115 tcg_temp_free(n);
1116 tcg_temp_free(z);
dceaf394 1117 }
8170028d
TS
1118 break;
1119 case CC_P:
1120 cris_evaluate_flags(dc);
c5631f48 1121 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], P_FLAG);
8170028d
TS
1122 break;
1123 case CC_A:
c5631f48 1124 tcg_gen_movi_tl(cc, 1);
8170028d
TS
1125 break;
1126 default:
1127 BUG();
1128 break;
1129 };
1130}
1131
2a44f7f1
EI
1132static void cris_store_direct_jmp(DisasContext *dc)
1133{
1134 /* Store the direct jmp state into the cpu-state. */
1135 if (dc->jmp == JMP_DIRECT) {
1136 tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
1137 tcg_gen_movi_tl(env_btaken, 1);
1138 }
1139}
1140
1141static void cris_prepare_cc_branch (DisasContext *dc,
1142 int offset, int cond)
8170028d
TS
1143{
1144 /* This helps us re-schedule the micro-code to insns in delay-slots
1145 before the actual jump. */
1146 dc->delayed_branch = 2;
2a44f7f1
EI
1147 dc->jmp_pc = dc->pc + offset;
1148
8170028d
TS
1149 if (cond != CC_A)
1150 {
2a44f7f1 1151 dc->jmp = JMP_INDIRECT;
c5631f48 1152 gen_tst_cc (dc, env_btaken, cond);
2a44f7f1
EI
1153 tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
1154 } else {
1155 /* Allow chaining. */
1156 dc->jmp = JMP_DIRECT;
1157 }
8170028d
TS
1158}
1159
b41f7df0 1160
2a44f7f1
EI
1161/* jumps, when the dest is in a live reg for example. Direct should be set
1162 when the dest addr is constant to allow tb chaining. */
1163static inline void cris_prepare_jmp (DisasContext *dc, unsigned int type)
8170028d
TS
1164{
1165 /* This helps us re-schedule the micro-code to insns in delay-slots
1166 before the actual jump. */
1167 dc->delayed_branch = 2;
2a44f7f1
EI
1168 dc->jmp = type;
1169 if (type == JMP_INDIRECT)
1170 tcg_gen_movi_tl(env_btaken, 1);
8170028d
TS
1171}
1172
a7812ae4
PB
1173static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr)
1174{
1175 int mem_index = cpu_mmu_index(dc->env);
1176
1177 /* If we get a fault on a delayslot we must keep the jmp state in
1178 the cpu-state to be able to re-execute the jmp. */
1179 if (dc->delayed_branch == 1)
1180 cris_store_direct_jmp(dc);
1181
1182 tcg_gen_qemu_ld64(dst, addr, mem_index);
1183}
1184
9b32fbf8
EI
1185static void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
1186 unsigned int size, int sign)
8170028d 1187{
b41f7df0
EI
1188 int mem_index = cpu_mmu_index(dc->env);
1189
2a44f7f1
EI
1190 /* If we get a fault on a delayslot we must keep the jmp state in
1191 the cpu-state to be able to re-execute the jmp. */
1192 if (dc->delayed_branch == 1)
1193 cris_store_direct_jmp(dc);
1194
8170028d
TS
1195 if (size == 1) {
1196 if (sign)
b41f7df0 1197 tcg_gen_qemu_ld8s(dst, addr, mem_index);
8170028d 1198 else
b41f7df0 1199 tcg_gen_qemu_ld8u(dst, addr, mem_index);
8170028d
TS
1200 }
1201 else if (size == 2) {
1202 if (sign)
b41f7df0 1203 tcg_gen_qemu_ld16s(dst, addr, mem_index);
8170028d 1204 else
b41f7df0 1205 tcg_gen_qemu_ld16u(dst, addr, mem_index);
8170028d 1206 }
28de16da 1207 else if (size == 4) {
30abcfc7 1208 tcg_gen_qemu_ld32u(dst, addr, mem_index);
8170028d 1209 }
a7812ae4
PB
1210 else {
1211 abort();
28de16da 1212 }
8170028d
TS
1213}
1214
9b32fbf8
EI
1215static void gen_store (DisasContext *dc, TCGv addr, TCGv val,
1216 unsigned int size)
8170028d 1217{
b41f7df0
EI
1218 int mem_index = cpu_mmu_index(dc->env);
1219
2a44f7f1
EI
1220 /* If we get a fault on a delayslot we must keep the jmp state in
1221 the cpu-state to be able to re-execute the jmp. */
1222 if (dc->delayed_branch == 1)
1223 cris_store_direct_jmp(dc);
1224
1225
1226 /* Conditional writes. We only support the kind were X and P are known
1227 at translation time. */
1228 if (dc->flagx_known && dc->flags_x && (dc->tb_flags & P_FLAG)) {
1229 dc->postinc = 0;
1230 cris_evaluate_flags(dc);
1231 tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], C_FLAG);
1232 return;
1233 }
1234
b41f7df0 1235 if (size == 1)
17ac9754 1236 tcg_gen_qemu_st8(val, addr, mem_index);
b41f7df0 1237 else if (size == 2)
17ac9754 1238 tcg_gen_qemu_st16(val, addr, mem_index);
8170028d 1239 else
17ac9754 1240 tcg_gen_qemu_st32(val, addr, mem_index);
2a44f7f1
EI
1241
1242 if (dc->flagx_known && dc->flags_x) {
1243 cris_evaluate_flags(dc);
1244 tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~C_FLAG);
1245 }
8170028d
TS
1246}
1247
05ba7d5f 1248static inline void t_gen_sext(TCGv d, TCGv s, int size)
8170028d
TS
1249{
1250 if (size == 1)
05ba7d5f 1251 tcg_gen_ext8s_i32(d, s);
8170028d 1252 else if (size == 2)
05ba7d5f 1253 tcg_gen_ext16s_i32(d, s);
a7812ae4 1254 else if(!TCGV_EQUAL(d, s))
50cfa95c 1255 tcg_gen_mov_tl(d, s);
8170028d
TS
1256}
1257
05ba7d5f 1258static inline void t_gen_zext(TCGv d, TCGv s, int size)
8170028d
TS
1259{
1260 if (size == 1)
86831435 1261 tcg_gen_ext8u_i32(d, s);
8170028d 1262 else if (size == 2)
86831435 1263 tcg_gen_ext16u_i32(d, s);
a7812ae4 1264 else if (!TCGV_EQUAL(d, s))
50cfa95c 1265 tcg_gen_mov_tl(d, s);
8170028d
TS
1266}
1267
1268#if DISAS_CRIS
1269static char memsize_char(int size)
1270{
1271 switch (size)
1272 {
1273 case 1: return 'b'; break;
1274 case 2: return 'w'; break;
1275 case 4: return 'd'; break;
1276 default:
1277 return 'x';
1278 break;
1279 }
1280}
1281#endif
1282
30abcfc7 1283static inline unsigned int memsize_z(DisasContext *dc)
8170028d
TS
1284{
1285 return dc->zsize + 1;
1286}
1287
30abcfc7 1288static inline unsigned int memsize_zz(DisasContext *dc)
8170028d
TS
1289{
1290 switch (dc->zzsize)
1291 {
1292 case 0: return 1;
1293 case 1: return 2;
1294 default:
1295 return 4;
1296 }
1297}
1298
c7d05695 1299static inline void do_postinc (DisasContext *dc, int size)
8170028d 1300{
c7d05695
EI
1301 if (dc->postinc)
1302 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], size);
8170028d
TS
1303}
1304
30abcfc7 1305static inline void dec_prep_move_r(DisasContext *dc, int rs, int rd,
43d7ac4e 1306 int size, int s_ext, TCGv dst)
8170028d 1307{
8170028d 1308 if (s_ext)
30abcfc7 1309 t_gen_sext(dst, cpu_R[rs], size);
8170028d 1310 else
30abcfc7 1311 t_gen_zext(dst, cpu_R[rs], size);
8170028d
TS
1312}
1313
1314/* Prepare T0 and T1 for a register alu operation.
1315 s_ext decides if the operand1 should be sign-extended or zero-extended when
1316 needed. */
1317static void dec_prep_alu_r(DisasContext *dc, int rs, int rd,
fb48f71b 1318 int size, int s_ext, TCGv dst, TCGv src)
8170028d 1319{
fb48f71b 1320 dec_prep_move_r(dc, rs, rd, size, s_ext, src);
8170028d 1321
8170028d 1322 if (s_ext)
fb48f71b 1323 t_gen_sext(dst, cpu_R[rd], size);
8170028d 1324 else
fb48f71b 1325 t_gen_zext(dst, cpu_R[rd], size);
8170028d
TS
1326}
1327
30abcfc7
EI
1328static int dec_prep_move_m(DisasContext *dc, int s_ext, int memsize,
1329 TCGv dst)
8170028d 1330{
0d84be5b 1331 unsigned int rs;
8170028d
TS
1332 uint32_t imm;
1333 int is_imm;
1334 int insn_len = 2;
1335
1336 rs = dc->op1;
8170028d
TS
1337 is_imm = rs == 15 && dc->postinc;
1338
1339 /* Load [$rs] onto T1. */
1340 if (is_imm) {
1341 insn_len = 2 + memsize;
1342 if (memsize == 1)
1343 insn_len++;
1344
7de141cb 1345 imm = cris_fetch(dc, dc->pc + 2, memsize, s_ext);
30abcfc7 1346 tcg_gen_movi_tl(dst, imm);
8170028d
TS
1347 dc->postinc = 0;
1348 } else {
30abcfc7
EI
1349 cris_flush_cc_state(dc);
1350 gen_load(dc, dst, cpu_R[rs], memsize, 0);
8170028d 1351 if (s_ext)
30abcfc7 1352 t_gen_sext(dst, dst, memsize);
8170028d 1353 else
30abcfc7 1354 t_gen_zext(dst, dst, memsize);
8170028d 1355 }
cf1d97f0
EI
1356 return insn_len;
1357}
1358
1359/* Prepare T0 and T1 for a memory + alu operation.
1360 s_ext decides if the operand1 should be sign-extended or zero-extended when
1361 needed. */
31c18d87
EI
1362static int dec_prep_alu_m(DisasContext *dc, int s_ext, int memsize,
1363 TCGv dst, TCGv src)
cf1d97f0
EI
1364{
1365 int insn_len;
1366
31c18d87
EI
1367 insn_len = dec_prep_move_m(dc, s_ext, memsize, src);
1368 tcg_gen_mov_tl(dst, cpu_R[dc->op2]);
8170028d
TS
1369 return insn_len;
1370}
1371
1372#if DISAS_CRIS
1373static const char *cc_name(int cc)
1374{
9b32fbf8 1375 static const char *cc_names[16] = {
8170028d
TS
1376 "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi",
1377 "ls", "hi", "ge", "lt", "gt", "le", "a", "p"
1378 };
1379 assert(cc < 16);
1380 return cc_names[cc];
1381}
1382#endif
1383
b41f7df0
EI
1384/* Start of insn decoders. */
1385
a699a7be 1386static int dec_bccq(DisasContext *dc)
8170028d
TS
1387{
1388 int32_t offset;
1389 int sign;
1390 uint32_t cond = dc->op2;
8170028d
TS
1391
1392 offset = EXTRACT_FIELD (dc->ir, 1, 7);
1393 sign = EXTRACT_FIELD(dc->ir, 0, 0);
1394
1395 offset *= 2;
1396 offset |= sign << 8;
8170028d
TS
1397 offset = sign_extend(offset, 8);
1398
d12d51d5 1399 LOG_DIS("b%s %x\n", cc_name(cond), dc->pc + offset);
2a44f7f1 1400
8170028d
TS
1401 /* op2 holds the condition-code. */
1402 cris_cc_mask(dc, 0);
1403 cris_prepare_cc_branch (dc, offset, cond);
1404 return 2;
1405}
a699a7be 1406static int dec_addoq(DisasContext *dc)
8170028d 1407{
b41f7df0 1408 int32_t imm;
8170028d
TS
1409
1410 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 7);
1411 imm = sign_extend(dc->op1, 7);
1412
d12d51d5 1413 LOG_DIS("addoq %d, $r%u\n", imm, dc->op2);
8170028d
TS
1414 cris_cc_mask(dc, 0);
1415 /* Fetch register operand, */
b41f7df0 1416 tcg_gen_addi_tl(cpu_R[R_ACR], cpu_R[dc->op2], imm);
fb48f71b 1417
8170028d
TS
1418 return 2;
1419}
a699a7be 1420static int dec_addq(DisasContext *dc)
8170028d 1421{
d12d51d5 1422 LOG_DIS("addq %u, $r%u\n", dc->op1, dc->op2);
8170028d
TS
1423
1424 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1425
1426 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7
EI
1427
1428 cris_alu(dc, CC_OP_ADD,
1429 cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
8170028d
TS
1430 return 2;
1431}
a699a7be 1432static int dec_moveq(DisasContext *dc)
8170028d
TS
1433{
1434 uint32_t imm;
1435
1436 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1437 imm = sign_extend(dc->op1, 5);
d12d51d5 1438 LOG_DIS("moveq %d, $r%u\n", imm, dc->op2);
8170028d 1439
46e246c9 1440 tcg_gen_movi_tl(cpu_R[dc->op2], imm);
8170028d
TS
1441 return 2;
1442}
a699a7be 1443static int dec_subq(DisasContext *dc)
8170028d
TS
1444{
1445 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1446
d12d51d5 1447 LOG_DIS("subq %u, $r%u\n", dc->op1, dc->op2);
8170028d
TS
1448
1449 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7
EI
1450 cris_alu(dc, CC_OP_SUB,
1451 cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
8170028d
TS
1452 return 2;
1453}
a699a7be 1454static int dec_cmpq(DisasContext *dc)
8170028d
TS
1455{
1456 uint32_t imm;
1457 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1458 imm = sign_extend(dc->op1, 5);
1459
d12d51d5 1460 LOG_DIS("cmpq %d, $r%d\n", imm, dc->op2);
8170028d 1461 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7
EI
1462
1463 cris_alu(dc, CC_OP_CMP,
1464 cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
8170028d
TS
1465 return 2;
1466}
a699a7be 1467static int dec_andq(DisasContext *dc)
8170028d
TS
1468{
1469 uint32_t imm;
1470 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1471 imm = sign_extend(dc->op1, 5);
1472
d12d51d5 1473 LOG_DIS("andq %d, $r%d\n", imm, dc->op2);
8170028d 1474 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7
EI
1475
1476 cris_alu(dc, CC_OP_AND,
1477 cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
8170028d
TS
1478 return 2;
1479}
a699a7be 1480static int dec_orq(DisasContext *dc)
8170028d
TS
1481{
1482 uint32_t imm;
1483 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1484 imm = sign_extend(dc->op1, 5);
d12d51d5 1485 LOG_DIS("orq %d, $r%d\n", imm, dc->op2);
8170028d 1486 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7
EI
1487
1488 cris_alu(dc, CC_OP_OR,
1489 cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
8170028d
TS
1490 return 2;
1491}
a699a7be 1492static int dec_btstq(DisasContext *dc)
8170028d
TS
1493{
1494 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
d12d51d5 1495 LOG_DIS("btstq %u, $r%d\n", dc->op1, dc->op2);
17ac9754 1496
8170028d 1497 cris_cc_mask(dc, CC_MASK_NZ);
abd5c94e
EI
1498 cris_evaluate_flags(dc);
1499 gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->op2],
1500 tcg_const_tl(dc->op1), cpu_PR[PR_CCS]);
1501 cris_alu(dc, CC_OP_MOVE,
1502 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4);
b41f7df0 1503 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
30abcfc7 1504 dc->flags_uptodate = 1;
8170028d
TS
1505 return 2;
1506}
a699a7be 1507static int dec_asrq(DisasContext *dc)
8170028d
TS
1508{
1509 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
d12d51d5 1510 LOG_DIS("asrq %u, $r%d\n", dc->op1, dc->op2);
8170028d 1511 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7 1512
2a44f7f1
EI
1513 tcg_gen_sari_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
1514 cris_alu(dc, CC_OP_MOVE,
30abcfc7 1515 cpu_R[dc->op2],
2a44f7f1 1516 cpu_R[dc->op2], cpu_R[dc->op2], 4);
8170028d
TS
1517 return 2;
1518}
a699a7be 1519static int dec_lslq(DisasContext *dc)
8170028d
TS
1520{
1521 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
d12d51d5 1522 LOG_DIS("lslq %u, $r%d\n", dc->op1, dc->op2);
8170028d
TS
1523
1524 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7 1525
2a44f7f1
EI
1526 tcg_gen_shli_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
1527
1528 cris_alu(dc, CC_OP_MOVE,
30abcfc7 1529 cpu_R[dc->op2],
2a44f7f1 1530 cpu_R[dc->op2], cpu_R[dc->op2], 4);
8170028d
TS
1531 return 2;
1532}
a699a7be 1533static int dec_lsrq(DisasContext *dc)
8170028d
TS
1534{
1535 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
d12d51d5 1536 LOG_DIS("lsrq %u, $r%d\n", dc->op1, dc->op2);
8170028d
TS
1537
1538 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7 1539
2a44f7f1
EI
1540 tcg_gen_shri_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
1541 cris_alu(dc, CC_OP_MOVE,
30abcfc7 1542 cpu_R[dc->op2],
2a44f7f1 1543 cpu_R[dc->op2], cpu_R[dc->op2], 4);
8170028d
TS
1544 return 2;
1545}
1546
a699a7be 1547static int dec_move_r(DisasContext *dc)
8170028d
TS
1548{
1549 int size = memsize_zz(dc);
1550
d12d51d5
AL
1551 LOG_DIS("move.%c $r%u, $r%u\n",
1552 memsize_char(size), dc->op1, dc->op2);
8170028d
TS
1553
1554 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7
EI
1555 if (size == 4) {
1556 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, cpu_R[dc->op2]);
1557 cris_cc_mask(dc, CC_MASK_NZ);
1558 cris_update_cc_op(dc, CC_OP_MOVE, 4);
1559 cris_update_cc_x(dc);
1560 cris_update_result(dc, cpu_R[dc->op2]);
1561 }
1562 else {
43d7ac4e
EI
1563 TCGv t0;
1564
a7812ae4 1565 t0 = tcg_temp_new();
43d7ac4e 1566 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0);
30abcfc7
EI
1567 cris_alu(dc, CC_OP_MOVE,
1568 cpu_R[dc->op2],
43d7ac4e
EI
1569 cpu_R[dc->op2], t0, size);
1570 tcg_temp_free(t0);
30abcfc7 1571 }
8170028d
TS
1572 return 2;
1573}
1574
a699a7be 1575static int dec_scc_r(DisasContext *dc)
8170028d
TS
1576{
1577 int cond = dc->op2;
1578
d12d51d5
AL
1579 LOG_DIS("s%s $r%u\n",
1580 cc_name(cond), dc->op1);
8170028d
TS
1581
1582 if (cond != CC_A)
1583 {
dceaf394
EI
1584 int l1;
1585
c5631f48 1586 gen_tst_cc (dc, cpu_R[dc->op1], cond);
dceaf394 1587 l1 = gen_new_label();
c5631f48 1588 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[dc->op1], 0, l1);
dceaf394
EI
1589 tcg_gen_movi_tl(cpu_R[dc->op1], 1);
1590 gen_set_label(l1);
8170028d
TS
1591 }
1592 else
dceaf394 1593 tcg_gen_movi_tl(cpu_R[dc->op1], 1);
8170028d
TS
1594
1595 cris_cc_mask(dc, 0);
8170028d
TS
1596 return 2;
1597}
1598
fb48f71b
EI
1599static inline void cris_alu_alloc_temps(DisasContext *dc, int size, TCGv *t)
1600{
1601 if (size == 4) {
1602 t[0] = cpu_R[dc->op2];
1603 t[1] = cpu_R[dc->op1];
1604 } else {
a7812ae4
PB
1605 t[0] = tcg_temp_new();
1606 t[1] = tcg_temp_new();
fb48f71b
EI
1607 }
1608}
1609
1610static inline void cris_alu_free_temps(DisasContext *dc, int size, TCGv *t)
1611{
1612 if (size != 4) {
1613 tcg_temp_free(t[0]);
1614 tcg_temp_free(t[1]);
1615 }
1616}
1617
a699a7be 1618static int dec_and_r(DisasContext *dc)
8170028d 1619{
fb48f71b 1620 TCGv t[2];
8170028d
TS
1621 int size = memsize_zz(dc);
1622
d12d51d5
AL
1623 LOG_DIS("and.%c $r%u, $r%u\n",
1624 memsize_char(size), dc->op1, dc->op2);
fb48f71b 1625
8170028d 1626 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7 1627
fb48f71b
EI
1628 cris_alu_alloc_temps(dc, size, t);
1629 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1630 cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], size);
1631 cris_alu_free_temps(dc, size, t);
8170028d
TS
1632 return 2;
1633}
1634
a699a7be 1635static int dec_lz_r(DisasContext *dc)
8170028d 1636{
fb48f71b 1637 TCGv t0;
d12d51d5
AL
1638 LOG_DIS("lz $r%u, $r%u\n",
1639 dc->op1, dc->op2);
8170028d 1640 cris_cc_mask(dc, CC_MASK_NZ);
a7812ae4 1641 t0 = tcg_temp_new();
fb48f71b
EI
1642 dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0, cpu_R[dc->op2], t0);
1643 cris_alu(dc, CC_OP_LZ, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
1644 tcg_temp_free(t0);
8170028d
TS
1645 return 2;
1646}
1647
a699a7be 1648static int dec_lsl_r(DisasContext *dc)
8170028d 1649{
fb48f71b 1650 TCGv t[2];
8170028d
TS
1651 int size = memsize_zz(dc);
1652
d12d51d5
AL
1653 LOG_DIS("lsl.%c $r%u, $r%u\n",
1654 memsize_char(size), dc->op1, dc->op2);
30abcfc7 1655
fb48f71b
EI
1656 cris_cc_mask(dc, CC_MASK_NZ);
1657 cris_alu_alloc_temps(dc, size, t);
1658 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1659 tcg_gen_andi_tl(t[1], t[1], 63);
1660 cris_alu(dc, CC_OP_LSL, cpu_R[dc->op2], t[0], t[1], size);
1661 cris_alu_alloc_temps(dc, size, t);
8170028d
TS
1662 return 2;
1663}
1664
a699a7be 1665static int dec_lsr_r(DisasContext *dc)
8170028d 1666{
fb48f71b 1667 TCGv t[2];
8170028d
TS
1668 int size = memsize_zz(dc);
1669
d12d51d5
AL
1670 LOG_DIS("lsr.%c $r%u, $r%u\n",
1671 memsize_char(size), dc->op1, dc->op2);
30abcfc7 1672
fb48f71b
EI
1673 cris_cc_mask(dc, CC_MASK_NZ);
1674 cris_alu_alloc_temps(dc, size, t);
1675 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1676 tcg_gen_andi_tl(t[1], t[1], 63);
1677 cris_alu(dc, CC_OP_LSR, cpu_R[dc->op2], t[0], t[1], size);
1678 cris_alu_free_temps(dc, size, t);
8170028d
TS
1679 return 2;
1680}
1681
a699a7be 1682static int dec_asr_r(DisasContext *dc)
8170028d 1683{
fb48f71b 1684 TCGv t[2];
8170028d
TS
1685 int size = memsize_zz(dc);
1686
d12d51d5
AL
1687 LOG_DIS("asr.%c $r%u, $r%u\n",
1688 memsize_char(size), dc->op1, dc->op2);
30abcfc7 1689
fb48f71b
EI
1690 cris_cc_mask(dc, CC_MASK_NZ);
1691 cris_alu_alloc_temps(dc, size, t);
1692 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]);
1693 tcg_gen_andi_tl(t[1], t[1], 63);
1694 cris_alu(dc, CC_OP_ASR, cpu_R[dc->op2], t[0], t[1], size);
1695 cris_alu_free_temps(dc, size, t);
8170028d
TS
1696 return 2;
1697}
1698
a699a7be 1699static int dec_muls_r(DisasContext *dc)
8170028d 1700{
fb48f71b 1701 TCGv t[2];
8170028d
TS
1702 int size = memsize_zz(dc);
1703
d12d51d5
AL
1704 LOG_DIS("muls.%c $r%u, $r%u\n",
1705 memsize_char(size), dc->op1, dc->op2);
8170028d 1706 cris_cc_mask(dc, CC_MASK_NZV);
fb48f71b
EI
1707 cris_alu_alloc_temps(dc, size, t);
1708 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]);
30abcfc7 1709
fb48f71b
EI
1710 cris_alu(dc, CC_OP_MULS, cpu_R[dc->op2], t[0], t[1], 4);
1711 cris_alu_free_temps(dc, size, t);
8170028d
TS
1712 return 2;
1713}
1714
a699a7be 1715static int dec_mulu_r(DisasContext *dc)
8170028d 1716{
fb48f71b 1717 TCGv t[2];
8170028d
TS
1718 int size = memsize_zz(dc);
1719
d12d51d5
AL
1720 LOG_DIS("mulu.%c $r%u, $r%u\n",
1721 memsize_char(size), dc->op1, dc->op2);
8170028d 1722 cris_cc_mask(dc, CC_MASK_NZV);
fb48f71b
EI
1723 cris_alu_alloc_temps(dc, size, t);
1724 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
30abcfc7 1725
fb48f71b
EI
1726 cris_alu(dc, CC_OP_MULU, cpu_R[dc->op2], t[0], t[1], 4);
1727 cris_alu_alloc_temps(dc, size, t);
8170028d
TS
1728 return 2;
1729}
1730
1731
a699a7be 1732static int dec_dstep_r(DisasContext *dc)
8170028d 1733{
d12d51d5 1734 LOG_DIS("dstep $r%u, $r%u\n", dc->op1, dc->op2);
8170028d 1735 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7
EI
1736 cris_alu(dc, CC_OP_DSTEP,
1737 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
8170028d
TS
1738 return 2;
1739}
1740
a699a7be 1741static int dec_xor_r(DisasContext *dc)
8170028d 1742{
fb48f71b 1743 TCGv t[2];
8170028d 1744 int size = memsize_zz(dc);
d12d51d5
AL
1745 LOG_DIS("xor.%c $r%u, $r%u\n",
1746 memsize_char(size), dc->op1, dc->op2);
8170028d
TS
1747 BUG_ON(size != 4); /* xor is dword. */
1748 cris_cc_mask(dc, CC_MASK_NZ);
fb48f71b
EI
1749 cris_alu_alloc_temps(dc, size, t);
1750 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
30abcfc7 1751
fb48f71b
EI
1752 cris_alu(dc, CC_OP_XOR, cpu_R[dc->op2], t[0], t[1], 4);
1753 cris_alu_free_temps(dc, size, t);
8170028d
TS
1754 return 2;
1755}
1756
a699a7be 1757static int dec_bound_r(DisasContext *dc)
8170028d 1758{
fb48f71b 1759 TCGv l0;
8170028d 1760 int size = memsize_zz(dc);
d12d51d5
AL
1761 LOG_DIS("bound.%c $r%u, $r%u\n",
1762 memsize_char(size), dc->op1, dc->op2);
8170028d 1763 cris_cc_mask(dc, CC_MASK_NZ);
a7812ae4 1764 l0 = tcg_temp_local_new();
fb48f71b 1765 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, l0);
31c18d87
EI
1766 cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], cpu_R[dc->op2], l0, 4);
1767 tcg_temp_free(l0);
8170028d
TS
1768 return 2;
1769}
1770
a699a7be 1771static int dec_cmp_r(DisasContext *dc)
8170028d 1772{
fb48f71b 1773 TCGv t[2];
8170028d 1774 int size = memsize_zz(dc);
d12d51d5
AL
1775 LOG_DIS("cmp.%c $r%u, $r%u\n",
1776 memsize_char(size), dc->op1, dc->op2);
8170028d 1777 cris_cc_mask(dc, CC_MASK_NZVC);
fb48f71b
EI
1778 cris_alu_alloc_temps(dc, size, t);
1779 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
30abcfc7 1780
fb48f71b
EI
1781 cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], t[0], t[1], size);
1782 cris_alu_free_temps(dc, size, t);
8170028d
TS
1783 return 2;
1784}
1785
a699a7be 1786static int dec_abs_r(DisasContext *dc)
8170028d 1787{
7dcfb089 1788 TCGv t0;
3157a0a9 1789
d12d51d5
AL
1790 LOG_DIS("abs $r%u, $r%u\n",
1791 dc->op1, dc->op2);
8170028d 1792 cris_cc_mask(dc, CC_MASK_NZ);
3157a0a9 1793
a7812ae4 1794 t0 = tcg_temp_new();
7dcfb089
EI
1795 tcg_gen_sari_tl(t0, cpu_R[dc->op1], 31);
1796 tcg_gen_xor_tl(cpu_R[dc->op2], cpu_R[dc->op1], t0);
1797 tcg_gen_sub_tl(cpu_R[dc->op2], cpu_R[dc->op2], t0);
1798 tcg_temp_free(t0);
1799
30abcfc7 1800 cris_alu(dc, CC_OP_MOVE,
7dcfb089 1801 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4);
8170028d
TS
1802 return 2;
1803}
1804
a699a7be 1805static int dec_add_r(DisasContext *dc)
8170028d 1806{
fb48f71b 1807 TCGv t[2];
8170028d 1808 int size = memsize_zz(dc);
d12d51d5
AL
1809 LOG_DIS("add.%c $r%u, $r%u\n",
1810 memsize_char(size), dc->op1, dc->op2);
8170028d 1811 cris_cc_mask(dc, CC_MASK_NZVC);
fb48f71b
EI
1812 cris_alu_alloc_temps(dc, size, t);
1813 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
30abcfc7 1814
fb48f71b
EI
1815 cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], t[0], t[1], size);
1816 cris_alu_free_temps(dc, size, t);
8170028d
TS
1817 return 2;
1818}
1819
a699a7be 1820static int dec_addc_r(DisasContext *dc)
8170028d 1821{
d12d51d5
AL
1822 LOG_DIS("addc $r%u, $r%u\n",
1823 dc->op1, dc->op2);
8170028d 1824 cris_evaluate_flags(dc);
a8cf66bb
EI
1825 /* Set for this insn. */
1826 dc->flagx_known = 1;
1827 dc->flags_x = X_FLAG;
1828
8170028d 1829 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7 1830 cris_alu(dc, CC_OP_ADDC,
fb48f71b 1831 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
8170028d
TS
1832 return 2;
1833}
1834
a699a7be 1835static int dec_mcp_r(DisasContext *dc)
8170028d 1836{
d12d51d5
AL
1837 LOG_DIS("mcp $p%u, $r%u\n",
1838 dc->op2, dc->op1);
8170028d
TS
1839 cris_evaluate_flags(dc);
1840 cris_cc_mask(dc, CC_MASK_RNZV);
30abcfc7
EI
1841 cris_alu(dc, CC_OP_MCP,
1842 cpu_R[dc->op1], cpu_R[dc->op1], cpu_PR[dc->op2], 4);
8170028d
TS
1843 return 2;
1844}
1845
1846#if DISAS_CRIS
1847static char * swapmode_name(int mode, char *modename) {
1848 int i = 0;
1849 if (mode & 8)
1850 modename[i++] = 'n';
1851 if (mode & 4)
1852 modename[i++] = 'w';
1853 if (mode & 2)
1854 modename[i++] = 'b';
1855 if (mode & 1)
1856 modename[i++] = 'r';
1857 modename[i++] = 0;
1858 return modename;
1859}
1860#endif
1861
a699a7be 1862static int dec_swap_r(DisasContext *dc)
8170028d 1863{
fb48f71b 1864 TCGv t0;
cf1d97f0
EI
1865#if DISAS_CRIS
1866 char modename[4];
1867#endif
d12d51d5
AL
1868 LOG_DIS("swap%s $r%u\n",
1869 swapmode_name(dc->op2, modename), dc->op1);
8170028d
TS
1870
1871 cris_cc_mask(dc, CC_MASK_NZ);
a7812ae4 1872 t0 = tcg_temp_new();
fb48f71b 1873 t_gen_mov_TN_reg(t0, dc->op1);
8170028d 1874 if (dc->op2 & 8)
fb48f71b 1875 tcg_gen_not_tl(t0, t0);
8170028d 1876 if (dc->op2 & 4)
fb48f71b 1877 t_gen_swapw(t0, t0);
8170028d 1878 if (dc->op2 & 2)
fb48f71b 1879 t_gen_swapb(t0, t0);
8170028d 1880 if (dc->op2 & 1)
fb48f71b 1881 t_gen_swapr(t0, t0);
30abcfc7 1882 cris_alu(dc, CC_OP_MOVE,
fb48f71b 1883 cpu_R[dc->op1], cpu_R[dc->op1], t0, 4);
f4b147f6 1884 tcg_temp_free(t0);
8170028d
TS
1885 return 2;
1886}
1887
a699a7be 1888static int dec_or_r(DisasContext *dc)
8170028d 1889{
fb48f71b 1890 TCGv t[2];
8170028d 1891 int size = memsize_zz(dc);
d12d51d5
AL
1892 LOG_DIS("or.%c $r%u, $r%u\n",
1893 memsize_char(size), dc->op1, dc->op2);
8170028d 1894 cris_cc_mask(dc, CC_MASK_NZ);
fb48f71b
EI
1895 cris_alu_alloc_temps(dc, size, t);
1896 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1897 cris_alu(dc, CC_OP_OR, cpu_R[dc->op2], t[0], t[1], size);
1898 cris_alu_free_temps(dc, size, t);
8170028d
TS
1899 return 2;
1900}
1901
a699a7be 1902static int dec_addi_r(DisasContext *dc)
8170028d 1903{
fb48f71b 1904 TCGv t0;
d12d51d5
AL
1905 LOG_DIS("addi.%c $r%u, $r%u\n",
1906 memsize_char(memsize_zz(dc)), dc->op2, dc->op1);
8170028d 1907 cris_cc_mask(dc, 0);
a7812ae4 1908 t0 = tcg_temp_new();
fb48f71b
EI
1909 tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize));
1910 tcg_gen_add_tl(cpu_R[dc->op1], cpu_R[dc->op1], t0);
f4b147f6 1911 tcg_temp_free(t0);
8170028d
TS
1912 return 2;
1913}
1914
a699a7be 1915static int dec_addi_acr(DisasContext *dc)
8170028d 1916{
fb48f71b 1917 TCGv t0;
d12d51d5
AL
1918 LOG_DIS("addi.%c $r%u, $r%u, $acr\n",
1919 memsize_char(memsize_zz(dc)), dc->op2, dc->op1);
8170028d 1920 cris_cc_mask(dc, 0);
a7812ae4 1921 t0 = tcg_temp_new();
fb48f71b
EI
1922 tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize));
1923 tcg_gen_add_tl(cpu_R[R_ACR], cpu_R[dc->op1], t0);
f4b147f6 1924 tcg_temp_free(t0);
8170028d
TS
1925 return 2;
1926}
1927
a699a7be 1928static int dec_neg_r(DisasContext *dc)
8170028d 1929{
fb48f71b 1930 TCGv t[2];
8170028d 1931 int size = memsize_zz(dc);
d12d51d5
AL
1932 LOG_DIS("neg.%c $r%u, $r%u\n",
1933 memsize_char(size), dc->op1, dc->op2);
8170028d 1934 cris_cc_mask(dc, CC_MASK_NZVC);
fb48f71b
EI
1935 cris_alu_alloc_temps(dc, size, t);
1936 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
30abcfc7 1937
fb48f71b
EI
1938 cris_alu(dc, CC_OP_NEG, cpu_R[dc->op2], t[0], t[1], size);
1939 cris_alu_free_temps(dc, size, t);
8170028d
TS
1940 return 2;
1941}
1942
a699a7be 1943static int dec_btst_r(DisasContext *dc)
8170028d 1944{
d12d51d5
AL
1945 LOG_DIS("btst $r%u, $r%u\n",
1946 dc->op1, dc->op2);
8170028d 1947 cris_cc_mask(dc, CC_MASK_NZ);
abd5c94e
EI
1948 cris_evaluate_flags(dc);
1949 gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->op2],
1950 cpu_R[dc->op1], cpu_PR[PR_CCS]);
1951 cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2],
1952 cpu_R[dc->op2], cpu_R[dc->op2], 4);
b41f7df0 1953 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
30abcfc7 1954 dc->flags_uptodate = 1;
8170028d
TS
1955 return 2;
1956}
1957
a699a7be 1958static int dec_sub_r(DisasContext *dc)
8170028d 1959{
fb48f71b 1960 TCGv t[2];
8170028d 1961 int size = memsize_zz(dc);
d12d51d5
AL
1962 LOG_DIS("sub.%c $r%u, $r%u\n",
1963 memsize_char(size), dc->op1, dc->op2);
8170028d 1964 cris_cc_mask(dc, CC_MASK_NZVC);
fb48f71b
EI
1965 cris_alu_alloc_temps(dc, size, t);
1966 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1967 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], size);
1968 cris_alu_free_temps(dc, size, t);
8170028d
TS
1969 return 2;
1970}
1971
1972/* Zero extension. From size to dword. */
a699a7be 1973static int dec_movu_r(DisasContext *dc)
8170028d 1974{
fb48f71b 1975 TCGv t0;
8170028d 1976 int size = memsize_z(dc);
d12d51d5 1977 LOG_DIS("movu.%c $r%u, $r%u\n",
8170028d 1978 memsize_char(size),
d12d51d5 1979 dc->op1, dc->op2);
8170028d
TS
1980
1981 cris_cc_mask(dc, CC_MASK_NZ);
a7812ae4 1982 t0 = tcg_temp_new();
fb48f71b
EI
1983 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0);
1984 cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
1985 tcg_temp_free(t0);
8170028d
TS
1986 return 2;
1987}
1988
1989/* Sign extension. From size to dword. */
a699a7be 1990static int dec_movs_r(DisasContext *dc)
8170028d 1991{
fb48f71b 1992 TCGv t0;
8170028d 1993 int size = memsize_z(dc);
d12d51d5 1994 LOG_DIS("movs.%c $r%u, $r%u\n",
8170028d 1995 memsize_char(size),
d12d51d5 1996 dc->op1, dc->op2);
8170028d
TS
1997
1998 cris_cc_mask(dc, CC_MASK_NZ);
a7812ae4 1999 t0 = tcg_temp_new();
8170028d 2000 /* Size can only be qi or hi. */
fb48f71b 2001 t_gen_sext(t0, cpu_R[dc->op1], size);
30abcfc7 2002 cris_alu(dc, CC_OP_MOVE,
fb48f71b
EI
2003 cpu_R[dc->op2], cpu_R[dc->op1], t0, 4);
2004 tcg_temp_free(t0);
8170028d
TS
2005 return 2;
2006}
2007
2008/* zero extension. From size to dword. */
a699a7be 2009static int dec_addu_r(DisasContext *dc)
8170028d 2010{
fb48f71b 2011 TCGv t0;
8170028d 2012 int size = memsize_z(dc);
d12d51d5 2013 LOG_DIS("addu.%c $r%u, $r%u\n",
8170028d 2014 memsize_char(size),
d12d51d5 2015 dc->op1, dc->op2);
8170028d
TS
2016
2017 cris_cc_mask(dc, CC_MASK_NZVC);
a7812ae4 2018 t0 = tcg_temp_new();
8170028d 2019 /* Size can only be qi or hi. */
fb48f71b 2020 t_gen_zext(t0, cpu_R[dc->op1], size);
30abcfc7 2021 cris_alu(dc, CC_OP_ADD,
fb48f71b
EI
2022 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
2023 tcg_temp_free(t0);
8170028d
TS
2024 return 2;
2025}
05ba7d5f 2026
8170028d 2027/* Sign extension. From size to dword. */
a699a7be 2028static int dec_adds_r(DisasContext *dc)
8170028d 2029{
fb48f71b 2030 TCGv t0;
8170028d 2031 int size = memsize_z(dc);
d12d51d5 2032 LOG_DIS("adds.%c $r%u, $r%u\n",
8170028d 2033 memsize_char(size),
d12d51d5 2034 dc->op1, dc->op2);
8170028d
TS
2035
2036 cris_cc_mask(dc, CC_MASK_NZVC);
a7812ae4 2037 t0 = tcg_temp_new();
8170028d 2038 /* Size can only be qi or hi. */
fb48f71b 2039 t_gen_sext(t0, cpu_R[dc->op1], size);
30abcfc7 2040 cris_alu(dc, CC_OP_ADD,
fb48f71b
EI
2041 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
2042 tcg_temp_free(t0);
8170028d
TS
2043 return 2;
2044}
2045
2046/* Zero extension. From size to dword. */
a699a7be 2047static int dec_subu_r(DisasContext *dc)
8170028d 2048{
fb48f71b 2049 TCGv t0;
8170028d 2050 int size = memsize_z(dc);
d12d51d5 2051 LOG_DIS("subu.%c $r%u, $r%u\n",
8170028d 2052 memsize_char(size),
d12d51d5 2053 dc->op1, dc->op2);
8170028d
TS
2054
2055 cris_cc_mask(dc, CC_MASK_NZVC);
a7812ae4 2056 t0 = tcg_temp_new();
8170028d 2057 /* Size can only be qi or hi. */
fb48f71b 2058 t_gen_zext(t0, cpu_R[dc->op1], size);
30abcfc7 2059 cris_alu(dc, CC_OP_SUB,
fb48f71b
EI
2060 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
2061 tcg_temp_free(t0);
8170028d
TS
2062 return 2;
2063}
2064
2065/* Sign extension. From size to dword. */
a699a7be 2066static int dec_subs_r(DisasContext *dc)
8170028d 2067{
fb48f71b 2068 TCGv t0;
8170028d 2069 int size = memsize_z(dc);
d12d51d5 2070 LOG_DIS("subs.%c $r%u, $r%u\n",
8170028d 2071 memsize_char(size),
d12d51d5 2072 dc->op1, dc->op2);
8170028d
TS
2073
2074 cris_cc_mask(dc, CC_MASK_NZVC);
a7812ae4 2075 t0 = tcg_temp_new();
8170028d 2076 /* Size can only be qi or hi. */
fb48f71b 2077 t_gen_sext(t0, cpu_R[dc->op1], size);
30abcfc7 2078 cris_alu(dc, CC_OP_SUB,
fb48f71b
EI
2079 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
2080 tcg_temp_free(t0);
8170028d
TS
2081 return 2;
2082}
2083
a699a7be 2084static int dec_setclrf(DisasContext *dc)
8170028d
TS
2085{
2086 uint32_t flags;
2087 int set = (~dc->opcode >> 2) & 1;
2088
fb48f71b 2089
8170028d
TS
2090 flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4)
2091 | EXTRACT_FIELD(dc->ir, 0, 3);
cf1d97f0 2092 if (set && flags == 0) {
d12d51d5 2093 LOG_DIS("nop\n");
30abcfc7 2094 return 2;
cf1d97f0 2095 } else if (!set && (flags & 0x20)) {
d12d51d5 2096 LOG_DIS("di\n");
cf1d97f0
EI
2097 }
2098 else {
d12d51d5 2099 LOG_DIS("%sf %x\n",
cf1d97f0 2100 set ? "set" : "clr",
d12d51d5 2101 flags);
cf1d97f0 2102 }
8170028d 2103
fb48f71b 2104 /* User space is not allowed to touch these. Silently ignore. */
2a44f7f1 2105 if (dc->tb_flags & U_FLAG) {
a1aebcb8 2106 flags &= ~(S_FLAG | I_FLAG | U_FLAG);
2a44f7f1
EI
2107 }
2108
2109 if (flags & X_FLAG) {
30abcfc7 2110 dc->flagx_known = 1;
2a44f7f1
EI
2111 if (set)
2112 dc->flags_x = X_FLAG;
2113 else
2114 dc->flags_x = 0;
8170028d
TS
2115 }
2116
40e9eddd
EI
2117 /* Break the TB if any of the SPI flag changes. */
2118 if (flags & (P_FLAG | S_FLAG)) {
2119 tcg_gen_movi_tl(env_pc, dc->pc + 2);
2120 dc->is_jmp = DISAS_UPDATE;
2121 dc->cpustate_changed = 1;
2a44f7f1 2122 }
40e9eddd
EI
2123
2124 /* For the I flag, only act on posedge. */
2125 if ((flags & I_FLAG)) {
2126 tcg_gen_movi_tl(env_pc, dc->pc + 2);
2127 dc->is_jmp = DISAS_UPDATE;
a1aebcb8
EI
2128 dc->cpustate_changed = 1;
2129 }
2a44f7f1
EI
2130
2131
8170028d
TS
2132 /* Simply decode the flags. */
2133 cris_evaluate_flags (dc);
b41f7df0 2134 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
30abcfc7 2135 cris_update_cc_x(dc);
b41f7df0
EI
2136 tcg_gen_movi_tl(cc_op, dc->cc_op);
2137
dceaf394 2138 if (set) {
2a44f7f1 2139 if (!(dc->tb_flags & U_FLAG) && (flags & U_FLAG)) {
dceaf394
EI
2140 /* Enter user mode. */
2141 t_gen_mov_env_TN(ksp, cpu_R[R_SP]);
2142 tcg_gen_mov_tl(cpu_R[R_SP], cpu_PR[PR_USP]);
2a44f7f1 2143 dc->cpustate_changed = 1;
dceaf394
EI
2144 }
2145 tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags);
2146 }
8170028d 2147 else
dceaf394
EI
2148 tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags);
2149
30abcfc7 2150 dc->flags_uptodate = 1;
b41f7df0 2151 dc->clear_x = 0;
8170028d
TS
2152 return 2;
2153}
2154
a699a7be 2155static int dec_move_rs(DisasContext *dc)
8170028d 2156{
d12d51d5 2157 LOG_DIS("move $r%u, $s%u\n", dc->op1, dc->op2);
8170028d 2158 cris_cc_mask(dc, 0);
a7812ae4 2159 gen_helper_movl_sreg_reg(tcg_const_tl(dc->op2), tcg_const_tl(dc->op1));
8170028d
TS
2160 return 2;
2161}
a699a7be 2162static int dec_move_sr(DisasContext *dc)
8170028d 2163{
d12d51d5 2164 LOG_DIS("move $s%u, $r%u\n", dc->op2, dc->op1);
8170028d 2165 cris_cc_mask(dc, 0);
a7812ae4 2166 gen_helper_movl_reg_sreg(tcg_const_tl(dc->op1), tcg_const_tl(dc->op2));
8170028d
TS
2167 return 2;
2168}
dceaf394 2169
a699a7be 2170static int dec_move_rp(DisasContext *dc)
8170028d 2171{
fb48f71b 2172 TCGv t[2];
d12d51d5 2173 LOG_DIS("move $r%u, $p%u\n", dc->op1, dc->op2);
8170028d 2174 cris_cc_mask(dc, 0);
b41f7df0 2175
a7812ae4 2176 t[0] = tcg_temp_new();
b41f7df0
EI
2177 if (dc->op2 == PR_CCS) {
2178 cris_evaluate_flags(dc);
fb48f71b 2179 t_gen_mov_TN_reg(t[0], dc->op1);
2a44f7f1 2180 if (dc->tb_flags & U_FLAG) {
a7812ae4 2181 t[1] = tcg_temp_new();
b41f7df0 2182 /* User space is not allowed to touch all flags. */
fb48f71b
EI
2183 tcg_gen_andi_tl(t[0], t[0], 0x39f);
2184 tcg_gen_andi_tl(t[1], cpu_PR[PR_CCS], ~0x39f);
2185 tcg_gen_or_tl(t[0], t[1], t[0]);
2186 tcg_temp_free(t[1]);
b41f7df0
EI
2187 }
2188 }
2189 else
fb48f71b 2190 t_gen_mov_TN_reg(t[0], dc->op1);
b41f7df0 2191
fb48f71b 2192 t_gen_mov_preg_TN(dc, dc->op2, t[0]);
b41f7df0
EI
2193 if (dc->op2 == PR_CCS) {
2194 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
30abcfc7 2195 dc->flags_uptodate = 1;
b41f7df0 2196 }
fb48f71b 2197 tcg_temp_free(t[0]);
8170028d
TS
2198 return 2;
2199}
a699a7be 2200static int dec_move_pr(DisasContext *dc)
8170028d 2201{
fb48f71b 2202 TCGv t0;
40e9eddd 2203 LOG_DIS("move $p%u, $r%u\n", dc->op2, dc->op1);
8170028d 2204 cris_cc_mask(dc, 0);
2a44f7f1
EI
2205
2206 if (dc->op2 == PR_CCS)
b41f7df0 2207 cris_evaluate_flags(dc);
2a44f7f1 2208
40e9eddd
EI
2209 if (dc->op2 == PR_DZ) {
2210 tcg_gen_movi_tl(cpu_R[dc->op1], 0);
2211 } else {
2212 t0 = tcg_temp_new();
2213 t_gen_mov_TN_preg(t0, dc->op2);
2214 cris_alu(dc, CC_OP_MOVE,
2215 cpu_R[dc->op1], cpu_R[dc->op1], t0,
2216 preg_sizes[dc->op2]);
2217 tcg_temp_free(t0);
2218 }
8170028d
TS
2219 return 2;
2220}
2221
a699a7be 2222static int dec_move_mr(DisasContext *dc)
8170028d
TS
2223{
2224 int memsize = memsize_zz(dc);
2225 int insn_len;
d12d51d5 2226 LOG_DIS("move.%c [$r%u%s, $r%u\n",
8170028d
TS
2227 memsize_char(memsize),
2228 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2229 dc->op2);
8170028d 2230
30abcfc7
EI
2231 if (memsize == 4) {
2232 insn_len = dec_prep_move_m(dc, 0, 4, cpu_R[dc->op2]);
2233 cris_cc_mask(dc, CC_MASK_NZ);
2234 cris_update_cc_op(dc, CC_OP_MOVE, 4);
2235 cris_update_cc_x(dc);
2236 cris_update_result(dc, cpu_R[dc->op2]);
2237 }
2238 else {
fb48f71b
EI
2239 TCGv t0;
2240
a7812ae4 2241 t0 = tcg_temp_new();
fb48f71b 2242 insn_len = dec_prep_move_m(dc, 0, memsize, t0);
30abcfc7
EI
2243 cris_cc_mask(dc, CC_MASK_NZ);
2244 cris_alu(dc, CC_OP_MOVE,
fb48f71b
EI
2245 cpu_R[dc->op2], cpu_R[dc->op2], t0, memsize);
2246 tcg_temp_free(t0);
30abcfc7 2247 }
8170028d
TS
2248 do_postinc(dc, memsize);
2249 return insn_len;
2250}
2251
31c18d87
EI
2252static inline void cris_alu_m_alloc_temps(TCGv *t)
2253{
a7812ae4
PB
2254 t[0] = tcg_temp_new();
2255 t[1] = tcg_temp_new();
31c18d87
EI
2256}
2257
2258static inline void cris_alu_m_free_temps(TCGv *t)
2259{
2260 tcg_temp_free(t[0]);
2261 tcg_temp_free(t[1]);
2262}
2263
a699a7be 2264static int dec_movs_m(DisasContext *dc)
8170028d 2265{
31c18d87 2266 TCGv t[2];
8170028d
TS
2267 int memsize = memsize_z(dc);
2268 int insn_len;
d12d51d5 2269 LOG_DIS("movs.%c [$r%u%s, $r%u\n",
8170028d
TS
2270 memsize_char(memsize),
2271 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2272 dc->op2);
8170028d 2273
31c18d87 2274 cris_alu_m_alloc_temps(t);
8170028d 2275 /* sign extend. */
31c18d87 2276 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
b41f7df0 2277 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7 2278 cris_alu(dc, CC_OP_MOVE,
31c18d87 2279 cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2280 do_postinc(dc, memsize);
31c18d87 2281 cris_alu_m_free_temps(t);
8170028d
TS
2282 return insn_len;
2283}
2284
a699a7be 2285static int dec_addu_m(DisasContext *dc)
8170028d 2286{
31c18d87 2287 TCGv t[2];
8170028d
TS
2288 int memsize = memsize_z(dc);
2289 int insn_len;
d12d51d5 2290 LOG_DIS("addu.%c [$r%u%s, $r%u\n",
8170028d
TS
2291 memsize_char(memsize),
2292 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2293 dc->op2);
8170028d 2294
31c18d87 2295 cris_alu_m_alloc_temps(t);
8170028d 2296 /* sign extend. */
31c18d87 2297 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2298 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7 2299 cris_alu(dc, CC_OP_ADD,
31c18d87 2300 cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2301 do_postinc(dc, memsize);
31c18d87 2302 cris_alu_m_free_temps(t);
8170028d
TS
2303 return insn_len;
2304}
2305
a699a7be 2306static int dec_adds_m(DisasContext *dc)
8170028d 2307{
31c18d87 2308 TCGv t[2];
8170028d
TS
2309 int memsize = memsize_z(dc);
2310 int insn_len;
d12d51d5 2311 LOG_DIS("adds.%c [$r%u%s, $r%u\n",
8170028d
TS
2312 memsize_char(memsize),
2313 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2314 dc->op2);
8170028d 2315
31c18d87 2316 cris_alu_m_alloc_temps(t);
8170028d 2317 /* sign extend. */
31c18d87 2318 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
b41f7df0 2319 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2320 cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2321 do_postinc(dc, memsize);
31c18d87 2322 cris_alu_m_free_temps(t);
8170028d
TS
2323 return insn_len;
2324}
2325
a699a7be 2326static int dec_subu_m(DisasContext *dc)
8170028d 2327{
31c18d87 2328 TCGv t[2];
8170028d
TS
2329 int memsize = memsize_z(dc);
2330 int insn_len;
d12d51d5 2331 LOG_DIS("subu.%c [$r%u%s, $r%u\n",
8170028d
TS
2332 memsize_char(memsize),
2333 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2334 dc->op2);
8170028d 2335
31c18d87 2336 cris_alu_m_alloc_temps(t);
8170028d 2337 /* sign extend. */
31c18d87 2338 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2339 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2340 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2341 do_postinc(dc, memsize);
31c18d87 2342 cris_alu_m_free_temps(t);
8170028d
TS
2343 return insn_len;
2344}
2345
a699a7be 2346static int dec_subs_m(DisasContext *dc)
8170028d 2347{
31c18d87 2348 TCGv t[2];
8170028d
TS
2349 int memsize = memsize_z(dc);
2350 int insn_len;
d12d51d5 2351 LOG_DIS("subs.%c [$r%u%s, $r%u\n",
8170028d
TS
2352 memsize_char(memsize),
2353 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2354 dc->op2);
8170028d 2355
31c18d87 2356 cris_alu_m_alloc_temps(t);
8170028d 2357 /* sign extend. */
31c18d87 2358 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
b41f7df0 2359 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2360 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2361 do_postinc(dc, memsize);
31c18d87 2362 cris_alu_m_free_temps(t);
8170028d
TS
2363 return insn_len;
2364}
2365
a699a7be 2366static int dec_movu_m(DisasContext *dc)
8170028d 2367{
31c18d87 2368 TCGv t[2];
8170028d
TS
2369 int memsize = memsize_z(dc);
2370 int insn_len;
2371
d12d51d5 2372 LOG_DIS("movu.%c [$r%u%s, $r%u\n",
8170028d
TS
2373 memsize_char(memsize),
2374 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2375 dc->op2);
8170028d 2376
31c18d87
EI
2377 cris_alu_m_alloc_temps(t);
2378 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2379 cris_cc_mask(dc, CC_MASK_NZ);
31c18d87 2380 cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2381 do_postinc(dc, memsize);
31c18d87 2382 cris_alu_m_free_temps(t);
8170028d
TS
2383 return insn_len;
2384}
2385
a699a7be 2386static int dec_cmpu_m(DisasContext *dc)
8170028d 2387{
31c18d87 2388 TCGv t[2];
8170028d
TS
2389 int memsize = memsize_z(dc);
2390 int insn_len;
d12d51d5 2391 LOG_DIS("cmpu.%c [$r%u%s, $r%u\n",
8170028d
TS
2392 memsize_char(memsize),
2393 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2394 dc->op2);
8170028d 2395
31c18d87
EI
2396 cris_alu_m_alloc_temps(t);
2397 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2398 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2399 cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2400 do_postinc(dc, memsize);
31c18d87 2401 cris_alu_m_free_temps(t);
8170028d
TS
2402 return insn_len;
2403}
2404
a699a7be 2405static int dec_cmps_m(DisasContext *dc)
8170028d 2406{
31c18d87 2407 TCGv t[2];
8170028d
TS
2408 int memsize = memsize_z(dc);
2409 int insn_len;
d12d51d5 2410 LOG_DIS("cmps.%c [$r%u%s, $r%u\n",
8170028d
TS
2411 memsize_char(memsize),
2412 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2413 dc->op2);
8170028d 2414
31c18d87
EI
2415 cris_alu_m_alloc_temps(t);
2416 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
b41f7df0 2417 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7 2418 cris_alu(dc, CC_OP_CMP,
31c18d87 2419 cpu_R[dc->op2], cpu_R[dc->op2], t[1],
30abcfc7 2420 memsize_zz(dc));
8170028d 2421 do_postinc(dc, memsize);
31c18d87 2422 cris_alu_m_free_temps(t);
8170028d
TS
2423 return insn_len;
2424}
2425
a699a7be 2426static int dec_cmp_m(DisasContext *dc)
8170028d 2427{
31c18d87 2428 TCGv t[2];
8170028d
TS
2429 int memsize = memsize_zz(dc);
2430 int insn_len;
d12d51d5 2431 LOG_DIS("cmp.%c [$r%u%s, $r%u\n",
8170028d
TS
2432 memsize_char(memsize),
2433 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2434 dc->op2);
8170028d 2435
31c18d87
EI
2436 cris_alu_m_alloc_temps(t);
2437 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2438 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7 2439 cris_alu(dc, CC_OP_CMP,
31c18d87 2440 cpu_R[dc->op2], cpu_R[dc->op2], t[1],
30abcfc7 2441 memsize_zz(dc));
8170028d 2442 do_postinc(dc, memsize);
31c18d87 2443 cris_alu_m_free_temps(t);
8170028d
TS
2444 return insn_len;
2445}
2446
a699a7be 2447static int dec_test_m(DisasContext *dc)
8170028d 2448{
31c18d87 2449 TCGv t[2];
8170028d
TS
2450 int memsize = memsize_zz(dc);
2451 int insn_len;
ce24e07b 2452 LOG_DIS("test.%c [$r%u%s] op2=%x\n",
8170028d
TS
2453 memsize_char(memsize),
2454 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2455 dc->op2);
8170028d 2456
dceaf394
EI
2457 cris_evaluate_flags(dc);
2458
31c18d87
EI
2459 cris_alu_m_alloc_temps(t);
2460 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
8170028d 2461 cris_cc_mask(dc, CC_MASK_NZ);
dceaf394 2462 tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3);
b41f7df0 2463
30abcfc7 2464 cris_alu(dc, CC_OP_CMP,
31c18d87 2465 cpu_R[dc->op2], t[1], tcg_const_tl(0), memsize_zz(dc));
8170028d 2466 do_postinc(dc, memsize);
31c18d87 2467 cris_alu_m_free_temps(t);
8170028d
TS
2468 return insn_len;
2469}
2470
a699a7be 2471static int dec_and_m(DisasContext *dc)
8170028d 2472{
31c18d87 2473 TCGv t[2];
8170028d
TS
2474 int memsize = memsize_zz(dc);
2475 int insn_len;
ce24e07b 2476 LOG_DIS("and.%c [$r%u%s, $r%u\n",
8170028d
TS
2477 memsize_char(memsize),
2478 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2479 dc->op2);
8170028d 2480
31c18d87
EI
2481 cris_alu_m_alloc_temps(t);
2482 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2483 cris_cc_mask(dc, CC_MASK_NZ);
31c18d87 2484 cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
8170028d 2485 do_postinc(dc, memsize);
31c18d87 2486 cris_alu_m_free_temps(t);
8170028d
TS
2487 return insn_len;
2488}
2489
a699a7be 2490static int dec_add_m(DisasContext *dc)
8170028d 2491{
31c18d87 2492 TCGv t[2];
8170028d
TS
2493 int memsize = memsize_zz(dc);
2494 int insn_len;
ce24e07b 2495 LOG_DIS("add.%c [$r%u%s, $r%u\n",
8170028d
TS
2496 memsize_char(memsize),
2497 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2498 dc->op2);
8170028d 2499
31c18d87
EI
2500 cris_alu_m_alloc_temps(t);
2501 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2502 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7 2503 cris_alu(dc, CC_OP_ADD,
31c18d87 2504 cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
8170028d 2505 do_postinc(dc, memsize);
31c18d87 2506 cris_alu_m_free_temps(t);
8170028d
TS
2507 return insn_len;
2508}
2509
a699a7be 2510static int dec_addo_m(DisasContext *dc)
8170028d 2511{
31c18d87 2512 TCGv t[2];
8170028d
TS
2513 int memsize = memsize_zz(dc);
2514 int insn_len;
ce24e07b 2515 LOG_DIS("add.%c [$r%u%s, $r%u\n",
8170028d
TS
2516 memsize_char(memsize),
2517 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2518 dc->op2);
8170028d 2519
31c18d87
EI
2520 cris_alu_m_alloc_temps(t);
2521 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
b41f7df0 2522 cris_cc_mask(dc, 0);
31c18d87 2523 cris_alu(dc, CC_OP_ADD, cpu_R[R_ACR], t[0], t[1], 4);
8170028d 2524 do_postinc(dc, memsize);
31c18d87 2525 cris_alu_m_free_temps(t);
8170028d
TS
2526 return insn_len;
2527}
2528
a699a7be 2529static int dec_bound_m(DisasContext *dc)
8170028d 2530{
31c18d87 2531 TCGv l[2];
8170028d
TS
2532 int memsize = memsize_zz(dc);
2533 int insn_len;
ce24e07b 2534 LOG_DIS("bound.%c [$r%u%s, $r%u\n",
8170028d
TS
2535 memsize_char(memsize),
2536 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2537 dc->op2);
8170028d 2538
a7812ae4
PB
2539 l[0] = tcg_temp_local_new();
2540 l[1] = tcg_temp_local_new();
31c18d87 2541 insn_len = dec_prep_alu_m(dc, 0, memsize, l[0], l[1]);
b41f7df0 2542 cris_cc_mask(dc, CC_MASK_NZ);
31c18d87 2543 cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], l[0], l[1], 4);
8170028d 2544 do_postinc(dc, memsize);
31c18d87
EI
2545 tcg_temp_free(l[0]);
2546 tcg_temp_free(l[1]);
8170028d
TS
2547 return insn_len;
2548}
2549
a699a7be 2550static int dec_addc_mr(DisasContext *dc)
8170028d 2551{
31c18d87 2552 TCGv t[2];
8170028d 2553 int insn_len = 2;
d12d51d5 2554 LOG_DIS("addc [$r%u%s, $r%u\n",
8170028d 2555 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2556 dc->op2);
8170028d
TS
2557
2558 cris_evaluate_flags(dc);
a8cf66bb
EI
2559
2560 /* Set for this insn. */
2561 dc->flagx_known = 1;
2562 dc->flags_x = X_FLAG;
2563
31c18d87
EI
2564 cris_alu_m_alloc_temps(t);
2565 insn_len = dec_prep_alu_m(dc, 0, 4, t[0], t[1]);
b41f7df0 2566 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2567 cris_alu(dc, CC_OP_ADDC, cpu_R[dc->op2], t[0], t[1], 4);
8170028d 2568 do_postinc(dc, 4);
31c18d87 2569 cris_alu_m_free_temps(t);
8170028d
TS
2570 return insn_len;
2571}
2572
a699a7be 2573static int dec_sub_m(DisasContext *dc)
8170028d 2574{
31c18d87 2575 TCGv t[2];
8170028d
TS
2576 int memsize = memsize_zz(dc);
2577 int insn_len;
d12d51d5 2578 LOG_DIS("sub.%c [$r%u%s, $r%u ir=%x zz=%x\n",
8170028d
TS
2579 memsize_char(memsize),
2580 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2581 dc->op2, dc->ir, dc->zzsize);
8170028d 2582
31c18d87
EI
2583 cris_alu_m_alloc_temps(t);
2584 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2585 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2586 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], memsize);
8170028d 2587 do_postinc(dc, memsize);
31c18d87 2588 cris_alu_m_free_temps(t);
8170028d
TS
2589 return insn_len;
2590}
2591
a699a7be 2592static int dec_or_m(DisasContext *dc)
8170028d 2593{
31c18d87 2594 TCGv t[2];
8170028d
TS
2595 int memsize = memsize_zz(dc);
2596 int insn_len;
ce24e07b 2597 LOG_DIS("or.%c [$r%u%s, $r%u pc=%x\n",
8170028d
TS
2598 memsize_char(memsize),
2599 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2600 dc->op2, dc->pc);
8170028d 2601
31c18d87
EI
2602 cris_alu_m_alloc_temps(t);
2603 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2604 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7 2605 cris_alu(dc, CC_OP_OR,
31c18d87 2606 cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
8170028d 2607 do_postinc(dc, memsize);
31c18d87 2608 cris_alu_m_free_temps(t);
8170028d
TS
2609 return insn_len;
2610}
2611
a699a7be 2612static int dec_move_mp(DisasContext *dc)
8170028d 2613{
31c18d87 2614 TCGv t[2];
8170028d
TS
2615 int memsize = memsize_zz(dc);
2616 int insn_len = 2;
2617
d12d51d5 2618 LOG_DIS("move.%c [$r%u%s, $p%u\n",
8170028d
TS
2619 memsize_char(memsize),
2620 dc->op1,
2621 dc->postinc ? "+]" : "]",
d12d51d5 2622 dc->op2);
8170028d 2623
31c18d87
EI
2624 cris_alu_m_alloc_temps(t);
2625 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0
EI
2626 cris_cc_mask(dc, 0);
2627 if (dc->op2 == PR_CCS) {
2628 cris_evaluate_flags(dc);
2a44f7f1 2629 if (dc->tb_flags & U_FLAG) {
b41f7df0 2630 /* User space is not allowed to touch all flags. */
31c18d87
EI
2631 tcg_gen_andi_tl(t[1], t[1], 0x39f);
2632 tcg_gen_andi_tl(t[0], cpu_PR[PR_CCS], ~0x39f);
2633 tcg_gen_or_tl(t[1], t[0], t[1]);
b41f7df0
EI
2634 }
2635 }
2636
31c18d87 2637 t_gen_mov_preg_TN(dc, dc->op2, t[1]);
8170028d
TS
2638
2639 do_postinc(dc, memsize);
31c18d87 2640 cris_alu_m_free_temps(t);
8170028d
TS
2641 return insn_len;
2642}
2643
a699a7be 2644static int dec_move_pm(DisasContext *dc)
8170028d 2645{
31c18d87 2646 TCGv t0;
8170028d
TS
2647 int memsize;
2648
2649 memsize = preg_sizes[dc->op2];
2650
d12d51d5 2651 LOG_DIS("move.%c $p%u, [$r%u%s\n",
fd56059f 2652 memsize_char(memsize),
d12d51d5 2653 dc->op2, dc->op1, dc->postinc ? "+]" : "]");
8170028d 2654
fd56059f 2655 /* prepare store. Address in T0, value in T1. */
17ac9754
EI
2656 if (dc->op2 == PR_CCS)
2657 cris_evaluate_flags(dc);
a7812ae4 2658 t0 = tcg_temp_new();
31c18d87 2659 t_gen_mov_TN_preg(t0, dc->op2);
30abcfc7 2660 cris_flush_cc_state(dc);
31c18d87
EI
2661 gen_store(dc, cpu_R[dc->op1], t0, memsize);
2662 tcg_temp_free(t0);
17ac9754 2663
b41f7df0 2664 cris_cc_mask(dc, 0);
8170028d 2665 if (dc->postinc)
17ac9754 2666 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize);
8170028d
TS
2667 return 2;
2668}
2669
a699a7be 2670static int dec_movem_mr(DisasContext *dc)
8170028d 2671{
a7812ae4
PB
2672 TCGv_i64 tmp[16];
2673 TCGv tmp32;
31c18d87 2674 TCGv addr;
8170028d 2675 int i;
28de16da 2676 int nr = dc->op2 + 1;
8170028d 2677
d12d51d5
AL
2678 LOG_DIS("movem [$r%u%s, $r%u\n", dc->op1,
2679 dc->postinc ? "+]" : "]", dc->op2);
8170028d 2680
a7812ae4 2681 addr = tcg_temp_new();
28de16da 2682 /* There are probably better ways of doing this. */
30abcfc7 2683 cris_flush_cc_state(dc);
28de16da 2684 for (i = 0; i < (nr >> 1); i++) {
a7812ae4 2685 tmp[i] = tcg_temp_new_i64();
31c18d87 2686 tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
a7812ae4 2687 gen_load64(dc, tmp[i], addr);
28de16da
EI
2688 }
2689 if (nr & 1) {
a7812ae4 2690 tmp32 = tcg_temp_new_i32();
31c18d87 2691 tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
a7812ae4 2692 gen_load(dc, tmp32, addr, 4, 0);
cc53adbc
EI
2693 } else
2694 TCGV_UNUSED(tmp32);
31c18d87 2695 tcg_temp_free(addr);
17ac9754 2696
28de16da
EI
2697 for (i = 0; i < (nr >> 1); i++) {
2698 tcg_gen_trunc_i64_i32(cpu_R[i * 2], tmp[i]);
2699 tcg_gen_shri_i64(tmp[i], tmp[i], 32);
2700 tcg_gen_trunc_i64_i32(cpu_R[i * 2 + 1], tmp[i]);
a7812ae4 2701 tcg_temp_free_i64(tmp[i]);
28de16da
EI
2702 }
2703 if (nr & 1) {
a7812ae4
PB
2704 tcg_gen_mov_tl(cpu_R[dc->op2], tmp32);
2705 tcg_temp_free(tmp32);
17ac9754
EI
2706 }
2707
05ba7d5f
EI
2708 /* writeback the updated pointer value. */
2709 if (dc->postinc)
28de16da 2710 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], nr * 4);
b41f7df0
EI
2711
2712 /* gen_load might want to evaluate the previous insns flags. */
2713 cris_cc_mask(dc, 0);
8170028d
TS
2714 return 2;
2715}
2716
a699a7be 2717static int dec_movem_rm(DisasContext *dc)
8170028d 2718{
30abcfc7 2719 TCGv tmp;
31c18d87 2720 TCGv addr;
8170028d
TS
2721 int i;
2722
d12d51d5
AL
2723 LOG_DIS("movem $r%u, [$r%u%s\n", dc->op2, dc->op1,
2724 dc->postinc ? "+]" : "]");
8170028d 2725
30abcfc7
EI
2726 cris_flush_cc_state(dc);
2727
a7812ae4
PB
2728 tmp = tcg_temp_new();
2729 addr = tcg_temp_new();
30abcfc7 2730 tcg_gen_movi_tl(tmp, 4);
31c18d87 2731 tcg_gen_mov_tl(addr, cpu_R[dc->op1]);
8170028d 2732 for (i = 0; i <= dc->op2; i++) {
17ac9754 2733 /* Displace addr. */
8170028d 2734 /* Perform the store. */
31c18d87
EI
2735 gen_store(dc, addr, cpu_R[i], 4);
2736 tcg_gen_add_tl(addr, addr, tmp);
8170028d 2737 }
17ac9754 2738 if (dc->postinc)
31c18d87 2739 tcg_gen_mov_tl(cpu_R[dc->op1], addr);
b41f7df0 2740 cris_cc_mask(dc, 0);
30abcfc7 2741 tcg_temp_free(tmp);
31c18d87 2742 tcg_temp_free(addr);
8170028d
TS
2743 return 2;
2744}
2745
a699a7be 2746static int dec_move_rm(DisasContext *dc)
8170028d
TS
2747{
2748 int memsize;
2749
2750 memsize = memsize_zz(dc);
2751
ce24e07b
EI
2752 LOG_DIS("move.%c $r%u, [$r%u]\n",
2753 memsize_char(memsize), dc->op2, dc->op1);
8170028d 2754
8170028d 2755 /* prepare store. */
30abcfc7 2756 cris_flush_cc_state(dc);
17ac9754
EI
2757 gen_store(dc, cpu_R[dc->op1], cpu_R[dc->op2], memsize);
2758
8170028d 2759 if (dc->postinc)
17ac9754 2760 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize);
b41f7df0 2761 cris_cc_mask(dc, 0);
8170028d
TS
2762 return 2;
2763}
2764
a699a7be 2765static int dec_lapcq(DisasContext *dc)
8170028d 2766{
d12d51d5
AL
2767 LOG_DIS("lapcq %x, $r%u\n",
2768 dc->pc + dc->op1*2, dc->op2);
8170028d 2769 cris_cc_mask(dc, 0);
30abcfc7 2770 tcg_gen_movi_tl(cpu_R[dc->op2], dc->pc + dc->op1 * 2);
8170028d
TS
2771 return 2;
2772}
2773
a699a7be 2774static int dec_lapc_im(DisasContext *dc)
8170028d
TS
2775{
2776 unsigned int rd;
2777 int32_t imm;
b41f7df0 2778 int32_t pc;
8170028d
TS
2779
2780 rd = dc->op2;
2781
2782 cris_cc_mask(dc, 0);
7de141cb 2783 imm = cris_fetch(dc, dc->pc + 2, 4, 0);
d12d51d5 2784 LOG_DIS("lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2);
b41f7df0
EI
2785
2786 pc = dc->pc;
2787 pc += imm;
46e246c9 2788 tcg_gen_movi_tl(cpu_R[rd], pc);
05ba7d5f 2789 return 6;
8170028d
TS
2790}
2791
2792/* Jump to special reg. */
a699a7be 2793static int dec_jump_p(DisasContext *dc)
8170028d 2794{
d12d51d5 2795 LOG_DIS("jump $p%u\n", dc->op2);
b41f7df0 2796
17ac9754
EI
2797 if (dc->op2 == PR_CCS)
2798 cris_evaluate_flags(dc);
31c18d87 2799 t_gen_mov_TN_preg(env_btarget, dc->op2);
b41f7df0 2800 /* rete will often have low bit set to indicate delayslot. */
31c18d87 2801 tcg_gen_andi_tl(env_btarget, env_btarget, ~1);
17ac9754 2802 cris_cc_mask(dc, 0);
2a44f7f1 2803 cris_prepare_jmp(dc, JMP_INDIRECT);
8170028d
TS
2804 return 2;
2805}
2806
2807/* Jump and save. */
a699a7be 2808static int dec_jas_r(DisasContext *dc)
8170028d 2809{
d12d51d5 2810 LOG_DIS("jas $r%u, $p%u\n", dc->op1, dc->op2);
8170028d 2811 cris_cc_mask(dc, 0);
b41f7df0
EI
2812 /* Store the return address in Pd. */
2813 tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
2814 if (dc->op2 > 15)
2815 abort();
30abcfc7 2816 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4));
b41f7df0 2817
2a44f7f1 2818 cris_prepare_jmp(dc, JMP_INDIRECT);
8170028d
TS
2819 return 2;
2820}
2821
a699a7be 2822static int dec_jas_im(DisasContext *dc)
8170028d
TS
2823{
2824 uint32_t imm;
2825
7de141cb 2826 imm = cris_fetch(dc, dc->pc + 2, 4, 0);
8170028d 2827
d12d51d5 2828 LOG_DIS("jas 0x%x\n", imm);
8170028d 2829 cris_cc_mask(dc, 0);
17ac9754 2830 /* Store the return address in Pd. */
cf1d97f0 2831 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
2a44f7f1
EI
2832
2833 dc->jmp_pc = imm;
2834 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2835 return 6;
2836}
2837
a699a7be 2838static int dec_jasc_im(DisasContext *dc)
8170028d
TS
2839{
2840 uint32_t imm;
2841
7de141cb 2842 imm = cris_fetch(dc, dc->pc + 2, 4, 0);
8170028d 2843
d12d51d5 2844 LOG_DIS("jasc 0x%x\n", imm);
8170028d 2845 cris_cc_mask(dc, 0);
17ac9754 2846 /* Store the return address in Pd. */
2a44f7f1
EI
2847 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8 + 4));
2848
2849 dc->jmp_pc = imm;
2850 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2851 return 6;
2852}
2853
a699a7be 2854static int dec_jasc_r(DisasContext *dc)
8170028d 2855{
d12d51d5 2856 LOG_DIS("jasc_r $r%u, $p%u\n", dc->op1, dc->op2);
8170028d 2857 cris_cc_mask(dc, 0);
17ac9754 2858 /* Store the return address in Pd. */
2a44f7f1
EI
2859 tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
2860 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4 + 4));
2861 cris_prepare_jmp(dc, JMP_INDIRECT);
8170028d
TS
2862 return 2;
2863}
2864
a699a7be 2865static int dec_bcc_im(DisasContext *dc)
8170028d
TS
2866{
2867 int32_t offset;
2868 uint32_t cond = dc->op2;
2869
7de141cb 2870 offset = cris_fetch(dc, dc->pc + 2, 2, 1);
8170028d 2871
d12d51d5 2872 LOG_DIS("b%s %d pc=%x dst=%x\n",
8170028d 2873 cc_name(cond), offset,
d12d51d5 2874 dc->pc, dc->pc + offset);
8170028d
TS
2875
2876 cris_cc_mask(dc, 0);
2877 /* op2 holds the condition-code. */
2878 cris_prepare_cc_branch (dc, offset, cond);
2879 return 4;
2880}
2881
a699a7be 2882static int dec_bas_im(DisasContext *dc)
8170028d
TS
2883{
2884 int32_t simm;
2885
2886
7de141cb 2887 simm = cris_fetch(dc, dc->pc + 2, 4, 0);
8170028d 2888
d12d51d5 2889 LOG_DIS("bas 0x%x, $p%u\n", dc->pc + simm, dc->op2);
8170028d 2890 cris_cc_mask(dc, 0);
2a44f7f1
EI
2891 /* Store the return address in Pd. */
2892 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
2893
2894 dc->jmp_pc = dc->pc + simm;
2895 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2896 return 6;
2897}
2898
a699a7be 2899static int dec_basc_im(DisasContext *dc)
8170028d
TS
2900{
2901 int32_t simm;
7de141cb 2902 simm = cris_fetch(dc, dc->pc + 2, 4, 0);
8170028d 2903
d12d51d5 2904 LOG_DIS("basc 0x%x, $p%u\n", dc->pc + simm, dc->op2);
8170028d 2905 cris_cc_mask(dc, 0);
2a44f7f1
EI
2906 /* Store the return address in Pd. */
2907 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 12));
2908
2909 dc->jmp_pc = dc->pc + simm;
2910 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2911 return 6;
2912}
2913
a699a7be 2914static int dec_rfe_etc(DisasContext *dc)
8170028d 2915{
8170028d
TS
2916 cris_cc_mask(dc, 0);
2917
213fb478
EI
2918 if (dc->op2 == 15) {
2919 t_gen_mov_env_TN(halted, tcg_const_tl(1));
2920 tcg_gen_movi_tl(env_pc, dc->pc + 2);
2921 t_gen_raise_exception(EXCP_HLT);
05ba7d5f 2922 return 2;
213fb478 2923 }
8170028d
TS
2924
2925 switch (dc->op2 & 7) {
2926 case 2:
2927 /* rfe. */
d12d51d5 2928 LOG_DIS("rfe\n");
8170028d 2929 cris_evaluate_flags(dc);
a7812ae4 2930 gen_helper_rfe();
b41f7df0 2931 dc->is_jmp = DISAS_UPDATE;
8170028d
TS
2932 break;
2933 case 5:
2934 /* rfn. */
d12d51d5 2935 LOG_DIS("rfn\n");
a7cfbba0 2936 cris_evaluate_flags(dc);
a7812ae4 2937 gen_helper_rfn();
a7cfbba0 2938 dc->is_jmp = DISAS_UPDATE;
8170028d
TS
2939 break;
2940 case 6:
d12d51d5 2941 LOG_DIS("break %d\n", dc->op1);
a1aebcb8 2942 cris_evaluate_flags (dc);
8170028d 2943 /* break. */
cddffe37 2944 tcg_gen_movi_tl(env_pc, dc->pc + 2);
a1aebcb8 2945
8170028d 2946 /* Breaks start at 16 in the exception vector. */
dceaf394
EI
2947 t_gen_mov_env_TN(trap_vector,
2948 tcg_const_tl(dc->op1 + 16));
2949 t_gen_raise_exception(EXCP_BREAK);
b41f7df0 2950 dc->is_jmp = DISAS_UPDATE;
8170028d
TS
2951 break;
2952 default:
2953 printf ("op2=%x\n", dc->op2);
2954 BUG();
2955 break;
2956
2957 }
8170028d
TS
2958 return 2;
2959}
2960
a699a7be 2961static int dec_ftag_fidx_d_m(DisasContext *dc)
5d4a534d 2962{
5d4a534d
EI
2963 return 2;
2964}
2965
a699a7be 2966static int dec_ftag_fidx_i_m(DisasContext *dc)
5d4a534d 2967{
5d4a534d
EI
2968 return 2;
2969}
2970
a699a7be 2971static int dec_null(DisasContext *dc)
8170028d
TS
2972{
2973 printf ("unknown insn pc=%x opc=%x op1=%x op2=%x\n",
2974 dc->pc, dc->opcode, dc->op1, dc->op2);
2975 fflush(NULL);
2976 BUG();
2977 return 2;
2978}
2979
9b32fbf8 2980static struct decoder_info {
8170028d
TS
2981 struct {
2982 uint32_t bits;
2983 uint32_t mask;
2984 };
a699a7be 2985 int (*dec)(DisasContext *dc);
8170028d
TS
2986} decinfo[] = {
2987 /* Order matters here. */
2988 {DEC_MOVEQ, dec_moveq},
2989 {DEC_BTSTQ, dec_btstq},
2990 {DEC_CMPQ, dec_cmpq},
2991 {DEC_ADDOQ, dec_addoq},
2992 {DEC_ADDQ, dec_addq},
2993 {DEC_SUBQ, dec_subq},
2994 {DEC_ANDQ, dec_andq},
2995 {DEC_ORQ, dec_orq},
2996 {DEC_ASRQ, dec_asrq},
2997 {DEC_LSLQ, dec_lslq},
2998 {DEC_LSRQ, dec_lsrq},
2999 {DEC_BCCQ, dec_bccq},
3000
3001 {DEC_BCC_IM, dec_bcc_im},
3002 {DEC_JAS_IM, dec_jas_im},
3003 {DEC_JAS_R, dec_jas_r},
3004 {DEC_JASC_IM, dec_jasc_im},
3005 {DEC_JASC_R, dec_jasc_r},
3006 {DEC_BAS_IM, dec_bas_im},
3007 {DEC_BASC_IM, dec_basc_im},
3008 {DEC_JUMP_P, dec_jump_p},
3009 {DEC_LAPC_IM, dec_lapc_im},
3010 {DEC_LAPCQ, dec_lapcq},
3011
3012 {DEC_RFE_ETC, dec_rfe_etc},
3013 {DEC_ADDC_MR, dec_addc_mr},
3014
3015 {DEC_MOVE_MP, dec_move_mp},
3016 {DEC_MOVE_PM, dec_move_pm},
3017 {DEC_MOVEM_MR, dec_movem_mr},
3018 {DEC_MOVEM_RM, dec_movem_rm},
3019 {DEC_MOVE_PR, dec_move_pr},
3020 {DEC_SCC_R, dec_scc_r},
3021 {DEC_SETF, dec_setclrf},
3022 {DEC_CLEARF, dec_setclrf},
3023
3024 {DEC_MOVE_SR, dec_move_sr},
3025 {DEC_MOVE_RP, dec_move_rp},
3026 {DEC_SWAP_R, dec_swap_r},
3027 {DEC_ABS_R, dec_abs_r},
3028 {DEC_LZ_R, dec_lz_r},
3029 {DEC_MOVE_RS, dec_move_rs},
3030 {DEC_BTST_R, dec_btst_r},
3031 {DEC_ADDC_R, dec_addc_r},
3032
3033 {DEC_DSTEP_R, dec_dstep_r},
3034 {DEC_XOR_R, dec_xor_r},
3035 {DEC_MCP_R, dec_mcp_r},
3036 {DEC_CMP_R, dec_cmp_r},
3037
3038 {DEC_ADDI_R, dec_addi_r},
3039 {DEC_ADDI_ACR, dec_addi_acr},
3040
3041 {DEC_ADD_R, dec_add_r},
3042 {DEC_SUB_R, dec_sub_r},
3043
3044 {DEC_ADDU_R, dec_addu_r},
3045 {DEC_ADDS_R, dec_adds_r},
3046 {DEC_SUBU_R, dec_subu_r},
3047 {DEC_SUBS_R, dec_subs_r},
3048 {DEC_LSL_R, dec_lsl_r},
3049
3050 {DEC_AND_R, dec_and_r},
3051 {DEC_OR_R, dec_or_r},
3052 {DEC_BOUND_R, dec_bound_r},
3053 {DEC_ASR_R, dec_asr_r},
3054 {DEC_LSR_R, dec_lsr_r},
3055
3056 {DEC_MOVU_R, dec_movu_r},
3057 {DEC_MOVS_R, dec_movs_r},
3058 {DEC_NEG_R, dec_neg_r},
3059 {DEC_MOVE_R, dec_move_r},
3060
5d4a534d
EI
3061 {DEC_FTAG_FIDX_I_M, dec_ftag_fidx_i_m},
3062 {DEC_FTAG_FIDX_D_M, dec_ftag_fidx_d_m},
8170028d
TS
3063
3064 {DEC_MULS_R, dec_muls_r},
3065 {DEC_MULU_R, dec_mulu_r},
3066
3067 {DEC_ADDU_M, dec_addu_m},
3068 {DEC_ADDS_M, dec_adds_m},
3069 {DEC_SUBU_M, dec_subu_m},
3070 {DEC_SUBS_M, dec_subs_m},
3071
3072 {DEC_CMPU_M, dec_cmpu_m},
3073 {DEC_CMPS_M, dec_cmps_m},
3074 {DEC_MOVU_M, dec_movu_m},
3075 {DEC_MOVS_M, dec_movs_m},
3076
3077 {DEC_CMP_M, dec_cmp_m},
3078 {DEC_ADDO_M, dec_addo_m},
3079 {DEC_BOUND_M, dec_bound_m},
3080 {DEC_ADD_M, dec_add_m},
3081 {DEC_SUB_M, dec_sub_m},
3082 {DEC_AND_M, dec_and_m},
3083 {DEC_OR_M, dec_or_m},
3084 {DEC_MOVE_RM, dec_move_rm},
3085 {DEC_TEST_M, dec_test_m},
3086 {DEC_MOVE_MR, dec_move_mr},
3087
3088 {{0, 0}, dec_null}
3089};
3090
40e9eddd 3091static unsigned int crisv32_decoder(DisasContext *dc)
8170028d 3092{
a699a7be 3093 int insn_len = 2;
8170028d
TS
3094 int i;
3095
8fec2b8c 3096 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
28de16da
EI
3097 tcg_gen_debug_insn_start(dc->pc);
3098
8170028d 3099 /* Load a halfword onto the instruction register. */
7de141cb 3100 dc->ir = cris_fetch(dc, dc->pc, 2, 0);
8170028d
TS
3101
3102 /* Now decode it. */
3103 dc->opcode = EXTRACT_FIELD(dc->ir, 4, 11);
3104 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 3);
3105 dc->op2 = EXTRACT_FIELD(dc->ir, 12, 15);
3106 dc->zsize = EXTRACT_FIELD(dc->ir, 4, 4);
3107 dc->zzsize = EXTRACT_FIELD(dc->ir, 4, 5);
3108 dc->postinc = EXTRACT_FIELD(dc->ir, 10, 10);
3109
3110 /* Large switch for all insns. */
b1503cda 3111 for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
8170028d
TS
3112 if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits)
3113 {
3114 insn_len = decinfo[i].dec(dc);
3115 break;
3116 }
3117 }
3118
dd20fcd0 3119#if !defined(CONFIG_USER_ONLY)
a1aebcb8
EI
3120 /* Single-stepping ? */
3121 if (dc->tb_flags & S_FLAG) {
3122 int l1;
3123
3124 l1 = gen_new_label();
dd20fcd0 3125 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_PR[PR_SPC], dc->pc, l1);
a1aebcb8
EI
3126 /* We treat SPC as a break with an odd trap vector. */
3127 cris_evaluate_flags (dc);
3128 t_gen_mov_env_TN(trap_vector, tcg_const_tl(3));
3129 tcg_gen_movi_tl(env_pc, dc->pc + insn_len);
cddffe37 3130 tcg_gen_movi_tl(cpu_PR[PR_SPC], dc->pc + insn_len);
a1aebcb8
EI
3131 t_gen_raise_exception(EXCP_BREAK);
3132 gen_set_label(l1);
3133 }
3134#endif
8170028d
TS
3135 return insn_len;
3136}
3137
3138static void check_breakpoint(CPUState *env, DisasContext *dc)
3139{
a1d1bb31
AL
3140 CPUBreakpoint *bp;
3141
72cf2d4f
BS
3142 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
3143 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 3144 if (bp->pc == dc->pc) {
8170028d 3145 cris_evaluate_flags (dc);
2a44f7f1 3146 tcg_gen_movi_tl(env_pc, dc->pc);
dceaf394 3147 t_gen_raise_exception(EXCP_DEBUG);
8170028d
TS
3148 dc->is_jmp = DISAS_UPDATE;
3149 }
3150 }
3151 }
3152}
3153
40e9eddd 3154#include "translate_v10.c"
cf1d97f0
EI
3155
3156/*
3157 * Delay slots on QEMU/CRIS.
3158 *
3159 * If an exception hits on a delayslot, the core will let ERP (the Exception
3160 * Return Pointer) point to the branch (the previous) insn and set the lsb to
3161 * to give SW a hint that the exception actually hit on the dslot.
3162 *
3163 * CRIS expects all PC addresses to be 16-bit aligned. The lsb is ignored by
3164 * the core and any jmp to an odd addresses will mask off that lsb. It is
3165 * simply there to let sw know there was an exception on a dslot.
3166 *
3167 * When the software returns from an exception, the branch will re-execute.
3168 * On QEMU care needs to be taken when a branch+delayslot sequence is broken
3169 * and the branch and delayslot dont share pages.
3170 *
3171 * The TB contaning the branch insn will set up env->btarget and evaluate
3172 * env->btaken. When the translation loop exits we will note that the branch
3173 * sequence is broken and let env->dslot be the size of the branch insn (those
3174 * vary in length).
3175 *
3176 * The TB contaning the delayslot will have the PC of its real insn (i.e no lsb
3177 * set). It will also expect to have env->dslot setup with the size of the
3178 * delay slot so that env->pc - env->dslot point to the branch insn. This TB
3179 * will execute the dslot and take the branch, either to btarget or just one
3180 * insn ahead.
3181 *
3182 * When exceptions occur, we check for env->dslot in do_interrupt to detect
3183 * broken branch sequences and setup $erp accordingly (i.e let it point to the
3184 * branch and set lsb). Then env->dslot gets cleared so that the exception
3185 * handler can enter. When returning from exceptions (jump $erp) the lsb gets
3186 * masked off and we will reexecute the branch insn.
3187 *
3188 */
3189
8170028d 3190/* generate intermediate code for basic block 'tb'. */
2cfc5f17 3191static void
8170028d
TS
3192gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
3193 int search_pc)
3194{
3195 uint16_t *gen_opc_end;
3196 uint32_t pc_start;
40e9eddd 3197 unsigned int insn_len, orig_flags;
8170028d 3198 int j, lj;
cf1d97f0 3199 struct DisasContext ctx;
8170028d
TS
3200 struct DisasContext *dc = &ctx;
3201 uint32_t next_page_start;
2a44f7f1 3202 target_ulong npc;
2e70f6ef
PB
3203 int num_insns;
3204 int max_insns;
8170028d 3205
93fcfe39 3206 qemu_log_try_set_file(stderr);
a825e703 3207
40e9eddd
EI
3208 if (env->pregs[PR_VR] == 32)
3209 dc->decoder = crisv32_decoder;
3210 else
3211 dc->decoder = crisv10_decoder;
3212
73e51723
EI
3213 /* Odd PC indicates that branch is rexecuting due to exception in the
3214 * delayslot, like in real hw.
73e51723
EI
3215 */
3216 pc_start = tb->pc & ~1;
8170028d
TS
3217 dc->env = env;
3218 dc->tb = tb;
3219
8170028d 3220 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8170028d
TS
3221
3222 dc->is_jmp = DISAS_NEXT;
b41f7df0 3223 dc->ppc = pc_start;
8170028d
TS
3224 dc->pc = pc_start;
3225 dc->singlestep_enabled = env->singlestep_enabled;
30abcfc7
EI
3226 dc->flags_uptodate = 1;
3227 dc->flagx_known = 1;
3228 dc->flags_x = tb->flags & X_FLAG;
3229 dc->cc_x_uptodate = 0;
b41f7df0 3230 dc->cc_mask = 0;
cf1d97f0 3231 dc->update_cc = 0;
40e9eddd
EI
3232 dc->clear_prefix = 0;
3233 dc->clear_locked_irq = 1;
30abcfc7 3234
b41f7df0 3235 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
30abcfc7 3236 dc->cc_size_uptodate = -1;
b41f7df0 3237
cf1d97f0 3238 /* Decode TB flags. */
40e9eddd
EI
3239 orig_flags = dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG \
3240 | X_FLAG | PFIX_FLAG);
cf1d97f0 3241 dc->delayed_branch = !!(tb->flags & 7);
2a44f7f1
EI
3242 if (dc->delayed_branch)
3243 dc->jmp = JMP_INDIRECT;
3244 else
3245 dc->jmp = JMP_NOJMP;
3246
3247 dc->cpustate_changed = 0;
b41f7df0 3248
8fec2b8c 3249 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39 3250 qemu_log(
0bfcd599 3251 "srch=%d pc=%x %x flg=%" PRIx64 " bt=%x ds=%u ccs=%x\n"
30abcfc7 3252 "pid=%x usp=%x\n"
b41f7df0
EI
3253 "%x.%x.%x.%x\n"
3254 "%x.%x.%x.%x\n"
3255 "%x.%x.%x.%x\n"
3256 "%x.%x.%x.%x\n",
d297f464 3257 search_pc, dc->pc, dc->ppc,
0bfcd599 3258 (uint64_t)tb->flags,
d297f464 3259 env->btarget, (unsigned)tb->flags & 7,
cf1d97f0 3260 env->pregs[PR_CCS],
b41f7df0
EI
3261 env->pregs[PR_PID], env->pregs[PR_USP],
3262 env->regs[0], env->regs[1], env->regs[2], env->regs[3],
3263 env->regs[4], env->regs[5], env->regs[6], env->regs[7],
3264 env->regs[8], env->regs[9],
3265 env->regs[10], env->regs[11],
3266 env->regs[12], env->regs[13],
3267 env->regs[14], env->regs[15]);
93fcfe39
AL
3268 qemu_log("--------------\n");
3269 qemu_log("IN: %s\n", lookup_symbol(pc_start));
b41f7df0 3270 }
3157a0a9 3271
8170028d
TS
3272 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
3273 lj = -1;
2e70f6ef
PB
3274 num_insns = 0;
3275 max_insns = tb->cflags & CF_COUNT_MASK;
3276 if (max_insns == 0)
3277 max_insns = CF_COUNT_MASK;
3278
3279 gen_icount_start();
8170028d
TS
3280 do
3281 {
3282 check_breakpoint(env, dc);
8170028d
TS
3283
3284 if (search_pc) {
3285 j = gen_opc_ptr - gen_opc_buf;
3286 if (lj < j) {
3287 lj++;
3288 while (lj < j)
3289 gen_opc_instr_start[lj++] = 0;
3290 }
cf1d97f0 3291 if (dc->delayed_branch == 1)
b41f7df0 3292 gen_opc_pc[lj] = dc->ppc | 1;
cf1d97f0 3293 else
b41f7df0 3294 gen_opc_pc[lj] = dc->pc;
cf1d97f0 3295 gen_opc_instr_start[lj] = 1;
2e70f6ef 3296 gen_opc_icount[lj] = num_insns;
cf1d97f0
EI
3297 }
3298
3299 /* Pretty disas. */
d12d51d5 3300 LOG_DIS("%8.8x:\t", dc->pc);
8170028d 3301
2e70f6ef
PB
3302 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
3303 gen_io_start();
b41f7df0 3304 dc->clear_x = 1;
28de16da 3305
40e9eddd 3306 insn_len = dc->decoder(dc);
b41f7df0 3307 dc->ppc = dc->pc;
8170028d 3308 dc->pc += insn_len;
b41f7df0
EI
3309 if (dc->clear_x)
3310 cris_clear_x_flag(dc);
8170028d 3311
2e70f6ef 3312 num_insns++;
8170028d 3313 /* Check for delayed branches here. If we do it before
bf20dc07 3314 actually generating any host code, the simulator will just
8170028d
TS
3315 loop doing nothing for on this program location. */
3316 if (dc->delayed_branch) {
3317 dc->delayed_branch--;
3318 if (dc->delayed_branch == 0)
3319 {
2a44f7f1
EI
3320 if (tb->flags & 7)
3321 t_gen_mov_env_TN(dslot,
3322 tcg_const_tl(0));
3323 if (dc->jmp == JMP_DIRECT) {
3324 dc->is_jmp = DISAS_NEXT;
3325 } else {
3326 t_gen_cc_jmp(env_btarget,
3327 tcg_const_tl(dc->pc));
3328 dc->is_jmp = DISAS_JUMP;
3329 }
3330 break;
8170028d
TS
3331 }
3332 }
3333
73e51723
EI
3334 /* If we are rexecuting a branch due to exceptions on
3335 delay slots dont break. */
3336 if (!(tb->pc & 1) && env->singlestep_enabled)
8170028d 3337 break;
fb48f71b
EI
3338 } while (!dc->is_jmp && !dc->cpustate_changed
3339 && gen_opc_ptr < gen_opc_end
1b530a6d 3340 && !singlestep
2e70f6ef
PB
3341 && (dc->pc < next_page_start)
3342 && num_insns < max_insns);
b41f7df0 3343
40e9eddd
EI
3344 if (dc->tb_flags != orig_flags) {
3345 dc->cpustate_changed = 1;
3346 }
3347
3348 if (dc->clear_locked_irq)
3349 t_gen_mov_env_TN(locked_irq, tcg_const_tl(0));
3350
2a44f7f1
EI
3351 npc = dc->pc;
3352 if (dc->jmp == JMP_DIRECT && !dc->delayed_branch)
3353 npc = dc->jmp_pc;
3354
2e70f6ef
PB
3355 if (tb->cflags & CF_LAST_IO)
3356 gen_io_end();
2a44f7f1
EI
3357 /* Force an update if the per-tb cpu state has changed. */
3358 if (dc->is_jmp == DISAS_NEXT
3359 && (dc->cpustate_changed || !dc->flagx_known
3360 || (dc->flags_x != (tb->flags & X_FLAG)))) {
3361 dc->is_jmp = DISAS_UPDATE;
3362 tcg_gen_movi_tl(env_pc, npc);
3363 }
cf1d97f0 3364 /* Broken branch+delayslot sequence. */
b41f7df0 3365 if (dc->delayed_branch == 1) {
cf1d97f0
EI
3366 /* Set env->dslot to the size of the branch insn. */
3367 t_gen_mov_env_TN(dslot, tcg_const_tl(dc->pc - dc->ppc));
2a44f7f1 3368 cris_store_direct_jmp(dc);
8170028d
TS
3369 }
3370
3371 cris_evaluate_flags (dc);
2a44f7f1 3372
551bd27f 3373 if (unlikely(env->singlestep_enabled)) {
89cc7382
EI
3374 if (dc->is_jmp == DISAS_NEXT)
3375 tcg_gen_movi_tl(env_pc, npc);
dceaf394 3376 t_gen_raise_exception(EXCP_DEBUG);
8170028d
TS
3377 } else {
3378 switch(dc->is_jmp) {
3379 case DISAS_NEXT:
2a44f7f1 3380 gen_goto_tb(dc, 1, npc);
8170028d
TS
3381 break;
3382 default:
3383 case DISAS_JUMP:
3384 case DISAS_UPDATE:
3385 /* indicate that the hash table must be used
3386 to find the next TB */
57fec1fe 3387 tcg_gen_exit_tb(0);
8170028d 3388 break;
4f400ab5 3389 case DISAS_SWI:
8170028d
TS
3390 case DISAS_TB_JUMP:
3391 /* nothing more to generate */
3392 break;
3393 }
3394 }
2e70f6ef 3395 gen_icount_end(tb, num_insns);
8170028d
TS
3396 *gen_opc_ptr = INDEX_op_end;
3397 if (search_pc) {
3398 j = gen_opc_ptr - gen_opc_buf;
3399 lj++;
3400 while (lj <= j)
3401 gen_opc_instr_start[lj++] = 0;
3402 } else {
3403 tb->size = dc->pc - pc_start;
2e70f6ef 3404 tb->icount = num_insns;
8170028d
TS
3405 }
3406
3407#ifdef DEBUG_DISAS
a1aebcb8 3408#if !DISAS_CRIS
8fec2b8c 3409 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
40e9eddd
EI
3410 log_target_disas(pc_start, dc->pc - pc_start,
3411 dc->env->pregs[PR_VR]);
93fcfe39 3412 qemu_log("\nisize=%d osize=%zd\n",
b41f7df0 3413 dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
8170028d
TS
3414 }
3415#endif
a1aebcb8 3416#endif
8170028d
TS
3417}
3418
2cfc5f17 3419void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8170028d 3420{
2cfc5f17 3421 gen_intermediate_code_internal(env, tb, 0);
8170028d
TS
3422}
3423
2cfc5f17 3424void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8170028d 3425{
2cfc5f17 3426 gen_intermediate_code_internal(env, tb, 1);
8170028d
TS
3427}
3428
3429void cpu_dump_state (CPUState *env, FILE *f,
3430 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
3431 int flags)
3432{
3433 int i;
3434 uint32_t srs;
3435
3436 if (!env || !f)
3437 return;
3438
3439 cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
30abcfc7 3440 "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n",
9004627f 3441 env->pc, env->pregs[PR_CCS], env->btaken, env->btarget,
8170028d 3442 env->cc_op,
30abcfc7
EI
3443 env->cc_src, env->cc_dest, env->cc_result, env->cc_mask);
3444
8170028d
TS
3445
3446 for (i = 0; i < 16; i++) {
416c6060 3447 cpu_fprintf(f, "%s=%8.8x ",regnames[i], env->regs[i]);
8170028d
TS
3448 if ((i + 1) % 4 == 0)
3449 cpu_fprintf(f, "\n");
3450 }
3451 cpu_fprintf(f, "\nspecial regs:\n");
3452 for (i = 0; i < 16; i++) {
416c6060 3453 cpu_fprintf(f, "%s=%8.8x ", pregnames[i], env->pregs[i]);
8170028d
TS
3454 if ((i + 1) % 4 == 0)
3455 cpu_fprintf(f, "\n");
3456 }
9004627f 3457 srs = env->pregs[PR_SRS];
b41f7df0 3458 cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
8170028d
TS
3459 if (srs < 256) {
3460 for (i = 0; i < 16; i++) {
3461 cpu_fprintf(f, "s%2.2d=%8.8x ",
3462 i, env->sregs[srs][i]);
3463 if ((i + 1) % 4 == 0)
3464 cpu_fprintf(f, "\n");
3465 }
3466 }
3467 cpu_fprintf(f, "\n\n");
3468
3469}
3470
40e9eddd
EI
3471struct
3472{
3473 uint32_t vr;
3474 const char *name;
3475} cris_cores[] = {
3476 {8, "crisv8"},
3477 {9, "crisv9"},
3478 {10, "crisv10"},
3479 {11, "crisv11"},
3480 {32, "crisv32"},
3481};
3482
3483void cris_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
3484{
3485 unsigned int i;
3486
3487 (*cpu_fprintf)(f, "Available CPUs:\n");
3488 for (i = 0; i < ARRAY_SIZE(cris_cores); i++) {
3489 (*cpu_fprintf)(f, " %s\n", cris_cores[i].name);
3490 }
3491}
3492
3493static uint32_t vr_by_name(const char *name)
3494{
3495 unsigned int i;
3496 for (i = 0; i < ARRAY_SIZE(cris_cores); i++) {
3497 if (strcmp(name, cris_cores[i].name) == 0) {
3498 return cris_cores[i].vr;
3499 }
3500 }
3501 return 32;
3502}
3503
aaed909a 3504CPUCRISState *cpu_cris_init (const char *cpu_model)
8170028d
TS
3505{
3506 CPUCRISState *env;
a7cfbba0 3507 static int tcg_initialized = 0;
a825e703 3508 int i;
8170028d
TS
3509
3510 env = qemu_mallocz(sizeof(CPUCRISState));
a7cfbba0 3511
40e9eddd 3512 env->pregs[PR_VR] = vr_by_name(cpu_model);
8170028d 3513 cpu_exec_init(env);
a7cfbba0 3514 cpu_reset(env);
0bf46a40 3515 qemu_init_vcpu(env);
a7cfbba0
EI
3516
3517 if (tcg_initialized)
3518 return env;
3519
3520 tcg_initialized = 1;
05ba7d5f 3521
40e9eddd
EI
3522#define GEN_HELPER 2
3523#include "helper.h"
3524
3525 if (env->pregs[PR_VR] < 32) {
3526 cpu_crisv10_init(env);
3527 return env;
3528 }
3529
3530
a7812ae4
PB
3531 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
3532 cc_x = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3533 offsetof(CPUState, cc_x), "cc_x");
a7812ae4 3534 cc_src = tcg_global_mem_new(TCG_AREG0,
a825e703 3535 offsetof(CPUState, cc_src), "cc_src");
a7812ae4 3536 cc_dest = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3537 offsetof(CPUState, cc_dest),
a825e703 3538 "cc_dest");
a7812ae4 3539 cc_result = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3540 offsetof(CPUState, cc_result),
a825e703 3541 "cc_result");
a7812ae4 3542 cc_op = tcg_global_mem_new(TCG_AREG0,
a825e703 3543 offsetof(CPUState, cc_op), "cc_op");
a7812ae4 3544 cc_size = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3545 offsetof(CPUState, cc_size),
a825e703 3546 "cc_size");
a7812ae4 3547 cc_mask = tcg_global_mem_new(TCG_AREG0,
a825e703
EI
3548 offsetof(CPUState, cc_mask),
3549 "cc_mask");
3550
a7812ae4 3551 env_pc = tcg_global_mem_new(TCG_AREG0,
30abcfc7
EI
3552 offsetof(CPUState, pc),
3553 "pc");
a7812ae4 3554 env_btarget = tcg_global_mem_new(TCG_AREG0,
30abcfc7
EI
3555 offsetof(CPUState, btarget),
3556 "btarget");
a7812ae4 3557 env_btaken = tcg_global_mem_new(TCG_AREG0,
2a44f7f1
EI
3558 offsetof(CPUState, btaken),
3559 "btaken");
a825e703 3560 for (i = 0; i < 16; i++) {
a7812ae4 3561 cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3562 offsetof(CPUState, regs[i]),
a825e703
EI
3563 regnames[i]);
3564 }
3565 for (i = 0; i < 16; i++) {
a7812ae4 3566 cpu_PR[i] = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3567 offsetof(CPUState, pregs[i]),
a825e703
EI
3568 pregnames[i]);
3569 }
3570
8170028d
TS
3571 return env;
3572}
3573
3574void cpu_reset (CPUCRISState *env)
3575{
40e9eddd
EI
3576 uint32_t vr;
3577
eca1bdf4
AL
3578 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
3579 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
3580 log_cpu_state(env, 0);
3581 }
3582
40e9eddd 3583 vr = env->pregs[PR_VR];
8170028d 3584 memset(env, 0, offsetof(CPUCRISState, breakpoints));
40e9eddd 3585 env->pregs[PR_VR] = vr;
8170028d 3586 tlb_flush(env, 1);
b41f7df0
EI
3587
3588#if defined(CONFIG_USER_ONLY)
3589 /* start in user mode with interrupts enabled. */
40e9eddd 3590 env->pregs[PR_CCS] |= U_FLAG | I_FLAG | P_FLAG;
b41f7df0 3591#else
52819664 3592 cris_mmu_init(env);
b41f7df0
EI
3593 env->pregs[PR_CCS] = 0;
3594#endif
8170028d 3595}
d2856f1a
AJ
3596
3597void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
3598 unsigned long searched_pc, int pc_pos, void *puc)
3599{
17ac9754 3600 env->pc = gen_opc_pc[pc_pos];
d2856f1a 3601}