xref: /openbmc/qemu/target/sparc/translate.c (revision fcf5ef2ab52c621a4617ebbef36bf43b4003f4c0)
1*fcf5ef2aSThomas Huth /*
2*fcf5ef2aSThomas Huth    SPARC translation
3*fcf5ef2aSThomas Huth 
4*fcf5ef2aSThomas Huth    Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
5*fcf5ef2aSThomas Huth    Copyright (C) 2003-2005 Fabrice Bellard
6*fcf5ef2aSThomas Huth 
7*fcf5ef2aSThomas Huth    This library is free software; you can redistribute it and/or
8*fcf5ef2aSThomas Huth    modify it under the terms of the GNU Lesser General Public
9*fcf5ef2aSThomas Huth    License as published by the Free Software Foundation; either
10*fcf5ef2aSThomas Huth    version 2 of the License, or (at your option) any later version.
11*fcf5ef2aSThomas Huth 
12*fcf5ef2aSThomas Huth    This library is distributed in the hope that it will be useful,
13*fcf5ef2aSThomas Huth    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*fcf5ef2aSThomas Huth    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15*fcf5ef2aSThomas Huth    Lesser General Public License for more details.
16*fcf5ef2aSThomas Huth 
17*fcf5ef2aSThomas Huth    You should have received a copy of the GNU Lesser General Public
18*fcf5ef2aSThomas Huth    License along with this library; if not, see <http://www.gnu.org/licenses/>.
19*fcf5ef2aSThomas Huth  */
20*fcf5ef2aSThomas Huth 
21*fcf5ef2aSThomas Huth #include "qemu/osdep.h"
22*fcf5ef2aSThomas Huth 
23*fcf5ef2aSThomas Huth #include "cpu.h"
24*fcf5ef2aSThomas Huth #include "disas/disas.h"
25*fcf5ef2aSThomas Huth #include "exec/helper-proto.h"
26*fcf5ef2aSThomas Huth #include "exec/exec-all.h"
27*fcf5ef2aSThomas Huth #include "tcg-op.h"
28*fcf5ef2aSThomas Huth #include "exec/cpu_ldst.h"
29*fcf5ef2aSThomas Huth 
30*fcf5ef2aSThomas Huth #include "exec/helper-gen.h"
31*fcf5ef2aSThomas Huth 
32*fcf5ef2aSThomas Huth #include "trace-tcg.h"
33*fcf5ef2aSThomas Huth #include "exec/log.h"
34*fcf5ef2aSThomas Huth #include "asi.h"
35*fcf5ef2aSThomas Huth 
36*fcf5ef2aSThomas Huth 
37*fcf5ef2aSThomas Huth #define DEBUG_DISAS
38*fcf5ef2aSThomas Huth 
39*fcf5ef2aSThomas Huth #define DYNAMIC_PC  1 /* dynamic pc value */
40*fcf5ef2aSThomas Huth #define JUMP_PC     2 /* dynamic pc value which takes only two values
41*fcf5ef2aSThomas Huth                          according to jump_pc[T2] */
42*fcf5ef2aSThomas Huth 
43*fcf5ef2aSThomas Huth /* global register indexes */
44*fcf5ef2aSThomas Huth static TCGv_env cpu_env;
45*fcf5ef2aSThomas Huth static TCGv_ptr cpu_regwptr;
46*fcf5ef2aSThomas Huth static TCGv cpu_cc_src, cpu_cc_src2, cpu_cc_dst;
47*fcf5ef2aSThomas Huth static TCGv_i32 cpu_cc_op;
48*fcf5ef2aSThomas Huth static TCGv_i32 cpu_psr;
49*fcf5ef2aSThomas Huth static TCGv cpu_fsr, cpu_pc, cpu_npc;
50*fcf5ef2aSThomas Huth static TCGv cpu_regs[32];
51*fcf5ef2aSThomas Huth static TCGv cpu_y;
52*fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
53*fcf5ef2aSThomas Huth static TCGv cpu_tbr;
54*fcf5ef2aSThomas Huth #endif
55*fcf5ef2aSThomas Huth static TCGv cpu_cond;
56*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
57*fcf5ef2aSThomas Huth static TCGv_i32 cpu_xcc, cpu_fprs;
58*fcf5ef2aSThomas Huth static TCGv cpu_gsr;
59*fcf5ef2aSThomas Huth static TCGv cpu_tick_cmpr, cpu_stick_cmpr, cpu_hstick_cmpr;
60*fcf5ef2aSThomas Huth static TCGv cpu_hintp, cpu_htba, cpu_hver, cpu_ssr, cpu_ver;
61*fcf5ef2aSThomas Huth #else
62*fcf5ef2aSThomas Huth static TCGv cpu_wim;
63*fcf5ef2aSThomas Huth #endif
64*fcf5ef2aSThomas Huth /* Floating point registers */
65*fcf5ef2aSThomas Huth static TCGv_i64 cpu_fpr[TARGET_DPREGS];
66*fcf5ef2aSThomas Huth 
67*fcf5ef2aSThomas Huth #include "exec/gen-icount.h"
68*fcf5ef2aSThomas Huth 
69*fcf5ef2aSThomas Huth typedef struct DisasContext {
70*fcf5ef2aSThomas Huth     target_ulong pc;    /* current Program Counter: integer or DYNAMIC_PC */
71*fcf5ef2aSThomas Huth     target_ulong npc;   /* next PC: integer or DYNAMIC_PC or JUMP_PC */
72*fcf5ef2aSThomas Huth     target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
73*fcf5ef2aSThomas Huth     int is_br;
74*fcf5ef2aSThomas Huth     int mem_idx;
75*fcf5ef2aSThomas Huth     int fpu_enabled;
76*fcf5ef2aSThomas Huth     int address_mask_32bit;
77*fcf5ef2aSThomas Huth     int singlestep;
78*fcf5ef2aSThomas Huth     uint32_t cc_op;  /* current CC operation */
79*fcf5ef2aSThomas Huth     struct TranslationBlock *tb;
80*fcf5ef2aSThomas Huth     sparc_def_t *def;
81*fcf5ef2aSThomas Huth     TCGv_i32 t32[3];
82*fcf5ef2aSThomas Huth     TCGv ttl[5];
83*fcf5ef2aSThomas Huth     int n_t32;
84*fcf5ef2aSThomas Huth     int n_ttl;
85*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
86*fcf5ef2aSThomas Huth     int fprs_dirty;
87*fcf5ef2aSThomas Huth     int asi;
88*fcf5ef2aSThomas Huth #endif
89*fcf5ef2aSThomas Huth } DisasContext;
90*fcf5ef2aSThomas Huth 
91*fcf5ef2aSThomas Huth typedef struct {
92*fcf5ef2aSThomas Huth     TCGCond cond;
93*fcf5ef2aSThomas Huth     bool is_bool;
94*fcf5ef2aSThomas Huth     bool g1, g2;
95*fcf5ef2aSThomas Huth     TCGv c1, c2;
96*fcf5ef2aSThomas Huth } DisasCompare;
97*fcf5ef2aSThomas Huth 
98*fcf5ef2aSThomas Huth // This function uses non-native bit order
99*fcf5ef2aSThomas Huth #define GET_FIELD(X, FROM, TO)                                  \
100*fcf5ef2aSThomas Huth     ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
101*fcf5ef2aSThomas Huth 
102*fcf5ef2aSThomas Huth // This function uses the order in the manuals, i.e. bit 0 is 2^0
103*fcf5ef2aSThomas Huth #define GET_FIELD_SP(X, FROM, TO)               \
104*fcf5ef2aSThomas Huth     GET_FIELD(X, 31 - (TO), 31 - (FROM))
105*fcf5ef2aSThomas Huth 
106*fcf5ef2aSThomas Huth #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
107*fcf5ef2aSThomas Huth #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
108*fcf5ef2aSThomas Huth 
109*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
110*fcf5ef2aSThomas Huth #define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
111*fcf5ef2aSThomas Huth #define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))
112*fcf5ef2aSThomas Huth #else
113*fcf5ef2aSThomas Huth #define DFPREG(r) (r & 0x1e)
114*fcf5ef2aSThomas Huth #define QFPREG(r) (r & 0x1c)
115*fcf5ef2aSThomas Huth #endif
116*fcf5ef2aSThomas Huth 
117*fcf5ef2aSThomas Huth #define UA2005_HTRAP_MASK 0xff
118*fcf5ef2aSThomas Huth #define V8_TRAP_MASK 0x7f
119*fcf5ef2aSThomas Huth 
120*fcf5ef2aSThomas Huth static int sign_extend(int x, int len)
121*fcf5ef2aSThomas Huth {
122*fcf5ef2aSThomas Huth     len = 32 - len;
123*fcf5ef2aSThomas Huth     return (x << len) >> len;
124*fcf5ef2aSThomas Huth }
125*fcf5ef2aSThomas Huth 
126*fcf5ef2aSThomas Huth #define IS_IMM (insn & (1<<13))
127*fcf5ef2aSThomas Huth 
128*fcf5ef2aSThomas Huth static inline TCGv_i32 get_temp_i32(DisasContext *dc)
129*fcf5ef2aSThomas Huth {
130*fcf5ef2aSThomas Huth     TCGv_i32 t;
131*fcf5ef2aSThomas Huth     assert(dc->n_t32 < ARRAY_SIZE(dc->t32));
132*fcf5ef2aSThomas Huth     dc->t32[dc->n_t32++] = t = tcg_temp_new_i32();
133*fcf5ef2aSThomas Huth     return t;
134*fcf5ef2aSThomas Huth }
135*fcf5ef2aSThomas Huth 
136*fcf5ef2aSThomas Huth static inline TCGv get_temp_tl(DisasContext *dc)
137*fcf5ef2aSThomas Huth {
138*fcf5ef2aSThomas Huth     TCGv t;
139*fcf5ef2aSThomas Huth     assert(dc->n_ttl < ARRAY_SIZE(dc->ttl));
140*fcf5ef2aSThomas Huth     dc->ttl[dc->n_ttl++] = t = tcg_temp_new();
141*fcf5ef2aSThomas Huth     return t;
142*fcf5ef2aSThomas Huth }
143*fcf5ef2aSThomas Huth 
144*fcf5ef2aSThomas Huth static inline void gen_update_fprs_dirty(DisasContext *dc, int rd)
145*fcf5ef2aSThomas Huth {
146*fcf5ef2aSThomas Huth #if defined(TARGET_SPARC64)
147*fcf5ef2aSThomas Huth     int bit = (rd < 32) ? 1 : 2;
148*fcf5ef2aSThomas Huth     /* If we know we've already set this bit within the TB,
149*fcf5ef2aSThomas Huth        we can avoid setting it again.  */
150*fcf5ef2aSThomas Huth     if (!(dc->fprs_dirty & bit)) {
151*fcf5ef2aSThomas Huth         dc->fprs_dirty |= bit;
152*fcf5ef2aSThomas Huth         tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit);
153*fcf5ef2aSThomas Huth     }
154*fcf5ef2aSThomas Huth #endif
155*fcf5ef2aSThomas Huth }
156*fcf5ef2aSThomas Huth 
157*fcf5ef2aSThomas Huth /* floating point registers moves */
158*fcf5ef2aSThomas Huth static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src)
159*fcf5ef2aSThomas Huth {
160*fcf5ef2aSThomas Huth #if TCG_TARGET_REG_BITS == 32
161*fcf5ef2aSThomas Huth     if (src & 1) {
162*fcf5ef2aSThomas Huth         return TCGV_LOW(cpu_fpr[src / 2]);
163*fcf5ef2aSThomas Huth     } else {
164*fcf5ef2aSThomas Huth         return TCGV_HIGH(cpu_fpr[src / 2]);
165*fcf5ef2aSThomas Huth     }
166*fcf5ef2aSThomas Huth #else
167*fcf5ef2aSThomas Huth     if (src & 1) {
168*fcf5ef2aSThomas Huth         return MAKE_TCGV_I32(GET_TCGV_I64(cpu_fpr[src / 2]));
169*fcf5ef2aSThomas Huth     } else {
170*fcf5ef2aSThomas Huth         TCGv_i32 ret = get_temp_i32(dc);
171*fcf5ef2aSThomas Huth         TCGv_i64 t = tcg_temp_new_i64();
172*fcf5ef2aSThomas Huth 
173*fcf5ef2aSThomas Huth         tcg_gen_shri_i64(t, cpu_fpr[src / 2], 32);
174*fcf5ef2aSThomas Huth         tcg_gen_extrl_i64_i32(ret, t);
175*fcf5ef2aSThomas Huth         tcg_temp_free_i64(t);
176*fcf5ef2aSThomas Huth 
177*fcf5ef2aSThomas Huth         return ret;
178*fcf5ef2aSThomas Huth     }
179*fcf5ef2aSThomas Huth #endif
180*fcf5ef2aSThomas Huth }
181*fcf5ef2aSThomas Huth 
182*fcf5ef2aSThomas Huth static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v)
183*fcf5ef2aSThomas Huth {
184*fcf5ef2aSThomas Huth #if TCG_TARGET_REG_BITS == 32
185*fcf5ef2aSThomas Huth     if (dst & 1) {
186*fcf5ef2aSThomas Huth         tcg_gen_mov_i32(TCGV_LOW(cpu_fpr[dst / 2]), v);
187*fcf5ef2aSThomas Huth     } else {
188*fcf5ef2aSThomas Huth         tcg_gen_mov_i32(TCGV_HIGH(cpu_fpr[dst / 2]), v);
189*fcf5ef2aSThomas Huth     }
190*fcf5ef2aSThomas Huth #else
191*fcf5ef2aSThomas Huth     TCGv_i64 t = MAKE_TCGV_I64(GET_TCGV_I32(v));
192*fcf5ef2aSThomas Huth     tcg_gen_deposit_i64(cpu_fpr[dst / 2], cpu_fpr[dst / 2], t,
193*fcf5ef2aSThomas Huth                         (dst & 1 ? 0 : 32), 32);
194*fcf5ef2aSThomas Huth #endif
195*fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, dst);
196*fcf5ef2aSThomas Huth }
197*fcf5ef2aSThomas Huth 
198*fcf5ef2aSThomas Huth static TCGv_i32 gen_dest_fpr_F(DisasContext *dc)
199*fcf5ef2aSThomas Huth {
200*fcf5ef2aSThomas Huth     return get_temp_i32(dc);
201*fcf5ef2aSThomas Huth }
202*fcf5ef2aSThomas Huth 
203*fcf5ef2aSThomas Huth static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src)
204*fcf5ef2aSThomas Huth {
205*fcf5ef2aSThomas Huth     src = DFPREG(src);
206*fcf5ef2aSThomas Huth     return cpu_fpr[src / 2];
207*fcf5ef2aSThomas Huth }
208*fcf5ef2aSThomas Huth 
209*fcf5ef2aSThomas Huth static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v)
210*fcf5ef2aSThomas Huth {
211*fcf5ef2aSThomas Huth     dst = DFPREG(dst);
212*fcf5ef2aSThomas Huth     tcg_gen_mov_i64(cpu_fpr[dst / 2], v);
213*fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, dst);
214*fcf5ef2aSThomas Huth }
215*fcf5ef2aSThomas Huth 
216*fcf5ef2aSThomas Huth static TCGv_i64 gen_dest_fpr_D(DisasContext *dc, unsigned int dst)
217*fcf5ef2aSThomas Huth {
218*fcf5ef2aSThomas Huth     return cpu_fpr[DFPREG(dst) / 2];
219*fcf5ef2aSThomas Huth }
220*fcf5ef2aSThomas Huth 
221*fcf5ef2aSThomas Huth static void gen_op_load_fpr_QT0(unsigned int src)
222*fcf5ef2aSThomas Huth {
223*fcf5ef2aSThomas Huth     tcg_gen_st_i64(cpu_fpr[src / 2], cpu_env, offsetof(CPUSPARCState, qt0) +
224*fcf5ef2aSThomas Huth                    offsetof(CPU_QuadU, ll.upper));
225*fcf5ef2aSThomas Huth     tcg_gen_st_i64(cpu_fpr[src/2 + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
226*fcf5ef2aSThomas Huth                    offsetof(CPU_QuadU, ll.lower));
227*fcf5ef2aSThomas Huth }
228*fcf5ef2aSThomas Huth 
229*fcf5ef2aSThomas Huth static void gen_op_load_fpr_QT1(unsigned int src)
230*fcf5ef2aSThomas Huth {
231*fcf5ef2aSThomas Huth     tcg_gen_st_i64(cpu_fpr[src / 2], cpu_env, offsetof(CPUSPARCState, qt1) +
232*fcf5ef2aSThomas Huth                    offsetof(CPU_QuadU, ll.upper));
233*fcf5ef2aSThomas Huth     tcg_gen_st_i64(cpu_fpr[src/2 + 1], cpu_env, offsetof(CPUSPARCState, qt1) +
234*fcf5ef2aSThomas Huth                    offsetof(CPU_QuadU, ll.lower));
235*fcf5ef2aSThomas Huth }
236*fcf5ef2aSThomas Huth 
237*fcf5ef2aSThomas Huth static void gen_op_store_QT0_fpr(unsigned int dst)
238*fcf5ef2aSThomas Huth {
239*fcf5ef2aSThomas Huth     tcg_gen_ld_i64(cpu_fpr[dst / 2], cpu_env, offsetof(CPUSPARCState, qt0) +
240*fcf5ef2aSThomas Huth                    offsetof(CPU_QuadU, ll.upper));
241*fcf5ef2aSThomas Huth     tcg_gen_ld_i64(cpu_fpr[dst/2 + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
242*fcf5ef2aSThomas Huth                    offsetof(CPU_QuadU, ll.lower));
243*fcf5ef2aSThomas Huth }
244*fcf5ef2aSThomas Huth 
245*fcf5ef2aSThomas Huth static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst,
246*fcf5ef2aSThomas Huth                             TCGv_i64 v1, TCGv_i64 v2)
247*fcf5ef2aSThomas Huth {
248*fcf5ef2aSThomas Huth     dst = QFPREG(dst);
249*fcf5ef2aSThomas Huth 
250*fcf5ef2aSThomas Huth     tcg_gen_mov_i64(cpu_fpr[dst / 2], v1);
251*fcf5ef2aSThomas Huth     tcg_gen_mov_i64(cpu_fpr[dst / 2 + 1], v2);
252*fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, dst);
253*fcf5ef2aSThomas Huth }
254*fcf5ef2aSThomas Huth 
255*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
256*fcf5ef2aSThomas Huth static TCGv_i64 gen_load_fpr_Q0(DisasContext *dc, unsigned int src)
257*fcf5ef2aSThomas Huth {
258*fcf5ef2aSThomas Huth     src = QFPREG(src);
259*fcf5ef2aSThomas Huth     return cpu_fpr[src / 2];
260*fcf5ef2aSThomas Huth }
261*fcf5ef2aSThomas Huth 
262*fcf5ef2aSThomas Huth static TCGv_i64 gen_load_fpr_Q1(DisasContext *dc, unsigned int src)
263*fcf5ef2aSThomas Huth {
264*fcf5ef2aSThomas Huth     src = QFPREG(src);
265*fcf5ef2aSThomas Huth     return cpu_fpr[src / 2 + 1];
266*fcf5ef2aSThomas Huth }
267*fcf5ef2aSThomas Huth 
268*fcf5ef2aSThomas Huth static void gen_move_Q(DisasContext *dc, unsigned int rd, unsigned int rs)
269*fcf5ef2aSThomas Huth {
270*fcf5ef2aSThomas Huth     rd = QFPREG(rd);
271*fcf5ef2aSThomas Huth     rs = QFPREG(rs);
272*fcf5ef2aSThomas Huth 
273*fcf5ef2aSThomas Huth     tcg_gen_mov_i64(cpu_fpr[rd / 2], cpu_fpr[rs / 2]);
274*fcf5ef2aSThomas Huth     tcg_gen_mov_i64(cpu_fpr[rd / 2 + 1], cpu_fpr[rs / 2 + 1]);
275*fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, rd);
276*fcf5ef2aSThomas Huth }
277*fcf5ef2aSThomas Huth #endif
278*fcf5ef2aSThomas Huth 
279*fcf5ef2aSThomas Huth /* moves */
280*fcf5ef2aSThomas Huth #ifdef CONFIG_USER_ONLY
281*fcf5ef2aSThomas Huth #define supervisor(dc) 0
282*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
283*fcf5ef2aSThomas Huth #define hypervisor(dc) 0
284*fcf5ef2aSThomas Huth #endif
285*fcf5ef2aSThomas Huth #else
286*fcf5ef2aSThomas Huth #define supervisor(dc) (dc->mem_idx >= MMU_KERNEL_IDX)
287*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
288*fcf5ef2aSThomas Huth #define hypervisor(dc) (dc->mem_idx == MMU_HYPV_IDX)
289*fcf5ef2aSThomas Huth #else
290*fcf5ef2aSThomas Huth #endif
291*fcf5ef2aSThomas Huth #endif
292*fcf5ef2aSThomas Huth 
293*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
294*fcf5ef2aSThomas Huth #ifndef TARGET_ABI32
295*fcf5ef2aSThomas Huth #define AM_CHECK(dc) ((dc)->address_mask_32bit)
296*fcf5ef2aSThomas Huth #else
297*fcf5ef2aSThomas Huth #define AM_CHECK(dc) (1)
298*fcf5ef2aSThomas Huth #endif
299*fcf5ef2aSThomas Huth #endif
300*fcf5ef2aSThomas Huth 
301*fcf5ef2aSThomas Huth static inline void gen_address_mask(DisasContext *dc, TCGv addr)
302*fcf5ef2aSThomas Huth {
303*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
304*fcf5ef2aSThomas Huth     if (AM_CHECK(dc))
305*fcf5ef2aSThomas Huth         tcg_gen_andi_tl(addr, addr, 0xffffffffULL);
306*fcf5ef2aSThomas Huth #endif
307*fcf5ef2aSThomas Huth }
308*fcf5ef2aSThomas Huth 
309*fcf5ef2aSThomas Huth static inline TCGv gen_load_gpr(DisasContext *dc, int reg)
310*fcf5ef2aSThomas Huth {
311*fcf5ef2aSThomas Huth     if (reg > 0) {
312*fcf5ef2aSThomas Huth         assert(reg < 32);
313*fcf5ef2aSThomas Huth         return cpu_regs[reg];
314*fcf5ef2aSThomas Huth     } else {
315*fcf5ef2aSThomas Huth         TCGv t = get_temp_tl(dc);
316*fcf5ef2aSThomas Huth         tcg_gen_movi_tl(t, 0);
317*fcf5ef2aSThomas Huth         return t;
318*fcf5ef2aSThomas Huth     }
319*fcf5ef2aSThomas Huth }
320*fcf5ef2aSThomas Huth 
321*fcf5ef2aSThomas Huth static inline void gen_store_gpr(DisasContext *dc, int reg, TCGv v)
322*fcf5ef2aSThomas Huth {
323*fcf5ef2aSThomas Huth     if (reg > 0) {
324*fcf5ef2aSThomas Huth         assert(reg < 32);
325*fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_regs[reg], v);
326*fcf5ef2aSThomas Huth     }
327*fcf5ef2aSThomas Huth }
328*fcf5ef2aSThomas Huth 
329*fcf5ef2aSThomas Huth static inline TCGv gen_dest_gpr(DisasContext *dc, int reg)
330*fcf5ef2aSThomas Huth {
331*fcf5ef2aSThomas Huth     if (reg > 0) {
332*fcf5ef2aSThomas Huth         assert(reg < 32);
333*fcf5ef2aSThomas Huth         return cpu_regs[reg];
334*fcf5ef2aSThomas Huth     } else {
335*fcf5ef2aSThomas Huth         return get_temp_tl(dc);
336*fcf5ef2aSThomas Huth     }
337*fcf5ef2aSThomas Huth }
338*fcf5ef2aSThomas Huth 
339*fcf5ef2aSThomas Huth static inline bool use_goto_tb(DisasContext *s, target_ulong pc,
340*fcf5ef2aSThomas Huth                                target_ulong npc)
341*fcf5ef2aSThomas Huth {
342*fcf5ef2aSThomas Huth     if (unlikely(s->singlestep)) {
343*fcf5ef2aSThomas Huth         return false;
344*fcf5ef2aSThomas Huth     }
345*fcf5ef2aSThomas Huth 
346*fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
347*fcf5ef2aSThomas Huth     return (pc & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK) &&
348*fcf5ef2aSThomas Huth            (npc & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK);
349*fcf5ef2aSThomas Huth #else
350*fcf5ef2aSThomas Huth     return true;
351*fcf5ef2aSThomas Huth #endif
352*fcf5ef2aSThomas Huth }
353*fcf5ef2aSThomas Huth 
354*fcf5ef2aSThomas Huth static inline void gen_goto_tb(DisasContext *s, int tb_num,
355*fcf5ef2aSThomas Huth                                target_ulong pc, target_ulong npc)
356*fcf5ef2aSThomas Huth {
357*fcf5ef2aSThomas Huth     if (use_goto_tb(s, pc, npc))  {
358*fcf5ef2aSThomas Huth         /* jump to same page: we can use a direct jump */
359*fcf5ef2aSThomas Huth         tcg_gen_goto_tb(tb_num);
360*fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_pc, pc);
361*fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_npc, npc);
362*fcf5ef2aSThomas Huth         tcg_gen_exit_tb((uintptr_t)s->tb + tb_num);
363*fcf5ef2aSThomas Huth     } else {
364*fcf5ef2aSThomas Huth         /* jump to another page: currently not optimized */
365*fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_pc, pc);
366*fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_npc, npc);
367*fcf5ef2aSThomas Huth         tcg_gen_exit_tb(0);
368*fcf5ef2aSThomas Huth     }
369*fcf5ef2aSThomas Huth }
370*fcf5ef2aSThomas Huth 
371*fcf5ef2aSThomas Huth // XXX suboptimal
372*fcf5ef2aSThomas Huth static inline void gen_mov_reg_N(TCGv reg, TCGv_i32 src)
373*fcf5ef2aSThomas Huth {
374*fcf5ef2aSThomas Huth     tcg_gen_extu_i32_tl(reg, src);
375*fcf5ef2aSThomas Huth     tcg_gen_shri_tl(reg, reg, PSR_NEG_SHIFT);
376*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(reg, reg, 0x1);
377*fcf5ef2aSThomas Huth }
378*fcf5ef2aSThomas Huth 
379*fcf5ef2aSThomas Huth static inline void gen_mov_reg_Z(TCGv reg, TCGv_i32 src)
380*fcf5ef2aSThomas Huth {
381*fcf5ef2aSThomas Huth     tcg_gen_extu_i32_tl(reg, src);
382*fcf5ef2aSThomas Huth     tcg_gen_shri_tl(reg, reg, PSR_ZERO_SHIFT);
383*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(reg, reg, 0x1);
384*fcf5ef2aSThomas Huth }
385*fcf5ef2aSThomas Huth 
386*fcf5ef2aSThomas Huth static inline void gen_mov_reg_V(TCGv reg, TCGv_i32 src)
387*fcf5ef2aSThomas Huth {
388*fcf5ef2aSThomas Huth     tcg_gen_extu_i32_tl(reg, src);
389*fcf5ef2aSThomas Huth     tcg_gen_shri_tl(reg, reg, PSR_OVF_SHIFT);
390*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(reg, reg, 0x1);
391*fcf5ef2aSThomas Huth }
392*fcf5ef2aSThomas Huth 
393*fcf5ef2aSThomas Huth static inline void gen_mov_reg_C(TCGv reg, TCGv_i32 src)
394*fcf5ef2aSThomas Huth {
395*fcf5ef2aSThomas Huth     tcg_gen_extu_i32_tl(reg, src);
396*fcf5ef2aSThomas Huth     tcg_gen_shri_tl(reg, reg, PSR_CARRY_SHIFT);
397*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(reg, reg, 0x1);
398*fcf5ef2aSThomas Huth }
399*fcf5ef2aSThomas Huth 
400*fcf5ef2aSThomas Huth static inline void gen_op_add_cc(TCGv dst, TCGv src1, TCGv src2)
401*fcf5ef2aSThomas Huth {
402*fcf5ef2aSThomas Huth     tcg_gen_mov_tl(cpu_cc_src, src1);
403*fcf5ef2aSThomas Huth     tcg_gen_mov_tl(cpu_cc_src2, src2);
404*fcf5ef2aSThomas Huth     tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
405*fcf5ef2aSThomas Huth     tcg_gen_mov_tl(dst, cpu_cc_dst);
406*fcf5ef2aSThomas Huth }
407*fcf5ef2aSThomas Huth 
408*fcf5ef2aSThomas Huth static TCGv_i32 gen_add32_carry32(void)
409*fcf5ef2aSThomas Huth {
410*fcf5ef2aSThomas Huth     TCGv_i32 carry_32, cc_src1_32, cc_src2_32;
411*fcf5ef2aSThomas Huth 
412*fcf5ef2aSThomas Huth     /* Carry is computed from a previous add: (dst < src)  */
413*fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 64
414*fcf5ef2aSThomas Huth     cc_src1_32 = tcg_temp_new_i32();
415*fcf5ef2aSThomas Huth     cc_src2_32 = tcg_temp_new_i32();
416*fcf5ef2aSThomas Huth     tcg_gen_extrl_i64_i32(cc_src1_32, cpu_cc_dst);
417*fcf5ef2aSThomas Huth     tcg_gen_extrl_i64_i32(cc_src2_32, cpu_cc_src);
418*fcf5ef2aSThomas Huth #else
419*fcf5ef2aSThomas Huth     cc_src1_32 = cpu_cc_dst;
420*fcf5ef2aSThomas Huth     cc_src2_32 = cpu_cc_src;
421*fcf5ef2aSThomas Huth #endif
422*fcf5ef2aSThomas Huth 
423*fcf5ef2aSThomas Huth     carry_32 = tcg_temp_new_i32();
424*fcf5ef2aSThomas Huth     tcg_gen_setcond_i32(TCG_COND_LTU, carry_32, cc_src1_32, cc_src2_32);
425*fcf5ef2aSThomas Huth 
426*fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 64
427*fcf5ef2aSThomas Huth     tcg_temp_free_i32(cc_src1_32);
428*fcf5ef2aSThomas Huth     tcg_temp_free_i32(cc_src2_32);
429*fcf5ef2aSThomas Huth #endif
430*fcf5ef2aSThomas Huth 
431*fcf5ef2aSThomas Huth     return carry_32;
432*fcf5ef2aSThomas Huth }
433*fcf5ef2aSThomas Huth 
434*fcf5ef2aSThomas Huth static TCGv_i32 gen_sub32_carry32(void)
435*fcf5ef2aSThomas Huth {
436*fcf5ef2aSThomas Huth     TCGv_i32 carry_32, cc_src1_32, cc_src2_32;
437*fcf5ef2aSThomas Huth 
438*fcf5ef2aSThomas Huth     /* Carry is computed from a previous borrow: (src1 < src2)  */
439*fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 64
440*fcf5ef2aSThomas Huth     cc_src1_32 = tcg_temp_new_i32();
441*fcf5ef2aSThomas Huth     cc_src2_32 = tcg_temp_new_i32();
442*fcf5ef2aSThomas Huth     tcg_gen_extrl_i64_i32(cc_src1_32, cpu_cc_src);
443*fcf5ef2aSThomas Huth     tcg_gen_extrl_i64_i32(cc_src2_32, cpu_cc_src2);
444*fcf5ef2aSThomas Huth #else
445*fcf5ef2aSThomas Huth     cc_src1_32 = cpu_cc_src;
446*fcf5ef2aSThomas Huth     cc_src2_32 = cpu_cc_src2;
447*fcf5ef2aSThomas Huth #endif
448*fcf5ef2aSThomas Huth 
449*fcf5ef2aSThomas Huth     carry_32 = tcg_temp_new_i32();
450*fcf5ef2aSThomas Huth     tcg_gen_setcond_i32(TCG_COND_LTU, carry_32, cc_src1_32, cc_src2_32);
451*fcf5ef2aSThomas Huth 
452*fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 64
453*fcf5ef2aSThomas Huth     tcg_temp_free_i32(cc_src1_32);
454*fcf5ef2aSThomas Huth     tcg_temp_free_i32(cc_src2_32);
455*fcf5ef2aSThomas Huth #endif
456*fcf5ef2aSThomas Huth 
457*fcf5ef2aSThomas Huth     return carry_32;
458*fcf5ef2aSThomas Huth }
459*fcf5ef2aSThomas Huth 
460*fcf5ef2aSThomas Huth static void gen_op_addx_int(DisasContext *dc, TCGv dst, TCGv src1,
461*fcf5ef2aSThomas Huth                             TCGv src2, int update_cc)
462*fcf5ef2aSThomas Huth {
463*fcf5ef2aSThomas Huth     TCGv_i32 carry_32;
464*fcf5ef2aSThomas Huth     TCGv carry;
465*fcf5ef2aSThomas Huth 
466*fcf5ef2aSThomas Huth     switch (dc->cc_op) {
467*fcf5ef2aSThomas Huth     case CC_OP_DIV:
468*fcf5ef2aSThomas Huth     case CC_OP_LOGIC:
469*fcf5ef2aSThomas Huth         /* Carry is known to be zero.  Fall back to plain ADD.  */
470*fcf5ef2aSThomas Huth         if (update_cc) {
471*fcf5ef2aSThomas Huth             gen_op_add_cc(dst, src1, src2);
472*fcf5ef2aSThomas Huth         } else {
473*fcf5ef2aSThomas Huth             tcg_gen_add_tl(dst, src1, src2);
474*fcf5ef2aSThomas Huth         }
475*fcf5ef2aSThomas Huth         return;
476*fcf5ef2aSThomas Huth 
477*fcf5ef2aSThomas Huth     case CC_OP_ADD:
478*fcf5ef2aSThomas Huth     case CC_OP_TADD:
479*fcf5ef2aSThomas Huth     case CC_OP_TADDTV:
480*fcf5ef2aSThomas Huth         if (TARGET_LONG_BITS == 32) {
481*fcf5ef2aSThomas Huth             /* We can re-use the host's hardware carry generation by using
482*fcf5ef2aSThomas Huth                an ADD2 opcode.  We discard the low part of the output.
483*fcf5ef2aSThomas Huth                Ideally we'd combine this operation with the add that
484*fcf5ef2aSThomas Huth                generated the carry in the first place.  */
485*fcf5ef2aSThomas Huth             carry = tcg_temp_new();
486*fcf5ef2aSThomas Huth             tcg_gen_add2_tl(carry, dst, cpu_cc_src, src1, cpu_cc_src2, src2);
487*fcf5ef2aSThomas Huth             tcg_temp_free(carry);
488*fcf5ef2aSThomas Huth             goto add_done;
489*fcf5ef2aSThomas Huth         }
490*fcf5ef2aSThomas Huth         carry_32 = gen_add32_carry32();
491*fcf5ef2aSThomas Huth         break;
492*fcf5ef2aSThomas Huth 
493*fcf5ef2aSThomas Huth     case CC_OP_SUB:
494*fcf5ef2aSThomas Huth     case CC_OP_TSUB:
495*fcf5ef2aSThomas Huth     case CC_OP_TSUBTV:
496*fcf5ef2aSThomas Huth         carry_32 = gen_sub32_carry32();
497*fcf5ef2aSThomas Huth         break;
498*fcf5ef2aSThomas Huth 
499*fcf5ef2aSThomas Huth     default:
500*fcf5ef2aSThomas Huth         /* We need external help to produce the carry.  */
501*fcf5ef2aSThomas Huth         carry_32 = tcg_temp_new_i32();
502*fcf5ef2aSThomas Huth         gen_helper_compute_C_icc(carry_32, cpu_env);
503*fcf5ef2aSThomas Huth         break;
504*fcf5ef2aSThomas Huth     }
505*fcf5ef2aSThomas Huth 
506*fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 64
507*fcf5ef2aSThomas Huth     carry = tcg_temp_new();
508*fcf5ef2aSThomas Huth     tcg_gen_extu_i32_i64(carry, carry_32);
509*fcf5ef2aSThomas Huth #else
510*fcf5ef2aSThomas Huth     carry = carry_32;
511*fcf5ef2aSThomas Huth #endif
512*fcf5ef2aSThomas Huth 
513*fcf5ef2aSThomas Huth     tcg_gen_add_tl(dst, src1, src2);
514*fcf5ef2aSThomas Huth     tcg_gen_add_tl(dst, dst, carry);
515*fcf5ef2aSThomas Huth 
516*fcf5ef2aSThomas Huth     tcg_temp_free_i32(carry_32);
517*fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 64
518*fcf5ef2aSThomas Huth     tcg_temp_free(carry);
519*fcf5ef2aSThomas Huth #endif
520*fcf5ef2aSThomas Huth 
521*fcf5ef2aSThomas Huth  add_done:
522*fcf5ef2aSThomas Huth     if (update_cc) {
523*fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_cc_src, src1);
524*fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_cc_src2, src2);
525*fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_cc_dst, dst);
526*fcf5ef2aSThomas Huth         tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADDX);
527*fcf5ef2aSThomas Huth         dc->cc_op = CC_OP_ADDX;
528*fcf5ef2aSThomas Huth     }
529*fcf5ef2aSThomas Huth }
530*fcf5ef2aSThomas Huth 
531*fcf5ef2aSThomas Huth static inline void gen_op_sub_cc(TCGv dst, TCGv src1, TCGv src2)
532*fcf5ef2aSThomas Huth {
533*fcf5ef2aSThomas Huth     tcg_gen_mov_tl(cpu_cc_src, src1);
534*fcf5ef2aSThomas Huth     tcg_gen_mov_tl(cpu_cc_src2, src2);
535*fcf5ef2aSThomas Huth     tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
536*fcf5ef2aSThomas Huth     tcg_gen_mov_tl(dst, cpu_cc_dst);
537*fcf5ef2aSThomas Huth }
538*fcf5ef2aSThomas Huth 
539*fcf5ef2aSThomas Huth static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1,
540*fcf5ef2aSThomas Huth                             TCGv src2, int update_cc)
541*fcf5ef2aSThomas Huth {
542*fcf5ef2aSThomas Huth     TCGv_i32 carry_32;
543*fcf5ef2aSThomas Huth     TCGv carry;
544*fcf5ef2aSThomas Huth 
545*fcf5ef2aSThomas Huth     switch (dc->cc_op) {
546*fcf5ef2aSThomas Huth     case CC_OP_DIV:
547*fcf5ef2aSThomas Huth     case CC_OP_LOGIC:
548*fcf5ef2aSThomas Huth         /* Carry is known to be zero.  Fall back to plain SUB.  */
549*fcf5ef2aSThomas Huth         if (update_cc) {
550*fcf5ef2aSThomas Huth             gen_op_sub_cc(dst, src1, src2);
551*fcf5ef2aSThomas Huth         } else {
552*fcf5ef2aSThomas Huth             tcg_gen_sub_tl(dst, src1, src2);
553*fcf5ef2aSThomas Huth         }
554*fcf5ef2aSThomas Huth         return;
555*fcf5ef2aSThomas Huth 
556*fcf5ef2aSThomas Huth     case CC_OP_ADD:
557*fcf5ef2aSThomas Huth     case CC_OP_TADD:
558*fcf5ef2aSThomas Huth     case CC_OP_TADDTV:
559*fcf5ef2aSThomas Huth         carry_32 = gen_add32_carry32();
560*fcf5ef2aSThomas Huth         break;
561*fcf5ef2aSThomas Huth 
562*fcf5ef2aSThomas Huth     case CC_OP_SUB:
563*fcf5ef2aSThomas Huth     case CC_OP_TSUB:
564*fcf5ef2aSThomas Huth     case CC_OP_TSUBTV:
565*fcf5ef2aSThomas Huth         if (TARGET_LONG_BITS == 32) {
566*fcf5ef2aSThomas Huth             /* We can re-use the host's hardware carry generation by using
567*fcf5ef2aSThomas Huth                a SUB2 opcode.  We discard the low part of the output.
568*fcf5ef2aSThomas Huth                Ideally we'd combine this operation with the add that
569*fcf5ef2aSThomas Huth                generated the carry in the first place.  */
570*fcf5ef2aSThomas Huth             carry = tcg_temp_new();
571*fcf5ef2aSThomas Huth             tcg_gen_sub2_tl(carry, dst, cpu_cc_src, src1, cpu_cc_src2, src2);
572*fcf5ef2aSThomas Huth             tcg_temp_free(carry);
573*fcf5ef2aSThomas Huth             goto sub_done;
574*fcf5ef2aSThomas Huth         }
575*fcf5ef2aSThomas Huth         carry_32 = gen_sub32_carry32();
576*fcf5ef2aSThomas Huth         break;
577*fcf5ef2aSThomas Huth 
578*fcf5ef2aSThomas Huth     default:
579*fcf5ef2aSThomas Huth         /* We need external help to produce the carry.  */
580*fcf5ef2aSThomas Huth         carry_32 = tcg_temp_new_i32();
581*fcf5ef2aSThomas Huth         gen_helper_compute_C_icc(carry_32, cpu_env);
582*fcf5ef2aSThomas Huth         break;
583*fcf5ef2aSThomas Huth     }
584*fcf5ef2aSThomas Huth 
585*fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 64
586*fcf5ef2aSThomas Huth     carry = tcg_temp_new();
587*fcf5ef2aSThomas Huth     tcg_gen_extu_i32_i64(carry, carry_32);
588*fcf5ef2aSThomas Huth #else
589*fcf5ef2aSThomas Huth     carry = carry_32;
590*fcf5ef2aSThomas Huth #endif
591*fcf5ef2aSThomas Huth 
592*fcf5ef2aSThomas Huth     tcg_gen_sub_tl(dst, src1, src2);
593*fcf5ef2aSThomas Huth     tcg_gen_sub_tl(dst, dst, carry);
594*fcf5ef2aSThomas Huth 
595*fcf5ef2aSThomas Huth     tcg_temp_free_i32(carry_32);
596*fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 64
597*fcf5ef2aSThomas Huth     tcg_temp_free(carry);
598*fcf5ef2aSThomas Huth #endif
599*fcf5ef2aSThomas Huth 
600*fcf5ef2aSThomas Huth  sub_done:
601*fcf5ef2aSThomas Huth     if (update_cc) {
602*fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_cc_src, src1);
603*fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_cc_src2, src2);
604*fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_cc_dst, dst);
605*fcf5ef2aSThomas Huth         tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUBX);
606*fcf5ef2aSThomas Huth         dc->cc_op = CC_OP_SUBX;
607*fcf5ef2aSThomas Huth     }
608*fcf5ef2aSThomas Huth }
609*fcf5ef2aSThomas Huth 
610*fcf5ef2aSThomas Huth static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
611*fcf5ef2aSThomas Huth {
612*fcf5ef2aSThomas Huth     TCGv r_temp, zero, t0;
613*fcf5ef2aSThomas Huth 
614*fcf5ef2aSThomas Huth     r_temp = tcg_temp_new();
615*fcf5ef2aSThomas Huth     t0 = tcg_temp_new();
616*fcf5ef2aSThomas Huth 
617*fcf5ef2aSThomas Huth     /* old op:
618*fcf5ef2aSThomas Huth     if (!(env->y & 1))
619*fcf5ef2aSThomas Huth         T1 = 0;
620*fcf5ef2aSThomas Huth     */
621*fcf5ef2aSThomas Huth     zero = tcg_const_tl(0);
622*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(cpu_cc_src, src1, 0xffffffff);
623*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(r_temp, cpu_y, 0x1);
624*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(cpu_cc_src2, src2, 0xffffffff);
625*fcf5ef2aSThomas Huth     tcg_gen_movcond_tl(TCG_COND_EQ, cpu_cc_src2, r_temp, zero,
626*fcf5ef2aSThomas Huth                        zero, cpu_cc_src2);
627*fcf5ef2aSThomas Huth     tcg_temp_free(zero);
628*fcf5ef2aSThomas Huth 
629*fcf5ef2aSThomas Huth     // b2 = T0 & 1;
630*fcf5ef2aSThomas Huth     // env->y = (b2 << 31) | (env->y >> 1);
631*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(r_temp, cpu_cc_src, 0x1);
632*fcf5ef2aSThomas Huth     tcg_gen_shli_tl(r_temp, r_temp, 31);
633*fcf5ef2aSThomas Huth     tcg_gen_shri_tl(t0, cpu_y, 1);
634*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(t0, t0, 0x7fffffff);
635*fcf5ef2aSThomas Huth     tcg_gen_or_tl(t0, t0, r_temp);
636*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(cpu_y, t0, 0xffffffff);
637*fcf5ef2aSThomas Huth 
638*fcf5ef2aSThomas Huth     // b1 = N ^ V;
639*fcf5ef2aSThomas Huth     gen_mov_reg_N(t0, cpu_psr);
640*fcf5ef2aSThomas Huth     gen_mov_reg_V(r_temp, cpu_psr);
641*fcf5ef2aSThomas Huth     tcg_gen_xor_tl(t0, t0, r_temp);
642*fcf5ef2aSThomas Huth     tcg_temp_free(r_temp);
643*fcf5ef2aSThomas Huth 
644*fcf5ef2aSThomas Huth     // T0 = (b1 << 31) | (T0 >> 1);
645*fcf5ef2aSThomas Huth     // src1 = T0;
646*fcf5ef2aSThomas Huth     tcg_gen_shli_tl(t0, t0, 31);
647*fcf5ef2aSThomas Huth     tcg_gen_shri_tl(cpu_cc_src, cpu_cc_src, 1);
648*fcf5ef2aSThomas Huth     tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t0);
649*fcf5ef2aSThomas Huth     tcg_temp_free(t0);
650*fcf5ef2aSThomas Huth 
651*fcf5ef2aSThomas Huth     tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
652*fcf5ef2aSThomas Huth 
653*fcf5ef2aSThomas Huth     tcg_gen_mov_tl(dst, cpu_cc_dst);
654*fcf5ef2aSThomas Huth }
655*fcf5ef2aSThomas Huth 
656*fcf5ef2aSThomas Huth static inline void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext)
657*fcf5ef2aSThomas Huth {
658*fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 32
659*fcf5ef2aSThomas Huth     if (sign_ext) {
660*fcf5ef2aSThomas Huth         tcg_gen_muls2_tl(dst, cpu_y, src1, src2);
661*fcf5ef2aSThomas Huth     } else {
662*fcf5ef2aSThomas Huth         tcg_gen_mulu2_tl(dst, cpu_y, src1, src2);
663*fcf5ef2aSThomas Huth     }
664*fcf5ef2aSThomas Huth #else
665*fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new_i64();
666*fcf5ef2aSThomas Huth     TCGv t1 = tcg_temp_new_i64();
667*fcf5ef2aSThomas Huth 
668*fcf5ef2aSThomas Huth     if (sign_ext) {
669*fcf5ef2aSThomas Huth         tcg_gen_ext32s_i64(t0, src1);
670*fcf5ef2aSThomas Huth         tcg_gen_ext32s_i64(t1, src2);
671*fcf5ef2aSThomas Huth     } else {
672*fcf5ef2aSThomas Huth         tcg_gen_ext32u_i64(t0, src1);
673*fcf5ef2aSThomas Huth         tcg_gen_ext32u_i64(t1, src2);
674*fcf5ef2aSThomas Huth     }
675*fcf5ef2aSThomas Huth 
676*fcf5ef2aSThomas Huth     tcg_gen_mul_i64(dst, t0, t1);
677*fcf5ef2aSThomas Huth     tcg_temp_free(t0);
678*fcf5ef2aSThomas Huth     tcg_temp_free(t1);
679*fcf5ef2aSThomas Huth 
680*fcf5ef2aSThomas Huth     tcg_gen_shri_i64(cpu_y, dst, 32);
681*fcf5ef2aSThomas Huth #endif
682*fcf5ef2aSThomas Huth }
683*fcf5ef2aSThomas Huth 
684*fcf5ef2aSThomas Huth static inline void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
685*fcf5ef2aSThomas Huth {
686*fcf5ef2aSThomas Huth     /* zero-extend truncated operands before multiplication */
687*fcf5ef2aSThomas Huth     gen_op_multiply(dst, src1, src2, 0);
688*fcf5ef2aSThomas Huth }
689*fcf5ef2aSThomas Huth 
690*fcf5ef2aSThomas Huth static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
691*fcf5ef2aSThomas Huth {
692*fcf5ef2aSThomas Huth     /* sign-extend truncated operands before multiplication */
693*fcf5ef2aSThomas Huth     gen_op_multiply(dst, src1, src2, 1);
694*fcf5ef2aSThomas Huth }
695*fcf5ef2aSThomas Huth 
696*fcf5ef2aSThomas Huth // 1
697*fcf5ef2aSThomas Huth static inline void gen_op_eval_ba(TCGv dst)
698*fcf5ef2aSThomas Huth {
699*fcf5ef2aSThomas Huth     tcg_gen_movi_tl(dst, 1);
700*fcf5ef2aSThomas Huth }
701*fcf5ef2aSThomas Huth 
702*fcf5ef2aSThomas Huth // Z
703*fcf5ef2aSThomas Huth static inline void gen_op_eval_be(TCGv dst, TCGv_i32 src)
704*fcf5ef2aSThomas Huth {
705*fcf5ef2aSThomas Huth     gen_mov_reg_Z(dst, src);
706*fcf5ef2aSThomas Huth }
707*fcf5ef2aSThomas Huth 
708*fcf5ef2aSThomas Huth // Z | (N ^ V)
709*fcf5ef2aSThomas Huth static inline void gen_op_eval_ble(TCGv dst, TCGv_i32 src)
710*fcf5ef2aSThomas Huth {
711*fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new();
712*fcf5ef2aSThomas Huth     gen_mov_reg_N(t0, src);
713*fcf5ef2aSThomas Huth     gen_mov_reg_V(dst, src);
714*fcf5ef2aSThomas Huth     tcg_gen_xor_tl(dst, dst, t0);
715*fcf5ef2aSThomas Huth     gen_mov_reg_Z(t0, src);
716*fcf5ef2aSThomas Huth     tcg_gen_or_tl(dst, dst, t0);
717*fcf5ef2aSThomas Huth     tcg_temp_free(t0);
718*fcf5ef2aSThomas Huth }
719*fcf5ef2aSThomas Huth 
720*fcf5ef2aSThomas Huth // N ^ V
721*fcf5ef2aSThomas Huth static inline void gen_op_eval_bl(TCGv dst, TCGv_i32 src)
722*fcf5ef2aSThomas Huth {
723*fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new();
724*fcf5ef2aSThomas Huth     gen_mov_reg_V(t0, src);
725*fcf5ef2aSThomas Huth     gen_mov_reg_N(dst, src);
726*fcf5ef2aSThomas Huth     tcg_gen_xor_tl(dst, dst, t0);
727*fcf5ef2aSThomas Huth     tcg_temp_free(t0);
728*fcf5ef2aSThomas Huth }
729*fcf5ef2aSThomas Huth 
730*fcf5ef2aSThomas Huth // C | Z
731*fcf5ef2aSThomas Huth static inline void gen_op_eval_bleu(TCGv dst, TCGv_i32 src)
732*fcf5ef2aSThomas Huth {
733*fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new();
734*fcf5ef2aSThomas Huth     gen_mov_reg_Z(t0, src);
735*fcf5ef2aSThomas Huth     gen_mov_reg_C(dst, src);
736*fcf5ef2aSThomas Huth     tcg_gen_or_tl(dst, dst, t0);
737*fcf5ef2aSThomas Huth     tcg_temp_free(t0);
738*fcf5ef2aSThomas Huth }
739*fcf5ef2aSThomas Huth 
740*fcf5ef2aSThomas Huth // C
741*fcf5ef2aSThomas Huth static inline void gen_op_eval_bcs(TCGv dst, TCGv_i32 src)
742*fcf5ef2aSThomas Huth {
743*fcf5ef2aSThomas Huth     gen_mov_reg_C(dst, src);
744*fcf5ef2aSThomas Huth }
745*fcf5ef2aSThomas Huth 
746*fcf5ef2aSThomas Huth // V
747*fcf5ef2aSThomas Huth static inline void gen_op_eval_bvs(TCGv dst, TCGv_i32 src)
748*fcf5ef2aSThomas Huth {
749*fcf5ef2aSThomas Huth     gen_mov_reg_V(dst, src);
750*fcf5ef2aSThomas Huth }
751*fcf5ef2aSThomas Huth 
752*fcf5ef2aSThomas Huth // 0
753*fcf5ef2aSThomas Huth static inline void gen_op_eval_bn(TCGv dst)
754*fcf5ef2aSThomas Huth {
755*fcf5ef2aSThomas Huth     tcg_gen_movi_tl(dst, 0);
756*fcf5ef2aSThomas Huth }
757*fcf5ef2aSThomas Huth 
758*fcf5ef2aSThomas Huth // N
759*fcf5ef2aSThomas Huth static inline void gen_op_eval_bneg(TCGv dst, TCGv_i32 src)
760*fcf5ef2aSThomas Huth {
761*fcf5ef2aSThomas Huth     gen_mov_reg_N(dst, src);
762*fcf5ef2aSThomas Huth }
763*fcf5ef2aSThomas Huth 
764*fcf5ef2aSThomas Huth // !Z
765*fcf5ef2aSThomas Huth static inline void gen_op_eval_bne(TCGv dst, TCGv_i32 src)
766*fcf5ef2aSThomas Huth {
767*fcf5ef2aSThomas Huth     gen_mov_reg_Z(dst, src);
768*fcf5ef2aSThomas Huth     tcg_gen_xori_tl(dst, dst, 0x1);
769*fcf5ef2aSThomas Huth }
770*fcf5ef2aSThomas Huth 
771*fcf5ef2aSThomas Huth // !(Z | (N ^ V))
772*fcf5ef2aSThomas Huth static inline void gen_op_eval_bg(TCGv dst, TCGv_i32 src)
773*fcf5ef2aSThomas Huth {
774*fcf5ef2aSThomas Huth     gen_op_eval_ble(dst, src);
775*fcf5ef2aSThomas Huth     tcg_gen_xori_tl(dst, dst, 0x1);
776*fcf5ef2aSThomas Huth }
777*fcf5ef2aSThomas Huth 
778*fcf5ef2aSThomas Huth // !(N ^ V)
779*fcf5ef2aSThomas Huth static inline void gen_op_eval_bge(TCGv dst, TCGv_i32 src)
780*fcf5ef2aSThomas Huth {
781*fcf5ef2aSThomas Huth     gen_op_eval_bl(dst, src);
782*fcf5ef2aSThomas Huth     tcg_gen_xori_tl(dst, dst, 0x1);
783*fcf5ef2aSThomas Huth }
784*fcf5ef2aSThomas Huth 
785*fcf5ef2aSThomas Huth // !(C | Z)
786*fcf5ef2aSThomas Huth static inline void gen_op_eval_bgu(TCGv dst, TCGv_i32 src)
787*fcf5ef2aSThomas Huth {
788*fcf5ef2aSThomas Huth     gen_op_eval_bleu(dst, src);
789*fcf5ef2aSThomas Huth     tcg_gen_xori_tl(dst, dst, 0x1);
790*fcf5ef2aSThomas Huth }
791*fcf5ef2aSThomas Huth 
792*fcf5ef2aSThomas Huth // !C
793*fcf5ef2aSThomas Huth static inline void gen_op_eval_bcc(TCGv dst, TCGv_i32 src)
794*fcf5ef2aSThomas Huth {
795*fcf5ef2aSThomas Huth     gen_mov_reg_C(dst, src);
796*fcf5ef2aSThomas Huth     tcg_gen_xori_tl(dst, dst, 0x1);
797*fcf5ef2aSThomas Huth }
798*fcf5ef2aSThomas Huth 
799*fcf5ef2aSThomas Huth // !N
800*fcf5ef2aSThomas Huth static inline void gen_op_eval_bpos(TCGv dst, TCGv_i32 src)
801*fcf5ef2aSThomas Huth {
802*fcf5ef2aSThomas Huth     gen_mov_reg_N(dst, src);
803*fcf5ef2aSThomas Huth     tcg_gen_xori_tl(dst, dst, 0x1);
804*fcf5ef2aSThomas Huth }
805*fcf5ef2aSThomas Huth 
806*fcf5ef2aSThomas Huth // !V
807*fcf5ef2aSThomas Huth static inline void gen_op_eval_bvc(TCGv dst, TCGv_i32 src)
808*fcf5ef2aSThomas Huth {
809*fcf5ef2aSThomas Huth     gen_mov_reg_V(dst, src);
810*fcf5ef2aSThomas Huth     tcg_gen_xori_tl(dst, dst, 0x1);
811*fcf5ef2aSThomas Huth }
812*fcf5ef2aSThomas Huth 
813*fcf5ef2aSThomas Huth /*
814*fcf5ef2aSThomas Huth   FPSR bit field FCC1 | FCC0:
815*fcf5ef2aSThomas Huth    0 =
816*fcf5ef2aSThomas Huth    1 <
817*fcf5ef2aSThomas Huth    2 >
818*fcf5ef2aSThomas Huth    3 unordered
819*fcf5ef2aSThomas Huth */
820*fcf5ef2aSThomas Huth static inline void gen_mov_reg_FCC0(TCGv reg, TCGv src,
821*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
822*fcf5ef2aSThomas Huth {
823*fcf5ef2aSThomas Huth     tcg_gen_shri_tl(reg, src, FSR_FCC0_SHIFT + fcc_offset);
824*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(reg, reg, 0x1);
825*fcf5ef2aSThomas Huth }
826*fcf5ef2aSThomas Huth 
827*fcf5ef2aSThomas Huth static inline void gen_mov_reg_FCC1(TCGv reg, TCGv src,
828*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
829*fcf5ef2aSThomas Huth {
830*fcf5ef2aSThomas Huth     tcg_gen_shri_tl(reg, src, FSR_FCC1_SHIFT + fcc_offset);
831*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(reg, reg, 0x1);
832*fcf5ef2aSThomas Huth }
833*fcf5ef2aSThomas Huth 
834*fcf5ef2aSThomas Huth // !0: FCC0 | FCC1
835*fcf5ef2aSThomas Huth static inline void gen_op_eval_fbne(TCGv dst, TCGv src,
836*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
837*fcf5ef2aSThomas Huth {
838*fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new();
839*fcf5ef2aSThomas Huth     gen_mov_reg_FCC0(dst, src, fcc_offset);
840*fcf5ef2aSThomas Huth     gen_mov_reg_FCC1(t0, src, fcc_offset);
841*fcf5ef2aSThomas Huth     tcg_gen_or_tl(dst, dst, t0);
842*fcf5ef2aSThomas Huth     tcg_temp_free(t0);
843*fcf5ef2aSThomas Huth }
844*fcf5ef2aSThomas Huth 
845*fcf5ef2aSThomas Huth // 1 or 2: FCC0 ^ FCC1
846*fcf5ef2aSThomas Huth static inline void gen_op_eval_fblg(TCGv dst, TCGv src,
847*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
848*fcf5ef2aSThomas Huth {
849*fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new();
850*fcf5ef2aSThomas Huth     gen_mov_reg_FCC0(dst, src, fcc_offset);
851*fcf5ef2aSThomas Huth     gen_mov_reg_FCC1(t0, src, fcc_offset);
852*fcf5ef2aSThomas Huth     tcg_gen_xor_tl(dst, dst, t0);
853*fcf5ef2aSThomas Huth     tcg_temp_free(t0);
854*fcf5ef2aSThomas Huth }
855*fcf5ef2aSThomas Huth 
856*fcf5ef2aSThomas Huth // 1 or 3: FCC0
857*fcf5ef2aSThomas Huth static inline void gen_op_eval_fbul(TCGv dst, TCGv src,
858*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
859*fcf5ef2aSThomas Huth {
860*fcf5ef2aSThomas Huth     gen_mov_reg_FCC0(dst, src, fcc_offset);
861*fcf5ef2aSThomas Huth }
862*fcf5ef2aSThomas Huth 
863*fcf5ef2aSThomas Huth // 1: FCC0 & !FCC1
864*fcf5ef2aSThomas Huth static inline void gen_op_eval_fbl(TCGv dst, TCGv src,
865*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
866*fcf5ef2aSThomas Huth {
867*fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new();
868*fcf5ef2aSThomas Huth     gen_mov_reg_FCC0(dst, src, fcc_offset);
869*fcf5ef2aSThomas Huth     gen_mov_reg_FCC1(t0, src, fcc_offset);
870*fcf5ef2aSThomas Huth     tcg_gen_andc_tl(dst, dst, t0);
871*fcf5ef2aSThomas Huth     tcg_temp_free(t0);
872*fcf5ef2aSThomas Huth }
873*fcf5ef2aSThomas Huth 
874*fcf5ef2aSThomas Huth // 2 or 3: FCC1
875*fcf5ef2aSThomas Huth static inline void gen_op_eval_fbug(TCGv dst, TCGv src,
876*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
877*fcf5ef2aSThomas Huth {
878*fcf5ef2aSThomas Huth     gen_mov_reg_FCC1(dst, src, fcc_offset);
879*fcf5ef2aSThomas Huth }
880*fcf5ef2aSThomas Huth 
881*fcf5ef2aSThomas Huth // 2: !FCC0 & FCC1
882*fcf5ef2aSThomas Huth static inline void gen_op_eval_fbg(TCGv dst, TCGv src,
883*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
884*fcf5ef2aSThomas Huth {
885*fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new();
886*fcf5ef2aSThomas Huth     gen_mov_reg_FCC0(dst, src, fcc_offset);
887*fcf5ef2aSThomas Huth     gen_mov_reg_FCC1(t0, src, fcc_offset);
888*fcf5ef2aSThomas Huth     tcg_gen_andc_tl(dst, t0, dst);
889*fcf5ef2aSThomas Huth     tcg_temp_free(t0);
890*fcf5ef2aSThomas Huth }
891*fcf5ef2aSThomas Huth 
892*fcf5ef2aSThomas Huth // 3: FCC0 & FCC1
893*fcf5ef2aSThomas Huth static inline void gen_op_eval_fbu(TCGv dst, TCGv src,
894*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
895*fcf5ef2aSThomas Huth {
896*fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new();
897*fcf5ef2aSThomas Huth     gen_mov_reg_FCC0(dst, src, fcc_offset);
898*fcf5ef2aSThomas Huth     gen_mov_reg_FCC1(t0, src, fcc_offset);
899*fcf5ef2aSThomas Huth     tcg_gen_and_tl(dst, dst, t0);
900*fcf5ef2aSThomas Huth     tcg_temp_free(t0);
901*fcf5ef2aSThomas Huth }
902*fcf5ef2aSThomas Huth 
903*fcf5ef2aSThomas Huth // 0: !(FCC0 | FCC1)
904*fcf5ef2aSThomas Huth static inline void gen_op_eval_fbe(TCGv dst, TCGv src,
905*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
906*fcf5ef2aSThomas Huth {
907*fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new();
908*fcf5ef2aSThomas Huth     gen_mov_reg_FCC0(dst, src, fcc_offset);
909*fcf5ef2aSThomas Huth     gen_mov_reg_FCC1(t0, src, fcc_offset);
910*fcf5ef2aSThomas Huth     tcg_gen_or_tl(dst, dst, t0);
911*fcf5ef2aSThomas Huth     tcg_gen_xori_tl(dst, dst, 0x1);
912*fcf5ef2aSThomas Huth     tcg_temp_free(t0);
913*fcf5ef2aSThomas Huth }
914*fcf5ef2aSThomas Huth 
915*fcf5ef2aSThomas Huth // 0 or 3: !(FCC0 ^ FCC1)
916*fcf5ef2aSThomas Huth static inline void gen_op_eval_fbue(TCGv dst, TCGv src,
917*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
918*fcf5ef2aSThomas Huth {
919*fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new();
920*fcf5ef2aSThomas Huth     gen_mov_reg_FCC0(dst, src, fcc_offset);
921*fcf5ef2aSThomas Huth     gen_mov_reg_FCC1(t0, src, fcc_offset);
922*fcf5ef2aSThomas Huth     tcg_gen_xor_tl(dst, dst, t0);
923*fcf5ef2aSThomas Huth     tcg_gen_xori_tl(dst, dst, 0x1);
924*fcf5ef2aSThomas Huth     tcg_temp_free(t0);
925*fcf5ef2aSThomas Huth }
926*fcf5ef2aSThomas Huth 
927*fcf5ef2aSThomas Huth // 0 or 2: !FCC0
928*fcf5ef2aSThomas Huth static inline void gen_op_eval_fbge(TCGv dst, TCGv src,
929*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
930*fcf5ef2aSThomas Huth {
931*fcf5ef2aSThomas Huth     gen_mov_reg_FCC0(dst, src, fcc_offset);
932*fcf5ef2aSThomas Huth     tcg_gen_xori_tl(dst, dst, 0x1);
933*fcf5ef2aSThomas Huth }
934*fcf5ef2aSThomas Huth 
935*fcf5ef2aSThomas Huth // !1: !(FCC0 & !FCC1)
936*fcf5ef2aSThomas Huth static inline void gen_op_eval_fbuge(TCGv dst, TCGv src,
937*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
938*fcf5ef2aSThomas Huth {
939*fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new();
940*fcf5ef2aSThomas Huth     gen_mov_reg_FCC0(dst, src, fcc_offset);
941*fcf5ef2aSThomas Huth     gen_mov_reg_FCC1(t0, src, fcc_offset);
942*fcf5ef2aSThomas Huth     tcg_gen_andc_tl(dst, dst, t0);
943*fcf5ef2aSThomas Huth     tcg_gen_xori_tl(dst, dst, 0x1);
944*fcf5ef2aSThomas Huth     tcg_temp_free(t0);
945*fcf5ef2aSThomas Huth }
946*fcf5ef2aSThomas Huth 
947*fcf5ef2aSThomas Huth // 0 or 1: !FCC1
948*fcf5ef2aSThomas Huth static inline void gen_op_eval_fble(TCGv dst, TCGv src,
949*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
950*fcf5ef2aSThomas Huth {
951*fcf5ef2aSThomas Huth     gen_mov_reg_FCC1(dst, src, fcc_offset);
952*fcf5ef2aSThomas Huth     tcg_gen_xori_tl(dst, dst, 0x1);
953*fcf5ef2aSThomas Huth }
954*fcf5ef2aSThomas Huth 
955*fcf5ef2aSThomas Huth // !2: !(!FCC0 & FCC1)
956*fcf5ef2aSThomas Huth static inline void gen_op_eval_fbule(TCGv dst, TCGv src,
957*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
958*fcf5ef2aSThomas Huth {
959*fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new();
960*fcf5ef2aSThomas Huth     gen_mov_reg_FCC0(dst, src, fcc_offset);
961*fcf5ef2aSThomas Huth     gen_mov_reg_FCC1(t0, src, fcc_offset);
962*fcf5ef2aSThomas Huth     tcg_gen_andc_tl(dst, t0, dst);
963*fcf5ef2aSThomas Huth     tcg_gen_xori_tl(dst, dst, 0x1);
964*fcf5ef2aSThomas Huth     tcg_temp_free(t0);
965*fcf5ef2aSThomas Huth }
966*fcf5ef2aSThomas Huth 
967*fcf5ef2aSThomas Huth // !3: !(FCC0 & FCC1)
968*fcf5ef2aSThomas Huth static inline void gen_op_eval_fbo(TCGv dst, TCGv src,
969*fcf5ef2aSThomas Huth                                     unsigned int fcc_offset)
970*fcf5ef2aSThomas Huth {
971*fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new();
972*fcf5ef2aSThomas Huth     gen_mov_reg_FCC0(dst, src, fcc_offset);
973*fcf5ef2aSThomas Huth     gen_mov_reg_FCC1(t0, src, fcc_offset);
974*fcf5ef2aSThomas Huth     tcg_gen_and_tl(dst, dst, t0);
975*fcf5ef2aSThomas Huth     tcg_gen_xori_tl(dst, dst, 0x1);
976*fcf5ef2aSThomas Huth     tcg_temp_free(t0);
977*fcf5ef2aSThomas Huth }
978*fcf5ef2aSThomas Huth 
979*fcf5ef2aSThomas Huth static inline void gen_branch2(DisasContext *dc, target_ulong pc1,
980*fcf5ef2aSThomas Huth                                target_ulong pc2, TCGv r_cond)
981*fcf5ef2aSThomas Huth {
982*fcf5ef2aSThomas Huth     TCGLabel *l1 = gen_new_label();
983*fcf5ef2aSThomas Huth 
984*fcf5ef2aSThomas Huth     tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
985*fcf5ef2aSThomas Huth 
986*fcf5ef2aSThomas Huth     gen_goto_tb(dc, 0, pc1, pc1 + 4);
987*fcf5ef2aSThomas Huth 
988*fcf5ef2aSThomas Huth     gen_set_label(l1);
989*fcf5ef2aSThomas Huth     gen_goto_tb(dc, 1, pc2, pc2 + 4);
990*fcf5ef2aSThomas Huth }
991*fcf5ef2aSThomas Huth 
992*fcf5ef2aSThomas Huth static void gen_branch_a(DisasContext *dc, target_ulong pc1)
993*fcf5ef2aSThomas Huth {
994*fcf5ef2aSThomas Huth     TCGLabel *l1 = gen_new_label();
995*fcf5ef2aSThomas Huth     target_ulong npc = dc->npc;
996*fcf5ef2aSThomas Huth 
997*fcf5ef2aSThomas Huth     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_cond, 0, l1);
998*fcf5ef2aSThomas Huth 
999*fcf5ef2aSThomas Huth     gen_goto_tb(dc, 0, npc, pc1);
1000*fcf5ef2aSThomas Huth 
1001*fcf5ef2aSThomas Huth     gen_set_label(l1);
1002*fcf5ef2aSThomas Huth     gen_goto_tb(dc, 1, npc + 4, npc + 8);
1003*fcf5ef2aSThomas Huth 
1004*fcf5ef2aSThomas Huth     dc->is_br = 1;
1005*fcf5ef2aSThomas Huth }
1006*fcf5ef2aSThomas Huth 
1007*fcf5ef2aSThomas Huth static void gen_branch_n(DisasContext *dc, target_ulong pc1)
1008*fcf5ef2aSThomas Huth {
1009*fcf5ef2aSThomas Huth     target_ulong npc = dc->npc;
1010*fcf5ef2aSThomas Huth 
1011*fcf5ef2aSThomas Huth     if (likely(npc != DYNAMIC_PC)) {
1012*fcf5ef2aSThomas Huth         dc->pc = npc;
1013*fcf5ef2aSThomas Huth         dc->jump_pc[0] = pc1;
1014*fcf5ef2aSThomas Huth         dc->jump_pc[1] = npc + 4;
1015*fcf5ef2aSThomas Huth         dc->npc = JUMP_PC;
1016*fcf5ef2aSThomas Huth     } else {
1017*fcf5ef2aSThomas Huth         TCGv t, z;
1018*fcf5ef2aSThomas Huth 
1019*fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_pc, cpu_npc);
1020*fcf5ef2aSThomas Huth 
1021*fcf5ef2aSThomas Huth         tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
1022*fcf5ef2aSThomas Huth         t = tcg_const_tl(pc1);
1023*fcf5ef2aSThomas Huth         z = tcg_const_tl(0);
1024*fcf5ef2aSThomas Huth         tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, z, t, cpu_npc);
1025*fcf5ef2aSThomas Huth         tcg_temp_free(t);
1026*fcf5ef2aSThomas Huth         tcg_temp_free(z);
1027*fcf5ef2aSThomas Huth 
1028*fcf5ef2aSThomas Huth         dc->pc = DYNAMIC_PC;
1029*fcf5ef2aSThomas Huth     }
1030*fcf5ef2aSThomas Huth }
1031*fcf5ef2aSThomas Huth 
1032*fcf5ef2aSThomas Huth static inline void gen_generic_branch(DisasContext *dc)
1033*fcf5ef2aSThomas Huth {
1034*fcf5ef2aSThomas Huth     TCGv npc0 = tcg_const_tl(dc->jump_pc[0]);
1035*fcf5ef2aSThomas Huth     TCGv npc1 = tcg_const_tl(dc->jump_pc[1]);
1036*fcf5ef2aSThomas Huth     TCGv zero = tcg_const_tl(0);
1037*fcf5ef2aSThomas Huth 
1038*fcf5ef2aSThomas Huth     tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, zero, npc0, npc1);
1039*fcf5ef2aSThomas Huth 
1040*fcf5ef2aSThomas Huth     tcg_temp_free(npc0);
1041*fcf5ef2aSThomas Huth     tcg_temp_free(npc1);
1042*fcf5ef2aSThomas Huth     tcg_temp_free(zero);
1043*fcf5ef2aSThomas Huth }
1044*fcf5ef2aSThomas Huth 
1045*fcf5ef2aSThomas Huth /* call this function before using the condition register as it may
1046*fcf5ef2aSThomas Huth    have been set for a jump */
1047*fcf5ef2aSThomas Huth static inline void flush_cond(DisasContext *dc)
1048*fcf5ef2aSThomas Huth {
1049*fcf5ef2aSThomas Huth     if (dc->npc == JUMP_PC) {
1050*fcf5ef2aSThomas Huth         gen_generic_branch(dc);
1051*fcf5ef2aSThomas Huth         dc->npc = DYNAMIC_PC;
1052*fcf5ef2aSThomas Huth     }
1053*fcf5ef2aSThomas Huth }
1054*fcf5ef2aSThomas Huth 
1055*fcf5ef2aSThomas Huth static inline void save_npc(DisasContext *dc)
1056*fcf5ef2aSThomas Huth {
1057*fcf5ef2aSThomas Huth     if (dc->npc == JUMP_PC) {
1058*fcf5ef2aSThomas Huth         gen_generic_branch(dc);
1059*fcf5ef2aSThomas Huth         dc->npc = DYNAMIC_PC;
1060*fcf5ef2aSThomas Huth     } else if (dc->npc != DYNAMIC_PC) {
1061*fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_npc, dc->npc);
1062*fcf5ef2aSThomas Huth     }
1063*fcf5ef2aSThomas Huth }
1064*fcf5ef2aSThomas Huth 
1065*fcf5ef2aSThomas Huth static inline void update_psr(DisasContext *dc)
1066*fcf5ef2aSThomas Huth {
1067*fcf5ef2aSThomas Huth     if (dc->cc_op != CC_OP_FLAGS) {
1068*fcf5ef2aSThomas Huth         dc->cc_op = CC_OP_FLAGS;
1069*fcf5ef2aSThomas Huth         gen_helper_compute_psr(cpu_env);
1070*fcf5ef2aSThomas Huth     }
1071*fcf5ef2aSThomas Huth }
1072*fcf5ef2aSThomas Huth 
1073*fcf5ef2aSThomas Huth static inline void save_state(DisasContext *dc)
1074*fcf5ef2aSThomas Huth {
1075*fcf5ef2aSThomas Huth     tcg_gen_movi_tl(cpu_pc, dc->pc);
1076*fcf5ef2aSThomas Huth     save_npc(dc);
1077*fcf5ef2aSThomas Huth }
1078*fcf5ef2aSThomas Huth 
1079*fcf5ef2aSThomas Huth static void gen_exception(DisasContext *dc, int which)
1080*fcf5ef2aSThomas Huth {
1081*fcf5ef2aSThomas Huth     TCGv_i32 t;
1082*fcf5ef2aSThomas Huth 
1083*fcf5ef2aSThomas Huth     save_state(dc);
1084*fcf5ef2aSThomas Huth     t = tcg_const_i32(which);
1085*fcf5ef2aSThomas Huth     gen_helper_raise_exception(cpu_env, t);
1086*fcf5ef2aSThomas Huth     tcg_temp_free_i32(t);
1087*fcf5ef2aSThomas Huth     dc->is_br = 1;
1088*fcf5ef2aSThomas Huth }
1089*fcf5ef2aSThomas Huth 
1090*fcf5ef2aSThomas Huth static void gen_check_align(TCGv addr, int mask)
1091*fcf5ef2aSThomas Huth {
1092*fcf5ef2aSThomas Huth     TCGv_i32 r_mask = tcg_const_i32(mask);
1093*fcf5ef2aSThomas Huth     gen_helper_check_align(cpu_env, addr, r_mask);
1094*fcf5ef2aSThomas Huth     tcg_temp_free_i32(r_mask);
1095*fcf5ef2aSThomas Huth }
1096*fcf5ef2aSThomas Huth 
1097*fcf5ef2aSThomas Huth static inline void gen_mov_pc_npc(DisasContext *dc)
1098*fcf5ef2aSThomas Huth {
1099*fcf5ef2aSThomas Huth     if (dc->npc == JUMP_PC) {
1100*fcf5ef2aSThomas Huth         gen_generic_branch(dc);
1101*fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_pc, cpu_npc);
1102*fcf5ef2aSThomas Huth         dc->pc = DYNAMIC_PC;
1103*fcf5ef2aSThomas Huth     } else if (dc->npc == DYNAMIC_PC) {
1104*fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_pc, cpu_npc);
1105*fcf5ef2aSThomas Huth         dc->pc = DYNAMIC_PC;
1106*fcf5ef2aSThomas Huth     } else {
1107*fcf5ef2aSThomas Huth         dc->pc = dc->npc;
1108*fcf5ef2aSThomas Huth     }
1109*fcf5ef2aSThomas Huth }
1110*fcf5ef2aSThomas Huth 
1111*fcf5ef2aSThomas Huth static inline void gen_op_next_insn(void)
1112*fcf5ef2aSThomas Huth {
1113*fcf5ef2aSThomas Huth     tcg_gen_mov_tl(cpu_pc, cpu_npc);
1114*fcf5ef2aSThomas Huth     tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
1115*fcf5ef2aSThomas Huth }
1116*fcf5ef2aSThomas Huth 
1117*fcf5ef2aSThomas Huth static void free_compare(DisasCompare *cmp)
1118*fcf5ef2aSThomas Huth {
1119*fcf5ef2aSThomas Huth     if (!cmp->g1) {
1120*fcf5ef2aSThomas Huth         tcg_temp_free(cmp->c1);
1121*fcf5ef2aSThomas Huth     }
1122*fcf5ef2aSThomas Huth     if (!cmp->g2) {
1123*fcf5ef2aSThomas Huth         tcg_temp_free(cmp->c2);
1124*fcf5ef2aSThomas Huth     }
1125*fcf5ef2aSThomas Huth }
1126*fcf5ef2aSThomas Huth 
1127*fcf5ef2aSThomas Huth static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond,
1128*fcf5ef2aSThomas Huth                         DisasContext *dc)
1129*fcf5ef2aSThomas Huth {
1130*fcf5ef2aSThomas Huth     static int subcc_cond[16] = {
1131*fcf5ef2aSThomas Huth         TCG_COND_NEVER,
1132*fcf5ef2aSThomas Huth         TCG_COND_EQ,
1133*fcf5ef2aSThomas Huth         TCG_COND_LE,
1134*fcf5ef2aSThomas Huth         TCG_COND_LT,
1135*fcf5ef2aSThomas Huth         TCG_COND_LEU,
1136*fcf5ef2aSThomas Huth         TCG_COND_LTU,
1137*fcf5ef2aSThomas Huth         -1, /* neg */
1138*fcf5ef2aSThomas Huth         -1, /* overflow */
1139*fcf5ef2aSThomas Huth         TCG_COND_ALWAYS,
1140*fcf5ef2aSThomas Huth         TCG_COND_NE,
1141*fcf5ef2aSThomas Huth         TCG_COND_GT,
1142*fcf5ef2aSThomas Huth         TCG_COND_GE,
1143*fcf5ef2aSThomas Huth         TCG_COND_GTU,
1144*fcf5ef2aSThomas Huth         TCG_COND_GEU,
1145*fcf5ef2aSThomas Huth         -1, /* pos */
1146*fcf5ef2aSThomas Huth         -1, /* no overflow */
1147*fcf5ef2aSThomas Huth     };
1148*fcf5ef2aSThomas Huth 
1149*fcf5ef2aSThomas Huth     static int logic_cond[16] = {
1150*fcf5ef2aSThomas Huth         TCG_COND_NEVER,
1151*fcf5ef2aSThomas Huth         TCG_COND_EQ,     /* eq:  Z */
1152*fcf5ef2aSThomas Huth         TCG_COND_LE,     /* le:  Z | (N ^ V) -> Z | N */
1153*fcf5ef2aSThomas Huth         TCG_COND_LT,     /* lt:  N ^ V -> N */
1154*fcf5ef2aSThomas Huth         TCG_COND_EQ,     /* leu: C | Z -> Z */
1155*fcf5ef2aSThomas Huth         TCG_COND_NEVER,  /* ltu: C -> 0 */
1156*fcf5ef2aSThomas Huth         TCG_COND_LT,     /* neg: N */
1157*fcf5ef2aSThomas Huth         TCG_COND_NEVER,  /* vs:  V -> 0 */
1158*fcf5ef2aSThomas Huth         TCG_COND_ALWAYS,
1159*fcf5ef2aSThomas Huth         TCG_COND_NE,     /* ne:  !Z */
1160*fcf5ef2aSThomas Huth         TCG_COND_GT,     /* gt:  !(Z | (N ^ V)) -> !(Z | N) */
1161*fcf5ef2aSThomas Huth         TCG_COND_GE,     /* ge:  !(N ^ V) -> !N */
1162*fcf5ef2aSThomas Huth         TCG_COND_NE,     /* gtu: !(C | Z) -> !Z */
1163*fcf5ef2aSThomas Huth         TCG_COND_ALWAYS, /* geu: !C -> 1 */
1164*fcf5ef2aSThomas Huth         TCG_COND_GE,     /* pos: !N */
1165*fcf5ef2aSThomas Huth         TCG_COND_ALWAYS, /* vc:  !V -> 1 */
1166*fcf5ef2aSThomas Huth     };
1167*fcf5ef2aSThomas Huth 
1168*fcf5ef2aSThomas Huth     TCGv_i32 r_src;
1169*fcf5ef2aSThomas Huth     TCGv r_dst;
1170*fcf5ef2aSThomas Huth 
1171*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1172*fcf5ef2aSThomas Huth     if (xcc) {
1173*fcf5ef2aSThomas Huth         r_src = cpu_xcc;
1174*fcf5ef2aSThomas Huth     } else {
1175*fcf5ef2aSThomas Huth         r_src = cpu_psr;
1176*fcf5ef2aSThomas Huth     }
1177*fcf5ef2aSThomas Huth #else
1178*fcf5ef2aSThomas Huth     r_src = cpu_psr;
1179*fcf5ef2aSThomas Huth #endif
1180*fcf5ef2aSThomas Huth 
1181*fcf5ef2aSThomas Huth     switch (dc->cc_op) {
1182*fcf5ef2aSThomas Huth     case CC_OP_LOGIC:
1183*fcf5ef2aSThomas Huth         cmp->cond = logic_cond[cond];
1184*fcf5ef2aSThomas Huth     do_compare_dst_0:
1185*fcf5ef2aSThomas Huth         cmp->is_bool = false;
1186*fcf5ef2aSThomas Huth         cmp->g2 = false;
1187*fcf5ef2aSThomas Huth         cmp->c2 = tcg_const_tl(0);
1188*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1189*fcf5ef2aSThomas Huth         if (!xcc) {
1190*fcf5ef2aSThomas Huth             cmp->g1 = false;
1191*fcf5ef2aSThomas Huth             cmp->c1 = tcg_temp_new();
1192*fcf5ef2aSThomas Huth             tcg_gen_ext32s_tl(cmp->c1, cpu_cc_dst);
1193*fcf5ef2aSThomas Huth             break;
1194*fcf5ef2aSThomas Huth         }
1195*fcf5ef2aSThomas Huth #endif
1196*fcf5ef2aSThomas Huth         cmp->g1 = true;
1197*fcf5ef2aSThomas Huth         cmp->c1 = cpu_cc_dst;
1198*fcf5ef2aSThomas Huth         break;
1199*fcf5ef2aSThomas Huth 
1200*fcf5ef2aSThomas Huth     case CC_OP_SUB:
1201*fcf5ef2aSThomas Huth         switch (cond) {
1202*fcf5ef2aSThomas Huth         case 6:  /* neg */
1203*fcf5ef2aSThomas Huth         case 14: /* pos */
1204*fcf5ef2aSThomas Huth             cmp->cond = (cond == 6 ? TCG_COND_LT : TCG_COND_GE);
1205*fcf5ef2aSThomas Huth             goto do_compare_dst_0;
1206*fcf5ef2aSThomas Huth 
1207*fcf5ef2aSThomas Huth         case 7: /* overflow */
1208*fcf5ef2aSThomas Huth         case 15: /* !overflow */
1209*fcf5ef2aSThomas Huth             goto do_dynamic;
1210*fcf5ef2aSThomas Huth 
1211*fcf5ef2aSThomas Huth         default:
1212*fcf5ef2aSThomas Huth             cmp->cond = subcc_cond[cond];
1213*fcf5ef2aSThomas Huth             cmp->is_bool = false;
1214*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1215*fcf5ef2aSThomas Huth             if (!xcc) {
1216*fcf5ef2aSThomas Huth                 /* Note that sign-extension works for unsigned compares as
1217*fcf5ef2aSThomas Huth                    long as both operands are sign-extended.  */
1218*fcf5ef2aSThomas Huth                 cmp->g1 = cmp->g2 = false;
1219*fcf5ef2aSThomas Huth                 cmp->c1 = tcg_temp_new();
1220*fcf5ef2aSThomas Huth                 cmp->c2 = tcg_temp_new();
1221*fcf5ef2aSThomas Huth                 tcg_gen_ext32s_tl(cmp->c1, cpu_cc_src);
1222*fcf5ef2aSThomas Huth                 tcg_gen_ext32s_tl(cmp->c2, cpu_cc_src2);
1223*fcf5ef2aSThomas Huth                 break;
1224*fcf5ef2aSThomas Huth             }
1225*fcf5ef2aSThomas Huth #endif
1226*fcf5ef2aSThomas Huth             cmp->g1 = cmp->g2 = true;
1227*fcf5ef2aSThomas Huth             cmp->c1 = cpu_cc_src;
1228*fcf5ef2aSThomas Huth             cmp->c2 = cpu_cc_src2;
1229*fcf5ef2aSThomas Huth             break;
1230*fcf5ef2aSThomas Huth         }
1231*fcf5ef2aSThomas Huth         break;
1232*fcf5ef2aSThomas Huth 
1233*fcf5ef2aSThomas Huth     default:
1234*fcf5ef2aSThomas Huth     do_dynamic:
1235*fcf5ef2aSThomas Huth         gen_helper_compute_psr(cpu_env);
1236*fcf5ef2aSThomas Huth         dc->cc_op = CC_OP_FLAGS;
1237*fcf5ef2aSThomas Huth         /* FALLTHRU */
1238*fcf5ef2aSThomas Huth 
1239*fcf5ef2aSThomas Huth     case CC_OP_FLAGS:
1240*fcf5ef2aSThomas Huth         /* We're going to generate a boolean result.  */
1241*fcf5ef2aSThomas Huth         cmp->cond = TCG_COND_NE;
1242*fcf5ef2aSThomas Huth         cmp->is_bool = true;
1243*fcf5ef2aSThomas Huth         cmp->g1 = cmp->g2 = false;
1244*fcf5ef2aSThomas Huth         cmp->c1 = r_dst = tcg_temp_new();
1245*fcf5ef2aSThomas Huth         cmp->c2 = tcg_const_tl(0);
1246*fcf5ef2aSThomas Huth 
1247*fcf5ef2aSThomas Huth         switch (cond) {
1248*fcf5ef2aSThomas Huth         case 0x0:
1249*fcf5ef2aSThomas Huth             gen_op_eval_bn(r_dst);
1250*fcf5ef2aSThomas Huth             break;
1251*fcf5ef2aSThomas Huth         case 0x1:
1252*fcf5ef2aSThomas Huth             gen_op_eval_be(r_dst, r_src);
1253*fcf5ef2aSThomas Huth             break;
1254*fcf5ef2aSThomas Huth         case 0x2:
1255*fcf5ef2aSThomas Huth             gen_op_eval_ble(r_dst, r_src);
1256*fcf5ef2aSThomas Huth             break;
1257*fcf5ef2aSThomas Huth         case 0x3:
1258*fcf5ef2aSThomas Huth             gen_op_eval_bl(r_dst, r_src);
1259*fcf5ef2aSThomas Huth             break;
1260*fcf5ef2aSThomas Huth         case 0x4:
1261*fcf5ef2aSThomas Huth             gen_op_eval_bleu(r_dst, r_src);
1262*fcf5ef2aSThomas Huth             break;
1263*fcf5ef2aSThomas Huth         case 0x5:
1264*fcf5ef2aSThomas Huth             gen_op_eval_bcs(r_dst, r_src);
1265*fcf5ef2aSThomas Huth             break;
1266*fcf5ef2aSThomas Huth         case 0x6:
1267*fcf5ef2aSThomas Huth             gen_op_eval_bneg(r_dst, r_src);
1268*fcf5ef2aSThomas Huth             break;
1269*fcf5ef2aSThomas Huth         case 0x7:
1270*fcf5ef2aSThomas Huth             gen_op_eval_bvs(r_dst, r_src);
1271*fcf5ef2aSThomas Huth             break;
1272*fcf5ef2aSThomas Huth         case 0x8:
1273*fcf5ef2aSThomas Huth             gen_op_eval_ba(r_dst);
1274*fcf5ef2aSThomas Huth             break;
1275*fcf5ef2aSThomas Huth         case 0x9:
1276*fcf5ef2aSThomas Huth             gen_op_eval_bne(r_dst, r_src);
1277*fcf5ef2aSThomas Huth             break;
1278*fcf5ef2aSThomas Huth         case 0xa:
1279*fcf5ef2aSThomas Huth             gen_op_eval_bg(r_dst, r_src);
1280*fcf5ef2aSThomas Huth             break;
1281*fcf5ef2aSThomas Huth         case 0xb:
1282*fcf5ef2aSThomas Huth             gen_op_eval_bge(r_dst, r_src);
1283*fcf5ef2aSThomas Huth             break;
1284*fcf5ef2aSThomas Huth         case 0xc:
1285*fcf5ef2aSThomas Huth             gen_op_eval_bgu(r_dst, r_src);
1286*fcf5ef2aSThomas Huth             break;
1287*fcf5ef2aSThomas Huth         case 0xd:
1288*fcf5ef2aSThomas Huth             gen_op_eval_bcc(r_dst, r_src);
1289*fcf5ef2aSThomas Huth             break;
1290*fcf5ef2aSThomas Huth         case 0xe:
1291*fcf5ef2aSThomas Huth             gen_op_eval_bpos(r_dst, r_src);
1292*fcf5ef2aSThomas Huth             break;
1293*fcf5ef2aSThomas Huth         case 0xf:
1294*fcf5ef2aSThomas Huth             gen_op_eval_bvc(r_dst, r_src);
1295*fcf5ef2aSThomas Huth             break;
1296*fcf5ef2aSThomas Huth         }
1297*fcf5ef2aSThomas Huth         break;
1298*fcf5ef2aSThomas Huth     }
1299*fcf5ef2aSThomas Huth }
1300*fcf5ef2aSThomas Huth 
1301*fcf5ef2aSThomas Huth static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond)
1302*fcf5ef2aSThomas Huth {
1303*fcf5ef2aSThomas Huth     unsigned int offset;
1304*fcf5ef2aSThomas Huth     TCGv r_dst;
1305*fcf5ef2aSThomas Huth 
1306*fcf5ef2aSThomas Huth     /* For now we still generate a straight boolean result.  */
1307*fcf5ef2aSThomas Huth     cmp->cond = TCG_COND_NE;
1308*fcf5ef2aSThomas Huth     cmp->is_bool = true;
1309*fcf5ef2aSThomas Huth     cmp->g1 = cmp->g2 = false;
1310*fcf5ef2aSThomas Huth     cmp->c1 = r_dst = tcg_temp_new();
1311*fcf5ef2aSThomas Huth     cmp->c2 = tcg_const_tl(0);
1312*fcf5ef2aSThomas Huth 
1313*fcf5ef2aSThomas Huth     switch (cc) {
1314*fcf5ef2aSThomas Huth     default:
1315*fcf5ef2aSThomas Huth     case 0x0:
1316*fcf5ef2aSThomas Huth         offset = 0;
1317*fcf5ef2aSThomas Huth         break;
1318*fcf5ef2aSThomas Huth     case 0x1:
1319*fcf5ef2aSThomas Huth         offset = 32 - 10;
1320*fcf5ef2aSThomas Huth         break;
1321*fcf5ef2aSThomas Huth     case 0x2:
1322*fcf5ef2aSThomas Huth         offset = 34 - 10;
1323*fcf5ef2aSThomas Huth         break;
1324*fcf5ef2aSThomas Huth     case 0x3:
1325*fcf5ef2aSThomas Huth         offset = 36 - 10;
1326*fcf5ef2aSThomas Huth         break;
1327*fcf5ef2aSThomas Huth     }
1328*fcf5ef2aSThomas Huth 
1329*fcf5ef2aSThomas Huth     switch (cond) {
1330*fcf5ef2aSThomas Huth     case 0x0:
1331*fcf5ef2aSThomas Huth         gen_op_eval_bn(r_dst);
1332*fcf5ef2aSThomas Huth         break;
1333*fcf5ef2aSThomas Huth     case 0x1:
1334*fcf5ef2aSThomas Huth         gen_op_eval_fbne(r_dst, cpu_fsr, offset);
1335*fcf5ef2aSThomas Huth         break;
1336*fcf5ef2aSThomas Huth     case 0x2:
1337*fcf5ef2aSThomas Huth         gen_op_eval_fblg(r_dst, cpu_fsr, offset);
1338*fcf5ef2aSThomas Huth         break;
1339*fcf5ef2aSThomas Huth     case 0x3:
1340*fcf5ef2aSThomas Huth         gen_op_eval_fbul(r_dst, cpu_fsr, offset);
1341*fcf5ef2aSThomas Huth         break;
1342*fcf5ef2aSThomas Huth     case 0x4:
1343*fcf5ef2aSThomas Huth         gen_op_eval_fbl(r_dst, cpu_fsr, offset);
1344*fcf5ef2aSThomas Huth         break;
1345*fcf5ef2aSThomas Huth     case 0x5:
1346*fcf5ef2aSThomas Huth         gen_op_eval_fbug(r_dst, cpu_fsr, offset);
1347*fcf5ef2aSThomas Huth         break;
1348*fcf5ef2aSThomas Huth     case 0x6:
1349*fcf5ef2aSThomas Huth         gen_op_eval_fbg(r_dst, cpu_fsr, offset);
1350*fcf5ef2aSThomas Huth         break;
1351*fcf5ef2aSThomas Huth     case 0x7:
1352*fcf5ef2aSThomas Huth         gen_op_eval_fbu(r_dst, cpu_fsr, offset);
1353*fcf5ef2aSThomas Huth         break;
1354*fcf5ef2aSThomas Huth     case 0x8:
1355*fcf5ef2aSThomas Huth         gen_op_eval_ba(r_dst);
1356*fcf5ef2aSThomas Huth         break;
1357*fcf5ef2aSThomas Huth     case 0x9:
1358*fcf5ef2aSThomas Huth         gen_op_eval_fbe(r_dst, cpu_fsr, offset);
1359*fcf5ef2aSThomas Huth         break;
1360*fcf5ef2aSThomas Huth     case 0xa:
1361*fcf5ef2aSThomas Huth         gen_op_eval_fbue(r_dst, cpu_fsr, offset);
1362*fcf5ef2aSThomas Huth         break;
1363*fcf5ef2aSThomas Huth     case 0xb:
1364*fcf5ef2aSThomas Huth         gen_op_eval_fbge(r_dst, cpu_fsr, offset);
1365*fcf5ef2aSThomas Huth         break;
1366*fcf5ef2aSThomas Huth     case 0xc:
1367*fcf5ef2aSThomas Huth         gen_op_eval_fbuge(r_dst, cpu_fsr, offset);
1368*fcf5ef2aSThomas Huth         break;
1369*fcf5ef2aSThomas Huth     case 0xd:
1370*fcf5ef2aSThomas Huth         gen_op_eval_fble(r_dst, cpu_fsr, offset);
1371*fcf5ef2aSThomas Huth         break;
1372*fcf5ef2aSThomas Huth     case 0xe:
1373*fcf5ef2aSThomas Huth         gen_op_eval_fbule(r_dst, cpu_fsr, offset);
1374*fcf5ef2aSThomas Huth         break;
1375*fcf5ef2aSThomas Huth     case 0xf:
1376*fcf5ef2aSThomas Huth         gen_op_eval_fbo(r_dst, cpu_fsr, offset);
1377*fcf5ef2aSThomas Huth         break;
1378*fcf5ef2aSThomas Huth     }
1379*fcf5ef2aSThomas Huth }
1380*fcf5ef2aSThomas Huth 
1381*fcf5ef2aSThomas Huth static void gen_cond(TCGv r_dst, unsigned int cc, unsigned int cond,
1382*fcf5ef2aSThomas Huth                      DisasContext *dc)
1383*fcf5ef2aSThomas Huth {
1384*fcf5ef2aSThomas Huth     DisasCompare cmp;
1385*fcf5ef2aSThomas Huth     gen_compare(&cmp, cc, cond, dc);
1386*fcf5ef2aSThomas Huth 
1387*fcf5ef2aSThomas Huth     /* The interface is to return a boolean in r_dst.  */
1388*fcf5ef2aSThomas Huth     if (cmp.is_bool) {
1389*fcf5ef2aSThomas Huth         tcg_gen_mov_tl(r_dst, cmp.c1);
1390*fcf5ef2aSThomas Huth     } else {
1391*fcf5ef2aSThomas Huth         tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2);
1392*fcf5ef2aSThomas Huth     }
1393*fcf5ef2aSThomas Huth 
1394*fcf5ef2aSThomas Huth     free_compare(&cmp);
1395*fcf5ef2aSThomas Huth }
1396*fcf5ef2aSThomas Huth 
1397*fcf5ef2aSThomas Huth static void gen_fcond(TCGv r_dst, unsigned int cc, unsigned int cond)
1398*fcf5ef2aSThomas Huth {
1399*fcf5ef2aSThomas Huth     DisasCompare cmp;
1400*fcf5ef2aSThomas Huth     gen_fcompare(&cmp, cc, cond);
1401*fcf5ef2aSThomas Huth 
1402*fcf5ef2aSThomas Huth     /* The interface is to return a boolean in r_dst.  */
1403*fcf5ef2aSThomas Huth     if (cmp.is_bool) {
1404*fcf5ef2aSThomas Huth         tcg_gen_mov_tl(r_dst, cmp.c1);
1405*fcf5ef2aSThomas Huth     } else {
1406*fcf5ef2aSThomas Huth         tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2);
1407*fcf5ef2aSThomas Huth     }
1408*fcf5ef2aSThomas Huth 
1409*fcf5ef2aSThomas Huth     free_compare(&cmp);
1410*fcf5ef2aSThomas Huth }
1411*fcf5ef2aSThomas Huth 
1412*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1413*fcf5ef2aSThomas Huth // Inverted logic
1414*fcf5ef2aSThomas Huth static const int gen_tcg_cond_reg[8] = {
1415*fcf5ef2aSThomas Huth     -1,
1416*fcf5ef2aSThomas Huth     TCG_COND_NE,
1417*fcf5ef2aSThomas Huth     TCG_COND_GT,
1418*fcf5ef2aSThomas Huth     TCG_COND_GE,
1419*fcf5ef2aSThomas Huth     -1,
1420*fcf5ef2aSThomas Huth     TCG_COND_EQ,
1421*fcf5ef2aSThomas Huth     TCG_COND_LE,
1422*fcf5ef2aSThomas Huth     TCG_COND_LT,
1423*fcf5ef2aSThomas Huth };
1424*fcf5ef2aSThomas Huth 
1425*fcf5ef2aSThomas Huth static void gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src)
1426*fcf5ef2aSThomas Huth {
1427*fcf5ef2aSThomas Huth     cmp->cond = tcg_invert_cond(gen_tcg_cond_reg[cond]);
1428*fcf5ef2aSThomas Huth     cmp->is_bool = false;
1429*fcf5ef2aSThomas Huth     cmp->g1 = true;
1430*fcf5ef2aSThomas Huth     cmp->g2 = false;
1431*fcf5ef2aSThomas Huth     cmp->c1 = r_src;
1432*fcf5ef2aSThomas Huth     cmp->c2 = tcg_const_tl(0);
1433*fcf5ef2aSThomas Huth }
1434*fcf5ef2aSThomas Huth 
1435*fcf5ef2aSThomas Huth static inline void gen_cond_reg(TCGv r_dst, int cond, TCGv r_src)
1436*fcf5ef2aSThomas Huth {
1437*fcf5ef2aSThomas Huth     DisasCompare cmp;
1438*fcf5ef2aSThomas Huth     gen_compare_reg(&cmp, cond, r_src);
1439*fcf5ef2aSThomas Huth 
1440*fcf5ef2aSThomas Huth     /* The interface is to return a boolean in r_dst.  */
1441*fcf5ef2aSThomas Huth     tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2);
1442*fcf5ef2aSThomas Huth 
1443*fcf5ef2aSThomas Huth     free_compare(&cmp);
1444*fcf5ef2aSThomas Huth }
1445*fcf5ef2aSThomas Huth #endif
1446*fcf5ef2aSThomas Huth 
1447*fcf5ef2aSThomas Huth static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc)
1448*fcf5ef2aSThomas Huth {
1449*fcf5ef2aSThomas Huth     unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
1450*fcf5ef2aSThomas Huth     target_ulong target = dc->pc + offset;
1451*fcf5ef2aSThomas Huth 
1452*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1453*fcf5ef2aSThomas Huth     if (unlikely(AM_CHECK(dc))) {
1454*fcf5ef2aSThomas Huth         target &= 0xffffffffULL;
1455*fcf5ef2aSThomas Huth     }
1456*fcf5ef2aSThomas Huth #endif
1457*fcf5ef2aSThomas Huth     if (cond == 0x0) {
1458*fcf5ef2aSThomas Huth         /* unconditional not taken */
1459*fcf5ef2aSThomas Huth         if (a) {
1460*fcf5ef2aSThomas Huth             dc->pc = dc->npc + 4;
1461*fcf5ef2aSThomas Huth             dc->npc = dc->pc + 4;
1462*fcf5ef2aSThomas Huth         } else {
1463*fcf5ef2aSThomas Huth             dc->pc = dc->npc;
1464*fcf5ef2aSThomas Huth             dc->npc = dc->pc + 4;
1465*fcf5ef2aSThomas Huth         }
1466*fcf5ef2aSThomas Huth     } else if (cond == 0x8) {
1467*fcf5ef2aSThomas Huth         /* unconditional taken */
1468*fcf5ef2aSThomas Huth         if (a) {
1469*fcf5ef2aSThomas Huth             dc->pc = target;
1470*fcf5ef2aSThomas Huth             dc->npc = dc->pc + 4;
1471*fcf5ef2aSThomas Huth         } else {
1472*fcf5ef2aSThomas Huth             dc->pc = dc->npc;
1473*fcf5ef2aSThomas Huth             dc->npc = target;
1474*fcf5ef2aSThomas Huth             tcg_gen_mov_tl(cpu_pc, cpu_npc);
1475*fcf5ef2aSThomas Huth         }
1476*fcf5ef2aSThomas Huth     } else {
1477*fcf5ef2aSThomas Huth         flush_cond(dc);
1478*fcf5ef2aSThomas Huth         gen_cond(cpu_cond, cc, cond, dc);
1479*fcf5ef2aSThomas Huth         if (a) {
1480*fcf5ef2aSThomas Huth             gen_branch_a(dc, target);
1481*fcf5ef2aSThomas Huth         } else {
1482*fcf5ef2aSThomas Huth             gen_branch_n(dc, target);
1483*fcf5ef2aSThomas Huth         }
1484*fcf5ef2aSThomas Huth     }
1485*fcf5ef2aSThomas Huth }
1486*fcf5ef2aSThomas Huth 
1487*fcf5ef2aSThomas Huth static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc)
1488*fcf5ef2aSThomas Huth {
1489*fcf5ef2aSThomas Huth     unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
1490*fcf5ef2aSThomas Huth     target_ulong target = dc->pc + offset;
1491*fcf5ef2aSThomas Huth 
1492*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1493*fcf5ef2aSThomas Huth     if (unlikely(AM_CHECK(dc))) {
1494*fcf5ef2aSThomas Huth         target &= 0xffffffffULL;
1495*fcf5ef2aSThomas Huth     }
1496*fcf5ef2aSThomas Huth #endif
1497*fcf5ef2aSThomas Huth     if (cond == 0x0) {
1498*fcf5ef2aSThomas Huth         /* unconditional not taken */
1499*fcf5ef2aSThomas Huth         if (a) {
1500*fcf5ef2aSThomas Huth             dc->pc = dc->npc + 4;
1501*fcf5ef2aSThomas Huth             dc->npc = dc->pc + 4;
1502*fcf5ef2aSThomas Huth         } else {
1503*fcf5ef2aSThomas Huth             dc->pc = dc->npc;
1504*fcf5ef2aSThomas Huth             dc->npc = dc->pc + 4;
1505*fcf5ef2aSThomas Huth         }
1506*fcf5ef2aSThomas Huth     } else if (cond == 0x8) {
1507*fcf5ef2aSThomas Huth         /* unconditional taken */
1508*fcf5ef2aSThomas Huth         if (a) {
1509*fcf5ef2aSThomas Huth             dc->pc = target;
1510*fcf5ef2aSThomas Huth             dc->npc = dc->pc + 4;
1511*fcf5ef2aSThomas Huth         } else {
1512*fcf5ef2aSThomas Huth             dc->pc = dc->npc;
1513*fcf5ef2aSThomas Huth             dc->npc = target;
1514*fcf5ef2aSThomas Huth             tcg_gen_mov_tl(cpu_pc, cpu_npc);
1515*fcf5ef2aSThomas Huth         }
1516*fcf5ef2aSThomas Huth     } else {
1517*fcf5ef2aSThomas Huth         flush_cond(dc);
1518*fcf5ef2aSThomas Huth         gen_fcond(cpu_cond, cc, cond);
1519*fcf5ef2aSThomas Huth         if (a) {
1520*fcf5ef2aSThomas Huth             gen_branch_a(dc, target);
1521*fcf5ef2aSThomas Huth         } else {
1522*fcf5ef2aSThomas Huth             gen_branch_n(dc, target);
1523*fcf5ef2aSThomas Huth         }
1524*fcf5ef2aSThomas Huth     }
1525*fcf5ef2aSThomas Huth }
1526*fcf5ef2aSThomas Huth 
1527*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1528*fcf5ef2aSThomas Huth static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn,
1529*fcf5ef2aSThomas Huth                           TCGv r_reg)
1530*fcf5ef2aSThomas Huth {
1531*fcf5ef2aSThomas Huth     unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29));
1532*fcf5ef2aSThomas Huth     target_ulong target = dc->pc + offset;
1533*fcf5ef2aSThomas Huth 
1534*fcf5ef2aSThomas Huth     if (unlikely(AM_CHECK(dc))) {
1535*fcf5ef2aSThomas Huth         target &= 0xffffffffULL;
1536*fcf5ef2aSThomas Huth     }
1537*fcf5ef2aSThomas Huth     flush_cond(dc);
1538*fcf5ef2aSThomas Huth     gen_cond_reg(cpu_cond, cond, r_reg);
1539*fcf5ef2aSThomas Huth     if (a) {
1540*fcf5ef2aSThomas Huth         gen_branch_a(dc, target);
1541*fcf5ef2aSThomas Huth     } else {
1542*fcf5ef2aSThomas Huth         gen_branch_n(dc, target);
1543*fcf5ef2aSThomas Huth     }
1544*fcf5ef2aSThomas Huth }
1545*fcf5ef2aSThomas Huth 
1546*fcf5ef2aSThomas Huth static inline void gen_op_fcmps(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
1547*fcf5ef2aSThomas Huth {
1548*fcf5ef2aSThomas Huth     switch (fccno) {
1549*fcf5ef2aSThomas Huth     case 0:
1550*fcf5ef2aSThomas Huth         gen_helper_fcmps(cpu_fsr, cpu_env, r_rs1, r_rs2);
1551*fcf5ef2aSThomas Huth         break;
1552*fcf5ef2aSThomas Huth     case 1:
1553*fcf5ef2aSThomas Huth         gen_helper_fcmps_fcc1(cpu_fsr, cpu_env, r_rs1, r_rs2);
1554*fcf5ef2aSThomas Huth         break;
1555*fcf5ef2aSThomas Huth     case 2:
1556*fcf5ef2aSThomas Huth         gen_helper_fcmps_fcc2(cpu_fsr, cpu_env, r_rs1, r_rs2);
1557*fcf5ef2aSThomas Huth         break;
1558*fcf5ef2aSThomas Huth     case 3:
1559*fcf5ef2aSThomas Huth         gen_helper_fcmps_fcc3(cpu_fsr, cpu_env, r_rs1, r_rs2);
1560*fcf5ef2aSThomas Huth         break;
1561*fcf5ef2aSThomas Huth     }
1562*fcf5ef2aSThomas Huth }
1563*fcf5ef2aSThomas Huth 
1564*fcf5ef2aSThomas Huth static inline void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1565*fcf5ef2aSThomas Huth {
1566*fcf5ef2aSThomas Huth     switch (fccno) {
1567*fcf5ef2aSThomas Huth     case 0:
1568*fcf5ef2aSThomas Huth         gen_helper_fcmpd(cpu_fsr, cpu_env, r_rs1, r_rs2);
1569*fcf5ef2aSThomas Huth         break;
1570*fcf5ef2aSThomas Huth     case 1:
1571*fcf5ef2aSThomas Huth         gen_helper_fcmpd_fcc1(cpu_fsr, cpu_env, r_rs1, r_rs2);
1572*fcf5ef2aSThomas Huth         break;
1573*fcf5ef2aSThomas Huth     case 2:
1574*fcf5ef2aSThomas Huth         gen_helper_fcmpd_fcc2(cpu_fsr, cpu_env, r_rs1, r_rs2);
1575*fcf5ef2aSThomas Huth         break;
1576*fcf5ef2aSThomas Huth     case 3:
1577*fcf5ef2aSThomas Huth         gen_helper_fcmpd_fcc3(cpu_fsr, cpu_env, r_rs1, r_rs2);
1578*fcf5ef2aSThomas Huth         break;
1579*fcf5ef2aSThomas Huth     }
1580*fcf5ef2aSThomas Huth }
1581*fcf5ef2aSThomas Huth 
1582*fcf5ef2aSThomas Huth static inline void gen_op_fcmpq(int fccno)
1583*fcf5ef2aSThomas Huth {
1584*fcf5ef2aSThomas Huth     switch (fccno) {
1585*fcf5ef2aSThomas Huth     case 0:
1586*fcf5ef2aSThomas Huth         gen_helper_fcmpq(cpu_fsr, cpu_env);
1587*fcf5ef2aSThomas Huth         break;
1588*fcf5ef2aSThomas Huth     case 1:
1589*fcf5ef2aSThomas Huth         gen_helper_fcmpq_fcc1(cpu_fsr, cpu_env);
1590*fcf5ef2aSThomas Huth         break;
1591*fcf5ef2aSThomas Huth     case 2:
1592*fcf5ef2aSThomas Huth         gen_helper_fcmpq_fcc2(cpu_fsr, cpu_env);
1593*fcf5ef2aSThomas Huth         break;
1594*fcf5ef2aSThomas Huth     case 3:
1595*fcf5ef2aSThomas Huth         gen_helper_fcmpq_fcc3(cpu_fsr, cpu_env);
1596*fcf5ef2aSThomas Huth         break;
1597*fcf5ef2aSThomas Huth     }
1598*fcf5ef2aSThomas Huth }
1599*fcf5ef2aSThomas Huth 
1600*fcf5ef2aSThomas Huth static inline void gen_op_fcmpes(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
1601*fcf5ef2aSThomas Huth {
1602*fcf5ef2aSThomas Huth     switch (fccno) {
1603*fcf5ef2aSThomas Huth     case 0:
1604*fcf5ef2aSThomas Huth         gen_helper_fcmpes(cpu_fsr, cpu_env, r_rs1, r_rs2);
1605*fcf5ef2aSThomas Huth         break;
1606*fcf5ef2aSThomas Huth     case 1:
1607*fcf5ef2aSThomas Huth         gen_helper_fcmpes_fcc1(cpu_fsr, cpu_env, r_rs1, r_rs2);
1608*fcf5ef2aSThomas Huth         break;
1609*fcf5ef2aSThomas Huth     case 2:
1610*fcf5ef2aSThomas Huth         gen_helper_fcmpes_fcc2(cpu_fsr, cpu_env, r_rs1, r_rs2);
1611*fcf5ef2aSThomas Huth         break;
1612*fcf5ef2aSThomas Huth     case 3:
1613*fcf5ef2aSThomas Huth         gen_helper_fcmpes_fcc3(cpu_fsr, cpu_env, r_rs1, r_rs2);
1614*fcf5ef2aSThomas Huth         break;
1615*fcf5ef2aSThomas Huth     }
1616*fcf5ef2aSThomas Huth }
1617*fcf5ef2aSThomas Huth 
1618*fcf5ef2aSThomas Huth static inline void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1619*fcf5ef2aSThomas Huth {
1620*fcf5ef2aSThomas Huth     switch (fccno) {
1621*fcf5ef2aSThomas Huth     case 0:
1622*fcf5ef2aSThomas Huth         gen_helper_fcmped(cpu_fsr, cpu_env, r_rs1, r_rs2);
1623*fcf5ef2aSThomas Huth         break;
1624*fcf5ef2aSThomas Huth     case 1:
1625*fcf5ef2aSThomas Huth         gen_helper_fcmped_fcc1(cpu_fsr, cpu_env, r_rs1, r_rs2);
1626*fcf5ef2aSThomas Huth         break;
1627*fcf5ef2aSThomas Huth     case 2:
1628*fcf5ef2aSThomas Huth         gen_helper_fcmped_fcc2(cpu_fsr, cpu_env, r_rs1, r_rs2);
1629*fcf5ef2aSThomas Huth         break;
1630*fcf5ef2aSThomas Huth     case 3:
1631*fcf5ef2aSThomas Huth         gen_helper_fcmped_fcc3(cpu_fsr, cpu_env, r_rs1, r_rs2);
1632*fcf5ef2aSThomas Huth         break;
1633*fcf5ef2aSThomas Huth     }
1634*fcf5ef2aSThomas Huth }
1635*fcf5ef2aSThomas Huth 
1636*fcf5ef2aSThomas Huth static inline void gen_op_fcmpeq(int fccno)
1637*fcf5ef2aSThomas Huth {
1638*fcf5ef2aSThomas Huth     switch (fccno) {
1639*fcf5ef2aSThomas Huth     case 0:
1640*fcf5ef2aSThomas Huth         gen_helper_fcmpeq(cpu_fsr, cpu_env);
1641*fcf5ef2aSThomas Huth         break;
1642*fcf5ef2aSThomas Huth     case 1:
1643*fcf5ef2aSThomas Huth         gen_helper_fcmpeq_fcc1(cpu_fsr, cpu_env);
1644*fcf5ef2aSThomas Huth         break;
1645*fcf5ef2aSThomas Huth     case 2:
1646*fcf5ef2aSThomas Huth         gen_helper_fcmpeq_fcc2(cpu_fsr, cpu_env);
1647*fcf5ef2aSThomas Huth         break;
1648*fcf5ef2aSThomas Huth     case 3:
1649*fcf5ef2aSThomas Huth         gen_helper_fcmpeq_fcc3(cpu_fsr, cpu_env);
1650*fcf5ef2aSThomas Huth         break;
1651*fcf5ef2aSThomas Huth     }
1652*fcf5ef2aSThomas Huth }
1653*fcf5ef2aSThomas Huth 
1654*fcf5ef2aSThomas Huth #else
1655*fcf5ef2aSThomas Huth 
1656*fcf5ef2aSThomas Huth static inline void gen_op_fcmps(int fccno, TCGv r_rs1, TCGv r_rs2)
1657*fcf5ef2aSThomas Huth {
1658*fcf5ef2aSThomas Huth     gen_helper_fcmps(cpu_fsr, cpu_env, r_rs1, r_rs2);
1659*fcf5ef2aSThomas Huth }
1660*fcf5ef2aSThomas Huth 
1661*fcf5ef2aSThomas Huth static inline void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1662*fcf5ef2aSThomas Huth {
1663*fcf5ef2aSThomas Huth     gen_helper_fcmpd(cpu_fsr, cpu_env, r_rs1, r_rs2);
1664*fcf5ef2aSThomas Huth }
1665*fcf5ef2aSThomas Huth 
1666*fcf5ef2aSThomas Huth static inline void gen_op_fcmpq(int fccno)
1667*fcf5ef2aSThomas Huth {
1668*fcf5ef2aSThomas Huth     gen_helper_fcmpq(cpu_fsr, cpu_env);
1669*fcf5ef2aSThomas Huth }
1670*fcf5ef2aSThomas Huth 
1671*fcf5ef2aSThomas Huth static inline void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2)
1672*fcf5ef2aSThomas Huth {
1673*fcf5ef2aSThomas Huth     gen_helper_fcmpes(cpu_fsr, cpu_env, r_rs1, r_rs2);
1674*fcf5ef2aSThomas Huth }
1675*fcf5ef2aSThomas Huth 
1676*fcf5ef2aSThomas Huth static inline void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1677*fcf5ef2aSThomas Huth {
1678*fcf5ef2aSThomas Huth     gen_helper_fcmped(cpu_fsr, cpu_env, r_rs1, r_rs2);
1679*fcf5ef2aSThomas Huth }
1680*fcf5ef2aSThomas Huth 
1681*fcf5ef2aSThomas Huth static inline void gen_op_fcmpeq(int fccno)
1682*fcf5ef2aSThomas Huth {
1683*fcf5ef2aSThomas Huth     gen_helper_fcmpeq(cpu_fsr, cpu_env);
1684*fcf5ef2aSThomas Huth }
1685*fcf5ef2aSThomas Huth #endif
1686*fcf5ef2aSThomas Huth 
1687*fcf5ef2aSThomas Huth static void gen_op_fpexception_im(DisasContext *dc, int fsr_flags)
1688*fcf5ef2aSThomas Huth {
1689*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_NMASK);
1690*fcf5ef2aSThomas Huth     tcg_gen_ori_tl(cpu_fsr, cpu_fsr, fsr_flags);
1691*fcf5ef2aSThomas Huth     gen_exception(dc, TT_FP_EXCP);
1692*fcf5ef2aSThomas Huth }
1693*fcf5ef2aSThomas Huth 
1694*fcf5ef2aSThomas Huth static int gen_trap_ifnofpu(DisasContext *dc)
1695*fcf5ef2aSThomas Huth {
1696*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY)
1697*fcf5ef2aSThomas Huth     if (!dc->fpu_enabled) {
1698*fcf5ef2aSThomas Huth         gen_exception(dc, TT_NFPU_INSN);
1699*fcf5ef2aSThomas Huth         return 1;
1700*fcf5ef2aSThomas Huth     }
1701*fcf5ef2aSThomas Huth #endif
1702*fcf5ef2aSThomas Huth     return 0;
1703*fcf5ef2aSThomas Huth }
1704*fcf5ef2aSThomas Huth 
1705*fcf5ef2aSThomas Huth static inline void gen_op_clear_ieee_excp_and_FTT(void)
1706*fcf5ef2aSThomas Huth {
1707*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_CEXC_NMASK);
1708*fcf5ef2aSThomas Huth }
1709*fcf5ef2aSThomas Huth 
1710*fcf5ef2aSThomas Huth static inline void gen_fop_FF(DisasContext *dc, int rd, int rs,
1711*fcf5ef2aSThomas Huth                               void (*gen)(TCGv_i32, TCGv_ptr, TCGv_i32))
1712*fcf5ef2aSThomas Huth {
1713*fcf5ef2aSThomas Huth     TCGv_i32 dst, src;
1714*fcf5ef2aSThomas Huth 
1715*fcf5ef2aSThomas Huth     src = gen_load_fpr_F(dc, rs);
1716*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_F(dc);
1717*fcf5ef2aSThomas Huth 
1718*fcf5ef2aSThomas Huth     gen(dst, cpu_env, src);
1719*fcf5ef2aSThomas Huth     gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
1720*fcf5ef2aSThomas Huth 
1721*fcf5ef2aSThomas Huth     gen_store_fpr_F(dc, rd, dst);
1722*fcf5ef2aSThomas Huth }
1723*fcf5ef2aSThomas Huth 
1724*fcf5ef2aSThomas Huth static inline void gen_ne_fop_FF(DisasContext *dc, int rd, int rs,
1725*fcf5ef2aSThomas Huth                                  void (*gen)(TCGv_i32, TCGv_i32))
1726*fcf5ef2aSThomas Huth {
1727*fcf5ef2aSThomas Huth     TCGv_i32 dst, src;
1728*fcf5ef2aSThomas Huth 
1729*fcf5ef2aSThomas Huth     src = gen_load_fpr_F(dc, rs);
1730*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_F(dc);
1731*fcf5ef2aSThomas Huth 
1732*fcf5ef2aSThomas Huth     gen(dst, src);
1733*fcf5ef2aSThomas Huth 
1734*fcf5ef2aSThomas Huth     gen_store_fpr_F(dc, rd, dst);
1735*fcf5ef2aSThomas Huth }
1736*fcf5ef2aSThomas Huth 
1737*fcf5ef2aSThomas Huth static inline void gen_fop_FFF(DisasContext *dc, int rd, int rs1, int rs2,
1738*fcf5ef2aSThomas Huth                         void (*gen)(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32))
1739*fcf5ef2aSThomas Huth {
1740*fcf5ef2aSThomas Huth     TCGv_i32 dst, src1, src2;
1741*fcf5ef2aSThomas Huth 
1742*fcf5ef2aSThomas Huth     src1 = gen_load_fpr_F(dc, rs1);
1743*fcf5ef2aSThomas Huth     src2 = gen_load_fpr_F(dc, rs2);
1744*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_F(dc);
1745*fcf5ef2aSThomas Huth 
1746*fcf5ef2aSThomas Huth     gen(dst, cpu_env, src1, src2);
1747*fcf5ef2aSThomas Huth     gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
1748*fcf5ef2aSThomas Huth 
1749*fcf5ef2aSThomas Huth     gen_store_fpr_F(dc, rd, dst);
1750*fcf5ef2aSThomas Huth }
1751*fcf5ef2aSThomas Huth 
1752*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1753*fcf5ef2aSThomas Huth static inline void gen_ne_fop_FFF(DisasContext *dc, int rd, int rs1, int rs2,
1754*fcf5ef2aSThomas Huth                                   void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
1755*fcf5ef2aSThomas Huth {
1756*fcf5ef2aSThomas Huth     TCGv_i32 dst, src1, src2;
1757*fcf5ef2aSThomas Huth 
1758*fcf5ef2aSThomas Huth     src1 = gen_load_fpr_F(dc, rs1);
1759*fcf5ef2aSThomas Huth     src2 = gen_load_fpr_F(dc, rs2);
1760*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_F(dc);
1761*fcf5ef2aSThomas Huth 
1762*fcf5ef2aSThomas Huth     gen(dst, src1, src2);
1763*fcf5ef2aSThomas Huth 
1764*fcf5ef2aSThomas Huth     gen_store_fpr_F(dc, rd, dst);
1765*fcf5ef2aSThomas Huth }
1766*fcf5ef2aSThomas Huth #endif
1767*fcf5ef2aSThomas Huth 
1768*fcf5ef2aSThomas Huth static inline void gen_fop_DD(DisasContext *dc, int rd, int rs,
1769*fcf5ef2aSThomas Huth                               void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i64))
1770*fcf5ef2aSThomas Huth {
1771*fcf5ef2aSThomas Huth     TCGv_i64 dst, src;
1772*fcf5ef2aSThomas Huth 
1773*fcf5ef2aSThomas Huth     src = gen_load_fpr_D(dc, rs);
1774*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_D(dc, rd);
1775*fcf5ef2aSThomas Huth 
1776*fcf5ef2aSThomas Huth     gen(dst, cpu_env, src);
1777*fcf5ef2aSThomas Huth     gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
1778*fcf5ef2aSThomas Huth 
1779*fcf5ef2aSThomas Huth     gen_store_fpr_D(dc, rd, dst);
1780*fcf5ef2aSThomas Huth }
1781*fcf5ef2aSThomas Huth 
1782*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1783*fcf5ef2aSThomas Huth static inline void gen_ne_fop_DD(DisasContext *dc, int rd, int rs,
1784*fcf5ef2aSThomas Huth                                  void (*gen)(TCGv_i64, TCGv_i64))
1785*fcf5ef2aSThomas Huth {
1786*fcf5ef2aSThomas Huth     TCGv_i64 dst, src;
1787*fcf5ef2aSThomas Huth 
1788*fcf5ef2aSThomas Huth     src = gen_load_fpr_D(dc, rs);
1789*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_D(dc, rd);
1790*fcf5ef2aSThomas Huth 
1791*fcf5ef2aSThomas Huth     gen(dst, src);
1792*fcf5ef2aSThomas Huth 
1793*fcf5ef2aSThomas Huth     gen_store_fpr_D(dc, rd, dst);
1794*fcf5ef2aSThomas Huth }
1795*fcf5ef2aSThomas Huth #endif
1796*fcf5ef2aSThomas Huth 
1797*fcf5ef2aSThomas Huth static inline void gen_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2,
1798*fcf5ef2aSThomas Huth                         void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64))
1799*fcf5ef2aSThomas Huth {
1800*fcf5ef2aSThomas Huth     TCGv_i64 dst, src1, src2;
1801*fcf5ef2aSThomas Huth 
1802*fcf5ef2aSThomas Huth     src1 = gen_load_fpr_D(dc, rs1);
1803*fcf5ef2aSThomas Huth     src2 = gen_load_fpr_D(dc, rs2);
1804*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_D(dc, rd);
1805*fcf5ef2aSThomas Huth 
1806*fcf5ef2aSThomas Huth     gen(dst, cpu_env, src1, src2);
1807*fcf5ef2aSThomas Huth     gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
1808*fcf5ef2aSThomas Huth 
1809*fcf5ef2aSThomas Huth     gen_store_fpr_D(dc, rd, dst);
1810*fcf5ef2aSThomas Huth }
1811*fcf5ef2aSThomas Huth 
1812*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1813*fcf5ef2aSThomas Huth static inline void gen_ne_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2,
1814*fcf5ef2aSThomas Huth                                   void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64))
1815*fcf5ef2aSThomas Huth {
1816*fcf5ef2aSThomas Huth     TCGv_i64 dst, src1, src2;
1817*fcf5ef2aSThomas Huth 
1818*fcf5ef2aSThomas Huth     src1 = gen_load_fpr_D(dc, rs1);
1819*fcf5ef2aSThomas Huth     src2 = gen_load_fpr_D(dc, rs2);
1820*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_D(dc, rd);
1821*fcf5ef2aSThomas Huth 
1822*fcf5ef2aSThomas Huth     gen(dst, src1, src2);
1823*fcf5ef2aSThomas Huth 
1824*fcf5ef2aSThomas Huth     gen_store_fpr_D(dc, rd, dst);
1825*fcf5ef2aSThomas Huth }
1826*fcf5ef2aSThomas Huth 
1827*fcf5ef2aSThomas Huth static inline void gen_gsr_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2,
1828*fcf5ef2aSThomas Huth                            void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
1829*fcf5ef2aSThomas Huth {
1830*fcf5ef2aSThomas Huth     TCGv_i64 dst, src1, src2;
1831*fcf5ef2aSThomas Huth 
1832*fcf5ef2aSThomas Huth     src1 = gen_load_fpr_D(dc, rs1);
1833*fcf5ef2aSThomas Huth     src2 = gen_load_fpr_D(dc, rs2);
1834*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_D(dc, rd);
1835*fcf5ef2aSThomas Huth 
1836*fcf5ef2aSThomas Huth     gen(dst, cpu_gsr, src1, src2);
1837*fcf5ef2aSThomas Huth 
1838*fcf5ef2aSThomas Huth     gen_store_fpr_D(dc, rd, dst);
1839*fcf5ef2aSThomas Huth }
1840*fcf5ef2aSThomas Huth 
1841*fcf5ef2aSThomas Huth static inline void gen_ne_fop_DDDD(DisasContext *dc, int rd, int rs1, int rs2,
1842*fcf5ef2aSThomas Huth                            void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
1843*fcf5ef2aSThomas Huth {
1844*fcf5ef2aSThomas Huth     TCGv_i64 dst, src0, src1, src2;
1845*fcf5ef2aSThomas Huth 
1846*fcf5ef2aSThomas Huth     src1 = gen_load_fpr_D(dc, rs1);
1847*fcf5ef2aSThomas Huth     src2 = gen_load_fpr_D(dc, rs2);
1848*fcf5ef2aSThomas Huth     src0 = gen_load_fpr_D(dc, rd);
1849*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_D(dc, rd);
1850*fcf5ef2aSThomas Huth 
1851*fcf5ef2aSThomas Huth     gen(dst, src0, src1, src2);
1852*fcf5ef2aSThomas Huth 
1853*fcf5ef2aSThomas Huth     gen_store_fpr_D(dc, rd, dst);
1854*fcf5ef2aSThomas Huth }
1855*fcf5ef2aSThomas Huth #endif
1856*fcf5ef2aSThomas Huth 
1857*fcf5ef2aSThomas Huth static inline void gen_fop_QQ(DisasContext *dc, int rd, int rs,
1858*fcf5ef2aSThomas Huth                               void (*gen)(TCGv_ptr))
1859*fcf5ef2aSThomas Huth {
1860*fcf5ef2aSThomas Huth     gen_op_load_fpr_QT1(QFPREG(rs));
1861*fcf5ef2aSThomas Huth 
1862*fcf5ef2aSThomas Huth     gen(cpu_env);
1863*fcf5ef2aSThomas Huth     gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
1864*fcf5ef2aSThomas Huth 
1865*fcf5ef2aSThomas Huth     gen_op_store_QT0_fpr(QFPREG(rd));
1866*fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, QFPREG(rd));
1867*fcf5ef2aSThomas Huth }
1868*fcf5ef2aSThomas Huth 
1869*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1870*fcf5ef2aSThomas Huth static inline void gen_ne_fop_QQ(DisasContext *dc, int rd, int rs,
1871*fcf5ef2aSThomas Huth                                  void (*gen)(TCGv_ptr))
1872*fcf5ef2aSThomas Huth {
1873*fcf5ef2aSThomas Huth     gen_op_load_fpr_QT1(QFPREG(rs));
1874*fcf5ef2aSThomas Huth 
1875*fcf5ef2aSThomas Huth     gen(cpu_env);
1876*fcf5ef2aSThomas Huth 
1877*fcf5ef2aSThomas Huth     gen_op_store_QT0_fpr(QFPREG(rd));
1878*fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, QFPREG(rd));
1879*fcf5ef2aSThomas Huth }
1880*fcf5ef2aSThomas Huth #endif
1881*fcf5ef2aSThomas Huth 
1882*fcf5ef2aSThomas Huth static inline void gen_fop_QQQ(DisasContext *dc, int rd, int rs1, int rs2,
1883*fcf5ef2aSThomas Huth                                void (*gen)(TCGv_ptr))
1884*fcf5ef2aSThomas Huth {
1885*fcf5ef2aSThomas Huth     gen_op_load_fpr_QT0(QFPREG(rs1));
1886*fcf5ef2aSThomas Huth     gen_op_load_fpr_QT1(QFPREG(rs2));
1887*fcf5ef2aSThomas Huth 
1888*fcf5ef2aSThomas Huth     gen(cpu_env);
1889*fcf5ef2aSThomas Huth     gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
1890*fcf5ef2aSThomas Huth 
1891*fcf5ef2aSThomas Huth     gen_op_store_QT0_fpr(QFPREG(rd));
1892*fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, QFPREG(rd));
1893*fcf5ef2aSThomas Huth }
1894*fcf5ef2aSThomas Huth 
1895*fcf5ef2aSThomas Huth static inline void gen_fop_DFF(DisasContext *dc, int rd, int rs1, int rs2,
1896*fcf5ef2aSThomas Huth                         void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i32, TCGv_i32))
1897*fcf5ef2aSThomas Huth {
1898*fcf5ef2aSThomas Huth     TCGv_i64 dst;
1899*fcf5ef2aSThomas Huth     TCGv_i32 src1, src2;
1900*fcf5ef2aSThomas Huth 
1901*fcf5ef2aSThomas Huth     src1 = gen_load_fpr_F(dc, rs1);
1902*fcf5ef2aSThomas Huth     src2 = gen_load_fpr_F(dc, rs2);
1903*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_D(dc, rd);
1904*fcf5ef2aSThomas Huth 
1905*fcf5ef2aSThomas Huth     gen(dst, cpu_env, src1, src2);
1906*fcf5ef2aSThomas Huth     gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
1907*fcf5ef2aSThomas Huth 
1908*fcf5ef2aSThomas Huth     gen_store_fpr_D(dc, rd, dst);
1909*fcf5ef2aSThomas Huth }
1910*fcf5ef2aSThomas Huth 
1911*fcf5ef2aSThomas Huth static inline void gen_fop_QDD(DisasContext *dc, int rd, int rs1, int rs2,
1912*fcf5ef2aSThomas Huth                                void (*gen)(TCGv_ptr, TCGv_i64, TCGv_i64))
1913*fcf5ef2aSThomas Huth {
1914*fcf5ef2aSThomas Huth     TCGv_i64 src1, src2;
1915*fcf5ef2aSThomas Huth 
1916*fcf5ef2aSThomas Huth     src1 = gen_load_fpr_D(dc, rs1);
1917*fcf5ef2aSThomas Huth     src2 = gen_load_fpr_D(dc, rs2);
1918*fcf5ef2aSThomas Huth 
1919*fcf5ef2aSThomas Huth     gen(cpu_env, src1, src2);
1920*fcf5ef2aSThomas Huth     gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
1921*fcf5ef2aSThomas Huth 
1922*fcf5ef2aSThomas Huth     gen_op_store_QT0_fpr(QFPREG(rd));
1923*fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, QFPREG(rd));
1924*fcf5ef2aSThomas Huth }
1925*fcf5ef2aSThomas Huth 
1926*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1927*fcf5ef2aSThomas Huth static inline void gen_fop_DF(DisasContext *dc, int rd, int rs,
1928*fcf5ef2aSThomas Huth                               void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i32))
1929*fcf5ef2aSThomas Huth {
1930*fcf5ef2aSThomas Huth     TCGv_i64 dst;
1931*fcf5ef2aSThomas Huth     TCGv_i32 src;
1932*fcf5ef2aSThomas Huth 
1933*fcf5ef2aSThomas Huth     src = gen_load_fpr_F(dc, rs);
1934*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_D(dc, rd);
1935*fcf5ef2aSThomas Huth 
1936*fcf5ef2aSThomas Huth     gen(dst, cpu_env, src);
1937*fcf5ef2aSThomas Huth     gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
1938*fcf5ef2aSThomas Huth 
1939*fcf5ef2aSThomas Huth     gen_store_fpr_D(dc, rd, dst);
1940*fcf5ef2aSThomas Huth }
1941*fcf5ef2aSThomas Huth #endif
1942*fcf5ef2aSThomas Huth 
1943*fcf5ef2aSThomas Huth static inline void gen_ne_fop_DF(DisasContext *dc, int rd, int rs,
1944*fcf5ef2aSThomas Huth                                  void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i32))
1945*fcf5ef2aSThomas Huth {
1946*fcf5ef2aSThomas Huth     TCGv_i64 dst;
1947*fcf5ef2aSThomas Huth     TCGv_i32 src;
1948*fcf5ef2aSThomas Huth 
1949*fcf5ef2aSThomas Huth     src = gen_load_fpr_F(dc, rs);
1950*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_D(dc, rd);
1951*fcf5ef2aSThomas Huth 
1952*fcf5ef2aSThomas Huth     gen(dst, cpu_env, src);
1953*fcf5ef2aSThomas Huth 
1954*fcf5ef2aSThomas Huth     gen_store_fpr_D(dc, rd, dst);
1955*fcf5ef2aSThomas Huth }
1956*fcf5ef2aSThomas Huth 
1957*fcf5ef2aSThomas Huth static inline void gen_fop_FD(DisasContext *dc, int rd, int rs,
1958*fcf5ef2aSThomas Huth                               void (*gen)(TCGv_i32, TCGv_ptr, TCGv_i64))
1959*fcf5ef2aSThomas Huth {
1960*fcf5ef2aSThomas Huth     TCGv_i32 dst;
1961*fcf5ef2aSThomas Huth     TCGv_i64 src;
1962*fcf5ef2aSThomas Huth 
1963*fcf5ef2aSThomas Huth     src = gen_load_fpr_D(dc, rs);
1964*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_F(dc);
1965*fcf5ef2aSThomas Huth 
1966*fcf5ef2aSThomas Huth     gen(dst, cpu_env, src);
1967*fcf5ef2aSThomas Huth     gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
1968*fcf5ef2aSThomas Huth 
1969*fcf5ef2aSThomas Huth     gen_store_fpr_F(dc, rd, dst);
1970*fcf5ef2aSThomas Huth }
1971*fcf5ef2aSThomas Huth 
1972*fcf5ef2aSThomas Huth static inline void gen_fop_FQ(DisasContext *dc, int rd, int rs,
1973*fcf5ef2aSThomas Huth                               void (*gen)(TCGv_i32, TCGv_ptr))
1974*fcf5ef2aSThomas Huth {
1975*fcf5ef2aSThomas Huth     TCGv_i32 dst;
1976*fcf5ef2aSThomas Huth 
1977*fcf5ef2aSThomas Huth     gen_op_load_fpr_QT1(QFPREG(rs));
1978*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_F(dc);
1979*fcf5ef2aSThomas Huth 
1980*fcf5ef2aSThomas Huth     gen(dst, cpu_env);
1981*fcf5ef2aSThomas Huth     gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
1982*fcf5ef2aSThomas Huth 
1983*fcf5ef2aSThomas Huth     gen_store_fpr_F(dc, rd, dst);
1984*fcf5ef2aSThomas Huth }
1985*fcf5ef2aSThomas Huth 
1986*fcf5ef2aSThomas Huth static inline void gen_fop_DQ(DisasContext *dc, int rd, int rs,
1987*fcf5ef2aSThomas Huth                               void (*gen)(TCGv_i64, TCGv_ptr))
1988*fcf5ef2aSThomas Huth {
1989*fcf5ef2aSThomas Huth     TCGv_i64 dst;
1990*fcf5ef2aSThomas Huth 
1991*fcf5ef2aSThomas Huth     gen_op_load_fpr_QT1(QFPREG(rs));
1992*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_D(dc, rd);
1993*fcf5ef2aSThomas Huth 
1994*fcf5ef2aSThomas Huth     gen(dst, cpu_env);
1995*fcf5ef2aSThomas Huth     gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
1996*fcf5ef2aSThomas Huth 
1997*fcf5ef2aSThomas Huth     gen_store_fpr_D(dc, rd, dst);
1998*fcf5ef2aSThomas Huth }
1999*fcf5ef2aSThomas Huth 
2000*fcf5ef2aSThomas Huth static inline void gen_ne_fop_QF(DisasContext *dc, int rd, int rs,
2001*fcf5ef2aSThomas Huth                                  void (*gen)(TCGv_ptr, TCGv_i32))
2002*fcf5ef2aSThomas Huth {
2003*fcf5ef2aSThomas Huth     TCGv_i32 src;
2004*fcf5ef2aSThomas Huth 
2005*fcf5ef2aSThomas Huth     src = gen_load_fpr_F(dc, rs);
2006*fcf5ef2aSThomas Huth 
2007*fcf5ef2aSThomas Huth     gen(cpu_env, src);
2008*fcf5ef2aSThomas Huth 
2009*fcf5ef2aSThomas Huth     gen_op_store_QT0_fpr(QFPREG(rd));
2010*fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, QFPREG(rd));
2011*fcf5ef2aSThomas Huth }
2012*fcf5ef2aSThomas Huth 
2013*fcf5ef2aSThomas Huth static inline void gen_ne_fop_QD(DisasContext *dc, int rd, int rs,
2014*fcf5ef2aSThomas Huth                                  void (*gen)(TCGv_ptr, TCGv_i64))
2015*fcf5ef2aSThomas Huth {
2016*fcf5ef2aSThomas Huth     TCGv_i64 src;
2017*fcf5ef2aSThomas Huth 
2018*fcf5ef2aSThomas Huth     src = gen_load_fpr_D(dc, rs);
2019*fcf5ef2aSThomas Huth 
2020*fcf5ef2aSThomas Huth     gen(cpu_env, src);
2021*fcf5ef2aSThomas Huth 
2022*fcf5ef2aSThomas Huth     gen_op_store_QT0_fpr(QFPREG(rd));
2023*fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, QFPREG(rd));
2024*fcf5ef2aSThomas Huth }
2025*fcf5ef2aSThomas Huth 
2026*fcf5ef2aSThomas Huth static void gen_swap(DisasContext *dc, TCGv dst, TCGv src,
2027*fcf5ef2aSThomas Huth                      TCGv addr, int mmu_idx, TCGMemOp memop)
2028*fcf5ef2aSThomas Huth {
2029*fcf5ef2aSThomas Huth     gen_address_mask(dc, addr);
2030*fcf5ef2aSThomas Huth     tcg_gen_atomic_xchg_tl(dst, addr, src, mmu_idx, memop);
2031*fcf5ef2aSThomas Huth }
2032*fcf5ef2aSThomas Huth 
2033*fcf5ef2aSThomas Huth static void gen_ldstub(DisasContext *dc, TCGv dst, TCGv addr, int mmu_idx)
2034*fcf5ef2aSThomas Huth {
2035*fcf5ef2aSThomas Huth     TCGv m1 = tcg_const_tl(0xff);
2036*fcf5ef2aSThomas Huth     gen_address_mask(dc, addr);
2037*fcf5ef2aSThomas Huth     tcg_gen_atomic_xchg_tl(dst, addr, m1, mmu_idx, MO_UB);
2038*fcf5ef2aSThomas Huth     tcg_temp_free(m1);
2039*fcf5ef2aSThomas Huth }
2040*fcf5ef2aSThomas Huth 
2041*fcf5ef2aSThomas Huth /* asi moves */
2042*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2043*fcf5ef2aSThomas Huth typedef enum {
2044*fcf5ef2aSThomas Huth     GET_ASI_HELPER,
2045*fcf5ef2aSThomas Huth     GET_ASI_EXCP,
2046*fcf5ef2aSThomas Huth     GET_ASI_DIRECT,
2047*fcf5ef2aSThomas Huth     GET_ASI_DTWINX,
2048*fcf5ef2aSThomas Huth     GET_ASI_BLOCK,
2049*fcf5ef2aSThomas Huth     GET_ASI_SHORT,
2050*fcf5ef2aSThomas Huth     GET_ASI_BCOPY,
2051*fcf5ef2aSThomas Huth     GET_ASI_BFILL,
2052*fcf5ef2aSThomas Huth } ASIType;
2053*fcf5ef2aSThomas Huth 
2054*fcf5ef2aSThomas Huth typedef struct {
2055*fcf5ef2aSThomas Huth     ASIType type;
2056*fcf5ef2aSThomas Huth     int asi;
2057*fcf5ef2aSThomas Huth     int mem_idx;
2058*fcf5ef2aSThomas Huth     TCGMemOp memop;
2059*fcf5ef2aSThomas Huth } DisasASI;
2060*fcf5ef2aSThomas Huth 
2061*fcf5ef2aSThomas Huth static DisasASI get_asi(DisasContext *dc, int insn, TCGMemOp memop)
2062*fcf5ef2aSThomas Huth {
2063*fcf5ef2aSThomas Huth     int asi = GET_FIELD(insn, 19, 26);
2064*fcf5ef2aSThomas Huth     ASIType type = GET_ASI_HELPER;
2065*fcf5ef2aSThomas Huth     int mem_idx = dc->mem_idx;
2066*fcf5ef2aSThomas Huth 
2067*fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64
2068*fcf5ef2aSThomas Huth     /* Before v9, all asis are immediate and privileged.  */
2069*fcf5ef2aSThomas Huth     if (IS_IMM) {
2070*fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
2071*fcf5ef2aSThomas Huth         type = GET_ASI_EXCP;
2072*fcf5ef2aSThomas Huth     } else if (supervisor(dc)
2073*fcf5ef2aSThomas Huth                /* Note that LEON accepts ASI_USERDATA in user mode, for
2074*fcf5ef2aSThomas Huth                   use with CASA.  Also note that previous versions of
2075*fcf5ef2aSThomas Huth                   QEMU allowed (and old versions of gcc emitted) ASI_P
2076*fcf5ef2aSThomas Huth                   for LEON, which is incorrect.  */
2077*fcf5ef2aSThomas Huth                || (asi == ASI_USERDATA
2078*fcf5ef2aSThomas Huth                    && (dc->def->features & CPU_FEATURE_CASA))) {
2079*fcf5ef2aSThomas Huth         switch (asi) {
2080*fcf5ef2aSThomas Huth         case ASI_USERDATA:   /* User data access */
2081*fcf5ef2aSThomas Huth             mem_idx = MMU_USER_IDX;
2082*fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
2083*fcf5ef2aSThomas Huth             break;
2084*fcf5ef2aSThomas Huth         case ASI_KERNELDATA: /* Supervisor data access */
2085*fcf5ef2aSThomas Huth             mem_idx = MMU_KERNEL_IDX;
2086*fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
2087*fcf5ef2aSThomas Huth             break;
2088*fcf5ef2aSThomas Huth         case ASI_M_BYPASS:    /* MMU passthrough */
2089*fcf5ef2aSThomas Huth         case ASI_LEON_BYPASS: /* LEON MMU passthrough */
2090*fcf5ef2aSThomas Huth             mem_idx = MMU_PHYS_IDX;
2091*fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
2092*fcf5ef2aSThomas Huth             break;
2093*fcf5ef2aSThomas Huth         case ASI_M_BCOPY: /* Block copy, sta access */
2094*fcf5ef2aSThomas Huth             mem_idx = MMU_KERNEL_IDX;
2095*fcf5ef2aSThomas Huth             type = GET_ASI_BCOPY;
2096*fcf5ef2aSThomas Huth             break;
2097*fcf5ef2aSThomas Huth         case ASI_M_BFILL: /* Block fill, stda access */
2098*fcf5ef2aSThomas Huth             mem_idx = MMU_KERNEL_IDX;
2099*fcf5ef2aSThomas Huth             type = GET_ASI_BFILL;
2100*fcf5ef2aSThomas Huth             break;
2101*fcf5ef2aSThomas Huth         }
2102*fcf5ef2aSThomas Huth     } else {
2103*fcf5ef2aSThomas Huth         gen_exception(dc, TT_PRIV_INSN);
2104*fcf5ef2aSThomas Huth         type = GET_ASI_EXCP;
2105*fcf5ef2aSThomas Huth     }
2106*fcf5ef2aSThomas Huth #else
2107*fcf5ef2aSThomas Huth     if (IS_IMM) {
2108*fcf5ef2aSThomas Huth         asi = dc->asi;
2109*fcf5ef2aSThomas Huth     }
2110*fcf5ef2aSThomas Huth     /* With v9, all asis below 0x80 are privileged.  */
2111*fcf5ef2aSThomas Huth     /* ??? We ought to check cpu_has_hypervisor, but we didn't copy
2112*fcf5ef2aSThomas Huth        down that bit into DisasContext.  For the moment that's ok,
2113*fcf5ef2aSThomas Huth        since the direct implementations below doesn't have any ASIs
2114*fcf5ef2aSThomas Huth        in the restricted [0x30, 0x7f] range, and the check will be
2115*fcf5ef2aSThomas Huth        done properly in the helper.  */
2116*fcf5ef2aSThomas Huth     if (!supervisor(dc) && asi < 0x80) {
2117*fcf5ef2aSThomas Huth         gen_exception(dc, TT_PRIV_ACT);
2118*fcf5ef2aSThomas Huth         type = GET_ASI_EXCP;
2119*fcf5ef2aSThomas Huth     } else {
2120*fcf5ef2aSThomas Huth         switch (asi) {
2121*fcf5ef2aSThomas Huth         case ASI_REAL:      /* Bypass */
2122*fcf5ef2aSThomas Huth         case ASI_REAL_IO:   /* Bypass, non-cacheable */
2123*fcf5ef2aSThomas Huth         case ASI_REAL_L:    /* Bypass LE */
2124*fcf5ef2aSThomas Huth         case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
2125*fcf5ef2aSThomas Huth         case ASI_TWINX_REAL:   /* Real address, twinx */
2126*fcf5ef2aSThomas Huth         case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
2127*fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS:
2128*fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS_L:
2129*fcf5ef2aSThomas Huth             mem_idx = MMU_PHYS_IDX;
2130*fcf5ef2aSThomas Huth             break;
2131*fcf5ef2aSThomas Huth         case ASI_N:  /* Nucleus */
2132*fcf5ef2aSThomas Huth         case ASI_NL: /* Nucleus LE */
2133*fcf5ef2aSThomas Huth         case ASI_TWINX_N:
2134*fcf5ef2aSThomas Huth         case ASI_TWINX_NL:
2135*fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD:
2136*fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD_L:
2137*fcf5ef2aSThomas Huth             mem_idx = MMU_NUCLEUS_IDX;
2138*fcf5ef2aSThomas Huth             break;
2139*fcf5ef2aSThomas Huth         case ASI_AIUP:  /* As if user primary */
2140*fcf5ef2aSThomas Huth         case ASI_AIUPL: /* As if user primary LE */
2141*fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP:
2142*fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP_L:
2143*fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_4V:
2144*fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_L_4V:
2145*fcf5ef2aSThomas Huth         case ASI_BLK_AIUP:
2146*fcf5ef2aSThomas Huth         case ASI_BLK_AIUPL:
2147*fcf5ef2aSThomas Huth             mem_idx = MMU_USER_IDX;
2148*fcf5ef2aSThomas Huth             break;
2149*fcf5ef2aSThomas Huth         case ASI_AIUS:  /* As if user secondary */
2150*fcf5ef2aSThomas Huth         case ASI_AIUSL: /* As if user secondary LE */
2151*fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS:
2152*fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS_L:
2153*fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_4V:
2154*fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_L_4V:
2155*fcf5ef2aSThomas Huth         case ASI_BLK_AIUS:
2156*fcf5ef2aSThomas Huth         case ASI_BLK_AIUSL:
2157*fcf5ef2aSThomas Huth             mem_idx = MMU_USER_SECONDARY_IDX;
2158*fcf5ef2aSThomas Huth             break;
2159*fcf5ef2aSThomas Huth         case ASI_S:  /* Secondary */
2160*fcf5ef2aSThomas Huth         case ASI_SL: /* Secondary LE */
2161*fcf5ef2aSThomas Huth         case ASI_TWINX_S:
2162*fcf5ef2aSThomas Huth         case ASI_TWINX_SL:
2163*fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_S:
2164*fcf5ef2aSThomas Huth         case ASI_BLK_S:
2165*fcf5ef2aSThomas Huth         case ASI_BLK_SL:
2166*fcf5ef2aSThomas Huth         case ASI_FL8_S:
2167*fcf5ef2aSThomas Huth         case ASI_FL8_SL:
2168*fcf5ef2aSThomas Huth         case ASI_FL16_S:
2169*fcf5ef2aSThomas Huth         case ASI_FL16_SL:
2170*fcf5ef2aSThomas Huth             if (mem_idx == MMU_USER_IDX) {
2171*fcf5ef2aSThomas Huth                 mem_idx = MMU_USER_SECONDARY_IDX;
2172*fcf5ef2aSThomas Huth             } else if (mem_idx == MMU_KERNEL_IDX) {
2173*fcf5ef2aSThomas Huth                 mem_idx = MMU_KERNEL_SECONDARY_IDX;
2174*fcf5ef2aSThomas Huth             }
2175*fcf5ef2aSThomas Huth             break;
2176*fcf5ef2aSThomas Huth         case ASI_P:  /* Primary */
2177*fcf5ef2aSThomas Huth         case ASI_PL: /* Primary LE */
2178*fcf5ef2aSThomas Huth         case ASI_TWINX_P:
2179*fcf5ef2aSThomas Huth         case ASI_TWINX_PL:
2180*fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_P:
2181*fcf5ef2aSThomas Huth         case ASI_BLK_P:
2182*fcf5ef2aSThomas Huth         case ASI_BLK_PL:
2183*fcf5ef2aSThomas Huth         case ASI_FL8_P:
2184*fcf5ef2aSThomas Huth         case ASI_FL8_PL:
2185*fcf5ef2aSThomas Huth         case ASI_FL16_P:
2186*fcf5ef2aSThomas Huth         case ASI_FL16_PL:
2187*fcf5ef2aSThomas Huth             break;
2188*fcf5ef2aSThomas Huth         }
2189*fcf5ef2aSThomas Huth         switch (asi) {
2190*fcf5ef2aSThomas Huth         case ASI_REAL:
2191*fcf5ef2aSThomas Huth         case ASI_REAL_IO:
2192*fcf5ef2aSThomas Huth         case ASI_REAL_L:
2193*fcf5ef2aSThomas Huth         case ASI_REAL_IO_L:
2194*fcf5ef2aSThomas Huth         case ASI_N:
2195*fcf5ef2aSThomas Huth         case ASI_NL:
2196*fcf5ef2aSThomas Huth         case ASI_AIUP:
2197*fcf5ef2aSThomas Huth         case ASI_AIUPL:
2198*fcf5ef2aSThomas Huth         case ASI_AIUS:
2199*fcf5ef2aSThomas Huth         case ASI_AIUSL:
2200*fcf5ef2aSThomas Huth         case ASI_S:
2201*fcf5ef2aSThomas Huth         case ASI_SL:
2202*fcf5ef2aSThomas Huth         case ASI_P:
2203*fcf5ef2aSThomas Huth         case ASI_PL:
2204*fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
2205*fcf5ef2aSThomas Huth             break;
2206*fcf5ef2aSThomas Huth         case ASI_TWINX_REAL:
2207*fcf5ef2aSThomas Huth         case ASI_TWINX_REAL_L:
2208*fcf5ef2aSThomas Huth         case ASI_TWINX_N:
2209*fcf5ef2aSThomas Huth         case ASI_TWINX_NL:
2210*fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP:
2211*fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP_L:
2212*fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS:
2213*fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS_L:
2214*fcf5ef2aSThomas Huth         case ASI_TWINX_P:
2215*fcf5ef2aSThomas Huth         case ASI_TWINX_PL:
2216*fcf5ef2aSThomas Huth         case ASI_TWINX_S:
2217*fcf5ef2aSThomas Huth         case ASI_TWINX_SL:
2218*fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS:
2219*fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS_L:
2220*fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD:
2221*fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD_L:
2222*fcf5ef2aSThomas Huth             type = GET_ASI_DTWINX;
2223*fcf5ef2aSThomas Huth             break;
2224*fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_P:
2225*fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_S:
2226*fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_4V:
2227*fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_L_4V:
2228*fcf5ef2aSThomas Huth         case ASI_BLK_AIUP:
2229*fcf5ef2aSThomas Huth         case ASI_BLK_AIUPL:
2230*fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_4V:
2231*fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_L_4V:
2232*fcf5ef2aSThomas Huth         case ASI_BLK_AIUS:
2233*fcf5ef2aSThomas Huth         case ASI_BLK_AIUSL:
2234*fcf5ef2aSThomas Huth         case ASI_BLK_S:
2235*fcf5ef2aSThomas Huth         case ASI_BLK_SL:
2236*fcf5ef2aSThomas Huth         case ASI_BLK_P:
2237*fcf5ef2aSThomas Huth         case ASI_BLK_PL:
2238*fcf5ef2aSThomas Huth             type = GET_ASI_BLOCK;
2239*fcf5ef2aSThomas Huth             break;
2240*fcf5ef2aSThomas Huth         case ASI_FL8_S:
2241*fcf5ef2aSThomas Huth         case ASI_FL8_SL:
2242*fcf5ef2aSThomas Huth         case ASI_FL8_P:
2243*fcf5ef2aSThomas Huth         case ASI_FL8_PL:
2244*fcf5ef2aSThomas Huth             memop = MO_UB;
2245*fcf5ef2aSThomas Huth             type = GET_ASI_SHORT;
2246*fcf5ef2aSThomas Huth             break;
2247*fcf5ef2aSThomas Huth         case ASI_FL16_S:
2248*fcf5ef2aSThomas Huth         case ASI_FL16_SL:
2249*fcf5ef2aSThomas Huth         case ASI_FL16_P:
2250*fcf5ef2aSThomas Huth         case ASI_FL16_PL:
2251*fcf5ef2aSThomas Huth             memop = MO_TEUW;
2252*fcf5ef2aSThomas Huth             type = GET_ASI_SHORT;
2253*fcf5ef2aSThomas Huth             break;
2254*fcf5ef2aSThomas Huth         }
2255*fcf5ef2aSThomas Huth         /* The little-endian asis all have bit 3 set.  */
2256*fcf5ef2aSThomas Huth         if (asi & 8) {
2257*fcf5ef2aSThomas Huth             memop ^= MO_BSWAP;
2258*fcf5ef2aSThomas Huth         }
2259*fcf5ef2aSThomas Huth     }
2260*fcf5ef2aSThomas Huth #endif
2261*fcf5ef2aSThomas Huth 
2262*fcf5ef2aSThomas Huth     return (DisasASI){ type, asi, mem_idx, memop };
2263*fcf5ef2aSThomas Huth }
2264*fcf5ef2aSThomas Huth 
2265*fcf5ef2aSThomas Huth static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr,
2266*fcf5ef2aSThomas Huth                        int insn, TCGMemOp memop)
2267*fcf5ef2aSThomas Huth {
2268*fcf5ef2aSThomas Huth     DisasASI da = get_asi(dc, insn, memop);
2269*fcf5ef2aSThomas Huth 
2270*fcf5ef2aSThomas Huth     switch (da.type) {
2271*fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
2272*fcf5ef2aSThomas Huth         break;
2273*fcf5ef2aSThomas Huth     case GET_ASI_DTWINX: /* Reserved for ldda.  */
2274*fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
2275*fcf5ef2aSThomas Huth         break;
2276*fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
2277*fcf5ef2aSThomas Huth         gen_address_mask(dc, addr);
2278*fcf5ef2aSThomas Huth         tcg_gen_qemu_ld_tl(dst, addr, da.mem_idx, da.memop);
2279*fcf5ef2aSThomas Huth         break;
2280*fcf5ef2aSThomas Huth     default:
2281*fcf5ef2aSThomas Huth         {
2282*fcf5ef2aSThomas Huth             TCGv_i32 r_asi = tcg_const_i32(da.asi);
2283*fcf5ef2aSThomas Huth             TCGv_i32 r_mop = tcg_const_i32(memop);
2284*fcf5ef2aSThomas Huth 
2285*fcf5ef2aSThomas Huth             save_state(dc);
2286*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
2287*fcf5ef2aSThomas Huth             gen_helper_ld_asi(dst, cpu_env, addr, r_asi, r_mop);
2288*fcf5ef2aSThomas Huth #else
2289*fcf5ef2aSThomas Huth             {
2290*fcf5ef2aSThomas Huth                 TCGv_i64 t64 = tcg_temp_new_i64();
2291*fcf5ef2aSThomas Huth                 gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_mop);
2292*fcf5ef2aSThomas Huth                 tcg_gen_trunc_i64_tl(dst, t64);
2293*fcf5ef2aSThomas Huth                 tcg_temp_free_i64(t64);
2294*fcf5ef2aSThomas Huth             }
2295*fcf5ef2aSThomas Huth #endif
2296*fcf5ef2aSThomas Huth             tcg_temp_free_i32(r_mop);
2297*fcf5ef2aSThomas Huth             tcg_temp_free_i32(r_asi);
2298*fcf5ef2aSThomas Huth         }
2299*fcf5ef2aSThomas Huth         break;
2300*fcf5ef2aSThomas Huth     }
2301*fcf5ef2aSThomas Huth }
2302*fcf5ef2aSThomas Huth 
2303*fcf5ef2aSThomas Huth static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr,
2304*fcf5ef2aSThomas Huth                        int insn, TCGMemOp memop)
2305*fcf5ef2aSThomas Huth {
2306*fcf5ef2aSThomas Huth     DisasASI da = get_asi(dc, insn, memop);
2307*fcf5ef2aSThomas Huth 
2308*fcf5ef2aSThomas Huth     switch (da.type) {
2309*fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
2310*fcf5ef2aSThomas Huth         break;
2311*fcf5ef2aSThomas Huth     case GET_ASI_DTWINX: /* Reserved for stda.  */
2312*fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
2313*fcf5ef2aSThomas Huth         break;
2314*fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
2315*fcf5ef2aSThomas Huth         gen_address_mask(dc, addr);
2316*fcf5ef2aSThomas Huth         tcg_gen_qemu_st_tl(src, addr, da.mem_idx, da.memop);
2317*fcf5ef2aSThomas Huth         break;
2318*fcf5ef2aSThomas Huth #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
2319*fcf5ef2aSThomas Huth     case GET_ASI_BCOPY:
2320*fcf5ef2aSThomas Huth         /* Copy 32 bytes from the address in SRC to ADDR.  */
2321*fcf5ef2aSThomas Huth         /* ??? The original qemu code suggests 4-byte alignment, dropping
2322*fcf5ef2aSThomas Huth            the low bits, but the only place I can see this used is in the
2323*fcf5ef2aSThomas Huth            Linux kernel with 32 byte alignment, which would make more sense
2324*fcf5ef2aSThomas Huth            as a cacheline-style operation.  */
2325*fcf5ef2aSThomas Huth         {
2326*fcf5ef2aSThomas Huth             TCGv saddr = tcg_temp_new();
2327*fcf5ef2aSThomas Huth             TCGv daddr = tcg_temp_new();
2328*fcf5ef2aSThomas Huth             TCGv four = tcg_const_tl(4);
2329*fcf5ef2aSThomas Huth             TCGv_i32 tmp = tcg_temp_new_i32();
2330*fcf5ef2aSThomas Huth             int i;
2331*fcf5ef2aSThomas Huth 
2332*fcf5ef2aSThomas Huth             tcg_gen_andi_tl(saddr, src, -4);
2333*fcf5ef2aSThomas Huth             tcg_gen_andi_tl(daddr, addr, -4);
2334*fcf5ef2aSThomas Huth             for (i = 0; i < 32; i += 4) {
2335*fcf5ef2aSThomas Huth                 /* Since the loads and stores are paired, allow the
2336*fcf5ef2aSThomas Huth                    copy to happen in the host endianness.  */
2337*fcf5ef2aSThomas Huth                 tcg_gen_qemu_ld_i32(tmp, saddr, da.mem_idx, MO_UL);
2338*fcf5ef2aSThomas Huth                 tcg_gen_qemu_st_i32(tmp, daddr, da.mem_idx, MO_UL);
2339*fcf5ef2aSThomas Huth                 tcg_gen_add_tl(saddr, saddr, four);
2340*fcf5ef2aSThomas Huth                 tcg_gen_add_tl(daddr, daddr, four);
2341*fcf5ef2aSThomas Huth             }
2342*fcf5ef2aSThomas Huth 
2343*fcf5ef2aSThomas Huth             tcg_temp_free(saddr);
2344*fcf5ef2aSThomas Huth             tcg_temp_free(daddr);
2345*fcf5ef2aSThomas Huth             tcg_temp_free(four);
2346*fcf5ef2aSThomas Huth             tcg_temp_free_i32(tmp);
2347*fcf5ef2aSThomas Huth         }
2348*fcf5ef2aSThomas Huth         break;
2349*fcf5ef2aSThomas Huth #endif
2350*fcf5ef2aSThomas Huth     default:
2351*fcf5ef2aSThomas Huth         {
2352*fcf5ef2aSThomas Huth             TCGv_i32 r_asi = tcg_const_i32(da.asi);
2353*fcf5ef2aSThomas Huth             TCGv_i32 r_mop = tcg_const_i32(memop & MO_SIZE);
2354*fcf5ef2aSThomas Huth 
2355*fcf5ef2aSThomas Huth             save_state(dc);
2356*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
2357*fcf5ef2aSThomas Huth             gen_helper_st_asi(cpu_env, addr, src, r_asi, r_mop);
2358*fcf5ef2aSThomas Huth #else
2359*fcf5ef2aSThomas Huth             {
2360*fcf5ef2aSThomas Huth                 TCGv_i64 t64 = tcg_temp_new_i64();
2361*fcf5ef2aSThomas Huth                 tcg_gen_extu_tl_i64(t64, src);
2362*fcf5ef2aSThomas Huth                 gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_mop);
2363*fcf5ef2aSThomas Huth                 tcg_temp_free_i64(t64);
2364*fcf5ef2aSThomas Huth             }
2365*fcf5ef2aSThomas Huth #endif
2366*fcf5ef2aSThomas Huth             tcg_temp_free_i32(r_mop);
2367*fcf5ef2aSThomas Huth             tcg_temp_free_i32(r_asi);
2368*fcf5ef2aSThomas Huth 
2369*fcf5ef2aSThomas Huth             /* A write to a TLB register may alter page maps.  End the TB. */
2370*fcf5ef2aSThomas Huth             dc->npc = DYNAMIC_PC;
2371*fcf5ef2aSThomas Huth         }
2372*fcf5ef2aSThomas Huth         break;
2373*fcf5ef2aSThomas Huth     }
2374*fcf5ef2aSThomas Huth }
2375*fcf5ef2aSThomas Huth 
2376*fcf5ef2aSThomas Huth static void gen_swap_asi(DisasContext *dc, TCGv dst, TCGv src,
2377*fcf5ef2aSThomas Huth                          TCGv addr, int insn)
2378*fcf5ef2aSThomas Huth {
2379*fcf5ef2aSThomas Huth     DisasASI da = get_asi(dc, insn, MO_TEUL);
2380*fcf5ef2aSThomas Huth 
2381*fcf5ef2aSThomas Huth     switch (da.type) {
2382*fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
2383*fcf5ef2aSThomas Huth         break;
2384*fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
2385*fcf5ef2aSThomas Huth         gen_swap(dc, dst, src, addr, da.mem_idx, da.memop);
2386*fcf5ef2aSThomas Huth         break;
2387*fcf5ef2aSThomas Huth     default:
2388*fcf5ef2aSThomas Huth         /* ??? Should be DAE_invalid_asi.  */
2389*fcf5ef2aSThomas Huth         gen_exception(dc, TT_DATA_ACCESS);
2390*fcf5ef2aSThomas Huth         break;
2391*fcf5ef2aSThomas Huth     }
2392*fcf5ef2aSThomas Huth }
2393*fcf5ef2aSThomas Huth 
2394*fcf5ef2aSThomas Huth static void gen_cas_asi(DisasContext *dc, TCGv addr, TCGv cmpv,
2395*fcf5ef2aSThomas Huth                         int insn, int rd)
2396*fcf5ef2aSThomas Huth {
2397*fcf5ef2aSThomas Huth     DisasASI da = get_asi(dc, insn, MO_TEUL);
2398*fcf5ef2aSThomas Huth     TCGv oldv;
2399*fcf5ef2aSThomas Huth 
2400*fcf5ef2aSThomas Huth     switch (da.type) {
2401*fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
2402*fcf5ef2aSThomas Huth         return;
2403*fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
2404*fcf5ef2aSThomas Huth         oldv = tcg_temp_new();
2405*fcf5ef2aSThomas Huth         tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, gen_load_gpr(dc, rd),
2406*fcf5ef2aSThomas Huth                                   da.mem_idx, da.memop);
2407*fcf5ef2aSThomas Huth         gen_store_gpr(dc, rd, oldv);
2408*fcf5ef2aSThomas Huth         tcg_temp_free(oldv);
2409*fcf5ef2aSThomas Huth         break;
2410*fcf5ef2aSThomas Huth     default:
2411*fcf5ef2aSThomas Huth         /* ??? Should be DAE_invalid_asi.  */
2412*fcf5ef2aSThomas Huth         gen_exception(dc, TT_DATA_ACCESS);
2413*fcf5ef2aSThomas Huth         break;
2414*fcf5ef2aSThomas Huth     }
2415*fcf5ef2aSThomas Huth }
2416*fcf5ef2aSThomas Huth 
2417*fcf5ef2aSThomas Huth static void gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn)
2418*fcf5ef2aSThomas Huth {
2419*fcf5ef2aSThomas Huth     DisasASI da = get_asi(dc, insn, MO_UB);
2420*fcf5ef2aSThomas Huth 
2421*fcf5ef2aSThomas Huth     switch (da.type) {
2422*fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
2423*fcf5ef2aSThomas Huth         break;
2424*fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
2425*fcf5ef2aSThomas Huth         gen_ldstub(dc, dst, addr, da.mem_idx);
2426*fcf5ef2aSThomas Huth         break;
2427*fcf5ef2aSThomas Huth     default:
2428*fcf5ef2aSThomas Huth         /* ??? Should be DAE_invalid_asi.  */
2429*fcf5ef2aSThomas Huth         gen_exception(dc, TT_DATA_ACCESS);
2430*fcf5ef2aSThomas Huth         break;
2431*fcf5ef2aSThomas Huth     }
2432*fcf5ef2aSThomas Huth }
2433*fcf5ef2aSThomas Huth #endif
2434*fcf5ef2aSThomas Huth 
2435*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
2436*fcf5ef2aSThomas Huth static void gen_ldf_asi(DisasContext *dc, TCGv addr,
2437*fcf5ef2aSThomas Huth                         int insn, int size, int rd)
2438*fcf5ef2aSThomas Huth {
2439*fcf5ef2aSThomas Huth     DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEQ));
2440*fcf5ef2aSThomas Huth     TCGv_i32 d32;
2441*fcf5ef2aSThomas Huth     TCGv_i64 d64;
2442*fcf5ef2aSThomas Huth 
2443*fcf5ef2aSThomas Huth     switch (da.type) {
2444*fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
2445*fcf5ef2aSThomas Huth         break;
2446*fcf5ef2aSThomas Huth 
2447*fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
2448*fcf5ef2aSThomas Huth         gen_address_mask(dc, addr);
2449*fcf5ef2aSThomas Huth         switch (size) {
2450*fcf5ef2aSThomas Huth         case 4:
2451*fcf5ef2aSThomas Huth             d32 = gen_dest_fpr_F(dc);
2452*fcf5ef2aSThomas Huth             tcg_gen_qemu_ld_i32(d32, addr, da.mem_idx, da.memop);
2453*fcf5ef2aSThomas Huth             gen_store_fpr_F(dc, rd, d32);
2454*fcf5ef2aSThomas Huth             break;
2455*fcf5ef2aSThomas Huth         case 8:
2456*fcf5ef2aSThomas Huth             tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx,
2457*fcf5ef2aSThomas Huth                                 da.memop | MO_ALIGN_4);
2458*fcf5ef2aSThomas Huth             break;
2459*fcf5ef2aSThomas Huth         case 16:
2460*fcf5ef2aSThomas Huth             d64 = tcg_temp_new_i64();
2461*fcf5ef2aSThomas Huth             tcg_gen_qemu_ld_i64(d64, addr, da.mem_idx, da.memop | MO_ALIGN_4);
2462*fcf5ef2aSThomas Huth             tcg_gen_addi_tl(addr, addr, 8);
2463*fcf5ef2aSThomas Huth             tcg_gen_qemu_ld_i64(cpu_fpr[rd/2+1], addr, da.mem_idx,
2464*fcf5ef2aSThomas Huth                                 da.memop | MO_ALIGN_4);
2465*fcf5ef2aSThomas Huth             tcg_gen_mov_i64(cpu_fpr[rd / 2], d64);
2466*fcf5ef2aSThomas Huth             tcg_temp_free_i64(d64);
2467*fcf5ef2aSThomas Huth             break;
2468*fcf5ef2aSThomas Huth         default:
2469*fcf5ef2aSThomas Huth             g_assert_not_reached();
2470*fcf5ef2aSThomas Huth         }
2471*fcf5ef2aSThomas Huth         break;
2472*fcf5ef2aSThomas Huth 
2473*fcf5ef2aSThomas Huth     case GET_ASI_BLOCK:
2474*fcf5ef2aSThomas Huth         /* Valid for lddfa on aligned registers only.  */
2475*fcf5ef2aSThomas Huth         if (size == 8 && (rd & 7) == 0) {
2476*fcf5ef2aSThomas Huth             TCGMemOp memop;
2477*fcf5ef2aSThomas Huth             TCGv eight;
2478*fcf5ef2aSThomas Huth             int i;
2479*fcf5ef2aSThomas Huth 
2480*fcf5ef2aSThomas Huth             gen_address_mask(dc, addr);
2481*fcf5ef2aSThomas Huth 
2482*fcf5ef2aSThomas Huth             /* The first operation checks required alignment.  */
2483*fcf5ef2aSThomas Huth             memop = da.memop | MO_ALIGN_64;
2484*fcf5ef2aSThomas Huth             eight = tcg_const_tl(8);
2485*fcf5ef2aSThomas Huth             for (i = 0; ; ++i) {
2486*fcf5ef2aSThomas Huth                 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + i], addr,
2487*fcf5ef2aSThomas Huth                                     da.mem_idx, memop);
2488*fcf5ef2aSThomas Huth                 if (i == 7) {
2489*fcf5ef2aSThomas Huth                     break;
2490*fcf5ef2aSThomas Huth                 }
2491*fcf5ef2aSThomas Huth                 tcg_gen_add_tl(addr, addr, eight);
2492*fcf5ef2aSThomas Huth                 memop = da.memop;
2493*fcf5ef2aSThomas Huth             }
2494*fcf5ef2aSThomas Huth             tcg_temp_free(eight);
2495*fcf5ef2aSThomas Huth         } else {
2496*fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
2497*fcf5ef2aSThomas Huth         }
2498*fcf5ef2aSThomas Huth         break;
2499*fcf5ef2aSThomas Huth 
2500*fcf5ef2aSThomas Huth     case GET_ASI_SHORT:
2501*fcf5ef2aSThomas Huth         /* Valid for lddfa only.  */
2502*fcf5ef2aSThomas Huth         if (size == 8) {
2503*fcf5ef2aSThomas Huth             gen_address_mask(dc, addr);
2504*fcf5ef2aSThomas Huth             tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
2505*fcf5ef2aSThomas Huth         } else {
2506*fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
2507*fcf5ef2aSThomas Huth         }
2508*fcf5ef2aSThomas Huth         break;
2509*fcf5ef2aSThomas Huth 
2510*fcf5ef2aSThomas Huth     default:
2511*fcf5ef2aSThomas Huth         {
2512*fcf5ef2aSThomas Huth             TCGv_i32 r_asi = tcg_const_i32(da.asi);
2513*fcf5ef2aSThomas Huth             TCGv_i32 r_mop = tcg_const_i32(da.memop);
2514*fcf5ef2aSThomas Huth 
2515*fcf5ef2aSThomas Huth             save_state(dc);
2516*fcf5ef2aSThomas Huth             /* According to the table in the UA2011 manual, the only
2517*fcf5ef2aSThomas Huth                other asis that are valid for ldfa/lddfa/ldqfa are
2518*fcf5ef2aSThomas Huth                the NO_FAULT asis.  We still need a helper for these,
2519*fcf5ef2aSThomas Huth                but we can just use the integer asi helper for them.  */
2520*fcf5ef2aSThomas Huth             switch (size) {
2521*fcf5ef2aSThomas Huth             case 4:
2522*fcf5ef2aSThomas Huth                 d64 = tcg_temp_new_i64();
2523*fcf5ef2aSThomas Huth                 gen_helper_ld_asi(d64, cpu_env, addr, r_asi, r_mop);
2524*fcf5ef2aSThomas Huth                 d32 = gen_dest_fpr_F(dc);
2525*fcf5ef2aSThomas Huth                 tcg_gen_extrl_i64_i32(d32, d64);
2526*fcf5ef2aSThomas Huth                 tcg_temp_free_i64(d64);
2527*fcf5ef2aSThomas Huth                 gen_store_fpr_F(dc, rd, d32);
2528*fcf5ef2aSThomas Huth                 break;
2529*fcf5ef2aSThomas Huth             case 8:
2530*fcf5ef2aSThomas Huth                 gen_helper_ld_asi(cpu_fpr[rd / 2], cpu_env, addr, r_asi, r_mop);
2531*fcf5ef2aSThomas Huth                 break;
2532*fcf5ef2aSThomas Huth             case 16:
2533*fcf5ef2aSThomas Huth                 d64 = tcg_temp_new_i64();
2534*fcf5ef2aSThomas Huth                 gen_helper_ld_asi(d64, cpu_env, addr, r_asi, r_mop);
2535*fcf5ef2aSThomas Huth                 tcg_gen_addi_tl(addr, addr, 8);
2536*fcf5ef2aSThomas Huth                 gen_helper_ld_asi(cpu_fpr[rd/2+1], cpu_env, addr, r_asi, r_mop);
2537*fcf5ef2aSThomas Huth                 tcg_gen_mov_i64(cpu_fpr[rd / 2], d64);
2538*fcf5ef2aSThomas Huth                 tcg_temp_free_i64(d64);
2539*fcf5ef2aSThomas Huth                 break;
2540*fcf5ef2aSThomas Huth             default:
2541*fcf5ef2aSThomas Huth                 g_assert_not_reached();
2542*fcf5ef2aSThomas Huth             }
2543*fcf5ef2aSThomas Huth             tcg_temp_free_i32(r_mop);
2544*fcf5ef2aSThomas Huth             tcg_temp_free_i32(r_asi);
2545*fcf5ef2aSThomas Huth         }
2546*fcf5ef2aSThomas Huth         break;
2547*fcf5ef2aSThomas Huth     }
2548*fcf5ef2aSThomas Huth }
2549*fcf5ef2aSThomas Huth 
2550*fcf5ef2aSThomas Huth static void gen_stf_asi(DisasContext *dc, TCGv addr,
2551*fcf5ef2aSThomas Huth                         int insn, int size, int rd)
2552*fcf5ef2aSThomas Huth {
2553*fcf5ef2aSThomas Huth     DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEQ));
2554*fcf5ef2aSThomas Huth     TCGv_i32 d32;
2555*fcf5ef2aSThomas Huth 
2556*fcf5ef2aSThomas Huth     switch (da.type) {
2557*fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
2558*fcf5ef2aSThomas Huth         break;
2559*fcf5ef2aSThomas Huth 
2560*fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
2561*fcf5ef2aSThomas Huth         gen_address_mask(dc, addr);
2562*fcf5ef2aSThomas Huth         switch (size) {
2563*fcf5ef2aSThomas Huth         case 4:
2564*fcf5ef2aSThomas Huth             d32 = gen_load_fpr_F(dc, rd);
2565*fcf5ef2aSThomas Huth             tcg_gen_qemu_st_i32(d32, addr, da.mem_idx, da.memop);
2566*fcf5ef2aSThomas Huth             break;
2567*fcf5ef2aSThomas Huth         case 8:
2568*fcf5ef2aSThomas Huth             tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx,
2569*fcf5ef2aSThomas Huth                                 da.memop | MO_ALIGN_4);
2570*fcf5ef2aSThomas Huth             break;
2571*fcf5ef2aSThomas Huth         case 16:
2572*fcf5ef2aSThomas Huth             /* Only 4-byte alignment required.  However, it is legal for the
2573*fcf5ef2aSThomas Huth                cpu to signal the alignment fault, and the OS trap handler is
2574*fcf5ef2aSThomas Huth                required to fix it up.  Requiring 16-byte alignment here avoids
2575*fcf5ef2aSThomas Huth                having to probe the second page before performing the first
2576*fcf5ef2aSThomas Huth                write.  */
2577*fcf5ef2aSThomas Huth             tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx,
2578*fcf5ef2aSThomas Huth                                 da.memop | MO_ALIGN_16);
2579*fcf5ef2aSThomas Huth             tcg_gen_addi_tl(addr, addr, 8);
2580*fcf5ef2aSThomas Huth             tcg_gen_qemu_st_i64(cpu_fpr[rd/2+1], addr, da.mem_idx, da.memop);
2581*fcf5ef2aSThomas Huth             break;
2582*fcf5ef2aSThomas Huth         default:
2583*fcf5ef2aSThomas Huth             g_assert_not_reached();
2584*fcf5ef2aSThomas Huth         }
2585*fcf5ef2aSThomas Huth         break;
2586*fcf5ef2aSThomas Huth 
2587*fcf5ef2aSThomas Huth     case GET_ASI_BLOCK:
2588*fcf5ef2aSThomas Huth         /* Valid for stdfa on aligned registers only.  */
2589*fcf5ef2aSThomas Huth         if (size == 8 && (rd & 7) == 0) {
2590*fcf5ef2aSThomas Huth             TCGMemOp memop;
2591*fcf5ef2aSThomas Huth             TCGv eight;
2592*fcf5ef2aSThomas Huth             int i;
2593*fcf5ef2aSThomas Huth 
2594*fcf5ef2aSThomas Huth             gen_address_mask(dc, addr);
2595*fcf5ef2aSThomas Huth 
2596*fcf5ef2aSThomas Huth             /* The first operation checks required alignment.  */
2597*fcf5ef2aSThomas Huth             memop = da.memop | MO_ALIGN_64;
2598*fcf5ef2aSThomas Huth             eight = tcg_const_tl(8);
2599*fcf5ef2aSThomas Huth             for (i = 0; ; ++i) {
2600*fcf5ef2aSThomas Huth                 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + i], addr,
2601*fcf5ef2aSThomas Huth                                     da.mem_idx, memop);
2602*fcf5ef2aSThomas Huth                 if (i == 7) {
2603*fcf5ef2aSThomas Huth                     break;
2604*fcf5ef2aSThomas Huth                 }
2605*fcf5ef2aSThomas Huth                 tcg_gen_add_tl(addr, addr, eight);
2606*fcf5ef2aSThomas Huth                 memop = da.memop;
2607*fcf5ef2aSThomas Huth             }
2608*fcf5ef2aSThomas Huth             tcg_temp_free(eight);
2609*fcf5ef2aSThomas Huth         } else {
2610*fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
2611*fcf5ef2aSThomas Huth         }
2612*fcf5ef2aSThomas Huth         break;
2613*fcf5ef2aSThomas Huth 
2614*fcf5ef2aSThomas Huth     case GET_ASI_SHORT:
2615*fcf5ef2aSThomas Huth         /* Valid for stdfa only.  */
2616*fcf5ef2aSThomas Huth         if (size == 8) {
2617*fcf5ef2aSThomas Huth             gen_address_mask(dc, addr);
2618*fcf5ef2aSThomas Huth             tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
2619*fcf5ef2aSThomas Huth         } else {
2620*fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
2621*fcf5ef2aSThomas Huth         }
2622*fcf5ef2aSThomas Huth         break;
2623*fcf5ef2aSThomas Huth 
2624*fcf5ef2aSThomas Huth     default:
2625*fcf5ef2aSThomas Huth         /* According to the table in the UA2011 manual, the only
2626*fcf5ef2aSThomas Huth            other asis that are valid for ldfa/lddfa/ldqfa are
2627*fcf5ef2aSThomas Huth            the PST* asis, which aren't currently handled.  */
2628*fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
2629*fcf5ef2aSThomas Huth         break;
2630*fcf5ef2aSThomas Huth     }
2631*fcf5ef2aSThomas Huth }
2632*fcf5ef2aSThomas Huth 
2633*fcf5ef2aSThomas Huth static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd)
2634*fcf5ef2aSThomas Huth {
2635*fcf5ef2aSThomas Huth     DisasASI da = get_asi(dc, insn, MO_TEQ);
2636*fcf5ef2aSThomas Huth     TCGv_i64 hi = gen_dest_gpr(dc, rd);
2637*fcf5ef2aSThomas Huth     TCGv_i64 lo = gen_dest_gpr(dc, rd + 1);
2638*fcf5ef2aSThomas Huth 
2639*fcf5ef2aSThomas Huth     switch (da.type) {
2640*fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
2641*fcf5ef2aSThomas Huth         return;
2642*fcf5ef2aSThomas Huth 
2643*fcf5ef2aSThomas Huth     case GET_ASI_DTWINX:
2644*fcf5ef2aSThomas Huth         gen_address_mask(dc, addr);
2645*fcf5ef2aSThomas Huth         tcg_gen_qemu_ld_i64(hi, addr, da.mem_idx, da.memop | MO_ALIGN_16);
2646*fcf5ef2aSThomas Huth         tcg_gen_addi_tl(addr, addr, 8);
2647*fcf5ef2aSThomas Huth         tcg_gen_qemu_ld_i64(lo, addr, da.mem_idx, da.memop);
2648*fcf5ef2aSThomas Huth         break;
2649*fcf5ef2aSThomas Huth 
2650*fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
2651*fcf5ef2aSThomas Huth         {
2652*fcf5ef2aSThomas Huth             TCGv_i64 tmp = tcg_temp_new_i64();
2653*fcf5ef2aSThomas Huth 
2654*fcf5ef2aSThomas Huth             gen_address_mask(dc, addr);
2655*fcf5ef2aSThomas Huth             tcg_gen_qemu_ld_i64(tmp, addr, da.mem_idx, da.memop);
2656*fcf5ef2aSThomas Huth 
2657*fcf5ef2aSThomas Huth             /* Note that LE ldda acts as if each 32-bit register
2658*fcf5ef2aSThomas Huth                result is byte swapped.  Having just performed one
2659*fcf5ef2aSThomas Huth                64-bit bswap, we need now to swap the writebacks.  */
2660*fcf5ef2aSThomas Huth             if ((da.memop & MO_BSWAP) == MO_TE) {
2661*fcf5ef2aSThomas Huth                 tcg_gen_extr32_i64(lo, hi, tmp);
2662*fcf5ef2aSThomas Huth             } else {
2663*fcf5ef2aSThomas Huth                 tcg_gen_extr32_i64(hi, lo, tmp);
2664*fcf5ef2aSThomas Huth             }
2665*fcf5ef2aSThomas Huth             tcg_temp_free_i64(tmp);
2666*fcf5ef2aSThomas Huth         }
2667*fcf5ef2aSThomas Huth         break;
2668*fcf5ef2aSThomas Huth 
2669*fcf5ef2aSThomas Huth     default:
2670*fcf5ef2aSThomas Huth         /* ??? In theory we've handled all of the ASIs that are valid
2671*fcf5ef2aSThomas Huth            for ldda, and this should raise DAE_invalid_asi.  However,
2672*fcf5ef2aSThomas Huth            real hardware allows others.  This can be seen with e.g.
2673*fcf5ef2aSThomas Huth            FreeBSD 10.3 wrt ASI_IC_TAG.  */
2674*fcf5ef2aSThomas Huth         {
2675*fcf5ef2aSThomas Huth             TCGv_i32 r_asi = tcg_const_i32(da.asi);
2676*fcf5ef2aSThomas Huth             TCGv_i32 r_mop = tcg_const_i32(da.memop);
2677*fcf5ef2aSThomas Huth             TCGv_i64 tmp = tcg_temp_new_i64();
2678*fcf5ef2aSThomas Huth 
2679*fcf5ef2aSThomas Huth             save_state(dc);
2680*fcf5ef2aSThomas Huth             gen_helper_ld_asi(tmp, cpu_env, addr, r_asi, r_mop);
2681*fcf5ef2aSThomas Huth             tcg_temp_free_i32(r_asi);
2682*fcf5ef2aSThomas Huth             tcg_temp_free_i32(r_mop);
2683*fcf5ef2aSThomas Huth 
2684*fcf5ef2aSThomas Huth             /* See above.  */
2685*fcf5ef2aSThomas Huth             if ((da.memop & MO_BSWAP) == MO_TE) {
2686*fcf5ef2aSThomas Huth                 tcg_gen_extr32_i64(lo, hi, tmp);
2687*fcf5ef2aSThomas Huth             } else {
2688*fcf5ef2aSThomas Huth                 tcg_gen_extr32_i64(hi, lo, tmp);
2689*fcf5ef2aSThomas Huth             }
2690*fcf5ef2aSThomas Huth             tcg_temp_free_i64(tmp);
2691*fcf5ef2aSThomas Huth         }
2692*fcf5ef2aSThomas Huth         break;
2693*fcf5ef2aSThomas Huth     }
2694*fcf5ef2aSThomas Huth 
2695*fcf5ef2aSThomas Huth     gen_store_gpr(dc, rd, hi);
2696*fcf5ef2aSThomas Huth     gen_store_gpr(dc, rd + 1, lo);
2697*fcf5ef2aSThomas Huth }
2698*fcf5ef2aSThomas Huth 
2699*fcf5ef2aSThomas Huth static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
2700*fcf5ef2aSThomas Huth                          int insn, int rd)
2701*fcf5ef2aSThomas Huth {
2702*fcf5ef2aSThomas Huth     DisasASI da = get_asi(dc, insn, MO_TEQ);
2703*fcf5ef2aSThomas Huth     TCGv lo = gen_load_gpr(dc, rd + 1);
2704*fcf5ef2aSThomas Huth 
2705*fcf5ef2aSThomas Huth     switch (da.type) {
2706*fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
2707*fcf5ef2aSThomas Huth         break;
2708*fcf5ef2aSThomas Huth 
2709*fcf5ef2aSThomas Huth     case GET_ASI_DTWINX:
2710*fcf5ef2aSThomas Huth         gen_address_mask(dc, addr);
2711*fcf5ef2aSThomas Huth         tcg_gen_qemu_st_i64(hi, addr, da.mem_idx, da.memop | MO_ALIGN_16);
2712*fcf5ef2aSThomas Huth         tcg_gen_addi_tl(addr, addr, 8);
2713*fcf5ef2aSThomas Huth         tcg_gen_qemu_st_i64(lo, addr, da.mem_idx, da.memop);
2714*fcf5ef2aSThomas Huth         break;
2715*fcf5ef2aSThomas Huth 
2716*fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
2717*fcf5ef2aSThomas Huth         {
2718*fcf5ef2aSThomas Huth             TCGv_i64 t64 = tcg_temp_new_i64();
2719*fcf5ef2aSThomas Huth 
2720*fcf5ef2aSThomas Huth             /* Note that LE stda acts as if each 32-bit register result is
2721*fcf5ef2aSThomas Huth                byte swapped.  We will perform one 64-bit LE store, so now
2722*fcf5ef2aSThomas Huth                we must swap the order of the construction.  */
2723*fcf5ef2aSThomas Huth             if ((da.memop & MO_BSWAP) == MO_TE) {
2724*fcf5ef2aSThomas Huth                 tcg_gen_concat32_i64(t64, lo, hi);
2725*fcf5ef2aSThomas Huth             } else {
2726*fcf5ef2aSThomas Huth                 tcg_gen_concat32_i64(t64, hi, lo);
2727*fcf5ef2aSThomas Huth             }
2728*fcf5ef2aSThomas Huth             gen_address_mask(dc, addr);
2729*fcf5ef2aSThomas Huth             tcg_gen_qemu_st_i64(t64, addr, da.mem_idx, da.memop);
2730*fcf5ef2aSThomas Huth             tcg_temp_free_i64(t64);
2731*fcf5ef2aSThomas Huth         }
2732*fcf5ef2aSThomas Huth         break;
2733*fcf5ef2aSThomas Huth 
2734*fcf5ef2aSThomas Huth     default:
2735*fcf5ef2aSThomas Huth         /* ??? In theory we've handled all of the ASIs that are valid
2736*fcf5ef2aSThomas Huth            for stda, and this should raise DAE_invalid_asi.  */
2737*fcf5ef2aSThomas Huth         {
2738*fcf5ef2aSThomas Huth             TCGv_i32 r_asi = tcg_const_i32(da.asi);
2739*fcf5ef2aSThomas Huth             TCGv_i32 r_mop = tcg_const_i32(da.memop);
2740*fcf5ef2aSThomas Huth             TCGv_i64 t64 = tcg_temp_new_i64();
2741*fcf5ef2aSThomas Huth 
2742*fcf5ef2aSThomas Huth             /* See above.  */
2743*fcf5ef2aSThomas Huth             if ((da.memop & MO_BSWAP) == MO_TE) {
2744*fcf5ef2aSThomas Huth                 tcg_gen_concat32_i64(t64, lo, hi);
2745*fcf5ef2aSThomas Huth             } else {
2746*fcf5ef2aSThomas Huth                 tcg_gen_concat32_i64(t64, hi, lo);
2747*fcf5ef2aSThomas Huth             }
2748*fcf5ef2aSThomas Huth 
2749*fcf5ef2aSThomas Huth             save_state(dc);
2750*fcf5ef2aSThomas Huth             gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_mop);
2751*fcf5ef2aSThomas Huth             tcg_temp_free_i32(r_mop);
2752*fcf5ef2aSThomas Huth             tcg_temp_free_i32(r_asi);
2753*fcf5ef2aSThomas Huth             tcg_temp_free_i64(t64);
2754*fcf5ef2aSThomas Huth         }
2755*fcf5ef2aSThomas Huth         break;
2756*fcf5ef2aSThomas Huth     }
2757*fcf5ef2aSThomas Huth }
2758*fcf5ef2aSThomas Huth 
2759*fcf5ef2aSThomas Huth static void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv cmpv,
2760*fcf5ef2aSThomas Huth                          int insn, int rd)
2761*fcf5ef2aSThomas Huth {
2762*fcf5ef2aSThomas Huth     DisasASI da = get_asi(dc, insn, MO_TEQ);
2763*fcf5ef2aSThomas Huth     TCGv oldv;
2764*fcf5ef2aSThomas Huth 
2765*fcf5ef2aSThomas Huth     switch (da.type) {
2766*fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
2767*fcf5ef2aSThomas Huth         return;
2768*fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
2769*fcf5ef2aSThomas Huth         oldv = tcg_temp_new();
2770*fcf5ef2aSThomas Huth         tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, gen_load_gpr(dc, rd),
2771*fcf5ef2aSThomas Huth                                   da.mem_idx, da.memop);
2772*fcf5ef2aSThomas Huth         gen_store_gpr(dc, rd, oldv);
2773*fcf5ef2aSThomas Huth         tcg_temp_free(oldv);
2774*fcf5ef2aSThomas Huth         break;
2775*fcf5ef2aSThomas Huth     default:
2776*fcf5ef2aSThomas Huth         /* ??? Should be DAE_invalid_asi.  */
2777*fcf5ef2aSThomas Huth         gen_exception(dc, TT_DATA_ACCESS);
2778*fcf5ef2aSThomas Huth         break;
2779*fcf5ef2aSThomas Huth     }
2780*fcf5ef2aSThomas Huth }
2781*fcf5ef2aSThomas Huth 
2782*fcf5ef2aSThomas Huth #elif !defined(CONFIG_USER_ONLY)
2783*fcf5ef2aSThomas Huth static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd)
2784*fcf5ef2aSThomas Huth {
2785*fcf5ef2aSThomas Huth     /* ??? Work around an apparent bug in Ubuntu gcc 4.8.2-10ubuntu2+12,
2786*fcf5ef2aSThomas Huth        whereby "rd + 1" elicits "error: array subscript is above array".
2787*fcf5ef2aSThomas Huth        Since we have already asserted that rd is even, the semantics
2788*fcf5ef2aSThomas Huth        are unchanged.  */
2789*fcf5ef2aSThomas Huth     TCGv lo = gen_dest_gpr(dc, rd | 1);
2790*fcf5ef2aSThomas Huth     TCGv hi = gen_dest_gpr(dc, rd);
2791*fcf5ef2aSThomas Huth     TCGv_i64 t64 = tcg_temp_new_i64();
2792*fcf5ef2aSThomas Huth     DisasASI da = get_asi(dc, insn, MO_TEQ);
2793*fcf5ef2aSThomas Huth 
2794*fcf5ef2aSThomas Huth     switch (da.type) {
2795*fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
2796*fcf5ef2aSThomas Huth         tcg_temp_free_i64(t64);
2797*fcf5ef2aSThomas Huth         return;
2798*fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
2799*fcf5ef2aSThomas Huth         gen_address_mask(dc, addr);
2800*fcf5ef2aSThomas Huth         tcg_gen_qemu_ld_i64(t64, addr, da.mem_idx, da.memop);
2801*fcf5ef2aSThomas Huth         break;
2802*fcf5ef2aSThomas Huth     default:
2803*fcf5ef2aSThomas Huth         {
2804*fcf5ef2aSThomas Huth             TCGv_i32 r_asi = tcg_const_i32(da.asi);
2805*fcf5ef2aSThomas Huth             TCGv_i32 r_mop = tcg_const_i32(MO_Q);
2806*fcf5ef2aSThomas Huth 
2807*fcf5ef2aSThomas Huth             save_state(dc);
2808*fcf5ef2aSThomas Huth             gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_mop);
2809*fcf5ef2aSThomas Huth             tcg_temp_free_i32(r_mop);
2810*fcf5ef2aSThomas Huth             tcg_temp_free_i32(r_asi);
2811*fcf5ef2aSThomas Huth         }
2812*fcf5ef2aSThomas Huth         break;
2813*fcf5ef2aSThomas Huth     }
2814*fcf5ef2aSThomas Huth 
2815*fcf5ef2aSThomas Huth     tcg_gen_extr_i64_i32(lo, hi, t64);
2816*fcf5ef2aSThomas Huth     tcg_temp_free_i64(t64);
2817*fcf5ef2aSThomas Huth     gen_store_gpr(dc, rd | 1, lo);
2818*fcf5ef2aSThomas Huth     gen_store_gpr(dc, rd, hi);
2819*fcf5ef2aSThomas Huth }
2820*fcf5ef2aSThomas Huth 
2821*fcf5ef2aSThomas Huth static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
2822*fcf5ef2aSThomas Huth                          int insn, int rd)
2823*fcf5ef2aSThomas Huth {
2824*fcf5ef2aSThomas Huth     DisasASI da = get_asi(dc, insn, MO_TEQ);
2825*fcf5ef2aSThomas Huth     TCGv lo = gen_load_gpr(dc, rd + 1);
2826*fcf5ef2aSThomas Huth     TCGv_i64 t64 = tcg_temp_new_i64();
2827*fcf5ef2aSThomas Huth 
2828*fcf5ef2aSThomas Huth     tcg_gen_concat_tl_i64(t64, lo, hi);
2829*fcf5ef2aSThomas Huth 
2830*fcf5ef2aSThomas Huth     switch (da.type) {
2831*fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
2832*fcf5ef2aSThomas Huth         break;
2833*fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
2834*fcf5ef2aSThomas Huth         gen_address_mask(dc, addr);
2835*fcf5ef2aSThomas Huth         tcg_gen_qemu_st_i64(t64, addr, da.mem_idx, da.memop);
2836*fcf5ef2aSThomas Huth         break;
2837*fcf5ef2aSThomas Huth     case GET_ASI_BFILL:
2838*fcf5ef2aSThomas Huth         /* Store 32 bytes of T64 to ADDR.  */
2839*fcf5ef2aSThomas Huth         /* ??? The original qemu code suggests 8-byte alignment, dropping
2840*fcf5ef2aSThomas Huth            the low bits, but the only place I can see this used is in the
2841*fcf5ef2aSThomas Huth            Linux kernel with 32 byte alignment, which would make more sense
2842*fcf5ef2aSThomas Huth            as a cacheline-style operation.  */
2843*fcf5ef2aSThomas Huth         {
2844*fcf5ef2aSThomas Huth             TCGv d_addr = tcg_temp_new();
2845*fcf5ef2aSThomas Huth             TCGv eight = tcg_const_tl(8);
2846*fcf5ef2aSThomas Huth             int i;
2847*fcf5ef2aSThomas Huth 
2848*fcf5ef2aSThomas Huth             tcg_gen_andi_tl(d_addr, addr, -8);
2849*fcf5ef2aSThomas Huth             for (i = 0; i < 32; i += 8) {
2850*fcf5ef2aSThomas Huth                 tcg_gen_qemu_st_i64(t64, d_addr, da.mem_idx, da.memop);
2851*fcf5ef2aSThomas Huth                 tcg_gen_add_tl(d_addr, d_addr, eight);
2852*fcf5ef2aSThomas Huth             }
2853*fcf5ef2aSThomas Huth 
2854*fcf5ef2aSThomas Huth             tcg_temp_free(d_addr);
2855*fcf5ef2aSThomas Huth             tcg_temp_free(eight);
2856*fcf5ef2aSThomas Huth         }
2857*fcf5ef2aSThomas Huth         break;
2858*fcf5ef2aSThomas Huth     default:
2859*fcf5ef2aSThomas Huth         {
2860*fcf5ef2aSThomas Huth             TCGv_i32 r_asi = tcg_const_i32(da.asi);
2861*fcf5ef2aSThomas Huth             TCGv_i32 r_mop = tcg_const_i32(MO_Q);
2862*fcf5ef2aSThomas Huth 
2863*fcf5ef2aSThomas Huth             save_state(dc);
2864*fcf5ef2aSThomas Huth             gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_mop);
2865*fcf5ef2aSThomas Huth             tcg_temp_free_i32(r_mop);
2866*fcf5ef2aSThomas Huth             tcg_temp_free_i32(r_asi);
2867*fcf5ef2aSThomas Huth         }
2868*fcf5ef2aSThomas Huth         break;
2869*fcf5ef2aSThomas Huth     }
2870*fcf5ef2aSThomas Huth 
2871*fcf5ef2aSThomas Huth     tcg_temp_free_i64(t64);
2872*fcf5ef2aSThomas Huth }
2873*fcf5ef2aSThomas Huth #endif
2874*fcf5ef2aSThomas Huth 
2875*fcf5ef2aSThomas Huth static TCGv get_src1(DisasContext *dc, unsigned int insn)
2876*fcf5ef2aSThomas Huth {
2877*fcf5ef2aSThomas Huth     unsigned int rs1 = GET_FIELD(insn, 13, 17);
2878*fcf5ef2aSThomas Huth     return gen_load_gpr(dc, rs1);
2879*fcf5ef2aSThomas Huth }
2880*fcf5ef2aSThomas Huth 
2881*fcf5ef2aSThomas Huth static TCGv get_src2(DisasContext *dc, unsigned int insn)
2882*fcf5ef2aSThomas Huth {
2883*fcf5ef2aSThomas Huth     if (IS_IMM) { /* immediate */
2884*fcf5ef2aSThomas Huth         target_long simm = GET_FIELDs(insn, 19, 31);
2885*fcf5ef2aSThomas Huth         TCGv t = get_temp_tl(dc);
2886*fcf5ef2aSThomas Huth         tcg_gen_movi_tl(t, simm);
2887*fcf5ef2aSThomas Huth         return t;
2888*fcf5ef2aSThomas Huth     } else {      /* register */
2889*fcf5ef2aSThomas Huth         unsigned int rs2 = GET_FIELD(insn, 27, 31);
2890*fcf5ef2aSThomas Huth         return gen_load_gpr(dc, rs2);
2891*fcf5ef2aSThomas Huth     }
2892*fcf5ef2aSThomas Huth }
2893*fcf5ef2aSThomas Huth 
2894*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
2895*fcf5ef2aSThomas Huth static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2896*fcf5ef2aSThomas Huth {
2897*fcf5ef2aSThomas Huth     TCGv_i32 c32, zero, dst, s1, s2;
2898*fcf5ef2aSThomas Huth 
2899*fcf5ef2aSThomas Huth     /* We have two choices here: extend the 32 bit data and use movcond_i64,
2900*fcf5ef2aSThomas Huth        or fold the comparison down to 32 bits and use movcond_i32.  Choose
2901*fcf5ef2aSThomas Huth        the later.  */
2902*fcf5ef2aSThomas Huth     c32 = tcg_temp_new_i32();
2903*fcf5ef2aSThomas Huth     if (cmp->is_bool) {
2904*fcf5ef2aSThomas Huth         tcg_gen_extrl_i64_i32(c32, cmp->c1);
2905*fcf5ef2aSThomas Huth     } else {
2906*fcf5ef2aSThomas Huth         TCGv_i64 c64 = tcg_temp_new_i64();
2907*fcf5ef2aSThomas Huth         tcg_gen_setcond_i64(cmp->cond, c64, cmp->c1, cmp->c2);
2908*fcf5ef2aSThomas Huth         tcg_gen_extrl_i64_i32(c32, c64);
2909*fcf5ef2aSThomas Huth         tcg_temp_free_i64(c64);
2910*fcf5ef2aSThomas Huth     }
2911*fcf5ef2aSThomas Huth 
2912*fcf5ef2aSThomas Huth     s1 = gen_load_fpr_F(dc, rs);
2913*fcf5ef2aSThomas Huth     s2 = gen_load_fpr_F(dc, rd);
2914*fcf5ef2aSThomas Huth     dst = gen_dest_fpr_F(dc);
2915*fcf5ef2aSThomas Huth     zero = tcg_const_i32(0);
2916*fcf5ef2aSThomas Huth 
2917*fcf5ef2aSThomas Huth     tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
2918*fcf5ef2aSThomas Huth 
2919*fcf5ef2aSThomas Huth     tcg_temp_free_i32(c32);
2920*fcf5ef2aSThomas Huth     tcg_temp_free_i32(zero);
2921*fcf5ef2aSThomas Huth     gen_store_fpr_F(dc, rd, dst);
2922*fcf5ef2aSThomas Huth }
2923*fcf5ef2aSThomas Huth 
2924*fcf5ef2aSThomas Huth static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2925*fcf5ef2aSThomas Huth {
2926*fcf5ef2aSThomas Huth     TCGv_i64 dst = gen_dest_fpr_D(dc, rd);
2927*fcf5ef2aSThomas Huth     tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, cmp->c2,
2928*fcf5ef2aSThomas Huth                         gen_load_fpr_D(dc, rs),
2929*fcf5ef2aSThomas Huth                         gen_load_fpr_D(dc, rd));
2930*fcf5ef2aSThomas Huth     gen_store_fpr_D(dc, rd, dst);
2931*fcf5ef2aSThomas Huth }
2932*fcf5ef2aSThomas Huth 
2933*fcf5ef2aSThomas Huth static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2934*fcf5ef2aSThomas Huth {
2935*fcf5ef2aSThomas Huth     int qd = QFPREG(rd);
2936*fcf5ef2aSThomas Huth     int qs = QFPREG(rs);
2937*fcf5ef2aSThomas Huth 
2938*fcf5ef2aSThomas Huth     tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, cmp->c2,
2939*fcf5ef2aSThomas Huth                         cpu_fpr[qs / 2], cpu_fpr[qd / 2]);
2940*fcf5ef2aSThomas Huth     tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, cmp->c2,
2941*fcf5ef2aSThomas Huth                         cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]);
2942*fcf5ef2aSThomas Huth 
2943*fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, qd);
2944*fcf5ef2aSThomas Huth }
2945*fcf5ef2aSThomas Huth 
2946*fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
2947*fcf5ef2aSThomas Huth static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_env cpu_env)
2948*fcf5ef2aSThomas Huth {
2949*fcf5ef2aSThomas Huth     TCGv_i32 r_tl = tcg_temp_new_i32();
2950*fcf5ef2aSThomas Huth 
2951*fcf5ef2aSThomas Huth     /* load env->tl into r_tl */
2952*fcf5ef2aSThomas Huth     tcg_gen_ld_i32(r_tl, cpu_env, offsetof(CPUSPARCState, tl));
2953*fcf5ef2aSThomas Huth 
2954*fcf5ef2aSThomas Huth     /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
2955*fcf5ef2aSThomas Huth     tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK);
2956*fcf5ef2aSThomas Huth 
2957*fcf5ef2aSThomas Huth     /* calculate offset to current trap state from env->ts, reuse r_tl */
2958*fcf5ef2aSThomas Huth     tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
2959*fcf5ef2aSThomas Huth     tcg_gen_addi_ptr(r_tsptr, cpu_env, offsetof(CPUSPARCState, ts));
2960*fcf5ef2aSThomas Huth 
2961*fcf5ef2aSThomas Huth     /* tsptr = env->ts[env->tl & MAXTL_MASK] */
2962*fcf5ef2aSThomas Huth     {
2963*fcf5ef2aSThomas Huth         TCGv_ptr r_tl_tmp = tcg_temp_new_ptr();
2964*fcf5ef2aSThomas Huth         tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl);
2965*fcf5ef2aSThomas Huth         tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp);
2966*fcf5ef2aSThomas Huth         tcg_temp_free_ptr(r_tl_tmp);
2967*fcf5ef2aSThomas Huth     }
2968*fcf5ef2aSThomas Huth 
2969*fcf5ef2aSThomas Huth     tcg_temp_free_i32(r_tl);
2970*fcf5ef2aSThomas Huth }
2971*fcf5ef2aSThomas Huth #endif
2972*fcf5ef2aSThomas Huth 
2973*fcf5ef2aSThomas Huth static void gen_edge(DisasContext *dc, TCGv dst, TCGv s1, TCGv s2,
2974*fcf5ef2aSThomas Huth                      int width, bool cc, bool left)
2975*fcf5ef2aSThomas Huth {
2976*fcf5ef2aSThomas Huth     TCGv lo1, lo2, t1, t2;
2977*fcf5ef2aSThomas Huth     uint64_t amask, tabl, tabr;
2978*fcf5ef2aSThomas Huth     int shift, imask, omask;
2979*fcf5ef2aSThomas Huth 
2980*fcf5ef2aSThomas Huth     if (cc) {
2981*fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_cc_src, s1);
2982*fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_cc_src2, s2);
2983*fcf5ef2aSThomas Huth         tcg_gen_sub_tl(cpu_cc_dst, s1, s2);
2984*fcf5ef2aSThomas Huth         tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB);
2985*fcf5ef2aSThomas Huth         dc->cc_op = CC_OP_SUB;
2986*fcf5ef2aSThomas Huth     }
2987*fcf5ef2aSThomas Huth 
2988*fcf5ef2aSThomas Huth     /* Theory of operation: there are two tables, left and right (not to
2989*fcf5ef2aSThomas Huth        be confused with the left and right versions of the opcode).  These
2990*fcf5ef2aSThomas Huth        are indexed by the low 3 bits of the inputs.  To make things "easy",
2991*fcf5ef2aSThomas Huth        these tables are loaded into two constants, TABL and TABR below.
2992*fcf5ef2aSThomas Huth        The operation index = (input & imask) << shift calculates the index
2993*fcf5ef2aSThomas Huth        into the constant, while val = (table >> index) & omask calculates
2994*fcf5ef2aSThomas Huth        the value we're looking for.  */
2995*fcf5ef2aSThomas Huth     switch (width) {
2996*fcf5ef2aSThomas Huth     case 8:
2997*fcf5ef2aSThomas Huth         imask = 0x7;
2998*fcf5ef2aSThomas Huth         shift = 3;
2999*fcf5ef2aSThomas Huth         omask = 0xff;
3000*fcf5ef2aSThomas Huth         if (left) {
3001*fcf5ef2aSThomas Huth             tabl = 0x80c0e0f0f8fcfeffULL;
3002*fcf5ef2aSThomas Huth             tabr = 0xff7f3f1f0f070301ULL;
3003*fcf5ef2aSThomas Huth         } else {
3004*fcf5ef2aSThomas Huth             tabl = 0x0103070f1f3f7fffULL;
3005*fcf5ef2aSThomas Huth             tabr = 0xfffefcf8f0e0c080ULL;
3006*fcf5ef2aSThomas Huth         }
3007*fcf5ef2aSThomas Huth         break;
3008*fcf5ef2aSThomas Huth     case 16:
3009*fcf5ef2aSThomas Huth         imask = 0x6;
3010*fcf5ef2aSThomas Huth         shift = 1;
3011*fcf5ef2aSThomas Huth         omask = 0xf;
3012*fcf5ef2aSThomas Huth         if (left) {
3013*fcf5ef2aSThomas Huth             tabl = 0x8cef;
3014*fcf5ef2aSThomas Huth             tabr = 0xf731;
3015*fcf5ef2aSThomas Huth         } else {
3016*fcf5ef2aSThomas Huth             tabl = 0x137f;
3017*fcf5ef2aSThomas Huth             tabr = 0xfec8;
3018*fcf5ef2aSThomas Huth         }
3019*fcf5ef2aSThomas Huth         break;
3020*fcf5ef2aSThomas Huth     case 32:
3021*fcf5ef2aSThomas Huth         imask = 0x4;
3022*fcf5ef2aSThomas Huth         shift = 0;
3023*fcf5ef2aSThomas Huth         omask = 0x3;
3024*fcf5ef2aSThomas Huth         if (left) {
3025*fcf5ef2aSThomas Huth             tabl = (2 << 2) | 3;
3026*fcf5ef2aSThomas Huth             tabr = (3 << 2) | 1;
3027*fcf5ef2aSThomas Huth         } else {
3028*fcf5ef2aSThomas Huth             tabl = (1 << 2) | 3;
3029*fcf5ef2aSThomas Huth             tabr = (3 << 2) | 2;
3030*fcf5ef2aSThomas Huth         }
3031*fcf5ef2aSThomas Huth         break;
3032*fcf5ef2aSThomas Huth     default:
3033*fcf5ef2aSThomas Huth         abort();
3034*fcf5ef2aSThomas Huth     }
3035*fcf5ef2aSThomas Huth 
3036*fcf5ef2aSThomas Huth     lo1 = tcg_temp_new();
3037*fcf5ef2aSThomas Huth     lo2 = tcg_temp_new();
3038*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(lo1, s1, imask);
3039*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(lo2, s2, imask);
3040*fcf5ef2aSThomas Huth     tcg_gen_shli_tl(lo1, lo1, shift);
3041*fcf5ef2aSThomas Huth     tcg_gen_shli_tl(lo2, lo2, shift);
3042*fcf5ef2aSThomas Huth 
3043*fcf5ef2aSThomas Huth     t1 = tcg_const_tl(tabl);
3044*fcf5ef2aSThomas Huth     t2 = tcg_const_tl(tabr);
3045*fcf5ef2aSThomas Huth     tcg_gen_shr_tl(lo1, t1, lo1);
3046*fcf5ef2aSThomas Huth     tcg_gen_shr_tl(lo2, t2, lo2);
3047*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(dst, lo1, omask);
3048*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(lo2, lo2, omask);
3049*fcf5ef2aSThomas Huth 
3050*fcf5ef2aSThomas Huth     amask = -8;
3051*fcf5ef2aSThomas Huth     if (AM_CHECK(dc)) {
3052*fcf5ef2aSThomas Huth         amask &= 0xffffffffULL;
3053*fcf5ef2aSThomas Huth     }
3054*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(s1, s1, amask);
3055*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(s2, s2, amask);
3056*fcf5ef2aSThomas Huth 
3057*fcf5ef2aSThomas Huth     /* We want to compute
3058*fcf5ef2aSThomas Huth         dst = (s1 == s2 ? lo1 : lo1 & lo2).
3059*fcf5ef2aSThomas Huth        We've already done dst = lo1, so this reduces to
3060*fcf5ef2aSThomas Huth         dst &= (s1 == s2 ? -1 : lo2)
3061*fcf5ef2aSThomas Huth        Which we perform by
3062*fcf5ef2aSThomas Huth         lo2 |= -(s1 == s2)
3063*fcf5ef2aSThomas Huth         dst &= lo2
3064*fcf5ef2aSThomas Huth     */
3065*fcf5ef2aSThomas Huth     tcg_gen_setcond_tl(TCG_COND_EQ, t1, s1, s2);
3066*fcf5ef2aSThomas Huth     tcg_gen_neg_tl(t1, t1);
3067*fcf5ef2aSThomas Huth     tcg_gen_or_tl(lo2, lo2, t1);
3068*fcf5ef2aSThomas Huth     tcg_gen_and_tl(dst, dst, lo2);
3069*fcf5ef2aSThomas Huth 
3070*fcf5ef2aSThomas Huth     tcg_temp_free(lo1);
3071*fcf5ef2aSThomas Huth     tcg_temp_free(lo2);
3072*fcf5ef2aSThomas Huth     tcg_temp_free(t1);
3073*fcf5ef2aSThomas Huth     tcg_temp_free(t2);
3074*fcf5ef2aSThomas Huth }
3075*fcf5ef2aSThomas Huth 
3076*fcf5ef2aSThomas Huth static void gen_alignaddr(TCGv dst, TCGv s1, TCGv s2, bool left)
3077*fcf5ef2aSThomas Huth {
3078*fcf5ef2aSThomas Huth     TCGv tmp = tcg_temp_new();
3079*fcf5ef2aSThomas Huth 
3080*fcf5ef2aSThomas Huth     tcg_gen_add_tl(tmp, s1, s2);
3081*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(dst, tmp, -8);
3082*fcf5ef2aSThomas Huth     if (left) {
3083*fcf5ef2aSThomas Huth         tcg_gen_neg_tl(tmp, tmp);
3084*fcf5ef2aSThomas Huth     }
3085*fcf5ef2aSThomas Huth     tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
3086*fcf5ef2aSThomas Huth 
3087*fcf5ef2aSThomas Huth     tcg_temp_free(tmp);
3088*fcf5ef2aSThomas Huth }
3089*fcf5ef2aSThomas Huth 
3090*fcf5ef2aSThomas Huth static void gen_faligndata(TCGv dst, TCGv gsr, TCGv s1, TCGv s2)
3091*fcf5ef2aSThomas Huth {
3092*fcf5ef2aSThomas Huth     TCGv t1, t2, shift;
3093*fcf5ef2aSThomas Huth 
3094*fcf5ef2aSThomas Huth     t1 = tcg_temp_new();
3095*fcf5ef2aSThomas Huth     t2 = tcg_temp_new();
3096*fcf5ef2aSThomas Huth     shift = tcg_temp_new();
3097*fcf5ef2aSThomas Huth 
3098*fcf5ef2aSThomas Huth     tcg_gen_andi_tl(shift, gsr, 7);
3099*fcf5ef2aSThomas Huth     tcg_gen_shli_tl(shift, shift, 3);
3100*fcf5ef2aSThomas Huth     tcg_gen_shl_tl(t1, s1, shift);
3101*fcf5ef2aSThomas Huth 
3102*fcf5ef2aSThomas Huth     /* A shift of 64 does not produce 0 in TCG.  Divide this into a
3103*fcf5ef2aSThomas Huth        shift of (up to 63) followed by a constant shift of 1.  */
3104*fcf5ef2aSThomas Huth     tcg_gen_xori_tl(shift, shift, 63);
3105*fcf5ef2aSThomas Huth     tcg_gen_shr_tl(t2, s2, shift);
3106*fcf5ef2aSThomas Huth     tcg_gen_shri_tl(t2, t2, 1);
3107*fcf5ef2aSThomas Huth 
3108*fcf5ef2aSThomas Huth     tcg_gen_or_tl(dst, t1, t2);
3109*fcf5ef2aSThomas Huth 
3110*fcf5ef2aSThomas Huth     tcg_temp_free(t1);
3111*fcf5ef2aSThomas Huth     tcg_temp_free(t2);
3112*fcf5ef2aSThomas Huth     tcg_temp_free(shift);
3113*fcf5ef2aSThomas Huth }
3114*fcf5ef2aSThomas Huth #endif
3115*fcf5ef2aSThomas Huth 
3116*fcf5ef2aSThomas Huth #define CHECK_IU_FEATURE(dc, FEATURE)                      \
3117*fcf5ef2aSThomas Huth     if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE))  \
3118*fcf5ef2aSThomas Huth         goto illegal_insn;
3119*fcf5ef2aSThomas Huth #define CHECK_FPU_FEATURE(dc, FEATURE)                     \
3120*fcf5ef2aSThomas Huth     if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE))  \
3121*fcf5ef2aSThomas Huth         goto nfpu_insn;
3122*fcf5ef2aSThomas Huth 
3123*fcf5ef2aSThomas Huth /* before an instruction, dc->pc must be static */
3124*fcf5ef2aSThomas Huth static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
3125*fcf5ef2aSThomas Huth {
3126*fcf5ef2aSThomas Huth     unsigned int opc, rs1, rs2, rd;
3127*fcf5ef2aSThomas Huth     TCGv cpu_src1, cpu_src2;
3128*fcf5ef2aSThomas Huth     TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
3129*fcf5ef2aSThomas Huth     TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
3130*fcf5ef2aSThomas Huth     target_long simm;
3131*fcf5ef2aSThomas Huth 
3132*fcf5ef2aSThomas Huth     opc = GET_FIELD(insn, 0, 1);
3133*fcf5ef2aSThomas Huth     rd = GET_FIELD(insn, 2, 6);
3134*fcf5ef2aSThomas Huth 
3135*fcf5ef2aSThomas Huth     switch (opc) {
3136*fcf5ef2aSThomas Huth     case 0:                     /* branches/sethi */
3137*fcf5ef2aSThomas Huth         {
3138*fcf5ef2aSThomas Huth             unsigned int xop = GET_FIELD(insn, 7, 9);
3139*fcf5ef2aSThomas Huth             int32_t target;
3140*fcf5ef2aSThomas Huth             switch (xop) {
3141*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
3142*fcf5ef2aSThomas Huth             case 0x1:           /* V9 BPcc */
3143*fcf5ef2aSThomas Huth                 {
3144*fcf5ef2aSThomas Huth                     int cc;
3145*fcf5ef2aSThomas Huth 
3146*fcf5ef2aSThomas Huth                     target = GET_FIELD_SP(insn, 0, 18);
3147*fcf5ef2aSThomas Huth                     target = sign_extend(target, 19);
3148*fcf5ef2aSThomas Huth                     target <<= 2;
3149*fcf5ef2aSThomas Huth                     cc = GET_FIELD_SP(insn, 20, 21);
3150*fcf5ef2aSThomas Huth                     if (cc == 0)
3151*fcf5ef2aSThomas Huth                         do_branch(dc, target, insn, 0);
3152*fcf5ef2aSThomas Huth                     else if (cc == 2)
3153*fcf5ef2aSThomas Huth                         do_branch(dc, target, insn, 1);
3154*fcf5ef2aSThomas Huth                     else
3155*fcf5ef2aSThomas Huth                         goto illegal_insn;
3156*fcf5ef2aSThomas Huth                     goto jmp_insn;
3157*fcf5ef2aSThomas Huth                 }
3158*fcf5ef2aSThomas Huth             case 0x3:           /* V9 BPr */
3159*fcf5ef2aSThomas Huth                 {
3160*fcf5ef2aSThomas Huth                     target = GET_FIELD_SP(insn, 0, 13) |
3161*fcf5ef2aSThomas Huth                         (GET_FIELD_SP(insn, 20, 21) << 14);
3162*fcf5ef2aSThomas Huth                     target = sign_extend(target, 16);
3163*fcf5ef2aSThomas Huth                     target <<= 2;
3164*fcf5ef2aSThomas Huth                     cpu_src1 = get_src1(dc, insn);
3165*fcf5ef2aSThomas Huth                     do_branch_reg(dc, target, insn, cpu_src1);
3166*fcf5ef2aSThomas Huth                     goto jmp_insn;
3167*fcf5ef2aSThomas Huth                 }
3168*fcf5ef2aSThomas Huth             case 0x5:           /* V9 FBPcc */
3169*fcf5ef2aSThomas Huth                 {
3170*fcf5ef2aSThomas Huth                     int cc = GET_FIELD_SP(insn, 20, 21);
3171*fcf5ef2aSThomas Huth                     if (gen_trap_ifnofpu(dc)) {
3172*fcf5ef2aSThomas Huth                         goto jmp_insn;
3173*fcf5ef2aSThomas Huth                     }
3174*fcf5ef2aSThomas Huth                     target = GET_FIELD_SP(insn, 0, 18);
3175*fcf5ef2aSThomas Huth                     target = sign_extend(target, 19);
3176*fcf5ef2aSThomas Huth                     target <<= 2;
3177*fcf5ef2aSThomas Huth                     do_fbranch(dc, target, insn, cc);
3178*fcf5ef2aSThomas Huth                     goto jmp_insn;
3179*fcf5ef2aSThomas Huth                 }
3180*fcf5ef2aSThomas Huth #else
3181*fcf5ef2aSThomas Huth             case 0x7:           /* CBN+x */
3182*fcf5ef2aSThomas Huth                 {
3183*fcf5ef2aSThomas Huth                     goto ncp_insn;
3184*fcf5ef2aSThomas Huth                 }
3185*fcf5ef2aSThomas Huth #endif
3186*fcf5ef2aSThomas Huth             case 0x2:           /* BN+x */
3187*fcf5ef2aSThomas Huth                 {
3188*fcf5ef2aSThomas Huth                     target = GET_FIELD(insn, 10, 31);
3189*fcf5ef2aSThomas Huth                     target = sign_extend(target, 22);
3190*fcf5ef2aSThomas Huth                     target <<= 2;
3191*fcf5ef2aSThomas Huth                     do_branch(dc, target, insn, 0);
3192*fcf5ef2aSThomas Huth                     goto jmp_insn;
3193*fcf5ef2aSThomas Huth                 }
3194*fcf5ef2aSThomas Huth             case 0x6:           /* FBN+x */
3195*fcf5ef2aSThomas Huth                 {
3196*fcf5ef2aSThomas Huth                     if (gen_trap_ifnofpu(dc)) {
3197*fcf5ef2aSThomas Huth                         goto jmp_insn;
3198*fcf5ef2aSThomas Huth                     }
3199*fcf5ef2aSThomas Huth                     target = GET_FIELD(insn, 10, 31);
3200*fcf5ef2aSThomas Huth                     target = sign_extend(target, 22);
3201*fcf5ef2aSThomas Huth                     target <<= 2;
3202*fcf5ef2aSThomas Huth                     do_fbranch(dc, target, insn, 0);
3203*fcf5ef2aSThomas Huth                     goto jmp_insn;
3204*fcf5ef2aSThomas Huth                 }
3205*fcf5ef2aSThomas Huth             case 0x4:           /* SETHI */
3206*fcf5ef2aSThomas Huth                 /* Special-case %g0 because that's the canonical nop.  */
3207*fcf5ef2aSThomas Huth                 if (rd) {
3208*fcf5ef2aSThomas Huth                     uint32_t value = GET_FIELD(insn, 10, 31);
3209*fcf5ef2aSThomas Huth                     TCGv t = gen_dest_gpr(dc, rd);
3210*fcf5ef2aSThomas Huth                     tcg_gen_movi_tl(t, value << 10);
3211*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, t);
3212*fcf5ef2aSThomas Huth                 }
3213*fcf5ef2aSThomas Huth                 break;
3214*fcf5ef2aSThomas Huth             case 0x0:           /* UNIMPL */
3215*fcf5ef2aSThomas Huth             default:
3216*fcf5ef2aSThomas Huth                 goto illegal_insn;
3217*fcf5ef2aSThomas Huth             }
3218*fcf5ef2aSThomas Huth             break;
3219*fcf5ef2aSThomas Huth         }
3220*fcf5ef2aSThomas Huth         break;
3221*fcf5ef2aSThomas Huth     case 1:                     /*CALL*/
3222*fcf5ef2aSThomas Huth         {
3223*fcf5ef2aSThomas Huth             target_long target = GET_FIELDs(insn, 2, 31) << 2;
3224*fcf5ef2aSThomas Huth             TCGv o7 = gen_dest_gpr(dc, 15);
3225*fcf5ef2aSThomas Huth 
3226*fcf5ef2aSThomas Huth             tcg_gen_movi_tl(o7, dc->pc);
3227*fcf5ef2aSThomas Huth             gen_store_gpr(dc, 15, o7);
3228*fcf5ef2aSThomas Huth             target += dc->pc;
3229*fcf5ef2aSThomas Huth             gen_mov_pc_npc(dc);
3230*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
3231*fcf5ef2aSThomas Huth             if (unlikely(AM_CHECK(dc))) {
3232*fcf5ef2aSThomas Huth                 target &= 0xffffffffULL;
3233*fcf5ef2aSThomas Huth             }
3234*fcf5ef2aSThomas Huth #endif
3235*fcf5ef2aSThomas Huth             dc->npc = target;
3236*fcf5ef2aSThomas Huth         }
3237*fcf5ef2aSThomas Huth         goto jmp_insn;
3238*fcf5ef2aSThomas Huth     case 2:                     /* FPU & Logical Operations */
3239*fcf5ef2aSThomas Huth         {
3240*fcf5ef2aSThomas Huth             unsigned int xop = GET_FIELD(insn, 7, 12);
3241*fcf5ef2aSThomas Huth             TCGv cpu_dst = get_temp_tl(dc);
3242*fcf5ef2aSThomas Huth             TCGv cpu_tmp0;
3243*fcf5ef2aSThomas Huth 
3244*fcf5ef2aSThomas Huth             if (xop == 0x3a) {  /* generate trap */
3245*fcf5ef2aSThomas Huth                 int cond = GET_FIELD(insn, 3, 6);
3246*fcf5ef2aSThomas Huth                 TCGv_i32 trap;
3247*fcf5ef2aSThomas Huth                 TCGLabel *l1 = NULL;
3248*fcf5ef2aSThomas Huth                 int mask;
3249*fcf5ef2aSThomas Huth 
3250*fcf5ef2aSThomas Huth                 if (cond == 0) {
3251*fcf5ef2aSThomas Huth                     /* Trap never.  */
3252*fcf5ef2aSThomas Huth                     break;
3253*fcf5ef2aSThomas Huth                 }
3254*fcf5ef2aSThomas Huth 
3255*fcf5ef2aSThomas Huth                 save_state(dc);
3256*fcf5ef2aSThomas Huth 
3257*fcf5ef2aSThomas Huth                 if (cond != 8) {
3258*fcf5ef2aSThomas Huth                     /* Conditional trap.  */
3259*fcf5ef2aSThomas Huth                     DisasCompare cmp;
3260*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
3261*fcf5ef2aSThomas Huth                     /* V9 icc/xcc */
3262*fcf5ef2aSThomas Huth                     int cc = GET_FIELD_SP(insn, 11, 12);
3263*fcf5ef2aSThomas Huth                     if (cc == 0) {
3264*fcf5ef2aSThomas Huth                         gen_compare(&cmp, 0, cond, dc);
3265*fcf5ef2aSThomas Huth                     } else if (cc == 2) {
3266*fcf5ef2aSThomas Huth                         gen_compare(&cmp, 1, cond, dc);
3267*fcf5ef2aSThomas Huth                     } else {
3268*fcf5ef2aSThomas Huth                         goto illegal_insn;
3269*fcf5ef2aSThomas Huth                     }
3270*fcf5ef2aSThomas Huth #else
3271*fcf5ef2aSThomas Huth                     gen_compare(&cmp, 0, cond, dc);
3272*fcf5ef2aSThomas Huth #endif
3273*fcf5ef2aSThomas Huth                     l1 = gen_new_label();
3274*fcf5ef2aSThomas Huth                     tcg_gen_brcond_tl(tcg_invert_cond(cmp.cond),
3275*fcf5ef2aSThomas Huth                                       cmp.c1, cmp.c2, l1);
3276*fcf5ef2aSThomas Huth                     free_compare(&cmp);
3277*fcf5ef2aSThomas Huth                 }
3278*fcf5ef2aSThomas Huth 
3279*fcf5ef2aSThomas Huth                 mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
3280*fcf5ef2aSThomas Huth                         ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
3281*fcf5ef2aSThomas Huth 
3282*fcf5ef2aSThomas Huth                 /* Don't use the normal temporaries, as they may well have
3283*fcf5ef2aSThomas Huth                    gone out of scope with the branch above.  While we're
3284*fcf5ef2aSThomas Huth                    doing that we might as well pre-truncate to 32-bit.  */
3285*fcf5ef2aSThomas Huth                 trap = tcg_temp_new_i32();
3286*fcf5ef2aSThomas Huth 
3287*fcf5ef2aSThomas Huth                 rs1 = GET_FIELD_SP(insn, 14, 18);
3288*fcf5ef2aSThomas Huth                 if (IS_IMM) {
3289*fcf5ef2aSThomas Huth                     rs2 = GET_FIELD_SP(insn, 0, 6);
3290*fcf5ef2aSThomas Huth                     if (rs1 == 0) {
3291*fcf5ef2aSThomas Huth                         tcg_gen_movi_i32(trap, (rs2 & mask) + TT_TRAP);
3292*fcf5ef2aSThomas Huth                         /* Signal that the trap value is fully constant.  */
3293*fcf5ef2aSThomas Huth                         mask = 0;
3294*fcf5ef2aSThomas Huth                     } else {
3295*fcf5ef2aSThomas Huth                         TCGv t1 = gen_load_gpr(dc, rs1);
3296*fcf5ef2aSThomas Huth                         tcg_gen_trunc_tl_i32(trap, t1);
3297*fcf5ef2aSThomas Huth                         tcg_gen_addi_i32(trap, trap, rs2);
3298*fcf5ef2aSThomas Huth                     }
3299*fcf5ef2aSThomas Huth                 } else {
3300*fcf5ef2aSThomas Huth                     TCGv t1, t2;
3301*fcf5ef2aSThomas Huth                     rs2 = GET_FIELD_SP(insn, 0, 4);
3302*fcf5ef2aSThomas Huth                     t1 = gen_load_gpr(dc, rs1);
3303*fcf5ef2aSThomas Huth                     t2 = gen_load_gpr(dc, rs2);
3304*fcf5ef2aSThomas Huth                     tcg_gen_add_tl(t1, t1, t2);
3305*fcf5ef2aSThomas Huth                     tcg_gen_trunc_tl_i32(trap, t1);
3306*fcf5ef2aSThomas Huth                 }
3307*fcf5ef2aSThomas Huth                 if (mask != 0) {
3308*fcf5ef2aSThomas Huth                     tcg_gen_andi_i32(trap, trap, mask);
3309*fcf5ef2aSThomas Huth                     tcg_gen_addi_i32(trap, trap, TT_TRAP);
3310*fcf5ef2aSThomas Huth                 }
3311*fcf5ef2aSThomas Huth 
3312*fcf5ef2aSThomas Huth                 gen_helper_raise_exception(cpu_env, trap);
3313*fcf5ef2aSThomas Huth                 tcg_temp_free_i32(trap);
3314*fcf5ef2aSThomas Huth 
3315*fcf5ef2aSThomas Huth                 if (cond == 8) {
3316*fcf5ef2aSThomas Huth                     /* An unconditional trap ends the TB.  */
3317*fcf5ef2aSThomas Huth                     dc->is_br = 1;
3318*fcf5ef2aSThomas Huth                     goto jmp_insn;
3319*fcf5ef2aSThomas Huth                 } else {
3320*fcf5ef2aSThomas Huth                     /* A conditional trap falls through to the next insn.  */
3321*fcf5ef2aSThomas Huth                     gen_set_label(l1);
3322*fcf5ef2aSThomas Huth                     break;
3323*fcf5ef2aSThomas Huth                 }
3324*fcf5ef2aSThomas Huth             } else if (xop == 0x28) {
3325*fcf5ef2aSThomas Huth                 rs1 = GET_FIELD(insn, 13, 17);
3326*fcf5ef2aSThomas Huth                 switch(rs1) {
3327*fcf5ef2aSThomas Huth                 case 0: /* rdy */
3328*fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64
3329*fcf5ef2aSThomas Huth                 case 0x01 ... 0x0e: /* undefined in the SPARCv8
3330*fcf5ef2aSThomas Huth                                        manual, rdy on the microSPARC
3331*fcf5ef2aSThomas Huth                                        II */
3332*fcf5ef2aSThomas Huth                 case 0x0f:          /* stbar in the SPARCv8 manual,
3333*fcf5ef2aSThomas Huth                                        rdy on the microSPARC II */
3334*fcf5ef2aSThomas Huth                 case 0x10 ... 0x1f: /* implementation-dependent in the
3335*fcf5ef2aSThomas Huth                                        SPARCv8 manual, rdy on the
3336*fcf5ef2aSThomas Huth                                        microSPARC II */
3337*fcf5ef2aSThomas Huth                     /* Read Asr17 */
3338*fcf5ef2aSThomas Huth                     if (rs1 == 0x11 && dc->def->features & CPU_FEATURE_ASR17) {
3339*fcf5ef2aSThomas Huth                         TCGv t = gen_dest_gpr(dc, rd);
3340*fcf5ef2aSThomas Huth                         /* Read Asr17 for a Leon3 monoprocessor */
3341*fcf5ef2aSThomas Huth                         tcg_gen_movi_tl(t, (1 << 8) | (dc->def->nwindows - 1));
3342*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, t);
3343*fcf5ef2aSThomas Huth                         break;
3344*fcf5ef2aSThomas Huth                     }
3345*fcf5ef2aSThomas Huth #endif
3346*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_y);
3347*fcf5ef2aSThomas Huth                     break;
3348*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
3349*fcf5ef2aSThomas Huth                 case 0x2: /* V9 rdccr */
3350*fcf5ef2aSThomas Huth                     update_psr(dc);
3351*fcf5ef2aSThomas Huth                     gen_helper_rdccr(cpu_dst, cpu_env);
3352*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
3353*fcf5ef2aSThomas Huth                     break;
3354*fcf5ef2aSThomas Huth                 case 0x3: /* V9 rdasi */
3355*fcf5ef2aSThomas Huth                     tcg_gen_movi_tl(cpu_dst, dc->asi);
3356*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
3357*fcf5ef2aSThomas Huth                     break;
3358*fcf5ef2aSThomas Huth                 case 0x4: /* V9 rdtick */
3359*fcf5ef2aSThomas Huth                     {
3360*fcf5ef2aSThomas Huth                         TCGv_ptr r_tickptr;
3361*fcf5ef2aSThomas Huth                         TCGv_i32 r_const;
3362*fcf5ef2aSThomas Huth 
3363*fcf5ef2aSThomas Huth                         r_tickptr = tcg_temp_new_ptr();
3364*fcf5ef2aSThomas Huth                         r_const = tcg_const_i32(dc->mem_idx);
3365*fcf5ef2aSThomas Huth                         tcg_gen_ld_ptr(r_tickptr, cpu_env,
3366*fcf5ef2aSThomas Huth                                        offsetof(CPUSPARCState, tick));
3367*fcf5ef2aSThomas Huth                         gen_helper_tick_get_count(cpu_dst, cpu_env, r_tickptr,
3368*fcf5ef2aSThomas Huth                                                   r_const);
3369*fcf5ef2aSThomas Huth                         tcg_temp_free_ptr(r_tickptr);
3370*fcf5ef2aSThomas Huth                         tcg_temp_free_i32(r_const);
3371*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, cpu_dst);
3372*fcf5ef2aSThomas Huth                     }
3373*fcf5ef2aSThomas Huth                     break;
3374*fcf5ef2aSThomas Huth                 case 0x5: /* V9 rdpc */
3375*fcf5ef2aSThomas Huth                     {
3376*fcf5ef2aSThomas Huth                         TCGv t = gen_dest_gpr(dc, rd);
3377*fcf5ef2aSThomas Huth                         if (unlikely(AM_CHECK(dc))) {
3378*fcf5ef2aSThomas Huth                             tcg_gen_movi_tl(t, dc->pc & 0xffffffffULL);
3379*fcf5ef2aSThomas Huth                         } else {
3380*fcf5ef2aSThomas Huth                             tcg_gen_movi_tl(t, dc->pc);
3381*fcf5ef2aSThomas Huth                         }
3382*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, t);
3383*fcf5ef2aSThomas Huth                     }
3384*fcf5ef2aSThomas Huth                     break;
3385*fcf5ef2aSThomas Huth                 case 0x6: /* V9 rdfprs */
3386*fcf5ef2aSThomas Huth                     tcg_gen_ext_i32_tl(cpu_dst, cpu_fprs);
3387*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
3388*fcf5ef2aSThomas Huth                     break;
3389*fcf5ef2aSThomas Huth                 case 0xf: /* V9 membar */
3390*fcf5ef2aSThomas Huth                     break; /* no effect */
3391*fcf5ef2aSThomas Huth                 case 0x13: /* Graphics Status */
3392*fcf5ef2aSThomas Huth                     if (gen_trap_ifnofpu(dc)) {
3393*fcf5ef2aSThomas Huth                         goto jmp_insn;
3394*fcf5ef2aSThomas Huth                     }
3395*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_gsr);
3396*fcf5ef2aSThomas Huth                     break;
3397*fcf5ef2aSThomas Huth                 case 0x16: /* Softint */
3398*fcf5ef2aSThomas Huth                     tcg_gen_ld32s_tl(cpu_dst, cpu_env,
3399*fcf5ef2aSThomas Huth                                      offsetof(CPUSPARCState, softint));
3400*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
3401*fcf5ef2aSThomas Huth                     break;
3402*fcf5ef2aSThomas Huth                 case 0x17: /* Tick compare */
3403*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_tick_cmpr);
3404*fcf5ef2aSThomas Huth                     break;
3405*fcf5ef2aSThomas Huth                 case 0x18: /* System tick */
3406*fcf5ef2aSThomas Huth                     {
3407*fcf5ef2aSThomas Huth                         TCGv_ptr r_tickptr;
3408*fcf5ef2aSThomas Huth                         TCGv_i32 r_const;
3409*fcf5ef2aSThomas Huth 
3410*fcf5ef2aSThomas Huth                         r_tickptr = tcg_temp_new_ptr();
3411*fcf5ef2aSThomas Huth                         r_const = tcg_const_i32(dc->mem_idx);
3412*fcf5ef2aSThomas Huth                         tcg_gen_ld_ptr(r_tickptr, cpu_env,
3413*fcf5ef2aSThomas Huth                                        offsetof(CPUSPARCState, stick));
3414*fcf5ef2aSThomas Huth                         gen_helper_tick_get_count(cpu_dst, cpu_env, r_tickptr,
3415*fcf5ef2aSThomas Huth                                                   r_const);
3416*fcf5ef2aSThomas Huth                         tcg_temp_free_ptr(r_tickptr);
3417*fcf5ef2aSThomas Huth                         tcg_temp_free_i32(r_const);
3418*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, cpu_dst);
3419*fcf5ef2aSThomas Huth                     }
3420*fcf5ef2aSThomas Huth                     break;
3421*fcf5ef2aSThomas Huth                 case 0x19: /* System tick compare */
3422*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_stick_cmpr);
3423*fcf5ef2aSThomas Huth                     break;
3424*fcf5ef2aSThomas Huth                 case 0x10: /* Performance Control */
3425*fcf5ef2aSThomas Huth                 case 0x11: /* Performance Instrumentation Counter */
3426*fcf5ef2aSThomas Huth                 case 0x12: /* Dispatch Control */
3427*fcf5ef2aSThomas Huth                 case 0x14: /* Softint set, WO */
3428*fcf5ef2aSThomas Huth                 case 0x15: /* Softint clear, WO */
3429*fcf5ef2aSThomas Huth #endif
3430*fcf5ef2aSThomas Huth                 default:
3431*fcf5ef2aSThomas Huth                     goto illegal_insn;
3432*fcf5ef2aSThomas Huth                 }
3433*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY)
3434*fcf5ef2aSThomas Huth             } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */
3435*fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64
3436*fcf5ef2aSThomas Huth                 if (!supervisor(dc)) {
3437*fcf5ef2aSThomas Huth                     goto priv_insn;
3438*fcf5ef2aSThomas Huth                 }
3439*fcf5ef2aSThomas Huth                 update_psr(dc);
3440*fcf5ef2aSThomas Huth                 gen_helper_rdpsr(cpu_dst, cpu_env);
3441*fcf5ef2aSThomas Huth #else
3442*fcf5ef2aSThomas Huth                 CHECK_IU_FEATURE(dc, HYPV);
3443*fcf5ef2aSThomas Huth                 if (!hypervisor(dc))
3444*fcf5ef2aSThomas Huth                     goto priv_insn;
3445*fcf5ef2aSThomas Huth                 rs1 = GET_FIELD(insn, 13, 17);
3446*fcf5ef2aSThomas Huth                 switch (rs1) {
3447*fcf5ef2aSThomas Huth                 case 0: // hpstate
3448*fcf5ef2aSThomas Huth                     // gen_op_rdhpstate();
3449*fcf5ef2aSThomas Huth                     break;
3450*fcf5ef2aSThomas Huth                 case 1: // htstate
3451*fcf5ef2aSThomas Huth                     // gen_op_rdhtstate();
3452*fcf5ef2aSThomas Huth                     break;
3453*fcf5ef2aSThomas Huth                 case 3: // hintp
3454*fcf5ef2aSThomas Huth                     tcg_gen_mov_tl(cpu_dst, cpu_hintp);
3455*fcf5ef2aSThomas Huth                     break;
3456*fcf5ef2aSThomas Huth                 case 5: // htba
3457*fcf5ef2aSThomas Huth                     tcg_gen_mov_tl(cpu_dst, cpu_htba);
3458*fcf5ef2aSThomas Huth                     break;
3459*fcf5ef2aSThomas Huth                 case 6: // hver
3460*fcf5ef2aSThomas Huth                     tcg_gen_mov_tl(cpu_dst, cpu_hver);
3461*fcf5ef2aSThomas Huth                     break;
3462*fcf5ef2aSThomas Huth                 case 31: // hstick_cmpr
3463*fcf5ef2aSThomas Huth                     tcg_gen_mov_tl(cpu_dst, cpu_hstick_cmpr);
3464*fcf5ef2aSThomas Huth                     break;
3465*fcf5ef2aSThomas Huth                 default:
3466*fcf5ef2aSThomas Huth                     goto illegal_insn;
3467*fcf5ef2aSThomas Huth                 }
3468*fcf5ef2aSThomas Huth #endif
3469*fcf5ef2aSThomas Huth                 gen_store_gpr(dc, rd, cpu_dst);
3470*fcf5ef2aSThomas Huth                 break;
3471*fcf5ef2aSThomas Huth             } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
3472*fcf5ef2aSThomas Huth                 if (!supervisor(dc)) {
3473*fcf5ef2aSThomas Huth                     goto priv_insn;
3474*fcf5ef2aSThomas Huth                 }
3475*fcf5ef2aSThomas Huth                 cpu_tmp0 = get_temp_tl(dc);
3476*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
3477*fcf5ef2aSThomas Huth                 rs1 = GET_FIELD(insn, 13, 17);
3478*fcf5ef2aSThomas Huth                 switch (rs1) {
3479*fcf5ef2aSThomas Huth                 case 0: // tpc
3480*fcf5ef2aSThomas Huth                     {
3481*fcf5ef2aSThomas Huth                         TCGv_ptr r_tsptr;
3482*fcf5ef2aSThomas Huth 
3483*fcf5ef2aSThomas Huth                         r_tsptr = tcg_temp_new_ptr();
3484*fcf5ef2aSThomas Huth                         gen_load_trap_state_at_tl(r_tsptr, cpu_env);
3485*fcf5ef2aSThomas Huth                         tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
3486*fcf5ef2aSThomas Huth                                       offsetof(trap_state, tpc));
3487*fcf5ef2aSThomas Huth                         tcg_temp_free_ptr(r_tsptr);
3488*fcf5ef2aSThomas Huth                     }
3489*fcf5ef2aSThomas Huth                     break;
3490*fcf5ef2aSThomas Huth                 case 1: // tnpc
3491*fcf5ef2aSThomas Huth                     {
3492*fcf5ef2aSThomas Huth                         TCGv_ptr r_tsptr;
3493*fcf5ef2aSThomas Huth 
3494*fcf5ef2aSThomas Huth                         r_tsptr = tcg_temp_new_ptr();
3495*fcf5ef2aSThomas Huth                         gen_load_trap_state_at_tl(r_tsptr, cpu_env);
3496*fcf5ef2aSThomas Huth                         tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
3497*fcf5ef2aSThomas Huth                                       offsetof(trap_state, tnpc));
3498*fcf5ef2aSThomas Huth                         tcg_temp_free_ptr(r_tsptr);
3499*fcf5ef2aSThomas Huth                     }
3500*fcf5ef2aSThomas Huth                     break;
3501*fcf5ef2aSThomas Huth                 case 2: // tstate
3502*fcf5ef2aSThomas Huth                     {
3503*fcf5ef2aSThomas Huth                         TCGv_ptr r_tsptr;
3504*fcf5ef2aSThomas Huth 
3505*fcf5ef2aSThomas Huth                         r_tsptr = tcg_temp_new_ptr();
3506*fcf5ef2aSThomas Huth                         gen_load_trap_state_at_tl(r_tsptr, cpu_env);
3507*fcf5ef2aSThomas Huth                         tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
3508*fcf5ef2aSThomas Huth                                       offsetof(trap_state, tstate));
3509*fcf5ef2aSThomas Huth                         tcg_temp_free_ptr(r_tsptr);
3510*fcf5ef2aSThomas Huth                     }
3511*fcf5ef2aSThomas Huth                     break;
3512*fcf5ef2aSThomas Huth                 case 3: // tt
3513*fcf5ef2aSThomas Huth                     {
3514*fcf5ef2aSThomas Huth                         TCGv_ptr r_tsptr = tcg_temp_new_ptr();
3515*fcf5ef2aSThomas Huth 
3516*fcf5ef2aSThomas Huth                         gen_load_trap_state_at_tl(r_tsptr, cpu_env);
3517*fcf5ef2aSThomas Huth                         tcg_gen_ld32s_tl(cpu_tmp0, r_tsptr,
3518*fcf5ef2aSThomas Huth                                          offsetof(trap_state, tt));
3519*fcf5ef2aSThomas Huth                         tcg_temp_free_ptr(r_tsptr);
3520*fcf5ef2aSThomas Huth                     }
3521*fcf5ef2aSThomas Huth                     break;
3522*fcf5ef2aSThomas Huth                 case 4: // tick
3523*fcf5ef2aSThomas Huth                     {
3524*fcf5ef2aSThomas Huth                         TCGv_ptr r_tickptr;
3525*fcf5ef2aSThomas Huth                         TCGv_i32 r_const;
3526*fcf5ef2aSThomas Huth 
3527*fcf5ef2aSThomas Huth                         r_tickptr = tcg_temp_new_ptr();
3528*fcf5ef2aSThomas Huth                         r_const = tcg_const_i32(dc->mem_idx);
3529*fcf5ef2aSThomas Huth                         tcg_gen_ld_ptr(r_tickptr, cpu_env,
3530*fcf5ef2aSThomas Huth                                        offsetof(CPUSPARCState, tick));
3531*fcf5ef2aSThomas Huth                         gen_helper_tick_get_count(cpu_tmp0, cpu_env,
3532*fcf5ef2aSThomas Huth                                                   r_tickptr, r_const);
3533*fcf5ef2aSThomas Huth                         tcg_temp_free_ptr(r_tickptr);
3534*fcf5ef2aSThomas Huth                         tcg_temp_free_i32(r_const);
3535*fcf5ef2aSThomas Huth                     }
3536*fcf5ef2aSThomas Huth                     break;
3537*fcf5ef2aSThomas Huth                 case 5: // tba
3538*fcf5ef2aSThomas Huth                     tcg_gen_mov_tl(cpu_tmp0, cpu_tbr);
3539*fcf5ef2aSThomas Huth                     break;
3540*fcf5ef2aSThomas Huth                 case 6: // pstate
3541*fcf5ef2aSThomas Huth                     tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3542*fcf5ef2aSThomas Huth                                      offsetof(CPUSPARCState, pstate));
3543*fcf5ef2aSThomas Huth                     break;
3544*fcf5ef2aSThomas Huth                 case 7: // tl
3545*fcf5ef2aSThomas Huth                     tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3546*fcf5ef2aSThomas Huth                                      offsetof(CPUSPARCState, tl));
3547*fcf5ef2aSThomas Huth                     break;
3548*fcf5ef2aSThomas Huth                 case 8: // pil
3549*fcf5ef2aSThomas Huth                     tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3550*fcf5ef2aSThomas Huth                                      offsetof(CPUSPARCState, psrpil));
3551*fcf5ef2aSThomas Huth                     break;
3552*fcf5ef2aSThomas Huth                 case 9: // cwp
3553*fcf5ef2aSThomas Huth                     gen_helper_rdcwp(cpu_tmp0, cpu_env);
3554*fcf5ef2aSThomas Huth                     break;
3555*fcf5ef2aSThomas Huth                 case 10: // cansave
3556*fcf5ef2aSThomas Huth                     tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3557*fcf5ef2aSThomas Huth                                      offsetof(CPUSPARCState, cansave));
3558*fcf5ef2aSThomas Huth                     break;
3559*fcf5ef2aSThomas Huth                 case 11: // canrestore
3560*fcf5ef2aSThomas Huth                     tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3561*fcf5ef2aSThomas Huth                                      offsetof(CPUSPARCState, canrestore));
3562*fcf5ef2aSThomas Huth                     break;
3563*fcf5ef2aSThomas Huth                 case 12: // cleanwin
3564*fcf5ef2aSThomas Huth                     tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3565*fcf5ef2aSThomas Huth                                      offsetof(CPUSPARCState, cleanwin));
3566*fcf5ef2aSThomas Huth                     break;
3567*fcf5ef2aSThomas Huth                 case 13: // otherwin
3568*fcf5ef2aSThomas Huth                     tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3569*fcf5ef2aSThomas Huth                                      offsetof(CPUSPARCState, otherwin));
3570*fcf5ef2aSThomas Huth                     break;
3571*fcf5ef2aSThomas Huth                 case 14: // wstate
3572*fcf5ef2aSThomas Huth                     tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3573*fcf5ef2aSThomas Huth                                      offsetof(CPUSPARCState, wstate));
3574*fcf5ef2aSThomas Huth                     break;
3575*fcf5ef2aSThomas Huth                 case 16: // UA2005 gl
3576*fcf5ef2aSThomas Huth                     CHECK_IU_FEATURE(dc, GL);
3577*fcf5ef2aSThomas Huth                     tcg_gen_ld32s_tl(cpu_tmp0, cpu_env,
3578*fcf5ef2aSThomas Huth                                      offsetof(CPUSPARCState, gl));
3579*fcf5ef2aSThomas Huth                     break;
3580*fcf5ef2aSThomas Huth                 case 26: // UA2005 strand status
3581*fcf5ef2aSThomas Huth                     CHECK_IU_FEATURE(dc, HYPV);
3582*fcf5ef2aSThomas Huth                     if (!hypervisor(dc))
3583*fcf5ef2aSThomas Huth                         goto priv_insn;
3584*fcf5ef2aSThomas Huth                     tcg_gen_mov_tl(cpu_tmp0, cpu_ssr);
3585*fcf5ef2aSThomas Huth                     break;
3586*fcf5ef2aSThomas Huth                 case 31: // ver
3587*fcf5ef2aSThomas Huth                     tcg_gen_mov_tl(cpu_tmp0, cpu_ver);
3588*fcf5ef2aSThomas Huth                     break;
3589*fcf5ef2aSThomas Huth                 case 15: // fq
3590*fcf5ef2aSThomas Huth                 default:
3591*fcf5ef2aSThomas Huth                     goto illegal_insn;
3592*fcf5ef2aSThomas Huth                 }
3593*fcf5ef2aSThomas Huth #else
3594*fcf5ef2aSThomas Huth                 tcg_gen_ext_i32_tl(cpu_tmp0, cpu_wim);
3595*fcf5ef2aSThomas Huth #endif
3596*fcf5ef2aSThomas Huth                 gen_store_gpr(dc, rd, cpu_tmp0);
3597*fcf5ef2aSThomas Huth                 break;
3598*fcf5ef2aSThomas Huth             } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
3599*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
3600*fcf5ef2aSThomas Huth                 gen_helper_flushw(cpu_env);
3601*fcf5ef2aSThomas Huth #else
3602*fcf5ef2aSThomas Huth                 if (!supervisor(dc))
3603*fcf5ef2aSThomas Huth                     goto priv_insn;
3604*fcf5ef2aSThomas Huth                 gen_store_gpr(dc, rd, cpu_tbr);
3605*fcf5ef2aSThomas Huth #endif
3606*fcf5ef2aSThomas Huth                 break;
3607*fcf5ef2aSThomas Huth #endif
3608*fcf5ef2aSThomas Huth             } else if (xop == 0x34) {   /* FPU Operations */
3609*fcf5ef2aSThomas Huth                 if (gen_trap_ifnofpu(dc)) {
3610*fcf5ef2aSThomas Huth                     goto jmp_insn;
3611*fcf5ef2aSThomas Huth                 }
3612*fcf5ef2aSThomas Huth                 gen_op_clear_ieee_excp_and_FTT();
3613*fcf5ef2aSThomas Huth                 rs1 = GET_FIELD(insn, 13, 17);
3614*fcf5ef2aSThomas Huth                 rs2 = GET_FIELD(insn, 27, 31);
3615*fcf5ef2aSThomas Huth                 xop = GET_FIELD(insn, 18, 26);
3616*fcf5ef2aSThomas Huth 
3617*fcf5ef2aSThomas Huth                 switch (xop) {
3618*fcf5ef2aSThomas Huth                 case 0x1: /* fmovs */
3619*fcf5ef2aSThomas Huth                     cpu_src1_32 = gen_load_fpr_F(dc, rs2);
3620*fcf5ef2aSThomas Huth                     gen_store_fpr_F(dc, rd, cpu_src1_32);
3621*fcf5ef2aSThomas Huth                     break;
3622*fcf5ef2aSThomas Huth                 case 0x5: /* fnegs */
3623*fcf5ef2aSThomas Huth                     gen_ne_fop_FF(dc, rd, rs2, gen_helper_fnegs);
3624*fcf5ef2aSThomas Huth                     break;
3625*fcf5ef2aSThomas Huth                 case 0x9: /* fabss */
3626*fcf5ef2aSThomas Huth                     gen_ne_fop_FF(dc, rd, rs2, gen_helper_fabss);
3627*fcf5ef2aSThomas Huth                     break;
3628*fcf5ef2aSThomas Huth                 case 0x29: /* fsqrts */
3629*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FSQRT);
3630*fcf5ef2aSThomas Huth                     gen_fop_FF(dc, rd, rs2, gen_helper_fsqrts);
3631*fcf5ef2aSThomas Huth                     break;
3632*fcf5ef2aSThomas Huth                 case 0x2a: /* fsqrtd */
3633*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FSQRT);
3634*fcf5ef2aSThomas Huth                     gen_fop_DD(dc, rd, rs2, gen_helper_fsqrtd);
3635*fcf5ef2aSThomas Huth                     break;
3636*fcf5ef2aSThomas Huth                 case 0x2b: /* fsqrtq */
3637*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3638*fcf5ef2aSThomas Huth                     gen_fop_QQ(dc, rd, rs2, gen_helper_fsqrtq);
3639*fcf5ef2aSThomas Huth                     break;
3640*fcf5ef2aSThomas Huth                 case 0x41: /* fadds */
3641*fcf5ef2aSThomas Huth                     gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fadds);
3642*fcf5ef2aSThomas Huth                     break;
3643*fcf5ef2aSThomas Huth                 case 0x42: /* faddd */
3644*fcf5ef2aSThomas Huth                     gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_faddd);
3645*fcf5ef2aSThomas Huth                     break;
3646*fcf5ef2aSThomas Huth                 case 0x43: /* faddq */
3647*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3648*fcf5ef2aSThomas Huth                     gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_faddq);
3649*fcf5ef2aSThomas Huth                     break;
3650*fcf5ef2aSThomas Huth                 case 0x45: /* fsubs */
3651*fcf5ef2aSThomas Huth                     gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fsubs);
3652*fcf5ef2aSThomas Huth                     break;
3653*fcf5ef2aSThomas Huth                 case 0x46: /* fsubd */
3654*fcf5ef2aSThomas Huth                     gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fsubd);
3655*fcf5ef2aSThomas Huth                     break;
3656*fcf5ef2aSThomas Huth                 case 0x47: /* fsubq */
3657*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3658*fcf5ef2aSThomas Huth                     gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fsubq);
3659*fcf5ef2aSThomas Huth                     break;
3660*fcf5ef2aSThomas Huth                 case 0x49: /* fmuls */
3661*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FMUL);
3662*fcf5ef2aSThomas Huth                     gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fmuls);
3663*fcf5ef2aSThomas Huth                     break;
3664*fcf5ef2aSThomas Huth                 case 0x4a: /* fmuld */
3665*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FMUL);
3666*fcf5ef2aSThomas Huth                     gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld);
3667*fcf5ef2aSThomas Huth                     break;
3668*fcf5ef2aSThomas Huth                 case 0x4b: /* fmulq */
3669*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3670*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FMUL);
3671*fcf5ef2aSThomas Huth                     gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fmulq);
3672*fcf5ef2aSThomas Huth                     break;
3673*fcf5ef2aSThomas Huth                 case 0x4d: /* fdivs */
3674*fcf5ef2aSThomas Huth                     gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fdivs);
3675*fcf5ef2aSThomas Huth                     break;
3676*fcf5ef2aSThomas Huth                 case 0x4e: /* fdivd */
3677*fcf5ef2aSThomas Huth                     gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fdivd);
3678*fcf5ef2aSThomas Huth                     break;
3679*fcf5ef2aSThomas Huth                 case 0x4f: /* fdivq */
3680*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3681*fcf5ef2aSThomas Huth                     gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fdivq);
3682*fcf5ef2aSThomas Huth                     break;
3683*fcf5ef2aSThomas Huth                 case 0x69: /* fsmuld */
3684*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FSMULD);
3685*fcf5ef2aSThomas Huth                     gen_fop_DFF(dc, rd, rs1, rs2, gen_helper_fsmuld);
3686*fcf5ef2aSThomas Huth                     break;
3687*fcf5ef2aSThomas Huth                 case 0x6e: /* fdmulq */
3688*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3689*fcf5ef2aSThomas Huth                     gen_fop_QDD(dc, rd, rs1, rs2, gen_helper_fdmulq);
3690*fcf5ef2aSThomas Huth                     break;
3691*fcf5ef2aSThomas Huth                 case 0xc4: /* fitos */
3692*fcf5ef2aSThomas Huth                     gen_fop_FF(dc, rd, rs2, gen_helper_fitos);
3693*fcf5ef2aSThomas Huth                     break;
3694*fcf5ef2aSThomas Huth                 case 0xc6: /* fdtos */
3695*fcf5ef2aSThomas Huth                     gen_fop_FD(dc, rd, rs2, gen_helper_fdtos);
3696*fcf5ef2aSThomas Huth                     break;
3697*fcf5ef2aSThomas Huth                 case 0xc7: /* fqtos */
3698*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3699*fcf5ef2aSThomas Huth                     gen_fop_FQ(dc, rd, rs2, gen_helper_fqtos);
3700*fcf5ef2aSThomas Huth                     break;
3701*fcf5ef2aSThomas Huth                 case 0xc8: /* fitod */
3702*fcf5ef2aSThomas Huth                     gen_ne_fop_DF(dc, rd, rs2, gen_helper_fitod);
3703*fcf5ef2aSThomas Huth                     break;
3704*fcf5ef2aSThomas Huth                 case 0xc9: /* fstod */
3705*fcf5ef2aSThomas Huth                     gen_ne_fop_DF(dc, rd, rs2, gen_helper_fstod);
3706*fcf5ef2aSThomas Huth                     break;
3707*fcf5ef2aSThomas Huth                 case 0xcb: /* fqtod */
3708*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3709*fcf5ef2aSThomas Huth                     gen_fop_DQ(dc, rd, rs2, gen_helper_fqtod);
3710*fcf5ef2aSThomas Huth                     break;
3711*fcf5ef2aSThomas Huth                 case 0xcc: /* fitoq */
3712*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3713*fcf5ef2aSThomas Huth                     gen_ne_fop_QF(dc, rd, rs2, gen_helper_fitoq);
3714*fcf5ef2aSThomas Huth                     break;
3715*fcf5ef2aSThomas Huth                 case 0xcd: /* fstoq */
3716*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3717*fcf5ef2aSThomas Huth                     gen_ne_fop_QF(dc, rd, rs2, gen_helper_fstoq);
3718*fcf5ef2aSThomas Huth                     break;
3719*fcf5ef2aSThomas Huth                 case 0xce: /* fdtoq */
3720*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3721*fcf5ef2aSThomas Huth                     gen_ne_fop_QD(dc, rd, rs2, gen_helper_fdtoq);
3722*fcf5ef2aSThomas Huth                     break;
3723*fcf5ef2aSThomas Huth                 case 0xd1: /* fstoi */
3724*fcf5ef2aSThomas Huth                     gen_fop_FF(dc, rd, rs2, gen_helper_fstoi);
3725*fcf5ef2aSThomas Huth                     break;
3726*fcf5ef2aSThomas Huth                 case 0xd2: /* fdtoi */
3727*fcf5ef2aSThomas Huth                     gen_fop_FD(dc, rd, rs2, gen_helper_fdtoi);
3728*fcf5ef2aSThomas Huth                     break;
3729*fcf5ef2aSThomas Huth                 case 0xd3: /* fqtoi */
3730*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3731*fcf5ef2aSThomas Huth                     gen_fop_FQ(dc, rd, rs2, gen_helper_fqtoi);
3732*fcf5ef2aSThomas Huth                     break;
3733*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
3734*fcf5ef2aSThomas Huth                 case 0x2: /* V9 fmovd */
3735*fcf5ef2aSThomas Huth                     cpu_src1_64 = gen_load_fpr_D(dc, rs2);
3736*fcf5ef2aSThomas Huth                     gen_store_fpr_D(dc, rd, cpu_src1_64);
3737*fcf5ef2aSThomas Huth                     break;
3738*fcf5ef2aSThomas Huth                 case 0x3: /* V9 fmovq */
3739*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3740*fcf5ef2aSThomas Huth                     gen_move_Q(dc, rd, rs2);
3741*fcf5ef2aSThomas Huth                     break;
3742*fcf5ef2aSThomas Huth                 case 0x6: /* V9 fnegd */
3743*fcf5ef2aSThomas Huth                     gen_ne_fop_DD(dc, rd, rs2, gen_helper_fnegd);
3744*fcf5ef2aSThomas Huth                     break;
3745*fcf5ef2aSThomas Huth                 case 0x7: /* V9 fnegq */
3746*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3747*fcf5ef2aSThomas Huth                     gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fnegq);
3748*fcf5ef2aSThomas Huth                     break;
3749*fcf5ef2aSThomas Huth                 case 0xa: /* V9 fabsd */
3750*fcf5ef2aSThomas Huth                     gen_ne_fop_DD(dc, rd, rs2, gen_helper_fabsd);
3751*fcf5ef2aSThomas Huth                     break;
3752*fcf5ef2aSThomas Huth                 case 0xb: /* V9 fabsq */
3753*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3754*fcf5ef2aSThomas Huth                     gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fabsq);
3755*fcf5ef2aSThomas Huth                     break;
3756*fcf5ef2aSThomas Huth                 case 0x81: /* V9 fstox */
3757*fcf5ef2aSThomas Huth                     gen_fop_DF(dc, rd, rs2, gen_helper_fstox);
3758*fcf5ef2aSThomas Huth                     break;
3759*fcf5ef2aSThomas Huth                 case 0x82: /* V9 fdtox */
3760*fcf5ef2aSThomas Huth                     gen_fop_DD(dc, rd, rs2, gen_helper_fdtox);
3761*fcf5ef2aSThomas Huth                     break;
3762*fcf5ef2aSThomas Huth                 case 0x83: /* V9 fqtox */
3763*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3764*fcf5ef2aSThomas Huth                     gen_fop_DQ(dc, rd, rs2, gen_helper_fqtox);
3765*fcf5ef2aSThomas Huth                     break;
3766*fcf5ef2aSThomas Huth                 case 0x84: /* V9 fxtos */
3767*fcf5ef2aSThomas Huth                     gen_fop_FD(dc, rd, rs2, gen_helper_fxtos);
3768*fcf5ef2aSThomas Huth                     break;
3769*fcf5ef2aSThomas Huth                 case 0x88: /* V9 fxtod */
3770*fcf5ef2aSThomas Huth                     gen_fop_DD(dc, rd, rs2, gen_helper_fxtod);
3771*fcf5ef2aSThomas Huth                     break;
3772*fcf5ef2aSThomas Huth                 case 0x8c: /* V9 fxtoq */
3773*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3774*fcf5ef2aSThomas Huth                     gen_ne_fop_QD(dc, rd, rs2, gen_helper_fxtoq);
3775*fcf5ef2aSThomas Huth                     break;
3776*fcf5ef2aSThomas Huth #endif
3777*fcf5ef2aSThomas Huth                 default:
3778*fcf5ef2aSThomas Huth                     goto illegal_insn;
3779*fcf5ef2aSThomas Huth                 }
3780*fcf5ef2aSThomas Huth             } else if (xop == 0x35) {   /* FPU Operations */
3781*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
3782*fcf5ef2aSThomas Huth                 int cond;
3783*fcf5ef2aSThomas Huth #endif
3784*fcf5ef2aSThomas Huth                 if (gen_trap_ifnofpu(dc)) {
3785*fcf5ef2aSThomas Huth                     goto jmp_insn;
3786*fcf5ef2aSThomas Huth                 }
3787*fcf5ef2aSThomas Huth                 gen_op_clear_ieee_excp_and_FTT();
3788*fcf5ef2aSThomas Huth                 rs1 = GET_FIELD(insn, 13, 17);
3789*fcf5ef2aSThomas Huth                 rs2 = GET_FIELD(insn, 27, 31);
3790*fcf5ef2aSThomas Huth                 xop = GET_FIELD(insn, 18, 26);
3791*fcf5ef2aSThomas Huth 
3792*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
3793*fcf5ef2aSThomas Huth #define FMOVR(sz)                                                  \
3794*fcf5ef2aSThomas Huth                 do {                                               \
3795*fcf5ef2aSThomas Huth                     DisasCompare cmp;                              \
3796*fcf5ef2aSThomas Huth                     cond = GET_FIELD_SP(insn, 10, 12);             \
3797*fcf5ef2aSThomas Huth                     cpu_src1 = get_src1(dc, insn);                 \
3798*fcf5ef2aSThomas Huth                     gen_compare_reg(&cmp, cond, cpu_src1);         \
3799*fcf5ef2aSThomas Huth                     gen_fmov##sz(dc, &cmp, rd, rs2);               \
3800*fcf5ef2aSThomas Huth                     free_compare(&cmp);                            \
3801*fcf5ef2aSThomas Huth                 } while (0)
3802*fcf5ef2aSThomas Huth 
3803*fcf5ef2aSThomas Huth                 if ((xop & 0x11f) == 0x005) { /* V9 fmovsr */
3804*fcf5ef2aSThomas Huth                     FMOVR(s);
3805*fcf5ef2aSThomas Huth                     break;
3806*fcf5ef2aSThomas Huth                 } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
3807*fcf5ef2aSThomas Huth                     FMOVR(d);
3808*fcf5ef2aSThomas Huth                     break;
3809*fcf5ef2aSThomas Huth                 } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
3810*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
3811*fcf5ef2aSThomas Huth                     FMOVR(q);
3812*fcf5ef2aSThomas Huth                     break;
3813*fcf5ef2aSThomas Huth                 }
3814*fcf5ef2aSThomas Huth #undef FMOVR
3815*fcf5ef2aSThomas Huth #endif
3816*fcf5ef2aSThomas Huth                 switch (xop) {
3817*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
3818*fcf5ef2aSThomas Huth #define FMOVCC(fcc, sz)                                                 \
3819*fcf5ef2aSThomas Huth                     do {                                                \
3820*fcf5ef2aSThomas Huth                         DisasCompare cmp;                               \
3821*fcf5ef2aSThomas Huth                         cond = GET_FIELD_SP(insn, 14, 17);              \
3822*fcf5ef2aSThomas Huth                         gen_fcompare(&cmp, fcc, cond);                  \
3823*fcf5ef2aSThomas Huth                         gen_fmov##sz(dc, &cmp, rd, rs2);                \
3824*fcf5ef2aSThomas Huth                         free_compare(&cmp);                             \
3825*fcf5ef2aSThomas Huth                     } while (0)
3826*fcf5ef2aSThomas Huth 
3827*fcf5ef2aSThomas Huth                     case 0x001: /* V9 fmovscc %fcc0 */
3828*fcf5ef2aSThomas Huth                         FMOVCC(0, s);
3829*fcf5ef2aSThomas Huth                         break;
3830*fcf5ef2aSThomas Huth                     case 0x002: /* V9 fmovdcc %fcc0 */
3831*fcf5ef2aSThomas Huth                         FMOVCC(0, d);
3832*fcf5ef2aSThomas Huth                         break;
3833*fcf5ef2aSThomas Huth                     case 0x003: /* V9 fmovqcc %fcc0 */
3834*fcf5ef2aSThomas Huth                         CHECK_FPU_FEATURE(dc, FLOAT128);
3835*fcf5ef2aSThomas Huth                         FMOVCC(0, q);
3836*fcf5ef2aSThomas Huth                         break;
3837*fcf5ef2aSThomas Huth                     case 0x041: /* V9 fmovscc %fcc1 */
3838*fcf5ef2aSThomas Huth                         FMOVCC(1, s);
3839*fcf5ef2aSThomas Huth                         break;
3840*fcf5ef2aSThomas Huth                     case 0x042: /* V9 fmovdcc %fcc1 */
3841*fcf5ef2aSThomas Huth                         FMOVCC(1, d);
3842*fcf5ef2aSThomas Huth                         break;
3843*fcf5ef2aSThomas Huth                     case 0x043: /* V9 fmovqcc %fcc1 */
3844*fcf5ef2aSThomas Huth                         CHECK_FPU_FEATURE(dc, FLOAT128);
3845*fcf5ef2aSThomas Huth                         FMOVCC(1, q);
3846*fcf5ef2aSThomas Huth                         break;
3847*fcf5ef2aSThomas Huth                     case 0x081: /* V9 fmovscc %fcc2 */
3848*fcf5ef2aSThomas Huth                         FMOVCC(2, s);
3849*fcf5ef2aSThomas Huth                         break;
3850*fcf5ef2aSThomas Huth                     case 0x082: /* V9 fmovdcc %fcc2 */
3851*fcf5ef2aSThomas Huth                         FMOVCC(2, d);
3852*fcf5ef2aSThomas Huth                         break;
3853*fcf5ef2aSThomas Huth                     case 0x083: /* V9 fmovqcc %fcc2 */
3854*fcf5ef2aSThomas Huth                         CHECK_FPU_FEATURE(dc, FLOAT128);
3855*fcf5ef2aSThomas Huth                         FMOVCC(2, q);
3856*fcf5ef2aSThomas Huth                         break;
3857*fcf5ef2aSThomas Huth                     case 0x0c1: /* V9 fmovscc %fcc3 */
3858*fcf5ef2aSThomas Huth                         FMOVCC(3, s);
3859*fcf5ef2aSThomas Huth                         break;
3860*fcf5ef2aSThomas Huth                     case 0x0c2: /* V9 fmovdcc %fcc3 */
3861*fcf5ef2aSThomas Huth                         FMOVCC(3, d);
3862*fcf5ef2aSThomas Huth                         break;
3863*fcf5ef2aSThomas Huth                     case 0x0c3: /* V9 fmovqcc %fcc3 */
3864*fcf5ef2aSThomas Huth                         CHECK_FPU_FEATURE(dc, FLOAT128);
3865*fcf5ef2aSThomas Huth                         FMOVCC(3, q);
3866*fcf5ef2aSThomas Huth                         break;
3867*fcf5ef2aSThomas Huth #undef FMOVCC
3868*fcf5ef2aSThomas Huth #define FMOVCC(xcc, sz)                                                 \
3869*fcf5ef2aSThomas Huth                     do {                                                \
3870*fcf5ef2aSThomas Huth                         DisasCompare cmp;                               \
3871*fcf5ef2aSThomas Huth                         cond = GET_FIELD_SP(insn, 14, 17);              \
3872*fcf5ef2aSThomas Huth                         gen_compare(&cmp, xcc, cond, dc);               \
3873*fcf5ef2aSThomas Huth                         gen_fmov##sz(dc, &cmp, rd, rs2);                \
3874*fcf5ef2aSThomas Huth                         free_compare(&cmp);                             \
3875*fcf5ef2aSThomas Huth                     } while (0)
3876*fcf5ef2aSThomas Huth 
3877*fcf5ef2aSThomas Huth                     case 0x101: /* V9 fmovscc %icc */
3878*fcf5ef2aSThomas Huth                         FMOVCC(0, s);
3879*fcf5ef2aSThomas Huth                         break;
3880*fcf5ef2aSThomas Huth                     case 0x102: /* V9 fmovdcc %icc */
3881*fcf5ef2aSThomas Huth                         FMOVCC(0, d);
3882*fcf5ef2aSThomas Huth                         break;
3883*fcf5ef2aSThomas Huth                     case 0x103: /* V9 fmovqcc %icc */
3884*fcf5ef2aSThomas Huth                         CHECK_FPU_FEATURE(dc, FLOAT128);
3885*fcf5ef2aSThomas Huth                         FMOVCC(0, q);
3886*fcf5ef2aSThomas Huth                         break;
3887*fcf5ef2aSThomas Huth                     case 0x181: /* V9 fmovscc %xcc */
3888*fcf5ef2aSThomas Huth                         FMOVCC(1, s);
3889*fcf5ef2aSThomas Huth                         break;
3890*fcf5ef2aSThomas Huth                     case 0x182: /* V9 fmovdcc %xcc */
3891*fcf5ef2aSThomas Huth                         FMOVCC(1, d);
3892*fcf5ef2aSThomas Huth                         break;
3893*fcf5ef2aSThomas Huth                     case 0x183: /* V9 fmovqcc %xcc */
3894*fcf5ef2aSThomas Huth                         CHECK_FPU_FEATURE(dc, FLOAT128);
3895*fcf5ef2aSThomas Huth                         FMOVCC(1, q);
3896*fcf5ef2aSThomas Huth                         break;
3897*fcf5ef2aSThomas Huth #undef FMOVCC
3898*fcf5ef2aSThomas Huth #endif
3899*fcf5ef2aSThomas Huth                     case 0x51: /* fcmps, V9 %fcc */
3900*fcf5ef2aSThomas Huth                         cpu_src1_32 = gen_load_fpr_F(dc, rs1);
3901*fcf5ef2aSThomas Huth                         cpu_src2_32 = gen_load_fpr_F(dc, rs2);
3902*fcf5ef2aSThomas Huth                         gen_op_fcmps(rd & 3, cpu_src1_32, cpu_src2_32);
3903*fcf5ef2aSThomas Huth                         break;
3904*fcf5ef2aSThomas Huth                     case 0x52: /* fcmpd, V9 %fcc */
3905*fcf5ef2aSThomas Huth                         cpu_src1_64 = gen_load_fpr_D(dc, rs1);
3906*fcf5ef2aSThomas Huth                         cpu_src2_64 = gen_load_fpr_D(dc, rs2);
3907*fcf5ef2aSThomas Huth                         gen_op_fcmpd(rd & 3, cpu_src1_64, cpu_src2_64);
3908*fcf5ef2aSThomas Huth                         break;
3909*fcf5ef2aSThomas Huth                     case 0x53: /* fcmpq, V9 %fcc */
3910*fcf5ef2aSThomas Huth                         CHECK_FPU_FEATURE(dc, FLOAT128);
3911*fcf5ef2aSThomas Huth                         gen_op_load_fpr_QT0(QFPREG(rs1));
3912*fcf5ef2aSThomas Huth                         gen_op_load_fpr_QT1(QFPREG(rs2));
3913*fcf5ef2aSThomas Huth                         gen_op_fcmpq(rd & 3);
3914*fcf5ef2aSThomas Huth                         break;
3915*fcf5ef2aSThomas Huth                     case 0x55: /* fcmpes, V9 %fcc */
3916*fcf5ef2aSThomas Huth                         cpu_src1_32 = gen_load_fpr_F(dc, rs1);
3917*fcf5ef2aSThomas Huth                         cpu_src2_32 = gen_load_fpr_F(dc, rs2);
3918*fcf5ef2aSThomas Huth                         gen_op_fcmpes(rd & 3, cpu_src1_32, cpu_src2_32);
3919*fcf5ef2aSThomas Huth                         break;
3920*fcf5ef2aSThomas Huth                     case 0x56: /* fcmped, V9 %fcc */
3921*fcf5ef2aSThomas Huth                         cpu_src1_64 = gen_load_fpr_D(dc, rs1);
3922*fcf5ef2aSThomas Huth                         cpu_src2_64 = gen_load_fpr_D(dc, rs2);
3923*fcf5ef2aSThomas Huth                         gen_op_fcmped(rd & 3, cpu_src1_64, cpu_src2_64);
3924*fcf5ef2aSThomas Huth                         break;
3925*fcf5ef2aSThomas Huth                     case 0x57: /* fcmpeq, V9 %fcc */
3926*fcf5ef2aSThomas Huth                         CHECK_FPU_FEATURE(dc, FLOAT128);
3927*fcf5ef2aSThomas Huth                         gen_op_load_fpr_QT0(QFPREG(rs1));
3928*fcf5ef2aSThomas Huth                         gen_op_load_fpr_QT1(QFPREG(rs2));
3929*fcf5ef2aSThomas Huth                         gen_op_fcmpeq(rd & 3);
3930*fcf5ef2aSThomas Huth                         break;
3931*fcf5ef2aSThomas Huth                     default:
3932*fcf5ef2aSThomas Huth                         goto illegal_insn;
3933*fcf5ef2aSThomas Huth                 }
3934*fcf5ef2aSThomas Huth             } else if (xop == 0x2) {
3935*fcf5ef2aSThomas Huth                 TCGv dst = gen_dest_gpr(dc, rd);
3936*fcf5ef2aSThomas Huth                 rs1 = GET_FIELD(insn, 13, 17);
3937*fcf5ef2aSThomas Huth                 if (rs1 == 0) {
3938*fcf5ef2aSThomas Huth                     /* clr/mov shortcut : or %g0, x, y -> mov x, y */
3939*fcf5ef2aSThomas Huth                     if (IS_IMM) {       /* immediate */
3940*fcf5ef2aSThomas Huth                         simm = GET_FIELDs(insn, 19, 31);
3941*fcf5ef2aSThomas Huth                         tcg_gen_movi_tl(dst, simm);
3942*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, dst);
3943*fcf5ef2aSThomas Huth                     } else {            /* register */
3944*fcf5ef2aSThomas Huth                         rs2 = GET_FIELD(insn, 27, 31);
3945*fcf5ef2aSThomas Huth                         if (rs2 == 0) {
3946*fcf5ef2aSThomas Huth                             tcg_gen_movi_tl(dst, 0);
3947*fcf5ef2aSThomas Huth                             gen_store_gpr(dc, rd, dst);
3948*fcf5ef2aSThomas Huth                         } else {
3949*fcf5ef2aSThomas Huth                             cpu_src2 = gen_load_gpr(dc, rs2);
3950*fcf5ef2aSThomas Huth                             gen_store_gpr(dc, rd, cpu_src2);
3951*fcf5ef2aSThomas Huth                         }
3952*fcf5ef2aSThomas Huth                     }
3953*fcf5ef2aSThomas Huth                 } else {
3954*fcf5ef2aSThomas Huth                     cpu_src1 = get_src1(dc, insn);
3955*fcf5ef2aSThomas Huth                     if (IS_IMM) {       /* immediate */
3956*fcf5ef2aSThomas Huth                         simm = GET_FIELDs(insn, 19, 31);
3957*fcf5ef2aSThomas Huth                         tcg_gen_ori_tl(dst, cpu_src1, simm);
3958*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, dst);
3959*fcf5ef2aSThomas Huth                     } else {            /* register */
3960*fcf5ef2aSThomas Huth                         rs2 = GET_FIELD(insn, 27, 31);
3961*fcf5ef2aSThomas Huth                         if (rs2 == 0) {
3962*fcf5ef2aSThomas Huth                             /* mov shortcut:  or x, %g0, y -> mov x, y */
3963*fcf5ef2aSThomas Huth                             gen_store_gpr(dc, rd, cpu_src1);
3964*fcf5ef2aSThomas Huth                         } else {
3965*fcf5ef2aSThomas Huth                             cpu_src2 = gen_load_gpr(dc, rs2);
3966*fcf5ef2aSThomas Huth                             tcg_gen_or_tl(dst, cpu_src1, cpu_src2);
3967*fcf5ef2aSThomas Huth                             gen_store_gpr(dc, rd, dst);
3968*fcf5ef2aSThomas Huth                         }
3969*fcf5ef2aSThomas Huth                     }
3970*fcf5ef2aSThomas Huth                 }
3971*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
3972*fcf5ef2aSThomas Huth             } else if (xop == 0x25) { /* sll, V9 sllx */
3973*fcf5ef2aSThomas Huth                 cpu_src1 = get_src1(dc, insn);
3974*fcf5ef2aSThomas Huth                 if (IS_IMM) {   /* immediate */
3975*fcf5ef2aSThomas Huth                     simm = GET_FIELDs(insn, 20, 31);
3976*fcf5ef2aSThomas Huth                     if (insn & (1 << 12)) {
3977*fcf5ef2aSThomas Huth                         tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x3f);
3978*fcf5ef2aSThomas Huth                     } else {
3979*fcf5ef2aSThomas Huth                         tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x1f);
3980*fcf5ef2aSThomas Huth                     }
3981*fcf5ef2aSThomas Huth                 } else {                /* register */
3982*fcf5ef2aSThomas Huth                     rs2 = GET_FIELD(insn, 27, 31);
3983*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
3984*fcf5ef2aSThomas Huth                     cpu_tmp0 = get_temp_tl(dc);
3985*fcf5ef2aSThomas Huth                     if (insn & (1 << 12)) {
3986*fcf5ef2aSThomas Huth                         tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
3987*fcf5ef2aSThomas Huth                     } else {
3988*fcf5ef2aSThomas Huth                         tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
3989*fcf5ef2aSThomas Huth                     }
3990*fcf5ef2aSThomas Huth                     tcg_gen_shl_i64(cpu_dst, cpu_src1, cpu_tmp0);
3991*fcf5ef2aSThomas Huth                 }
3992*fcf5ef2aSThomas Huth                 gen_store_gpr(dc, rd, cpu_dst);
3993*fcf5ef2aSThomas Huth             } else if (xop == 0x26) { /* srl, V9 srlx */
3994*fcf5ef2aSThomas Huth                 cpu_src1 = get_src1(dc, insn);
3995*fcf5ef2aSThomas Huth                 if (IS_IMM) {   /* immediate */
3996*fcf5ef2aSThomas Huth                     simm = GET_FIELDs(insn, 20, 31);
3997*fcf5ef2aSThomas Huth                     if (insn & (1 << 12)) {
3998*fcf5ef2aSThomas Huth                         tcg_gen_shri_i64(cpu_dst, cpu_src1, simm & 0x3f);
3999*fcf5ef2aSThomas Huth                     } else {
4000*fcf5ef2aSThomas Huth                         tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
4001*fcf5ef2aSThomas Huth                         tcg_gen_shri_i64(cpu_dst, cpu_dst, simm & 0x1f);
4002*fcf5ef2aSThomas Huth                     }
4003*fcf5ef2aSThomas Huth                 } else {                /* register */
4004*fcf5ef2aSThomas Huth                     rs2 = GET_FIELD(insn, 27, 31);
4005*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4006*fcf5ef2aSThomas Huth                     cpu_tmp0 = get_temp_tl(dc);
4007*fcf5ef2aSThomas Huth                     if (insn & (1 << 12)) {
4008*fcf5ef2aSThomas Huth                         tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
4009*fcf5ef2aSThomas Huth                         tcg_gen_shr_i64(cpu_dst, cpu_src1, cpu_tmp0);
4010*fcf5ef2aSThomas Huth                     } else {
4011*fcf5ef2aSThomas Huth                         tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
4012*fcf5ef2aSThomas Huth                         tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
4013*fcf5ef2aSThomas Huth                         tcg_gen_shr_i64(cpu_dst, cpu_dst, cpu_tmp0);
4014*fcf5ef2aSThomas Huth                     }
4015*fcf5ef2aSThomas Huth                 }
4016*fcf5ef2aSThomas Huth                 gen_store_gpr(dc, rd, cpu_dst);
4017*fcf5ef2aSThomas Huth             } else if (xop == 0x27) { /* sra, V9 srax */
4018*fcf5ef2aSThomas Huth                 cpu_src1 = get_src1(dc, insn);
4019*fcf5ef2aSThomas Huth                 if (IS_IMM) {   /* immediate */
4020*fcf5ef2aSThomas Huth                     simm = GET_FIELDs(insn, 20, 31);
4021*fcf5ef2aSThomas Huth                     if (insn & (1 << 12)) {
4022*fcf5ef2aSThomas Huth                         tcg_gen_sari_i64(cpu_dst, cpu_src1, simm & 0x3f);
4023*fcf5ef2aSThomas Huth                     } else {
4024*fcf5ef2aSThomas Huth                         tcg_gen_ext32s_i64(cpu_dst, cpu_src1);
4025*fcf5ef2aSThomas Huth                         tcg_gen_sari_i64(cpu_dst, cpu_dst, simm & 0x1f);
4026*fcf5ef2aSThomas Huth                     }
4027*fcf5ef2aSThomas Huth                 } else {                /* register */
4028*fcf5ef2aSThomas Huth                     rs2 = GET_FIELD(insn, 27, 31);
4029*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4030*fcf5ef2aSThomas Huth                     cpu_tmp0 = get_temp_tl(dc);
4031*fcf5ef2aSThomas Huth                     if (insn & (1 << 12)) {
4032*fcf5ef2aSThomas Huth                         tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
4033*fcf5ef2aSThomas Huth                         tcg_gen_sar_i64(cpu_dst, cpu_src1, cpu_tmp0);
4034*fcf5ef2aSThomas Huth                     } else {
4035*fcf5ef2aSThomas Huth                         tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
4036*fcf5ef2aSThomas Huth                         tcg_gen_ext32s_i64(cpu_dst, cpu_src1);
4037*fcf5ef2aSThomas Huth                         tcg_gen_sar_i64(cpu_dst, cpu_dst, cpu_tmp0);
4038*fcf5ef2aSThomas Huth                     }
4039*fcf5ef2aSThomas Huth                 }
4040*fcf5ef2aSThomas Huth                 gen_store_gpr(dc, rd, cpu_dst);
4041*fcf5ef2aSThomas Huth #endif
4042*fcf5ef2aSThomas Huth             } else if (xop < 0x36) {
4043*fcf5ef2aSThomas Huth                 if (xop < 0x20) {
4044*fcf5ef2aSThomas Huth                     cpu_src1 = get_src1(dc, insn);
4045*fcf5ef2aSThomas Huth                     cpu_src2 = get_src2(dc, insn);
4046*fcf5ef2aSThomas Huth                     switch (xop & ~0x10) {
4047*fcf5ef2aSThomas Huth                     case 0x0: /* add */
4048*fcf5ef2aSThomas Huth                         if (xop & 0x10) {
4049*fcf5ef2aSThomas Huth                             gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2);
4050*fcf5ef2aSThomas Huth                             tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
4051*fcf5ef2aSThomas Huth                             dc->cc_op = CC_OP_ADD;
4052*fcf5ef2aSThomas Huth                         } else {
4053*fcf5ef2aSThomas Huth                             tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
4054*fcf5ef2aSThomas Huth                         }
4055*fcf5ef2aSThomas Huth                         break;
4056*fcf5ef2aSThomas Huth                     case 0x1: /* and */
4057*fcf5ef2aSThomas Huth                         tcg_gen_and_tl(cpu_dst, cpu_src1, cpu_src2);
4058*fcf5ef2aSThomas Huth                         if (xop & 0x10) {
4059*fcf5ef2aSThomas Huth                             tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
4060*fcf5ef2aSThomas Huth                             tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
4061*fcf5ef2aSThomas Huth                             dc->cc_op = CC_OP_LOGIC;
4062*fcf5ef2aSThomas Huth                         }
4063*fcf5ef2aSThomas Huth                         break;
4064*fcf5ef2aSThomas Huth                     case 0x2: /* or */
4065*fcf5ef2aSThomas Huth                         tcg_gen_or_tl(cpu_dst, cpu_src1, cpu_src2);
4066*fcf5ef2aSThomas Huth                         if (xop & 0x10) {
4067*fcf5ef2aSThomas Huth                             tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
4068*fcf5ef2aSThomas Huth                             tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
4069*fcf5ef2aSThomas Huth                             dc->cc_op = CC_OP_LOGIC;
4070*fcf5ef2aSThomas Huth                         }
4071*fcf5ef2aSThomas Huth                         break;
4072*fcf5ef2aSThomas Huth                     case 0x3: /* xor */
4073*fcf5ef2aSThomas Huth                         tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
4074*fcf5ef2aSThomas Huth                         if (xop & 0x10) {
4075*fcf5ef2aSThomas Huth                             tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
4076*fcf5ef2aSThomas Huth                             tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
4077*fcf5ef2aSThomas Huth                             dc->cc_op = CC_OP_LOGIC;
4078*fcf5ef2aSThomas Huth                         }
4079*fcf5ef2aSThomas Huth                         break;
4080*fcf5ef2aSThomas Huth                     case 0x4: /* sub */
4081*fcf5ef2aSThomas Huth                         if (xop & 0x10) {
4082*fcf5ef2aSThomas Huth                             gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2);
4083*fcf5ef2aSThomas Huth                             tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB);
4084*fcf5ef2aSThomas Huth                             dc->cc_op = CC_OP_SUB;
4085*fcf5ef2aSThomas Huth                         } else {
4086*fcf5ef2aSThomas Huth                             tcg_gen_sub_tl(cpu_dst, cpu_src1, cpu_src2);
4087*fcf5ef2aSThomas Huth                         }
4088*fcf5ef2aSThomas Huth                         break;
4089*fcf5ef2aSThomas Huth                     case 0x5: /* andn */
4090*fcf5ef2aSThomas Huth                         tcg_gen_andc_tl(cpu_dst, cpu_src1, cpu_src2);
4091*fcf5ef2aSThomas Huth                         if (xop & 0x10) {
4092*fcf5ef2aSThomas Huth                             tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
4093*fcf5ef2aSThomas Huth                             tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
4094*fcf5ef2aSThomas Huth                             dc->cc_op = CC_OP_LOGIC;
4095*fcf5ef2aSThomas Huth                         }
4096*fcf5ef2aSThomas Huth                         break;
4097*fcf5ef2aSThomas Huth                     case 0x6: /* orn */
4098*fcf5ef2aSThomas Huth                         tcg_gen_orc_tl(cpu_dst, cpu_src1, cpu_src2);
4099*fcf5ef2aSThomas Huth                         if (xop & 0x10) {
4100*fcf5ef2aSThomas Huth                             tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
4101*fcf5ef2aSThomas Huth                             tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
4102*fcf5ef2aSThomas Huth                             dc->cc_op = CC_OP_LOGIC;
4103*fcf5ef2aSThomas Huth                         }
4104*fcf5ef2aSThomas Huth                         break;
4105*fcf5ef2aSThomas Huth                     case 0x7: /* xorn */
4106*fcf5ef2aSThomas Huth                         tcg_gen_eqv_tl(cpu_dst, cpu_src1, cpu_src2);
4107*fcf5ef2aSThomas Huth                         if (xop & 0x10) {
4108*fcf5ef2aSThomas Huth                             tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
4109*fcf5ef2aSThomas Huth                             tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
4110*fcf5ef2aSThomas Huth                             dc->cc_op = CC_OP_LOGIC;
4111*fcf5ef2aSThomas Huth                         }
4112*fcf5ef2aSThomas Huth                         break;
4113*fcf5ef2aSThomas Huth                     case 0x8: /* addx, V9 addc */
4114*fcf5ef2aSThomas Huth                         gen_op_addx_int(dc, cpu_dst, cpu_src1, cpu_src2,
4115*fcf5ef2aSThomas Huth                                         (xop & 0x10));
4116*fcf5ef2aSThomas Huth                         break;
4117*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
4118*fcf5ef2aSThomas Huth                     case 0x9: /* V9 mulx */
4119*fcf5ef2aSThomas Huth                         tcg_gen_mul_i64(cpu_dst, cpu_src1, cpu_src2);
4120*fcf5ef2aSThomas Huth                         break;
4121*fcf5ef2aSThomas Huth #endif
4122*fcf5ef2aSThomas Huth                     case 0xa: /* umul */
4123*fcf5ef2aSThomas Huth                         CHECK_IU_FEATURE(dc, MUL);
4124*fcf5ef2aSThomas Huth                         gen_op_umul(cpu_dst, cpu_src1, cpu_src2);
4125*fcf5ef2aSThomas Huth                         if (xop & 0x10) {
4126*fcf5ef2aSThomas Huth                             tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
4127*fcf5ef2aSThomas Huth                             tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
4128*fcf5ef2aSThomas Huth                             dc->cc_op = CC_OP_LOGIC;
4129*fcf5ef2aSThomas Huth                         }
4130*fcf5ef2aSThomas Huth                         break;
4131*fcf5ef2aSThomas Huth                     case 0xb: /* smul */
4132*fcf5ef2aSThomas Huth                         CHECK_IU_FEATURE(dc, MUL);
4133*fcf5ef2aSThomas Huth                         gen_op_smul(cpu_dst, cpu_src1, cpu_src2);
4134*fcf5ef2aSThomas Huth                         if (xop & 0x10) {
4135*fcf5ef2aSThomas Huth                             tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
4136*fcf5ef2aSThomas Huth                             tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
4137*fcf5ef2aSThomas Huth                             dc->cc_op = CC_OP_LOGIC;
4138*fcf5ef2aSThomas Huth                         }
4139*fcf5ef2aSThomas Huth                         break;
4140*fcf5ef2aSThomas Huth                     case 0xc: /* subx, V9 subc */
4141*fcf5ef2aSThomas Huth                         gen_op_subx_int(dc, cpu_dst, cpu_src1, cpu_src2,
4142*fcf5ef2aSThomas Huth                                         (xop & 0x10));
4143*fcf5ef2aSThomas Huth                         break;
4144*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
4145*fcf5ef2aSThomas Huth                     case 0xd: /* V9 udivx */
4146*fcf5ef2aSThomas Huth                         gen_helper_udivx(cpu_dst, cpu_env, cpu_src1, cpu_src2);
4147*fcf5ef2aSThomas Huth                         break;
4148*fcf5ef2aSThomas Huth #endif
4149*fcf5ef2aSThomas Huth                     case 0xe: /* udiv */
4150*fcf5ef2aSThomas Huth                         CHECK_IU_FEATURE(dc, DIV);
4151*fcf5ef2aSThomas Huth                         if (xop & 0x10) {
4152*fcf5ef2aSThomas Huth                             gen_helper_udiv_cc(cpu_dst, cpu_env, cpu_src1,
4153*fcf5ef2aSThomas Huth                                                cpu_src2);
4154*fcf5ef2aSThomas Huth                             dc->cc_op = CC_OP_DIV;
4155*fcf5ef2aSThomas Huth                         } else {
4156*fcf5ef2aSThomas Huth                             gen_helper_udiv(cpu_dst, cpu_env, cpu_src1,
4157*fcf5ef2aSThomas Huth                                             cpu_src2);
4158*fcf5ef2aSThomas Huth                         }
4159*fcf5ef2aSThomas Huth                         break;
4160*fcf5ef2aSThomas Huth                     case 0xf: /* sdiv */
4161*fcf5ef2aSThomas Huth                         CHECK_IU_FEATURE(dc, DIV);
4162*fcf5ef2aSThomas Huth                         if (xop & 0x10) {
4163*fcf5ef2aSThomas Huth                             gen_helper_sdiv_cc(cpu_dst, cpu_env, cpu_src1,
4164*fcf5ef2aSThomas Huth                                                cpu_src2);
4165*fcf5ef2aSThomas Huth                             dc->cc_op = CC_OP_DIV;
4166*fcf5ef2aSThomas Huth                         } else {
4167*fcf5ef2aSThomas Huth                             gen_helper_sdiv(cpu_dst, cpu_env, cpu_src1,
4168*fcf5ef2aSThomas Huth                                             cpu_src2);
4169*fcf5ef2aSThomas Huth                         }
4170*fcf5ef2aSThomas Huth                         break;
4171*fcf5ef2aSThomas Huth                     default:
4172*fcf5ef2aSThomas Huth                         goto illegal_insn;
4173*fcf5ef2aSThomas Huth                     }
4174*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4175*fcf5ef2aSThomas Huth                 } else {
4176*fcf5ef2aSThomas Huth                     cpu_src1 = get_src1(dc, insn);
4177*fcf5ef2aSThomas Huth                     cpu_src2 = get_src2(dc, insn);
4178*fcf5ef2aSThomas Huth                     switch (xop) {
4179*fcf5ef2aSThomas Huth                     case 0x20: /* taddcc */
4180*fcf5ef2aSThomas Huth                         gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2);
4181*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, cpu_dst);
4182*fcf5ef2aSThomas Huth                         tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADD);
4183*fcf5ef2aSThomas Huth                         dc->cc_op = CC_OP_TADD;
4184*fcf5ef2aSThomas Huth                         break;
4185*fcf5ef2aSThomas Huth                     case 0x21: /* tsubcc */
4186*fcf5ef2aSThomas Huth                         gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2);
4187*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, cpu_dst);
4188*fcf5ef2aSThomas Huth                         tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUB);
4189*fcf5ef2aSThomas Huth                         dc->cc_op = CC_OP_TSUB;
4190*fcf5ef2aSThomas Huth                         break;
4191*fcf5ef2aSThomas Huth                     case 0x22: /* taddcctv */
4192*fcf5ef2aSThomas Huth                         gen_helper_taddcctv(cpu_dst, cpu_env,
4193*fcf5ef2aSThomas Huth                                             cpu_src1, cpu_src2);
4194*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, cpu_dst);
4195*fcf5ef2aSThomas Huth                         dc->cc_op = CC_OP_TADDTV;
4196*fcf5ef2aSThomas Huth                         break;
4197*fcf5ef2aSThomas Huth                     case 0x23: /* tsubcctv */
4198*fcf5ef2aSThomas Huth                         gen_helper_tsubcctv(cpu_dst, cpu_env,
4199*fcf5ef2aSThomas Huth                                             cpu_src1, cpu_src2);
4200*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, cpu_dst);
4201*fcf5ef2aSThomas Huth                         dc->cc_op = CC_OP_TSUBTV;
4202*fcf5ef2aSThomas Huth                         break;
4203*fcf5ef2aSThomas Huth                     case 0x24: /* mulscc */
4204*fcf5ef2aSThomas Huth                         update_psr(dc);
4205*fcf5ef2aSThomas Huth                         gen_op_mulscc(cpu_dst, cpu_src1, cpu_src2);
4206*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, cpu_dst);
4207*fcf5ef2aSThomas Huth                         tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
4208*fcf5ef2aSThomas Huth                         dc->cc_op = CC_OP_ADD;
4209*fcf5ef2aSThomas Huth                         break;
4210*fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64
4211*fcf5ef2aSThomas Huth                     case 0x25:  /* sll */
4212*fcf5ef2aSThomas Huth                         if (IS_IMM) { /* immediate */
4213*fcf5ef2aSThomas Huth                             simm = GET_FIELDs(insn, 20, 31);
4214*fcf5ef2aSThomas Huth                             tcg_gen_shli_tl(cpu_dst, cpu_src1, simm & 0x1f);
4215*fcf5ef2aSThomas Huth                         } else { /* register */
4216*fcf5ef2aSThomas Huth                             cpu_tmp0 = get_temp_tl(dc);
4217*fcf5ef2aSThomas Huth                             tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
4218*fcf5ef2aSThomas Huth                             tcg_gen_shl_tl(cpu_dst, cpu_src1, cpu_tmp0);
4219*fcf5ef2aSThomas Huth                         }
4220*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, cpu_dst);
4221*fcf5ef2aSThomas Huth                         break;
4222*fcf5ef2aSThomas Huth                     case 0x26:  /* srl */
4223*fcf5ef2aSThomas Huth                         if (IS_IMM) { /* immediate */
4224*fcf5ef2aSThomas Huth                             simm = GET_FIELDs(insn, 20, 31);
4225*fcf5ef2aSThomas Huth                             tcg_gen_shri_tl(cpu_dst, cpu_src1, simm & 0x1f);
4226*fcf5ef2aSThomas Huth                         } else { /* register */
4227*fcf5ef2aSThomas Huth                             cpu_tmp0 = get_temp_tl(dc);
4228*fcf5ef2aSThomas Huth                             tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
4229*fcf5ef2aSThomas Huth                             tcg_gen_shr_tl(cpu_dst, cpu_src1, cpu_tmp0);
4230*fcf5ef2aSThomas Huth                         }
4231*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, cpu_dst);
4232*fcf5ef2aSThomas Huth                         break;
4233*fcf5ef2aSThomas Huth                     case 0x27:  /* sra */
4234*fcf5ef2aSThomas Huth                         if (IS_IMM) { /* immediate */
4235*fcf5ef2aSThomas Huth                             simm = GET_FIELDs(insn, 20, 31);
4236*fcf5ef2aSThomas Huth                             tcg_gen_sari_tl(cpu_dst, cpu_src1, simm & 0x1f);
4237*fcf5ef2aSThomas Huth                         } else { /* register */
4238*fcf5ef2aSThomas Huth                             cpu_tmp0 = get_temp_tl(dc);
4239*fcf5ef2aSThomas Huth                             tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
4240*fcf5ef2aSThomas Huth                             tcg_gen_sar_tl(cpu_dst, cpu_src1, cpu_tmp0);
4241*fcf5ef2aSThomas Huth                         }
4242*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, cpu_dst);
4243*fcf5ef2aSThomas Huth                         break;
4244*fcf5ef2aSThomas Huth #endif
4245*fcf5ef2aSThomas Huth                     case 0x30:
4246*fcf5ef2aSThomas Huth                         {
4247*fcf5ef2aSThomas Huth                             cpu_tmp0 = get_temp_tl(dc);
4248*fcf5ef2aSThomas Huth                             switch(rd) {
4249*fcf5ef2aSThomas Huth                             case 0: /* wry */
4250*fcf5ef2aSThomas Huth                                 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4251*fcf5ef2aSThomas Huth                                 tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
4252*fcf5ef2aSThomas Huth                                 break;
4253*fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64
4254*fcf5ef2aSThomas Huth                             case 0x01 ... 0x0f: /* undefined in the
4255*fcf5ef2aSThomas Huth                                                    SPARCv8 manual, nop
4256*fcf5ef2aSThomas Huth                                                    on the microSPARC
4257*fcf5ef2aSThomas Huth                                                    II */
4258*fcf5ef2aSThomas Huth                             case 0x10 ... 0x1f: /* implementation-dependent
4259*fcf5ef2aSThomas Huth                                                    in the SPARCv8
4260*fcf5ef2aSThomas Huth                                                    manual, nop on the
4261*fcf5ef2aSThomas Huth                                                    microSPARC II */
4262*fcf5ef2aSThomas Huth                                 if ((rd == 0x13) && (dc->def->features &
4263*fcf5ef2aSThomas Huth                                                      CPU_FEATURE_POWERDOWN)) {
4264*fcf5ef2aSThomas Huth                                     /* LEON3 power-down */
4265*fcf5ef2aSThomas Huth                                     save_state(dc);
4266*fcf5ef2aSThomas Huth                                     gen_helper_power_down(cpu_env);
4267*fcf5ef2aSThomas Huth                                 }
4268*fcf5ef2aSThomas Huth                                 break;
4269*fcf5ef2aSThomas Huth #else
4270*fcf5ef2aSThomas Huth                             case 0x2: /* V9 wrccr */
4271*fcf5ef2aSThomas Huth                                 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4272*fcf5ef2aSThomas Huth                                 gen_helper_wrccr(cpu_env, cpu_tmp0);
4273*fcf5ef2aSThomas Huth                                 tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
4274*fcf5ef2aSThomas Huth                                 dc->cc_op = CC_OP_FLAGS;
4275*fcf5ef2aSThomas Huth                                 break;
4276*fcf5ef2aSThomas Huth                             case 0x3: /* V9 wrasi */
4277*fcf5ef2aSThomas Huth                                 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4278*fcf5ef2aSThomas Huth                                 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xff);
4279*fcf5ef2aSThomas Huth                                 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
4280*fcf5ef2aSThomas Huth                                                 offsetof(CPUSPARCState, asi));
4281*fcf5ef2aSThomas Huth                                 /* End TB to notice changed ASI.  */
4282*fcf5ef2aSThomas Huth                                 save_state(dc);
4283*fcf5ef2aSThomas Huth                                 gen_op_next_insn();
4284*fcf5ef2aSThomas Huth                                 tcg_gen_exit_tb(0);
4285*fcf5ef2aSThomas Huth                                 dc->is_br = 1;
4286*fcf5ef2aSThomas Huth                                 break;
4287*fcf5ef2aSThomas Huth                             case 0x6: /* V9 wrfprs */
4288*fcf5ef2aSThomas Huth                                 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4289*fcf5ef2aSThomas Huth                                 tcg_gen_trunc_tl_i32(cpu_fprs, cpu_tmp0);
4290*fcf5ef2aSThomas Huth                                 dc->fprs_dirty = 0;
4291*fcf5ef2aSThomas Huth                                 save_state(dc);
4292*fcf5ef2aSThomas Huth                                 gen_op_next_insn();
4293*fcf5ef2aSThomas Huth                                 tcg_gen_exit_tb(0);
4294*fcf5ef2aSThomas Huth                                 dc->is_br = 1;
4295*fcf5ef2aSThomas Huth                                 break;
4296*fcf5ef2aSThomas Huth                             case 0xf: /* V9 sir, nop if user */
4297*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY)
4298*fcf5ef2aSThomas Huth                                 if (supervisor(dc)) {
4299*fcf5ef2aSThomas Huth                                     ; // XXX
4300*fcf5ef2aSThomas Huth                                 }
4301*fcf5ef2aSThomas Huth #endif
4302*fcf5ef2aSThomas Huth                                 break;
4303*fcf5ef2aSThomas Huth                             case 0x13: /* Graphics Status */
4304*fcf5ef2aSThomas Huth                                 if (gen_trap_ifnofpu(dc)) {
4305*fcf5ef2aSThomas Huth                                     goto jmp_insn;
4306*fcf5ef2aSThomas Huth                                 }
4307*fcf5ef2aSThomas Huth                                 tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2);
4308*fcf5ef2aSThomas Huth                                 break;
4309*fcf5ef2aSThomas Huth                             case 0x14: /* Softint set */
4310*fcf5ef2aSThomas Huth                                 if (!supervisor(dc))
4311*fcf5ef2aSThomas Huth                                     goto illegal_insn;
4312*fcf5ef2aSThomas Huth                                 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4313*fcf5ef2aSThomas Huth                                 gen_helper_set_softint(cpu_env, cpu_tmp0);
4314*fcf5ef2aSThomas Huth                                 break;
4315*fcf5ef2aSThomas Huth                             case 0x15: /* Softint clear */
4316*fcf5ef2aSThomas Huth                                 if (!supervisor(dc))
4317*fcf5ef2aSThomas Huth                                     goto illegal_insn;
4318*fcf5ef2aSThomas Huth                                 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4319*fcf5ef2aSThomas Huth                                 gen_helper_clear_softint(cpu_env, cpu_tmp0);
4320*fcf5ef2aSThomas Huth                                 break;
4321*fcf5ef2aSThomas Huth                             case 0x16: /* Softint write */
4322*fcf5ef2aSThomas Huth                                 if (!supervisor(dc))
4323*fcf5ef2aSThomas Huth                                     goto illegal_insn;
4324*fcf5ef2aSThomas Huth                                 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4325*fcf5ef2aSThomas Huth                                 gen_helper_write_softint(cpu_env, cpu_tmp0);
4326*fcf5ef2aSThomas Huth                                 break;
4327*fcf5ef2aSThomas Huth                             case 0x17: /* Tick compare */
4328*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY)
4329*fcf5ef2aSThomas Huth                                 if (!supervisor(dc))
4330*fcf5ef2aSThomas Huth                                     goto illegal_insn;
4331*fcf5ef2aSThomas Huth #endif
4332*fcf5ef2aSThomas Huth                                 {
4333*fcf5ef2aSThomas Huth                                     TCGv_ptr r_tickptr;
4334*fcf5ef2aSThomas Huth 
4335*fcf5ef2aSThomas Huth                                     tcg_gen_xor_tl(cpu_tick_cmpr, cpu_src1,
4336*fcf5ef2aSThomas Huth                                                    cpu_src2);
4337*fcf5ef2aSThomas Huth                                     r_tickptr = tcg_temp_new_ptr();
4338*fcf5ef2aSThomas Huth                                     tcg_gen_ld_ptr(r_tickptr, cpu_env,
4339*fcf5ef2aSThomas Huth                                                    offsetof(CPUSPARCState, tick));
4340*fcf5ef2aSThomas Huth                                     gen_helper_tick_set_limit(r_tickptr,
4341*fcf5ef2aSThomas Huth                                                               cpu_tick_cmpr);
4342*fcf5ef2aSThomas Huth                                     tcg_temp_free_ptr(r_tickptr);
4343*fcf5ef2aSThomas Huth                                 }
4344*fcf5ef2aSThomas Huth                                 break;
4345*fcf5ef2aSThomas Huth                             case 0x18: /* System tick */
4346*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY)
4347*fcf5ef2aSThomas Huth                                 if (!supervisor(dc))
4348*fcf5ef2aSThomas Huth                                     goto illegal_insn;
4349*fcf5ef2aSThomas Huth #endif
4350*fcf5ef2aSThomas Huth                                 {
4351*fcf5ef2aSThomas Huth                                     TCGv_ptr r_tickptr;
4352*fcf5ef2aSThomas Huth 
4353*fcf5ef2aSThomas Huth                                     tcg_gen_xor_tl(cpu_tmp0, cpu_src1,
4354*fcf5ef2aSThomas Huth                                                    cpu_src2);
4355*fcf5ef2aSThomas Huth                                     r_tickptr = tcg_temp_new_ptr();
4356*fcf5ef2aSThomas Huth                                     tcg_gen_ld_ptr(r_tickptr, cpu_env,
4357*fcf5ef2aSThomas Huth                                                    offsetof(CPUSPARCState, stick));
4358*fcf5ef2aSThomas Huth                                     gen_helper_tick_set_count(r_tickptr,
4359*fcf5ef2aSThomas Huth                                                               cpu_tmp0);
4360*fcf5ef2aSThomas Huth                                     tcg_temp_free_ptr(r_tickptr);
4361*fcf5ef2aSThomas Huth                                 }
4362*fcf5ef2aSThomas Huth                                 break;
4363*fcf5ef2aSThomas Huth                             case 0x19: /* System tick compare */
4364*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY)
4365*fcf5ef2aSThomas Huth                                 if (!supervisor(dc))
4366*fcf5ef2aSThomas Huth                                     goto illegal_insn;
4367*fcf5ef2aSThomas Huth #endif
4368*fcf5ef2aSThomas Huth                                 {
4369*fcf5ef2aSThomas Huth                                     TCGv_ptr r_tickptr;
4370*fcf5ef2aSThomas Huth 
4371*fcf5ef2aSThomas Huth                                     tcg_gen_xor_tl(cpu_stick_cmpr, cpu_src1,
4372*fcf5ef2aSThomas Huth                                                    cpu_src2);
4373*fcf5ef2aSThomas Huth                                     r_tickptr = tcg_temp_new_ptr();
4374*fcf5ef2aSThomas Huth                                     tcg_gen_ld_ptr(r_tickptr, cpu_env,
4375*fcf5ef2aSThomas Huth                                                    offsetof(CPUSPARCState, stick));
4376*fcf5ef2aSThomas Huth                                     gen_helper_tick_set_limit(r_tickptr,
4377*fcf5ef2aSThomas Huth                                                               cpu_stick_cmpr);
4378*fcf5ef2aSThomas Huth                                     tcg_temp_free_ptr(r_tickptr);
4379*fcf5ef2aSThomas Huth                                 }
4380*fcf5ef2aSThomas Huth                                 break;
4381*fcf5ef2aSThomas Huth 
4382*fcf5ef2aSThomas Huth                             case 0x10: /* Performance Control */
4383*fcf5ef2aSThomas Huth                             case 0x11: /* Performance Instrumentation
4384*fcf5ef2aSThomas Huth                                           Counter */
4385*fcf5ef2aSThomas Huth                             case 0x12: /* Dispatch Control */
4386*fcf5ef2aSThomas Huth #endif
4387*fcf5ef2aSThomas Huth                             default:
4388*fcf5ef2aSThomas Huth                                 goto illegal_insn;
4389*fcf5ef2aSThomas Huth                             }
4390*fcf5ef2aSThomas Huth                         }
4391*fcf5ef2aSThomas Huth                         break;
4392*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY)
4393*fcf5ef2aSThomas Huth                     case 0x31: /* wrpsr, V9 saved, restored */
4394*fcf5ef2aSThomas Huth                         {
4395*fcf5ef2aSThomas Huth                             if (!supervisor(dc))
4396*fcf5ef2aSThomas Huth                                 goto priv_insn;
4397*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
4398*fcf5ef2aSThomas Huth                             switch (rd) {
4399*fcf5ef2aSThomas Huth                             case 0:
4400*fcf5ef2aSThomas Huth                                 gen_helper_saved(cpu_env);
4401*fcf5ef2aSThomas Huth                                 break;
4402*fcf5ef2aSThomas Huth                             case 1:
4403*fcf5ef2aSThomas Huth                                 gen_helper_restored(cpu_env);
4404*fcf5ef2aSThomas Huth                                 break;
4405*fcf5ef2aSThomas Huth                             case 2: /* UA2005 allclean */
4406*fcf5ef2aSThomas Huth                             case 3: /* UA2005 otherw */
4407*fcf5ef2aSThomas Huth                             case 4: /* UA2005 normalw */
4408*fcf5ef2aSThomas Huth                             case 5: /* UA2005 invalw */
4409*fcf5ef2aSThomas Huth                                 // XXX
4410*fcf5ef2aSThomas Huth                             default:
4411*fcf5ef2aSThomas Huth                                 goto illegal_insn;
4412*fcf5ef2aSThomas Huth                             }
4413*fcf5ef2aSThomas Huth #else
4414*fcf5ef2aSThomas Huth                             cpu_tmp0 = get_temp_tl(dc);
4415*fcf5ef2aSThomas Huth                             tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4416*fcf5ef2aSThomas Huth                             gen_helper_wrpsr(cpu_env, cpu_tmp0);
4417*fcf5ef2aSThomas Huth                             tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
4418*fcf5ef2aSThomas Huth                             dc->cc_op = CC_OP_FLAGS;
4419*fcf5ef2aSThomas Huth                             save_state(dc);
4420*fcf5ef2aSThomas Huth                             gen_op_next_insn();
4421*fcf5ef2aSThomas Huth                             tcg_gen_exit_tb(0);
4422*fcf5ef2aSThomas Huth                             dc->is_br = 1;
4423*fcf5ef2aSThomas Huth #endif
4424*fcf5ef2aSThomas Huth                         }
4425*fcf5ef2aSThomas Huth                         break;
4426*fcf5ef2aSThomas Huth                     case 0x32: /* wrwim, V9 wrpr */
4427*fcf5ef2aSThomas Huth                         {
4428*fcf5ef2aSThomas Huth                             if (!supervisor(dc))
4429*fcf5ef2aSThomas Huth                                 goto priv_insn;
4430*fcf5ef2aSThomas Huth                             cpu_tmp0 = get_temp_tl(dc);
4431*fcf5ef2aSThomas Huth                             tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4432*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
4433*fcf5ef2aSThomas Huth                             switch (rd) {
4434*fcf5ef2aSThomas Huth                             case 0: // tpc
4435*fcf5ef2aSThomas Huth                                 {
4436*fcf5ef2aSThomas Huth                                     TCGv_ptr r_tsptr;
4437*fcf5ef2aSThomas Huth 
4438*fcf5ef2aSThomas Huth                                     r_tsptr = tcg_temp_new_ptr();
4439*fcf5ef2aSThomas Huth                                     gen_load_trap_state_at_tl(r_tsptr, cpu_env);
4440*fcf5ef2aSThomas Huth                                     tcg_gen_st_tl(cpu_tmp0, r_tsptr,
4441*fcf5ef2aSThomas Huth                                                   offsetof(trap_state, tpc));
4442*fcf5ef2aSThomas Huth                                     tcg_temp_free_ptr(r_tsptr);
4443*fcf5ef2aSThomas Huth                                 }
4444*fcf5ef2aSThomas Huth                                 break;
4445*fcf5ef2aSThomas Huth                             case 1: // tnpc
4446*fcf5ef2aSThomas Huth                                 {
4447*fcf5ef2aSThomas Huth                                     TCGv_ptr r_tsptr;
4448*fcf5ef2aSThomas Huth 
4449*fcf5ef2aSThomas Huth                                     r_tsptr = tcg_temp_new_ptr();
4450*fcf5ef2aSThomas Huth                                     gen_load_trap_state_at_tl(r_tsptr, cpu_env);
4451*fcf5ef2aSThomas Huth                                     tcg_gen_st_tl(cpu_tmp0, r_tsptr,
4452*fcf5ef2aSThomas Huth                                                   offsetof(trap_state, tnpc));
4453*fcf5ef2aSThomas Huth                                     tcg_temp_free_ptr(r_tsptr);
4454*fcf5ef2aSThomas Huth                                 }
4455*fcf5ef2aSThomas Huth                                 break;
4456*fcf5ef2aSThomas Huth                             case 2: // tstate
4457*fcf5ef2aSThomas Huth                                 {
4458*fcf5ef2aSThomas Huth                                     TCGv_ptr r_tsptr;
4459*fcf5ef2aSThomas Huth 
4460*fcf5ef2aSThomas Huth                                     r_tsptr = tcg_temp_new_ptr();
4461*fcf5ef2aSThomas Huth                                     gen_load_trap_state_at_tl(r_tsptr, cpu_env);
4462*fcf5ef2aSThomas Huth                                     tcg_gen_st_tl(cpu_tmp0, r_tsptr,
4463*fcf5ef2aSThomas Huth                                                   offsetof(trap_state,
4464*fcf5ef2aSThomas Huth                                                            tstate));
4465*fcf5ef2aSThomas Huth                                     tcg_temp_free_ptr(r_tsptr);
4466*fcf5ef2aSThomas Huth                                 }
4467*fcf5ef2aSThomas Huth                                 break;
4468*fcf5ef2aSThomas Huth                             case 3: // tt
4469*fcf5ef2aSThomas Huth                                 {
4470*fcf5ef2aSThomas Huth                                     TCGv_ptr r_tsptr;
4471*fcf5ef2aSThomas Huth 
4472*fcf5ef2aSThomas Huth                                     r_tsptr = tcg_temp_new_ptr();
4473*fcf5ef2aSThomas Huth                                     gen_load_trap_state_at_tl(r_tsptr, cpu_env);
4474*fcf5ef2aSThomas Huth                                     tcg_gen_st32_tl(cpu_tmp0, r_tsptr,
4475*fcf5ef2aSThomas Huth                                                     offsetof(trap_state, tt));
4476*fcf5ef2aSThomas Huth                                     tcg_temp_free_ptr(r_tsptr);
4477*fcf5ef2aSThomas Huth                                 }
4478*fcf5ef2aSThomas Huth                                 break;
4479*fcf5ef2aSThomas Huth                             case 4: // tick
4480*fcf5ef2aSThomas Huth                                 {
4481*fcf5ef2aSThomas Huth                                     TCGv_ptr r_tickptr;
4482*fcf5ef2aSThomas Huth 
4483*fcf5ef2aSThomas Huth                                     r_tickptr = tcg_temp_new_ptr();
4484*fcf5ef2aSThomas Huth                                     tcg_gen_ld_ptr(r_tickptr, cpu_env,
4485*fcf5ef2aSThomas Huth                                                    offsetof(CPUSPARCState, tick));
4486*fcf5ef2aSThomas Huth                                     gen_helper_tick_set_count(r_tickptr,
4487*fcf5ef2aSThomas Huth                                                               cpu_tmp0);
4488*fcf5ef2aSThomas Huth                                     tcg_temp_free_ptr(r_tickptr);
4489*fcf5ef2aSThomas Huth                                 }
4490*fcf5ef2aSThomas Huth                                 break;
4491*fcf5ef2aSThomas Huth                             case 5: // tba
4492*fcf5ef2aSThomas Huth                                 tcg_gen_mov_tl(cpu_tbr, cpu_tmp0);
4493*fcf5ef2aSThomas Huth                                 break;
4494*fcf5ef2aSThomas Huth                             case 6: // pstate
4495*fcf5ef2aSThomas Huth                                 save_state(dc);
4496*fcf5ef2aSThomas Huth                                 gen_helper_wrpstate(cpu_env, cpu_tmp0);
4497*fcf5ef2aSThomas Huth                                 dc->npc = DYNAMIC_PC;
4498*fcf5ef2aSThomas Huth                                 break;
4499*fcf5ef2aSThomas Huth                             case 7: // tl
4500*fcf5ef2aSThomas Huth                                 save_state(dc);
4501*fcf5ef2aSThomas Huth                                 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
4502*fcf5ef2aSThomas Huth                                                offsetof(CPUSPARCState, tl));
4503*fcf5ef2aSThomas Huth                                 dc->npc = DYNAMIC_PC;
4504*fcf5ef2aSThomas Huth                                 break;
4505*fcf5ef2aSThomas Huth                             case 8: // pil
4506*fcf5ef2aSThomas Huth                                 gen_helper_wrpil(cpu_env, cpu_tmp0);
4507*fcf5ef2aSThomas Huth                                 break;
4508*fcf5ef2aSThomas Huth                             case 9: // cwp
4509*fcf5ef2aSThomas Huth                                 gen_helper_wrcwp(cpu_env, cpu_tmp0);
4510*fcf5ef2aSThomas Huth                                 break;
4511*fcf5ef2aSThomas Huth                             case 10: // cansave
4512*fcf5ef2aSThomas Huth                                 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
4513*fcf5ef2aSThomas Huth                                                 offsetof(CPUSPARCState,
4514*fcf5ef2aSThomas Huth                                                          cansave));
4515*fcf5ef2aSThomas Huth                                 break;
4516*fcf5ef2aSThomas Huth                             case 11: // canrestore
4517*fcf5ef2aSThomas Huth                                 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
4518*fcf5ef2aSThomas Huth                                                 offsetof(CPUSPARCState,
4519*fcf5ef2aSThomas Huth                                                          canrestore));
4520*fcf5ef2aSThomas Huth                                 break;
4521*fcf5ef2aSThomas Huth                             case 12: // cleanwin
4522*fcf5ef2aSThomas Huth                                 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
4523*fcf5ef2aSThomas Huth                                                 offsetof(CPUSPARCState,
4524*fcf5ef2aSThomas Huth                                                          cleanwin));
4525*fcf5ef2aSThomas Huth                                 break;
4526*fcf5ef2aSThomas Huth                             case 13: // otherwin
4527*fcf5ef2aSThomas Huth                                 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
4528*fcf5ef2aSThomas Huth                                                 offsetof(CPUSPARCState,
4529*fcf5ef2aSThomas Huth                                                          otherwin));
4530*fcf5ef2aSThomas Huth                                 break;
4531*fcf5ef2aSThomas Huth                             case 14: // wstate
4532*fcf5ef2aSThomas Huth                                 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
4533*fcf5ef2aSThomas Huth                                                 offsetof(CPUSPARCState,
4534*fcf5ef2aSThomas Huth                                                          wstate));
4535*fcf5ef2aSThomas Huth                                 break;
4536*fcf5ef2aSThomas Huth                             case 16: // UA2005 gl
4537*fcf5ef2aSThomas Huth                                 CHECK_IU_FEATURE(dc, GL);
4538*fcf5ef2aSThomas Huth                                 tcg_gen_st32_tl(cpu_tmp0, cpu_env,
4539*fcf5ef2aSThomas Huth                                                 offsetof(CPUSPARCState, gl));
4540*fcf5ef2aSThomas Huth                                 break;
4541*fcf5ef2aSThomas Huth                             case 26: // UA2005 strand status
4542*fcf5ef2aSThomas Huth                                 CHECK_IU_FEATURE(dc, HYPV);
4543*fcf5ef2aSThomas Huth                                 if (!hypervisor(dc))
4544*fcf5ef2aSThomas Huth                                     goto priv_insn;
4545*fcf5ef2aSThomas Huth                                 tcg_gen_mov_tl(cpu_ssr, cpu_tmp0);
4546*fcf5ef2aSThomas Huth                                 break;
4547*fcf5ef2aSThomas Huth                             default:
4548*fcf5ef2aSThomas Huth                                 goto illegal_insn;
4549*fcf5ef2aSThomas Huth                             }
4550*fcf5ef2aSThomas Huth #else
4551*fcf5ef2aSThomas Huth                             tcg_gen_trunc_tl_i32(cpu_wim, cpu_tmp0);
4552*fcf5ef2aSThomas Huth                             if (dc->def->nwindows != 32) {
4553*fcf5ef2aSThomas Huth                                 tcg_gen_andi_tl(cpu_wim, cpu_wim,
4554*fcf5ef2aSThomas Huth                                                 (1 << dc->def->nwindows) - 1);
4555*fcf5ef2aSThomas Huth                             }
4556*fcf5ef2aSThomas Huth #endif
4557*fcf5ef2aSThomas Huth                         }
4558*fcf5ef2aSThomas Huth                         break;
4559*fcf5ef2aSThomas Huth                     case 0x33: /* wrtbr, UA2005 wrhpr */
4560*fcf5ef2aSThomas Huth                         {
4561*fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64
4562*fcf5ef2aSThomas Huth                             if (!supervisor(dc))
4563*fcf5ef2aSThomas Huth                                 goto priv_insn;
4564*fcf5ef2aSThomas Huth                             tcg_gen_xor_tl(cpu_tbr, cpu_src1, cpu_src2);
4565*fcf5ef2aSThomas Huth #else
4566*fcf5ef2aSThomas Huth                             CHECK_IU_FEATURE(dc, HYPV);
4567*fcf5ef2aSThomas Huth                             if (!hypervisor(dc))
4568*fcf5ef2aSThomas Huth                                 goto priv_insn;
4569*fcf5ef2aSThomas Huth                             cpu_tmp0 = get_temp_tl(dc);
4570*fcf5ef2aSThomas Huth                             tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4571*fcf5ef2aSThomas Huth                             switch (rd) {
4572*fcf5ef2aSThomas Huth                             case 0: // hpstate
4573*fcf5ef2aSThomas Huth                                 // XXX gen_op_wrhpstate();
4574*fcf5ef2aSThomas Huth                                 save_state(dc);
4575*fcf5ef2aSThomas Huth                                 gen_op_next_insn();
4576*fcf5ef2aSThomas Huth                                 tcg_gen_exit_tb(0);
4577*fcf5ef2aSThomas Huth                                 dc->is_br = 1;
4578*fcf5ef2aSThomas Huth                                 break;
4579*fcf5ef2aSThomas Huth                             case 1: // htstate
4580*fcf5ef2aSThomas Huth                                 // XXX gen_op_wrhtstate();
4581*fcf5ef2aSThomas Huth                                 break;
4582*fcf5ef2aSThomas Huth                             case 3: // hintp
4583*fcf5ef2aSThomas Huth                                 tcg_gen_mov_tl(cpu_hintp, cpu_tmp0);
4584*fcf5ef2aSThomas Huth                                 break;
4585*fcf5ef2aSThomas Huth                             case 5: // htba
4586*fcf5ef2aSThomas Huth                                 tcg_gen_mov_tl(cpu_htba, cpu_tmp0);
4587*fcf5ef2aSThomas Huth                                 break;
4588*fcf5ef2aSThomas Huth                             case 31: // hstick_cmpr
4589*fcf5ef2aSThomas Huth                                 {
4590*fcf5ef2aSThomas Huth                                     TCGv_ptr r_tickptr;
4591*fcf5ef2aSThomas Huth 
4592*fcf5ef2aSThomas Huth                                     tcg_gen_mov_tl(cpu_hstick_cmpr, cpu_tmp0);
4593*fcf5ef2aSThomas Huth                                     r_tickptr = tcg_temp_new_ptr();
4594*fcf5ef2aSThomas Huth                                     tcg_gen_ld_ptr(r_tickptr, cpu_env,
4595*fcf5ef2aSThomas Huth                                                    offsetof(CPUSPARCState, hstick));
4596*fcf5ef2aSThomas Huth                                     gen_helper_tick_set_limit(r_tickptr,
4597*fcf5ef2aSThomas Huth                                                               cpu_hstick_cmpr);
4598*fcf5ef2aSThomas Huth                                     tcg_temp_free_ptr(r_tickptr);
4599*fcf5ef2aSThomas Huth                                 }
4600*fcf5ef2aSThomas Huth                                 break;
4601*fcf5ef2aSThomas Huth                             case 6: // hver readonly
4602*fcf5ef2aSThomas Huth                             default:
4603*fcf5ef2aSThomas Huth                                 goto illegal_insn;
4604*fcf5ef2aSThomas Huth                             }
4605*fcf5ef2aSThomas Huth #endif
4606*fcf5ef2aSThomas Huth                         }
4607*fcf5ef2aSThomas Huth                         break;
4608*fcf5ef2aSThomas Huth #endif
4609*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
4610*fcf5ef2aSThomas Huth                     case 0x2c: /* V9 movcc */
4611*fcf5ef2aSThomas Huth                         {
4612*fcf5ef2aSThomas Huth                             int cc = GET_FIELD_SP(insn, 11, 12);
4613*fcf5ef2aSThomas Huth                             int cond = GET_FIELD_SP(insn, 14, 17);
4614*fcf5ef2aSThomas Huth                             DisasCompare cmp;
4615*fcf5ef2aSThomas Huth                             TCGv dst;
4616*fcf5ef2aSThomas Huth 
4617*fcf5ef2aSThomas Huth                             if (insn & (1 << 18)) {
4618*fcf5ef2aSThomas Huth                                 if (cc == 0) {
4619*fcf5ef2aSThomas Huth                                     gen_compare(&cmp, 0, cond, dc);
4620*fcf5ef2aSThomas Huth                                 } else if (cc == 2) {
4621*fcf5ef2aSThomas Huth                                     gen_compare(&cmp, 1, cond, dc);
4622*fcf5ef2aSThomas Huth                                 } else {
4623*fcf5ef2aSThomas Huth                                     goto illegal_insn;
4624*fcf5ef2aSThomas Huth                                 }
4625*fcf5ef2aSThomas Huth                             } else {
4626*fcf5ef2aSThomas Huth                                 gen_fcompare(&cmp, cc, cond);
4627*fcf5ef2aSThomas Huth                             }
4628*fcf5ef2aSThomas Huth 
4629*fcf5ef2aSThomas Huth                             /* The get_src2 above loaded the normal 13-bit
4630*fcf5ef2aSThomas Huth                                immediate field, not the 11-bit field we have
4631*fcf5ef2aSThomas Huth                                in movcc.  But it did handle the reg case.  */
4632*fcf5ef2aSThomas Huth                             if (IS_IMM) {
4633*fcf5ef2aSThomas Huth                                 simm = GET_FIELD_SPs(insn, 0, 10);
4634*fcf5ef2aSThomas Huth                                 tcg_gen_movi_tl(cpu_src2, simm);
4635*fcf5ef2aSThomas Huth                             }
4636*fcf5ef2aSThomas Huth 
4637*fcf5ef2aSThomas Huth                             dst = gen_load_gpr(dc, rd);
4638*fcf5ef2aSThomas Huth                             tcg_gen_movcond_tl(cmp.cond, dst,
4639*fcf5ef2aSThomas Huth                                                cmp.c1, cmp.c2,
4640*fcf5ef2aSThomas Huth                                                cpu_src2, dst);
4641*fcf5ef2aSThomas Huth                             free_compare(&cmp);
4642*fcf5ef2aSThomas Huth                             gen_store_gpr(dc, rd, dst);
4643*fcf5ef2aSThomas Huth                             break;
4644*fcf5ef2aSThomas Huth                         }
4645*fcf5ef2aSThomas Huth                     case 0x2d: /* V9 sdivx */
4646*fcf5ef2aSThomas Huth                         gen_helper_sdivx(cpu_dst, cpu_env, cpu_src1, cpu_src2);
4647*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, cpu_dst);
4648*fcf5ef2aSThomas Huth                         break;
4649*fcf5ef2aSThomas Huth                     case 0x2e: /* V9 popc */
4650*fcf5ef2aSThomas Huth                         gen_helper_popc(cpu_dst, cpu_src2);
4651*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, cpu_dst);
4652*fcf5ef2aSThomas Huth                         break;
4653*fcf5ef2aSThomas Huth                     case 0x2f: /* V9 movr */
4654*fcf5ef2aSThomas Huth                         {
4655*fcf5ef2aSThomas Huth                             int cond = GET_FIELD_SP(insn, 10, 12);
4656*fcf5ef2aSThomas Huth                             DisasCompare cmp;
4657*fcf5ef2aSThomas Huth                             TCGv dst;
4658*fcf5ef2aSThomas Huth 
4659*fcf5ef2aSThomas Huth                             gen_compare_reg(&cmp, cond, cpu_src1);
4660*fcf5ef2aSThomas Huth 
4661*fcf5ef2aSThomas Huth                             /* The get_src2 above loaded the normal 13-bit
4662*fcf5ef2aSThomas Huth                                immediate field, not the 10-bit field we have
4663*fcf5ef2aSThomas Huth                                in movr.  But it did handle the reg case.  */
4664*fcf5ef2aSThomas Huth                             if (IS_IMM) {
4665*fcf5ef2aSThomas Huth                                 simm = GET_FIELD_SPs(insn, 0, 9);
4666*fcf5ef2aSThomas Huth                                 tcg_gen_movi_tl(cpu_src2, simm);
4667*fcf5ef2aSThomas Huth                             }
4668*fcf5ef2aSThomas Huth 
4669*fcf5ef2aSThomas Huth                             dst = gen_load_gpr(dc, rd);
4670*fcf5ef2aSThomas Huth                             tcg_gen_movcond_tl(cmp.cond, dst,
4671*fcf5ef2aSThomas Huth                                                cmp.c1, cmp.c2,
4672*fcf5ef2aSThomas Huth                                                cpu_src2, dst);
4673*fcf5ef2aSThomas Huth                             free_compare(&cmp);
4674*fcf5ef2aSThomas Huth                             gen_store_gpr(dc, rd, dst);
4675*fcf5ef2aSThomas Huth                             break;
4676*fcf5ef2aSThomas Huth                         }
4677*fcf5ef2aSThomas Huth #endif
4678*fcf5ef2aSThomas Huth                     default:
4679*fcf5ef2aSThomas Huth                         goto illegal_insn;
4680*fcf5ef2aSThomas Huth                     }
4681*fcf5ef2aSThomas Huth                 }
4682*fcf5ef2aSThomas Huth             } else if (xop == 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */
4683*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
4684*fcf5ef2aSThomas Huth                 int opf = GET_FIELD_SP(insn, 5, 13);
4685*fcf5ef2aSThomas Huth                 rs1 = GET_FIELD(insn, 13, 17);
4686*fcf5ef2aSThomas Huth                 rs2 = GET_FIELD(insn, 27, 31);
4687*fcf5ef2aSThomas Huth                 if (gen_trap_ifnofpu(dc)) {
4688*fcf5ef2aSThomas Huth                     goto jmp_insn;
4689*fcf5ef2aSThomas Huth                 }
4690*fcf5ef2aSThomas Huth 
4691*fcf5ef2aSThomas Huth                 switch (opf) {
4692*fcf5ef2aSThomas Huth                 case 0x000: /* VIS I edge8cc */
4693*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4694*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4695*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4696*fcf5ef2aSThomas Huth                     gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 0);
4697*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4698*fcf5ef2aSThomas Huth                     break;
4699*fcf5ef2aSThomas Huth                 case 0x001: /* VIS II edge8n */
4700*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS2);
4701*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4702*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4703*fcf5ef2aSThomas Huth                     gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 0);
4704*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4705*fcf5ef2aSThomas Huth                     break;
4706*fcf5ef2aSThomas Huth                 case 0x002: /* VIS I edge8lcc */
4707*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4708*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4709*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4710*fcf5ef2aSThomas Huth                     gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 1);
4711*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4712*fcf5ef2aSThomas Huth                     break;
4713*fcf5ef2aSThomas Huth                 case 0x003: /* VIS II edge8ln */
4714*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS2);
4715*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4716*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4717*fcf5ef2aSThomas Huth                     gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 1);
4718*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4719*fcf5ef2aSThomas Huth                     break;
4720*fcf5ef2aSThomas Huth                 case 0x004: /* VIS I edge16cc */
4721*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4722*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4723*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4724*fcf5ef2aSThomas Huth                     gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 0);
4725*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4726*fcf5ef2aSThomas Huth                     break;
4727*fcf5ef2aSThomas Huth                 case 0x005: /* VIS II edge16n */
4728*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS2);
4729*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4730*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4731*fcf5ef2aSThomas Huth                     gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 0);
4732*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4733*fcf5ef2aSThomas Huth                     break;
4734*fcf5ef2aSThomas Huth                 case 0x006: /* VIS I edge16lcc */
4735*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4736*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4737*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4738*fcf5ef2aSThomas Huth                     gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 1);
4739*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4740*fcf5ef2aSThomas Huth                     break;
4741*fcf5ef2aSThomas Huth                 case 0x007: /* VIS II edge16ln */
4742*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS2);
4743*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4744*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4745*fcf5ef2aSThomas Huth                     gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 1);
4746*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4747*fcf5ef2aSThomas Huth                     break;
4748*fcf5ef2aSThomas Huth                 case 0x008: /* VIS I edge32cc */
4749*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4750*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4751*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4752*fcf5ef2aSThomas Huth                     gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 0);
4753*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4754*fcf5ef2aSThomas Huth                     break;
4755*fcf5ef2aSThomas Huth                 case 0x009: /* VIS II edge32n */
4756*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS2);
4757*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4758*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4759*fcf5ef2aSThomas Huth                     gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 0);
4760*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4761*fcf5ef2aSThomas Huth                     break;
4762*fcf5ef2aSThomas Huth                 case 0x00a: /* VIS I edge32lcc */
4763*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4764*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4765*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4766*fcf5ef2aSThomas Huth                     gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 1);
4767*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4768*fcf5ef2aSThomas Huth                     break;
4769*fcf5ef2aSThomas Huth                 case 0x00b: /* VIS II edge32ln */
4770*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS2);
4771*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4772*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4773*fcf5ef2aSThomas Huth                     gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 1);
4774*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4775*fcf5ef2aSThomas Huth                     break;
4776*fcf5ef2aSThomas Huth                 case 0x010: /* VIS I array8 */
4777*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4778*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4779*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4780*fcf5ef2aSThomas Huth                     gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
4781*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4782*fcf5ef2aSThomas Huth                     break;
4783*fcf5ef2aSThomas Huth                 case 0x012: /* VIS I array16 */
4784*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4785*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4786*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4787*fcf5ef2aSThomas Huth                     gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
4788*fcf5ef2aSThomas Huth                     tcg_gen_shli_i64(cpu_dst, cpu_dst, 1);
4789*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4790*fcf5ef2aSThomas Huth                     break;
4791*fcf5ef2aSThomas Huth                 case 0x014: /* VIS I array32 */
4792*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4793*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4794*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4795*fcf5ef2aSThomas Huth                     gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
4796*fcf5ef2aSThomas Huth                     tcg_gen_shli_i64(cpu_dst, cpu_dst, 2);
4797*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4798*fcf5ef2aSThomas Huth                     break;
4799*fcf5ef2aSThomas Huth                 case 0x018: /* VIS I alignaddr */
4800*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4801*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4802*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4803*fcf5ef2aSThomas Huth                     gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 0);
4804*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4805*fcf5ef2aSThomas Huth                     break;
4806*fcf5ef2aSThomas Huth                 case 0x01a: /* VIS I alignaddrl */
4807*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4808*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4809*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4810*fcf5ef2aSThomas Huth                     gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 1);
4811*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4812*fcf5ef2aSThomas Huth                     break;
4813*fcf5ef2aSThomas Huth                 case 0x019: /* VIS II bmask */
4814*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS2);
4815*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rs1);
4816*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
4817*fcf5ef2aSThomas Huth                     tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
4818*fcf5ef2aSThomas Huth                     tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, cpu_dst, 32, 32);
4819*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4820*fcf5ef2aSThomas Huth                     break;
4821*fcf5ef2aSThomas Huth                 case 0x020: /* VIS I fcmple16 */
4822*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4823*fcf5ef2aSThomas Huth                     cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4824*fcf5ef2aSThomas Huth                     cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4825*fcf5ef2aSThomas Huth                     gen_helper_fcmple16(cpu_dst, cpu_src1_64, cpu_src2_64);
4826*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4827*fcf5ef2aSThomas Huth                     break;
4828*fcf5ef2aSThomas Huth                 case 0x022: /* VIS I fcmpne16 */
4829*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4830*fcf5ef2aSThomas Huth                     cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4831*fcf5ef2aSThomas Huth                     cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4832*fcf5ef2aSThomas Huth                     gen_helper_fcmpne16(cpu_dst, cpu_src1_64, cpu_src2_64);
4833*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4834*fcf5ef2aSThomas Huth                     break;
4835*fcf5ef2aSThomas Huth                 case 0x024: /* VIS I fcmple32 */
4836*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4837*fcf5ef2aSThomas Huth                     cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4838*fcf5ef2aSThomas Huth                     cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4839*fcf5ef2aSThomas Huth                     gen_helper_fcmple32(cpu_dst, cpu_src1_64, cpu_src2_64);
4840*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4841*fcf5ef2aSThomas Huth                     break;
4842*fcf5ef2aSThomas Huth                 case 0x026: /* VIS I fcmpne32 */
4843*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4844*fcf5ef2aSThomas Huth                     cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4845*fcf5ef2aSThomas Huth                     cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4846*fcf5ef2aSThomas Huth                     gen_helper_fcmpne32(cpu_dst, cpu_src1_64, cpu_src2_64);
4847*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4848*fcf5ef2aSThomas Huth                     break;
4849*fcf5ef2aSThomas Huth                 case 0x028: /* VIS I fcmpgt16 */
4850*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4851*fcf5ef2aSThomas Huth                     cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4852*fcf5ef2aSThomas Huth                     cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4853*fcf5ef2aSThomas Huth                     gen_helper_fcmpgt16(cpu_dst, cpu_src1_64, cpu_src2_64);
4854*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4855*fcf5ef2aSThomas Huth                     break;
4856*fcf5ef2aSThomas Huth                 case 0x02a: /* VIS I fcmpeq16 */
4857*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4858*fcf5ef2aSThomas Huth                     cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4859*fcf5ef2aSThomas Huth                     cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4860*fcf5ef2aSThomas Huth                     gen_helper_fcmpeq16(cpu_dst, cpu_src1_64, cpu_src2_64);
4861*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4862*fcf5ef2aSThomas Huth                     break;
4863*fcf5ef2aSThomas Huth                 case 0x02c: /* VIS I fcmpgt32 */
4864*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4865*fcf5ef2aSThomas Huth                     cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4866*fcf5ef2aSThomas Huth                     cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4867*fcf5ef2aSThomas Huth                     gen_helper_fcmpgt32(cpu_dst, cpu_src1_64, cpu_src2_64);
4868*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4869*fcf5ef2aSThomas Huth                     break;
4870*fcf5ef2aSThomas Huth                 case 0x02e: /* VIS I fcmpeq32 */
4871*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4872*fcf5ef2aSThomas Huth                     cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4873*fcf5ef2aSThomas Huth                     cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4874*fcf5ef2aSThomas Huth                     gen_helper_fcmpeq32(cpu_dst, cpu_src1_64, cpu_src2_64);
4875*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_dst);
4876*fcf5ef2aSThomas Huth                     break;
4877*fcf5ef2aSThomas Huth                 case 0x031: /* VIS I fmul8x16 */
4878*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4879*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16);
4880*fcf5ef2aSThomas Huth                     break;
4881*fcf5ef2aSThomas Huth                 case 0x033: /* VIS I fmul8x16au */
4882*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4883*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16au);
4884*fcf5ef2aSThomas Huth                     break;
4885*fcf5ef2aSThomas Huth                 case 0x035: /* VIS I fmul8x16al */
4886*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4887*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16al);
4888*fcf5ef2aSThomas Huth                     break;
4889*fcf5ef2aSThomas Huth                 case 0x036: /* VIS I fmul8sux16 */
4890*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4891*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8sux16);
4892*fcf5ef2aSThomas Huth                     break;
4893*fcf5ef2aSThomas Huth                 case 0x037: /* VIS I fmul8ulx16 */
4894*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4895*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8ulx16);
4896*fcf5ef2aSThomas Huth                     break;
4897*fcf5ef2aSThomas Huth                 case 0x038: /* VIS I fmuld8sux16 */
4898*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4899*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8sux16);
4900*fcf5ef2aSThomas Huth                     break;
4901*fcf5ef2aSThomas Huth                 case 0x039: /* VIS I fmuld8ulx16 */
4902*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4903*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8ulx16);
4904*fcf5ef2aSThomas Huth                     break;
4905*fcf5ef2aSThomas Huth                 case 0x03a: /* VIS I fpack32 */
4906*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4907*fcf5ef2aSThomas Huth                     gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpack32);
4908*fcf5ef2aSThomas Huth                     break;
4909*fcf5ef2aSThomas Huth                 case 0x03b: /* VIS I fpack16 */
4910*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4911*fcf5ef2aSThomas Huth                     cpu_src1_64 = gen_load_fpr_D(dc, rs2);
4912*fcf5ef2aSThomas Huth                     cpu_dst_32 = gen_dest_fpr_F(dc);
4913*fcf5ef2aSThomas Huth                     gen_helper_fpack16(cpu_dst_32, cpu_gsr, cpu_src1_64);
4914*fcf5ef2aSThomas Huth                     gen_store_fpr_F(dc, rd, cpu_dst_32);
4915*fcf5ef2aSThomas Huth                     break;
4916*fcf5ef2aSThomas Huth                 case 0x03d: /* VIS I fpackfix */
4917*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4918*fcf5ef2aSThomas Huth                     cpu_src1_64 = gen_load_fpr_D(dc, rs2);
4919*fcf5ef2aSThomas Huth                     cpu_dst_32 = gen_dest_fpr_F(dc);
4920*fcf5ef2aSThomas Huth                     gen_helper_fpackfix(cpu_dst_32, cpu_gsr, cpu_src1_64);
4921*fcf5ef2aSThomas Huth                     gen_store_fpr_F(dc, rd, cpu_dst_32);
4922*fcf5ef2aSThomas Huth                     break;
4923*fcf5ef2aSThomas Huth                 case 0x03e: /* VIS I pdist */
4924*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4925*fcf5ef2aSThomas Huth                     gen_ne_fop_DDDD(dc, rd, rs1, rs2, gen_helper_pdist);
4926*fcf5ef2aSThomas Huth                     break;
4927*fcf5ef2aSThomas Huth                 case 0x048: /* VIS I faligndata */
4928*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4929*fcf5ef2aSThomas Huth                     gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_faligndata);
4930*fcf5ef2aSThomas Huth                     break;
4931*fcf5ef2aSThomas Huth                 case 0x04b: /* VIS I fpmerge */
4932*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4933*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpmerge);
4934*fcf5ef2aSThomas Huth                     break;
4935*fcf5ef2aSThomas Huth                 case 0x04c: /* VIS II bshuffle */
4936*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS2);
4937*fcf5ef2aSThomas Huth                     gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_bshuffle);
4938*fcf5ef2aSThomas Huth                     break;
4939*fcf5ef2aSThomas Huth                 case 0x04d: /* VIS I fexpand */
4940*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4941*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fexpand);
4942*fcf5ef2aSThomas Huth                     break;
4943*fcf5ef2aSThomas Huth                 case 0x050: /* VIS I fpadd16 */
4944*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4945*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd16);
4946*fcf5ef2aSThomas Huth                     break;
4947*fcf5ef2aSThomas Huth                 case 0x051: /* VIS I fpadd16s */
4948*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4949*fcf5ef2aSThomas Huth                     gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpadd16s);
4950*fcf5ef2aSThomas Huth                     break;
4951*fcf5ef2aSThomas Huth                 case 0x052: /* VIS I fpadd32 */
4952*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4953*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd32);
4954*fcf5ef2aSThomas Huth                     break;
4955*fcf5ef2aSThomas Huth                 case 0x053: /* VIS I fpadd32s */
4956*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4957*fcf5ef2aSThomas Huth                     gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_add_i32);
4958*fcf5ef2aSThomas Huth                     break;
4959*fcf5ef2aSThomas Huth                 case 0x054: /* VIS I fpsub16 */
4960*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4961*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub16);
4962*fcf5ef2aSThomas Huth                     break;
4963*fcf5ef2aSThomas Huth                 case 0x055: /* VIS I fpsub16s */
4964*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4965*fcf5ef2aSThomas Huth                     gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpsub16s);
4966*fcf5ef2aSThomas Huth                     break;
4967*fcf5ef2aSThomas Huth                 case 0x056: /* VIS I fpsub32 */
4968*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4969*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub32);
4970*fcf5ef2aSThomas Huth                     break;
4971*fcf5ef2aSThomas Huth                 case 0x057: /* VIS I fpsub32s */
4972*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4973*fcf5ef2aSThomas Huth                     gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_sub_i32);
4974*fcf5ef2aSThomas Huth                     break;
4975*fcf5ef2aSThomas Huth                 case 0x060: /* VIS I fzero */
4976*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4977*fcf5ef2aSThomas Huth                     cpu_dst_64 = gen_dest_fpr_D(dc, rd);
4978*fcf5ef2aSThomas Huth                     tcg_gen_movi_i64(cpu_dst_64, 0);
4979*fcf5ef2aSThomas Huth                     gen_store_fpr_D(dc, rd, cpu_dst_64);
4980*fcf5ef2aSThomas Huth                     break;
4981*fcf5ef2aSThomas Huth                 case 0x061: /* VIS I fzeros */
4982*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4983*fcf5ef2aSThomas Huth                     cpu_dst_32 = gen_dest_fpr_F(dc);
4984*fcf5ef2aSThomas Huth                     tcg_gen_movi_i32(cpu_dst_32, 0);
4985*fcf5ef2aSThomas Huth                     gen_store_fpr_F(dc, rd, cpu_dst_32);
4986*fcf5ef2aSThomas Huth                     break;
4987*fcf5ef2aSThomas Huth                 case 0x062: /* VIS I fnor */
4988*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4989*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nor_i64);
4990*fcf5ef2aSThomas Huth                     break;
4991*fcf5ef2aSThomas Huth                 case 0x063: /* VIS I fnors */
4992*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4993*fcf5ef2aSThomas Huth                     gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nor_i32);
4994*fcf5ef2aSThomas Huth                     break;
4995*fcf5ef2aSThomas Huth                 case 0x064: /* VIS I fandnot2 */
4996*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
4997*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_andc_i64);
4998*fcf5ef2aSThomas Huth                     break;
4999*fcf5ef2aSThomas Huth                 case 0x065: /* VIS I fandnot2s */
5000*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5001*fcf5ef2aSThomas Huth                     gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_andc_i32);
5002*fcf5ef2aSThomas Huth                     break;
5003*fcf5ef2aSThomas Huth                 case 0x066: /* VIS I fnot2 */
5004*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5005*fcf5ef2aSThomas Huth                     gen_ne_fop_DD(dc, rd, rs2, tcg_gen_not_i64);
5006*fcf5ef2aSThomas Huth                     break;
5007*fcf5ef2aSThomas Huth                 case 0x067: /* VIS I fnot2s */
5008*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5009*fcf5ef2aSThomas Huth                     gen_ne_fop_FF(dc, rd, rs2, tcg_gen_not_i32);
5010*fcf5ef2aSThomas Huth                     break;
5011*fcf5ef2aSThomas Huth                 case 0x068: /* VIS I fandnot1 */
5012*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5013*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_andc_i64);
5014*fcf5ef2aSThomas Huth                     break;
5015*fcf5ef2aSThomas Huth                 case 0x069: /* VIS I fandnot1s */
5016*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5017*fcf5ef2aSThomas Huth                     gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_andc_i32);
5018*fcf5ef2aSThomas Huth                     break;
5019*fcf5ef2aSThomas Huth                 case 0x06a: /* VIS I fnot1 */
5020*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5021*fcf5ef2aSThomas Huth                     gen_ne_fop_DD(dc, rd, rs1, tcg_gen_not_i64);
5022*fcf5ef2aSThomas Huth                     break;
5023*fcf5ef2aSThomas Huth                 case 0x06b: /* VIS I fnot1s */
5024*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5025*fcf5ef2aSThomas Huth                     gen_ne_fop_FF(dc, rd, rs1, tcg_gen_not_i32);
5026*fcf5ef2aSThomas Huth                     break;
5027*fcf5ef2aSThomas Huth                 case 0x06c: /* VIS I fxor */
5028*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5029*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_xor_i64);
5030*fcf5ef2aSThomas Huth                     break;
5031*fcf5ef2aSThomas Huth                 case 0x06d: /* VIS I fxors */
5032*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5033*fcf5ef2aSThomas Huth                     gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_xor_i32);
5034*fcf5ef2aSThomas Huth                     break;
5035*fcf5ef2aSThomas Huth                 case 0x06e: /* VIS I fnand */
5036*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5037*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nand_i64);
5038*fcf5ef2aSThomas Huth                     break;
5039*fcf5ef2aSThomas Huth                 case 0x06f: /* VIS I fnands */
5040*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5041*fcf5ef2aSThomas Huth                     gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nand_i32);
5042*fcf5ef2aSThomas Huth                     break;
5043*fcf5ef2aSThomas Huth                 case 0x070: /* VIS I fand */
5044*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5045*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_and_i64);
5046*fcf5ef2aSThomas Huth                     break;
5047*fcf5ef2aSThomas Huth                 case 0x071: /* VIS I fands */
5048*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5049*fcf5ef2aSThomas Huth                     gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_and_i32);
5050*fcf5ef2aSThomas Huth                     break;
5051*fcf5ef2aSThomas Huth                 case 0x072: /* VIS I fxnor */
5052*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5053*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_eqv_i64);
5054*fcf5ef2aSThomas Huth                     break;
5055*fcf5ef2aSThomas Huth                 case 0x073: /* VIS I fxnors */
5056*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5057*fcf5ef2aSThomas Huth                     gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_eqv_i32);
5058*fcf5ef2aSThomas Huth                     break;
5059*fcf5ef2aSThomas Huth                 case 0x074: /* VIS I fsrc1 */
5060*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5061*fcf5ef2aSThomas Huth                     cpu_src1_64 = gen_load_fpr_D(dc, rs1);
5062*fcf5ef2aSThomas Huth                     gen_store_fpr_D(dc, rd, cpu_src1_64);
5063*fcf5ef2aSThomas Huth                     break;
5064*fcf5ef2aSThomas Huth                 case 0x075: /* VIS I fsrc1s */
5065*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5066*fcf5ef2aSThomas Huth                     cpu_src1_32 = gen_load_fpr_F(dc, rs1);
5067*fcf5ef2aSThomas Huth                     gen_store_fpr_F(dc, rd, cpu_src1_32);
5068*fcf5ef2aSThomas Huth                     break;
5069*fcf5ef2aSThomas Huth                 case 0x076: /* VIS I fornot2 */
5070*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5071*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_orc_i64);
5072*fcf5ef2aSThomas Huth                     break;
5073*fcf5ef2aSThomas Huth                 case 0x077: /* VIS I fornot2s */
5074*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5075*fcf5ef2aSThomas Huth                     gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_orc_i32);
5076*fcf5ef2aSThomas Huth                     break;
5077*fcf5ef2aSThomas Huth                 case 0x078: /* VIS I fsrc2 */
5078*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5079*fcf5ef2aSThomas Huth                     cpu_src1_64 = gen_load_fpr_D(dc, rs2);
5080*fcf5ef2aSThomas Huth                     gen_store_fpr_D(dc, rd, cpu_src1_64);
5081*fcf5ef2aSThomas Huth                     break;
5082*fcf5ef2aSThomas Huth                 case 0x079: /* VIS I fsrc2s */
5083*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5084*fcf5ef2aSThomas Huth                     cpu_src1_32 = gen_load_fpr_F(dc, rs2);
5085*fcf5ef2aSThomas Huth                     gen_store_fpr_F(dc, rd, cpu_src1_32);
5086*fcf5ef2aSThomas Huth                     break;
5087*fcf5ef2aSThomas Huth                 case 0x07a: /* VIS I fornot1 */
5088*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5089*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_orc_i64);
5090*fcf5ef2aSThomas Huth                     break;
5091*fcf5ef2aSThomas Huth                 case 0x07b: /* VIS I fornot1s */
5092*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5093*fcf5ef2aSThomas Huth                     gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_orc_i32);
5094*fcf5ef2aSThomas Huth                     break;
5095*fcf5ef2aSThomas Huth                 case 0x07c: /* VIS I for */
5096*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5097*fcf5ef2aSThomas Huth                     gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_or_i64);
5098*fcf5ef2aSThomas Huth                     break;
5099*fcf5ef2aSThomas Huth                 case 0x07d: /* VIS I fors */
5100*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5101*fcf5ef2aSThomas Huth                     gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_or_i32);
5102*fcf5ef2aSThomas Huth                     break;
5103*fcf5ef2aSThomas Huth                 case 0x07e: /* VIS I fone */
5104*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5105*fcf5ef2aSThomas Huth                     cpu_dst_64 = gen_dest_fpr_D(dc, rd);
5106*fcf5ef2aSThomas Huth                     tcg_gen_movi_i64(cpu_dst_64, -1);
5107*fcf5ef2aSThomas Huth                     gen_store_fpr_D(dc, rd, cpu_dst_64);
5108*fcf5ef2aSThomas Huth                     break;
5109*fcf5ef2aSThomas Huth                 case 0x07f: /* VIS I fones */
5110*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, VIS1);
5111*fcf5ef2aSThomas Huth                     cpu_dst_32 = gen_dest_fpr_F(dc);
5112*fcf5ef2aSThomas Huth                     tcg_gen_movi_i32(cpu_dst_32, -1);
5113*fcf5ef2aSThomas Huth                     gen_store_fpr_F(dc, rd, cpu_dst_32);
5114*fcf5ef2aSThomas Huth                     break;
5115*fcf5ef2aSThomas Huth                 case 0x080: /* VIS I shutdown */
5116*fcf5ef2aSThomas Huth                 case 0x081: /* VIS II siam */
5117*fcf5ef2aSThomas Huth                     // XXX
5118*fcf5ef2aSThomas Huth                     goto illegal_insn;
5119*fcf5ef2aSThomas Huth                 default:
5120*fcf5ef2aSThomas Huth                     goto illegal_insn;
5121*fcf5ef2aSThomas Huth                 }
5122*fcf5ef2aSThomas Huth #else
5123*fcf5ef2aSThomas Huth                 goto ncp_insn;
5124*fcf5ef2aSThomas Huth #endif
5125*fcf5ef2aSThomas Huth             } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */
5126*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5127*fcf5ef2aSThomas Huth                 goto illegal_insn;
5128*fcf5ef2aSThomas Huth #else
5129*fcf5ef2aSThomas Huth                 goto ncp_insn;
5130*fcf5ef2aSThomas Huth #endif
5131*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5132*fcf5ef2aSThomas Huth             } else if (xop == 0x39) { /* V9 return */
5133*fcf5ef2aSThomas Huth                 save_state(dc);
5134*fcf5ef2aSThomas Huth                 cpu_src1 = get_src1(dc, insn);
5135*fcf5ef2aSThomas Huth                 cpu_tmp0 = get_temp_tl(dc);
5136*fcf5ef2aSThomas Huth                 if (IS_IMM) {   /* immediate */
5137*fcf5ef2aSThomas Huth                     simm = GET_FIELDs(insn, 19, 31);
5138*fcf5ef2aSThomas Huth                     tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm);
5139*fcf5ef2aSThomas Huth                 } else {                /* register */
5140*fcf5ef2aSThomas Huth                     rs2 = GET_FIELD(insn, 27, 31);
5141*fcf5ef2aSThomas Huth                     if (rs2) {
5142*fcf5ef2aSThomas Huth                         cpu_src2 = gen_load_gpr(dc, rs2);
5143*fcf5ef2aSThomas Huth                         tcg_gen_add_tl(cpu_tmp0, cpu_src1, cpu_src2);
5144*fcf5ef2aSThomas Huth                     } else {
5145*fcf5ef2aSThomas Huth                         tcg_gen_mov_tl(cpu_tmp0, cpu_src1);
5146*fcf5ef2aSThomas Huth                     }
5147*fcf5ef2aSThomas Huth                 }
5148*fcf5ef2aSThomas Huth                 gen_helper_restore(cpu_env);
5149*fcf5ef2aSThomas Huth                 gen_mov_pc_npc(dc);
5150*fcf5ef2aSThomas Huth                 gen_check_align(cpu_tmp0, 3);
5151*fcf5ef2aSThomas Huth                 tcg_gen_mov_tl(cpu_npc, cpu_tmp0);
5152*fcf5ef2aSThomas Huth                 dc->npc = DYNAMIC_PC;
5153*fcf5ef2aSThomas Huth                 goto jmp_insn;
5154*fcf5ef2aSThomas Huth #endif
5155*fcf5ef2aSThomas Huth             } else {
5156*fcf5ef2aSThomas Huth                 cpu_src1 = get_src1(dc, insn);
5157*fcf5ef2aSThomas Huth                 cpu_tmp0 = get_temp_tl(dc);
5158*fcf5ef2aSThomas Huth                 if (IS_IMM) {   /* immediate */
5159*fcf5ef2aSThomas Huth                     simm = GET_FIELDs(insn, 19, 31);
5160*fcf5ef2aSThomas Huth                     tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm);
5161*fcf5ef2aSThomas Huth                 } else {                /* register */
5162*fcf5ef2aSThomas Huth                     rs2 = GET_FIELD(insn, 27, 31);
5163*fcf5ef2aSThomas Huth                     if (rs2) {
5164*fcf5ef2aSThomas Huth                         cpu_src2 = gen_load_gpr(dc, rs2);
5165*fcf5ef2aSThomas Huth                         tcg_gen_add_tl(cpu_tmp0, cpu_src1, cpu_src2);
5166*fcf5ef2aSThomas Huth                     } else {
5167*fcf5ef2aSThomas Huth                         tcg_gen_mov_tl(cpu_tmp0, cpu_src1);
5168*fcf5ef2aSThomas Huth                     }
5169*fcf5ef2aSThomas Huth                 }
5170*fcf5ef2aSThomas Huth                 switch (xop) {
5171*fcf5ef2aSThomas Huth                 case 0x38:      /* jmpl */
5172*fcf5ef2aSThomas Huth                     {
5173*fcf5ef2aSThomas Huth                         TCGv t = gen_dest_gpr(dc, rd);
5174*fcf5ef2aSThomas Huth                         tcg_gen_movi_tl(t, dc->pc);
5175*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd, t);
5176*fcf5ef2aSThomas Huth 
5177*fcf5ef2aSThomas Huth                         gen_mov_pc_npc(dc);
5178*fcf5ef2aSThomas Huth                         gen_check_align(cpu_tmp0, 3);
5179*fcf5ef2aSThomas Huth                         gen_address_mask(dc, cpu_tmp0);
5180*fcf5ef2aSThomas Huth                         tcg_gen_mov_tl(cpu_npc, cpu_tmp0);
5181*fcf5ef2aSThomas Huth                         dc->npc = DYNAMIC_PC;
5182*fcf5ef2aSThomas Huth                     }
5183*fcf5ef2aSThomas Huth                     goto jmp_insn;
5184*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
5185*fcf5ef2aSThomas Huth                 case 0x39:      /* rett, V9 return */
5186*fcf5ef2aSThomas Huth                     {
5187*fcf5ef2aSThomas Huth                         if (!supervisor(dc))
5188*fcf5ef2aSThomas Huth                             goto priv_insn;
5189*fcf5ef2aSThomas Huth                         gen_mov_pc_npc(dc);
5190*fcf5ef2aSThomas Huth                         gen_check_align(cpu_tmp0, 3);
5191*fcf5ef2aSThomas Huth                         tcg_gen_mov_tl(cpu_npc, cpu_tmp0);
5192*fcf5ef2aSThomas Huth                         dc->npc = DYNAMIC_PC;
5193*fcf5ef2aSThomas Huth                         gen_helper_rett(cpu_env);
5194*fcf5ef2aSThomas Huth                     }
5195*fcf5ef2aSThomas Huth                     goto jmp_insn;
5196*fcf5ef2aSThomas Huth #endif
5197*fcf5ef2aSThomas Huth                 case 0x3b: /* flush */
5198*fcf5ef2aSThomas Huth                     if (!((dc)->def->features & CPU_FEATURE_FLUSH))
5199*fcf5ef2aSThomas Huth                         goto unimp_flush;
5200*fcf5ef2aSThomas Huth                     /* nop */
5201*fcf5ef2aSThomas Huth                     break;
5202*fcf5ef2aSThomas Huth                 case 0x3c:      /* save */
5203*fcf5ef2aSThomas Huth                     gen_helper_save(cpu_env);
5204*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_tmp0);
5205*fcf5ef2aSThomas Huth                     break;
5206*fcf5ef2aSThomas Huth                 case 0x3d:      /* restore */
5207*fcf5ef2aSThomas Huth                     gen_helper_restore(cpu_env);
5208*fcf5ef2aSThomas Huth                     gen_store_gpr(dc, rd, cpu_tmp0);
5209*fcf5ef2aSThomas Huth                     break;
5210*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
5211*fcf5ef2aSThomas Huth                 case 0x3e:      /* V9 done/retry */
5212*fcf5ef2aSThomas Huth                     {
5213*fcf5ef2aSThomas Huth                         switch (rd) {
5214*fcf5ef2aSThomas Huth                         case 0:
5215*fcf5ef2aSThomas Huth                             if (!supervisor(dc))
5216*fcf5ef2aSThomas Huth                                 goto priv_insn;
5217*fcf5ef2aSThomas Huth                             dc->npc = DYNAMIC_PC;
5218*fcf5ef2aSThomas Huth                             dc->pc = DYNAMIC_PC;
5219*fcf5ef2aSThomas Huth                             gen_helper_done(cpu_env);
5220*fcf5ef2aSThomas Huth                             goto jmp_insn;
5221*fcf5ef2aSThomas Huth                         case 1:
5222*fcf5ef2aSThomas Huth                             if (!supervisor(dc))
5223*fcf5ef2aSThomas Huth                                 goto priv_insn;
5224*fcf5ef2aSThomas Huth                             dc->npc = DYNAMIC_PC;
5225*fcf5ef2aSThomas Huth                             dc->pc = DYNAMIC_PC;
5226*fcf5ef2aSThomas Huth                             gen_helper_retry(cpu_env);
5227*fcf5ef2aSThomas Huth                             goto jmp_insn;
5228*fcf5ef2aSThomas Huth                         default:
5229*fcf5ef2aSThomas Huth                             goto illegal_insn;
5230*fcf5ef2aSThomas Huth                         }
5231*fcf5ef2aSThomas Huth                     }
5232*fcf5ef2aSThomas Huth                     break;
5233*fcf5ef2aSThomas Huth #endif
5234*fcf5ef2aSThomas Huth                 default:
5235*fcf5ef2aSThomas Huth                     goto illegal_insn;
5236*fcf5ef2aSThomas Huth                 }
5237*fcf5ef2aSThomas Huth             }
5238*fcf5ef2aSThomas Huth             break;
5239*fcf5ef2aSThomas Huth         }
5240*fcf5ef2aSThomas Huth         break;
5241*fcf5ef2aSThomas Huth     case 3:                     /* load/store instructions */
5242*fcf5ef2aSThomas Huth         {
5243*fcf5ef2aSThomas Huth             unsigned int xop = GET_FIELD(insn, 7, 12);
5244*fcf5ef2aSThomas Huth             /* ??? gen_address_mask prevents us from using a source
5245*fcf5ef2aSThomas Huth                register directly.  Always generate a temporary.  */
5246*fcf5ef2aSThomas Huth             TCGv cpu_addr = get_temp_tl(dc);
5247*fcf5ef2aSThomas Huth 
5248*fcf5ef2aSThomas Huth             tcg_gen_mov_tl(cpu_addr, get_src1(dc, insn));
5249*fcf5ef2aSThomas Huth             if (xop == 0x3c || xop == 0x3e) {
5250*fcf5ef2aSThomas Huth                 /* V9 casa/casxa : no offset */
5251*fcf5ef2aSThomas Huth             } else if (IS_IMM) {     /* immediate */
5252*fcf5ef2aSThomas Huth                 simm = GET_FIELDs(insn, 19, 31);
5253*fcf5ef2aSThomas Huth                 if (simm != 0) {
5254*fcf5ef2aSThomas Huth                     tcg_gen_addi_tl(cpu_addr, cpu_addr, simm);
5255*fcf5ef2aSThomas Huth                 }
5256*fcf5ef2aSThomas Huth             } else {            /* register */
5257*fcf5ef2aSThomas Huth                 rs2 = GET_FIELD(insn, 27, 31);
5258*fcf5ef2aSThomas Huth                 if (rs2 != 0) {
5259*fcf5ef2aSThomas Huth                     tcg_gen_add_tl(cpu_addr, cpu_addr, gen_load_gpr(dc, rs2));
5260*fcf5ef2aSThomas Huth                 }
5261*fcf5ef2aSThomas Huth             }
5262*fcf5ef2aSThomas Huth             if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) ||
5263*fcf5ef2aSThomas Huth                 (xop > 0x17 && xop <= 0x1d ) ||
5264*fcf5ef2aSThomas Huth                 (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
5265*fcf5ef2aSThomas Huth                 TCGv cpu_val = gen_dest_gpr(dc, rd);
5266*fcf5ef2aSThomas Huth 
5267*fcf5ef2aSThomas Huth                 switch (xop) {
5268*fcf5ef2aSThomas Huth                 case 0x0:       /* ld, V9 lduw, load unsigned word */
5269*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5270*fcf5ef2aSThomas Huth                     tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx);
5271*fcf5ef2aSThomas Huth                     break;
5272*fcf5ef2aSThomas Huth                 case 0x1:       /* ldub, load unsigned byte */
5273*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5274*fcf5ef2aSThomas Huth                     tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx);
5275*fcf5ef2aSThomas Huth                     break;
5276*fcf5ef2aSThomas Huth                 case 0x2:       /* lduh, load unsigned halfword */
5277*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5278*fcf5ef2aSThomas Huth                     tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx);
5279*fcf5ef2aSThomas Huth                     break;
5280*fcf5ef2aSThomas Huth                 case 0x3:       /* ldd, load double word */
5281*fcf5ef2aSThomas Huth                     if (rd & 1)
5282*fcf5ef2aSThomas Huth                         goto illegal_insn;
5283*fcf5ef2aSThomas Huth                     else {
5284*fcf5ef2aSThomas Huth                         TCGv_i64 t64;
5285*fcf5ef2aSThomas Huth 
5286*fcf5ef2aSThomas Huth                         gen_address_mask(dc, cpu_addr);
5287*fcf5ef2aSThomas Huth                         t64 = tcg_temp_new_i64();
5288*fcf5ef2aSThomas Huth                         tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx);
5289*fcf5ef2aSThomas Huth                         tcg_gen_trunc_i64_tl(cpu_val, t64);
5290*fcf5ef2aSThomas Huth                         tcg_gen_ext32u_tl(cpu_val, cpu_val);
5291*fcf5ef2aSThomas Huth                         gen_store_gpr(dc, rd + 1, cpu_val);
5292*fcf5ef2aSThomas Huth                         tcg_gen_shri_i64(t64, t64, 32);
5293*fcf5ef2aSThomas Huth                         tcg_gen_trunc_i64_tl(cpu_val, t64);
5294*fcf5ef2aSThomas Huth                         tcg_temp_free_i64(t64);
5295*fcf5ef2aSThomas Huth                         tcg_gen_ext32u_tl(cpu_val, cpu_val);
5296*fcf5ef2aSThomas Huth                     }
5297*fcf5ef2aSThomas Huth                     break;
5298*fcf5ef2aSThomas Huth                 case 0x9:       /* ldsb, load signed byte */
5299*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5300*fcf5ef2aSThomas Huth                     tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
5301*fcf5ef2aSThomas Huth                     break;
5302*fcf5ef2aSThomas Huth                 case 0xa:       /* ldsh, load signed halfword */
5303*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5304*fcf5ef2aSThomas Huth                     tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx);
5305*fcf5ef2aSThomas Huth                     break;
5306*fcf5ef2aSThomas Huth                 case 0xd:       /* ldstub */
5307*fcf5ef2aSThomas Huth                     gen_ldstub(dc, cpu_val, cpu_addr, dc->mem_idx);
5308*fcf5ef2aSThomas Huth                     break;
5309*fcf5ef2aSThomas Huth                 case 0x0f:
5310*fcf5ef2aSThomas Huth                     /* swap, swap register with memory. Also atomically */
5311*fcf5ef2aSThomas Huth                     CHECK_IU_FEATURE(dc, SWAP);
5312*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rd);
5313*fcf5ef2aSThomas Huth                     gen_swap(dc, cpu_val, cpu_src1, cpu_addr,
5314*fcf5ef2aSThomas Huth                              dc->mem_idx, MO_TEUL);
5315*fcf5ef2aSThomas Huth                     break;
5316*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
5317*fcf5ef2aSThomas Huth                 case 0x10:      /* lda, V9 lduwa, load word alternate */
5318*fcf5ef2aSThomas Huth                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEUL);
5319*fcf5ef2aSThomas Huth                     break;
5320*fcf5ef2aSThomas Huth                 case 0x11:      /* lduba, load unsigned byte alternate */
5321*fcf5ef2aSThomas Huth                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_UB);
5322*fcf5ef2aSThomas Huth                     break;
5323*fcf5ef2aSThomas Huth                 case 0x12:      /* lduha, load unsigned halfword alternate */
5324*fcf5ef2aSThomas Huth                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEUW);
5325*fcf5ef2aSThomas Huth                     break;
5326*fcf5ef2aSThomas Huth                 case 0x13:      /* ldda, load double word alternate */
5327*fcf5ef2aSThomas Huth                     if (rd & 1) {
5328*fcf5ef2aSThomas Huth                         goto illegal_insn;
5329*fcf5ef2aSThomas Huth                     }
5330*fcf5ef2aSThomas Huth                     gen_ldda_asi(dc, cpu_addr, insn, rd);
5331*fcf5ef2aSThomas Huth                     goto skip_move;
5332*fcf5ef2aSThomas Huth                 case 0x19:      /* ldsba, load signed byte alternate */
5333*fcf5ef2aSThomas Huth                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_SB);
5334*fcf5ef2aSThomas Huth                     break;
5335*fcf5ef2aSThomas Huth                 case 0x1a:      /* ldsha, load signed halfword alternate */
5336*fcf5ef2aSThomas Huth                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESW);
5337*fcf5ef2aSThomas Huth                     break;
5338*fcf5ef2aSThomas Huth                 case 0x1d:      /* ldstuba -- XXX: should be atomically */
5339*fcf5ef2aSThomas Huth                     gen_ldstub_asi(dc, cpu_val, cpu_addr, insn);
5340*fcf5ef2aSThomas Huth                     break;
5341*fcf5ef2aSThomas Huth                 case 0x1f:      /* swapa, swap reg with alt. memory. Also
5342*fcf5ef2aSThomas Huth                                    atomically */
5343*fcf5ef2aSThomas Huth                     CHECK_IU_FEATURE(dc, SWAP);
5344*fcf5ef2aSThomas Huth                     cpu_src1 = gen_load_gpr(dc, rd);
5345*fcf5ef2aSThomas Huth                     gen_swap_asi(dc, cpu_val, cpu_src1, cpu_addr, insn);
5346*fcf5ef2aSThomas Huth                     break;
5347*fcf5ef2aSThomas Huth 
5348*fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64
5349*fcf5ef2aSThomas Huth                 case 0x30: /* ldc */
5350*fcf5ef2aSThomas Huth                 case 0x31: /* ldcsr */
5351*fcf5ef2aSThomas Huth                 case 0x33: /* lddc */
5352*fcf5ef2aSThomas Huth                     goto ncp_insn;
5353*fcf5ef2aSThomas Huth #endif
5354*fcf5ef2aSThomas Huth #endif
5355*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5356*fcf5ef2aSThomas Huth                 case 0x08: /* V9 ldsw */
5357*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5358*fcf5ef2aSThomas Huth                     tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx);
5359*fcf5ef2aSThomas Huth                     break;
5360*fcf5ef2aSThomas Huth                 case 0x0b: /* V9 ldx */
5361*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5362*fcf5ef2aSThomas Huth                     tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx);
5363*fcf5ef2aSThomas Huth                     break;
5364*fcf5ef2aSThomas Huth                 case 0x18: /* V9 ldswa */
5365*fcf5ef2aSThomas Huth                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESL);
5366*fcf5ef2aSThomas Huth                     break;
5367*fcf5ef2aSThomas Huth                 case 0x1b: /* V9 ldxa */
5368*fcf5ef2aSThomas Huth                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEQ);
5369*fcf5ef2aSThomas Huth                     break;
5370*fcf5ef2aSThomas Huth                 case 0x2d: /* V9 prefetch, no effect */
5371*fcf5ef2aSThomas Huth                     goto skip_move;
5372*fcf5ef2aSThomas Huth                 case 0x30: /* V9 ldfa */
5373*fcf5ef2aSThomas Huth                     if (gen_trap_ifnofpu(dc)) {
5374*fcf5ef2aSThomas Huth                         goto jmp_insn;
5375*fcf5ef2aSThomas Huth                     }
5376*fcf5ef2aSThomas Huth                     gen_ldf_asi(dc, cpu_addr, insn, 4, rd);
5377*fcf5ef2aSThomas Huth                     gen_update_fprs_dirty(dc, rd);
5378*fcf5ef2aSThomas Huth                     goto skip_move;
5379*fcf5ef2aSThomas Huth                 case 0x33: /* V9 lddfa */
5380*fcf5ef2aSThomas Huth                     if (gen_trap_ifnofpu(dc)) {
5381*fcf5ef2aSThomas Huth                         goto jmp_insn;
5382*fcf5ef2aSThomas Huth                     }
5383*fcf5ef2aSThomas Huth                     gen_ldf_asi(dc, cpu_addr, insn, 8, DFPREG(rd));
5384*fcf5ef2aSThomas Huth                     gen_update_fprs_dirty(dc, DFPREG(rd));
5385*fcf5ef2aSThomas Huth                     goto skip_move;
5386*fcf5ef2aSThomas Huth                 case 0x3d: /* V9 prefetcha, no effect */
5387*fcf5ef2aSThomas Huth                     goto skip_move;
5388*fcf5ef2aSThomas Huth                 case 0x32: /* V9 ldqfa */
5389*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
5390*fcf5ef2aSThomas Huth                     if (gen_trap_ifnofpu(dc)) {
5391*fcf5ef2aSThomas Huth                         goto jmp_insn;
5392*fcf5ef2aSThomas Huth                     }
5393*fcf5ef2aSThomas Huth                     gen_ldf_asi(dc, cpu_addr, insn, 16, QFPREG(rd));
5394*fcf5ef2aSThomas Huth                     gen_update_fprs_dirty(dc, QFPREG(rd));
5395*fcf5ef2aSThomas Huth                     goto skip_move;
5396*fcf5ef2aSThomas Huth #endif
5397*fcf5ef2aSThomas Huth                 default:
5398*fcf5ef2aSThomas Huth                     goto illegal_insn;
5399*fcf5ef2aSThomas Huth                 }
5400*fcf5ef2aSThomas Huth                 gen_store_gpr(dc, rd, cpu_val);
5401*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
5402*fcf5ef2aSThomas Huth             skip_move: ;
5403*fcf5ef2aSThomas Huth #endif
5404*fcf5ef2aSThomas Huth             } else if (xop >= 0x20 && xop < 0x24) {
5405*fcf5ef2aSThomas Huth                 if (gen_trap_ifnofpu(dc)) {
5406*fcf5ef2aSThomas Huth                     goto jmp_insn;
5407*fcf5ef2aSThomas Huth                 }
5408*fcf5ef2aSThomas Huth                 switch (xop) {
5409*fcf5ef2aSThomas Huth                 case 0x20:      /* ldf, load fpreg */
5410*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5411*fcf5ef2aSThomas Huth                     cpu_dst_32 = gen_dest_fpr_F(dc);
5412*fcf5ef2aSThomas Huth                     tcg_gen_qemu_ld_i32(cpu_dst_32, cpu_addr,
5413*fcf5ef2aSThomas Huth                                         dc->mem_idx, MO_TEUL);
5414*fcf5ef2aSThomas Huth                     gen_store_fpr_F(dc, rd, cpu_dst_32);
5415*fcf5ef2aSThomas Huth                     break;
5416*fcf5ef2aSThomas Huth                 case 0x21:      /* ldfsr, V9 ldxfsr */
5417*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5418*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5419*fcf5ef2aSThomas Huth                     if (rd == 1) {
5420*fcf5ef2aSThomas Huth                         TCGv_i64 t64 = tcg_temp_new_i64();
5421*fcf5ef2aSThomas Huth                         tcg_gen_qemu_ld_i64(t64, cpu_addr,
5422*fcf5ef2aSThomas Huth                                             dc->mem_idx, MO_TEQ);
5423*fcf5ef2aSThomas Huth                         gen_helper_ldxfsr(cpu_fsr, cpu_env, cpu_fsr, t64);
5424*fcf5ef2aSThomas Huth                         tcg_temp_free_i64(t64);
5425*fcf5ef2aSThomas Huth                         break;
5426*fcf5ef2aSThomas Huth                     }
5427*fcf5ef2aSThomas Huth #endif
5428*fcf5ef2aSThomas Huth                     cpu_dst_32 = get_temp_i32(dc);
5429*fcf5ef2aSThomas Huth                     tcg_gen_qemu_ld_i32(cpu_dst_32, cpu_addr,
5430*fcf5ef2aSThomas Huth                                         dc->mem_idx, MO_TEUL);
5431*fcf5ef2aSThomas Huth                     gen_helper_ldfsr(cpu_fsr, cpu_env, cpu_fsr, cpu_dst_32);
5432*fcf5ef2aSThomas Huth                     break;
5433*fcf5ef2aSThomas Huth                 case 0x22:      /* ldqf, load quad fpreg */
5434*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
5435*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5436*fcf5ef2aSThomas Huth                     cpu_src1_64 = tcg_temp_new_i64();
5437*fcf5ef2aSThomas Huth                     tcg_gen_qemu_ld_i64(cpu_src1_64, cpu_addr, dc->mem_idx,
5438*fcf5ef2aSThomas Huth                                         MO_TEQ | MO_ALIGN_4);
5439*fcf5ef2aSThomas Huth                     tcg_gen_addi_tl(cpu_addr, cpu_addr, 8);
5440*fcf5ef2aSThomas Huth                     cpu_src2_64 = tcg_temp_new_i64();
5441*fcf5ef2aSThomas Huth                     tcg_gen_qemu_ld_i64(cpu_src2_64, cpu_addr, dc->mem_idx,
5442*fcf5ef2aSThomas Huth                                         MO_TEQ | MO_ALIGN_4);
5443*fcf5ef2aSThomas Huth                     gen_store_fpr_Q(dc, rd, cpu_src1_64, cpu_src2_64);
5444*fcf5ef2aSThomas Huth                     tcg_temp_free_i64(cpu_src1_64);
5445*fcf5ef2aSThomas Huth                     tcg_temp_free_i64(cpu_src2_64);
5446*fcf5ef2aSThomas Huth                     break;
5447*fcf5ef2aSThomas Huth                 case 0x23:      /* lddf, load double fpreg */
5448*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5449*fcf5ef2aSThomas Huth                     cpu_dst_64 = gen_dest_fpr_D(dc, rd);
5450*fcf5ef2aSThomas Huth                     tcg_gen_qemu_ld_i64(cpu_dst_64, cpu_addr, dc->mem_idx,
5451*fcf5ef2aSThomas Huth                                         MO_TEQ | MO_ALIGN_4);
5452*fcf5ef2aSThomas Huth                     gen_store_fpr_D(dc, rd, cpu_dst_64);
5453*fcf5ef2aSThomas Huth                     break;
5454*fcf5ef2aSThomas Huth                 default:
5455*fcf5ef2aSThomas Huth                     goto illegal_insn;
5456*fcf5ef2aSThomas Huth                 }
5457*fcf5ef2aSThomas Huth             } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) ||
5458*fcf5ef2aSThomas Huth                        xop == 0xe || xop == 0x1e) {
5459*fcf5ef2aSThomas Huth                 TCGv cpu_val = gen_load_gpr(dc, rd);
5460*fcf5ef2aSThomas Huth 
5461*fcf5ef2aSThomas Huth                 switch (xop) {
5462*fcf5ef2aSThomas Huth                 case 0x4: /* st, store word */
5463*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5464*fcf5ef2aSThomas Huth                     tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
5465*fcf5ef2aSThomas Huth                     break;
5466*fcf5ef2aSThomas Huth                 case 0x5: /* stb, store byte */
5467*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5468*fcf5ef2aSThomas Huth                     tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx);
5469*fcf5ef2aSThomas Huth                     break;
5470*fcf5ef2aSThomas Huth                 case 0x6: /* sth, store halfword */
5471*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5472*fcf5ef2aSThomas Huth                     tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx);
5473*fcf5ef2aSThomas Huth                     break;
5474*fcf5ef2aSThomas Huth                 case 0x7: /* std, store double word */
5475*fcf5ef2aSThomas Huth                     if (rd & 1)
5476*fcf5ef2aSThomas Huth                         goto illegal_insn;
5477*fcf5ef2aSThomas Huth                     else {
5478*fcf5ef2aSThomas Huth                         TCGv_i64 t64;
5479*fcf5ef2aSThomas Huth                         TCGv lo;
5480*fcf5ef2aSThomas Huth 
5481*fcf5ef2aSThomas Huth                         gen_address_mask(dc, cpu_addr);
5482*fcf5ef2aSThomas Huth                         lo = gen_load_gpr(dc, rd + 1);
5483*fcf5ef2aSThomas Huth                         t64 = tcg_temp_new_i64();
5484*fcf5ef2aSThomas Huth                         tcg_gen_concat_tl_i64(t64, lo, cpu_val);
5485*fcf5ef2aSThomas Huth                         tcg_gen_qemu_st64(t64, cpu_addr, dc->mem_idx);
5486*fcf5ef2aSThomas Huth                         tcg_temp_free_i64(t64);
5487*fcf5ef2aSThomas Huth                     }
5488*fcf5ef2aSThomas Huth                     break;
5489*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
5490*fcf5ef2aSThomas Huth                 case 0x14: /* sta, V9 stwa, store word alternate */
5491*fcf5ef2aSThomas Huth                     gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUL);
5492*fcf5ef2aSThomas Huth                     break;
5493*fcf5ef2aSThomas Huth                 case 0x15: /* stba, store byte alternate */
5494*fcf5ef2aSThomas Huth                     gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_UB);
5495*fcf5ef2aSThomas Huth                     break;
5496*fcf5ef2aSThomas Huth                 case 0x16: /* stha, store halfword alternate */
5497*fcf5ef2aSThomas Huth                     gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUW);
5498*fcf5ef2aSThomas Huth                     break;
5499*fcf5ef2aSThomas Huth                 case 0x17: /* stda, store double word alternate */
5500*fcf5ef2aSThomas Huth                     if (rd & 1) {
5501*fcf5ef2aSThomas Huth                         goto illegal_insn;
5502*fcf5ef2aSThomas Huth                     }
5503*fcf5ef2aSThomas Huth                     gen_stda_asi(dc, cpu_val, cpu_addr, insn, rd);
5504*fcf5ef2aSThomas Huth                     break;
5505*fcf5ef2aSThomas Huth #endif
5506*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5507*fcf5ef2aSThomas Huth                 case 0x0e: /* V9 stx */
5508*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5509*fcf5ef2aSThomas Huth                     tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx);
5510*fcf5ef2aSThomas Huth                     break;
5511*fcf5ef2aSThomas Huth                 case 0x1e: /* V9 stxa */
5512*fcf5ef2aSThomas Huth                     gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEQ);
5513*fcf5ef2aSThomas Huth                     break;
5514*fcf5ef2aSThomas Huth #endif
5515*fcf5ef2aSThomas Huth                 default:
5516*fcf5ef2aSThomas Huth                     goto illegal_insn;
5517*fcf5ef2aSThomas Huth                 }
5518*fcf5ef2aSThomas Huth             } else if (xop > 0x23 && xop < 0x28) {
5519*fcf5ef2aSThomas Huth                 if (gen_trap_ifnofpu(dc)) {
5520*fcf5ef2aSThomas Huth                     goto jmp_insn;
5521*fcf5ef2aSThomas Huth                 }
5522*fcf5ef2aSThomas Huth                 switch (xop) {
5523*fcf5ef2aSThomas Huth                 case 0x24: /* stf, store fpreg */
5524*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5525*fcf5ef2aSThomas Huth                     cpu_src1_32 = gen_load_fpr_F(dc, rd);
5526*fcf5ef2aSThomas Huth                     tcg_gen_qemu_st_i32(cpu_src1_32, cpu_addr,
5527*fcf5ef2aSThomas Huth                                         dc->mem_idx, MO_TEUL);
5528*fcf5ef2aSThomas Huth                     break;
5529*fcf5ef2aSThomas Huth                 case 0x25: /* stfsr, V9 stxfsr */
5530*fcf5ef2aSThomas Huth                     {
5531*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5532*fcf5ef2aSThomas Huth                         gen_address_mask(dc, cpu_addr);
5533*fcf5ef2aSThomas Huth                         if (rd == 1) {
5534*fcf5ef2aSThomas Huth                             tcg_gen_qemu_st64(cpu_fsr, cpu_addr, dc->mem_idx);
5535*fcf5ef2aSThomas Huth                             break;
5536*fcf5ef2aSThomas Huth                         }
5537*fcf5ef2aSThomas Huth #endif
5538*fcf5ef2aSThomas Huth                         tcg_gen_qemu_st32(cpu_fsr, cpu_addr, dc->mem_idx);
5539*fcf5ef2aSThomas Huth                     }
5540*fcf5ef2aSThomas Huth                     break;
5541*fcf5ef2aSThomas Huth                 case 0x26:
5542*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5543*fcf5ef2aSThomas Huth                     /* V9 stqf, store quad fpreg */
5544*fcf5ef2aSThomas Huth                     CHECK_FPU_FEATURE(dc, FLOAT128);
5545*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5546*fcf5ef2aSThomas Huth                     /* ??? While stqf only requires 4-byte alignment, it is
5547*fcf5ef2aSThomas Huth                        legal for the cpu to signal the unaligned exception.
5548*fcf5ef2aSThomas Huth                        The OS trap handler is then required to fix it up.
5549*fcf5ef2aSThomas Huth                        For qemu, this avoids having to probe the second page
5550*fcf5ef2aSThomas Huth                        before performing the first write.  */
5551*fcf5ef2aSThomas Huth                     cpu_src1_64 = gen_load_fpr_Q0(dc, rd);
5552*fcf5ef2aSThomas Huth                     tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr,
5553*fcf5ef2aSThomas Huth                                         dc->mem_idx, MO_TEQ | MO_ALIGN_16);
5554*fcf5ef2aSThomas Huth                     tcg_gen_addi_tl(cpu_addr, cpu_addr, 8);
5555*fcf5ef2aSThomas Huth                     cpu_src2_64 = gen_load_fpr_Q1(dc, rd);
5556*fcf5ef2aSThomas Huth                     tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr,
5557*fcf5ef2aSThomas Huth                                         dc->mem_idx, MO_TEQ);
5558*fcf5ef2aSThomas Huth                     break;
5559*fcf5ef2aSThomas Huth #else /* !TARGET_SPARC64 */
5560*fcf5ef2aSThomas Huth                     /* stdfq, store floating point queue */
5561*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY)
5562*fcf5ef2aSThomas Huth                     goto illegal_insn;
5563*fcf5ef2aSThomas Huth #else
5564*fcf5ef2aSThomas Huth                     if (!supervisor(dc))
5565*fcf5ef2aSThomas Huth                         goto priv_insn;
5566*fcf5ef2aSThomas Huth                     if (gen_trap_ifnofpu(dc)) {
5567*fcf5ef2aSThomas Huth                         goto jmp_insn;
5568*fcf5ef2aSThomas Huth                     }
5569*fcf5ef2aSThomas Huth                     goto nfq_insn;
5570*fcf5ef2aSThomas Huth #endif
5571*fcf5ef2aSThomas Huth #endif
5572*fcf5ef2aSThomas Huth                 case 0x27: /* stdf, store double fpreg */
5573*fcf5ef2aSThomas Huth                     gen_address_mask(dc, cpu_addr);
5574*fcf5ef2aSThomas Huth                     cpu_src1_64 = gen_load_fpr_D(dc, rd);
5575*fcf5ef2aSThomas Huth                     tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr, dc->mem_idx,
5576*fcf5ef2aSThomas Huth                                         MO_TEQ | MO_ALIGN_4);
5577*fcf5ef2aSThomas Huth                     break;
5578*fcf5ef2aSThomas Huth                 default:
5579*fcf5ef2aSThomas Huth                     goto illegal_insn;
5580*fcf5ef2aSThomas Huth                 }
5581*fcf5ef2aSThomas Huth             } else if (xop > 0x33 && xop < 0x3f) {
5582*fcf5ef2aSThomas Huth                 switch (xop) {
5583*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5584*fcf5ef2aSThomas Huth                 case 0x34: /* V9 stfa */
5585*fcf5ef2aSThomas Huth                     if (gen_trap_ifnofpu(dc)) {
5586*fcf5ef2aSThomas Huth                         goto jmp_insn;
5587*fcf5ef2aSThomas Huth                     }
5588*fcf5ef2aSThomas Huth                     gen_stf_asi(dc, cpu_addr, insn, 4, rd);
5589*fcf5ef2aSThomas Huth                     break;
5590*fcf5ef2aSThomas Huth                 case 0x36: /* V9 stqfa */
5591*fcf5ef2aSThomas Huth                     {
5592*fcf5ef2aSThomas Huth                         CHECK_FPU_FEATURE(dc, FLOAT128);
5593*fcf5ef2aSThomas Huth                         if (gen_trap_ifnofpu(dc)) {
5594*fcf5ef2aSThomas Huth                             goto jmp_insn;
5595*fcf5ef2aSThomas Huth                         }
5596*fcf5ef2aSThomas Huth                         gen_stf_asi(dc, cpu_addr, insn, 16, QFPREG(rd));
5597*fcf5ef2aSThomas Huth                     }
5598*fcf5ef2aSThomas Huth                     break;
5599*fcf5ef2aSThomas Huth                 case 0x37: /* V9 stdfa */
5600*fcf5ef2aSThomas Huth                     if (gen_trap_ifnofpu(dc)) {
5601*fcf5ef2aSThomas Huth                         goto jmp_insn;
5602*fcf5ef2aSThomas Huth                     }
5603*fcf5ef2aSThomas Huth                     gen_stf_asi(dc, cpu_addr, insn, 8, DFPREG(rd));
5604*fcf5ef2aSThomas Huth                     break;
5605*fcf5ef2aSThomas Huth                 case 0x3e: /* V9 casxa */
5606*fcf5ef2aSThomas Huth                     rs2 = GET_FIELD(insn, 27, 31);
5607*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
5608*fcf5ef2aSThomas Huth                     gen_casx_asi(dc, cpu_addr, cpu_src2, insn, rd);
5609*fcf5ef2aSThomas Huth                     break;
5610*fcf5ef2aSThomas Huth #else
5611*fcf5ef2aSThomas Huth                 case 0x34: /* stc */
5612*fcf5ef2aSThomas Huth                 case 0x35: /* stcsr */
5613*fcf5ef2aSThomas Huth                 case 0x36: /* stdcq */
5614*fcf5ef2aSThomas Huth                 case 0x37: /* stdc */
5615*fcf5ef2aSThomas Huth                     goto ncp_insn;
5616*fcf5ef2aSThomas Huth #endif
5617*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
5618*fcf5ef2aSThomas Huth                 case 0x3c: /* V9 or LEON3 casa */
5619*fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64
5620*fcf5ef2aSThomas Huth                     CHECK_IU_FEATURE(dc, CASA);
5621*fcf5ef2aSThomas Huth #endif
5622*fcf5ef2aSThomas Huth                     rs2 = GET_FIELD(insn, 27, 31);
5623*fcf5ef2aSThomas Huth                     cpu_src2 = gen_load_gpr(dc, rs2);
5624*fcf5ef2aSThomas Huth                     gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd);
5625*fcf5ef2aSThomas Huth                     break;
5626*fcf5ef2aSThomas Huth #endif
5627*fcf5ef2aSThomas Huth                 default:
5628*fcf5ef2aSThomas Huth                     goto illegal_insn;
5629*fcf5ef2aSThomas Huth                 }
5630*fcf5ef2aSThomas Huth             } else {
5631*fcf5ef2aSThomas Huth                 goto illegal_insn;
5632*fcf5ef2aSThomas Huth             }
5633*fcf5ef2aSThomas Huth         }
5634*fcf5ef2aSThomas Huth         break;
5635*fcf5ef2aSThomas Huth     }
5636*fcf5ef2aSThomas Huth     /* default case for non jump instructions */
5637*fcf5ef2aSThomas Huth     if (dc->npc == DYNAMIC_PC) {
5638*fcf5ef2aSThomas Huth         dc->pc = DYNAMIC_PC;
5639*fcf5ef2aSThomas Huth         gen_op_next_insn();
5640*fcf5ef2aSThomas Huth     } else if (dc->npc == JUMP_PC) {
5641*fcf5ef2aSThomas Huth         /* we can do a static jump */
5642*fcf5ef2aSThomas Huth         gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
5643*fcf5ef2aSThomas Huth         dc->is_br = 1;
5644*fcf5ef2aSThomas Huth     } else {
5645*fcf5ef2aSThomas Huth         dc->pc = dc->npc;
5646*fcf5ef2aSThomas Huth         dc->npc = dc->npc + 4;
5647*fcf5ef2aSThomas Huth     }
5648*fcf5ef2aSThomas Huth  jmp_insn:
5649*fcf5ef2aSThomas Huth     goto egress;
5650*fcf5ef2aSThomas Huth  illegal_insn:
5651*fcf5ef2aSThomas Huth     gen_exception(dc, TT_ILL_INSN);
5652*fcf5ef2aSThomas Huth     goto egress;
5653*fcf5ef2aSThomas Huth  unimp_flush:
5654*fcf5ef2aSThomas Huth     gen_exception(dc, TT_UNIMP_FLUSH);
5655*fcf5ef2aSThomas Huth     goto egress;
5656*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY)
5657*fcf5ef2aSThomas Huth  priv_insn:
5658*fcf5ef2aSThomas Huth     gen_exception(dc, TT_PRIV_INSN);
5659*fcf5ef2aSThomas Huth     goto egress;
5660*fcf5ef2aSThomas Huth #endif
5661*fcf5ef2aSThomas Huth  nfpu_insn:
5662*fcf5ef2aSThomas Huth     gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP);
5663*fcf5ef2aSThomas Huth     goto egress;
5664*fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
5665*fcf5ef2aSThomas Huth  nfq_insn:
5666*fcf5ef2aSThomas Huth     gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
5667*fcf5ef2aSThomas Huth     goto egress;
5668*fcf5ef2aSThomas Huth #endif
5669*fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64
5670*fcf5ef2aSThomas Huth  ncp_insn:
5671*fcf5ef2aSThomas Huth     gen_exception(dc, TT_NCP_INSN);
5672*fcf5ef2aSThomas Huth     goto egress;
5673*fcf5ef2aSThomas Huth #endif
5674*fcf5ef2aSThomas Huth  egress:
5675*fcf5ef2aSThomas Huth     if (dc->n_t32 != 0) {
5676*fcf5ef2aSThomas Huth         int i;
5677*fcf5ef2aSThomas Huth         for (i = dc->n_t32 - 1; i >= 0; --i) {
5678*fcf5ef2aSThomas Huth             tcg_temp_free_i32(dc->t32[i]);
5679*fcf5ef2aSThomas Huth         }
5680*fcf5ef2aSThomas Huth         dc->n_t32 = 0;
5681*fcf5ef2aSThomas Huth     }
5682*fcf5ef2aSThomas Huth     if (dc->n_ttl != 0) {
5683*fcf5ef2aSThomas Huth         int i;
5684*fcf5ef2aSThomas Huth         for (i = dc->n_ttl - 1; i >= 0; --i) {
5685*fcf5ef2aSThomas Huth             tcg_temp_free(dc->ttl[i]);
5686*fcf5ef2aSThomas Huth         }
5687*fcf5ef2aSThomas Huth         dc->n_ttl = 0;
5688*fcf5ef2aSThomas Huth     }
5689*fcf5ef2aSThomas Huth }
5690*fcf5ef2aSThomas Huth 
5691*fcf5ef2aSThomas Huth void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
5692*fcf5ef2aSThomas Huth {
5693*fcf5ef2aSThomas Huth     SPARCCPU *cpu = sparc_env_get_cpu(env);
5694*fcf5ef2aSThomas Huth     CPUState *cs = CPU(cpu);
5695*fcf5ef2aSThomas Huth     target_ulong pc_start, last_pc;
5696*fcf5ef2aSThomas Huth     DisasContext dc1, *dc = &dc1;
5697*fcf5ef2aSThomas Huth     int num_insns;
5698*fcf5ef2aSThomas Huth     int max_insns;
5699*fcf5ef2aSThomas Huth     unsigned int insn;
5700*fcf5ef2aSThomas Huth 
5701*fcf5ef2aSThomas Huth     memset(dc, 0, sizeof(DisasContext));
5702*fcf5ef2aSThomas Huth     dc->tb = tb;
5703*fcf5ef2aSThomas Huth     pc_start = tb->pc;
5704*fcf5ef2aSThomas Huth     dc->pc = pc_start;
5705*fcf5ef2aSThomas Huth     last_pc = dc->pc;
5706*fcf5ef2aSThomas Huth     dc->npc = (target_ulong) tb->cs_base;
5707*fcf5ef2aSThomas Huth     dc->cc_op = CC_OP_DYNAMIC;
5708*fcf5ef2aSThomas Huth     dc->mem_idx = tb->flags & TB_FLAG_MMU_MASK;
5709*fcf5ef2aSThomas Huth     dc->def = env->def;
5710*fcf5ef2aSThomas Huth     dc->fpu_enabled = tb_fpu_enabled(tb->flags);
5711*fcf5ef2aSThomas Huth     dc->address_mask_32bit = tb_am_enabled(tb->flags);
5712*fcf5ef2aSThomas Huth     dc->singlestep = (cs->singlestep_enabled || singlestep);
5713*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5714*fcf5ef2aSThomas Huth     dc->fprs_dirty = 0;
5715*fcf5ef2aSThomas Huth     dc->asi = (tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff;
5716*fcf5ef2aSThomas Huth #endif
5717*fcf5ef2aSThomas Huth 
5718*fcf5ef2aSThomas Huth     num_insns = 0;
5719*fcf5ef2aSThomas Huth     max_insns = tb->cflags & CF_COUNT_MASK;
5720*fcf5ef2aSThomas Huth     if (max_insns == 0) {
5721*fcf5ef2aSThomas Huth         max_insns = CF_COUNT_MASK;
5722*fcf5ef2aSThomas Huth     }
5723*fcf5ef2aSThomas Huth     if (max_insns > TCG_MAX_INSNS) {
5724*fcf5ef2aSThomas Huth         max_insns = TCG_MAX_INSNS;
5725*fcf5ef2aSThomas Huth     }
5726*fcf5ef2aSThomas Huth 
5727*fcf5ef2aSThomas Huth     gen_tb_start(tb);
5728*fcf5ef2aSThomas Huth     do {
5729*fcf5ef2aSThomas Huth         if (dc->npc & JUMP_PC) {
5730*fcf5ef2aSThomas Huth             assert(dc->jump_pc[1] == dc->pc + 4);
5731*fcf5ef2aSThomas Huth             tcg_gen_insn_start(dc->pc, dc->jump_pc[0] | JUMP_PC);
5732*fcf5ef2aSThomas Huth         } else {
5733*fcf5ef2aSThomas Huth             tcg_gen_insn_start(dc->pc, dc->npc);
5734*fcf5ef2aSThomas Huth         }
5735*fcf5ef2aSThomas Huth         num_insns++;
5736*fcf5ef2aSThomas Huth         last_pc = dc->pc;
5737*fcf5ef2aSThomas Huth 
5738*fcf5ef2aSThomas Huth         if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
5739*fcf5ef2aSThomas Huth             if (dc->pc != pc_start) {
5740*fcf5ef2aSThomas Huth                 save_state(dc);
5741*fcf5ef2aSThomas Huth             }
5742*fcf5ef2aSThomas Huth             gen_helper_debug(cpu_env);
5743*fcf5ef2aSThomas Huth             tcg_gen_exit_tb(0);
5744*fcf5ef2aSThomas Huth             dc->is_br = 1;
5745*fcf5ef2aSThomas Huth             goto exit_gen_loop;
5746*fcf5ef2aSThomas Huth         }
5747*fcf5ef2aSThomas Huth 
5748*fcf5ef2aSThomas Huth         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
5749*fcf5ef2aSThomas Huth             gen_io_start();
5750*fcf5ef2aSThomas Huth         }
5751*fcf5ef2aSThomas Huth 
5752*fcf5ef2aSThomas Huth         insn = cpu_ldl_code(env, dc->pc);
5753*fcf5ef2aSThomas Huth 
5754*fcf5ef2aSThomas Huth         disas_sparc_insn(dc, insn);
5755*fcf5ef2aSThomas Huth 
5756*fcf5ef2aSThomas Huth         if (dc->is_br)
5757*fcf5ef2aSThomas Huth             break;
5758*fcf5ef2aSThomas Huth         /* if the next PC is different, we abort now */
5759*fcf5ef2aSThomas Huth         if (dc->pc != (last_pc + 4))
5760*fcf5ef2aSThomas Huth             break;
5761*fcf5ef2aSThomas Huth         /* if we reach a page boundary, we stop generation so that the
5762*fcf5ef2aSThomas Huth            PC of a TT_TFAULT exception is always in the right page */
5763*fcf5ef2aSThomas Huth         if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
5764*fcf5ef2aSThomas Huth             break;
5765*fcf5ef2aSThomas Huth         /* if single step mode, we generate only one instruction and
5766*fcf5ef2aSThomas Huth            generate an exception */
5767*fcf5ef2aSThomas Huth         if (dc->singlestep) {
5768*fcf5ef2aSThomas Huth             break;
5769*fcf5ef2aSThomas Huth         }
5770*fcf5ef2aSThomas Huth     } while (!tcg_op_buf_full() &&
5771*fcf5ef2aSThomas Huth              (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) &&
5772*fcf5ef2aSThomas Huth              num_insns < max_insns);
5773*fcf5ef2aSThomas Huth 
5774*fcf5ef2aSThomas Huth  exit_gen_loop:
5775*fcf5ef2aSThomas Huth     if (tb->cflags & CF_LAST_IO) {
5776*fcf5ef2aSThomas Huth         gen_io_end();
5777*fcf5ef2aSThomas Huth     }
5778*fcf5ef2aSThomas Huth     if (!dc->is_br) {
5779*fcf5ef2aSThomas Huth         if (dc->pc != DYNAMIC_PC &&
5780*fcf5ef2aSThomas Huth             (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
5781*fcf5ef2aSThomas Huth             /* static PC and NPC: we can use direct chaining */
5782*fcf5ef2aSThomas Huth             gen_goto_tb(dc, 0, dc->pc, dc->npc);
5783*fcf5ef2aSThomas Huth         } else {
5784*fcf5ef2aSThomas Huth             if (dc->pc != DYNAMIC_PC) {
5785*fcf5ef2aSThomas Huth                 tcg_gen_movi_tl(cpu_pc, dc->pc);
5786*fcf5ef2aSThomas Huth             }
5787*fcf5ef2aSThomas Huth             save_npc(dc);
5788*fcf5ef2aSThomas Huth             tcg_gen_exit_tb(0);
5789*fcf5ef2aSThomas Huth         }
5790*fcf5ef2aSThomas Huth     }
5791*fcf5ef2aSThomas Huth     gen_tb_end(tb, num_insns);
5792*fcf5ef2aSThomas Huth 
5793*fcf5ef2aSThomas Huth     tb->size = last_pc + 4 - pc_start;
5794*fcf5ef2aSThomas Huth     tb->icount = num_insns;
5795*fcf5ef2aSThomas Huth 
5796*fcf5ef2aSThomas Huth #ifdef DEBUG_DISAS
5797*fcf5ef2aSThomas Huth     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
5798*fcf5ef2aSThomas Huth         && qemu_log_in_addr_range(pc_start)) {
5799*fcf5ef2aSThomas Huth         qemu_log_lock();
5800*fcf5ef2aSThomas Huth         qemu_log("--------------\n");
5801*fcf5ef2aSThomas Huth         qemu_log("IN: %s\n", lookup_symbol(pc_start));
5802*fcf5ef2aSThomas Huth         log_target_disas(cs, pc_start, last_pc + 4 - pc_start, 0);
5803*fcf5ef2aSThomas Huth         qemu_log("\n");
5804*fcf5ef2aSThomas Huth         qemu_log_unlock();
5805*fcf5ef2aSThomas Huth     }
5806*fcf5ef2aSThomas Huth #endif
5807*fcf5ef2aSThomas Huth }
5808*fcf5ef2aSThomas Huth 
5809*fcf5ef2aSThomas Huth void gen_intermediate_code_init(CPUSPARCState *env)
5810*fcf5ef2aSThomas Huth {
5811*fcf5ef2aSThomas Huth     static int inited;
5812*fcf5ef2aSThomas Huth     static const char gregnames[32][4] = {
5813*fcf5ef2aSThomas Huth         "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
5814*fcf5ef2aSThomas Huth         "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
5815*fcf5ef2aSThomas Huth         "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
5816*fcf5ef2aSThomas Huth         "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
5817*fcf5ef2aSThomas Huth     };
5818*fcf5ef2aSThomas Huth     static const char fregnames[32][4] = {
5819*fcf5ef2aSThomas Huth         "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
5820*fcf5ef2aSThomas Huth         "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
5821*fcf5ef2aSThomas Huth         "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
5822*fcf5ef2aSThomas Huth         "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
5823*fcf5ef2aSThomas Huth     };
5824*fcf5ef2aSThomas Huth 
5825*fcf5ef2aSThomas Huth     static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = {
5826*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5827*fcf5ef2aSThomas Huth         { &cpu_xcc, offsetof(CPUSPARCState, xcc), "xcc" },
5828*fcf5ef2aSThomas Huth         { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" },
5829*fcf5ef2aSThomas Huth #else
5830*fcf5ef2aSThomas Huth         { &cpu_wim, offsetof(CPUSPARCState, wim), "wim" },
5831*fcf5ef2aSThomas Huth #endif
5832*fcf5ef2aSThomas Huth         { &cpu_cc_op, offsetof(CPUSPARCState, cc_op), "cc_op" },
5833*fcf5ef2aSThomas Huth         { &cpu_psr, offsetof(CPUSPARCState, psr), "psr" },
5834*fcf5ef2aSThomas Huth     };
5835*fcf5ef2aSThomas Huth 
5836*fcf5ef2aSThomas Huth     static const struct { TCGv *ptr; int off; const char *name; } rtl[] = {
5837*fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5838*fcf5ef2aSThomas Huth         { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" },
5839*fcf5ef2aSThomas Huth         { &cpu_tick_cmpr, offsetof(CPUSPARCState, tick_cmpr), "tick_cmpr" },
5840*fcf5ef2aSThomas Huth         { &cpu_stick_cmpr, offsetof(CPUSPARCState, stick_cmpr), "stick_cmpr" },
5841*fcf5ef2aSThomas Huth         { &cpu_hstick_cmpr, offsetof(CPUSPARCState, hstick_cmpr),
5842*fcf5ef2aSThomas Huth           "hstick_cmpr" },
5843*fcf5ef2aSThomas Huth         { &cpu_hintp, offsetof(CPUSPARCState, hintp), "hintp" },
5844*fcf5ef2aSThomas Huth         { &cpu_htba, offsetof(CPUSPARCState, htba), "htba" },
5845*fcf5ef2aSThomas Huth         { &cpu_hver, offsetof(CPUSPARCState, hver), "hver" },
5846*fcf5ef2aSThomas Huth         { &cpu_ssr, offsetof(CPUSPARCState, ssr), "ssr" },
5847*fcf5ef2aSThomas Huth         { &cpu_ver, offsetof(CPUSPARCState, version), "ver" },
5848*fcf5ef2aSThomas Huth #endif
5849*fcf5ef2aSThomas Huth         { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" },
5850*fcf5ef2aSThomas Huth         { &cpu_cc_src, offsetof(CPUSPARCState, cc_src), "cc_src" },
5851*fcf5ef2aSThomas Huth         { &cpu_cc_src2, offsetof(CPUSPARCState, cc_src2), "cc_src2" },
5852*fcf5ef2aSThomas Huth         { &cpu_cc_dst, offsetof(CPUSPARCState, cc_dst), "cc_dst" },
5853*fcf5ef2aSThomas Huth         { &cpu_fsr, offsetof(CPUSPARCState, fsr), "fsr" },
5854*fcf5ef2aSThomas Huth         { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" },
5855*fcf5ef2aSThomas Huth         { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" },
5856*fcf5ef2aSThomas Huth         { &cpu_y, offsetof(CPUSPARCState, y), "y" },
5857*fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
5858*fcf5ef2aSThomas Huth         { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" },
5859*fcf5ef2aSThomas Huth #endif
5860*fcf5ef2aSThomas Huth     };
5861*fcf5ef2aSThomas Huth 
5862*fcf5ef2aSThomas Huth     unsigned int i;
5863*fcf5ef2aSThomas Huth 
5864*fcf5ef2aSThomas Huth     /* init various static tables */
5865*fcf5ef2aSThomas Huth     if (inited) {
5866*fcf5ef2aSThomas Huth         return;
5867*fcf5ef2aSThomas Huth     }
5868*fcf5ef2aSThomas Huth     inited = 1;
5869*fcf5ef2aSThomas Huth 
5870*fcf5ef2aSThomas Huth     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
5871*fcf5ef2aSThomas Huth     tcg_ctx.tcg_env = cpu_env;
5872*fcf5ef2aSThomas Huth 
5873*fcf5ef2aSThomas Huth     cpu_regwptr = tcg_global_mem_new_ptr(cpu_env,
5874*fcf5ef2aSThomas Huth                                          offsetof(CPUSPARCState, regwptr),
5875*fcf5ef2aSThomas Huth                                          "regwptr");
5876*fcf5ef2aSThomas Huth 
5877*fcf5ef2aSThomas Huth     for (i = 0; i < ARRAY_SIZE(r32); ++i) {
5878*fcf5ef2aSThomas Huth         *r32[i].ptr = tcg_global_mem_new_i32(cpu_env, r32[i].off, r32[i].name);
5879*fcf5ef2aSThomas Huth     }
5880*fcf5ef2aSThomas Huth 
5881*fcf5ef2aSThomas Huth     for (i = 0; i < ARRAY_SIZE(rtl); ++i) {
5882*fcf5ef2aSThomas Huth         *rtl[i].ptr = tcg_global_mem_new(cpu_env, rtl[i].off, rtl[i].name);
5883*fcf5ef2aSThomas Huth     }
5884*fcf5ef2aSThomas Huth 
5885*fcf5ef2aSThomas Huth     TCGV_UNUSED(cpu_regs[0]);
5886*fcf5ef2aSThomas Huth     for (i = 1; i < 8; ++i) {
5887*fcf5ef2aSThomas Huth         cpu_regs[i] = tcg_global_mem_new(cpu_env,
5888*fcf5ef2aSThomas Huth                                          offsetof(CPUSPARCState, gregs[i]),
5889*fcf5ef2aSThomas Huth                                          gregnames[i]);
5890*fcf5ef2aSThomas Huth     }
5891*fcf5ef2aSThomas Huth 
5892*fcf5ef2aSThomas Huth     for (i = 8; i < 32; ++i) {
5893*fcf5ef2aSThomas Huth         cpu_regs[i] = tcg_global_mem_new(cpu_regwptr,
5894*fcf5ef2aSThomas Huth                                          (i - 8) * sizeof(target_ulong),
5895*fcf5ef2aSThomas Huth                                          gregnames[i]);
5896*fcf5ef2aSThomas Huth     }
5897*fcf5ef2aSThomas Huth 
5898*fcf5ef2aSThomas Huth     for (i = 0; i < TARGET_DPREGS; i++) {
5899*fcf5ef2aSThomas Huth         cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env,
5900*fcf5ef2aSThomas Huth                                             offsetof(CPUSPARCState, fpr[i]),
5901*fcf5ef2aSThomas Huth                                             fregnames[i]);
5902*fcf5ef2aSThomas Huth     }
5903*fcf5ef2aSThomas Huth }
5904*fcf5ef2aSThomas Huth 
5905*fcf5ef2aSThomas Huth void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb,
5906*fcf5ef2aSThomas Huth                           target_ulong *data)
5907*fcf5ef2aSThomas Huth {
5908*fcf5ef2aSThomas Huth     target_ulong pc = data[0];
5909*fcf5ef2aSThomas Huth     target_ulong npc = data[1];
5910*fcf5ef2aSThomas Huth 
5911*fcf5ef2aSThomas Huth     env->pc = pc;
5912*fcf5ef2aSThomas Huth     if (npc == DYNAMIC_PC) {
5913*fcf5ef2aSThomas Huth         /* dynamic NPC: already stored */
5914*fcf5ef2aSThomas Huth     } else if (npc & JUMP_PC) {
5915*fcf5ef2aSThomas Huth         /* jump PC: use 'cond' and the jump targets of the translation */
5916*fcf5ef2aSThomas Huth         if (env->cond) {
5917*fcf5ef2aSThomas Huth             env->npc = npc & ~3;
5918*fcf5ef2aSThomas Huth         } else {
5919*fcf5ef2aSThomas Huth             env->npc = pc + 4;
5920*fcf5ef2aSThomas Huth         }
5921*fcf5ef2aSThomas Huth     } else {
5922*fcf5ef2aSThomas Huth         env->npc = npc;
5923*fcf5ef2aSThomas Huth     }
5924*fcf5ef2aSThomas Huth }
5925