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