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