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