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