]> git.proxmox.com Git - qemu.git/blame - target-sh4/translate.c
[sh4] sleep instruction
[qemu.git] / target-sh4 / translate.c
CommitLineData
fdf9b3e8
FB
1/*
2 * SH4 translation
5fafdf24 3 *
fdf9b3e8
FB
4 * Copyright (c) 2005 Samuel Tardieu
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <stdarg.h>
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include <inttypes.h>
25#include <assert.h>
26
27#define DEBUG_DISAS
28#define SH4_DEBUG_DISAS
29//#define SH4_SINGLE_STEP
30
31#include "cpu.h"
32#include "exec-all.h"
33#include "disas.h"
57fec1fe 34#include "tcg-op.h"
ca10f867 35#include "qemu-common.h"
fdf9b3e8
FB
36
37typedef struct DisasContext {
38 struct TranslationBlock *tb;
39 target_ulong pc;
40 uint32_t sr;
eda9b09b 41 uint32_t fpscr;
fdf9b3e8
FB
42 uint16_t opcode;
43 uint32_t flags;
823029f9 44 int bstate;
fdf9b3e8
FB
45 int memidx;
46 uint32_t delayed_pc;
47 int singlestep_enabled;
48} DisasContext;
49
823029f9
TS
50enum {
51 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
52 * exception condition
53 */
54 BS_STOP = 1, /* We want to stop translation for any reason */
55 BS_BRANCH = 2, /* We reached a branch condition */
56 BS_EXCP = 3, /* We reached an exception condition */
57};
58
2e70f6ef
PB
59static TCGv cpu_env;
60
61#include "gen-icount.h"
62
a5f1b965 63static void sh4_translate_init(void)
2e70f6ef
PB
64{
65 static int done_init = 0;
66 if (done_init)
67 return;
68 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
69 done_init = 1;
70}
71
fdf9b3e8
FB
72#ifdef CONFIG_USER_ONLY
73
eda9b09b
FB
74#define GEN_OP_LD(width, reg) \
75 void gen_op_ld##width##_T0_##reg (DisasContext *ctx) { \
76 gen_op_ld##width##_T0_##reg##_raw(); \
fdf9b3e8 77 }
eda9b09b
FB
78#define GEN_OP_ST(width, reg) \
79 void gen_op_st##width##_##reg##_T1 (DisasContext *ctx) { \
80 gen_op_st##width##_##reg##_T1_raw(); \
fdf9b3e8
FB
81 }
82
83#else
84
eda9b09b
FB
85#define GEN_OP_LD(width, reg) \
86 void gen_op_ld##width##_T0_##reg (DisasContext *ctx) { \
87 if (ctx->memidx) gen_op_ld##width##_T0_##reg##_kernel(); \
88 else gen_op_ld##width##_T0_##reg##_user();\
fdf9b3e8 89 }
eda9b09b
FB
90#define GEN_OP_ST(width, reg) \
91 void gen_op_st##width##_##reg##_T1 (DisasContext *ctx) { \
92 if (ctx->memidx) gen_op_st##width##_##reg##_T1_kernel(); \
93 else gen_op_st##width##_##reg##_T1_user();\
fdf9b3e8
FB
94 }
95
96#endif
97
eda9b09b
FB
98GEN_OP_LD(ub, T0)
99GEN_OP_LD(b, T0)
100GEN_OP_ST(b, T0)
101GEN_OP_LD(uw, T0)
102GEN_OP_LD(w, T0)
103GEN_OP_ST(w, T0)
104GEN_OP_LD(l, T0)
105GEN_OP_ST(l, T0)
106GEN_OP_LD(fl, FT0)
107GEN_OP_ST(fl, FT0)
108GEN_OP_LD(fq, DT0)
109GEN_OP_ST(fq, DT0)
fdf9b3e8
FB
110
111void cpu_dump_state(CPUState * env, FILE * f,
112 int (*cpu_fprintf) (FILE * f, const char *fmt, ...),
113 int flags)
114{
115 int i;
eda9b09b
FB
116 cpu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n",
117 env->pc, env->sr, env->pr, env->fpscr);
fdf9b3e8
FB
118 for (i = 0; i < 24; i += 4) {
119 cpu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
120 i, env->gregs[i], i + 1, env->gregs[i + 1],
121 i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
122 }
123 if (env->flags & DELAY_SLOT) {
124 cpu_fprintf(f, "in delay slot (delayed_pc=0x%08x)\n",
125 env->delayed_pc);
126 } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
127 cpu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n",
128 env->delayed_pc);
129 }
130}
131
132void cpu_sh4_reset(CPUSH4State * env)
133{
9c2a9ea1 134#if defined(CONFIG_USER_ONLY)
4c909d14 135 env->sr = SR_FD; /* FD - kernel does lazy fpu context switch */
9c2a9ea1 136#else
fdf9b3e8 137 env->sr = 0x700000F0; /* MD, RB, BL, I3-I0 */
9c2a9ea1 138#endif
fdf9b3e8
FB
139 env->vbr = 0;
140 env->pc = 0xA0000000;
ea6cf6be
TS
141#if defined(CONFIG_USER_ONLY)
142 env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
b0b3de89 143 set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
ea6cf6be
TS
144#else
145 env->fpscr = 0x00040001; /* CPU reset value according to SH4 manual */
b0b3de89 146 set_float_rounding_mode(float_round_to_zero, &env->fp_status);
ea6cf6be 147#endif
fdf9b3e8
FB
148 env->mmucr = 0;
149}
150
aaed909a 151CPUSH4State *cpu_sh4_init(const char *cpu_model)
fdf9b3e8
FB
152{
153 CPUSH4State *env;
154
155 env = qemu_mallocz(sizeof(CPUSH4State));
156 if (!env)
157 return NULL;
158 cpu_exec_init(env);
2e70f6ef 159 sh4_translate_init();
fdf9b3e8
FB
160 cpu_sh4_reset(env);
161 tlb_flush(env, 1);
162 return env;
163}
164
fdf9b3e8
FB
165static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
166{
167 TranslationBlock *tb;
168 tb = ctx->tb;
169
170 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
171 !ctx->singlestep_enabled) {
172 /* Use a direct jump if in same page and singlestep not enabled */
57fec1fe
FB
173 tcg_gen_goto_tb(n);
174 gen_op_movl_imm_PC(dest);
175 tcg_gen_exit_tb((long) tb + n);
fdf9b3e8 176 } else {
57fec1fe
FB
177 gen_op_movl_imm_PC(dest);
178 if (ctx->singlestep_enabled)
179 gen_op_debug();
180 tcg_gen_exit_tb(0);
fdf9b3e8 181 }
fdf9b3e8
FB
182}
183
fdf9b3e8
FB
184static void gen_jump(DisasContext * ctx)
185{
186 if (ctx->delayed_pc == (uint32_t) - 1) {
187 /* Target is not statically known, it comes necessarily from a
188 delayed jump as immediate jump are conditinal jumps */
189 gen_op_movl_delayed_pc_PC();
fdf9b3e8
FB
190 if (ctx->singlestep_enabled)
191 gen_op_debug();
57fec1fe 192 tcg_gen_exit_tb(0);
fdf9b3e8
FB
193 } else {
194 gen_goto_tb(ctx, 0, ctx->delayed_pc);
195 }
196}
197
198/* Immediate conditional jump (bt or bf) */
199static void gen_conditional_jump(DisasContext * ctx,
200 target_ulong ift, target_ulong ifnott)
201{
202 int l1;
203
204 l1 = gen_new_label();
205 gen_op_jT(l1);
206 gen_goto_tb(ctx, 0, ifnott);
207 gen_set_label(l1);
208 gen_goto_tb(ctx, 1, ift);
209}
210
211/* Delayed conditional jump (bt or bf) */
212static void gen_delayed_conditional_jump(DisasContext * ctx)
213{
214 int l1;
215
216 l1 = gen_new_label();
9c2a9ea1 217 gen_op_jdelayed(l1);
823029f9 218 gen_goto_tb(ctx, 1, ctx->pc + 2);
fdf9b3e8 219 gen_set_label(l1);
9c2a9ea1 220 gen_jump(ctx);
fdf9b3e8
FB
221}
222
223#define B3_0 (ctx->opcode & 0xf)
224#define B6_4 ((ctx->opcode >> 4) & 0x7)
225#define B7_4 ((ctx->opcode >> 4) & 0xf)
226#define B7_0 (ctx->opcode & 0xff)
227#define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
228#define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
229 (ctx->opcode & 0xfff))
230#define B11_8 ((ctx->opcode >> 8) & 0xf)
231#define B15_12 ((ctx->opcode >> 12) & 0xf)
232
233#define REG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB) ? \
234 (x) + 16 : (x))
235
236#define ALTREG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) != (SR_MD | SR_RB) \
237 ? (x) + 16 : (x))
238
eda9b09b 239#define FREG(x) (ctx->fpscr & FPSCR_FR ? (x) ^ 0x10 : (x))
f09111e0 240#define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
eda9b09b 241#define XREG(x) (ctx->fpscr & FPSCR_FR ? XHACK(x) ^ 0x10 : XHACK(x))
ea6cf6be 242#define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */
eda9b09b 243
fdf9b3e8
FB
244#define CHECK_NOT_DELAY_SLOT \
245 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \
823029f9 246 {gen_op_raise_slot_illegal_instruction (); ctx->bstate = BS_EXCP; \
fdf9b3e8
FB
247 return;}
248
823029f9 249void _decode_opc(DisasContext * ctx)
fdf9b3e8
FB
250{
251#if 0
252 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
253#endif
254 switch (ctx->opcode) {
255 case 0x0019: /* div0u */
fdf9b3e8
FB
256 gen_op_div0u();
257 return;
258 case 0x000b: /* rts */
259 CHECK_NOT_DELAY_SLOT gen_op_rts();
260 ctx->flags |= DELAY_SLOT;
261 ctx->delayed_pc = (uint32_t) - 1;
262 return;
263 case 0x0028: /* clrmac */
264 gen_op_clrmac();
265 return;
266 case 0x0048: /* clrs */
267 gen_op_clrs();
268 return;
269 case 0x0008: /* clrt */
270 gen_op_clrt();
271 return;
272 case 0x0038: /* ldtlb */
ea2b542a 273#if defined(CONFIG_USER_ONLY)
fdf9b3e8 274 assert(0); /* XXXXX */
ea2b542a
AJ
275#else
276 gen_op_ldtlb();
277#endif
fdf9b3e8 278 return;
c5e814b2 279 case 0x002b: /* rte */
fdf9b3e8
FB
280 CHECK_NOT_DELAY_SLOT gen_op_rte();
281 ctx->flags |= DELAY_SLOT;
282 ctx->delayed_pc = (uint32_t) - 1;
283 return;
284 case 0x0058: /* sets */
285 gen_op_sets();
286 return;
287 case 0x0018: /* sett */
288 gen_op_sett();
289 return;
24988dc2 290 case 0xfbfd: /* frchg */
eda9b09b 291 gen_op_frchg();
823029f9 292 ctx->bstate = BS_STOP;
fdf9b3e8 293 return;
24988dc2 294 case 0xf3fd: /* fschg */
eda9b09b 295 gen_op_fschg();
823029f9 296 ctx->bstate = BS_STOP;
fdf9b3e8
FB
297 return;
298 case 0x0009: /* nop */
299 return;
300 case 0x001b: /* sleep */
833ed386
AJ
301 if (ctx->memidx) {
302 gen_op_sleep();
303 } else {
304 gen_op_raise_illegal_instruction();
305 ctx->bstate = BS_EXCP;
306 }
fdf9b3e8
FB
307 return;
308 }
309
310 switch (ctx->opcode & 0xf000) {
311 case 0x1000: /* mov.l Rm,@(disp,Rn) */
312 gen_op_movl_rN_T0(REG(B7_4));
313 gen_op_movl_rN_T1(REG(B11_8));
314 gen_op_addl_imm_T1(B3_0 * 4);
315 gen_op_stl_T0_T1(ctx);
316 return;
317 case 0x5000: /* mov.l @(disp,Rm),Rn */
318 gen_op_movl_rN_T0(REG(B7_4));
319 gen_op_addl_imm_T0(B3_0 * 4);
320 gen_op_ldl_T0_T0(ctx);
321 gen_op_movl_T0_rN(REG(B11_8));
322 return;
24988dc2 323 case 0xe000: /* mov #imm,Rn */
fdf9b3e8
FB
324 gen_op_movl_imm_rN(B7_0s, REG(B11_8));
325 return;
326 case 0x9000: /* mov.w @(disp,PC),Rn */
327 gen_op_movl_imm_T0(ctx->pc + 4 + B7_0 * 2);
328 gen_op_ldw_T0_T0(ctx);
329 gen_op_movl_T0_rN(REG(B11_8));
330 return;
331 case 0xd000: /* mov.l @(disp,PC),Rn */
332 gen_op_movl_imm_T0((ctx->pc + 4 + B7_0 * 4) & ~3);
333 gen_op_ldl_T0_T0(ctx);
334 gen_op_movl_T0_rN(REG(B11_8));
335 return;
24988dc2 336 case 0x7000: /* add #imm,Rn */
fdf9b3e8
FB
337 gen_op_add_imm_rN(B7_0s, REG(B11_8));
338 return;
339 case 0xa000: /* bra disp */
340 CHECK_NOT_DELAY_SLOT
341 gen_op_bra(ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2);
342 ctx->flags |= DELAY_SLOT;
343 return;
344 case 0xb000: /* bsr disp */
345 CHECK_NOT_DELAY_SLOT
346 gen_op_bsr(ctx->pc + 4, ctx->delayed_pc =
347 ctx->pc + 4 + B11_0s * 2);
348 ctx->flags |= DELAY_SLOT;
349 return;
350 }
351
352 switch (ctx->opcode & 0xf00f) {
353 case 0x6003: /* mov Rm,Rn */
354 gen_op_movl_rN_T0(REG(B7_4));
355 gen_op_movl_T0_rN(REG(B11_8));
356 return;
357 case 0x2000: /* mov.b Rm,@Rn */
358 gen_op_movl_rN_T0(REG(B7_4));
359 gen_op_movl_rN_T1(REG(B11_8));
360 gen_op_stb_T0_T1(ctx);
361 return;
362 case 0x2001: /* mov.w Rm,@Rn */
363 gen_op_movl_rN_T0(REG(B7_4));
364 gen_op_movl_rN_T1(REG(B11_8));
365 gen_op_stw_T0_T1(ctx);
366 return;
367 case 0x2002: /* mov.l Rm,@Rn */
368 gen_op_movl_rN_T0(REG(B7_4));
369 gen_op_movl_rN_T1(REG(B11_8));
370 gen_op_stl_T0_T1(ctx);
371 return;
372 case 0x6000: /* mov.b @Rm,Rn */
373 gen_op_movl_rN_T0(REG(B7_4));
374 gen_op_ldb_T0_T0(ctx);
375 gen_op_movl_T0_rN(REG(B11_8));
376 return;
377 case 0x6001: /* mov.w @Rm,Rn */
378 gen_op_movl_rN_T0(REG(B7_4));
379 gen_op_ldw_T0_T0(ctx);
380 gen_op_movl_T0_rN(REG(B11_8));
381 return;
382 case 0x6002: /* mov.l @Rm,Rn */
383 gen_op_movl_rN_T0(REG(B7_4));
384 gen_op_ldl_T0_T0(ctx);
385 gen_op_movl_T0_rN(REG(B11_8));
386 return;
387 case 0x2004: /* mov.b Rm,@-Rn */
fdf9b3e8 388 gen_op_movl_rN_T0(REG(B7_4));
24988dc2 389 gen_op_dec1_rN(REG(B11_8));
fdf9b3e8
FB
390 gen_op_movl_rN_T1(REG(B11_8));
391 gen_op_stb_T0_T1(ctx);
392 return;
393 case 0x2005: /* mov.w Rm,@-Rn */
fdf9b3e8 394 gen_op_movl_rN_T0(REG(B7_4));
24988dc2 395 gen_op_dec2_rN(REG(B11_8));
fdf9b3e8
FB
396 gen_op_movl_rN_T1(REG(B11_8));
397 gen_op_stw_T0_T1(ctx);
398 return;
399 case 0x2006: /* mov.l Rm,@-Rn */
fdf9b3e8 400 gen_op_movl_rN_T0(REG(B7_4));
24988dc2 401 gen_op_dec4_rN(REG(B11_8));
fdf9b3e8
FB
402 gen_op_movl_rN_T1(REG(B11_8));
403 gen_op_stl_T0_T1(ctx);
404 return;
eda9b09b 405 case 0x6004: /* mov.b @Rm+,Rn */
fdf9b3e8
FB
406 gen_op_movl_rN_T0(REG(B7_4));
407 gen_op_ldb_T0_T0(ctx);
408 gen_op_movl_T0_rN(REG(B11_8));
24988dc2
AJ
409 if ( B11_8 != B7_4 )
410 gen_op_inc1_rN(REG(B7_4));
fdf9b3e8
FB
411 return;
412 case 0x6005: /* mov.w @Rm+,Rn */
413 gen_op_movl_rN_T0(REG(B7_4));
414 gen_op_ldw_T0_T0(ctx);
415 gen_op_movl_T0_rN(REG(B11_8));
24988dc2
AJ
416 if ( B11_8 != B7_4 )
417 gen_op_inc2_rN(REG(B7_4));
fdf9b3e8
FB
418 return;
419 case 0x6006: /* mov.l @Rm+,Rn */
420 gen_op_movl_rN_T0(REG(B7_4));
421 gen_op_ldl_T0_T0(ctx);
422 gen_op_movl_T0_rN(REG(B11_8));
24988dc2
AJ
423 if ( B11_8 != B7_4 )
424 gen_op_inc4_rN(REG(B7_4));
fdf9b3e8
FB
425 return;
426 case 0x0004: /* mov.b Rm,@(R0,Rn) */
427 gen_op_movl_rN_T0(REG(B7_4));
428 gen_op_movl_rN_T1(REG(B11_8));
429 gen_op_add_rN_T1(REG(0));
430 gen_op_stb_T0_T1(ctx);
431 return;
432 case 0x0005: /* mov.w Rm,@(R0,Rn) */
433 gen_op_movl_rN_T0(REG(B7_4));
434 gen_op_movl_rN_T1(REG(B11_8));
435 gen_op_add_rN_T1(REG(0));
436 gen_op_stw_T0_T1(ctx);
437 return;
438 case 0x0006: /* mov.l Rm,@(R0,Rn) */
439 gen_op_movl_rN_T0(REG(B7_4));
440 gen_op_movl_rN_T1(REG(B11_8));
441 gen_op_add_rN_T1(REG(0));
442 gen_op_stl_T0_T1(ctx);
443 return;
444 case 0x000c: /* mov.b @(R0,Rm),Rn */
445 gen_op_movl_rN_T0(REG(B7_4));
446 gen_op_add_rN_T0(REG(0));
447 gen_op_ldb_T0_T0(ctx);
448 gen_op_movl_T0_rN(REG(B11_8));
449 return;
450 case 0x000d: /* mov.w @(R0,Rm),Rn */
451 gen_op_movl_rN_T0(REG(B7_4));
452 gen_op_add_rN_T0(REG(0));
453 gen_op_ldw_T0_T0(ctx);
454 gen_op_movl_T0_rN(REG(B11_8));
455 return;
456 case 0x000e: /* mov.l @(R0,Rm),Rn */
457 gen_op_movl_rN_T0(REG(B7_4));
458 gen_op_add_rN_T0(REG(0));
459 gen_op_ldl_T0_T0(ctx);
460 gen_op_movl_T0_rN(REG(B11_8));
461 return;
462 case 0x6008: /* swap.b Rm,Rn */
463 gen_op_movl_rN_T0(REG(B7_4));
464 gen_op_swapb_T0();
465 gen_op_movl_T0_rN(REG(B11_8));
466 return;
467 case 0x6009: /* swap.w Rm,Rn */
468 gen_op_movl_rN_T0(REG(B7_4));
469 gen_op_swapw_T0();
470 gen_op_movl_T0_rN(REG(B11_8));
471 return;
472 case 0x200d: /* xtrct Rm,Rn */
473 gen_op_movl_rN_T0(REG(B7_4));
474 gen_op_movl_rN_T1(REG(B11_8));
475 gen_op_xtrct_T0_T1();
476 gen_op_movl_T1_rN(REG(B11_8));
477 return;
478 case 0x300c: /* add Rm,Rn */
479 gen_op_movl_rN_T0(REG(B7_4));
480 gen_op_add_T0_rN(REG(B11_8));
481 return;
482 case 0x300e: /* addc Rm,Rn */
483 gen_op_movl_rN_T0(REG(B7_4));
484 gen_op_movl_rN_T1(REG(B11_8));
485 gen_op_addc_T0_T1();
486 gen_op_movl_T1_rN(REG(B11_8));
487 return;
488 case 0x300f: /* addv Rm,Rn */
489 gen_op_movl_rN_T0(REG(B7_4));
490 gen_op_movl_rN_T1(REG(B11_8));
491 gen_op_addv_T0_T1();
492 gen_op_movl_T1_rN(REG(B11_8));
493 return;
494 case 0x2009: /* and Rm,Rn */
495 gen_op_movl_rN_T0(REG(B7_4));
496 gen_op_and_T0_rN(REG(B11_8));
497 return;
498 case 0x3000: /* cmp/eq Rm,Rn */
499 gen_op_movl_rN_T0(REG(B7_4));
500 gen_op_movl_rN_T1(REG(B11_8));
501 gen_op_cmp_eq_T0_T1();
502 return;
503 case 0x3003: /* cmp/ge Rm,Rn */
504 gen_op_movl_rN_T0(REG(B7_4));
505 gen_op_movl_rN_T1(REG(B11_8));
506 gen_op_cmp_ge_T0_T1();
507 return;
508 case 0x3007: /* cmp/gt Rm,Rn */
509 gen_op_movl_rN_T0(REG(B7_4));
510 gen_op_movl_rN_T1(REG(B11_8));
511 gen_op_cmp_gt_T0_T1();
512 return;
513 case 0x3006: /* cmp/hi Rm,Rn */
514 gen_op_movl_rN_T0(REG(B7_4));
515 gen_op_movl_rN_T1(REG(B11_8));
516 gen_op_cmp_hi_T0_T1();
517 return;
518 case 0x3002: /* cmp/hs Rm,Rn */
519 gen_op_movl_rN_T0(REG(B7_4));
520 gen_op_movl_rN_T1(REG(B11_8));
521 gen_op_cmp_hs_T0_T1();
522 return;
523 case 0x200c: /* cmp/str Rm,Rn */
524 gen_op_movl_rN_T0(REG(B7_4));
525 gen_op_movl_rN_T1(REG(B11_8));
526 gen_op_cmp_str_T0_T1();
527 return;
528 case 0x2007: /* div0s Rm,Rn */
fdf9b3e8
FB
529 gen_op_movl_rN_T0(REG(B7_4));
530 gen_op_movl_rN_T1(REG(B11_8));
531 gen_op_div0s_T0_T1();
fdf9b3e8
FB
532 return;
533 case 0x3004: /* div1 Rm,Rn */
534 gen_op_movl_rN_T0(REG(B7_4));
535 gen_op_movl_rN_T1(REG(B11_8));
536 gen_op_div1_T0_T1();
537 gen_op_movl_T1_rN(REG(B11_8));
538 return;
539 case 0x300d: /* dmuls.l Rm,Rn */
540 gen_op_movl_rN_T0(REG(B7_4));
541 gen_op_movl_rN_T1(REG(B11_8));
542 gen_op_dmulsl_T0_T1();
543 return;
544 case 0x3005: /* dmulu.l Rm,Rn */
545 gen_op_movl_rN_T0(REG(B7_4));
546 gen_op_movl_rN_T1(REG(B11_8));
547 gen_op_dmulul_T0_T1();
548 return;
549 case 0x600e: /* exts.b Rm,Rn */
550 gen_op_movb_rN_T0(REG(B7_4));
551 gen_op_movl_T0_rN(REG(B11_8));
552 return;
553 case 0x600f: /* exts.w Rm,Rn */
554 gen_op_movw_rN_T0(REG(B7_4));
555 gen_op_movl_T0_rN(REG(B11_8));
556 return;
557 case 0x600c: /* extu.b Rm,Rn */
558 gen_op_movub_rN_T0(REG(B7_4));
559 gen_op_movl_T0_rN(REG(B11_8));
560 return;
561 case 0x600d: /* extu.w Rm,Rn */
562 gen_op_movuw_rN_T0(REG(B7_4));
563 gen_op_movl_T0_rN(REG(B11_8));
564 return;
24988dc2 565 case 0x000f: /* mac.l @Rm+,@Rn+ */
fdf9b3e8
FB
566 gen_op_movl_rN_T0(REG(B11_8));
567 gen_op_ldl_T0_T0(ctx);
568 gen_op_movl_T0_T1();
24988dc2
AJ
569 gen_op_inc4_rN(REG(B11_8));
570 gen_op_movl_rN_T0(REG(B7_4));
fdf9b3e8
FB
571 gen_op_ldl_T0_T0(ctx);
572 gen_op_macl_T0_T1();
573 gen_op_inc4_rN(REG(B7_4));
fdf9b3e8
FB
574 return;
575 case 0x400f: /* mac.w @Rm+,@Rn+ */
576 gen_op_movl_rN_T0(REG(B11_8));
577 gen_op_ldl_T0_T0(ctx);
578 gen_op_movl_T0_T1();
24988dc2
AJ
579 gen_op_inc2_rN(REG(B11_8));
580 gen_op_movl_rN_T0(REG(B7_4));
fdf9b3e8
FB
581 gen_op_ldl_T0_T0(ctx);
582 gen_op_macw_T0_T1();
583 gen_op_inc2_rN(REG(B7_4));
fdf9b3e8
FB
584 return;
585 case 0x0007: /* mul.l Rm,Rn */
586 gen_op_movl_rN_T0(REG(B7_4));
587 gen_op_movl_rN_T1(REG(B11_8));
588 gen_op_mull_T0_T1();
589 return;
590 case 0x200f: /* muls.w Rm,Rn */
591 gen_op_movw_rN_T0(REG(B7_4));
592 gen_op_movw_rN_T1(REG(B11_8));
593 gen_op_mulsw_T0_T1();
594 return;
595 case 0x200e: /* mulu.w Rm,Rn */
596 gen_op_movuw_rN_T0(REG(B7_4));
597 gen_op_movuw_rN_T1(REG(B11_8));
598 gen_op_muluw_T0_T1();
599 return;
600 case 0x600b: /* neg Rm,Rn */
601 gen_op_movl_rN_T0(REG(B7_4));
602 gen_op_neg_T0();
603 gen_op_movl_T0_rN(REG(B11_8));
604 return;
605 case 0x600a: /* negc Rm,Rn */
606 gen_op_movl_rN_T0(REG(B7_4));
607 gen_op_negc_T0();
608 gen_op_movl_T0_rN(REG(B11_8));
609 return;
610 case 0x6007: /* not Rm,Rn */
611 gen_op_movl_rN_T0(REG(B7_4));
612 gen_op_not_T0();
613 gen_op_movl_T0_rN(REG(B11_8));
614 return;
615 case 0x200b: /* or Rm,Rn */
616 gen_op_movl_rN_T0(REG(B7_4));
617 gen_op_or_T0_rN(REG(B11_8));
618 return;
619 case 0x400c: /* shad Rm,Rn */
620 gen_op_movl_rN_T0(REG(B7_4));
621 gen_op_movl_rN_T1(REG(B11_8));
622 gen_op_shad_T0_T1();
623 gen_op_movl_T1_rN(REG(B11_8));
624 return;
625 case 0x400d: /* shld Rm,Rn */
626 gen_op_movl_rN_T0(REG(B7_4));
627 gen_op_movl_rN_T1(REG(B11_8));
628 gen_op_shld_T0_T1();
629 gen_op_movl_T1_rN(REG(B11_8));
630 return;
631 case 0x3008: /* sub Rm,Rn */
632 gen_op_movl_rN_T0(REG(B7_4));
633 gen_op_sub_T0_rN(REG(B11_8));
634 return;
635 case 0x300a: /* subc Rm,Rn */
636 gen_op_movl_rN_T0(REG(B7_4));
637 gen_op_movl_rN_T1(REG(B11_8));
638 gen_op_subc_T0_T1();
639 gen_op_movl_T1_rN(REG(B11_8));
640 return;
641 case 0x300b: /* subv Rm,Rn */
642 gen_op_movl_rN_T0(REG(B7_4));
643 gen_op_movl_rN_T1(REG(B11_8));
644 gen_op_subv_T0_T1();
645 gen_op_movl_T1_rN(REG(B11_8));
646 return;
647 case 0x2008: /* tst Rm,Rn */
648 gen_op_movl_rN_T0(REG(B7_4));
649 gen_op_movl_rN_T1(REG(B11_8));
650 gen_op_tst_T0_T1();
651 return;
652 case 0x200a: /* xor Rm,Rn */
653 gen_op_movl_rN_T0(REG(B7_4));
654 gen_op_xor_T0_rN(REG(B11_8));
655 return;
e67888a7 656 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
022a22c7 657 if (ctx->fpscr & FPSCR_SZ) {
24988dc2
AJ
658 gen_op_fmov_drN_DT0(XREG(B7_4));
659 gen_op_fmov_DT0_drN(XREG(B11_8));
eda9b09b
FB
660 } else {
661 gen_op_fmov_frN_FT0(FREG(B7_4));
662 gen_op_fmov_FT0_frN(FREG(B11_8));
663 }
664 return;
e67888a7 665 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
022a22c7 666 if (ctx->fpscr & FPSCR_SZ) {
24988dc2 667 gen_op_fmov_drN_DT0(XREG(B7_4));
eda9b09b
FB
668 gen_op_movl_rN_T1(REG(B11_8));
669 gen_op_stfq_DT0_T1(ctx);
670 } else {
671 gen_op_fmov_frN_FT0(FREG(B7_4));
672 gen_op_movl_rN_T1(REG(B11_8));
673 gen_op_stfl_FT0_T1(ctx);
674 }
675 return;
e67888a7 676 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
022a22c7 677 if (ctx->fpscr & FPSCR_SZ) {
eda9b09b
FB
678 gen_op_movl_rN_T0(REG(B7_4));
679 gen_op_ldfq_T0_DT0(ctx);
24988dc2 680 gen_op_fmov_DT0_drN(XREG(B11_8));
eda9b09b
FB
681 } else {
682 gen_op_movl_rN_T0(REG(B7_4));
683 gen_op_ldfl_T0_FT0(ctx);
f09111e0 684 gen_op_fmov_FT0_frN(FREG(B11_8));
eda9b09b
FB
685 }
686 return;
e67888a7 687 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
022a22c7 688 if (ctx->fpscr & FPSCR_SZ) {
eda9b09b
FB
689 gen_op_movl_rN_T0(REG(B7_4));
690 gen_op_ldfq_T0_DT0(ctx);
24988dc2 691 gen_op_fmov_DT0_drN(XREG(B11_8));
eda9b09b
FB
692 gen_op_inc8_rN(REG(B7_4));
693 } else {
694 gen_op_movl_rN_T0(REG(B7_4));
695 gen_op_ldfl_T0_FT0(ctx);
f09111e0 696 gen_op_fmov_FT0_frN(FREG(B11_8));
eda9b09b
FB
697 gen_op_inc4_rN(REG(B7_4));
698 }
699 return;
e67888a7 700 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
022a22c7 701 if (ctx->fpscr & FPSCR_SZ) {
eda9b09b 702 gen_op_dec8_rN(REG(B11_8));
24988dc2 703 gen_op_fmov_drN_DT0(XREG(B7_4));
eda9b09b
FB
704 gen_op_movl_rN_T1(REG(B11_8));
705 gen_op_stfq_DT0_T1(ctx);
706 } else {
707 gen_op_dec4_rN(REG(B11_8));
708 gen_op_fmov_frN_FT0(FREG(B7_4));
709 gen_op_movl_rN_T1(REG(B11_8));
710 gen_op_stfl_FT0_T1(ctx);
711 }
712 return;
e67888a7 713 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
022a22c7 714 if (ctx->fpscr & FPSCR_SZ) {
eda9b09b
FB
715 gen_op_movl_rN_T0(REG(B7_4));
716 gen_op_add_rN_T0(REG(0));
717 gen_op_ldfq_T0_DT0(ctx);
24988dc2 718 gen_op_fmov_DT0_drN(XREG(B11_8));
eda9b09b
FB
719 } else {
720 gen_op_movl_rN_T0(REG(B7_4));
721 gen_op_add_rN_T0(REG(0));
722 gen_op_ldfl_T0_FT0(ctx);
f09111e0 723 gen_op_fmov_FT0_frN(FREG(B11_8));
eda9b09b
FB
724 }
725 return;
e67888a7 726 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
022a22c7 727 if (ctx->fpscr & FPSCR_SZ) {
24988dc2 728 gen_op_fmov_drN_DT0(XREG(B7_4));
eda9b09b
FB
729 gen_op_movl_rN_T1(REG(B11_8));
730 gen_op_add_rN_T1(REG(0));
731 gen_op_stfq_DT0_T1(ctx);
732 } else {
733 gen_op_fmov_frN_FT0(FREG(B7_4));
734 gen_op_movl_rN_T1(REG(B11_8));
735 gen_op_add_rN_T1(REG(0));
736 gen_op_stfl_FT0_T1(ctx);
737 }
738 return;
e67888a7
TS
739 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
740 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
741 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
742 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
743 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
744 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
ea6cf6be
TS
745 if (ctx->fpscr & FPSCR_PR) {
746 if (ctx->opcode & 0x0110)
747 break; /* illegal instruction */
748 gen_op_fmov_drN_DT1(DREG(B7_4));
749 gen_op_fmov_drN_DT0(DREG(B11_8));
750 }
751 else {
752 gen_op_fmov_frN_FT1(FREG(B7_4));
753 gen_op_fmov_frN_FT0(FREG(B11_8));
754 }
755
756 switch (ctx->opcode & 0xf00f) {
757 case 0xf000: /* fadd Rm,Rn */
758 ctx->fpscr & FPSCR_PR ? gen_op_fadd_DT() : gen_op_fadd_FT();
759 break;
760 case 0xf001: /* fsub Rm,Rn */
761 ctx->fpscr & FPSCR_PR ? gen_op_fsub_DT() : gen_op_fsub_FT();
762 break;
763 case 0xf002: /* fmul Rm,Rn */
764 ctx->fpscr & FPSCR_PR ? gen_op_fmul_DT() : gen_op_fmul_FT();
765 break;
766 case 0xf003: /* fdiv Rm,Rn */
767 ctx->fpscr & FPSCR_PR ? gen_op_fdiv_DT() : gen_op_fdiv_FT();
768 break;
769 case 0xf004: /* fcmp/eq Rm,Rn */
24988dc2 770 ctx->fpscr & FPSCR_PR ? gen_op_fcmp_eq_DT() : gen_op_fcmp_eq_FT();
ea6cf6be
TS
771 return;
772 case 0xf005: /* fcmp/gt Rm,Rn */
24988dc2 773 ctx->fpscr & FPSCR_PR ? gen_op_fcmp_gt_DT() : gen_op_fcmp_gt_FT();
ea6cf6be
TS
774 return;
775 }
776
777 if (ctx->fpscr & FPSCR_PR) {
778 gen_op_fmov_DT0_drN(DREG(B11_8));
779 }
780 else {
781 gen_op_fmov_FT0_frN(FREG(B11_8));
782 }
783 return;
fdf9b3e8
FB
784 }
785
786 switch (ctx->opcode & 0xff00) {
787 case 0xc900: /* and #imm,R0 */
788 gen_op_and_imm_rN(B7_0, REG(0));
789 return;
24988dc2 790 case 0xcd00: /* and.b #imm,@(R0,GBR) */
fdf9b3e8
FB
791 gen_op_movl_rN_T0(REG(0));
792 gen_op_addl_GBR_T0();
793 gen_op_movl_T0_T1();
24988dc2 794 gen_op_ldub_T0_T0(ctx);
fdf9b3e8
FB
795 gen_op_and_imm_T0(B7_0);
796 gen_op_stb_T0_T1(ctx);
797 return;
798 case 0x8b00: /* bf label */
799 CHECK_NOT_DELAY_SLOT
800 gen_conditional_jump(ctx, ctx->pc + 2,
801 ctx->pc + 4 + B7_0s * 2);
823029f9 802 ctx->bstate = BS_BRANCH;
fdf9b3e8
FB
803 return;
804 case 0x8f00: /* bf/s label */
805 CHECK_NOT_DELAY_SLOT
806 gen_op_bf_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2);
807 ctx->flags |= DELAY_SLOT_CONDITIONAL;
808 return;
809 case 0x8900: /* bt label */
810 CHECK_NOT_DELAY_SLOT
811 gen_conditional_jump(ctx, ctx->pc + 4 + B7_0s * 2,
812 ctx->pc + 2);
823029f9 813 ctx->bstate = BS_BRANCH;
fdf9b3e8
FB
814 return;
815 case 0x8d00: /* bt/s label */
816 CHECK_NOT_DELAY_SLOT
817 gen_op_bt_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2);
818 ctx->flags |= DELAY_SLOT_CONDITIONAL;
819 return;
820 case 0x8800: /* cmp/eq #imm,R0 */
821 gen_op_movl_rN_T0(REG(0));
822 gen_op_cmp_eq_imm_T0(B7_0s);
823 return;
824 case 0xc400: /* mov.b @(disp,GBR),R0 */
825 gen_op_stc_gbr_T0();
826 gen_op_addl_imm_T0(B7_0);
827 gen_op_ldb_T0_T0(ctx);
828 gen_op_movl_T0_rN(REG(0));
829 return;
830 case 0xc500: /* mov.w @(disp,GBR),R0 */
831 gen_op_stc_gbr_T0();
24988dc2 832 gen_op_addl_imm_T0(B7_0 * 2);
fdf9b3e8
FB
833 gen_op_ldw_T0_T0(ctx);
834 gen_op_movl_T0_rN(REG(0));
835 return;
836 case 0xc600: /* mov.l @(disp,GBR),R0 */
837 gen_op_stc_gbr_T0();
24988dc2 838 gen_op_addl_imm_T0(B7_0 * 4);
fdf9b3e8
FB
839 gen_op_ldl_T0_T0(ctx);
840 gen_op_movl_T0_rN(REG(0));
841 return;
842 case 0xc000: /* mov.b R0,@(disp,GBR) */
843 gen_op_stc_gbr_T0();
844 gen_op_addl_imm_T0(B7_0);
845 gen_op_movl_T0_T1();
846 gen_op_movl_rN_T0(REG(0));
847 gen_op_stb_T0_T1(ctx);
848 return;
849 case 0xc100: /* mov.w R0,@(disp,GBR) */
850 gen_op_stc_gbr_T0();
24988dc2 851 gen_op_addl_imm_T0(B7_0 * 2);
fdf9b3e8
FB
852 gen_op_movl_T0_T1();
853 gen_op_movl_rN_T0(REG(0));
854 gen_op_stw_T0_T1(ctx);
855 return;
856 case 0xc200: /* mov.l R0,@(disp,GBR) */
857 gen_op_stc_gbr_T0();
24988dc2 858 gen_op_addl_imm_T0(B7_0 * 4);
fdf9b3e8
FB
859 gen_op_movl_T0_T1();
860 gen_op_movl_rN_T0(REG(0));
861 gen_op_stl_T0_T1(ctx);
862 return;
863 case 0x8000: /* mov.b R0,@(disp,Rn) */
864 gen_op_movl_rN_T0(REG(0));
865 gen_op_movl_rN_T1(REG(B7_4));
866 gen_op_addl_imm_T1(B3_0);
867 gen_op_stb_T0_T1(ctx);
868 return;
869 case 0x8100: /* mov.w R0,@(disp,Rn) */
870 gen_op_movl_rN_T0(REG(0));
871 gen_op_movl_rN_T1(REG(B7_4));
872 gen_op_addl_imm_T1(B3_0 * 2);
873 gen_op_stw_T0_T1(ctx);
874 return;
875 case 0x8400: /* mov.b @(disp,Rn),R0 */
8c2cc7ce
TS
876 gen_op_movl_rN_T0(REG(B7_4));
877 gen_op_addl_imm_T0(B3_0);
878 gen_op_ldb_T0_T0(ctx);
879 gen_op_movl_T0_rN(REG(0));
fdf9b3e8
FB
880 return;
881 case 0x8500: /* mov.w @(disp,Rn),R0 */
882 gen_op_movl_rN_T0(REG(B7_4));
883 gen_op_addl_imm_T0(B3_0 * 2);
884 gen_op_ldw_T0_T0(ctx);
885 gen_op_movl_T0_rN(REG(0));
886 return;
887 case 0xc700: /* mova @(disp,PC),R0 */
888 gen_op_movl_imm_rN(((ctx->pc & 0xfffffffc) + 4 + B7_0 * 4) & ~3,
889 REG(0));
890 return;
891 case 0xcb00: /* or #imm,R0 */
892 gen_op_or_imm_rN(B7_0, REG(0));
893 return;
24988dc2 894 case 0xcf00: /* or.b #imm,@(R0,GBR) */
fdf9b3e8
FB
895 gen_op_movl_rN_T0(REG(0));
896 gen_op_addl_GBR_T0();
897 gen_op_movl_T0_T1();
24988dc2 898 gen_op_ldub_T0_T0(ctx);
fdf9b3e8
FB
899 gen_op_or_imm_T0(B7_0);
900 gen_op_stb_T0_T1(ctx);
901 return;
902 case 0xc300: /* trapa #imm */
903 CHECK_NOT_DELAY_SLOT gen_op_movl_imm_PC(ctx->pc);
904 gen_op_trapa(B7_0);
823029f9 905 ctx->bstate = BS_BRANCH;
fdf9b3e8
FB
906 return;
907 case 0xc800: /* tst #imm,R0 */
908 gen_op_tst_imm_rN(B7_0, REG(0));
909 return;
24988dc2 910 case 0xcc00: /* tst.b #imm,@(R0,GBR) */
fdf9b3e8
FB
911 gen_op_movl_rN_T0(REG(0));
912 gen_op_addl_GBR_T0();
24988dc2 913 gen_op_ldub_T0_T0(ctx);
fdf9b3e8
FB
914 gen_op_tst_imm_T0(B7_0);
915 return;
916 case 0xca00: /* xor #imm,R0 */
917 gen_op_xor_imm_rN(B7_0, REG(0));
918 return;
24988dc2 919 case 0xce00: /* xor.b #imm,@(R0,GBR) */
fdf9b3e8
FB
920 gen_op_movl_rN_T0(REG(0));
921 gen_op_addl_GBR_T0();
922 gen_op_movl_T0_T1();
24988dc2 923 gen_op_ldub_T0_T0(ctx);
fdf9b3e8
FB
924 gen_op_xor_imm_T0(B7_0);
925 gen_op_stb_T0_T1(ctx);
926 return;
927 }
928
929 switch (ctx->opcode & 0xf08f) {
930 case 0x408e: /* ldc Rm,Rn_BANK */
931 gen_op_movl_rN_rN(REG(B11_8), ALTREG(B6_4));
932 return;
933 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
934 gen_op_movl_rN_T0(REG(B11_8));
935 gen_op_ldl_T0_T0(ctx);
936 gen_op_movl_T0_rN(ALTREG(B6_4));
937 gen_op_inc4_rN(REG(B11_8));
938 return;
939 case 0x0082: /* stc Rm_BANK,Rn */
940 gen_op_movl_rN_rN(ALTREG(B6_4), REG(B11_8));
941 return;
942 case 0x4083: /* stc.l Rm_BANK,@-Rn */
943 gen_op_dec4_rN(REG(B11_8));
944 gen_op_movl_rN_T1(REG(B11_8));
945 gen_op_movl_rN_T0(ALTREG(B6_4));
946 gen_op_stl_T0_T1(ctx);
947 return;
948 }
949
950 switch (ctx->opcode & 0xf0ff) {
951 case 0x0023: /* braf Rn */
952 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
953 gen_op_braf_T0(ctx->pc + 4);
954 ctx->flags |= DELAY_SLOT;
955 ctx->delayed_pc = (uint32_t) - 1;
956 return;
957 case 0x0003: /* bsrf Rn */
958 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
959 gen_op_bsrf_T0(ctx->pc + 4);
960 ctx->flags |= DELAY_SLOT;
961 ctx->delayed_pc = (uint32_t) - 1;
962 return;
963 case 0x4015: /* cmp/pl Rn */
964 gen_op_movl_rN_T0(REG(B11_8));
965 gen_op_cmp_pl_T0();
966 return;
967 case 0x4011: /* cmp/pz Rn */
968 gen_op_movl_rN_T0(REG(B11_8));
969 gen_op_cmp_pz_T0();
970 return;
971 case 0x4010: /* dt Rn */
972 gen_op_dt_rN(REG(B11_8));
973 return;
974 case 0x402b: /* jmp @Rn */
975 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
976 gen_op_jmp_T0();
977 ctx->flags |= DELAY_SLOT;
978 ctx->delayed_pc = (uint32_t) - 1;
979 return;
980 case 0x400b: /* jsr @Rn */
981 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
982 gen_op_jsr_T0(ctx->pc + 4);
983 ctx->flags |= DELAY_SLOT;
984 ctx->delayed_pc = (uint32_t) - 1;
985 return;
986#define LDST(reg,ldnum,ldpnum,ldop,stnum,stpnum,stop,extrald) \
987 case ldnum: \
988 gen_op_movl_rN_T0 (REG(B11_8)); \
989 gen_op_##ldop##_T0_##reg (); \
990 extrald \
991 return; \
992 case ldpnum: \
993 gen_op_movl_rN_T0 (REG(B11_8)); \
994 gen_op_ldl_T0_T0 (ctx); \
995 gen_op_inc4_rN (REG(B11_8)); \
996 gen_op_##ldop##_T0_##reg (); \
997 extrald \
998 return; \
999 case stnum: \
1000 gen_op_##stop##_##reg##_T0 (); \
1001 gen_op_movl_T0_rN (REG(B11_8)); \
1002 return; \
1003 case stpnum: \
1004 gen_op_##stop##_##reg##_T0 (); \
1005 gen_op_dec4_rN (REG(B11_8)); \
1006 gen_op_movl_rN_T1 (REG(B11_8)); \
1007 gen_op_stl_T0_T1 (ctx); \
1008 return;
823029f9
TS
1009 LDST(sr, 0x400e, 0x4007, ldc, 0x0002, 0x4003, stc, ctx->bstate =
1010 BS_STOP;)
eda9b09b
FB
1011 LDST(gbr, 0x401e, 0x4017, ldc, 0x0012, 0x4013, stc,)
1012 LDST(vbr, 0x402e, 0x4027, ldc, 0x0022, 0x4023, stc,)
1013 LDST(ssr, 0x403e, 0x4037, ldc, 0x0032, 0x4033, stc,)
1014 LDST(spc, 0x404e, 0x4047, ldc, 0x0042, 0x4043, stc,)
1015 LDST(dbr, 0x40fa, 0x40f6, ldc, 0x00fa, 0x40f2, stc,)
1016 LDST(mach, 0x400a, 0x4006, lds, 0x000a, 0x4002, sts,)
1017 LDST(macl, 0x401a, 0x4016, lds, 0x001a, 0x4012, sts,)
1018 LDST(pr, 0x402a, 0x4026, lds, 0x002a, 0x4022, sts,)
8bf5a804 1019 LDST(fpul, 0x405a, 0x4056, lds, 0x005a, 0x4052, sts,)
823029f9
TS
1020 LDST(fpscr, 0x406a, 0x4066, lds, 0x006a, 0x4062, sts, ctx->bstate =
1021 BS_STOP;)
fdf9b3e8
FB
1022 case 0x00c3: /* movca.l R0,@Rm */
1023 gen_op_movl_rN_T0(REG(0));
1024 gen_op_movl_rN_T1(REG(B11_8));
1025 gen_op_stl_T0_T1(ctx);
1026 return;
1027 case 0x0029: /* movt Rn */
1028 gen_op_movt_rN(REG(B11_8));
1029 return;
1030 case 0x0093: /* ocbi @Rn */
1031 gen_op_movl_rN_T0(REG(B11_8));
1032 gen_op_ldl_T0_T0(ctx);
1033 return;
24988dc2 1034 case 0x00a3: /* ocbp @Rn */
fdf9b3e8
FB
1035 gen_op_movl_rN_T0(REG(B11_8));
1036 gen_op_ldl_T0_T0(ctx);
1037 return;
1038 case 0x00b3: /* ocbwb @Rn */
1039 gen_op_movl_rN_T0(REG(B11_8));
1040 gen_op_ldl_T0_T0(ctx);
1041 return;
1042 case 0x0083: /* pref @Rn */
1043 return;
1044 case 0x4024: /* rotcl Rn */
1045 gen_op_rotcl_Rn(REG(B11_8));
1046 return;
1047 case 0x4025: /* rotcr Rn */
1048 gen_op_rotcr_Rn(REG(B11_8));
1049 return;
1050 case 0x4004: /* rotl Rn */
1051 gen_op_rotl_Rn(REG(B11_8));
1052 return;
1053 case 0x4005: /* rotr Rn */
1054 gen_op_rotr_Rn(REG(B11_8));
1055 return;
1056 case 0x4000: /* shll Rn */
1057 case 0x4020: /* shal Rn */
1058 gen_op_shal_Rn(REG(B11_8));
1059 return;
1060 case 0x4021: /* shar Rn */
1061 gen_op_shar_Rn(REG(B11_8));
1062 return;
1063 case 0x4001: /* shlr Rn */
1064 gen_op_shlr_Rn(REG(B11_8));
1065 return;
1066 case 0x4008: /* shll2 Rn */
1067 gen_op_shll2_Rn(REG(B11_8));
1068 return;
1069 case 0x4018: /* shll8 Rn */
1070 gen_op_shll8_Rn(REG(B11_8));
1071 return;
1072 case 0x4028: /* shll16 Rn */
1073 gen_op_shll16_Rn(REG(B11_8));
1074 return;
1075 case 0x4009: /* shlr2 Rn */
1076 gen_op_shlr2_Rn(REG(B11_8));
1077 return;
1078 case 0x4019: /* shlr8 Rn */
1079 gen_op_shlr8_Rn(REG(B11_8));
1080 return;
1081 case 0x4029: /* shlr16 Rn */
1082 gen_op_shlr16_Rn(REG(B11_8));
1083 return;
1084 case 0x401b: /* tas.b @Rn */
1085 gen_op_tasb_rN(REG(B11_8));
1086 return;
e67888a7 1087 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
eda9b09b
FB
1088 gen_op_movl_fpul_FT0();
1089 gen_op_fmov_FT0_frN(FREG(B11_8));
1090 return;
e67888a7 1091 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
eda9b09b
FB
1092 gen_op_fmov_frN_FT0(FREG(B11_8));
1093 gen_op_movl_FT0_fpul();
1094 return;
e67888a7 1095 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
ea6cf6be
TS
1096 if (ctx->fpscr & FPSCR_PR) {
1097 if (ctx->opcode & 0x0100)
1098 break; /* illegal instruction */
1099 gen_op_float_DT();
1100 gen_op_fmov_DT0_drN(DREG(B11_8));
1101 }
1102 else {
1103 gen_op_float_FT();
1104 gen_op_fmov_FT0_frN(FREG(B11_8));
1105 }
1106 return;
e67888a7 1107 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
ea6cf6be
TS
1108 if (ctx->fpscr & FPSCR_PR) {
1109 if (ctx->opcode & 0x0100)
1110 break; /* illegal instruction */
1111 gen_op_fmov_drN_DT0(DREG(B11_8));
1112 gen_op_ftrc_DT();
1113 }
1114 else {
1115 gen_op_fmov_frN_FT0(FREG(B11_8));
1116 gen_op_ftrc_FT();
1117 }
1118 return;
24988dc2
AJ
1119 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */
1120 gen_op_fneg_frN(FREG(B11_8));
1121 return;
1122 case 0xf05d: /* fabs FRn/DRn */
1123 if (ctx->fpscr & FPSCR_PR) {
1124 if (ctx->opcode & 0x0100)
1125 break; /* illegal instruction */
1126 gen_op_fmov_drN_DT0(DREG(B11_8));
1127 gen_op_fabs_DT();
1128 gen_op_fmov_DT0_drN(DREG(B11_8));
1129 } else {
1130 gen_op_fmov_frN_FT0(FREG(B11_8));
1131 gen_op_fabs_FT();
1132 gen_op_fmov_FT0_frN(FREG(B11_8));
1133 }
1134 return;
1135 case 0xf06d: /* fsqrt FRn */
1136 if (ctx->fpscr & FPSCR_PR) {
1137 if (ctx->opcode & 0x0100)
1138 break; /* illegal instruction */
1139 gen_op_fmov_drN_DT0(FREG(B11_8));
1140 gen_op_fsqrt_DT();
1141 gen_op_fmov_DT0_drN(FREG(B11_8));
1142 } else {
1143 gen_op_fmov_frN_FT0(FREG(B11_8));
1144 gen_op_fsqrt_FT();
1145 gen_op_fmov_FT0_frN(FREG(B11_8));
1146 }
1147 return;
1148 case 0xf07d: /* fsrra FRn */
1149 break;
e67888a7 1150 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
ea6cf6be
TS
1151 if (!(ctx->fpscr & FPSCR_PR)) {
1152 gen_op_movl_imm_T0(0);
1153 gen_op_fmov_T0_frN(FREG(B11_8));
1154 return;
1155 }
1156 break;
e67888a7 1157 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
ea6cf6be
TS
1158 if (!(ctx->fpscr & FPSCR_PR)) {
1159 gen_op_movl_imm_T0(0x3f800000);
1160 gen_op_fmov_T0_frN(FREG(B11_8));
1161 return;
1162 }
1163 break;
24988dc2
AJ
1164 case 0xf0ad: /* fcnvsd FPUL,DRn */
1165 gen_op_movl_fpul_FT0();
1166 gen_op_fcnvsd_FT_DT();
1167 gen_op_fmov_DT0_drN(DREG(B11_8));
1168 return;
1169 case 0xf0bd: /* fcnvds DRn,FPUL */
1170 gen_op_fmov_drN_DT0(DREG(B11_8));
1171 gen_op_fcnvds_DT_FT();
1172 gen_op_movl_FT0_fpul();
1173 return;
fdf9b3e8
FB
1174 }
1175
1176 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
1177 ctx->opcode, ctx->pc);
1178 gen_op_raise_illegal_instruction();
823029f9
TS
1179 ctx->bstate = BS_EXCP;
1180}
1181
1182void decode_opc(DisasContext * ctx)
1183{
1184 uint32_t old_flags = ctx->flags;
1185
1186 _decode_opc(ctx);
1187
1188 if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
1189 if (ctx->flags & DELAY_SLOT_CLEARME) {
1190 gen_op_store_flags(0);
1191 }
1192 ctx->flags = 0;
1193 ctx->bstate = BS_BRANCH;
1194 if (old_flags & DELAY_SLOT_CONDITIONAL) {
1195 gen_delayed_conditional_jump(ctx);
1196 } else if (old_flags & DELAY_SLOT) {
1197 gen_jump(ctx);
1198 }
1199
1200 }
fdf9b3e8
FB
1201}
1202
2cfc5f17 1203static inline void
820e00f2
TS
1204gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
1205 int search_pc)
fdf9b3e8
FB
1206{
1207 DisasContext ctx;
1208 target_ulong pc_start;
1209 static uint16_t *gen_opc_end;
355fb23d 1210 int i, ii;
2e70f6ef
PB
1211 int num_insns;
1212 int max_insns;
fdf9b3e8
FB
1213
1214 pc_start = tb->pc;
fdf9b3e8 1215 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
fdf9b3e8 1216 ctx.pc = pc_start;
823029f9
TS
1217 ctx.flags = (uint32_t)tb->flags;
1218 ctx.bstate = BS_NONE;
fdf9b3e8 1219 ctx.sr = env->sr;
eda9b09b 1220 ctx.fpscr = env->fpscr;
fdf9b3e8 1221 ctx.memidx = (env->sr & SR_MD) ? 1 : 0;
9854bc46
PB
1222 /* We don't know if the delayed pc came from a dynamic or static branch,
1223 so assume it is a dynamic branch. */
823029f9 1224 ctx.delayed_pc = -1; /* use delayed pc from env pointer */
fdf9b3e8
FB
1225 ctx.tb = tb;
1226 ctx.singlestep_enabled = env->singlestep_enabled;
fdf9b3e8
FB
1227
1228#ifdef DEBUG_DISAS
1229 if (loglevel & CPU_LOG_TB_CPU) {
1230 fprintf(logfile,
1231 "------------------------------------------------\n");
1232 cpu_dump_state(env, logfile, fprintf, 0);
1233 }
1234#endif
1235
355fb23d 1236 ii = -1;
2e70f6ef
PB
1237 num_insns = 0;
1238 max_insns = tb->cflags & CF_COUNT_MASK;
1239 if (max_insns == 0)
1240 max_insns = CF_COUNT_MASK;
1241 gen_icount_start();
823029f9 1242 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
fdf9b3e8
FB
1243 if (env->nb_breakpoints > 0) {
1244 for (i = 0; i < env->nb_breakpoints; i++) {
1245 if (ctx.pc == env->breakpoints[i]) {
1246 /* We have hit a breakpoint - make sure PC is up-to-date */
1247 gen_op_movl_imm_PC(ctx.pc);
1248 gen_op_debug();
823029f9 1249 ctx.bstate = BS_EXCP;
fdf9b3e8
FB
1250 break;
1251 }
1252 }
1253 }
355fb23d
PB
1254 if (search_pc) {
1255 i = gen_opc_ptr - gen_opc_buf;
1256 if (ii < i) {
1257 ii++;
1258 while (ii < i)
1259 gen_opc_instr_start[ii++] = 0;
1260 }
1261 gen_opc_pc[ii] = ctx.pc;
823029f9 1262 gen_opc_hflags[ii] = ctx.flags;
355fb23d 1263 gen_opc_instr_start[ii] = 1;
2e70f6ef 1264 gen_opc_icount[ii] = num_insns;
355fb23d 1265 }
2e70f6ef
PB
1266 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
1267 gen_io_start();
fdf9b3e8
FB
1268#if 0
1269 fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc);
1270 fflush(stderr);
1271#endif
1272 ctx.opcode = lduw_code(ctx.pc);
1273 decode_opc(&ctx);
2e70f6ef 1274 num_insns++;
fdf9b3e8
FB
1275 ctx.pc += 2;
1276 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1277 break;
1278 if (env->singlestep_enabled)
1279 break;
2e70f6ef
PB
1280 if (num_insns >= max_insns)
1281 break;
fdf9b3e8
FB
1282#ifdef SH4_SINGLE_STEP
1283 break;
1284#endif
1285 }
2e70f6ef
PB
1286 if (tb->cflags & CF_LAST_IO)
1287 gen_io_end();
fdf9b3e8 1288 if (env->singlestep_enabled) {
823029f9
TS
1289 gen_op_debug();
1290 } else {
1291 switch (ctx.bstate) {
1292 case BS_STOP:
1293 /* gen_op_interrupt_restart(); */
1294 /* fall through */
1295 case BS_NONE:
1296 if (ctx.flags) {
1297 gen_op_store_flags(ctx.flags | DELAY_SLOT_CLEARME);
1298 }
1299 gen_goto_tb(&ctx, 0, ctx.pc);
1300 break;
1301 case BS_EXCP:
1302 /* gen_op_interrupt_restart(); */
57fec1fe 1303 tcg_gen_exit_tb(0);
823029f9
TS
1304 break;
1305 case BS_BRANCH:
1306 default:
1307 break;
1308 }
fdf9b3e8 1309 }
823029f9 1310
2e70f6ef 1311 gen_icount_end(tb, num_insns);
fdf9b3e8 1312 *gen_opc_ptr = INDEX_op_end;
355fb23d
PB
1313 if (search_pc) {
1314 i = gen_opc_ptr - gen_opc_buf;
1315 ii++;
1316 while (ii <= i)
1317 gen_opc_instr_start[ii++] = 0;
355fb23d
PB
1318 } else {
1319 tb->size = ctx.pc - pc_start;
2e70f6ef 1320 tb->icount = num_insns;
355fb23d 1321 }
fdf9b3e8
FB
1322
1323#ifdef DEBUG_DISAS
1324#ifdef SH4_DEBUG_DISAS
1325 if (loglevel & CPU_LOG_TB_IN_ASM)
1326 fprintf(logfile, "\n");
1327#endif
1328 if (loglevel & CPU_LOG_TB_IN_ASM) {
1329 fprintf(logfile, "IN:\n"); /* , lookup_symbol(pc_start)); */
1330 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
1331 fprintf(logfile, "\n");
1332 }
fdf9b3e8 1333#endif
fdf9b3e8
FB
1334}
1335
2cfc5f17 1336void gen_intermediate_code(CPUState * env, struct TranslationBlock *tb)
fdf9b3e8 1337{
2cfc5f17 1338 gen_intermediate_code_internal(env, tb, 0);
fdf9b3e8
FB
1339}
1340
2cfc5f17 1341void gen_intermediate_code_pc(CPUState * env, struct TranslationBlock *tb)
fdf9b3e8 1342{
2cfc5f17 1343 gen_intermediate_code_internal(env, tb, 1);
fdf9b3e8 1344}
d2856f1a
AJ
1345
1346void gen_pc_load(CPUState *env, TranslationBlock *tb,
1347 unsigned long searched_pc, int pc_pos, void *puc)
1348{
1349 env->pc = gen_opc_pc[pc_pos];
1350 env->flags = gen_opc_hflags[pc_pos];
1351}