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