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