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