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