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