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