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