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