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