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