1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22
23#include "cpu.h"
24#include "exec/helper-proto.h"
25#include "exec/target_page.h"
26#include "tcg/tcg-op.h"
27#include "tcg/tcg-op-gvec.h"
28#include "exec/helper-gen.h"
29#include "exec/translator.h"
30#include "exec/translation-block.h"
31#include "exec/log.h"
32#include "fpu/softfloat.h"
33#include "asi.h"
34#include "target/sparc/translate.h"
35
36#define HELPER_H "helper.h"
37#include "exec/helper-info.c.inc"
38#undef HELPER_H
39
40#ifdef TARGET_SPARC64
41# define gen_helper_rdpsr(D, E) qemu_build_not_reached()
42# define gen_helper_rdasr17(D, E) qemu_build_not_reached()
43# define gen_helper_rett(E) qemu_build_not_reached()
44# define gen_helper_power_down(E) qemu_build_not_reached()
45# define gen_helper_wrpsr(E, S) qemu_build_not_reached()
46#else
47# define gen_helper_clear_softint(E, S) qemu_build_not_reached()
48# define gen_helper_done(E) qemu_build_not_reached()
49# define gen_helper_flushw(E) qemu_build_not_reached()
50# define gen_helper_fmul8x16a(D, S1, S2) qemu_build_not_reached()
51# define gen_helper_rdccr(D, E) qemu_build_not_reached()
52# define gen_helper_rdcwp(D, E) qemu_build_not_reached()
53# define gen_helper_restored(E) qemu_build_not_reached()
54# define gen_helper_retry(E) qemu_build_not_reached()
55# define gen_helper_saved(E) qemu_build_not_reached()
56# define gen_helper_set_softint(E, S) qemu_build_not_reached()
57# define gen_helper_tick_get_count(D, E, T, C) qemu_build_not_reached()
58# define gen_helper_tick_set_count(P, S) qemu_build_not_reached()
59# define gen_helper_tick_set_limit(P, S) qemu_build_not_reached()
60# define gen_helper_wrccr(E, S) qemu_build_not_reached()
61# define gen_helper_wrcwp(E, S) qemu_build_not_reached()
62# define gen_helper_wrgl(E, S) qemu_build_not_reached()
63# define gen_helper_write_softint(E, S) qemu_build_not_reached()
64# define gen_helper_wrpil(E, S) qemu_build_not_reached()
65# define gen_helper_wrpstate(E, S) qemu_build_not_reached()
66# define gen_helper_cmask8 ({ qemu_build_not_reached(); NULL; })
67# define gen_helper_cmask16 ({ qemu_build_not_reached(); NULL; })
68# define gen_helper_cmask32 ({ qemu_build_not_reached(); NULL; })
69# define gen_helper_fcmpeq8 ({ qemu_build_not_reached(); NULL; })
70# define gen_helper_fcmpeq16 ({ qemu_build_not_reached(); NULL; })
71# define gen_helper_fcmpeq32 ({ qemu_build_not_reached(); NULL; })
72# define gen_helper_fcmpgt8 ({ qemu_build_not_reached(); NULL; })
73# define gen_helper_fcmpgt16 ({ qemu_build_not_reached(); NULL; })
74# define gen_helper_fcmpgt32 ({ qemu_build_not_reached(); NULL; })
75# define gen_helper_fcmple8 ({ qemu_build_not_reached(); NULL; })
76# define gen_helper_fcmple16 ({ qemu_build_not_reached(); NULL; })
77# define gen_helper_fcmple32 ({ qemu_build_not_reached(); NULL; })
78# define gen_helper_fcmpne8 ({ qemu_build_not_reached(); NULL; })
79# define gen_helper_fcmpne16 ({ qemu_build_not_reached(); NULL; })
80# define gen_helper_fcmpne32 ({ qemu_build_not_reached(); NULL; })
81# define gen_helper_fcmpule8 ({ qemu_build_not_reached(); NULL; })
82# define gen_helper_fcmpule16 ({ qemu_build_not_reached(); NULL; })
83# define gen_helper_fcmpule32 ({ qemu_build_not_reached(); NULL; })
84# define gen_helper_fcmpugt8 ({ qemu_build_not_reached(); NULL; })
85# define gen_helper_fcmpugt16 ({ qemu_build_not_reached(); NULL; })
86# define gen_helper_fcmpugt32 ({ qemu_build_not_reached(); NULL; })
87# define gen_helper_fdtox ({ qemu_build_not_reached(); NULL; })
88# define gen_helper_fexpand ({ qemu_build_not_reached(); NULL; })
89# define gen_helper_fmul8sux16 ({ qemu_build_not_reached(); NULL; })
90# define gen_helper_fmul8ulx16 ({ qemu_build_not_reached(); NULL; })
91# define gen_helper_fmul8x16 ({ qemu_build_not_reached(); NULL; })
92# define gen_helper_fpmerge ({ qemu_build_not_reached(); NULL; })
93# define gen_helper_fqtox ({ qemu_build_not_reached(); NULL; })
94# define gen_helper_fslas16 ({ qemu_build_not_reached(); NULL; })
95# define gen_helper_fslas32 ({ qemu_build_not_reached(); NULL; })
96# define gen_helper_fstox ({ qemu_build_not_reached(); NULL; })
97# define gen_helper_fxtod ({ qemu_build_not_reached(); NULL; })
98# define gen_helper_fxtoq ({ qemu_build_not_reached(); NULL; })
99# define gen_helper_fxtos ({ qemu_build_not_reached(); NULL; })
100# define gen_helper_pdist ({ qemu_build_not_reached(); NULL; })
101# define gen_helper_xmulx ({ qemu_build_not_reached(); NULL; })
102# define gen_helper_xmulxhi ({ qemu_build_not_reached(); NULL; })
103# define MAXTL_MASK 0
104#endif
105
106#define DISAS_EXIT DISAS_TARGET_0
107
108
109static TCGv_ptr cpu_regwptr;
110static TCGv cpu_pc, cpu_npc;
111static TCGv cpu_regs[32];
112static TCGv cpu_y;
113static TCGv cpu_tbr;
114static TCGv cpu_cond;
115static TCGv cpu_cc_N;
116static TCGv cpu_cc_V;
117static TCGv cpu_icc_Z;
118static TCGv cpu_icc_C;
119#ifdef TARGET_SPARC64
120static TCGv cpu_xcc_Z;
121static TCGv cpu_xcc_C;
122static TCGv_i32 cpu_fprs;
123static TCGv cpu_gsr;
124#else
125# define cpu_fprs ({ qemu_build_not_reached(); (TCGv)NULL; })
126# define cpu_gsr ({ qemu_build_not_reached(); (TCGv)NULL; })
127#endif
128
129#ifdef TARGET_SPARC64
130#define cpu_cc_Z cpu_xcc_Z
131#define cpu_cc_C cpu_xcc_C
132#else
133#define cpu_cc_Z cpu_icc_Z
134#define cpu_cc_C cpu_icc_C
135#define cpu_xcc_Z ({ qemu_build_not_reached(); NULL; })
136#define cpu_xcc_C ({ qemu_build_not_reached(); NULL; })
137#endif
138
139
140static TCGv_i32 cpu_fcc[TARGET_FCCREGS];
141
142#define env_field_offsetof(X) offsetof(CPUSPARCState, X)
143#ifdef TARGET_SPARC64
144# define env32_field_offsetof(X) ({ qemu_build_not_reached(); 0; })
145# define env64_field_offsetof(X) env_field_offsetof(X)
146#else
147# define env32_field_offsetof(X) env_field_offsetof(X)
148# define env64_field_offsetof(X) ({ qemu_build_not_reached(); 0; })
149#endif
150
151typedef struct DisasCompare {
152 TCGCond cond;
153 TCGv c1;
154 int c2;
155} DisasCompare;
156
157typedef struct DisasDelayException {
158 struct DisasDelayException *next;
159 TCGLabel *lab;
160 TCGv_i32 excp;
161
162 target_ulong pc;
163 target_ulong npc;
164} DisasDelayException;
165
166typedef struct DisasContext {
167 DisasContextBase base;
168 target_ulong pc;
169 target_ulong npc;
170
171
172 DisasCompare jump;
173 target_ulong jump_pc[2];
174
175 int mem_idx;
176 bool cpu_cond_live;
177 bool fpu_enabled;
178 bool address_mask_32bit;
179#ifndef CONFIG_USER_ONLY
180 bool supervisor;
181#ifdef TARGET_SPARC64
182 bool hypervisor;
183#else
184 bool fsr_qne;
185#endif
186#endif
187
188 sparc_def_t *def;
189#ifdef TARGET_SPARC64
190 int fprs_dirty;
191 int asi;
192#endif
193 DisasDelayException *delay_excp_list;
194} DisasContext;
195
196
197#define GET_FIELD(X, FROM, TO) \
198 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
199
200
201#define GET_FIELD_SP(X, FROM, TO) \
202 GET_FIELD(X, 31 - (TO), 31 - (FROM))
203
204#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
205#define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
206
207#define UA2005_HTRAP_MASK 0xff
208#define V8_TRAP_MASK 0x7f
209
210#define IS_IMM (insn & (1<<13))
211
212static void gen_update_fprs_dirty(DisasContext *dc, int rd)
213{
214#if defined(TARGET_SPARC64)
215 int bit = (rd < 32) ? 1 : 2;
216
217
218 if (!(dc->fprs_dirty & bit)) {
219 dc->fprs_dirty |= bit;
220 tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit);
221 }
222#endif
223}
224
225
226
227static int gen_offset_fpr_F(unsigned int reg)
228{
229 int ret;
230
231 tcg_debug_assert(reg < 32);
232 ret= offsetof(CPUSPARCState, fpr[reg / 2]);
233 if (reg & 1) {
234 ret += offsetof(CPU_DoubleU, l.lower);
235 } else {
236 ret += offsetof(CPU_DoubleU, l.upper);
237 }
238 return ret;
239}
240
241static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src)
242{
243 TCGv_i32 ret = tcg_temp_new_i32();
244 tcg_gen_ld_i32(ret, tcg_env, gen_offset_fpr_F(src));
245 return ret;
246}
247
248static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v)
249{
250 tcg_gen_st_i32(v, tcg_env, gen_offset_fpr_F(dst));
251 gen_update_fprs_dirty(dc, dst);
252}
253
254static int gen_offset_fpr_D(unsigned int reg)
255{
256 tcg_debug_assert(reg < 64);
257 tcg_debug_assert(reg % 2 == 0);
258 return offsetof(CPUSPARCState, fpr[reg / 2]);
259}
260
261static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src)
262{
263 TCGv_i64 ret = tcg_temp_new_i64();
264 tcg_gen_ld_i64(ret, tcg_env, gen_offset_fpr_D(src));
265 return ret;
266}
267
268static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v)
269{
270 tcg_gen_st_i64(v, tcg_env, gen_offset_fpr_D(dst));
271 gen_update_fprs_dirty(dc, dst);
272}
273
274static TCGv_i128 gen_load_fpr_Q(DisasContext *dc, unsigned int src)
275{
276 TCGv_i128 ret = tcg_temp_new_i128();
277 TCGv_i64 h = gen_load_fpr_D(dc, src);
278 TCGv_i64 l = gen_load_fpr_D(dc, src + 2);
279
280 tcg_gen_concat_i64_i128(ret, l, h);
281 return ret;
282}
283
284static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst, TCGv_i128 v)
285{
286 TCGv_i64 h = tcg_temp_new_i64();
287 TCGv_i64 l = tcg_temp_new_i64();
288
289 tcg_gen_extr_i128_i64(l, h, v);
290 gen_store_fpr_D(dc, dst, h);
291 gen_store_fpr_D(dc, dst + 2, l);
292}
293
294
295#ifdef CONFIG_USER_ONLY
296#define supervisor(dc) 0
297#define hypervisor(dc) 0
298#else
299#ifdef TARGET_SPARC64
300#define hypervisor(dc) (dc->hypervisor)
301#define supervisor(dc) (dc->supervisor | dc->hypervisor)
302#else
303#define supervisor(dc) (dc->supervisor)
304#define hypervisor(dc) 0
305#endif
306#endif
307
308#if !defined(TARGET_SPARC64)
309# define AM_CHECK(dc) false
310#elif defined(TARGET_ABI32)
311# define AM_CHECK(dc) true
312#elif defined(CONFIG_USER_ONLY)
313# define AM_CHECK(dc) false
314#else
315# define AM_CHECK(dc) ((dc)->address_mask_32bit)
316#endif
317
318static void gen_address_mask(DisasContext *dc, TCGv addr)
319{
320 if (AM_CHECK(dc)) {
321 tcg_gen_andi_tl(addr, addr, 0xffffffffULL);
322 }
323}
324
325static target_ulong address_mask_i(DisasContext *dc, target_ulong addr)
326{
327 return AM_CHECK(dc) ? (uint32_t)addr : addr;
328}
329
330static TCGv gen_load_gpr(DisasContext *dc, int reg)
331{
332 if (reg > 0) {
333 assert(reg < 32);
334 return cpu_regs[reg];
335 } else {
336 TCGv t = tcg_temp_new();
337 tcg_gen_movi_tl(t, 0);
338 return t;
339 }
340}
341
342static void gen_store_gpr(DisasContext *dc, int reg, TCGv v)
343{
344 if (reg > 0) {
345 assert(reg < 32);
346 tcg_gen_mov_tl(cpu_regs[reg], v);
347 }
348}
349
350static TCGv gen_dest_gpr(DisasContext *dc, int reg)
351{
352 if (reg > 0) {
353 assert(reg < 32);
354 return cpu_regs[reg];
355 } else {
356 return tcg_temp_new();
357 }
358}
359
360static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc)
361{
362 return translator_use_goto_tb(&s->base, pc) &&
363 translator_use_goto_tb(&s->base, npc);
364}
365
366static void gen_goto_tb(DisasContext *s, int tb_num,
367 target_ulong pc, target_ulong npc)
368{
369 if (use_goto_tb(s, pc, npc)) {
370
371 tcg_gen_goto_tb(tb_num);
372 tcg_gen_movi_tl(cpu_pc, pc);
373 tcg_gen_movi_tl(cpu_npc, npc);
374 tcg_gen_exit_tb(s->base.tb, tb_num);
375 } else {
376
377 tcg_gen_movi_tl(cpu_pc, pc);
378 tcg_gen_movi_tl(cpu_npc, npc);
379 tcg_gen_lookup_and_goto_ptr();
380 }
381}
382
383static TCGv gen_carry32(void)
384{
385 if (TARGET_LONG_BITS == 64) {
386 TCGv t = tcg_temp_new();
387 tcg_gen_extract_tl(t, cpu_icc_C, 32, 1);
388 return t;
389 }
390 return cpu_icc_C;
391}
392
393static void gen_op_addcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin)
394{
395 TCGv z = tcg_constant_tl(0);
396
397 if (cin) {
398 tcg_gen_addcio_tl(cpu_cc_N, cpu_cc_C, src1, src2, cin);
399 } else {
400 tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z);
401 }
402 tcg_gen_xor_tl(cpu_cc_Z, src1, src2);
403 tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src2);
404 tcg_gen_andc_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z);
405 if (TARGET_LONG_BITS == 64) {
406
407
408
409
410 tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N);
411 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
412 }
413 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
414 tcg_gen_mov_tl(dst, cpu_cc_N);
415}
416
417static void gen_op_addcc(TCGv dst, TCGv src1, TCGv src2)
418{
419 gen_op_addcc_int(dst, src1, src2, NULL);
420}
421
422static void gen_op_taddcc(TCGv dst, TCGv src1, TCGv src2)
423{
424 TCGv t = tcg_temp_new();
425
426
427 tcg_gen_or_tl(t, src1, src2);
428
429 gen_op_addcc(dst, src1, src2);
430
431
432 tcg_gen_andi_tl(t, t, 3);
433 tcg_gen_neg_tl(t, t);
434 tcg_gen_ext32u_tl(t, t);
435 tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t);
436}
437
438static void gen_op_addc(TCGv dst, TCGv src1, TCGv src2)
439{
440 tcg_gen_add_tl(dst, src1, src2);
441 tcg_gen_add_tl(dst, dst, gen_carry32());
442}
443
444static void gen_op_addccc(TCGv dst, TCGv src1, TCGv src2)
445{
446 gen_op_addcc_int(dst, src1, src2, gen_carry32());
447}
448
449static void gen_op_addxc(TCGv dst, TCGv src1, TCGv src2)
450{
451 tcg_gen_add_tl(dst, src1, src2);
452 tcg_gen_add_tl(dst, dst, cpu_cc_C);
453}
454
455static void gen_op_addxccc(TCGv dst, TCGv src1, TCGv src2)
456{
457 gen_op_addcc_int(dst, src1, src2, cpu_cc_C);
458}
459
460static void gen_op_subcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin)
461{
462 TCGv z = tcg_constant_tl(0);
463
464 if (cin) {
465 tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z);
466 tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z);
467 } else {
468 tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z);
469 }
470 tcg_gen_neg_tl(cpu_cc_C, cpu_cc_C);
471 tcg_gen_xor_tl(cpu_cc_Z, src1, src2);
472 tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src1);
473 tcg_gen_and_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z);
474#ifdef TARGET_SPARC64
475 tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N);
476 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
477#endif
478 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
479 tcg_gen_mov_tl(dst, cpu_cc_N);
480}
481
482static void gen_op_subcc(TCGv dst, TCGv src1, TCGv src2)
483{
484 gen_op_subcc_int(dst, src1, src2, NULL);
485}
486
487static void gen_op_tsubcc(TCGv dst, TCGv src1, TCGv src2)
488{
489 TCGv t = tcg_temp_new();
490
491
492 tcg_gen_or_tl(t, src1, src2);
493
494 gen_op_subcc(dst, src1, src2);
495
496
497 tcg_gen_andi_tl(t, t, 3);
498 tcg_gen_neg_tl(t, t);
499 tcg_gen_ext32u_tl(t, t);
500 tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t);
501}
502
503static void gen_op_subc(TCGv dst, TCGv src1, TCGv src2)
504{
505 tcg_gen_sub_tl(dst, src1, src2);
506 tcg_gen_sub_tl(dst, dst, gen_carry32());
507}
508
509static void gen_op_subccc(TCGv dst, TCGv src1, TCGv src2)
510{
511 gen_op_subcc_int(dst, src1, src2, gen_carry32());
512}
513
514static void gen_op_subxc(TCGv dst, TCGv src1, TCGv src2)
515{
516 tcg_gen_sub_tl(dst, src1, src2);
517 tcg_gen_sub_tl(dst, dst, cpu_cc_C);
518}
519
520static void gen_op_subxccc(TCGv dst, TCGv src1, TCGv src2)
521{
522 gen_op_subcc_int(dst, src1, src2, cpu_cc_C);
523}
524
525static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
526{
527 TCGv zero = tcg_constant_tl(0);
528 TCGv one = tcg_constant_tl(1);
529 TCGv t_src1 = tcg_temp_new();
530 TCGv t_src2 = tcg_temp_new();
531 TCGv t0 = tcg_temp_new();
532
533 tcg_gen_ext32u_tl(t_src1, src1);
534 tcg_gen_ext32u_tl(t_src2, src2);
535
536
537
538
539
540 tcg_gen_movcond_tl(TCG_COND_TSTEQ, t_src2, cpu_y, one, zero, t_src2);
541
542
543
544
545
546 tcg_gen_extract_tl(t0, cpu_y, 1, 31);
547 tcg_gen_deposit_tl(cpu_y, t0, src1, 31, 1);
548
549
550 tcg_gen_xor_tl(t0, cpu_cc_N, cpu_cc_V);
551
552
553
554
555 tcg_gen_andi_tl(t0, t0, 1u << 31);
556 tcg_gen_shri_tl(t_src1, t_src1, 1);
557 tcg_gen_or_tl(t_src1, t_src1, t0);
558
559 gen_op_addcc(dst, t_src1, t_src2);
560}
561
562static void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext)
563{
564#if TARGET_LONG_BITS == 32
565 if (sign_ext) {
566 tcg_gen_muls2_tl(dst, cpu_y, src1, src2);
567 } else {
568 tcg_gen_mulu2_tl(dst, cpu_y, src1, src2);
569 }
570#else
571 TCGv t0 = tcg_temp_new_i64();
572 TCGv t1 = tcg_temp_new_i64();
573
574 if (sign_ext) {
575 tcg_gen_ext32s_i64(t0, src1);
576 tcg_gen_ext32s_i64(t1, src2);
577 } else {
578 tcg_gen_ext32u_i64(t0, src1);
579 tcg_gen_ext32u_i64(t1, src2);
580 }
581
582 tcg_gen_mul_i64(dst, t0, t1);
583 tcg_gen_shri_i64(cpu_y, dst, 32);
584#endif
585}
586
587static void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
588{
589
590 gen_op_multiply(dst, src1, src2, 0);
591}
592
593static void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
594{
595
596 gen_op_multiply(dst, src1, src2, 1);
597}
598
599static void gen_op_umulxhi(TCGv dst, TCGv src1, TCGv src2)
600{
601 TCGv discard = tcg_temp_new();
602 tcg_gen_mulu2_tl(discard, dst, src1, src2);
603}
604
605static void gen_op_fpmaddx(TCGv_i64 dst, TCGv_i64 src1,
606 TCGv_i64 src2, TCGv_i64 src3)
607{
608 TCGv_i64 t = tcg_temp_new_i64();
609
610 tcg_gen_mul_i64(t, src1, src2);
611 tcg_gen_add_i64(dst, src3, t);
612}
613
614static void gen_op_fpmaddxhi(TCGv_i64 dst, TCGv_i64 src1,
615 TCGv_i64 src2, TCGv_i64 src3)
616{
617 TCGv_i64 l = tcg_temp_new_i64();
618 TCGv_i64 h = tcg_temp_new_i64();
619 TCGv_i64 z = tcg_constant_i64(0);
620
621 tcg_gen_mulu2_i64(l, h, src1, src2);
622 tcg_gen_add2_i64(l, dst, l, h, src3, z);
623}
624
625static void gen_op_sdiv(TCGv dst, TCGv src1, TCGv src2)
626{
627#ifdef TARGET_SPARC64
628 gen_helper_sdiv(dst, tcg_env, src1, src2);
629 tcg_gen_ext32s_tl(dst, dst);
630#else
631 TCGv_i64 t64 = tcg_temp_new_i64();
632 gen_helper_sdiv(t64, tcg_env, src1, src2);
633 tcg_gen_trunc_i64_tl(dst, t64);
634#endif
635}
636
637static void gen_op_udivcc(TCGv dst, TCGv src1, TCGv src2)
638{
639 TCGv_i64 t64;
640
641#ifdef TARGET_SPARC64
642 t64 = cpu_cc_V;
643#else
644 t64 = tcg_temp_new_i64();
645#endif
646
647 gen_helper_udiv(t64, tcg_env, src1, src2);
648
649#ifdef TARGET_SPARC64
650 tcg_gen_ext32u_tl(cpu_cc_N, t64);
651 tcg_gen_shri_tl(cpu_cc_V, t64, 32);
652 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
653 tcg_gen_movi_tl(cpu_icc_C, 0);
654#else
655 tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
656#endif
657 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
658 tcg_gen_movi_tl(cpu_cc_C, 0);
659 tcg_gen_mov_tl(dst, cpu_cc_N);
660}
661
662static void gen_op_sdivcc(TCGv dst, TCGv src1, TCGv src2)
663{
664 TCGv_i64 t64;
665
666#ifdef TARGET_SPARC64
667 t64 = cpu_cc_V;
668#else
669 t64 = tcg_temp_new_i64();
670#endif
671
672 gen_helper_sdiv(t64, tcg_env, src1, src2);
673
674#ifdef TARGET_SPARC64
675 tcg_gen_ext32s_tl(cpu_cc_N, t64);
676 tcg_gen_shri_tl(cpu_cc_V, t64, 32);
677 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
678 tcg_gen_movi_tl(cpu_icc_C, 0);
679#else
680 tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
681#endif
682 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
683 tcg_gen_movi_tl(cpu_cc_C, 0);
684 tcg_gen_mov_tl(dst, cpu_cc_N);
685}
686
687static void gen_op_taddcctv(TCGv dst, TCGv src1, TCGv src2)
688{
689 gen_helper_taddcctv(dst, tcg_env, src1, src2);
690}
691
692static void gen_op_tsubcctv(TCGv dst, TCGv src1, TCGv src2)
693{
694 gen_helper_tsubcctv(dst, tcg_env, src1, src2);
695}
696
697static void gen_op_popc(TCGv dst, TCGv src1, TCGv src2)
698{
699 tcg_gen_ctpop_tl(dst, src2);
700}
701
702static void gen_op_lzcnt(TCGv dst, TCGv src)
703{
704 tcg_gen_clzi_tl(dst, src, TARGET_LONG_BITS);
705}
706
707#ifndef TARGET_SPARC64
708static void gen_helper_array8(TCGv dst, TCGv src1, TCGv src2)
709{
710 g_assert_not_reached();
711}
712#endif
713
714static void gen_op_array16(TCGv dst, TCGv src1, TCGv src2)
715{
716 gen_helper_array8(dst, src1, src2);
717 tcg_gen_shli_tl(dst, dst, 1);
718}
719
720static void gen_op_array32(TCGv dst, TCGv src1, TCGv src2)
721{
722 gen_helper_array8(dst, src1, src2);
723 tcg_gen_shli_tl(dst, dst, 2);
724}
725
726static void gen_op_fpack16(TCGv_i32 dst, TCGv_i64 src)
727{
728#ifdef TARGET_SPARC64
729 gen_helper_fpack16(dst, cpu_gsr, src);
730#else
731 g_assert_not_reached();
732#endif
733}
734
735static void gen_op_fpackfix(TCGv_i32 dst, TCGv_i64 src)
736{
737#ifdef TARGET_SPARC64
738 gen_helper_fpackfix(dst, cpu_gsr, src);
739#else
740 g_assert_not_reached();
741#endif
742}
743
744static void gen_op_fpack32(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2)
745{
746#ifdef TARGET_SPARC64
747 gen_helper_fpack32(dst, cpu_gsr, src1, src2);
748#else
749 g_assert_not_reached();
750#endif
751}
752
753static void gen_op_fpadds16s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2)
754{
755 TCGv_i32 t[2];
756
757 for (int i = 0; i < 2; i++) {
758 TCGv_i32 u = tcg_temp_new_i32();
759 TCGv_i32 v = tcg_temp_new_i32();
760
761 tcg_gen_sextract_i32(u, src1, i * 16, 16);
762 tcg_gen_sextract_i32(v, src2, i * 16, 16);
763 tcg_gen_add_i32(u, u, v);
764 tcg_gen_smax_i32(u, u, tcg_constant_i32(INT16_MIN));
765 tcg_gen_smin_i32(u, u, tcg_constant_i32(INT16_MAX));
766 t[i] = u;
767 }
768 tcg_gen_deposit_i32(d, t[0], t[1], 16, 16);
769}
770
771static void gen_op_fpsubs16s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2)
772{
773 TCGv_i32 t[2];
774
775 for (int i = 0; i < 2; i++) {
776 TCGv_i32 u = tcg_temp_new_i32();
777 TCGv_i32 v = tcg_temp_new_i32();
778
779 tcg_gen_sextract_i32(u, src1, i * 16, 16);
780 tcg_gen_sextract_i32(v, src2, i * 16, 16);
781 tcg_gen_sub_i32(u, u, v);
782 tcg_gen_smax_i32(u, u, tcg_constant_i32(INT16_MIN));
783 tcg_gen_smin_i32(u, u, tcg_constant_i32(INT16_MAX));
784 t[i] = u;
785 }
786 tcg_gen_deposit_i32(d, t[0], t[1], 16, 16);
787}
788
789static void gen_op_fpadds32s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2)
790{
791 TCGv_i32 r = tcg_temp_new_i32();
792 TCGv_i32 t = tcg_temp_new_i32();
793 TCGv_i32 v = tcg_temp_new_i32();
794 TCGv_i32 z = tcg_constant_i32(0);
795
796 tcg_gen_add_i32(r, src1, src2);
797 tcg_gen_xor_i32(t, src1, src2);
798 tcg_gen_xor_i32(v, r, src2);
799 tcg_gen_andc_i32(v, v, t);
800
801 tcg_gen_setcond_i32(TCG_COND_GE, t, r, z);
802 tcg_gen_addi_i32(t, t, INT32_MAX);
803
804 tcg_gen_movcond_i32(TCG_COND_LT, d, v, z, t, r);
805}
806
807static void gen_op_fpsubs32s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2)
808{
809 TCGv_i32 r = tcg_temp_new_i32();
810 TCGv_i32 t = tcg_temp_new_i32();
811 TCGv_i32 v = tcg_temp_new_i32();
812 TCGv_i32 z = tcg_constant_i32(0);
813
814 tcg_gen_sub_i32(r, src1, src2);
815 tcg_gen_xor_i32(t, src1, src2);
816 tcg_gen_xor_i32(v, r, src1);
817 tcg_gen_and_i32(v, v, t);
818
819 tcg_gen_setcond_i32(TCG_COND_GE, t, r, z);
820 tcg_gen_addi_i32(t, t, INT32_MAX);
821
822 tcg_gen_movcond_i32(TCG_COND_LT, d, v, z, t, r);
823}
824
825static void gen_op_faligndata_i(TCGv_i64 dst, TCGv_i64 s1,
826 TCGv_i64 s2, TCGv gsr)
827{
828#ifdef TARGET_SPARC64
829 TCGv t1, t2, shift;
830
831 t1 = tcg_temp_new();
832 t2 = tcg_temp_new();
833 shift = tcg_temp_new();
834
835 tcg_gen_andi_tl(shift, gsr, 7);
836 tcg_gen_shli_tl(shift, shift, 3);
837 tcg_gen_shl_tl(t1, s1, shift);
838
839
840
841
842
843 tcg_gen_xori_tl(shift, shift, 63);
844 tcg_gen_shr_tl(t2, s2, shift);
845 tcg_gen_shri_tl(t2, t2, 1);
846
847 tcg_gen_or_tl(dst, t1, t2);
848#else
849 g_assert_not_reached();
850#endif
851}
852
853static void gen_op_faligndata_g(TCGv_i64 dst, TCGv_i64 s1, TCGv_i64 s2)
854{
855 gen_op_faligndata_i(dst, s1, s2, cpu_gsr);
856}
857
858static void gen_op_bshuffle(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2)
859{
860#ifdef TARGET_SPARC64
861 gen_helper_bshuffle(dst, cpu_gsr, src1, src2);
862#else
863 g_assert_not_reached();
864#endif
865}
866
867static void gen_op_pdistn(TCGv dst, TCGv_i64 src1, TCGv_i64 src2)
868{
869#ifdef TARGET_SPARC64
870 gen_helper_pdist(dst, tcg_constant_i64(0), src1, src2);
871#else
872 g_assert_not_reached();
873#endif
874}
875
876static void gen_op_fmul8x16al(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
877{
878 tcg_gen_ext16s_i32(src2, src2);
879 gen_helper_fmul8x16a(dst, src1, src2);
880}
881
882static void gen_op_fmul8x16au(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
883{
884 tcg_gen_sari_i32(src2, src2, 16);
885 gen_helper_fmul8x16a(dst, src1, src2);
886}
887
888static void gen_op_fmuld8ulx16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
889{
890 TCGv_i32 t0 = tcg_temp_new_i32();
891 TCGv_i32 t1 = tcg_temp_new_i32();
892 TCGv_i32 t2 = tcg_temp_new_i32();
893
894 tcg_gen_ext8u_i32(t0, src1);
895 tcg_gen_ext16s_i32(t1, src2);
896 tcg_gen_mul_i32(t0, t0, t1);
897
898 tcg_gen_extract_i32(t1, src1, 16, 8);
899 tcg_gen_sextract_i32(t2, src2, 16, 16);
900 tcg_gen_mul_i32(t1, t1, t2);
901
902 tcg_gen_concat_i32_i64(dst, t0, t1);
903}
904
905static void gen_op_fmuld8sux16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
906{
907 TCGv_i32 t0 = tcg_temp_new_i32();
908 TCGv_i32 t1 = tcg_temp_new_i32();
909 TCGv_i32 t2 = tcg_temp_new_i32();
910
911
912
913
914
915
916
917 tcg_gen_ext16s_i32(t0, src1);
918 tcg_gen_andi_i32(t0, t0, ~0xff);
919 tcg_gen_ext16s_i32(t1, src2);
920 tcg_gen_mul_i32(t0, t0, t1);
921
922 tcg_gen_sextract_i32(t1, src1, 16, 16);
923 tcg_gen_andi_i32(t1, t1, ~0xff);
924 tcg_gen_sextract_i32(t2, src2, 16, 16);
925 tcg_gen_mul_i32(t1, t1, t2);
926
927 tcg_gen_concat_i32_i64(dst, t0, t1);
928}
929
930#ifdef TARGET_SPARC64
931static void gen_vec_fchksm16(unsigned vece, TCGv_vec dst,
932 TCGv_vec src1, TCGv_vec src2)
933{
934 TCGv_vec a = tcg_temp_new_vec_matching(dst);
935 TCGv_vec c = tcg_temp_new_vec_matching(dst);
936
937 tcg_gen_add_vec(vece, a, src1, src2);
938 tcg_gen_cmp_vec(TCG_COND_LTU, vece, c, a, src1);
939
940 tcg_gen_sub_vec(vece, dst, a, c);
941}
942
943static void gen_op_fchksm16(unsigned vece, uint32_t dofs, uint32_t aofs,
944 uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
945{
946 static const TCGOpcode vecop_list[] = {
947 INDEX_op_cmp_vec, INDEX_op_add_vec, INDEX_op_sub_vec,
948 };
949 static const GVecGen3 op = {
950 .fni8 = gen_helper_fchksm16,
951 .fniv = gen_vec_fchksm16,
952 .opt_opc = vecop_list,
953 .vece = MO_16,
954 };
955 tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &op);
956}
957
958static void gen_vec_fmean16(unsigned vece, TCGv_vec dst,
959 TCGv_vec src1, TCGv_vec src2)
960{
961 TCGv_vec t = tcg_temp_new_vec_matching(dst);
962
963 tcg_gen_or_vec(vece, t, src1, src2);
964 tcg_gen_and_vec(vece, t, t, tcg_constant_vec_matching(dst, vece, 1));
965 tcg_gen_sari_vec(vece, src1, src1, 1);
966 tcg_gen_sari_vec(vece, src2, src2, 1);
967 tcg_gen_add_vec(vece, dst, src1, src2);
968 tcg_gen_add_vec(vece, dst, dst, t);
969}
970
971static void gen_op_fmean16(unsigned vece, uint32_t dofs, uint32_t aofs,
972 uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
973{
974 static const TCGOpcode vecop_list[] = {
975 INDEX_op_add_vec, INDEX_op_sari_vec,
976 };
977 static const GVecGen3 op = {
978 .fni8 = gen_helper_fmean16,
979 .fniv = gen_vec_fmean16,
980 .opt_opc = vecop_list,
981 .vece = MO_16,
982 };
983 tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &op);
984}
985#else
986#define gen_op_fchksm16 ({ qemu_build_not_reached(); NULL; })
987#define gen_op_fmean16 ({ qemu_build_not_reached(); NULL; })
988#endif
989
990static void finishing_insn(DisasContext *dc)
991{
992
993
994
995
996
997 if (dc->cpu_cond_live) {
998 tcg_gen_discard_tl(cpu_cond);
999 dc->cpu_cond_live = false;
1000 }
1001}
1002
1003static void gen_generic_branch(DisasContext *dc)
1004{
1005 TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]);
1006 TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]);
1007 TCGv c2 = tcg_constant_tl(dc->jump.c2);
1008
1009 tcg_gen_movcond_tl(dc->jump.cond, cpu_npc, dc->jump.c1, c2, npc0, npc1);
1010}
1011
1012
1013
1014static void flush_cond(DisasContext *dc)
1015{
1016 if (dc->npc == JUMP_PC) {
1017 gen_generic_branch(dc);
1018 dc->npc = DYNAMIC_PC_LOOKUP;
1019 }
1020}
1021
1022static void save_npc(DisasContext *dc)
1023{
1024 if (dc->npc & 3) {
1025 switch (dc->npc) {
1026 case JUMP_PC:
1027 gen_generic_branch(dc);
1028 dc->npc = DYNAMIC_PC_LOOKUP;
1029 break;
1030 case DYNAMIC_PC:
1031 case DYNAMIC_PC_LOOKUP:
1032 break;
1033 default:
1034 g_assert_not_reached();
1035 }
1036 } else {
1037 tcg_gen_movi_tl(cpu_npc, dc->npc);
1038 }
1039}
1040
1041static void save_state(DisasContext *dc)
1042{
1043 tcg_gen_movi_tl(cpu_pc, dc->pc);
1044 save_npc(dc);
1045}
1046
1047static void gen_exception(DisasContext *dc, int which)
1048{
1049 finishing_insn(dc);
1050 save_state(dc);
1051 gen_helper_raise_exception(tcg_env, tcg_constant_i32(which));
1052 dc->base.is_jmp = DISAS_NORETURN;
1053}
1054
1055static TCGLabel *delay_exceptionv(DisasContext *dc, TCGv_i32 excp)
1056{
1057 DisasDelayException *e = g_new0(DisasDelayException, 1);
1058
1059 e->next = dc->delay_excp_list;
1060 dc->delay_excp_list = e;
1061
1062 e->lab = gen_new_label();
1063 e->excp = excp;
1064 e->pc = dc->pc;
1065
1066 assert(e->npc != JUMP_PC);
1067 e->npc = dc->npc;
1068
1069 return e->lab;
1070}
1071
1072static TCGLabel *delay_exception(DisasContext *dc, int excp)
1073{
1074 return delay_exceptionv(dc, tcg_constant_i32(excp));
1075}
1076
1077static void gen_check_align(DisasContext *dc, TCGv addr, int mask)
1078{
1079 TCGv t = tcg_temp_new();
1080 TCGLabel *lab;
1081
1082 tcg_gen_andi_tl(t, addr, mask);
1083
1084 flush_cond(dc);
1085 lab = delay_exception(dc, TT_UNALIGNED);
1086 tcg_gen_brcondi_tl(TCG_COND_NE, t, 0, lab);
1087}
1088
1089static void gen_mov_pc_npc(DisasContext *dc)
1090{
1091 finishing_insn(dc);
1092
1093 if (dc->npc & 3) {
1094 switch (dc->npc) {
1095 case JUMP_PC:
1096 gen_generic_branch(dc);
1097 tcg_gen_mov_tl(cpu_pc, cpu_npc);
1098 dc->pc = DYNAMIC_PC_LOOKUP;
1099 break;
1100 case DYNAMIC_PC:
1101 case DYNAMIC_PC_LOOKUP:
1102 tcg_gen_mov_tl(cpu_pc, cpu_npc);
1103 dc->pc = dc->npc;
1104 break;
1105 default:
1106 g_assert_not_reached();
1107 }
1108 } else {
1109 dc->pc = dc->npc;
1110 }
1111}
1112
1113static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond,
1114 DisasContext *dc)
1115{
1116 TCGv t1;
1117
1118 cmp->c1 = t1 = tcg_temp_new();
1119 cmp->c2 = 0;
1120
1121 switch (cond & 7) {
1122 case 0x0:
1123 cmp->cond = TCG_COND_NEVER;
1124 cmp->c1 = tcg_constant_tl(0);
1125 break;
1126
1127 case 0x1:
1128 cmp->cond = TCG_COND_EQ;
1129 if (TARGET_LONG_BITS == 32 || xcc) {
1130 tcg_gen_mov_tl(t1, cpu_cc_Z);
1131 } else {
1132 tcg_gen_ext32u_tl(t1, cpu_icc_Z);
1133 }
1134 break;
1135
1136 case 0x2:
1137
1138
1139
1140
1141
1142
1143 cmp->cond = TCG_COND_EQ;
1144 tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V);
1145 tcg_gen_sextract_tl(t1, t1, xcc ? 63 : 31, 1);
1146 tcg_gen_andc_tl(t1, xcc ? cpu_cc_Z : cpu_icc_Z, t1);
1147 if (TARGET_LONG_BITS == 64 && !xcc) {
1148 tcg_gen_ext32u_tl(t1, t1);
1149 }
1150 break;
1151
1152 case 0x3:
1153 cmp->cond = TCG_COND_LT;
1154 tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V);
1155 if (TARGET_LONG_BITS == 64 && !xcc) {
1156 tcg_gen_ext32s_tl(t1, t1);
1157 }
1158 break;
1159
1160 case 0x4:
1161
1162
1163
1164
1165
1166
1167
1168 cmp->cond = TCG_COND_EQ;
1169 if (TARGET_LONG_BITS == 32 || xcc) {
1170 tcg_gen_subi_tl(t1, cpu_cc_C, 1);
1171 tcg_gen_and_tl(t1, t1, cpu_cc_Z);
1172 } else {
1173 tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1);
1174 tcg_gen_subi_tl(t1, t1, 1);
1175 tcg_gen_and_tl(t1, t1, cpu_icc_Z);
1176 tcg_gen_ext32u_tl(t1, t1);
1177 }
1178 break;
1179
1180 case 0x5:
1181 cmp->cond = TCG_COND_NE;
1182 if (TARGET_LONG_BITS == 32 || xcc) {
1183 tcg_gen_mov_tl(t1, cpu_cc_C);
1184 } else {
1185 tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1);
1186 }
1187 break;
1188
1189 case 0x6:
1190 cmp->cond = TCG_COND_LT;
1191 if (TARGET_LONG_BITS == 32 || xcc) {
1192 tcg_gen_mov_tl(t1, cpu_cc_N);
1193 } else {
1194 tcg_gen_ext32s_tl(t1, cpu_cc_N);
1195 }
1196 break;
1197
1198 case 0x7:
1199 cmp->cond = TCG_COND_LT;
1200 if (TARGET_LONG_BITS == 32 || xcc) {
1201 tcg_gen_mov_tl(t1, cpu_cc_V);
1202 } else {
1203 tcg_gen_ext32s_tl(t1, cpu_cc_V);
1204 }
1205 break;
1206 }
1207 if (cond & 8) {
1208 cmp->cond = tcg_invert_cond(cmp->cond);
1209 }
1210}
1211
1212static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond)
1213{
1214 TCGv_i32 fcc = cpu_fcc[cc];
1215 TCGv_i32 c1 = fcc;
1216 int c2 = 0;
1217 TCGCond tcond;
1218
1219
1220
1221
1222
1223
1224
1225
1226 switch (cond & 7) {
1227 case 0x0:
1228 tcond = TCG_COND_NEVER;
1229 break;
1230 case 0x1:
1231 tcond = TCG_COND_NE;
1232 break;
1233 case 0x2:
1234
1235 c1 = tcg_temp_new_i32();
1236 tcg_gen_addi_i32(c1, fcc, -1);
1237 c2 = 1;
1238 tcond = TCG_COND_LEU;
1239 break;
1240 case 0x3:
1241 c1 = tcg_temp_new_i32();
1242 tcg_gen_andi_i32(c1, fcc, 1);
1243 tcond = TCG_COND_NE;
1244 break;
1245 case 0x4:
1246 c2 = 1;
1247 tcond = TCG_COND_EQ;
1248 break;
1249 case 0x5:
1250 c2 = 2;
1251 tcond = TCG_COND_GEU;
1252 break;
1253 case 0x6:
1254 c2 = 2;
1255 tcond = TCG_COND_EQ;
1256 break;
1257 case 0x7:
1258 c2 = 3;
1259 tcond = TCG_COND_EQ;
1260 break;
1261 }
1262 if (cond & 8) {
1263 tcond = tcg_invert_cond(tcond);
1264 }
1265
1266 cmp->cond = tcond;
1267 cmp->c2 = c2;
1268 cmp->c1 = tcg_temp_new();
1269 tcg_gen_extu_i32_tl(cmp->c1, c1);
1270}
1271
1272static bool gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src)
1273{
1274 static const TCGCond cond_reg[4] = {
1275 TCG_COND_NEVER,
1276 TCG_COND_EQ,
1277 TCG_COND_LE,
1278 TCG_COND_LT,
1279 };
1280 TCGCond tcond;
1281
1282 if ((cond & 3) == 0) {
1283 return false;
1284 }
1285 tcond = cond_reg[cond & 3];
1286 if (cond & 4) {
1287 tcond = tcg_invert_cond(tcond);
1288 }
1289
1290 cmp->cond = tcond;
1291 cmp->c1 = tcg_temp_new();
1292 cmp->c2 = 0;
1293 tcg_gen_mov_tl(cmp->c1, r_src);
1294 return true;
1295}
1296
1297static void gen_op_clear_ieee_excp_and_FTT(void)
1298{
1299 tcg_gen_st_i32(tcg_constant_i32(0), tcg_env,
1300 offsetof(CPUSPARCState, fsr_cexc_ftt));
1301}
1302
1303static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src)
1304{
1305 gen_op_clear_ieee_excp_and_FTT();
1306 tcg_gen_mov_i32(dst, src);
1307}
1308
1309static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src)
1310{
1311 gen_op_clear_ieee_excp_and_FTT();
1312 tcg_gen_xori_i32(dst, src, 1u << 31);
1313}
1314
1315static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src)
1316{
1317 gen_op_clear_ieee_excp_and_FTT();
1318 tcg_gen_andi_i32(dst, src, ~(1u << 31));
1319}
1320
1321static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src)
1322{
1323 gen_op_clear_ieee_excp_and_FTT();
1324 tcg_gen_mov_i64(dst, src);
1325}
1326
1327static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src)
1328{
1329 gen_op_clear_ieee_excp_and_FTT();
1330 tcg_gen_xori_i64(dst, src, 1ull << 63);
1331}
1332
1333static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src)
1334{
1335 gen_op_clear_ieee_excp_and_FTT();
1336 tcg_gen_andi_i64(dst, src, ~(1ull << 63));
1337}
1338
1339static void gen_op_fnegq(TCGv_i128 dst, TCGv_i128 src)
1340{
1341 TCGv_i64 l = tcg_temp_new_i64();
1342 TCGv_i64 h = tcg_temp_new_i64();
1343
1344 tcg_gen_extr_i128_i64(l, h, src);
1345 tcg_gen_xori_i64(h, h, 1ull << 63);
1346 tcg_gen_concat_i64_i128(dst, l, h);
1347}
1348
1349static void gen_op_fabsq(TCGv_i128 dst, TCGv_i128 src)
1350{
1351 TCGv_i64 l = tcg_temp_new_i64();
1352 TCGv_i64 h = tcg_temp_new_i64();
1353
1354 tcg_gen_extr_i128_i64(l, h, src);
1355 tcg_gen_andi_i64(h, h, ~(1ull << 63));
1356 tcg_gen_concat_i64_i128(dst, l, h);
1357}
1358
1359static void gen_op_fmadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3)
1360{
1361 TCGv_i32 z = tcg_constant_i32(0);
1362 gen_helper_fmadds(d, tcg_env, s1, s2, s3, z, z);
1363}
1364
1365static void gen_op_fmaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3)
1366{
1367 TCGv_i32 z = tcg_constant_i32(0);
1368 gen_helper_fmaddd(d, tcg_env, s1, s2, s3, z, z);
1369}
1370
1371static void gen_op_fmsubs(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3)
1372{
1373 TCGv_i32 z = tcg_constant_i32(0);
1374 TCGv_i32 op = tcg_constant_i32(float_muladd_negate_c);
1375 gen_helper_fmadds(d, tcg_env, s1, s2, s3, z, op);
1376}
1377
1378static void gen_op_fmsubd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3)
1379{
1380 TCGv_i32 z = tcg_constant_i32(0);
1381 TCGv_i32 op = tcg_constant_i32(float_muladd_negate_c);
1382 gen_helper_fmaddd(d, tcg_env, s1, s2, s3, z, op);
1383}
1384
1385static void gen_op_fnmsubs(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3)
1386{
1387 TCGv_i32 z = tcg_constant_i32(0);
1388 TCGv_i32 op = tcg_constant_i32(float_muladd_negate_c |
1389 float_muladd_negate_result);
1390 gen_helper_fmadds(d, tcg_env, s1, s2, s3, z, op);
1391}
1392
1393static void gen_op_fnmsubd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3)
1394{
1395 TCGv_i32 z = tcg_constant_i32(0);
1396 TCGv_i32 op = tcg_constant_i32(float_muladd_negate_c |
1397 float_muladd_negate_result);
1398 gen_helper_fmaddd(d, tcg_env, s1, s2, s3, z, op);
1399}
1400
1401static void gen_op_fnmadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3)
1402{
1403 TCGv_i32 z = tcg_constant_i32(0);
1404 TCGv_i32 op = tcg_constant_i32(float_muladd_negate_result);
1405 gen_helper_fmadds(d, tcg_env, s1, s2, s3, z, op);
1406}
1407
1408static void gen_op_fnmaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3)
1409{
1410 TCGv_i32 z = tcg_constant_i32(0);
1411 TCGv_i32 op = tcg_constant_i32(float_muladd_negate_result);
1412 gen_helper_fmaddd(d, tcg_env, s1, s2, s3, z, op);
1413}
1414
1415
1416static void gen_op_fhadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2)
1417{
1418 TCGv_i32 fone = tcg_constant_i32(float32_one);
1419 TCGv_i32 mone = tcg_constant_i32(-1);
1420 TCGv_i32 op = tcg_constant_i32(0);
1421 gen_helper_fmadds(d, tcg_env, fone, s1, s2, mone, op);
1422}
1423
1424static void gen_op_fhaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2)
1425{
1426 TCGv_i64 fone = tcg_constant_i64(float64_one);
1427 TCGv_i32 mone = tcg_constant_i32(-1);
1428 TCGv_i32 op = tcg_constant_i32(0);
1429 gen_helper_fmaddd(d, tcg_env, fone, s1, s2, mone, op);
1430}
1431
1432
1433static void gen_op_fhsubs(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2)
1434{
1435 TCGv_i32 fone = tcg_constant_i32(float32_one);
1436 TCGv_i32 mone = tcg_constant_i32(-1);
1437 TCGv_i32 op = tcg_constant_i32(float_muladd_negate_c);
1438 gen_helper_fmadds(d, tcg_env, fone, s1, s2, mone, op);
1439}
1440
1441static void gen_op_fhsubd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2)
1442{
1443 TCGv_i64 fone = tcg_constant_i64(float64_one);
1444 TCGv_i32 mone = tcg_constant_i32(-1);
1445 TCGv_i32 op = tcg_constant_i32(float_muladd_negate_c);
1446 gen_helper_fmaddd(d, tcg_env, fone, s1, s2, mone, op);
1447}
1448
1449
1450static void gen_op_fnhadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2)
1451{
1452 TCGv_i32 fone = tcg_constant_i32(float32_one);
1453 TCGv_i32 mone = tcg_constant_i32(-1);
1454 TCGv_i32 op = tcg_constant_i32(float_muladd_negate_result);
1455 gen_helper_fmadds(d, tcg_env, fone, s1, s2, mone, op);
1456}
1457
1458static void gen_op_fnhaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2)
1459{
1460 TCGv_i64 fone = tcg_constant_i64(float64_one);
1461 TCGv_i32 mone = tcg_constant_i32(-1);
1462 TCGv_i32 op = tcg_constant_i32(float_muladd_negate_result);
1463 gen_helper_fmaddd(d, tcg_env, fone, s1, s2, mone, op);
1464}
1465
1466static void gen_op_fpexception_im(DisasContext *dc, int ftt)
1467{
1468
1469
1470
1471
1472
1473 tcg_gen_st_i32(tcg_constant_i32(ftt), tcg_env,
1474 offsetof(CPUSPARCState, fsr_cexc_ftt));
1475 gen_exception(dc, TT_FP_EXCP);
1476}
1477
1478static bool gen_trap_ifnofpu(DisasContext *dc)
1479{
1480#if !defined(CONFIG_USER_ONLY)
1481 if (!dc->fpu_enabled) {
1482 gen_exception(dc, TT_NFPU_INSN);
1483 return true;
1484 }
1485#endif
1486 return false;
1487}
1488
1489static bool gen_trap_iffpexception(DisasContext *dc)
1490{
1491#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509 if (dc->fsr_qne) {
1510 gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
1511 return true;
1512 }
1513#endif
1514 return false;
1515}
1516
1517static bool gen_trap_if_nofpu_fpexception(DisasContext *dc)
1518{
1519 return gen_trap_ifnofpu(dc) || gen_trap_iffpexception(dc);
1520}
1521
1522
1523typedef enum {
1524 GET_ASI_HELPER,
1525 GET_ASI_EXCP,
1526 GET_ASI_DIRECT,
1527 GET_ASI_DTWINX,
1528 GET_ASI_CODE,
1529 GET_ASI_BLOCK,
1530 GET_ASI_SHORT,
1531 GET_ASI_BCOPY,
1532 GET_ASI_BFILL,
1533} ASIType;
1534
1535typedef struct {
1536 ASIType type;
1537 int asi;
1538 int mem_idx;
1539 MemOp memop;
1540} DisasASI;
1541
1542
1543
1544
1545
1546
1547static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop)
1548{
1549 ASIType type = GET_ASI_HELPER;
1550 int mem_idx = dc->mem_idx;
1551
1552 if (asi == -1) {
1553
1554 type = GET_ASI_DIRECT;
1555 goto done;
1556 }
1557
1558#ifndef TARGET_SPARC64
1559
1560 if (asi < 0) {
1561 gen_exception(dc, TT_ILL_INSN);
1562 type = GET_ASI_EXCP;
1563 } else if (supervisor(dc)
1564
1565
1566
1567
1568 || (asi == ASI_USERDATA
1569 && (dc->def->features & CPU_FEATURE_CASA))) {
1570 switch (asi) {
1571 case ASI_USERDATA:
1572 mem_idx = MMU_USER_IDX;
1573 type = GET_ASI_DIRECT;
1574 break;
1575 case ASI_KERNELDATA:
1576 mem_idx = MMU_KERNEL_IDX;
1577 type = GET_ASI_DIRECT;
1578 break;
1579 case ASI_USERTXT:
1580 mem_idx = MMU_USER_IDX;
1581 type = GET_ASI_CODE;
1582 break;
1583 case ASI_KERNELTXT:
1584 mem_idx = MMU_KERNEL_IDX;
1585 type = GET_ASI_CODE;
1586 break;
1587 case ASI_M_BYPASS:
1588 case ASI_LEON_BYPASS:
1589 mem_idx = MMU_PHYS_IDX;
1590 type = GET_ASI_DIRECT;
1591 break;
1592 case ASI_M_BCOPY:
1593 mem_idx = MMU_KERNEL_IDX;
1594 type = GET_ASI_BCOPY;
1595 break;
1596 case ASI_M_BFILL:
1597 mem_idx = MMU_KERNEL_IDX;
1598 type = GET_ASI_BFILL;
1599 break;
1600 }
1601
1602
1603
1604
1605 mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx;
1606 } else {
1607 gen_exception(dc, TT_PRIV_INSN);
1608 type = GET_ASI_EXCP;
1609 }
1610#else
1611 if (asi < 0) {
1612 asi = dc->asi;
1613 }
1614
1615
1616
1617
1618
1619
1620 if (!supervisor(dc) && asi < 0x80) {
1621 gen_exception(dc, TT_PRIV_ACT);
1622 type = GET_ASI_EXCP;
1623 } else {
1624 switch (asi) {
1625 case ASI_REAL:
1626 case ASI_REAL_IO:
1627 case ASI_REAL_L:
1628 case ASI_REAL_IO_L:
1629 case ASI_TWINX_REAL:
1630 case ASI_TWINX_REAL_L:
1631 case ASI_QUAD_LDD_PHYS:
1632 case ASI_QUAD_LDD_PHYS_L:
1633 mem_idx = MMU_PHYS_IDX;
1634 break;
1635 case ASI_N:
1636 case ASI_NL:
1637 case ASI_TWINX_N:
1638 case ASI_TWINX_NL:
1639 case ASI_NUCLEUS_QUAD_LDD:
1640 case ASI_NUCLEUS_QUAD_LDD_L:
1641 if (hypervisor(dc)) {
1642 mem_idx = MMU_PHYS_IDX;
1643 } else {
1644 mem_idx = MMU_NUCLEUS_IDX;
1645 }
1646 break;
1647 case ASI_AIUP:
1648 case ASI_AIUPL:
1649 case ASI_TWINX_AIUP:
1650 case ASI_TWINX_AIUP_L:
1651 case ASI_BLK_AIUP_4V:
1652 case ASI_BLK_AIUP_L_4V:
1653 case ASI_BLK_AIUP:
1654 case ASI_BLK_AIUPL:
1655 case ASI_MON_AIUP:
1656 mem_idx = MMU_USER_IDX;
1657 break;
1658 case ASI_AIUS:
1659 case ASI_AIUSL:
1660 case ASI_TWINX_AIUS:
1661 case ASI_TWINX_AIUS_L:
1662 case ASI_BLK_AIUS_4V:
1663 case ASI_BLK_AIUS_L_4V:
1664 case ASI_BLK_AIUS:
1665 case ASI_BLK_AIUSL:
1666 case ASI_MON_AIUS:
1667 mem_idx = MMU_USER_SECONDARY_IDX;
1668 break;
1669 case ASI_S:
1670 case ASI_SL:
1671 case ASI_TWINX_S:
1672 case ASI_TWINX_SL:
1673 case ASI_BLK_COMMIT_S:
1674 case ASI_BLK_S:
1675 case ASI_BLK_SL:
1676 case ASI_FL8_S:
1677 case ASI_FL8_SL:
1678 case ASI_FL16_S:
1679 case ASI_FL16_SL:
1680 case ASI_MON_S:
1681 if (mem_idx == MMU_USER_IDX) {
1682 mem_idx = MMU_USER_SECONDARY_IDX;
1683 } else if (mem_idx == MMU_KERNEL_IDX) {
1684 mem_idx = MMU_KERNEL_SECONDARY_IDX;
1685 }
1686 break;
1687 case ASI_P:
1688 case ASI_PL:
1689 case ASI_TWINX_P:
1690 case ASI_TWINX_PL:
1691 case ASI_BLK_COMMIT_P:
1692 case ASI_BLK_P:
1693 case ASI_BLK_PL:
1694 case ASI_FL8_P:
1695 case ASI_FL8_PL:
1696 case ASI_FL16_P:
1697 case ASI_FL16_PL:
1698 case ASI_MON_P:
1699 break;
1700 }
1701 switch (asi) {
1702 case ASI_REAL:
1703 case ASI_REAL_IO:
1704 case ASI_REAL_L:
1705 case ASI_REAL_IO_L:
1706 case ASI_N:
1707 case ASI_NL:
1708 case ASI_AIUP:
1709 case ASI_AIUPL:
1710 case ASI_AIUS:
1711 case ASI_AIUSL:
1712 case ASI_S:
1713 case ASI_SL:
1714 case ASI_P:
1715 case ASI_PL:
1716 case ASI_MON_P:
1717 case ASI_MON_S:
1718 case ASI_MON_AIUP:
1719 case ASI_MON_AIUS:
1720 type = GET_ASI_DIRECT;
1721 break;
1722 case ASI_TWINX_REAL:
1723 case ASI_TWINX_REAL_L:
1724 case ASI_TWINX_N:
1725 case ASI_TWINX_NL:
1726 case ASI_TWINX_AIUP:
1727 case ASI_TWINX_AIUP_L:
1728 case ASI_TWINX_AIUS:
1729 case ASI_TWINX_AIUS_L:
1730 case ASI_TWINX_P:
1731 case ASI_TWINX_PL:
1732 case ASI_TWINX_S:
1733 case ASI_TWINX_SL:
1734 case ASI_QUAD_LDD_PHYS:
1735 case ASI_QUAD_LDD_PHYS_L:
1736 case ASI_NUCLEUS_QUAD_LDD:
1737 case ASI_NUCLEUS_QUAD_LDD_L:
1738 type = GET_ASI_DTWINX;
1739 break;
1740 case ASI_BLK_COMMIT_P:
1741 case ASI_BLK_COMMIT_S:
1742 case ASI_BLK_AIUP_4V:
1743 case ASI_BLK_AIUP_L_4V:
1744 case ASI_BLK_AIUP:
1745 case ASI_BLK_AIUPL:
1746 case ASI_BLK_AIUS_4V:
1747 case ASI_BLK_AIUS_L_4V:
1748 case ASI_BLK_AIUS:
1749 case ASI_BLK_AIUSL:
1750 case ASI_BLK_S:
1751 case ASI_BLK_SL:
1752 case ASI_BLK_P:
1753 case ASI_BLK_PL:
1754 type = GET_ASI_BLOCK;
1755 break;
1756 case ASI_FL8_S:
1757 case ASI_FL8_SL:
1758 case ASI_FL8_P:
1759 case ASI_FL8_PL:
1760 memop = MO_UB;
1761 type = GET_ASI_SHORT;
1762 break;
1763 case ASI_FL16_S:
1764 case ASI_FL16_SL:
1765 case ASI_FL16_P:
1766 case ASI_FL16_PL:
1767 memop = MO_TEUW;
1768 type = GET_ASI_SHORT;
1769 break;
1770 }
1771
1772 if (asi & 8) {
1773 memop ^= MO_BSWAP;
1774 }
1775 }
1776#endif
1777
1778 done:
1779 return (DisasASI){ type, asi, mem_idx, memop };
1780}
1781
1782#if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
1783static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a,
1784 TCGv_i32 asi, TCGv_i32 mop)
1785{
1786 g_assert_not_reached();
1787}
1788
1789static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r,
1790 TCGv_i32 asi, TCGv_i32 mop)
1791{
1792 g_assert_not_reached();
1793}
1794#endif
1795
1796static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
1797{
1798 switch (da->type) {
1799 case GET_ASI_EXCP:
1800 break;
1801 case GET_ASI_DTWINX:
1802 gen_exception(dc, TT_ILL_INSN);
1803 break;
1804 case GET_ASI_DIRECT:
1805 tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN);
1806 break;
1807
1808 case GET_ASI_CODE:
1809#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
1810 {
1811 MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx);
1812 TCGv_i64 t64 = tcg_temp_new_i64();
1813
1814 gen_helper_ld_code(t64, tcg_env, addr, tcg_constant_i32(oi));
1815 tcg_gen_trunc_i64_tl(dst, t64);
1816 }
1817 break;
1818#else
1819 g_assert_not_reached();
1820#endif
1821
1822 default:
1823 {
1824 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1825 TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
1826
1827 save_state(dc);
1828#ifdef TARGET_SPARC64
1829 gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop);
1830#else
1831 {
1832 TCGv_i64 t64 = tcg_temp_new_i64();
1833 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
1834 tcg_gen_trunc_i64_tl(dst, t64);
1835 }
1836#endif
1837 }
1838 break;
1839 }
1840}
1841
1842static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr)
1843{
1844 switch (da->type) {
1845 case GET_ASI_EXCP:
1846 break;
1847
1848 case GET_ASI_DTWINX:
1849 if (TARGET_LONG_BITS == 32) {
1850 gen_exception(dc, TT_ILL_INSN);
1851 break;
1852 } else if (!(dc->def->features & CPU_FEATURE_HYPV)) {
1853
1854 gen_exception(dc, TT_ILL_INSN);
1855 break;
1856 }
1857
1858
1859
1860 case GET_ASI_DIRECT:
1861 tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN);
1862 break;
1863
1864 case GET_ASI_BCOPY:
1865 assert(TARGET_LONG_BITS == 32);
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881 {
1882 MemOp mop = MO_128 | MO_ATOM_IFALIGN_PAIR;
1883 TCGv saddr = tcg_temp_new();
1884 TCGv daddr = tcg_temp_new();
1885 TCGv_i128 tmp = tcg_temp_new_i128();
1886
1887 tcg_gen_andi_tl(saddr, src, -32);
1888 tcg_gen_andi_tl(daddr, addr, -32);
1889 tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop);
1890 tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop);
1891 tcg_gen_addi_tl(saddr, saddr, 16);
1892 tcg_gen_addi_tl(daddr, daddr, 16);
1893 tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop);
1894 tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop);
1895 }
1896 break;
1897
1898 default:
1899 {
1900 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1901 TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
1902
1903 save_state(dc);
1904#ifdef TARGET_SPARC64
1905 gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop);
1906#else
1907 {
1908 TCGv_i64 t64 = tcg_temp_new_i64();
1909 tcg_gen_extu_tl_i64(t64, src);
1910 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
1911 }
1912#endif
1913
1914
1915 dc->npc = DYNAMIC_PC;
1916 }
1917 break;
1918 }
1919}
1920
1921static void gen_swap_asi(DisasContext *dc, DisasASI *da,
1922 TCGv dst, TCGv src, TCGv addr)
1923{
1924 switch (da->type) {
1925 case GET_ASI_EXCP:
1926 break;
1927 case GET_ASI_DIRECT:
1928 tcg_gen_atomic_xchg_tl(dst, addr, src,
1929 da->mem_idx, da->memop | MO_ALIGN);
1930 break;
1931 default:
1932
1933 gen_exception(dc, TT_DATA_ACCESS);
1934 break;
1935 }
1936}
1937
1938static void gen_cas_asi(DisasContext *dc, DisasASI *da,
1939 TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr)
1940{
1941 switch (da->type) {
1942 case GET_ASI_EXCP:
1943 return;
1944 case GET_ASI_DIRECT:
1945 tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv,
1946 da->mem_idx, da->memop | MO_ALIGN);
1947 break;
1948 default:
1949
1950 gen_exception(dc, TT_DATA_ACCESS);
1951 break;
1952 }
1953}
1954
1955static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
1956{
1957 switch (da->type) {
1958 case GET_ASI_EXCP:
1959 break;
1960 case GET_ASI_DIRECT:
1961 tcg_gen_atomic_xchg_tl(dst, addr, tcg_constant_tl(0xff),
1962 da->mem_idx, MO_UB);
1963 break;
1964 default:
1965
1966
1967 if (tb_cflags(dc->base.tb) & CF_PARALLEL) {
1968 gen_helper_exit_atomic(tcg_env);
1969 } else {
1970 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1971 TCGv_i32 r_mop = tcg_constant_i32(MO_UB);
1972 TCGv_i64 s64, t64;
1973
1974 save_state(dc);
1975 t64 = tcg_temp_new_i64();
1976 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
1977
1978 s64 = tcg_constant_i64(0xff);
1979 gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop);
1980
1981 tcg_gen_trunc_i64_tl(dst, t64);
1982
1983
1984 dc->npc = DYNAMIC_PC;
1985 }
1986 break;
1987 }
1988}
1989
1990static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
1991 TCGv addr, int rd)
1992{
1993 MemOp memop = da->memop;
1994 MemOp size = memop & MO_SIZE;
1995 TCGv_i32 d32;
1996 TCGv_i64 d64, l64;
1997 TCGv addr_tmp;
1998
1999
2000 if (size == MO_128) {
2001 memop = (memop & ~MO_SIZE) | MO_64;
2002 }
2003
2004 switch (da->type) {
2005 case GET_ASI_EXCP:
2006 break;
2007
2008 case GET_ASI_DIRECT:
2009 memop |= MO_ALIGN_4;
2010 switch (size) {
2011 case MO_32:
2012 d32 = tcg_temp_new_i32();
2013 tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop);
2014 gen_store_fpr_F(dc, rd, d32);
2015 break;
2016
2017 case MO_64:
2018 d64 = tcg_temp_new_i64();
2019 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop);
2020 gen_store_fpr_D(dc, rd, d64);
2021 break;
2022
2023 case MO_128:
2024 d64 = tcg_temp_new_i64();
2025 l64 = tcg_temp_new_i64();
2026 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop);
2027 addr_tmp = tcg_temp_new();
2028 tcg_gen_addi_tl(addr_tmp, addr, 8);
2029 tcg_gen_qemu_ld_i64(l64, addr_tmp, da->mem_idx, memop);
2030 gen_store_fpr_D(dc, rd, d64);
2031 gen_store_fpr_D(dc, rd + 2, l64);
2032 break;
2033 default:
2034 g_assert_not_reached();
2035 }
2036 break;
2037
2038 case GET_ASI_BLOCK:
2039
2040 if (orig_size == MO_64 && (rd & 7) == 0) {
2041
2042 addr_tmp = tcg_temp_new();
2043 d64 = tcg_temp_new_i64();
2044 for (int i = 0; ; ++i) {
2045 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx,
2046 memop | (i == 0 ? MO_ALIGN_64 : 0));
2047 gen_store_fpr_D(dc, rd + 2 * i, d64);
2048 if (i == 7) {
2049 break;
2050 }
2051 tcg_gen_addi_tl(addr_tmp, addr, 8);
2052 addr = addr_tmp;
2053 }
2054 } else {
2055 gen_exception(dc, TT_ILL_INSN);
2056 }
2057 break;
2058
2059 case GET_ASI_SHORT:
2060
2061 if (orig_size == MO_64) {
2062 d64 = tcg_temp_new_i64();
2063 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop | MO_ALIGN);
2064 gen_store_fpr_D(dc, rd, d64);
2065 } else {
2066 gen_exception(dc, TT_ILL_INSN);
2067 }
2068 break;
2069
2070 default:
2071 {
2072 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
2073 TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN);
2074
2075 save_state(dc);
2076
2077
2078
2079
2080 switch (size) {
2081 case MO_32:
2082 d64 = tcg_temp_new_i64();
2083 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
2084 d32 = tcg_temp_new_i32();
2085 tcg_gen_extrl_i64_i32(d32, d64);
2086 gen_store_fpr_F(dc, rd, d32);
2087 break;
2088 case MO_64:
2089 d64 = tcg_temp_new_i64();
2090 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
2091 gen_store_fpr_D(dc, rd, d64);
2092 break;
2093 case MO_128:
2094 d64 = tcg_temp_new_i64();
2095 l64 = tcg_temp_new_i64();
2096 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
2097 addr_tmp = tcg_temp_new();
2098 tcg_gen_addi_tl(addr_tmp, addr, 8);
2099 gen_helper_ld_asi(l64, tcg_env, addr_tmp, r_asi, r_mop);
2100 gen_store_fpr_D(dc, rd, d64);
2101 gen_store_fpr_D(dc, rd + 2, l64);
2102 break;
2103 default:
2104 g_assert_not_reached();
2105 }
2106 }
2107 break;
2108 }
2109}
2110
2111static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
2112 TCGv addr, int rd)
2113{
2114 MemOp memop = da->memop;
2115 MemOp size = memop & MO_SIZE;
2116 TCGv_i32 d32;
2117 TCGv_i64 d64;
2118 TCGv addr_tmp;
2119
2120
2121 if (size == MO_128) {
2122 memop = (memop & ~MO_SIZE) | MO_64;
2123 }
2124
2125 switch (da->type) {
2126 case GET_ASI_EXCP:
2127 break;
2128
2129 case GET_ASI_DIRECT:
2130 memop |= MO_ALIGN_4;
2131 switch (size) {
2132 case MO_32:
2133 d32 = gen_load_fpr_F(dc, rd);
2134 tcg_gen_qemu_st_i32(d32, addr, da->mem_idx, memop | MO_ALIGN);
2135 break;
2136 case MO_64:
2137 d64 = gen_load_fpr_D(dc, rd);
2138 tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_4);
2139 break;
2140 case MO_128:
2141
2142
2143
2144
2145
2146 d64 = gen_load_fpr_D(dc, rd);
2147 tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_16);
2148 addr_tmp = tcg_temp_new();
2149 tcg_gen_addi_tl(addr_tmp, addr, 8);
2150 d64 = gen_load_fpr_D(dc, rd + 2);
2151 tcg_gen_qemu_st_i64(d64, addr_tmp, da->mem_idx, memop);
2152 break;
2153 default:
2154 g_assert_not_reached();
2155 }
2156 break;
2157
2158 case GET_ASI_BLOCK:
2159
2160 if (orig_size == MO_64 && (rd & 7) == 0) {
2161
2162 addr_tmp = tcg_temp_new();
2163 for (int i = 0; ; ++i) {
2164 d64 = gen_load_fpr_D(dc, rd + 2 * i);
2165 tcg_gen_qemu_st_i64(d64, addr, da->mem_idx,
2166 memop | (i == 0 ? MO_ALIGN_64 : 0));
2167 if (i == 7) {
2168 break;
2169 }
2170 tcg_gen_addi_tl(addr_tmp, addr, 8);
2171 addr = addr_tmp;
2172 }
2173 } else {
2174 gen_exception(dc, TT_ILL_INSN);
2175 }
2176 break;
2177
2178 case GET_ASI_SHORT:
2179
2180 if (orig_size == MO_64) {
2181 d64 = gen_load_fpr_D(dc, rd);
2182 tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN);
2183 } else {
2184 gen_exception(dc, TT_ILL_INSN);
2185 }
2186 break;
2187
2188 default:
2189
2190
2191
2192 gen_exception(dc, TT_ILL_INSN);
2193 break;
2194 }
2195}
2196
2197static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
2198{
2199 TCGv hi = gen_dest_gpr(dc, rd);
2200 TCGv lo = gen_dest_gpr(dc, rd + 1);
2201
2202 switch (da->type) {
2203 case GET_ASI_EXCP:
2204 return;
2205
2206 case GET_ASI_DTWINX:
2207#ifdef TARGET_SPARC64
2208 {
2209 MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
2210 TCGv_i128 t = tcg_temp_new_i128();
2211
2212 tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop);
2213
2214
2215
2216
2217
2218 if ((mop & MO_BSWAP) == MO_TE) {
2219 tcg_gen_extr_i128_i64(lo, hi, t);
2220 } else {
2221 tcg_gen_extr_i128_i64(hi, lo, t);
2222 }
2223 }
2224 break;
2225#else
2226 g_assert_not_reached();
2227#endif
2228
2229 case GET_ASI_DIRECT:
2230 {
2231 TCGv_i64 tmp = tcg_temp_new_i64();
2232
2233 tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN);
2234
2235
2236
2237
2238 if ((da->memop & MO_BSWAP) == MO_TE) {
2239 tcg_gen_extr_i64_tl(lo, hi, tmp);
2240 } else {
2241 tcg_gen_extr_i64_tl(hi, lo, tmp);
2242 }
2243 }
2244 break;
2245
2246 case GET_ASI_CODE:
2247#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
2248 {
2249 MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx);
2250 TCGv_i64 tmp = tcg_temp_new_i64();
2251
2252 gen_helper_ld_code(tmp, tcg_env, addr, tcg_constant_i32(oi));
2253
2254
2255 if ((da->memop & MO_BSWAP) == MO_TE) {
2256 tcg_gen_extr_i64_tl(lo, hi, tmp);
2257 } else {
2258 tcg_gen_extr_i64_tl(hi, lo, tmp);
2259 }
2260 }
2261 break;
2262#else
2263 g_assert_not_reached();
2264#endif
2265
2266 default:
2267
2268
2269
2270
2271 {
2272 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
2273 TCGv_i32 r_mop = tcg_constant_i32(da->memop);
2274 TCGv_i64 tmp = tcg_temp_new_i64();
2275
2276 save_state(dc);
2277 gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop);
2278
2279
2280 if ((da->memop & MO_BSWAP) == MO_TE) {
2281 tcg_gen_extr_i64_tl(lo, hi, tmp);
2282 } else {
2283 tcg_gen_extr_i64_tl(hi, lo, tmp);
2284 }
2285 }
2286 break;
2287 }
2288
2289 gen_store_gpr(dc, rd, hi);
2290 gen_store_gpr(dc, rd + 1, lo);
2291}
2292
2293static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
2294{
2295 TCGv hi = gen_load_gpr(dc, rd);
2296 TCGv lo = gen_load_gpr(dc, rd + 1);
2297
2298 switch (da->type) {
2299 case GET_ASI_EXCP:
2300 break;
2301
2302 case GET_ASI_DTWINX:
2303#ifdef TARGET_SPARC64
2304 {
2305 MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
2306 TCGv_i128 t = tcg_temp_new_i128();
2307
2308
2309
2310
2311
2312
2313 if ((mop & MO_BSWAP) == MO_TE) {
2314 tcg_gen_concat_i64_i128(t, lo, hi);
2315 } else {
2316 tcg_gen_concat_i64_i128(t, hi, lo);
2317 }
2318 tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop);
2319 }
2320 break;
2321#else
2322 g_assert_not_reached();
2323#endif
2324
2325 case GET_ASI_DIRECT:
2326 {
2327 TCGv_i64 t64 = tcg_temp_new_i64();
2328
2329
2330
2331
2332 if ((da->memop & MO_BSWAP) == MO_TE) {
2333 tcg_gen_concat_tl_i64(t64, lo, hi);
2334 } else {
2335 tcg_gen_concat_tl_i64(t64, hi, lo);
2336 }
2337 tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN);
2338 }
2339 break;
2340
2341 case GET_ASI_BFILL:
2342 assert(TARGET_LONG_BITS == 32);
2343
2344
2345
2346
2347 {
2348 MemOp mop = MO_TE | MO_128 | MO_ATOM_IFALIGN_PAIR;
2349 TCGv_i64 t8 = tcg_temp_new_i64();
2350 TCGv_i128 t16 = tcg_temp_new_i128();
2351 TCGv daddr = tcg_temp_new();
2352
2353 tcg_gen_concat_tl_i64(t8, lo, hi);
2354 tcg_gen_concat_i64_i128(t16, t8, t8);
2355 tcg_gen_andi_tl(daddr, addr, -32);
2356 tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop);
2357 tcg_gen_addi_tl(daddr, daddr, 16);
2358 tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop);
2359 }
2360 break;
2361
2362 default:
2363
2364
2365 {
2366 TCGv_i32 r_asi = tcg_constant_i32(da->asi);
2367 TCGv_i32 r_mop = tcg_constant_i32(da->memop);
2368 TCGv_i64 t64 = tcg_temp_new_i64();
2369
2370
2371 if ((da->memop & MO_BSWAP) == MO_TE) {
2372 tcg_gen_concat_tl_i64(t64, lo, hi);
2373 } else {
2374 tcg_gen_concat_tl_i64(t64, hi, lo);
2375 }
2376
2377 save_state(dc);
2378 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
2379 }
2380 break;
2381 }
2382}
2383
2384static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2385{
2386#ifdef TARGET_SPARC64
2387 TCGv_i32 c32, zero, dst, s1, s2;
2388 TCGv_i64 c64 = tcg_temp_new_i64();
2389
2390
2391
2392
2393 c32 = tcg_temp_new_i32();
2394 tcg_gen_setcondi_i64(cmp->cond, c64, cmp->c1, cmp->c2);
2395 tcg_gen_extrl_i64_i32(c32, c64);
2396
2397 s1 = gen_load_fpr_F(dc, rs);
2398 s2 = gen_load_fpr_F(dc, rd);
2399 dst = tcg_temp_new_i32();
2400 zero = tcg_constant_i32(0);
2401
2402 tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
2403
2404 gen_store_fpr_F(dc, rd, dst);
2405#else
2406 qemu_build_not_reached();
2407#endif
2408}
2409
2410static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2411{
2412#ifdef TARGET_SPARC64
2413 TCGv_i64 dst = tcg_temp_new_i64();
2414 tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, tcg_constant_tl(cmp->c2),
2415 gen_load_fpr_D(dc, rs),
2416 gen_load_fpr_D(dc, rd));
2417 gen_store_fpr_D(dc, rd, dst);
2418#else
2419 qemu_build_not_reached();
2420#endif
2421}
2422
2423static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2424{
2425#ifdef TARGET_SPARC64
2426 TCGv c2 = tcg_constant_tl(cmp->c2);
2427 TCGv_i64 h = tcg_temp_new_i64();
2428 TCGv_i64 l = tcg_temp_new_i64();
2429
2430 tcg_gen_movcond_i64(cmp->cond, h, cmp->c1, c2,
2431 gen_load_fpr_D(dc, rs),
2432 gen_load_fpr_D(dc, rd));
2433 tcg_gen_movcond_i64(cmp->cond, l, cmp->c1, c2,
2434 gen_load_fpr_D(dc, rs + 2),
2435 gen_load_fpr_D(dc, rd + 2));
2436 gen_store_fpr_D(dc, rd, h);
2437 gen_store_fpr_D(dc, rd + 2, l);
2438#else
2439 qemu_build_not_reached();
2440#endif
2441}
2442
2443#ifdef TARGET_SPARC64
2444static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr)
2445{
2446 TCGv_i32 r_tl = tcg_temp_new_i32();
2447
2448
2449 tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl));
2450
2451
2452 tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK);
2453
2454
2455 tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
2456 tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts));
2457
2458
2459 {
2460 TCGv_ptr r_tl_tmp = tcg_temp_new_ptr();
2461 tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl);
2462 tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp);
2463 }
2464}
2465#endif
2466
2467static int extract_dfpreg(DisasContext *dc, int x)
2468{
2469 int r = x & 0x1e;
2470#ifdef TARGET_SPARC64
2471 r |= (x & 1) << 5;
2472#endif
2473 return r;
2474}
2475
2476static int extract_qfpreg(DisasContext *dc, int x)
2477{
2478 int r = x & 0x1c;
2479#ifdef TARGET_SPARC64
2480 r |= (x & 1) << 5;
2481#endif
2482 return r;
2483}
2484
2485
2486#include "decode-insns.c.inc"
2487
2488#define TRANS(NAME, AVAIL, FUNC, ...) \
2489 static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \
2490 { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); }
2491
2492#define avail_ALL(C) true
2493#ifdef TARGET_SPARC64
2494# define avail_32(C) false
2495# define avail_ASR17(C) false
2496# define avail_CASA(C) true
2497# define avail_DIV(C) true
2498# define avail_MUL(C) true
2499# define avail_POWERDOWN(C) false
2500# define avail_64(C) true
2501# define avail_FMAF(C) ((C)->def->features & CPU_FEATURE_FMAF)
2502# define avail_GL(C) ((C)->def->features & CPU_FEATURE_GL)
2503# define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV)
2504# define avail_IMA(C) ((C)->def->features & CPU_FEATURE_IMA)
2505# define avail_VIS1(C) ((C)->def->features & CPU_FEATURE_VIS1)
2506# define avail_VIS2(C) ((C)->def->features & CPU_FEATURE_VIS2)
2507# define avail_VIS3(C) ((C)->def->features & CPU_FEATURE_VIS3)
2508# define avail_VIS3B(C) avail_VIS3(C)
2509# define avail_VIS4(C) ((C)->def->features & CPU_FEATURE_VIS4)
2510#else
2511# define avail_32(C) true
2512# define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17)
2513# define avail_CASA(C) ((C)->def->features & CPU_FEATURE_CASA)
2514# define avail_DIV(C) ((C)->def->features & CPU_FEATURE_DIV)
2515# define avail_MUL(C) ((C)->def->features & CPU_FEATURE_MUL)
2516# define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN)
2517# define avail_64(C) false
2518# define avail_FMAF(C) false
2519# define avail_GL(C) false
2520# define avail_HYPV(C) false
2521# define avail_IMA(C) false
2522# define avail_VIS1(C) false
2523# define avail_VIS2(C) false
2524# define avail_VIS3(C) false
2525# define avail_VIS3B(C) false
2526# define avail_VIS4(C) false
2527#endif
2528
2529
2530static bool advance_pc(DisasContext *dc)
2531{
2532 TCGLabel *l1;
2533
2534 finishing_insn(dc);
2535
2536 if (dc->npc & 3) {
2537 switch (dc->npc) {
2538 case DYNAMIC_PC:
2539 case DYNAMIC_PC_LOOKUP:
2540 dc->pc = dc->npc;
2541 tcg_gen_mov_tl(cpu_pc, cpu_npc);
2542 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
2543 break;
2544
2545 case JUMP_PC:
2546
2547 l1 = gen_new_label();
2548 tcg_gen_brcondi_tl(dc->jump.cond, dc->jump.c1, dc->jump.c2, l1);
2549
2550
2551 gen_goto_tb(dc, 1, dc->jump_pc[1], dc->jump_pc[1] + 4);
2552
2553
2554 gen_set_label(l1);
2555 gen_goto_tb(dc, 0, dc->jump_pc[0], dc->jump_pc[0] + 4);
2556
2557 dc->base.is_jmp = DISAS_NORETURN;
2558 break;
2559
2560 default:
2561 g_assert_not_reached();
2562 }
2563 } else {
2564 dc->pc = dc->npc;
2565 dc->npc = dc->npc + 4;
2566 }
2567 return true;
2568}
2569
2570
2571
2572
2573
2574static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp,
2575 bool annul, int disp)
2576{
2577 target_ulong dest = address_mask_i(dc, dc->pc + disp * 4);
2578 target_ulong npc;
2579
2580 finishing_insn(dc);
2581
2582 if (cmp->cond == TCG_COND_ALWAYS) {
2583 if (annul) {
2584 dc->pc = dest;
2585 dc->npc = dest + 4;
2586 } else {
2587 gen_mov_pc_npc(dc);
2588 dc->npc = dest;
2589 }
2590 return true;
2591 }
2592
2593 if (cmp->cond == TCG_COND_NEVER) {
2594 npc = dc->npc;
2595 if (npc & 3) {
2596 gen_mov_pc_npc(dc);
2597 if (annul) {
2598 tcg_gen_addi_tl(cpu_pc, cpu_pc, 4);
2599 }
2600 tcg_gen_addi_tl(cpu_npc, cpu_pc, 4);
2601 } else {
2602 dc->pc = npc + (annul ? 4 : 0);
2603 dc->npc = dc->pc + 4;
2604 }
2605 return true;
2606 }
2607
2608 flush_cond(dc);
2609 npc = dc->npc;
2610
2611 if (annul) {
2612 TCGLabel *l1 = gen_new_label();
2613
2614 tcg_gen_brcondi_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1);
2615 gen_goto_tb(dc, 0, npc, dest);
2616 gen_set_label(l1);
2617 gen_goto_tb(dc, 1, npc + 4, npc + 8);
2618
2619 dc->base.is_jmp = DISAS_NORETURN;
2620 } else {
2621 if (npc & 3) {
2622 switch (npc) {
2623 case DYNAMIC_PC:
2624 case DYNAMIC_PC_LOOKUP:
2625 tcg_gen_mov_tl(cpu_pc, cpu_npc);
2626 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
2627 tcg_gen_movcond_tl(cmp->cond, cpu_npc,
2628 cmp->c1, tcg_constant_tl(cmp->c2),
2629 tcg_constant_tl(dest), cpu_npc);
2630 dc->pc = npc;
2631 break;
2632 default:
2633 g_assert_not_reached();
2634 }
2635 } else {
2636 dc->pc = npc;
2637 dc->npc = JUMP_PC;
2638 dc->jump = *cmp;
2639 dc->jump_pc[0] = dest;
2640 dc->jump_pc[1] = npc + 4;
2641
2642
2643 if (cmp->cond == TCG_COND_NE) {
2644 tcg_gen_xori_tl(cpu_cond, cmp->c1, cmp->c2);
2645 } else {
2646 tcg_gen_setcondi_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2);
2647 }
2648 dc->cpu_cond_live = true;
2649 }
2650 }
2651 return true;
2652}
2653
2654static bool raise_priv(DisasContext *dc)
2655{
2656 gen_exception(dc, TT_PRIV_INSN);
2657 return true;
2658}
2659
2660static bool raise_unimpfpop(DisasContext *dc)
2661{
2662 gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP);
2663 return true;
2664}
2665
2666static bool gen_trap_float128(DisasContext *dc)
2667{
2668 if (dc->def->features & CPU_FEATURE_FLOAT128) {
2669 return false;
2670 }
2671 return raise_unimpfpop(dc);
2672}
2673
2674static bool do_bpcc(DisasContext *dc, arg_bcc *a)
2675{
2676 DisasCompare cmp;
2677
2678 gen_compare(&cmp, a->cc, a->cond, dc);
2679 return advance_jump_cond(dc, &cmp, a->a, a->i);
2680}
2681
2682TRANS(Bicc, ALL, do_bpcc, a)
2683TRANS(BPcc, 64, do_bpcc, a)
2684
2685static bool do_fbpfcc(DisasContext *dc, arg_bcc *a)
2686{
2687 DisasCompare cmp;
2688
2689 if (gen_trap_if_nofpu_fpexception(dc)) {
2690 return true;
2691 }
2692 gen_fcompare(&cmp, a->cc, a->cond);
2693 return advance_jump_cond(dc, &cmp, a->a, a->i);
2694}
2695
2696TRANS(FBPfcc, 64, do_fbpfcc, a)
2697TRANS(FBfcc, ALL, do_fbpfcc, a)
2698
2699static bool trans_BPr(DisasContext *dc, arg_BPr *a)
2700{
2701 DisasCompare cmp;
2702
2703 if (!avail_64(dc)) {
2704 return false;
2705 }
2706 if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
2707 return false;
2708 }
2709 return advance_jump_cond(dc, &cmp, a->a, a->i);
2710}
2711
2712static bool trans_CALL(DisasContext *dc, arg_CALL *a)
2713{
2714 target_long target = address_mask_i(dc, dc->pc + a->i * 4);
2715
2716 gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc));
2717 gen_mov_pc_npc(dc);
2718 dc->npc = target;
2719 return true;
2720}
2721
2722static bool trans_NCP(DisasContext *dc, arg_NCP *a)
2723{
2724
2725
2726
2727
2728#ifdef TARGET_SPARC64
2729 return false;
2730#else
2731 gen_exception(dc, TT_NCP_INSN);
2732 return true;
2733#endif
2734}
2735
2736static bool trans_SETHI(DisasContext *dc, arg_SETHI *a)
2737{
2738
2739 if (a->rd) {
2740 gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10));
2741 }
2742 return advance_pc(dc);
2743}
2744
2745
2746
2747
2748
2749static bool do_tcc(DisasContext *dc, int cond, int cc,
2750 int rs1, bool imm, int rs2_or_imm)
2751{
2752 int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
2753 ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
2754 DisasCompare cmp;
2755 TCGLabel *lab;
2756 TCGv_i32 trap;
2757
2758
2759 if (cond == 0) {
2760 return advance_pc(dc);
2761 }
2762
2763
2764
2765
2766
2767 if (rs1 == 0 && (imm || rs2_or_imm == 0)) {
2768 trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP);
2769 } else {
2770 trap = tcg_temp_new_i32();
2771 tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1));
2772 if (imm) {
2773 tcg_gen_addi_i32(trap, trap, rs2_or_imm);
2774 } else {
2775 TCGv_i32 t2 = tcg_temp_new_i32();
2776 tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm));
2777 tcg_gen_add_i32(trap, trap, t2);
2778 }
2779 tcg_gen_andi_i32(trap, trap, mask);
2780 tcg_gen_addi_i32(trap, trap, TT_TRAP);
2781 }
2782
2783 finishing_insn(dc);
2784
2785
2786 if (cond == 8) {
2787 save_state(dc);
2788 gen_helper_raise_exception(tcg_env, trap);
2789 dc->base.is_jmp = DISAS_NORETURN;
2790 return true;
2791 }
2792
2793
2794 flush_cond(dc);
2795 lab = delay_exceptionv(dc, trap);
2796 gen_compare(&cmp, cc, cond, dc);
2797 tcg_gen_brcondi_tl(cmp.cond, cmp.c1, cmp.c2, lab);
2798
2799 return advance_pc(dc);
2800}
2801
2802static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a)
2803{
2804 if (avail_32(dc) && a->cc) {
2805 return false;
2806 }
2807 return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2);
2808}
2809
2810static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a)
2811{
2812 if (avail_64(dc)) {
2813 return false;
2814 }
2815 return do_tcc(dc, a->cond, 0, a->rs1, true, a->i);
2816}
2817
2818static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a)
2819{
2820 if (avail_32(dc)) {
2821 return false;
2822 }
2823 return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i);
2824}
2825
2826static bool trans_STBAR(DisasContext *dc, arg_STBAR *a)
2827{
2828 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
2829 return advance_pc(dc);
2830}
2831
2832static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a)
2833{
2834 if (avail_32(dc)) {
2835 return false;
2836 }
2837 if (a->mmask) {
2838
2839 tcg_gen_mb(a->mmask | TCG_BAR_SC);
2840 }
2841 if (a->cmask) {
2842
2843 dc->base.is_jmp = DISAS_EXIT;
2844 }
2845 return advance_pc(dc);
2846}
2847
2848static bool do_rd_special(DisasContext *dc, bool priv, int rd,
2849 TCGv (*func)(DisasContext *, TCGv))
2850{
2851 if (!priv) {
2852 return raise_priv(dc);
2853 }
2854 gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd)));
2855 return advance_pc(dc);
2856}
2857
2858static TCGv do_rdy(DisasContext *dc, TCGv dst)
2859{
2860 return cpu_y;
2861}
2862
2863static bool trans_RDY(DisasContext *dc, arg_RDY *a)
2864{
2865
2866
2867
2868
2869
2870 if (avail_64(dc) && a->rs1 != 0) {
2871 return false;
2872 }
2873 return do_rd_special(dc, true, a->rd, do_rdy);
2874}
2875
2876static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst)
2877{
2878 gen_helper_rdasr17(dst, tcg_env);
2879 return dst;
2880}
2881
2882TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config)
2883
2884static TCGv do_rdpic(DisasContext *dc, TCGv dst)
2885{
2886 return tcg_constant_tl(0);
2887}
2888
2889TRANS(RDPIC, HYPV, do_rd_special, supervisor(dc), a->rd, do_rdpic)
2890
2891
2892static TCGv do_rdccr(DisasContext *dc, TCGv dst)
2893{
2894 gen_helper_rdccr(dst, tcg_env);
2895 return dst;
2896}
2897
2898TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr)
2899
2900static TCGv do_rdasi(DisasContext *dc, TCGv dst)
2901{
2902#ifdef TARGET_SPARC64
2903 return tcg_constant_tl(dc->asi);
2904#else
2905 qemu_build_not_reached();
2906#endif
2907}
2908
2909TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi)
2910
2911static TCGv do_rdtick(DisasContext *dc, TCGv dst)
2912{
2913 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
2914
2915 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
2916 if (translator_io_start(&dc->base)) {
2917 dc->base.is_jmp = DISAS_EXIT;
2918 }
2919 gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
2920 tcg_constant_i32(dc->mem_idx));
2921 return dst;
2922}
2923
2924
2925TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick)
2926
2927static TCGv do_rdpc(DisasContext *dc, TCGv dst)
2928{
2929 return tcg_constant_tl(address_mask_i(dc, dc->pc));
2930}
2931
2932TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc)
2933
2934static TCGv do_rdfprs(DisasContext *dc, TCGv dst)
2935{
2936 tcg_gen_ext_i32_tl(dst, cpu_fprs);
2937 return dst;
2938}
2939
2940TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs)
2941
2942static TCGv do_rdgsr(DisasContext *dc, TCGv dst)
2943{
2944 gen_trap_ifnofpu(dc);
2945 return cpu_gsr;
2946}
2947
2948TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr)
2949
2950static TCGv do_rdsoftint(DisasContext *dc, TCGv dst)
2951{
2952 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint));
2953 return dst;
2954}
2955
2956TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint)
2957
2958static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst)
2959{
2960 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr));
2961 return dst;
2962}
2963
2964
2965TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr)
2966
2967static TCGv do_rdstick(DisasContext *dc, TCGv dst)
2968{
2969 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
2970
2971 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
2972 if (translator_io_start(&dc->base)) {
2973 dc->base.is_jmp = DISAS_EXIT;
2974 }
2975 gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
2976 tcg_constant_i32(dc->mem_idx));
2977 return dst;
2978}
2979
2980
2981TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick)
2982
2983static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst)
2984{
2985 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr));
2986 return dst;
2987}
2988
2989
2990TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr)
2991
2992
2993
2994
2995
2996
2997static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst)
2998{
2999 return tcg_constant_tl(1);
3000}
3001
3002TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status)
3003
3004static TCGv do_rdpsr(DisasContext *dc, TCGv dst)
3005{
3006 gen_helper_rdpsr(dst, tcg_env);
3007 return dst;
3008}
3009
3010TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr)
3011
3012static TCGv do_rdhpstate(DisasContext *dc, TCGv dst)
3013{
3014 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate));
3015 return dst;
3016}
3017
3018TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate)
3019
3020static TCGv do_rdhtstate(DisasContext *dc, TCGv dst)
3021{
3022 TCGv_i32 tl = tcg_temp_new_i32();
3023 TCGv_ptr tp = tcg_temp_new_ptr();
3024
3025 tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
3026 tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
3027 tcg_gen_shli_i32(tl, tl, 3);
3028 tcg_gen_ext_i32_ptr(tp, tl);
3029 tcg_gen_add_ptr(tp, tp, tcg_env);
3030
3031 tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate));
3032 return dst;
3033}
3034
3035TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate)
3036
3037static TCGv do_rdhintp(DisasContext *dc, TCGv dst)
3038{
3039 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp));
3040 return dst;
3041}
3042
3043TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp)
3044
3045static TCGv do_rdhtba(DisasContext *dc, TCGv dst)
3046{
3047 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba));
3048 return dst;
3049}
3050
3051TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba)
3052
3053static TCGv do_rdhver(DisasContext *dc, TCGv dst)
3054{
3055 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver));
3056 return dst;
3057}
3058
3059TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver)
3060
3061static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst)
3062{
3063 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr));
3064 return dst;
3065}
3066
3067TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd,
3068 do_rdhstick_cmpr)
3069
3070static TCGv do_rdwim(DisasContext *dc, TCGv dst)
3071{
3072 tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim));
3073 return dst;
3074}
3075
3076TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim)
3077
3078static TCGv do_rdtpc(DisasContext *dc, TCGv dst)
3079{
3080#ifdef TARGET_SPARC64
3081 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3082
3083 gen_load_trap_state_at_tl(r_tsptr);
3084 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc));
3085 return dst;
3086#else
3087 qemu_build_not_reached();
3088#endif
3089}
3090
3091TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc)
3092
3093static TCGv do_rdtnpc(DisasContext *dc, TCGv dst)
3094{
3095#ifdef TARGET_SPARC64
3096 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3097
3098 gen_load_trap_state_at_tl(r_tsptr);
3099 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc));
3100 return dst;
3101#else
3102 qemu_build_not_reached();
3103#endif
3104}
3105
3106TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc)
3107
3108static TCGv do_rdtstate(DisasContext *dc, TCGv dst)
3109{
3110#ifdef TARGET_SPARC64
3111 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3112
3113 gen_load_trap_state_at_tl(r_tsptr);
3114 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate));
3115 return dst;
3116#else
3117 qemu_build_not_reached();
3118#endif
3119}
3120
3121TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate)
3122
3123static TCGv do_rdtt(DisasContext *dc, TCGv dst)
3124{
3125#ifdef TARGET_SPARC64
3126 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3127
3128 gen_load_trap_state_at_tl(r_tsptr);
3129 tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt));
3130 return dst;
3131#else
3132 qemu_build_not_reached();
3133#endif
3134}
3135
3136TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt)
3137TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick)
3138
3139static TCGv do_rdtba(DisasContext *dc, TCGv dst)
3140{
3141 return cpu_tbr;
3142}
3143
3144TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba)
3145TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba)
3146
3147static TCGv do_rdpstate(DisasContext *dc, TCGv dst)
3148{
3149 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate));
3150 return dst;
3151}
3152
3153TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate)
3154
3155static TCGv do_rdtl(DisasContext *dc, TCGv dst)
3156{
3157 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl));
3158 return dst;
3159}
3160
3161TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl)
3162
3163static TCGv do_rdpil(DisasContext *dc, TCGv dst)
3164{
3165 tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil));
3166 return dst;
3167}
3168
3169TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil)
3170
3171static TCGv do_rdcwp(DisasContext *dc, TCGv dst)
3172{
3173 gen_helper_rdcwp(dst, tcg_env);
3174 return dst;
3175}
3176
3177TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp)
3178
3179static TCGv do_rdcansave(DisasContext *dc, TCGv dst)
3180{
3181 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave));
3182 return dst;
3183}
3184
3185TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave)
3186
3187static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst)
3188{
3189 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore));
3190 return dst;
3191}
3192
3193TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd,
3194 do_rdcanrestore)
3195
3196static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst)
3197{
3198 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin));
3199 return dst;
3200}
3201
3202TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin)
3203
3204static TCGv do_rdotherwin(DisasContext *dc, TCGv dst)
3205{
3206 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin));
3207 return dst;
3208}
3209
3210TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin)
3211
3212static TCGv do_rdwstate(DisasContext *dc, TCGv dst)
3213{
3214 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate));
3215 return dst;
3216}
3217
3218TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate)
3219
3220static TCGv do_rdgl(DisasContext *dc, TCGv dst)
3221{
3222 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl));
3223 return dst;
3224}
3225
3226TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl)
3227
3228
3229static TCGv do_rdssr(DisasContext *dc, TCGv dst)
3230{
3231 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr));
3232 return dst;
3233}
3234
3235TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr)
3236
3237static TCGv do_rdver(DisasContext *dc, TCGv dst)
3238{
3239 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version));
3240 return dst;
3241}
3242
3243TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver)
3244
3245static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a)
3246{
3247 if (avail_64(dc)) {
3248 gen_helper_flushw(tcg_env);
3249 return advance_pc(dc);
3250 }
3251 return false;
3252}
3253
3254static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv,
3255 void (*func)(DisasContext *, TCGv))
3256{
3257 TCGv src;
3258
3259
3260 if (!a->imm && (a->rs2_or_imm & ~0x1f)) {
3261 return false;
3262 }
3263 if (!priv) {
3264 return raise_priv(dc);
3265 }
3266
3267 if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) {
3268 src = tcg_constant_tl(a->rs2_or_imm);
3269 } else {
3270 TCGv src1 = gen_load_gpr(dc, a->rs1);
3271 if (a->rs2_or_imm == 0) {
3272 src = src1;
3273 } else {
3274 src = tcg_temp_new();
3275 if (a->imm) {
3276 tcg_gen_xori_tl(src, src1, a->rs2_or_imm);
3277 } else {
3278 tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm));
3279 }
3280 }
3281 }
3282 func(dc, src);
3283 return advance_pc(dc);
3284}
3285
3286static void do_wry(DisasContext *dc, TCGv src)
3287{
3288 tcg_gen_ext32u_tl(cpu_y, src);
3289}
3290
3291TRANS(WRY, ALL, do_wr_special, a, true, do_wry)
3292
3293static void do_wrccr(DisasContext *dc, TCGv src)
3294{
3295 gen_helper_wrccr(tcg_env, src);
3296}
3297
3298TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr)
3299
3300static void do_wrasi(DisasContext *dc, TCGv src)
3301{
3302 TCGv tmp = tcg_temp_new();
3303
3304 tcg_gen_ext8u_tl(tmp, src);
3305 tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi));
3306
3307 dc->base.is_jmp = DISAS_EXIT;
3308}
3309
3310TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi)
3311
3312static void do_wrfprs(DisasContext *dc, TCGv src)
3313{
3314#ifdef TARGET_SPARC64
3315 tcg_gen_trunc_tl_i32(cpu_fprs, src);
3316 dc->fprs_dirty = 0;
3317 dc->base.is_jmp = DISAS_EXIT;
3318#else
3319 qemu_build_not_reached();
3320#endif
3321}
3322
3323TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs)
3324
3325static bool do_priv_nop(DisasContext *dc, bool priv)
3326{
3327 if (!priv) {
3328 return raise_priv(dc);
3329 }
3330 return advance_pc(dc);
3331}
3332
3333TRANS(WRPCR, HYPV, do_priv_nop, supervisor(dc))
3334TRANS(WRPIC, HYPV, do_priv_nop, supervisor(dc))
3335
3336static void do_wrgsr(DisasContext *dc, TCGv src)
3337{
3338 gen_trap_ifnofpu(dc);
3339 tcg_gen_mov_tl(cpu_gsr, src);
3340}
3341
3342TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr)
3343
3344static void do_wrsoftint_set(DisasContext *dc, TCGv src)
3345{
3346 gen_helper_set_softint(tcg_env, src);
3347}
3348
3349TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set)
3350
3351static void do_wrsoftint_clr(DisasContext *dc, TCGv src)
3352{
3353 gen_helper_clear_softint(tcg_env, src);
3354}
3355
3356TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr)
3357
3358static void do_wrsoftint(DisasContext *dc, TCGv src)
3359{
3360 gen_helper_write_softint(tcg_env, src);
3361}
3362
3363TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint)
3364
3365static void do_wrtick_cmpr(DisasContext *dc, TCGv src)
3366{
3367 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3368
3369 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr));
3370 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
3371 translator_io_start(&dc->base);
3372 gen_helper_tick_set_limit(r_tickptr, src);
3373
3374 dc->base.is_jmp = DISAS_EXIT;
3375}
3376
3377TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr)
3378
3379static void do_wrstick(DisasContext *dc, TCGv src)
3380{
3381#ifdef TARGET_SPARC64
3382 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3383
3384 tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick));
3385 translator_io_start(&dc->base);
3386 gen_helper_tick_set_count(r_tickptr, src);
3387
3388 dc->base.is_jmp = DISAS_EXIT;
3389#else
3390 qemu_build_not_reached();
3391#endif
3392}
3393
3394TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick)
3395
3396static void do_wrstick_cmpr(DisasContext *dc, TCGv src)
3397{
3398 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3399
3400 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr));
3401 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
3402 translator_io_start(&dc->base);
3403 gen_helper_tick_set_limit(r_tickptr, src);
3404
3405 dc->base.is_jmp = DISAS_EXIT;
3406}
3407
3408TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr)
3409
3410static void do_wrpowerdown(DisasContext *dc, TCGv src)
3411{
3412 finishing_insn(dc);
3413 save_state(dc);
3414 gen_helper_power_down(tcg_env);
3415}
3416
3417TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown)
3418
3419static void do_wrmwait(DisasContext *dc, TCGv src)
3420{
3421
3422
3423
3424
3425 dc->base.is_jmp = DISAS_EXIT;
3426}
3427
3428TRANS(WRMWAIT, VIS4, do_wr_special, a, true, do_wrmwait)
3429
3430static void do_wrpsr(DisasContext *dc, TCGv src)
3431{
3432 gen_helper_wrpsr(tcg_env, src);
3433 dc->base.is_jmp = DISAS_EXIT;
3434}
3435
3436TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr)
3437
3438static void do_wrwim(DisasContext *dc, TCGv src)
3439{
3440 target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows);
3441 TCGv tmp = tcg_temp_new();
3442
3443 tcg_gen_andi_tl(tmp, src, mask);
3444 tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim));
3445}
3446
3447TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim)
3448
3449static void do_wrtpc(DisasContext *dc, TCGv src)
3450{
3451#ifdef TARGET_SPARC64
3452 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3453
3454 gen_load_trap_state_at_tl(r_tsptr);
3455 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc));
3456#else
3457 qemu_build_not_reached();
3458#endif
3459}
3460
3461TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc)
3462
3463static void do_wrtnpc(DisasContext *dc, TCGv src)
3464{
3465#ifdef TARGET_SPARC64
3466 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3467
3468 gen_load_trap_state_at_tl(r_tsptr);
3469 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc));
3470#else
3471 qemu_build_not_reached();
3472#endif
3473}
3474
3475TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc)
3476
3477static void do_wrtstate(DisasContext *dc, TCGv src)
3478{
3479#ifdef TARGET_SPARC64
3480 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3481
3482 gen_load_trap_state_at_tl(r_tsptr);
3483 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate));
3484#else
3485 qemu_build_not_reached();
3486#endif
3487}
3488
3489TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate)
3490
3491static void do_wrtt(DisasContext *dc, TCGv src)
3492{
3493#ifdef TARGET_SPARC64
3494 TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3495
3496 gen_load_trap_state_at_tl(r_tsptr);
3497 tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt));
3498#else
3499 qemu_build_not_reached();
3500#endif
3501}
3502
3503TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt)
3504
3505static void do_wrtick(DisasContext *dc, TCGv src)
3506{
3507 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3508
3509 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
3510 translator_io_start(&dc->base);
3511 gen_helper_tick_set_count(r_tickptr, src);
3512
3513 dc->base.is_jmp = DISAS_EXIT;
3514}
3515
3516TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick)
3517
3518static void do_wrtba(DisasContext *dc, TCGv src)
3519{
3520 tcg_gen_mov_tl(cpu_tbr, src);
3521}
3522
3523TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba)
3524
3525static void do_wrpstate(DisasContext *dc, TCGv src)
3526{
3527 save_state(dc);
3528 if (translator_io_start(&dc->base)) {
3529 dc->base.is_jmp = DISAS_EXIT;
3530 }
3531 gen_helper_wrpstate(tcg_env, src);
3532 dc->npc = DYNAMIC_PC;
3533}
3534
3535TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate)
3536
3537static void do_wrtl(DisasContext *dc, TCGv src)
3538{
3539 save_state(dc);
3540 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl));
3541 dc->npc = DYNAMIC_PC;
3542}
3543
3544TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl)
3545
3546static void do_wrpil(DisasContext *dc, TCGv src)
3547{
3548 if (translator_io_start(&dc->base)) {
3549 dc->base.is_jmp = DISAS_EXIT;
3550 }
3551 gen_helper_wrpil(tcg_env, src);
3552}
3553
3554TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil)
3555
3556static void do_wrcwp(DisasContext *dc, TCGv src)
3557{
3558 gen_helper_wrcwp(tcg_env, src);
3559}
3560
3561TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp)
3562
3563static void do_wrcansave(DisasContext *dc, TCGv src)
3564{
3565 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave));
3566}
3567
3568TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave)
3569
3570static void do_wrcanrestore(DisasContext *dc, TCGv src)
3571{
3572 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore));
3573}
3574
3575TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore)
3576
3577static void do_wrcleanwin(DisasContext *dc, TCGv src)
3578{
3579 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin));
3580}
3581
3582TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin)
3583
3584static void do_wrotherwin(DisasContext *dc, TCGv src)
3585{
3586 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin));
3587}
3588
3589TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin)
3590
3591static void do_wrwstate(DisasContext *dc, TCGv src)
3592{
3593 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate));
3594}
3595
3596TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate)
3597
3598static void do_wrgl(DisasContext *dc, TCGv src)
3599{
3600 gen_helper_wrgl(tcg_env, src);
3601}
3602
3603TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl)
3604
3605
3606static void do_wrssr(DisasContext *dc, TCGv src)
3607{
3608 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr));
3609}
3610
3611TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr)
3612
3613TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba)
3614
3615static void do_wrhpstate(DisasContext *dc, TCGv src)
3616{
3617 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate));
3618 dc->base.is_jmp = DISAS_EXIT;
3619}
3620
3621TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate)
3622
3623static void do_wrhtstate(DisasContext *dc, TCGv src)
3624{
3625 TCGv_i32 tl = tcg_temp_new_i32();
3626 TCGv_ptr tp = tcg_temp_new_ptr();
3627
3628 tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
3629 tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
3630 tcg_gen_shli_i32(tl, tl, 3);
3631 tcg_gen_ext_i32_ptr(tp, tl);
3632 tcg_gen_add_ptr(tp, tp, tcg_env);
3633
3634 tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate));
3635}
3636
3637TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate)
3638
3639static void do_wrhintp(DisasContext *dc, TCGv src)
3640{
3641 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp));
3642}
3643
3644TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp)
3645
3646static void do_wrhtba(DisasContext *dc, TCGv src)
3647{
3648 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba));
3649}
3650
3651TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba)
3652
3653static void do_wrhstick_cmpr(DisasContext *dc, TCGv src)
3654{
3655 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3656
3657 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr));
3658 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick));
3659 translator_io_start(&dc->base);
3660 gen_helper_tick_set_limit(r_tickptr, src);
3661
3662 dc->base.is_jmp = DISAS_EXIT;
3663}
3664
3665TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc),
3666 do_wrhstick_cmpr)
3667
3668static bool do_saved_restored(DisasContext *dc, bool saved)
3669{
3670 if (!supervisor(dc)) {
3671 return raise_priv(dc);
3672 }
3673 if (saved) {
3674 gen_helper_saved(tcg_env);
3675 } else {
3676 gen_helper_restored(tcg_env);
3677 }
3678 return advance_pc(dc);
3679}
3680
3681TRANS(SAVED, 64, do_saved_restored, true)
3682TRANS(RESTORED, 64, do_saved_restored, false)
3683
3684static bool trans_NOP(DisasContext *dc, arg_NOP *a)
3685{
3686 return advance_pc(dc);
3687}
3688
3689
3690
3691
3692
3693TRANS(NOP_v7, 32, trans_NOP, a)
3694TRANS(NOP_v9, 64, trans_NOP, a)
3695
3696static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a,
3697 void (*func)(TCGv, TCGv, TCGv),
3698 void (*funci)(TCGv, TCGv, target_long),
3699 bool logic_cc)
3700{
3701 TCGv dst, src1;
3702
3703
3704 if (!a->imm && a->rs2_or_imm & ~0x1f) {
3705 return false;
3706 }
3707
3708 if (logic_cc) {
3709 dst = cpu_cc_N;
3710 } else {
3711 dst = gen_dest_gpr(dc, a->rd);
3712 }
3713 src1 = gen_load_gpr(dc, a->rs1);
3714
3715 if (a->imm || a->rs2_or_imm == 0) {
3716 if (funci) {
3717 funci(dst, src1, a->rs2_or_imm);
3718 } else {
3719 func(dst, src1, tcg_constant_tl(a->rs2_or_imm));
3720 }
3721 } else {
3722 func(dst, src1, cpu_regs[a->rs2_or_imm]);
3723 }
3724
3725 if (logic_cc) {
3726 if (TARGET_LONG_BITS == 64) {
3727 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
3728 tcg_gen_movi_tl(cpu_icc_C, 0);
3729 }
3730 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
3731 tcg_gen_movi_tl(cpu_cc_C, 0);
3732 tcg_gen_movi_tl(cpu_cc_V, 0);
3733 }
3734
3735 gen_store_gpr(dc, a->rd, dst);
3736 return advance_pc(dc);
3737}
3738
3739static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a,
3740 void (*func)(TCGv, TCGv, TCGv),
3741 void (*funci)(TCGv, TCGv, target_long),
3742 void (*func_cc)(TCGv, TCGv, TCGv))
3743{
3744 if (a->cc) {
3745 return do_arith_int(dc, a, func_cc, NULL, false);
3746 }
3747 return do_arith_int(dc, a, func, funci, false);
3748}
3749
3750static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a,
3751 void (*func)(TCGv, TCGv, TCGv),
3752 void (*funci)(TCGv, TCGv, target_long))
3753{
3754 return do_arith_int(dc, a, func, funci, a->cc);
3755}
3756
3757TRANS(ADD, ALL, do_arith, a, tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_addcc)
3758TRANS(SUB, ALL, do_arith, a, tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_subcc)
3759TRANS(ADDC, ALL, do_arith, a, gen_op_addc, NULL, gen_op_addccc)
3760TRANS(SUBC, ALL, do_arith, a, gen_op_subc, NULL, gen_op_subccc)
3761
3762TRANS(TADDcc, ALL, do_arith, a, NULL, NULL, gen_op_taddcc)
3763TRANS(TSUBcc, ALL, do_arith, a, NULL, NULL, gen_op_tsubcc)
3764TRANS(TADDccTV, ALL, do_arith, a, NULL, NULL, gen_op_taddcctv)
3765TRANS(TSUBccTV, ALL, do_arith, a, NULL, NULL, gen_op_tsubcctv)
3766
3767TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl)
3768TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl)
3769TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL)
3770TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL)
3771TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL)
3772
3773TRANS(MULX, 64, do_arith, a, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL)
3774TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL)
3775TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL)
3776TRANS(MULScc, ALL, do_arith, a, NULL, NULL, gen_op_mulscc)
3777
3778TRANS(UDIVcc, DIV, do_arith, a, NULL, NULL, gen_op_udivcc)
3779TRANS(SDIV, DIV, do_arith, a, gen_op_sdiv, NULL, gen_op_sdivcc)
3780
3781
3782TRANS(POPC, 64, do_arith, a, gen_op_popc, NULL, NULL)
3783
3784static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a)
3785{
3786
3787 if (!a->cc && a->rs1 == 0) {
3788 if (a->imm || a->rs2_or_imm == 0) {
3789 gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm));
3790 } else if (a->rs2_or_imm & ~0x1f) {
3791
3792 return false;
3793 } else {
3794 gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]);
3795 }
3796 return advance_pc(dc);
3797 }
3798 return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl);
3799}
3800
3801static bool trans_UDIV(DisasContext *dc, arg_r_r_ri *a)
3802{
3803 TCGv_i64 t1, t2;
3804 TCGv dst;
3805
3806 if (!avail_DIV(dc)) {
3807 return false;
3808 }
3809
3810 if (!a->imm && a->rs2_or_imm & ~0x1f) {
3811 return false;
3812 }
3813
3814 if (unlikely(a->rs2_or_imm == 0)) {
3815 gen_exception(dc, TT_DIV_ZERO);
3816 return true;
3817 }
3818
3819 if (a->imm) {
3820 t2 = tcg_constant_i64((uint32_t)a->rs2_or_imm);
3821 } else {
3822 TCGLabel *lab;
3823 TCGv_i32 n2;
3824
3825 finishing_insn(dc);
3826 flush_cond(dc);
3827
3828 n2 = tcg_temp_new_i32();
3829 tcg_gen_trunc_tl_i32(n2, cpu_regs[a->rs2_or_imm]);
3830
3831 lab = delay_exception(dc, TT_DIV_ZERO);
3832 tcg_gen_brcondi_i32(TCG_COND_EQ, n2, 0, lab);
3833
3834 t2 = tcg_temp_new_i64();
3835#ifdef TARGET_SPARC64
3836 tcg_gen_ext32u_i64(t2, cpu_regs[a->rs2_or_imm]);
3837#else
3838 tcg_gen_extu_i32_i64(t2, cpu_regs[a->rs2_or_imm]);
3839#endif
3840 }
3841
3842 t1 = tcg_temp_new_i64();
3843 tcg_gen_concat_tl_i64(t1, gen_load_gpr(dc, a->rs1), cpu_y);
3844
3845 tcg_gen_divu_i64(t1, t1, t2);
3846 tcg_gen_umin_i64(t1, t1, tcg_constant_i64(UINT32_MAX));
3847
3848 dst = gen_dest_gpr(dc, a->rd);
3849 tcg_gen_trunc_i64_tl(dst, t1);
3850 gen_store_gpr(dc, a->rd, dst);
3851 return advance_pc(dc);
3852}
3853
3854static bool trans_UDIVX(DisasContext *dc, arg_r_r_ri *a)
3855{
3856 TCGv dst, src1, src2;
3857
3858 if (!avail_64(dc)) {
3859 return false;
3860 }
3861
3862 if (!a->imm && a->rs2_or_imm & ~0x1f) {
3863 return false;
3864 }
3865
3866 if (unlikely(a->rs2_or_imm == 0)) {
3867 gen_exception(dc, TT_DIV_ZERO);
3868 return true;
3869 }
3870
3871 if (a->imm) {
3872 src2 = tcg_constant_tl(a->rs2_or_imm);
3873 } else {
3874 TCGLabel *lab;
3875
3876 finishing_insn(dc);
3877 flush_cond(dc);
3878
3879 lab = delay_exception(dc, TT_DIV_ZERO);
3880 src2 = cpu_regs[a->rs2_or_imm];
3881 tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab);
3882 }
3883
3884 dst = gen_dest_gpr(dc, a->rd);
3885 src1 = gen_load_gpr(dc, a->rs1);
3886
3887 tcg_gen_divu_tl(dst, src1, src2);
3888 gen_store_gpr(dc, a->rd, dst);
3889 return advance_pc(dc);
3890}
3891
3892static bool trans_SDIVX(DisasContext *dc, arg_r_r_ri *a)
3893{
3894 TCGv dst, src1, src2;
3895
3896 if (!avail_64(dc)) {
3897 return false;
3898 }
3899
3900 if (!a->imm && a->rs2_or_imm & ~0x1f) {
3901 return false;
3902 }
3903
3904 if (unlikely(a->rs2_or_imm == 0)) {
3905 gen_exception(dc, TT_DIV_ZERO);
3906 return true;
3907 }
3908
3909 dst = gen_dest_gpr(dc, a->rd);
3910 src1 = gen_load_gpr(dc, a->rs1);
3911
3912 if (a->imm) {
3913 if (unlikely(a->rs2_or_imm == -1)) {
3914 tcg_gen_neg_tl(dst, src1);
3915 gen_store_gpr(dc, a->rd, dst);
3916 return advance_pc(dc);
3917 }
3918 src2 = tcg_constant_tl(a->rs2_or_imm);
3919 } else {
3920 TCGLabel *lab;
3921 TCGv t1, t2;
3922
3923 finishing_insn(dc);
3924 flush_cond(dc);
3925
3926 lab = delay_exception(dc, TT_DIV_ZERO);
3927 src2 = cpu_regs[a->rs2_or_imm];
3928 tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab);
3929
3930
3931
3932
3933
3934 t1 = tcg_temp_new();
3935 t2 = tcg_temp_new();
3936 tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src1, (target_long)INT64_MIN);
3937 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, -1);
3938 tcg_gen_and_tl(t1, t1, t2);
3939 tcg_gen_movcond_tl(TCG_COND_NE, t1, t1, tcg_constant_tl(0),
3940 tcg_constant_tl(1), src2);
3941 src2 = t1;
3942 }
3943
3944 tcg_gen_div_tl(dst, src1, src2);
3945 gen_store_gpr(dc, a->rd, dst);
3946 return advance_pc(dc);
3947}
3948
3949static bool gen_edge(DisasContext *dc, arg_r_r_r *a,
3950 int width, bool cc, bool little_endian)
3951{
3952 TCGv dst, s1, s2, l, r, t, m;
3953 uint64_t amask = address_mask_i(dc, -8);
3954
3955 dst = gen_dest_gpr(dc, a->rd);
3956 s1 = gen_load_gpr(dc, a->rs1);
3957 s2 = gen_load_gpr(dc, a->rs2);
3958
3959 if (cc) {
3960 gen_op_subcc(cpu_cc_N, s1, s2);
3961 }
3962
3963 l = tcg_temp_new();
3964 r = tcg_temp_new();
3965 t = tcg_temp_new();
3966
3967 switch (width) {
3968 case 8:
3969 tcg_gen_andi_tl(l, s1, 7);
3970 tcg_gen_andi_tl(r, s2, 7);
3971 tcg_gen_xori_tl(r, r, 7);
3972 m = tcg_constant_tl(0xff);
3973 break;
3974 case 16:
3975 tcg_gen_extract_tl(l, s1, 1, 2);
3976 tcg_gen_extract_tl(r, s2, 1, 2);
3977 tcg_gen_xori_tl(r, r, 3);
3978 m = tcg_constant_tl(0xf);
3979 break;
3980 case 32:
3981 tcg_gen_extract_tl(l, s1, 2, 1);
3982 tcg_gen_extract_tl(r, s2, 2, 1);
3983 tcg_gen_xori_tl(r, r, 1);
3984 m = tcg_constant_tl(0x3);
3985 break;
3986 default:
3987 abort();
3988 }
3989
3990
3991 if (little_endian) {
3992 tcg_gen_shl_tl(l, m, l);
3993 tcg_gen_and_tl(l, l, m);
3994 } else {
3995 tcg_gen_shr_tl(l, m, l);
3996 }
3997
3998 if (little_endian) {
3999 tcg_gen_shr_tl(r, m, r);
4000 } else {
4001 tcg_gen_shl_tl(r, m, r);
4002 tcg_gen_and_tl(r, r, m);
4003 }
4004
4005
4006 tcg_gen_xor_tl(t, s1, s2);
4007 tcg_gen_and_tl(r, r, l);
4008 tcg_gen_movcond_tl(TCG_COND_TSTEQ, dst, t, tcg_constant_tl(amask), r, l);
4009
4010 gen_store_gpr(dc, a->rd, dst);
4011 return advance_pc(dc);
4012}
4013
4014TRANS(EDGE8cc, VIS1, gen_edge, a, 8, 1, 0)
4015TRANS(EDGE8Lcc, VIS1, gen_edge, a, 8, 1, 1)
4016TRANS(EDGE16cc, VIS1, gen_edge, a, 16, 1, 0)
4017TRANS(EDGE16Lcc, VIS1, gen_edge, a, 16, 1, 1)
4018TRANS(EDGE32cc, VIS1, gen_edge, a, 32, 1, 0)
4019TRANS(EDGE32Lcc, VIS1, gen_edge, a, 32, 1, 1)
4020
4021TRANS(EDGE8N, VIS2, gen_edge, a, 8, 0, 0)
4022TRANS(EDGE8LN, VIS2, gen_edge, a, 8, 0, 1)
4023TRANS(EDGE16N, VIS2, gen_edge, a, 16, 0, 0)
4024TRANS(EDGE16LN, VIS2, gen_edge, a, 16, 0, 1)
4025TRANS(EDGE32N, VIS2, gen_edge, a, 32, 0, 0)
4026TRANS(EDGE32LN, VIS2, gen_edge, a, 32, 0, 1)
4027
4028static bool do_rr(DisasContext *dc, arg_r_r *a,
4029 void (*func)(TCGv, TCGv))
4030{
4031 TCGv dst = gen_dest_gpr(dc, a->rd);
4032 TCGv src = gen_load_gpr(dc, a->rs);
4033
4034 func(dst, src);
4035 gen_store_gpr(dc, a->rd, dst);
4036 return advance_pc(dc);
4037}
4038
4039TRANS(LZCNT, VIS3, do_rr, a, gen_op_lzcnt)
4040
4041static bool do_rrr(DisasContext *dc, arg_r_r_r *a,
4042 void (*func)(TCGv, TCGv, TCGv))
4043{
4044 TCGv dst = gen_dest_gpr(dc, a->rd);
4045 TCGv src1 = gen_load_gpr(dc, a->rs1);
4046 TCGv src2 = gen_load_gpr(dc, a->rs2);
4047
4048 func(dst, src1, src2);
4049 gen_store_gpr(dc, a->rd, dst);
4050 return advance_pc(dc);
4051}
4052
4053TRANS(ARRAY8, VIS1, do_rrr, a, gen_helper_array8)
4054TRANS(ARRAY16, VIS1, do_rrr, a, gen_op_array16)
4055TRANS(ARRAY32, VIS1, do_rrr, a, gen_op_array32)
4056
4057TRANS(ADDXC, VIS3, do_rrr, a, gen_op_addxc)
4058TRANS(ADDXCcc, VIS3, do_rrr, a, gen_op_addxccc)
4059
4060TRANS(SUBXC, VIS4, do_rrr, a, gen_op_subxc)
4061TRANS(SUBXCcc, VIS4, do_rrr, a, gen_op_subxccc)
4062
4063TRANS(UMULXHI, VIS3, do_rrr, a, gen_op_umulxhi)
4064
4065static void gen_op_alignaddr(TCGv dst, TCGv s1, TCGv s2)
4066{
4067#ifdef TARGET_SPARC64
4068 TCGv tmp = tcg_temp_new();
4069
4070 tcg_gen_add_tl(tmp, s1, s2);
4071 tcg_gen_andi_tl(dst, tmp, -8);
4072 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
4073#else
4074 g_assert_not_reached();
4075#endif
4076}
4077
4078static void gen_op_alignaddrl(TCGv dst, TCGv s1, TCGv s2)
4079{
4080#ifdef TARGET_SPARC64
4081 TCGv tmp = tcg_temp_new();
4082
4083 tcg_gen_add_tl(tmp, s1, s2);
4084 tcg_gen_andi_tl(dst, tmp, -8);
4085 tcg_gen_neg_tl(tmp, tmp);
4086 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
4087#else
4088 g_assert_not_reached();
4089#endif
4090}
4091
4092TRANS(ALIGNADDR, VIS1, do_rrr, a, gen_op_alignaddr)
4093TRANS(ALIGNADDRL, VIS1, do_rrr, a, gen_op_alignaddrl)
4094
4095static void gen_op_bmask(TCGv dst, TCGv s1, TCGv s2)
4096{
4097#ifdef TARGET_SPARC64
4098 tcg_gen_add_tl(dst, s1, s2);
4099 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, dst, 32, 32);
4100#else
4101 g_assert_not_reached();
4102#endif
4103}
4104
4105TRANS(BMASK, VIS2, do_rrr, a, gen_op_bmask)
4106
4107static bool do_cmask(DisasContext *dc, int rs2, void (*func)(TCGv, TCGv, TCGv))
4108{
4109 func(cpu_gsr, cpu_gsr, gen_load_gpr(dc, rs2));
4110 return true;
4111}
4112
4113TRANS(CMASK8, VIS3, do_cmask, a->rs2, gen_helper_cmask8)
4114TRANS(CMASK16, VIS3, do_cmask, a->rs2, gen_helper_cmask16)
4115TRANS(CMASK32, VIS3, do_cmask, a->rs2, gen_helper_cmask32)
4116
4117static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u)
4118{
4119 TCGv dst, src1, src2;
4120
4121
4122 if (avail_32(dc) && a->x) {
4123 return false;
4124 }
4125
4126 src2 = tcg_temp_new();
4127 tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31);
4128 src1 = gen_load_gpr(dc, a->rs1);
4129 dst = gen_dest_gpr(dc, a->rd);
4130
4131 if (l) {
4132 tcg_gen_shl_tl(dst, src1, src2);
4133 if (!a->x) {
4134 tcg_gen_ext32u_tl(dst, dst);
4135 }
4136 } else if (u) {
4137 if (!a->x) {
4138 tcg_gen_ext32u_tl(dst, src1);
4139 src1 = dst;
4140 }
4141 tcg_gen_shr_tl(dst, src1, src2);
4142 } else {
4143 if (!a->x) {
4144 tcg_gen_ext32s_tl(dst, src1);
4145 src1 = dst;
4146 }
4147 tcg_gen_sar_tl(dst, src1, src2);
4148 }
4149 gen_store_gpr(dc, a->rd, dst);
4150 return advance_pc(dc);
4151}
4152
4153TRANS(SLL_r, ALL, do_shift_r, a, true, true)
4154TRANS(SRL_r, ALL, do_shift_r, a, false, true)
4155TRANS(SRA_r, ALL, do_shift_r, a, false, false)
4156
4157static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u)
4158{
4159 TCGv dst, src1;
4160
4161
4162 if (avail_32(dc) && (a->x || a->i >= 32)) {
4163 return false;
4164 }
4165
4166 src1 = gen_load_gpr(dc, a->rs1);
4167 dst = gen_dest_gpr(dc, a->rd);
4168
4169 if (avail_32(dc) || a->x) {
4170 if (l) {
4171 tcg_gen_shli_tl(dst, src1, a->i);
4172 } else if (u) {
4173 tcg_gen_shri_tl(dst, src1, a->i);
4174 } else {
4175 tcg_gen_sari_tl(dst, src1, a->i);
4176 }
4177 } else {
4178 if (l) {
4179 tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i);
4180 } else if (u) {
4181 tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i);
4182 } else {
4183 tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i);
4184 }
4185 }
4186 gen_store_gpr(dc, a->rd, dst);
4187 return advance_pc(dc);
4188}
4189
4190TRANS(SLL_i, ALL, do_shift_i, a, true, true)
4191TRANS(SRL_i, ALL, do_shift_i, a, false, true)
4192TRANS(SRA_i, ALL, do_shift_i, a, false, false)
4193
4194static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm)
4195{
4196
4197 if (!imm && rs2_or_imm & ~0x1f) {
4198 return NULL;
4199 }
4200 if (imm || rs2_or_imm == 0) {
4201 return tcg_constant_tl(rs2_or_imm);
4202 } else {
4203 return cpu_regs[rs2_or_imm];
4204 }
4205}
4206
4207static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2)
4208{
4209 TCGv dst = gen_load_gpr(dc, rd);
4210 TCGv c2 = tcg_constant_tl(cmp->c2);
4211
4212 tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, c2, src2, dst);
4213 gen_store_gpr(dc, rd, dst);
4214 return advance_pc(dc);
4215}
4216
4217static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *a)
4218{
4219 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
4220 DisasCompare cmp;
4221
4222 if (src2 == NULL) {
4223 return false;
4224 }
4225 gen_compare(&cmp, a->cc, a->cond, dc);
4226 return do_mov_cond(dc, &cmp, a->rd, src2);
4227}
4228
4229static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *a)
4230{
4231 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
4232 DisasCompare cmp;
4233
4234 if (src2 == NULL) {
4235 return false;
4236 }
4237 gen_fcompare(&cmp, a->cc, a->cond);
4238 return do_mov_cond(dc, &cmp, a->rd, src2);
4239}
4240
4241static bool trans_MOVR(DisasContext *dc, arg_MOVR *a)
4242{
4243 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
4244 DisasCompare cmp;
4245
4246 if (src2 == NULL) {
4247 return false;
4248 }
4249 if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
4250 return false;
4251 }
4252 return do_mov_cond(dc, &cmp, a->rd, src2);
4253}
4254
4255static bool do_add_special(DisasContext *dc, arg_r_r_ri *a,
4256 bool (*func)(DisasContext *dc, int rd, TCGv src))
4257{
4258 TCGv src1, sum;
4259
4260
4261 if (!a->imm && a->rs2_or_imm & ~0x1f) {
4262 return false;
4263 }
4264
4265
4266
4267
4268
4269
4270 sum = tcg_temp_new();
4271 src1 = gen_load_gpr(dc, a->rs1);
4272 if (a->imm || a->rs2_or_imm == 0) {
4273 tcg_gen_addi_tl(sum, src1, a->rs2_or_imm);
4274 } else {
4275 tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]);
4276 }
4277 return func(dc, a->rd, sum);
4278}
4279
4280static bool do_jmpl(DisasContext *dc, int rd, TCGv src)
4281{
4282
4283
4284
4285
4286 target_ulong cur_pc = dc->pc;
4287
4288 gen_check_align(dc, src, 3);
4289
4290 gen_mov_pc_npc(dc);
4291 tcg_gen_mov_tl(cpu_npc, src);
4292 gen_address_mask(dc, cpu_npc);
4293 gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc));
4294
4295 dc->npc = DYNAMIC_PC_LOOKUP;
4296 return true;
4297}
4298
4299TRANS(JMPL, ALL, do_add_special, a, do_jmpl)
4300
4301static bool do_rett(DisasContext *dc, int rd, TCGv src)
4302{
4303 if (!supervisor(dc)) {
4304 return raise_priv(dc);
4305 }
4306
4307 gen_check_align(dc, src, 3);
4308
4309 gen_mov_pc_npc(dc);
4310 tcg_gen_mov_tl(cpu_npc, src);
4311 gen_helper_rett(tcg_env);
4312
4313 dc->npc = DYNAMIC_PC;
4314 return true;
4315}
4316
4317TRANS(RETT, 32, do_add_special, a, do_rett)
4318
4319static bool do_return(DisasContext *dc, int rd, TCGv src)
4320{
4321 gen_check_align(dc, src, 3);
4322 gen_helper_restore(tcg_env);
4323
4324 gen_mov_pc_npc(dc);
4325 tcg_gen_mov_tl(cpu_npc, src);
4326 gen_address_mask(dc, cpu_npc);
4327
4328 dc->npc = DYNAMIC_PC_LOOKUP;
4329 return true;
4330}
4331
4332TRANS(RETURN, 64, do_add_special, a, do_return)
4333
4334static bool do_save(DisasContext *dc, int rd, TCGv src)
4335{
4336 gen_helper_save(tcg_env);
4337 gen_store_gpr(dc, rd, src);
4338 return advance_pc(dc);
4339}
4340
4341TRANS(SAVE, ALL, do_add_special, a, do_save)
4342
4343static bool do_restore(DisasContext *dc, int rd, TCGv src)
4344{
4345 gen_helper_restore(tcg_env);
4346 gen_store_gpr(dc, rd, src);
4347 return advance_pc(dc);
4348}
4349
4350TRANS(RESTORE, ALL, do_add_special, a, do_restore)
4351
4352static bool do_done_retry(DisasContext *dc, bool done)
4353{
4354 if (!supervisor(dc)) {
4355 return raise_priv(dc);
4356 }
4357 dc->npc = DYNAMIC_PC;
4358 dc->pc = DYNAMIC_PC;
4359 translator_io_start(&dc->base);
4360 if (done) {
4361 gen_helper_done(tcg_env);
4362 } else {
4363 gen_helper_retry(tcg_env);
4364 }
4365 return true;
4366}
4367
4368TRANS(DONE, 64, do_done_retry, true)
4369TRANS(RETRY, 64, do_done_retry, false)
4370
4371
4372
4373
4374
4375static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm)
4376{
4377 TCGv addr, tmp = NULL;
4378
4379
4380 if (!imm && rs2_or_imm & ~0x1f) {
4381 return NULL;
4382 }
4383
4384 addr = gen_load_gpr(dc, rs1);
4385 if (rs2_or_imm) {
4386 tmp = tcg_temp_new();
4387 if (imm) {
4388 tcg_gen_addi_tl(tmp, addr, rs2_or_imm);
4389 } else {
4390 tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]);
4391 }
4392 addr = tmp;
4393 }
4394 if (AM_CHECK(dc)) {
4395 if (!tmp) {
4396 tmp = tcg_temp_new();
4397 }
4398 tcg_gen_ext32u_tl(tmp, addr);
4399 addr = tmp;
4400 }
4401 return addr;
4402}
4403
4404static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
4405{
4406 TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4407 DisasASI da;
4408
4409 if (addr == NULL) {
4410 return false;
4411 }
4412 da = resolve_asi(dc, a->asi, mop);
4413
4414 reg = gen_dest_gpr(dc, a->rd);
4415 gen_ld_asi(dc, &da, reg, addr);
4416 gen_store_gpr(dc, a->rd, reg);
4417 return advance_pc(dc);
4418}
4419
4420TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL)
4421TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB)
4422TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW)
4423TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB)
4424TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW)
4425TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL)
4426TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ)
4427
4428static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
4429{
4430 TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4431 DisasASI da;
4432
4433 if (addr == NULL) {
4434 return false;
4435 }
4436 da = resolve_asi(dc, a->asi, mop);
4437
4438 reg = gen_load_gpr(dc, a->rd);
4439 gen_st_asi(dc, &da, reg, addr);
4440 return advance_pc(dc);
4441}
4442
4443TRANS(STW, ALL, do_st_gpr, a, MO_TEUL)
4444TRANS(STB, ALL, do_st_gpr, a, MO_UB)
4445TRANS(STH, ALL, do_st_gpr, a, MO_TEUW)
4446TRANS(STX, 64, do_st_gpr, a, MO_TEUQ)
4447
4448static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a)
4449{
4450 TCGv addr;
4451 DisasASI da;
4452
4453 if (a->rd & 1) {
4454 return false;
4455 }
4456 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4457 if (addr == NULL) {
4458 return false;
4459 }
4460 da = resolve_asi(dc, a->asi, MO_TEUQ);
4461 gen_ldda_asi(dc, &da, addr, a->rd);
4462 return advance_pc(dc);
4463}
4464
4465static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a)
4466{
4467 TCGv addr;
4468 DisasASI da;
4469
4470 if (a->rd & 1) {
4471 return false;
4472 }
4473 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4474 if (addr == NULL) {
4475 return false;
4476 }
4477 da = resolve_asi(dc, a->asi, MO_TEUQ);
4478 gen_stda_asi(dc, &da, addr, a->rd);
4479 return advance_pc(dc);
4480}
4481
4482static bool trans_LDSTUB(DisasContext *dc, arg_r_r_ri_asi *a)
4483{
4484 TCGv addr, reg;
4485 DisasASI da;
4486
4487 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4488 if (addr == NULL) {
4489 return false;
4490 }
4491 da = resolve_asi(dc, a->asi, MO_UB);
4492
4493 reg = gen_dest_gpr(dc, a->rd);
4494 gen_ldstub_asi(dc, &da, reg, addr);
4495 gen_store_gpr(dc, a->rd, reg);
4496 return advance_pc(dc);
4497}
4498
4499static bool trans_SWAP(DisasContext *dc, arg_r_r_ri_asi *a)
4500{
4501 TCGv addr, dst, src;
4502 DisasASI da;
4503
4504 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4505 if (addr == NULL) {
4506 return false;
4507 }
4508 da = resolve_asi(dc, a->asi, MO_TEUL);
4509
4510 dst = gen_dest_gpr(dc, a->rd);
4511 src = gen_load_gpr(dc, a->rd);
4512 gen_swap_asi(dc, &da, dst, src, addr);
4513 gen_store_gpr(dc, a->rd, dst);
4514 return advance_pc(dc);
4515}
4516
4517static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
4518{
4519 TCGv addr, o, n, c;
4520 DisasASI da;
4521
4522 addr = gen_ldst_addr(dc, a->rs1, true, 0);
4523 if (addr == NULL) {
4524 return false;
4525 }
4526 da = resolve_asi(dc, a->asi, mop);
4527
4528 o = gen_dest_gpr(dc, a->rd);
4529 n = gen_load_gpr(dc, a->rd);
4530 c = gen_load_gpr(dc, a->rs2_or_imm);
4531 gen_cas_asi(dc, &da, o, n, c, addr);
4532 gen_store_gpr(dc, a->rd, o);
4533 return advance_pc(dc);
4534}
4535
4536TRANS(CASA, CASA, do_casa, a, MO_TEUL)
4537TRANS(CASXA, 64, do_casa, a, MO_TEUQ)
4538
4539static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
4540{
4541 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4542 DisasASI da;
4543
4544 if (addr == NULL) {
4545 return false;
4546 }
4547 if (gen_trap_if_nofpu_fpexception(dc)) {
4548 return true;
4549 }
4550 if (sz == MO_128 && gen_trap_float128(dc)) {
4551 return true;
4552 }
4553 da = resolve_asi(dc, a->asi, MO_TE | sz);
4554 gen_ldf_asi(dc, &da, sz, addr, a->rd);
4555 gen_update_fprs_dirty(dc, a->rd);
4556 return advance_pc(dc);
4557}
4558
4559TRANS(LDF, ALL, do_ld_fpr, a, MO_32)
4560TRANS(LDDF, ALL, do_ld_fpr, a, MO_64)
4561TRANS(LDQF, ALL, do_ld_fpr, a, MO_128)
4562
4563TRANS(LDFA, 64, do_ld_fpr, a, MO_32)
4564TRANS(LDDFA, 64, do_ld_fpr, a, MO_64)
4565TRANS(LDQFA, 64, do_ld_fpr, a, MO_128)
4566
4567static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
4568{
4569 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4570 DisasASI da;
4571
4572 if (addr == NULL) {
4573 return false;
4574 }
4575
4576 if (gen_trap_ifnofpu(dc)) {
4577 return true;
4578 }
4579 if (sz == MO_128 && gen_trap_float128(dc)) {
4580 return true;
4581 }
4582 da = resolve_asi(dc, a->asi, MO_TE | sz);
4583 gen_stf_asi(dc, &da, sz, addr, a->rd);
4584 return advance_pc(dc);
4585}
4586
4587TRANS(STF, ALL, do_st_fpr, a, MO_32)
4588TRANS(STDF, ALL, do_st_fpr, a, MO_64)
4589TRANS(STQF, 64, do_st_fpr, a, MO_128)
4590
4591TRANS(STFA, 64, do_st_fpr, a, MO_32)
4592TRANS(STDFA, 64, do_st_fpr, a, MO_64)
4593TRANS(STQFA, 64, do_st_fpr, a, MO_128)
4594
4595static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a)
4596{
4597 TCGv addr;
4598
4599 if (!avail_32(dc)) {
4600 return false;
4601 }
4602 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4603 if (addr == NULL) {
4604 return false;
4605 }
4606 if (!supervisor(dc)) {
4607 return raise_priv(dc);
4608 }
4609#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
4610 if (gen_trap_ifnofpu(dc)) {
4611 return true;
4612 }
4613 if (!dc->fsr_qne) {
4614 gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
4615 return true;
4616 }
4617
4618
4619 TCGv_i64 fq = tcg_temp_new_i64();
4620 tcg_gen_ld_i64(fq, tcg_env, offsetof(CPUSPARCState, fq.d));
4621 tcg_gen_qemu_st_i64(fq, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN_4);
4622
4623
4624 tcg_gen_st_i32(tcg_constant_i32(0), tcg_env,
4625 offsetof(CPUSPARCState, fsr_qne));
4626 dc->fsr_qne = 0;
4627
4628 return advance_pc(dc);
4629#else
4630 qemu_build_not_reached();
4631#endif
4632}
4633
4634static bool trans_LDFSR(DisasContext *dc, arg_r_r_ri *a)
4635{
4636 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4637 TCGv_i32 tmp;
4638
4639 if (addr == NULL) {
4640 return false;
4641 }
4642 if (gen_trap_if_nofpu_fpexception(dc)) {
4643 return true;
4644 }
4645
4646 tmp = tcg_temp_new_i32();
4647 tcg_gen_qemu_ld_i32(tmp, addr, dc->mem_idx, MO_TEUL | MO_ALIGN);
4648
4649 tcg_gen_extract_i32(cpu_fcc[0], tmp, FSR_FCC0_SHIFT, 2);
4650
4651
4652 gen_helper_set_fsr_nofcc_noftt(tcg_env, tmp);
4653 return advance_pc(dc);
4654}
4655
4656static bool do_ldxfsr(DisasContext *dc, arg_r_r_ri *a, bool entire)
4657{
4658#ifdef TARGET_SPARC64
4659 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4660 TCGv_i64 t64;
4661 TCGv_i32 lo, hi;
4662
4663 if (addr == NULL) {
4664 return false;
4665 }
4666 if (gen_trap_if_nofpu_fpexception(dc)) {
4667 return true;
4668 }
4669
4670 t64 = tcg_temp_new_i64();
4671 tcg_gen_qemu_ld_i64(t64, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN);
4672
4673 lo = tcg_temp_new_i32();
4674 hi = cpu_fcc[3];
4675 tcg_gen_extr_i64_i32(lo, hi, t64);
4676 tcg_gen_extract_i32(cpu_fcc[0], lo, FSR_FCC0_SHIFT, 2);
4677 tcg_gen_extract_i32(cpu_fcc[1], hi, FSR_FCC1_SHIFT - 32, 2);
4678 tcg_gen_extract_i32(cpu_fcc[2], hi, FSR_FCC2_SHIFT - 32, 2);
4679 tcg_gen_extract_i32(cpu_fcc[3], hi, FSR_FCC3_SHIFT - 32, 2);
4680
4681 if (entire) {
4682 gen_helper_set_fsr_nofcc(tcg_env, lo);
4683 } else {
4684 gen_helper_set_fsr_nofcc_noftt(tcg_env, lo);
4685 }
4686 return advance_pc(dc);
4687#else
4688 return false;
4689#endif
4690}
4691
4692TRANS(LDXFSR, 64, do_ldxfsr, a, false)
4693TRANS(LDXEFSR, VIS3B, do_ldxfsr, a, true)
4694
4695static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop)
4696{
4697 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4698 TCGv fsr;
4699
4700 if (addr == NULL) {
4701 return false;
4702 }
4703
4704 if (gen_trap_ifnofpu(dc)) {
4705 return true;
4706 }
4707
4708 fsr = tcg_temp_new();
4709 gen_helper_get_fsr(fsr, tcg_env);
4710 tcg_gen_qemu_st_tl(fsr, addr, dc->mem_idx, mop | MO_ALIGN);
4711 return advance_pc(dc);
4712}
4713
4714TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL)
4715TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ)
4716
4717static bool do_fc(DisasContext *dc, int rd, int32_t c)
4718{
4719 if (gen_trap_ifnofpu(dc)) {
4720 return true;
4721 }
4722 gen_store_fpr_F(dc, rd, tcg_constant_i32(c));
4723 return advance_pc(dc);
4724}
4725
4726TRANS(FZEROs, VIS1, do_fc, a->rd, 0)
4727TRANS(FONEs, VIS1, do_fc, a->rd, -1)
4728
4729static bool do_dc(DisasContext *dc, int rd, int64_t c)
4730{
4731 if (gen_trap_ifnofpu(dc)) {
4732 return true;
4733 }
4734 gen_store_fpr_D(dc, rd, tcg_constant_i64(c));
4735 return advance_pc(dc);
4736}
4737
4738TRANS(FZEROd, VIS1, do_dc, a->rd, 0)
4739TRANS(FONEd, VIS1, do_dc, a->rd, -1)
4740
4741static bool do_ff(DisasContext *dc, arg_r_r *a,
4742 void (*func)(TCGv_i32, TCGv_i32))
4743{
4744 TCGv_i32 tmp;
4745
4746 if (gen_trap_if_nofpu_fpexception(dc)) {
4747 return true;
4748 }
4749
4750 tmp = gen_load_fpr_F(dc, a->rs);
4751 func(tmp, tmp);
4752 gen_store_fpr_F(dc, a->rd, tmp);
4753 return advance_pc(dc);
4754}
4755
4756TRANS(FMOVs, ALL, do_ff, a, gen_op_fmovs)
4757TRANS(FNEGs, ALL, do_ff, a, gen_op_fnegs)
4758TRANS(FABSs, ALL, do_ff, a, gen_op_fabss)
4759TRANS(FSRCs, VIS1, do_ff, a, tcg_gen_mov_i32)
4760TRANS(FNOTs, VIS1, do_ff, a, tcg_gen_not_i32)
4761
4762static bool do_fd(DisasContext *dc, arg_r_r *a,
4763 void (*func)(TCGv_i32, TCGv_i64))
4764{
4765 TCGv_i32 dst;
4766 TCGv_i64 src;
4767
4768 if (gen_trap_ifnofpu(dc)) {
4769 return true;
4770 }
4771
4772 dst = tcg_temp_new_i32();
4773 src = gen_load_fpr_D(dc, a->rs);
4774 func(dst, src);
4775 gen_store_fpr_F(dc, a->rd, dst);
4776 return advance_pc(dc);
4777}
4778
4779TRANS(FPACK16, VIS1, do_fd, a, gen_op_fpack16)
4780TRANS(FPACKFIX, VIS1, do_fd, a, gen_op_fpackfix)
4781
4782static bool do_env_ff(DisasContext *dc, arg_r_r *a,
4783 void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
4784{
4785 TCGv_i32 tmp;
4786
4787 if (gen_trap_if_nofpu_fpexception(dc)) {
4788 return true;
4789 }
4790
4791 tmp = gen_load_fpr_F(dc, a->rs);
4792 func(tmp, tcg_env, tmp);
4793 gen_store_fpr_F(dc, a->rd, tmp);
4794 return advance_pc(dc);
4795}
4796
4797TRANS(FSQRTs, ALL, do_env_ff, a, gen_helper_fsqrts)
4798TRANS(FiTOs, ALL, do_env_ff, a, gen_helper_fitos)
4799TRANS(FsTOi, ALL, do_env_ff, a, gen_helper_fstoi)
4800
4801static bool do_env_fd(DisasContext *dc, arg_r_r *a,
4802 void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
4803{
4804 TCGv_i32 dst;
4805 TCGv_i64 src;
4806
4807 if (gen_trap_if_nofpu_fpexception(dc)) {
4808 return true;
4809 }
4810
4811 dst = tcg_temp_new_i32();
4812 src = gen_load_fpr_D(dc, a->rs);
4813 func(dst, tcg_env, src);
4814 gen_store_fpr_F(dc, a->rd, dst);
4815 return advance_pc(dc);
4816}
4817
4818TRANS(FdTOs, ALL, do_env_fd, a, gen_helper_fdtos)
4819TRANS(FdTOi, ALL, do_env_fd, a, gen_helper_fdtoi)
4820TRANS(FxTOs, 64, do_env_fd, a, gen_helper_fxtos)
4821
4822static bool do_dd(DisasContext *dc, arg_r_r *a,
4823 void (*func)(TCGv_i64, TCGv_i64))
4824{
4825 TCGv_i64 dst, src;
4826
4827 if (gen_trap_if_nofpu_fpexception(dc)) {
4828 return true;
4829 }
4830
4831 dst = tcg_temp_new_i64();
4832 src = gen_load_fpr_D(dc, a->rs);
4833 func(dst, src);
4834 gen_store_fpr_D(dc, a->rd, dst);
4835 return advance_pc(dc);
4836}
4837
4838TRANS(FMOVd, 64, do_dd, a, gen_op_fmovd)
4839TRANS(FNEGd, 64, do_dd, a, gen_op_fnegd)
4840TRANS(FABSd, 64, do_dd, a, gen_op_fabsd)
4841TRANS(FSRCd, VIS1, do_dd, a, tcg_gen_mov_i64)
4842TRANS(FNOTd, VIS1, do_dd, a, tcg_gen_not_i64)
4843
4844static bool do_env_dd(DisasContext *dc, arg_r_r *a,
4845 void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
4846{
4847 TCGv_i64 dst, src;
4848
4849 if (gen_trap_if_nofpu_fpexception(dc)) {
4850 return true;
4851 }
4852
4853 dst = tcg_temp_new_i64();
4854 src = gen_load_fpr_D(dc, a->rs);
4855 func(dst, tcg_env, src);
4856 gen_store_fpr_D(dc, a->rd, dst);
4857 return advance_pc(dc);
4858}
4859
4860TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd)
4861TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod)
4862TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox)
4863
4864static bool do_df(DisasContext *dc, arg_r_r *a,
4865 void (*func)(TCGv_i64, TCGv_i32))
4866{
4867 TCGv_i64 dst;
4868 TCGv_i32 src;
4869
4870 if (gen_trap_ifnofpu(dc)) {
4871 return true;
4872 }
4873
4874 dst = tcg_temp_new_i64();
4875 src = gen_load_fpr_F(dc, a->rs);
4876 func(dst, src);
4877 gen_store_fpr_D(dc, a->rd, dst);
4878 return advance_pc(dc);
4879}
4880
4881TRANS(FEXPAND, VIS1, do_df, a, gen_helper_fexpand)
4882
4883static bool do_env_df(DisasContext *dc, arg_r_r *a,
4884 void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
4885{
4886 TCGv_i64 dst;
4887 TCGv_i32 src;
4888
4889 if (gen_trap_if_nofpu_fpexception(dc)) {
4890 return true;
4891 }
4892
4893 dst = tcg_temp_new_i64();
4894 src = gen_load_fpr_F(dc, a->rs);
4895 func(dst, tcg_env, src);
4896 gen_store_fpr_D(dc, a->rd, dst);
4897 return advance_pc(dc);
4898}
4899
4900TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod)
4901TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod)
4902TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox)
4903
4904static bool do_qq(DisasContext *dc, arg_r_r *a,
4905 void (*func)(TCGv_i128, TCGv_i128))
4906{
4907 TCGv_i128 t;
4908
4909 if (gen_trap_ifnofpu(dc)) {
4910 return true;
4911 }
4912 if (gen_trap_float128(dc)) {
4913 return true;
4914 }
4915
4916 gen_op_clear_ieee_excp_and_FTT();
4917 t = gen_load_fpr_Q(dc, a->rs);
4918 func(t, t);
4919 gen_store_fpr_Q(dc, a->rd, t);
4920 return advance_pc(dc);
4921}
4922
4923TRANS(FMOVq, 64, do_qq, a, tcg_gen_mov_i128)
4924TRANS(FNEGq, 64, do_qq, a, gen_op_fnegq)
4925TRANS(FABSq, 64, do_qq, a, gen_op_fabsq)
4926
4927static bool do_env_qq(DisasContext *dc, arg_r_r *a,
4928 void (*func)(TCGv_i128, TCGv_env, TCGv_i128))
4929{
4930 TCGv_i128 t;
4931
4932 if (gen_trap_if_nofpu_fpexception(dc)) {
4933 return true;
4934 }
4935 if (gen_trap_float128(dc)) {
4936 return true;
4937 }
4938
4939 t = gen_load_fpr_Q(dc, a->rs);
4940 func(t, tcg_env, t);
4941 gen_store_fpr_Q(dc, a->rd, t);
4942 return advance_pc(dc);
4943}
4944
4945TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq)
4946
4947static bool do_env_fq(DisasContext *dc, arg_r_r *a,
4948 void (*func)(TCGv_i32, TCGv_env, TCGv_i128))
4949{
4950 TCGv_i128 src;
4951 TCGv_i32 dst;
4952
4953 if (gen_trap_if_nofpu_fpexception(dc)) {
4954 return true;
4955 }
4956 if (gen_trap_float128(dc)) {
4957 return true;
4958 }
4959
4960 src = gen_load_fpr_Q(dc, a->rs);
4961 dst = tcg_temp_new_i32();
4962 func(dst, tcg_env, src);
4963 gen_store_fpr_F(dc, a->rd, dst);
4964 return advance_pc(dc);
4965}
4966
4967TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos)
4968TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi)
4969
4970static bool do_env_dq(DisasContext *dc, arg_r_r *a,
4971 void (*func)(TCGv_i64, TCGv_env, TCGv_i128))
4972{
4973 TCGv_i128 src;
4974 TCGv_i64 dst;
4975
4976 if (gen_trap_if_nofpu_fpexception(dc)) {
4977 return true;
4978 }
4979 if (gen_trap_float128(dc)) {
4980 return true;
4981 }
4982
4983 src = gen_load_fpr_Q(dc, a->rs);
4984 dst = tcg_temp_new_i64();
4985 func(dst, tcg_env, src);
4986 gen_store_fpr_D(dc, a->rd, dst);
4987 return advance_pc(dc);
4988}
4989
4990TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod)
4991TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox)
4992
4993static bool do_env_qf(DisasContext *dc, arg_r_r *a,
4994 void (*func)(TCGv_i128, TCGv_env, TCGv_i32))
4995{
4996 TCGv_i32 src;
4997 TCGv_i128 dst;
4998
4999 if (gen_trap_if_nofpu_fpexception(dc)) {
5000 return true;
5001 }
5002 if (gen_trap_float128(dc)) {
5003 return true;
5004 }
5005
5006 src = gen_load_fpr_F(dc, a->rs);
5007 dst = tcg_temp_new_i128();
5008 func(dst, tcg_env, src);
5009 gen_store_fpr_Q(dc, a->rd, dst);
5010 return advance_pc(dc);
5011}
5012
5013TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq)
5014TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq)
5015
5016static bool do_env_qd(DisasContext *dc, arg_r_r *a,
5017 void (*func)(TCGv_i128, TCGv_env, TCGv_i64))
5018{
5019 TCGv_i64 src;
5020 TCGv_i128 dst;
5021
5022 if (gen_trap_if_nofpu_fpexception(dc)) {
5023 return true;
5024 }
5025
5026 src = gen_load_fpr_D(dc, a->rs);
5027 dst = tcg_temp_new_i128();
5028 func(dst, tcg_env, src);
5029 gen_store_fpr_Q(dc, a->rd, dst);
5030 return advance_pc(dc);
5031}
5032
5033TRANS(FdTOq, ALL, do_env_qd, a, gen_helper_fdtoq)
5034TRANS(FxTOq, 64, do_env_qd, a, gen_helper_fxtoq)
5035
5036static bool do_fff(DisasContext *dc, arg_r_r_r *a,
5037 void (*func)(TCGv_i32, TCGv_i32, TCGv_i32))
5038{
5039 TCGv_i32 src1, src2;
5040
5041 if (gen_trap_ifnofpu(dc)) {
5042 return true;
5043 }
5044
5045 src1 = gen_load_fpr_F(dc, a->rs1);
5046 src2 = gen_load_fpr_F(dc, a->rs2);
5047 func(src1, src1, src2);
5048 gen_store_fpr_F(dc, a->rd, src1);
5049 return advance_pc(dc);
5050}
5051
5052TRANS(FPADD16s, VIS1, do_fff, a, tcg_gen_vec_add16_i32)
5053TRANS(FPADD32s, VIS1, do_fff, a, tcg_gen_add_i32)
5054TRANS(FPSUB16s, VIS1, do_fff, a, tcg_gen_vec_sub16_i32)
5055TRANS(FPSUB32s, VIS1, do_fff, a, tcg_gen_sub_i32)
5056TRANS(FNORs, VIS1, do_fff, a, tcg_gen_nor_i32)
5057TRANS(FANDNOTs, VIS1, do_fff, a, tcg_gen_andc_i32)
5058TRANS(FXORs, VIS1, do_fff, a, tcg_gen_xor_i32)
5059TRANS(FNANDs, VIS1, do_fff, a, tcg_gen_nand_i32)
5060TRANS(FANDs, VIS1, do_fff, a, tcg_gen_and_i32)
5061TRANS(FXNORs, VIS1, do_fff, a, tcg_gen_eqv_i32)
5062TRANS(FORNOTs, VIS1, do_fff, a, tcg_gen_orc_i32)
5063TRANS(FORs, VIS1, do_fff, a, tcg_gen_or_i32)
5064
5065TRANS(FHADDs, VIS3, do_fff, a, gen_op_fhadds)
5066TRANS(FHSUBs, VIS3, do_fff, a, gen_op_fhsubs)
5067TRANS(FNHADDs, VIS3, do_fff, a, gen_op_fnhadds)
5068
5069TRANS(FPADDS16s, VIS3, do_fff, a, gen_op_fpadds16s)
5070TRANS(FPSUBS16s, VIS3, do_fff, a, gen_op_fpsubs16s)
5071TRANS(FPADDS32s, VIS3, do_fff, a, gen_op_fpadds32s)
5072TRANS(FPSUBS32s, VIS3, do_fff, a, gen_op_fpsubs32s)
5073
5074static bool do_env_fff(DisasContext *dc, arg_r_r_r *a,
5075 void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
5076{
5077 TCGv_i32 src1, src2;
5078
5079 if (gen_trap_if_nofpu_fpexception(dc)) {
5080 return true;
5081 }
5082
5083 src1 = gen_load_fpr_F(dc, a->rs1);
5084 src2 = gen_load_fpr_F(dc, a->rs2);
5085 func(src1, tcg_env, src1, src2);
5086 gen_store_fpr_F(dc, a->rd, src1);
5087 return advance_pc(dc);
5088}
5089
5090TRANS(FADDs, ALL, do_env_fff, a, gen_helper_fadds)
5091TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs)
5092TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls)
5093TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs)
5094TRANS(FNADDs, VIS3, do_env_fff, a, gen_helper_fnadds)
5095TRANS(FNMULs, VIS3, do_env_fff, a, gen_helper_fnmuls)
5096
5097static bool do_dff(DisasContext *dc, arg_r_r_r *a,
5098 void (*func)(TCGv_i64, TCGv_i32, TCGv_i32))
5099{
5100 TCGv_i64 dst;
5101 TCGv_i32 src1, src2;
5102
5103 if (gen_trap_ifnofpu(dc)) {
5104 return true;
5105 }
5106
5107 dst = tcg_temp_new_i64();
5108 src1 = gen_load_fpr_F(dc, a->rs1);
5109 src2 = gen_load_fpr_F(dc, a->rs2);
5110 func(dst, src1, src2);
5111 gen_store_fpr_D(dc, a->rd, dst);
5112 return advance_pc(dc);
5113}
5114
5115TRANS(FMUL8x16AU, VIS1, do_dff, a, gen_op_fmul8x16au)
5116TRANS(FMUL8x16AL, VIS1, do_dff, a, gen_op_fmul8x16al)
5117TRANS(FMULD8SUx16, VIS1, do_dff, a, gen_op_fmuld8sux16)
5118TRANS(FMULD8ULx16, VIS1, do_dff, a, gen_op_fmuld8ulx16)
5119TRANS(FPMERGE, VIS1, do_dff, a, gen_helper_fpmerge)
5120
5121static bool do_dfd(DisasContext *dc, arg_r_r_r *a,
5122 void (*func)(TCGv_i64, TCGv_i32, TCGv_i64))
5123{
5124 TCGv_i64 dst, src2;
5125 TCGv_i32 src1;
5126
5127 if (gen_trap_ifnofpu(dc)) {
5128 return true;
5129 }
5130
5131 dst = tcg_temp_new_i64();
5132 src1 = gen_load_fpr_F(dc, a->rs1);
5133 src2 = gen_load_fpr_D(dc, a->rs2);
5134 func(dst, src1, src2);
5135 gen_store_fpr_D(dc, a->rd, dst);
5136 return advance_pc(dc);
5137}
5138
5139TRANS(FMUL8x16, VIS1, do_dfd, a, gen_helper_fmul8x16)
5140
5141static bool do_gvec_ddd(DisasContext *dc, arg_r_r_r *a, MemOp vece,
5142 void (*func)(unsigned, uint32_t, uint32_t,
5143 uint32_t, uint32_t, uint32_t))
5144{
5145 if (gen_trap_ifnofpu(dc)) {
5146 return true;
5147 }
5148
5149 func(vece, gen_offset_fpr_D(a->rd), gen_offset_fpr_D(a->rs1),
5150 gen_offset_fpr_D(a->rs2), 8, 8);
5151 return advance_pc(dc);
5152}
5153
5154TRANS(FPADD8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_add)
5155TRANS(FPADD16, VIS1, do_gvec_ddd, a, MO_16, tcg_gen_gvec_add)
5156TRANS(FPADD32, VIS1, do_gvec_ddd, a, MO_32, tcg_gen_gvec_add)
5157
5158TRANS(FPSUB8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_sub)
5159TRANS(FPSUB16, VIS1, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sub)
5160TRANS(FPSUB32, VIS1, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sub)
5161
5162TRANS(FCHKSM16, VIS3, do_gvec_ddd, a, MO_16, gen_op_fchksm16)
5163TRANS(FMEAN16, VIS3, do_gvec_ddd, a, MO_16, gen_op_fmean16)
5164
5165TRANS(FPADDS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_ssadd)
5166TRANS(FPADDS16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_ssadd)
5167TRANS(FPADDS32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_ssadd)
5168TRANS(FPADDUS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_usadd)
5169TRANS(FPADDUS16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_usadd)
5170
5171TRANS(FPSUBS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_sssub)
5172TRANS(FPSUBS16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sssub)
5173TRANS(FPSUBS32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sssub)
5174TRANS(FPSUBUS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_ussub)
5175TRANS(FPSUBUS16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_ussub)
5176
5177TRANS(FSLL16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_shlv)
5178TRANS(FSLL32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_shlv)
5179TRANS(FSRL16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_shrv)
5180TRANS(FSRL32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_shrv)
5181TRANS(FSRA16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sarv)
5182TRANS(FSRA32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sarv)
5183
5184TRANS(FPMIN8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_smin)
5185TRANS(FPMIN16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_smin)
5186TRANS(FPMIN32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_smin)
5187TRANS(FPMINU8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_umin)
5188TRANS(FPMINU16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_umin)
5189TRANS(FPMINU32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_umin)
5190
5191TRANS(FPMAX8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_smax)
5192TRANS(FPMAX16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_smax)
5193TRANS(FPMAX32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_smax)
5194TRANS(FPMAXU8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_umax)
5195TRANS(FPMAXU16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_umax)
5196TRANS(FPMAXU32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_umax)
5197
5198static bool do_ddd(DisasContext *dc, arg_r_r_r *a,
5199 void (*func)(TCGv_i64, TCGv_i64, TCGv_i64))
5200{
5201 TCGv_i64 dst, src1, src2;
5202
5203 if (gen_trap_ifnofpu(dc)) {
5204 return true;
5205 }
5206
5207 dst = tcg_temp_new_i64();
5208 src1 = gen_load_fpr_D(dc, a->rs1);
5209 src2 = gen_load_fpr_D(dc, a->rs2);
5210 func(dst, src1, src2);
5211 gen_store_fpr_D(dc, a->rd, dst);
5212 return advance_pc(dc);
5213}
5214
5215TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16)
5216TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16)
5217
5218TRANS(FNORd, VIS1, do_ddd, a, tcg_gen_nor_i64)
5219TRANS(FANDNOTd, VIS1, do_ddd, a, tcg_gen_andc_i64)
5220TRANS(FXORd, VIS1, do_ddd, a, tcg_gen_xor_i64)
5221TRANS(FNANDd, VIS1, do_ddd, a, tcg_gen_nand_i64)
5222TRANS(FANDd, VIS1, do_ddd, a, tcg_gen_and_i64)
5223TRANS(FXNORd, VIS1, do_ddd, a, tcg_gen_eqv_i64)
5224TRANS(FORNOTd, VIS1, do_ddd, a, tcg_gen_orc_i64)
5225TRANS(FORd, VIS1, do_ddd, a, tcg_gen_or_i64)
5226
5227TRANS(FPACK32, VIS1, do_ddd, a, gen_op_fpack32)
5228TRANS(FALIGNDATAg, VIS1, do_ddd, a, gen_op_faligndata_g)
5229TRANS(BSHUFFLE, VIS2, do_ddd, a, gen_op_bshuffle)
5230
5231TRANS(FHADDd, VIS3, do_ddd, a, gen_op_fhaddd)
5232TRANS(FHSUBd, VIS3, do_ddd, a, gen_op_fhsubd)
5233TRANS(FNHADDd, VIS3, do_ddd, a, gen_op_fnhaddd)
5234
5235TRANS(FPADD64, VIS3B, do_ddd, a, tcg_gen_add_i64)
5236TRANS(FPSUB64, VIS3B, do_ddd, a, tcg_gen_sub_i64)
5237TRANS(FSLAS16, VIS3, do_ddd, a, gen_helper_fslas16)
5238TRANS(FSLAS32, VIS3, do_ddd, a, gen_helper_fslas32)
5239
5240static bool do_rdd(DisasContext *dc, arg_r_r_r *a,
5241 void (*func)(TCGv, TCGv_i64, TCGv_i64))
5242{
5243 TCGv_i64 src1, src2;
5244 TCGv dst;
5245
5246 if (gen_trap_ifnofpu(dc)) {
5247 return true;
5248 }
5249
5250 dst = gen_dest_gpr(dc, a->rd);
5251 src1 = gen_load_fpr_D(dc, a->rs1);
5252 src2 = gen_load_fpr_D(dc, a->rs2);
5253 func(dst, src1, src2);
5254 gen_store_gpr(dc, a->rd, dst);
5255 return advance_pc(dc);
5256}
5257
5258TRANS(FPCMPLE16, VIS1, do_rdd, a, gen_helper_fcmple16)
5259TRANS(FPCMPNE16, VIS1, do_rdd, a, gen_helper_fcmpne16)
5260TRANS(FPCMPGT16, VIS1, do_rdd, a, gen_helper_fcmpgt16)
5261TRANS(FPCMPEQ16, VIS1, do_rdd, a, gen_helper_fcmpeq16)
5262TRANS(FPCMPULE16, VIS4, do_rdd, a, gen_helper_fcmpule16)
5263TRANS(FPCMPUGT16, VIS4, do_rdd, a, gen_helper_fcmpugt16)
5264
5265TRANS(FPCMPLE32, VIS1, do_rdd, a, gen_helper_fcmple32)
5266TRANS(FPCMPNE32, VIS1, do_rdd, a, gen_helper_fcmpne32)
5267TRANS(FPCMPGT32, VIS1, do_rdd, a, gen_helper_fcmpgt32)
5268TRANS(FPCMPEQ32, VIS1, do_rdd, a, gen_helper_fcmpeq32)
5269TRANS(FPCMPULE32, VIS4, do_rdd, a, gen_helper_fcmpule32)
5270TRANS(FPCMPUGT32, VIS4, do_rdd, a, gen_helper_fcmpugt32)
5271
5272TRANS(FPCMPEQ8, VIS3B, do_rdd, a, gen_helper_fcmpeq8)
5273TRANS(FPCMPNE8, VIS3B, do_rdd, a, gen_helper_fcmpne8)
5274TRANS(FPCMPULE8, VIS3B, do_rdd, a, gen_helper_fcmpule8)
5275TRANS(FPCMPUGT8, VIS3B, do_rdd, a, gen_helper_fcmpugt8)
5276TRANS(FPCMPLE8, VIS4, do_rdd, a, gen_helper_fcmple8)
5277TRANS(FPCMPGT8, VIS4, do_rdd, a, gen_helper_fcmpgt8)
5278
5279TRANS(PDISTN, VIS3, do_rdd, a, gen_op_pdistn)
5280TRANS(XMULX, VIS3, do_rrr, a, gen_helper_xmulx)
5281TRANS(XMULXHI, VIS3, do_rrr, a, gen_helper_xmulxhi)
5282
5283static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a,
5284 void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
5285{
5286 TCGv_i64 dst, src1, src2;
5287
5288 if (gen_trap_if_nofpu_fpexception(dc)) {
5289 return true;
5290 }
5291
5292 dst = tcg_temp_new_i64();
5293 src1 = gen_load_fpr_D(dc, a->rs1);
5294 src2 = gen_load_fpr_D(dc, a->rs2);
5295 func(dst, tcg_env, src1, src2);
5296 gen_store_fpr_D(dc, a->rd, dst);
5297 return advance_pc(dc);
5298}
5299
5300TRANS(FADDd, ALL, do_env_ddd, a, gen_helper_faddd)
5301TRANS(FSUBd, ALL, do_env_ddd, a, gen_helper_fsubd)
5302TRANS(FMULd, ALL, do_env_ddd, a, gen_helper_fmuld)
5303TRANS(FDIVd, ALL, do_env_ddd, a, gen_helper_fdivd)
5304TRANS(FNADDd, VIS3, do_env_ddd, a, gen_helper_fnaddd)
5305TRANS(FNMULd, VIS3, do_env_ddd, a, gen_helper_fnmuld)
5306
5307static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a)
5308{
5309 TCGv_i64 dst;
5310 TCGv_i32 src1, src2;
5311
5312 if (gen_trap_if_nofpu_fpexception(dc)) {
5313 return true;
5314 }
5315 if (!(dc->def->features & CPU_FEATURE_FSMULD)) {
5316 return raise_unimpfpop(dc);
5317 }
5318
5319 dst = tcg_temp_new_i64();
5320 src1 = gen_load_fpr_F(dc, a->rs1);
5321 src2 = gen_load_fpr_F(dc, a->rs2);
5322 gen_helper_fsmuld(dst, tcg_env, src1, src2);
5323 gen_store_fpr_D(dc, a->rd, dst);
5324 return advance_pc(dc);
5325}
5326
5327static bool trans_FNsMULd(DisasContext *dc, arg_r_r_r *a)
5328{
5329 TCGv_i64 dst;
5330 TCGv_i32 src1, src2;
5331
5332 if (!avail_VIS3(dc)) {
5333 return false;
5334 }
5335 if (gen_trap_ifnofpu(dc)) {
5336 return true;
5337 }
5338 dst = tcg_temp_new_i64();
5339 src1 = gen_load_fpr_F(dc, a->rs1);
5340 src2 = gen_load_fpr_F(dc, a->rs2);
5341 gen_helper_fnsmuld(dst, tcg_env, src1, src2);
5342 gen_store_fpr_D(dc, a->rd, dst);
5343 return advance_pc(dc);
5344}
5345
5346static bool do_ffff(DisasContext *dc, arg_r_r_r_r *a,
5347 void (*func)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32))
5348{
5349 TCGv_i32 dst, src1, src2, src3;
5350
5351 if (gen_trap_ifnofpu(dc)) {
5352 return true;
5353 }
5354
5355 src1 = gen_load_fpr_F(dc, a->rs1);
5356 src2 = gen_load_fpr_F(dc, a->rs2);
5357 src3 = gen_load_fpr_F(dc, a->rs3);
5358 dst = tcg_temp_new_i32();
5359 func(dst, src1, src2, src3);
5360 gen_store_fpr_F(dc, a->rd, dst);
5361 return advance_pc(dc);
5362}
5363
5364TRANS(FMADDs, FMAF, do_ffff, a, gen_op_fmadds)
5365TRANS(FMSUBs, FMAF, do_ffff, a, gen_op_fmsubs)
5366TRANS(FNMSUBs, FMAF, do_ffff, a, gen_op_fnmsubs)
5367TRANS(FNMADDs, FMAF, do_ffff, a, gen_op_fnmadds)
5368
5369static bool do_dddd(DisasContext *dc, arg_r_r_r_r *a,
5370 void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
5371{
5372 TCGv_i64 dst, src1, src2, src3;
5373
5374 if (gen_trap_ifnofpu(dc)) {
5375 return true;
5376 }
5377
5378 dst = tcg_temp_new_i64();
5379 src1 = gen_load_fpr_D(dc, a->rs1);
5380 src2 = gen_load_fpr_D(dc, a->rs2);
5381 src3 = gen_load_fpr_D(dc, a->rs3);
5382 func(dst, src1, src2, src3);
5383 gen_store_fpr_D(dc, a->rd, dst);
5384 return advance_pc(dc);
5385}
5386
5387TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist)
5388TRANS(FMADDd, FMAF, do_dddd, a, gen_op_fmaddd)
5389TRANS(FMSUBd, FMAF, do_dddd, a, gen_op_fmsubd)
5390TRANS(FNMSUBd, FMAF, do_dddd, a, gen_op_fnmsubd)
5391TRANS(FNMADDd, FMAF, do_dddd, a, gen_op_fnmaddd)
5392TRANS(FPMADDX, IMA, do_dddd, a, gen_op_fpmaddx)
5393TRANS(FPMADDXHI, IMA, do_dddd, a, gen_op_fpmaddxhi)
5394
5395static bool trans_FALIGNDATAi(DisasContext *dc, arg_r_r_r *a)
5396{
5397 TCGv_i64 dst, src1, src2;
5398 TCGv src3;
5399
5400 if (!avail_VIS4(dc)) {
5401 return false;
5402 }
5403 if (gen_trap_ifnofpu(dc)) {
5404 return true;
5405 }
5406
5407 dst = tcg_temp_new_i64();
5408 src1 = gen_load_fpr_D(dc, a->rd);
5409 src2 = gen_load_fpr_D(dc, a->rs2);
5410 src3 = gen_load_gpr(dc, a->rs1);
5411 gen_op_faligndata_i(dst, src1, src2, src3);
5412 gen_store_fpr_D(dc, a->rd, dst);
5413 return advance_pc(dc);
5414}
5415
5416static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a,
5417 void (*func)(TCGv_i128, TCGv_env, TCGv_i128, TCGv_i128))
5418{
5419 TCGv_i128 src1, src2;
5420
5421 if (gen_trap_if_nofpu_fpexception(dc)) {
5422 return true;
5423 }
5424 if (gen_trap_float128(dc)) {
5425 return true;
5426 }
5427
5428 src1 = gen_load_fpr_Q(dc, a->rs1);
5429 src2 = gen_load_fpr_Q(dc, a->rs2);
5430 func(src1, tcg_env, src1, src2);
5431 gen_store_fpr_Q(dc, a->rd, src1);
5432 return advance_pc(dc);
5433}
5434
5435TRANS(FADDq, ALL, do_env_qqq, a, gen_helper_faddq)
5436TRANS(FSUBq, ALL, do_env_qqq, a, gen_helper_fsubq)
5437TRANS(FMULq, ALL, do_env_qqq, a, gen_helper_fmulq)
5438TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq)
5439
5440static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a)
5441{
5442 TCGv_i64 src1, src2;
5443 TCGv_i128 dst;
5444
5445 if (gen_trap_if_nofpu_fpexception(dc)) {
5446 return true;
5447 }
5448 if (gen_trap_float128(dc)) {
5449 return true;
5450 }
5451
5452 src1 = gen_load_fpr_D(dc, a->rs1);
5453 src2 = gen_load_fpr_D(dc, a->rs2);
5454 dst = tcg_temp_new_i128();
5455 gen_helper_fdmulq(dst, tcg_env, src1, src2);
5456 gen_store_fpr_Q(dc, a->rd, dst);
5457 return advance_pc(dc);
5458}
5459
5460static bool do_fmovr(DisasContext *dc, arg_FMOVRs *a, bool is_128,
5461 void (*func)(DisasContext *, DisasCompare *, int, int))
5462{
5463 DisasCompare cmp;
5464
5465 if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
5466 return false;
5467 }
5468 if (gen_trap_ifnofpu(dc)) {
5469 return true;
5470 }
5471 if (is_128 && gen_trap_float128(dc)) {
5472 return true;
5473 }
5474
5475 gen_op_clear_ieee_excp_and_FTT();
5476 func(dc, &cmp, a->rd, a->rs2);
5477 return advance_pc(dc);
5478}
5479
5480TRANS(FMOVRs, 64, do_fmovr, a, false, gen_fmovs)
5481TRANS(FMOVRd, 64, do_fmovr, a, false, gen_fmovd)
5482TRANS(FMOVRq, 64, do_fmovr, a, true, gen_fmovq)
5483
5484static bool do_fmovcc(DisasContext *dc, arg_FMOVscc *a, bool is_128,
5485 void (*func)(DisasContext *, DisasCompare *, int, int))
5486{
5487 DisasCompare cmp;
5488
5489 if (gen_trap_ifnofpu(dc)) {
5490 return true;
5491 }
5492 if (is_128 && gen_trap_float128(dc)) {
5493 return true;
5494 }
5495
5496 gen_op_clear_ieee_excp_and_FTT();
5497 gen_compare(&cmp, a->cc, a->cond, dc);
5498 func(dc, &cmp, a->rd, a->rs2);
5499 return advance_pc(dc);
5500}
5501
5502TRANS(FMOVscc, 64, do_fmovcc, a, false, gen_fmovs)
5503TRANS(FMOVdcc, 64, do_fmovcc, a, false, gen_fmovd)
5504TRANS(FMOVqcc, 64, do_fmovcc, a, true, gen_fmovq)
5505
5506static bool do_fmovfcc(DisasContext *dc, arg_FMOVsfcc *a, bool is_128,
5507 void (*func)(DisasContext *, DisasCompare *, int, int))
5508{
5509 DisasCompare cmp;
5510
5511 if (gen_trap_ifnofpu(dc)) {
5512 return true;
5513 }
5514 if (is_128 && gen_trap_float128(dc)) {
5515 return true;
5516 }
5517
5518 gen_op_clear_ieee_excp_and_FTT();
5519 gen_fcompare(&cmp, a->cc, a->cond);
5520 func(dc, &cmp, a->rd, a->rs2);
5521 return advance_pc(dc);
5522}
5523
5524TRANS(FMOVsfcc, 64, do_fmovfcc, a, false, gen_fmovs)
5525TRANS(FMOVdfcc, 64, do_fmovfcc, a, false, gen_fmovd)
5526TRANS(FMOVqfcc, 64, do_fmovfcc, a, true, gen_fmovq)
5527
5528static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e)
5529{
5530 TCGv_i32 src1, src2;
5531
5532 if (avail_32(dc) && a->cc != 0) {
5533 return false;
5534 }
5535 if (gen_trap_if_nofpu_fpexception(dc)) {
5536 return true;
5537 }
5538
5539 src1 = gen_load_fpr_F(dc, a->rs1);
5540 src2 = gen_load_fpr_F(dc, a->rs2);
5541 if (e) {
5542 gen_helper_fcmpes(cpu_fcc[a->cc], tcg_env, src1, src2);
5543 } else {
5544 gen_helper_fcmps(cpu_fcc[a->cc], tcg_env, src1, src2);
5545 }
5546 return advance_pc(dc);
5547}
5548
5549TRANS(FCMPs, ALL, do_fcmps, a, false)
5550TRANS(FCMPEs, ALL, do_fcmps, a, true)
5551
5552static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e)
5553{
5554 TCGv_i64 src1, src2;
5555
5556 if (avail_32(dc) && a->cc != 0) {
5557 return false;
5558 }
5559 if (gen_trap_if_nofpu_fpexception(dc)) {
5560 return true;
5561 }
5562
5563 src1 = gen_load_fpr_D(dc, a->rs1);
5564 src2 = gen_load_fpr_D(dc, a->rs2);
5565 if (e) {
5566 gen_helper_fcmped(cpu_fcc[a->cc], tcg_env, src1, src2);
5567 } else {
5568 gen_helper_fcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
5569 }
5570 return advance_pc(dc);
5571}
5572
5573TRANS(FCMPd, ALL, do_fcmpd, a, false)
5574TRANS(FCMPEd, ALL, do_fcmpd, a, true)
5575
5576static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e)
5577{
5578 TCGv_i128 src1, src2;
5579
5580 if (avail_32(dc) && a->cc != 0) {
5581 return false;
5582 }
5583 if (gen_trap_if_nofpu_fpexception(dc)) {
5584 return true;
5585 }
5586 if (gen_trap_float128(dc)) {
5587 return true;
5588 }
5589
5590 src1 = gen_load_fpr_Q(dc, a->rs1);
5591 src2 = gen_load_fpr_Q(dc, a->rs2);
5592 if (e) {
5593 gen_helper_fcmpeq(cpu_fcc[a->cc], tcg_env, src1, src2);
5594 } else {
5595 gen_helper_fcmpq(cpu_fcc[a->cc], tcg_env, src1, src2);
5596 }
5597 return advance_pc(dc);
5598}
5599
5600TRANS(FCMPq, ALL, do_fcmpq, a, false)
5601TRANS(FCMPEq, ALL, do_fcmpq, a, true)
5602
5603static bool trans_FLCMPs(DisasContext *dc, arg_FLCMPs *a)
5604{
5605 TCGv_i32 src1, src2;
5606
5607 if (!avail_VIS3(dc)) {
5608 return false;
5609 }
5610 if (gen_trap_ifnofpu(dc)) {
5611 return true;
5612 }
5613
5614 src1 = gen_load_fpr_F(dc, a->rs1);
5615 src2 = gen_load_fpr_F(dc, a->rs2);
5616 gen_helper_flcmps(cpu_fcc[a->cc], tcg_env, src1, src2);
5617 return advance_pc(dc);
5618}
5619
5620static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a)
5621{
5622 TCGv_i64 src1, src2;
5623
5624 if (!avail_VIS3(dc)) {
5625 return false;
5626 }
5627 if (gen_trap_ifnofpu(dc)) {
5628 return true;
5629 }
5630
5631 src1 = gen_load_fpr_D(dc, a->rs1);
5632 src2 = gen_load_fpr_D(dc, a->rs2);
5633 gen_helper_flcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
5634 return advance_pc(dc);
5635}
5636
5637static bool do_movf2r(DisasContext *dc, arg_r_r *a,
5638 int (*offset)(unsigned int),
5639 void (*load)(TCGv, TCGv_ptr, tcg_target_long))
5640{
5641 TCGv dst;
5642
5643 if (gen_trap_ifnofpu(dc)) {
5644 return true;
5645 }
5646 dst = gen_dest_gpr(dc, a->rd);
5647 load(dst, tcg_env, offset(a->rs));
5648 gen_store_gpr(dc, a->rd, dst);
5649 return advance_pc(dc);
5650}
5651
5652TRANS(MOVsTOsw, VIS3B, do_movf2r, a, gen_offset_fpr_F, tcg_gen_ld32s_tl)
5653TRANS(MOVsTOuw, VIS3B, do_movf2r, a, gen_offset_fpr_F, tcg_gen_ld32u_tl)
5654TRANS(MOVdTOx, VIS3B, do_movf2r, a, gen_offset_fpr_D, tcg_gen_ld_tl)
5655
5656static bool do_movr2f(DisasContext *dc, arg_r_r *a,
5657 int (*offset)(unsigned int),
5658 void (*store)(TCGv, TCGv_ptr, tcg_target_long))
5659{
5660 TCGv src;
5661
5662 if (gen_trap_ifnofpu(dc)) {
5663 return true;
5664 }
5665 src = gen_load_gpr(dc, a->rs);
5666 store(src, tcg_env, offset(a->rd));
5667 return advance_pc(dc);
5668}
5669
5670TRANS(MOVwTOs, VIS3B, do_movr2f, a, gen_offset_fpr_F, tcg_gen_st32_tl)
5671TRANS(MOVxTOd, VIS3B, do_movr2f, a, gen_offset_fpr_D, tcg_gen_st_tl)
5672
5673static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
5674{
5675 DisasContext *dc = container_of(dcbase, DisasContext, base);
5676 int bound;
5677
5678 dc->pc = dc->base.pc_first;
5679 dc->npc = (target_ulong)dc->base.tb->cs_base;
5680 dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK;
5681 dc->def = &cpu_env(cs)->def;
5682 dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags);
5683 dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags);
5684#ifndef CONFIG_USER_ONLY
5685 dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0;
5686# ifdef TARGET_SPARC64
5687 dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0;
5688# else
5689 dc->fsr_qne = (dc->base.tb->flags & TB_FLAG_FSR_QNE) != 0;
5690# endif
5691#endif
5692#ifdef TARGET_SPARC64
5693 dc->fprs_dirty = 0;
5694 dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff;
5695#endif
5696
5697
5698
5699
5700 bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
5701 dc->base.max_insns = MIN(dc->base.max_insns, bound);
5702}
5703
5704static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs)
5705{
5706}
5707
5708static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
5709{
5710 DisasContext *dc = container_of(dcbase, DisasContext, base);
5711 target_ulong npc = dc->npc;
5712
5713 if (npc & 3) {
5714 switch (npc) {
5715 case JUMP_PC:
5716 assert(dc->jump_pc[1] == dc->pc + 4);
5717 npc = dc->jump_pc[0] | JUMP_PC;
5718 break;
5719 case DYNAMIC_PC:
5720 case DYNAMIC_PC_LOOKUP:
5721 npc = DYNAMIC_PC;
5722 break;
5723 default:
5724 g_assert_not_reached();
5725 }
5726 }
5727 tcg_gen_insn_start(dc->pc, npc);
5728}
5729
5730static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
5731{
5732 DisasContext *dc = container_of(dcbase, DisasContext, base);
5733 unsigned int insn;
5734
5735 insn = translator_ldl(cpu_env(cs), &dc->base, dc->pc);
5736 dc->base.pc_next += 4;
5737
5738 if (!decode(dc, insn)) {
5739 gen_exception(dc, TT_ILL_INSN);
5740 }
5741
5742 if (dc->base.is_jmp == DISAS_NORETURN) {
5743 return;
5744 }
5745 if (dc->pc != dc->base.pc_next) {
5746 dc->base.is_jmp = DISAS_TOO_MANY;
5747 }
5748}
5749
5750static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
5751{
5752 DisasContext *dc = container_of(dcbase, DisasContext, base);
5753 DisasDelayException *e, *e_next;
5754 bool may_lookup;
5755
5756 finishing_insn(dc);
5757
5758 switch (dc->base.is_jmp) {
5759 case DISAS_NEXT:
5760 case DISAS_TOO_MANY:
5761 if (((dc->pc | dc->npc) & 3) == 0) {
5762
5763 gen_goto_tb(dc, 0, dc->pc, dc->npc);
5764 break;
5765 }
5766
5767 may_lookup = true;
5768 if (dc->pc & 3) {
5769 switch (dc->pc) {
5770 case DYNAMIC_PC_LOOKUP:
5771 break;
5772 case DYNAMIC_PC:
5773 may_lookup = false;
5774 break;
5775 default:
5776 g_assert_not_reached();
5777 }
5778 } else {
5779 tcg_gen_movi_tl(cpu_pc, dc->pc);
5780 }
5781
5782 if (dc->npc & 3) {
5783 switch (dc->npc) {
5784 case JUMP_PC:
5785 gen_generic_branch(dc);
5786 break;
5787 case DYNAMIC_PC:
5788 may_lookup = false;
5789 break;
5790 case DYNAMIC_PC_LOOKUP:
5791 break;
5792 default:
5793 g_assert_not_reached();
5794 }
5795 } else {
5796 tcg_gen_movi_tl(cpu_npc, dc->npc);
5797 }
5798 if (may_lookup) {
5799 tcg_gen_lookup_and_goto_ptr();
5800 } else {
5801 tcg_gen_exit_tb(NULL, 0);
5802 }
5803 break;
5804
5805 case DISAS_NORETURN:
5806 break;
5807
5808 case DISAS_EXIT:
5809
5810 save_state(dc);
5811 tcg_gen_exit_tb(NULL, 0);
5812 break;
5813
5814 default:
5815 g_assert_not_reached();
5816 }
5817
5818 for (e = dc->delay_excp_list; e ; e = e_next) {
5819 gen_set_label(e->lab);
5820
5821 tcg_gen_movi_tl(cpu_pc, e->pc);
5822 if (e->npc % 4 == 0) {
5823 tcg_gen_movi_tl(cpu_npc, e->npc);
5824 }
5825 gen_helper_raise_exception(tcg_env, e->excp);
5826
5827 e_next = e->next;
5828 g_free(e);
5829 }
5830}
5831
5832static const TranslatorOps sparc_tr_ops = {
5833 .init_disas_context = sparc_tr_init_disas_context,
5834 .tb_start = sparc_tr_tb_start,
5835 .insn_start = sparc_tr_insn_start,
5836 .translate_insn = sparc_tr_translate_insn,
5837 .tb_stop = sparc_tr_tb_stop,
5838};
5839
5840void sparc_translate_code(CPUState *cs, TranslationBlock *tb,
5841 int *max_insns, vaddr pc, void *host_pc)
5842{
5843 DisasContext dc = {};
5844
5845 translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base);
5846}
5847
5848void sparc_tcg_init(void)
5849{
5850 static const char gregnames[32][4] = {
5851 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
5852 "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
5853 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
5854 "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
5855 };
5856
5857 static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = {
5858#ifdef TARGET_SPARC64
5859 { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" },
5860 { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc0" },
5861 { &cpu_fcc[1], offsetof(CPUSPARCState, fcc[1]), "fcc1" },
5862 { &cpu_fcc[2], offsetof(CPUSPARCState, fcc[2]), "fcc2" },
5863 { &cpu_fcc[3], offsetof(CPUSPARCState, fcc[3]), "fcc3" },
5864#else
5865 { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc" },
5866#endif
5867 };
5868
5869 static const struct { TCGv *ptr; int off; const char *name; } rtl[] = {
5870#ifdef TARGET_SPARC64
5871 { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" },
5872 { &cpu_xcc_Z, offsetof(CPUSPARCState, xcc_Z), "xcc_Z" },
5873 { &cpu_xcc_C, offsetof(CPUSPARCState, xcc_C), "xcc_C" },
5874#endif
5875 { &cpu_cc_N, offsetof(CPUSPARCState, cc_N), "cc_N" },
5876 { &cpu_cc_V, offsetof(CPUSPARCState, cc_V), "cc_V" },
5877 { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" },
5878 { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" },
5879 { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" },
5880 { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" },
5881 { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" },
5882 { &cpu_y, offsetof(CPUSPARCState, y), "y" },
5883 { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" },
5884 };
5885
5886 unsigned int i;
5887
5888 cpu_regwptr = tcg_global_mem_new_ptr(tcg_env,
5889 offsetof(CPUSPARCState, regwptr),
5890 "regwptr");
5891
5892 for (i = 0; i < ARRAY_SIZE(r32); ++i) {
5893 *r32[i].ptr = tcg_global_mem_new_i32(tcg_env, r32[i].off, r32[i].name);
5894 }
5895
5896 for (i = 0; i < ARRAY_SIZE(rtl); ++i) {
5897 *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name);
5898 }
5899
5900 cpu_regs[0] = NULL;
5901 for (i = 1; i < 8; ++i) {
5902 cpu_regs[i] = tcg_global_mem_new(tcg_env,
5903 offsetof(CPUSPARCState, gregs[i]),
5904 gregnames[i]);
5905 }
5906
5907 for (i = 8; i < 32; ++i) {
5908 cpu_regs[i] = tcg_global_mem_new(cpu_regwptr,
5909 (i - 8) * sizeof(target_ulong),
5910 gregnames[i]);
5911 }
5912}
5913