]> git.proxmox.com Git - mirror_qemu.git/blame - target-cris/translate.c
Control + i and [tab] share keycode in curses, simulate [tab].
[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);
f4b147f6 1931 tcg_temp_free(t0);
8170028d
TS
1932 return 2;
1933}
1934
1935static unsigned int dec_or_r(DisasContext *dc)
1936{
fb48f71b 1937 TCGv t[2];
8170028d
TS
1938 int size = memsize_zz(dc);
1939 DIS(fprintf (logfile, "or.%c $r%u, $r%u\n",
1940 memsize_char(size), dc->op1, dc->op2));
1941 cris_cc_mask(dc, CC_MASK_NZ);
fb48f71b
EI
1942 cris_alu_alloc_temps(dc, size, t);
1943 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1944 cris_alu(dc, CC_OP_OR, cpu_R[dc->op2], t[0], t[1], size);
1945 cris_alu_free_temps(dc, size, t);
8170028d
TS
1946 return 2;
1947}
1948
1949static unsigned int dec_addi_r(DisasContext *dc)
1950{
fb48f71b 1951 TCGv t0;
8170028d
TS
1952 DIS(fprintf (logfile, "addi.%c $r%u, $r%u\n",
1953 memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
1954 cris_cc_mask(dc, 0);
fb48f71b
EI
1955 t0 = tcg_temp_new(TCG_TYPE_TL);
1956 tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize));
1957 tcg_gen_add_tl(cpu_R[dc->op1], cpu_R[dc->op1], t0);
f4b147f6 1958 tcg_temp_free(t0);
8170028d
TS
1959 return 2;
1960}
1961
1962static unsigned int dec_addi_acr(DisasContext *dc)
1963{
fb48f71b 1964 TCGv t0;
8170028d 1965 DIS(fprintf (logfile, "addi.%c $r%u, $r%u, $acr\n",
b41f7df0 1966 memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
8170028d 1967 cris_cc_mask(dc, 0);
fb48f71b
EI
1968 t0 = tcg_temp_new(TCG_TYPE_TL);
1969 tcg_gen_shl_tl(t0, cpu_R[dc->op2], tcg_const_tl(dc->zzsize));
1970 tcg_gen_add_tl(cpu_R[R_ACR], cpu_R[dc->op1], t0);
f4b147f6 1971 tcg_temp_free(t0);
8170028d
TS
1972 return 2;
1973}
1974
1975static unsigned int dec_neg_r(DisasContext *dc)
1976{
fb48f71b 1977 TCGv t[2];
8170028d
TS
1978 int size = memsize_zz(dc);
1979 DIS(fprintf (logfile, "neg.%c $r%u, $r%u\n",
1980 memsize_char(size), dc->op1, dc->op2));
1981 cris_cc_mask(dc, CC_MASK_NZVC);
fb48f71b
EI
1982 cris_alu_alloc_temps(dc, size, t);
1983 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
30abcfc7 1984
fb48f71b
EI
1985 cris_alu(dc, CC_OP_NEG, cpu_R[dc->op2], t[0], t[1], size);
1986 cris_alu_free_temps(dc, size, t);
8170028d
TS
1987 return 2;
1988}
1989
1990static unsigned int dec_btst_r(DisasContext *dc)
1991{
31c18d87 1992 TCGv l0;
8170028d
TS
1993 DIS(fprintf (logfile, "btst $r%u, $r%u\n",
1994 dc->op1, dc->op2));
8170028d 1995 cris_cc_mask(dc, CC_MASK_NZ);
8170028d 1996
31c18d87
EI
1997 l0 = tcg_temp_local_new(TCG_TYPE_TL);
1998 cris_alu(dc, CC_OP_BTST, l0, cpu_R[dc->op2], cpu_R[dc->op1], 4);
b41f7df0 1999 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
31c18d87 2000 t_gen_mov_preg_TN(dc, PR_CCS, l0);
30abcfc7 2001 dc->flags_uptodate = 1;
31c18d87 2002 tcg_temp_free(l0);
8170028d
TS
2003 return 2;
2004}
2005
2006static unsigned int dec_sub_r(DisasContext *dc)
2007{
fb48f71b 2008 TCGv t[2];
8170028d
TS
2009 int size = memsize_zz(dc);
2010 DIS(fprintf (logfile, "sub.%c $r%u, $r%u\n",
2011 memsize_char(size), dc->op1, dc->op2));
2012 cris_cc_mask(dc, CC_MASK_NZVC);
fb48f71b
EI
2013 cris_alu_alloc_temps(dc, size, t);
2014 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
2015 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], size);
2016 cris_alu_free_temps(dc, size, t);
8170028d
TS
2017 return 2;
2018}
2019
2020/* Zero extension. From size to dword. */
2021static unsigned int dec_movu_r(DisasContext *dc)
2022{
fb48f71b 2023 TCGv t0;
8170028d
TS
2024 int size = memsize_z(dc);
2025 DIS(fprintf (logfile, "movu.%c $r%u, $r%u\n",
2026 memsize_char(size),
2027 dc->op1, dc->op2));
2028
2029 cris_cc_mask(dc, CC_MASK_NZ);
fb48f71b
EI
2030 t0 = tcg_temp_new(TCG_TYPE_TL);
2031 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0);
2032 cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
2033 tcg_temp_free(t0);
8170028d
TS
2034 return 2;
2035}
2036
2037/* Sign extension. From size to dword. */
2038static unsigned int dec_movs_r(DisasContext *dc)
2039{
fb48f71b 2040 TCGv t0;
8170028d
TS
2041 int size = memsize_z(dc);
2042 DIS(fprintf (logfile, "movs.%c $r%u, $r%u\n",
2043 memsize_char(size),
2044 dc->op1, dc->op2));
2045
2046 cris_cc_mask(dc, CC_MASK_NZ);
fb48f71b 2047 t0 = tcg_temp_new(TCG_TYPE_TL);
8170028d 2048 /* Size can only be qi or hi. */
fb48f71b 2049 t_gen_sext(t0, cpu_R[dc->op1], size);
30abcfc7 2050 cris_alu(dc, CC_OP_MOVE,
fb48f71b
EI
2051 cpu_R[dc->op2], cpu_R[dc->op1], t0, 4);
2052 tcg_temp_free(t0);
8170028d
TS
2053 return 2;
2054}
2055
2056/* zero extension. From size to dword. */
2057static unsigned int dec_addu_r(DisasContext *dc)
2058{
fb48f71b 2059 TCGv t0;
8170028d
TS
2060 int size = memsize_z(dc);
2061 DIS(fprintf (logfile, "addu.%c $r%u, $r%u\n",
2062 memsize_char(size),
2063 dc->op1, dc->op2));
2064
2065 cris_cc_mask(dc, CC_MASK_NZVC);
fb48f71b 2066 t0 = tcg_temp_new(TCG_TYPE_TL);
8170028d 2067 /* Size can only be qi or hi. */
fb48f71b 2068 t_gen_zext(t0, cpu_R[dc->op1], size);
30abcfc7 2069 cris_alu(dc, CC_OP_ADD,
fb48f71b
EI
2070 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
2071 tcg_temp_free(t0);
8170028d
TS
2072 return 2;
2073}
05ba7d5f 2074
8170028d
TS
2075/* Sign extension. From size to dword. */
2076static unsigned int dec_adds_r(DisasContext *dc)
2077{
fb48f71b 2078 TCGv t0;
8170028d
TS
2079 int size = memsize_z(dc);
2080 DIS(fprintf (logfile, "adds.%c $r%u, $r%u\n",
2081 memsize_char(size),
2082 dc->op1, dc->op2));
2083
2084 cris_cc_mask(dc, CC_MASK_NZVC);
fb48f71b 2085 t0 = tcg_temp_new(TCG_TYPE_TL);
8170028d 2086 /* Size can only be qi or hi. */
fb48f71b 2087 t_gen_sext(t0, cpu_R[dc->op1], size);
30abcfc7 2088 cris_alu(dc, CC_OP_ADD,
fb48f71b
EI
2089 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
2090 tcg_temp_free(t0);
8170028d
TS
2091 return 2;
2092}
2093
2094/* Zero extension. From size to dword. */
2095static unsigned int dec_subu_r(DisasContext *dc)
2096{
fb48f71b 2097 TCGv t0;
8170028d
TS
2098 int size = memsize_z(dc);
2099 DIS(fprintf (logfile, "subu.%c $r%u, $r%u\n",
2100 memsize_char(size),
2101 dc->op1, dc->op2));
2102
2103 cris_cc_mask(dc, CC_MASK_NZVC);
fb48f71b 2104 t0 = tcg_temp_new(TCG_TYPE_TL);
8170028d 2105 /* Size can only be qi or hi. */
fb48f71b 2106 t_gen_zext(t0, cpu_R[dc->op1], size);
30abcfc7 2107 cris_alu(dc, CC_OP_SUB,
fb48f71b
EI
2108 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
2109 tcg_temp_free(t0);
8170028d
TS
2110 return 2;
2111}
2112
2113/* Sign extension. From size to dword. */
2114static unsigned int dec_subs_r(DisasContext *dc)
2115{
fb48f71b 2116 TCGv t0;
8170028d
TS
2117 int size = memsize_z(dc);
2118 DIS(fprintf (logfile, "subs.%c $r%u, $r%u\n",
2119 memsize_char(size),
2120 dc->op1, dc->op2));
2121
2122 cris_cc_mask(dc, CC_MASK_NZVC);
fb48f71b 2123 t0 = tcg_temp_new(TCG_TYPE_TL);
8170028d 2124 /* Size can only be qi or hi. */
fb48f71b 2125 t_gen_sext(t0, cpu_R[dc->op1], size);
30abcfc7 2126 cris_alu(dc, CC_OP_SUB,
fb48f71b
EI
2127 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
2128 tcg_temp_free(t0);
8170028d
TS
2129 return 2;
2130}
2131
2132static unsigned int dec_setclrf(DisasContext *dc)
2133{
2134 uint32_t flags;
2135 int set = (~dc->opcode >> 2) & 1;
2136
fb48f71b 2137
8170028d
TS
2138 flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4)
2139 | EXTRACT_FIELD(dc->ir, 0, 3);
cf1d97f0 2140 if (set && flags == 0) {
8170028d 2141 DIS(fprintf (logfile, "nop\n"));
30abcfc7 2142 return 2;
cf1d97f0 2143 } else if (!set && (flags & 0x20)) {
8170028d 2144 DIS(fprintf (logfile, "di\n"));
cf1d97f0
EI
2145 }
2146 else {
8170028d 2147 DIS(fprintf (logfile, "%sf %x\n",
cf1d97f0 2148 set ? "set" : "clr",
8170028d 2149 flags));
cf1d97f0 2150 }
8170028d 2151
fb48f71b 2152 /* User space is not allowed to touch these. Silently ignore. */
2a44f7f1 2153 if (dc->tb_flags & U_FLAG) {
a1aebcb8 2154 flags &= ~(S_FLAG | I_FLAG | U_FLAG);
2a44f7f1
EI
2155 }
2156
2157 if (flags & X_FLAG) {
30abcfc7 2158 dc->flagx_known = 1;
2a44f7f1
EI
2159 if (set)
2160 dc->flags_x = X_FLAG;
2161 else
2162 dc->flags_x = 0;
8170028d
TS
2163 }
2164
2a44f7f1
EI
2165 /* Break the TB if the P flag changes. */
2166 if (flags & P_FLAG) {
2167 if ((set && !(dc->tb_flags & P_FLAG))
2168 || (!set && (dc->tb_flags & P_FLAG))) {
2169 tcg_gen_movi_tl(env_pc, dc->pc + 2);
2170 dc->is_jmp = DISAS_UPDATE;
2171 dc->cpustate_changed = 1;
2172 }
2173 }
a1aebcb8
EI
2174 if (flags & S_FLAG) {
2175 dc->cpustate_changed = 1;
2176 }
2a44f7f1
EI
2177
2178
8170028d
TS
2179 /* Simply decode the flags. */
2180 cris_evaluate_flags (dc);
b41f7df0 2181 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
30abcfc7 2182 cris_update_cc_x(dc);
b41f7df0
EI
2183 tcg_gen_movi_tl(cc_op, dc->cc_op);
2184
dceaf394 2185 if (set) {
2a44f7f1 2186 if (!(dc->tb_flags & U_FLAG) && (flags & U_FLAG)) {
dceaf394
EI
2187 /* Enter user mode. */
2188 t_gen_mov_env_TN(ksp, cpu_R[R_SP]);
2189 tcg_gen_mov_tl(cpu_R[R_SP], cpu_PR[PR_USP]);
2a44f7f1 2190 dc->cpustate_changed = 1;
dceaf394
EI
2191 }
2192 tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags);
2193 }
8170028d 2194 else
dceaf394
EI
2195 tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags);
2196
30abcfc7 2197 dc->flags_uptodate = 1;
b41f7df0 2198 dc->clear_x = 0;
8170028d
TS
2199 return 2;
2200}
2201
2202static unsigned int dec_move_rs(DisasContext *dc)
2203{
2204 DIS(fprintf (logfile, "move $r%u, $s%u\n", dc->op1, dc->op2));
2205 cris_cc_mask(dc, 0);
dceaf394
EI
2206 tcg_gen_helper_0_2(helper_movl_sreg_reg,
2207 tcg_const_tl(dc->op2), tcg_const_tl(dc->op1));
8170028d
TS
2208 return 2;
2209}
2210static unsigned int dec_move_sr(DisasContext *dc)
2211{
05ba7d5f 2212 DIS(fprintf (logfile, "move $s%u, $r%u\n", dc->op2, dc->op1));
8170028d 2213 cris_cc_mask(dc, 0);
dceaf394
EI
2214 tcg_gen_helper_0_2(helper_movl_reg_sreg,
2215 tcg_const_tl(dc->op1), tcg_const_tl(dc->op2));
8170028d
TS
2216 return 2;
2217}
dceaf394 2218
8170028d
TS
2219static unsigned int dec_move_rp(DisasContext *dc)
2220{
fb48f71b 2221 TCGv t[2];
8170028d
TS
2222 DIS(fprintf (logfile, "move $r%u, $p%u\n", dc->op1, dc->op2));
2223 cris_cc_mask(dc, 0);
b41f7df0 2224
fb48f71b 2225 t[0] = tcg_temp_new(TCG_TYPE_TL);
b41f7df0
EI
2226 if (dc->op2 == PR_CCS) {
2227 cris_evaluate_flags(dc);
fb48f71b 2228 t_gen_mov_TN_reg(t[0], dc->op1);
2a44f7f1 2229 if (dc->tb_flags & U_FLAG) {
fb48f71b 2230 t[1] = tcg_temp_new(TCG_TYPE_TL);
b41f7df0 2231 /* User space is not allowed to touch all flags. */
fb48f71b
EI
2232 tcg_gen_andi_tl(t[0], t[0], 0x39f);
2233 tcg_gen_andi_tl(t[1], cpu_PR[PR_CCS], ~0x39f);
2234 tcg_gen_or_tl(t[0], t[1], t[0]);
2235 tcg_temp_free(t[1]);
b41f7df0
EI
2236 }
2237 }
2238 else
fb48f71b 2239 t_gen_mov_TN_reg(t[0], dc->op1);
b41f7df0 2240
fb48f71b 2241 t_gen_mov_preg_TN(dc, dc->op2, t[0]);
b41f7df0
EI
2242 if (dc->op2 == PR_CCS) {
2243 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
30abcfc7 2244 dc->flags_uptodate = 1;
b41f7df0 2245 }
fb48f71b 2246 tcg_temp_free(t[0]);
8170028d
TS
2247 return 2;
2248}
2249static unsigned int dec_move_pr(DisasContext *dc)
2250{
fb48f71b 2251 TCGv t0;
8170028d
TS
2252 DIS(fprintf (logfile, "move $p%u, $r%u\n", dc->op1, dc->op2));
2253 cris_cc_mask(dc, 0);
2a44f7f1
EI
2254
2255 if (dc->op2 == PR_CCS)
b41f7df0 2256 cris_evaluate_flags(dc);
2a44f7f1 2257
fb48f71b
EI
2258 t0 = tcg_temp_new(TCG_TYPE_TL);
2259 t_gen_mov_TN_preg(t0, dc->op2);
2a44f7f1 2260 cris_alu(dc, CC_OP_MOVE,
fb48f71b
EI
2261 cpu_R[dc->op1], cpu_R[dc->op1], t0, preg_sizes[dc->op2]);
2262 tcg_temp_free(t0);
8170028d
TS
2263 return 2;
2264}
2265
2266static unsigned int dec_move_mr(DisasContext *dc)
2267{
2268 int memsize = memsize_zz(dc);
2269 int insn_len;
2270 DIS(fprintf (logfile, "move.%c [$r%u%s, $r%u\n",
2271 memsize_char(memsize),
2272 dc->op1, dc->postinc ? "+]" : "]",
2273 dc->op2));
2274
30abcfc7
EI
2275 if (memsize == 4) {
2276 insn_len = dec_prep_move_m(dc, 0, 4, cpu_R[dc->op2]);
2277 cris_cc_mask(dc, CC_MASK_NZ);
2278 cris_update_cc_op(dc, CC_OP_MOVE, 4);
2279 cris_update_cc_x(dc);
2280 cris_update_result(dc, cpu_R[dc->op2]);
2281 }
2282 else {
fb48f71b
EI
2283 TCGv t0;
2284
2285 t0 = tcg_temp_new(TCG_TYPE_TL);
2286 insn_len = dec_prep_move_m(dc, 0, memsize, t0);
30abcfc7
EI
2287 cris_cc_mask(dc, CC_MASK_NZ);
2288 cris_alu(dc, CC_OP_MOVE,
fb48f71b
EI
2289 cpu_R[dc->op2], cpu_R[dc->op2], t0, memsize);
2290 tcg_temp_free(t0);
30abcfc7 2291 }
8170028d
TS
2292 do_postinc(dc, memsize);
2293 return insn_len;
2294}
2295
31c18d87
EI
2296static inline void cris_alu_m_alloc_temps(TCGv *t)
2297{
2298 t[0] = tcg_temp_new(TCG_TYPE_TL);
2299 t[1] = tcg_temp_new(TCG_TYPE_TL);
2300}
2301
2302static inline void cris_alu_m_free_temps(TCGv *t)
2303{
2304 tcg_temp_free(t[0]);
2305 tcg_temp_free(t[1]);
2306}
2307
8170028d
TS
2308static unsigned int dec_movs_m(DisasContext *dc)
2309{
31c18d87 2310 TCGv t[2];
8170028d
TS
2311 int memsize = memsize_z(dc);
2312 int insn_len;
2313 DIS(fprintf (logfile, "movs.%c [$r%u%s, $r%u\n",
2314 memsize_char(memsize),
2315 dc->op1, dc->postinc ? "+]" : "]",
2316 dc->op2));
2317
31c18d87 2318 cris_alu_m_alloc_temps(t);
8170028d 2319 /* sign extend. */
31c18d87 2320 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
b41f7df0 2321 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7 2322 cris_alu(dc, CC_OP_MOVE,
31c18d87 2323 cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2324 do_postinc(dc, memsize);
31c18d87 2325 cris_alu_m_free_temps(t);
8170028d
TS
2326 return insn_len;
2327}
2328
2329static unsigned int dec_addu_m(DisasContext *dc)
2330{
31c18d87 2331 TCGv t[2];
8170028d
TS
2332 int memsize = memsize_z(dc);
2333 int insn_len;
2334 DIS(fprintf (logfile, "addu.%c [$r%u%s, $r%u\n",
2335 memsize_char(memsize),
2336 dc->op1, dc->postinc ? "+]" : "]",
2337 dc->op2));
2338
31c18d87 2339 cris_alu_m_alloc_temps(t);
8170028d 2340 /* sign extend. */
31c18d87 2341 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2342 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7 2343 cris_alu(dc, CC_OP_ADD,
31c18d87 2344 cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2345 do_postinc(dc, memsize);
31c18d87 2346 cris_alu_m_free_temps(t);
8170028d
TS
2347 return insn_len;
2348}
2349
2350static unsigned int dec_adds_m(DisasContext *dc)
2351{
31c18d87 2352 TCGv t[2];
8170028d
TS
2353 int memsize = memsize_z(dc);
2354 int insn_len;
2355 DIS(fprintf (logfile, "adds.%c [$r%u%s, $r%u\n",
2356 memsize_char(memsize),
2357 dc->op1, dc->postinc ? "+]" : "]",
2358 dc->op2));
2359
31c18d87 2360 cris_alu_m_alloc_temps(t);
8170028d 2361 /* sign extend. */
31c18d87 2362 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
b41f7df0 2363 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2364 cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2365 do_postinc(dc, memsize);
31c18d87 2366 cris_alu_m_free_temps(t);
8170028d
TS
2367 return insn_len;
2368}
2369
2370static unsigned int dec_subu_m(DisasContext *dc)
2371{
31c18d87 2372 TCGv t[2];
8170028d
TS
2373 int memsize = memsize_z(dc);
2374 int insn_len;
2375 DIS(fprintf (logfile, "subu.%c [$r%u%s, $r%u\n",
2376 memsize_char(memsize),
2377 dc->op1, dc->postinc ? "+]" : "]",
2378 dc->op2));
2379
31c18d87 2380 cris_alu_m_alloc_temps(t);
8170028d 2381 /* sign extend. */
31c18d87 2382 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2383 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2384 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2385 do_postinc(dc, memsize);
31c18d87 2386 cris_alu_m_free_temps(t);
8170028d
TS
2387 return insn_len;
2388}
2389
2390static unsigned int dec_subs_m(DisasContext *dc)
2391{
31c18d87 2392 TCGv t[2];
8170028d
TS
2393 int memsize = memsize_z(dc);
2394 int insn_len;
2395 DIS(fprintf (logfile, "subs.%c [$r%u%s, $r%u\n",
2396 memsize_char(memsize),
2397 dc->op1, dc->postinc ? "+]" : "]",
2398 dc->op2));
2399
31c18d87 2400 cris_alu_m_alloc_temps(t);
8170028d 2401 /* sign extend. */
31c18d87 2402 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
b41f7df0 2403 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2404 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2405 do_postinc(dc, memsize);
31c18d87 2406 cris_alu_m_free_temps(t);
8170028d
TS
2407 return insn_len;
2408}
2409
2410static unsigned int dec_movu_m(DisasContext *dc)
2411{
31c18d87 2412 TCGv t[2];
8170028d
TS
2413 int memsize = memsize_z(dc);
2414 int insn_len;
2415
2416 DIS(fprintf (logfile, "movu.%c [$r%u%s, $r%u\n",
2417 memsize_char(memsize),
2418 dc->op1, dc->postinc ? "+]" : "]",
2419 dc->op2));
2420
31c18d87
EI
2421 cris_alu_m_alloc_temps(t);
2422 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2423 cris_cc_mask(dc, CC_MASK_NZ);
31c18d87 2424 cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2425 do_postinc(dc, memsize);
31c18d87 2426 cris_alu_m_free_temps(t);
8170028d
TS
2427 return insn_len;
2428}
2429
2430static unsigned int dec_cmpu_m(DisasContext *dc)
2431{
31c18d87 2432 TCGv t[2];
8170028d
TS
2433 int memsize = memsize_z(dc);
2434 int insn_len;
2435 DIS(fprintf (logfile, "cmpu.%c [$r%u%s, $r%u\n",
2436 memsize_char(memsize),
2437 dc->op1, dc->postinc ? "+]" : "]",
2438 dc->op2));
2439
31c18d87
EI
2440 cris_alu_m_alloc_temps(t);
2441 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2442 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2443 cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
8170028d 2444 do_postinc(dc, memsize);
31c18d87 2445 cris_alu_m_free_temps(t);
8170028d
TS
2446 return insn_len;
2447}
2448
2449static unsigned int dec_cmps_m(DisasContext *dc)
2450{
31c18d87 2451 TCGv t[2];
8170028d
TS
2452 int memsize = memsize_z(dc);
2453 int insn_len;
2454 DIS(fprintf (logfile, "cmps.%c [$r%u%s, $r%u\n",
2455 memsize_char(memsize),
2456 dc->op1, dc->postinc ? "+]" : "]",
2457 dc->op2));
2458
31c18d87
EI
2459 cris_alu_m_alloc_temps(t);
2460 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
b41f7df0 2461 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7 2462 cris_alu(dc, CC_OP_CMP,
31c18d87 2463 cpu_R[dc->op2], cpu_R[dc->op2], t[1],
30abcfc7 2464 memsize_zz(dc));
8170028d 2465 do_postinc(dc, memsize);
31c18d87 2466 cris_alu_m_free_temps(t);
8170028d
TS
2467 return insn_len;
2468}
2469
2470static unsigned int dec_cmp_m(DisasContext *dc)
2471{
31c18d87 2472 TCGv t[2];
8170028d
TS
2473 int memsize = memsize_zz(dc);
2474 int insn_len;
2475 DIS(fprintf (logfile, "cmp.%c [$r%u%s, $r%u\n",
2476 memsize_char(memsize),
2477 dc->op1, dc->postinc ? "+]" : "]",
2478 dc->op2));
2479
31c18d87
EI
2480 cris_alu_m_alloc_temps(t);
2481 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2482 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7 2483 cris_alu(dc, CC_OP_CMP,
31c18d87 2484 cpu_R[dc->op2], cpu_R[dc->op2], t[1],
30abcfc7 2485 memsize_zz(dc));
8170028d 2486 do_postinc(dc, memsize);
31c18d87 2487 cris_alu_m_free_temps(t);
8170028d
TS
2488 return insn_len;
2489}
2490
2491static unsigned int dec_test_m(DisasContext *dc)
2492{
31c18d87 2493 TCGv t[2];
8170028d
TS
2494 int memsize = memsize_zz(dc);
2495 int insn_len;
2496 DIS(fprintf (logfile, "test.%d [$r%u%s] op2=%x\n",
2497 memsize_char(memsize),
2498 dc->op1, dc->postinc ? "+]" : "]",
2499 dc->op2));
2500
dceaf394
EI
2501 cris_evaluate_flags(dc);
2502
31c18d87
EI
2503 cris_alu_m_alloc_temps(t);
2504 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
8170028d 2505 cris_cc_mask(dc, CC_MASK_NZ);
dceaf394 2506 tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3);
b41f7df0 2507
30abcfc7 2508 cris_alu(dc, CC_OP_CMP,
31c18d87 2509 cpu_R[dc->op2], t[1], tcg_const_tl(0), memsize_zz(dc));
8170028d 2510 do_postinc(dc, memsize);
31c18d87 2511 cris_alu_m_free_temps(t);
8170028d
TS
2512 return insn_len;
2513}
2514
2515static unsigned int dec_and_m(DisasContext *dc)
2516{
31c18d87 2517 TCGv t[2];
8170028d
TS
2518 int memsize = memsize_zz(dc);
2519 int insn_len;
2520 DIS(fprintf (logfile, "and.%d [$r%u%s, $r%u\n",
2521 memsize_char(memsize),
2522 dc->op1, dc->postinc ? "+]" : "]",
2523 dc->op2));
2524
31c18d87
EI
2525 cris_alu_m_alloc_temps(t);
2526 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2527 cris_cc_mask(dc, CC_MASK_NZ);
31c18d87 2528 cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
8170028d 2529 do_postinc(dc, memsize);
31c18d87 2530 cris_alu_m_free_temps(t);
8170028d
TS
2531 return insn_len;
2532}
2533
2534static unsigned int dec_add_m(DisasContext *dc)
2535{
31c18d87 2536 TCGv t[2];
8170028d
TS
2537 int memsize = memsize_zz(dc);
2538 int insn_len;
2539 DIS(fprintf (logfile, "add.%d [$r%u%s, $r%u\n",
2540 memsize_char(memsize),
2541 dc->op1, dc->postinc ? "+]" : "]",
2542 dc->op2));
2543
31c18d87
EI
2544 cris_alu_m_alloc_temps(t);
2545 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2546 cris_cc_mask(dc, CC_MASK_NZVC);
30abcfc7 2547 cris_alu(dc, CC_OP_ADD,
31c18d87 2548 cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
8170028d 2549 do_postinc(dc, memsize);
31c18d87 2550 cris_alu_m_free_temps(t);
8170028d
TS
2551 return insn_len;
2552}
2553
2554static unsigned int dec_addo_m(DisasContext *dc)
2555{
31c18d87 2556 TCGv t[2];
8170028d
TS
2557 int memsize = memsize_zz(dc);
2558 int insn_len;
2559 DIS(fprintf (logfile, "add.%d [$r%u%s, $r%u\n",
2560 memsize_char(memsize),
2561 dc->op1, dc->postinc ? "+]" : "]",
2562 dc->op2));
2563
31c18d87
EI
2564 cris_alu_m_alloc_temps(t);
2565 insn_len = dec_prep_alu_m(dc, 1, memsize, t[0], t[1]);
b41f7df0 2566 cris_cc_mask(dc, 0);
31c18d87 2567 cris_alu(dc, CC_OP_ADD, cpu_R[R_ACR], t[0], t[1], 4);
8170028d 2568 do_postinc(dc, memsize);
31c18d87 2569 cris_alu_m_free_temps(t);
8170028d
TS
2570 return insn_len;
2571}
2572
2573static unsigned int dec_bound_m(DisasContext *dc)
2574{
31c18d87 2575 TCGv l[2];
8170028d
TS
2576 int memsize = memsize_zz(dc);
2577 int insn_len;
2578 DIS(fprintf (logfile, "bound.%d [$r%u%s, $r%u\n",
2579 memsize_char(memsize),
2580 dc->op1, dc->postinc ? "+]" : "]",
2581 dc->op2));
2582
31c18d87
EI
2583 l[0] = tcg_temp_local_new(TCG_TYPE_TL);
2584 l[1] = tcg_temp_local_new(TCG_TYPE_TL);
2585 insn_len = dec_prep_alu_m(dc, 0, memsize, l[0], l[1]);
b41f7df0 2586 cris_cc_mask(dc, CC_MASK_NZ);
31c18d87 2587 cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], l[0], l[1], 4);
8170028d 2588 do_postinc(dc, memsize);
31c18d87
EI
2589 tcg_temp_free(l[0]);
2590 tcg_temp_free(l[1]);
8170028d
TS
2591 return insn_len;
2592}
2593
2594static unsigned int dec_addc_mr(DisasContext *dc)
2595{
31c18d87 2596 TCGv t[2];
8170028d
TS
2597 int insn_len = 2;
2598 DIS(fprintf (logfile, "addc [$r%u%s, $r%u\n",
2599 dc->op1, dc->postinc ? "+]" : "]",
2600 dc->op2));
2601
2602 cris_evaluate_flags(dc);
31c18d87
EI
2603 cris_alu_m_alloc_temps(t);
2604 insn_len = dec_prep_alu_m(dc, 0, 4, t[0], t[1]);
b41f7df0 2605 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2606 cris_alu(dc, CC_OP_ADDC, cpu_R[dc->op2], t[0], t[1], 4);
8170028d 2607 do_postinc(dc, 4);
31c18d87 2608 cris_alu_m_free_temps(t);
8170028d
TS
2609 return insn_len;
2610}
2611
2612static unsigned int dec_sub_m(DisasContext *dc)
2613{
31c18d87 2614 TCGv t[2];
8170028d
TS
2615 int memsize = memsize_zz(dc);
2616 int insn_len;
2617 DIS(fprintf (logfile, "sub.%c [$r%u%s, $r%u ir=%x zz=%x\n",
2618 memsize_char(memsize),
2619 dc->op1, dc->postinc ? "+]" : "]",
2620 dc->op2, dc->ir, dc->zzsize));
2621
31c18d87
EI
2622 cris_alu_m_alloc_temps(t);
2623 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2624 cris_cc_mask(dc, CC_MASK_NZVC);
31c18d87 2625 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], memsize);
8170028d 2626 do_postinc(dc, memsize);
31c18d87 2627 cris_alu_m_free_temps(t);
8170028d
TS
2628 return insn_len;
2629}
2630
2631static unsigned int dec_or_m(DisasContext *dc)
2632{
31c18d87 2633 TCGv t[2];
8170028d
TS
2634 int memsize = memsize_zz(dc);
2635 int insn_len;
2636 DIS(fprintf (logfile, "or.%d [$r%u%s, $r%u pc=%x\n",
2637 memsize_char(memsize),
2638 dc->op1, dc->postinc ? "+]" : "]",
2639 dc->op2, dc->pc));
2640
31c18d87
EI
2641 cris_alu_m_alloc_temps(t);
2642 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0 2643 cris_cc_mask(dc, CC_MASK_NZ);
30abcfc7 2644 cris_alu(dc, CC_OP_OR,
31c18d87 2645 cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
8170028d 2646 do_postinc(dc, memsize);
31c18d87 2647 cris_alu_m_free_temps(t);
8170028d
TS
2648 return insn_len;
2649}
2650
2651static unsigned int dec_move_mp(DisasContext *dc)
2652{
31c18d87 2653 TCGv t[2];
8170028d
TS
2654 int memsize = memsize_zz(dc);
2655 int insn_len = 2;
2656
2657 DIS(fprintf (logfile, "move.%c [$r%u%s, $p%u\n",
2658 memsize_char(memsize),
2659 dc->op1,
2660 dc->postinc ? "+]" : "]",
2661 dc->op2));
2662
31c18d87
EI
2663 cris_alu_m_alloc_temps(t);
2664 insn_len = dec_prep_alu_m(dc, 0, memsize, t[0], t[1]);
b41f7df0
EI
2665 cris_cc_mask(dc, 0);
2666 if (dc->op2 == PR_CCS) {
2667 cris_evaluate_flags(dc);
2a44f7f1 2668 if (dc->tb_flags & U_FLAG) {
b41f7df0 2669 /* User space is not allowed to touch all flags. */
31c18d87
EI
2670 tcg_gen_andi_tl(t[1], t[1], 0x39f);
2671 tcg_gen_andi_tl(t[0], cpu_PR[PR_CCS], ~0x39f);
2672 tcg_gen_or_tl(t[1], t[0], t[1]);
b41f7df0
EI
2673 }
2674 }
2675
31c18d87 2676 t_gen_mov_preg_TN(dc, dc->op2, t[1]);
8170028d
TS
2677
2678 do_postinc(dc, memsize);
31c18d87 2679 cris_alu_m_free_temps(t);
8170028d
TS
2680 return insn_len;
2681}
2682
2683static unsigned int dec_move_pm(DisasContext *dc)
2684{
31c18d87 2685 TCGv t0;
8170028d
TS
2686 int memsize;
2687
2688 memsize = preg_sizes[dc->op2];
2689
fd56059f
AZ
2690 DIS(fprintf (logfile, "move.%c $p%u, [$r%u%s\n",
2691 memsize_char(memsize),
2692 dc->op2, dc->op1, dc->postinc ? "+]" : "]"));
8170028d 2693
fd56059f 2694 /* prepare store. Address in T0, value in T1. */
17ac9754
EI
2695 if (dc->op2 == PR_CCS)
2696 cris_evaluate_flags(dc);
31c18d87
EI
2697 t0 = tcg_temp_new(TCG_TYPE_TL);
2698 t_gen_mov_TN_preg(t0, dc->op2);
30abcfc7 2699 cris_flush_cc_state(dc);
31c18d87
EI
2700 gen_store(dc, cpu_R[dc->op1], t0, memsize);
2701 tcg_temp_free(t0);
17ac9754 2702
b41f7df0 2703 cris_cc_mask(dc, 0);
8170028d 2704 if (dc->postinc)
17ac9754 2705 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize);
8170028d
TS
2706 return 2;
2707}
2708
2709static unsigned int dec_movem_mr(DisasContext *dc)
2710{
17ac9754 2711 TCGv tmp[16];
31c18d87 2712 TCGv addr;
8170028d 2713 int i;
28de16da 2714 int nr = dc->op2 + 1;
8170028d
TS
2715
2716 DIS(fprintf (logfile, "movem [$r%u%s, $r%u\n", dc->op1,
2717 dc->postinc ? "+]" : "]", dc->op2));
2718
31c18d87 2719 addr = tcg_temp_new(TCG_TYPE_TL);
28de16da 2720 /* There are probably better ways of doing this. */
30abcfc7 2721 cris_flush_cc_state(dc);
28de16da
EI
2722 for (i = 0; i < (nr >> 1); i++) {
2723 tmp[i] = tcg_temp_new(TCG_TYPE_I64);
31c18d87
EI
2724 tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
2725 gen_load(dc, tmp[i], addr, 8, 0);
28de16da
EI
2726 }
2727 if (nr & 1) {
2728 tmp[i] = tcg_temp_new(TCG_TYPE_I32);
31c18d87
EI
2729 tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
2730 gen_load(dc, tmp[i], addr, 4, 0);
8170028d 2731 }
31c18d87 2732 tcg_temp_free(addr);
17ac9754 2733
28de16da
EI
2734 for (i = 0; i < (nr >> 1); i++) {
2735 tcg_gen_trunc_i64_i32(cpu_R[i * 2], tmp[i]);
2736 tcg_gen_shri_i64(tmp[i], tmp[i], 32);
2737 tcg_gen_trunc_i64_i32(cpu_R[i * 2 + 1], tmp[i]);
2738 tcg_temp_free(tmp[i]);
2739 }
2740 if (nr & 1) {
2741 tcg_gen_mov_tl(cpu_R[dc->op2], tmp[i]);
30abcfc7 2742 tcg_temp_free(tmp[i]);
17ac9754
EI
2743 }
2744
05ba7d5f
EI
2745 /* writeback the updated pointer value. */
2746 if (dc->postinc)
28de16da 2747 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], nr * 4);
b41f7df0
EI
2748
2749 /* gen_load might want to evaluate the previous insns flags. */
2750 cris_cc_mask(dc, 0);
8170028d
TS
2751 return 2;
2752}
2753
2754static unsigned int dec_movem_rm(DisasContext *dc)
2755{
30abcfc7 2756 TCGv tmp;
31c18d87 2757 TCGv addr;
8170028d
TS
2758 int i;
2759
2760 DIS(fprintf (logfile, "movem $r%u, [$r%u%s\n", dc->op2, dc->op1,
2761 dc->postinc ? "+]" : "]"));
2762
30abcfc7
EI
2763 cris_flush_cc_state(dc);
2764
2765 tmp = tcg_temp_new(TCG_TYPE_TL);
31c18d87 2766 addr = tcg_temp_new(TCG_TYPE_TL);
30abcfc7 2767 tcg_gen_movi_tl(tmp, 4);
31c18d87 2768 tcg_gen_mov_tl(addr, cpu_R[dc->op1]);
8170028d 2769 for (i = 0; i <= dc->op2; i++) {
17ac9754 2770 /* Displace addr. */
8170028d 2771 /* Perform the store. */
31c18d87
EI
2772 gen_store(dc, addr, cpu_R[i], 4);
2773 tcg_gen_add_tl(addr, addr, tmp);
8170028d 2774 }
17ac9754 2775 if (dc->postinc)
31c18d87 2776 tcg_gen_mov_tl(cpu_R[dc->op1], addr);
b41f7df0 2777 cris_cc_mask(dc, 0);
30abcfc7 2778 tcg_temp_free(tmp);
31c18d87 2779 tcg_temp_free(addr);
8170028d
TS
2780 return 2;
2781}
2782
2783static unsigned int dec_move_rm(DisasContext *dc)
2784{
2785 int memsize;
2786
2787 memsize = memsize_zz(dc);
2788
2789 DIS(fprintf (logfile, "move.%d $r%u, [$r%u]\n",
2790 memsize, dc->op2, dc->op1));
2791
8170028d 2792 /* prepare store. */
30abcfc7 2793 cris_flush_cc_state(dc);
17ac9754
EI
2794 gen_store(dc, cpu_R[dc->op1], cpu_R[dc->op2], memsize);
2795
8170028d 2796 if (dc->postinc)
17ac9754 2797 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize);
b41f7df0 2798 cris_cc_mask(dc, 0);
8170028d
TS
2799 return 2;
2800}
2801
8170028d
TS
2802static unsigned int dec_lapcq(DisasContext *dc)
2803{
2804 DIS(fprintf (logfile, "lapcq %x, $r%u\n",
2805 dc->pc + dc->op1*2, dc->op2));
2806 cris_cc_mask(dc, 0);
30abcfc7 2807 tcg_gen_movi_tl(cpu_R[dc->op2], dc->pc + dc->op1 * 2);
8170028d
TS
2808 return 2;
2809}
2810
2811static unsigned int dec_lapc_im(DisasContext *dc)
2812{
2813 unsigned int rd;
2814 int32_t imm;
b41f7df0 2815 int32_t pc;
8170028d
TS
2816
2817 rd = dc->op2;
2818
2819 cris_cc_mask(dc, 0);
2820 imm = ldl_code(dc->pc + 2);
2821 DIS(fprintf (logfile, "lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2));
b41f7df0
EI
2822
2823 pc = dc->pc;
2824 pc += imm;
2825 t_gen_mov_reg_TN(rd, tcg_const_tl(pc));
05ba7d5f 2826 return 6;
8170028d
TS
2827}
2828
2829/* Jump to special reg. */
2830static unsigned int dec_jump_p(DisasContext *dc)
2831{
2832 DIS(fprintf (logfile, "jump $p%u\n", dc->op2));
b41f7df0 2833
17ac9754
EI
2834 if (dc->op2 == PR_CCS)
2835 cris_evaluate_flags(dc);
31c18d87 2836 t_gen_mov_TN_preg(env_btarget, dc->op2);
b41f7df0 2837 /* rete will often have low bit set to indicate delayslot. */
31c18d87 2838 tcg_gen_andi_tl(env_btarget, env_btarget, ~1);
17ac9754 2839 cris_cc_mask(dc, 0);
2a44f7f1 2840 cris_prepare_jmp(dc, JMP_INDIRECT);
8170028d
TS
2841 return 2;
2842}
2843
2844/* Jump and save. */
2845static unsigned int dec_jas_r(DisasContext *dc)
2846{
2847 DIS(fprintf (logfile, "jas $r%u, $p%u\n", dc->op1, dc->op2));
2848 cris_cc_mask(dc, 0);
b41f7df0
EI
2849 /* Store the return address in Pd. */
2850 tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
2851 if (dc->op2 > 15)
2852 abort();
30abcfc7 2853 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4));
b41f7df0 2854
2a44f7f1 2855 cris_prepare_jmp(dc, JMP_INDIRECT);
8170028d
TS
2856 return 2;
2857}
2858
2859static unsigned int dec_jas_im(DisasContext *dc)
2860{
2861 uint32_t imm;
2862
2863 imm = ldl_code(dc->pc + 2);
2864
2865 DIS(fprintf (logfile, "jas 0x%x\n", imm));
2866 cris_cc_mask(dc, 0);
17ac9754 2867 /* Store the return address in Pd. */
cf1d97f0 2868 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
2a44f7f1
EI
2869
2870 dc->jmp_pc = imm;
2871 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2872 return 6;
2873}
2874
2875static unsigned int dec_jasc_im(DisasContext *dc)
2876{
2877 uint32_t imm;
2878
2879 imm = ldl_code(dc->pc + 2);
2880
2881 DIS(fprintf (logfile, "jasc 0x%x\n", imm));
2882 cris_cc_mask(dc, 0);
17ac9754 2883 /* Store the return address in Pd. */
2a44f7f1
EI
2884 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8 + 4));
2885
2886 dc->jmp_pc = imm;
2887 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2888 return 6;
2889}
2890
2891static unsigned int dec_jasc_r(DisasContext *dc)
2892{
2893 DIS(fprintf (logfile, "jasc_r $r%u, $p%u\n", dc->op1, dc->op2));
2894 cris_cc_mask(dc, 0);
17ac9754 2895 /* Store the return address in Pd. */
2a44f7f1
EI
2896 tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
2897 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4 + 4));
2898 cris_prepare_jmp(dc, JMP_INDIRECT);
8170028d
TS
2899 return 2;
2900}
2901
2902static unsigned int dec_bcc_im(DisasContext *dc)
2903{
2904 int32_t offset;
2905 uint32_t cond = dc->op2;
2906
17ac9754 2907 offset = ldsw_code(dc->pc + 2);
8170028d
TS
2908
2909 DIS(fprintf (logfile, "b%s %d pc=%x dst=%x\n",
2910 cc_name(cond), offset,
2911 dc->pc, dc->pc + offset));
2912
2913 cris_cc_mask(dc, 0);
2914 /* op2 holds the condition-code. */
2915 cris_prepare_cc_branch (dc, offset, cond);
2916 return 4;
2917}
2918
2919static unsigned int dec_bas_im(DisasContext *dc)
2920{
2921 int32_t simm;
2922
2923
2924 simm = ldl_code(dc->pc + 2);
2925
2926 DIS(fprintf (logfile, "bas 0x%x, $p%u\n", dc->pc + simm, dc->op2));
2927 cris_cc_mask(dc, 0);
2a44f7f1
EI
2928 /* Store the return address in Pd. */
2929 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8));
2930
2931 dc->jmp_pc = dc->pc + simm;
2932 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2933 return 6;
2934}
2935
2936static unsigned int dec_basc_im(DisasContext *dc)
2937{
2938 int32_t simm;
2939 simm = ldl_code(dc->pc + 2);
2940
2941 DIS(fprintf (logfile, "basc 0x%x, $p%u\n", dc->pc + simm, dc->op2));
2942 cris_cc_mask(dc, 0);
2a44f7f1
EI
2943 /* Store the return address in Pd. */
2944 t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 12));
2945
2946 dc->jmp_pc = dc->pc + simm;
2947 cris_prepare_jmp(dc, JMP_DIRECT);
8170028d
TS
2948 return 6;
2949}
2950
2951static unsigned int dec_rfe_etc(DisasContext *dc)
2952{
8170028d
TS
2953 cris_cc_mask(dc, 0);
2954
2955 if (dc->op2 == 15) /* ignore halt. */
05ba7d5f 2956 return 2;
8170028d
TS
2957
2958 switch (dc->op2 & 7) {
2959 case 2:
2960 /* rfe. */
a1aebcb8 2961 DIS(fprintf(logfile, "rfe\n"));
8170028d 2962 cris_evaluate_flags(dc);
b41f7df0
EI
2963 tcg_gen_helper_0_0(helper_rfe);
2964 dc->is_jmp = DISAS_UPDATE;
8170028d
TS
2965 break;
2966 case 5:
2967 /* rfn. */
a1aebcb8 2968 DIS(fprintf(logfile, "rfn\n"));
a7cfbba0
EI
2969 cris_evaluate_flags(dc);
2970 tcg_gen_helper_0_0(helper_rfn);
2971 dc->is_jmp = DISAS_UPDATE;
8170028d
TS
2972 break;
2973 case 6:
a1aebcb8
EI
2974 DIS(fprintf(logfile, "break %d\n", dc->op1));
2975 cris_evaluate_flags (dc);
8170028d 2976 /* break. */
cddffe37 2977 tcg_gen_movi_tl(env_pc, dc->pc + 2);
a1aebcb8 2978
8170028d 2979 /* Breaks start at 16 in the exception vector. */
dceaf394
EI
2980 t_gen_mov_env_TN(trap_vector,
2981 tcg_const_tl(dc->op1 + 16));
2982 t_gen_raise_exception(EXCP_BREAK);
b41f7df0 2983 dc->is_jmp = DISAS_UPDATE;
8170028d
TS
2984 break;
2985 default:
2986 printf ("op2=%x\n", dc->op2);
2987 BUG();
2988 break;
2989
2990 }
8170028d
TS
2991 return 2;
2992}
2993
5d4a534d
EI
2994static unsigned int dec_ftag_fidx_d_m(DisasContext *dc)
2995{
5d4a534d
EI
2996 return 2;
2997}
2998
2999static unsigned int dec_ftag_fidx_i_m(DisasContext *dc)
3000{
5d4a534d
EI
3001 return 2;
3002}
3003
8170028d
TS
3004static unsigned int dec_null(DisasContext *dc)
3005{
3006 printf ("unknown insn pc=%x opc=%x op1=%x op2=%x\n",
3007 dc->pc, dc->opcode, dc->op1, dc->op2);
3008 fflush(NULL);
3009 BUG();
3010 return 2;
3011}
3012
9b32fbf8 3013static struct decoder_info {
8170028d
TS
3014 struct {
3015 uint32_t bits;
3016 uint32_t mask;
3017 };
3018 unsigned int (*dec)(DisasContext *dc);
3019} decinfo[] = {
3020 /* Order matters here. */
3021 {DEC_MOVEQ, dec_moveq},
3022 {DEC_BTSTQ, dec_btstq},
3023 {DEC_CMPQ, dec_cmpq},
3024 {DEC_ADDOQ, dec_addoq},
3025 {DEC_ADDQ, dec_addq},
3026 {DEC_SUBQ, dec_subq},
3027 {DEC_ANDQ, dec_andq},
3028 {DEC_ORQ, dec_orq},
3029 {DEC_ASRQ, dec_asrq},
3030 {DEC_LSLQ, dec_lslq},
3031 {DEC_LSRQ, dec_lsrq},
3032 {DEC_BCCQ, dec_bccq},
3033
3034 {DEC_BCC_IM, dec_bcc_im},
3035 {DEC_JAS_IM, dec_jas_im},
3036 {DEC_JAS_R, dec_jas_r},
3037 {DEC_JASC_IM, dec_jasc_im},
3038 {DEC_JASC_R, dec_jasc_r},
3039 {DEC_BAS_IM, dec_bas_im},
3040 {DEC_BASC_IM, dec_basc_im},
3041 {DEC_JUMP_P, dec_jump_p},
3042 {DEC_LAPC_IM, dec_lapc_im},
3043 {DEC_LAPCQ, dec_lapcq},
3044
3045 {DEC_RFE_ETC, dec_rfe_etc},
3046 {DEC_ADDC_MR, dec_addc_mr},
3047
3048 {DEC_MOVE_MP, dec_move_mp},
3049 {DEC_MOVE_PM, dec_move_pm},
3050 {DEC_MOVEM_MR, dec_movem_mr},
3051 {DEC_MOVEM_RM, dec_movem_rm},
3052 {DEC_MOVE_PR, dec_move_pr},
3053 {DEC_SCC_R, dec_scc_r},
3054 {DEC_SETF, dec_setclrf},
3055 {DEC_CLEARF, dec_setclrf},
3056
3057 {DEC_MOVE_SR, dec_move_sr},
3058 {DEC_MOVE_RP, dec_move_rp},
3059 {DEC_SWAP_R, dec_swap_r},
3060 {DEC_ABS_R, dec_abs_r},
3061 {DEC_LZ_R, dec_lz_r},
3062 {DEC_MOVE_RS, dec_move_rs},
3063 {DEC_BTST_R, dec_btst_r},
3064 {DEC_ADDC_R, dec_addc_r},
3065
3066 {DEC_DSTEP_R, dec_dstep_r},
3067 {DEC_XOR_R, dec_xor_r},
3068 {DEC_MCP_R, dec_mcp_r},
3069 {DEC_CMP_R, dec_cmp_r},
3070
3071 {DEC_ADDI_R, dec_addi_r},
3072 {DEC_ADDI_ACR, dec_addi_acr},
3073
3074 {DEC_ADD_R, dec_add_r},
3075 {DEC_SUB_R, dec_sub_r},
3076
3077 {DEC_ADDU_R, dec_addu_r},
3078 {DEC_ADDS_R, dec_adds_r},
3079 {DEC_SUBU_R, dec_subu_r},
3080 {DEC_SUBS_R, dec_subs_r},
3081 {DEC_LSL_R, dec_lsl_r},
3082
3083 {DEC_AND_R, dec_and_r},
3084 {DEC_OR_R, dec_or_r},
3085 {DEC_BOUND_R, dec_bound_r},
3086 {DEC_ASR_R, dec_asr_r},
3087 {DEC_LSR_R, dec_lsr_r},
3088
3089 {DEC_MOVU_R, dec_movu_r},
3090 {DEC_MOVS_R, dec_movs_r},
3091 {DEC_NEG_R, dec_neg_r},
3092 {DEC_MOVE_R, dec_move_r},
3093
5d4a534d
EI
3094 {DEC_FTAG_FIDX_I_M, dec_ftag_fidx_i_m},
3095 {DEC_FTAG_FIDX_D_M, dec_ftag_fidx_d_m},
8170028d
TS
3096
3097 {DEC_MULS_R, dec_muls_r},
3098 {DEC_MULU_R, dec_mulu_r},
3099
3100 {DEC_ADDU_M, dec_addu_m},
3101 {DEC_ADDS_M, dec_adds_m},
3102 {DEC_SUBU_M, dec_subu_m},
3103 {DEC_SUBS_M, dec_subs_m},
3104
3105 {DEC_CMPU_M, dec_cmpu_m},
3106 {DEC_CMPS_M, dec_cmps_m},
3107 {DEC_MOVU_M, dec_movu_m},
3108 {DEC_MOVS_M, dec_movs_m},
3109
3110 {DEC_CMP_M, dec_cmp_m},
3111 {DEC_ADDO_M, dec_addo_m},
3112 {DEC_BOUND_M, dec_bound_m},
3113 {DEC_ADD_M, dec_add_m},
3114 {DEC_SUB_M, dec_sub_m},
3115 {DEC_AND_M, dec_and_m},
3116 {DEC_OR_M, dec_or_m},
3117 {DEC_MOVE_RM, dec_move_rm},
3118 {DEC_TEST_M, dec_test_m},
3119 {DEC_MOVE_MR, dec_move_mr},
3120
3121 {{0, 0}, dec_null}
3122};
3123
3124static inline unsigned int
3125cris_decoder(DisasContext *dc)
3126{
3127 unsigned int insn_len = 2;
8170028d
TS
3128 int i;
3129
28de16da
EI
3130 if (unlikely(loglevel & CPU_LOG_TB_OP))
3131 tcg_gen_debug_insn_start(dc->pc);
3132
8170028d 3133 /* Load a halfword onto the instruction register. */
17ac9754 3134 dc->ir = lduw_code(dc->pc);
8170028d
TS
3135
3136 /* Now decode it. */
3137 dc->opcode = EXTRACT_FIELD(dc->ir, 4, 11);
3138 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 3);
3139 dc->op2 = EXTRACT_FIELD(dc->ir, 12, 15);
3140 dc->zsize = EXTRACT_FIELD(dc->ir, 4, 4);
3141 dc->zzsize = EXTRACT_FIELD(dc->ir, 4, 5);
3142 dc->postinc = EXTRACT_FIELD(dc->ir, 10, 10);
3143
3144 /* Large switch for all insns. */
3145 for (i = 0; i < sizeof decinfo / sizeof decinfo[0]; i++) {
3146 if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits)
3147 {
3148 insn_len = decinfo[i].dec(dc);
3149 break;
3150 }
3151 }
3152
dd20fcd0 3153#if !defined(CONFIG_USER_ONLY)
a1aebcb8
EI
3154 /* Single-stepping ? */
3155 if (dc->tb_flags & S_FLAG) {
3156 int l1;
3157
3158 l1 = gen_new_label();
dd20fcd0 3159 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_PR[PR_SPC], dc->pc, l1);
a1aebcb8
EI
3160 /* We treat SPC as a break with an odd trap vector. */
3161 cris_evaluate_flags (dc);
3162 t_gen_mov_env_TN(trap_vector, tcg_const_tl(3));
3163 tcg_gen_movi_tl(env_pc, dc->pc + insn_len);
cddffe37 3164 tcg_gen_movi_tl(cpu_PR[PR_SPC], dc->pc + insn_len);
a1aebcb8
EI
3165 t_gen_raise_exception(EXCP_BREAK);
3166 gen_set_label(l1);
3167 }
3168#endif
8170028d
TS
3169 return insn_len;
3170}
3171
3172static void check_breakpoint(CPUState *env, DisasContext *dc)
3173{
3174 int j;
3175 if (env->nb_breakpoints > 0) {
3176 for(j = 0; j < env->nb_breakpoints; j++) {
3177 if (env->breakpoints[j] == dc->pc) {
3178 cris_evaluate_flags (dc);
2a44f7f1 3179 tcg_gen_movi_tl(env_pc, dc->pc);
dceaf394 3180 t_gen_raise_exception(EXCP_DEBUG);
8170028d
TS
3181 dc->is_jmp = DISAS_UPDATE;
3182 }
3183 }
3184 }
3185}
3186
cf1d97f0
EI
3187
3188/*
3189 * Delay slots on QEMU/CRIS.
3190 *
3191 * If an exception hits on a delayslot, the core will let ERP (the Exception
3192 * Return Pointer) point to the branch (the previous) insn and set the lsb to
3193 * to give SW a hint that the exception actually hit on the dslot.
3194 *
3195 * CRIS expects all PC addresses to be 16-bit aligned. The lsb is ignored by
3196 * the core and any jmp to an odd addresses will mask off that lsb. It is
3197 * simply there to let sw know there was an exception on a dslot.
3198 *
3199 * When the software returns from an exception, the branch will re-execute.
3200 * On QEMU care needs to be taken when a branch+delayslot sequence is broken
3201 * and the branch and delayslot dont share pages.
3202 *
3203 * The TB contaning the branch insn will set up env->btarget and evaluate
3204 * env->btaken. When the translation loop exits we will note that the branch
3205 * sequence is broken and let env->dslot be the size of the branch insn (those
3206 * vary in length).
3207 *
3208 * The TB contaning the delayslot will have the PC of its real insn (i.e no lsb
3209 * set). It will also expect to have env->dslot setup with the size of the
3210 * delay slot so that env->pc - env->dslot point to the branch insn. This TB
3211 * will execute the dslot and take the branch, either to btarget or just one
3212 * insn ahead.
3213 *
3214 * When exceptions occur, we check for env->dslot in do_interrupt to detect
3215 * broken branch sequences and setup $erp accordingly (i.e let it point to the
3216 * branch and set lsb). Then env->dslot gets cleared so that the exception
3217 * handler can enter. When returning from exceptions (jump $erp) the lsb gets
3218 * masked off and we will reexecute the branch insn.
3219 *
3220 */
3221
8170028d 3222/* generate intermediate code for basic block 'tb'. */
2cfc5f17 3223static void
8170028d
TS
3224gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
3225 int search_pc)
3226{
3227 uint16_t *gen_opc_end;
3228 uint32_t pc_start;
3229 unsigned int insn_len;
3230 int j, lj;
cf1d97f0 3231 struct DisasContext ctx;
8170028d
TS
3232 struct DisasContext *dc = &ctx;
3233 uint32_t next_page_start;
2a44f7f1 3234 target_ulong npc;
2e70f6ef
PB
3235 int num_insns;
3236 int max_insns;
8170028d 3237
a825e703
EI
3238 if (!logfile)
3239 logfile = stderr;
3240
73e51723
EI
3241 /* Odd PC indicates that branch is rexecuting due to exception in the
3242 * delayslot, like in real hw.
73e51723
EI
3243 */
3244 pc_start = tb->pc & ~1;
8170028d
TS
3245 dc->env = env;
3246 dc->tb = tb;
3247
8170028d 3248 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8170028d
TS
3249
3250 dc->is_jmp = DISAS_NEXT;
b41f7df0 3251 dc->ppc = pc_start;
8170028d
TS
3252 dc->pc = pc_start;
3253 dc->singlestep_enabled = env->singlestep_enabled;
30abcfc7
EI
3254 dc->flags_uptodate = 1;
3255 dc->flagx_known = 1;
3256 dc->flags_x = tb->flags & X_FLAG;
3257 dc->cc_x_uptodate = 0;
b41f7df0 3258 dc->cc_mask = 0;
cf1d97f0 3259 dc->update_cc = 0;
30abcfc7 3260
b41f7df0 3261 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
30abcfc7 3262 dc->cc_size_uptodate = -1;
b41f7df0 3263
cf1d97f0 3264 /* Decode TB flags. */
a1aebcb8 3265 dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG | X_FLAG);
cf1d97f0 3266 dc->delayed_branch = !!(tb->flags & 7);
2a44f7f1
EI
3267 if (dc->delayed_branch)
3268 dc->jmp = JMP_INDIRECT;
3269 else
3270 dc->jmp = JMP_NOJMP;
3271
3272 dc->cpustate_changed = 0;
b41f7df0
EI
3273
3274 if (loglevel & CPU_LOG_TB_IN_ASM) {
3275 fprintf(logfile,
d297f464 3276 "srch=%d pc=%x %x flg=%llx bt=%x ds=%u ccs=%x\n"
30abcfc7 3277 "pid=%x usp=%x\n"
b41f7df0
EI
3278 "%x.%x.%x.%x\n"
3279 "%x.%x.%x.%x\n"
3280 "%x.%x.%x.%x\n"
3281 "%x.%x.%x.%x\n",
d297f464
EI
3282 search_pc, dc->pc, dc->ppc,
3283 (unsigned long long)tb->flags,
3284 env->btarget, (unsigned)tb->flags & 7,
cf1d97f0 3285 env->pregs[PR_CCS],
b41f7df0
EI
3286 env->pregs[PR_PID], env->pregs[PR_USP],
3287 env->regs[0], env->regs[1], env->regs[2], env->regs[3],
3288 env->regs[4], env->regs[5], env->regs[6], env->regs[7],
3289 env->regs[8], env->regs[9],
3290 env->regs[10], env->regs[11],
3291 env->regs[12], env->regs[13],
3292 env->regs[14], env->regs[15]);
a1aebcb8
EI
3293 fprintf(logfile, "--------------\n");
3294 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
b41f7df0 3295 }
3157a0a9 3296
8170028d
TS
3297 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
3298 lj = -1;
2e70f6ef
PB
3299 num_insns = 0;
3300 max_insns = tb->cflags & CF_COUNT_MASK;
3301 if (max_insns == 0)
3302 max_insns = CF_COUNT_MASK;
3303
3304 gen_icount_start();
8170028d
TS
3305 do
3306 {
3307 check_breakpoint(env, dc);
8170028d
TS
3308
3309 if (search_pc) {
3310 j = gen_opc_ptr - gen_opc_buf;
3311 if (lj < j) {
3312 lj++;
3313 while (lj < j)
3314 gen_opc_instr_start[lj++] = 0;
3315 }
cf1d97f0 3316 if (dc->delayed_branch == 1)
b41f7df0 3317 gen_opc_pc[lj] = dc->ppc | 1;
cf1d97f0 3318 else
b41f7df0 3319 gen_opc_pc[lj] = dc->pc;
cf1d97f0 3320 gen_opc_instr_start[lj] = 1;
2e70f6ef 3321 gen_opc_icount[lj] = num_insns;
cf1d97f0
EI
3322 }
3323
3324 /* Pretty disas. */
a1aebcb8 3325 DIS(fprintf(logfile, "%8.8x:\t", dc->pc));
8170028d 3326
2e70f6ef
PB
3327 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
3328 gen_io_start();
b41f7df0 3329 dc->clear_x = 1;
28de16da
EI
3330
3331 insn_len = cris_decoder(dc);
b41f7df0 3332 dc->ppc = dc->pc;
8170028d 3333 dc->pc += insn_len;
b41f7df0
EI
3334 if (dc->clear_x)
3335 cris_clear_x_flag(dc);
8170028d 3336
2e70f6ef 3337 num_insns++;
8170028d 3338 /* Check for delayed branches here. If we do it before
bf20dc07 3339 actually generating any host code, the simulator will just
8170028d
TS
3340 loop doing nothing for on this program location. */
3341 if (dc->delayed_branch) {
3342 dc->delayed_branch--;
3343 if (dc->delayed_branch == 0)
3344 {
2a44f7f1
EI
3345 if (tb->flags & 7)
3346 t_gen_mov_env_TN(dslot,
3347 tcg_const_tl(0));
3348 if (dc->jmp == JMP_DIRECT) {
3349 dc->is_jmp = DISAS_NEXT;
3350 } else {
3351 t_gen_cc_jmp(env_btarget,
3352 tcg_const_tl(dc->pc));
3353 dc->is_jmp = DISAS_JUMP;
3354 }
3355 break;
8170028d
TS
3356 }
3357 }
3358
73e51723
EI
3359 /* If we are rexecuting a branch due to exceptions on
3360 delay slots dont break. */
3361 if (!(tb->pc & 1) && env->singlestep_enabled)
8170028d 3362 break;
fb48f71b
EI
3363 } while (!dc->is_jmp && !dc->cpustate_changed
3364 && gen_opc_ptr < gen_opc_end
2e70f6ef
PB
3365 && (dc->pc < next_page_start)
3366 && num_insns < max_insns);
b41f7df0 3367
2a44f7f1
EI
3368 npc = dc->pc;
3369 if (dc->jmp == JMP_DIRECT && !dc->delayed_branch)
3370 npc = dc->jmp_pc;
3371
2e70f6ef
PB
3372 if (tb->cflags & CF_LAST_IO)
3373 gen_io_end();
2a44f7f1
EI
3374 /* Force an update if the per-tb cpu state has changed. */
3375 if (dc->is_jmp == DISAS_NEXT
3376 && (dc->cpustate_changed || !dc->flagx_known
3377 || (dc->flags_x != (tb->flags & X_FLAG)))) {
3378 dc->is_jmp = DISAS_UPDATE;
3379 tcg_gen_movi_tl(env_pc, npc);
3380 }
cf1d97f0 3381 /* Broken branch+delayslot sequence. */
b41f7df0 3382 if (dc->delayed_branch == 1) {
cf1d97f0
EI
3383 /* Set env->dslot to the size of the branch insn. */
3384 t_gen_mov_env_TN(dslot, tcg_const_tl(dc->pc - dc->ppc));
2a44f7f1 3385 cris_store_direct_jmp(dc);
8170028d
TS
3386 }
3387
3388 cris_evaluate_flags (dc);
2a44f7f1 3389
551bd27f 3390 if (unlikely(env->singlestep_enabled)) {
89cc7382
EI
3391 if (dc->is_jmp == DISAS_NEXT)
3392 tcg_gen_movi_tl(env_pc, npc);
dceaf394 3393 t_gen_raise_exception(EXCP_DEBUG);
8170028d
TS
3394 } else {
3395 switch(dc->is_jmp) {
3396 case DISAS_NEXT:
2a44f7f1 3397 gen_goto_tb(dc, 1, npc);
8170028d
TS
3398 break;
3399 default:
3400 case DISAS_JUMP:
3401 case DISAS_UPDATE:
3402 /* indicate that the hash table must be used
3403 to find the next TB */
57fec1fe 3404 tcg_gen_exit_tb(0);
8170028d 3405 break;
4f400ab5 3406 case DISAS_SWI:
8170028d
TS
3407 case DISAS_TB_JUMP:
3408 /* nothing more to generate */
3409 break;
3410 }
3411 }
2e70f6ef 3412 gen_icount_end(tb, num_insns);
8170028d
TS
3413 *gen_opc_ptr = INDEX_op_end;
3414 if (search_pc) {
3415 j = gen_opc_ptr - gen_opc_buf;
3416 lj++;
3417 while (lj <= j)
3418 gen_opc_instr_start[lj++] = 0;
3419 } else {
3420 tb->size = dc->pc - pc_start;
2e70f6ef 3421 tb->icount = num_insns;
8170028d
TS
3422 }
3423
3424#ifdef DEBUG_DISAS
a1aebcb8 3425#if !DISAS_CRIS
8170028d 3426 if (loglevel & CPU_LOG_TB_IN_ASM) {
17ac9754 3427 target_disas(logfile, pc_start, dc->pc - pc_start, 0);
d297f464 3428 fprintf(logfile, "\nisize=%d osize=%zd\n",
b41f7df0 3429 dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
8170028d
TS
3430 }
3431#endif
a1aebcb8 3432#endif
8170028d
TS
3433}
3434
2cfc5f17 3435void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8170028d 3436{
2cfc5f17 3437 gen_intermediate_code_internal(env, tb, 0);
8170028d
TS
3438}
3439
2cfc5f17 3440void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8170028d 3441{
2cfc5f17 3442 gen_intermediate_code_internal(env, tb, 1);
8170028d
TS
3443}
3444
3445void cpu_dump_state (CPUState *env, FILE *f,
3446 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
3447 int flags)
3448{
3449 int i;
3450 uint32_t srs;
3451
3452 if (!env || !f)
3453 return;
3454
3455 cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
30abcfc7 3456 "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n",
9004627f 3457 env->pc, env->pregs[PR_CCS], env->btaken, env->btarget,
8170028d 3458 env->cc_op,
30abcfc7
EI
3459 env->cc_src, env->cc_dest, env->cc_result, env->cc_mask);
3460
8170028d
TS
3461
3462 for (i = 0; i < 16; i++) {
3463 cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
3464 if ((i + 1) % 4 == 0)
3465 cpu_fprintf(f, "\n");
3466 }
3467 cpu_fprintf(f, "\nspecial regs:\n");
3468 for (i = 0; i < 16; i++) {
3469 cpu_fprintf(f, "p%2.2d=%8.8x ", i, env->pregs[i]);
3470 if ((i + 1) % 4 == 0)
3471 cpu_fprintf(f, "\n");
3472 }
9004627f 3473 srs = env->pregs[PR_SRS];
b41f7df0 3474 cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
8170028d
TS
3475 if (srs < 256) {
3476 for (i = 0; i < 16; i++) {
3477 cpu_fprintf(f, "s%2.2d=%8.8x ",
3478 i, env->sregs[srs][i]);
3479 if ((i + 1) % 4 == 0)
3480 cpu_fprintf(f, "\n");
3481 }
3482 }
3483 cpu_fprintf(f, "\n\n");
3484
3485}
3486
aaed909a 3487CPUCRISState *cpu_cris_init (const char *cpu_model)
8170028d
TS
3488{
3489 CPUCRISState *env;
a7cfbba0 3490 static int tcg_initialized = 0;
a825e703 3491 int i;
8170028d
TS
3492
3493 env = qemu_mallocz(sizeof(CPUCRISState));
3494 if (!env)
3495 return NULL;
a7cfbba0 3496
8170028d 3497 cpu_exec_init(env);
a7cfbba0
EI
3498 cpu_reset(env);
3499
3500 if (tcg_initialized)
3501 return env;
3502
3503 tcg_initialized = 1;
05ba7d5f 3504
05ba7d5f 3505 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
4f9cc927 3506 cc_x = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
30abcfc7 3507 offsetof(CPUState, cc_x), "cc_x");
4f9cc927 3508 cc_src = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
a825e703 3509 offsetof(CPUState, cc_src), "cc_src");
4f9cc927 3510 cc_dest = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
30abcfc7 3511 offsetof(CPUState, cc_dest),
a825e703 3512 "cc_dest");
4f9cc927 3513 cc_result = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
30abcfc7 3514 offsetof(CPUState, cc_result),
a825e703 3515 "cc_result");
4f9cc927 3516 cc_op = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
a825e703 3517 offsetof(CPUState, cc_op), "cc_op");
4f9cc927 3518 cc_size = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
30abcfc7 3519 offsetof(CPUState, cc_size),
a825e703 3520 "cc_size");
4f9cc927 3521 cc_mask = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
a825e703
EI
3522 offsetof(CPUState, cc_mask),
3523 "cc_mask");
3524
4f9cc927 3525 env_pc = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
30abcfc7
EI
3526 offsetof(CPUState, pc),
3527 "pc");
4f9cc927 3528 env_btarget = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
30abcfc7
EI
3529 offsetof(CPUState, btarget),
3530 "btarget");
4f9cc927 3531 env_btaken = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
2a44f7f1
EI
3532 offsetof(CPUState, btaken),
3533 "btaken");
a825e703 3534 for (i = 0; i < 16; i++) {
4f9cc927 3535 cpu_R[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
30abcfc7 3536 offsetof(CPUState, regs[i]),
a825e703
EI
3537 regnames[i]);
3538 }
3539 for (i = 0; i < 16; i++) {
4f9cc927 3540 cpu_PR[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
30abcfc7 3541 offsetof(CPUState, pregs[i]),
a825e703
EI
3542 pregnames[i]);
3543 }
3544
dceaf394 3545 TCG_HELPER(helper_raise_exception);
b41f7df0 3546 TCG_HELPER(helper_dump);
b41f7df0 3547
cf1d97f0 3548 TCG_HELPER(helper_tlb_flush_pid);
dceaf394
EI
3549 TCG_HELPER(helper_movl_sreg_reg);
3550 TCG_HELPER(helper_movl_reg_sreg);
3551 TCG_HELPER(helper_rfe);
a7cfbba0 3552 TCG_HELPER(helper_rfn);
dceaf394 3553
b41f7df0
EI
3554 TCG_HELPER(helper_evaluate_flags_muls);
3555 TCG_HELPER(helper_evaluate_flags_mulu);
3556 TCG_HELPER(helper_evaluate_flags_mcp);
3557 TCG_HELPER(helper_evaluate_flags_alu_4);
3558 TCG_HELPER(helper_evaluate_flags_move_4);
3559 TCG_HELPER(helper_evaluate_flags_move_2);
3560 TCG_HELPER(helper_evaluate_flags);
30abcfc7 3561 TCG_HELPER(helper_top_evaluate_flags);
8170028d
TS
3562 return env;
3563}
3564
3565void cpu_reset (CPUCRISState *env)
3566{
3567 memset(env, 0, offsetof(CPUCRISState, breakpoints));
3568 tlb_flush(env, 1);
b41f7df0 3569
a855593c 3570 env->pregs[PR_VR] = 32;
b41f7df0
EI
3571#if defined(CONFIG_USER_ONLY)
3572 /* start in user mode with interrupts enabled. */
3573 env->pregs[PR_CCS] |= U_FLAG | I_FLAG;
3574#else
3575 env->pregs[PR_CCS] = 0;
3576#endif
8170028d 3577}
d2856f1a
AJ
3578
3579void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
3580 unsigned long searched_pc, int pc_pos, void *puc)
3581{
17ac9754 3582 env->pc = gen_opc_pc[pc_pos];
d2856f1a 3583}