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