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