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.1 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, see <http://www.gnu.org/licenses/>.
20 #include "qemu/osdep.h"
22 #include "disas/disas.h"
23 #include "exec/exec-all.h"
24 #include "tcg/tcg-op.h"
25 #include "exec/cpu_ldst.h"
26 #include "exec/helper-proto.h"
27 #include "exec/helper-gen.h"
28 #include "exec/translator.h"
30 #include "qemu/qemu-print.h"
32 #define HELPER_H "helper.h"
33 #include "exec/helper-info.c.inc"
37 typedef struct DisasContext
{
38 DisasContextBase base
;
40 uint32_t tbflags
; /* should stay unmodified during the TB translation */
41 uint32_t envflags
; /* should stay in sync with env->flags using TCG ops */
53 #if defined(CONFIG_USER_ONLY)
54 #define IS_USER(ctx) 1
55 #define UNALIGN(C) (ctx->tbflags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN)
57 #define IS_USER(ctx) (!(ctx->tbflags & (1u << SR_MD)))
61 /* Target-specific values for ctx->base.is_jmp. */
62 /* We want to exit back to the cpu loop for some reason.
63 Usually this is to recognize interrupts immediately. */
64 #define DISAS_STOP DISAS_TARGET_0
66 /* global register indexes */
67 static TCGv cpu_gregs
[32];
68 static TCGv cpu_sr
, cpu_sr_m
, cpu_sr_q
, cpu_sr_t
;
69 static TCGv cpu_pc
, cpu_ssr
, cpu_spc
, cpu_gbr
;
70 static TCGv cpu_vbr
, cpu_sgr
, cpu_dbr
, cpu_mach
, cpu_macl
;
71 static TCGv cpu_pr
, cpu_fpscr
, cpu_fpul
;
72 static TCGv cpu_lock_addr
, cpu_lock_value
;
73 static TCGv cpu_fregs
[32];
75 /* internal register indexes */
76 static TCGv cpu_flags
, cpu_delayed_pc
, cpu_delayed_cond
;
78 void sh4_translate_init(void)
81 static const char * const gregnames
[24] = {
82 "R0_BANK0", "R1_BANK0", "R2_BANK0", "R3_BANK0",
83 "R4_BANK0", "R5_BANK0", "R6_BANK0", "R7_BANK0",
84 "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
85 "R0_BANK1", "R1_BANK1", "R2_BANK1", "R3_BANK1",
86 "R4_BANK1", "R5_BANK1", "R6_BANK1", "R7_BANK1"
88 static const char * const fregnames
[32] = {
89 "FPR0_BANK0", "FPR1_BANK0", "FPR2_BANK0", "FPR3_BANK0",
90 "FPR4_BANK0", "FPR5_BANK0", "FPR6_BANK0", "FPR7_BANK0",
91 "FPR8_BANK0", "FPR9_BANK0", "FPR10_BANK0", "FPR11_BANK0",
92 "FPR12_BANK0", "FPR13_BANK0", "FPR14_BANK0", "FPR15_BANK0",
93 "FPR0_BANK1", "FPR1_BANK1", "FPR2_BANK1", "FPR3_BANK1",
94 "FPR4_BANK1", "FPR5_BANK1", "FPR6_BANK1", "FPR7_BANK1",
95 "FPR8_BANK1", "FPR9_BANK1", "FPR10_BANK1", "FPR11_BANK1",
96 "FPR12_BANK1", "FPR13_BANK1", "FPR14_BANK1", "FPR15_BANK1",
99 for (i
= 0; i
< 24; i
++) {
100 cpu_gregs
[i
] = tcg_global_mem_new_i32(cpu_env
,
101 offsetof(CPUSH4State
, gregs
[i
]),
104 memcpy(cpu_gregs
+ 24, cpu_gregs
+ 8, 8 * sizeof(TCGv
));
106 cpu_pc
= tcg_global_mem_new_i32(cpu_env
,
107 offsetof(CPUSH4State
, pc
), "PC");
108 cpu_sr
= tcg_global_mem_new_i32(cpu_env
,
109 offsetof(CPUSH4State
, sr
), "SR");
110 cpu_sr_m
= tcg_global_mem_new_i32(cpu_env
,
111 offsetof(CPUSH4State
, sr_m
), "SR_M");
112 cpu_sr_q
= tcg_global_mem_new_i32(cpu_env
,
113 offsetof(CPUSH4State
, sr_q
), "SR_Q");
114 cpu_sr_t
= tcg_global_mem_new_i32(cpu_env
,
115 offsetof(CPUSH4State
, sr_t
), "SR_T");
116 cpu_ssr
= tcg_global_mem_new_i32(cpu_env
,
117 offsetof(CPUSH4State
, ssr
), "SSR");
118 cpu_spc
= tcg_global_mem_new_i32(cpu_env
,
119 offsetof(CPUSH4State
, spc
), "SPC");
120 cpu_gbr
= tcg_global_mem_new_i32(cpu_env
,
121 offsetof(CPUSH4State
, gbr
), "GBR");
122 cpu_vbr
= tcg_global_mem_new_i32(cpu_env
,
123 offsetof(CPUSH4State
, vbr
), "VBR");
124 cpu_sgr
= tcg_global_mem_new_i32(cpu_env
,
125 offsetof(CPUSH4State
, sgr
), "SGR");
126 cpu_dbr
= tcg_global_mem_new_i32(cpu_env
,
127 offsetof(CPUSH4State
, dbr
), "DBR");
128 cpu_mach
= tcg_global_mem_new_i32(cpu_env
,
129 offsetof(CPUSH4State
, mach
), "MACH");
130 cpu_macl
= tcg_global_mem_new_i32(cpu_env
,
131 offsetof(CPUSH4State
, macl
), "MACL");
132 cpu_pr
= tcg_global_mem_new_i32(cpu_env
,
133 offsetof(CPUSH4State
, pr
), "PR");
134 cpu_fpscr
= tcg_global_mem_new_i32(cpu_env
,
135 offsetof(CPUSH4State
, fpscr
), "FPSCR");
136 cpu_fpul
= tcg_global_mem_new_i32(cpu_env
,
137 offsetof(CPUSH4State
, fpul
), "FPUL");
139 cpu_flags
= tcg_global_mem_new_i32(cpu_env
,
140 offsetof(CPUSH4State
, flags
), "_flags_");
141 cpu_delayed_pc
= tcg_global_mem_new_i32(cpu_env
,
142 offsetof(CPUSH4State
, delayed_pc
),
144 cpu_delayed_cond
= tcg_global_mem_new_i32(cpu_env
,
145 offsetof(CPUSH4State
,
148 cpu_lock_addr
= tcg_global_mem_new_i32(cpu_env
,
149 offsetof(CPUSH4State
, lock_addr
),
151 cpu_lock_value
= tcg_global_mem_new_i32(cpu_env
,
152 offsetof(CPUSH4State
, lock_value
),
155 for (i
= 0; i
< 32; i
++)
156 cpu_fregs
[i
] = tcg_global_mem_new_i32(cpu_env
,
157 offsetof(CPUSH4State
, fregs
[i
]),
161 void superh_cpu_dump_state(CPUState
*cs
, FILE *f
, int flags
)
163 SuperHCPU
*cpu
= SUPERH_CPU(cs
);
164 CPUSH4State
*env
= &cpu
->env
;
167 qemu_fprintf(f
, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n",
168 env
->pc
, cpu_read_sr(env
), env
->pr
, env
->fpscr
);
169 qemu_fprintf(f
, "spc=0x%08x ssr=0x%08x gbr=0x%08x vbr=0x%08x\n",
170 env
->spc
, env
->ssr
, env
->gbr
, env
->vbr
);
171 qemu_fprintf(f
, "sgr=0x%08x dbr=0x%08x delayed_pc=0x%08x fpul=0x%08x\n",
172 env
->sgr
, env
->dbr
, env
->delayed_pc
, env
->fpul
);
173 for (i
= 0; i
< 24; i
+= 4) {
174 qemu_fprintf(f
, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
175 i
, env
->gregs
[i
], i
+ 1, env
->gregs
[i
+ 1],
176 i
+ 2, env
->gregs
[i
+ 2], i
+ 3, env
->gregs
[i
+ 3]);
178 if (env
->flags
& TB_FLAG_DELAY_SLOT
) {
179 qemu_fprintf(f
, "in delay slot (delayed_pc=0x%08x)\n",
181 } else if (env
->flags
& TB_FLAG_DELAY_SLOT_COND
) {
182 qemu_fprintf(f
, "in conditional delay slot (delayed_pc=0x%08x)\n",
184 } else if (env
->flags
& TB_FLAG_DELAY_SLOT_RTE
) {
185 qemu_fprintf(f
, "in rte delay slot (delayed_pc=0x%08x)\n",
190 static void gen_read_sr(TCGv dst
)
192 TCGv t0
= tcg_temp_new();
193 tcg_gen_shli_i32(t0
, cpu_sr_q
, SR_Q
);
194 tcg_gen_or_i32(dst
, dst
, t0
);
195 tcg_gen_shli_i32(t0
, cpu_sr_m
, SR_M
);
196 tcg_gen_or_i32(dst
, dst
, t0
);
197 tcg_gen_shli_i32(t0
, cpu_sr_t
, SR_T
);
198 tcg_gen_or_i32(dst
, cpu_sr
, t0
);
201 static void gen_write_sr(TCGv src
)
203 tcg_gen_andi_i32(cpu_sr
, src
,
204 ~((1u << SR_Q
) | (1u << SR_M
) | (1u << SR_T
)));
205 tcg_gen_extract_i32(cpu_sr_q
, src
, SR_Q
, 1);
206 tcg_gen_extract_i32(cpu_sr_m
, src
, SR_M
, 1);
207 tcg_gen_extract_i32(cpu_sr_t
, src
, SR_T
, 1);
210 static inline void gen_save_cpu_state(DisasContext
*ctx
, bool save_pc
)
213 tcg_gen_movi_i32(cpu_pc
, ctx
->base
.pc_next
);
215 if (ctx
->delayed_pc
!= (uint32_t) -1) {
216 tcg_gen_movi_i32(cpu_delayed_pc
, ctx
->delayed_pc
);
218 if ((ctx
->tbflags
& TB_FLAG_ENVFLAGS_MASK
) != ctx
->envflags
) {
219 tcg_gen_movi_i32(cpu_flags
, ctx
->envflags
);
223 static inline bool use_exit_tb(DisasContext
*ctx
)
225 return (ctx
->tbflags
& TB_FLAG_GUSA_EXCLUSIVE
) != 0;
228 static bool use_goto_tb(DisasContext
*ctx
, target_ulong dest
)
230 if (use_exit_tb(ctx
)) {
233 return translator_use_goto_tb(&ctx
->base
, dest
);
236 static void gen_goto_tb(DisasContext
*ctx
, int n
, target_ulong dest
)
238 if (use_goto_tb(ctx
, dest
)) {
240 tcg_gen_movi_i32(cpu_pc
, dest
);
241 tcg_gen_exit_tb(ctx
->base
.tb
, n
);
243 tcg_gen_movi_i32(cpu_pc
, dest
);
244 if (use_exit_tb(ctx
)) {
245 tcg_gen_exit_tb(NULL
, 0);
247 tcg_gen_lookup_and_goto_ptr();
250 ctx
->base
.is_jmp
= DISAS_NORETURN
;
253 static void gen_jump(DisasContext
* ctx
)
255 if (ctx
->delayed_pc
== -1) {
256 /* Target is not statically known, it comes necessarily from a
257 delayed jump as immediate jump are conditinal jumps */
258 tcg_gen_mov_i32(cpu_pc
, cpu_delayed_pc
);
259 tcg_gen_discard_i32(cpu_delayed_pc
);
260 if (use_exit_tb(ctx
)) {
261 tcg_gen_exit_tb(NULL
, 0);
263 tcg_gen_lookup_and_goto_ptr();
265 ctx
->base
.is_jmp
= DISAS_NORETURN
;
267 gen_goto_tb(ctx
, 0, ctx
->delayed_pc
);
271 /* Immediate conditional jump (bt or bf) */
272 static void gen_conditional_jump(DisasContext
*ctx
, target_ulong dest
,
275 TCGLabel
*l1
= gen_new_label();
276 TCGCond cond_not_taken
= jump_if_true
? TCG_COND_EQ
: TCG_COND_NE
;
278 if (ctx
->tbflags
& TB_FLAG_GUSA_EXCLUSIVE
) {
279 /* When in an exclusive region, we must continue to the end.
280 Therefore, exit the region on a taken branch, but otherwise
281 fall through to the next instruction. */
282 tcg_gen_brcondi_i32(cond_not_taken
, cpu_sr_t
, 0, l1
);
283 tcg_gen_movi_i32(cpu_flags
, ctx
->envflags
& ~TB_FLAG_GUSA_MASK
);
284 /* Note that this won't actually use a goto_tb opcode because we
285 disallow it in use_goto_tb, but it handles exit + singlestep. */
286 gen_goto_tb(ctx
, 0, dest
);
288 ctx
->base
.is_jmp
= DISAS_NEXT
;
292 gen_save_cpu_state(ctx
, false);
293 tcg_gen_brcondi_i32(cond_not_taken
, cpu_sr_t
, 0, l1
);
294 gen_goto_tb(ctx
, 0, dest
);
296 gen_goto_tb(ctx
, 1, ctx
->base
.pc_next
+ 2);
297 ctx
->base
.is_jmp
= DISAS_NORETURN
;
300 /* Delayed conditional jump (bt or bf) */
301 static void gen_delayed_conditional_jump(DisasContext
* ctx
)
303 TCGLabel
*l1
= gen_new_label();
304 TCGv ds
= tcg_temp_new();
306 tcg_gen_mov_i32(ds
, cpu_delayed_cond
);
307 tcg_gen_discard_i32(cpu_delayed_cond
);
309 if (ctx
->tbflags
& TB_FLAG_GUSA_EXCLUSIVE
) {
310 /* When in an exclusive region, we must continue to the end.
311 Therefore, exit the region on a taken branch, but otherwise
312 fall through to the next instruction. */
313 tcg_gen_brcondi_i32(TCG_COND_EQ
, ds
, 0, l1
);
315 /* Leave the gUSA region. */
316 tcg_gen_movi_i32(cpu_flags
, ctx
->envflags
& ~TB_FLAG_GUSA_MASK
);
320 ctx
->base
.is_jmp
= DISAS_NEXT
;
324 tcg_gen_brcondi_i32(TCG_COND_NE
, ds
, 0, l1
);
325 gen_goto_tb(ctx
, 1, ctx
->base
.pc_next
+ 2);
330 static inline void gen_load_fpr64(DisasContext
*ctx
, TCGv_i64 t
, int reg
)
332 /* We have already signaled illegal instruction for odd Dr. */
333 tcg_debug_assert((reg
& 1) == 0);
335 tcg_gen_concat_i32_i64(t
, cpu_fregs
[reg
+ 1], cpu_fregs
[reg
]);
338 static inline void gen_store_fpr64(DisasContext
*ctx
, TCGv_i64 t
, int reg
)
340 /* We have already signaled illegal instruction for odd Dr. */
341 tcg_debug_assert((reg
& 1) == 0);
343 tcg_gen_extr_i64_i32(cpu_fregs
[reg
+ 1], cpu_fregs
[reg
], t
);
346 #define B3_0 (ctx->opcode & 0xf)
347 #define B6_4 ((ctx->opcode >> 4) & 0x7)
348 #define B7_4 ((ctx->opcode >> 4) & 0xf)
349 #define B7_0 (ctx->opcode & 0xff)
350 #define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
351 #define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
352 (ctx->opcode & 0xfff))
353 #define B11_8 ((ctx->opcode >> 8) & 0xf)
354 #define B15_12 ((ctx->opcode >> 12) & 0xf)
356 #define REG(x) cpu_gregs[(x) ^ ctx->gbank]
357 #define ALTREG(x) cpu_gregs[(x) ^ ctx->gbank ^ 0x10]
358 #define FREG(x) cpu_fregs[(x) ^ ctx->fbank]
360 #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
362 #define CHECK_NOT_DELAY_SLOT \
363 if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) { \
364 goto do_illegal_slot; \
367 #define CHECK_PRIVILEGED \
368 if (IS_USER(ctx)) { \
372 #define CHECK_FPU_ENABLED \
373 if (ctx->tbflags & (1u << SR_FD)) { \
374 goto do_fpu_disabled; \
377 #define CHECK_FPSCR_PR_0 \
378 if (ctx->tbflags & FPSCR_PR) { \
382 #define CHECK_FPSCR_PR_1 \
383 if (!(ctx->tbflags & FPSCR_PR)) { \
388 if (!(ctx->features & SH_FEATURE_SH4A)) { \
392 static void _decode_opc(DisasContext
* ctx
)
394 /* This code tries to make movcal emulation sufficiently
395 accurate for Linux purposes. This instruction writes
396 memory, and prior to that, always allocates a cache line.
397 It is used in two contexts:
398 - in memcpy, where data is copied in blocks, the first write
399 of to a block uses movca.l for performance.
400 - in arch/sh/mm/cache-sh4.c, movcal.l + ocbi combination is used
401 to flush the cache. Here, the data written by movcal.l is never
402 written to memory, and the data written is just bogus.
404 To simulate this, we simulate movcal.l, we store the value to memory,
405 but we also remember the previous content. If we see ocbi, we check
406 if movcal.l for that address was done previously. If so, the write should
407 not have hit the memory, so we restore the previous content.
408 When we see an instruction that is neither movca.l
409 nor ocbi, the previous content is discarded.
411 To optimize, we only try to flush stores when we're at the start of
412 TB, or if we already saw movca.l in this TB and did not flush stores
416 int opcode
= ctx
->opcode
& 0xf0ff;
417 if (opcode
!= 0x0093 /* ocbi */
418 && opcode
!= 0x00c3 /* movca.l */)
420 gen_helper_discard_movcal_backup(cpu_env
);
426 fprintf(stderr
, "Translating opcode 0x%04x\n", ctx
->opcode
);
429 switch (ctx
->opcode
) {
430 case 0x0019: /* div0u */
431 tcg_gen_movi_i32(cpu_sr_m
, 0);
432 tcg_gen_movi_i32(cpu_sr_q
, 0);
433 tcg_gen_movi_i32(cpu_sr_t
, 0);
435 case 0x000b: /* rts */
437 tcg_gen_mov_i32(cpu_delayed_pc
, cpu_pr
);
438 ctx
->envflags
|= TB_FLAG_DELAY_SLOT
;
439 ctx
->delayed_pc
= (uint32_t) - 1;
441 case 0x0028: /* clrmac */
442 tcg_gen_movi_i32(cpu_mach
, 0);
443 tcg_gen_movi_i32(cpu_macl
, 0);
445 case 0x0048: /* clrs */
446 tcg_gen_andi_i32(cpu_sr
, cpu_sr
, ~(1u << SR_S
));
448 case 0x0008: /* clrt */
449 tcg_gen_movi_i32(cpu_sr_t
, 0);
451 case 0x0038: /* ldtlb */
453 gen_helper_ldtlb(cpu_env
);
455 case 0x002b: /* rte */
458 gen_write_sr(cpu_ssr
);
459 tcg_gen_mov_i32(cpu_delayed_pc
, cpu_spc
);
460 ctx
->envflags
|= TB_FLAG_DELAY_SLOT_RTE
;
461 ctx
->delayed_pc
= (uint32_t) - 1;
462 ctx
->base
.is_jmp
= DISAS_STOP
;
464 case 0x0058: /* sets */
465 tcg_gen_ori_i32(cpu_sr
, cpu_sr
, (1u << SR_S
));
467 case 0x0018: /* sett */
468 tcg_gen_movi_i32(cpu_sr_t
, 1);
470 case 0xfbfd: /* frchg */
472 tcg_gen_xori_i32(cpu_fpscr
, cpu_fpscr
, FPSCR_FR
);
473 ctx
->base
.is_jmp
= DISAS_STOP
;
475 case 0xf3fd: /* fschg */
477 tcg_gen_xori_i32(cpu_fpscr
, cpu_fpscr
, FPSCR_SZ
);
478 ctx
->base
.is_jmp
= DISAS_STOP
;
480 case 0xf7fd: /* fpchg */
482 tcg_gen_xori_i32(cpu_fpscr
, cpu_fpscr
, FPSCR_PR
);
483 ctx
->base
.is_jmp
= DISAS_STOP
;
485 case 0x0009: /* nop */
487 case 0x001b: /* sleep */
489 tcg_gen_movi_i32(cpu_pc
, ctx
->base
.pc_next
+ 2);
490 gen_helper_sleep(cpu_env
);
494 switch (ctx
->opcode
& 0xf000) {
495 case 0x1000: /* mov.l Rm,@(disp,Rn) */
497 TCGv addr
= tcg_temp_new();
498 tcg_gen_addi_i32(addr
, REG(B11_8
), B3_0
* 4);
499 tcg_gen_qemu_st_i32(REG(B7_4
), addr
, ctx
->memidx
,
500 MO_TEUL
| UNALIGN(ctx
));
503 case 0x5000: /* mov.l @(disp,Rm),Rn */
505 TCGv addr
= tcg_temp_new();
506 tcg_gen_addi_i32(addr
, REG(B7_4
), B3_0
* 4);
507 tcg_gen_qemu_ld_i32(REG(B11_8
), addr
, ctx
->memidx
,
508 MO_TESL
| UNALIGN(ctx
));
511 case 0xe000: /* mov #imm,Rn */
512 #ifdef CONFIG_USER_ONLY
514 * Detect the start of a gUSA region (mov #-n, r15).
515 * If so, update envflags and end the TB. This will allow us
516 * to see the end of the region (stored in R0) in the next TB.
518 if (B11_8
== 15 && B7_0s
< 0 &&
519 (tb_cflags(ctx
->base
.tb
) & CF_PARALLEL
)) {
521 deposit32(ctx
->envflags
, TB_FLAG_GUSA_SHIFT
, 8, B7_0s
);
522 ctx
->base
.is_jmp
= DISAS_STOP
;
525 tcg_gen_movi_i32(REG(B11_8
), B7_0s
);
527 case 0x9000: /* mov.w @(disp,PC),Rn */
529 TCGv addr
= tcg_constant_i32(ctx
->base
.pc_next
+ 4 + B7_0
* 2);
530 tcg_gen_qemu_ld_i32(REG(B11_8
), addr
, ctx
->memidx
,
534 case 0xd000: /* mov.l @(disp,PC),Rn */
536 TCGv addr
= tcg_constant_i32((ctx
->base
.pc_next
+ 4 + B7_0
* 4) & ~3);
537 tcg_gen_qemu_ld_i32(REG(B11_8
), addr
, ctx
->memidx
,
541 case 0x7000: /* add #imm,Rn */
542 tcg_gen_addi_i32(REG(B11_8
), REG(B11_8
), B7_0s
);
544 case 0xa000: /* bra disp */
546 ctx
->delayed_pc
= ctx
->base
.pc_next
+ 4 + B11_0s
* 2;
547 ctx
->envflags
|= TB_FLAG_DELAY_SLOT
;
549 case 0xb000: /* bsr disp */
551 tcg_gen_movi_i32(cpu_pr
, ctx
->base
.pc_next
+ 4);
552 ctx
->delayed_pc
= ctx
->base
.pc_next
+ 4 + B11_0s
* 2;
553 ctx
->envflags
|= TB_FLAG_DELAY_SLOT
;
557 switch (ctx
->opcode
& 0xf00f) {
558 case 0x6003: /* mov Rm,Rn */
559 tcg_gen_mov_i32(REG(B11_8
), REG(B7_4
));
561 case 0x2000: /* mov.b Rm,@Rn */
562 tcg_gen_qemu_st_i32(REG(B7_4
), REG(B11_8
), ctx
->memidx
, MO_UB
);
564 case 0x2001: /* mov.w Rm,@Rn */
565 tcg_gen_qemu_st_i32(REG(B7_4
), REG(B11_8
), ctx
->memidx
,
566 MO_TEUW
| UNALIGN(ctx
));
568 case 0x2002: /* mov.l Rm,@Rn */
569 tcg_gen_qemu_st_i32(REG(B7_4
), REG(B11_8
), ctx
->memidx
,
570 MO_TEUL
| UNALIGN(ctx
));
572 case 0x6000: /* mov.b @Rm,Rn */
573 tcg_gen_qemu_ld_i32(REG(B11_8
), REG(B7_4
), ctx
->memidx
, MO_SB
);
575 case 0x6001: /* mov.w @Rm,Rn */
576 tcg_gen_qemu_ld_i32(REG(B11_8
), REG(B7_4
), ctx
->memidx
,
577 MO_TESW
| UNALIGN(ctx
));
579 case 0x6002: /* mov.l @Rm,Rn */
580 tcg_gen_qemu_ld_i32(REG(B11_8
), REG(B7_4
), ctx
->memidx
,
581 MO_TESL
| UNALIGN(ctx
));
583 case 0x2004: /* mov.b Rm,@-Rn */
585 TCGv addr
= tcg_temp_new();
586 tcg_gen_subi_i32(addr
, REG(B11_8
), 1);
587 /* might cause re-execution */
588 tcg_gen_qemu_st_i32(REG(B7_4
), addr
, ctx
->memidx
, MO_UB
);
589 tcg_gen_mov_i32(REG(B11_8
), addr
); /* modify register status */
592 case 0x2005: /* mov.w Rm,@-Rn */
594 TCGv addr
= tcg_temp_new();
595 tcg_gen_subi_i32(addr
, REG(B11_8
), 2);
596 tcg_gen_qemu_st_i32(REG(B7_4
), addr
, ctx
->memidx
,
597 MO_TEUW
| UNALIGN(ctx
));
598 tcg_gen_mov_i32(REG(B11_8
), addr
);
601 case 0x2006: /* mov.l Rm,@-Rn */
603 TCGv addr
= tcg_temp_new();
604 tcg_gen_subi_i32(addr
, REG(B11_8
), 4);
605 tcg_gen_qemu_st_i32(REG(B7_4
), addr
, ctx
->memidx
,
606 MO_TEUL
| UNALIGN(ctx
));
607 tcg_gen_mov_i32(REG(B11_8
), addr
);
610 case 0x6004: /* mov.b @Rm+,Rn */
611 tcg_gen_qemu_ld_i32(REG(B11_8
), REG(B7_4
), ctx
->memidx
, MO_SB
);
613 tcg_gen_addi_i32(REG(B7_4
), REG(B7_4
), 1);
615 case 0x6005: /* mov.w @Rm+,Rn */
616 tcg_gen_qemu_ld_i32(REG(B11_8
), REG(B7_4
), ctx
->memidx
,
617 MO_TESW
| UNALIGN(ctx
));
619 tcg_gen_addi_i32(REG(B7_4
), REG(B7_4
), 2);
621 case 0x6006: /* mov.l @Rm+,Rn */
622 tcg_gen_qemu_ld_i32(REG(B11_8
), REG(B7_4
), ctx
->memidx
,
623 MO_TESL
| UNALIGN(ctx
));
625 tcg_gen_addi_i32(REG(B7_4
), REG(B7_4
), 4);
627 case 0x0004: /* mov.b Rm,@(R0,Rn) */
629 TCGv addr
= tcg_temp_new();
630 tcg_gen_add_i32(addr
, REG(B11_8
), REG(0));
631 tcg_gen_qemu_st_i32(REG(B7_4
), addr
, ctx
->memidx
, MO_UB
);
634 case 0x0005: /* mov.w Rm,@(R0,Rn) */
636 TCGv addr
= tcg_temp_new();
637 tcg_gen_add_i32(addr
, REG(B11_8
), REG(0));
638 tcg_gen_qemu_st_i32(REG(B7_4
), addr
, ctx
->memidx
,
639 MO_TEUW
| UNALIGN(ctx
));
642 case 0x0006: /* mov.l Rm,@(R0,Rn) */
644 TCGv addr
= tcg_temp_new();
645 tcg_gen_add_i32(addr
, REG(B11_8
), REG(0));
646 tcg_gen_qemu_st_i32(REG(B7_4
), addr
, ctx
->memidx
,
647 MO_TEUL
| UNALIGN(ctx
));
650 case 0x000c: /* mov.b @(R0,Rm),Rn */
652 TCGv addr
= tcg_temp_new();
653 tcg_gen_add_i32(addr
, REG(B7_4
), REG(0));
654 tcg_gen_qemu_ld_i32(REG(B11_8
), addr
, ctx
->memidx
, MO_SB
);
657 case 0x000d: /* mov.w @(R0,Rm),Rn */
659 TCGv addr
= tcg_temp_new();
660 tcg_gen_add_i32(addr
, REG(B7_4
), REG(0));
661 tcg_gen_qemu_ld_i32(REG(B11_8
), addr
, ctx
->memidx
,
662 MO_TESW
| UNALIGN(ctx
));
665 case 0x000e: /* mov.l @(R0,Rm),Rn */
667 TCGv addr
= tcg_temp_new();
668 tcg_gen_add_i32(addr
, REG(B7_4
), REG(0));
669 tcg_gen_qemu_ld_i32(REG(B11_8
), addr
, ctx
->memidx
,
670 MO_TESL
| UNALIGN(ctx
));
673 case 0x6008: /* swap.b Rm,Rn */
675 TCGv low
= tcg_temp_new();
676 tcg_gen_bswap16_i32(low
, REG(B7_4
), 0);
677 tcg_gen_deposit_i32(REG(B11_8
), REG(B7_4
), low
, 0, 16);
680 case 0x6009: /* swap.w Rm,Rn */
681 tcg_gen_rotli_i32(REG(B11_8
), REG(B7_4
), 16);
683 case 0x200d: /* xtrct Rm,Rn */
686 high
= tcg_temp_new();
687 tcg_gen_shli_i32(high
, REG(B7_4
), 16);
688 low
= tcg_temp_new();
689 tcg_gen_shri_i32(low
, REG(B11_8
), 16);
690 tcg_gen_or_i32(REG(B11_8
), high
, low
);
693 case 0x300c: /* add Rm,Rn */
694 tcg_gen_add_i32(REG(B11_8
), REG(B11_8
), REG(B7_4
));
696 case 0x300e: /* addc Rm,Rn */
699 t0
= tcg_constant_tl(0);
701 tcg_gen_add2_i32(t1
, cpu_sr_t
, cpu_sr_t
, t0
, REG(B7_4
), t0
);
702 tcg_gen_add2_i32(REG(B11_8
), cpu_sr_t
,
703 REG(B11_8
), t0
, t1
, cpu_sr_t
);
706 case 0x300f: /* addv Rm,Rn */
710 tcg_gen_add_i32(t0
, REG(B7_4
), REG(B11_8
));
712 tcg_gen_xor_i32(t1
, t0
, REG(B11_8
));
714 tcg_gen_xor_i32(t2
, REG(B7_4
), REG(B11_8
));
715 tcg_gen_andc_i32(cpu_sr_t
, t1
, t2
);
716 tcg_gen_shri_i32(cpu_sr_t
, cpu_sr_t
, 31);
717 tcg_gen_mov_i32(REG(B7_4
), t0
);
720 case 0x2009: /* and Rm,Rn */
721 tcg_gen_and_i32(REG(B11_8
), REG(B11_8
), REG(B7_4
));
723 case 0x3000: /* cmp/eq Rm,Rn */
724 tcg_gen_setcond_i32(TCG_COND_EQ
, cpu_sr_t
, REG(B11_8
), REG(B7_4
));
726 case 0x3003: /* cmp/ge Rm,Rn */
727 tcg_gen_setcond_i32(TCG_COND_GE
, cpu_sr_t
, REG(B11_8
), REG(B7_4
));
729 case 0x3007: /* cmp/gt Rm,Rn */
730 tcg_gen_setcond_i32(TCG_COND_GT
, cpu_sr_t
, REG(B11_8
), REG(B7_4
));
732 case 0x3006: /* cmp/hi Rm,Rn */
733 tcg_gen_setcond_i32(TCG_COND_GTU
, cpu_sr_t
, REG(B11_8
), REG(B7_4
));
735 case 0x3002: /* cmp/hs Rm,Rn */
736 tcg_gen_setcond_i32(TCG_COND_GEU
, cpu_sr_t
, REG(B11_8
), REG(B7_4
));
738 case 0x200c: /* cmp/str Rm,Rn */
740 TCGv cmp1
= tcg_temp_new();
741 TCGv cmp2
= tcg_temp_new();
742 tcg_gen_xor_i32(cmp2
, REG(B7_4
), REG(B11_8
));
743 tcg_gen_subi_i32(cmp1
, cmp2
, 0x01010101);
744 tcg_gen_andc_i32(cmp1
, cmp1
, cmp2
);
745 tcg_gen_andi_i32(cmp1
, cmp1
, 0x80808080);
746 tcg_gen_setcondi_i32(TCG_COND_NE
, cpu_sr_t
, cmp1
, 0);
749 case 0x2007: /* div0s Rm,Rn */
750 tcg_gen_shri_i32(cpu_sr_q
, REG(B11_8
), 31); /* SR_Q */
751 tcg_gen_shri_i32(cpu_sr_m
, REG(B7_4
), 31); /* SR_M */
752 tcg_gen_xor_i32(cpu_sr_t
, cpu_sr_q
, cpu_sr_m
); /* SR_T */
754 case 0x3004: /* div1 Rm,Rn */
756 TCGv t0
= tcg_temp_new();
757 TCGv t1
= tcg_temp_new();
758 TCGv t2
= tcg_temp_new();
759 TCGv zero
= tcg_constant_i32(0);
761 /* shift left arg1, saving the bit being pushed out and inserting
763 tcg_gen_shri_i32(t0
, REG(B11_8
), 31);
764 tcg_gen_shli_i32(REG(B11_8
), REG(B11_8
), 1);
765 tcg_gen_or_i32(REG(B11_8
), REG(B11_8
), cpu_sr_t
);
767 /* Add or subtract arg0 from arg1 depending if Q == M. To avoid
768 using 64-bit temps, we compute arg0's high part from q ^ m, so
769 that it is 0x00000000 when adding the value or 0xffffffff when
771 tcg_gen_xor_i32(t1
, cpu_sr_q
, cpu_sr_m
);
772 tcg_gen_subi_i32(t1
, t1
, 1);
773 tcg_gen_neg_i32(t2
, REG(B7_4
));
774 tcg_gen_movcond_i32(TCG_COND_EQ
, t2
, t1
, zero
, REG(B7_4
), t2
);
775 tcg_gen_add2_i32(REG(B11_8
), t1
, REG(B11_8
), zero
, t2
, t1
);
777 /* compute T and Q depending on carry */
778 tcg_gen_andi_i32(t1
, t1
, 1);
779 tcg_gen_xor_i32(t1
, t1
, t0
);
780 tcg_gen_xori_i32(cpu_sr_t
, t1
, 1);
781 tcg_gen_xor_i32(cpu_sr_q
, cpu_sr_m
, t1
);
784 case 0x300d: /* dmuls.l Rm,Rn */
785 tcg_gen_muls2_i32(cpu_macl
, cpu_mach
, REG(B7_4
), REG(B11_8
));
787 case 0x3005: /* dmulu.l Rm,Rn */
788 tcg_gen_mulu2_i32(cpu_macl
, cpu_mach
, REG(B7_4
), REG(B11_8
));
790 case 0x600e: /* exts.b Rm,Rn */
791 tcg_gen_ext8s_i32(REG(B11_8
), REG(B7_4
));
793 case 0x600f: /* exts.w Rm,Rn */
794 tcg_gen_ext16s_i32(REG(B11_8
), REG(B7_4
));
796 case 0x600c: /* extu.b Rm,Rn */
797 tcg_gen_ext8u_i32(REG(B11_8
), REG(B7_4
));
799 case 0x600d: /* extu.w Rm,Rn */
800 tcg_gen_ext16u_i32(REG(B11_8
), REG(B7_4
));
802 case 0x000f: /* mac.l @Rm+,@Rn+ */
805 arg0
= tcg_temp_new();
806 tcg_gen_qemu_ld_i32(arg0
, REG(B7_4
), ctx
->memidx
,
808 arg1
= tcg_temp_new();
809 tcg_gen_qemu_ld_i32(arg1
, REG(B11_8
), ctx
->memidx
,
811 gen_helper_macl(cpu_env
, arg0
, arg1
);
812 tcg_gen_addi_i32(REG(B7_4
), REG(B7_4
), 4);
813 tcg_gen_addi_i32(REG(B11_8
), REG(B11_8
), 4);
816 case 0x400f: /* mac.w @Rm+,@Rn+ */
819 arg0
= tcg_temp_new();
820 tcg_gen_qemu_ld_i32(arg0
, REG(B7_4
), ctx
->memidx
,
822 arg1
= tcg_temp_new();
823 tcg_gen_qemu_ld_i32(arg1
, REG(B11_8
), ctx
->memidx
,
825 gen_helper_macw(cpu_env
, arg0
, arg1
);
826 tcg_gen_addi_i32(REG(B11_8
), REG(B11_8
), 2);
827 tcg_gen_addi_i32(REG(B7_4
), REG(B7_4
), 2);
830 case 0x0007: /* mul.l Rm,Rn */
831 tcg_gen_mul_i32(cpu_macl
, REG(B7_4
), REG(B11_8
));
833 case 0x200f: /* muls.w Rm,Rn */
836 arg0
= tcg_temp_new();
837 tcg_gen_ext16s_i32(arg0
, REG(B7_4
));
838 arg1
= tcg_temp_new();
839 tcg_gen_ext16s_i32(arg1
, REG(B11_8
));
840 tcg_gen_mul_i32(cpu_macl
, arg0
, arg1
);
843 case 0x200e: /* mulu.w Rm,Rn */
846 arg0
= tcg_temp_new();
847 tcg_gen_ext16u_i32(arg0
, REG(B7_4
));
848 arg1
= tcg_temp_new();
849 tcg_gen_ext16u_i32(arg1
, REG(B11_8
));
850 tcg_gen_mul_i32(cpu_macl
, arg0
, arg1
);
853 case 0x600b: /* neg Rm,Rn */
854 tcg_gen_neg_i32(REG(B11_8
), REG(B7_4
));
856 case 0x600a: /* negc Rm,Rn */
858 TCGv t0
= tcg_constant_i32(0);
859 tcg_gen_add2_i32(REG(B11_8
), cpu_sr_t
,
860 REG(B7_4
), t0
, cpu_sr_t
, t0
);
861 tcg_gen_sub2_i32(REG(B11_8
), cpu_sr_t
,
862 t0
, t0
, REG(B11_8
), cpu_sr_t
);
863 tcg_gen_andi_i32(cpu_sr_t
, cpu_sr_t
, 1);
866 case 0x6007: /* not Rm,Rn */
867 tcg_gen_not_i32(REG(B11_8
), REG(B7_4
));
869 case 0x200b: /* or Rm,Rn */
870 tcg_gen_or_i32(REG(B11_8
), REG(B11_8
), REG(B7_4
));
872 case 0x400c: /* shad Rm,Rn */
874 TCGv t0
= tcg_temp_new();
875 TCGv t1
= tcg_temp_new();
876 TCGv t2
= tcg_temp_new();
878 tcg_gen_andi_i32(t0
, REG(B7_4
), 0x1f);
880 /* positive case: shift to the left */
881 tcg_gen_shl_i32(t1
, REG(B11_8
), t0
);
883 /* negative case: shift to the right in two steps to
884 correctly handle the -32 case */
885 tcg_gen_xori_i32(t0
, t0
, 0x1f);
886 tcg_gen_sar_i32(t2
, REG(B11_8
), t0
);
887 tcg_gen_sari_i32(t2
, t2
, 1);
889 /* select between the two cases */
890 tcg_gen_movi_i32(t0
, 0);
891 tcg_gen_movcond_i32(TCG_COND_GE
, REG(B11_8
), REG(B7_4
), t0
, t1
, t2
);
894 case 0x400d: /* shld Rm,Rn */
896 TCGv t0
= tcg_temp_new();
897 TCGv t1
= tcg_temp_new();
898 TCGv t2
= tcg_temp_new();
900 tcg_gen_andi_i32(t0
, REG(B7_4
), 0x1f);
902 /* positive case: shift to the left */
903 tcg_gen_shl_i32(t1
, REG(B11_8
), t0
);
905 /* negative case: shift to the right in two steps to
906 correctly handle the -32 case */
907 tcg_gen_xori_i32(t0
, t0
, 0x1f);
908 tcg_gen_shr_i32(t2
, REG(B11_8
), t0
);
909 tcg_gen_shri_i32(t2
, t2
, 1);
911 /* select between the two cases */
912 tcg_gen_movi_i32(t0
, 0);
913 tcg_gen_movcond_i32(TCG_COND_GE
, REG(B11_8
), REG(B7_4
), t0
, t1
, t2
);
916 case 0x3008: /* sub Rm,Rn */
917 tcg_gen_sub_i32(REG(B11_8
), REG(B11_8
), REG(B7_4
));
919 case 0x300a: /* subc Rm,Rn */
922 t0
= tcg_constant_tl(0);
924 tcg_gen_add2_i32(t1
, cpu_sr_t
, cpu_sr_t
, t0
, REG(B7_4
), t0
);
925 tcg_gen_sub2_i32(REG(B11_8
), cpu_sr_t
,
926 REG(B11_8
), t0
, t1
, cpu_sr_t
);
927 tcg_gen_andi_i32(cpu_sr_t
, cpu_sr_t
, 1);
930 case 0x300b: /* subv Rm,Rn */
934 tcg_gen_sub_i32(t0
, REG(B11_8
), REG(B7_4
));
936 tcg_gen_xor_i32(t1
, t0
, REG(B7_4
));
938 tcg_gen_xor_i32(t2
, REG(B11_8
), REG(B7_4
));
939 tcg_gen_and_i32(t1
, t1
, t2
);
940 tcg_gen_shri_i32(cpu_sr_t
, t1
, 31);
941 tcg_gen_mov_i32(REG(B11_8
), t0
);
944 case 0x2008: /* tst Rm,Rn */
946 TCGv val
= tcg_temp_new();
947 tcg_gen_and_i32(val
, REG(B7_4
), REG(B11_8
));
948 tcg_gen_setcondi_i32(TCG_COND_EQ
, cpu_sr_t
, val
, 0);
951 case 0x200a: /* xor Rm,Rn */
952 tcg_gen_xor_i32(REG(B11_8
), REG(B11_8
), REG(B7_4
));
954 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
956 if (ctx
->tbflags
& FPSCR_SZ
) {
957 int xsrc
= XHACK(B7_4
);
958 int xdst
= XHACK(B11_8
);
959 tcg_gen_mov_i32(FREG(xdst
), FREG(xsrc
));
960 tcg_gen_mov_i32(FREG(xdst
+ 1), FREG(xsrc
+ 1));
962 tcg_gen_mov_i32(FREG(B11_8
), FREG(B7_4
));
965 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
967 if (ctx
->tbflags
& FPSCR_SZ
) {
968 TCGv_i64 fp
= tcg_temp_new_i64();
969 gen_load_fpr64(ctx
, fp
, XHACK(B7_4
));
970 tcg_gen_qemu_st_i64(fp
, REG(B11_8
), ctx
->memidx
,
973 tcg_gen_qemu_st_i32(FREG(B7_4
), REG(B11_8
), ctx
->memidx
,
977 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
979 if (ctx
->tbflags
& FPSCR_SZ
) {
980 TCGv_i64 fp
= tcg_temp_new_i64();
981 tcg_gen_qemu_ld_i64(fp
, REG(B7_4
), ctx
->memidx
,
983 gen_store_fpr64(ctx
, fp
, XHACK(B11_8
));
985 tcg_gen_qemu_ld_i32(FREG(B11_8
), REG(B7_4
), ctx
->memidx
,
989 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
991 if (ctx
->tbflags
& FPSCR_SZ
) {
992 TCGv_i64 fp
= tcg_temp_new_i64();
993 tcg_gen_qemu_ld_i64(fp
, REG(B7_4
), ctx
->memidx
,
995 gen_store_fpr64(ctx
, fp
, XHACK(B11_8
));
996 tcg_gen_addi_i32(REG(B7_4
), REG(B7_4
), 8);
998 tcg_gen_qemu_ld_i32(FREG(B11_8
), REG(B7_4
), ctx
->memidx
,
1000 tcg_gen_addi_i32(REG(B7_4
), REG(B7_4
), 4);
1003 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
1006 TCGv addr
= tcg_temp_new_i32();
1007 if (ctx
->tbflags
& FPSCR_SZ
) {
1008 TCGv_i64 fp
= tcg_temp_new_i64();
1009 gen_load_fpr64(ctx
, fp
, XHACK(B7_4
));
1010 tcg_gen_subi_i32(addr
, REG(B11_8
), 8);
1011 tcg_gen_qemu_st_i64(fp
, addr
, ctx
->memidx
,
1012 MO_TEUQ
| MO_ALIGN
);
1014 tcg_gen_subi_i32(addr
, REG(B11_8
), 4);
1015 tcg_gen_qemu_st_i32(FREG(B7_4
), addr
, ctx
->memidx
,
1016 MO_TEUL
| MO_ALIGN
);
1018 tcg_gen_mov_i32(REG(B11_8
), addr
);
1021 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
1024 TCGv addr
= tcg_temp_new_i32();
1025 tcg_gen_add_i32(addr
, REG(B7_4
), REG(0));
1026 if (ctx
->tbflags
& FPSCR_SZ
) {
1027 TCGv_i64 fp
= tcg_temp_new_i64();
1028 tcg_gen_qemu_ld_i64(fp
, addr
, ctx
->memidx
,
1029 MO_TEUQ
| MO_ALIGN
);
1030 gen_store_fpr64(ctx
, fp
, XHACK(B11_8
));
1032 tcg_gen_qemu_ld_i32(FREG(B11_8
), addr
, ctx
->memidx
,
1033 MO_TEUL
| MO_ALIGN
);
1037 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
1040 TCGv addr
= tcg_temp_new();
1041 tcg_gen_add_i32(addr
, REG(B11_8
), REG(0));
1042 if (ctx
->tbflags
& FPSCR_SZ
) {
1043 TCGv_i64 fp
= tcg_temp_new_i64();
1044 gen_load_fpr64(ctx
, fp
, XHACK(B7_4
));
1045 tcg_gen_qemu_st_i64(fp
, addr
, ctx
->memidx
,
1046 MO_TEUQ
| MO_ALIGN
);
1048 tcg_gen_qemu_st_i32(FREG(B7_4
), addr
, ctx
->memidx
,
1049 MO_TEUL
| MO_ALIGN
);
1053 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1054 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1055 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1056 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1057 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1058 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1061 if (ctx
->tbflags
& FPSCR_PR
) {
1064 if (ctx
->opcode
& 0x0110) {
1067 fp0
= tcg_temp_new_i64();
1068 fp1
= tcg_temp_new_i64();
1069 gen_load_fpr64(ctx
, fp0
, B11_8
);
1070 gen_load_fpr64(ctx
, fp1
, B7_4
);
1071 switch (ctx
->opcode
& 0xf00f) {
1072 case 0xf000: /* fadd Rm,Rn */
1073 gen_helper_fadd_DT(fp0
, cpu_env
, fp0
, fp1
);
1075 case 0xf001: /* fsub Rm,Rn */
1076 gen_helper_fsub_DT(fp0
, cpu_env
, fp0
, fp1
);
1078 case 0xf002: /* fmul Rm,Rn */
1079 gen_helper_fmul_DT(fp0
, cpu_env
, fp0
, fp1
);
1081 case 0xf003: /* fdiv Rm,Rn */
1082 gen_helper_fdiv_DT(fp0
, cpu_env
, fp0
, fp1
);
1084 case 0xf004: /* fcmp/eq Rm,Rn */
1085 gen_helper_fcmp_eq_DT(cpu_sr_t
, cpu_env
, fp0
, fp1
);
1087 case 0xf005: /* fcmp/gt Rm,Rn */
1088 gen_helper_fcmp_gt_DT(cpu_sr_t
, cpu_env
, fp0
, fp1
);
1091 gen_store_fpr64(ctx
, fp0
, B11_8
);
1093 switch (ctx
->opcode
& 0xf00f) {
1094 case 0xf000: /* fadd Rm,Rn */
1095 gen_helper_fadd_FT(FREG(B11_8
), cpu_env
,
1096 FREG(B11_8
), FREG(B7_4
));
1098 case 0xf001: /* fsub Rm,Rn */
1099 gen_helper_fsub_FT(FREG(B11_8
), cpu_env
,
1100 FREG(B11_8
), FREG(B7_4
));
1102 case 0xf002: /* fmul Rm,Rn */
1103 gen_helper_fmul_FT(FREG(B11_8
), cpu_env
,
1104 FREG(B11_8
), FREG(B7_4
));
1106 case 0xf003: /* fdiv Rm,Rn */
1107 gen_helper_fdiv_FT(FREG(B11_8
), cpu_env
,
1108 FREG(B11_8
), FREG(B7_4
));
1110 case 0xf004: /* fcmp/eq Rm,Rn */
1111 gen_helper_fcmp_eq_FT(cpu_sr_t
, cpu_env
,
1112 FREG(B11_8
), FREG(B7_4
));
1114 case 0xf005: /* fcmp/gt Rm,Rn */
1115 gen_helper_fcmp_gt_FT(cpu_sr_t
, cpu_env
,
1116 FREG(B11_8
), FREG(B7_4
));
1122 case 0xf00e: /* fmac FR0,RM,Rn */
1125 gen_helper_fmac_FT(FREG(B11_8
), cpu_env
,
1126 FREG(0), FREG(B7_4
), FREG(B11_8
));
1130 switch (ctx
->opcode
& 0xff00) {
1131 case 0xc900: /* and #imm,R0 */
1132 tcg_gen_andi_i32(REG(0), REG(0), B7_0
);
1134 case 0xcd00: /* and.b #imm,@(R0,GBR) */
1137 addr
= tcg_temp_new();
1138 tcg_gen_add_i32(addr
, REG(0), cpu_gbr
);
1139 val
= tcg_temp_new();
1140 tcg_gen_qemu_ld_i32(val
, addr
, ctx
->memidx
, MO_UB
);
1141 tcg_gen_andi_i32(val
, val
, B7_0
);
1142 tcg_gen_qemu_st_i32(val
, addr
, ctx
->memidx
, MO_UB
);
1145 case 0x8b00: /* bf label */
1146 CHECK_NOT_DELAY_SLOT
1147 gen_conditional_jump(ctx
, ctx
->base
.pc_next
+ 4 + B7_0s
* 2, false);
1149 case 0x8f00: /* bf/s label */
1150 CHECK_NOT_DELAY_SLOT
1151 tcg_gen_xori_i32(cpu_delayed_cond
, cpu_sr_t
, 1);
1152 ctx
->delayed_pc
= ctx
->base
.pc_next
+ 4 + B7_0s
* 2;
1153 ctx
->envflags
|= TB_FLAG_DELAY_SLOT_COND
;
1155 case 0x8900: /* bt label */
1156 CHECK_NOT_DELAY_SLOT
1157 gen_conditional_jump(ctx
, ctx
->base
.pc_next
+ 4 + B7_0s
* 2, true);
1159 case 0x8d00: /* bt/s label */
1160 CHECK_NOT_DELAY_SLOT
1161 tcg_gen_mov_i32(cpu_delayed_cond
, cpu_sr_t
);
1162 ctx
->delayed_pc
= ctx
->base
.pc_next
+ 4 + B7_0s
* 2;
1163 ctx
->envflags
|= TB_FLAG_DELAY_SLOT_COND
;
1165 case 0x8800: /* cmp/eq #imm,R0 */
1166 tcg_gen_setcondi_i32(TCG_COND_EQ
, cpu_sr_t
, REG(0), B7_0s
);
1168 case 0xc400: /* mov.b @(disp,GBR),R0 */
1170 TCGv addr
= tcg_temp_new();
1171 tcg_gen_addi_i32(addr
, cpu_gbr
, B7_0
);
1172 tcg_gen_qemu_ld_i32(REG(0), addr
, ctx
->memidx
, MO_SB
);
1175 case 0xc500: /* mov.w @(disp,GBR),R0 */
1177 TCGv addr
= tcg_temp_new();
1178 tcg_gen_addi_i32(addr
, cpu_gbr
, B7_0
* 2);
1179 tcg_gen_qemu_ld_i32(REG(0), addr
, ctx
->memidx
, MO_TESW
| MO_ALIGN
);
1182 case 0xc600: /* mov.l @(disp,GBR),R0 */
1184 TCGv addr
= tcg_temp_new();
1185 tcg_gen_addi_i32(addr
, cpu_gbr
, B7_0
* 4);
1186 tcg_gen_qemu_ld_i32(REG(0), addr
, ctx
->memidx
, MO_TESL
| MO_ALIGN
);
1189 case 0xc000: /* mov.b R0,@(disp,GBR) */
1191 TCGv addr
= tcg_temp_new();
1192 tcg_gen_addi_i32(addr
, cpu_gbr
, B7_0
);
1193 tcg_gen_qemu_st_i32(REG(0), addr
, ctx
->memidx
, MO_UB
);
1196 case 0xc100: /* mov.w R0,@(disp,GBR) */
1198 TCGv addr
= tcg_temp_new();
1199 tcg_gen_addi_i32(addr
, cpu_gbr
, B7_0
* 2);
1200 tcg_gen_qemu_st_i32(REG(0), addr
, ctx
->memidx
, MO_TEUW
| MO_ALIGN
);
1203 case 0xc200: /* mov.l R0,@(disp,GBR) */
1205 TCGv addr
= tcg_temp_new();
1206 tcg_gen_addi_i32(addr
, cpu_gbr
, B7_0
* 4);
1207 tcg_gen_qemu_st_i32(REG(0), addr
, ctx
->memidx
, MO_TEUL
| MO_ALIGN
);
1210 case 0x8000: /* mov.b R0,@(disp,Rn) */
1212 TCGv addr
= tcg_temp_new();
1213 tcg_gen_addi_i32(addr
, REG(B7_4
), B3_0
);
1214 tcg_gen_qemu_st_i32(REG(0), addr
, ctx
->memidx
, MO_UB
);
1217 case 0x8100: /* mov.w R0,@(disp,Rn) */
1219 TCGv addr
= tcg_temp_new();
1220 tcg_gen_addi_i32(addr
, REG(B7_4
), B3_0
* 2);
1221 tcg_gen_qemu_st_i32(REG(0), addr
, ctx
->memidx
,
1222 MO_TEUW
| UNALIGN(ctx
));
1225 case 0x8400: /* mov.b @(disp,Rn),R0 */
1227 TCGv addr
= tcg_temp_new();
1228 tcg_gen_addi_i32(addr
, REG(B7_4
), B3_0
);
1229 tcg_gen_qemu_ld_i32(REG(0), addr
, ctx
->memidx
, MO_SB
);
1232 case 0x8500: /* mov.w @(disp,Rn),R0 */
1234 TCGv addr
= tcg_temp_new();
1235 tcg_gen_addi_i32(addr
, REG(B7_4
), B3_0
* 2);
1236 tcg_gen_qemu_ld_i32(REG(0), addr
, ctx
->memidx
,
1237 MO_TESW
| UNALIGN(ctx
));
1240 case 0xc700: /* mova @(disp,PC),R0 */
1241 tcg_gen_movi_i32(REG(0), ((ctx
->base
.pc_next
& 0xfffffffc) +
1242 4 + B7_0
* 4) & ~3);
1244 case 0xcb00: /* or #imm,R0 */
1245 tcg_gen_ori_i32(REG(0), REG(0), B7_0
);
1247 case 0xcf00: /* or.b #imm,@(R0,GBR) */
1250 addr
= tcg_temp_new();
1251 tcg_gen_add_i32(addr
, REG(0), cpu_gbr
);
1252 val
= tcg_temp_new();
1253 tcg_gen_qemu_ld_i32(val
, addr
, ctx
->memidx
, MO_UB
);
1254 tcg_gen_ori_i32(val
, val
, B7_0
);
1255 tcg_gen_qemu_st_i32(val
, addr
, ctx
->memidx
, MO_UB
);
1258 case 0xc300: /* trapa #imm */
1261 CHECK_NOT_DELAY_SLOT
1262 gen_save_cpu_state(ctx
, true);
1263 imm
= tcg_constant_i32(B7_0
);
1264 gen_helper_trapa(cpu_env
, imm
);
1265 ctx
->base
.is_jmp
= DISAS_NORETURN
;
1268 case 0xc800: /* tst #imm,R0 */
1270 TCGv val
= tcg_temp_new();
1271 tcg_gen_andi_i32(val
, REG(0), B7_0
);
1272 tcg_gen_setcondi_i32(TCG_COND_EQ
, cpu_sr_t
, val
, 0);
1275 case 0xcc00: /* tst.b #imm,@(R0,GBR) */
1277 TCGv val
= tcg_temp_new();
1278 tcg_gen_add_i32(val
, REG(0), cpu_gbr
);
1279 tcg_gen_qemu_ld_i32(val
, val
, ctx
->memidx
, MO_UB
);
1280 tcg_gen_andi_i32(val
, val
, B7_0
);
1281 tcg_gen_setcondi_i32(TCG_COND_EQ
, cpu_sr_t
, val
, 0);
1284 case 0xca00: /* xor #imm,R0 */
1285 tcg_gen_xori_i32(REG(0), REG(0), B7_0
);
1287 case 0xce00: /* xor.b #imm,@(R0,GBR) */
1290 addr
= tcg_temp_new();
1291 tcg_gen_add_i32(addr
, REG(0), cpu_gbr
);
1292 val
= tcg_temp_new();
1293 tcg_gen_qemu_ld_i32(val
, addr
, ctx
->memidx
, MO_UB
);
1294 tcg_gen_xori_i32(val
, val
, B7_0
);
1295 tcg_gen_qemu_st_i32(val
, addr
, ctx
->memidx
, MO_UB
);
1300 switch (ctx
->opcode
& 0xf08f) {
1301 case 0x408e: /* ldc Rm,Rn_BANK */
1303 tcg_gen_mov_i32(ALTREG(B6_4
), REG(B11_8
));
1305 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
1307 tcg_gen_qemu_ld_i32(ALTREG(B6_4
), REG(B11_8
), ctx
->memidx
,
1308 MO_TESL
| MO_ALIGN
);
1309 tcg_gen_addi_i32(REG(B11_8
), REG(B11_8
), 4);
1311 case 0x0082: /* stc Rm_BANK,Rn */
1313 tcg_gen_mov_i32(REG(B11_8
), ALTREG(B6_4
));
1315 case 0x4083: /* stc.l Rm_BANK,@-Rn */
1318 TCGv addr
= tcg_temp_new();
1319 tcg_gen_subi_i32(addr
, REG(B11_8
), 4);
1320 tcg_gen_qemu_st_i32(ALTREG(B6_4
), addr
, ctx
->memidx
,
1321 MO_TEUL
| MO_ALIGN
);
1322 tcg_gen_mov_i32(REG(B11_8
), addr
);
1327 switch (ctx
->opcode
& 0xf0ff) {
1328 case 0x0023: /* braf Rn */
1329 CHECK_NOT_DELAY_SLOT
1330 tcg_gen_addi_i32(cpu_delayed_pc
, REG(B11_8
), ctx
->base
.pc_next
+ 4);
1331 ctx
->envflags
|= TB_FLAG_DELAY_SLOT
;
1332 ctx
->delayed_pc
= (uint32_t) - 1;
1334 case 0x0003: /* bsrf Rn */
1335 CHECK_NOT_DELAY_SLOT
1336 tcg_gen_movi_i32(cpu_pr
, ctx
->base
.pc_next
+ 4);
1337 tcg_gen_add_i32(cpu_delayed_pc
, REG(B11_8
), cpu_pr
);
1338 ctx
->envflags
|= TB_FLAG_DELAY_SLOT
;
1339 ctx
->delayed_pc
= (uint32_t) - 1;
1341 case 0x4015: /* cmp/pl Rn */
1342 tcg_gen_setcondi_i32(TCG_COND_GT
, cpu_sr_t
, REG(B11_8
), 0);
1344 case 0x4011: /* cmp/pz Rn */
1345 tcg_gen_setcondi_i32(TCG_COND_GE
, cpu_sr_t
, REG(B11_8
), 0);
1347 case 0x4010: /* dt Rn */
1348 tcg_gen_subi_i32(REG(B11_8
), REG(B11_8
), 1);
1349 tcg_gen_setcondi_i32(TCG_COND_EQ
, cpu_sr_t
, REG(B11_8
), 0);
1351 case 0x402b: /* jmp @Rn */
1352 CHECK_NOT_DELAY_SLOT
1353 tcg_gen_mov_i32(cpu_delayed_pc
, REG(B11_8
));
1354 ctx
->envflags
|= TB_FLAG_DELAY_SLOT
;
1355 ctx
->delayed_pc
= (uint32_t) - 1;
1357 case 0x400b: /* jsr @Rn */
1358 CHECK_NOT_DELAY_SLOT
1359 tcg_gen_movi_i32(cpu_pr
, ctx
->base
.pc_next
+ 4);
1360 tcg_gen_mov_i32(cpu_delayed_pc
, REG(B11_8
));
1361 ctx
->envflags
|= TB_FLAG_DELAY_SLOT
;
1362 ctx
->delayed_pc
= (uint32_t) - 1;
1364 case 0x400e: /* ldc Rm,SR */
1367 TCGv val
= tcg_temp_new();
1368 tcg_gen_andi_i32(val
, REG(B11_8
), 0x700083f3);
1370 ctx
->base
.is_jmp
= DISAS_STOP
;
1373 case 0x4007: /* ldc.l @Rm+,SR */
1376 TCGv val
= tcg_temp_new();
1377 tcg_gen_qemu_ld_i32(val
, REG(B11_8
), ctx
->memidx
,
1378 MO_TESL
| MO_ALIGN
);
1379 tcg_gen_andi_i32(val
, val
, 0x700083f3);
1381 tcg_gen_addi_i32(REG(B11_8
), REG(B11_8
), 4);
1382 ctx
->base
.is_jmp
= DISAS_STOP
;
1385 case 0x0002: /* stc SR,Rn */
1387 gen_read_sr(REG(B11_8
));
1389 case 0x4003: /* stc SR,@-Rn */
1392 TCGv addr
= tcg_temp_new();
1393 TCGv val
= tcg_temp_new();
1394 tcg_gen_subi_i32(addr
, REG(B11_8
), 4);
1396 tcg_gen_qemu_st_i32(val
, addr
, ctx
->memidx
, MO_TEUL
| MO_ALIGN
);
1397 tcg_gen_mov_i32(REG(B11_8
), addr
);
1400 #define LD(reg,ldnum,ldpnum,prechk) \
1403 tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \
1407 tcg_gen_qemu_ld_i32(cpu_##reg, REG(B11_8), ctx->memidx, \
1408 MO_TESL | MO_ALIGN); \
1409 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \
1411 #define ST(reg,stnum,stpnum,prechk) \
1414 tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \
1419 TCGv addr = tcg_temp_new(); \
1420 tcg_gen_subi_i32(addr, REG(B11_8), 4); \
1421 tcg_gen_qemu_st_i32(cpu_##reg, addr, ctx->memidx, \
1422 MO_TEUL | MO_ALIGN); \
1423 tcg_gen_mov_i32(REG(B11_8), addr); \
1426 #define LDST(reg,ldnum,ldpnum,stnum,stpnum,prechk) \
1427 LD(reg,ldnum,ldpnum,prechk) \
1428 ST(reg,stnum,stpnum,prechk)
1429 LDST(gbr
, 0x401e, 0x4017, 0x0012, 0x4013, {})
1430 LDST(vbr
, 0x402e, 0x4027, 0x0022, 0x4023, CHECK_PRIVILEGED
)
1431 LDST(ssr
, 0x403e, 0x4037, 0x0032, 0x4033, CHECK_PRIVILEGED
)
1432 LDST(spc
, 0x404e, 0x4047, 0x0042, 0x4043, CHECK_PRIVILEGED
)
1433 ST(sgr
, 0x003a, 0x4032, CHECK_PRIVILEGED
)
1434 LD(sgr
, 0x403a, 0x4036, CHECK_PRIVILEGED CHECK_SH4A
)
1435 LDST(dbr
, 0x40fa, 0x40f6, 0x00fa, 0x40f2, CHECK_PRIVILEGED
)
1436 LDST(mach
, 0x400a, 0x4006, 0x000a, 0x4002, {})
1437 LDST(macl
, 0x401a, 0x4016, 0x001a, 0x4012, {})
1438 LDST(pr
, 0x402a, 0x4026, 0x002a, 0x4022, {})
1439 LDST(fpul
, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED
})
1440 case 0x406a: /* lds Rm,FPSCR */
1442 gen_helper_ld_fpscr(cpu_env
, REG(B11_8
));
1443 ctx
->base
.is_jmp
= DISAS_STOP
;
1445 case 0x4066: /* lds.l @Rm+,FPSCR */
1448 TCGv addr
= tcg_temp_new();
1449 tcg_gen_qemu_ld_i32(addr
, REG(B11_8
), ctx
->memidx
,
1450 MO_TESL
| MO_ALIGN
);
1451 tcg_gen_addi_i32(REG(B11_8
), REG(B11_8
), 4);
1452 gen_helper_ld_fpscr(cpu_env
, addr
);
1453 ctx
->base
.is_jmp
= DISAS_STOP
;
1456 case 0x006a: /* sts FPSCR,Rn */
1458 tcg_gen_andi_i32(REG(B11_8
), cpu_fpscr
, 0x003fffff);
1460 case 0x4062: /* sts FPSCR,@-Rn */
1464 val
= tcg_temp_new();
1465 tcg_gen_andi_i32(val
, cpu_fpscr
, 0x003fffff);
1466 addr
= tcg_temp_new();
1467 tcg_gen_subi_i32(addr
, REG(B11_8
), 4);
1468 tcg_gen_qemu_st_i32(val
, addr
, ctx
->memidx
, MO_TEUL
| MO_ALIGN
);
1469 tcg_gen_mov_i32(REG(B11_8
), addr
);
1472 case 0x00c3: /* movca.l R0,@Rm */
1474 TCGv val
= tcg_temp_new();
1475 tcg_gen_qemu_ld_i32(val
, REG(B11_8
), ctx
->memidx
,
1476 MO_TEUL
| MO_ALIGN
);
1477 gen_helper_movcal(cpu_env
, REG(B11_8
), val
);
1478 tcg_gen_qemu_st_i32(REG(0), REG(B11_8
), ctx
->memidx
,
1479 MO_TEUL
| MO_ALIGN
);
1481 ctx
->has_movcal
= 1;
1483 case 0x40a9: /* movua.l @Rm,R0 */
1485 /* Load non-boundary-aligned data */
1486 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8
), ctx
->memidx
,
1487 MO_TEUL
| MO_UNALN
);
1489 case 0x40e9: /* movua.l @Rm+,R0 */
1491 /* Load non-boundary-aligned data */
1492 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8
), ctx
->memidx
,
1493 MO_TEUL
| MO_UNALN
);
1494 tcg_gen_addi_i32(REG(B11_8
), REG(B11_8
), 4);
1496 case 0x0029: /* movt Rn */
1497 tcg_gen_mov_i32(REG(B11_8
), cpu_sr_t
);
1502 * If (T == 1) R0 -> (Rn)
1505 * The above description doesn't work in a parallel context.
1506 * Since we currently support no smp boards, this implies user-mode.
1507 * But we can still support the official mechanism while user-mode
1508 * is single-threaded. */
1511 TCGLabel
*fail
= gen_new_label();
1512 TCGLabel
*done
= gen_new_label();
1514 if ((tb_cflags(ctx
->base
.tb
) & CF_PARALLEL
)) {
1517 tcg_gen_brcond_i32(TCG_COND_NE
, REG(B11_8
),
1518 cpu_lock_addr
, fail
);
1519 tmp
= tcg_temp_new();
1520 tcg_gen_atomic_cmpxchg_i32(tmp
, REG(B11_8
), cpu_lock_value
,
1521 REG(0), ctx
->memidx
,
1522 MO_TEUL
| MO_ALIGN
);
1523 tcg_gen_setcond_i32(TCG_COND_EQ
, cpu_sr_t
, tmp
, cpu_lock_value
);
1525 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_lock_addr
, -1, fail
);
1526 tcg_gen_qemu_st_i32(REG(0), REG(B11_8
), ctx
->memidx
,
1527 MO_TEUL
| MO_ALIGN
);
1528 tcg_gen_movi_i32(cpu_sr_t
, 1);
1532 gen_set_label(fail
);
1533 tcg_gen_movi_i32(cpu_sr_t
, 0);
1535 gen_set_label(done
);
1536 tcg_gen_movi_i32(cpu_lock_addr
, -1);
1543 * When interrupt/exception
1544 * occurred 0 -> LDST
1546 * In a parallel context, we must also save the loaded value
1547 * for use with the cmpxchg that we'll use with movco.l. */
1549 if ((tb_cflags(ctx
->base
.tb
) & CF_PARALLEL
)) {
1550 TCGv tmp
= tcg_temp_new();
1551 tcg_gen_mov_i32(tmp
, REG(B11_8
));
1552 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8
), ctx
->memidx
,
1553 MO_TESL
| MO_ALIGN
);
1554 tcg_gen_mov_i32(cpu_lock_value
, REG(0));
1555 tcg_gen_mov_i32(cpu_lock_addr
, tmp
);
1557 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8
), ctx
->memidx
,
1558 MO_TESL
| MO_ALIGN
);
1559 tcg_gen_movi_i32(cpu_lock_addr
, 0);
1562 case 0x0093: /* ocbi @Rn */
1564 gen_helper_ocbi(cpu_env
, REG(B11_8
));
1567 case 0x00a3: /* ocbp @Rn */
1568 case 0x00b3: /* ocbwb @Rn */
1569 /* These instructions are supposed to do nothing in case of
1570 a cache miss. Given that we only partially emulate caches
1571 it is safe to simply ignore them. */
1573 case 0x0083: /* pref @Rn */
1575 case 0x00d3: /* prefi @Rn */
1578 case 0x00e3: /* icbi @Rn */
1581 case 0x00ab: /* synco */
1583 tcg_gen_mb(TCG_MO_ALL
| TCG_BAR_SC
);
1585 case 0x4024: /* rotcl Rn */
1587 TCGv tmp
= tcg_temp_new();
1588 tcg_gen_mov_i32(tmp
, cpu_sr_t
);
1589 tcg_gen_shri_i32(cpu_sr_t
, REG(B11_8
), 31);
1590 tcg_gen_shli_i32(REG(B11_8
), REG(B11_8
), 1);
1591 tcg_gen_or_i32(REG(B11_8
), REG(B11_8
), tmp
);
1594 case 0x4025: /* rotcr Rn */
1596 TCGv tmp
= tcg_temp_new();
1597 tcg_gen_shli_i32(tmp
, cpu_sr_t
, 31);
1598 tcg_gen_andi_i32(cpu_sr_t
, REG(B11_8
), 1);
1599 tcg_gen_shri_i32(REG(B11_8
), REG(B11_8
), 1);
1600 tcg_gen_or_i32(REG(B11_8
), REG(B11_8
), tmp
);
1603 case 0x4004: /* rotl Rn */
1604 tcg_gen_rotli_i32(REG(B11_8
), REG(B11_8
), 1);
1605 tcg_gen_andi_i32(cpu_sr_t
, REG(B11_8
), 0);
1607 case 0x4005: /* rotr Rn */
1608 tcg_gen_andi_i32(cpu_sr_t
, REG(B11_8
), 0);
1609 tcg_gen_rotri_i32(REG(B11_8
), REG(B11_8
), 1);
1611 case 0x4000: /* shll Rn */
1612 case 0x4020: /* shal Rn */
1613 tcg_gen_shri_i32(cpu_sr_t
, REG(B11_8
), 31);
1614 tcg_gen_shli_i32(REG(B11_8
), REG(B11_8
), 1);
1616 case 0x4021: /* shar Rn */
1617 tcg_gen_andi_i32(cpu_sr_t
, REG(B11_8
), 1);
1618 tcg_gen_sari_i32(REG(B11_8
), REG(B11_8
), 1);
1620 case 0x4001: /* shlr Rn */
1621 tcg_gen_andi_i32(cpu_sr_t
, REG(B11_8
), 1);
1622 tcg_gen_shri_i32(REG(B11_8
), REG(B11_8
), 1);
1624 case 0x4008: /* shll2 Rn */
1625 tcg_gen_shli_i32(REG(B11_8
), REG(B11_8
), 2);
1627 case 0x4018: /* shll8 Rn */
1628 tcg_gen_shli_i32(REG(B11_8
), REG(B11_8
), 8);
1630 case 0x4028: /* shll16 Rn */
1631 tcg_gen_shli_i32(REG(B11_8
), REG(B11_8
), 16);
1633 case 0x4009: /* shlr2 Rn */
1634 tcg_gen_shri_i32(REG(B11_8
), REG(B11_8
), 2);
1636 case 0x4019: /* shlr8 Rn */
1637 tcg_gen_shri_i32(REG(B11_8
), REG(B11_8
), 8);
1639 case 0x4029: /* shlr16 Rn */
1640 tcg_gen_shri_i32(REG(B11_8
), REG(B11_8
), 16);
1642 case 0x401b: /* tas.b @Rn */
1643 tcg_gen_atomic_fetch_or_i32(cpu_sr_t
, REG(B11_8
),
1644 tcg_constant_i32(0x80), ctx
->memidx
, MO_UB
);
1645 tcg_gen_setcondi_i32(TCG_COND_EQ
, cpu_sr_t
, cpu_sr_t
, 0);
1647 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
1649 tcg_gen_mov_i32(FREG(B11_8
), cpu_fpul
);
1651 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
1653 tcg_gen_mov_i32(cpu_fpul
, FREG(B11_8
));
1655 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
1657 if (ctx
->tbflags
& FPSCR_PR
) {
1659 if (ctx
->opcode
& 0x0100) {
1662 fp
= tcg_temp_new_i64();
1663 gen_helper_float_DT(fp
, cpu_env
, cpu_fpul
);
1664 gen_store_fpr64(ctx
, fp
, B11_8
);
1667 gen_helper_float_FT(FREG(B11_8
), cpu_env
, cpu_fpul
);
1670 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1672 if (ctx
->tbflags
& FPSCR_PR
) {
1674 if (ctx
->opcode
& 0x0100) {
1677 fp
= tcg_temp_new_i64();
1678 gen_load_fpr64(ctx
, fp
, B11_8
);
1679 gen_helper_ftrc_DT(cpu_fpul
, cpu_env
, fp
);
1682 gen_helper_ftrc_FT(cpu_fpul
, cpu_env
, FREG(B11_8
));
1685 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */
1687 tcg_gen_xori_i32(FREG(B11_8
), FREG(B11_8
), 0x80000000);
1689 case 0xf05d: /* fabs FRn/DRn - FPCSR: Nothing */
1691 tcg_gen_andi_i32(FREG(B11_8
), FREG(B11_8
), 0x7fffffff);
1693 case 0xf06d: /* fsqrt FRn */
1695 if (ctx
->tbflags
& FPSCR_PR
) {
1696 if (ctx
->opcode
& 0x0100) {
1699 TCGv_i64 fp
= tcg_temp_new_i64();
1700 gen_load_fpr64(ctx
, fp
, B11_8
);
1701 gen_helper_fsqrt_DT(fp
, cpu_env
, fp
);
1702 gen_store_fpr64(ctx
, fp
, B11_8
);
1704 gen_helper_fsqrt_FT(FREG(B11_8
), cpu_env
, FREG(B11_8
));
1707 case 0xf07d: /* fsrra FRn */
1710 gen_helper_fsrra_FT(FREG(B11_8
), cpu_env
, FREG(B11_8
));
1712 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
1715 tcg_gen_movi_i32(FREG(B11_8
), 0);
1717 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
1720 tcg_gen_movi_i32(FREG(B11_8
), 0x3f800000);
1722 case 0xf0ad: /* fcnvsd FPUL,DRn */
1725 TCGv_i64 fp
= tcg_temp_new_i64();
1726 gen_helper_fcnvsd_FT_DT(fp
, cpu_env
, cpu_fpul
);
1727 gen_store_fpr64(ctx
, fp
, B11_8
);
1730 case 0xf0bd: /* fcnvds DRn,FPUL */
1733 TCGv_i64 fp
= tcg_temp_new_i64();
1734 gen_load_fpr64(ctx
, fp
, B11_8
);
1735 gen_helper_fcnvds_DT_FT(cpu_fpul
, cpu_env
, fp
);
1738 case 0xf0ed: /* fipr FVm,FVn */
1742 TCGv m
= tcg_constant_i32((ctx
->opcode
>> 8) & 3);
1743 TCGv n
= tcg_constant_i32((ctx
->opcode
>> 10) & 3);
1744 gen_helper_fipr(cpu_env
, m
, n
);
1748 case 0xf0fd: /* ftrv XMTRX,FVn */
1752 if ((ctx
->opcode
& 0x0300) != 0x0100) {
1755 TCGv n
= tcg_constant_i32((ctx
->opcode
>> 10) & 3);
1756 gen_helper_ftrv(cpu_env
, n
);
1762 fprintf(stderr
, "unknown instruction 0x%04x at pc 0x%08x\n",
1763 ctx
->opcode
, ctx
->base
.pc_next
);
1767 if (ctx
->envflags
& TB_FLAG_DELAY_SLOT_MASK
) {
1769 gen_save_cpu_state(ctx
, true);
1770 gen_helper_raise_slot_illegal_instruction(cpu_env
);
1772 gen_save_cpu_state(ctx
, true);
1773 gen_helper_raise_illegal_instruction(cpu_env
);
1775 ctx
->base
.is_jmp
= DISAS_NORETURN
;
1779 gen_save_cpu_state(ctx
, true);
1780 if (ctx
->envflags
& TB_FLAG_DELAY_SLOT_MASK
) {
1781 gen_helper_raise_slot_fpu_disable(cpu_env
);
1783 gen_helper_raise_fpu_disable(cpu_env
);
1785 ctx
->base
.is_jmp
= DISAS_NORETURN
;
1789 static void decode_opc(DisasContext
* ctx
)
1791 uint32_t old_flags
= ctx
->envflags
;
1795 if (old_flags
& TB_FLAG_DELAY_SLOT_MASK
) {
1796 /* go out of the delay slot */
1797 ctx
->envflags
&= ~TB_FLAG_DELAY_SLOT_MASK
;
1799 /* When in an exclusive region, we must continue to the end
1800 for conditional branches. */
1801 if (ctx
->tbflags
& TB_FLAG_GUSA_EXCLUSIVE
1802 && old_flags
& TB_FLAG_DELAY_SLOT_COND
) {
1803 gen_delayed_conditional_jump(ctx
);
1806 /* Otherwise this is probably an invalid gUSA region.
1807 Drop the GUSA bits so the next TB doesn't see them. */
1808 ctx
->envflags
&= ~TB_FLAG_GUSA_MASK
;
1810 tcg_gen_movi_i32(cpu_flags
, ctx
->envflags
);
1811 if (old_flags
& TB_FLAG_DELAY_SLOT_COND
) {
1812 gen_delayed_conditional_jump(ctx
);
1819 #ifdef CONFIG_USER_ONLY
1820 /* For uniprocessors, SH4 uses optimistic restartable atomic sequences.
1821 Upon an interrupt, a real kernel would simply notice magic values in
1822 the registers and reset the PC to the start of the sequence.
1824 For QEMU, we cannot do this in quite the same way. Instead, we notice
1825 the normal start of such a sequence (mov #-x,r15). While we can handle
1826 any sequence via cpu_exec_step_atomic, we can recognize the "normal"
1827 sequences and transform them into atomic operations as seen by the host.
1829 static void decode_gusa(DisasContext
*ctx
, CPUSH4State
*env
)
1832 int ld_adr
, ld_dst
, ld_mop
;
1833 int op_dst
, op_src
, op_opc
;
1834 int mv_src
, mt_dst
, st_src
, st_mop
;
1836 uint32_t pc
= ctx
->base
.pc_next
;
1837 uint32_t pc_end
= ctx
->base
.tb
->cs_base
;
1838 int max_insns
= (pc_end
- pc
) / 2;
1841 /* The state machine below will consume only a few insns.
1842 If there are more than that in a region, fail now. */
1843 if (max_insns
> ARRAY_SIZE(insns
)) {
1847 /* Read all of the insns for the region. */
1848 for (i
= 0; i
< max_insns
; ++i
) {
1849 insns
[i
] = translator_lduw(env
, &ctx
->base
, pc
+ i
* 2);
1852 ld_adr
= ld_dst
= ld_mop
= -1;
1854 op_dst
= op_src
= op_opc
= -1;
1856 st_src
= st_mop
= -1;
1861 do { if (i >= max_insns) goto fail; ctx->opcode = insns[i++]; } while (0)
1864 * Expect a load to begin the region.
1867 switch (ctx
->opcode
& 0xf00f) {
1868 case 0x6000: /* mov.b @Rm,Rn */
1871 case 0x6001: /* mov.w @Rm,Rn */
1874 case 0x6002: /* mov.l @Rm,Rn */
1882 if (ld_adr
== ld_dst
) {
1885 /* Unless we see a mov, any two-operand operation must use ld_dst. */
1889 * Expect an optional register move.
1892 switch (ctx
->opcode
& 0xf00f) {
1893 case 0x6003: /* mov Rm,Rn */
1895 * Here we want to recognize ld_dst being saved for later consumption,
1896 * or for another input register being copied so that ld_dst need not
1897 * be clobbered during the operation.
1901 if (op_dst
== ld_dst
) {
1902 /* Overwriting the load output. */
1905 if (mv_src
!= ld_dst
) {
1906 /* Copying a new input; constrain op_src to match the load. */
1912 /* Put back and re-examine as operation. */
1917 * Expect the operation.
1920 switch (ctx
->opcode
& 0xf00f) {
1921 case 0x300c: /* add Rm,Rn */
1922 op_opc
= INDEX_op_add_i32
;
1924 case 0x2009: /* and Rm,Rn */
1925 op_opc
= INDEX_op_and_i32
;
1927 case 0x200a: /* xor Rm,Rn */
1928 op_opc
= INDEX_op_xor_i32
;
1930 case 0x200b: /* or Rm,Rn */
1931 op_opc
= INDEX_op_or_i32
;
1933 /* The operation register should be as expected, and the
1934 other input cannot depend on the load. */
1935 if (op_dst
!= B11_8
) {
1939 /* Unconstrainted input. */
1941 } else if (op_src
== B7_4
) {
1942 /* Constrained input matched load. All operations are
1943 commutative; "swap" them by "moving" the load output
1944 to the (implicit) first argument and the move source
1945 to the (explicit) second argument. */
1950 op_arg
= REG(op_src
);
1953 case 0x6007: /* not Rm,Rn */
1954 if (ld_dst
!= B7_4
|| mv_src
>= 0) {
1958 op_opc
= INDEX_op_xor_i32
;
1959 op_arg
= tcg_constant_i32(-1);
1962 case 0x7000 ... 0x700f: /* add #imm,Rn */
1963 if (op_dst
!= B11_8
|| mv_src
>= 0) {
1966 op_opc
= INDEX_op_add_i32
;
1967 op_arg
= tcg_constant_i32(B7_0s
);
1970 case 0x3000: /* cmp/eq Rm,Rn */
1971 /* Looking for the middle of a compare-and-swap sequence,
1972 beginning with the compare. Operands can be either order,
1973 but with only one overlapping the load. */
1974 if ((ld_dst
== B11_8
) + (ld_dst
== B7_4
) != 1 || mv_src
>= 0) {
1977 op_opc
= INDEX_op_setcond_i32
; /* placeholder */
1978 op_src
= (ld_dst
== B11_8
? B7_4
: B11_8
);
1979 op_arg
= REG(op_src
);
1982 switch (ctx
->opcode
& 0xff00) {
1983 case 0x8b00: /* bf label */
1984 case 0x8f00: /* bf/s label */
1985 if (pc
+ (i
+ 1 + B7_0s
) * 2 != pc_end
) {
1988 if ((ctx
->opcode
& 0xff00) == 0x8b00) { /* bf label */
1991 /* We're looking to unconditionally modify Rn with the
1992 result of the comparison, within the delay slot of
1993 the branch. This is used by older gcc. */
1995 if ((ctx
->opcode
& 0xf0ff) == 0x0029) { /* movt Rn */
2007 case 0x2008: /* tst Rm,Rn */
2008 /* Looking for a compare-and-swap against zero. */
2009 if (ld_dst
!= B11_8
|| ld_dst
!= B7_4
|| mv_src
>= 0) {
2012 op_opc
= INDEX_op_setcond_i32
;
2013 op_arg
= tcg_constant_i32(0);
2016 if ((ctx
->opcode
& 0xff00) != 0x8900 /* bt label */
2017 || pc
+ (i
+ 1 + B7_0s
) * 2 != pc_end
) {
2023 /* Put back and re-examine as store. */
2030 /* The store must be the last insn. */
2031 if (i
!= max_insns
- 1) {
2035 switch (ctx
->opcode
& 0xf00f) {
2036 case 0x2000: /* mov.b Rm,@Rn */
2039 case 0x2001: /* mov.w Rm,@Rn */
2042 case 0x2002: /* mov.l Rm,@Rn */
2048 /* The store must match the load. */
2049 if (ld_adr
!= B11_8
|| st_mop
!= (ld_mop
& MO_SIZE
)) {
2057 * Emit the operation.
2061 /* No operation found. Look for exchange pattern. */
2062 if (st_src
== ld_dst
|| mv_src
>= 0) {
2065 tcg_gen_atomic_xchg_i32(REG(ld_dst
), REG(ld_adr
), REG(st_src
),
2066 ctx
->memidx
, ld_mop
);
2069 case INDEX_op_add_i32
:
2070 if (op_dst
!= st_src
) {
2073 if (op_dst
== ld_dst
&& st_mop
== MO_UL
) {
2074 tcg_gen_atomic_add_fetch_i32(REG(ld_dst
), REG(ld_adr
),
2075 op_arg
, ctx
->memidx
, ld_mop
);
2077 tcg_gen_atomic_fetch_add_i32(REG(ld_dst
), REG(ld_adr
),
2078 op_arg
, ctx
->memidx
, ld_mop
);
2079 if (op_dst
!= ld_dst
) {
2080 /* Note that mop sizes < 4 cannot use add_fetch
2081 because it won't carry into the higher bits. */
2082 tcg_gen_add_i32(REG(op_dst
), REG(ld_dst
), op_arg
);
2087 case INDEX_op_and_i32
:
2088 if (op_dst
!= st_src
) {
2091 if (op_dst
== ld_dst
) {
2092 tcg_gen_atomic_and_fetch_i32(REG(ld_dst
), REG(ld_adr
),
2093 op_arg
, ctx
->memidx
, ld_mop
);
2095 tcg_gen_atomic_fetch_and_i32(REG(ld_dst
), REG(ld_adr
),
2096 op_arg
, ctx
->memidx
, ld_mop
);
2097 tcg_gen_and_i32(REG(op_dst
), REG(ld_dst
), op_arg
);
2101 case INDEX_op_or_i32
:
2102 if (op_dst
!= st_src
) {
2105 if (op_dst
== ld_dst
) {
2106 tcg_gen_atomic_or_fetch_i32(REG(ld_dst
), REG(ld_adr
),
2107 op_arg
, ctx
->memidx
, ld_mop
);
2109 tcg_gen_atomic_fetch_or_i32(REG(ld_dst
), REG(ld_adr
),
2110 op_arg
, ctx
->memidx
, ld_mop
);
2111 tcg_gen_or_i32(REG(op_dst
), REG(ld_dst
), op_arg
);
2115 case INDEX_op_xor_i32
:
2116 if (op_dst
!= st_src
) {
2119 if (op_dst
== ld_dst
) {
2120 tcg_gen_atomic_xor_fetch_i32(REG(ld_dst
), REG(ld_adr
),
2121 op_arg
, ctx
->memidx
, ld_mop
);
2123 tcg_gen_atomic_fetch_xor_i32(REG(ld_dst
), REG(ld_adr
),
2124 op_arg
, ctx
->memidx
, ld_mop
);
2125 tcg_gen_xor_i32(REG(op_dst
), REG(ld_dst
), op_arg
);
2129 case INDEX_op_setcond_i32
:
2130 if (st_src
== ld_dst
) {
2133 tcg_gen_atomic_cmpxchg_i32(REG(ld_dst
), REG(ld_adr
), op_arg
,
2134 REG(st_src
), ctx
->memidx
, ld_mop
);
2135 tcg_gen_setcond_i32(TCG_COND_EQ
, cpu_sr_t
, REG(ld_dst
), op_arg
);
2137 tcg_gen_mov_i32(REG(mt_dst
), cpu_sr_t
);
2142 g_assert_not_reached();
2145 /* The entire region has been translated. */
2146 ctx
->envflags
&= ~TB_FLAG_GUSA_MASK
;
2150 qemu_log_mask(LOG_UNIMP
, "Unrecognized gUSA sequence %08x-%08x\n",
2153 /* Restart with the EXCLUSIVE bit set, within a TB run via
2154 cpu_exec_step_atomic holding the exclusive lock. */
2155 ctx
->envflags
|= TB_FLAG_GUSA_EXCLUSIVE
;
2156 gen_save_cpu_state(ctx
, false);
2157 gen_helper_exclusive(cpu_env
);
2158 ctx
->base
.is_jmp
= DISAS_NORETURN
;
2160 /* We're not executing an instruction, but we must report one for the
2161 purposes of accounting within the TB. We might as well report the
2162 entire region consumed via ctx->base.pc_next so that it's immediately
2163 available in the disassembly dump. */
2166 ctx
->base
.pc_next
= pc_end
;
2167 ctx
->base
.num_insns
+= max_insns
- 1;
2170 * Emit insn_start to cover each of the insns in the region.
2171 * This matches an assert in tcg.c making sure that we have
2172 * tb->icount * insn_start.
2174 for (i
= 1; i
< max_insns
; ++i
) {
2175 tcg_gen_insn_start(pc
+ i
* 2, ctx
->envflags
);
2180 static void sh4_tr_init_disas_context(DisasContextBase
*dcbase
, CPUState
*cs
)
2182 DisasContext
*ctx
= container_of(dcbase
, DisasContext
, base
);
2183 CPUSH4State
*env
= cs
->env_ptr
;
2187 ctx
->tbflags
= tbflags
= ctx
->base
.tb
->flags
;
2188 ctx
->envflags
= tbflags
& TB_FLAG_ENVFLAGS_MASK
;
2189 ctx
->memidx
= (tbflags
& (1u << SR_MD
)) == 0 ? 1 : 0;
2190 /* We don't know if the delayed pc came from a dynamic or static branch,
2191 so assume it is a dynamic branch. */
2192 ctx
->delayed_pc
= -1; /* use delayed pc from env pointer */
2193 ctx
->features
= env
->features
;
2194 ctx
->has_movcal
= (tbflags
& TB_FLAG_PENDING_MOVCA
);
2195 ctx
->gbank
= ((tbflags
& (1 << SR_MD
)) &&
2196 (tbflags
& (1 << SR_RB
))) * 0x10;
2197 ctx
->fbank
= tbflags
& FPSCR_FR
? 0x10 : 0;
2199 #ifdef CONFIG_USER_ONLY
2200 if (tbflags
& TB_FLAG_GUSA_MASK
) {
2201 /* In gUSA exclusive region. */
2202 uint32_t pc
= ctx
->base
.pc_next
;
2203 uint32_t pc_end
= ctx
->base
.tb
->cs_base
;
2204 int backup
= sextract32(ctx
->tbflags
, TB_FLAG_GUSA_SHIFT
, 8);
2205 int max_insns
= (pc_end
- pc
) / 2;
2207 if (pc
!= pc_end
+ backup
|| max_insns
< 2) {
2208 /* This is a malformed gUSA region. Don't do anything special,
2209 since the interpreter is likely to get confused. */
2210 ctx
->envflags
&= ~TB_FLAG_GUSA_MASK
;
2211 } else if (tbflags
& TB_FLAG_GUSA_EXCLUSIVE
) {
2212 /* Regardless of single-stepping or the end of the page,
2213 we must complete execution of the gUSA region while
2214 holding the exclusive lock. */
2215 ctx
->base
.max_insns
= max_insns
;
2221 /* Since the ISA is fixed-width, we can bound by the number
2222 of instructions remaining on the page. */
2223 bound
= -(ctx
->base
.pc_next
| TARGET_PAGE_MASK
) / 2;
2224 ctx
->base
.max_insns
= MIN(ctx
->base
.max_insns
, bound
);
2227 static void sh4_tr_tb_start(DisasContextBase
*dcbase
, CPUState
*cs
)
2231 static void sh4_tr_insn_start(DisasContextBase
*dcbase
, CPUState
*cs
)
2233 DisasContext
*ctx
= container_of(dcbase
, DisasContext
, base
);
2235 tcg_gen_insn_start(ctx
->base
.pc_next
, ctx
->envflags
);
2238 static void sh4_tr_translate_insn(DisasContextBase
*dcbase
, CPUState
*cs
)
2240 CPUSH4State
*env
= cs
->env_ptr
;
2241 DisasContext
*ctx
= container_of(dcbase
, DisasContext
, base
);
2243 #ifdef CONFIG_USER_ONLY
2244 if (unlikely(ctx
->envflags
& TB_FLAG_GUSA_MASK
)
2245 && !(ctx
->envflags
& TB_FLAG_GUSA_EXCLUSIVE
)) {
2246 /* We're in an gUSA region, and we have not already fallen
2247 back on using an exclusive region. Attempt to parse the
2248 region into a single supported atomic operation. Failure
2249 is handled within the parser by raising an exception to
2250 retry using an exclusive region. */
2251 decode_gusa(ctx
, env
);
2256 ctx
->opcode
= translator_lduw(env
, &ctx
->base
, ctx
->base
.pc_next
);
2258 ctx
->base
.pc_next
+= 2;
2261 static void sh4_tr_tb_stop(DisasContextBase
*dcbase
, CPUState
*cs
)
2263 DisasContext
*ctx
= container_of(dcbase
, DisasContext
, base
);
2265 if (ctx
->tbflags
& TB_FLAG_GUSA_EXCLUSIVE
) {
2266 /* Ending the region of exclusivity. Clear the bits. */
2267 ctx
->envflags
&= ~TB_FLAG_GUSA_MASK
;
2270 switch (ctx
->base
.is_jmp
) {
2272 gen_save_cpu_state(ctx
, true);
2273 tcg_gen_exit_tb(NULL
, 0);
2276 case DISAS_TOO_MANY
:
2277 gen_save_cpu_state(ctx
, false);
2278 gen_goto_tb(ctx
, 0, ctx
->base
.pc_next
);
2280 case DISAS_NORETURN
:
2283 g_assert_not_reached();
2287 static void sh4_tr_disas_log(const DisasContextBase
*dcbase
,
2288 CPUState
*cs
, FILE *logfile
)
2290 fprintf(logfile
, "IN: %s\n", lookup_symbol(dcbase
->pc_first
));
2291 target_disas(logfile
, cs
, dcbase
->pc_first
, dcbase
->tb
->size
);
2294 static const TranslatorOps sh4_tr_ops
= {
2295 .init_disas_context
= sh4_tr_init_disas_context
,
2296 .tb_start
= sh4_tr_tb_start
,
2297 .insn_start
= sh4_tr_insn_start
,
2298 .translate_insn
= sh4_tr_translate_insn
,
2299 .tb_stop
= sh4_tr_tb_stop
,
2300 .disas_log
= sh4_tr_disas_log
,
2303 void gen_intermediate_code(CPUState
*cs
, TranslationBlock
*tb
, int *max_insns
,
2304 target_ulong pc
, void *host_pc
)
2308 translator_loop(cs
, tb
, max_insns
, pc
, host_pc
, &sh4_tr_ops
, &ctx
.base
);