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