]> git.proxmox.com Git - qemu.git/blame - target-cris/translate.c
Remove cpu_get_phys_page_debug from userspace emulation
[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
TS
1294{
1295 unsigned int rs, rd;
1296 uint32_t imm;
1297 int is_imm;
1298 int insn_len = 2;
1299
1300 rs = dc->op1;
1301 rd = dc->op2;
1302 is_imm = rs == 15 && dc->postinc;
1303
1304 /* Load [$rs] onto T1. */
1305 if (is_imm) {
1306 insn_len = 2 + memsize;
1307 if (memsize == 1)
1308 insn_len++;
1309
8170028d
TS
1310 if (memsize != 4) {
1311 if (s_ext) {
17ac9754
EI
1312 if (memsize == 1)
1313 imm = ldsb_code(dc->pc + 2);
1314 else
1315 imm = ldsw_code(dc->pc + 2);
8170028d
TS
1316 } else {
1317 if (memsize == 1)
17ac9754 1318 imm = ldub_code(dc->pc + 2);
8170028d 1319 else
17ac9754 1320 imm = lduw_code(dc->pc + 2);
8170028d 1321 }
17ac9754
EI
1322 } else
1323 imm = ldl_code(dc->pc + 2);
1324
30abcfc7 1325 tcg_gen_movi_tl(dst, imm);
8170028d
TS
1326 dc->postinc = 0;
1327 } else {
30abcfc7
EI
1328 cris_flush_cc_state(dc);
1329 gen_load(dc, dst, cpu_R[rs], memsize, 0);
8170028d 1330 if (s_ext)
30abcfc7 1331 t_gen_sext(dst, dst, memsize);
8170028d 1332 else
30abcfc7 1333 t_gen_zext(dst, dst, memsize);
8170028d 1334 }
cf1d97f0
EI
1335 return insn_len;
1336}
1337
1338/* Prepare T0 and T1 for a memory + alu operation.
1339 s_ext decides if the operand1 should be sign-extended or zero-extended when
1340 needed. */
31c18d87
EI
1341static int dec_prep_alu_m(DisasContext *dc, int s_ext, int memsize,
1342 TCGv dst, TCGv src)
cf1d97f0
EI
1343{
1344 int insn_len;
1345
31c18d87
EI
1346 insn_len = dec_prep_move_m(dc, s_ext, memsize, src);
1347 tcg_gen_mov_tl(dst, cpu_R[dc->op2]);
8170028d
TS
1348 return insn_len;
1349}
1350
1351#if DISAS_CRIS
1352static const char *cc_name(int cc)
1353{
9b32fbf8 1354 static const char *cc_names[16] = {
8170028d
TS
1355 "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi",
1356 "ls", "hi", "ge", "lt", "gt", "le", "a", "p"
1357 };
1358 assert(cc < 16);
1359 return cc_names[cc];
1360}
1361#endif
1362
b41f7df0
EI
1363/* Start of insn decoders. */
1364
8170028d
TS
1365static unsigned int dec_bccq(DisasContext *dc)
1366{
1367 int32_t offset;
1368 int sign;
1369 uint32_t cond = dc->op2;
1370 int tmp;
1371
1372 offset = EXTRACT_FIELD (dc->ir, 1, 7);
1373 sign = EXTRACT_FIELD(dc->ir, 0, 0);
1374
1375 offset *= 2;
1376 offset |= sign << 8;
1377 tmp = offset;
1378 offset = sign_extend(offset, 8);
1379
d12d51d5 1380 LOG_DIS("b%s %x\n", cc_name(cond), dc->pc + offset);
2a44f7f1 1381
8170028d
TS
1382 /* op2 holds the condition-code. */
1383 cris_cc_mask(dc, 0);
1384 cris_prepare_cc_branch (dc, offset, cond);
1385 return 2;
1386}
1387static unsigned int dec_addoq(DisasContext *dc)
1388{
b41f7df0 1389 int32_t imm;
8170028d
TS
1390
1391 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 7);
1392 imm = sign_extend(dc->op1, 7);
1393
d12d51d5 1394 LOG_DIS("addoq %d, $r%u\n", imm, dc->op2);
8170028d
TS
1395 cris_cc_mask(dc, 0);
1396 /* Fetch register operand, */
b41f7df0 1397 tcg_gen_addi_tl(cpu_R[R_ACR], cpu_R[dc->op2], imm);
fb48f71b 1398
8170028d
TS
1399 return 2;
1400}
1401static unsigned int dec_addq(DisasContext *dc)
1402{
d12d51d5 1403 LOG_DIS("addq %u, $r%u\n", dc->op1, dc->op2);
8170028d
TS
1404
1405 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1406
1407 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7
EI
1408
1409 cris_alu(dc, CC_OP_ADD,
1410 cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
8170028d
TS
1411 return 2;
1412}
1413static unsigned int dec_moveq(DisasContext *dc)
1414{
1415 uint32_t imm;
1416
1417 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1418 imm = sign_extend(dc->op1, 5);
d12d51d5 1419 LOG_DIS("moveq %d, $r%u\n", imm, dc->op2);
8170028d 1420
46e246c9 1421 tcg_gen_movi_tl(cpu_R[dc->op2], imm);
8170028d
TS
1422 return 2;
1423}
1424static unsigned int dec_subq(DisasContext *dc)
1425{
1426 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1427
d12d51d5 1428 LOG_DIS("subq %u, $r%u\n", dc->op1, dc->op2);
8170028d
TS
1429
1430 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7
EI
1431 cris_alu(dc, CC_OP_SUB,
1432 cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
8170028d
TS
1433 return 2;
1434}
1435static unsigned int dec_cmpq(DisasContext *dc)
1436{
1437 uint32_t imm;
1438 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1439 imm = sign_extend(dc->op1, 5);
1440
d12d51d5 1441 LOG_DIS("cmpq %d, $r%d\n", imm, dc->op2);
8170028d 1442 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7
EI
1443
1444 cris_alu(dc, CC_OP_CMP,
1445 cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
8170028d
TS
1446 return 2;
1447}
1448static unsigned int dec_andq(DisasContext *dc)
1449{
1450 uint32_t imm;
1451 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1452 imm = sign_extend(dc->op1, 5);
1453
d12d51d5 1454 LOG_DIS("andq %d, $r%d\n", imm, dc->op2);
8170028d 1455 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7
EI
1456
1457 cris_alu(dc, CC_OP_AND,
1458 cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
8170028d
TS
1459 return 2;
1460}
1461static unsigned int dec_orq(DisasContext *dc)
1462{
1463 uint32_t imm;
1464 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1465 imm = sign_extend(dc->op1, 5);
d12d51d5 1466 LOG_DIS("orq %d, $r%d\n", imm, dc->op2);
8170028d 1467 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7
EI
1468
1469 cris_alu(dc, CC_OP_OR,
1470 cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
8170028d
TS
1471 return 2;
1472}
1473static unsigned int dec_btstq(DisasContext *dc)
1474{
1475 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
d12d51d5 1476 LOG_DIS("btstq %u, $r%d\n", dc->op1, dc->op2);
17ac9754 1477
8170028d 1478 cris_cc_mask(dc, CC_MASK_NZ);
abd5c94e
EI
1479 cris_evaluate_flags(dc);
1480 gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->op2],
1481 tcg_const_tl(dc->op1), cpu_PR[PR_CCS]);
1482 cris_alu(dc, CC_OP_MOVE,
1483 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4);
b41f7df0 1484 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
30abcfc7 1485 dc->flags_uptodate = 1;
8170028d
TS
1486 return 2;
1487}
1488static unsigned int dec_asrq(DisasContext *dc)
1489{
1490 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
d12d51d5 1491 LOG_DIS("asrq %u, $r%d\n", dc->op1, dc->op2);
8170028d 1492 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7 1493
2a44f7f1
EI
1494 tcg_gen_sari_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
1495 cris_alu(dc, CC_OP_MOVE,
30abcfc7 1496 cpu_R[dc->op2],
2a44f7f1 1497 cpu_R[dc->op2], cpu_R[dc->op2], 4);
8170028d
TS
1498 return 2;
1499}
1500static unsigned int dec_lslq(DisasContext *dc)
1501{
1502 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
d12d51d5 1503 LOG_DIS("lslq %u, $r%d\n", dc->op1, dc->op2);
8170028d
TS
1504
1505 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7 1506
2a44f7f1
EI
1507 tcg_gen_shli_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
1508
1509 cris_alu(dc, CC_OP_MOVE,
30abcfc7 1510 cpu_R[dc->op2],
2a44f7f1 1511 cpu_R[dc->op2], cpu_R[dc->op2], 4);
8170028d
TS
1512 return 2;
1513}
1514static unsigned int dec_lsrq(DisasContext *dc)
1515{
1516 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
d12d51d5 1517 LOG_DIS("lsrq %u, $r%d\n", dc->op1, dc->op2);
8170028d
TS
1518
1519 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7 1520
2a44f7f1
EI
1521 tcg_gen_shri_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
1522 cris_alu(dc, CC_OP_MOVE,
30abcfc7 1523 cpu_R[dc->op2],
2a44f7f1 1524 cpu_R[dc->op2], cpu_R[dc->op2], 4);
8170028d
TS
1525 return 2;
1526}
1527
1528static unsigned int dec_move_r(DisasContext *dc)
1529{
1530 int size = memsize_zz(dc);
1531
d12d51d5
AL
1532 LOG_DIS("move.%c $r%u, $r%u\n",
1533 memsize_char(size), dc->op1, dc->op2);
8170028d
TS
1534
1535 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7
EI
1536 if (size == 4) {
1537 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, cpu_R[dc->op2]);
1538 cris_cc_mask(dc, CC_MASK_NZ);
1539 cris_update_cc_op(dc, CC_OP_MOVE, 4);
1540 cris_update_cc_x(dc);
1541 cris_update_result(dc, cpu_R[dc->op2]);
1542 }
1543 else {
43d7ac4e
EI
1544 TCGv t0;
1545
a7812ae4 1546 t0 = tcg_temp_new();
43d7ac4e 1547 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0);
30abcfc7
EI
1548 cris_alu(dc, CC_OP_MOVE,
1549 cpu_R[dc->op2],
43d7ac4e
EI
1550 cpu_R[dc->op2], t0, size);
1551 tcg_temp_free(t0);
30abcfc7 1552 }
8170028d
TS
1553 return 2;
1554}
1555
1556static unsigned int dec_scc_r(DisasContext *dc)
1557{
1558 int cond = dc->op2;
1559
d12d51d5
AL
1560 LOG_DIS("s%s $r%u\n",
1561 cc_name(cond), dc->op1);
8170028d
TS
1562
1563 if (cond != CC_A)
1564 {
dceaf394
EI
1565 int l1;
1566
c5631f48 1567 gen_tst_cc (dc, cpu_R[dc->op1], cond);
dceaf394 1568 l1 = gen_new_label();
c5631f48 1569 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[dc->op1], 0, l1);
dceaf394
EI
1570 tcg_gen_movi_tl(cpu_R[dc->op1], 1);
1571 gen_set_label(l1);
8170028d
TS
1572 }
1573 else
dceaf394 1574 tcg_gen_movi_tl(cpu_R[dc->op1], 1);
8170028d
TS
1575
1576 cris_cc_mask(dc, 0);
8170028d
TS
1577 return 2;
1578}
1579
fb48f71b
EI
1580static inline void cris_alu_alloc_temps(DisasContext *dc, int size, TCGv *t)
1581{
1582 if (size == 4) {
1583 t[0] = cpu_R[dc->op2];
1584 t[1] = cpu_R[dc->op1];
1585 } else {
a7812ae4
PB
1586 t[0] = tcg_temp_new();
1587 t[1] = tcg_temp_new();
fb48f71b
EI
1588 }
1589}
1590
1591static inline void cris_alu_free_temps(DisasContext *dc, int size, TCGv *t)
1592{
1593 if (size != 4) {
1594 tcg_temp_free(t[0]);
1595 tcg_temp_free(t[1]);
1596 }
1597}
1598
8170028d
TS
1599static unsigned int dec_and_r(DisasContext *dc)
1600{
fb48f71b 1601 TCGv t[2];
8170028d
TS
1602 int size = memsize_zz(dc);
1603
d12d51d5
AL
1604 LOG_DIS("and.%c $r%u, $r%u\n",
1605 memsize_char(size), dc->op1, dc->op2);
fb48f71b 1606
8170028d 1607 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7 1608
fb48f71b
EI
1609 cris_alu_alloc_temps(dc, size, t);
1610 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1611 cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], size);
1612 cris_alu_free_temps(dc, size, t);
8170028d
TS
1613 return 2;
1614}
1615
1616static unsigned int dec_lz_r(DisasContext *dc)
1617{
fb48f71b 1618 TCGv t0;
d12d51d5
AL
1619 LOG_DIS("lz $r%u, $r%u\n",
1620 dc->op1, dc->op2);
8170028d 1621 cris_cc_mask(dc, CC_MASK_NZ);
a7812ae4 1622 t0 = tcg_temp_new();
fb48f71b
EI
1623 dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0, cpu_R[dc->op2], t0);
1624 cris_alu(dc, CC_OP_LZ, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
1625 tcg_temp_free(t0);
8170028d
TS
1626 return 2;
1627}
1628
1629static unsigned int dec_lsl_r(DisasContext *dc)
1630{
fb48f71b 1631 TCGv t[2];
8170028d
TS
1632 int size = memsize_zz(dc);
1633
d12d51d5
AL
1634 LOG_DIS("lsl.%c $r%u, $r%u\n",
1635 memsize_char(size), dc->op1, dc->op2);
30abcfc7 1636
fb48f71b
EI
1637 cris_cc_mask(dc, CC_MASK_NZ);
1638 cris_alu_alloc_temps(dc, size, t);
1639 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1640 tcg_gen_andi_tl(t[1], t[1], 63);
1641 cris_alu(dc, CC_OP_LSL, cpu_R[dc->op2], t[0], t[1], size);
1642 cris_alu_alloc_temps(dc, size, t);
8170028d
TS
1643 return 2;
1644}
1645
1646static unsigned int dec_lsr_r(DisasContext *dc)
1647{
fb48f71b 1648 TCGv t[2];
8170028d
TS
1649 int size = memsize_zz(dc);
1650
d12d51d5
AL
1651 LOG_DIS("lsr.%c $r%u, $r%u\n",
1652 memsize_char(size), dc->op1, dc->op2);
30abcfc7 1653
fb48f71b
EI
1654 cris_cc_mask(dc, CC_MASK_NZ);
1655 cris_alu_alloc_temps(dc, size, t);
1656 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1657 tcg_gen_andi_tl(t[1], t[1], 63);
1658 cris_alu(dc, CC_OP_LSR, cpu_R[dc->op2], t[0], t[1], size);
1659 cris_alu_free_temps(dc, size, t);
8170028d
TS
1660 return 2;
1661}
1662
1663static unsigned int dec_asr_r(DisasContext *dc)
1664{
fb48f71b 1665 TCGv t[2];
8170028d
TS
1666 int size = memsize_zz(dc);
1667
d12d51d5
AL
1668 LOG_DIS("asr.%c $r%u, $r%u\n",
1669 memsize_char(size), dc->op1, dc->op2);
30abcfc7 1670
fb48f71b
EI
1671 cris_cc_mask(dc, CC_MASK_NZ);
1672 cris_alu_alloc_temps(dc, size, t);
1673 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]);
1674 tcg_gen_andi_tl(t[1], t[1], 63);
1675 cris_alu(dc, CC_OP_ASR, cpu_R[dc->op2], t[0], t[1], size);
1676 cris_alu_free_temps(dc, size, t);
8170028d
TS
1677 return 2;
1678}
1679
1680static unsigned int dec_muls_r(DisasContext *dc)
1681{
fb48f71b 1682 TCGv t[2];
8170028d
TS
1683 int size = memsize_zz(dc);
1684
d12d51d5
AL
1685 LOG_DIS("muls.%c $r%u, $r%u\n",
1686 memsize_char(size), dc->op1, dc->op2);
8170028d 1687 cris_cc_mask(dc, CC_MASK_NZV);
fb48f71b
EI
1688 cris_alu_alloc_temps(dc, size, t);
1689 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]);
30abcfc7 1690
fb48f71b
EI
1691 cris_alu(dc, CC_OP_MULS, cpu_R[dc->op2], t[0], t[1], 4);
1692 cris_alu_free_temps(dc, size, t);
8170028d
TS
1693 return 2;
1694}
1695
1696static unsigned int dec_mulu_r(DisasContext *dc)
1697{
fb48f71b 1698 TCGv t[2];
8170028d
TS
1699 int size = memsize_zz(dc);
1700
d12d51d5
AL
1701 LOG_DIS("mulu.%c $r%u, $r%u\n",
1702 memsize_char(size), dc->op1, dc->op2);
8170028d 1703 cris_cc_mask(dc, CC_MASK_NZV);
fb48f71b
EI
1704 cris_alu_alloc_temps(dc, size, t);
1705 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
30abcfc7 1706
fb48f71b
EI
1707 cris_alu(dc, CC_OP_MULU, cpu_R[dc->op2], t[0], t[1], 4);
1708 cris_alu_alloc_temps(dc, size, t);
8170028d
TS
1709 return 2;
1710}
1711
1712
1713static unsigned int dec_dstep_r(DisasContext *dc)
1714{
d12d51d5 1715 LOG_DIS("dstep $r%u, $r%u\n", dc->op1, dc->op2);
8170028d 1716 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7
EI
1717 cris_alu(dc, CC_OP_DSTEP,
1718 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
8170028d
TS
1719 return 2;
1720}
1721
1722static unsigned int dec_xor_r(DisasContext *dc)
1723{
fb48f71b 1724 TCGv t[2];
8170028d 1725 int size = memsize_zz(dc);
d12d51d5
AL
1726 LOG_DIS("xor.%c $r%u, $r%u\n",
1727 memsize_char(size), dc->op1, dc->op2);
8170028d
TS
1728 BUG_ON(size != 4); /* xor is dword. */
1729 cris_cc_mask(dc, CC_MASK_NZ);
fb48f71b
EI
1730 cris_alu_alloc_temps(dc, size, t);
1731 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
30abcfc7 1732
fb48f71b
EI
1733 cris_alu(dc, CC_OP_XOR, cpu_R[dc->op2], t[0], t[1], 4);
1734 cris_alu_free_temps(dc, size, t);
8170028d
TS
1735 return 2;
1736}
1737
1738static unsigned int dec_bound_r(DisasContext *dc)
1739{
fb48f71b 1740 TCGv l0;
8170028d 1741 int size = memsize_zz(dc);
d12d51d5
AL
1742 LOG_DIS("bound.%c $r%u, $r%u\n",
1743 memsize_char(size), dc->op1, dc->op2);
8170028d 1744 cris_cc_mask(dc, CC_MASK_NZ);
a7812ae4 1745 l0 = tcg_temp_local_new();
fb48f71b 1746 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, l0);
31c18d87
EI
1747 cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], cpu_R[dc->op2], l0, 4);
1748 tcg_temp_free(l0);
8170028d
TS
1749 return 2;
1750}
1751
1752static unsigned int dec_cmp_r(DisasContext *dc)
1753{
fb48f71b 1754 TCGv t[2];
8170028d 1755 int size = memsize_zz(dc);
d12d51d5
AL
1756 LOG_DIS("cmp.%c $r%u, $r%u\n",
1757 memsize_char(size), dc->op1, dc->op2);
8170028d 1758 cris_cc_mask(dc, CC_MASK_NZVC);
fb48f71b
EI
1759 cris_alu_alloc_temps(dc, size, t);
1760 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
30abcfc7 1761
fb48f71b
EI
1762 cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], t[0], t[1], size);
1763 cris_alu_free_temps(dc, size, t);
8170028d
TS
1764 return 2;
1765}
1766
1767static unsigned int dec_abs_r(DisasContext *dc)
1768{
7dcfb089 1769 TCGv t0;
3157a0a9 1770
d12d51d5
AL
1771 LOG_DIS("abs $r%u, $r%u\n",
1772 dc->op1, dc->op2);
8170028d 1773 cris_cc_mask(dc, CC_MASK_NZ);
3157a0a9 1774
a7812ae4 1775 t0 = tcg_temp_new();
7dcfb089
EI
1776 tcg_gen_sari_tl(t0, cpu_R[dc->op1], 31);
1777 tcg_gen_xor_tl(cpu_R[dc->op2], cpu_R[dc->op1], t0);
1778 tcg_gen_sub_tl(cpu_R[dc->op2], cpu_R[dc->op2], t0);
1779 tcg_temp_free(t0);
1780
30abcfc7 1781 cris_alu(dc, CC_OP_MOVE,
7dcfb089 1782 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4);
8170028d
TS
1783 return 2;
1784}
1785
1786static unsigned int dec_add_r(DisasContext *dc)
1787{
fb48f71b 1788 TCGv t[2];
8170028d 1789 int size = memsize_zz(dc);
d12d51d5
AL
1790 LOG_DIS("add.%c $r%u, $r%u\n",
1791 memsize_char(size), dc->op1, dc->op2);
8170028d 1792 cris_cc_mask(dc, CC_MASK_NZVC);
fb48f71b
EI
1793 cris_alu_alloc_temps(dc, size, t);
1794 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
30abcfc7 1795
fb48f71b
EI
1796 cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], t[0], t[1], size);
1797 cris_alu_free_temps(dc, size, t);
8170028d
TS
1798 return 2;
1799}
1800
1801static unsigned int dec_addc_r(DisasContext *dc)
1802{
d12d51d5
AL
1803 LOG_DIS("addc $r%u, $r%u\n",
1804 dc->op1, dc->op2);
8170028d 1805 cris_evaluate_flags(dc);
a8cf66bb
EI
1806 /* Set for this insn. */
1807 dc->flagx_known = 1;
1808 dc->flags_x = X_FLAG;
1809
8170028d 1810 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7 1811 cris_alu(dc, CC_OP_ADDC,
fb48f71b 1812 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
8170028d
TS
1813 return 2;
1814}
1815
1816static unsigned int dec_mcp_r(DisasContext *dc)
1817{
d12d51d5
AL
1818 LOG_DIS("mcp $p%u, $r%u\n",
1819 dc->op2, dc->op1);
8170028d
TS
1820 cris_evaluate_flags(dc);
1821 cris_cc_mask(dc, CC_MASK_RNZV);
30abcfc7
EI
1822 cris_alu(dc, CC_OP_MCP,
1823 cpu_R[dc->op1], cpu_R[dc->op1], cpu_PR[dc->op2], 4);
8170028d
TS
1824 return 2;
1825}
1826
1827#if DISAS_CRIS
1828static char * swapmode_name(int mode, char *modename) {
1829 int i = 0;
1830 if (mode & 8)
1831 modename[i++] = 'n';
1832 if (mode & 4)
1833 modename[i++] = 'w';
1834 if (mode & 2)
1835 modename[i++] = 'b';
1836 if (mode & 1)
1837 modename[i++] = 'r';
1838 modename[i++] = 0;
1839 return modename;
1840}
1841#endif
1842
1843static unsigned int dec_swap_r(DisasContext *dc)
1844{
fb48f71b 1845 TCGv t0;
cf1d97f0
EI
1846#if DISAS_CRIS
1847 char modename[4];
1848#endif
d12d51d5
AL
1849 LOG_DIS("swap%s $r%u\n",
1850 swapmode_name(dc->op2, modename), dc->op1);
8170028d
TS
1851
1852 cris_cc_mask(dc, CC_MASK_NZ);
a7812ae4 1853 t0 = tcg_temp_new();
fb48f71b 1854 t_gen_mov_TN_reg(t0, dc->op1);
8170028d 1855 if (dc->op2 & 8)
fb48f71b 1856 tcg_gen_not_tl(t0, t0);
8170028d 1857 if (dc->op2 & 4)
fb48f71b 1858 t_gen_swapw(t0, t0);
8170028d 1859 if (dc->op2 & 2)
fb48f71b 1860 t_gen_swapb(t0, t0);
8170028d 1861 if (dc->op2 & 1)
fb48f71b 1862 t_gen_swapr(t0, t0);
30abcfc7 1863 cris_alu(dc, CC_OP_MOVE,
fb48f71b 1864 cpu_R[dc->op1], cpu_R[dc->op1], t0, 4);
f4b147f6 1865 tcg_temp_free(t0);
8170028d
TS
1866 return 2;
1867}
1868
1869static unsigned int dec_or_r(DisasContext *dc)
1870{
fb48f71b 1871 TCGv t[2];
8170028d 1872 int size = memsize_zz(dc);
d12d51d5
AL
1873 LOG_DIS("or.%c $r%u, $r%u\n",
1874 memsize_char(size), dc->op1, dc->op2);
8170028d 1875 cris_cc_mask(dc, CC_MASK_NZ);
fb48f71b
EI
1876 cris_alu_alloc_temps(dc, size, t);
1877 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1878 cris_alu(dc, CC_OP_OR, cpu_R[dc->op2], t[0], t[1], size);
1879 cris_alu_free_temps(dc, size, t);
8170028d
TS
1880 return 2;
1881}
1882
1883static unsigned int dec_addi_r(DisasContext *dc)
1884{
fb48f71b 1885 TCGv t0;
d12d51d5
AL
1886 LOG_DIS("addi.%c $r%u, $r%u\n",
1887 memsize_char(memsize_zz(dc)), dc->op2, dc->op1);
8170028d 1888 cris_cc_mask(dc, 0);
a7812ae4 1889 t0 = tcg_temp_new();
fb48f71b
EI
1890 tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize));
1891 tcg_gen_add_tl(cpu_R[dc->op1], cpu_R[dc->op1], t0);
f4b147f6 1892 tcg_temp_free(t0);
8170028d
TS
1893 return 2;
1894}
1895
1896static unsigned int dec_addi_acr(DisasContext *dc)
1897{
fb48f71b 1898 TCGv t0;
d12d51d5
AL
1899 LOG_DIS("addi.%c $r%u, $r%u, $acr\n",
1900 memsize_char(memsize_zz(dc)), dc->op2, dc->op1);
8170028d 1901 cris_cc_mask(dc, 0);
a7812ae4 1902 t0 = tcg_temp_new();
fb48f71b
EI
1903 tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize));
1904 tcg_gen_add_tl(cpu_R[R_ACR], cpu_R[dc->op1], t0);
f4b147f6 1905 tcg_temp_free(t0);
8170028d
TS
1906 return 2;
1907}
1908
1909static unsigned int dec_neg_r(DisasContext *dc)
1910{
fb48f71b 1911 TCGv t[2];
8170028d 1912 int size = memsize_zz(dc);
d12d51d5
AL
1913 LOG_DIS("neg.%c $r%u, $r%u\n",
1914 memsize_char(size), dc->op1, dc->op2);
8170028d 1915 cris_cc_mask(dc, CC_MASK_NZVC);
fb48f71b
EI
1916 cris_alu_alloc_temps(dc, size, t);
1917 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
30abcfc7 1918
fb48f71b
EI
1919 cris_alu(dc, CC_OP_NEG, cpu_R[dc->op2], t[0], t[1], size);
1920 cris_alu_free_temps(dc, size, t);
8170028d
TS
1921 return 2;
1922}
1923
1924static unsigned int dec_btst_r(DisasContext *dc)
1925{
d12d51d5
AL
1926 LOG_DIS("btst $r%u, $r%u\n",
1927 dc->op1, dc->op2);
8170028d 1928 cris_cc_mask(dc, CC_MASK_NZ);
abd5c94e
EI
1929 cris_evaluate_flags(dc);
1930 gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->op2],
1931 cpu_R[dc->op1], cpu_PR[PR_CCS]);
1932 cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2],
1933 cpu_R[dc->op2], cpu_R[dc->op2], 4);
b41f7df0 1934 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
30abcfc7 1935 dc->flags_uptodate = 1;
8170028d
TS
1936 return 2;
1937}
1938
1939static unsigned int dec_sub_r(DisasContext *dc)
1940{
fb48f71b 1941 TCGv t[2];
8170028d 1942 int size = memsize_zz(dc);
d12d51d5
AL
1943 LOG_DIS("sub.%c $r%u, $r%u\n",
1944 memsize_char(size), dc->op1, dc->op2);
8170028d 1945 cris_cc_mask(dc, CC_MASK_NZVC);
fb48f71b
EI
1946 cris_alu_alloc_temps(dc, size, t);
1947 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1948 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], size);
1949 cris_alu_free_temps(dc, size, t);
8170028d
TS
1950 return 2;
1951}
1952
1953/* Zero extension. From size to dword. */
1954static unsigned int dec_movu_r(DisasContext *dc)
1955{
fb48f71b 1956 TCGv t0;
8170028d 1957 int size = memsize_z(dc);
d12d51d5 1958 LOG_DIS("movu.%c $r%u, $r%u\n",
8170028d 1959 memsize_char(size),
d12d51d5 1960 dc->op1, dc->op2);
8170028d
TS
1961
1962 cris_cc_mask(dc, CC_MASK_NZ);
a7812ae4 1963 t0 = tcg_temp_new();
fb48f71b
EI
1964 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0);
1965 cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
1966 tcg_temp_free(t0);
8170028d
TS
1967 return 2;
1968}
1969
1970/* Sign extension. From size to dword. */
1971static unsigned int dec_movs_r(DisasContext *dc)
1972{
fb48f71b 1973 TCGv t0;
8170028d 1974 int size = memsize_z(dc);
d12d51d5 1975 LOG_DIS("movs.%c $r%u, $r%u\n",
8170028d 1976 memsize_char(size),
d12d51d5 1977 dc->op1, dc->op2);
8170028d
TS
1978
1979 cris_cc_mask(dc, CC_MASK_NZ);
a7812ae4 1980 t0 = tcg_temp_new();
8170028d 1981 /* Size can only be qi or hi. */
fb48f71b 1982 t_gen_sext(t0, cpu_R[dc->op1], size);
30abcfc7 1983 cris_alu(dc, CC_OP_MOVE,
fb48f71b
EI
1984 cpu_R[dc->op2], cpu_R[dc->op1], t0, 4);
1985 tcg_temp_free(t0);
8170028d
TS
1986 return 2;
1987}
1988
1989/* zero extension. From size to dword. */
1990static unsigned int dec_addu_r(DisasContext *dc)
1991{
fb48f71b 1992 TCGv t0;
8170028d 1993 int size = memsize_z(dc);
d12d51d5 1994 LOG_DIS("addu.%c $r%u, $r%u\n",
8170028d 1995 memsize_char(size),
d12d51d5 1996 dc->op1, dc->op2);
8170028d
TS
1997
1998 cris_cc_mask(dc, CC_MASK_NZVC);
a7812ae4 1999 t0 = tcg_temp_new();
8170028d 2000 /* Size can only be qi or hi. */
fb48f71b 2001 t_gen_zext(t0, cpu_R[dc->op1], size);
30abcfc7 2002 cris_alu(dc, CC_OP_ADD,
fb48f71b
EI
2003 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
2004 tcg_temp_free(t0);
8170028d
TS
2005 return 2;
2006}
05ba7d5f 2007
8170028d
TS
2008/* Sign extension. From size to dword. */
2009static unsigned int dec_adds_r(DisasContext *dc)
2010{
fb48f71b 2011 TCGv t0;
8170028d 2012 int size = memsize_z(dc);
d12d51d5 2013 LOG_DIS("adds.%c $r%u, $r%u\n",
8170028d 2014 memsize_char(size),
d12d51d5 2015 dc->op1, dc->op2);
8170028d
TS
2016
2017 cris_cc_mask(dc, CC_MASK_NZVC);
a7812ae4 2018 t0 = tcg_temp_new();
8170028d 2019 /* Size can only be qi or hi. */
fb48f71b 2020 t_gen_sext(t0, cpu_R[dc->op1], size);
30abcfc7 2021 cris_alu(dc, CC_OP_ADD,
fb48f71b
EI
2022 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
2023 tcg_temp_free(t0);
8170028d
TS
2024 return 2;
2025}
2026
2027/* Zero extension. From size to dword. */
2028static unsigned int dec_subu_r(DisasContext *dc)
2029{
fb48f71b 2030 TCGv t0;
8170028d 2031 int size = memsize_z(dc);
d12d51d5 2032 LOG_DIS("subu.%c $r%u, $r%u\n",
8170028d 2033 memsize_char(size),
d12d51d5 2034 dc->op1, dc->op2);
8170028d
TS
2035
2036 cris_cc_mask(dc, CC_MASK_NZVC);
a7812ae4 2037 t0 = tcg_temp_new();
8170028d 2038 /* Size can only be qi or hi. */
fb48f71b 2039 t_gen_zext(t0, cpu_R[dc->op1], size);
30abcfc7 2040 cris_alu(dc, CC_OP_SUB,
fb48f71b
EI
2041 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
2042 tcg_temp_free(t0);
8170028d
TS
2043 return 2;
2044}
2045
2046/* Sign extension. From size to dword. */
2047static unsigned int dec_subs_r(DisasContext *dc)
2048{
fb48f71b 2049 TCGv t0;
8170028d 2050 int size = memsize_z(dc);
d12d51d5 2051 LOG_DIS("subs.%c $r%u, $r%u\n",
8170028d 2052 memsize_char(size),
d12d51d5 2053 dc->op1, dc->op2);
8170028d
TS
2054
2055 cris_cc_mask(dc, CC_MASK_NZVC);
a7812ae4 2056 t0 = tcg_temp_new();
8170028d 2057 /* Size can only be qi or hi. */
fb48f71b 2058 t_gen_sext(t0, cpu_R[dc->op1], size);
30abcfc7 2059 cris_alu(dc, CC_OP_SUB,
fb48f71b
EI
2060 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
2061 tcg_temp_free(t0);
8170028d
TS
2062 return 2;
2063}
2064
2065static unsigned int dec_setclrf(DisasContext *dc)
2066{
2067 uint32_t flags;
2068 int set = (~dc->opcode >> 2) & 1;
2069
fb48f71b 2070
8170028d
TS
2071 flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4)
2072 | EXTRACT_FIELD(dc->ir, 0, 3);
cf1d97f0 2073 if (set && flags == 0) {
d12d51d5 2074 LOG_DIS("nop\n");
30abcfc7 2075 return 2;
cf1d97f0 2076 } else if (!set && (flags & 0x20)) {
d12d51d5 2077 LOG_DIS("di\n");
cf1d97f0
EI
2078 }
2079 else {
d12d51d5 2080 LOG_DIS("%sf %x\n",
cf1d97f0 2081 set ? "set" : "clr",
d12d51d5 2082 flags);
cf1d97f0 2083 }
8170028d 2084
fb48f71b 2085 /* User space is not allowed to touch these. Silently ignore. */
2a44f7f1 2086 if (dc->tb_flags & U_FLAG) {
a1aebcb8 2087 flags &= ~(S_FLAG | I_FLAG | U_FLAG);
2a44f7f1
EI
2088 }
2089
2090 if (flags & X_FLAG) {
30abcfc7 2091 dc->flagx_known = 1;
2a44f7f1
EI
2092 if (set)
2093 dc->flags_x = X_FLAG;
2094 else
2095 dc->flags_x = 0;
8170028d
TS
2096 }
2097
40e9eddd
EI
2098 /* Break the TB if any of the SPI flag changes. */
2099 if (flags & (P_FLAG | S_FLAG)) {
2100 tcg_gen_movi_tl(env_pc, dc->pc + 2);
2101 dc->is_jmp = DISAS_UPDATE;
2102 dc->cpustate_changed = 1;
2a44f7f1 2103 }
40e9eddd
EI
2104
2105 /* For the I flag, only act on posedge. */
2106 if ((flags & I_FLAG)) {
2107 tcg_gen_movi_tl(env_pc, dc->pc + 2);
2108 dc->is_jmp = DISAS_UPDATE;
a1aebcb8
EI
2109 dc->cpustate_changed = 1;
2110 }
2a44f7f1
EI
2111
2112
8170028d
TS
2113 /* Simply decode the flags. */
2114 cris_evaluate_flags (dc);
b41f7df0 2115 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
30abcfc7 2116 cris_update_cc_x(dc);
b41f7df0
EI
2117 tcg_gen_movi_tl(cc_op, dc->cc_op);
2118
dceaf394 2119 if (set) {
2a44f7f1 2120 if (!(dc->tb_flags & U_FLAG) && (flags & U_FLAG)) {
dceaf394
EI
2121 /* Enter user mode. */
2122 t_gen_mov_env_TN(ksp, cpu_R[R_SP]);
2123 tcg_gen_mov_tl(cpu_R[R_SP], cpu_PR[PR_USP]);
2a44f7f1 2124 dc->cpustate_changed = 1;
dceaf394
EI
2125 }
2126 tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags);
2127 }
8170028d 2128 else
dceaf394
EI
2129 tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags);
2130
30abcfc7 2131 dc->flags_uptodate = 1;
b41f7df0 2132 dc->clear_x = 0;
8170028d
TS
2133 return 2;
2134}
2135
2136static unsigned int dec_move_rs(DisasContext *dc)
2137{
d12d51d5 2138 LOG_DIS("move $r%u, $s%u\n", dc->op1, dc->op2);
8170028d 2139 cris_cc_mask(dc, 0);
a7812ae4 2140 gen_helper_movl_sreg_reg(tcg_const_tl(dc->op2), tcg_const_tl(dc->op1));
8170028d
TS
2141 return 2;
2142}
2143static unsigned int dec_move_sr(DisasContext *dc)
2144{
d12d51d5 2145 LOG_DIS("move $s%u, $r%u\n", dc->op2, dc->op1);
8170028d 2146 cris_cc_mask(dc, 0);
a7812ae4 2147 gen_helper_movl_reg_sreg(tcg_const_tl(dc->op1), tcg_const_tl(dc->op2));
8170028d
TS
2148 return 2;
2149}
dceaf394 2150
8170028d
TS
2151static unsigned int dec_move_rp(DisasContext *dc)
2152{
fb48f71b 2153 TCGv t[2];
d12d51d5 2154 LOG_DIS("move $r%u, $p%u\n", dc->op1, dc->op2);
8170028d 2155 cris_cc_mask(dc, 0);
b41f7df0 2156
a7812ae4 2157 t[0] = tcg_temp_new();
b41f7df0
EI
2158 if (dc->op2 == PR_CCS) {
2159 cris_evaluate_flags(dc);
fb48f71b 2160 t_gen_mov_TN_reg(t[0], dc->op1);
2a44f7f1 2161 if (dc->tb_flags & U_FLAG) {
a7812ae4 2162 t[1] = tcg_temp_new();
b41f7df0 2163 /* User space is not allowed to touch all flags. */
fb48f71b
EI
2164 tcg_gen_andi_tl(t[0], t[0], 0x39f);
2165 tcg_gen_andi_tl(t[1], cpu_PR[PR_CCS], ~0x39f);
2166 tcg_gen_or_tl(t[0], t[1], t[0]);
2167 tcg_temp_free(t[1]);
b41f7df0
EI
2168 }
2169 }
2170 else
fb48f71b 2171 t_gen_mov_TN_reg(t[0], dc->op1);
b41f7df0 2172
fb48f71b 2173 t_gen_mov_preg_TN(dc, dc->op2, t[0]);
b41f7df0
EI
2174 if (dc->op2 == PR_CCS) {
2175 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
30abcfc7 2176 dc->flags_uptodate = 1;
b41f7df0 2177 }
fb48f71b 2178 tcg_temp_free(t[0]);
8170028d
TS
2179 return 2;
2180}
2181static unsigned int dec_move_pr(DisasContext *dc)
2182{
fb48f71b 2183 TCGv t0;
40e9eddd 2184 LOG_DIS("move $p%u, $r%u\n", dc->op2, dc->op1);
8170028d 2185 cris_cc_mask(dc, 0);
2a44f7f1
EI
2186
2187 if (dc->op2 == PR_CCS)
b41f7df0 2188 cris_evaluate_flags(dc);
2a44f7f1 2189
40e9eddd
EI
2190 if (dc->op2 == PR_DZ) {
2191 tcg_gen_movi_tl(cpu_R[dc->op1], 0);
2192 } else {
2193 t0 = tcg_temp_new();
2194 t_gen_mov_TN_preg(t0, dc->op2);
2195 cris_alu(dc, CC_OP_MOVE,
2196 cpu_R[dc->op1], cpu_R[dc->op1], t0,
2197 preg_sizes[dc->op2]);
2198 tcg_temp_free(t0);
2199 }
8170028d
TS
2200 return 2;
2201}
2202
2203static unsigned int dec_move_mr(DisasContext *dc)
2204{
2205 int memsize = memsize_zz(dc);
2206 int insn_len;
d12d51d5 2207 LOG_DIS("move.%c [$r%u%s, $r%u\n",
8170028d
TS
2208 memsize_char(memsize),
2209 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2210 dc->op2);
8170028d 2211
30abcfc7
EI
2212 if (memsize == 4) {
2213 insn_len = dec_prep_move_m(dc, 0, 4, cpu_R[dc->op2]);
2214 cris_cc_mask(dc, CC_MASK_NZ);
2215 cris_update_cc_op(dc, CC_OP_MOVE, 4);
2216 cris_update_cc_x(dc);
2217 cris_update_result(dc, cpu_R[dc->op2]);
2218 }
2219 else {
fb48f71b
EI
2220 TCGv t0;
2221
a7812ae4 2222 t0 = tcg_temp_new();
fb48f71b 2223 insn_len = dec_prep_move_m(dc, 0, memsize, t0);
30abcfc7
EI
2224 cris_cc_mask(dc, CC_MASK_NZ);
2225 cris_alu(dc, CC_OP_MOVE,
fb48f71b
EI
2226 cpu_R[dc->op2], cpu_R[dc->op2], t0, memsize);
2227 tcg_temp_free(t0);
30abcfc7 2228 }
8170028d
TS
2229 do_postinc(dc, memsize);
2230 return insn_len;
2231}
2232
31c18d87
EI
2233static inline void cris_alu_m_alloc_temps(TCGv *t)
2234{
a7812ae4
PB
2235 t[0] = tcg_temp_new();
2236 t[1] = tcg_temp_new();
31c18d87
EI
2237}
2238
2239static inline void cris_alu_m_free_temps(TCGv *t)
2240{
2241 tcg_temp_free(t[0]);
2242 tcg_temp_free(t[1]);
2243}
2244
8170028d
TS
2245static unsigned int dec_movs_m(DisasContext *dc)
2246{
31c18d87 2247 TCGv t[2];
8170028d
TS
2248 int memsize = memsize_z(dc);
2249 int insn_len;
d12d51d5 2250 LOG_DIS("movs.%c [$r%u%s, $r%u\n",
8170028d
TS
2251 memsize_char(memsize),
2252 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2253 dc->op2);
8170028d 2254
31c18d87 2255 cris_alu_m_alloc_temps(t);
8170028d 2256 /* sign extend. */
31c18d87 2257 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
b41f7df0 2258 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7 2259 cris_alu(dc, CC_OP_MOVE,
31c18d87 2260 cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2261 do_postinc(dc, memsize);
31c18d87 2262 cris_alu_m_free_temps(t);
8170028d
TS
2263 return insn_len;
2264}
2265
2266static unsigned int dec_addu_m(DisasContext *dc)
2267{
31c18d87 2268 TCGv t[2];
8170028d
TS
2269 int memsize = memsize_z(dc);
2270 int insn_len;
d12d51d5 2271 LOG_DIS("addu.%c [$r%u%s, $r%u\n",
8170028d
TS
2272 memsize_char(memsize),
2273 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2274 dc->op2);
8170028d 2275
31c18d87 2276 cris_alu_m_alloc_temps(t);
8170028d 2277 /* sign extend. */
31c18d87 2278 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2279 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7 2280 cris_alu(dc, CC_OP_ADD,
31c18d87 2281 cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2282 do_postinc(dc, memsize);
31c18d87 2283 cris_alu_m_free_temps(t);
8170028d
TS
2284 return insn_len;
2285}
2286
2287static unsigned int dec_adds_m(DisasContext *dc)
2288{
31c18d87 2289 TCGv t[2];
8170028d
TS
2290 int memsize = memsize_z(dc);
2291 int insn_len;
d12d51d5 2292 LOG_DIS("adds.%c [$r%u%s, $r%u\n",
8170028d
TS
2293 memsize_char(memsize),
2294 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2295 dc->op2);
8170028d 2296
31c18d87 2297 cris_alu_m_alloc_temps(t);
8170028d 2298 /* sign extend. */
31c18d87 2299 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
b41f7df0 2300 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2301 cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2302 do_postinc(dc, memsize);
31c18d87 2303 cris_alu_m_free_temps(t);
8170028d
TS
2304 return insn_len;
2305}
2306
2307static unsigned int dec_subu_m(DisasContext *dc)
2308{
31c18d87 2309 TCGv t[2];
8170028d
TS
2310 int memsize = memsize_z(dc);
2311 int insn_len;
d12d51d5 2312 LOG_DIS("subu.%c [$r%u%s, $r%u\n",
8170028d
TS
2313 memsize_char(memsize),
2314 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2315 dc->op2);
8170028d 2316
31c18d87 2317 cris_alu_m_alloc_temps(t);
8170028d 2318 /* sign extend. */
31c18d87 2319 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2320 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2321 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2322 do_postinc(dc, memsize);
31c18d87 2323 cris_alu_m_free_temps(t);
8170028d
TS
2324 return insn_len;
2325}
2326
2327static unsigned int dec_subs_m(DisasContext *dc)
2328{
31c18d87 2329 TCGv t[2];
8170028d
TS
2330 int memsize = memsize_z(dc);
2331 int insn_len;
d12d51d5 2332 LOG_DIS("subs.%c [$r%u%s, $r%u\n",
8170028d
TS
2333 memsize_char(memsize),
2334 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2335 dc->op2);
8170028d 2336
31c18d87 2337 cris_alu_m_alloc_temps(t);
8170028d 2338 /* sign extend. */
31c18d87 2339 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
b41f7df0 2340 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2341 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2342 do_postinc(dc, memsize);
31c18d87 2343 cris_alu_m_free_temps(t);
8170028d
TS
2344 return insn_len;
2345}
2346
2347static unsigned int dec_movu_m(DisasContext *dc)
2348{
31c18d87 2349 TCGv t[2];
8170028d
TS
2350 int memsize = memsize_z(dc);
2351 int insn_len;
2352
d12d51d5 2353 LOG_DIS("movu.%c [$r%u%s, $r%u\n",
8170028d
TS
2354 memsize_char(memsize),
2355 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2356 dc->op2);
8170028d 2357
31c18d87
EI
2358 cris_alu_m_alloc_temps(t);
2359 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2360 cris_cc_mask(dc, CC_MASK_NZ);
31c18d87 2361 cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2362 do_postinc(dc, memsize);
31c18d87 2363 cris_alu_m_free_temps(t);
8170028d
TS
2364 return insn_len;
2365}
2366
2367static unsigned int dec_cmpu_m(DisasContext *dc)
2368{
31c18d87 2369 TCGv t[2];
8170028d
TS
2370 int memsize = memsize_z(dc);
2371 int insn_len;
d12d51d5 2372 LOG_DIS("cmpu.%c [$r%u%s, $r%u\n",
8170028d
TS
2373 memsize_char(memsize),
2374 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2375 dc->op2);
8170028d 2376
31c18d87
EI
2377 cris_alu_m_alloc_temps(t);
2378 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2379 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2380 cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2381 do_postinc(dc, memsize);
31c18d87 2382 cris_alu_m_free_temps(t);
8170028d
TS
2383 return insn_len;
2384}
2385
2386static unsigned int dec_cmps_m(DisasContext *dc)
2387{
31c18d87 2388 TCGv t[2];
8170028d
TS
2389 int memsize = memsize_z(dc);
2390 int insn_len;
d12d51d5 2391 LOG_DIS("cmps.%c [$r%u%s, $r%u\n",
8170028d
TS
2392 memsize_char(memsize),
2393 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2394 dc->op2);
8170028d 2395
31c18d87
EI
2396 cris_alu_m_alloc_temps(t);
2397 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
b41f7df0 2398 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7 2399 cris_alu(dc, CC_OP_CMP,
31c18d87 2400 cpu_R[dc->op2], cpu_R[dc->op2], t[1],
30abcfc7 2401 memsize_zz(dc));
8170028d 2402 do_postinc(dc, memsize);
31c18d87 2403 cris_alu_m_free_temps(t);
8170028d
TS
2404 return insn_len;
2405}
2406
2407static unsigned int dec_cmp_m(DisasContext *dc)
2408{
31c18d87 2409 TCGv t[2];
8170028d
TS
2410 int memsize = memsize_zz(dc);
2411 int insn_len;
d12d51d5 2412 LOG_DIS("cmp.%c [$r%u%s, $r%u\n",
8170028d
TS
2413 memsize_char(memsize),
2414 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2415 dc->op2);
8170028d 2416
31c18d87
EI
2417 cris_alu_m_alloc_temps(t);
2418 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2419 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7 2420 cris_alu(dc, CC_OP_CMP,
31c18d87 2421 cpu_R[dc->op2], cpu_R[dc->op2], t[1],
30abcfc7 2422 memsize_zz(dc));
8170028d 2423 do_postinc(dc, memsize);
31c18d87 2424 cris_alu_m_free_temps(t);
8170028d
TS
2425 return insn_len;
2426}
2427
2428static unsigned int dec_test_m(DisasContext *dc)
2429{
31c18d87 2430 TCGv t[2];
8170028d
TS
2431 int memsize = memsize_zz(dc);
2432 int insn_len;
ce24e07b 2433 LOG_DIS("test.%c [$r%u%s] op2=%x\n",
8170028d
TS
2434 memsize_char(memsize),
2435 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2436 dc->op2);
8170028d 2437
dceaf394
EI
2438 cris_evaluate_flags(dc);
2439
31c18d87
EI
2440 cris_alu_m_alloc_temps(t);
2441 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
8170028d 2442 cris_cc_mask(dc, CC_MASK_NZ);
dceaf394 2443 tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3);
b41f7df0 2444
30abcfc7 2445 cris_alu(dc, CC_OP_CMP,
31c18d87 2446 cpu_R[dc->op2], t[1], tcg_const_tl(0), memsize_zz(dc));
8170028d 2447 do_postinc(dc, memsize);
31c18d87 2448 cris_alu_m_free_temps(t);
8170028d
TS
2449 return insn_len;
2450}
2451
2452static unsigned int dec_and_m(DisasContext *dc)
2453{
31c18d87 2454 TCGv t[2];
8170028d
TS
2455 int memsize = memsize_zz(dc);
2456 int insn_len;
ce24e07b 2457 LOG_DIS("and.%c [$r%u%s, $r%u\n",
8170028d
TS
2458 memsize_char(memsize),
2459 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2460 dc->op2);
8170028d 2461
31c18d87
EI
2462 cris_alu_m_alloc_temps(t);
2463 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2464 cris_cc_mask(dc, CC_MASK_NZ);
31c18d87 2465 cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
8170028d 2466 do_postinc(dc, memsize);
31c18d87 2467 cris_alu_m_free_temps(t);
8170028d
TS
2468 return insn_len;
2469}
2470
2471static unsigned int dec_add_m(DisasContext *dc)
2472{
31c18d87 2473 TCGv t[2];
8170028d
TS
2474 int memsize = memsize_zz(dc);
2475 int insn_len;
ce24e07b 2476 LOG_DIS("add.%c [$r%u%s, $r%u\n",
8170028d
TS
2477 memsize_char(memsize),
2478 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2479 dc->op2);
8170028d 2480
31c18d87
EI
2481 cris_alu_m_alloc_temps(t);
2482 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2483 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7 2484 cris_alu(dc, CC_OP_ADD,
31c18d87 2485 cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
8170028d 2486 do_postinc(dc, memsize);
31c18d87 2487 cris_alu_m_free_temps(t);
8170028d
TS
2488 return insn_len;
2489}
2490
2491static unsigned int dec_addo_m(DisasContext *dc)
2492{
31c18d87 2493 TCGv t[2];
8170028d
TS
2494 int memsize = memsize_zz(dc);
2495 int insn_len;
ce24e07b 2496 LOG_DIS("add.%c [$r%u%s, $r%u\n",
8170028d
TS
2497 memsize_char(memsize),
2498 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2499 dc->op2);
8170028d 2500
31c18d87
EI
2501 cris_alu_m_alloc_temps(t);
2502 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
b41f7df0 2503 cris_cc_mask(dc, 0);
31c18d87 2504 cris_alu(dc, CC_OP_ADD, cpu_R[R_ACR], t[0], t[1], 4);
8170028d 2505 do_postinc(dc, memsize);
31c18d87 2506 cris_alu_m_free_temps(t);
8170028d
TS
2507 return insn_len;
2508}
2509
2510static unsigned int dec_bound_m(DisasContext *dc)
2511{
31c18d87 2512 TCGv l[2];
8170028d
TS
2513 int memsize = memsize_zz(dc);
2514 int insn_len;
ce24e07b 2515 LOG_DIS("bound.%c [$r%u%s, $r%u\n",
8170028d
TS
2516 memsize_char(memsize),
2517 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2518 dc->op2);
8170028d 2519
a7812ae4
PB
2520 l[0] = tcg_temp_local_new();
2521 l[1] = tcg_temp_local_new();
31c18d87 2522 insn_len = dec_prep_alu_m(dc, 0, memsize, l[0], l[1]);
b41f7df0 2523 cris_cc_mask(dc, CC_MASK_NZ);
31c18d87 2524 cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], l[0], l[1], 4);
8170028d 2525 do_postinc(dc, memsize);
31c18d87
EI
2526 tcg_temp_free(l[0]);
2527 tcg_temp_free(l[1]);
8170028d
TS
2528 return insn_len;
2529}
2530
2531static unsigned int dec_addc_mr(DisasContext *dc)
2532{
31c18d87 2533 TCGv t[2];
8170028d 2534 int insn_len = 2;
d12d51d5 2535 LOG_DIS("addc [$r%u%s, $r%u\n",
8170028d 2536 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2537 dc->op2);
8170028d
TS
2538
2539 cris_evaluate_flags(dc);
a8cf66bb
EI
2540
2541 /* Set for this insn. */
2542 dc->flagx_known = 1;
2543 dc->flags_x = X_FLAG;
2544
31c18d87
EI
2545 cris_alu_m_alloc_temps(t);
2546 insn_len = dec_prep_alu_m(dc, 0, 4, t[0], t[1]);
b41f7df0 2547 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2548 cris_alu(dc, CC_OP_ADDC, cpu_R[dc->op2], t[0], t[1], 4);
8170028d 2549 do_postinc(dc, 4);
31c18d87 2550 cris_alu_m_free_temps(t);
8170028d
TS
2551 return insn_len;
2552}
2553
2554static unsigned int dec_sub_m(DisasContext *dc)
2555{
31c18d87 2556 TCGv t[2];
8170028d
TS
2557 int memsize = memsize_zz(dc);
2558 int insn_len;
d12d51d5 2559 LOG_DIS("sub.%c [$r%u%s, $r%u ir=%x zz=%x\n",
8170028d
TS
2560 memsize_char(memsize),
2561 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2562 dc->op2, dc->ir, dc->zzsize);
8170028d 2563
31c18d87
EI
2564 cris_alu_m_alloc_temps(t);
2565 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2566 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2567 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], memsize);
8170028d 2568 do_postinc(dc, memsize);
31c18d87 2569 cris_alu_m_free_temps(t);
8170028d
TS
2570 return insn_len;
2571}
2572
2573static unsigned int dec_or_m(DisasContext *dc)
2574{
31c18d87 2575 TCGv t[2];
8170028d
TS
2576 int memsize = memsize_zz(dc);
2577 int insn_len;
ce24e07b 2578 LOG_DIS("or.%c [$r%u%s, $r%u pc=%x\n",
8170028d
TS
2579 memsize_char(memsize),
2580 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2581 dc->op2, dc->pc);
8170028d 2582
31c18d87
EI
2583 cris_alu_m_alloc_temps(t);
2584 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2585 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7 2586 cris_alu(dc, CC_OP_OR,
31c18d87 2587 cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
8170028d 2588 do_postinc(dc, memsize);
31c18d87 2589 cris_alu_m_free_temps(t);
8170028d
TS
2590 return insn_len;
2591}
2592
2593static unsigned int dec_move_mp(DisasContext *dc)
2594{
31c18d87 2595 TCGv t[2];
8170028d
TS
2596 int memsize = memsize_zz(dc);
2597 int insn_len = 2;
2598
d12d51d5 2599 LOG_DIS("move.%c [$r%u%s, $p%u\n",
8170028d
TS
2600 memsize_char(memsize),
2601 dc->op1,
2602 dc->postinc ? "+]" : "]",
d12d51d5 2603 dc->op2);
8170028d 2604
31c18d87
EI
2605 cris_alu_m_alloc_temps(t);
2606 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0
EI
2607 cris_cc_mask(dc, 0);
2608 if (dc->op2 == PR_CCS) {
2609 cris_evaluate_flags(dc);
2a44f7f1 2610 if (dc->tb_flags & U_FLAG) {
b41f7df0 2611 /* User space is not allowed to touch all flags. */
31c18d87
EI
2612 tcg_gen_andi_tl(t[1], t[1], 0x39f);
2613 tcg_gen_andi_tl(t[0], cpu_PR[PR_CCS], ~0x39f);
2614 tcg_gen_or_tl(t[1], t[0], t[1]);
b41f7df0
EI
2615 }
2616 }
2617
31c18d87 2618 t_gen_mov_preg_TN(dc, dc->op2, t[1]);
8170028d
TS
2619
2620 do_postinc(dc, memsize);
31c18d87 2621 cris_alu_m_free_temps(t);
8170028d
TS
2622 return insn_len;
2623}
2624
2625static unsigned int dec_move_pm(DisasContext *dc)
2626{
31c18d87 2627 TCGv t0;
8170028d
TS
2628 int memsize;
2629
2630 memsize = preg_sizes[dc->op2];
2631
d12d51d5 2632 LOG_DIS("move.%c $p%u, [$r%u%s\n",
fd56059f 2633 memsize_char(memsize),
d12d51d5 2634 dc->op2, dc->op1, dc->postinc ? "+]" : "]");
8170028d 2635
fd56059f 2636 /* prepare store. Address in T0, value in T1. */
17ac9754
EI
2637 if (dc->op2 == PR_CCS)
2638 cris_evaluate_flags(dc);
a7812ae4 2639 t0 = tcg_temp_new();
31c18d87 2640 t_gen_mov_TN_preg(t0, dc->op2);
30abcfc7 2641 cris_flush_cc_state(dc);
31c18d87
EI
2642 gen_store(dc, cpu_R[dc->op1], t0, memsize);
2643 tcg_temp_free(t0);
17ac9754 2644
b41f7df0 2645 cris_cc_mask(dc, 0);
8170028d 2646 if (dc->postinc)
17ac9754 2647 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize);
8170028d
TS
2648 return 2;
2649}
2650
2651static unsigned int dec_movem_mr(DisasContext *dc)
2652{
a7812ae4
PB
2653 TCGv_i64 tmp[16];
2654 TCGv tmp32;
31c18d87 2655 TCGv addr;
8170028d 2656 int i;
28de16da 2657 int nr = dc->op2 + 1;
8170028d 2658
d12d51d5
AL
2659 LOG_DIS("movem [$r%u%s, $r%u\n", dc->op1,
2660 dc->postinc ? "+]" : "]", dc->op2);
8170028d 2661
a7812ae4 2662 addr = tcg_temp_new();
28de16da 2663 /* There are probably better ways of doing this. */
30abcfc7 2664 cris_flush_cc_state(dc);
28de16da 2665 for (i = 0; i < (nr >> 1); i++) {
a7812ae4 2666 tmp[i] = tcg_temp_new_i64();
31c18d87 2667 tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
a7812ae4 2668 gen_load64(dc, tmp[i], addr);
28de16da
EI
2669 }
2670 if (nr & 1) {
a7812ae4 2671 tmp32 = tcg_temp_new_i32();
31c18d87 2672 tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
a7812ae4 2673 gen_load(dc, tmp32, addr, 4, 0);
cc53adbc
EI
2674 } else
2675 TCGV_UNUSED(tmp32);
31c18d87 2676 tcg_temp_free(addr);
17ac9754 2677
28de16da
EI
2678 for (i = 0; i < (nr >> 1); i++) {
2679 tcg_gen_trunc_i64_i32(cpu_R[i * 2], tmp[i]);
2680 tcg_gen_shri_i64(tmp[i], tmp[i], 32);
2681 tcg_gen_trunc_i64_i32(cpu_R[i * 2 + 1], tmp[i]);
a7812ae4 2682 tcg_temp_free_i64(tmp[i]);
28de16da
EI
2683 }
2684 if (nr & 1) {
a7812ae4
PB
2685 tcg_gen_mov_tl(cpu_R[dc->op2], tmp32);
2686 tcg_temp_free(tmp32);
17ac9754
EI
2687 }
2688
05ba7d5f
EI
2689 /* writeback the updated pointer value. */
2690 if (dc->postinc)
28de16da 2691 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], nr * 4);
b41f7df0
EI
2692
2693 /* gen_load might want to evaluate the previous insns flags. */
2694 cris_cc_mask(dc, 0);
8170028d
TS
2695 return 2;
2696}
2697
2698static unsigned int dec_movem_rm(DisasContext *dc)
2699{
30abcfc7 2700 TCGv tmp;
31c18d87 2701 TCGv addr;
8170028d
TS
2702 int i;
2703
d12d51d5
AL
2704 LOG_DIS("movem $r%u, [$r%u%s\n", dc->op2, dc->op1,
2705 dc->postinc ? "+]" : "]");
8170028d 2706
30abcfc7
EI
2707 cris_flush_cc_state(dc);
2708
a7812ae4
PB
2709 tmp = tcg_temp_new();
2710 addr = tcg_temp_new();
30abcfc7 2711 tcg_gen_movi_tl(tmp, 4);
31c18d87 2712 tcg_gen_mov_tl(addr, cpu_R[dc->op1]);
8170028d 2713 for (i = 0; i <= dc->op2; i++) {
17ac9754 2714 /* Displace addr. */
8170028d 2715 /* Perform the store. */
31c18d87
EI
2716 gen_store(dc, addr, cpu_R[i], 4);
2717 tcg_gen_add_tl(addr, addr, tmp);
8170028d 2718 }
17ac9754 2719 if (dc->postinc)
31c18d87 2720 tcg_gen_mov_tl(cpu_R[dc->op1], addr);
b41f7df0 2721 cris_cc_mask(dc, 0);
30abcfc7 2722 tcg_temp_free(tmp);
31c18d87 2723 tcg_temp_free(addr);
8170028d
TS
2724 return 2;
2725}
2726
2727static unsigned int dec_move_rm(DisasContext *dc)
2728{
2729 int memsize;
2730
2731 memsize = memsize_zz(dc);
2732
ce24e07b
EI
2733 LOG_DIS("move.%c $r%u, [$r%u]\n",
2734 memsize_char(memsize), dc->op2, dc->op1);
8170028d 2735
8170028d 2736 /* prepare store. */
30abcfc7 2737 cris_flush_cc_state(dc);
17ac9754
EI
2738 gen_store(dc, cpu_R[dc->op1], cpu_R[dc->op2], memsize);
2739
8170028d 2740 if (dc->postinc)
17ac9754 2741 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize);
b41f7df0 2742 cris_cc_mask(dc, 0);
8170028d
TS
2743 return 2;
2744}
2745
8170028d
TS
2746static unsigned int dec_lapcq(DisasContext *dc)
2747{
d12d51d5
AL
2748 LOG_DIS("lapcq %x, $r%u\n",
2749 dc->pc + dc->op1*2, dc->op2);
8170028d 2750 cris_cc_mask(dc, 0);
30abcfc7 2751 tcg_gen_movi_tl(cpu_R[dc->op2], dc->pc + dc->op1 * 2);
8170028d
TS
2752 return 2;
2753}
2754
2755static unsigned int dec_lapc_im(DisasContext *dc)
2756{
2757 unsigned int rd;
2758 int32_t imm;
b41f7df0 2759 int32_t pc;
8170028d
TS
2760
2761 rd = dc->op2;
2762
2763 cris_cc_mask(dc, 0);
2764 imm = ldl_code(dc->pc + 2);
d12d51d5 2765 LOG_DIS("lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2);
b41f7df0
EI
2766
2767 pc = dc->pc;
2768 pc += imm;
46e246c9 2769 tcg_gen_movi_tl(cpu_R[rd], pc);
05ba7d5f 2770 return 6;
8170028d
TS
2771}
2772
2773/* Jump to special reg. */
2774static unsigned int dec_jump_p(DisasContext *dc)
2775{
d12d51d5 2776 LOG_DIS("jump $p%u\n", dc->op2);
b41f7df0 2777
17ac9754
EI
2778 if (dc->op2 == PR_CCS)
2779 cris_evaluate_flags(dc);
31c18d87 2780 t_gen_mov_TN_preg(env_btarget, dc->op2);
b41f7df0 2781 /* rete will often have low bit set to indicate delayslot. */
31c18d87 2782 tcg_gen_andi_tl(env_btarget, env_btarget, ~1);
17ac9754 2783 cris_cc_mask(dc, 0);
2a44f7f1 2784 cris_prepare_jmp(dc, JMP_INDIRECT);
8170028d
TS
2785 return 2;
2786}
2787
2788/* Jump and save. */
2789static unsigned int dec_jas_r(DisasContext *dc)
2790{
d12d51d5 2791 LOG_DIS("jas $r%u, $p%u\n", dc->op1, dc->op2);
8170028d 2792 cris_cc_mask(dc, 0);
b41f7df0
EI
2793 /* Store the return address in Pd. */
2794 tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
2795 if (dc->op2 > 15)
2796 abort();
30abcfc7 2797 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4));
b41f7df0 2798
2a44f7f1 2799 cris_prepare_jmp(dc, JMP_INDIRECT);
8170028d
TS
2800 return 2;
2801}
2802
2803static unsigned int dec_jas_im(DisasContext *dc)
2804{
2805 uint32_t imm;
2806
2807 imm = ldl_code(dc->pc + 2);
2808
d12d51d5 2809 LOG_DIS("jas 0x%x\n", imm);
8170028d 2810 cris_cc_mask(dc, 0);
17ac9754 2811 /* Store the return address in Pd. */
cf1d97f0 2812 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
2a44f7f1
EI
2813
2814 dc->jmp_pc = imm;
2815 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2816 return 6;
2817}
2818
2819static unsigned int dec_jasc_im(DisasContext *dc)
2820{
2821 uint32_t imm;
2822
2823 imm = ldl_code(dc->pc + 2);
2824
d12d51d5 2825 LOG_DIS("jasc 0x%x\n", imm);
8170028d 2826 cris_cc_mask(dc, 0);
17ac9754 2827 /* Store the return address in Pd. */
2a44f7f1
EI
2828 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8 + 4));
2829
2830 dc->jmp_pc = imm;
2831 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2832 return 6;
2833}
2834
2835static unsigned int dec_jasc_r(DisasContext *dc)
2836{
d12d51d5 2837 LOG_DIS("jasc_r $r%u, $p%u\n", dc->op1, dc->op2);
8170028d 2838 cris_cc_mask(dc, 0);
17ac9754 2839 /* Store the return address in Pd. */
2a44f7f1
EI
2840 tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
2841 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4 + 4));
2842 cris_prepare_jmp(dc, JMP_INDIRECT);
8170028d
TS
2843 return 2;
2844}
2845
2846static unsigned int dec_bcc_im(DisasContext *dc)
2847{
2848 int32_t offset;
2849 uint32_t cond = dc->op2;
2850
17ac9754 2851 offset = ldsw_code(dc->pc + 2);
8170028d 2852
d12d51d5 2853 LOG_DIS("b%s %d pc=%x dst=%x\n",
8170028d 2854 cc_name(cond), offset,
d12d51d5 2855 dc->pc, dc->pc + offset);
8170028d
TS
2856
2857 cris_cc_mask(dc, 0);
2858 /* op2 holds the condition-code. */
2859 cris_prepare_cc_branch (dc, offset, cond);
2860 return 4;
2861}
2862
2863static unsigned int dec_bas_im(DisasContext *dc)
2864{
2865 int32_t simm;
2866
2867
2868 simm = ldl_code(dc->pc + 2);
2869
d12d51d5 2870 LOG_DIS("bas 0x%x, $p%u\n", dc->pc + simm, dc->op2);
8170028d 2871 cris_cc_mask(dc, 0);
2a44f7f1
EI
2872 /* Store the return address in Pd. */
2873 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
2874
2875 dc->jmp_pc = dc->pc + simm;
2876 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2877 return 6;
2878}
2879
2880static unsigned int dec_basc_im(DisasContext *dc)
2881{
2882 int32_t simm;
2883 simm = ldl_code(dc->pc + 2);
2884
d12d51d5 2885 LOG_DIS("basc 0x%x, $p%u\n", dc->pc + simm, dc->op2);
8170028d 2886 cris_cc_mask(dc, 0);
2a44f7f1
EI
2887 /* Store the return address in Pd. */
2888 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 12));
2889
2890 dc->jmp_pc = dc->pc + simm;
2891 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2892 return 6;
2893}
2894
2895static unsigned int dec_rfe_etc(DisasContext *dc)
2896{
8170028d
TS
2897 cris_cc_mask(dc, 0);
2898
213fb478
EI
2899 if (dc->op2 == 15) {
2900 t_gen_mov_env_TN(halted, tcg_const_tl(1));
2901 tcg_gen_movi_tl(env_pc, dc->pc + 2);
2902 t_gen_raise_exception(EXCP_HLT);
05ba7d5f 2903 return 2;
213fb478 2904 }
8170028d
TS
2905
2906 switch (dc->op2 & 7) {
2907 case 2:
2908 /* rfe. */
d12d51d5 2909 LOG_DIS("rfe\n");
8170028d 2910 cris_evaluate_flags(dc);
a7812ae4 2911 gen_helper_rfe();
b41f7df0 2912 dc->is_jmp = DISAS_UPDATE;
8170028d
TS
2913 break;
2914 case 5:
2915 /* rfn. */
d12d51d5 2916 LOG_DIS("rfn\n");
a7cfbba0 2917 cris_evaluate_flags(dc);
a7812ae4 2918 gen_helper_rfn();
a7cfbba0 2919 dc->is_jmp = DISAS_UPDATE;
8170028d
TS
2920 break;
2921 case 6:
d12d51d5 2922 LOG_DIS("break %d\n", dc->op1);
a1aebcb8 2923 cris_evaluate_flags (dc);
8170028d 2924 /* break. */
cddffe37 2925 tcg_gen_movi_tl(env_pc, dc->pc + 2);
a1aebcb8 2926
8170028d 2927 /* Breaks start at 16 in the exception vector. */
dceaf394
EI
2928 t_gen_mov_env_TN(trap_vector,
2929 tcg_const_tl(dc->op1 + 16));
2930 t_gen_raise_exception(EXCP_BREAK);
b41f7df0 2931 dc->is_jmp = DISAS_UPDATE;
8170028d
TS
2932 break;
2933 default:
2934 printf ("op2=%x\n", dc->op2);
2935 BUG();
2936 break;
2937
2938 }
8170028d
TS
2939 return 2;
2940}
2941
5d4a534d
EI
2942static unsigned int dec_ftag_fidx_d_m(DisasContext *dc)
2943{
5d4a534d
EI
2944 return 2;
2945}
2946
2947static unsigned int dec_ftag_fidx_i_m(DisasContext *dc)
2948{
5d4a534d
EI
2949 return 2;
2950}
2951
8170028d
TS
2952static unsigned int dec_null(DisasContext *dc)
2953{
2954 printf ("unknown insn pc=%x opc=%x op1=%x op2=%x\n",
2955 dc->pc, dc->opcode, dc->op1, dc->op2);
2956 fflush(NULL);
2957 BUG();
2958 return 2;
2959}
2960
9b32fbf8 2961static struct decoder_info {
8170028d
TS
2962 struct {
2963 uint32_t bits;
2964 uint32_t mask;
2965 };
2966 unsigned int (*dec)(DisasContext *dc);
2967} decinfo[] = {
2968 /* Order matters here. */
2969 {DEC_MOVEQ, dec_moveq},
2970 {DEC_BTSTQ, dec_btstq},
2971 {DEC_CMPQ, dec_cmpq},
2972 {DEC_ADDOQ, dec_addoq},
2973 {DEC_ADDQ, dec_addq},
2974 {DEC_SUBQ, dec_subq},
2975 {DEC_ANDQ, dec_andq},
2976 {DEC_ORQ, dec_orq},
2977 {DEC_ASRQ, dec_asrq},
2978 {DEC_LSLQ, dec_lslq},
2979 {DEC_LSRQ, dec_lsrq},
2980 {DEC_BCCQ, dec_bccq},
2981
2982 {DEC_BCC_IM, dec_bcc_im},
2983 {DEC_JAS_IM, dec_jas_im},
2984 {DEC_JAS_R, dec_jas_r},
2985 {DEC_JASC_IM, dec_jasc_im},
2986 {DEC_JASC_R, dec_jasc_r},
2987 {DEC_BAS_IM, dec_bas_im},
2988 {DEC_BASC_IM, dec_basc_im},
2989 {DEC_JUMP_P, dec_jump_p},
2990 {DEC_LAPC_IM, dec_lapc_im},
2991 {DEC_LAPCQ, dec_lapcq},
2992
2993 {DEC_RFE_ETC, dec_rfe_etc},
2994 {DEC_ADDC_MR, dec_addc_mr},
2995
2996 {DEC_MOVE_MP, dec_move_mp},
2997 {DEC_MOVE_PM, dec_move_pm},
2998 {DEC_MOVEM_MR, dec_movem_mr},
2999 {DEC_MOVEM_RM, dec_movem_rm},
3000 {DEC_MOVE_PR, dec_move_pr},
3001 {DEC_SCC_R, dec_scc_r},
3002 {DEC_SETF, dec_setclrf},
3003 {DEC_CLEARF, dec_setclrf},
3004
3005 {DEC_MOVE_SR, dec_move_sr},
3006 {DEC_MOVE_RP, dec_move_rp},
3007 {DEC_SWAP_R, dec_swap_r},
3008 {DEC_ABS_R, dec_abs_r},
3009 {DEC_LZ_R, dec_lz_r},
3010 {DEC_MOVE_RS, dec_move_rs},
3011 {DEC_BTST_R, dec_btst_r},
3012 {DEC_ADDC_R, dec_addc_r},
3013
3014 {DEC_DSTEP_R, dec_dstep_r},
3015 {DEC_XOR_R, dec_xor_r},
3016 {DEC_MCP_R, dec_mcp_r},
3017 {DEC_CMP_R, dec_cmp_r},
3018
3019 {DEC_ADDI_R, dec_addi_r},
3020 {DEC_ADDI_ACR, dec_addi_acr},
3021
3022 {DEC_ADD_R, dec_add_r},
3023 {DEC_SUB_R, dec_sub_r},
3024
3025 {DEC_ADDU_R, dec_addu_r},
3026 {DEC_ADDS_R, dec_adds_r},
3027 {DEC_SUBU_R, dec_subu_r},
3028 {DEC_SUBS_R, dec_subs_r},
3029 {DEC_LSL_R, dec_lsl_r},
3030
3031 {DEC_AND_R, dec_and_r},
3032 {DEC_OR_R, dec_or_r},
3033 {DEC_BOUND_R, dec_bound_r},
3034 {DEC_ASR_R, dec_asr_r},
3035 {DEC_LSR_R, dec_lsr_r},
3036
3037 {DEC_MOVU_R, dec_movu_r},
3038 {DEC_MOVS_R, dec_movs_r},
3039 {DEC_NEG_R, dec_neg_r},
3040 {DEC_MOVE_R, dec_move_r},
3041
5d4a534d
EI
3042 {DEC_FTAG_FIDX_I_M, dec_ftag_fidx_i_m},
3043 {DEC_FTAG_FIDX_D_M, dec_ftag_fidx_d_m},
8170028d
TS
3044
3045 {DEC_MULS_R, dec_muls_r},
3046 {DEC_MULU_R, dec_mulu_r},
3047
3048 {DEC_ADDU_M, dec_addu_m},
3049 {DEC_ADDS_M, dec_adds_m},
3050 {DEC_SUBU_M, dec_subu_m},
3051 {DEC_SUBS_M, dec_subs_m},
3052
3053 {DEC_CMPU_M, dec_cmpu_m},
3054 {DEC_CMPS_M, dec_cmps_m},
3055 {DEC_MOVU_M, dec_movu_m},
3056 {DEC_MOVS_M, dec_movs_m},
3057
3058 {DEC_CMP_M, dec_cmp_m},
3059 {DEC_ADDO_M, dec_addo_m},
3060 {DEC_BOUND_M, dec_bound_m},
3061 {DEC_ADD_M, dec_add_m},
3062 {DEC_SUB_M, dec_sub_m},
3063 {DEC_AND_M, dec_and_m},
3064 {DEC_OR_M, dec_or_m},
3065 {DEC_MOVE_RM, dec_move_rm},
3066 {DEC_TEST_M, dec_test_m},
3067 {DEC_MOVE_MR, dec_move_mr},
3068
3069 {{0, 0}, dec_null}
3070};
3071
40e9eddd 3072static unsigned int crisv32_decoder(DisasContext *dc)
8170028d
TS
3073{
3074 unsigned int insn_len = 2;
8170028d
TS
3075 int i;
3076
8fec2b8c 3077 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
28de16da
EI
3078 tcg_gen_debug_insn_start(dc->pc);
3079
8170028d 3080 /* Load a halfword onto the instruction register. */
17ac9754 3081 dc->ir = lduw_code(dc->pc);
8170028d
TS
3082
3083 /* Now decode it. */
3084 dc->opcode = EXTRACT_FIELD(dc->ir, 4, 11);
3085 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 3);
3086 dc->op2 = EXTRACT_FIELD(dc->ir, 12, 15);
3087 dc->zsize = EXTRACT_FIELD(dc->ir, 4, 4);
3088 dc->zzsize = EXTRACT_FIELD(dc->ir, 4, 5);
3089 dc->postinc = EXTRACT_FIELD(dc->ir, 10, 10);
3090
3091 /* Large switch for all insns. */
b1503cda 3092 for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
8170028d
TS
3093 if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits)
3094 {
3095 insn_len = decinfo[i].dec(dc);
3096 break;
3097 }
3098 }
3099
dd20fcd0 3100#if !defined(CONFIG_USER_ONLY)
a1aebcb8
EI
3101 /* Single-stepping ? */
3102 if (dc->tb_flags & S_FLAG) {
3103 int l1;
3104
3105 l1 = gen_new_label();
dd20fcd0 3106 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_PR[PR_SPC], dc->pc, l1);
a1aebcb8
EI
3107 /* We treat SPC as a break with an odd trap vector. */
3108 cris_evaluate_flags (dc);
3109 t_gen_mov_env_TN(trap_vector, tcg_const_tl(3));
3110 tcg_gen_movi_tl(env_pc, dc->pc + insn_len);
cddffe37 3111 tcg_gen_movi_tl(cpu_PR[PR_SPC], dc->pc + insn_len);
a1aebcb8
EI
3112 t_gen_raise_exception(EXCP_BREAK);
3113 gen_set_label(l1);
3114 }
3115#endif
8170028d
TS
3116 return insn_len;
3117}
3118
3119static void check_breakpoint(CPUState *env, DisasContext *dc)
3120{
a1d1bb31
AL
3121 CPUBreakpoint *bp;
3122
72cf2d4f
BS
3123 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
3124 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 3125 if (bp->pc == dc->pc) {
8170028d 3126 cris_evaluate_flags (dc);
2a44f7f1 3127 tcg_gen_movi_tl(env_pc, dc->pc);
dceaf394 3128 t_gen_raise_exception(EXCP_DEBUG);
8170028d
TS
3129 dc->is_jmp = DISAS_UPDATE;
3130 }
3131 }
3132 }
3133}
3134
40e9eddd 3135#include "translate_v10.c"
cf1d97f0
EI
3136
3137/*
3138 * Delay slots on QEMU/CRIS.
3139 *
3140 * If an exception hits on a delayslot, the core will let ERP (the Exception
3141 * Return Pointer) point to the branch (the previous) insn and set the lsb to
3142 * to give SW a hint that the exception actually hit on the dslot.
3143 *
3144 * CRIS expects all PC addresses to be 16-bit aligned. The lsb is ignored by
3145 * the core and any jmp to an odd addresses will mask off that lsb. It is
3146 * simply there to let sw know there was an exception on a dslot.
3147 *
3148 * When the software returns from an exception, the branch will re-execute.
3149 * On QEMU care needs to be taken when a branch+delayslot sequence is broken
3150 * and the branch and delayslot dont share pages.
3151 *
3152 * The TB contaning the branch insn will set up env->btarget and evaluate
3153 * env->btaken. When the translation loop exits we will note that the branch
3154 * sequence is broken and let env->dslot be the size of the branch insn (those
3155 * vary in length).
3156 *
3157 * The TB contaning the delayslot will have the PC of its real insn (i.e no lsb
3158 * set). It will also expect to have env->dslot setup with the size of the
3159 * delay slot so that env->pc - env->dslot point to the branch insn. This TB
3160 * will execute the dslot and take the branch, either to btarget or just one
3161 * insn ahead.
3162 *
3163 * When exceptions occur, we check for env->dslot in do_interrupt to detect
3164 * broken branch sequences and setup $erp accordingly (i.e let it point to the
3165 * branch and set lsb). Then env->dslot gets cleared so that the exception
3166 * handler can enter. When returning from exceptions (jump $erp) the lsb gets
3167 * masked off and we will reexecute the branch insn.
3168 *
3169 */
3170
8170028d 3171/* generate intermediate code for basic block 'tb'. */
2cfc5f17 3172static void
8170028d
TS
3173gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
3174 int search_pc)
3175{
3176 uint16_t *gen_opc_end;
3177 uint32_t pc_start;
40e9eddd 3178 unsigned int insn_len, orig_flags;
8170028d 3179 int j, lj;
cf1d97f0 3180 struct DisasContext ctx;
8170028d
TS
3181 struct DisasContext *dc = &ctx;
3182 uint32_t next_page_start;
2a44f7f1 3183 target_ulong npc;
2e70f6ef
PB
3184 int num_insns;
3185 int max_insns;
8170028d 3186
93fcfe39 3187 qemu_log_try_set_file(stderr);
a825e703 3188
40e9eddd
EI
3189 if (env->pregs[PR_VR] == 32)
3190 dc->decoder = crisv32_decoder;
3191 else
3192 dc->decoder = crisv10_decoder;
3193
73e51723
EI
3194 /* Odd PC indicates that branch is rexecuting due to exception in the
3195 * delayslot, like in real hw.
73e51723
EI
3196 */
3197 pc_start = tb->pc & ~1;
8170028d
TS
3198 dc->env = env;
3199 dc->tb = tb;
3200
8170028d 3201 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8170028d
TS
3202
3203 dc->is_jmp = DISAS_NEXT;
b41f7df0 3204 dc->ppc = pc_start;
8170028d
TS
3205 dc->pc = pc_start;
3206 dc->singlestep_enabled = env->singlestep_enabled;
30abcfc7
EI
3207 dc->flags_uptodate = 1;
3208 dc->flagx_known = 1;
3209 dc->flags_x = tb->flags & X_FLAG;
3210 dc->cc_x_uptodate = 0;
b41f7df0 3211 dc->cc_mask = 0;
cf1d97f0 3212 dc->update_cc = 0;
40e9eddd
EI
3213 dc->clear_prefix = 0;
3214 dc->clear_locked_irq = 1;
30abcfc7 3215
b41f7df0 3216 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
30abcfc7 3217 dc->cc_size_uptodate = -1;
b41f7df0 3218
cf1d97f0 3219 /* Decode TB flags. */
40e9eddd
EI
3220 orig_flags = dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG \
3221 | X_FLAG | PFIX_FLAG);
cf1d97f0 3222 dc->delayed_branch = !!(tb->flags & 7);
2a44f7f1
EI
3223 if (dc->delayed_branch)
3224 dc->jmp = JMP_INDIRECT;
3225 else
3226 dc->jmp = JMP_NOJMP;
3227
3228 dc->cpustate_changed = 0;
b41f7df0 3229
8fec2b8c 3230 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39 3231 qemu_log(
d297f464 3232 "srch=%d pc=%x %x flg=%llx bt=%x ds=%u ccs=%x\n"
30abcfc7 3233 "pid=%x usp=%x\n"
b41f7df0
EI
3234 "%x.%x.%x.%x\n"
3235 "%x.%x.%x.%x\n"
3236 "%x.%x.%x.%x\n"
3237 "%x.%x.%x.%x\n",
d297f464
EI
3238 search_pc, dc->pc, dc->ppc,
3239 (unsigned long long)tb->flags,
3240 env->btarget, (unsigned)tb->flags & 7,
cf1d97f0 3241 env->pregs[PR_CCS],
b41f7df0
EI
3242 env->pregs[PR_PID], env->pregs[PR_USP],
3243 env->regs[0], env->regs[1], env->regs[2], env->regs[3],
3244 env->regs[4], env->regs[5], env->regs[6], env->regs[7],
3245 env->regs[8], env->regs[9],
3246 env->regs[10], env->regs[11],
3247 env->regs[12], env->regs[13],
3248 env->regs[14], env->regs[15]);
93fcfe39
AL
3249 qemu_log("--------------\n");
3250 qemu_log("IN: %s\n", lookup_symbol(pc_start));
b41f7df0 3251 }
3157a0a9 3252
8170028d
TS
3253 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
3254 lj = -1;
2e70f6ef
PB
3255 num_insns = 0;
3256 max_insns = tb->cflags & CF_COUNT_MASK;
3257 if (max_insns == 0)
3258 max_insns = CF_COUNT_MASK;
3259
3260 gen_icount_start();
8170028d
TS
3261 do
3262 {
3263 check_breakpoint(env, dc);
8170028d
TS
3264
3265 if (search_pc) {
3266 j = gen_opc_ptr - gen_opc_buf;
3267 if (lj < j) {
3268 lj++;
3269 while (lj < j)
3270 gen_opc_instr_start[lj++] = 0;
3271 }
cf1d97f0 3272 if (dc->delayed_branch == 1)
b41f7df0 3273 gen_opc_pc[lj] = dc->ppc | 1;
cf1d97f0 3274 else
b41f7df0 3275 gen_opc_pc[lj] = dc->pc;
cf1d97f0 3276 gen_opc_instr_start[lj] = 1;
2e70f6ef 3277 gen_opc_icount[lj] = num_insns;
cf1d97f0
EI
3278 }
3279
3280 /* Pretty disas. */
d12d51d5 3281 LOG_DIS("%8.8x:\t", dc->pc);
8170028d 3282
2e70f6ef
PB
3283 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
3284 gen_io_start();
b41f7df0 3285 dc->clear_x = 1;
28de16da 3286
40e9eddd 3287 insn_len = dc->decoder(dc);
b41f7df0 3288 dc->ppc = dc->pc;
8170028d 3289 dc->pc += insn_len;
b41f7df0
EI
3290 if (dc->clear_x)
3291 cris_clear_x_flag(dc);
8170028d 3292
2e70f6ef 3293 num_insns++;
8170028d 3294 /* Check for delayed branches here. If we do it before
bf20dc07 3295 actually generating any host code, the simulator will just
8170028d
TS
3296 loop doing nothing for on this program location. */
3297 if (dc->delayed_branch) {
3298 dc->delayed_branch--;
3299 if (dc->delayed_branch == 0)
3300 {
2a44f7f1
EI
3301 if (tb->flags & 7)
3302 t_gen_mov_env_TN(dslot,
3303 tcg_const_tl(0));
3304 if (dc->jmp == JMP_DIRECT) {
3305 dc->is_jmp = DISAS_NEXT;
3306 } else {
3307 t_gen_cc_jmp(env_btarget,
3308 tcg_const_tl(dc->pc));
3309 dc->is_jmp = DISAS_JUMP;
3310 }
3311 break;
8170028d
TS
3312 }
3313 }
3314
73e51723
EI
3315 /* If we are rexecuting a branch due to exceptions on
3316 delay slots dont break. */
3317 if (!(tb->pc & 1) && env->singlestep_enabled)
8170028d 3318 break;
fb48f71b
EI
3319 } while (!dc->is_jmp && !dc->cpustate_changed
3320 && gen_opc_ptr < gen_opc_end
1b530a6d 3321 && !singlestep
2e70f6ef
PB
3322 && (dc->pc < next_page_start)
3323 && num_insns < max_insns);
b41f7df0 3324
40e9eddd
EI
3325 if (dc->tb_flags != orig_flags) {
3326 dc->cpustate_changed = 1;
3327 }
3328
3329 if (dc->clear_locked_irq)
3330 t_gen_mov_env_TN(locked_irq, tcg_const_tl(0));
3331
2a44f7f1
EI
3332 npc = dc->pc;
3333 if (dc->jmp == JMP_DIRECT && !dc->delayed_branch)
3334 npc = dc->jmp_pc;
3335
2e70f6ef
PB
3336 if (tb->cflags & CF_LAST_IO)
3337 gen_io_end();
2a44f7f1
EI
3338 /* Force an update if the per-tb cpu state has changed. */
3339 if (dc->is_jmp == DISAS_NEXT
3340 && (dc->cpustate_changed || !dc->flagx_known
3341 || (dc->flags_x != (tb->flags & X_FLAG)))) {
3342 dc->is_jmp = DISAS_UPDATE;
3343 tcg_gen_movi_tl(env_pc, npc);
3344 }
cf1d97f0 3345 /* Broken branch+delayslot sequence. */
b41f7df0 3346 if (dc->delayed_branch == 1) {
cf1d97f0
EI
3347 /* Set env->dslot to the size of the branch insn. */
3348 t_gen_mov_env_TN(dslot, tcg_const_tl(dc->pc - dc->ppc));
2a44f7f1 3349 cris_store_direct_jmp(dc);
8170028d
TS
3350 }
3351
3352 cris_evaluate_flags (dc);
2a44f7f1 3353
551bd27f 3354 if (unlikely(env->singlestep_enabled)) {
89cc7382
EI
3355 if (dc->is_jmp == DISAS_NEXT)
3356 tcg_gen_movi_tl(env_pc, npc);
dceaf394 3357 t_gen_raise_exception(EXCP_DEBUG);
8170028d
TS
3358 } else {
3359 switch(dc->is_jmp) {
3360 case DISAS_NEXT:
2a44f7f1 3361 gen_goto_tb(dc, 1, npc);
8170028d
TS
3362 break;
3363 default:
3364 case DISAS_JUMP:
3365 case DISAS_UPDATE:
3366 /* indicate that the hash table must be used
3367 to find the next TB */
57fec1fe 3368 tcg_gen_exit_tb(0);
8170028d 3369 break;
4f400ab5 3370 case DISAS_SWI:
8170028d
TS
3371 case DISAS_TB_JUMP:
3372 /* nothing more to generate */
3373 break;
3374 }
3375 }
2e70f6ef 3376 gen_icount_end(tb, num_insns);
8170028d
TS
3377 *gen_opc_ptr = INDEX_op_end;
3378 if (search_pc) {
3379 j = gen_opc_ptr - gen_opc_buf;
3380 lj++;
3381 while (lj <= j)
3382 gen_opc_instr_start[lj++] = 0;
3383 } else {
3384 tb->size = dc->pc - pc_start;
2e70f6ef 3385 tb->icount = num_insns;
8170028d
TS
3386 }
3387
3388#ifdef DEBUG_DISAS
a1aebcb8 3389#if !DISAS_CRIS
8fec2b8c 3390 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
40e9eddd
EI
3391 log_target_disas(pc_start, dc->pc - pc_start,
3392 dc->env->pregs[PR_VR]);
93fcfe39 3393 qemu_log("\nisize=%d osize=%zd\n",
b41f7df0 3394 dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
8170028d
TS
3395 }
3396#endif
a1aebcb8 3397#endif
8170028d
TS
3398}
3399
2cfc5f17 3400void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8170028d 3401{
2cfc5f17 3402 gen_intermediate_code_internal(env, tb, 0);
8170028d
TS
3403}
3404
2cfc5f17 3405void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8170028d 3406{
2cfc5f17 3407 gen_intermediate_code_internal(env, tb, 1);
8170028d
TS
3408}
3409
3410void cpu_dump_state (CPUState *env, FILE *f,
3411 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
3412 int flags)
3413{
3414 int i;
3415 uint32_t srs;
3416
3417 if (!env || !f)
3418 return;
3419
3420 cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
30abcfc7 3421 "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n",
9004627f 3422 env->pc, env->pregs[PR_CCS], env->btaken, env->btarget,
8170028d 3423 env->cc_op,
30abcfc7
EI
3424 env->cc_src, env->cc_dest, env->cc_result, env->cc_mask);
3425
8170028d
TS
3426
3427 for (i = 0; i < 16; i++) {
416c6060 3428 cpu_fprintf(f, "%s=%8.8x ",regnames[i], env->regs[i]);
8170028d
TS
3429 if ((i + 1) % 4 == 0)
3430 cpu_fprintf(f, "\n");
3431 }
3432 cpu_fprintf(f, "\nspecial regs:\n");
3433 for (i = 0; i < 16; i++) {
416c6060 3434 cpu_fprintf(f, "%s=%8.8x ", pregnames[i], env->pregs[i]);
8170028d
TS
3435 if ((i + 1) % 4 == 0)
3436 cpu_fprintf(f, "\n");
3437 }
9004627f 3438 srs = env->pregs[PR_SRS];
b41f7df0 3439 cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
8170028d
TS
3440 if (srs < 256) {
3441 for (i = 0; i < 16; i++) {
3442 cpu_fprintf(f, "s%2.2d=%8.8x ",
3443 i, env->sregs[srs][i]);
3444 if ((i + 1) % 4 == 0)
3445 cpu_fprintf(f, "\n");
3446 }
3447 }
3448 cpu_fprintf(f, "\n\n");
3449
3450}
3451
40e9eddd
EI
3452struct
3453{
3454 uint32_t vr;
3455 const char *name;
3456} cris_cores[] = {
3457 {8, "crisv8"},
3458 {9, "crisv9"},
3459 {10, "crisv10"},
3460 {11, "crisv11"},
3461 {32, "crisv32"},
3462};
3463
3464void cris_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
3465{
3466 unsigned int i;
3467
3468 (*cpu_fprintf)(f, "Available CPUs:\n");
3469 for (i = 0; i < ARRAY_SIZE(cris_cores); i++) {
3470 (*cpu_fprintf)(f, " %s\n", cris_cores[i].name);
3471 }
3472}
3473
3474static uint32_t vr_by_name(const char *name)
3475{
3476 unsigned int i;
3477 for (i = 0; i < ARRAY_SIZE(cris_cores); i++) {
3478 if (strcmp(name, cris_cores[i].name) == 0) {
3479 return cris_cores[i].vr;
3480 }
3481 }
3482 return 32;
3483}
3484
aaed909a 3485CPUCRISState *cpu_cris_init (const char *cpu_model)
8170028d
TS
3486{
3487 CPUCRISState *env;
a7cfbba0 3488 static int tcg_initialized = 0;
a825e703 3489 int i;
8170028d
TS
3490
3491 env = qemu_mallocz(sizeof(CPUCRISState));
a7cfbba0 3492
40e9eddd 3493 env->pregs[PR_VR] = vr_by_name(cpu_model);
8170028d 3494 cpu_exec_init(env);
a7cfbba0 3495 cpu_reset(env);
0bf46a40 3496 qemu_init_vcpu(env);
a7cfbba0
EI
3497
3498 if (tcg_initialized)
3499 return env;
3500
3501 tcg_initialized = 1;
05ba7d5f 3502
40e9eddd
EI
3503#define GEN_HELPER 2
3504#include "helper.h"
3505
3506 if (env->pregs[PR_VR] < 32) {
3507 cpu_crisv10_init(env);
3508 return env;
3509 }
3510
3511
a7812ae4
PB
3512 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
3513 cc_x = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3514 offsetof(CPUState, cc_x), "cc_x");
a7812ae4 3515 cc_src = tcg_global_mem_new(TCG_AREG0,
a825e703 3516 offsetof(CPUState, cc_src), "cc_src");
a7812ae4 3517 cc_dest = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3518 offsetof(CPUState, cc_dest),
a825e703 3519 "cc_dest");
a7812ae4 3520 cc_result = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3521 offsetof(CPUState, cc_result),
a825e703 3522 "cc_result");
a7812ae4 3523 cc_op = tcg_global_mem_new(TCG_AREG0,
a825e703 3524 offsetof(CPUState, cc_op), "cc_op");
a7812ae4 3525 cc_size = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3526 offsetof(CPUState, cc_size),
a825e703 3527 "cc_size");
a7812ae4 3528 cc_mask = tcg_global_mem_new(TCG_AREG0,
a825e703
EI
3529 offsetof(CPUState, cc_mask),
3530 "cc_mask");
3531
a7812ae4 3532 env_pc = tcg_global_mem_new(TCG_AREG0,
30abcfc7
EI
3533 offsetof(CPUState, pc),
3534 "pc");
a7812ae4 3535 env_btarget = tcg_global_mem_new(TCG_AREG0,
30abcfc7
EI
3536 offsetof(CPUState, btarget),
3537 "btarget");
a7812ae4 3538 env_btaken = tcg_global_mem_new(TCG_AREG0,
2a44f7f1
EI
3539 offsetof(CPUState, btaken),
3540 "btaken");
a825e703 3541 for (i = 0; i < 16; i++) {
a7812ae4 3542 cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3543 offsetof(CPUState, regs[i]),
a825e703
EI
3544 regnames[i]);
3545 }
3546 for (i = 0; i < 16; i++) {
a7812ae4 3547 cpu_PR[i] = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3548 offsetof(CPUState, pregs[i]),
a825e703
EI
3549 pregnames[i]);
3550 }
3551
8170028d
TS
3552 return env;
3553}
3554
3555void cpu_reset (CPUCRISState *env)
3556{
40e9eddd
EI
3557 uint32_t vr;
3558
eca1bdf4
AL
3559 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
3560 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
3561 log_cpu_state(env, 0);
3562 }
3563
40e9eddd 3564 vr = env->pregs[PR_VR];
8170028d 3565 memset(env, 0, offsetof(CPUCRISState, breakpoints));
40e9eddd 3566 env->pregs[PR_VR] = vr;
8170028d 3567 tlb_flush(env, 1);
b41f7df0
EI
3568
3569#if defined(CONFIG_USER_ONLY)
3570 /* start in user mode with interrupts enabled. */
40e9eddd 3571 env->pregs[PR_CCS] |= U_FLAG | I_FLAG | P_FLAG;
b41f7df0 3572#else
52819664 3573 cris_mmu_init(env);
b41f7df0
EI
3574 env->pregs[PR_CCS] = 0;
3575#endif
8170028d 3576}
d2856f1a
AJ
3577
3578void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
3579 unsigned long searched_pc, int pc_pos, void *puc)
3580{
17ac9754 3581 env->pc = gen_opc_pc[pc_pos];
d2856f1a 3582}