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