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