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