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