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