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