Use lookup table for PCI class descriptions.
[qemu/mini2440.git] / target-sh4 / translate.c
blob0013e492d3e9688f9d0075b7a415e441d0050476
1 /*
2 * SH4 translation
3 *
4 * Copyright (c) 2005 Samuel Tardieu
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
25 #include <assert.h>
27 #define DEBUG_DISAS
28 #define SH4_DEBUG_DISAS
29 //#define SH4_SINGLE_STEP
31 #include "cpu.h"
32 #include "exec-all.h"
33 #include "disas.h"
35 enum {
36 #define DEF(s, n, copy_size) INDEX_op_ ## s,
37 #include "opc.h"
38 #undef DEF
39 NB_OPS,
42 #ifdef USE_DIRECT_JUMP
43 #define TBPARAM(x)
44 #else
45 #define TBPARAM(x) ((long)(x))
46 #endif
48 static uint16_t *gen_opc_ptr;
49 static uint32_t *gen_opparam_ptr;
51 #include "gen-op.h"
53 typedef struct DisasContext {
54 struct TranslationBlock *tb;
55 target_ulong pc;
56 uint32_t sr;
57 uint16_t opcode;
58 uint32_t flags;
59 int memidx;
60 uint32_t delayed_pc;
61 int singlestep_enabled;
62 } DisasContext;
64 #ifdef CONFIG_USER_ONLY
66 #define GEN_OP_LD(width) \
67 void gen_op_ld##width##_T0_T0 (DisasContext *ctx) { \
68 gen_op_ld##width##_T0_T0_raw(); \
70 #define GEN_OP_ST(width) \
71 void gen_op_st##width##_T0_T1 (DisasContext *ctx) { \
72 gen_op_st##width##_T0_T1_raw(); \
75 #else
77 #define GEN_OP_LD(width) \
78 void gen_op_ld##width##_T0_T0 (DisasContext *ctx) { \
79 if (ctx->memidx) gen_op_ld##width##_T0_T0_kernel(); \
80 else gen_op_ld##width##_T0_T0_user();\
82 #define GEN_OP_ST(width) \
83 void gen_op_st##width##_T0_T1 (DisasContext *ctx) { \
84 if (ctx->memidx) gen_op_st##width##_T0_T1_kernel(); \
85 else gen_op_st##width##_T0_T1_user();\
88 #endif
90 GEN_OP_LD(ub)
91 GEN_OP_LD(b)
92 GEN_OP_ST(b)
93 GEN_OP_LD(uw)
94 GEN_OP_LD(w)
95 GEN_OP_ST(w)
96 GEN_OP_LD(l)
97 GEN_OP_ST(l)
99 void cpu_dump_state(CPUState * env, FILE * f,
100 int (*cpu_fprintf) (FILE * f, const char *fmt, ...),
101 int flags)
103 int i;
104 cpu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x\n",
105 env->pc, env->sr, env->pr);
106 for (i = 0; i < 24; i += 4) {
107 cpu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
108 i, env->gregs[i], i + 1, env->gregs[i + 1],
109 i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
111 if (env->flags & DELAY_SLOT) {
112 cpu_fprintf(f, "in delay slot (delayed_pc=0x%08x)\n",
113 env->delayed_pc);
114 } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
115 cpu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n",
116 env->delayed_pc);
120 void cpu_sh4_reset(CPUSH4State * env)
122 env->sr = 0x700000F0; /* MD, RB, BL, I3-I0 */
123 env->vbr = 0;
124 env->pc = 0xA0000000;
125 env->fpscr = 0x00040001;
126 env->mmucr = 0;
129 CPUSH4State *cpu_sh4_init(void)
131 CPUSH4State *env;
133 env = qemu_mallocz(sizeof(CPUSH4State));
134 if (!env)
135 return NULL;
136 cpu_exec_init(env);
137 cpu_sh4_reset(env);
138 tlb_flush(env, 1);
139 return env;
142 #ifdef CONFIG_USER_ONLY
143 target_ulong cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
145 return addr;
147 #else
148 target_ulong cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
150 target_ulong physical;
151 int prot;
153 get_physical_address(env, &physical, &prot, addr, PAGE_READ, 0);
154 return physical;
156 #endif
158 static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
160 TranslationBlock *tb;
161 tb = ctx->tb;
163 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
164 !ctx->singlestep_enabled) {
165 /* Use a direct jump if in same page and singlestep not enabled */
166 if (n == 0)
167 gen_op_goto_tb0(TBPARAM(tb));
168 else
169 gen_op_goto_tb1(TBPARAM(tb));
170 gen_op_movl_imm_T0((long) tb + n);
171 } else {
172 gen_op_movl_imm_T0(0);
174 gen_op_movl_imm_PC(dest);
175 if (ctx->singlestep_enabled)
176 gen_op_debug();
177 gen_op_exit_tb();
180 /* Jump to pc after an exception */
181 static void gen_jump_exception(DisasContext * ctx)
183 gen_op_movl_imm_T0(0);
184 if (ctx->singlestep_enabled)
185 gen_op_debug();
186 gen_op_exit_tb();
189 static void gen_jump(DisasContext * ctx)
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);
204 /* Immediate conditional jump (bt or bf) */
205 static void gen_conditional_jump(DisasContext * ctx,
206 target_ulong ift, target_ulong ifnott)
208 int l1;
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);
217 /* Delayed conditional jump (bt or bf) */
218 static void gen_delayed_conditional_jump(DisasContext * ctx)
220 int l1;
222 l1 = gen_new_label();
223 gen_op_jTT2(l1);
224 gen_goto_tb(ctx, 0, ctx->pc);
225 gen_set_label(l1);
226 gen_goto_tb(ctx, 1, ctx->delayed_pc);
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)
239 #define REG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB) ? \
240 (x) + 16 : (x))
242 #define ALTREG(x) ((x) < 8 && (ctx->sr & (SR_MD | SR_RB)) != (SR_MD | SR_RB) \
243 ? (x) + 16 : (x))
245 #define CHECK_NOT_DELAY_SLOT \
246 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \
247 {gen_op_raise_slot_illegal_instruction (); ctx->flags |= BRANCH_EXCEPTION; \
248 return;}
250 void decode_opc(DisasContext * ctx)
252 #if 0
253 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
254 #endif
255 switch (ctx->opcode) {
256 case 0x0019: /* div0u */
257 printf("div0u\n");
258 gen_op_div0u();
259 return;
260 case 0x000b: /* rts */
261 CHECK_NOT_DELAY_SLOT gen_op_rts();
262 ctx->flags |= DELAY_SLOT;
263 ctx->delayed_pc = (uint32_t) - 1;
264 return;
265 case 0x0028: /* clrmac */
266 gen_op_clrmac();
267 return;
268 case 0x0048: /* clrs */
269 gen_op_clrs();
270 return;
271 case 0x0008: /* clrt */
272 gen_op_clrt();
273 return;
274 case 0x0038: /* ldtlb */
275 assert(0); /* XXXXX */
276 return;
277 case 0x004b: /* rte */
278 CHECK_NOT_DELAY_SLOT gen_op_rte();
279 ctx->flags |= DELAY_SLOT;
280 ctx->delayed_pc = (uint32_t) - 1;
281 return;
282 case 0x0058: /* sets */
283 gen_op_sets();
284 return;
285 case 0x0018: /* sett */
286 gen_op_sett();
287 return;
288 case 0xfbfb: /* frchg */
289 assert(0); /* XXXXX */
290 return;
291 case 0xf3fb: /* fschg */
292 assert(0); /* XXXXX */
293 return;
294 case 0x0009: /* nop */
295 return;
296 case 0x001b: /* sleep */
297 assert(0); /* XXXXX */
298 return;
301 switch (ctx->opcode & 0xf000) {
302 case 0x1000: /* mov.l Rm,@(disp,Rn) */
303 gen_op_movl_rN_T0(REG(B7_4));
304 gen_op_movl_rN_T1(REG(B11_8));
305 gen_op_addl_imm_T1(B3_0 * 4);
306 gen_op_stl_T0_T1(ctx);
307 return;
308 case 0x5000: /* mov.l @(disp,Rm),Rn */
309 gen_op_movl_rN_T0(REG(B7_4));
310 gen_op_addl_imm_T0(B3_0 * 4);
311 gen_op_ldl_T0_T0(ctx);
312 gen_op_movl_T0_rN(REG(B11_8));
313 return;
314 case 0xe000: /* mov.l #imm,Rn */
315 gen_op_movl_imm_rN(B7_0s, REG(B11_8));
316 return;
317 case 0x9000: /* mov.w @(disp,PC),Rn */
318 gen_op_movl_imm_T0(ctx->pc + 4 + B7_0 * 2);
319 gen_op_ldw_T0_T0(ctx);
320 gen_op_movl_T0_rN(REG(B11_8));
321 return;
322 case 0xd000: /* mov.l @(disp,PC),Rn */
323 gen_op_movl_imm_T0((ctx->pc + 4 + B7_0 * 4) & ~3);
324 gen_op_ldl_T0_T0(ctx);
325 gen_op_movl_T0_rN(REG(B11_8));
326 return;
327 case 0x7000: /* add.l #imm,Rn */
328 gen_op_add_imm_rN(B7_0s, REG(B11_8));
329 return;
330 case 0xa000: /* bra disp */
331 CHECK_NOT_DELAY_SLOT
332 gen_op_bra(ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2);
333 ctx->flags |= DELAY_SLOT;
334 return;
335 case 0xb000: /* bsr disp */
336 CHECK_NOT_DELAY_SLOT
337 gen_op_bsr(ctx->pc + 4, ctx->delayed_pc =
338 ctx->pc + 4 + B11_0s * 2);
339 ctx->flags |= DELAY_SLOT;
340 return;
343 switch (ctx->opcode & 0xf00f) {
344 case 0x6003: /* mov Rm,Rn */
345 gen_op_movl_rN_T0(REG(B7_4));
346 gen_op_movl_T0_rN(REG(B11_8));
347 return;
348 case 0x2000: /* mov.b Rm,@Rn */
349 gen_op_movl_rN_T0(REG(B7_4));
350 gen_op_movl_rN_T1(REG(B11_8));
351 gen_op_stb_T0_T1(ctx);
352 return;
353 case 0x2001: /* mov.w Rm,@Rn */
354 gen_op_movl_rN_T0(REG(B7_4));
355 gen_op_movl_rN_T1(REG(B11_8));
356 gen_op_stw_T0_T1(ctx);
357 return;
358 case 0x2002: /* mov.l Rm,@Rn */
359 gen_op_movl_rN_T0(REG(B7_4));
360 gen_op_movl_rN_T1(REG(B11_8));
361 gen_op_stl_T0_T1(ctx);
362 return;
363 case 0x6000: /* mov.b @Rm,Rn */
364 gen_op_movl_rN_T0(REG(B7_4));
365 gen_op_ldb_T0_T0(ctx);
366 gen_op_movl_T0_rN(REG(B11_8));
367 return;
368 case 0x6001: /* mov.w @Rm,Rn */
369 gen_op_movl_rN_T0(REG(B7_4));
370 gen_op_ldw_T0_T0(ctx);
371 gen_op_movl_T0_rN(REG(B11_8));
372 return;
373 case 0x6002: /* mov.l @Rm,Rn */
374 gen_op_movl_rN_T0(REG(B7_4));
375 gen_op_ldl_T0_T0(ctx);
376 gen_op_movl_T0_rN(REG(B11_8));
377 return;
378 case 0x2004: /* mov.b Rm,@-Rn */
379 gen_op_dec1_rN(REG(B11_8));
380 gen_op_movl_rN_T0(REG(B7_4));
381 gen_op_movl_rN_T1(REG(B11_8));
382 gen_op_stb_T0_T1(ctx);
383 return;
384 case 0x2005: /* mov.w Rm,@-Rn */
385 gen_op_dec2_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_stw_T0_T1(ctx);
389 return;
390 case 0x2006: /* mov.l Rm,@-Rn */
391 gen_op_dec4_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_stl_T0_T1(ctx);
395 return;
396 case 0x6004: /* mov.l @Rm+,Rn */
397 gen_op_movl_rN_T0(REG(B7_4));
398 gen_op_ldb_T0_T0(ctx);
399 gen_op_movl_T0_rN(REG(B11_8));
400 gen_op_inc1_rN(REG(B7_4));
401 return;
402 case 0x6005: /* mov.w @Rm+,Rn */
403 gen_op_movl_rN_T0(REG(B7_4));
404 gen_op_ldw_T0_T0(ctx);
405 gen_op_movl_T0_rN(REG(B11_8));
406 gen_op_inc2_rN(REG(B7_4));
407 return;
408 case 0x6006: /* mov.l @Rm+,Rn */
409 gen_op_movl_rN_T0(REG(B7_4));
410 gen_op_ldl_T0_T0(ctx);
411 gen_op_movl_T0_rN(REG(B11_8));
412 gen_op_inc4_rN(REG(B7_4));
413 return;
414 case 0x0004: /* mov.b Rm,@(R0,Rn) */
415 gen_op_movl_rN_T0(REG(B7_4));
416 gen_op_movl_rN_T1(REG(B11_8));
417 gen_op_add_rN_T1(REG(0));
418 gen_op_stb_T0_T1(ctx);
419 return;
420 case 0x0005: /* mov.w 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_stw_T0_T1(ctx);
425 return;
426 case 0x0006: /* mov.l 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_stl_T0_T1(ctx);
431 return;
432 case 0x000c: /* mov.b @(R0,Rm),Rn */
433 gen_op_movl_rN_T0(REG(B7_4));
434 gen_op_add_rN_T0(REG(0));
435 gen_op_ldb_T0_T0(ctx);
436 gen_op_movl_T0_rN(REG(B11_8));
437 return;
438 case 0x000d: /* mov.w @(R0,Rm),Rn */
439 gen_op_movl_rN_T0(REG(B7_4));
440 gen_op_add_rN_T0(REG(0));
441 gen_op_ldw_T0_T0(ctx);
442 gen_op_movl_T0_rN(REG(B11_8));
443 return;
444 case 0x000e: /* mov.l @(R0,Rm),Rn */
445 gen_op_movl_rN_T0(REG(B7_4));
446 gen_op_add_rN_T0(REG(0));
447 gen_op_ldl_T0_T0(ctx);
448 gen_op_movl_T0_rN(REG(B11_8));
449 return;
450 case 0x6008: /* swap.b Rm,Rn */
451 gen_op_movl_rN_T0(REG(B7_4));
452 gen_op_swapb_T0();
453 gen_op_movl_T0_rN(REG(B11_8));
454 return;
455 case 0x6009: /* swap.w Rm,Rn */
456 gen_op_movl_rN_T0(REG(B7_4));
457 gen_op_swapw_T0();
458 gen_op_movl_T0_rN(REG(B11_8));
459 return;
460 case 0x200d: /* xtrct Rm,Rn */
461 gen_op_movl_rN_T0(REG(B7_4));
462 gen_op_movl_rN_T1(REG(B11_8));
463 gen_op_xtrct_T0_T1();
464 gen_op_movl_T1_rN(REG(B11_8));
465 return;
466 case 0x300c: /* add Rm,Rn */
467 gen_op_movl_rN_T0(REG(B7_4));
468 gen_op_add_T0_rN(REG(B11_8));
469 return;
470 case 0x300e: /* addc Rm,Rn */
471 gen_op_movl_rN_T0(REG(B7_4));
472 gen_op_movl_rN_T1(REG(B11_8));
473 gen_op_addc_T0_T1();
474 gen_op_movl_T1_rN(REG(B11_8));
475 return;
476 case 0x300f: /* addv Rm,Rn */
477 gen_op_movl_rN_T0(REG(B7_4));
478 gen_op_movl_rN_T1(REG(B11_8));
479 gen_op_addv_T0_T1();
480 gen_op_movl_T1_rN(REG(B11_8));
481 return;
482 case 0x2009: /* and Rm,Rn */
483 gen_op_movl_rN_T0(REG(B7_4));
484 gen_op_and_T0_rN(REG(B11_8));
485 return;
486 case 0x3000: /* cmp/eq Rm,Rn */
487 gen_op_movl_rN_T0(REG(B7_4));
488 gen_op_movl_rN_T1(REG(B11_8));
489 gen_op_cmp_eq_T0_T1();
490 return;
491 case 0x3003: /* cmp/ge Rm,Rn */
492 gen_op_movl_rN_T0(REG(B7_4));
493 gen_op_movl_rN_T1(REG(B11_8));
494 gen_op_cmp_ge_T0_T1();
495 return;
496 case 0x3007: /* cmp/gt Rm,Rn */
497 gen_op_movl_rN_T0(REG(B7_4));
498 gen_op_movl_rN_T1(REG(B11_8));
499 gen_op_cmp_gt_T0_T1();
500 return;
501 case 0x3006: /* cmp/hi Rm,Rn */
502 gen_op_movl_rN_T0(REG(B7_4));
503 gen_op_movl_rN_T1(REG(B11_8));
504 gen_op_cmp_hi_T0_T1();
505 return;
506 case 0x3002: /* cmp/hs Rm,Rn */
507 gen_op_movl_rN_T0(REG(B7_4));
508 gen_op_movl_rN_T1(REG(B11_8));
509 gen_op_cmp_hs_T0_T1();
510 return;
511 case 0x200c: /* cmp/str Rm,Rn */
512 gen_op_movl_rN_T0(REG(B7_4));
513 gen_op_movl_rN_T1(REG(B11_8));
514 gen_op_cmp_str_T0_T1();
515 return;
516 case 0x2007: /* div0s Rm,Rn */
517 printf("div0s\n");
518 gen_op_movl_rN_T0(REG(B7_4));
519 gen_op_movl_rN_T1(REG(B11_8));
520 gen_op_div0s_T0_T1();
521 gen_op_movl_T1_rN(REG(B11_8));
522 return;
523 case 0x3004: /* div1 Rm,Rn */
524 gen_op_movl_rN_T0(REG(B7_4));
525 gen_op_movl_rN_T1(REG(B11_8));
526 gen_op_div1_T0_T1();
527 gen_op_movl_T1_rN(REG(B11_8));
528 return;
529 case 0x300d: /* dmuls.l Rm,Rn */
530 gen_op_movl_rN_T0(REG(B7_4));
531 gen_op_movl_rN_T1(REG(B11_8));
532 gen_op_dmulsl_T0_T1();
533 return;
534 case 0x3005: /* dmulu.l Rm,Rn */
535 gen_op_movl_rN_T0(REG(B7_4));
536 gen_op_movl_rN_T1(REG(B11_8));
537 gen_op_dmulul_T0_T1();
538 return;
539 case 0x600e: /* exts.b Rm,Rn */
540 gen_op_movb_rN_T0(REG(B7_4));
541 gen_op_movl_T0_rN(REG(B11_8));
542 return;
543 case 0x600f: /* exts.w Rm,Rn */
544 gen_op_movw_rN_T0(REG(B7_4));
545 gen_op_movl_T0_rN(REG(B11_8));
546 return;
547 case 0x600c: /* extu.b Rm,Rn */
548 gen_op_movub_rN_T0(REG(B7_4));
549 gen_op_movl_T0_rN(REG(B11_8));
550 return;
551 case 0x600d: /* extu.w Rm,Rn */
552 gen_op_movuw_rN_T0(REG(B7_4));
553 gen_op_movl_T0_rN(REG(B11_8));
554 return;
555 case 0x000f: /* mac.l @Rm+,@Rn- */
556 gen_op_movl_rN_T0(REG(B11_8));
557 gen_op_ldl_T0_T0(ctx);
558 gen_op_movl_T0_T1();
559 gen_op_movl_rN_T1(REG(B7_4));
560 gen_op_ldl_T0_T0(ctx);
561 gen_op_macl_T0_T1();
562 gen_op_inc4_rN(REG(B7_4));
563 gen_op_inc4_rN(REG(B11_8));
564 return;
565 case 0x400f: /* mac.w @Rm+,@Rn+ */
566 gen_op_movl_rN_T0(REG(B11_8));
567 gen_op_ldl_T0_T0(ctx);
568 gen_op_movl_T0_T1();
569 gen_op_movl_rN_T1(REG(B7_4));
570 gen_op_ldl_T0_T0(ctx);
571 gen_op_macw_T0_T1();
572 gen_op_inc2_rN(REG(B7_4));
573 gen_op_inc2_rN(REG(B11_8));
574 return;
575 case 0x0007: /* mul.l Rm,Rn */
576 gen_op_movl_rN_T0(REG(B7_4));
577 gen_op_movl_rN_T1(REG(B11_8));
578 gen_op_mull_T0_T1();
579 return;
580 case 0x200f: /* muls.w Rm,Rn */
581 gen_op_movw_rN_T0(REG(B7_4));
582 gen_op_movw_rN_T1(REG(B11_8));
583 gen_op_mulsw_T0_T1();
584 return;
585 case 0x200e: /* mulu.w Rm,Rn */
586 gen_op_movuw_rN_T0(REG(B7_4));
587 gen_op_movuw_rN_T1(REG(B11_8));
588 gen_op_muluw_T0_T1();
589 return;
590 case 0x600b: /* neg Rm,Rn */
591 gen_op_movl_rN_T0(REG(B7_4));
592 gen_op_neg_T0();
593 gen_op_movl_T0_rN(REG(B11_8));
594 return;
595 case 0x600a: /* negc Rm,Rn */
596 gen_op_movl_rN_T0(REG(B7_4));
597 gen_op_negc_T0();
598 gen_op_movl_T0_rN(REG(B11_8));
599 return;
600 case 0x6007: /* not Rm,Rn */
601 gen_op_movl_rN_T0(REG(B7_4));
602 gen_op_not_T0();
603 gen_op_movl_T0_rN(REG(B11_8));
604 return;
605 case 0x200b: /* or Rm,Rn */
606 gen_op_movl_rN_T0(REG(B7_4));
607 gen_op_or_T0_rN(REG(B11_8));
608 return;
609 case 0x400c: /* shad Rm,Rn */
610 gen_op_movl_rN_T0(REG(B7_4));
611 gen_op_movl_rN_T1(REG(B11_8));
612 gen_op_shad_T0_T1();
613 gen_op_movl_T1_rN(REG(B11_8));
614 return;
615 case 0x400d: /* shld Rm,Rn */
616 gen_op_movl_rN_T0(REG(B7_4));
617 gen_op_movl_rN_T1(REG(B11_8));
618 gen_op_shld_T0_T1();
619 gen_op_movl_T1_rN(REG(B11_8));
620 return;
621 case 0x3008: /* sub Rm,Rn */
622 gen_op_movl_rN_T0(REG(B7_4));
623 gen_op_sub_T0_rN(REG(B11_8));
624 return;
625 case 0x300a: /* subc Rm,Rn */
626 gen_op_movl_rN_T0(REG(B7_4));
627 gen_op_movl_rN_T1(REG(B11_8));
628 gen_op_subc_T0_T1();
629 gen_op_movl_T1_rN(REG(B11_8));
630 return;
631 case 0x300b: /* subv Rm,Rn */
632 gen_op_movl_rN_T0(REG(B7_4));
633 gen_op_movl_rN_T1(REG(B11_8));
634 gen_op_subv_T0_T1();
635 gen_op_movl_T1_rN(REG(B11_8));
636 return;
637 case 0x2008: /* tst Rm,Rn */
638 gen_op_movl_rN_T0(REG(B7_4));
639 gen_op_movl_rN_T1(REG(B11_8));
640 gen_op_tst_T0_T1();
641 return;
642 case 0x200a: /* xor Rm,Rn */
643 gen_op_movl_rN_T0(REG(B7_4));
644 gen_op_xor_T0_rN(REG(B11_8));
645 return;
648 switch (ctx->opcode & 0xff00) {
649 case 0xc900: /* and #imm,R0 */
650 gen_op_and_imm_rN(B7_0, REG(0));
651 return;
652 case 0xcd00: /* and.b #imm,@(R0+GBR) */
653 gen_op_movl_rN_T0(REG(0));
654 gen_op_addl_GBR_T0();
655 gen_op_movl_T0_T1();
656 gen_op_ldb_T0_T0(ctx);
657 gen_op_and_imm_T0(B7_0);
658 gen_op_stb_T0_T1(ctx);
659 return;
660 case 0x8b00: /* bf label */
661 CHECK_NOT_DELAY_SLOT
662 gen_conditional_jump(ctx, ctx->pc + 2,
663 ctx->pc + 4 + B7_0s * 2);
664 ctx->flags |= BRANCH_CONDITIONAL;
665 return;
666 case 0x8f00: /* bf/s label */
667 CHECK_NOT_DELAY_SLOT
668 gen_op_bf_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2);
669 ctx->flags |= DELAY_SLOT_CONDITIONAL;
670 return;
671 case 0x8900: /* bt label */
672 CHECK_NOT_DELAY_SLOT
673 gen_conditional_jump(ctx, ctx->pc + 4 + B7_0s * 2,
674 ctx->pc + 2);
675 ctx->flags |= BRANCH_CONDITIONAL;
676 return;
677 case 0x8d00: /* bt/s label */
678 CHECK_NOT_DELAY_SLOT
679 gen_op_bt_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2);
680 ctx->flags |= DELAY_SLOT_CONDITIONAL;
681 return;
682 case 0x8800: /* cmp/eq #imm,R0 */
683 gen_op_movl_rN_T0(REG(0));
684 gen_op_cmp_eq_imm_T0(B7_0s);
685 return;
686 case 0xc400: /* mov.b @(disp,GBR),R0 */
687 gen_op_stc_gbr_T0();
688 gen_op_addl_imm_T0(B7_0);
689 gen_op_ldb_T0_T0(ctx);
690 gen_op_movl_T0_rN(REG(0));
691 return;
692 case 0xc500: /* mov.w @(disp,GBR),R0 */
693 gen_op_stc_gbr_T0();
694 gen_op_addl_imm_T0(B7_0);
695 gen_op_ldw_T0_T0(ctx);
696 gen_op_movl_T0_rN(REG(0));
697 return;
698 case 0xc600: /* mov.l @(disp,GBR),R0 */
699 gen_op_stc_gbr_T0();
700 gen_op_addl_imm_T0(B7_0);
701 gen_op_ldl_T0_T0(ctx);
702 gen_op_movl_T0_rN(REG(0));
703 return;
704 case 0xc000: /* mov.b R0,@(disp,GBR) */
705 gen_op_stc_gbr_T0();
706 gen_op_addl_imm_T0(B7_0);
707 gen_op_movl_T0_T1();
708 gen_op_movl_rN_T0(REG(0));
709 gen_op_stb_T0_T1(ctx);
710 return;
711 case 0xc100: /* mov.w R0,@(disp,GBR) */
712 gen_op_stc_gbr_T0();
713 gen_op_addl_imm_T0(B7_0);
714 gen_op_movl_T0_T1();
715 gen_op_movl_rN_T0(REG(0));
716 gen_op_stw_T0_T1(ctx);
717 return;
718 case 0xc200: /* mov.l R0,@(disp,GBR) */
719 gen_op_stc_gbr_T0();
720 gen_op_addl_imm_T0(B7_0);
721 gen_op_movl_T0_T1();
722 gen_op_movl_rN_T0(REG(0));
723 gen_op_stl_T0_T1(ctx);
724 return;
725 case 0x8000: /* mov.b R0,@(disp,Rn) */
726 gen_op_movl_rN_T0(REG(0));
727 gen_op_movl_rN_T1(REG(B7_4));
728 gen_op_addl_imm_T1(B3_0);
729 gen_op_stb_T0_T1(ctx);
730 return;
731 case 0x8100: /* mov.w R0,@(disp,Rn) */
732 gen_op_movl_rN_T0(REG(0));
733 gen_op_movl_rN_T1(REG(B7_4));
734 gen_op_addl_imm_T1(B3_0 * 2);
735 gen_op_stw_T0_T1(ctx);
736 return;
737 case 0x8400: /* mov.b @(disp,Rn),R0 */
738 gen_op_movl_rN_T0(REG(0));
739 gen_op_movl_rN_T1(REG(B7_4));
740 gen_op_addl_imm_T1(B3_0);
741 gen_op_stb_T0_T1(ctx);
742 return;
743 case 0x8500: /* mov.w @(disp,Rn),R0 */
744 gen_op_movl_rN_T0(REG(B7_4));
745 gen_op_addl_imm_T0(B3_0 * 2);
746 gen_op_ldw_T0_T0(ctx);
747 gen_op_movl_T0_rN(REG(0));
748 return;
749 case 0xc700: /* mova @(disp,PC),R0 */
750 gen_op_movl_imm_rN(((ctx->pc & 0xfffffffc) + 4 + B7_0 * 4) & ~3,
751 REG(0));
752 return;
753 case 0xcb00: /* or #imm,R0 */
754 gen_op_or_imm_rN(B7_0, REG(0));
755 return;
756 case 0xcf00: /* or.b #imm,@(R0+GBR) */
757 gen_op_movl_rN_T0(REG(0));
758 gen_op_addl_GBR_T0();
759 gen_op_movl_T0_T1();
760 gen_op_ldb_T0_T0(ctx);
761 gen_op_or_imm_T0(B7_0);
762 gen_op_stb_T0_T1(ctx);
763 return;
764 case 0xc300: /* trapa #imm */
765 CHECK_NOT_DELAY_SLOT gen_op_movl_imm_PC(ctx->pc);
766 gen_op_trapa(B7_0);
767 ctx->flags |= BRANCH;
768 return;
769 case 0xc800: /* tst #imm,R0 */
770 gen_op_tst_imm_rN(B7_0, REG(0));
771 return;
772 case 0xcc00: /* tst #imm,@(R0+GBR) */
773 gen_op_movl_rN_T0(REG(0));
774 gen_op_addl_GBR_T0();
775 gen_op_ldb_T0_T0(ctx);
776 gen_op_tst_imm_T0(B7_0);
777 return;
778 case 0xca00: /* xor #imm,R0 */
779 gen_op_xor_imm_rN(B7_0, REG(0));
780 return;
781 case 0xce00: /* xor.b #imm,@(R0+GBR) */
782 gen_op_movl_rN_T0(REG(0));
783 gen_op_addl_GBR_T0();
784 gen_op_movl_T0_T1();
785 gen_op_ldb_T0_T0(ctx);
786 gen_op_xor_imm_T0(B7_0);
787 gen_op_stb_T0_T1(ctx);
788 return;
791 switch (ctx->opcode & 0xf08f) {
792 case 0x408e: /* ldc Rm,Rn_BANK */
793 gen_op_movl_rN_rN(REG(B11_8), ALTREG(B6_4));
794 return;
795 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
796 gen_op_movl_rN_T0(REG(B11_8));
797 gen_op_ldl_T0_T0(ctx);
798 gen_op_movl_T0_rN(ALTREG(B6_4));
799 gen_op_inc4_rN(REG(B11_8));
800 return;
801 case 0x0082: /* stc Rm_BANK,Rn */
802 gen_op_movl_rN_rN(ALTREG(B6_4), REG(B11_8));
803 return;
804 case 0x4083: /* stc.l Rm_BANK,@-Rn */
805 gen_op_dec4_rN(REG(B11_8));
806 gen_op_movl_rN_T1(REG(B11_8));
807 gen_op_movl_rN_T0(ALTREG(B6_4));
808 gen_op_stl_T0_T1(ctx);
809 return;
812 switch (ctx->opcode & 0xf0ff) {
813 case 0x0023: /* braf Rn */
814 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
815 gen_op_braf_T0(ctx->pc + 4);
816 ctx->flags |= DELAY_SLOT;
817 ctx->delayed_pc = (uint32_t) - 1;
818 return;
819 case 0x0003: /* bsrf Rn */
820 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
821 gen_op_bsrf_T0(ctx->pc + 4);
822 ctx->flags |= DELAY_SLOT;
823 ctx->delayed_pc = (uint32_t) - 1;
824 return;
825 case 0x4015: /* cmp/pl Rn */
826 gen_op_movl_rN_T0(REG(B11_8));
827 gen_op_cmp_pl_T0();
828 return;
829 case 0x4011: /* cmp/pz Rn */
830 gen_op_movl_rN_T0(REG(B11_8));
831 gen_op_cmp_pz_T0();
832 return;
833 case 0x4010: /* dt Rn */
834 gen_op_dt_rN(REG(B11_8));
835 return;
836 case 0x402b: /* jmp @Rn */
837 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
838 gen_op_jmp_T0();
839 ctx->flags |= DELAY_SLOT;
840 ctx->delayed_pc = (uint32_t) - 1;
841 return;
842 case 0x400b: /* jsr @Rn */
843 CHECK_NOT_DELAY_SLOT gen_op_movl_rN_T0(REG(B11_8));
844 gen_op_jsr_T0(ctx->pc + 4);
845 ctx->flags |= DELAY_SLOT;
846 ctx->delayed_pc = (uint32_t) - 1;
847 return;
848 #define LDST(reg,ldnum,ldpnum,ldop,stnum,stpnum,stop,extrald) \
849 case ldnum: \
850 gen_op_movl_rN_T0 (REG(B11_8)); \
851 gen_op_##ldop##_T0_##reg (); \
852 extrald \
853 return; \
854 case ldpnum: \
855 gen_op_movl_rN_T0 (REG(B11_8)); \
856 gen_op_ldl_T0_T0 (ctx); \
857 gen_op_inc4_rN (REG(B11_8)); \
858 gen_op_##ldop##_T0_##reg (); \
859 extrald \
860 return; \
861 case stnum: \
862 gen_op_##stop##_##reg##_T0 (); \
863 gen_op_movl_T0_rN (REG(B11_8)); \
864 return; \
865 case stpnum: \
866 gen_op_##stop##_##reg##_T0 (); \
867 gen_op_dec4_rN (REG(B11_8)); \
868 gen_op_movl_rN_T1 (REG(B11_8)); \
869 gen_op_stl_T0_T1 (ctx); \
870 return;
871 LDST(sr, 0x400e, 0x4007, ldc, 0x0002, 0x4003, stc, ctx->flags |=
872 MODE_CHANGE;
874 LDST(gbr, 0x401e, 0x4017, ldc, 0x0012, 0x4013, stc,)
875 LDST(vbr, 0x402e, 0x4027, ldc, 0x0022, 0x4023, stc,)
876 LDST(ssr, 0x403e, 0x4037, ldc, 0x0032, 0x4033, stc,)
877 LDST(spc, 0x404e, 0x4047, ldc, 0x0042, 0x4043, stc,)
878 LDST(dbr, 0x40fa, 0x40f6, ldc, 0x00fa, 0x40f2, stc,)
879 LDST(mach, 0x400a, 0x4006, lds, 0x000a, 0x4002, sts,)
880 LDST(macl, 0x401a, 0x4016, lds, 0x001a, 0x4012, sts,)
881 LDST(pr, 0x402a, 0x4026, lds, 0x002a, 0x4022, sts,)
882 case 0x00c3: /* movca.l R0,@Rm */
883 gen_op_movl_rN_T0(REG(0));
884 gen_op_movl_rN_T1(REG(B11_8));
885 gen_op_stl_T0_T1(ctx);
886 return;
887 case 0x0029: /* movt Rn */
888 gen_op_movt_rN(REG(B11_8));
889 return;
890 case 0x0093: /* ocbi @Rn */
891 gen_op_movl_rN_T0(REG(B11_8));
892 gen_op_ldl_T0_T0(ctx);
893 return;
894 case 0x00a2: /* ocbp @Rn */
895 gen_op_movl_rN_T0(REG(B11_8));
896 gen_op_ldl_T0_T0(ctx);
897 return;
898 case 0x00b3: /* ocbwb @Rn */
899 gen_op_movl_rN_T0(REG(B11_8));
900 gen_op_ldl_T0_T0(ctx);
901 return;
902 case 0x0083: /* pref @Rn */
903 return;
904 case 0x4024: /* rotcl Rn */
905 gen_op_rotcl_Rn(REG(B11_8));
906 return;
907 case 0x4025: /* rotcr Rn */
908 gen_op_rotcr_Rn(REG(B11_8));
909 return;
910 case 0x4004: /* rotl Rn */
911 gen_op_rotl_Rn(REG(B11_8));
912 return;
913 case 0x4005: /* rotr Rn */
914 gen_op_rotr_Rn(REG(B11_8));
915 return;
916 case 0x4000: /* shll Rn */
917 case 0x4020: /* shal Rn */
918 gen_op_shal_Rn(REG(B11_8));
919 return;
920 case 0x4021: /* shar Rn */
921 gen_op_shar_Rn(REG(B11_8));
922 return;
923 case 0x4001: /* shlr Rn */
924 gen_op_shlr_Rn(REG(B11_8));
925 return;
926 case 0x4008: /* shll2 Rn */
927 gen_op_shll2_Rn(REG(B11_8));
928 return;
929 case 0x4018: /* shll8 Rn */
930 gen_op_shll8_Rn(REG(B11_8));
931 return;
932 case 0x4028: /* shll16 Rn */
933 gen_op_shll16_Rn(REG(B11_8));
934 return;
935 case 0x4009: /* shlr2 Rn */
936 gen_op_shlr2_Rn(REG(B11_8));
937 return;
938 case 0x4019: /* shlr8 Rn */
939 gen_op_shlr8_Rn(REG(B11_8));
940 return;
941 case 0x4029: /* shlr16 Rn */
942 gen_op_shlr16_Rn(REG(B11_8));
943 return;
944 case 0x401b: /* tas.b @Rn */
945 gen_op_tasb_rN(REG(B11_8));
946 return;
949 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
950 ctx->opcode, ctx->pc);
951 gen_op_raise_illegal_instruction();
952 ctx->flags |= BRANCH_EXCEPTION;
955 int gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
956 int search_pc)
958 DisasContext ctx;
959 target_ulong pc_start;
960 static uint16_t *gen_opc_end;
961 uint32_t old_flags;
962 int i;
964 pc_start = tb->pc;
965 gen_opc_ptr = gen_opc_buf;
966 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
967 gen_opparam_ptr = gen_opparam_buf;
968 ctx.pc = pc_start;
969 ctx.flags = env->flags;
970 old_flags = 0;
971 ctx.sr = env->sr;
972 ctx.memidx = (env->sr & SR_MD) ? 1 : 0;
973 ctx.delayed_pc = env->delayed_pc;
974 ctx.tb = tb;
975 ctx.singlestep_enabled = env->singlestep_enabled;
976 nb_gen_labels = 0;
978 #ifdef DEBUG_DISAS
979 if (loglevel & CPU_LOG_TB_CPU) {
980 fprintf(logfile,
981 "------------------------------------------------\n");
982 cpu_dump_state(env, logfile, fprintf, 0);
984 #endif
986 while ((old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) == 0 &&
987 (ctx.flags & (BRANCH | BRANCH_CONDITIONAL | MODE_CHANGE |
988 BRANCH_EXCEPTION)) == 0 &&
989 gen_opc_ptr < gen_opc_end && ctx.sr == env->sr) {
990 old_flags = ctx.flags;
991 if (env->nb_breakpoints > 0) {
992 for (i = 0; i < env->nb_breakpoints; i++) {
993 if (ctx.pc == env->breakpoints[i]) {
994 /* We have hit a breakpoint - make sure PC is up-to-date */
995 gen_op_movl_imm_PC(ctx.pc);
996 gen_op_debug();
997 ctx.flags |= BRANCH_EXCEPTION;
998 break;
1002 #if 0
1003 fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc);
1004 fflush(stderr);
1005 #endif
1006 ctx.opcode = lduw_code(ctx.pc);
1007 decode_opc(&ctx);
1008 ctx.pc += 2;
1009 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1010 break;
1011 if (env->singlestep_enabled)
1012 break;
1013 #ifdef SH4_SINGLE_STEP
1014 break;
1015 #endif
1018 switch (old_flags & (DELAY_SLOT_CONDITIONAL | DELAY_SLOT)) {
1019 case DELAY_SLOT_CONDITIONAL:
1020 gen_op_clr_delay_slot_conditional();
1021 gen_delayed_conditional_jump(&ctx);
1022 break;
1023 case DELAY_SLOT:
1024 gen_op_clr_delay_slot();
1025 gen_jump(&ctx);
1026 break;
1027 case 0:
1028 if (ctx.flags & BRANCH_EXCEPTION) {
1029 gen_jump_exception(&ctx);
1030 } else if ((ctx.flags & (BRANCH | BRANCH_CONDITIONAL)) == 0) {
1031 gen_goto_tb(&ctx, 0, ctx.pc);
1033 break;
1034 default:
1035 /* Both cannot be set at the same time */
1036 assert(0);
1039 if (env->singlestep_enabled) {
1040 gen_op_debug();
1042 *gen_opc_ptr = INDEX_op_end;
1043 tb->size = ctx.pc - pc_start;
1045 #ifdef DEBUG_DISAS
1046 #ifdef SH4_DEBUG_DISAS
1047 if (loglevel & CPU_LOG_TB_IN_ASM)
1048 fprintf(logfile, "\n");
1049 #endif
1050 if (loglevel & CPU_LOG_TB_IN_ASM) {
1051 fprintf(logfile, "IN:\n"); /* , lookup_symbol(pc_start)); */
1052 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
1053 fprintf(logfile, "\n");
1055 if (loglevel & CPU_LOG_TB_OP) {
1056 fprintf(logfile, "OP:\n");
1057 dump_ops(gen_opc_buf, gen_opparam_buf);
1058 fprintf(logfile, "\n");
1060 #endif
1061 return 0;
1064 int gen_intermediate_code(CPUState * env, struct TranslationBlock *tb)
1066 return gen_intermediate_code_internal(env, tb, 0);
1069 int gen_intermediate_code_pc(CPUState * env, struct TranslationBlock *tb)
1071 assert(0);
1072 return gen_intermediate_code_internal(env, tb, 1);