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/>.
22 #include "qemu/osdep.h"
24 #include "disas/disas.h"
25 #include "exec/exec-all.h"
26 #include "tcg/tcg-op.h"
27 #include "exec/cpu_ldst.h"
28 #include "exec/helper-proto.h"
29 #include "exec/helper-gen.h"
30 #include "exec/translator.h"
32 #include "qemu/qemu-print.h"
35 typedef struct DisasContext
{
36 DisasContextBase base
;
38 uint32_t tbflags
; /* should stay unmodified during the TB translation */
39 uint32_t envflags
; /* should stay in sync with env->flags using TCG ops */
51 #if defined(CONFIG_USER_ONLY)
52 #define IS_USER(ctx) 1
53 #define UNALIGN(C) (ctx->tbflags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN)
55 #define IS_USER(ctx) (!(ctx->tbflags & (1u << SR_MD)))
59 /* Target-specific values for ctx->base.is_jmp. */
60 /* We want to exit back to the cpu loop for some reason.
61 Usually this is to recognize interrupts immediately. */
62 #define DISAS_STOP DISAS_TARGET_0
64 /* global register indexes */
65 static TCGv cpu_gregs
[32];
66 static TCGv cpu_sr
, cpu_sr_m
, cpu_sr_q
, cpu_sr_t
;
67 static TCGv cpu_pc
, cpu_ssr
, cpu_spc
, cpu_gbr
;
68 static TCGv cpu_vbr
, cpu_sgr
, cpu_dbr
, cpu_mach
, cpu_macl
;
69 static TCGv cpu_pr
, cpu_fpscr
, cpu_fpul
;
70 static TCGv cpu_lock_addr
, cpu_lock_value
;
71 static TCGv cpu_fregs
[32];
73 /* internal register indexes */
74 static TCGv cpu_flags
, cpu_delayed_pc
, cpu_delayed_cond
;
76 #include "exec/gen-icount.h"
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_printf("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_printf("in delay slot (delayed_pc=0x%08x)\n",
181 } else if (env
->flags
& TB_FLAG_DELAY_SLOT_COND
) {
182 qemu_printf("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
);
199 tcg_temp_free_i32(t0
);
202 static void gen_write_sr(TCGv src
)
204 tcg_gen_andi_i32(cpu_sr
, src
,
205 ~((1u << SR_Q
) | (1u << SR_M
) | (1u << SR_T
)));
206 tcg_gen_extract_i32(cpu_sr_q
, src
, SR_Q
, 1);
207 tcg_gen_extract_i32(cpu_sr_m
, src
, SR_M
, 1);
208 tcg_gen_extract_i32(cpu_sr_t
, src
, SR_T
, 1);
211 static inline void gen_save_cpu_state(DisasContext
*ctx
, bool save_pc
)
214 tcg_gen_movi_i32(cpu_pc
, ctx
->base
.pc_next
);
216 if (ctx
->delayed_pc
!= (uint32_t) -1) {
217 tcg_gen_movi_i32(cpu_delayed_pc
, ctx
->delayed_pc
);
219 if ((ctx
->tbflags
& TB_FLAG_ENVFLAGS_MASK
) != ctx
->envflags
) {
220 tcg_gen_movi_i32(cpu_flags
, ctx
->envflags
);
224 static inline bool use_exit_tb(DisasContext
*ctx
)
226 return (ctx
->tbflags
& TB_FLAG_GUSA_EXCLUSIVE
) != 0;
229 static bool use_goto_tb(DisasContext
*ctx
, target_ulong dest
)
231 if (use_exit_tb(ctx
)) {
234 return translator_use_goto_tb(&ctx
->base
, dest
);
237 static void gen_goto_tb(DisasContext
*ctx
, int n
, target_ulong dest
)
239 if (use_goto_tb(ctx
, dest
)) {
241 tcg_gen_movi_i32(cpu_pc
, dest
);
242 tcg_gen_exit_tb(ctx
->base
.tb
, n
);
244 tcg_gen_movi_i32(cpu_pc
, dest
);
245 if (use_exit_tb(ctx
)) {
246 tcg_gen_exit_tb(NULL
, 0);
248 tcg_gen_lookup_and_goto_ptr();
251 ctx
->base
.is_jmp
= DISAS_NORETURN
;
254 static void gen_jump(DisasContext
* ctx
)
256 if (ctx
->delayed_pc
== -1) {
257 /* Target is not statically known, it comes necessarily from a
258 delayed jump as immediate jump are conditinal jumps */
259 tcg_gen_mov_i32(cpu_pc
, cpu_delayed_pc
);
260 tcg_gen_discard_i32(cpu_delayed_pc
);
261 if (use_exit_tb(ctx
)) {
262 tcg_gen_exit_tb(NULL
, 0);
264 tcg_gen_lookup_and_goto_ptr();
266 ctx
->base
.is_jmp
= DISAS_NORETURN
;
268 gen_goto_tb(ctx
, 0, ctx
->delayed_pc
);
272 /* Immediate conditional jump (bt or bf) */
273 static void gen_conditional_jump(DisasContext
*ctx
, target_ulong dest
,
276 TCGLabel
*l1
= gen_new_label();
277 TCGCond cond_not_taken
= jump_if_true
? TCG_COND_EQ
: TCG_COND_NE
;
279 if (ctx
->tbflags
& TB_FLAG_GUSA_EXCLUSIVE
) {
280 /* When in an exclusive region, we must continue to the end.
281 Therefore, exit the region on a taken branch, but otherwise
282 fall through to the next instruction. */
283 tcg_gen_brcondi_i32(cond_not_taken
, cpu_sr_t
, 0, l1
);
284 tcg_gen_movi_i32(cpu_flags
, ctx
->envflags
& ~TB_FLAG_GUSA_MASK
);
285 /* Note that this won't actually use a goto_tb opcode because we
286 disallow it in use_goto_tb, but it handles exit + singlestep. */
287 gen_goto_tb(ctx
, 0, dest
);
289 ctx
->base
.is_jmp
= DISAS_NEXT
;
293 gen_save_cpu_state(ctx
, false);
294 tcg_gen_brcondi_i32(cond_not_taken
, cpu_sr_t
, 0, l1
);
295 gen_goto_tb(ctx
, 0, dest
);
297 gen_goto_tb(ctx
, 1, ctx
->base
.pc_next
+ 2);
298 ctx
->base
.is_jmp
= DISAS_NORETURN
;
301 /* Delayed conditional jump (bt or bf) */
302 static void gen_delayed_conditional_jump(DisasContext
* ctx
)
304 TCGLabel
*l1
= gen_new_label();
305 TCGv ds
= tcg_temp_new();
307 tcg_gen_mov_i32(ds
, cpu_delayed_cond
);
308 tcg_gen_discard_i32(cpu_delayed_cond
);
310 if (ctx
->tbflags
& TB_FLAG_GUSA_EXCLUSIVE
) {
311 /* When in an exclusive region, we must continue to the end.
312 Therefore, exit the region on a taken branch, but otherwise
313 fall through to the next instruction. */
314 tcg_gen_brcondi_i32(TCG_COND_EQ
, ds
, 0, l1
);
316 /* Leave the gUSA region. */
317 tcg_gen_movi_i32(cpu_flags
, ctx
->envflags
& ~TB_FLAG_GUSA_MASK
);
321 ctx
->base
.is_jmp
= DISAS_NEXT
;
325 tcg_gen_brcondi_i32(TCG_COND_NE
, ds
, 0, l1
);
326 gen_goto_tb(ctx
, 1, ctx
->base
.pc_next
+ 2);
331 static inline void gen_load_fpr64(DisasContext
*ctx
, TCGv_i64 t
, int reg
)
333 /* We have already signaled illegal instruction for odd Dr. */
334 tcg_debug_assert((reg
& 1) == 0);
336 tcg_gen_concat_i32_i64(t
, cpu_fregs
[reg
+ 1], cpu_fregs
[reg
]);
339 static inline void gen_store_fpr64(DisasContext
*ctx
, TCGv_i64 t
, int reg
)
341 /* We have already signaled illegal instruction for odd Dr. */
342 tcg_debug_assert((reg
& 1) == 0);
344 tcg_gen_extr_i64_i32(cpu_fregs
[reg
+ 1], cpu_fregs
[reg
], t
);
347 #define B3_0 (ctx->opcode & 0xf)
348 #define B6_4 ((ctx->opcode >> 4) & 0x7)
349 #define B7_4 ((ctx->opcode >> 4) & 0xf)
350 #define B7_0 (ctx->opcode & 0xff)
351 #define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
352 #define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
353 (ctx->opcode & 0xfff))
354 #define B11_8 ((ctx->opcode >> 8) & 0xf)
355 #define B15_12 ((ctx->opcode >> 12) & 0xf)
357 #define REG(x) cpu_gregs[(x) ^ ctx->gbank]
358 #define ALTREG(x) cpu_gregs[(x) ^ ctx->gbank ^ 0x10]
359 #define FREG(x) cpu_fregs[(x) ^ ctx->fbank]
361 #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
363 #define CHECK_NOT_DELAY_SLOT \
364 if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) { \
365 goto do_illegal_slot; \
368 #define CHECK_PRIVILEGED \
369 if (IS_USER(ctx)) { \
373 #define CHECK_FPU_ENABLED \
374 if (ctx->tbflags & (1u << SR_FD)) { \
375 goto do_fpu_disabled; \
378 #define CHECK_FPSCR_PR_0 \
379 if (ctx->tbflags & FPSCR_PR) { \
383 #define CHECK_FPSCR_PR_1 \
384 if (!(ctx->tbflags & FPSCR_PR)) { \
389 if (!(ctx->features & SH_FEATURE_SH4A)) { \
393 static void _decode_opc(DisasContext
* ctx
)
395 /* This code tries to make movcal emulation sufficiently
396 accurate for Linux purposes. This instruction writes
397 memory, and prior to that, always allocates a cache line.
398 It is used in two contexts:
399 - in memcpy, where data is copied in blocks, the first write
400 of to a block uses movca.l for performance.
401 - in arch/sh/mm/cache-sh4.c, movcal.l + ocbi combination is used
402 to flush the cache. Here, the data written by movcal.l is never
403 written to memory, and the data written is just bogus.
405 To simulate this, we simulate movcal.l, we store the value to memory,
406 but we also remember the previous content. If we see ocbi, we check
407 if movcal.l for that address was done previously. If so, the write should
408 not have hit the memory, so we restore the previous content.
409 When we see an instruction that is neither movca.l
410 nor ocbi, the previous content is discarded.
412 To optimize, we only try to flush stores when we're at the start of
413 TB, or if we already saw movca.l in this TB and did not flush stores
417 int opcode
= ctx
->opcode
& 0xf0ff;
418 if (opcode
!= 0x0093 /* ocbi */
419 && opcode
!= 0x00c3 /* movca.l */)
421 gen_helper_discard_movcal_backup(cpu_env
);
427 fprintf(stderr
, "Translating opcode 0x%04x\n", ctx
->opcode
);
430 switch (ctx
->opcode
) {
431 case 0x0019: /* div0u */
432 tcg_gen_movi_i32(cpu_sr_m
, 0);
433 tcg_gen_movi_i32(cpu_sr_q
, 0);
434 tcg_gen_movi_i32(cpu_sr_t
, 0);
436 case 0x000b: /* rts */
438 tcg_gen_mov_i32(cpu_delayed_pc
, cpu_pr
);
439 ctx
->envflags
|= TB_FLAG_DELAY_SLOT
;
440 ctx
->delayed_pc
= (uint32_t) - 1;
442 case 0x0028: /* clrmac */
443 tcg_gen_movi_i32(cpu_mach
, 0);
444 tcg_gen_movi_i32(cpu_macl
, 0);
446 case 0x0048: /* clrs */
447 tcg_gen_andi_i32(cpu_sr
, cpu_sr
, ~(1u << SR_S
));
449 case 0x0008: /* clrt */
450 tcg_gen_movi_i32(cpu_sr_t
, 0);
452 case 0x0038: /* ldtlb */
454 gen_helper_ldtlb(cpu_env
);
456 case 0x002b: /* rte */
459 gen_write_sr(cpu_ssr
);
460 tcg_gen_mov_i32(cpu_delayed_pc
, cpu_spc
);
461 ctx
->envflags
|= TB_FLAG_DELAY_SLOT_RTE
;
462 ctx
->delayed_pc
= (uint32_t) - 1;
463 ctx
->base
.is_jmp
= DISAS_STOP
;
465 case 0x0058: /* sets */
466 tcg_gen_ori_i32(cpu_sr
, cpu_sr
, (1u << SR_S
));
468 case 0x0018: /* sett */
469 tcg_gen_movi_i32(cpu_sr_t
, 1);
471 case 0xfbfd: /* frchg */
473 tcg_gen_xori_i32(cpu_fpscr
, cpu_fpscr
, FPSCR_FR
);
474 ctx
->base
.is_jmp
= DISAS_STOP
;
476 case 0xf3fd: /* fschg */
478 tcg_gen_xori_i32(cpu_fpscr
, cpu_fpscr
, FPSCR_SZ
);
479 ctx
->base
.is_jmp
= DISAS_STOP
;
481 case 0xf7fd: /* fpchg */
483 tcg_gen_xori_i32(cpu_fpscr
, cpu_fpscr
, FPSCR_PR
);
484 ctx
->base
.is_jmp
= DISAS_STOP
;
486 case 0x0009: /* nop */
488 case 0x001b: /* sleep */
490 tcg_gen_movi_i32(cpu_pc
, ctx
->base
.pc_next
+ 2);
491 gen_helper_sleep(cpu_env
);
495 switch (ctx
->opcode
& 0xf000) {
496 case 0x1000: /* mov.l Rm,@(disp,Rn) */
498 TCGv addr
= tcg_temp_new();
499 tcg_gen_addi_i32(addr
, REG(B11_8
), B3_0
* 4);
500 tcg_gen_qemu_st_i32(REG(B7_4
), addr
, ctx
->memidx
,
501 MO_TEUL
| UNALIGN(ctx
));
505 case 0x5000: /* mov.l @(disp,Rm),Rn */
507 TCGv addr
= tcg_temp_new();
508 tcg_gen_addi_i32(addr
, REG(B7_4
), B3_0
* 4);
509 tcg_gen_qemu_ld_i32(REG(B11_8
), addr
, ctx
->memidx
,
510 MO_TESL
| UNALIGN(ctx
));
514 case 0xe000: /* mov #imm,Rn */
515 #ifdef CONFIG_USER_ONLY
517 * Detect the start of a gUSA region (mov #-n, r15).
518 * If so, update envflags and end the TB. This will allow us
519 * to see the end of the region (stored in R0) in the next TB.
521 if (B11_8
== 15 && B7_0s
< 0 &&
522 (tb_cflags(ctx
->base
.tb
) & CF_PARALLEL
)) {
524 deposit32(ctx
->envflags
, TB_FLAG_GUSA_SHIFT
, 8, B7_0s
);
525 ctx
->base
.is_jmp
= DISAS_STOP
;
528 tcg_gen_movi_i32(REG(B11_8
), B7_0s
);
530 case 0x9000: /* mov.w @(disp,PC),Rn */
532 TCGv addr
= tcg_const_i32(ctx
->base
.pc_next
+ 4 + B7_0
* 2);
533 tcg_gen_qemu_ld_i32(REG(B11_8
), addr
, ctx
->memidx
, MO_TESW
);
537 case 0xd000: /* mov.l @(disp,PC),Rn */
539 TCGv addr
= tcg_const_i32((ctx
->base
.pc_next
+ 4 + B7_0
* 4) & ~3);
540 tcg_gen_qemu_ld_i32(REG(B11_8
), addr
, ctx
->memidx
, MO_TESL
);
544 case 0x7000: /* add #imm,Rn */
545 tcg_gen_addi_i32(REG(B11_8
), REG(B11_8
), B7_0s
);
547 case 0xa000: /* bra disp */
549 ctx
->delayed_pc
= ctx
->base
.pc_next
+ 4 + B11_0s
* 2;
550 ctx
->envflags
|= TB_FLAG_DELAY_SLOT
;
552 case 0xb000: /* bsr disp */
554 tcg_gen_movi_i32(cpu_pr
, ctx
->base
.pc_next
+ 4);
555 ctx
->delayed_pc
= ctx
->base
.pc_next
+ 4 + B11_0s
* 2;
556 ctx
->envflags
|= TB_FLAG_DELAY_SLOT
;
560 switch (ctx
->opcode
& 0xf00f) {
561 case 0x6003: /* mov Rm,Rn */
562 tcg_gen_mov_i32(REG(B11_8
), REG(B7_4
));
564 case 0x2000: /* mov.b Rm,@Rn */
565 tcg_gen_qemu_st_i32(REG(B7_4
), REG(B11_8
), ctx
->memidx
, MO_UB
);
567 case 0x2001: /* mov.w Rm,@Rn */
568 tcg_gen_qemu_st_i32(REG(B7_4
), REG(B11_8
), ctx
->memidx
,
569 MO_TEUW
| UNALIGN(ctx
));
571 case 0x2002: /* mov.l Rm,@Rn */
572 tcg_gen_qemu_st_i32(REG(B7_4
), REG(B11_8
), ctx
->memidx
,
573 MO_TEUL
| UNALIGN(ctx
));
575 case 0x6000: /* mov.b @Rm,Rn */
576 tcg_gen_qemu_ld_i32(REG(B11_8
), REG(B7_4
), ctx
->memidx
, MO_SB
);
578 case 0x6001: /* mov.w @Rm,Rn */
579 tcg_gen_qemu_ld_i32(REG(B11_8
), REG(B7_4
), ctx
->memidx
,
580 MO_TESW
| UNALIGN(ctx
));
582 case 0x6002: /* mov.l @Rm,Rn */
583 tcg_gen_qemu_ld_i32(REG(B11_8
), REG(B7_4
), ctx
->memidx
,
584 MO_TESL
| UNALIGN(ctx
));
586 case 0x2004: /* mov.b Rm,@-Rn */
588 TCGv addr
= tcg_temp_new();
589 tcg_gen_subi_i32(addr
, REG(B11_8
), 1);
590 /* might cause re-execution */
591 tcg_gen_qemu_st_i32(REG(B7_4
), addr
, ctx
->memidx
, MO_UB
);
592 tcg_gen_mov_i32(REG(B11_8
), addr
); /* modify register status */
596 case 0x2005: /* mov.w Rm,@-Rn */
598 TCGv addr
= tcg_temp_new();
599 tcg_gen_subi_i32(addr
, REG(B11_8
), 2);
600 tcg_gen_qemu_st_i32(REG(B7_4
), addr
, ctx
->memidx
,
601 MO_TEUW
| UNALIGN(ctx
));
602 tcg_gen_mov_i32(REG(B11_8
), addr
);
606 case 0x2006: /* mov.l Rm,@-Rn */
608 TCGv addr
= tcg_temp_new();
609 tcg_gen_subi_i32(addr
, REG(B11_8
), 4);
610 tcg_gen_qemu_st_i32(REG(B7_4
), addr
, ctx
->memidx
,
611 MO_TEUL
| UNALIGN(ctx
));
612 tcg_gen_mov_i32(REG(B11_8
), addr
);
616 case 0x6004: /* mov.b @Rm+,Rn */
617 tcg_gen_qemu_ld_i32(REG(B11_8
), REG(B7_4
), ctx
->memidx
, MO_SB
);
619 tcg_gen_addi_i32(REG(B7_4
), REG(B7_4
), 1);
621 case 0x6005: /* mov.w @Rm+,Rn */
622 tcg_gen_qemu_ld_i32(REG(B11_8
), REG(B7_4
), ctx
->memidx
,
623 MO_TESW
| UNALIGN(ctx
));
625 tcg_gen_addi_i32(REG(B7_4
), REG(B7_4
), 2);
627 case 0x6006: /* mov.l @Rm+,Rn */
628 tcg_gen_qemu_ld_i32(REG(B11_8
), REG(B7_4
), ctx
->memidx
,
629 MO_TESL
| UNALIGN(ctx
));
631 tcg_gen_addi_i32(REG(B7_4
), REG(B7_4
), 4);
633 case 0x0004: /* mov.b Rm,@(R0,Rn) */
635 TCGv addr
= tcg_temp_new();
636 tcg_gen_add_i32(addr
, REG(B11_8
), REG(0));
637 tcg_gen_qemu_st_i32(REG(B7_4
), addr
, ctx
->memidx
, MO_UB
);
641 case 0x0005: /* mov.w Rm,@(R0,Rn) */
643 TCGv addr
= tcg_temp_new();
644 tcg_gen_add_i32(addr
, REG(B11_8
), REG(0));
645 tcg_gen_qemu_st_i32(REG(B7_4
), addr
, ctx
->memidx
,
646 MO_TEUW
| UNALIGN(ctx
));
650 case 0x0006: /* mov.l Rm,@(R0,Rn) */
652 TCGv addr
= tcg_temp_new();
653 tcg_gen_add_i32(addr
, REG(B11_8
), REG(0));
654 tcg_gen_qemu_st_i32(REG(B7_4
), addr
, ctx
->memidx
,
655 MO_TEUL
| UNALIGN(ctx
));
659 case 0x000c: /* mov.b @(R0,Rm),Rn */
661 TCGv addr
= tcg_temp_new();
662 tcg_gen_add_i32(addr
, REG(B7_4
), REG(0));
663 tcg_gen_qemu_ld_i32(REG(B11_8
), addr
, ctx
->memidx
, MO_SB
);
667 case 0x000d: /* mov.w @(R0,Rm),Rn */
669 TCGv addr
= tcg_temp_new();
670 tcg_gen_add_i32(addr
, REG(B7_4
), REG(0));
671 tcg_gen_qemu_ld_i32(REG(B11_8
), addr
, ctx
->memidx
,
672 MO_TESW
| UNALIGN(ctx
));
676 case 0x000e: /* mov.l @(R0,Rm),Rn */
678 TCGv addr
= tcg_temp_new();
679 tcg_gen_add_i32(addr
, REG(B7_4
), REG(0));
680 tcg_gen_qemu_ld_i32(REG(B11_8
), addr
, ctx
->memidx
,
681 MO_TESL
| UNALIGN(ctx
));
685 case 0x6008: /* swap.b Rm,Rn */
687 TCGv low
= tcg_temp_new();
688 tcg_gen_bswap16_i32(low
, REG(B7_4
), 0);
689 tcg_gen_deposit_i32(REG(B11_8
), REG(B7_4
), low
, 0, 16);
693 case 0x6009: /* swap.w Rm,Rn */
694 tcg_gen_rotli_i32(REG(B11_8
), REG(B7_4
), 16);
696 case 0x200d: /* xtrct Rm,Rn */
699 high
= tcg_temp_new();
700 tcg_gen_shli_i32(high
, REG(B7_4
), 16);
701 low
= tcg_temp_new();
702 tcg_gen_shri_i32(low
, REG(B11_8
), 16);
703 tcg_gen_or_i32(REG(B11_8
), high
, low
);
708 case 0x300c: /* add Rm,Rn */
709 tcg_gen_add_i32(REG(B11_8
), REG(B11_8
), REG(B7_4
));
711 case 0x300e: /* addc Rm,Rn */
714 t0
= tcg_const_tl(0);
716 tcg_gen_add2_i32(t1
, cpu_sr_t
, cpu_sr_t
, t0
, REG(B7_4
), t0
);
717 tcg_gen_add2_i32(REG(B11_8
), cpu_sr_t
,
718 REG(B11_8
), t0
, t1
, cpu_sr_t
);
723 case 0x300f: /* addv Rm,Rn */
727 tcg_gen_add_i32(t0
, REG(B7_4
), REG(B11_8
));
729 tcg_gen_xor_i32(t1
, t0
, REG(B11_8
));
731 tcg_gen_xor_i32(t2
, REG(B7_4
), REG(B11_8
));
732 tcg_gen_andc_i32(cpu_sr_t
, t1
, t2
);
734 tcg_gen_shri_i32(cpu_sr_t
, cpu_sr_t
, 31);
736 tcg_gen_mov_i32(REG(B7_4
), t0
);
740 case 0x2009: /* and Rm,Rn */
741 tcg_gen_and_i32(REG(B11_8
), REG(B11_8
), REG(B7_4
));
743 case 0x3000: /* cmp/eq Rm,Rn */
744 tcg_gen_setcond_i32(TCG_COND_EQ
, cpu_sr_t
, REG(B11_8
), REG(B7_4
));
746 case 0x3003: /* cmp/ge Rm,Rn */
747 tcg_gen_setcond_i32(TCG_COND_GE
, cpu_sr_t
, REG(B11_8
), REG(B7_4
));
749 case 0x3007: /* cmp/gt Rm,Rn */
750 tcg_gen_setcond_i32(TCG_COND_GT
, cpu_sr_t
, REG(B11_8
), REG(B7_4
));
752 case 0x3006: /* cmp/hi Rm,Rn */
753 tcg_gen_setcond_i32(TCG_COND_GTU
, cpu_sr_t
, REG(B11_8
), REG(B7_4
));
755 case 0x3002: /* cmp/hs Rm,Rn */
756 tcg_gen_setcond_i32(TCG_COND_GEU
, cpu_sr_t
, REG(B11_8
), REG(B7_4
));
758 case 0x200c: /* cmp/str Rm,Rn */
760 TCGv cmp1
= tcg_temp_new();
761 TCGv cmp2
= tcg_temp_new();
762 tcg_gen_xor_i32(cmp2
, REG(B7_4
), REG(B11_8
));
763 tcg_gen_subi_i32(cmp1
, cmp2
, 0x01010101);
764 tcg_gen_andc_i32(cmp1
, cmp1
, cmp2
);
765 tcg_gen_andi_i32(cmp1
, cmp1
, 0x80808080);
766 tcg_gen_setcondi_i32(TCG_COND_NE
, cpu_sr_t
, cmp1
, 0);
771 case 0x2007: /* div0s Rm,Rn */
772 tcg_gen_shri_i32(cpu_sr_q
, REG(B11_8
), 31); /* SR_Q */
773 tcg_gen_shri_i32(cpu_sr_m
, REG(B7_4
), 31); /* SR_M */
774 tcg_gen_xor_i32(cpu_sr_t
, cpu_sr_q
, cpu_sr_m
); /* SR_T */
776 case 0x3004: /* div1 Rm,Rn */
778 TCGv t0
= tcg_temp_new();
779 TCGv t1
= tcg_temp_new();
780 TCGv t2
= tcg_temp_new();
781 TCGv zero
= tcg_const_i32(0);
783 /* shift left arg1, saving the bit being pushed out and inserting
785 tcg_gen_shri_i32(t0
, REG(B11_8
), 31);
786 tcg_gen_shli_i32(REG(B11_8
), REG(B11_8
), 1);
787 tcg_gen_or_i32(REG(B11_8
), REG(B11_8
), cpu_sr_t
);
789 /* Add or subtract arg0 from arg1 depending if Q == M. To avoid
790 using 64-bit temps, we compute arg0's high part from q ^ m, so
791 that it is 0x00000000 when adding the value or 0xffffffff when
793 tcg_gen_xor_i32(t1
, cpu_sr_q
, cpu_sr_m
);
794 tcg_gen_subi_i32(t1
, t1
, 1);
795 tcg_gen_neg_i32(t2
, REG(B7_4
));
796 tcg_gen_movcond_i32(TCG_COND_EQ
, t2
, t1
, zero
, REG(B7_4
), t2
);
797 tcg_gen_add2_i32(REG(B11_8
), t1
, REG(B11_8
), zero
, t2
, t1
);
799 /* compute T and Q depending on carry */
800 tcg_gen_andi_i32(t1
, t1
, 1);
801 tcg_gen_xor_i32(t1
, t1
, t0
);
802 tcg_gen_xori_i32(cpu_sr_t
, t1
, 1);
803 tcg_gen_xor_i32(cpu_sr_q
, cpu_sr_m
, t1
);
811 case 0x300d: /* dmuls.l Rm,Rn */
812 tcg_gen_muls2_i32(cpu_macl
, cpu_mach
, REG(B7_4
), REG(B11_8
));
814 case 0x3005: /* dmulu.l Rm,Rn */
815 tcg_gen_mulu2_i32(cpu_macl
, cpu_mach
, REG(B7_4
), REG(B11_8
));
817 case 0x600e: /* exts.b Rm,Rn */
818 tcg_gen_ext8s_i32(REG(B11_8
), REG(B7_4
));
820 case 0x600f: /* exts.w Rm,Rn */
821 tcg_gen_ext16s_i32(REG(B11_8
), REG(B7_4
));
823 case 0x600c: /* extu.b Rm,Rn */
824 tcg_gen_ext8u_i32(REG(B11_8
), REG(B7_4
));
826 case 0x600d: /* extu.w Rm,Rn */
827 tcg_gen_ext16u_i32(REG(B11_8
), REG(B7_4
));
829 case 0x000f: /* mac.l @Rm+,@Rn+ */
832 arg0
= tcg_temp_new();
833 tcg_gen_qemu_ld_i32(arg0
, REG(B7_4
), ctx
->memidx
, MO_TESL
);
834 arg1
= tcg_temp_new();
835 tcg_gen_qemu_ld_i32(arg1
, REG(B11_8
), ctx
->memidx
, MO_TESL
);
836 gen_helper_macl(cpu_env
, arg0
, arg1
);
839 tcg_gen_addi_i32(REG(B7_4
), REG(B7_4
), 4);
840 tcg_gen_addi_i32(REG(B11_8
), REG(B11_8
), 4);
843 case 0x400f: /* mac.w @Rm+,@Rn+ */
846 arg0
= tcg_temp_new();
847 tcg_gen_qemu_ld_i32(arg0
, REG(B7_4
), ctx
->memidx
, MO_TESL
);
848 arg1
= tcg_temp_new();
849 tcg_gen_qemu_ld_i32(arg1
, REG(B11_8
), ctx
->memidx
, MO_TESL
);
850 gen_helper_macw(cpu_env
, arg0
, arg1
);
853 tcg_gen_addi_i32(REG(B11_8
), REG(B11_8
), 2);
854 tcg_gen_addi_i32(REG(B7_4
), REG(B7_4
), 2);
857 case 0x0007: /* mul.l Rm,Rn */
858 tcg_gen_mul_i32(cpu_macl
, REG(B7_4
), REG(B11_8
));
860 case 0x200f: /* muls.w Rm,Rn */
863 arg0
= tcg_temp_new();
864 tcg_gen_ext16s_i32(arg0
, REG(B7_4
));
865 arg1
= tcg_temp_new();
866 tcg_gen_ext16s_i32(arg1
, REG(B11_8
));
867 tcg_gen_mul_i32(cpu_macl
, arg0
, arg1
);
872 case 0x200e: /* mulu.w Rm,Rn */
875 arg0
= tcg_temp_new();
876 tcg_gen_ext16u_i32(arg0
, REG(B7_4
));
877 arg1
= tcg_temp_new();
878 tcg_gen_ext16u_i32(arg1
, REG(B11_8
));
879 tcg_gen_mul_i32(cpu_macl
, arg0
, arg1
);
884 case 0x600b: /* neg Rm,Rn */
885 tcg_gen_neg_i32(REG(B11_8
), REG(B7_4
));
887 case 0x600a: /* negc Rm,Rn */
889 TCGv t0
= tcg_const_i32(0);
890 tcg_gen_add2_i32(REG(B11_8
), cpu_sr_t
,
891 REG(B7_4
), t0
, cpu_sr_t
, t0
);
892 tcg_gen_sub2_i32(REG(B11_8
), cpu_sr_t
,
893 t0
, t0
, REG(B11_8
), cpu_sr_t
);
894 tcg_gen_andi_i32(cpu_sr_t
, cpu_sr_t
, 1);
898 case 0x6007: /* not Rm,Rn */
899 tcg_gen_not_i32(REG(B11_8
), REG(B7_4
));
901 case 0x200b: /* or Rm,Rn */
902 tcg_gen_or_i32(REG(B11_8
), REG(B11_8
), REG(B7_4
));
904 case 0x400c: /* shad Rm,Rn */
906 TCGv t0
= tcg_temp_new();
907 TCGv t1
= tcg_temp_new();
908 TCGv t2
= tcg_temp_new();
910 tcg_gen_andi_i32(t0
, REG(B7_4
), 0x1f);
912 /* positive case: shift to the left */
913 tcg_gen_shl_i32(t1
, REG(B11_8
), t0
);
915 /* negative case: shift to the right in two steps to
916 correctly handle the -32 case */
917 tcg_gen_xori_i32(t0
, t0
, 0x1f);
918 tcg_gen_sar_i32(t2
, REG(B11_8
), t0
);
919 tcg_gen_sari_i32(t2
, t2
, 1);
921 /* select between the two cases */
922 tcg_gen_movi_i32(t0
, 0);
923 tcg_gen_movcond_i32(TCG_COND_GE
, REG(B11_8
), REG(B7_4
), t0
, t1
, t2
);
930 case 0x400d: /* shld Rm,Rn */
932 TCGv t0
= tcg_temp_new();
933 TCGv t1
= tcg_temp_new();
934 TCGv t2
= tcg_temp_new();
936 tcg_gen_andi_i32(t0
, REG(B7_4
), 0x1f);
938 /* positive case: shift to the left */
939 tcg_gen_shl_i32(t1
, REG(B11_8
), t0
);
941 /* negative case: shift to the right in two steps to
942 correctly handle the -32 case */
943 tcg_gen_xori_i32(t0
, t0
, 0x1f);
944 tcg_gen_shr_i32(t2
, REG(B11_8
), t0
);
945 tcg_gen_shri_i32(t2
, t2
, 1);
947 /* select between the two cases */
948 tcg_gen_movi_i32(t0
, 0);
949 tcg_gen_movcond_i32(TCG_COND_GE
, REG(B11_8
), REG(B7_4
), t0
, t1
, t2
);
956 case 0x3008: /* sub Rm,Rn */
957 tcg_gen_sub_i32(REG(B11_8
), REG(B11_8
), REG(B7_4
));
959 case 0x300a: /* subc Rm,Rn */
962 t0
= tcg_const_tl(0);
964 tcg_gen_add2_i32(t1
, cpu_sr_t
, cpu_sr_t
, t0
, REG(B7_4
), t0
);
965 tcg_gen_sub2_i32(REG(B11_8
), cpu_sr_t
,
966 REG(B11_8
), t0
, t1
, cpu_sr_t
);
967 tcg_gen_andi_i32(cpu_sr_t
, cpu_sr_t
, 1);
972 case 0x300b: /* subv Rm,Rn */
976 tcg_gen_sub_i32(t0
, REG(B11_8
), REG(B7_4
));
978 tcg_gen_xor_i32(t1
, t0
, REG(B7_4
));
980 tcg_gen_xor_i32(t2
, REG(B11_8
), REG(B7_4
));
981 tcg_gen_and_i32(t1
, t1
, t2
);
983 tcg_gen_shri_i32(cpu_sr_t
, t1
, 31);
985 tcg_gen_mov_i32(REG(B11_8
), t0
);
989 case 0x2008: /* tst Rm,Rn */
991 TCGv val
= tcg_temp_new();
992 tcg_gen_and_i32(val
, REG(B7_4
), REG(B11_8
));
993 tcg_gen_setcondi_i32(TCG_COND_EQ
, cpu_sr_t
, val
, 0);
997 case 0x200a: /* xor Rm,Rn */
998 tcg_gen_xor_i32(REG(B11_8
), REG(B11_8
), REG(B7_4
));
1000 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
1002 if (ctx
->tbflags
& FPSCR_SZ
) {
1003 int xsrc
= XHACK(B7_4
);
1004 int xdst
= XHACK(B11_8
);
1005 tcg_gen_mov_i32(FREG(xdst
), FREG(xsrc
));
1006 tcg_gen_mov_i32(FREG(xdst
+ 1), FREG(xsrc
+ 1));
1008 tcg_gen_mov_i32(FREG(B11_8
), FREG(B7_4
));
1011 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
1013 if (ctx
->tbflags
& FPSCR_SZ
) {
1014 TCGv_i64 fp
= tcg_temp_new_i64();
1015 gen_load_fpr64(ctx
, fp
, XHACK(B7_4
));
1016 tcg_gen_qemu_st_i64(fp
, REG(B11_8
), ctx
->memidx
, MO_TEUQ
);
1017 tcg_temp_free_i64(fp
);
1019 tcg_gen_qemu_st_i32(FREG(B7_4
), REG(B11_8
), ctx
->memidx
, MO_TEUL
);
1022 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
1024 if (ctx
->tbflags
& FPSCR_SZ
) {
1025 TCGv_i64 fp
= tcg_temp_new_i64();
1026 tcg_gen_qemu_ld_i64(fp
, REG(B7_4
), ctx
->memidx
, MO_TEUQ
);
1027 gen_store_fpr64(ctx
, fp
, XHACK(B11_8
));
1028 tcg_temp_free_i64(fp
);
1030 tcg_gen_qemu_ld_i32(FREG(B11_8
), REG(B7_4
), ctx
->memidx
, MO_TEUL
);
1033 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
1035 if (ctx
->tbflags
& FPSCR_SZ
) {
1036 TCGv_i64 fp
= tcg_temp_new_i64();
1037 tcg_gen_qemu_ld_i64(fp
, REG(B7_4
), ctx
->memidx
, MO_TEUQ
);
1038 gen_store_fpr64(ctx
, fp
, XHACK(B11_8
));
1039 tcg_temp_free_i64(fp
);
1040 tcg_gen_addi_i32(REG(B7_4
), REG(B7_4
), 8);
1042 tcg_gen_qemu_ld_i32(FREG(B11_8
), REG(B7_4
), ctx
->memidx
, MO_TEUL
);
1043 tcg_gen_addi_i32(REG(B7_4
), REG(B7_4
), 4);
1046 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
1049 TCGv addr
= tcg_temp_new_i32();
1050 if (ctx
->tbflags
& FPSCR_SZ
) {
1051 TCGv_i64 fp
= tcg_temp_new_i64();
1052 gen_load_fpr64(ctx
, fp
, XHACK(B7_4
));
1053 tcg_gen_subi_i32(addr
, REG(B11_8
), 8);
1054 tcg_gen_qemu_st_i64(fp
, addr
, ctx
->memidx
, MO_TEUQ
);
1055 tcg_temp_free_i64(fp
);
1057 tcg_gen_subi_i32(addr
, REG(B11_8
), 4);
1058 tcg_gen_qemu_st_i32(FREG(B7_4
), addr
, ctx
->memidx
, MO_TEUL
);
1060 tcg_gen_mov_i32(REG(B11_8
), addr
);
1061 tcg_temp_free(addr
);
1064 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
1067 TCGv addr
= tcg_temp_new_i32();
1068 tcg_gen_add_i32(addr
, REG(B7_4
), REG(0));
1069 if (ctx
->tbflags
& FPSCR_SZ
) {
1070 TCGv_i64 fp
= tcg_temp_new_i64();
1071 tcg_gen_qemu_ld_i64(fp
, addr
, ctx
->memidx
, MO_TEUQ
);
1072 gen_store_fpr64(ctx
, fp
, XHACK(B11_8
));
1073 tcg_temp_free_i64(fp
);
1075 tcg_gen_qemu_ld_i32(FREG(B11_8
), addr
, ctx
->memidx
, MO_TEUL
);
1077 tcg_temp_free(addr
);
1080 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
1083 TCGv addr
= tcg_temp_new();
1084 tcg_gen_add_i32(addr
, REG(B11_8
), REG(0));
1085 if (ctx
->tbflags
& FPSCR_SZ
) {
1086 TCGv_i64 fp
= tcg_temp_new_i64();
1087 gen_load_fpr64(ctx
, fp
, XHACK(B7_4
));
1088 tcg_gen_qemu_st_i64(fp
, addr
, ctx
->memidx
, MO_TEUQ
);
1089 tcg_temp_free_i64(fp
);
1091 tcg_gen_qemu_st_i32(FREG(B7_4
), addr
, ctx
->memidx
, MO_TEUL
);
1093 tcg_temp_free(addr
);
1096 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1097 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1098 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1099 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1100 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1101 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1104 if (ctx
->tbflags
& FPSCR_PR
) {
1107 if (ctx
->opcode
& 0x0110) {
1110 fp0
= tcg_temp_new_i64();
1111 fp1
= tcg_temp_new_i64();
1112 gen_load_fpr64(ctx
, fp0
, B11_8
);
1113 gen_load_fpr64(ctx
, fp1
, B7_4
);
1114 switch (ctx
->opcode
& 0xf00f) {
1115 case 0xf000: /* fadd Rm,Rn */
1116 gen_helper_fadd_DT(fp0
, cpu_env
, fp0
, fp1
);
1118 case 0xf001: /* fsub Rm,Rn */
1119 gen_helper_fsub_DT(fp0
, cpu_env
, fp0
, fp1
);
1121 case 0xf002: /* fmul Rm,Rn */
1122 gen_helper_fmul_DT(fp0
, cpu_env
, fp0
, fp1
);
1124 case 0xf003: /* fdiv Rm,Rn */
1125 gen_helper_fdiv_DT(fp0
, cpu_env
, fp0
, fp1
);
1127 case 0xf004: /* fcmp/eq Rm,Rn */
1128 gen_helper_fcmp_eq_DT(cpu_sr_t
, cpu_env
, fp0
, fp1
);
1130 case 0xf005: /* fcmp/gt Rm,Rn */
1131 gen_helper_fcmp_gt_DT(cpu_sr_t
, cpu_env
, fp0
, fp1
);
1134 gen_store_fpr64(ctx
, fp0
, B11_8
);
1135 tcg_temp_free_i64(fp0
);
1136 tcg_temp_free_i64(fp1
);
1138 switch (ctx
->opcode
& 0xf00f) {
1139 case 0xf000: /* fadd Rm,Rn */
1140 gen_helper_fadd_FT(FREG(B11_8
), cpu_env
,
1141 FREG(B11_8
), FREG(B7_4
));
1143 case 0xf001: /* fsub Rm,Rn */
1144 gen_helper_fsub_FT(FREG(B11_8
), cpu_env
,
1145 FREG(B11_8
), FREG(B7_4
));
1147 case 0xf002: /* fmul Rm,Rn */
1148 gen_helper_fmul_FT(FREG(B11_8
), cpu_env
,
1149 FREG(B11_8
), FREG(B7_4
));
1151 case 0xf003: /* fdiv Rm,Rn */
1152 gen_helper_fdiv_FT(FREG(B11_8
), cpu_env
,
1153 FREG(B11_8
), FREG(B7_4
));
1155 case 0xf004: /* fcmp/eq Rm,Rn */
1156 gen_helper_fcmp_eq_FT(cpu_sr_t
, cpu_env
,
1157 FREG(B11_8
), FREG(B7_4
));
1159 case 0xf005: /* fcmp/gt Rm,Rn */
1160 gen_helper_fcmp_gt_FT(cpu_sr_t
, cpu_env
,
1161 FREG(B11_8
), FREG(B7_4
));
1167 case 0xf00e: /* fmac FR0,RM,Rn */
1170 gen_helper_fmac_FT(FREG(B11_8
), cpu_env
,
1171 FREG(0), FREG(B7_4
), FREG(B11_8
));
1175 switch (ctx
->opcode
& 0xff00) {
1176 case 0xc900: /* and #imm,R0 */
1177 tcg_gen_andi_i32(REG(0), REG(0), B7_0
);
1179 case 0xcd00: /* and.b #imm,@(R0,GBR) */
1182 addr
= tcg_temp_new();
1183 tcg_gen_add_i32(addr
, REG(0), cpu_gbr
);
1184 val
= tcg_temp_new();
1185 tcg_gen_qemu_ld_i32(val
, addr
, ctx
->memidx
, MO_UB
);
1186 tcg_gen_andi_i32(val
, val
, B7_0
);
1187 tcg_gen_qemu_st_i32(val
, addr
, ctx
->memidx
, MO_UB
);
1189 tcg_temp_free(addr
);
1192 case 0x8b00: /* bf label */
1193 CHECK_NOT_DELAY_SLOT
1194 gen_conditional_jump(ctx
, ctx
->base
.pc_next
+ 4 + B7_0s
* 2, false);
1196 case 0x8f00: /* bf/s label */
1197 CHECK_NOT_DELAY_SLOT
1198 tcg_gen_xori_i32(cpu_delayed_cond
, cpu_sr_t
, 1);
1199 ctx
->delayed_pc
= ctx
->base
.pc_next
+ 4 + B7_0s
* 2;
1200 ctx
->envflags
|= TB_FLAG_DELAY_SLOT_COND
;
1202 case 0x8900: /* bt label */
1203 CHECK_NOT_DELAY_SLOT
1204 gen_conditional_jump(ctx
, ctx
->base
.pc_next
+ 4 + B7_0s
* 2, true);
1206 case 0x8d00: /* bt/s label */
1207 CHECK_NOT_DELAY_SLOT
1208 tcg_gen_mov_i32(cpu_delayed_cond
, cpu_sr_t
);
1209 ctx
->delayed_pc
= ctx
->base
.pc_next
+ 4 + B7_0s
* 2;
1210 ctx
->envflags
|= TB_FLAG_DELAY_SLOT_COND
;
1212 case 0x8800: /* cmp/eq #imm,R0 */
1213 tcg_gen_setcondi_i32(TCG_COND_EQ
, cpu_sr_t
, REG(0), B7_0s
);
1215 case 0xc400: /* mov.b @(disp,GBR),R0 */
1217 TCGv addr
= tcg_temp_new();
1218 tcg_gen_addi_i32(addr
, cpu_gbr
, B7_0
);
1219 tcg_gen_qemu_ld_i32(REG(0), addr
, ctx
->memidx
, MO_SB
);
1220 tcg_temp_free(addr
);
1223 case 0xc500: /* mov.w @(disp,GBR),R0 */
1225 TCGv addr
= tcg_temp_new();
1226 tcg_gen_addi_i32(addr
, cpu_gbr
, B7_0
* 2);
1227 tcg_gen_qemu_ld_i32(REG(0), addr
, ctx
->memidx
, MO_TESW
);
1228 tcg_temp_free(addr
);
1231 case 0xc600: /* mov.l @(disp,GBR),R0 */
1233 TCGv addr
= tcg_temp_new();
1234 tcg_gen_addi_i32(addr
, cpu_gbr
, B7_0
* 4);
1235 tcg_gen_qemu_ld_i32(REG(0), addr
, ctx
->memidx
, MO_TESL
);
1236 tcg_temp_free(addr
);
1239 case 0xc000: /* mov.b R0,@(disp,GBR) */
1241 TCGv addr
= tcg_temp_new();
1242 tcg_gen_addi_i32(addr
, cpu_gbr
, B7_0
);
1243 tcg_gen_qemu_st_i32(REG(0), addr
, ctx
->memidx
, MO_UB
);
1244 tcg_temp_free(addr
);
1247 case 0xc100: /* mov.w R0,@(disp,GBR) */
1249 TCGv addr
= tcg_temp_new();
1250 tcg_gen_addi_i32(addr
, cpu_gbr
, B7_0
* 2);
1251 tcg_gen_qemu_st_i32(REG(0), addr
, ctx
->memidx
, MO_TEUW
);
1252 tcg_temp_free(addr
);
1255 case 0xc200: /* mov.l R0,@(disp,GBR) */
1257 TCGv addr
= tcg_temp_new();
1258 tcg_gen_addi_i32(addr
, cpu_gbr
, B7_0
* 4);
1259 tcg_gen_qemu_st_i32(REG(0), addr
, ctx
->memidx
, MO_TEUL
);
1260 tcg_temp_free(addr
);
1263 case 0x8000: /* mov.b R0,@(disp,Rn) */
1265 TCGv addr
= tcg_temp_new();
1266 tcg_gen_addi_i32(addr
, REG(B7_4
), B3_0
);
1267 tcg_gen_qemu_st_i32(REG(0), addr
, ctx
->memidx
, MO_UB
);
1268 tcg_temp_free(addr
);
1271 case 0x8100: /* mov.w R0,@(disp,Rn) */
1273 TCGv addr
= tcg_temp_new();
1274 tcg_gen_addi_i32(addr
, REG(B7_4
), B3_0
* 2);
1275 tcg_gen_qemu_st_i32(REG(0), addr
, ctx
->memidx
,
1276 MO_TEUW
| UNALIGN(ctx
));
1277 tcg_temp_free(addr
);
1280 case 0x8400: /* mov.b @(disp,Rn),R0 */
1282 TCGv addr
= tcg_temp_new();
1283 tcg_gen_addi_i32(addr
, REG(B7_4
), B3_0
);
1284 tcg_gen_qemu_ld_i32(REG(0), addr
, ctx
->memidx
, MO_SB
);
1285 tcg_temp_free(addr
);
1288 case 0x8500: /* mov.w @(disp,Rn),R0 */
1290 TCGv addr
= tcg_temp_new();
1291 tcg_gen_addi_i32(addr
, REG(B7_4
), B3_0
* 2);
1292 tcg_gen_qemu_ld_i32(REG(0), addr
, ctx
->memidx
,
1293 MO_TESW
| UNALIGN(ctx
));
1294 tcg_temp_free(addr
);
1297 case 0xc700: /* mova @(disp,PC),R0 */
1298 tcg_gen_movi_i32(REG(0), ((ctx
->base
.pc_next
& 0xfffffffc) +
1299 4 + B7_0
* 4) & ~3);
1301 case 0xcb00: /* or #imm,R0 */
1302 tcg_gen_ori_i32(REG(0), REG(0), B7_0
);
1304 case 0xcf00: /* or.b #imm,@(R0,GBR) */
1307 addr
= tcg_temp_new();
1308 tcg_gen_add_i32(addr
, REG(0), cpu_gbr
);
1309 val
= tcg_temp_new();
1310 tcg_gen_qemu_ld_i32(val
, addr
, ctx
->memidx
, MO_UB
);
1311 tcg_gen_ori_i32(val
, val
, B7_0
);
1312 tcg_gen_qemu_st_i32(val
, addr
, ctx
->memidx
, MO_UB
);
1314 tcg_temp_free(addr
);
1317 case 0xc300: /* trapa #imm */
1320 CHECK_NOT_DELAY_SLOT
1321 gen_save_cpu_state(ctx
, true);
1322 imm
= tcg_const_i32(B7_0
);
1323 gen_helper_trapa(cpu_env
, imm
);
1325 ctx
->base
.is_jmp
= DISAS_NORETURN
;
1328 case 0xc800: /* tst #imm,R0 */
1330 TCGv val
= tcg_temp_new();
1331 tcg_gen_andi_i32(val
, REG(0), B7_0
);
1332 tcg_gen_setcondi_i32(TCG_COND_EQ
, cpu_sr_t
, val
, 0);
1336 case 0xcc00: /* tst.b #imm,@(R0,GBR) */
1338 TCGv val
= tcg_temp_new();
1339 tcg_gen_add_i32(val
, REG(0), cpu_gbr
);
1340 tcg_gen_qemu_ld_i32(val
, val
, ctx
->memidx
, MO_UB
);
1341 tcg_gen_andi_i32(val
, val
, B7_0
);
1342 tcg_gen_setcondi_i32(TCG_COND_EQ
, cpu_sr_t
, val
, 0);
1346 case 0xca00: /* xor #imm,R0 */
1347 tcg_gen_xori_i32(REG(0), REG(0), B7_0
);
1349 case 0xce00: /* xor.b #imm,@(R0,GBR) */
1352 addr
= tcg_temp_new();
1353 tcg_gen_add_i32(addr
, REG(0), cpu_gbr
);
1354 val
= tcg_temp_new();
1355 tcg_gen_qemu_ld_i32(val
, addr
, ctx
->memidx
, MO_UB
);
1356 tcg_gen_xori_i32(val
, val
, B7_0
);
1357 tcg_gen_qemu_st_i32(val
, addr
, ctx
->memidx
, MO_UB
);
1359 tcg_temp_free(addr
);
1364 switch (ctx
->opcode
& 0xf08f) {
1365 case 0x408e: /* ldc Rm,Rn_BANK */
1367 tcg_gen_mov_i32(ALTREG(B6_4
), REG(B11_8
));
1369 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
1371 tcg_gen_qemu_ld_i32(ALTREG(B6_4
), REG(B11_8
), ctx
->memidx
, MO_TESL
);
1372 tcg_gen_addi_i32(REG(B11_8
), REG(B11_8
), 4);
1374 case 0x0082: /* stc Rm_BANK,Rn */
1376 tcg_gen_mov_i32(REG(B11_8
), ALTREG(B6_4
));
1378 case 0x4083: /* stc.l Rm_BANK,@-Rn */
1381 TCGv addr
= tcg_temp_new();
1382 tcg_gen_subi_i32(addr
, REG(B11_8
), 4);
1383 tcg_gen_qemu_st_i32(ALTREG(B6_4
), addr
, ctx
->memidx
, MO_TEUL
);
1384 tcg_gen_mov_i32(REG(B11_8
), addr
);
1385 tcg_temp_free(addr
);
1390 switch (ctx
->opcode
& 0xf0ff) {
1391 case 0x0023: /* braf Rn */
1392 CHECK_NOT_DELAY_SLOT
1393 tcg_gen_addi_i32(cpu_delayed_pc
, REG(B11_8
), ctx
->base
.pc_next
+ 4);
1394 ctx
->envflags
|= TB_FLAG_DELAY_SLOT
;
1395 ctx
->delayed_pc
= (uint32_t) - 1;
1397 case 0x0003: /* bsrf Rn */
1398 CHECK_NOT_DELAY_SLOT
1399 tcg_gen_movi_i32(cpu_pr
, ctx
->base
.pc_next
+ 4);
1400 tcg_gen_add_i32(cpu_delayed_pc
, REG(B11_8
), cpu_pr
);
1401 ctx
->envflags
|= TB_FLAG_DELAY_SLOT
;
1402 ctx
->delayed_pc
= (uint32_t) - 1;
1404 case 0x4015: /* cmp/pl Rn */
1405 tcg_gen_setcondi_i32(TCG_COND_GT
, cpu_sr_t
, REG(B11_8
), 0);
1407 case 0x4011: /* cmp/pz Rn */
1408 tcg_gen_setcondi_i32(TCG_COND_GE
, cpu_sr_t
, REG(B11_8
), 0);
1410 case 0x4010: /* dt Rn */
1411 tcg_gen_subi_i32(REG(B11_8
), REG(B11_8
), 1);
1412 tcg_gen_setcondi_i32(TCG_COND_EQ
, cpu_sr_t
, REG(B11_8
), 0);
1414 case 0x402b: /* jmp @Rn */
1415 CHECK_NOT_DELAY_SLOT
1416 tcg_gen_mov_i32(cpu_delayed_pc
, REG(B11_8
));
1417 ctx
->envflags
|= TB_FLAG_DELAY_SLOT
;
1418 ctx
->delayed_pc
= (uint32_t) - 1;
1420 case 0x400b: /* jsr @Rn */
1421 CHECK_NOT_DELAY_SLOT
1422 tcg_gen_movi_i32(cpu_pr
, ctx
->base
.pc_next
+ 4);
1423 tcg_gen_mov_i32(cpu_delayed_pc
, REG(B11_8
));
1424 ctx
->envflags
|= TB_FLAG_DELAY_SLOT
;
1425 ctx
->delayed_pc
= (uint32_t) - 1;
1427 case 0x400e: /* ldc Rm,SR */
1430 TCGv val
= tcg_temp_new();
1431 tcg_gen_andi_i32(val
, REG(B11_8
), 0x700083f3);
1434 ctx
->base
.is_jmp
= DISAS_STOP
;
1437 case 0x4007: /* ldc.l @Rm+,SR */
1440 TCGv val
= tcg_temp_new();
1441 tcg_gen_qemu_ld_i32(val
, REG(B11_8
), ctx
->memidx
, MO_TESL
);
1442 tcg_gen_andi_i32(val
, val
, 0x700083f3);
1445 tcg_gen_addi_i32(REG(B11_8
), REG(B11_8
), 4);
1446 ctx
->base
.is_jmp
= DISAS_STOP
;
1449 case 0x0002: /* stc SR,Rn */
1451 gen_read_sr(REG(B11_8
));
1453 case 0x4003: /* stc SR,@-Rn */
1456 TCGv addr
= tcg_temp_new();
1457 TCGv val
= tcg_temp_new();
1458 tcg_gen_subi_i32(addr
, REG(B11_8
), 4);
1460 tcg_gen_qemu_st_i32(val
, addr
, ctx
->memidx
, MO_TEUL
);
1461 tcg_gen_mov_i32(REG(B11_8
), addr
);
1463 tcg_temp_free(addr
);
1466 #define LD(reg,ldnum,ldpnum,prechk) \
1469 tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \
1473 tcg_gen_qemu_ld_i32(cpu_##reg, REG(B11_8), ctx->memidx, MO_TESL); \
1474 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \
1476 #define ST(reg,stnum,stpnum,prechk) \
1479 tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \
1484 TCGv addr = tcg_temp_new(); \
1485 tcg_gen_subi_i32(addr, REG(B11_8), 4); \
1486 tcg_gen_qemu_st_i32(cpu_##reg, addr, ctx->memidx, MO_TEUL); \
1487 tcg_gen_mov_i32(REG(B11_8), addr); \
1488 tcg_temp_free(addr); \
1491 #define LDST(reg,ldnum,ldpnum,stnum,stpnum,prechk) \
1492 LD(reg,ldnum,ldpnum,prechk) \
1493 ST(reg,stnum,stpnum,prechk)
1494 LDST(gbr
, 0x401e, 0x4017, 0x0012, 0x4013, {})
1495 LDST(vbr
, 0x402e, 0x4027, 0x0022, 0x4023, CHECK_PRIVILEGED
)
1496 LDST(ssr
, 0x403e, 0x4037, 0x0032, 0x4033, CHECK_PRIVILEGED
)
1497 LDST(spc
, 0x404e, 0x4047, 0x0042, 0x4043, CHECK_PRIVILEGED
)
1498 ST(sgr
, 0x003a, 0x4032, CHECK_PRIVILEGED
)
1499 LD(sgr
, 0x403a, 0x4036, CHECK_PRIVILEGED CHECK_SH4A
)
1500 LDST(dbr
, 0x40fa, 0x40f6, 0x00fa, 0x40f2, CHECK_PRIVILEGED
)
1501 LDST(mach
, 0x400a, 0x4006, 0x000a, 0x4002, {})
1502 LDST(macl
, 0x401a, 0x4016, 0x001a, 0x4012, {})
1503 LDST(pr
, 0x402a, 0x4026, 0x002a, 0x4022, {})
1504 LDST(fpul
, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED
})
1505 case 0x406a: /* lds Rm,FPSCR */
1507 gen_helper_ld_fpscr(cpu_env
, REG(B11_8
));
1508 ctx
->base
.is_jmp
= DISAS_STOP
;
1510 case 0x4066: /* lds.l @Rm+,FPSCR */
1513 TCGv addr
= tcg_temp_new();
1514 tcg_gen_qemu_ld_i32(addr
, REG(B11_8
), ctx
->memidx
, MO_TESL
);
1515 tcg_gen_addi_i32(REG(B11_8
), REG(B11_8
), 4);
1516 gen_helper_ld_fpscr(cpu_env
, addr
);
1517 tcg_temp_free(addr
);
1518 ctx
->base
.is_jmp
= DISAS_STOP
;
1521 case 0x006a: /* sts FPSCR,Rn */
1523 tcg_gen_andi_i32(REG(B11_8
), cpu_fpscr
, 0x003fffff);
1525 case 0x4062: /* sts FPSCR,@-Rn */
1529 val
= tcg_temp_new();
1530 tcg_gen_andi_i32(val
, cpu_fpscr
, 0x003fffff);
1531 addr
= tcg_temp_new();
1532 tcg_gen_subi_i32(addr
, REG(B11_8
), 4);
1533 tcg_gen_qemu_st_i32(val
, addr
, ctx
->memidx
, MO_TEUL
);
1534 tcg_gen_mov_i32(REG(B11_8
), addr
);
1535 tcg_temp_free(addr
);
1539 case 0x00c3: /* movca.l R0,@Rm */
1541 TCGv val
= tcg_temp_new();
1542 tcg_gen_qemu_ld_i32(val
, REG(B11_8
), ctx
->memidx
, MO_TEUL
);
1543 gen_helper_movcal(cpu_env
, REG(B11_8
), val
);
1544 tcg_gen_qemu_st_i32(REG(0), REG(B11_8
), ctx
->memidx
, MO_TEUL
);
1547 ctx
->has_movcal
= 1;
1549 case 0x40a9: /* movua.l @Rm,R0 */
1551 /* Load non-boundary-aligned data */
1552 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8
), ctx
->memidx
,
1553 MO_TEUL
| MO_UNALN
);
1555 case 0x40e9: /* movua.l @Rm+,R0 */
1557 /* Load non-boundary-aligned data */
1558 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8
), ctx
->memidx
,
1559 MO_TEUL
| MO_UNALN
);
1560 tcg_gen_addi_i32(REG(B11_8
), REG(B11_8
), 4);
1562 case 0x0029: /* movt Rn */
1563 tcg_gen_mov_i32(REG(B11_8
), cpu_sr_t
);
1568 * If (T == 1) R0 -> (Rn)
1571 * The above description doesn't work in a parallel context.
1572 * Since we currently support no smp boards, this implies user-mode.
1573 * But we can still support the official mechanism while user-mode
1574 * is single-threaded. */
1577 TCGLabel
*fail
= gen_new_label();
1578 TCGLabel
*done
= gen_new_label();
1580 if ((tb_cflags(ctx
->base
.tb
) & CF_PARALLEL
)) {
1583 tcg_gen_brcond_i32(TCG_COND_NE
, REG(B11_8
),
1584 cpu_lock_addr
, fail
);
1585 tmp
= tcg_temp_new();
1586 tcg_gen_atomic_cmpxchg_i32(tmp
, REG(B11_8
), cpu_lock_value
,
1587 REG(0), ctx
->memidx
, MO_TEUL
);
1588 tcg_gen_setcond_i32(TCG_COND_EQ
, cpu_sr_t
, tmp
, cpu_lock_value
);
1591 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_lock_addr
, -1, fail
);
1592 tcg_gen_qemu_st_i32(REG(0), REG(B11_8
), ctx
->memidx
, MO_TEUL
);
1593 tcg_gen_movi_i32(cpu_sr_t
, 1);
1597 gen_set_label(fail
);
1598 tcg_gen_movi_i32(cpu_sr_t
, 0);
1600 gen_set_label(done
);
1601 tcg_gen_movi_i32(cpu_lock_addr
, -1);
1608 * When interrupt/exception
1609 * occurred 0 -> LDST
1611 * In a parallel context, we must also save the loaded value
1612 * for use with the cmpxchg that we'll use with movco.l. */
1614 if ((tb_cflags(ctx
->base
.tb
) & CF_PARALLEL
)) {
1615 TCGv tmp
= tcg_temp_new();
1616 tcg_gen_mov_i32(tmp
, REG(B11_8
));
1617 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8
), ctx
->memidx
, MO_TESL
);
1618 tcg_gen_mov_i32(cpu_lock_value
, REG(0));
1619 tcg_gen_mov_i32(cpu_lock_addr
, tmp
);
1622 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8
), ctx
->memidx
, MO_TESL
);
1623 tcg_gen_movi_i32(cpu_lock_addr
, 0);
1626 case 0x0093: /* ocbi @Rn */
1628 gen_helper_ocbi(cpu_env
, REG(B11_8
));
1631 case 0x00a3: /* ocbp @Rn */
1632 case 0x00b3: /* ocbwb @Rn */
1633 /* These instructions are supposed to do nothing in case of
1634 a cache miss. Given that we only partially emulate caches
1635 it is safe to simply ignore them. */
1637 case 0x0083: /* pref @Rn */
1639 case 0x00d3: /* prefi @Rn */
1642 case 0x00e3: /* icbi @Rn */
1645 case 0x00ab: /* synco */
1647 tcg_gen_mb(TCG_MO_ALL
| TCG_BAR_SC
);
1649 case 0x4024: /* rotcl Rn */
1651 TCGv tmp
= tcg_temp_new();
1652 tcg_gen_mov_i32(tmp
, cpu_sr_t
);
1653 tcg_gen_shri_i32(cpu_sr_t
, REG(B11_8
), 31);
1654 tcg_gen_shli_i32(REG(B11_8
), REG(B11_8
), 1);
1655 tcg_gen_or_i32(REG(B11_8
), REG(B11_8
), tmp
);
1659 case 0x4025: /* rotcr Rn */
1661 TCGv tmp
= tcg_temp_new();
1662 tcg_gen_shli_i32(tmp
, cpu_sr_t
, 31);
1663 tcg_gen_andi_i32(cpu_sr_t
, REG(B11_8
), 1);
1664 tcg_gen_shri_i32(REG(B11_8
), REG(B11_8
), 1);
1665 tcg_gen_or_i32(REG(B11_8
), REG(B11_8
), tmp
);
1669 case 0x4004: /* rotl Rn */
1670 tcg_gen_rotli_i32(REG(B11_8
), REG(B11_8
), 1);
1671 tcg_gen_andi_i32(cpu_sr_t
, REG(B11_8
), 0);
1673 case 0x4005: /* rotr Rn */
1674 tcg_gen_andi_i32(cpu_sr_t
, REG(B11_8
), 0);
1675 tcg_gen_rotri_i32(REG(B11_8
), REG(B11_8
), 1);
1677 case 0x4000: /* shll Rn */
1678 case 0x4020: /* shal Rn */
1679 tcg_gen_shri_i32(cpu_sr_t
, REG(B11_8
), 31);
1680 tcg_gen_shli_i32(REG(B11_8
), REG(B11_8
), 1);
1682 case 0x4021: /* shar Rn */
1683 tcg_gen_andi_i32(cpu_sr_t
, REG(B11_8
), 1);
1684 tcg_gen_sari_i32(REG(B11_8
), REG(B11_8
), 1);
1686 case 0x4001: /* shlr Rn */
1687 tcg_gen_andi_i32(cpu_sr_t
, REG(B11_8
), 1);
1688 tcg_gen_shri_i32(REG(B11_8
), REG(B11_8
), 1);
1690 case 0x4008: /* shll2 Rn */
1691 tcg_gen_shli_i32(REG(B11_8
), REG(B11_8
), 2);
1693 case 0x4018: /* shll8 Rn */
1694 tcg_gen_shli_i32(REG(B11_8
), REG(B11_8
), 8);
1696 case 0x4028: /* shll16 Rn */
1697 tcg_gen_shli_i32(REG(B11_8
), REG(B11_8
), 16);
1699 case 0x4009: /* shlr2 Rn */
1700 tcg_gen_shri_i32(REG(B11_8
), REG(B11_8
), 2);
1702 case 0x4019: /* shlr8 Rn */
1703 tcg_gen_shri_i32(REG(B11_8
), REG(B11_8
), 8);
1705 case 0x4029: /* shlr16 Rn */
1706 tcg_gen_shri_i32(REG(B11_8
), REG(B11_8
), 16);
1708 case 0x401b: /* tas.b @Rn */
1710 TCGv val
= tcg_const_i32(0x80);
1711 tcg_gen_atomic_fetch_or_i32(val
, REG(B11_8
), val
,
1712 ctx
->memidx
, MO_UB
);
1713 tcg_gen_setcondi_i32(TCG_COND_EQ
, cpu_sr_t
, val
, 0);
1717 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
1719 tcg_gen_mov_i32(FREG(B11_8
), cpu_fpul
);
1721 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
1723 tcg_gen_mov_i32(cpu_fpul
, FREG(B11_8
));
1725 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
1727 if (ctx
->tbflags
& FPSCR_PR
) {
1729 if (ctx
->opcode
& 0x0100) {
1732 fp
= tcg_temp_new_i64();
1733 gen_helper_float_DT(fp
, cpu_env
, cpu_fpul
);
1734 gen_store_fpr64(ctx
, fp
, B11_8
);
1735 tcg_temp_free_i64(fp
);
1738 gen_helper_float_FT(FREG(B11_8
), cpu_env
, cpu_fpul
);
1741 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1743 if (ctx
->tbflags
& FPSCR_PR
) {
1745 if (ctx
->opcode
& 0x0100) {
1748 fp
= tcg_temp_new_i64();
1749 gen_load_fpr64(ctx
, fp
, B11_8
);
1750 gen_helper_ftrc_DT(cpu_fpul
, cpu_env
, fp
);
1751 tcg_temp_free_i64(fp
);
1754 gen_helper_ftrc_FT(cpu_fpul
, cpu_env
, FREG(B11_8
));
1757 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */
1759 tcg_gen_xori_i32(FREG(B11_8
), FREG(B11_8
), 0x80000000);
1761 case 0xf05d: /* fabs FRn/DRn - FPCSR: Nothing */
1763 tcg_gen_andi_i32(FREG(B11_8
), FREG(B11_8
), 0x7fffffff);
1765 case 0xf06d: /* fsqrt FRn */
1767 if (ctx
->tbflags
& FPSCR_PR
) {
1768 if (ctx
->opcode
& 0x0100) {
1771 TCGv_i64 fp
= tcg_temp_new_i64();
1772 gen_load_fpr64(ctx
, fp
, B11_8
);
1773 gen_helper_fsqrt_DT(fp
, cpu_env
, fp
);
1774 gen_store_fpr64(ctx
, fp
, B11_8
);
1775 tcg_temp_free_i64(fp
);
1777 gen_helper_fsqrt_FT(FREG(B11_8
), cpu_env
, FREG(B11_8
));
1780 case 0xf07d: /* fsrra FRn */
1783 gen_helper_fsrra_FT(FREG(B11_8
), cpu_env
, FREG(B11_8
));
1785 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
1788 tcg_gen_movi_i32(FREG(B11_8
), 0);
1790 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
1793 tcg_gen_movi_i32(FREG(B11_8
), 0x3f800000);
1795 case 0xf0ad: /* fcnvsd FPUL,DRn */
1798 TCGv_i64 fp
= tcg_temp_new_i64();
1799 gen_helper_fcnvsd_FT_DT(fp
, cpu_env
, cpu_fpul
);
1800 gen_store_fpr64(ctx
, fp
, B11_8
);
1801 tcg_temp_free_i64(fp
);
1804 case 0xf0bd: /* fcnvds DRn,FPUL */
1807 TCGv_i64 fp
= tcg_temp_new_i64();
1808 gen_load_fpr64(ctx
, fp
, B11_8
);
1809 gen_helper_fcnvds_DT_FT(cpu_fpul
, cpu_env
, fp
);
1810 tcg_temp_free_i64(fp
);
1813 case 0xf0ed: /* fipr FVm,FVn */
1817 TCGv m
= tcg_const_i32((ctx
->opcode
>> 8) & 3);
1818 TCGv n
= tcg_const_i32((ctx
->opcode
>> 10) & 3);
1819 gen_helper_fipr(cpu_env
, m
, n
);
1825 case 0xf0fd: /* ftrv XMTRX,FVn */
1829 if ((ctx
->opcode
& 0x0300) != 0x0100) {
1832 TCGv n
= tcg_const_i32((ctx
->opcode
>> 10) & 3);
1833 gen_helper_ftrv(cpu_env
, n
);
1840 fprintf(stderr
, "unknown instruction 0x%04x at pc 0x%08x\n",
1841 ctx
->opcode
, ctx
->base
.pc_next
);
1845 if (ctx
->envflags
& TB_FLAG_DELAY_SLOT_MASK
) {
1847 gen_save_cpu_state(ctx
, true);
1848 gen_helper_raise_slot_illegal_instruction(cpu_env
);
1850 gen_save_cpu_state(ctx
, true);
1851 gen_helper_raise_illegal_instruction(cpu_env
);
1853 ctx
->base
.is_jmp
= DISAS_NORETURN
;
1857 gen_save_cpu_state(ctx
, true);
1858 if (ctx
->envflags
& TB_FLAG_DELAY_SLOT_MASK
) {
1859 gen_helper_raise_slot_fpu_disable(cpu_env
);
1861 gen_helper_raise_fpu_disable(cpu_env
);
1863 ctx
->base
.is_jmp
= DISAS_NORETURN
;
1867 static void decode_opc(DisasContext
* ctx
)
1869 uint32_t old_flags
= ctx
->envflags
;
1873 if (old_flags
& TB_FLAG_DELAY_SLOT_MASK
) {
1874 /* go out of the delay slot */
1875 ctx
->envflags
&= ~TB_FLAG_DELAY_SLOT_MASK
;
1877 /* When in an exclusive region, we must continue to the end
1878 for conditional branches. */
1879 if (ctx
->tbflags
& TB_FLAG_GUSA_EXCLUSIVE
1880 && old_flags
& TB_FLAG_DELAY_SLOT_COND
) {
1881 gen_delayed_conditional_jump(ctx
);
1884 /* Otherwise this is probably an invalid gUSA region.
1885 Drop the GUSA bits so the next TB doesn't see them. */
1886 ctx
->envflags
&= ~TB_FLAG_GUSA_MASK
;
1888 tcg_gen_movi_i32(cpu_flags
, ctx
->envflags
);
1889 if (old_flags
& TB_FLAG_DELAY_SLOT_COND
) {
1890 gen_delayed_conditional_jump(ctx
);
1897 #ifdef CONFIG_USER_ONLY
1898 /* For uniprocessors, SH4 uses optimistic restartable atomic sequences.
1899 Upon an interrupt, a real kernel would simply notice magic values in
1900 the registers and reset the PC to the start of the sequence.
1902 For QEMU, we cannot do this in quite the same way. Instead, we notice
1903 the normal start of such a sequence (mov #-x,r15). While we can handle
1904 any sequence via cpu_exec_step_atomic, we can recognize the "normal"
1905 sequences and transform them into atomic operations as seen by the host.
1907 static void decode_gusa(DisasContext
*ctx
, CPUSH4State
*env
)
1910 int ld_adr
, ld_dst
, ld_mop
;
1911 int op_dst
, op_src
, op_opc
;
1912 int mv_src
, mt_dst
, st_src
, st_mop
;
1914 uint32_t pc
= ctx
->base
.pc_next
;
1915 uint32_t pc_end
= ctx
->base
.tb
->cs_base
;
1916 int max_insns
= (pc_end
- pc
) / 2;
1919 /* The state machine below will consume only a few insns.
1920 If there are more than that in a region, fail now. */
1921 if (max_insns
> ARRAY_SIZE(insns
)) {
1925 /* Read all of the insns for the region. */
1926 for (i
= 0; i
< max_insns
; ++i
) {
1927 insns
[i
] = translator_lduw(env
, &ctx
->base
, pc
+ i
* 2);
1930 ld_adr
= ld_dst
= ld_mop
= -1;
1932 op_dst
= op_src
= op_opc
= -1;
1934 st_src
= st_mop
= -1;
1939 do { if (i >= max_insns) goto fail; ctx->opcode = insns[i++]; } while (0)
1942 * Expect a load to begin the region.
1945 switch (ctx
->opcode
& 0xf00f) {
1946 case 0x6000: /* mov.b @Rm,Rn */
1949 case 0x6001: /* mov.w @Rm,Rn */
1952 case 0x6002: /* mov.l @Rm,Rn */
1960 if (ld_adr
== ld_dst
) {
1963 /* Unless we see a mov, any two-operand operation must use ld_dst. */
1967 * Expect an optional register move.
1970 switch (ctx
->opcode
& 0xf00f) {
1971 case 0x6003: /* mov Rm,Rn */
1973 * Here we want to recognize ld_dst being saved for later consumption,
1974 * or for another input register being copied so that ld_dst need not
1975 * be clobbered during the operation.
1979 if (op_dst
== ld_dst
) {
1980 /* Overwriting the load output. */
1983 if (mv_src
!= ld_dst
) {
1984 /* Copying a new input; constrain op_src to match the load. */
1990 /* Put back and re-examine as operation. */
1995 * Expect the operation.
1998 switch (ctx
->opcode
& 0xf00f) {
1999 case 0x300c: /* add Rm,Rn */
2000 op_opc
= INDEX_op_add_i32
;
2002 case 0x2009: /* and Rm,Rn */
2003 op_opc
= INDEX_op_and_i32
;
2005 case 0x200a: /* xor Rm,Rn */
2006 op_opc
= INDEX_op_xor_i32
;
2008 case 0x200b: /* or Rm,Rn */
2009 op_opc
= INDEX_op_or_i32
;
2011 /* The operation register should be as expected, and the
2012 other input cannot depend on the load. */
2013 if (op_dst
!= B11_8
) {
2017 /* Unconstrainted input. */
2019 } else if (op_src
== B7_4
) {
2020 /* Constrained input matched load. All operations are
2021 commutative; "swap" them by "moving" the load output
2022 to the (implicit) first argument and the move source
2023 to the (explicit) second argument. */
2028 op_arg
= REG(op_src
);
2031 case 0x6007: /* not Rm,Rn */
2032 if (ld_dst
!= B7_4
|| mv_src
>= 0) {
2036 op_opc
= INDEX_op_xor_i32
;
2037 op_arg
= tcg_const_i32(-1);
2040 case 0x7000 ... 0x700f: /* add #imm,Rn */
2041 if (op_dst
!= B11_8
|| mv_src
>= 0) {
2044 op_opc
= INDEX_op_add_i32
;
2045 op_arg
= tcg_const_i32(B7_0s
);
2048 case 0x3000: /* cmp/eq Rm,Rn */
2049 /* Looking for the middle of a compare-and-swap sequence,
2050 beginning with the compare. Operands can be either order,
2051 but with only one overlapping the load. */
2052 if ((ld_dst
== B11_8
) + (ld_dst
== B7_4
) != 1 || mv_src
>= 0) {
2055 op_opc
= INDEX_op_setcond_i32
; /* placeholder */
2056 op_src
= (ld_dst
== B11_8
? B7_4
: B11_8
);
2057 op_arg
= REG(op_src
);
2060 switch (ctx
->opcode
& 0xff00) {
2061 case 0x8b00: /* bf label */
2062 case 0x8f00: /* bf/s label */
2063 if (pc
+ (i
+ 1 + B7_0s
) * 2 != pc_end
) {
2066 if ((ctx
->opcode
& 0xff00) == 0x8b00) { /* bf label */
2069 /* We're looking to unconditionally modify Rn with the
2070 result of the comparison, within the delay slot of
2071 the branch. This is used by older gcc. */
2073 if ((ctx
->opcode
& 0xf0ff) == 0x0029) { /* movt Rn */
2085 case 0x2008: /* tst Rm,Rn */
2086 /* Looking for a compare-and-swap against zero. */
2087 if (ld_dst
!= B11_8
|| ld_dst
!= B7_4
|| mv_src
>= 0) {
2090 op_opc
= INDEX_op_setcond_i32
;
2091 op_arg
= tcg_const_i32(0);
2094 if ((ctx
->opcode
& 0xff00) != 0x8900 /* bt label */
2095 || pc
+ (i
+ 1 + B7_0s
) * 2 != pc_end
) {
2101 /* Put back and re-examine as store. */
2108 /* The store must be the last insn. */
2109 if (i
!= max_insns
- 1) {
2113 switch (ctx
->opcode
& 0xf00f) {
2114 case 0x2000: /* mov.b Rm,@Rn */
2117 case 0x2001: /* mov.w Rm,@Rn */
2120 case 0x2002: /* mov.l Rm,@Rn */
2126 /* The store must match the load. */
2127 if (ld_adr
!= B11_8
|| st_mop
!= (ld_mop
& MO_SIZE
)) {
2135 * Emit the operation.
2139 /* No operation found. Look for exchange pattern. */
2140 if (st_src
== ld_dst
|| mv_src
>= 0) {
2143 tcg_gen_atomic_xchg_i32(REG(ld_dst
), REG(ld_adr
), REG(st_src
),
2144 ctx
->memidx
, ld_mop
);
2147 case INDEX_op_add_i32
:
2148 if (op_dst
!= st_src
) {
2151 if (op_dst
== ld_dst
&& st_mop
== MO_UL
) {
2152 tcg_gen_atomic_add_fetch_i32(REG(ld_dst
), REG(ld_adr
),
2153 op_arg
, ctx
->memidx
, ld_mop
);
2155 tcg_gen_atomic_fetch_add_i32(REG(ld_dst
), REG(ld_adr
),
2156 op_arg
, ctx
->memidx
, ld_mop
);
2157 if (op_dst
!= ld_dst
) {
2158 /* Note that mop sizes < 4 cannot use add_fetch
2159 because it won't carry into the higher bits. */
2160 tcg_gen_add_i32(REG(op_dst
), REG(ld_dst
), op_arg
);
2165 case INDEX_op_and_i32
:
2166 if (op_dst
!= st_src
) {
2169 if (op_dst
== ld_dst
) {
2170 tcg_gen_atomic_and_fetch_i32(REG(ld_dst
), REG(ld_adr
),
2171 op_arg
, ctx
->memidx
, ld_mop
);
2173 tcg_gen_atomic_fetch_and_i32(REG(ld_dst
), REG(ld_adr
),
2174 op_arg
, ctx
->memidx
, ld_mop
);
2175 tcg_gen_and_i32(REG(op_dst
), REG(ld_dst
), op_arg
);
2179 case INDEX_op_or_i32
:
2180 if (op_dst
!= st_src
) {
2183 if (op_dst
== ld_dst
) {
2184 tcg_gen_atomic_or_fetch_i32(REG(ld_dst
), REG(ld_adr
),
2185 op_arg
, ctx
->memidx
, ld_mop
);
2187 tcg_gen_atomic_fetch_or_i32(REG(ld_dst
), REG(ld_adr
),
2188 op_arg
, ctx
->memidx
, ld_mop
);
2189 tcg_gen_or_i32(REG(op_dst
), REG(ld_dst
), op_arg
);
2193 case INDEX_op_xor_i32
:
2194 if (op_dst
!= st_src
) {
2197 if (op_dst
== ld_dst
) {
2198 tcg_gen_atomic_xor_fetch_i32(REG(ld_dst
), REG(ld_adr
),
2199 op_arg
, ctx
->memidx
, ld_mop
);
2201 tcg_gen_atomic_fetch_xor_i32(REG(ld_dst
), REG(ld_adr
),
2202 op_arg
, ctx
->memidx
, ld_mop
);
2203 tcg_gen_xor_i32(REG(op_dst
), REG(ld_dst
), op_arg
);
2207 case INDEX_op_setcond_i32
:
2208 if (st_src
== ld_dst
) {
2211 tcg_gen_atomic_cmpxchg_i32(REG(ld_dst
), REG(ld_adr
), op_arg
,
2212 REG(st_src
), ctx
->memidx
, ld_mop
);
2213 tcg_gen_setcond_i32(TCG_COND_EQ
, cpu_sr_t
, REG(ld_dst
), op_arg
);
2215 tcg_gen_mov_i32(REG(mt_dst
), cpu_sr_t
);
2220 g_assert_not_reached();
2223 /* If op_src is not a valid register, then op_arg was a constant. */
2224 if (op_src
< 0 && op_arg
) {
2225 tcg_temp_free_i32(op_arg
);
2228 /* The entire region has been translated. */
2229 ctx
->envflags
&= ~TB_FLAG_GUSA_MASK
;
2230 ctx
->base
.pc_next
= pc_end
;
2231 ctx
->base
.num_insns
+= max_insns
- 1;
2235 qemu_log_mask(LOG_UNIMP
, "Unrecognized gUSA sequence %08x-%08x\n",
2238 /* Restart with the EXCLUSIVE bit set, within a TB run via
2239 cpu_exec_step_atomic holding the exclusive lock. */
2240 ctx
->envflags
|= TB_FLAG_GUSA_EXCLUSIVE
;
2241 gen_save_cpu_state(ctx
, false);
2242 gen_helper_exclusive(cpu_env
);
2243 ctx
->base
.is_jmp
= DISAS_NORETURN
;
2245 /* We're not executing an instruction, but we must report one for the
2246 purposes of accounting within the TB. We might as well report the
2247 entire region consumed via ctx->base.pc_next so that it's immediately
2248 available in the disassembly dump. */
2249 ctx
->base
.pc_next
= pc_end
;
2250 ctx
->base
.num_insns
+= max_insns
- 1;
2254 static void sh4_tr_init_disas_context(DisasContextBase
*dcbase
, CPUState
*cs
)
2256 DisasContext
*ctx
= container_of(dcbase
, DisasContext
, base
);
2257 CPUSH4State
*env
= cs
->env_ptr
;
2261 ctx
->tbflags
= tbflags
= ctx
->base
.tb
->flags
;
2262 ctx
->envflags
= tbflags
& TB_FLAG_ENVFLAGS_MASK
;
2263 ctx
->memidx
= (tbflags
& (1u << SR_MD
)) == 0 ? 1 : 0;
2264 /* We don't know if the delayed pc came from a dynamic or static branch,
2265 so assume it is a dynamic branch. */
2266 ctx
->delayed_pc
= -1; /* use delayed pc from env pointer */
2267 ctx
->features
= env
->features
;
2268 ctx
->has_movcal
= (tbflags
& TB_FLAG_PENDING_MOVCA
);
2269 ctx
->gbank
= ((tbflags
& (1 << SR_MD
)) &&
2270 (tbflags
& (1 << SR_RB
))) * 0x10;
2271 ctx
->fbank
= tbflags
& FPSCR_FR
? 0x10 : 0;
2273 #ifdef CONFIG_USER_ONLY
2274 if (tbflags
& TB_FLAG_GUSA_MASK
) {
2275 /* In gUSA exclusive region. */
2276 uint32_t pc
= ctx
->base
.pc_next
;
2277 uint32_t pc_end
= ctx
->base
.tb
->cs_base
;
2278 int backup
= sextract32(ctx
->tbflags
, TB_FLAG_GUSA_SHIFT
, 8);
2279 int max_insns
= (pc_end
- pc
) / 2;
2281 if (pc
!= pc_end
+ backup
|| max_insns
< 2) {
2282 /* This is a malformed gUSA region. Don't do anything special,
2283 since the interpreter is likely to get confused. */
2284 ctx
->envflags
&= ~TB_FLAG_GUSA_MASK
;
2285 } else if (tbflags
& TB_FLAG_GUSA_EXCLUSIVE
) {
2286 /* Regardless of single-stepping or the end of the page,
2287 we must complete execution of the gUSA region while
2288 holding the exclusive lock. */
2289 ctx
->base
.max_insns
= max_insns
;
2295 /* Since the ISA is fixed-width, we can bound by the number
2296 of instructions remaining on the page. */
2297 bound
= -(ctx
->base
.pc_next
| TARGET_PAGE_MASK
) / 2;
2298 ctx
->base
.max_insns
= MIN(ctx
->base
.max_insns
, bound
);
2301 static void sh4_tr_tb_start(DisasContextBase
*dcbase
, CPUState
*cs
)
2305 static void sh4_tr_insn_start(DisasContextBase
*dcbase
, CPUState
*cs
)
2307 DisasContext
*ctx
= container_of(dcbase
, DisasContext
, base
);
2309 tcg_gen_insn_start(ctx
->base
.pc_next
, ctx
->envflags
);
2312 static void sh4_tr_translate_insn(DisasContextBase
*dcbase
, CPUState
*cs
)
2314 CPUSH4State
*env
= cs
->env_ptr
;
2315 DisasContext
*ctx
= container_of(dcbase
, DisasContext
, base
);
2317 #ifdef CONFIG_USER_ONLY
2318 if (unlikely(ctx
->envflags
& TB_FLAG_GUSA_MASK
)
2319 && !(ctx
->envflags
& TB_FLAG_GUSA_EXCLUSIVE
)) {
2320 /* We're in an gUSA region, and we have not already fallen
2321 back on using an exclusive region. Attempt to parse the
2322 region into a single supported atomic operation. Failure
2323 is handled within the parser by raising an exception to
2324 retry using an exclusive region. */
2325 decode_gusa(ctx
, env
);
2330 ctx
->opcode
= translator_lduw(env
, &ctx
->base
, ctx
->base
.pc_next
);
2332 ctx
->base
.pc_next
+= 2;
2335 static void sh4_tr_tb_stop(DisasContextBase
*dcbase
, CPUState
*cs
)
2337 DisasContext
*ctx
= container_of(dcbase
, DisasContext
, base
);
2339 if (ctx
->tbflags
& TB_FLAG_GUSA_EXCLUSIVE
) {
2340 /* Ending the region of exclusivity. Clear the bits. */
2341 ctx
->envflags
&= ~TB_FLAG_GUSA_MASK
;
2344 switch (ctx
->base
.is_jmp
) {
2346 gen_save_cpu_state(ctx
, true);
2347 tcg_gen_exit_tb(NULL
, 0);
2350 case DISAS_TOO_MANY
:
2351 gen_save_cpu_state(ctx
, false);
2352 gen_goto_tb(ctx
, 0, ctx
->base
.pc_next
);
2354 case DISAS_NORETURN
:
2357 g_assert_not_reached();
2361 static void sh4_tr_disas_log(const DisasContextBase
*dcbase
,
2362 CPUState
*cs
, FILE *logfile
)
2364 fprintf(logfile
, "IN: %s\n", lookup_symbol(dcbase
->pc_first
));
2365 target_disas(logfile
, cs
, dcbase
->pc_first
, dcbase
->tb
->size
);
2368 static const TranslatorOps sh4_tr_ops
= {
2369 .init_disas_context
= sh4_tr_init_disas_context
,
2370 .tb_start
= sh4_tr_tb_start
,
2371 .insn_start
= sh4_tr_insn_start
,
2372 .translate_insn
= sh4_tr_translate_insn
,
2373 .tb_stop
= sh4_tr_tb_stop
,
2374 .disas_log
= sh4_tr_disas_log
,
2377 void gen_intermediate_code(CPUState
*cs
, TranslationBlock
*tb
, int max_insns
,
2378 target_ulong pc
, void *host_pc
)
2382 translator_loop(cs
, tb
, max_insns
, pc
, host_pc
, &sh4_tr_ops
, &ctx
.base
);