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