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