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