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