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