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