1 /*
2 * SH4 translation
3 *
4 * Copyright (c) 2005 Samuel Tardieu
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "qemu/osdep.h"
21 #include "cpu.h"
22 #include "tcg/tcg-op.h"
23 #include "exec/helper-proto.h"
24 #include "exec/helper-gen.h"
25 #include "exec/translation-block.h"
26 #include "exec/translator.h"
27 #include "exec/target_page.h"
28 #include "exec/log.h"
29 #include "qemu/qemu-print.h"
30
31 #define HELPER_H "helper.h"
32 #include "exec/helper-info.c.inc"
33 #undef HELPER_H
34
35
36 typedef struct DisasContext {
37 DisasContextBase base;
38
39 uint32_t tbflags; /* should stay unmodified during the TB translation */
40 uint32_t envflags; /* should stay in sync with env->flags using TCG ops */
41 int memidx;
42 int gbank;
43 int fbank;
44 uint32_t delayed_pc;
45 uint32_t features;
46
47 uint16_t opcode;
48
49 bool has_movcal;
50 } DisasContext;
51
52 #if defined(CONFIG_USER_ONLY)
53 #define IS_USER(ctx) 1
54 #define UNALIGN(C) (ctx->tbflags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN)
55 #else
56 #define IS_USER(ctx) (!(ctx->tbflags & (1u << SR_MD)))
57 #define UNALIGN(C) MO_ALIGN
58 #endif
59
60 /* Target-specific values for ctx->base.is_jmp. */
61 /* We want to exit back to the cpu loop for some reason.
62 Usually this is to recognize interrupts immediately. */
63 #define DISAS_STOP DISAS_TARGET_0
64
65 /* global register indexes */
66 static TCGv cpu_gregs[32];
67 static TCGv cpu_sr, cpu_sr_m, cpu_sr_q, cpu_sr_t;
68 static TCGv cpu_pc, cpu_ssr, cpu_spc, cpu_gbr;
69 static TCGv cpu_vbr, cpu_sgr, cpu_dbr, cpu_mach, cpu_macl;
70 static TCGv cpu_pr, cpu_fpscr, cpu_fpul;
71 static TCGv cpu_lock_addr, cpu_lock_value;
72 static TCGv cpu_fregs[32];
73
74 /* internal register indexes */
75 static TCGv cpu_flags, cpu_delayed_pc, cpu_delayed_cond;
76
sh4_translate_init(void)77 void sh4_translate_init(void)
78 {
79 int i;
80 static const char * const gregnames[24] = {
81 "R0_BANK0", "R1_BANK0", "R2_BANK0", "R3_BANK0",
82 "R4_BANK0", "R5_BANK0", "R6_BANK0", "R7_BANK0",
83 "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
84 "R0_BANK1", "R1_BANK1", "R2_BANK1", "R3_BANK1",
85 "R4_BANK1", "R5_BANK1", "R6_BANK1", "R7_BANK1"
86 };
87 static const char * const fregnames[32] = {
88 "FPR0_BANK0", "FPR1_BANK0", "FPR2_BANK0", "FPR3_BANK0",
89 "FPR4_BANK0", "FPR5_BANK0", "FPR6_BANK0", "FPR7_BANK0",
90 "FPR8_BANK0", "FPR9_BANK0", "FPR10_BANK0", "FPR11_BANK0",
91 "FPR12_BANK0", "FPR13_BANK0", "FPR14_BANK0", "FPR15_BANK0",
92 "FPR0_BANK1", "FPR1_BANK1", "FPR2_BANK1", "FPR3_BANK1",
93 "FPR4_BANK1", "FPR5_BANK1", "FPR6_BANK1", "FPR7_BANK1",
94 "FPR8_BANK1", "FPR9_BANK1", "FPR10_BANK1", "FPR11_BANK1",
95 "FPR12_BANK1", "FPR13_BANK1", "FPR14_BANK1", "FPR15_BANK1",
96 };
97
98 for (i = 0; i < 24; i++) {
99 cpu_gregs[i] = tcg_global_mem_new_i32(tcg_env,
100 offsetof(CPUSH4State, gregs[i]),
101 gregnames[i]);
102 }
103 memcpy(cpu_gregs + 24, cpu_gregs + 8, 8 * sizeof(TCGv));
104
105 cpu_pc = tcg_global_mem_new_i32(tcg_env,
106 offsetof(CPUSH4State, pc), "PC");
107 cpu_sr = tcg_global_mem_new_i32(tcg_env,
108 offsetof(CPUSH4State, sr), "SR");
109 cpu_sr_m = tcg_global_mem_new_i32(tcg_env,
110 offsetof(CPUSH4State, sr_m), "SR_M");
111 cpu_sr_q = tcg_global_mem_new_i32(tcg_env,
112 offsetof(CPUSH4State, sr_q), "SR_Q");
113 cpu_sr_t = tcg_global_mem_new_i32(tcg_env,
114 offsetof(CPUSH4State, sr_t), "SR_T");
115 cpu_ssr = tcg_global_mem_new_i32(tcg_env,
116 offsetof(CPUSH4State, ssr), "SSR");
117 cpu_spc = tcg_global_mem_new_i32(tcg_env,
118 offsetof(CPUSH4State, spc), "SPC");
119 cpu_gbr = tcg_global_mem_new_i32(tcg_env,
120 offsetof(CPUSH4State, gbr), "GBR");
121 cpu_vbr = tcg_global_mem_new_i32(tcg_env,
122 offsetof(CPUSH4State, vbr), "VBR");
123 cpu_sgr = tcg_global_mem_new_i32(tcg_env,
124 offsetof(CPUSH4State, sgr), "SGR");
125 cpu_dbr = tcg_global_mem_new_i32(tcg_env,
126 offsetof(CPUSH4State, dbr), "DBR");
127 cpu_mach = tcg_global_mem_new_i32(tcg_env,
128 offsetof(CPUSH4State, mach), "MACH");
129 cpu_macl = tcg_global_mem_new_i32(tcg_env,
130 offsetof(CPUSH4State, macl), "MACL");
131 cpu_pr = tcg_global_mem_new_i32(tcg_env,
132 offsetof(CPUSH4State, pr), "PR");
133 cpu_fpscr = tcg_global_mem_new_i32(tcg_env,
134 offsetof(CPUSH4State, fpscr), "FPSCR");
135 cpu_fpul = tcg_global_mem_new_i32(tcg_env,
136 offsetof(CPUSH4State, fpul), "FPUL");
137
138 cpu_flags = tcg_global_mem_new_i32(tcg_env,
139 offsetof(CPUSH4State, flags), "_flags_");
140 cpu_delayed_pc = tcg_global_mem_new_i32(tcg_env,
141 offsetof(CPUSH4State, delayed_pc),
142 "_delayed_pc_");
143 cpu_delayed_cond = tcg_global_mem_new_i32(tcg_env,
144 offsetof(CPUSH4State,
145 delayed_cond),
146 "_delayed_cond_");
147 cpu_lock_addr = tcg_global_mem_new_i32(tcg_env,
148 offsetof(CPUSH4State, lock_addr),
149 "_lock_addr_");
150 cpu_lock_value = tcg_global_mem_new_i32(tcg_env,
151 offsetof(CPUSH4State, lock_value),
152 "_lock_value_");
153
154 for (i = 0; i < 32; i++)
155 cpu_fregs[i] = tcg_global_mem_new_i32(tcg_env,
156 offsetof(CPUSH4State, fregs[i]),
157 fregnames[i]);
158 }
159
superh_cpu_dump_state(CPUState * cs,FILE * f,int flags)160 void superh_cpu_dump_state(CPUState *cs, FILE *f, int flags)
161 {
162 CPUSH4State *env = cpu_env(cs);
163 int i;
164
165 qemu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n",
166 env->pc, cpu_read_sr(env), env->pr, env->fpscr);
167 qemu_fprintf(f, "spc=0x%08x ssr=0x%08x gbr=0x%08x vbr=0x%08x\n",
168 env->spc, env->ssr, env->gbr, env->vbr);
169 qemu_fprintf(f, "sgr=0x%08x dbr=0x%08x delayed_pc=0x%08x fpul=0x%08x\n",
170 env->sgr, env->dbr, env->delayed_pc, env->fpul);
171 for (i = 0; i < 24; i += 4) {
172 qemu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
173 i, env->gregs[i], i + 1, env->gregs[i + 1],
174 i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
175 }
176 if (env->flags & TB_FLAG_DELAY_SLOT) {
177 qemu_fprintf(f, "in delay slot (delayed_pc=0x%08x)\n",
178 env->delayed_pc);
179 } else if (env->flags & TB_FLAG_DELAY_SLOT_COND) {
180 qemu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n",
181 env->delayed_pc);
182 } else if (env->flags & TB_FLAG_DELAY_SLOT_RTE) {
183 qemu_fprintf(f, "in rte delay slot (delayed_pc=0x%08x)\n",
184 env->delayed_pc);
185 }
186 }
187
gen_read_sr(TCGv dst)188 static void gen_read_sr(TCGv dst)
189 {
190 TCGv t0 = tcg_temp_new();
191 tcg_gen_shli_i32(t0, cpu_sr_q, SR_Q);
192 tcg_gen_or_i32(dst, dst, t0);
193 tcg_gen_shli_i32(t0, cpu_sr_m, SR_M);
194 tcg_gen_or_i32(dst, dst, t0);
195 tcg_gen_shli_i32(t0, cpu_sr_t, SR_T);
196 tcg_gen_or_i32(dst, cpu_sr, t0);
197 }
198
gen_write_sr(TCGv src)199 static void gen_write_sr(TCGv src)
200 {
201 tcg_gen_andi_i32(cpu_sr, src,
202 ~((1u << SR_Q) | (1u << SR_M) | (1u << SR_T)));
203 tcg_gen_extract_i32(cpu_sr_q, src, SR_Q, 1);
204 tcg_gen_extract_i32(cpu_sr_m, src, SR_M, 1);
205 tcg_gen_extract_i32(cpu_sr_t, src, SR_T, 1);
206 }
207
gen_save_cpu_state(DisasContext * ctx,bool save_pc)208 static inline void gen_save_cpu_state(DisasContext *ctx, bool save_pc)
209 {
210 if (save_pc) {
211 tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
212 }
213 if (ctx->delayed_pc != (uint32_t) -1) {
214 tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
215 }
216 if ((ctx->tbflags & TB_FLAG_ENVFLAGS_MASK) != ctx->envflags) {
217 tcg_gen_movi_i32(cpu_flags, ctx->envflags);
218 }
219 }
220
use_exit_tb(DisasContext * ctx)221 static inline bool use_exit_tb(DisasContext *ctx)
222 {
223 return (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) != 0;
224 }
225
use_goto_tb(DisasContext * ctx,target_ulong dest)226 static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
227 {
228 if (use_exit_tb(ctx)) {
229 return false;
230 }
231 return translator_use_goto_tb(&ctx->base, dest);
232 }
233
gen_goto_tb(DisasContext * ctx,int n,target_ulong dest)234 static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
235 {
236 if (use_goto_tb(ctx, dest)) {
237 tcg_gen_goto_tb(n);
238 tcg_gen_movi_i32(cpu_pc, dest);
239 tcg_gen_exit_tb(ctx->base.tb, n);
240 } else {
241 tcg_gen_movi_i32(cpu_pc, dest);
242 if (use_exit_tb(ctx)) {
243 tcg_gen_exit_tb(NULL, 0);
244 } else {
245 tcg_gen_lookup_and_goto_ptr();
246 }
247 }
248 ctx->base.is_jmp = DISAS_NORETURN;
249 }
250
gen_jump(DisasContext * ctx)251 static void gen_jump(DisasContext * ctx)
252 {
253 if (ctx->delayed_pc == -1) {
254 /* Target is not statically known, it comes necessarily from a
255 delayed jump as immediate jump are conditinal jumps */
256 tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc);
257 tcg_gen_discard_i32(cpu_delayed_pc);
258 if (use_exit_tb(ctx)) {
259 tcg_gen_exit_tb(NULL, 0);
260 } else {
261 tcg_gen_lookup_and_goto_ptr();
262 }
263 ctx->base.is_jmp = DISAS_NORETURN;
264 } else {
265 gen_goto_tb(ctx, 0, ctx->delayed_pc);
266 }
267 }
268
269 /* Immediate conditional jump (bt or bf) */
gen_conditional_jump(DisasContext * ctx,target_ulong dest,bool jump_if_true)270 static void gen_conditional_jump(DisasContext *ctx, target_ulong dest,
271 bool jump_if_true)
272 {
273 TCGLabel *l1 = gen_new_label();
274 TCGCond cond_not_taken = jump_if_true ? TCG_COND_EQ : TCG_COND_NE;
275
276 if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
277 /* When in an exclusive region, we must continue to the end.
278 Therefore, exit the region on a taken branch, but otherwise
279 fall through to the next instruction. */
280 tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1);
281 tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~TB_FLAG_GUSA_MASK);
282 /* Note that this won't actually use a goto_tb opcode because we
283 disallow it in use_goto_tb, but it handles exit + singlestep. */
284 gen_goto_tb(ctx, 0, dest);
285 gen_set_label(l1);
286 ctx->base.is_jmp = DISAS_NEXT;
287 return;
288 }
289
290 gen_save_cpu_state(ctx, false);
291 tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1);
292 gen_goto_tb(ctx, 0, dest);
293 gen_set_label(l1);
294 gen_goto_tb(ctx, 1, ctx->base.pc_next + 2);
295 ctx->base.is_jmp = DISAS_NORETURN;
296 }
297
298 /* Delayed conditional jump (bt or bf) */
gen_delayed_conditional_jump(DisasContext * ctx)299 static void gen_delayed_conditional_jump(DisasContext * ctx)
300 {
301 TCGLabel *l1 = gen_new_label();
302 TCGv ds = tcg_temp_new();
303
304 tcg_gen_mov_i32(ds, cpu_delayed_cond);
305 tcg_gen_discard_i32(cpu_delayed_cond);
306
307 if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
308 /* When in an exclusive region, we must continue to the end.
309 Therefore, exit the region on a taken branch, but otherwise
310 fall through to the next instruction. */
311 tcg_gen_brcondi_i32(TCG_COND_EQ, ds, 0, l1);
312
313 /* Leave the gUSA region. */
314 tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~TB_FLAG_GUSA_MASK);
315 gen_jump(ctx);
316
317 gen_set_label(l1);
318 ctx->base.is_jmp = DISAS_NEXT;
319 return;
320 }
321
322 tcg_gen_brcondi_i32(TCG_COND_NE, ds, 0, l1);
323 gen_goto_tb(ctx, 1, ctx->base.pc_next + 2);
324 gen_set_label(l1);
325 gen_jump(ctx);
326 }
327
gen_load_fpr64(DisasContext * ctx,TCGv_i64 t,int reg)328 static inline void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
329 {
330 /* We have already signaled illegal instruction for odd Dr. */
331 tcg_debug_assert((reg & 1) == 0);
332 reg ^= ctx->fbank;
333 tcg_gen_concat_i32_i64(t, cpu_fregs[reg + 1], cpu_fregs[reg]);
334 }
335
gen_store_fpr64(DisasContext * ctx,TCGv_i64 t,int reg)336 static inline void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
337 {
338 /* We have already signaled illegal instruction for odd Dr. */
339 tcg_debug_assert((reg & 1) == 0);
340 reg ^= ctx->fbank;
341 tcg_gen_extr_i64_i32(cpu_fregs[reg + 1], cpu_fregs[reg], t);
342 }
343
344 #define B3_0 (ctx->opcode & 0xf)
345 #define B6_4 ((ctx->opcode >> 4) & 0x7)
346 #define B7_4 ((ctx->opcode >> 4) & 0xf)
347 #define B7_0 (ctx->opcode & 0xff)
348 #define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff))
349 #define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \
350 (ctx->opcode & 0xfff))
351 #define B11_8 ((ctx->opcode >> 8) & 0xf)
352 #define B15_12 ((ctx->opcode >> 12) & 0xf)
353
354 #define REG(x) cpu_gregs[(x) ^ ctx->gbank]
355 #define ALTREG(x) cpu_gregs[(x) ^ ctx->gbank ^ 0x10]
356 #define FREG(x) cpu_fregs[(x) ^ ctx->fbank]
357
358 #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
359
360 #define CHECK_NOT_DELAY_SLOT \
361 if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) { \
362 goto do_illegal_slot; \
363 }
364
365 #define CHECK_PRIVILEGED \
366 if (IS_USER(ctx)) { \
367 goto do_illegal; \
368 }
369
370 #define CHECK_FPU_ENABLED \
371 if (ctx->tbflags & (1u << SR_FD)) { \
372 goto do_fpu_disabled; \
373 }
374
375 #define CHECK_FPSCR_PR_0 \
376 if (ctx->tbflags & FPSCR_PR) { \
377 goto do_illegal; \
378 }
379
380 #define CHECK_FPSCR_PR_1 \
381 if (!(ctx->tbflags & FPSCR_PR)) { \
382 goto do_illegal; \
383 }
384
385 #define CHECK_SH4A \
386 if (!(ctx->features & SH_FEATURE_SH4A)) { \
387 goto do_illegal; \
388 }
389
_decode_opc(DisasContext * ctx)390 static void _decode_opc(DisasContext * ctx)
391 {
392 /* This code tries to make movcal emulation sufficiently
393 accurate for Linux purposes. This instruction writes
394 memory, and prior to that, always allocates a cache line.
395 It is used in two contexts:
396 - in memcpy, where data is copied in blocks, the first write
397 of to a block uses movca.l for performance.
398 - in arch/sh/mm/cache-sh4.c, movcal.l + ocbi combination is used
399 to flush the cache. Here, the data written by movcal.l is never
400 written to memory, and the data written is just bogus.
401
402 To simulate this, we simulate movcal.l, we store the value to memory,
403 but we also remember the previous content. If we see ocbi, we check
404 if movcal.l for that address was done previously. If so, the write should
405 not have hit the memory, so we restore the previous content.
406 When we see an instruction that is neither movca.l
407 nor ocbi, the previous content is discarded.
408
409 To optimize, we only try to flush stores when we're at the start of
410 TB, or if we already saw movca.l in this TB and did not flush stores
411 yet. */
412 if (ctx->has_movcal)
413 {
414 int opcode = ctx->opcode & 0xf0ff;
415 if (opcode != 0x0093 /* ocbi */
416 && opcode != 0x00c3 /* movca.l */)
417 {
418 gen_helper_discard_movcal_backup(tcg_env);
419 ctx->has_movcal = 0;
420 }
421 }
422
423 #if 0
424 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
425 #endif
426
427 switch (ctx->opcode) {
428 case 0x0019: /* div0u */
429 tcg_gen_movi_i32(cpu_sr_m, 0);
430 tcg_gen_movi_i32(cpu_sr_q, 0);
431 tcg_gen_movi_i32(cpu_sr_t, 0);
432 return;
433 case 0x000b: /* rts */
434 CHECK_NOT_DELAY_SLOT
435 tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr);
436 ctx->envflags |= TB_FLAG_DELAY_SLOT;
437 ctx->delayed_pc = (uint32_t) - 1;
438 return;
439 case 0x0028: /* clrmac */
440 tcg_gen_movi_i32(cpu_mach, 0);
441 tcg_gen_movi_i32(cpu_macl, 0);
442 return;
443 case 0x0048: /* clrs */
444 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(1u << SR_S));
445 return;
446 case 0x0008: /* clrt */
447 tcg_gen_movi_i32(cpu_sr_t, 0);
448 return;
449 case 0x0038: /* ldtlb */
450 CHECK_PRIVILEGED
451 gen_helper_ldtlb(tcg_env);
452 return;
453 case 0x002b: /* rte */
454 CHECK_PRIVILEGED
455 CHECK_NOT_DELAY_SLOT
456 gen_write_sr(cpu_ssr);
457 tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
458 ctx->envflags |= TB_FLAG_DELAY_SLOT_RTE;
459 ctx->delayed_pc = (uint32_t) - 1;
460 ctx->base.is_jmp = DISAS_STOP;
461 return;
462 case 0x0058: /* sets */
463 tcg_gen_ori_i32(cpu_sr, cpu_sr, (1u << SR_S));
464 return;
465 case 0x0018: /* sett */
466 tcg_gen_movi_i32(cpu_sr_t, 1);
467 return;
468 case 0xfbfd: /* frchg */
469 CHECK_FPSCR_PR_0
470 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR);
471 ctx->base.is_jmp = DISAS_STOP;
472 return;
473 case 0xf3fd: /* fschg */
474 CHECK_FPSCR_PR_0
475 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ);
476 ctx->base.is_jmp = DISAS_STOP;
477 return;
478 case 0xf7fd: /* fpchg */
479 CHECK_SH4A
480 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_PR);
481 ctx->base.is_jmp = DISAS_STOP;
482 return;
483 case 0x0009: /* nop */
484 return;
485 case 0x001b: /* sleep */
486 CHECK_PRIVILEGED
487 tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next + 2);
488 gen_helper_sleep(tcg_env);
489 return;
490 }
491
492 switch (ctx->opcode & 0xf000) {
493 case 0x1000: /* mov.l Rm,@(disp,Rn) */
494 {
495 TCGv addr = tcg_temp_new();
496 tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4);
497 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
498 MO_TEUL | UNALIGN(ctx));
499 }
500 return;
501 case 0x5000: /* mov.l @(disp,Rm),Rn */
502 {
503 TCGv addr = tcg_temp_new();
504 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4);
505 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx,
506 MO_TESL | UNALIGN(ctx));
507 }
508 return;
509 case 0xe000: /* mov #imm,Rn */
510 #ifdef CONFIG_USER_ONLY
511 /*
512 * Detect the start of a gUSA region (mov #-n, r15).
513 * If so, update envflags and end the TB. This will allow us
514 * to see the end of the region (stored in R0) in the next TB.
515 */
516 if (B11_8 == 15 && B7_0s < 0 &&
517 (tb_cflags(ctx->base.tb) & CF_PARALLEL)) {
518 ctx->envflags =
519 deposit32(ctx->envflags, TB_FLAG_GUSA_SHIFT, 8, B7_0s);
520 ctx->base.is_jmp = DISAS_STOP;
521 }
522 #endif
523 tcg_gen_movi_i32(REG(B11_8), B7_0s);
524 return;
525 case 0x9000: /* mov.w @(disp,PC),Rn */
526 CHECK_NOT_DELAY_SLOT
527 {
528 TCGv addr = tcg_constant_i32(ctx->base.pc_next + 4 + B7_0 * 2);
529 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx,
530 MO_TESW | MO_ALIGN);
531 }
532 return;
533 case 0xd000: /* mov.l @(disp,PC),Rn */
534 CHECK_NOT_DELAY_SLOT
535 {
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,
538 MO_TESL | MO_ALIGN);
539 }
540 return;
541 case 0x7000: /* add #imm,Rn */
542 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), B7_0s);
543 return;
544 case 0xa000: /* bra disp */
545 CHECK_NOT_DELAY_SLOT
546 ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2;
547 ctx->envflags |= TB_FLAG_DELAY_SLOT;
548 return;
549 case 0xb000: /* bsr disp */
550 CHECK_NOT_DELAY_SLOT
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;
554 return;
555 }
556
557 switch (ctx->opcode & 0xf00f) {
558 case 0x6003: /* mov Rm,Rn */
559 tcg_gen_mov_i32(REG(B11_8), REG(B7_4));
560 return;
561 case 0x2000: /* mov.b Rm,@Rn */
562 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_UB);
563 return;
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));
567 return;
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));
571 return;
572 case 0x6000: /* mov.b @Rm,Rn */
573 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB);
574 return;
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));
578 return;
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));
582 return;
583 case 0x2004: /* mov.b Rm,@-Rn */
584 {
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 */
590 }
591 return;
592 case 0x2005: /* mov.w Rm,@-Rn */
593 {
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);
599 }
600 return;
601 case 0x2006: /* mov.l Rm,@-Rn */
602 {
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);
608 }
609 return;
610 case 0x6004: /* mov.b @Rm+,Rn */
611 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB);
612 if ( B11_8 != B7_4 )
613 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1);
614 return;
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));
618 if ( B11_8 != B7_4 )
619 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
620 return;
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));
624 if ( B11_8 != B7_4 )
625 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
626 return;
627 case 0x0004: /* mov.b Rm,@(R0,Rn) */
628 {
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);
632 }
633 return;
634 case 0x0005: /* mov.w Rm,@(R0,Rn) */
635 {
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));
640 }
641 return;
642 case 0x0006: /* mov.l Rm,@(R0,Rn) */
643 {
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));
648 }
649 return;
650 case 0x000c: /* mov.b @(R0,Rm),Rn */
651 {
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);
655 }
656 return;
657 case 0x000d: /* mov.w @(R0,Rm),Rn */
658 {
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));
663 }
664 return;
665 case 0x000e: /* mov.l @(R0,Rm),Rn */
666 {
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));
671 }
672 return;
673 case 0x6008: /* swap.b Rm,Rn */
674 {
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);
678 }
679 return;
680 case 0x6009: /* swap.w Rm,Rn */
681 tcg_gen_rotli_i32(REG(B11_8), REG(B7_4), 16);
682 return;
683 case 0x200d: /* xtrct Rm,Rn */
684 {
685 TCGv high, low;
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);
691 }
692 return;
693 case 0x300c: /* add Rm,Rn */
694 tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4));
695 return;
696 case 0x300e: /* addc Rm,Rn */
697 tcg_gen_addcio_i32(REG(B11_8), cpu_sr_t,
698 REG(B11_8), REG(B7_4), cpu_sr_t);
699 return;
700 case 0x300f: /* addv Rm,Rn */
701 {
702 TCGv Rn = REG(B11_8);
703 TCGv Rm = REG(B7_4);
704 TCGv result, t1, t2;
705
706 result = tcg_temp_new();
707 t1 = tcg_temp_new();
708 t2 = tcg_temp_new();
709 tcg_gen_add_i32(result, Rm, Rn);
710 /* T = ((Rn ^ Rm) & (Result ^ Rn)) >> 31 */
711 tcg_gen_xor_i32(t1, result, Rn);
712 tcg_gen_xor_i32(t2, Rm, Rn);
713 tcg_gen_andc_i32(cpu_sr_t, t1, t2);
714 tcg_gen_shri_i32(cpu_sr_t, cpu_sr_t, 31);
715 tcg_gen_mov_i32(Rn, result);
716 }
717 return;
718 case 0x2009: /* and Rm,Rn */
719 tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4));
720 return;
721 case 0x3000: /* cmp/eq Rm,Rn */
722 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), REG(B7_4));
723 return;
724 case 0x3003: /* cmp/ge Rm,Rn */
725 tcg_gen_setcond_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), REG(B7_4));
726 return;
727 case 0x3007: /* cmp/gt Rm,Rn */
728 tcg_gen_setcond_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), REG(B7_4));
729 return;
730 case 0x3006: /* cmp/hi Rm,Rn */
731 tcg_gen_setcond_i32(TCG_COND_GTU, cpu_sr_t, REG(B11_8), REG(B7_4));
732 return;
733 case 0x3002: /* cmp/hs Rm,Rn */
734 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_sr_t, REG(B11_8), REG(B7_4));
735 return;
736 case 0x200c: /* cmp/str Rm,Rn */
737 {
738 TCGv cmp1 = tcg_temp_new();
739 TCGv cmp2 = tcg_temp_new();
740 tcg_gen_xor_i32(cmp2, REG(B7_4), REG(B11_8));
741 tcg_gen_subi_i32(cmp1, cmp2, 0x01010101);
742 tcg_gen_andc_i32(cmp1, cmp1, cmp2);
743 tcg_gen_andi_i32(cmp1, cmp1, 0x80808080);
744 tcg_gen_setcondi_i32(TCG_COND_NE, cpu_sr_t, cmp1, 0);
745 }
746 return;
747 case 0x2007: /* div0s Rm,Rn */
748 tcg_gen_shri_i32(cpu_sr_q, REG(B11_8), 31); /* SR_Q */
749 tcg_gen_shri_i32(cpu_sr_m, REG(B7_4), 31); /* SR_M */
750 tcg_gen_xor_i32(cpu_sr_t, cpu_sr_q, cpu_sr_m); /* SR_T */
751 return;
752 case 0x3004: /* div1 Rm,Rn */
753 {
754 TCGv t0 = tcg_temp_new();
755 TCGv t1 = tcg_temp_new();
756 TCGv t2 = tcg_temp_new();
757 TCGv zero = tcg_constant_i32(0);
758
759 /* shift left arg1, saving the bit being pushed out and inserting
760 T on the right */
761 tcg_gen_shri_i32(t0, REG(B11_8), 31);
762 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
763 tcg_gen_or_i32(REG(B11_8), REG(B11_8), cpu_sr_t);
764
765 /* Add or subtract arg0 from arg1 depending if Q == M. To avoid
766 using 64-bit temps, we compute arg0's high part from q ^ m, so
767 that it is 0x00000000 when adding the value or 0xffffffff when
768 subtracting it. */
769 tcg_gen_xor_i32(t1, cpu_sr_q, cpu_sr_m);
770 tcg_gen_subi_i32(t1, t1, 1);
771 tcg_gen_neg_i32(t2, REG(B7_4));
772 tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, zero, REG(B7_4), t2);
773 tcg_gen_add2_i32(REG(B11_8), t1, REG(B11_8), zero, t2, t1);
774
775 /* compute T and Q depending on carry */
776 tcg_gen_andi_i32(t1, t1, 1);
777 tcg_gen_xor_i32(t1, t1, t0);
778 tcg_gen_xori_i32(cpu_sr_t, t1, 1);
779 tcg_gen_xor_i32(cpu_sr_q, cpu_sr_m, t1);
780 }
781 return;
782 case 0x300d: /* dmuls.l Rm,Rn */
783 tcg_gen_muls2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
784 return;
785 case 0x3005: /* dmulu.l Rm,Rn */
786 tcg_gen_mulu2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8));
787 return;
788 case 0x600e: /* exts.b Rm,Rn */
789 tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4));
790 return;
791 case 0x600f: /* exts.w Rm,Rn */
792 tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4));
793 return;
794 case 0x600c: /* extu.b Rm,Rn */
795 tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4));
796 return;
797 case 0x600d: /* extu.w Rm,Rn */
798 tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4));
799 return;
800 case 0x000f: /* mac.l @Rm+,@Rn+ */
801 {
802 TCGv arg0, arg1;
803 arg0 = tcg_temp_new();
804 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx,
805 MO_TESL | MO_ALIGN);
806 arg1 = tcg_temp_new();
807 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx,
808 MO_TESL | MO_ALIGN);
809 gen_helper_macl(tcg_env, arg0, arg1);
810 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
811 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
812 }
813 return;
814 case 0x400f: /* mac.w @Rm+,@Rn+ */
815 {
816 TCGv arg0, arg1;
817 arg0 = tcg_temp_new();
818 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx,
819 MO_TESW | MO_ALIGN);
820 arg1 = tcg_temp_new();
821 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx,
822 MO_TESW | MO_ALIGN);
823 gen_helper_macw(tcg_env, arg0, arg1);
824 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2);
825 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
826 }
827 return;
828 case 0x0007: /* mul.l Rm,Rn */
829 tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8));
830 return;
831 case 0x200f: /* muls.w Rm,Rn */
832 {
833 TCGv arg0, arg1;
834 arg0 = tcg_temp_new();
835 tcg_gen_ext16s_i32(arg0, REG(B7_4));
836 arg1 = tcg_temp_new();
837 tcg_gen_ext16s_i32(arg1, REG(B11_8));
838 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
839 }
840 return;
841 case 0x200e: /* mulu.w Rm,Rn */
842 {
843 TCGv arg0, arg1;
844 arg0 = tcg_temp_new();
845 tcg_gen_ext16u_i32(arg0, REG(B7_4));
846 arg1 = tcg_temp_new();
847 tcg_gen_ext16u_i32(arg1, REG(B11_8));
848 tcg_gen_mul_i32(cpu_macl, arg0, arg1);
849 }
850 return;
851 case 0x600b: /* neg Rm,Rn */
852 tcg_gen_neg_i32(REG(B11_8), REG(B7_4));
853 return;
854 case 0x600a: /* negc Rm,Rn */
855 {
856 TCGv t0 = tcg_constant_i32(0);
857 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t,
858 REG(B7_4), t0, cpu_sr_t, t0);
859 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t,
860 t0, t0, REG(B11_8), cpu_sr_t);
861 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1);
862 }
863 return;
864 case 0x6007: /* not Rm,Rn */
865 tcg_gen_not_i32(REG(B11_8), REG(B7_4));
866 return;
867 case 0x200b: /* or Rm,Rn */
868 tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4));
869 return;
870 case 0x400c: /* shad Rm,Rn */
871 {
872 TCGv t0 = tcg_temp_new();
873 TCGv t1 = tcg_temp_new();
874 TCGv t2 = tcg_temp_new();
875
876 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
877
878 /* positive case: shift to the left */
879 tcg_gen_shl_i32(t1, REG(B11_8), t0);
880
881 /* negative case: shift to the right in two steps to
882 correctly handle the -32 case */
883 tcg_gen_xori_i32(t0, t0, 0x1f);
884 tcg_gen_sar_i32(t2, REG(B11_8), t0);
885 tcg_gen_sari_i32(t2, t2, 1);
886
887 /* select between the two cases */
888 tcg_gen_movi_i32(t0, 0);
889 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
890 }
891 return;
892 case 0x400d: /* shld Rm,Rn */
893 {
894 TCGv t0 = tcg_temp_new();
895 TCGv t1 = tcg_temp_new();
896 TCGv t2 = tcg_temp_new();
897
898 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
899
900 /* positive case: shift to the left */
901 tcg_gen_shl_i32(t1, REG(B11_8), t0);
902
903 /* negative case: shift to the right in two steps to
904 correctly handle the -32 case */
905 tcg_gen_xori_i32(t0, t0, 0x1f);
906 tcg_gen_shr_i32(t2, REG(B11_8), t0);
907 tcg_gen_shri_i32(t2, t2, 1);
908
909 /* select between the two cases */
910 tcg_gen_movi_i32(t0, 0);
911 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
912 }
913 return;
914 case 0x3008: /* sub Rm,Rn */
915 tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4));
916 return;
917 case 0x300a: /* subc Rm,Rn */
918 {
919 TCGv t0, t1;
920 t0 = tcg_constant_tl(0);
921 t1 = tcg_temp_new();
922 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0);
923 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t,
924 REG(B11_8), t0, t1, cpu_sr_t);
925 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1);
926 }
927 return;
928 case 0x300b: /* subv Rm,Rn */
929 {
930 TCGv Rn = REG(B11_8);
931 TCGv Rm = REG(B7_4);
932 TCGv result, t1, t2;
933
934 result = tcg_temp_new();
935 t1 = tcg_temp_new();
936 t2 = tcg_temp_new();
937 tcg_gen_sub_i32(result, Rn, Rm);
938 /* T = ((Rn ^ Rm) & (Result ^ Rn)) >> 31 */
939 tcg_gen_xor_i32(t1, result, Rn);
940 tcg_gen_xor_i32(t2, Rn, Rm);
941 tcg_gen_and_i32(t1, t1, t2);
942 tcg_gen_shri_i32(cpu_sr_t, t1, 31);
943 tcg_gen_mov_i32(Rn, result);
944 }
945 return;
946 case 0x2008: /* tst Rm,Rn */
947 {
948 TCGv val = tcg_temp_new();
949 tcg_gen_and_i32(val, REG(B7_4), REG(B11_8));
950 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
951 }
952 return;
953 case 0x200a: /* xor Rm,Rn */
954 tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4));
955 return;
956 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
957 CHECK_FPU_ENABLED
958 if (ctx->tbflags & FPSCR_SZ) {
959 int xsrc = XHACK(B7_4);
960 int xdst = XHACK(B11_8);
961 tcg_gen_mov_i32(FREG(xdst), FREG(xsrc));
962 tcg_gen_mov_i32(FREG(xdst + 1), FREG(xsrc + 1));
963 } else {
964 tcg_gen_mov_i32(FREG(B11_8), FREG(B7_4));
965 }
966 return;
967 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
968 CHECK_FPU_ENABLED
969 if (ctx->tbflags & FPSCR_SZ) {
970 TCGv_i64 fp = tcg_temp_new_i64();
971 gen_load_fpr64(ctx, fp, XHACK(B7_4));
972 tcg_gen_qemu_st_i64(fp, REG(B11_8), ctx->memidx,
973 MO_TEUQ | MO_ALIGN);
974 } else {
975 tcg_gen_qemu_st_i32(FREG(B7_4), REG(B11_8), ctx->memidx,
976 MO_TEUL | MO_ALIGN);
977 }
978 return;
979 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
980 CHECK_FPU_ENABLED
981 if (ctx->tbflags & FPSCR_SZ) {
982 TCGv_i64 fp = tcg_temp_new_i64();
983 tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx,
984 MO_TEUQ | MO_ALIGN);
985 gen_store_fpr64(ctx, fp, XHACK(B11_8));
986 } else {
987 tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx,
988 MO_TEUL | MO_ALIGN);
989 }
990 return;
991 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
992 CHECK_FPU_ENABLED
993 if (ctx->tbflags & FPSCR_SZ) {
994 TCGv_i64 fp = tcg_temp_new_i64();
995 tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx,
996 MO_TEUQ | MO_ALIGN);
997 gen_store_fpr64(ctx, fp, XHACK(B11_8));
998 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 8);
999 } else {
1000 tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx,
1001 MO_TEUL | MO_ALIGN);
1002 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
1003 }
1004 return;
1005 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
1006 CHECK_FPU_ENABLED
1007 {
1008 TCGv addr = tcg_temp_new_i32();
1009 if (ctx->tbflags & FPSCR_SZ) {
1010 TCGv_i64 fp = tcg_temp_new_i64();
1011 gen_load_fpr64(ctx, fp, XHACK(B7_4));
1012 tcg_gen_subi_i32(addr, REG(B11_8), 8);
1013 tcg_gen_qemu_st_i64(fp, addr, ctx->memidx,
1014 MO_TEUQ | MO_ALIGN);
1015 } else {
1016 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1017 tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx,
1018 MO_TEUL | MO_ALIGN);
1019 }
1020 tcg_gen_mov_i32(REG(B11_8), addr);
1021 }
1022 return;
1023 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
1024 CHECK_FPU_ENABLED
1025 {
1026 TCGv addr = tcg_temp_new_i32();
1027 tcg_gen_add_i32(addr, REG(B7_4), REG(0));
1028 if (ctx->tbflags & FPSCR_SZ) {
1029 TCGv_i64 fp = tcg_temp_new_i64();
1030 tcg_gen_qemu_ld_i64(fp, addr, ctx->memidx,
1031 MO_TEUQ | MO_ALIGN);
1032 gen_store_fpr64(ctx, fp, XHACK(B11_8));
1033 } else {
1034 tcg_gen_qemu_ld_i32(FREG(B11_8), addr, ctx->memidx,
1035 MO_TEUL | MO_ALIGN);
1036 }
1037 }
1038 return;
1039 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
1040 CHECK_FPU_ENABLED
1041 {
1042 TCGv addr = tcg_temp_new();
1043 tcg_gen_add_i32(addr, REG(B11_8), REG(0));
1044 if (ctx->tbflags & FPSCR_SZ) {
1045 TCGv_i64 fp = tcg_temp_new_i64();
1046 gen_load_fpr64(ctx, fp, XHACK(B7_4));
1047 tcg_gen_qemu_st_i64(fp, addr, ctx->memidx,
1048 MO_TEUQ | MO_ALIGN);
1049 } else {
1050 tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx,
1051 MO_TEUL | MO_ALIGN);
1052 }
1053 }
1054 return;
1055 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1056 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1057 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1058 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */
1059 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1060 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1061 {
1062 CHECK_FPU_ENABLED
1063 if (ctx->tbflags & FPSCR_PR) {
1064 TCGv_i64 fp0, fp1;
1065
1066 if (ctx->opcode & 0x0110) {
1067 goto do_illegal;
1068 }
1069 fp0 = tcg_temp_new_i64();
1070 fp1 = tcg_temp_new_i64();
1071 gen_load_fpr64(ctx, fp0, B11_8);
1072 gen_load_fpr64(ctx, fp1, B7_4);
1073 switch (ctx->opcode & 0xf00f) {
1074 case 0xf000: /* fadd Rm,Rn */
1075 gen_helper_fadd_DT(fp0, tcg_env, fp0, fp1);
1076 break;
1077 case 0xf001: /* fsub Rm,Rn */
1078 gen_helper_fsub_DT(fp0, tcg_env, fp0, fp1);
1079 break;
1080 case 0xf002: /* fmul Rm,Rn */
1081 gen_helper_fmul_DT(fp0, tcg_env, fp0, fp1);
1082 break;
1083 case 0xf003: /* fdiv Rm,Rn */
1084 gen_helper_fdiv_DT(fp0, tcg_env, fp0, fp1);
1085 break;
1086 case 0xf004: /* fcmp/eq Rm,Rn */
1087 gen_helper_fcmp_eq_DT(cpu_sr_t, tcg_env, fp0, fp1);
1088 return;
1089 case 0xf005: /* fcmp/gt Rm,Rn */
1090 gen_helper_fcmp_gt_DT(cpu_sr_t, tcg_env, fp0, fp1);
1091 return;
1092 }
1093 gen_store_fpr64(ctx, fp0, B11_8);
1094 } else {
1095 switch (ctx->opcode & 0xf00f) {
1096 case 0xf000: /* fadd Rm,Rn */
1097 gen_helper_fadd_FT(FREG(B11_8), tcg_env,
1098 FREG(B11_8), FREG(B7_4));
1099 break;
1100 case 0xf001: /* fsub Rm,Rn */
1101 gen_helper_fsub_FT(FREG(B11_8), tcg_env,
1102 FREG(B11_8), FREG(B7_4));
1103 break;
1104 case 0xf002: /* fmul Rm,Rn */
1105 gen_helper_fmul_FT(FREG(B11_8), tcg_env,
1106 FREG(B11_8), FREG(B7_4));
1107 break;
1108 case 0xf003: /* fdiv Rm,Rn */
1109 gen_helper_fdiv_FT(FREG(B11_8), tcg_env,
1110 FREG(B11_8), FREG(B7_4));
1111 break;
1112 case 0xf004: /* fcmp/eq Rm,Rn */
1113 gen_helper_fcmp_eq_FT(cpu_sr_t, tcg_env,
1114 FREG(B11_8), FREG(B7_4));
1115 return;
1116 case 0xf005: /* fcmp/gt Rm,Rn */
1117 gen_helper_fcmp_gt_FT(cpu_sr_t, tcg_env,
1118 FREG(B11_8), FREG(B7_4));
1119 return;
1120 }
1121 }
1122 }
1123 return;
1124 case 0xf00e: /* fmac FR0,RM,Rn */
1125 CHECK_FPU_ENABLED
1126 CHECK_FPSCR_PR_0
1127 gen_helper_fmac_FT(FREG(B11_8), tcg_env,
1128 FREG(0), FREG(B7_4), FREG(B11_8));
1129 return;
1130 }
1131
1132 switch (ctx->opcode & 0xff00) {
1133 case 0xc900: /* and #imm,R0 */
1134 tcg_gen_andi_i32(REG(0), REG(0), B7_0);
1135 return;
1136 case 0xcd00: /* and.b #imm,@(R0,GBR) */
1137 {
1138 TCGv addr, val;
1139 addr = tcg_temp_new();
1140 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1141 val = tcg_temp_new();
1142 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1143 tcg_gen_andi_i32(val, val, B7_0);
1144 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1145 }
1146 return;
1147 case 0x8b00: /* bf label */
1148 CHECK_NOT_DELAY_SLOT
1149 gen_conditional_jump(ctx, ctx->base.pc_next + 4 + B7_0s * 2, false);
1150 return;
1151 case 0x8f00: /* bf/s label */
1152 CHECK_NOT_DELAY_SLOT
1153 tcg_gen_xori_i32(cpu_delayed_cond, cpu_sr_t, 1);
1154 ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2;
1155 ctx->envflags |= TB_FLAG_DELAY_SLOT_COND;
1156 return;
1157 case 0x8900: /* bt label */
1158 CHECK_NOT_DELAY_SLOT
1159 gen_conditional_jump(ctx, ctx->base.pc_next + 4 + B7_0s * 2, true);
1160 return;
1161 case 0x8d00: /* bt/s label */
1162 CHECK_NOT_DELAY_SLOT
1163 tcg_gen_mov_i32(cpu_delayed_cond, cpu_sr_t);
1164 ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2;
1165 ctx->envflags |= TB_FLAG_DELAY_SLOT_COND;
1166 return;
1167 case 0x8800: /* cmp/eq #imm,R0 */
1168 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(0), B7_0s);
1169 return;
1170 case 0xc400: /* mov.b @(disp,GBR),R0 */
1171 {
1172 TCGv addr = tcg_temp_new();
1173 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
1174 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB);
1175 }
1176 return;
1177 case 0xc500: /* mov.w @(disp,GBR),R0 */
1178 {
1179 TCGv addr = tcg_temp_new();
1180 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
1181 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW | MO_ALIGN);
1182 }
1183 return;
1184 case 0xc600: /* mov.l @(disp,GBR),R0 */
1185 {
1186 TCGv addr = tcg_temp_new();
1187 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
1188 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESL | MO_ALIGN);
1189 }
1190 return;
1191 case 0xc000: /* mov.b R0,@(disp,GBR) */
1192 {
1193 TCGv addr = tcg_temp_new();
1194 tcg_gen_addi_i32(addr, cpu_gbr, B7_0);
1195 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB);
1196 }
1197 return;
1198 case 0xc100: /* mov.w R0,@(disp,GBR) */
1199 {
1200 TCGv addr = tcg_temp_new();
1201 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2);
1202 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW | MO_ALIGN);
1203 }
1204 return;
1205 case 0xc200: /* mov.l R0,@(disp,GBR) */
1206 {
1207 TCGv addr = tcg_temp_new();
1208 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4);
1209 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUL | MO_ALIGN);
1210 }
1211 return;
1212 case 0x8000: /* mov.b R0,@(disp,Rn) */
1213 {
1214 TCGv addr = tcg_temp_new();
1215 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
1216 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB);
1217 }
1218 return;
1219 case 0x8100: /* mov.w R0,@(disp,Rn) */
1220 {
1221 TCGv addr = tcg_temp_new();
1222 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
1223 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx,
1224 MO_TEUW | UNALIGN(ctx));
1225 }
1226 return;
1227 case 0x8400: /* mov.b @(disp,Rn),R0 */
1228 {
1229 TCGv addr = tcg_temp_new();
1230 tcg_gen_addi_i32(addr, REG(B7_4), B3_0);
1231 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB);
1232 }
1233 return;
1234 case 0x8500: /* mov.w @(disp,Rn),R0 */
1235 {
1236 TCGv addr = tcg_temp_new();
1237 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
1238 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx,
1239 MO_TESW | UNALIGN(ctx));
1240 }
1241 return;
1242 case 0xc700: /* mova @(disp,PC),R0 */
1243 CHECK_NOT_DELAY_SLOT
1244 tcg_gen_movi_i32(REG(0), ((ctx->base.pc_next & 0xfffffffc) +
1245 4 + B7_0 * 4) & ~3);
1246 return;
1247 case 0xcb00: /* or #imm,R0 */
1248 tcg_gen_ori_i32(REG(0), REG(0), B7_0);
1249 return;
1250 case 0xcf00: /* or.b #imm,@(R0,GBR) */
1251 {
1252 TCGv addr, val;
1253 addr = tcg_temp_new();
1254 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1255 val = tcg_temp_new();
1256 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1257 tcg_gen_ori_i32(val, val, B7_0);
1258 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1259 }
1260 return;
1261 case 0xc300: /* trapa #imm */
1262 {
1263 TCGv imm;
1264 CHECK_NOT_DELAY_SLOT
1265 gen_save_cpu_state(ctx, true);
1266 imm = tcg_constant_i32(B7_0);
1267 gen_helper_trapa(tcg_env, imm);
1268 ctx->base.is_jmp = DISAS_NORETURN;
1269 }
1270 return;
1271 case 0xc800: /* tst #imm,R0 */
1272 {
1273 TCGv val = tcg_temp_new();
1274 tcg_gen_andi_i32(val, REG(0), B7_0);
1275 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
1276 }
1277 return;
1278 case 0xcc00: /* tst.b #imm,@(R0,GBR) */
1279 {
1280 TCGv val = tcg_temp_new();
1281 tcg_gen_add_i32(val, REG(0), cpu_gbr);
1282 tcg_gen_qemu_ld_i32(val, val, ctx->memidx, MO_UB);
1283 tcg_gen_andi_i32(val, val, B7_0);
1284 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0);
1285 }
1286 return;
1287 case 0xca00: /* xor #imm,R0 */
1288 tcg_gen_xori_i32(REG(0), REG(0), B7_0);
1289 return;
1290 case 0xce00: /* xor.b #imm,@(R0,GBR) */
1291 {
1292 TCGv addr, val;
1293 addr = tcg_temp_new();
1294 tcg_gen_add_i32(addr, REG(0), cpu_gbr);
1295 val = tcg_temp_new();
1296 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB);
1297 tcg_gen_xori_i32(val, val, B7_0);
1298 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB);
1299 }
1300 return;
1301 }
1302
1303 switch (ctx->opcode & 0xf08f) {
1304 case 0x408e: /* ldc Rm,Rn_BANK */
1305 CHECK_PRIVILEGED
1306 tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8));
1307 return;
1308 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
1309 CHECK_PRIVILEGED
1310 tcg_gen_qemu_ld_i32(ALTREG(B6_4), REG(B11_8), ctx->memidx,
1311 MO_TESL | MO_ALIGN);
1312 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1313 return;
1314 case 0x0082: /* stc Rm_BANK,Rn */
1315 CHECK_PRIVILEGED
1316 tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4));
1317 return;
1318 case 0x4083: /* stc.l Rm_BANK,@-Rn */
1319 CHECK_PRIVILEGED
1320 {
1321 TCGv addr = tcg_temp_new();
1322 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1323 tcg_gen_qemu_st_i32(ALTREG(B6_4), addr, ctx->memidx,
1324 MO_TEUL | MO_ALIGN);
1325 tcg_gen_mov_i32(REG(B11_8), addr);
1326 }
1327 return;
1328 }
1329
1330 switch (ctx->opcode & 0xf0ff) {
1331 case 0x0023: /* braf Rn */
1332 CHECK_NOT_DELAY_SLOT
1333 tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->base.pc_next + 4);
1334 ctx->envflags |= TB_FLAG_DELAY_SLOT;
1335 ctx->delayed_pc = (uint32_t) - 1;
1336 return;
1337 case 0x0003: /* bsrf Rn */
1338 CHECK_NOT_DELAY_SLOT
1339 tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
1340 tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr);
1341 ctx->envflags |= TB_FLAG_DELAY_SLOT;
1342 ctx->delayed_pc = (uint32_t) - 1;
1343 return;
1344 case 0x4015: /* cmp/pl Rn */
1345 tcg_gen_setcondi_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), 0);
1346 return;
1347 case 0x4011: /* cmp/pz Rn */
1348 tcg_gen_setcondi_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), 0);
1349 return;
1350 case 0x4010: /* dt Rn */
1351 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1);
1352 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), 0);
1353 return;
1354 case 0x402b: /* jmp @Rn */
1355 CHECK_NOT_DELAY_SLOT
1356 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
1357 ctx->envflags |= TB_FLAG_DELAY_SLOT;
1358 ctx->delayed_pc = (uint32_t) - 1;
1359 return;
1360 case 0x400b: /* jsr @Rn */
1361 CHECK_NOT_DELAY_SLOT
1362 tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
1363 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
1364 ctx->envflags |= TB_FLAG_DELAY_SLOT;
1365 ctx->delayed_pc = (uint32_t) - 1;
1366 return;
1367 case 0x400e: /* ldc Rm,SR */
1368 CHECK_PRIVILEGED
1369 {
1370 TCGv val = tcg_temp_new();
1371 tcg_gen_andi_i32(val, REG(B11_8), 0x700083f3);
1372 gen_write_sr(val);
1373 ctx->base.is_jmp = DISAS_STOP;
1374 }
1375 return;
1376 case 0x4007: /* ldc.l @Rm+,SR */
1377 CHECK_PRIVILEGED
1378 {
1379 TCGv val = tcg_temp_new();
1380 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx,
1381 MO_TESL | MO_ALIGN);
1382 tcg_gen_andi_i32(val, val, 0x700083f3);
1383 gen_write_sr(val);
1384 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1385 ctx->base.is_jmp = DISAS_STOP;
1386 }
1387 return;
1388 case 0x0002: /* stc SR,Rn */
1389 CHECK_PRIVILEGED
1390 gen_read_sr(REG(B11_8));
1391 return;
1392 case 0x4003: /* stc SR,@-Rn */
1393 CHECK_PRIVILEGED
1394 {
1395 TCGv addr = tcg_temp_new();
1396 TCGv val = tcg_temp_new();
1397 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1398 gen_read_sr(val);
1399 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL | MO_ALIGN);
1400 tcg_gen_mov_i32(REG(B11_8), addr);
1401 }
1402 return;
1403 #define LD(reg,ldnum,ldpnum,prechk) \
1404 case ldnum: \
1405 prechk \
1406 tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \
1407 return; \
1408 case ldpnum: \
1409 prechk \
1410 tcg_gen_qemu_ld_i32(cpu_##reg, REG(B11_8), ctx->memidx, \
1411 MO_TESL | MO_ALIGN); \
1412 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \
1413 return;
1414 #define ST(reg,stnum,stpnum,prechk) \
1415 case stnum: \
1416 prechk \
1417 tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \
1418 return; \
1419 case stpnum: \
1420 prechk \
1421 { \
1422 TCGv addr = tcg_temp_new(); \
1423 tcg_gen_subi_i32(addr, REG(B11_8), 4); \
1424 tcg_gen_qemu_st_i32(cpu_##reg, addr, ctx->memidx, \
1425 MO_TEUL | MO_ALIGN); \
1426 tcg_gen_mov_i32(REG(B11_8), addr); \
1427 } \
1428 return;
1429 #define LDST(reg,ldnum,ldpnum,stnum,stpnum,prechk) \
1430 LD(reg,ldnum,ldpnum,prechk) \
1431 ST(reg,stnum,stpnum,prechk)
1432 LDST(gbr, 0x401e, 0x4017, 0x0012, 0x4013, {})
1433 LDST(vbr, 0x402e, 0x4027, 0x0022, 0x4023, CHECK_PRIVILEGED)
1434 LDST(ssr, 0x403e, 0x4037, 0x0032, 0x4033, CHECK_PRIVILEGED)
1435 LDST(spc, 0x404e, 0x4047, 0x0042, 0x4043, CHECK_PRIVILEGED)
1436 ST(sgr, 0x003a, 0x4032, CHECK_PRIVILEGED)
1437 LD(sgr, 0x403a, 0x4036, CHECK_PRIVILEGED CHECK_SH4A)
1438 LDST(dbr, 0x40fa, 0x40f6, 0x00fa, 0x40f2, CHECK_PRIVILEGED)
1439 LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {})
1440 LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {})
1441 LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {})
1442 LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED})
1443 case 0x406a: /* lds Rm,FPSCR */
1444 CHECK_FPU_ENABLED
1445 gen_helper_ld_fpscr(tcg_env, REG(B11_8));
1446 ctx->base.is_jmp = DISAS_STOP;
1447 return;
1448 case 0x4066: /* lds.l @Rm+,FPSCR */
1449 CHECK_FPU_ENABLED
1450 {
1451 TCGv addr = tcg_temp_new();
1452 tcg_gen_qemu_ld_i32(addr, REG(B11_8), ctx->memidx,
1453 MO_TESL | MO_ALIGN);
1454 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1455 gen_helper_ld_fpscr(tcg_env, addr);
1456 ctx->base.is_jmp = DISAS_STOP;
1457 }
1458 return;
1459 case 0x006a: /* sts FPSCR,Rn */
1460 CHECK_FPU_ENABLED
1461 tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff);
1462 return;
1463 case 0x4062: /* sts FPSCR,@-Rn */
1464 CHECK_FPU_ENABLED
1465 {
1466 TCGv addr, val;
1467 val = tcg_temp_new();
1468 tcg_gen_andi_i32(val, cpu_fpscr, 0x003fffff);
1469 addr = tcg_temp_new();
1470 tcg_gen_subi_i32(addr, REG(B11_8), 4);
1471 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL | MO_ALIGN);
1472 tcg_gen_mov_i32(REG(B11_8), addr);
1473 }
1474 return;
1475 case 0x00c3: /* movca.l R0,@Rm */
1476 {
1477 TCGv val = tcg_temp_new();
1478 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx,
1479 MO_TEUL | MO_ALIGN);
1480 gen_helper_movcal(tcg_env, REG(B11_8), val);
1481 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx,
1482 MO_TEUL | MO_ALIGN);
1483 }
1484 ctx->has_movcal = 1;
1485 return;
1486 case 0x40a9: /* movua.l @Rm,R0 */
1487 CHECK_SH4A
1488 /* Load non-boundary-aligned data */
1489 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx,
1490 MO_TEUL | MO_UNALN);
1491 return;
1492 case 0x40e9: /* movua.l @Rm+,R0 */
1493 CHECK_SH4A
1494 /* Load non-boundary-aligned data */
1495 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx,
1496 MO_TEUL | MO_UNALN);
1497 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
1498 return;
1499 case 0x0029: /* movt Rn */
1500 tcg_gen_mov_i32(REG(B11_8), cpu_sr_t);
1501 return;
1502 case 0x0073:
1503 /* MOVCO.L
1504 * LDST -> T
1505 * If (T == 1) R0 -> (Rn)
1506 * 0 -> LDST
1507 *
1508 * The above description doesn't work in a parallel context.
1509 * Since we currently support no smp boards, this implies user-mode.
1510 * But we can still support the official mechanism while user-mode
1511 * is single-threaded. */
1512 CHECK_SH4A
1513 {
1514 TCGLabel *fail = gen_new_label();
1515 TCGLabel *done = gen_new_label();
1516
1517 if ((tb_cflags(ctx->base.tb) & CF_PARALLEL)) {
1518 TCGv tmp;
1519
1520 tcg_gen_brcond_i32(TCG_COND_NE, REG(B11_8),
1521 cpu_lock_addr, fail);
1522 tmp = tcg_temp_new();
1523 tcg_gen_atomic_cmpxchg_i32(tmp, REG(B11_8), cpu_lock_value,
1524 REG(0), ctx->memidx,
1525 MO_TEUL | MO_ALIGN);
1526 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, tmp, cpu_lock_value);
1527 } else {
1528 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_lock_addr, -1, fail);
1529 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx,
1530 MO_TEUL | MO_ALIGN);
1531 tcg_gen_movi_i32(cpu_sr_t, 1);
1532 }
1533 tcg_gen_br(done);
1534
1535 gen_set_label(fail);
1536 tcg_gen_movi_i32(cpu_sr_t, 0);
1537
1538 gen_set_label(done);
1539 tcg_gen_movi_i32(cpu_lock_addr, -1);
1540 }
1541 return;
1542 case 0x0063:
1543 /* MOVLI.L @Rm,R0
1544 * 1 -> LDST
1545 * (Rm) -> R0
1546 * When interrupt/exception
1547 * occurred 0 -> LDST
1548 *
1549 * In a parallel context, we must also save the loaded value
1550 * for use with the cmpxchg that we'll use with movco.l. */
1551 CHECK_SH4A
1552 if ((tb_cflags(ctx->base.tb) & CF_PARALLEL)) {
1553 TCGv tmp = tcg_temp_new();
1554 tcg_gen_mov_i32(tmp, REG(B11_8));
1555 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx,
1556 MO_TESL | MO_ALIGN);
1557 tcg_gen_mov_i32(cpu_lock_value, REG(0));
1558 tcg_gen_mov_i32(cpu_lock_addr, tmp);
1559 } else {
1560 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx,
1561 MO_TESL | MO_ALIGN);
1562 tcg_gen_movi_i32(cpu_lock_addr, 0);
1563 }
1564 return;
1565 case 0x0093: /* ocbi @Rn */
1566 {
1567 gen_helper_ocbi(tcg_env, REG(B11_8));
1568 }
1569 return;
1570 case 0x00a3: /* ocbp @Rn */
1571 case 0x00b3: /* ocbwb @Rn */
1572 /* These instructions are supposed to do nothing in case of
1573 a cache miss. Given that we only partially emulate caches
1574 it is safe to simply ignore them. */
1575 return;
1576 case 0x0083: /* pref @Rn */
1577 return;
1578 case 0x00d3: /* prefi @Rn */
1579 CHECK_SH4A
1580 return;
1581 case 0x00e3: /* icbi @Rn */
1582 CHECK_SH4A
1583 return;
1584 case 0x00ab: /* synco */
1585 CHECK_SH4A
1586 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
1587 return;
1588 case 0x4024: /* rotcl Rn */
1589 {
1590 TCGv tmp = tcg_temp_new();
1591 tcg_gen_mov_i32(tmp, cpu_sr_t);
1592 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31);
1593 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1594 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp);
1595 }
1596 return;
1597 case 0x4025: /* rotcr Rn */
1598 {
1599 TCGv tmp = tcg_temp_new();
1600 tcg_gen_shli_i32(tmp, cpu_sr_t, 31);
1601 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
1602 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1603 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp);
1604 }
1605 return;
1606 case 0x4004: /* rotl Rn */
1607 tcg_gen_rotli_i32(REG(B11_8), REG(B11_8), 1);
1608 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0);
1609 return;
1610 case 0x4005: /* rotr Rn */
1611 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0);
1612 tcg_gen_rotri_i32(REG(B11_8), REG(B11_8), 1);
1613 return;
1614 case 0x4000: /* shll Rn */
1615 case 0x4020: /* shal Rn */
1616 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31);
1617 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
1618 return;
1619 case 0x4021: /* shar Rn */
1620 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
1621 tcg_gen_sari_i32(REG(B11_8), REG(B11_8), 1);
1622 return;
1623 case 0x4001: /* shlr Rn */
1624 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1);
1625 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
1626 return;
1627 case 0x4008: /* shll2 Rn */
1628 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 2);
1629 return;
1630 case 0x4018: /* shll8 Rn */
1631 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 8);
1632 return;
1633 case 0x4028: /* shll16 Rn */
1634 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 16);
1635 return;
1636 case 0x4009: /* shlr2 Rn */
1637 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 2);
1638 return;
1639 case 0x4019: /* shlr8 Rn */
1640 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 8);
1641 return;
1642 case 0x4029: /* shlr16 Rn */
1643 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 16);
1644 return;
1645 case 0x401b: /* tas.b @Rn */
1646 tcg_gen_atomic_fetch_or_i32(cpu_sr_t, REG(B11_8),
1647 tcg_constant_i32(0x80), ctx->memidx, MO_UB);
1648 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, cpu_sr_t, 0);
1649 return;
1650 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
1651 CHECK_FPU_ENABLED
1652 tcg_gen_mov_i32(FREG(B11_8), cpu_fpul);
1653 return;
1654 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
1655 CHECK_FPU_ENABLED
1656 tcg_gen_mov_i32(cpu_fpul, FREG(B11_8));
1657 return;
1658 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
1659 CHECK_FPU_ENABLED
1660 if (ctx->tbflags & FPSCR_PR) {
1661 TCGv_i64 fp;
1662 if (ctx->opcode & 0x0100) {
1663 goto do_illegal;
1664 }
1665 fp = tcg_temp_new_i64();
1666 gen_helper_float_DT(fp, tcg_env, cpu_fpul);
1667 gen_store_fpr64(ctx, fp, B11_8);
1668 }
1669 else {
1670 gen_helper_float_FT(FREG(B11_8), tcg_env, cpu_fpul);
1671 }
1672 return;
1673 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1674 CHECK_FPU_ENABLED
1675 if (ctx->tbflags & FPSCR_PR) {
1676 TCGv_i64 fp;
1677 if (ctx->opcode & 0x0100) {
1678 goto do_illegal;
1679 }
1680 fp = tcg_temp_new_i64();
1681 gen_load_fpr64(ctx, fp, B11_8);
1682 gen_helper_ftrc_DT(cpu_fpul, tcg_env, fp);
1683 }
1684 else {
1685 gen_helper_ftrc_FT(cpu_fpul, tcg_env, FREG(B11_8));
1686 }
1687 return;
1688 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */
1689 CHECK_FPU_ENABLED
1690 tcg_gen_xori_i32(FREG(B11_8), FREG(B11_8), 0x80000000);
1691 return;
1692 case 0xf05d: /* fabs FRn/DRn - FPCSR: Nothing */
1693 CHECK_FPU_ENABLED
1694 tcg_gen_andi_i32(FREG(B11_8), FREG(B11_8), 0x7fffffff);
1695 return;
1696 case 0xf06d: /* fsqrt FRn */
1697 CHECK_FPU_ENABLED
1698 if (ctx->tbflags & FPSCR_PR) {
1699 if (ctx->opcode & 0x0100) {
1700 goto do_illegal;
1701 }
1702 TCGv_i64 fp = tcg_temp_new_i64();
1703 gen_load_fpr64(ctx, fp, B11_8);
1704 gen_helper_fsqrt_DT(fp, tcg_env, fp);
1705 gen_store_fpr64(ctx, fp, B11_8);
1706 } else {
1707 gen_helper_fsqrt_FT(FREG(B11_8), tcg_env, FREG(B11_8));
1708 }
1709 return;
1710 case 0xf07d: /* fsrra FRn */
1711 CHECK_FPU_ENABLED
1712 CHECK_FPSCR_PR_0
1713 gen_helper_fsrra_FT(FREG(B11_8), tcg_env, FREG(B11_8));
1714 break;
1715 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
1716 CHECK_FPU_ENABLED
1717 CHECK_FPSCR_PR_0
1718 tcg_gen_movi_i32(FREG(B11_8), 0);
1719 return;
1720 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
1721 CHECK_FPU_ENABLED
1722 CHECK_FPSCR_PR_0
1723 tcg_gen_movi_i32(FREG(B11_8), 0x3f800000);
1724 return;
1725 case 0xf0ad: /* fcnvsd FPUL,DRn */
1726 CHECK_FPU_ENABLED
1727 {
1728 TCGv_i64 fp = tcg_temp_new_i64();
1729 gen_helper_fcnvsd_FT_DT(fp, tcg_env, cpu_fpul);
1730 gen_store_fpr64(ctx, fp, B11_8);
1731 }
1732 return;
1733 case 0xf0bd: /* fcnvds DRn,FPUL */
1734 CHECK_FPU_ENABLED
1735 {
1736 TCGv_i64 fp = tcg_temp_new_i64();
1737 gen_load_fpr64(ctx, fp, B11_8);
1738 gen_helper_fcnvds_DT_FT(cpu_fpul, tcg_env, fp);
1739 }
1740 return;
1741 case 0xf0ed: /* fipr FVm,FVn */
1742 CHECK_FPU_ENABLED
1743 CHECK_FPSCR_PR_1
1744 {
1745 TCGv m = tcg_constant_i32((ctx->opcode >> 8) & 3);
1746 TCGv n = tcg_constant_i32((ctx->opcode >> 10) & 3);
1747 gen_helper_fipr(tcg_env, m, n);
1748 return;
1749 }
1750 break;
1751 case 0xf0fd: /* ftrv XMTRX,FVn */
1752 CHECK_FPU_ENABLED
1753 CHECK_FPSCR_PR_1
1754 {
1755 if ((ctx->opcode & 0x0300) != 0x0100) {
1756 goto do_illegal;
1757 }
1758 TCGv n = tcg_constant_i32((ctx->opcode >> 10) & 3);
1759 gen_helper_ftrv(tcg_env, n);
1760 return;
1761 }
1762 break;
1763 }
1764 #if 0
1765 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
1766 ctx->opcode, ctx->base.pc_next);
1767 fflush(stderr);
1768 #endif
1769 do_illegal:
1770 if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) {
1771 do_illegal_slot:
1772 gen_save_cpu_state(ctx, true);
1773 gen_helper_raise_slot_illegal_instruction(tcg_env);
1774 } else {
1775 gen_save_cpu_state(ctx, true);
1776 gen_helper_raise_illegal_instruction(tcg_env);
1777 }
1778 ctx->base.is_jmp = DISAS_NORETURN;
1779 return;
1780
1781 do_fpu_disabled:
1782 gen_save_cpu_state(ctx, true);
1783 if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) {
1784 gen_helper_raise_slot_fpu_disable(tcg_env);
1785 } else {
1786 gen_helper_raise_fpu_disable(tcg_env);
1787 }
1788 ctx->base.is_jmp = DISAS_NORETURN;
1789 }
1790
decode_opc(DisasContext * ctx)1791 static void decode_opc(DisasContext * ctx)
1792 {
1793 uint32_t old_flags = ctx->envflags;
1794
1795 _decode_opc(ctx);
1796
1797 if (old_flags & TB_FLAG_DELAY_SLOT_MASK) {
1798 /* go out of the delay slot */
1799 ctx->envflags &= ~TB_FLAG_DELAY_SLOT_MASK;
1800
1801 /* When in an exclusive region, we must continue to the end
1802 for conditional branches. */
1803 if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE
1804 && old_flags & TB_FLAG_DELAY_SLOT_COND) {
1805 gen_delayed_conditional_jump(ctx);
1806 return;
1807 }
1808 /* Otherwise this is probably an invalid gUSA region.
1809 Drop the GUSA bits so the next TB doesn't see them. */
1810 ctx->envflags &= ~TB_FLAG_GUSA_MASK;
1811
1812 tcg_gen_movi_i32(cpu_flags, ctx->envflags);
1813 if (old_flags & TB_FLAG_DELAY_SLOT_COND) {
1814 gen_delayed_conditional_jump(ctx);
1815 } else {
1816 gen_jump(ctx);
1817 }
1818 }
1819 }
1820
1821 #ifdef CONFIG_USER_ONLY
1822 /*
1823 * Restart with the EXCLUSIVE bit set, within a TB run via
1824 * cpu_exec_step_atomic holding the exclusive lock.
1825 */
gen_restart_exclusive(DisasContext * ctx)1826 static void gen_restart_exclusive(DisasContext *ctx)
1827 {
1828 ctx->envflags |= TB_FLAG_GUSA_EXCLUSIVE;
1829 gen_save_cpu_state(ctx, false);
1830 gen_helper_exclusive(tcg_env);
1831 ctx->base.is_jmp = DISAS_NORETURN;
1832 }
1833
1834 /* For uniprocessors, SH4 uses optimistic restartable atomic sequences.
1835 Upon an interrupt, a real kernel would simply notice magic values in
1836 the registers and reset the PC to the start of the sequence.
1837
1838 For QEMU, we cannot do this in quite the same way. Instead, we notice
1839 the normal start of such a sequence (mov #-x,r15). While we can handle
1840 any sequence via cpu_exec_step_atomic, we can recognize the "normal"
1841 sequences and transform them into atomic operations as seen by the host.
1842 */
decode_gusa(DisasContext * ctx,CPUSH4State * env)1843 static void decode_gusa(DisasContext *ctx, CPUSH4State *env)
1844 {
1845 uint16_t insns[5];
1846 int ld_adr, ld_dst, ld_mop;
1847 int op_dst, op_src, op_opc;
1848 int mv_src, mt_dst, st_src, st_mop;
1849 TCGv op_arg;
1850 uint32_t pc = ctx->base.pc_next;
1851 uint32_t pc_end = ctx->base.tb->cs_base;
1852 int max_insns = (pc_end - pc) / 2;
1853 int i;
1854
1855 /* The state machine below will consume only a few insns.
1856 If there are more than that in a region, fail now. */
1857 if (max_insns > ARRAY_SIZE(insns)) {
1858 goto fail;
1859 }
1860
1861 /* Read all of the insns for the region. */
1862 for (i = 0; i < max_insns; ++i) {
1863 insns[i] = translator_lduw(env, &ctx->base, pc + i * 2);
1864 }
1865
1866 ld_adr = ld_dst = ld_mop = -1;
1867 mv_src = -1;
1868 op_dst = op_src = op_opc = -1;
1869 mt_dst = -1;
1870 st_src = st_mop = -1;
1871 op_arg = NULL;
1872 i = 0;
1873
1874 #define NEXT_INSN \
1875 do { if (i >= max_insns) goto fail; ctx->opcode = insns[i++]; } while (0)
1876
1877 /*
1878 * Expect a load to begin the region.
1879 */
1880 NEXT_INSN;
1881 switch (ctx->opcode & 0xf00f) {
1882 case 0x6000: /* mov.b @Rm,Rn */
1883 ld_mop = MO_SB;
1884 break;
1885 case 0x6001: /* mov.w @Rm,Rn */
1886 ld_mop = MO_TESW;
1887 break;
1888 case 0x6002: /* mov.l @Rm,Rn */
1889 ld_mop = MO_TESL;
1890 break;
1891 default:
1892 goto fail;
1893 }
1894 ld_adr = B7_4;
1895 ld_dst = B11_8;
1896 if (ld_adr == ld_dst) {
1897 goto fail;
1898 }
1899 /* Unless we see a mov, any two-operand operation must use ld_dst. */
1900 op_dst = ld_dst;
1901
1902 /*
1903 * Expect an optional register move.
1904 */
1905 NEXT_INSN;
1906 switch (ctx->opcode & 0xf00f) {
1907 case 0x6003: /* mov Rm,Rn */
1908 /*
1909 * Here we want to recognize ld_dst being saved for later consumption,
1910 * or for another input register being copied so that ld_dst need not
1911 * be clobbered during the operation.
1912 */
1913 op_dst = B11_8;
1914 mv_src = B7_4;
1915 if (op_dst == ld_dst) {
1916 /* Overwriting the load output. */
1917 goto fail;
1918 }
1919 if (mv_src != ld_dst) {
1920 /* Copying a new input; constrain op_src to match the load. */
1921 op_src = ld_dst;
1922 }
1923 break;
1924
1925 default:
1926 /* Put back and re-examine as operation. */
1927 --i;
1928 }
1929
1930 /*
1931 * Expect the operation.
1932 */
1933 NEXT_INSN;
1934 switch (ctx->opcode & 0xf00f) {
1935 case 0x300c: /* add Rm,Rn */
1936 op_opc = INDEX_op_add;
1937 goto do_reg_op;
1938 case 0x2009: /* and Rm,Rn */
1939 op_opc = INDEX_op_and;
1940 goto do_reg_op;
1941 case 0x200a: /* xor Rm,Rn */
1942 op_opc = INDEX_op_xor;
1943 goto do_reg_op;
1944 case 0x200b: /* or Rm,Rn */
1945 op_opc = INDEX_op_or;
1946 do_reg_op:
1947 /* The operation register should be as expected, and the
1948 other input cannot depend on the load. */
1949 if (op_dst != B11_8) {
1950 goto fail;
1951 }
1952 if (op_src < 0) {
1953 /* Unconstrainted input. */
1954 op_src = B7_4;
1955 } else if (op_src == B7_4) {
1956 /* Constrained input matched load. All operations are
1957 commutative; "swap" them by "moving" the load output
1958 to the (implicit) first argument and the move source
1959 to the (explicit) second argument. */
1960 op_src = mv_src;
1961 } else {
1962 goto fail;
1963 }
1964 op_arg = REG(op_src);
1965 break;
1966
1967 case 0x6007: /* not Rm,Rn */
1968 if (ld_dst != B7_4 || mv_src >= 0) {
1969 goto fail;
1970 }
1971 op_dst = B11_8;
1972 op_opc = INDEX_op_xor;
1973 op_arg = tcg_constant_i32(-1);
1974 break;
1975
1976 case 0x7000 ... 0x700f: /* add #imm,Rn */
1977 if (op_dst != B11_8 || mv_src >= 0) {
1978 goto fail;
1979 }
1980 op_opc = INDEX_op_add;
1981 op_arg = tcg_constant_i32(B7_0s);
1982 break;
1983
1984 case 0x3000: /* cmp/eq Rm,Rn */
1985 /* Looking for the middle of a compare-and-swap sequence,
1986 beginning with the compare. Operands can be either order,
1987 but with only one overlapping the load. */
1988 if ((ld_dst == B11_8) + (ld_dst == B7_4) != 1 || mv_src >= 0) {
1989 goto fail;
1990 }
1991 op_opc = INDEX_op_setcond; /* placeholder */
1992 op_src = (ld_dst == B11_8 ? B7_4 : B11_8);
1993 op_arg = REG(op_src);
1994
1995 NEXT_INSN;
1996 switch (ctx->opcode & 0xff00) {
1997 case 0x8b00: /* bf label */
1998 case 0x8f00: /* bf/s label */
1999 if (pc + (i + 1 + B7_0s) * 2 != pc_end) {
2000 goto fail;
2001 }
2002 if ((ctx->opcode & 0xff00) == 0x8b00) { /* bf label */
2003 break;
2004 }
2005 /* We're looking to unconditionally modify Rn with the
2006 result of the comparison, within the delay slot of
2007 the branch. This is used by older gcc. */
2008 NEXT_INSN;
2009 if ((ctx->opcode & 0xf0ff) == 0x0029) { /* movt Rn */
2010 mt_dst = B11_8;
2011 } else {
2012 goto fail;
2013 }
2014 break;
2015
2016 default:
2017 goto fail;
2018 }
2019 break;
2020
2021 case 0x2008: /* tst Rm,Rn */
2022 /* Looking for a compare-and-swap against zero. */
2023 if (ld_dst != B11_8 || ld_dst != B7_4 || mv_src >= 0) {
2024 goto fail;
2025 }
2026 op_opc = INDEX_op_setcond;
2027 op_arg = tcg_constant_i32(0);
2028
2029 NEXT_INSN;
2030 if ((ctx->opcode & 0xff00) != 0x8900 /* bt label */
2031 || pc + (i + 1 + B7_0s) * 2 != pc_end) {
2032 goto fail;
2033 }
2034 break;
2035
2036 default:
2037 /* Put back and re-examine as store. */
2038 --i;
2039 }
2040
2041 /*
2042 * Expect the store.
2043 */
2044 /* The store must be the last insn. */
2045 if (i != max_insns - 1) {
2046 goto fail;
2047 }
2048 NEXT_INSN;
2049 switch (ctx->opcode & 0xf00f) {
2050 case 0x2000: /* mov.b Rm,@Rn */
2051 st_mop = MO_UB;
2052 break;
2053 case 0x2001: /* mov.w Rm,@Rn */
2054 st_mop = MO_UW;
2055 break;
2056 case 0x2002: /* mov.l Rm,@Rn */
2057 st_mop = MO_UL;
2058 break;
2059 default:
2060 goto fail;
2061 }
2062 /* The store must match the load. */
2063 if (ld_adr != B11_8 || st_mop != (ld_mop & MO_SIZE)) {
2064 goto fail;
2065 }
2066 st_src = B7_4;
2067
2068 #undef NEXT_INSN
2069
2070 /*
2071 * Emit the operation.
2072 */
2073 switch (op_opc) {
2074 case -1:
2075 /* No operation found. Look for exchange pattern. */
2076 if (st_src == ld_dst || mv_src >= 0) {
2077 goto fail;
2078 }
2079 tcg_gen_atomic_xchg_i32(REG(ld_dst), REG(ld_adr), REG(st_src),
2080 ctx->memidx, ld_mop);
2081 break;
2082
2083 case INDEX_op_add:
2084 if (op_dst != st_src) {
2085 goto fail;
2086 }
2087 if (op_dst == ld_dst && st_mop == MO_UL) {
2088 tcg_gen_atomic_add_fetch_i32(REG(ld_dst), REG(ld_adr),
2089 op_arg, ctx->memidx, ld_mop);
2090 } else {
2091 tcg_gen_atomic_fetch_add_i32(REG(ld_dst), REG(ld_adr),
2092 op_arg, ctx->memidx, ld_mop);
2093 if (op_dst != ld_dst) {
2094 /* Note that mop sizes < 4 cannot use add_fetch
2095 because it won't carry into the higher bits. */
2096 tcg_gen_add_i32(REG(op_dst), REG(ld_dst), op_arg);
2097 }
2098 }
2099 break;
2100
2101 case INDEX_op_and:
2102 if (op_dst != st_src) {
2103 goto fail;
2104 }
2105 if (op_dst == ld_dst) {
2106 tcg_gen_atomic_and_fetch_i32(REG(ld_dst), REG(ld_adr),
2107 op_arg, ctx->memidx, ld_mop);
2108 } else {
2109 tcg_gen_atomic_fetch_and_i32(REG(ld_dst), REG(ld_adr),
2110 op_arg, ctx->memidx, ld_mop);
2111 tcg_gen_and_i32(REG(op_dst), REG(ld_dst), op_arg);
2112 }
2113 break;
2114
2115 case INDEX_op_or:
2116 if (op_dst != st_src) {
2117 goto fail;
2118 }
2119 if (op_dst == ld_dst) {
2120 tcg_gen_atomic_or_fetch_i32(REG(ld_dst), REG(ld_adr),
2121 op_arg, ctx->memidx, ld_mop);
2122 } else {
2123 tcg_gen_atomic_fetch_or_i32(REG(ld_dst), REG(ld_adr),
2124 op_arg, ctx->memidx, ld_mop);
2125 tcg_gen_or_i32(REG(op_dst), REG(ld_dst), op_arg);
2126 }
2127 break;
2128
2129 case INDEX_op_xor:
2130 if (op_dst != st_src) {
2131 goto fail;
2132 }
2133 if (op_dst == ld_dst) {
2134 tcg_gen_atomic_xor_fetch_i32(REG(ld_dst), REG(ld_adr),
2135 op_arg, ctx->memidx, ld_mop);
2136 } else {
2137 tcg_gen_atomic_fetch_xor_i32(REG(ld_dst), REG(ld_adr),
2138 op_arg, ctx->memidx, ld_mop);
2139 tcg_gen_xor_i32(REG(op_dst), REG(ld_dst), op_arg);
2140 }
2141 break;
2142
2143 case INDEX_op_setcond:
2144 if (st_src == ld_dst) {
2145 goto fail;
2146 }
2147 tcg_gen_atomic_cmpxchg_i32(REG(ld_dst), REG(ld_adr), op_arg,
2148 REG(st_src), ctx->memidx, ld_mop);
2149 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(ld_dst), op_arg);
2150 if (mt_dst >= 0) {
2151 tcg_gen_mov_i32(REG(mt_dst), cpu_sr_t);
2152 }
2153 break;
2154
2155 default:
2156 g_assert_not_reached();
2157 }
2158
2159 /* The entire region has been translated. */
2160 ctx->envflags &= ~TB_FLAG_GUSA_MASK;
2161 goto done;
2162
2163 fail:
2164 qemu_log_mask(LOG_UNIMP, "Unrecognized gUSA sequence %08x-%08x\n",
2165 pc, pc_end);
2166
2167 gen_restart_exclusive(ctx);
2168
2169 /* We're not executing an instruction, but we must report one for the
2170 purposes of accounting within the TB. We might as well report the
2171 entire region consumed via ctx->base.pc_next so that it's immediately
2172 available in the disassembly dump. */
2173
2174 done:
2175 ctx->base.pc_next = pc_end;
2176 ctx->base.num_insns += max_insns - 1;
2177
2178 /*
2179 * Emit insn_start to cover each of the insns in the region.
2180 * This matches an assert in tcg.c making sure that we have
2181 * tb->icount * insn_start.
2182 */
2183 for (i = 1; i < max_insns; ++i) {
2184 tcg_gen_insn_start(pc + i * 2, ctx->envflags);
2185 ctx->base.insn_start = tcg_last_op();
2186 }
2187 }
2188 #endif
2189
sh4_tr_init_disas_context(DisasContextBase * dcbase,CPUState * cs)2190 static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
2191 {
2192 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2193 uint32_t tbflags;
2194 int bound;
2195
2196 ctx->tbflags = tbflags = ctx->base.tb->flags;
2197 ctx->envflags = tbflags & TB_FLAG_ENVFLAGS_MASK;
2198 ctx->memidx = (tbflags & (1u << SR_MD)) == 0 ? 1 : 0;
2199 /* We don't know if the delayed pc came from a dynamic or static branch,
2200 so assume it is a dynamic branch. */
2201 ctx->delayed_pc = -1; /* use delayed pc from env pointer */
2202 ctx->features = cpu_env(cs)->features;
2203 ctx->has_movcal = (tbflags & TB_FLAG_PENDING_MOVCA);
2204 ctx->gbank = ((tbflags & (1 << SR_MD)) &&
2205 (tbflags & (1 << SR_RB))) * 0x10;
2206 ctx->fbank = tbflags & FPSCR_FR ? 0x10 : 0;
2207
2208 #ifdef CONFIG_USER_ONLY
2209 if (tbflags & TB_FLAG_GUSA_MASK) {
2210 /* In gUSA exclusive region. */
2211 uint32_t pc = ctx->base.pc_next;
2212 uint32_t pc_end = ctx->base.tb->cs_base;
2213 int backup = sextract32(ctx->tbflags, TB_FLAG_GUSA_SHIFT, 8);
2214 int max_insns = (pc_end - pc) / 2;
2215
2216 if (pc != pc_end + backup || max_insns < 2) {
2217 /* This is a malformed gUSA region. Don't do anything special,
2218 since the interpreter is likely to get confused. */
2219 ctx->envflags &= ~TB_FLAG_GUSA_MASK;
2220 } else if (tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
2221 /* Regardless of single-stepping or the end of the page,
2222 we must complete execution of the gUSA region while
2223 holding the exclusive lock. */
2224 ctx->base.max_insns = max_insns;
2225 return;
2226 }
2227 }
2228 #endif
2229
2230 /* Since the ISA is fixed-width, we can bound by the number
2231 of instructions remaining on the page. */
2232 bound = -(ctx->base.pc_next | TARGET_PAGE_MASK) / 2;
2233 ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
2234 }
2235
sh4_tr_tb_start(DisasContextBase * dcbase,CPUState * cs)2236 static void sh4_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
2237 {
2238 }
2239
sh4_tr_insn_start(DisasContextBase * dcbase,CPUState * cs)2240 static void sh4_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
2241 {
2242 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2243
2244 tcg_gen_insn_start(ctx->base.pc_next, ctx->envflags);
2245 }
2246
sh4_tr_translate_insn(DisasContextBase * dcbase,CPUState * cs)2247 static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
2248 {
2249 CPUSH4State *env = cpu_env(cs);
2250 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2251
2252 #ifdef CONFIG_USER_ONLY
2253 if (unlikely(ctx->envflags & TB_FLAG_GUSA_MASK)
2254 && !(ctx->envflags & TB_FLAG_GUSA_EXCLUSIVE)) {
2255 /*
2256 * We're in an gUSA region, and we have not already fallen
2257 * back on using an exclusive region. Attempt to parse the
2258 * region into a single supported atomic operation. Failure
2259 * is handled within the parser by raising an exception to
2260 * retry using an exclusive region.
2261 *
2262 * Parsing the region in one block conflicts with plugins,
2263 * so always use exclusive mode if plugins enabled.
2264 */
2265 if (ctx->base.plugin_enabled) {
2266 gen_restart_exclusive(ctx);
2267 ctx->base.pc_next += 2;
2268 } else {
2269 decode_gusa(ctx, env);
2270 }
2271 return;
2272 }
2273 #endif
2274
2275 ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next);
2276 decode_opc(ctx);
2277 ctx->base.pc_next += 2;
2278 }
2279
sh4_tr_tb_stop(DisasContextBase * dcbase,CPUState * cs)2280 static void sh4_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
2281 {
2282 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2283
2284 if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
2285 /* Ending the region of exclusivity. Clear the bits. */
2286 ctx->envflags &= ~TB_FLAG_GUSA_MASK;
2287 }
2288
2289 switch (ctx->base.is_jmp) {
2290 case DISAS_STOP:
2291 gen_save_cpu_state(ctx, true);
2292 tcg_gen_exit_tb(NULL, 0);
2293 break;
2294 case DISAS_NEXT:
2295 case DISAS_TOO_MANY:
2296 gen_save_cpu_state(ctx, false);
2297 gen_goto_tb(ctx, 0, ctx->base.pc_next);
2298 break;
2299 case DISAS_NORETURN:
2300 break;
2301 default:
2302 g_assert_not_reached();
2303 }
2304 }
2305
2306 static const TranslatorOps sh4_tr_ops = {
2307 .init_disas_context = sh4_tr_init_disas_context,
2308 .tb_start = sh4_tr_tb_start,
2309 .insn_start = sh4_tr_insn_start,
2310 .translate_insn = sh4_tr_translate_insn,
2311 .tb_stop = sh4_tr_tb_stop,
2312 };
2313
sh4_translate_code(CPUState * cs,TranslationBlock * tb,int * max_insns,vaddr pc,void * host_pc)2314 void sh4_translate_code(CPUState *cs, TranslationBlock *tb,
2315 int *max_insns, vaddr pc, void *host_pc)
2316 {
2317 DisasContext ctx;
2318
2319 translator_loop(cs, tb, max_insns, pc, host_pc, &sh4_tr_ops, &ctx.base);
2320 }
2321