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