]> git.proxmox.com Git - mirror_qemu.git/blame - target-cris/translate.c
tcg/i386: optimize and $0xff(ff), reg
[mirror_qemu.git] / target-cris / translate.c
CommitLineData
8170028d
TS
1/*
2 * CRIS emulation for qemu: main translation routines.
3 *
05ba7d5f 4 * Copyright (c) 2008 AXIS Communications AB
8170028d
TS
5 * Written by Edgar E. Iglesias.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
8167ee88 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
8170028d
TS
19 */
20
b41f7df0
EI
21/*
22 * FIXME:
cf1d97f0 23 * The condition code translation is in need of attention.
b41f7df0
EI
24 */
25
8170028d
TS
26#include <stdarg.h>
27#include <stdlib.h>
28#include <stdio.h>
29#include <string.h>
30#include <inttypes.h>
8170028d
TS
31
32#include "cpu.h"
33#include "exec-all.h"
34#include "disas.h"
57fec1fe 35#include "tcg-op.h"
05ba7d5f 36#include "helper.h"
52819664 37#include "mmu.h"
8170028d 38#include "crisv32-decode.h"
ca10f867 39#include "qemu-common.h"
8170028d 40
a7812ae4
PB
41#define GEN_HELPER 1
42#include "helper.h"
43
8170028d
TS
44#define DISAS_CRIS 0
45#if DISAS_CRIS
93fcfe39 46# define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
8170028d 47#else
d12d51d5 48# define LOG_DIS(...) do { } while (0)
8170028d
TS
49#endif
50
b41f7df0 51#define D(x)
8170028d
TS
52#define BUG() (gen_BUG(dc, __FILE__, __LINE__))
53#define BUG_ON(x) ({if (x) BUG();})
54
4f400ab5
EI
55#define DISAS_SWI 5
56
8170028d
TS
57/* Used by the decoder. */
58#define EXTRACT_FIELD(src, start, end) \
59 (((src) >> start) & ((1 << (end - start + 1)) - 1))
60
61#define CC_MASK_NZ 0xc
62#define CC_MASK_NZV 0xe
63#define CC_MASK_NZVC 0xf
64#define CC_MASK_RNZV 0x10e
65
a7812ae4 66static TCGv_ptr cpu_env;
9b32fbf8
EI
67static TCGv cpu_R[16];
68static TCGv cpu_PR[16];
69static TCGv cc_x;
70static TCGv cc_src;
71static TCGv cc_dest;
72static TCGv cc_result;
73static TCGv cc_op;
74static TCGv cc_size;
75static TCGv cc_mask;
76
77static TCGv env_btaken;
78static TCGv env_btarget;
79static TCGv env_pc;
b41f7df0 80
2e70f6ef
PB
81#include "gen-icount.h"
82
8170028d
TS
83/* This is the state at translation time. */
84typedef struct DisasContext {
85 CPUState *env;
b41f7df0 86 target_ulong pc, ppc;
8170028d
TS
87
88 /* Decoder. */
89 uint32_t ir;
90 uint32_t opcode;
91 unsigned int op1;
92 unsigned int op2;
93 unsigned int zsize, zzsize;
94 unsigned int mode;
95 unsigned int postinc;
96
8170028d
TS
97 int update_cc;
98 int cc_op;
99 int cc_size;
100 uint32_t cc_mask;
30abcfc7
EI
101
102 int cc_size_uptodate; /* -1 invalid or last written value. */
103
104 int cc_x_uptodate; /* 1 - ccs, 2 - known | X_FLAG. 0 not uptodate. */
105 int flags_uptodate; /* Wether or not $ccs is uptodate. */
106 int flagx_known; /* Wether or not flags_x has the x flag known at
107 translation time. */
8170028d 108 int flags_x;
8170028d 109
30abcfc7 110 int clear_x; /* Clear x after this insn? */
2a44f7f1
EI
111 int cpustate_changed;
112 unsigned int tb_flags; /* tb dependent flags. */
8170028d 113 int is_jmp;
8170028d 114
2a44f7f1
EI
115#define JMP_NOJMP 0
116#define JMP_DIRECT 1
117#define JMP_INDIRECT 2
118 int jmp; /* 0=nojmp, 1=direct, 2=indirect. */
119 uint32_t jmp_pc;
120
8170028d 121 int delayed_branch;
8170028d
TS
122
123 struct TranslationBlock *tb;
124 int singlestep_enabled;
125} DisasContext;
126
7ccfb2eb 127static void gen_BUG(DisasContext *dc, const char *file, int line)
8170028d
TS
128{
129 printf ("BUG: pc=%x %s %d\n", dc->pc, file, line);
93fcfe39 130 qemu_log("BUG: pc=%x %s %d\n", dc->pc, file, line);
cf1d97f0 131 cpu_abort(dc->env, "%s:%d\n", file, line);
8170028d
TS
132}
133
9b32fbf8 134static const char *regnames[] =
a825e703
EI
135{
136 "$r0", "$r1", "$r2", "$r3",
137 "$r4", "$r5", "$r6", "$r7",
138 "$r8", "$r9", "$r10", "$r11",
139 "$r12", "$r13", "$sp", "$acr",
140};
9b32fbf8 141static const char *pregnames[] =
a825e703
EI
142{
143 "$bz", "$vr", "$pid", "$srs",
144 "$wz", "$exs", "$eda", "$mof",
145 "$dz", "$ebp", "$erp", "$srp",
146 "$nrp", "$ccs", "$usp", "$spc",
147};
148
05ba7d5f 149/* We need this table to handle preg-moves with implicit width. */
9b32fbf8 150static int preg_sizes[] = {
05ba7d5f
EI
151 1, /* bz. */
152 1, /* vr. */
153 4, /* pid. */
154 1, /* srs. */
155 2, /* wz. */
156 4, 4, 4,
157 4, 4, 4, 4,
158 4, 4, 4, 4,
159};
160
161#define t_gen_mov_TN_env(tn, member) \
3157a0a9 162 _t_gen_mov_TN_env((tn), offsetof(CPUState, member))
05ba7d5f 163#define t_gen_mov_env_TN(member, tn) \
3157a0a9 164 _t_gen_mov_env_TN(offsetof(CPUState, member), (tn))
05ba7d5f 165
b41f7df0
EI
166static inline void t_gen_mov_TN_reg(TCGv tn, int r)
167{
168 if (r < 0 || r > 15)
169 fprintf(stderr, "wrong register read $r%d\n", r);
170 tcg_gen_mov_tl(tn, cpu_R[r]);
171}
172static inline void t_gen_mov_reg_TN(int r, TCGv tn)
173{
174 if (r < 0 || r > 15)
175 fprintf(stderr, "wrong register write $r%d\n", r);
176 tcg_gen_mov_tl(cpu_R[r], tn);
177}
05ba7d5f
EI
178
179static inline void _t_gen_mov_TN_env(TCGv tn, int offset)
180{
b41f7df0
EI
181 if (offset > sizeof (CPUState))
182 fprintf(stderr, "wrong load from env from off=%d\n", offset);
05ba7d5f
EI
183 tcg_gen_ld_tl(tn, cpu_env, offset);
184}
185static inline void _t_gen_mov_env_TN(int offset, TCGv tn)
186{
b41f7df0
EI
187 if (offset > sizeof (CPUState))
188 fprintf(stderr, "wrong store to env at off=%d\n", offset);
05ba7d5f
EI
189 tcg_gen_st_tl(tn, cpu_env, offset);
190}
191
192static inline void t_gen_mov_TN_preg(TCGv tn, int r)
193{
b41f7df0
EI
194 if (r < 0 || r > 15)
195 fprintf(stderr, "wrong register read $p%d\n", r);
05ba7d5f 196 if (r == PR_BZ || r == PR_WZ || r == PR_DZ)
3157a0a9 197 tcg_gen_mov_tl(tn, tcg_const_tl(0));
05ba7d5f 198 else if (r == PR_VR)
3157a0a9 199 tcg_gen_mov_tl(tn, tcg_const_tl(32));
b41f7df0
EI
200 else if (r == PR_EDA) {
201 printf("read from EDA!\n");
202 tcg_gen_mov_tl(tn, cpu_PR[r]);
203 }
05ba7d5f 204 else
a825e703 205 tcg_gen_mov_tl(tn, cpu_PR[r]);
05ba7d5f 206}
cf1d97f0 207static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn)
05ba7d5f 208{
b41f7df0
EI
209 if (r < 0 || r > 15)
210 fprintf(stderr, "wrong register write $p%d\n", r);
05ba7d5f
EI
211 if (r == PR_BZ || r == PR_WZ || r == PR_DZ)
212 return;
b41f7df0
EI
213 else if (r == PR_SRS)
214 tcg_gen_andi_tl(cpu_PR[r], tn, 3);
215 else {
2a44f7f1 216 if (r == PR_PID)
a7812ae4 217 gen_helper_tlb_flush_pid(tn);
a1aebcb8 218 if (dc->tb_flags & S_FLAG && r == PR_SPC)
a7812ae4 219 gen_helper_spc_write(tn);
2a44f7f1
EI
220 else if (r == PR_CCS)
221 dc->cpustate_changed = 1;
28de16da 222 tcg_gen_mov_tl(cpu_PR[r], tn);
b41f7df0 223 }
05ba7d5f
EI
224}
225
dceaf394 226static inline void t_gen_raise_exception(uint32_t index)
05ba7d5f 227{
a7812ae4
PB
228 TCGv_i32 tmp = tcg_const_i32(index);
229 gen_helper_raise_exception(tmp);
230 tcg_temp_free_i32(tmp);
05ba7d5f
EI
231}
232
233static void t_gen_lsl(TCGv d, TCGv a, TCGv b)
234{
7dcfb089 235 TCGv t0, t_31;
05ba7d5f 236
a7812ae4 237 t0 = tcg_temp_new();
44696296 238 t_31 = tcg_const_tl(31);
05ba7d5f 239 tcg_gen_shl_tl(d, a, b);
7dcfb089 240
7dcfb089
EI
241 tcg_gen_sub_tl(t0, t_31, b);
242 tcg_gen_sar_tl(t0, t0, t_31);
243 tcg_gen_and_tl(t0, t0, d);
244 tcg_gen_xor_tl(d, d, t0);
245 tcg_temp_free(t0);
246 tcg_temp_free(t_31);
05ba7d5f
EI
247}
248
249static void t_gen_lsr(TCGv d, TCGv a, TCGv b)
250{
7dcfb089 251 TCGv t0, t_31;
05ba7d5f 252
a7812ae4
PB
253 t0 = tcg_temp_new();
254 t_31 = tcg_temp_new();
05ba7d5f 255 tcg_gen_shr_tl(d, a, b);
7dcfb089
EI
256
257 tcg_gen_movi_tl(t_31, 31);
258 tcg_gen_sub_tl(t0, t_31, b);
259 tcg_gen_sar_tl(t0, t0, t_31);
260 tcg_gen_and_tl(t0, t0, d);
261 tcg_gen_xor_tl(d, d, t0);
262 tcg_temp_free(t0);
263 tcg_temp_free(t_31);
05ba7d5f
EI
264}
265
266static void t_gen_asr(TCGv d, TCGv a, TCGv b)
267{
7dcfb089 268 TCGv t0, t_31;
05ba7d5f 269
a7812ae4
PB
270 t0 = tcg_temp_new();
271 t_31 = tcg_temp_new();
05ba7d5f 272 tcg_gen_sar_tl(d, a, b);
7dcfb089
EI
273
274 tcg_gen_movi_tl(t_31, 31);
275 tcg_gen_sub_tl(t0, t_31, b);
276 tcg_gen_sar_tl(t0, t0, t_31);
277 tcg_gen_or_tl(d, d, t0);
278 tcg_temp_free(t0);
279 tcg_temp_free(t_31);
05ba7d5f
EI
280}
281
3157a0a9
EI
282/* 64-bit signed mul, lower result in d and upper in d2. */
283static void t_gen_muls(TCGv d, TCGv d2, TCGv a, TCGv b)
284{
a7812ae4 285 TCGv_i64 t0, t1;
3157a0a9 286
a7812ae4
PB
287 t0 = tcg_temp_new_i64();
288 t1 = tcg_temp_new_i64();
3157a0a9 289
a7812ae4
PB
290 tcg_gen_ext_i32_i64(t0, a);
291 tcg_gen_ext_i32_i64(t1, b);
3157a0a9
EI
292 tcg_gen_mul_i64(t0, t0, t1);
293
294 tcg_gen_trunc_i64_i32(d, t0);
295 tcg_gen_shri_i64(t0, t0, 32);
296 tcg_gen_trunc_i64_i32(d2, t0);
b41f7df0 297
a7812ae4
PB
298 tcg_temp_free_i64(t0);
299 tcg_temp_free_i64(t1);
3157a0a9
EI
300}
301
302/* 64-bit unsigned muls, lower result in d and upper in d2. */
303static void t_gen_mulu(TCGv d, TCGv d2, TCGv a, TCGv b)
304{
a7812ae4 305 TCGv_i64 t0, t1;
3157a0a9 306
a7812ae4
PB
307 t0 = tcg_temp_new_i64();
308 t1 = tcg_temp_new_i64();
3157a0a9
EI
309
310 tcg_gen_extu_i32_i64(t0, a);
311 tcg_gen_extu_i32_i64(t1, b);
312 tcg_gen_mul_i64(t0, t0, t1);
313
314 tcg_gen_trunc_i64_i32(d, t0);
315 tcg_gen_shri_i64(t0, t0, 32);
316 tcg_gen_trunc_i64_i32(d2, t0);
b41f7df0 317
a7812ae4
PB
318 tcg_temp_free_i64(t0);
319 tcg_temp_free_i64(t1);
3157a0a9
EI
320}
321
30abcfc7 322static void t_gen_cris_dstep(TCGv d, TCGv a, TCGv b)
aae6b32a
EI
323{
324 int l1;
325
326 l1 = gen_new_label();
327
328 /*
329 * d <<= 1
330 * if (d >= s)
331 * d -= s;
332 */
30abcfc7
EI
333 tcg_gen_shli_tl(d, a, 1);
334 tcg_gen_brcond_tl(TCG_COND_LTU, d, b, l1);
335 tcg_gen_sub_tl(d, d, b);
aae6b32a
EI
336 gen_set_label(l1);
337}
338
3157a0a9
EI
339/* Extended arithmetics on CRIS. */
340static inline void t_gen_add_flag(TCGv d, int flag)
341{
342 TCGv c;
343
a7812ae4 344 c = tcg_temp_new();
3157a0a9
EI
345 t_gen_mov_TN_preg(c, PR_CCS);
346 /* Propagate carry into d. */
347 tcg_gen_andi_tl(c, c, 1 << flag);
348 if (flag)
349 tcg_gen_shri_tl(c, c, flag);
350 tcg_gen_add_tl(d, d, c);
30abcfc7 351 tcg_temp_free(c);
3157a0a9
EI
352}
353
30abcfc7 354static inline void t_gen_addx_carry(DisasContext *dc, TCGv d)
3157a0a9 355{
30abcfc7
EI
356 if (dc->flagx_known) {
357 if (dc->flags_x) {
358 TCGv c;
359
a7812ae4 360 c = tcg_temp_new();
30abcfc7
EI
361 t_gen_mov_TN_preg(c, PR_CCS);
362 /* C flag is already at bit 0. */
363 tcg_gen_andi_tl(c, c, C_FLAG);
364 tcg_gen_add_tl(d, d, c);
365 tcg_temp_free(c);
366 }
367 } else {
368 TCGv x, c;
3157a0a9 369
a7812ae4
PB
370 x = tcg_temp_new();
371 c = tcg_temp_new();
30abcfc7
EI
372 t_gen_mov_TN_preg(x, PR_CCS);
373 tcg_gen_mov_tl(c, x);
3157a0a9 374
30abcfc7
EI
375 /* Propagate carry into d if X is set. Branch free. */
376 tcg_gen_andi_tl(c, c, C_FLAG);
377 tcg_gen_andi_tl(x, x, X_FLAG);
378 tcg_gen_shri_tl(x, x, 4);
3157a0a9 379
30abcfc7
EI
380 tcg_gen_and_tl(x, x, c);
381 tcg_gen_add_tl(d, d, x);
382 tcg_temp_free(x);
383 tcg_temp_free(c);
384 }
3157a0a9
EI
385}
386
a39f8f3a 387static inline void t_gen_subx_carry(DisasContext *dc, TCGv d)
3157a0a9 388{
30abcfc7
EI
389 if (dc->flagx_known) {
390 if (dc->flags_x) {
391 TCGv c;
392
a7812ae4 393 c = tcg_temp_new();
30abcfc7
EI
394 t_gen_mov_TN_preg(c, PR_CCS);
395 /* C flag is already at bit 0. */
396 tcg_gen_andi_tl(c, c, C_FLAG);
397 tcg_gen_sub_tl(d, d, c);
398 tcg_temp_free(c);
399 }
400 } else {
a39f8f3a
EI
401 TCGv x, c;
402
a7812ae4
PB
403 x = tcg_temp_new();
404 c = tcg_temp_new();
a39f8f3a
EI
405 t_gen_mov_TN_preg(x, PR_CCS);
406 tcg_gen_mov_tl(c, x);
407
408 /* Propagate carry into d if X is set. Branch free. */
409 tcg_gen_andi_tl(c, c, C_FLAG);
410 tcg_gen_andi_tl(x, x, X_FLAG);
411 tcg_gen_shri_tl(x, x, 4);
412
413 tcg_gen_and_tl(x, x, c);
414 tcg_gen_sub_tl(d, d, x);
30abcfc7
EI
415 tcg_temp_free(x);
416 tcg_temp_free(c);
a39f8f3a 417 }
3157a0a9
EI
418}
419
420/* Swap the two bytes within each half word of the s operand.
421 T0 = ((T0 << 8) & 0xff00ff00) | ((T0 >> 8) & 0x00ff00ff) */
422static inline void t_gen_swapb(TCGv d, TCGv s)
423{
424 TCGv t, org_s;
425
a7812ae4
PB
426 t = tcg_temp_new();
427 org_s = tcg_temp_new();
3157a0a9
EI
428
429 /* d and s may refer to the same object. */
430 tcg_gen_mov_tl(org_s, s);
431 tcg_gen_shli_tl(t, org_s, 8);
432 tcg_gen_andi_tl(d, t, 0xff00ff00);
433 tcg_gen_shri_tl(t, org_s, 8);
434 tcg_gen_andi_tl(t, t, 0x00ff00ff);
435 tcg_gen_or_tl(d, d, t);
30abcfc7
EI
436 tcg_temp_free(t);
437 tcg_temp_free(org_s);
3157a0a9
EI
438}
439
440/* Swap the halfwords of the s operand. */
441static inline void t_gen_swapw(TCGv d, TCGv s)
442{
443 TCGv t;
444 /* d and s refer the same object. */
a7812ae4 445 t = tcg_temp_new();
3157a0a9
EI
446 tcg_gen_mov_tl(t, s);
447 tcg_gen_shli_tl(d, t, 16);
448 tcg_gen_shri_tl(t, t, 16);
449 tcg_gen_or_tl(d, d, t);
30abcfc7 450 tcg_temp_free(t);
3157a0a9
EI
451}
452
453/* Reverse the within each byte.
454 T0 = (((T0 << 7) & 0x80808080) |
455 ((T0 << 5) & 0x40404040) |
456 ((T0 << 3) & 0x20202020) |
457 ((T0 << 1) & 0x10101010) |
458 ((T0 >> 1) & 0x08080808) |
459 ((T0 >> 3) & 0x04040404) |
460 ((T0 >> 5) & 0x02020202) |
461 ((T0 >> 7) & 0x01010101));
462 */
463static inline void t_gen_swapr(TCGv d, TCGv s)
464{
465 struct {
466 int shift; /* LSL when positive, LSR when negative. */
467 uint32_t mask;
468 } bitrev [] = {
469 {7, 0x80808080},
470 {5, 0x40404040},
471 {3, 0x20202020},
472 {1, 0x10101010},
473 {-1, 0x08080808},
474 {-3, 0x04040404},
475 {-5, 0x02020202},
476 {-7, 0x01010101}
477 };
478 int i;
479 TCGv t, org_s;
480
481 /* d and s refer the same object. */
a7812ae4
PB
482 t = tcg_temp_new();
483 org_s = tcg_temp_new();
3157a0a9
EI
484 tcg_gen_mov_tl(org_s, s);
485
486 tcg_gen_shli_tl(t, org_s, bitrev[0].shift);
487 tcg_gen_andi_tl(d, t, bitrev[0].mask);
b1503cda 488 for (i = 1; i < ARRAY_SIZE(bitrev); i++) {
3157a0a9
EI
489 if (bitrev[i].shift >= 0) {
490 tcg_gen_shli_tl(t, org_s, bitrev[i].shift);
491 } else {
492 tcg_gen_shri_tl(t, org_s, -bitrev[i].shift);
493 }
494 tcg_gen_andi_tl(t, t, bitrev[i].mask);
495 tcg_gen_or_tl(d, d, t);
496 }
30abcfc7
EI
497 tcg_temp_free(t);
498 tcg_temp_free(org_s);
3157a0a9
EI
499}
500
cf1d97f0 501static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false)
17ac9754
EI
502{
503 TCGv btaken;
504 int l1;
505
506 l1 = gen_new_label();
a7812ae4 507 btaken = tcg_temp_new();
17ac9754
EI
508
509 /* Conditional jmp. */
2a44f7f1 510 tcg_gen_mov_tl(btaken, env_btaken);
cf1d97f0 511 tcg_gen_mov_tl(env_pc, pc_false);
cb63669a 512 tcg_gen_brcondi_tl(TCG_COND_EQ, btaken, 0, l1);
cf1d97f0 513 tcg_gen_mov_tl(env_pc, pc_true);
17ac9754
EI
514 gen_set_label(l1);
515
30abcfc7 516 tcg_temp_free(btaken);
17ac9754
EI
517}
518
8170028d
TS
519static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
520{
521 TranslationBlock *tb;
522 tb = dc->tb;
523 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
05ba7d5f 524 tcg_gen_goto_tb(n);
50cfa95c 525 tcg_gen_movi_tl(env_pc, dest);
05ba7d5f 526 tcg_gen_exit_tb((long)tb + n);
8170028d 527 } else {
2a44f7f1 528 tcg_gen_movi_tl(env_pc, dest);
05ba7d5f 529 tcg_gen_exit_tb(0);
8170028d 530 }
8170028d
TS
531}
532
533/* Sign extend at translation time. */
534static int sign_extend(unsigned int val, unsigned int width)
535{
536 int sval;
537
538 /* LSL. */
539 val <<= 31 - width;
540 sval = val;
541 /* ASR. */
542 sval >>= 31 - width;
543 return sval;
544}
545
05ba7d5f
EI
546static inline void cris_clear_x_flag(DisasContext *dc)
547{
2a44f7f1
EI
548 if (dc->flagx_known && dc->flags_x)
549 dc->flags_uptodate = 0;
550
30abcfc7 551 dc->flagx_known = 1;
b41f7df0 552 dc->flags_x = 0;
05ba7d5f
EI
553}
554
30abcfc7 555static void cris_flush_cc_state(DisasContext *dc)
8170028d 556{
30abcfc7 557 if (dc->cc_size_uptodate != dc->cc_size) {
b41f7df0 558 tcg_gen_movi_tl(cc_size, dc->cc_size);
30abcfc7
EI
559 dc->cc_size_uptodate = dc->cc_size;
560 }
561 tcg_gen_movi_tl(cc_op, dc->cc_op);
562 tcg_gen_movi_tl(cc_mask, dc->cc_mask);
563}
564
565static void cris_evaluate_flags(DisasContext *dc)
566{
6231868b
EI
567 if (dc->flags_uptodate)
568 return;
b41f7df0 569
6231868b
EI
570 cris_flush_cc_state(dc);
571
572 switch (dc->cc_op)
573 {
574 case CC_OP_MCP:
575 gen_helper_evaluate_flags_mcp(cpu_PR[PR_CCS],
576 cpu_PR[PR_CCS], cc_src,
577 cc_dest, cc_result);
578 break;
579 case CC_OP_MULS:
580 gen_helper_evaluate_flags_muls(cpu_PR[PR_CCS],
581 cpu_PR[PR_CCS], cc_result,
582 cpu_PR[PR_MOF]);
583 break;
584 case CC_OP_MULU:
585 gen_helper_evaluate_flags_mulu(cpu_PR[PR_CCS],
586 cpu_PR[PR_CCS], cc_result,
587 cpu_PR[PR_MOF]);
588 break;
589 case CC_OP_MOVE:
590 case CC_OP_AND:
591 case CC_OP_OR:
592 case CC_OP_XOR:
593 case CC_OP_ASR:
594 case CC_OP_LSR:
595 case CC_OP_LSL:
596 switch (dc->cc_size)
8170028d 597 {
6231868b
EI
598 case 4:
599 gen_helper_evaluate_flags_move_4(cpu_PR[PR_CCS],
600 cpu_PR[PR_CCS], cc_result);
601 break;
602 case 2:
603 gen_helper_evaluate_flags_move_2(cpu_PR[PR_CCS],
604 cpu_PR[PR_CCS], cc_result);
605 break;
606 default:
607 gen_helper_evaluate_flags();
608 break;
609 }
610 break;
611 case CC_OP_FLAGS:
612 /* live. */
613 break;
614 case CC_OP_SUB:
615 case CC_OP_CMP:
616 if (dc->cc_size == 4)
617 gen_helper_evaluate_flags_sub_4(cpu_PR[PR_CCS],
618 cpu_PR[PR_CCS], cc_src, cc_dest, cc_result);
619 else
620 gen_helper_evaluate_flags();
621
622 break;
623 default:
624 switch (dc->cc_size)
625 {
626 case 4:
627 gen_helper_evaluate_flags_alu_4(cpu_PR[PR_CCS],
628 cpu_PR[PR_CCS], cc_src, cc_dest, cc_result);
a8cf66bb 629 break;
8170028d 630 default:
6231868b
EI
631 gen_helper_evaluate_flags();
632 break;
8170028d 633 }
6231868b 634 break;
8170028d 635 }
6231868b
EI
636
637 if (dc->flagx_known) {
638 if (dc->flags_x)
639 tcg_gen_ori_tl(cpu_PR[PR_CCS],
640 cpu_PR[PR_CCS], X_FLAG);
641 else
642 tcg_gen_andi_tl(cpu_PR[PR_CCS],
643 cpu_PR[PR_CCS], ~X_FLAG);
644 }
645 dc->flags_uptodate = 1;
8170028d
TS
646}
647
648static void cris_cc_mask(DisasContext *dc, unsigned int mask)
649{
650 uint32_t ovl;
651
2a44f7f1
EI
652 if (!mask) {
653 dc->update_cc = 0;
654 return;
655 }
656
fd56059f
AZ
657 /* Check if we need to evaluate the condition codes due to
658 CC overlaying. */
8170028d
TS
659 ovl = (dc->cc_mask ^ mask) & ~mask;
660 if (ovl) {
661 /* TODO: optimize this case. It trigs all the time. */
662 cris_evaluate_flags (dc);
663 }
664 dc->cc_mask = mask;
8170028d 665 dc->update_cc = 1;
8170028d
TS
666}
667
b41f7df0 668static void cris_update_cc_op(DisasContext *dc, int op, int size)
8170028d
TS
669{
670 dc->cc_op = op;
8170028d 671 dc->cc_size = size;
30abcfc7 672 dc->flags_uptodate = 0;
8170028d
TS
673}
674
30abcfc7
EI
675static inline void cris_update_cc_x(DisasContext *dc)
676{
677 /* Save the x flag state at the time of the cc snapshot. */
678 if (dc->flagx_known) {
679 if (dc->cc_x_uptodate == (2 | dc->flags_x))
680 return;
681 tcg_gen_movi_tl(cc_x, dc->flags_x);
682 dc->cc_x_uptodate = 2 | dc->flags_x;
683 }
684 else {
685 tcg_gen_andi_tl(cc_x, cpu_PR[PR_CCS], X_FLAG);
686 dc->cc_x_uptodate = 1;
687 }
688}
689
690/* Update cc prior to executing ALU op. Needs source operands untouched. */
691static void cris_pre_alu_update_cc(DisasContext *dc, int op,
692 TCGv dst, TCGv src, int size)
8170028d 693{
8170028d 694 if (dc->update_cc) {
b41f7df0 695 cris_update_cc_op(dc, op, size);
30abcfc7
EI
696 tcg_gen_mov_tl(cc_src, src);
697
698 if (op != CC_OP_MOVE
699 && op != CC_OP_AND
700 && op != CC_OP_OR
701 && op != CC_OP_XOR
702 && op != CC_OP_ASR
703 && op != CC_OP_LSR
704 && op != CC_OP_LSL)
705 tcg_gen_mov_tl(cc_dest, dst);
706
707 cris_update_cc_x(dc);
708 }
709}
3157a0a9 710
30abcfc7
EI
711/* Update cc after executing ALU op. needs the result. */
712static inline void cris_update_result(DisasContext *dc, TCGv res)
713{
a8cf66bb 714 if (dc->update_cc)
30abcfc7 715 tcg_gen_mov_tl(cc_result, res);
30abcfc7 716}
8170028d 717
30abcfc7
EI
718/* Returns one if the write back stage should execute. */
719static void cris_alu_op_exec(DisasContext *dc, int op,
720 TCGv dst, TCGv a, TCGv b, int size)
721{
8170028d
TS
722 /* Emit the ALU insns. */
723 switch (op)
724 {
725 case CC_OP_ADD:
30abcfc7 726 tcg_gen_add_tl(dst, a, b);
8170028d 727 /* Extended arithmetics. */
30abcfc7 728 t_gen_addx_carry(dc, dst);
8170028d
TS
729 break;
730 case CC_OP_ADDC:
30abcfc7
EI
731 tcg_gen_add_tl(dst, a, b);
732 t_gen_add_flag(dst, 0); /* C_FLAG. */
8170028d
TS
733 break;
734 case CC_OP_MCP:
30abcfc7
EI
735 tcg_gen_add_tl(dst, a, b);
736 t_gen_add_flag(dst, 8); /* R_FLAG. */
8170028d
TS
737 break;
738 case CC_OP_SUB:
30abcfc7 739 tcg_gen_sub_tl(dst, a, b);
8170028d 740 /* Extended arithmetics. */
30abcfc7 741 t_gen_subx_carry(dc, dst);
8170028d
TS
742 break;
743 case CC_OP_MOVE:
30abcfc7 744 tcg_gen_mov_tl(dst, b);
8170028d
TS
745 break;
746 case CC_OP_OR:
30abcfc7 747 tcg_gen_or_tl(dst, a, b);
8170028d
TS
748 break;
749 case CC_OP_AND:
30abcfc7 750 tcg_gen_and_tl(dst, a, b);
8170028d
TS
751 break;
752 case CC_OP_XOR:
30abcfc7 753 tcg_gen_xor_tl(dst, a, b);
8170028d
TS
754 break;
755 case CC_OP_LSL:
30abcfc7 756 t_gen_lsl(dst, a, b);
8170028d
TS
757 break;
758 case CC_OP_LSR:
30abcfc7 759 t_gen_lsr(dst, a, b);
8170028d
TS
760 break;
761 case CC_OP_ASR:
30abcfc7 762 t_gen_asr(dst, a, b);
8170028d
TS
763 break;
764 case CC_OP_NEG:
30abcfc7 765 tcg_gen_neg_tl(dst, b);
8170028d 766 /* Extended arithmetics. */
30abcfc7 767 t_gen_subx_carry(dc, dst);
8170028d
TS
768 break;
769 case CC_OP_LZ:
c38ac98d 770 gen_helper_lz(dst, b);
8170028d 771 break;
8170028d 772 case CC_OP_MULS:
30abcfc7
EI
773 t_gen_muls(dst, cpu_PR[PR_MOF], a, b);
774 break;
8170028d 775 case CC_OP_MULU:
30abcfc7
EI
776 t_gen_mulu(dst, cpu_PR[PR_MOF], a, b);
777 break;
8170028d 778 case CC_OP_DSTEP:
30abcfc7 779 t_gen_cris_dstep(dst, a, b);
8170028d
TS
780 break;
781 case CC_OP_BOUND:
3157a0a9
EI
782 {
783 int l1;
784 l1 = gen_new_label();
30abcfc7
EI
785 tcg_gen_mov_tl(dst, a);
786 tcg_gen_brcond_tl(TCG_COND_LEU, a, b, l1);
787 tcg_gen_mov_tl(dst, b);
3157a0a9
EI
788 gen_set_label(l1);
789 }
790 break;
8170028d 791 case CC_OP_CMP:
30abcfc7 792 tcg_gen_sub_tl(dst, a, b);
8170028d 793 /* Extended arithmetics. */
30abcfc7 794 t_gen_subx_carry(dc, dst);
8170028d
TS
795 break;
796 default:
93fcfe39 797 qemu_log("illegal ALU op.\n");
8170028d
TS
798 BUG();
799 break;
800 }
801
8170028d 802 if (size == 1)
30abcfc7 803 tcg_gen_andi_tl(dst, dst, 0xff);
8170028d 804 else if (size == 2)
30abcfc7
EI
805 tcg_gen_andi_tl(dst, dst, 0xffff);
806}
807
808static void cris_alu(DisasContext *dc, int op,
809 TCGv d, TCGv op_a, TCGv op_b, int size)
810{
811 TCGv tmp;
812 int writeback;
813
814 writeback = 1;
31c18d87 815
31c18d87 816 if (op == CC_OP_CMP) {
a7812ae4 817 tmp = tcg_temp_new();
30abcfc7 818 writeback = 0;
31c18d87 819 } else if (size == 4) {
30abcfc7
EI
820 tmp = d;
821 writeback = 0;
44696296 822 } else
a7812ae4 823 tmp = tcg_temp_new();
44696296 824
30abcfc7
EI
825
826 cris_pre_alu_update_cc(dc, op, op_a, op_b, size);
827 cris_alu_op_exec(dc, op, tmp, op_a, op_b, size);
828 cris_update_result(dc, tmp);
05ba7d5f 829
8170028d
TS
830 /* Writeback. */
831 if (writeback) {
30abcfc7
EI
832 if (size == 1)
833 tcg_gen_andi_tl(d, d, ~0xff);
834 else
835 tcg_gen_andi_tl(d, d, ~0xffff);
836 tcg_gen_or_tl(d, d, tmp);
8170028d 837 }
a7812ae4 838 if (!TCGV_EQUAL(tmp, d))
31c18d87 839 tcg_temp_free(tmp);
8170028d
TS
840}
841
842static int arith_cc(DisasContext *dc)
843{
844 if (dc->update_cc) {
845 switch (dc->cc_op) {
30abcfc7 846 case CC_OP_ADDC: return 1;
8170028d
TS
847 case CC_OP_ADD: return 1;
848 case CC_OP_SUB: return 1;
30abcfc7 849 case CC_OP_DSTEP: return 1;
8170028d
TS
850 case CC_OP_LSL: return 1;
851 case CC_OP_LSR: return 1;
852 case CC_OP_ASR: return 1;
853 case CC_OP_CMP: return 1;
30abcfc7
EI
854 case CC_OP_NEG: return 1;
855 case CC_OP_OR: return 1;
459e5185 856 case CC_OP_AND: return 1;
30abcfc7
EI
857 case CC_OP_XOR: return 1;
858 case CC_OP_MULU: return 1;
859 case CC_OP_MULS: return 1;
8170028d
TS
860 default:
861 return 0;
862 }
863 }
864 return 0;
865}
866
c5631f48 867static void gen_tst_cc (DisasContext *dc, TCGv cc, int cond)
8170028d 868{
2a44f7f1 869 int arith_opt, move_opt;
8170028d
TS
870
871 /* TODO: optimize more condition codes. */
dceaf394
EI
872
873 /*
874 * If the flags are live, we've gotta look into the bits of CCS.
875 * Otherwise, if we just did an arithmetic operation we try to
876 * evaluate the condition code faster.
877 *
878 * When this function is done, T0 should be non-zero if the condition
879 * code is true.
880 */
30abcfc7 881 arith_opt = arith_cc(dc) && !dc->flags_uptodate;
459e5185 882 move_opt = (dc->cc_op == CC_OP_MOVE);
8170028d
TS
883 switch (cond) {
884 case CC_EQ:
2a44f7f1 885 if (arith_opt || move_opt) {
dceaf394
EI
886 /* If cc_result is zero, T0 should be
887 non-zero otherwise T0 should be zero. */
888 int l1;
889 l1 = gen_new_label();
c5631f48 890 tcg_gen_movi_tl(cc, 0);
cb63669a
PB
891 tcg_gen_brcondi_tl(TCG_COND_NE, cc_result,
892 0, l1);
c5631f48 893 tcg_gen_movi_tl(cc, 1);
dceaf394
EI
894 gen_set_label(l1);
895 }
8170028d
TS
896 else {
897 cris_evaluate_flags(dc);
c5631f48 898 tcg_gen_andi_tl(cc,
dceaf394 899 cpu_PR[PR_CCS], Z_FLAG);
8170028d
TS
900 }
901 break;
902 case CC_NE:
2a44f7f1 903 if (arith_opt || move_opt)
c5631f48 904 tcg_gen_mov_tl(cc, cc_result);
8170028d
TS
905 else {
906 cris_evaluate_flags(dc);
c5631f48 907 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
dceaf394 908 Z_FLAG);
c5631f48 909 tcg_gen_andi_tl(cc, cc, Z_FLAG);
8170028d
TS
910 }
911 break;
912 case CC_CS:
913 cris_evaluate_flags(dc);
c5631f48 914 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], C_FLAG);
8170028d
TS
915 break;
916 case CC_CC:
917 cris_evaluate_flags(dc);
c5631f48
EI
918 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS], C_FLAG);
919 tcg_gen_andi_tl(cc, cc, C_FLAG);
8170028d
TS
920 break;
921 case CC_VS:
922 cris_evaluate_flags(dc);
c5631f48 923 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], V_FLAG);
8170028d
TS
924 break;
925 case CC_VC:
926 cris_evaluate_flags(dc);
c5631f48 927 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
dceaf394 928 V_FLAG);
c5631f48 929 tcg_gen_andi_tl(cc, cc, V_FLAG);
8170028d
TS
930 break;
931 case CC_PL:
2a44f7f1
EI
932 if (arith_opt || move_opt) {
933 int bits = 31;
934
935 if (dc->cc_size == 1)
936 bits = 7;
937 else if (dc->cc_size == 2)
938 bits = 15;
939
c5631f48
EI
940 tcg_gen_shri_tl(cc, cc_result, bits);
941 tcg_gen_xori_tl(cc, cc, 1);
2a44f7f1 942 } else {
8170028d 943 cris_evaluate_flags(dc);
c5631f48 944 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
dceaf394 945 N_FLAG);
c5631f48 946 tcg_gen_andi_tl(cc, cc, N_FLAG);
8170028d
TS
947 }
948 break;
949 case CC_MI:
2a44f7f1
EI
950 if (arith_opt || move_opt) {
951 int bits = 31;
952
953 if (dc->cc_size == 1)
954 bits = 7;
955 else if (dc->cc_size == 2)
956 bits = 15;
957
f3bc5238
EI
958 tcg_gen_shri_tl(cc, cc_result, bits);
959 tcg_gen_andi_tl(cc, cc, 1);
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;
ce24e07b 2394 LOG_DIS("test.%c [$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;
ce24e07b 2418 LOG_DIS("and.%c [$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;
ce24e07b 2437 LOG_DIS("add.%c [$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;
ce24e07b 2457 LOG_DIS("add.%c [$r%u%s, $r%u\n",
8170028d
TS
2458 memsize_char(memsize),
2459 dc->op1, dc->postinc ? "+]" : "]",
d12d51d5 2460 dc->op2);
8170028d 2461
31c18d87
EI
2462 cris_alu_m_alloc_temps(t);
2463 insn_len = dec_prep_alu_m(dc, 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;
ce24e07b 2476 LOG_DIS("bound.%c [$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;
ce24e07b 2539 LOG_DIS("or.%c [$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);
cc53adbc
EI
2635 } else
2636 TCGV_UNUSED(tmp32);
31c18d87 2637 tcg_temp_free(addr);
17ac9754 2638
28de16da
EI
2639 for (i = 0; i < (nr >> 1); i++) {
2640 tcg_gen_trunc_i64_i32(cpu_R[i * 2], tmp[i]);
2641 tcg_gen_shri_i64(tmp[i], tmp[i], 32);
2642 tcg_gen_trunc_i64_i32(cpu_R[i * 2 + 1], tmp[i]);
a7812ae4 2643 tcg_temp_free_i64(tmp[i]);
28de16da
EI
2644 }
2645 if (nr & 1) {
a7812ae4
PB
2646 tcg_gen_mov_tl(cpu_R[dc->op2], tmp32);
2647 tcg_temp_free(tmp32);
17ac9754
EI
2648 }
2649
05ba7d5f
EI
2650 /* writeback the updated pointer value. */
2651 if (dc->postinc)
28de16da 2652 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], nr * 4);
b41f7df0
EI
2653
2654 /* gen_load might want to evaluate the previous insns flags. */
2655 cris_cc_mask(dc, 0);
8170028d
TS
2656 return 2;
2657}
2658
2659static unsigned int dec_movem_rm(DisasContext *dc)
2660{
30abcfc7 2661 TCGv tmp;
31c18d87 2662 TCGv addr;
8170028d
TS
2663 int i;
2664
d12d51d5
AL
2665 LOG_DIS("movem $r%u, [$r%u%s\n", dc->op2, dc->op1,
2666 dc->postinc ? "+]" : "]");
8170028d 2667
30abcfc7
EI
2668 cris_flush_cc_state(dc);
2669
a7812ae4
PB
2670 tmp = tcg_temp_new();
2671 addr = tcg_temp_new();
30abcfc7 2672 tcg_gen_movi_tl(tmp, 4);
31c18d87 2673 tcg_gen_mov_tl(addr, cpu_R[dc->op1]);
8170028d 2674 for (i = 0; i <= dc->op2; i++) {
17ac9754 2675 /* Displace addr. */
8170028d 2676 /* Perform the store. */
31c18d87
EI
2677 gen_store(dc, addr, cpu_R[i], 4);
2678 tcg_gen_add_tl(addr, addr, tmp);
8170028d 2679 }
17ac9754 2680 if (dc->postinc)
31c18d87 2681 tcg_gen_mov_tl(cpu_R[dc->op1], addr);
b41f7df0 2682 cris_cc_mask(dc, 0);
30abcfc7 2683 tcg_temp_free(tmp);
31c18d87 2684 tcg_temp_free(addr);
8170028d
TS
2685 return 2;
2686}
2687
2688static unsigned int dec_move_rm(DisasContext *dc)
2689{
2690 int memsize;
2691
2692 memsize = memsize_zz(dc);
2693
ce24e07b
EI
2694 LOG_DIS("move.%c $r%u, [$r%u]\n",
2695 memsize_char(memsize), dc->op2, dc->op1);
8170028d 2696
8170028d 2697 /* prepare store. */
30abcfc7 2698 cris_flush_cc_state(dc);
17ac9754
EI
2699 gen_store(dc, cpu_R[dc->op1], cpu_R[dc->op2], memsize);
2700
8170028d 2701 if (dc->postinc)
17ac9754 2702 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize);
b41f7df0 2703 cris_cc_mask(dc, 0);
8170028d
TS
2704 return 2;
2705}
2706
8170028d
TS
2707static unsigned int dec_lapcq(DisasContext *dc)
2708{
d12d51d5
AL
2709 LOG_DIS("lapcq %x, $r%u\n",
2710 dc->pc + dc->op1*2, dc->op2);
8170028d 2711 cris_cc_mask(dc, 0);
30abcfc7 2712 tcg_gen_movi_tl(cpu_R[dc->op2], dc->pc + dc->op1 * 2);
8170028d
TS
2713 return 2;
2714}
2715
2716static unsigned int dec_lapc_im(DisasContext *dc)
2717{
2718 unsigned int rd;
2719 int32_t imm;
b41f7df0 2720 int32_t pc;
8170028d
TS
2721
2722 rd = dc->op2;
2723
2724 cris_cc_mask(dc, 0);
2725 imm = ldl_code(dc->pc + 2);
d12d51d5 2726 LOG_DIS("lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2);
b41f7df0
EI
2727
2728 pc = dc->pc;
2729 pc += imm;
2730 t_gen_mov_reg_TN(rd, tcg_const_tl(pc));
05ba7d5f 2731 return 6;
8170028d
TS
2732}
2733
2734/* Jump to special reg. */
2735static unsigned int dec_jump_p(DisasContext *dc)
2736{
d12d51d5 2737 LOG_DIS("jump $p%u\n", dc->op2);
b41f7df0 2738
17ac9754
EI
2739 if (dc->op2 == PR_CCS)
2740 cris_evaluate_flags(dc);
31c18d87 2741 t_gen_mov_TN_preg(env_btarget, dc->op2);
b41f7df0 2742 /* rete will often have low bit set to indicate delayslot. */
31c18d87 2743 tcg_gen_andi_tl(env_btarget, env_btarget, ~1);
17ac9754 2744 cris_cc_mask(dc, 0);
2a44f7f1 2745 cris_prepare_jmp(dc, JMP_INDIRECT);
8170028d
TS
2746 return 2;
2747}
2748
2749/* Jump and save. */
2750static unsigned int dec_jas_r(DisasContext *dc)
2751{
d12d51d5 2752 LOG_DIS("jas $r%u, $p%u\n", dc->op1, dc->op2);
8170028d 2753 cris_cc_mask(dc, 0);
b41f7df0
EI
2754 /* Store the return address in Pd. */
2755 tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
2756 if (dc->op2 > 15)
2757 abort();
30abcfc7 2758 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4));
b41f7df0 2759
2a44f7f1 2760 cris_prepare_jmp(dc, JMP_INDIRECT);
8170028d
TS
2761 return 2;
2762}
2763
2764static unsigned int dec_jas_im(DisasContext *dc)
2765{
2766 uint32_t imm;
2767
2768 imm = ldl_code(dc->pc + 2);
2769
d12d51d5 2770 LOG_DIS("jas 0x%x\n", imm);
8170028d 2771 cris_cc_mask(dc, 0);
17ac9754 2772 /* Store the return address in Pd. */
cf1d97f0 2773 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
2a44f7f1
EI
2774
2775 dc->jmp_pc = imm;
2776 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2777 return 6;
2778}
2779
2780static unsigned int dec_jasc_im(DisasContext *dc)
2781{
2782 uint32_t imm;
2783
2784 imm = ldl_code(dc->pc + 2);
2785
d12d51d5 2786 LOG_DIS("jasc 0x%x\n", imm);
8170028d 2787 cris_cc_mask(dc, 0);
17ac9754 2788 /* Store the return address in Pd. */
2a44f7f1
EI
2789 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8 + 4));
2790
2791 dc->jmp_pc = imm;
2792 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2793 return 6;
2794}
2795
2796static unsigned int dec_jasc_r(DisasContext *dc)
2797{
d12d51d5 2798 LOG_DIS("jasc_r $r%u, $p%u\n", dc->op1, dc->op2);
8170028d 2799 cris_cc_mask(dc, 0);
17ac9754 2800 /* Store the return address in Pd. */
2a44f7f1
EI
2801 tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
2802 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4 + 4));
2803 cris_prepare_jmp(dc, JMP_INDIRECT);
8170028d
TS
2804 return 2;
2805}
2806
2807static unsigned int dec_bcc_im(DisasContext *dc)
2808{
2809 int32_t offset;
2810 uint32_t cond = dc->op2;
2811
17ac9754 2812 offset = ldsw_code(dc->pc + 2);
8170028d 2813
d12d51d5 2814 LOG_DIS("b%s %d pc=%x dst=%x\n",
8170028d 2815 cc_name(cond), offset,
d12d51d5 2816 dc->pc, dc->pc + offset);
8170028d
TS
2817
2818 cris_cc_mask(dc, 0);
2819 /* op2 holds the condition-code. */
2820 cris_prepare_cc_branch (dc, offset, cond);
2821 return 4;
2822}
2823
2824static unsigned int dec_bas_im(DisasContext *dc)
2825{
2826 int32_t simm;
2827
2828
2829 simm = ldl_code(dc->pc + 2);
2830
d12d51d5 2831 LOG_DIS("bas 0x%x, $p%u\n", dc->pc + simm, dc->op2);
8170028d 2832 cris_cc_mask(dc, 0);
2a44f7f1
EI
2833 /* Store the return address in Pd. */
2834 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
2835
2836 dc->jmp_pc = dc->pc + simm;
2837 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2838 return 6;
2839}
2840
2841static unsigned int dec_basc_im(DisasContext *dc)
2842{
2843 int32_t simm;
2844 simm = ldl_code(dc->pc + 2);
2845
d12d51d5 2846 LOG_DIS("basc 0x%x, $p%u\n", dc->pc + simm, dc->op2);
8170028d 2847 cris_cc_mask(dc, 0);
2a44f7f1
EI
2848 /* Store the return address in Pd. */
2849 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 12));
2850
2851 dc->jmp_pc = dc->pc + simm;
2852 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2853 return 6;
2854}
2855
2856static unsigned int dec_rfe_etc(DisasContext *dc)
2857{
8170028d
TS
2858 cris_cc_mask(dc, 0);
2859
213fb478
EI
2860 if (dc->op2 == 15) {
2861 t_gen_mov_env_TN(halted, tcg_const_tl(1));
2862 tcg_gen_movi_tl(env_pc, dc->pc + 2);
2863 t_gen_raise_exception(EXCP_HLT);
05ba7d5f 2864 return 2;
213fb478 2865 }
8170028d
TS
2866
2867 switch (dc->op2 & 7) {
2868 case 2:
2869 /* rfe. */
d12d51d5 2870 LOG_DIS("rfe\n");
8170028d 2871 cris_evaluate_flags(dc);
a7812ae4 2872 gen_helper_rfe();
b41f7df0 2873 dc->is_jmp = DISAS_UPDATE;
8170028d
TS
2874 break;
2875 case 5:
2876 /* rfn. */
d12d51d5 2877 LOG_DIS("rfn\n");
a7cfbba0 2878 cris_evaluate_flags(dc);
a7812ae4 2879 gen_helper_rfn();
a7cfbba0 2880 dc->is_jmp = DISAS_UPDATE;
8170028d
TS
2881 break;
2882 case 6:
d12d51d5 2883 LOG_DIS("break %d\n", dc->op1);
a1aebcb8 2884 cris_evaluate_flags (dc);
8170028d 2885 /* break. */
cddffe37 2886 tcg_gen_movi_tl(env_pc, dc->pc + 2);
a1aebcb8 2887
8170028d 2888 /* Breaks start at 16 in the exception vector. */
dceaf394
EI
2889 t_gen_mov_env_TN(trap_vector,
2890 tcg_const_tl(dc->op1 + 16));
2891 t_gen_raise_exception(EXCP_BREAK);
b41f7df0 2892 dc->is_jmp = DISAS_UPDATE;
8170028d
TS
2893 break;
2894 default:
2895 printf ("op2=%x\n", dc->op2);
2896 BUG();
2897 break;
2898
2899 }
8170028d
TS
2900 return 2;
2901}
2902
5d4a534d
EI
2903static unsigned int dec_ftag_fidx_d_m(DisasContext *dc)
2904{
5d4a534d
EI
2905 return 2;
2906}
2907
2908static unsigned int dec_ftag_fidx_i_m(DisasContext *dc)
2909{
5d4a534d
EI
2910 return 2;
2911}
2912
8170028d
TS
2913static unsigned int dec_null(DisasContext *dc)
2914{
2915 printf ("unknown insn pc=%x opc=%x op1=%x op2=%x\n",
2916 dc->pc, dc->opcode, dc->op1, dc->op2);
2917 fflush(NULL);
2918 BUG();
2919 return 2;
2920}
2921
9b32fbf8 2922static struct decoder_info {
8170028d
TS
2923 struct {
2924 uint32_t bits;
2925 uint32_t mask;
2926 };
2927 unsigned int (*dec)(DisasContext *dc);
2928} decinfo[] = {
2929 /* Order matters here. */
2930 {DEC_MOVEQ, dec_moveq},
2931 {DEC_BTSTQ, dec_btstq},
2932 {DEC_CMPQ, dec_cmpq},
2933 {DEC_ADDOQ, dec_addoq},
2934 {DEC_ADDQ, dec_addq},
2935 {DEC_SUBQ, dec_subq},
2936 {DEC_ANDQ, dec_andq},
2937 {DEC_ORQ, dec_orq},
2938 {DEC_ASRQ, dec_asrq},
2939 {DEC_LSLQ, dec_lslq},
2940 {DEC_LSRQ, dec_lsrq},
2941 {DEC_BCCQ, dec_bccq},
2942
2943 {DEC_BCC_IM, dec_bcc_im},
2944 {DEC_JAS_IM, dec_jas_im},
2945 {DEC_JAS_R, dec_jas_r},
2946 {DEC_JASC_IM, dec_jasc_im},
2947 {DEC_JASC_R, dec_jasc_r},
2948 {DEC_BAS_IM, dec_bas_im},
2949 {DEC_BASC_IM, dec_basc_im},
2950 {DEC_JUMP_P, dec_jump_p},
2951 {DEC_LAPC_IM, dec_lapc_im},
2952 {DEC_LAPCQ, dec_lapcq},
2953
2954 {DEC_RFE_ETC, dec_rfe_etc},
2955 {DEC_ADDC_MR, dec_addc_mr},
2956
2957 {DEC_MOVE_MP, dec_move_mp},
2958 {DEC_MOVE_PM, dec_move_pm},
2959 {DEC_MOVEM_MR, dec_movem_mr},
2960 {DEC_MOVEM_RM, dec_movem_rm},
2961 {DEC_MOVE_PR, dec_move_pr},
2962 {DEC_SCC_R, dec_scc_r},
2963 {DEC_SETF, dec_setclrf},
2964 {DEC_CLEARF, dec_setclrf},
2965
2966 {DEC_MOVE_SR, dec_move_sr},
2967 {DEC_MOVE_RP, dec_move_rp},
2968 {DEC_SWAP_R, dec_swap_r},
2969 {DEC_ABS_R, dec_abs_r},
2970 {DEC_LZ_R, dec_lz_r},
2971 {DEC_MOVE_RS, dec_move_rs},
2972 {DEC_BTST_R, dec_btst_r},
2973 {DEC_ADDC_R, dec_addc_r},
2974
2975 {DEC_DSTEP_R, dec_dstep_r},
2976 {DEC_XOR_R, dec_xor_r},
2977 {DEC_MCP_R, dec_mcp_r},
2978 {DEC_CMP_R, dec_cmp_r},
2979
2980 {DEC_ADDI_R, dec_addi_r},
2981 {DEC_ADDI_ACR, dec_addi_acr},
2982
2983 {DEC_ADD_R, dec_add_r},
2984 {DEC_SUB_R, dec_sub_r},
2985
2986 {DEC_ADDU_R, dec_addu_r},
2987 {DEC_ADDS_R, dec_adds_r},
2988 {DEC_SUBU_R, dec_subu_r},
2989 {DEC_SUBS_R, dec_subs_r},
2990 {DEC_LSL_R, dec_lsl_r},
2991
2992 {DEC_AND_R, dec_and_r},
2993 {DEC_OR_R, dec_or_r},
2994 {DEC_BOUND_R, dec_bound_r},
2995 {DEC_ASR_R, dec_asr_r},
2996 {DEC_LSR_R, dec_lsr_r},
2997
2998 {DEC_MOVU_R, dec_movu_r},
2999 {DEC_MOVS_R, dec_movs_r},
3000 {DEC_NEG_R, dec_neg_r},
3001 {DEC_MOVE_R, dec_move_r},
3002
5d4a534d
EI
3003 {DEC_FTAG_FIDX_I_M, dec_ftag_fidx_i_m},
3004 {DEC_FTAG_FIDX_D_M, dec_ftag_fidx_d_m},
8170028d
TS
3005
3006 {DEC_MULS_R, dec_muls_r},
3007 {DEC_MULU_R, dec_mulu_r},
3008
3009 {DEC_ADDU_M, dec_addu_m},
3010 {DEC_ADDS_M, dec_adds_m},
3011 {DEC_SUBU_M, dec_subu_m},
3012 {DEC_SUBS_M, dec_subs_m},
3013
3014 {DEC_CMPU_M, dec_cmpu_m},
3015 {DEC_CMPS_M, dec_cmps_m},
3016 {DEC_MOVU_M, dec_movu_m},
3017 {DEC_MOVS_M, dec_movs_m},
3018
3019 {DEC_CMP_M, dec_cmp_m},
3020 {DEC_ADDO_M, dec_addo_m},
3021 {DEC_BOUND_M, dec_bound_m},
3022 {DEC_ADD_M, dec_add_m},
3023 {DEC_SUB_M, dec_sub_m},
3024 {DEC_AND_M, dec_and_m},
3025 {DEC_OR_M, dec_or_m},
3026 {DEC_MOVE_RM, dec_move_rm},
3027 {DEC_TEST_M, dec_test_m},
3028 {DEC_MOVE_MR, dec_move_mr},
3029
3030 {{0, 0}, dec_null}
3031};
3032
3033static inline unsigned int
3034cris_decoder(DisasContext *dc)
3035{
3036 unsigned int insn_len = 2;
8170028d
TS
3037 int i;
3038
8fec2b8c 3039 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
28de16da
EI
3040 tcg_gen_debug_insn_start(dc->pc);
3041
8170028d 3042 /* Load a halfword onto the instruction register. */
17ac9754 3043 dc->ir = lduw_code(dc->pc);
8170028d
TS
3044
3045 /* Now decode it. */
3046 dc->opcode = EXTRACT_FIELD(dc->ir, 4, 11);
3047 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 3);
3048 dc->op2 = EXTRACT_FIELD(dc->ir, 12, 15);
3049 dc->zsize = EXTRACT_FIELD(dc->ir, 4, 4);
3050 dc->zzsize = EXTRACT_FIELD(dc->ir, 4, 5);
3051 dc->postinc = EXTRACT_FIELD(dc->ir, 10, 10);
3052
3053 /* Large switch for all insns. */
b1503cda 3054 for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
8170028d
TS
3055 if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits)
3056 {
3057 insn_len = decinfo[i].dec(dc);
3058 break;
3059 }
3060 }
3061
dd20fcd0 3062#if !defined(CONFIG_USER_ONLY)
a1aebcb8
EI
3063 /* Single-stepping ? */
3064 if (dc->tb_flags & S_FLAG) {
3065 int l1;
3066
3067 l1 = gen_new_label();
dd20fcd0 3068 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_PR[PR_SPC], dc->pc, l1);
a1aebcb8
EI
3069 /* We treat SPC as a break with an odd trap vector. */
3070 cris_evaluate_flags (dc);
3071 t_gen_mov_env_TN(trap_vector, tcg_const_tl(3));
3072 tcg_gen_movi_tl(env_pc, dc->pc + insn_len);
cddffe37 3073 tcg_gen_movi_tl(cpu_PR[PR_SPC], dc->pc + insn_len);
a1aebcb8
EI
3074 t_gen_raise_exception(EXCP_BREAK);
3075 gen_set_label(l1);
3076 }
3077#endif
8170028d
TS
3078 return insn_len;
3079}
3080
3081static void check_breakpoint(CPUState *env, DisasContext *dc)
3082{
a1d1bb31
AL
3083 CPUBreakpoint *bp;
3084
72cf2d4f
BS
3085 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
3086 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 3087 if (bp->pc == dc->pc) {
8170028d 3088 cris_evaluate_flags (dc);
2a44f7f1 3089 tcg_gen_movi_tl(env_pc, dc->pc);
dceaf394 3090 t_gen_raise_exception(EXCP_DEBUG);
8170028d
TS
3091 dc->is_jmp = DISAS_UPDATE;
3092 }
3093 }
3094 }
3095}
3096
cf1d97f0
EI
3097
3098/*
3099 * Delay slots on QEMU/CRIS.
3100 *
3101 * If an exception hits on a delayslot, the core will let ERP (the Exception
3102 * Return Pointer) point to the branch (the previous) insn and set the lsb to
3103 * to give SW a hint that the exception actually hit on the dslot.
3104 *
3105 * CRIS expects all PC addresses to be 16-bit aligned. The lsb is ignored by
3106 * the core and any jmp to an odd addresses will mask off that lsb. It is
3107 * simply there to let sw know there was an exception on a dslot.
3108 *
3109 * When the software returns from an exception, the branch will re-execute.
3110 * On QEMU care needs to be taken when a branch+delayslot sequence is broken
3111 * and the branch and delayslot dont share pages.
3112 *
3113 * The TB contaning the branch insn will set up env->btarget and evaluate
3114 * env->btaken. When the translation loop exits we will note that the branch
3115 * sequence is broken and let env->dslot be the size of the branch insn (those
3116 * vary in length).
3117 *
3118 * The TB contaning the delayslot will have the PC of its real insn (i.e no lsb
3119 * set). It will also expect to have env->dslot setup with the size of the
3120 * delay slot so that env->pc - env->dslot point to the branch insn. This TB
3121 * will execute the dslot and take the branch, either to btarget or just one
3122 * insn ahead.
3123 *
3124 * When exceptions occur, we check for env->dslot in do_interrupt to detect
3125 * broken branch sequences and setup $erp accordingly (i.e let it point to the
3126 * branch and set lsb). Then env->dslot gets cleared so that the exception
3127 * handler can enter. When returning from exceptions (jump $erp) the lsb gets
3128 * masked off and we will reexecute the branch insn.
3129 *
3130 */
3131
8170028d 3132/* generate intermediate code for basic block 'tb'. */
2cfc5f17 3133static void
8170028d
TS
3134gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
3135 int search_pc)
3136{
3137 uint16_t *gen_opc_end;
3138 uint32_t pc_start;
3139 unsigned int insn_len;
3140 int j, lj;
cf1d97f0 3141 struct DisasContext ctx;
8170028d
TS
3142 struct DisasContext *dc = &ctx;
3143 uint32_t next_page_start;
2a44f7f1 3144 target_ulong npc;
2e70f6ef
PB
3145 int num_insns;
3146 int max_insns;
8170028d 3147
93fcfe39 3148 qemu_log_try_set_file(stderr);
a825e703 3149
73e51723
EI
3150 /* Odd PC indicates that branch is rexecuting due to exception in the
3151 * delayslot, like in real hw.
73e51723
EI
3152 */
3153 pc_start = tb->pc & ~1;
8170028d
TS
3154 dc->env = env;
3155 dc->tb = tb;
3156
8170028d 3157 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8170028d
TS
3158
3159 dc->is_jmp = DISAS_NEXT;
b41f7df0 3160 dc->ppc = pc_start;
8170028d
TS
3161 dc->pc = pc_start;
3162 dc->singlestep_enabled = env->singlestep_enabled;
30abcfc7
EI
3163 dc->flags_uptodate = 1;
3164 dc->flagx_known = 1;
3165 dc->flags_x = tb->flags & X_FLAG;
3166 dc->cc_x_uptodate = 0;
b41f7df0 3167 dc->cc_mask = 0;
cf1d97f0 3168 dc->update_cc = 0;
30abcfc7 3169
b41f7df0 3170 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
30abcfc7 3171 dc->cc_size_uptodate = -1;
b41f7df0 3172
cf1d97f0 3173 /* Decode TB flags. */
a1aebcb8 3174 dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG | X_FLAG);
cf1d97f0 3175 dc->delayed_branch = !!(tb->flags & 7);
2a44f7f1
EI
3176 if (dc->delayed_branch)
3177 dc->jmp = JMP_INDIRECT;
3178 else
3179 dc->jmp = JMP_NOJMP;
3180
3181 dc->cpustate_changed = 0;
b41f7df0 3182
8fec2b8c 3183 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39 3184 qemu_log(
d297f464 3185 "srch=%d pc=%x %x flg=%llx bt=%x ds=%u ccs=%x\n"
30abcfc7 3186 "pid=%x usp=%x\n"
b41f7df0
EI
3187 "%x.%x.%x.%x\n"
3188 "%x.%x.%x.%x\n"
3189 "%x.%x.%x.%x\n"
3190 "%x.%x.%x.%x\n",
d297f464
EI
3191 search_pc, dc->pc, dc->ppc,
3192 (unsigned long long)tb->flags,
3193 env->btarget, (unsigned)tb->flags & 7,
cf1d97f0 3194 env->pregs[PR_CCS],
b41f7df0
EI
3195 env->pregs[PR_PID], env->pregs[PR_USP],
3196 env->regs[0], env->regs[1], env->regs[2], env->regs[3],
3197 env->regs[4], env->regs[5], env->regs[6], env->regs[7],
3198 env->regs[8], env->regs[9],
3199 env->regs[10], env->regs[11],
3200 env->regs[12], env->regs[13],
3201 env->regs[14], env->regs[15]);
93fcfe39
AL
3202 qemu_log("--------------\n");
3203 qemu_log("IN: %s\n", lookup_symbol(pc_start));
b41f7df0 3204 }
3157a0a9 3205
8170028d
TS
3206 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
3207 lj = -1;
2e70f6ef
PB
3208 num_insns = 0;
3209 max_insns = tb->cflags & CF_COUNT_MASK;
3210 if (max_insns == 0)
3211 max_insns = CF_COUNT_MASK;
3212
3213 gen_icount_start();
8170028d
TS
3214 do
3215 {
3216 check_breakpoint(env, dc);
8170028d
TS
3217
3218 if (search_pc) {
3219 j = gen_opc_ptr - gen_opc_buf;
3220 if (lj < j) {
3221 lj++;
3222 while (lj < j)
3223 gen_opc_instr_start[lj++] = 0;
3224 }
cf1d97f0 3225 if (dc->delayed_branch == 1)
b41f7df0 3226 gen_opc_pc[lj] = dc->ppc | 1;
cf1d97f0 3227 else
b41f7df0 3228 gen_opc_pc[lj] = dc->pc;
cf1d97f0 3229 gen_opc_instr_start[lj] = 1;
2e70f6ef 3230 gen_opc_icount[lj] = num_insns;
cf1d97f0
EI
3231 }
3232
3233 /* Pretty disas. */
d12d51d5 3234 LOG_DIS("%8.8x:\t", dc->pc);
8170028d 3235
2e70f6ef
PB
3236 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
3237 gen_io_start();
b41f7df0 3238 dc->clear_x = 1;
28de16da
EI
3239
3240 insn_len = cris_decoder(dc);
b41f7df0 3241 dc->ppc = dc->pc;
8170028d 3242 dc->pc += insn_len;
b41f7df0
EI
3243 if (dc->clear_x)
3244 cris_clear_x_flag(dc);
8170028d 3245
2e70f6ef 3246 num_insns++;
8170028d 3247 /* Check for delayed branches here. If we do it before
bf20dc07 3248 actually generating any host code, the simulator will just
8170028d
TS
3249 loop doing nothing for on this program location. */
3250 if (dc->delayed_branch) {
3251 dc->delayed_branch--;
3252 if (dc->delayed_branch == 0)
3253 {
2a44f7f1
EI
3254 if (tb->flags & 7)
3255 t_gen_mov_env_TN(dslot,
3256 tcg_const_tl(0));
3257 if (dc->jmp == JMP_DIRECT) {
3258 dc->is_jmp = DISAS_NEXT;
3259 } else {
3260 t_gen_cc_jmp(env_btarget,
3261 tcg_const_tl(dc->pc));
3262 dc->is_jmp = DISAS_JUMP;
3263 }
3264 break;
8170028d
TS
3265 }
3266 }
3267
73e51723
EI
3268 /* If we are rexecuting a branch due to exceptions on
3269 delay slots dont break. */
3270 if (!(tb->pc & 1) && env->singlestep_enabled)
8170028d 3271 break;
fb48f71b
EI
3272 } while (!dc->is_jmp && !dc->cpustate_changed
3273 && gen_opc_ptr < gen_opc_end
1b530a6d 3274 && !singlestep
2e70f6ef
PB
3275 && (dc->pc < next_page_start)
3276 && num_insns < max_insns);
b41f7df0 3277
2a44f7f1
EI
3278 npc = dc->pc;
3279 if (dc->jmp == JMP_DIRECT && !dc->delayed_branch)
3280 npc = dc->jmp_pc;
3281
2e70f6ef
PB
3282 if (tb->cflags & CF_LAST_IO)
3283 gen_io_end();
2a44f7f1
EI
3284 /* Force an update if the per-tb cpu state has changed. */
3285 if (dc->is_jmp == DISAS_NEXT
3286 && (dc->cpustate_changed || !dc->flagx_known
3287 || (dc->flags_x != (tb->flags & X_FLAG)))) {
3288 dc->is_jmp = DISAS_UPDATE;
3289 tcg_gen_movi_tl(env_pc, npc);
3290 }
cf1d97f0 3291 /* Broken branch+delayslot sequence. */
b41f7df0 3292 if (dc->delayed_branch == 1) {
cf1d97f0
EI
3293 /* Set env->dslot to the size of the branch insn. */
3294 t_gen_mov_env_TN(dslot, tcg_const_tl(dc->pc - dc->ppc));
2a44f7f1 3295 cris_store_direct_jmp(dc);
8170028d
TS
3296 }
3297
3298 cris_evaluate_flags (dc);
2a44f7f1 3299
551bd27f 3300 if (unlikely(env->singlestep_enabled)) {
89cc7382
EI
3301 if (dc->is_jmp == DISAS_NEXT)
3302 tcg_gen_movi_tl(env_pc, npc);
dceaf394 3303 t_gen_raise_exception(EXCP_DEBUG);
8170028d
TS
3304 } else {
3305 switch(dc->is_jmp) {
3306 case DISAS_NEXT:
2a44f7f1 3307 gen_goto_tb(dc, 1, npc);
8170028d
TS
3308 break;
3309 default:
3310 case DISAS_JUMP:
3311 case DISAS_UPDATE:
3312 /* indicate that the hash table must be used
3313 to find the next TB */
57fec1fe 3314 tcg_gen_exit_tb(0);
8170028d 3315 break;
4f400ab5 3316 case DISAS_SWI:
8170028d
TS
3317 case DISAS_TB_JUMP:
3318 /* nothing more to generate */
3319 break;
3320 }
3321 }
2e70f6ef 3322 gen_icount_end(tb, num_insns);
8170028d
TS
3323 *gen_opc_ptr = INDEX_op_end;
3324 if (search_pc) {
3325 j = gen_opc_ptr - gen_opc_buf;
3326 lj++;
3327 while (lj <= j)
3328 gen_opc_instr_start[lj++] = 0;
3329 } else {
3330 tb->size = dc->pc - pc_start;
2e70f6ef 3331 tb->icount = num_insns;
8170028d
TS
3332 }
3333
3334#ifdef DEBUG_DISAS
a1aebcb8 3335#if !DISAS_CRIS
8fec2b8c 3336 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
3337 log_target_disas(pc_start, dc->pc - pc_start, 0);
3338 qemu_log("\nisize=%d osize=%zd\n",
b41f7df0 3339 dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
8170028d
TS
3340 }
3341#endif
a1aebcb8 3342#endif
8170028d
TS
3343}
3344
2cfc5f17 3345void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8170028d 3346{
2cfc5f17 3347 gen_intermediate_code_internal(env, tb, 0);
8170028d
TS
3348}
3349
2cfc5f17 3350void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8170028d 3351{
2cfc5f17 3352 gen_intermediate_code_internal(env, tb, 1);
8170028d
TS
3353}
3354
3355void cpu_dump_state (CPUState *env, FILE *f,
3356 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
3357 int flags)
3358{
3359 int i;
3360 uint32_t srs;
3361
3362 if (!env || !f)
3363 return;
3364
3365 cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
30abcfc7 3366 "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n",
9004627f 3367 env->pc, env->pregs[PR_CCS], env->btaken, env->btarget,
8170028d 3368 env->cc_op,
30abcfc7
EI
3369 env->cc_src, env->cc_dest, env->cc_result, env->cc_mask);
3370
8170028d
TS
3371
3372 for (i = 0; i < 16; i++) {
3373 cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
3374 if ((i + 1) % 4 == 0)
3375 cpu_fprintf(f, "\n");
3376 }
3377 cpu_fprintf(f, "\nspecial regs:\n");
3378 for (i = 0; i < 16; i++) {
3379 cpu_fprintf(f, "p%2.2d=%8.8x ", i, env->pregs[i]);
3380 if ((i + 1) % 4 == 0)
3381 cpu_fprintf(f, "\n");
3382 }
9004627f 3383 srs = env->pregs[PR_SRS];
b41f7df0 3384 cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
8170028d
TS
3385 if (srs < 256) {
3386 for (i = 0; i < 16; i++) {
3387 cpu_fprintf(f, "s%2.2d=%8.8x ",
3388 i, env->sregs[srs][i]);
3389 if ((i + 1) % 4 == 0)
3390 cpu_fprintf(f, "\n");
3391 }
3392 }
3393 cpu_fprintf(f, "\n\n");
3394
3395}
3396
aaed909a 3397CPUCRISState *cpu_cris_init (const char *cpu_model)
8170028d
TS
3398{
3399 CPUCRISState *env;
a7cfbba0 3400 static int tcg_initialized = 0;
a825e703 3401 int i;
8170028d
TS
3402
3403 env = qemu_mallocz(sizeof(CPUCRISState));
a7cfbba0 3404
8170028d 3405 cpu_exec_init(env);
a7cfbba0 3406 cpu_reset(env);
0bf46a40 3407 qemu_init_vcpu(env);
a7cfbba0
EI
3408
3409 if (tcg_initialized)
3410 return env;
3411
3412 tcg_initialized = 1;
05ba7d5f 3413
a7812ae4
PB
3414 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
3415 cc_x = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3416 offsetof(CPUState, cc_x), "cc_x");
a7812ae4 3417 cc_src = tcg_global_mem_new(TCG_AREG0,
a825e703 3418 offsetof(CPUState, cc_src), "cc_src");
a7812ae4 3419 cc_dest = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3420 offsetof(CPUState, cc_dest),
a825e703 3421 "cc_dest");
a7812ae4 3422 cc_result = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3423 offsetof(CPUState, cc_result),
a825e703 3424 "cc_result");
a7812ae4 3425 cc_op = tcg_global_mem_new(TCG_AREG0,
a825e703 3426 offsetof(CPUState, cc_op), "cc_op");
a7812ae4 3427 cc_size = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3428 offsetof(CPUState, cc_size),
a825e703 3429 "cc_size");
a7812ae4 3430 cc_mask = tcg_global_mem_new(TCG_AREG0,
a825e703
EI
3431 offsetof(CPUState, cc_mask),
3432 "cc_mask");
3433
a7812ae4 3434 env_pc = tcg_global_mem_new(TCG_AREG0,
30abcfc7
EI
3435 offsetof(CPUState, pc),
3436 "pc");
a7812ae4 3437 env_btarget = tcg_global_mem_new(TCG_AREG0,
30abcfc7
EI
3438 offsetof(CPUState, btarget),
3439 "btarget");
a7812ae4 3440 env_btaken = tcg_global_mem_new(TCG_AREG0,
2a44f7f1
EI
3441 offsetof(CPUState, btaken),
3442 "btaken");
a825e703 3443 for (i = 0; i < 16; i++) {
a7812ae4 3444 cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3445 offsetof(CPUState, regs[i]),
a825e703
EI
3446 regnames[i]);
3447 }
3448 for (i = 0; i < 16; i++) {
a7812ae4 3449 cpu_PR[i] = tcg_global_mem_new(TCG_AREG0,
30abcfc7 3450 offsetof(CPUState, pregs[i]),
a825e703
EI
3451 pregnames[i]);
3452 }
3453
a7812ae4
PB
3454#define GEN_HELPER 2
3455#include "helper.h"
dceaf394 3456
8170028d
TS
3457 return env;
3458}
3459
3460void cpu_reset (CPUCRISState *env)
3461{
eca1bdf4
AL
3462 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
3463 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
3464 log_cpu_state(env, 0);
3465 }
3466
8170028d
TS
3467 memset(env, 0, offsetof(CPUCRISState, breakpoints));
3468 tlb_flush(env, 1);
b41f7df0 3469
a855593c 3470 env->pregs[PR_VR] = 32;
b41f7df0
EI
3471#if defined(CONFIG_USER_ONLY)
3472 /* start in user mode with interrupts enabled. */
3473 env->pregs[PR_CCS] |= U_FLAG | I_FLAG;
3474#else
52819664 3475 cris_mmu_init(env);
b41f7df0
EI
3476 env->pregs[PR_CCS] = 0;
3477#endif
8170028d 3478}
d2856f1a
AJ
3479
3480void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
3481 unsigned long searched_pc, int pc_pos, void *puc)
3482{
17ac9754 3483 env->pc = gen_opc_pc[pc_pos];
d2856f1a 3484}