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