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