|
|
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.1.13! root 1346: #ifdef TARGET_SPARC64
! 1347: if (unlikely(AM_CHECK(dc))) {
! 1348: target &= 0xffffffffULL;
! 1349: }
! 1350: #endif
1.1 root 1351: if (cond == 0x0) {
1.1.1.5 root 1352: /* unconditional not taken */
1353: if (a) {
1354: dc->pc = dc->npc + 4;
1355: dc->npc = dc->pc + 4;
1356: } else {
1357: dc->pc = dc->npc;
1358: dc->npc = dc->pc + 4;
1359: }
1.1 root 1360: } else if (cond == 0x8) {
1.1.1.5 root 1361: /* unconditional taken */
1362: if (a) {
1363: dc->pc = target;
1364: dc->npc = dc->pc + 4;
1365: } else {
1366: dc->pc = dc->npc;
1367: dc->npc = target;
1.1.1.8 root 1368: tcg_gen_mov_tl(cpu_pc, cpu_npc);
1.1.1.5 root 1369: }
1.1 root 1370: } else {
1.1.1.6 root 1371: flush_cond(dc, r_cond);
1.1.1.7 root 1372: gen_cond(r_cond, cc, cond, dc);
1.1.1.5 root 1373: if (a) {
1.1.1.6 root 1374: gen_branch_a(dc, target, dc->npc, r_cond);
1.1 root 1375: dc->is_br = 1;
1.1.1.5 root 1376: } else {
1.1 root 1377: dc->pc = dc->npc;
1378: dc->jump_pc[0] = target;
1.1.1.12 root 1379: if (unlikely(dc->npc == DYNAMIC_PC)) {
1380: dc->jump_pc[1] = DYNAMIC_PC;
1381: tcg_gen_addi_tl(cpu_pc, cpu_npc, 4);
1382: } else {
1383: dc->jump_pc[1] = dc->npc + 4;
1384: dc->npc = JUMP_PC;
1385: }
1.1.1.5 root 1386: }
1.1 root 1387: }
1388: }
1389:
1.1.1.6 root 1390: static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc,
1391: TCGv r_cond)
1.1 root 1392: {
1393: unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
1394: target_ulong target = dc->pc + offset;
1395:
1.1.1.13! root 1396: #ifdef TARGET_SPARC64
! 1397: if (unlikely(AM_CHECK(dc))) {
! 1398: target &= 0xffffffffULL;
! 1399: }
! 1400: #endif
1.1 root 1401: if (cond == 0x0) {
1.1.1.5 root 1402: /* unconditional not taken */
1403: if (a) {
1404: dc->pc = dc->npc + 4;
1405: dc->npc = dc->pc + 4;
1406: } else {
1407: dc->pc = dc->npc;
1408: dc->npc = dc->pc + 4;
1409: }
1.1 root 1410: } else if (cond == 0x8) {
1.1.1.5 root 1411: /* unconditional taken */
1412: if (a) {
1413: dc->pc = target;
1414: dc->npc = dc->pc + 4;
1415: } else {
1416: dc->pc = dc->npc;
1417: dc->npc = target;
1.1.1.8 root 1418: tcg_gen_mov_tl(cpu_pc, cpu_npc);
1.1.1.5 root 1419: }
1.1 root 1420: } else {
1.1.1.6 root 1421: flush_cond(dc, r_cond);
1422: gen_fcond(r_cond, cc, cond);
1.1.1.5 root 1423: if (a) {
1.1.1.6 root 1424: gen_branch_a(dc, target, dc->npc, r_cond);
1.1 root 1425: dc->is_br = 1;
1.1.1.5 root 1426: } else {
1.1 root 1427: dc->pc = dc->npc;
1428: dc->jump_pc[0] = target;
1.1.1.12 root 1429: if (unlikely(dc->npc == DYNAMIC_PC)) {
1430: dc->jump_pc[1] = DYNAMIC_PC;
1431: tcg_gen_addi_tl(cpu_pc, cpu_npc, 4);
1432: } else {
1433: dc->jump_pc[1] = dc->npc + 4;
1434: dc->npc = JUMP_PC;
1435: }
1.1.1.5 root 1436: }
1.1 root 1437: }
1438: }
1439:
1440: #ifdef TARGET_SPARC64
1.1.1.6 root 1441: static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn,
1442: TCGv r_cond, TCGv r_reg)
1.1 root 1443: {
1444: unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29));
1445: target_ulong target = dc->pc + offset;
1446:
1.1.1.13! root 1447: if (unlikely(AM_CHECK(dc))) {
! 1448: target &= 0xffffffffULL;
! 1449: }
1.1.1.6 root 1450: flush_cond(dc, r_cond);
1451: gen_cond_reg(r_cond, cond, r_reg);
1.1 root 1452: if (a) {
1.1.1.6 root 1453: gen_branch_a(dc, target, dc->npc, r_cond);
1.1.1.5 root 1454: dc->is_br = 1;
1.1 root 1455: } else {
1.1.1.5 root 1456: dc->pc = dc->npc;
1457: dc->jump_pc[0] = target;
1.1.1.12 root 1458: if (unlikely(dc->npc == DYNAMIC_PC)) {
1459: dc->jump_pc[1] = DYNAMIC_PC;
1460: tcg_gen_addi_tl(cpu_pc, cpu_npc, 4);
1461: } else {
1462: dc->jump_pc[1] = dc->npc + 4;
1463: dc->npc = JUMP_PC;
1464: }
1.1 root 1465: }
1466: }
1467:
1.1.1.6 root 1468: static inline void gen_op_fcmps(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
1469: {
1470: switch (fccno) {
1471: case 0:
1.1.1.12 root 1472: gen_helper_fcmps(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1473: break;
1474: case 1:
1.1.1.12 root 1475: gen_helper_fcmps_fcc1(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1476: break;
1477: case 2:
1.1.1.12 root 1478: gen_helper_fcmps_fcc2(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1479: break;
1480: case 3:
1.1.1.12 root 1481: gen_helper_fcmps_fcc3(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1482: break;
1483: }
1484: }
1.1 root 1485:
1.1.1.12 root 1486: static inline void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1.1.1.6 root 1487: {
1488: switch (fccno) {
1489: case 0:
1.1.1.12 root 1490: gen_helper_fcmpd(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1491: break;
1492: case 1:
1.1.1.12 root 1493: gen_helper_fcmpd_fcc1(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1494: break;
1495: case 2:
1.1.1.12 root 1496: gen_helper_fcmpd_fcc2(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1497: break;
1498: case 3:
1.1.1.12 root 1499: gen_helper_fcmpd_fcc3(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1500: break;
1501: }
1502: }
1.1.1.5 root 1503:
1.1.1.6 root 1504: static inline void gen_op_fcmpq(int fccno)
1505: {
1506: switch (fccno) {
1507: case 0:
1.1.1.12 root 1508: gen_helper_fcmpq(cpu_env);
1.1.1.6 root 1509: break;
1510: case 1:
1.1.1.12 root 1511: gen_helper_fcmpq_fcc1(cpu_env);
1.1.1.6 root 1512: break;
1513: case 2:
1.1.1.12 root 1514: gen_helper_fcmpq_fcc2(cpu_env);
1.1.1.6 root 1515: break;
1516: case 3:
1.1.1.12 root 1517: gen_helper_fcmpq_fcc3(cpu_env);
1.1.1.6 root 1518: break;
1519: }
1520: }
1.1.1.5 root 1521:
1.1.1.6 root 1522: static inline void gen_op_fcmpes(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
1523: {
1524: switch (fccno) {
1525: case 0:
1.1.1.12 root 1526: gen_helper_fcmpes(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1527: break;
1528: case 1:
1.1.1.12 root 1529: gen_helper_fcmpes_fcc1(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1530: break;
1531: case 2:
1.1.1.12 root 1532: gen_helper_fcmpes_fcc2(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1533: break;
1534: case 3:
1.1.1.12 root 1535: gen_helper_fcmpes_fcc3(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1536: break;
1537: }
1538: }
1.1.1.5 root 1539:
1.1.1.12 root 1540: static inline void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1.1.1.6 root 1541: {
1542: switch (fccno) {
1543: case 0:
1.1.1.12 root 1544: gen_helper_fcmped(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1545: break;
1546: case 1:
1.1.1.12 root 1547: gen_helper_fcmped_fcc1(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1548: break;
1549: case 2:
1.1.1.12 root 1550: gen_helper_fcmped_fcc2(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1551: break;
1552: case 3:
1.1.1.12 root 1553: gen_helper_fcmped_fcc3(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1554: break;
1555: }
1556: }
1.1.1.5 root 1557:
1.1.1.6 root 1558: static inline void gen_op_fcmpeq(int fccno)
1559: {
1560: switch (fccno) {
1561: case 0:
1.1.1.12 root 1562: gen_helper_fcmpeq(cpu_env);
1.1.1.6 root 1563: break;
1564: case 1:
1.1.1.12 root 1565: gen_helper_fcmpeq_fcc1(cpu_env);
1.1.1.6 root 1566: break;
1567: case 2:
1.1.1.12 root 1568: gen_helper_fcmpeq_fcc2(cpu_env);
1.1.1.6 root 1569: break;
1570: case 3:
1.1.1.12 root 1571: gen_helper_fcmpeq_fcc3(cpu_env);
1.1.1.6 root 1572: break;
1573: }
1574: }
1575:
1576: #else
1577:
1578: static inline void gen_op_fcmps(int fccno, TCGv r_rs1, TCGv r_rs2)
1579: {
1.1.1.12 root 1580: gen_helper_fcmps(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1581: }
1582:
1.1.1.12 root 1583: static inline void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1.1.1.6 root 1584: {
1.1.1.12 root 1585: gen_helper_fcmpd(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1586: }
1587:
1588: static inline void gen_op_fcmpq(int fccno)
1589: {
1.1.1.12 root 1590: gen_helper_fcmpq(cpu_env);
1.1.1.6 root 1591: }
1592:
1593: static inline void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2)
1594: {
1.1.1.12 root 1595: gen_helper_fcmpes(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1596: }
1597:
1.1.1.12 root 1598: static inline void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
1.1.1.6 root 1599: {
1.1.1.12 root 1600: gen_helper_fcmped(cpu_env, r_rs1, r_rs2);
1.1.1.6 root 1601: }
1602:
1603: static inline void gen_op_fcmpeq(int fccno)
1604: {
1.1.1.12 root 1605: gen_helper_fcmpeq(cpu_env);
1.1.1.6 root 1606: }
1.1 root 1607: #endif
1608:
1.1.1.6 root 1609: static inline void gen_op_fpexception_im(int fsr_flags)
1610: {
1611: TCGv_i32 r_const;
1612:
1613: tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_NMASK);
1614: tcg_gen_ori_tl(cpu_fsr, cpu_fsr, fsr_flags);
1615: r_const = tcg_const_i32(TT_FP_EXCP);
1.1.1.12 root 1616: gen_helper_raise_exception(cpu_env, r_const);
1.1.1.6 root 1617: tcg_temp_free_i32(r_const);
1618: }
1619:
1620: static int gen_trap_ifnofpu(DisasContext *dc, TCGv r_cond)
1.1.1.3 root 1621: {
1622: #if !defined(CONFIG_USER_ONLY)
1623: if (!dc->fpu_enabled) {
1.1.1.6 root 1624: TCGv_i32 r_const;
1625:
1626: save_state(dc, r_cond);
1627: r_const = tcg_const_i32(TT_NFPU_INSN);
1.1.1.12 root 1628: gen_helper_raise_exception(cpu_env, r_const);
1.1.1.6 root 1629: tcg_temp_free_i32(r_const);
1.1.1.3 root 1630: dc->is_br = 1;
1631: return 1;
1632: }
1633: #endif
1634: return 0;
1635: }
1636:
1.1.1.6 root 1637: static inline void gen_op_clear_ieee_excp_and_FTT(void)
1638: {
1639: tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_CEXC_NMASK);
1640: }
1641:
1.1.1.12 root 1642: static inline void gen_fop_FF(DisasContext *dc, int rd, int rs,
1643: void (*gen)(TCGv_i32, TCGv_ptr, 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, cpu_env, src);
1651:
1652: gen_store_fpr_F(dc, rd, dst);
1653: }
1654:
1655: static inline void gen_ne_fop_FF(DisasContext *dc, int rd, int rs,
1656: void (*gen)(TCGv_i32, TCGv_i32))
1657: {
1658: TCGv_i32 dst, src;
1659:
1660: src = gen_load_fpr_F(dc, rs);
1661: dst = gen_dest_fpr_F();
1662:
1663: gen(dst, src);
1664:
1665: gen_store_fpr_F(dc, rd, dst);
1666: }
1667:
1668: static inline void gen_fop_FFF(DisasContext *dc, int rd, int rs1, int rs2,
1669: void (*gen)(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32))
1.1.1.6 root 1670: {
1.1.1.12 root 1671: TCGv_i32 dst, src1, src2;
1672:
1673: src1 = gen_load_fpr_F(dc, rs1);
1674: src2 = gen_load_fpr_F(dc, rs2);
1675: dst = gen_dest_fpr_F();
1676:
1677: gen(dst, cpu_env, src1, src2);
1678:
1679: gen_store_fpr_F(dc, rd, dst);
1680: }
1681:
1682: #ifdef TARGET_SPARC64
1683: static inline void gen_ne_fop_FFF(DisasContext *dc, int rd, int rs1, int rs2,
1684: void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
1685: {
1686: TCGv_i32 dst, src1, src2;
1687:
1688: src1 = gen_load_fpr_F(dc, rs1);
1689: src2 = gen_load_fpr_F(dc, rs2);
1690: dst = gen_dest_fpr_F();
1691:
1692: gen(dst, src1, src2);
1693:
1694: gen_store_fpr_F(dc, rd, dst);
1695: }
1696: #endif
1697:
1698: static inline void gen_fop_DD(DisasContext *dc, int rd, int rs,
1699: void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i64))
1700: {
1701: TCGv_i64 dst, src;
1702:
1703: src = gen_load_fpr_D(dc, rs);
1704: dst = gen_dest_fpr_D();
1705:
1706: gen(dst, cpu_env, src);
1707:
1708: gen_store_fpr_D(dc, rd, dst);
1709: }
1710:
1711: #ifdef TARGET_SPARC64
1712: static inline void gen_ne_fop_DD(DisasContext *dc, int rd, int rs,
1713: void (*gen)(TCGv_i64, TCGv_i64))
1714: {
1715: TCGv_i64 dst, src;
1716:
1717: src = gen_load_fpr_D(dc, rs);
1718: dst = gen_dest_fpr_D();
1719:
1720: gen(dst, src);
1721:
1722: gen_store_fpr_D(dc, rd, dst);
1723: }
1724: #endif
1725:
1726: static inline void gen_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2,
1727: void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64))
1728: {
1729: TCGv_i64 dst, src1, src2;
1730:
1731: src1 = gen_load_fpr_D(dc, rs1);
1732: src2 = gen_load_fpr_D(dc, rs2);
1733: dst = gen_dest_fpr_D();
1734:
1735: gen(dst, cpu_env, src1, src2);
1736:
1737: gen_store_fpr_D(dc, rd, dst);
1738: }
1739:
1740: #ifdef TARGET_SPARC64
1741: static inline void gen_ne_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2,
1742: void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64))
1743: {
1744: TCGv_i64 dst, src1, src2;
1745:
1746: src1 = gen_load_fpr_D(dc, rs1);
1747: src2 = gen_load_fpr_D(dc, rs2);
1748: dst = gen_dest_fpr_D();
1749:
1750: gen(dst, src1, src2);
1751:
1752: gen_store_fpr_D(dc, rd, dst);
1753: }
1754:
1755: static inline void gen_gsr_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2,
1756: void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
1757: {
1758: TCGv_i64 dst, src1, src2;
1759:
1760: src1 = gen_load_fpr_D(dc, rs1);
1761: src2 = gen_load_fpr_D(dc, rs2);
1762: dst = gen_dest_fpr_D();
1763:
1764: gen(dst, cpu_gsr, src1, src2);
1765:
1766: gen_store_fpr_D(dc, rd, dst);
1767: }
1768:
1769: static inline void gen_ne_fop_DDDD(DisasContext *dc, int rd, int rs1, int rs2,
1770: void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
1771: {
1772: TCGv_i64 dst, src0, src1, src2;
1773:
1774: src1 = gen_load_fpr_D(dc, rs1);
1775: src2 = gen_load_fpr_D(dc, rs2);
1776: src0 = gen_load_fpr_D(dc, rd);
1777: dst = gen_dest_fpr_D();
1778:
1779: gen(dst, src0, src1, src2);
1780:
1781: gen_store_fpr_D(dc, rd, dst);
1782: }
1783: #endif
1784:
1785: static inline void gen_fop_QQ(DisasContext *dc, int rd, int rs,
1786: void (*gen)(TCGv_ptr))
1787: {
1788: gen_op_load_fpr_QT1(QFPREG(rs));
1789:
1790: gen(cpu_env);
1791:
1792: gen_op_store_QT0_fpr(QFPREG(rd));
1793: gen_update_fprs_dirty(QFPREG(rd));
1794: }
1795:
1796: #ifdef TARGET_SPARC64
1797: static inline void gen_ne_fop_QQ(DisasContext *dc, int rd, int rs,
1798: void (*gen)(TCGv_ptr))
1799: {
1800: gen_op_load_fpr_QT1(QFPREG(rs));
1801:
1802: gen(cpu_env);
1803:
1804: gen_op_store_QT0_fpr(QFPREG(rd));
1805: gen_update_fprs_dirty(QFPREG(rd));
1806: }
1807: #endif
1808:
1809: static inline void gen_fop_QQQ(DisasContext *dc, int rd, int rs1, int rs2,
1810: void (*gen)(TCGv_ptr))
1811: {
1812: gen_op_load_fpr_QT0(QFPREG(rs1));
1813: gen_op_load_fpr_QT1(QFPREG(rs2));
1814:
1815: gen(cpu_env);
1816:
1817: gen_op_store_QT0_fpr(QFPREG(rd));
1818: gen_update_fprs_dirty(QFPREG(rd));
1819: }
1820:
1821: static inline void gen_fop_DFF(DisasContext *dc, int rd, int rs1, int rs2,
1822: void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i32, TCGv_i32))
1823: {
1824: TCGv_i64 dst;
1825: TCGv_i32 src1, src2;
1826:
1827: src1 = gen_load_fpr_F(dc, rs1);
1828: src2 = gen_load_fpr_F(dc, rs2);
1829: dst = gen_dest_fpr_D();
1830:
1831: gen(dst, cpu_env, src1, src2);
1832:
1833: gen_store_fpr_D(dc, rd, dst);
1834: }
1835:
1836: static inline void gen_fop_QDD(DisasContext *dc, int rd, int rs1, int rs2,
1837: void (*gen)(TCGv_ptr, TCGv_i64, TCGv_i64))
1838: {
1839: TCGv_i64 src1, src2;
1840:
1841: src1 = gen_load_fpr_D(dc, rs1);
1842: src2 = gen_load_fpr_D(dc, rs2);
1843:
1844: gen(cpu_env, src1, src2);
1845:
1846: gen_op_store_QT0_fpr(QFPREG(rd));
1847: gen_update_fprs_dirty(QFPREG(rd));
1848: }
1849:
1850: #ifdef TARGET_SPARC64
1851: static inline void gen_fop_DF(DisasContext *dc, int rd, int rs,
1852: void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i32))
1853: {
1854: TCGv_i64 dst;
1855: TCGv_i32 src;
1856:
1857: src = gen_load_fpr_F(dc, rs);
1858: dst = gen_dest_fpr_D();
1859:
1860: gen(dst, cpu_env, src);
1861:
1862: gen_store_fpr_D(dc, rd, dst);
1863: }
1864: #endif
1865:
1866: static inline void gen_ne_fop_DF(DisasContext *dc, int rd, int rs,
1867: void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i32))
1868: {
1869: TCGv_i64 dst;
1870: TCGv_i32 src;
1871:
1872: src = gen_load_fpr_F(dc, rs);
1873: dst = gen_dest_fpr_D();
1874:
1875: gen(dst, cpu_env, src);
1876:
1877: gen_store_fpr_D(dc, rd, dst);
1878: }
1879:
1880: static inline void gen_fop_FD(DisasContext *dc, int rd, int rs,
1881: void (*gen)(TCGv_i32, TCGv_ptr, TCGv_i64))
1882: {
1883: TCGv_i32 dst;
1884: TCGv_i64 src;
1885:
1886: src = gen_load_fpr_D(dc, rs);
1887: dst = gen_dest_fpr_F();
1888:
1889: gen(dst, cpu_env, src);
1890:
1891: gen_store_fpr_F(dc, rd, dst);
1892: }
1893:
1894: static inline void gen_fop_FQ(DisasContext *dc, int rd, int rs,
1895: void (*gen)(TCGv_i32, TCGv_ptr))
1896: {
1897: TCGv_i32 dst;
1898:
1899: gen_op_load_fpr_QT1(QFPREG(rs));
1900: dst = gen_dest_fpr_F();
1901:
1902: gen(dst, cpu_env);
1903:
1904: gen_store_fpr_F(dc, rd, dst);
1905: }
1906:
1907: static inline void gen_fop_DQ(DisasContext *dc, int rd, int rs,
1908: void (*gen)(TCGv_i64, TCGv_ptr))
1909: {
1910: TCGv_i64 dst;
1911:
1912: gen_op_load_fpr_QT1(QFPREG(rs));
1913: dst = gen_dest_fpr_D();
1914:
1915: gen(dst, cpu_env);
1916:
1917: gen_store_fpr_D(dc, rd, dst);
1918: }
1919:
1920: static inline void gen_ne_fop_QF(DisasContext *dc, int rd, int rs,
1921: void (*gen)(TCGv_ptr, TCGv_i32))
1922: {
1923: TCGv_i32 src;
1924:
1925: src = gen_load_fpr_F(dc, rs);
1926:
1927: gen(cpu_env, src);
1928:
1929: gen_op_store_QT0_fpr(QFPREG(rd));
1930: gen_update_fprs_dirty(QFPREG(rd));
1931: }
1932:
1933: static inline void gen_ne_fop_QD(DisasContext *dc, int rd, int rs,
1934: void (*gen)(TCGv_ptr, TCGv_i64))
1935: {
1936: TCGv_i64 src;
1937:
1938: src = gen_load_fpr_D(dc, rs);
1939:
1940: gen(cpu_env, src);
1941:
1942: gen_op_store_QT0_fpr(QFPREG(rd));
1943: gen_update_fprs_dirty(QFPREG(rd));
1.1.1.6 root 1944: }
1945:
1946: /* asi moves */
1947: #ifdef TARGET_SPARC64
1948: static inline TCGv_i32 gen_get_asi(int insn, TCGv r_addr)
1949: {
1950: int asi;
1951: TCGv_i32 r_asi;
1952:
1953: if (IS_IMM) {
1954: r_asi = tcg_temp_new_i32();
1955: tcg_gen_mov_i32(r_asi, cpu_asi);
1956: } else {
1957: asi = GET_FIELD(insn, 19, 26);
1958: r_asi = tcg_const_i32(asi);
1959: }
1960: return r_asi;
1961: }
1962:
1963: static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
1964: int sign)
1965: {
1966: TCGv_i32 r_asi, r_size, r_sign;
1967:
1968: r_asi = gen_get_asi(insn, addr);
1969: r_size = tcg_const_i32(size);
1970: r_sign = tcg_const_i32(sign);
1.1.1.13! root 1971: gen_helper_ld_asi(dst, cpu_env, addr, r_asi, r_size, r_sign);
1.1.1.6 root 1972: tcg_temp_free_i32(r_sign);
1973: tcg_temp_free_i32(r_size);
1974: tcg_temp_free_i32(r_asi);
1975: }
1976:
1977: static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
1978: {
1979: TCGv_i32 r_asi, r_size;
1980:
1981: r_asi = gen_get_asi(insn, addr);
1982: r_size = tcg_const_i32(size);
1.1.1.13! root 1983: gen_helper_st_asi(cpu_env, addr, src, r_asi, r_size);
1.1.1.6 root 1984: tcg_temp_free_i32(r_size);
1985: tcg_temp_free_i32(r_asi);
1986: }
1987:
1988: static inline void gen_ldf_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);
1.1.1.13! root 1995: gen_helper_ldf_asi(cpu_env, addr, r_asi, r_size, r_rd);
1.1.1.6 root 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_stf_asi(TCGv addr, int insn, int size, int rd)
2002: {
2003: TCGv_i32 r_asi, r_size, r_rd;
2004:
2005: r_asi = gen_get_asi(insn, addr);
2006: r_size = tcg_const_i32(size);
2007: r_rd = tcg_const_i32(rd);
1.1.1.13! root 2008: gen_helper_stf_asi(cpu_env, addr, r_asi, r_size, r_rd);
1.1.1.6 root 2009: tcg_temp_free_i32(r_rd);
2010: tcg_temp_free_i32(r_size);
2011: tcg_temp_free_i32(r_asi);
2012: }
2013:
2014: static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn)
2015: {
2016: TCGv_i32 r_asi, r_size, r_sign;
2017:
2018: r_asi = gen_get_asi(insn, addr);
2019: r_size = tcg_const_i32(4);
2020: r_sign = tcg_const_i32(0);
1.1.1.13! root 2021: gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
1.1.1.6 root 2022: tcg_temp_free_i32(r_sign);
1.1.1.13! root 2023: gen_helper_st_asi(cpu_env, addr, dst, r_asi, r_size);
1.1.1.6 root 2024: tcg_temp_free_i32(r_size);
2025: tcg_temp_free_i32(r_asi);
2026: tcg_gen_trunc_i64_tl(dst, cpu_tmp64);
2027: }
2028:
2029: static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd)
2030: {
2031: TCGv_i32 r_asi, r_rd;
2032:
2033: r_asi = gen_get_asi(insn, addr);
2034: r_rd = tcg_const_i32(rd);
1.1.1.13! root 2035: gen_helper_ldda_asi(cpu_env, addr, r_asi, r_rd);
1.1.1.6 root 2036: tcg_temp_free_i32(r_rd);
2037: tcg_temp_free_i32(r_asi);
2038: }
2039:
2040: static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd)
2041: {
2042: TCGv_i32 r_asi, r_size;
2043:
2044: gen_movl_reg_TN(rd + 1, cpu_tmp0);
2045: tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, hi);
2046: r_asi = gen_get_asi(insn, addr);
2047: r_size = tcg_const_i32(8);
1.1.1.13! root 2048: gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size);
1.1.1.6 root 2049: tcg_temp_free_i32(r_size);
2050: tcg_temp_free_i32(r_asi);
2051: }
2052:
2053: static inline void gen_cas_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
2054: int rd)
2055: {
2056: TCGv r_val1;
2057: TCGv_i32 r_asi;
2058:
2059: r_val1 = tcg_temp_new();
2060: gen_movl_reg_TN(rd, r_val1);
2061: r_asi = gen_get_asi(insn, addr);
1.1.1.13! root 2062: gen_helper_cas_asi(dst, cpu_env, addr, r_val1, val2, r_asi);
1.1.1.6 root 2063: tcg_temp_free_i32(r_asi);
2064: tcg_temp_free(r_val1);
2065: }
2066:
2067: static inline void gen_casx_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
2068: int rd)
2069: {
2070: TCGv_i32 r_asi;
2071:
2072: gen_movl_reg_TN(rd, cpu_tmp64);
2073: r_asi = gen_get_asi(insn, addr);
1.1.1.13! root 2074: gen_helper_casx_asi(dst, cpu_env, addr, cpu_tmp64, val2, r_asi);
1.1.1.6 root 2075: tcg_temp_free_i32(r_asi);
2076: }
2077:
2078: #elif !defined(CONFIG_USER_ONLY)
2079:
2080: static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
2081: int sign)
2082: {
2083: TCGv_i32 r_asi, r_size, r_sign;
2084:
2085: r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
2086: r_size = tcg_const_i32(size);
2087: r_sign = tcg_const_i32(sign);
1.1.1.13! root 2088: gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
1.1.1.6 root 2089: tcg_temp_free(r_sign);
2090: tcg_temp_free(r_size);
2091: tcg_temp_free(r_asi);
2092: tcg_gen_trunc_i64_tl(dst, cpu_tmp64);
2093: }
2094:
2095: static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
2096: {
2097: TCGv_i32 r_asi, r_size;
2098:
2099: tcg_gen_extu_tl_i64(cpu_tmp64, src);
2100: r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
2101: r_size = tcg_const_i32(size);
1.1.1.13! root 2102: gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size);
1.1.1.6 root 2103: tcg_temp_free(r_size);
2104: tcg_temp_free(r_asi);
2105: }
2106:
2107: static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn)
2108: {
2109: TCGv_i32 r_asi, r_size, r_sign;
2110: TCGv_i64 r_val;
2111:
2112: r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
2113: r_size = tcg_const_i32(4);
2114: r_sign = tcg_const_i32(0);
1.1.1.13! root 2115: gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
1.1.1.6 root 2116: tcg_temp_free(r_sign);
2117: r_val = tcg_temp_new_i64();
2118: tcg_gen_extu_tl_i64(r_val, dst);
1.1.1.13! root 2119: gen_helper_st_asi(cpu_env, addr, r_val, r_asi, r_size);
1.1.1.6 root 2120: tcg_temp_free_i64(r_val);
2121: tcg_temp_free(r_size);
2122: tcg_temp_free(r_asi);
2123: tcg_gen_trunc_i64_tl(dst, cpu_tmp64);
2124: }
2125:
2126: static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd)
2127: {
2128: TCGv_i32 r_asi, r_size, r_sign;
2129:
2130: r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
2131: r_size = tcg_const_i32(8);
2132: r_sign = tcg_const_i32(0);
1.1.1.13! root 2133: gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
1.1.1.6 root 2134: tcg_temp_free(r_sign);
2135: tcg_temp_free(r_size);
2136: tcg_temp_free(r_asi);
2137: tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64);
2138: gen_movl_TN_reg(rd + 1, cpu_tmp0);
2139: tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32);
2140: tcg_gen_trunc_i64_tl(hi, cpu_tmp64);
2141: gen_movl_TN_reg(rd, hi);
2142: }
2143:
2144: static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd)
2145: {
2146: TCGv_i32 r_asi, r_size;
2147:
2148: gen_movl_reg_TN(rd + 1, cpu_tmp0);
2149: tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, hi);
2150: r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
2151: r_size = tcg_const_i32(8);
1.1.1.13! root 2152: gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size);
1.1.1.6 root 2153: tcg_temp_free(r_size);
2154: tcg_temp_free(r_asi);
2155: }
2156: #endif
2157:
2158: #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2159: static inline void gen_ldstub_asi(TCGv dst, TCGv addr, int insn)
2160: {
2161: TCGv_i64 r_val;
2162: TCGv_i32 r_asi, r_size;
2163:
2164: gen_ld_asi(dst, addr, insn, 1, 0);
2165:
2166: r_val = tcg_const_i64(0xffULL);
2167: r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
2168: r_size = tcg_const_i32(1);
1.1.1.13! root 2169: gen_helper_st_asi(cpu_env, addr, r_val, r_asi, r_size);
1.1.1.6 root 2170: tcg_temp_free_i32(r_size);
2171: tcg_temp_free_i32(r_asi);
2172: tcg_temp_free_i64(r_val);
2173: }
2174: #endif
2175:
2176: static inline TCGv get_src1(unsigned int insn, TCGv def)
2177: {
2178: TCGv r_rs1 = def;
2179: unsigned int rs1;
2180:
2181: rs1 = GET_FIELD(insn, 13, 17);
1.1.1.9 root 2182: if (rs1 == 0) {
2183: tcg_gen_movi_tl(def, 0);
2184: } else if (rs1 < 8) {
1.1.1.6 root 2185: r_rs1 = cpu_gregs[rs1];
1.1.1.9 root 2186: } else {
1.1.1.6 root 2187: tcg_gen_ld_tl(def, cpu_regwptr, (rs1 - 8) * sizeof(target_ulong));
1.1.1.9 root 2188: }
1.1.1.6 root 2189: return r_rs1;
2190: }
2191:
2192: static inline TCGv get_src2(unsigned int insn, TCGv def)
2193: {
2194: TCGv r_rs2 = def;
2195:
2196: if (IS_IMM) { /* immediate */
1.1.1.9 root 2197: target_long simm = GET_FIELDs(insn, 19, 31);
2198: tcg_gen_movi_tl(def, simm);
1.1.1.6 root 2199: } else { /* register */
1.1.1.9 root 2200: unsigned int rs2 = GET_FIELD(insn, 27, 31);
2201: if (rs2 == 0) {
2202: tcg_gen_movi_tl(def, 0);
2203: } else if (rs2 < 8) {
1.1.1.6 root 2204: r_rs2 = cpu_gregs[rs2];
1.1.1.9 root 2205: } else {
1.1.1.6 root 2206: tcg_gen_ld_tl(def, cpu_regwptr, (rs2 - 8) * sizeof(target_ulong));
1.1.1.9 root 2207: }
1.1.1.6 root 2208: }
2209: return r_rs2;
2210: }
2211:
1.1.1.8 root 2212: #ifdef TARGET_SPARC64
2213: static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_ptr cpu_env)
2214: {
1.1.1.9 root 2215: TCGv_i32 r_tl = tcg_temp_new_i32();
1.1.1.8 root 2216:
2217: /* load env->tl into r_tl */
1.1.1.9 root 2218: tcg_gen_ld_i32(r_tl, cpu_env, offsetof(CPUSPARCState, tl));
1.1.1.8 root 2219:
2220: /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
1.1.1.9 root 2221: tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK);
1.1.1.8 root 2222:
2223: /* calculate offset to current trap state from env->ts, reuse r_tl */
1.1.1.9 root 2224: tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
1.1.1.13! root 2225: tcg_gen_addi_ptr(r_tsptr, cpu_env, offsetof(CPUSPARCState, ts));
1.1.1.8 root 2226:
2227: /* tsptr = env->ts[env->tl & MAXTL_MASK] */
1.1.1.9 root 2228: {
2229: TCGv_ptr r_tl_tmp = tcg_temp_new_ptr();
2230: tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl);
2231: tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp);
2232: tcg_temp_free_ptr(r_tl_tmp);
2233: }
1.1.1.8 root 2234:
1.1.1.9 root 2235: tcg_temp_free_i32(r_tl);
1.1.1.8 root 2236: }
1.1.1.12 root 2237:
2238: static void gen_edge(DisasContext *dc, TCGv dst, TCGv s1, TCGv s2,
2239: int width, bool cc, bool left)
2240: {
2241: TCGv lo1, lo2, t1, t2;
2242: uint64_t amask, tabl, tabr;
2243: int shift, imask, omask;
2244:
2245: if (cc) {
2246: tcg_gen_mov_tl(cpu_cc_src, s1);
2247: tcg_gen_mov_tl(cpu_cc_src2, s2);
2248: tcg_gen_sub_tl(cpu_cc_dst, s1, s2);
2249: tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB);
2250: dc->cc_op = CC_OP_SUB;
2251: }
2252:
2253: /* Theory of operation: there are two tables, left and right (not to
2254: be confused with the left and right versions of the opcode). These
2255: are indexed by the low 3 bits of the inputs. To make things "easy",
2256: these tables are loaded into two constants, TABL and TABR below.
2257: The operation index = (input & imask) << shift calculates the index
2258: into the constant, while val = (table >> index) & omask calculates
2259: the value we're looking for. */
2260: switch (width) {
2261: case 8:
2262: imask = 0x7;
2263: shift = 3;
2264: omask = 0xff;
2265: if (left) {
2266: tabl = 0x80c0e0f0f8fcfeffULL;
2267: tabr = 0xff7f3f1f0f070301ULL;
2268: } else {
2269: tabl = 0x0103070f1f3f7fffULL;
2270: tabr = 0xfffefcf8f0e0c080ULL;
2271: }
2272: break;
2273: case 16:
2274: imask = 0x6;
2275: shift = 1;
2276: omask = 0xf;
2277: if (left) {
2278: tabl = 0x8cef;
2279: tabr = 0xf731;
2280: } else {
2281: tabl = 0x137f;
2282: tabr = 0xfec8;
2283: }
2284: break;
2285: case 32:
2286: imask = 0x4;
2287: shift = 0;
2288: omask = 0x3;
2289: if (left) {
2290: tabl = (2 << 2) | 3;
2291: tabr = (3 << 2) | 1;
2292: } else {
2293: tabl = (1 << 2) | 3;
2294: tabr = (3 << 2) | 2;
2295: }
2296: break;
2297: default:
2298: abort();
2299: }
2300:
2301: lo1 = tcg_temp_new();
2302: lo2 = tcg_temp_new();
2303: tcg_gen_andi_tl(lo1, s1, imask);
2304: tcg_gen_andi_tl(lo2, s2, imask);
2305: tcg_gen_shli_tl(lo1, lo1, shift);
2306: tcg_gen_shli_tl(lo2, lo2, shift);
2307:
2308: t1 = tcg_const_tl(tabl);
2309: t2 = tcg_const_tl(tabr);
2310: tcg_gen_shr_tl(lo1, t1, lo1);
2311: tcg_gen_shr_tl(lo2, t2, lo2);
2312: tcg_gen_andi_tl(dst, lo1, omask);
2313: tcg_gen_andi_tl(lo2, lo2, omask);
2314:
2315: amask = -8;
2316: if (AM_CHECK(dc)) {
2317: amask &= 0xffffffffULL;
2318: }
2319: tcg_gen_andi_tl(s1, s1, amask);
2320: tcg_gen_andi_tl(s2, s2, amask);
2321:
2322: /* We want to compute
2323: dst = (s1 == s2 ? lo1 : lo1 & lo2).
2324: We've already done dst = lo1, so this reduces to
2325: dst &= (s1 == s2 ? -1 : lo2)
2326: Which we perform by
2327: lo2 |= -(s1 == s2)
2328: dst &= lo2
2329: */
2330: tcg_gen_setcond_tl(TCG_COND_EQ, t1, s1, s2);
2331: tcg_gen_neg_tl(t1, t1);
2332: tcg_gen_or_tl(lo2, lo2, t1);
2333: tcg_gen_and_tl(dst, dst, lo2);
2334:
2335: tcg_temp_free(lo1);
2336: tcg_temp_free(lo2);
2337: tcg_temp_free(t1);
2338: tcg_temp_free(t2);
2339: }
2340:
2341: static void gen_alignaddr(TCGv dst, TCGv s1, TCGv s2, bool left)
2342: {
2343: TCGv tmp = tcg_temp_new();
2344:
2345: tcg_gen_add_tl(tmp, s1, s2);
2346: tcg_gen_andi_tl(dst, tmp, -8);
2347: if (left) {
2348: tcg_gen_neg_tl(tmp, tmp);
2349: }
2350: tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
2351:
2352: tcg_temp_free(tmp);
2353: }
2354:
2355: static void gen_faligndata(TCGv dst, TCGv gsr, TCGv s1, TCGv s2)
2356: {
2357: TCGv t1, t2, shift;
2358:
2359: t1 = tcg_temp_new();
2360: t2 = tcg_temp_new();
2361: shift = tcg_temp_new();
2362:
2363: tcg_gen_andi_tl(shift, gsr, 7);
2364: tcg_gen_shli_tl(shift, shift, 3);
2365: tcg_gen_shl_tl(t1, s1, shift);
2366:
2367: /* A shift of 64 does not produce 0 in TCG. Divide this into a
2368: shift of (up to 63) followed by a constant shift of 1. */
2369: tcg_gen_xori_tl(shift, shift, 63);
2370: tcg_gen_shr_tl(t2, s2, shift);
2371: tcg_gen_shri_tl(t2, t2, 1);
2372:
2373: tcg_gen_or_tl(dst, t1, t2);
2374:
2375: tcg_temp_free(t1);
2376: tcg_temp_free(t2);
2377: tcg_temp_free(shift);
2378: }
1.1.1.8 root 2379: #endif
2380:
1.1.1.6 root 2381: #define CHECK_IU_FEATURE(dc, FEATURE) \
2382: if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
2383: goto illegal_insn;
2384: #define CHECK_FPU_FEATURE(dc, FEATURE) \
2385: if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
2386: goto nfpu_insn;
2387:
1.1 root 2388: /* before an instruction, dc->pc must be static */
1.1.1.13! root 2389: static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
1.1 root 2390: {
1.1.1.13! root 2391: unsigned int opc, rs1, rs2, rd;
1.1.1.9 root 2392: TCGv cpu_src1, cpu_src2, cpu_tmp1, cpu_tmp2;
1.1.1.12 root 2393: TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
2394: TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
1.1.1.7 root 2395: target_long simm;
1.1 root 2396:
1.1.1.6 root 2397: if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
2398: tcg_gen_debug_insn_start(dc->pc);
1.1.1.13! root 2399:
1.1 root 2400: opc = GET_FIELD(insn, 0, 1);
2401:
2402: rd = GET_FIELD(insn, 2, 6);
1.1.1.6 root 2403:
1.1.1.9 root 2404: cpu_tmp1 = cpu_src1 = tcg_temp_new();
2405: cpu_tmp2 = cpu_src2 = tcg_temp_new();
1.1.1.6 root 2406:
1.1 root 2407: switch (opc) {
1.1.1.5 root 2408: case 0: /* branches/sethi */
2409: {
2410: unsigned int xop = GET_FIELD(insn, 7, 9);
2411: int32_t target;
2412: switch (xop) {
2413: #ifdef TARGET_SPARC64
2414: case 0x1: /* V9 BPcc */
2415: {
2416: int cc;
2417:
2418: target = GET_FIELD_SP(insn, 0, 18);
1.1.1.11 root 2419: target = sign_extend(target, 19);
1.1.1.5 root 2420: target <<= 2;
2421: cc = GET_FIELD_SP(insn, 20, 21);
2422: if (cc == 0)
1.1.1.6 root 2423: do_branch(dc, target, insn, 0, cpu_cond);
1.1.1.5 root 2424: else if (cc == 2)
1.1.1.6 root 2425: do_branch(dc, target, insn, 1, cpu_cond);
1.1.1.5 root 2426: else
2427: goto illegal_insn;
2428: goto jmp_insn;
2429: }
2430: case 0x3: /* V9 BPr */
2431: {
2432: target = GET_FIELD_SP(insn, 0, 13) |
1.1.1.3 root 2433: (GET_FIELD_SP(insn, 20, 21) << 14);
1.1.1.5 root 2434: target = sign_extend(target, 16);
2435: target <<= 2;
1.1.1.6 root 2436: cpu_src1 = get_src1(insn, cpu_src1);
2437: do_branch_reg(dc, target, insn, cpu_cond, cpu_src1);
1.1.1.5 root 2438: goto jmp_insn;
2439: }
2440: case 0x5: /* V9 FBPcc */
2441: {
2442: int cc = GET_FIELD_SP(insn, 20, 21);
1.1.1.6 root 2443: if (gen_trap_ifnofpu(dc, cpu_cond))
1.1.1.3 root 2444: goto jmp_insn;
1.1.1.5 root 2445: target = GET_FIELD_SP(insn, 0, 18);
2446: target = sign_extend(target, 19);
2447: target <<= 2;
1.1.1.6 root 2448: do_fbranch(dc, target, insn, cc, cpu_cond);
1.1.1.5 root 2449: goto jmp_insn;
2450: }
2451: #else
2452: case 0x7: /* CBN+x */
2453: {
2454: goto ncp_insn;
2455: }
2456: #endif
2457: case 0x2: /* BN+x */
2458: {
2459: target = GET_FIELD(insn, 10, 31);
2460: target = sign_extend(target, 22);
2461: target <<= 2;
1.1.1.6 root 2462: do_branch(dc, target, insn, 0, cpu_cond);
1.1.1.5 root 2463: goto jmp_insn;
2464: }
2465: case 0x6: /* FBN+x */
2466: {
1.1.1.6 root 2467: if (gen_trap_ifnofpu(dc, cpu_cond))
1.1.1.3 root 2468: goto jmp_insn;
1.1.1.5 root 2469: target = GET_FIELD(insn, 10, 31);
2470: target = sign_extend(target, 22);
2471: target <<= 2;
1.1.1.6 root 2472: do_fbranch(dc, target, insn, 0, cpu_cond);
1.1.1.5 root 2473: goto jmp_insn;
2474: }
2475: case 0x4: /* SETHI */
2476: if (rd) { // nop
2477: uint32_t value = GET_FIELD(insn, 10, 31);
1.1.1.6 root 2478: TCGv r_const;
2479:
2480: r_const = tcg_const_tl(value << 10);
2481: gen_movl_TN_reg(rd, r_const);
2482: tcg_temp_free(r_const);
1.1.1.5 root 2483: }
2484: break;
2485: case 0x0: /* UNIMPL */
2486: default:
1.1 root 2487: goto illegal_insn;
1.1.1.5 root 2488: }
2489: break;
2490: }
2491: break;
1.1.1.7 root 2492: case 1: /*CALL*/
2493: {
1.1.1.5 root 2494: target_long target = GET_FIELDs(insn, 2, 31) << 2;
1.1.1.6 root 2495: TCGv r_const;
1.1 root 2496:
1.1.1.6 root 2497: r_const = tcg_const_tl(dc->pc);
2498: gen_movl_TN_reg(15, r_const);
2499: tcg_temp_free(r_const);
1.1.1.5 root 2500: target += dc->pc;
1.1.1.6 root 2501: gen_mov_pc_npc(dc, cpu_cond);
1.1.1.13! root 2502: #ifdef TARGET_SPARC64
! 2503: if (unlikely(AM_CHECK(dc))) {
! 2504: target &= 0xffffffffULL;
! 2505: }
! 2506: #endif
1.1.1.5 root 2507: dc->npc = target;
2508: }
2509: goto jmp_insn;
2510: case 2: /* FPU & Logical Operations */
2511: {
2512: unsigned int xop = GET_FIELD(insn, 7, 12);
2513: if (xop == 0x3a) { /* generate trap */
1.1 root 2514: int cond;
2515:
1.1.1.6 root 2516: cpu_src1 = get_src1(insn, cpu_src1);
1.1.1.5 root 2517: if (IS_IMM) {
2518: rs2 = GET_FIELD(insn, 25, 31);
1.1.1.6 root 2519: tcg_gen_addi_tl(cpu_dst, cpu_src1, rs2);
1.1 root 2520: } else {
2521: rs2 = GET_FIELD(insn, 27, 31);
1.1.1.5 root 2522: if (rs2 != 0) {
1.1.1.6 root 2523: gen_movl_reg_TN(rs2, cpu_src2);
2524: tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
2525: } else
2526: tcg_gen_mov_tl(cpu_dst, cpu_src1);
1.1 root 2527: }
1.1.1.10 root 2528:
1.1 root 2529: cond = GET_FIELD(insn, 3, 6);
1.1.1.10 root 2530: if (cond == 0x8) { /* Trap Always */
1.1.1.6 root 2531: save_state(dc, cpu_cond);
2532: if ((dc->def->features & CPU_FEATURE_HYPV) &&
2533: supervisor(dc))
2534: tcg_gen_andi_tl(cpu_dst, cpu_dst, UA2005_HTRAP_MASK);
2535: else
2536: tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK);
2537: tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP);
2538: tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
1.1.1.12 root 2539: gen_helper_raise_exception(cpu_env, cpu_tmp32);
1.1.1.10 root 2540:
1.1 root 2541: } else if (cond != 0) {
1.1.1.6 root 2542: TCGv r_cond = tcg_temp_new();
2543: int l1;
1.1 root 2544: #ifdef TARGET_SPARC64
1.1.1.5 root 2545: /* V9 icc/xcc */
2546: int cc = GET_FIELD_SP(insn, 11, 12);
1.1.1.6 root 2547:
2548: save_state(dc, cpu_cond);
1.1.1.5 root 2549: if (cc == 0)
1.1.1.7 root 2550: gen_cond(r_cond, 0, cond, dc);
1.1.1.5 root 2551: else if (cc == 2)
1.1.1.7 root 2552: gen_cond(r_cond, 1, cond, dc);
1.1.1.5 root 2553: else
2554: goto illegal_insn;
1.1 root 2555: #else
1.1.1.6 root 2556: save_state(dc, cpu_cond);
1.1.1.7 root 2557: gen_cond(r_cond, 0, cond, dc);
1.1 root 2558: #endif
1.1.1.6 root 2559: l1 = gen_new_label();
2560: tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
2561:
2562: if ((dc->def->features & CPU_FEATURE_HYPV) &&
2563: supervisor(dc))
2564: tcg_gen_andi_tl(cpu_dst, cpu_dst, UA2005_HTRAP_MASK);
2565: else
2566: tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK);
2567: tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP);
2568: tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
1.1.1.12 root 2569: gen_helper_raise_exception(cpu_env, cpu_tmp32);
1.1.1.6 root 2570:
2571: gen_set_label(l1);
2572: tcg_temp_free(r_cond);
1.1 root 2573: }
1.1.1.3 root 2574: gen_op_next_insn();
1.1.1.6 root 2575: tcg_gen_exit_tb(0);
1.1.1.3 root 2576: dc->is_br = 1;
2577: goto jmp_insn;
1.1 root 2578: } else if (xop == 0x28) {
2579: rs1 = GET_FIELD(insn, 13, 17);
2580: switch(rs1) {
2581: case 0: /* rdy */
1.1.1.5 root 2582: #ifndef TARGET_SPARC64
2583: case 0x01 ... 0x0e: /* undefined in the SPARCv8
2584: manual, rdy on the microSPARC
2585: II */
2586: case 0x0f: /* stbar in the SPARCv8 manual,
2587: rdy on the microSPARC II */
2588: case 0x10 ... 0x1f: /* implementation-dependent in the
2589: SPARCv8 manual, rdy on the
2590: microSPARC II */
1.1.1.10 root 2591: /* Read Asr17 */
2592: if (rs1 == 0x11 && dc->def->features & CPU_FEATURE_ASR17) {
2593: TCGv r_const;
2594:
2595: /* Read Asr17 for a Leon3 monoprocessor */
2596: r_const = tcg_const_tl((1 << 8)
2597: | (dc->def->nwindows - 1));
2598: gen_movl_TN_reg(rd, r_const);
2599: tcg_temp_free(r_const);
2600: break;
2601: }
1.1.1.5 root 2602: #endif
1.1.1.6 root 2603: gen_movl_TN_reg(rd, cpu_y);
1.1 root 2604: break;
2605: #ifdef TARGET_SPARC64
1.1.1.5 root 2606: case 0x2: /* V9 rdccr */
1.1.1.12 root 2607: gen_helper_compute_psr(cpu_env);
2608: gen_helper_rdccr(cpu_dst, cpu_env);
1.1.1.6 root 2609: gen_movl_TN_reg(rd, cpu_dst);
1.1 root 2610: break;
1.1.1.5 root 2611: case 0x3: /* V9 rdasi */
1.1.1.6 root 2612: tcg_gen_ext_i32_tl(cpu_dst, cpu_asi);
2613: gen_movl_TN_reg(rd, cpu_dst);
1.1 root 2614: break;
1.1.1.5 root 2615: case 0x4: /* V9 rdtick */
1.1.1.6 root 2616: {
2617: TCGv_ptr r_tickptr;
2618:
2619: r_tickptr = tcg_temp_new_ptr();
2620: tcg_gen_ld_ptr(r_tickptr, cpu_env,
1.1.1.13! root 2621: offsetof(CPUSPARCState, tick));
1.1.1.6 root 2622: gen_helper_tick_get_count(cpu_dst, r_tickptr);
2623: tcg_temp_free_ptr(r_tickptr);
2624: gen_movl_TN_reg(rd, cpu_dst);
2625: }
1.1 root 2626: break;
1.1.1.5 root 2627: case 0x5: /* V9 rdpc */
1.1.1.6 root 2628: {
2629: TCGv r_const;
2630:
1.1.1.13! root 2631: if (unlikely(AM_CHECK(dc))) {
! 2632: r_const = tcg_const_tl(dc->pc & 0xffffffffULL);
! 2633: } else {
! 2634: r_const = tcg_const_tl(dc->pc);
! 2635: }
1.1.1.6 root 2636: gen_movl_TN_reg(rd, r_const);
2637: tcg_temp_free(r_const);
1.1.1.5 root 2638: }
2639: break;
2640: case 0x6: /* V9 rdfprs */
1.1.1.6 root 2641: tcg_gen_ext_i32_tl(cpu_dst, cpu_fprs);
2642: gen_movl_TN_reg(rd, cpu_dst);
1.1 root 2643: break;
1.1.1.5 root 2644: case 0xf: /* V9 membar */
2645: break; /* no effect */
2646: case 0x13: /* Graphics Status */
1.1.1.6 root 2647: if (gen_trap_ifnofpu(dc, cpu_cond))
1.1.1.3 root 2648: goto jmp_insn;
1.1.1.6 root 2649: gen_movl_TN_reg(rd, cpu_gsr);
2650: break;
2651: case 0x16: /* Softint */
2652: tcg_gen_ext_i32_tl(cpu_dst, cpu_softint);
2653: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.3 root 2654: break;
1.1.1.5 root 2655: case 0x17: /* Tick compare */
1.1.1.6 root 2656: gen_movl_TN_reg(rd, cpu_tick_cmpr);
1.1 root 2657: break;
1.1.1.5 root 2658: case 0x18: /* System tick */
1.1.1.6 root 2659: {
2660: TCGv_ptr r_tickptr;
2661:
2662: r_tickptr = tcg_temp_new_ptr();
2663: tcg_gen_ld_ptr(r_tickptr, cpu_env,
1.1.1.13! root 2664: offsetof(CPUSPARCState, stick));
1.1.1.6 root 2665: gen_helper_tick_get_count(cpu_dst, r_tickptr);
2666: tcg_temp_free_ptr(r_tickptr);
2667: gen_movl_TN_reg(rd, cpu_dst);
2668: }
1.1 root 2669: break;
1.1.1.5 root 2670: case 0x19: /* System tick compare */
1.1.1.6 root 2671: gen_movl_TN_reg(rd, cpu_stick_cmpr);
1.1 root 2672: break;
1.1.1.5 root 2673: case 0x10: /* Performance Control */
2674: case 0x11: /* Performance Instrumentation Counter */
2675: case 0x12: /* Dispatch Control */
2676: case 0x14: /* Softint set, WO */
2677: case 0x15: /* Softint clear, WO */
1.1 root 2678: #endif
2679: default:
2680: goto illegal_insn;
2681: }
2682: #if !defined(CONFIG_USER_ONLY)
1.1.1.5 root 2683: } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */
1.1 root 2684: #ifndef TARGET_SPARC64
1.1.1.5 root 2685: if (!supervisor(dc))
2686: goto priv_insn;
1.1.1.12 root 2687: gen_helper_compute_psr(cpu_env);
1.1.1.7 root 2688: dc->cc_op = CC_OP_FLAGS;
1.1.1.12 root 2689: gen_helper_rdpsr(cpu_dst, cpu_env);
1.1.1.5 root 2690: #else
1.1.1.6 root 2691: CHECK_IU_FEATURE(dc, HYPV);
1.1.1.5 root 2692: if (!hypervisor(dc))
2693: goto priv_insn;
2694: rs1 = GET_FIELD(insn, 13, 17);
2695: switch (rs1) {
2696: case 0: // hpstate
2697: // gen_op_rdhpstate();
2698: break;
2699: case 1: // htstate
2700: // gen_op_rdhtstate();
2701: break;
2702: case 3: // hintp
1.1.1.6 root 2703: tcg_gen_mov_tl(cpu_dst, cpu_hintp);
1.1.1.5 root 2704: break;
2705: case 5: // htba
1.1.1.6 root 2706: tcg_gen_mov_tl(cpu_dst, cpu_htba);
1.1.1.5 root 2707: break;
2708: case 6: // hver
1.1.1.6 root 2709: tcg_gen_mov_tl(cpu_dst, cpu_hver);
1.1.1.5 root 2710: break;
2711: case 31: // hstick_cmpr
1.1.1.6 root 2712: tcg_gen_mov_tl(cpu_dst, cpu_hstick_cmpr);
1.1.1.5 root 2713: break;
2714: default:
2715: goto illegal_insn;
2716: }
2717: #endif
1.1.1.6 root 2718: gen_movl_TN_reg(rd, cpu_dst);
1.1 root 2719: break;
2720: } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
1.1.1.5 root 2721: if (!supervisor(dc))
2722: goto priv_insn;
1.1 root 2723: #ifdef TARGET_SPARC64
2724: rs1 = GET_FIELD(insn, 13, 17);
1.1.1.5 root 2725: switch (rs1) {
2726: case 0: // tpc
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, tpc));
2734: tcg_temp_free_ptr(r_tsptr);
2735: }
1.1.1.5 root 2736: break;
2737: case 1: // tnpc
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_tl(cpu_tmp0, r_tsptr,
2744: offsetof(trap_state, tnpc));
2745: tcg_temp_free_ptr(r_tsptr);
2746: }
1.1.1.5 root 2747: break;
2748: case 2: // tstate
1.1.1.6 root 2749: {
2750: TCGv_ptr r_tsptr;
2751:
2752: r_tsptr = tcg_temp_new_ptr();
1.1.1.8 root 2753: gen_load_trap_state_at_tl(r_tsptr, cpu_env);
1.1.1.6 root 2754: tcg_gen_ld_tl(cpu_tmp0, r_tsptr,
2755: offsetof(trap_state, tstate));
2756: tcg_temp_free_ptr(r_tsptr);
2757: }
1.1.1.5 root 2758: break;
2759: case 3: // tt
1.1.1.6 root 2760: {
2761: TCGv_ptr r_tsptr;
2762:
2763: r_tsptr = tcg_temp_new_ptr();
1.1.1.8 root 2764: gen_load_trap_state_at_tl(r_tsptr, cpu_env);
1.1.1.6 root 2765: tcg_gen_ld_i32(cpu_tmp32, r_tsptr,
2766: offsetof(trap_state, tt));
2767: tcg_temp_free_ptr(r_tsptr);
2768: tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
2769: }
1.1.1.5 root 2770: break;
2771: case 4: // tick
1.1.1.6 root 2772: {
2773: TCGv_ptr r_tickptr;
2774:
2775: r_tickptr = tcg_temp_new_ptr();
2776: tcg_gen_ld_ptr(r_tickptr, cpu_env,
1.1.1.13! root 2777: offsetof(CPUSPARCState, tick));
1.1.1.6 root 2778: gen_helper_tick_get_count(cpu_tmp0, r_tickptr);
2779: gen_movl_TN_reg(rd, cpu_tmp0);
2780: tcg_temp_free_ptr(r_tickptr);
2781: }
1.1.1.5 root 2782: break;
2783: case 5: // tba
1.1.1.6 root 2784: tcg_gen_mov_tl(cpu_tmp0, cpu_tbr);
1.1.1.5 root 2785: break;
2786: case 6: // pstate
1.1.1.6 root 2787: tcg_gen_ld_i32(cpu_tmp32, cpu_env,
2788: offsetof(CPUSPARCState, pstate));
2789: tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
1.1.1.5 root 2790: break;
2791: case 7: // tl
1.1.1.6 root 2792: tcg_gen_ld_i32(cpu_tmp32, cpu_env,
2793: offsetof(CPUSPARCState, tl));
2794: tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
1.1.1.5 root 2795: break;
2796: case 8: // pil
1.1.1.6 root 2797: tcg_gen_ld_i32(cpu_tmp32, cpu_env,
2798: offsetof(CPUSPARCState, psrpil));
2799: tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
1.1.1.5 root 2800: break;
2801: case 9: // cwp
1.1.1.12 root 2802: gen_helper_rdcwp(cpu_tmp0, cpu_env);
1.1.1.5 root 2803: break;
2804: case 10: // cansave
1.1.1.6 root 2805: tcg_gen_ld_i32(cpu_tmp32, cpu_env,
2806: offsetof(CPUSPARCState, cansave));
2807: tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
1.1.1.5 root 2808: break;
2809: case 11: // canrestore
1.1.1.6 root 2810: tcg_gen_ld_i32(cpu_tmp32, cpu_env,
2811: offsetof(CPUSPARCState, canrestore));
2812: tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
1.1.1.5 root 2813: break;
2814: case 12: // cleanwin
1.1.1.6 root 2815: tcg_gen_ld_i32(cpu_tmp32, cpu_env,
2816: offsetof(CPUSPARCState, cleanwin));
2817: tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
1.1.1.5 root 2818: break;
2819: case 13: // otherwin
1.1.1.6 root 2820: tcg_gen_ld_i32(cpu_tmp32, cpu_env,
2821: offsetof(CPUSPARCState, otherwin));
2822: tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
1.1.1.5 root 2823: break;
2824: case 14: // wstate
1.1.1.6 root 2825: tcg_gen_ld_i32(cpu_tmp32, cpu_env,
2826: offsetof(CPUSPARCState, wstate));
2827: tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
1.1.1.5 root 2828: break;
2829: case 16: // UA2005 gl
1.1.1.6 root 2830: CHECK_IU_FEATURE(dc, GL);
2831: tcg_gen_ld_i32(cpu_tmp32, cpu_env,
2832: offsetof(CPUSPARCState, gl));
2833: tcg_gen_ext_i32_tl(cpu_tmp0, cpu_tmp32);
1.1.1.5 root 2834: break;
2835: case 26: // UA2005 strand status
1.1.1.6 root 2836: CHECK_IU_FEATURE(dc, HYPV);
1.1.1.5 root 2837: if (!hypervisor(dc))
2838: goto priv_insn;
1.1.1.6 root 2839: tcg_gen_mov_tl(cpu_tmp0, cpu_ssr);
1.1.1.5 root 2840: break;
2841: case 31: // ver
1.1.1.6 root 2842: tcg_gen_mov_tl(cpu_tmp0, cpu_ver);
1.1.1.5 root 2843: break;
2844: case 15: // fq
2845: default:
2846: goto illegal_insn;
2847: }
1.1 root 2848: #else
1.1.1.6 root 2849: tcg_gen_ext_i32_tl(cpu_tmp0, cpu_wim);
1.1 root 2850: #endif
1.1.1.6 root 2851: gen_movl_TN_reg(rd, cpu_tmp0);
1.1 root 2852: break;
2853: } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
2854: #ifdef TARGET_SPARC64
1.1.1.6 root 2855: save_state(dc, cpu_cond);
1.1.1.12 root 2856: gen_helper_flushw(cpu_env);
1.1 root 2857: #else
1.1.1.5 root 2858: if (!supervisor(dc))
2859: goto priv_insn;
1.1.1.6 root 2860: gen_movl_TN_reg(rd, cpu_tbr);
1.1 root 2861: #endif
2862: break;
2863: #endif
1.1.1.5 root 2864: } else if (xop == 0x34) { /* FPU Operations */
1.1.1.6 root 2865: if (gen_trap_ifnofpu(dc, cpu_cond))
1.1.1.3 root 2866: goto jmp_insn;
1.1.1.5 root 2867: gen_op_clear_ieee_excp_and_FTT();
1.1 root 2868: rs1 = GET_FIELD(insn, 13, 17);
1.1.1.5 root 2869: rs2 = GET_FIELD(insn, 27, 31);
2870: xop = GET_FIELD(insn, 18, 26);
1.1.1.9 root 2871: save_state(dc, cpu_cond);
1.1.1.5 root 2872: switch (xop) {
1.1.1.7 root 2873: case 0x1: /* fmovs */
1.1.1.12 root 2874: cpu_src1_32 = gen_load_fpr_F(dc, rs2);
2875: gen_store_fpr_F(dc, rd, cpu_src1_32);
1.1.1.7 root 2876: break;
2877: case 0x5: /* fnegs */
1.1.1.12 root 2878: gen_ne_fop_FF(dc, rd, rs2, gen_helper_fnegs);
1.1.1.7 root 2879: break;
2880: case 0x9: /* fabss */
1.1.1.12 root 2881: gen_ne_fop_FF(dc, rd, rs2, gen_helper_fabss);
1.1.1.7 root 2882: break;
2883: case 0x29: /* fsqrts */
2884: CHECK_FPU_FEATURE(dc, FSQRT);
1.1.1.12 root 2885: gen_fop_FF(dc, rd, rs2, gen_helper_fsqrts);
1.1.1.7 root 2886: break;
2887: case 0x2a: /* fsqrtd */
2888: CHECK_FPU_FEATURE(dc, FSQRT);
1.1.1.12 root 2889: gen_fop_DD(dc, rd, rs2, gen_helper_fsqrtd);
1.1.1.7 root 2890: break;
2891: case 0x2b: /* fsqrtq */
2892: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 2893: gen_fop_QQ(dc, rd, rs2, gen_helper_fsqrtq);
1.1.1.7 root 2894: break;
2895: case 0x41: /* fadds */
1.1.1.12 root 2896: gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fadds);
1.1.1.7 root 2897: break;
2898: case 0x42: /* faddd */
1.1.1.12 root 2899: gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_faddd);
1.1.1.7 root 2900: break;
2901: case 0x43: /* faddq */
2902: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 2903: gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_faddq);
1.1.1.7 root 2904: break;
2905: case 0x45: /* fsubs */
1.1.1.12 root 2906: gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fsubs);
1.1.1.7 root 2907: break;
2908: case 0x46: /* fsubd */
1.1.1.12 root 2909: gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fsubd);
1.1.1.7 root 2910: break;
2911: case 0x47: /* fsubq */
2912: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 2913: gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fsubq);
1.1.1.7 root 2914: break;
2915: case 0x49: /* fmuls */
2916: CHECK_FPU_FEATURE(dc, FMUL);
1.1.1.12 root 2917: gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fmuls);
1.1.1.7 root 2918: break;
2919: case 0x4a: /* fmuld */
2920: CHECK_FPU_FEATURE(dc, FMUL);
1.1.1.12 root 2921: gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld);
1.1.1.7 root 2922: break;
2923: case 0x4b: /* fmulq */
2924: CHECK_FPU_FEATURE(dc, FLOAT128);
2925: CHECK_FPU_FEATURE(dc, FMUL);
1.1.1.12 root 2926: gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fmulq);
1.1.1.7 root 2927: break;
2928: case 0x4d: /* fdivs */
1.1.1.12 root 2929: gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fdivs);
1.1.1.7 root 2930: break;
2931: case 0x4e: /* fdivd */
1.1.1.12 root 2932: gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fdivd);
1.1.1.7 root 2933: break;
2934: case 0x4f: /* fdivq */
2935: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 2936: gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fdivq);
1.1.1.7 root 2937: break;
2938: case 0x69: /* fsmuld */
2939: CHECK_FPU_FEATURE(dc, FSMULD);
1.1.1.12 root 2940: gen_fop_DFF(dc, rd, rs1, rs2, gen_helper_fsmuld);
1.1.1.7 root 2941: break;
2942: case 0x6e: /* fdmulq */
2943: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 2944: gen_fop_QDD(dc, rd, rs1, rs2, gen_helper_fdmulq);
1.1.1.7 root 2945: break;
2946: case 0xc4: /* fitos */
1.1.1.12 root 2947: gen_fop_FF(dc, rd, rs2, gen_helper_fitos);
1.1.1.7 root 2948: break;
2949: case 0xc6: /* fdtos */
1.1.1.12 root 2950: gen_fop_FD(dc, rd, rs2, gen_helper_fdtos);
1.1.1.7 root 2951: break;
2952: case 0xc7: /* fqtos */
2953: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 2954: gen_fop_FQ(dc, rd, rs2, gen_helper_fqtos);
1.1.1.7 root 2955: break;
2956: case 0xc8: /* fitod */
1.1.1.12 root 2957: gen_ne_fop_DF(dc, rd, rs2, gen_helper_fitod);
1.1.1.7 root 2958: break;
2959: case 0xc9: /* fstod */
1.1.1.12 root 2960: gen_ne_fop_DF(dc, rd, rs2, gen_helper_fstod);
1.1.1.7 root 2961: break;
2962: case 0xcb: /* fqtod */
2963: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 2964: gen_fop_DQ(dc, rd, rs2, gen_helper_fqtod);
1.1.1.7 root 2965: break;
2966: case 0xcc: /* fitoq */
2967: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 2968: gen_ne_fop_QF(dc, rd, rs2, gen_helper_fitoq);
1.1.1.7 root 2969: break;
2970: case 0xcd: /* fstoq */
2971: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 2972: gen_ne_fop_QF(dc, rd, rs2, gen_helper_fstoq);
1.1.1.7 root 2973: break;
2974: case 0xce: /* fdtoq */
2975: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 2976: gen_ne_fop_QD(dc, rd, rs2, gen_helper_fdtoq);
1.1.1.7 root 2977: break;
2978: case 0xd1: /* fstoi */
1.1.1.12 root 2979: gen_fop_FF(dc, rd, rs2, gen_helper_fstoi);
1.1.1.7 root 2980: break;
2981: case 0xd2: /* fdtoi */
1.1.1.12 root 2982: gen_fop_FD(dc, rd, rs2, gen_helper_fdtoi);
1.1.1.7 root 2983: break;
2984: case 0xd3: /* fqtoi */
2985: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 2986: gen_fop_FQ(dc, rd, rs2, gen_helper_fqtoi);
1.1.1.7 root 2987: break;
1.1.1.5 root 2988: #ifdef TARGET_SPARC64
1.1.1.7 root 2989: case 0x2: /* V9 fmovd */
1.1.1.12 root 2990: cpu_src1_64 = gen_load_fpr_D(dc, rs2);
2991: gen_store_fpr_D(dc, rd, cpu_src1_64);
1.1.1.7 root 2992: break;
2993: case 0x3: /* V9 fmovq */
2994: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 2995: gen_move_Q(rd, rs2);
1.1.1.7 root 2996: break;
2997: case 0x6: /* V9 fnegd */
1.1.1.12 root 2998: gen_ne_fop_DD(dc, rd, rs2, gen_helper_fnegd);
1.1.1.7 root 2999: break;
3000: case 0x7: /* V9 fnegq */
3001: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 3002: gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fnegq);
1.1.1.7 root 3003: break;
3004: case 0xa: /* V9 fabsd */
1.1.1.12 root 3005: gen_ne_fop_DD(dc, rd, rs2, gen_helper_fabsd);
1.1.1.7 root 3006: break;
3007: case 0xb: /* V9 fabsq */
3008: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 3009: gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fabsq);
1.1.1.7 root 3010: break;
3011: case 0x81: /* V9 fstox */
1.1.1.12 root 3012: gen_fop_DF(dc, rd, rs2, gen_helper_fstox);
1.1.1.7 root 3013: break;
3014: case 0x82: /* V9 fdtox */
1.1.1.12 root 3015: gen_fop_DD(dc, rd, rs2, gen_helper_fdtox);
1.1.1.7 root 3016: break;
3017: case 0x83: /* V9 fqtox */
3018: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 3019: gen_fop_DQ(dc, rd, rs2, gen_helper_fqtox);
1.1.1.7 root 3020: break;
3021: case 0x84: /* V9 fxtos */
1.1.1.12 root 3022: gen_fop_FD(dc, rd, rs2, gen_helper_fxtos);
1.1.1.7 root 3023: break;
3024: case 0x88: /* V9 fxtod */
1.1.1.12 root 3025: gen_fop_DD(dc, rd, rs2, gen_helper_fxtod);
1.1.1.7 root 3026: break;
3027: case 0x8c: /* V9 fxtoq */
3028: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.12 root 3029: gen_ne_fop_QD(dc, rd, rs2, gen_helper_fxtoq);
1.1.1.7 root 3030: break;
1.1.1.5 root 3031: #endif
1.1.1.7 root 3032: default:
3033: goto illegal_insn;
1.1.1.5 root 3034: }
3035: } else if (xop == 0x35) { /* FPU Operations */
3036: #ifdef TARGET_SPARC64
3037: int cond;
3038: #endif
1.1.1.6 root 3039: if (gen_trap_ifnofpu(dc, cpu_cond))
1.1.1.5 root 3040: goto jmp_insn;
3041: gen_op_clear_ieee_excp_and_FTT();
3042: rs1 = GET_FIELD(insn, 13, 17);
3043: rs2 = GET_FIELD(insn, 27, 31);
3044: xop = GET_FIELD(insn, 18, 26);
1.1.1.9 root 3045: save_state(dc, cpu_cond);
1.1.1.5 root 3046: #ifdef TARGET_SPARC64
3047: if ((xop & 0x11f) == 0x005) { // V9 fmovsr
1.1.1.6 root 3048: int l1;
3049:
3050: l1 = gen_new_label();
1.1.1.5 root 3051: cond = GET_FIELD_SP(insn, 14, 17);
1.1.1.6 root 3052: cpu_src1 = get_src1(insn, cpu_src1);
3053: tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
3054: 0, l1);
1.1.1.12 root 3055: cpu_src1_32 = gen_load_fpr_F(dc, rs2);
3056: gen_store_fpr_F(dc, rd, cpu_src1_32);
1.1.1.6 root 3057: gen_set_label(l1);
1.1.1.5 root 3058: break;
3059: } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
1.1.1.6 root 3060: int l1;
3061:
3062: l1 = gen_new_label();
1.1.1.5 root 3063: cond = GET_FIELD_SP(insn, 14, 17);
1.1.1.6 root 3064: cpu_src1 = get_src1(insn, cpu_src1);
3065: tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
3066: 0, l1);
1.1.1.12 root 3067: cpu_src1_64 = gen_load_fpr_D(dc, rs2);
3068: gen_store_fpr_D(dc, rd, cpu_src1_64);
1.1.1.6 root 3069: gen_set_label(l1);
1.1.1.5 root 3070: break;
3071: } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
1.1.1.6 root 3072: int l1;
3073:
3074: CHECK_FPU_FEATURE(dc, FLOAT128);
3075: l1 = gen_new_label();
1.1.1.5 root 3076: cond = GET_FIELD_SP(insn, 14, 17);
1.1.1.6 root 3077: cpu_src1 = get_src1(insn, cpu_src1);
3078: tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
3079: 0, l1);
1.1.1.12 root 3080: gen_move_Q(rd, rs2);
1.1.1.6 root 3081: gen_set_label(l1);
1.1.1.5 root 3082: break;
3083: }
3084: #endif
3085: switch (xop) {
3086: #ifdef TARGET_SPARC64
1.1.1.6 root 3087: #define FMOVSCC(fcc) \
3088: { \
3089: TCGv r_cond; \
3090: int l1; \
3091: \
3092: l1 = gen_new_label(); \
1.1.1.7 root 3093: r_cond = tcg_temp_new(); \
1.1.1.6 root 3094: cond = GET_FIELD_SP(insn, 14, 17); \
3095: gen_fcond(r_cond, fcc, cond); \
3096: tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
3097: 0, l1); \
1.1.1.12 root 3098: cpu_src1_32 = gen_load_fpr_F(dc, rs2); \
3099: gen_store_fpr_F(dc, rd, cpu_src1_32); \
1.1.1.6 root 3100: gen_set_label(l1); \
3101: tcg_temp_free(r_cond); \
3102: }
3103: #define FMOVDCC(fcc) \
3104: { \
3105: TCGv r_cond; \
3106: int l1; \
3107: \
3108: l1 = gen_new_label(); \
1.1.1.7 root 3109: r_cond = tcg_temp_new(); \
1.1.1.6 root 3110: cond = GET_FIELD_SP(insn, 14, 17); \
3111: gen_fcond(r_cond, fcc, cond); \
3112: tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
3113: 0, l1); \
1.1.1.12 root 3114: cpu_src1_64 = gen_load_fpr_D(dc, rs2); \
3115: gen_store_fpr_D(dc, rd, cpu_src1_64); \
1.1.1.6 root 3116: gen_set_label(l1); \
3117: tcg_temp_free(r_cond); \
3118: }
3119: #define FMOVQCC(fcc) \
3120: { \
3121: TCGv r_cond; \
3122: int l1; \
3123: \
3124: l1 = gen_new_label(); \
1.1.1.7 root 3125: r_cond = tcg_temp_new(); \
1.1.1.6 root 3126: cond = GET_FIELD_SP(insn, 14, 17); \
3127: gen_fcond(r_cond, fcc, cond); \
3128: tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
3129: 0, l1); \
1.1.1.12 root 3130: gen_move_Q(rd, rs2); \
1.1.1.6 root 3131: gen_set_label(l1); \
3132: tcg_temp_free(r_cond); \
3133: }
1.1.1.5 root 3134: case 0x001: /* V9 fmovscc %fcc0 */
1.1.1.6 root 3135: FMOVSCC(0);
1.1.1.5 root 3136: break;
3137: case 0x002: /* V9 fmovdcc %fcc0 */
1.1.1.6 root 3138: FMOVDCC(0);
1.1.1.5 root 3139: break;
3140: case 0x003: /* V9 fmovqcc %fcc0 */
1.1.1.6 root 3141: CHECK_FPU_FEATURE(dc, FLOAT128);
3142: FMOVQCC(0);
1.1.1.5 root 3143: break;
3144: case 0x041: /* V9 fmovscc %fcc1 */
1.1.1.6 root 3145: FMOVSCC(1);
1.1.1.5 root 3146: break;
3147: case 0x042: /* V9 fmovdcc %fcc1 */
1.1.1.6 root 3148: FMOVDCC(1);
1.1.1.5 root 3149: break;
3150: case 0x043: /* V9 fmovqcc %fcc1 */
1.1.1.6 root 3151: CHECK_FPU_FEATURE(dc, FLOAT128);
3152: FMOVQCC(1);
1.1.1.5 root 3153: break;
3154: case 0x081: /* V9 fmovscc %fcc2 */
1.1.1.6 root 3155: FMOVSCC(2);
1.1.1.5 root 3156: break;
3157: case 0x082: /* V9 fmovdcc %fcc2 */
1.1.1.6 root 3158: FMOVDCC(2);
1.1.1.5 root 3159: break;
3160: case 0x083: /* V9 fmovqcc %fcc2 */
1.1.1.6 root 3161: CHECK_FPU_FEATURE(dc, FLOAT128);
3162: FMOVQCC(2);
1.1.1.5 root 3163: break;
3164: case 0x0c1: /* V9 fmovscc %fcc3 */
1.1.1.6 root 3165: FMOVSCC(3);
1.1.1.5 root 3166: break;
3167: case 0x0c2: /* V9 fmovdcc %fcc3 */
1.1.1.6 root 3168: FMOVDCC(3);
1.1.1.5 root 3169: break;
3170: case 0x0c3: /* V9 fmovqcc %fcc3 */
1.1.1.6 root 3171: CHECK_FPU_FEATURE(dc, FLOAT128);
3172: FMOVQCC(3);
1.1.1.5 root 3173: break;
1.1.1.6 root 3174: #undef FMOVSCC
3175: #undef FMOVDCC
3176: #undef FMOVQCC
3177: #define FMOVSCC(icc) \
3178: { \
3179: TCGv r_cond; \
3180: int l1; \
3181: \
3182: l1 = gen_new_label(); \
1.1.1.7 root 3183: r_cond = tcg_temp_new(); \
1.1.1.6 root 3184: cond = GET_FIELD_SP(insn, 14, 17); \
1.1.1.7 root 3185: gen_cond(r_cond, icc, cond, dc); \
1.1.1.6 root 3186: tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
3187: 0, l1); \
1.1.1.12 root 3188: cpu_src1_32 = gen_load_fpr_F(dc, rs2); \
3189: gen_store_fpr_F(dc, rd, cpu_src1_32); \
1.1.1.6 root 3190: gen_set_label(l1); \
3191: tcg_temp_free(r_cond); \
3192: }
3193: #define FMOVDCC(icc) \
3194: { \
3195: TCGv r_cond; \
3196: int l1; \
3197: \
3198: l1 = gen_new_label(); \
1.1.1.7 root 3199: r_cond = tcg_temp_new(); \
1.1.1.6 root 3200: cond = GET_FIELD_SP(insn, 14, 17); \
1.1.1.7 root 3201: gen_cond(r_cond, icc, cond, dc); \
1.1.1.6 root 3202: tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
3203: 0, l1); \
1.1.1.12 root 3204: cpu_src1_64 = gen_load_fpr_D(dc, rs2); \
3205: gen_store_fpr_D(dc, rd, cpu_src1_64); \
3206: gen_update_fprs_dirty(DFPREG(rd)); \
1.1.1.6 root 3207: gen_set_label(l1); \
3208: tcg_temp_free(r_cond); \
3209: }
3210: #define FMOVQCC(icc) \
3211: { \
3212: TCGv r_cond; \
3213: int l1; \
3214: \
3215: l1 = gen_new_label(); \
1.1.1.7 root 3216: r_cond = tcg_temp_new(); \
1.1.1.6 root 3217: cond = GET_FIELD_SP(insn, 14, 17); \
1.1.1.7 root 3218: gen_cond(r_cond, icc, cond, dc); \
1.1.1.6 root 3219: tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \
3220: 0, l1); \
1.1.1.12 root 3221: gen_move_Q(rd, rs2); \
1.1.1.6 root 3222: gen_set_label(l1); \
3223: tcg_temp_free(r_cond); \
3224: }
3225:
1.1.1.5 root 3226: case 0x101: /* V9 fmovscc %icc */
1.1.1.6 root 3227: FMOVSCC(0);
1.1.1.5 root 3228: break;
3229: case 0x102: /* V9 fmovdcc %icc */
1.1.1.6 root 3230: FMOVDCC(0);
1.1.1.11 root 3231: break;
1.1.1.5 root 3232: case 0x103: /* V9 fmovqcc %icc */
1.1.1.6 root 3233: CHECK_FPU_FEATURE(dc, FLOAT128);
3234: FMOVQCC(0);
1.1.1.5 root 3235: break;
3236: case 0x181: /* V9 fmovscc %xcc */
1.1.1.6 root 3237: FMOVSCC(1);
1.1.1.5 root 3238: break;
3239: case 0x182: /* V9 fmovdcc %xcc */
1.1.1.6 root 3240: FMOVDCC(1);
1.1.1.5 root 3241: break;
3242: case 0x183: /* V9 fmovqcc %xcc */
1.1.1.6 root 3243: CHECK_FPU_FEATURE(dc, FLOAT128);
3244: FMOVQCC(1);
1.1.1.5 root 3245: break;
1.1.1.6 root 3246: #undef FMOVSCC
3247: #undef FMOVDCC
3248: #undef FMOVQCC
1.1.1.5 root 3249: #endif
3250: case 0x51: /* fcmps, V9 %fcc */
1.1.1.12 root 3251: cpu_src1_32 = gen_load_fpr_F(dc, rs1);
3252: cpu_src2_32 = gen_load_fpr_F(dc, rs2);
3253: gen_op_fcmps(rd & 3, cpu_src1_32, cpu_src2_32);
1.1.1.5 root 3254: break;
3255: case 0x52: /* fcmpd, V9 %fcc */
1.1.1.12 root 3256: cpu_src1_64 = gen_load_fpr_D(dc, rs1);
3257: cpu_src2_64 = gen_load_fpr_D(dc, rs2);
3258: gen_op_fcmpd(rd & 3, cpu_src1_64, cpu_src2_64);
1.1.1.5 root 3259: break;
3260: case 0x53: /* fcmpq, V9 %fcc */
1.1.1.6 root 3261: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.5 root 3262: gen_op_load_fpr_QT0(QFPREG(rs1));
3263: gen_op_load_fpr_QT1(QFPREG(rs2));
1.1.1.6 root 3264: gen_op_fcmpq(rd & 3);
1.1.1.5 root 3265: break;
3266: case 0x55: /* fcmpes, V9 %fcc */
1.1.1.12 root 3267: cpu_src1_32 = gen_load_fpr_F(dc, rs1);
3268: cpu_src2_32 = gen_load_fpr_F(dc, rs2);
3269: gen_op_fcmpes(rd & 3, cpu_src1_32, cpu_src2_32);
1.1.1.5 root 3270: break;
3271: case 0x56: /* fcmped, V9 %fcc */
1.1.1.12 root 3272: cpu_src1_64 = gen_load_fpr_D(dc, rs1);
3273: cpu_src2_64 = gen_load_fpr_D(dc, rs2);
3274: gen_op_fcmped(rd & 3, cpu_src1_64, cpu_src2_64);
1.1.1.5 root 3275: break;
3276: case 0x57: /* fcmpeq, V9 %fcc */
1.1.1.6 root 3277: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.5 root 3278: gen_op_load_fpr_QT0(QFPREG(rs1));
3279: gen_op_load_fpr_QT1(QFPREG(rs2));
1.1.1.6 root 3280: gen_op_fcmpeq(rd & 3);
1.1.1.5 root 3281: break;
3282: default:
3283: goto illegal_insn;
3284: }
3285: } else if (xop == 0x2) {
3286: // clr/mov shortcut
3287:
3288: rs1 = GET_FIELD(insn, 13, 17);
3289: if (rs1 == 0) {
1.1.1.6 root 3290: // or %g0, x, y -> mov T0, x; mov y, T0
1.1.1.5 root 3291: if (IS_IMM) { /* immediate */
1.1.1.6 root 3292: TCGv r_const;
3293:
1.1.1.7 root 3294: simm = GET_FIELDs(insn, 19, 31);
3295: r_const = tcg_const_tl(simm);
1.1.1.6 root 3296: gen_movl_TN_reg(rd, r_const);
3297: tcg_temp_free(r_const);
1.1.1.5 root 3298: } else { /* register */
3299: rs2 = GET_FIELD(insn, 27, 31);
1.1.1.6 root 3300: gen_movl_reg_TN(rs2, cpu_dst);
3301: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 3302: }
3303: } else {
1.1.1.6 root 3304: cpu_src1 = get_src1(insn, cpu_src1);
1.1.1.5 root 3305: if (IS_IMM) { /* immediate */
1.1.1.7 root 3306: simm = GET_FIELDs(insn, 19, 31);
3307: tcg_gen_ori_tl(cpu_dst, cpu_src1, simm);
1.1.1.6 root 3308: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 3309: } else { /* register */
3310: // or x, %g0, y -> mov T1, x; mov y, T1
3311: rs2 = GET_FIELD(insn, 27, 31);
3312: if (rs2 != 0) {
1.1.1.6 root 3313: gen_movl_reg_TN(rs2, cpu_src2);
3314: tcg_gen_or_tl(cpu_dst, cpu_src1, cpu_src2);
3315: gen_movl_TN_reg(rd, cpu_dst);
3316: } else
3317: gen_movl_TN_reg(rd, cpu_src1);
1.1.1.5 root 3318: }
3319: }
3320: #ifdef TARGET_SPARC64
3321: } else if (xop == 0x25) { /* sll, V9 sllx */
1.1.1.6 root 3322: cpu_src1 = get_src1(insn, cpu_src1);
1.1.1.5 root 3323: if (IS_IMM) { /* immediate */
1.1.1.7 root 3324: simm = GET_FIELDs(insn, 20, 31);
1.1.1.6 root 3325: if (insn & (1 << 12)) {
1.1.1.7 root 3326: tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x3f);
1.1.1.6 root 3327: } else {
1.1.1.7 root 3328: tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x1f);
1.1.1.6 root 3329: }
1.1.1.5 root 3330: } else { /* register */
3331: rs2 = GET_FIELD(insn, 27, 31);
1.1.1.6 root 3332: gen_movl_reg_TN(rs2, cpu_src2);
3333: if (insn & (1 << 12)) {
3334: tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
3335: } else {
3336: tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
3337: }
3338: tcg_gen_shl_i64(cpu_dst, cpu_src1, cpu_tmp0);
1.1.1.5 root 3339: }
1.1.1.6 root 3340: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 3341: } else if (xop == 0x26) { /* srl, V9 srlx */
1.1.1.6 root 3342: cpu_src1 = get_src1(insn, cpu_src1);
1.1.1.5 root 3343: if (IS_IMM) { /* immediate */
1.1.1.7 root 3344: simm = GET_FIELDs(insn, 20, 31);
1.1.1.6 root 3345: if (insn & (1 << 12)) {
1.1.1.7 root 3346: tcg_gen_shri_i64(cpu_dst, cpu_src1, simm & 0x3f);
1.1.1.6 root 3347: } else {
3348: tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
1.1.1.7 root 3349: tcg_gen_shri_i64(cpu_dst, cpu_dst, simm & 0x1f);
1.1.1.6 root 3350: }
1.1.1.5 root 3351: } else { /* register */
1.1 root 3352: rs2 = GET_FIELD(insn, 27, 31);
1.1.1.6 root 3353: gen_movl_reg_TN(rs2, cpu_src2);
3354: if (insn & (1 << 12)) {
3355: tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
3356: tcg_gen_shr_i64(cpu_dst, cpu_src1, cpu_tmp0);
3357: } else {
3358: tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
3359: tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
3360: tcg_gen_shr_i64(cpu_dst, cpu_dst, cpu_tmp0);
3361: }
1.1 root 3362: }
1.1.1.6 root 3363: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 3364: } else if (xop == 0x27) { /* sra, V9 srax */
1.1.1.6 root 3365: cpu_src1 = get_src1(insn, cpu_src1);
1.1.1.5 root 3366: if (IS_IMM) { /* immediate */
1.1.1.7 root 3367: simm = GET_FIELDs(insn, 20, 31);
1.1.1.6 root 3368: if (insn & (1 << 12)) {
1.1.1.7 root 3369: tcg_gen_sari_i64(cpu_dst, cpu_src1, simm & 0x3f);
1.1.1.6 root 3370: } else {
3371: tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
3372: tcg_gen_ext32s_i64(cpu_dst, cpu_dst);
1.1.1.7 root 3373: tcg_gen_sari_i64(cpu_dst, cpu_dst, simm & 0x1f);
1.1.1.6 root 3374: }
1.1.1.5 root 3375: } else { /* register */
1.1 root 3376: rs2 = GET_FIELD(insn, 27, 31);
1.1.1.6 root 3377: gen_movl_reg_TN(rs2, cpu_src2);
3378: if (insn & (1 << 12)) {
3379: tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
3380: tcg_gen_sar_i64(cpu_dst, cpu_src1, cpu_tmp0);
3381: } else {
3382: tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
3383: tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
3384: tcg_gen_ext32s_i64(cpu_dst, cpu_dst);
3385: tcg_gen_sar_i64(cpu_dst, cpu_dst, cpu_tmp0);
3386: }
1.1 root 3387: }
1.1.1.6 root 3388: gen_movl_TN_reg(rd, cpu_dst);
1.1 root 3389: #endif
1.1.1.5 root 3390: } else if (xop < 0x36) {
1.1 root 3391: if (xop < 0x20) {
1.1.1.7 root 3392: cpu_src1 = get_src1(insn, cpu_src1);
3393: cpu_src2 = get_src2(insn, cpu_src2);
1.1 root 3394: switch (xop & ~0x10) {
1.1.1.7 root 3395: case 0x0: /* add */
3396: if (IS_IMM) {
3397: simm = GET_FIELDs(insn, 19, 31);
3398: if (xop & 0x10) {
3399: gen_op_addi_cc(cpu_dst, cpu_src1, simm);
3400: tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
3401: dc->cc_op = CC_OP_ADD;
3402: } else {
3403: tcg_gen_addi_tl(cpu_dst, cpu_src1, simm);
3404: }
3405: } else {
3406: if (xop & 0x10) {
3407: gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2);
3408: tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
3409: dc->cc_op = CC_OP_ADD;
3410: } else {
3411: tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
3412: }
3413: }
3414: break;
3415: case 0x1: /* and */
3416: if (IS_IMM) {
3417: simm = GET_FIELDs(insn, 19, 31);
3418: tcg_gen_andi_tl(cpu_dst, cpu_src1, simm);
3419: } else {
3420: tcg_gen_and_tl(cpu_dst, cpu_src1, cpu_src2);
3421: }
3422: if (xop & 0x10) {
3423: tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3424: tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3425: dc->cc_op = CC_OP_LOGIC;
3426: }
3427: break;
3428: case 0x2: /* or */
3429: if (IS_IMM) {
3430: simm = GET_FIELDs(insn, 19, 31);
3431: tcg_gen_ori_tl(cpu_dst, cpu_src1, simm);
3432: } else {
3433: tcg_gen_or_tl(cpu_dst, cpu_src1, cpu_src2);
3434: }
3435: if (xop & 0x10) {
3436: tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3437: tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3438: dc->cc_op = CC_OP_LOGIC;
3439: }
3440: break;
3441: case 0x3: /* xor */
3442: if (IS_IMM) {
3443: simm = GET_FIELDs(insn, 19, 31);
3444: tcg_gen_xori_tl(cpu_dst, cpu_src1, simm);
3445: } else {
3446: tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
3447: }
3448: if (xop & 0x10) {
3449: tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3450: tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3451: dc->cc_op = CC_OP_LOGIC;
3452: }
3453: break;
3454: case 0x4: /* sub */
3455: if (IS_IMM) {
3456: simm = GET_FIELDs(insn, 19, 31);
3457: if (xop & 0x10) {
3458: gen_op_subi_cc(cpu_dst, cpu_src1, simm, dc);
3459: } else {
3460: tcg_gen_subi_tl(cpu_dst, cpu_src1, simm);
3461: }
3462: } else {
3463: if (xop & 0x10) {
3464: gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2);
3465: tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB);
3466: dc->cc_op = CC_OP_SUB;
3467: } else {
3468: tcg_gen_sub_tl(cpu_dst, cpu_src1, cpu_src2);
3469: }
3470: }
3471: break;
3472: case 0x5: /* andn */
3473: if (IS_IMM) {
3474: simm = GET_FIELDs(insn, 19, 31);
3475: tcg_gen_andi_tl(cpu_dst, cpu_src1, ~simm);
3476: } else {
3477: tcg_gen_andc_tl(cpu_dst, cpu_src1, cpu_src2);
3478: }
3479: if (xop & 0x10) {
3480: tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3481: tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3482: dc->cc_op = CC_OP_LOGIC;
3483: }
3484: break;
3485: case 0x6: /* orn */
3486: if (IS_IMM) {
3487: simm = GET_FIELDs(insn, 19, 31);
3488: tcg_gen_ori_tl(cpu_dst, cpu_src1, ~simm);
3489: } else {
3490: tcg_gen_orc_tl(cpu_dst, cpu_src1, cpu_src2);
3491: }
3492: if (xop & 0x10) {
3493: tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3494: tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3495: dc->cc_op = CC_OP_LOGIC;
3496: }
3497: break;
3498: case 0x7: /* xorn */
3499: if (IS_IMM) {
3500: simm = GET_FIELDs(insn, 19, 31);
3501: tcg_gen_xori_tl(cpu_dst, cpu_src1, ~simm);
3502: } else {
3503: tcg_gen_not_tl(cpu_tmp0, cpu_src2);
3504: tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_tmp0);
3505: }
3506: if (xop & 0x10) {
3507: tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3508: tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3509: dc->cc_op = CC_OP_LOGIC;
3510: }
3511: break;
3512: case 0x8: /* addx, V9 addc */
1.1.1.9 root 3513: gen_op_addx_int(dc, cpu_dst, cpu_src1, cpu_src2,
3514: (xop & 0x10));
1.1 root 3515: break;
1.1.1.3 root 3516: #ifdef TARGET_SPARC64
1.1.1.5 root 3517: case 0x9: /* V9 mulx */
1.1.1.7 root 3518: if (IS_IMM) {
3519: simm = GET_FIELDs(insn, 19, 31);
3520: tcg_gen_muli_i64(cpu_dst, cpu_src1, simm);
3521: } else {
3522: tcg_gen_mul_i64(cpu_dst, cpu_src1, cpu_src2);
3523: }
1.1.1.3 root 3524: break;
3525: #endif
1.1.1.7 root 3526: case 0xa: /* umul */
1.1.1.6 root 3527: CHECK_IU_FEATURE(dc, MUL);
3528: gen_op_umul(cpu_dst, cpu_src1, cpu_src2);
1.1.1.7 root 3529: if (xop & 0x10) {
3530: tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3531: tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3532: dc->cc_op = CC_OP_LOGIC;
3533: }
1.1 root 3534: break;
1.1.1.7 root 3535: case 0xb: /* smul */
1.1.1.6 root 3536: CHECK_IU_FEATURE(dc, MUL);
3537: gen_op_smul(cpu_dst, cpu_src1, cpu_src2);
1.1.1.7 root 3538: if (xop & 0x10) {
3539: tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
3540: tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC);
3541: dc->cc_op = CC_OP_LOGIC;
3542: }
1.1 root 3543: break;
1.1.1.7 root 3544: case 0xc: /* subx, V9 subc */
1.1.1.9 root 3545: gen_op_subx_int(dc, cpu_dst, cpu_src1, cpu_src2,
3546: (xop & 0x10));
1.1 root 3547: break;
1.1.1.3 root 3548: #ifdef TARGET_SPARC64
1.1.1.5 root 3549: case 0xd: /* V9 udivx */
1.1.1.11 root 3550: {
3551: TCGv r_temp1, r_temp2;
3552: r_temp1 = tcg_temp_local_new();
3553: r_temp2 = tcg_temp_local_new();
3554: tcg_gen_mov_tl(r_temp1, cpu_src1);
3555: tcg_gen_mov_tl(r_temp2, cpu_src2);
3556: gen_trap_ifdivzero_tl(r_temp2);
3557: tcg_gen_divu_i64(cpu_dst, r_temp1, r_temp2);
3558: tcg_temp_free(r_temp1);
3559: tcg_temp_free(r_temp2);
3560: }
1.1.1.3 root 3561: break;
3562: #endif
1.1.1.7 root 3563: case 0xe: /* udiv */
1.1.1.6 root 3564: CHECK_IU_FEATURE(dc, DIV);
1.1.1.7 root 3565: if (xop & 0x10) {
1.1.1.12 root 3566: gen_helper_udiv_cc(cpu_dst, cpu_env, cpu_src1,
3567: cpu_src2);
1.1.1.7 root 3568: dc->cc_op = CC_OP_DIV;
1.1.1.10 root 3569: } else {
1.1.1.12 root 3570: gen_helper_udiv(cpu_dst, cpu_env, cpu_src1,
3571: cpu_src2);
1.1.1.7 root 3572: }
1.1 root 3573: break;
1.1.1.7 root 3574: case 0xf: /* sdiv */
1.1.1.6 root 3575: CHECK_IU_FEATURE(dc, DIV);
1.1.1.7 root 3576: if (xop & 0x10) {
1.1.1.12 root 3577: gen_helper_sdiv_cc(cpu_dst, cpu_env, cpu_src1,
3578: cpu_src2);
1.1.1.7 root 3579: dc->cc_op = CC_OP_DIV;
1.1.1.10 root 3580: } else {
1.1.1.12 root 3581: gen_helper_sdiv(cpu_dst, cpu_env, cpu_src1,
3582: cpu_src2);
1.1.1.7 root 3583: }
1.1 root 3584: break;
3585: default:
3586: goto illegal_insn;
3587: }
1.1.1.6 root 3588: gen_movl_TN_reg(rd, cpu_dst);
1.1 root 3589: } else {
1.1.1.7 root 3590: cpu_src1 = get_src1(insn, cpu_src1);
3591: cpu_src2 = get_src2(insn, cpu_src2);
1.1 root 3592: switch (xop) {
1.1.1.5 root 3593: case 0x20: /* taddcc */
1.1.1.6 root 3594: gen_op_tadd_cc(cpu_dst, cpu_src1, cpu_src2);
3595: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.7 root 3596: tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADD);
3597: dc->cc_op = CC_OP_TADD;
1.1.1.5 root 3598: break;
3599: case 0x21: /* tsubcc */
1.1.1.6 root 3600: gen_op_tsub_cc(cpu_dst, cpu_src1, cpu_src2);
3601: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.7 root 3602: tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUB);
3603: dc->cc_op = CC_OP_TSUB;
1.1.1.5 root 3604: break;
3605: case 0x22: /* taddcctv */
1.1.1.6 root 3606: save_state(dc, cpu_cond);
3607: gen_op_tadd_ccTV(cpu_dst, cpu_src1, cpu_src2);
3608: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.7 root 3609: tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADDTV);
3610: dc->cc_op = CC_OP_TADDTV;
1.1.1.5 root 3611: break;
3612: case 0x23: /* tsubcctv */
1.1.1.6 root 3613: save_state(dc, cpu_cond);
3614: gen_op_tsub_ccTV(cpu_dst, cpu_src1, cpu_src2);
3615: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.7 root 3616: tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUBTV);
3617: dc->cc_op = CC_OP_TSUBTV;
1.1.1.5 root 3618: break;
1.1 root 3619: case 0x24: /* mulscc */
1.1.1.12 root 3620: gen_helper_compute_psr(cpu_env);
1.1.1.6 root 3621: gen_op_mulscc(cpu_dst, cpu_src1, cpu_src2);
3622: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.7 root 3623: tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
3624: dc->cc_op = CC_OP_ADD;
1.1 root 3625: break;
3626: #ifndef TARGET_SPARC64
1.1.1.5 root 3627: case 0x25: /* sll */
1.1.1.6 root 3628: if (IS_IMM) { /* immediate */
1.1.1.7 root 3629: simm = GET_FIELDs(insn, 20, 31);
3630: tcg_gen_shli_tl(cpu_dst, cpu_src1, simm & 0x1f);
1.1.1.6 root 3631: } else { /* register */
3632: tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
3633: tcg_gen_shl_tl(cpu_dst, cpu_src1, cpu_tmp0);
3634: }
3635: gen_movl_TN_reg(rd, cpu_dst);
1.1 root 3636: break;
3637: case 0x26: /* srl */
1.1.1.6 root 3638: if (IS_IMM) { /* immediate */
1.1.1.7 root 3639: simm = GET_FIELDs(insn, 20, 31);
3640: tcg_gen_shri_tl(cpu_dst, cpu_src1, simm & 0x1f);
1.1.1.6 root 3641: } else { /* register */
3642: tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
3643: tcg_gen_shr_tl(cpu_dst, cpu_src1, cpu_tmp0);
3644: }
3645: gen_movl_TN_reg(rd, cpu_dst);
1.1 root 3646: break;
3647: case 0x27: /* sra */
1.1.1.6 root 3648: if (IS_IMM) { /* immediate */
1.1.1.7 root 3649: simm = GET_FIELDs(insn, 20, 31);
3650: tcg_gen_sari_tl(cpu_dst, cpu_src1, simm & 0x1f);
1.1.1.6 root 3651: } else { /* register */
3652: tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
3653: tcg_gen_sar_tl(cpu_dst, cpu_src1, cpu_tmp0);
3654: }
3655: gen_movl_TN_reg(rd, cpu_dst);
1.1 root 3656: break;
3657: #endif
3658: case 0x30:
3659: {
3660: switch(rd) {
3661: case 0: /* wry */
1.1.1.6 root 3662: tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
3663: tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
1.1 root 3664: break;
1.1.1.5 root 3665: #ifndef TARGET_SPARC64
3666: case 0x01 ... 0x0f: /* undefined in the
3667: SPARCv8 manual, nop
3668: on the microSPARC
3669: II */
3670: case 0x10 ... 0x1f: /* implementation-dependent
3671: in the SPARCv8
3672: manual, nop on the
3673: microSPARC II */
3674: break;
3675: #else
3676: case 0x2: /* V9 wrccr */
1.1.1.6 root 3677: tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
1.1.1.12 root 3678: gen_helper_wrccr(cpu_env, cpu_dst);
1.1.1.7 root 3679: tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
3680: dc->cc_op = CC_OP_FLAGS;
1.1.1.5 root 3681: break;
3682: case 0x3: /* V9 wrasi */
1.1.1.6 root 3683: tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
1.1.1.8 root 3684: tcg_gen_andi_tl(cpu_dst, cpu_dst, 0xff);
1.1.1.6 root 3685: tcg_gen_trunc_tl_i32(cpu_asi, cpu_dst);
1.1.1.5 root 3686: break;
3687: case 0x6: /* V9 wrfprs */
1.1.1.6 root 3688: tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
3689: tcg_gen_trunc_tl_i32(cpu_fprs, cpu_dst);
3690: save_state(dc, cpu_cond);
1.1.1.5 root 3691: gen_op_next_insn();
1.1.1.6 root 3692: tcg_gen_exit_tb(0);
1.1.1.5 root 3693: dc->is_br = 1;
3694: break;
3695: case 0xf: /* V9 sir, nop if user */
1.1 root 3696: #if !defined(CONFIG_USER_ONLY)
1.1.1.9 root 3697: if (supervisor(dc)) {
1.1.1.6 root 3698: ; // XXX
1.1.1.9 root 3699: }
1.1 root 3700: #endif
1.1.1.5 root 3701: break;
3702: case 0x13: /* Graphics Status */
1.1.1.6 root 3703: if (gen_trap_ifnofpu(dc, cpu_cond))
1.1.1.3 root 3704: goto jmp_insn;
1.1.1.6 root 3705: tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2);
3706: break;
3707: case 0x14: /* Softint set */
3708: if (!supervisor(dc))
3709: goto illegal_insn;
3710: tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2);
1.1.1.12 root 3711: gen_helper_set_softint(cpu_env, cpu_tmp64);
1.1.1.6 root 3712: break;
3713: case 0x15: /* Softint clear */
3714: if (!supervisor(dc))
3715: goto illegal_insn;
3716: tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2);
1.1.1.12 root 3717: gen_helper_clear_softint(cpu_env, cpu_tmp64);
1.1.1.6 root 3718: break;
3719: case 0x16: /* Softint write */
3720: if (!supervisor(dc))
3721: goto illegal_insn;
3722: tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2);
1.1.1.12 root 3723: gen_helper_write_softint(cpu_env, cpu_tmp64);
1.1.1.5 root 3724: break;
3725: case 0x17: /* Tick compare */
1.1 root 3726: #if !defined(CONFIG_USER_ONLY)
1.1.1.5 root 3727: if (!supervisor(dc))
3728: goto illegal_insn;
1.1 root 3729: #endif
1.1.1.6 root 3730: {
3731: TCGv_ptr r_tickptr;
3732:
3733: tcg_gen_xor_tl(cpu_tick_cmpr, cpu_src1,
3734: cpu_src2);
3735: r_tickptr = tcg_temp_new_ptr();
3736: tcg_gen_ld_ptr(r_tickptr, cpu_env,
1.1.1.13! root 3737: offsetof(CPUSPARCState, tick));
1.1.1.6 root 3738: gen_helper_tick_set_limit(r_tickptr,
3739: cpu_tick_cmpr);
3740: tcg_temp_free_ptr(r_tickptr);
3741: }
1.1.1.5 root 3742: break;
3743: case 0x18: /* System tick */
1.1 root 3744: #if !defined(CONFIG_USER_ONLY)
1.1.1.5 root 3745: if (!supervisor(dc))
3746: goto illegal_insn;
1.1 root 3747: #endif
1.1.1.6 root 3748: {
3749: TCGv_ptr r_tickptr;
3750:
3751: tcg_gen_xor_tl(cpu_dst, cpu_src1,
3752: cpu_src2);
3753: r_tickptr = tcg_temp_new_ptr();
3754: tcg_gen_ld_ptr(r_tickptr, cpu_env,
1.1.1.13! root 3755: offsetof(CPUSPARCState, stick));
1.1.1.6 root 3756: gen_helper_tick_set_count(r_tickptr,
3757: cpu_dst);
3758: tcg_temp_free_ptr(r_tickptr);
3759: }
1.1.1.5 root 3760: break;
3761: case 0x19: /* System tick compare */
1.1 root 3762: #if !defined(CONFIG_USER_ONLY)
1.1.1.5 root 3763: if (!supervisor(dc))
3764: goto illegal_insn;
1.1 root 3765: #endif
1.1.1.6 root 3766: {
3767: TCGv_ptr r_tickptr;
3768:
3769: tcg_gen_xor_tl(cpu_stick_cmpr, cpu_src1,
3770: cpu_src2);
3771: r_tickptr = tcg_temp_new_ptr();
3772: tcg_gen_ld_ptr(r_tickptr, cpu_env,
1.1.1.13! root 3773: offsetof(CPUSPARCState, stick));
1.1.1.6 root 3774: gen_helper_tick_set_limit(r_tickptr,
3775: cpu_stick_cmpr);
3776: tcg_temp_free_ptr(r_tickptr);
3777: }
1.1.1.5 root 3778: break;
1.1 root 3779:
1.1.1.5 root 3780: case 0x10: /* Performance Control */
1.1.1.6 root 3781: case 0x11: /* Performance Instrumentation
3782: Counter */
1.1.1.5 root 3783: case 0x12: /* Dispatch Control */
1.1 root 3784: #endif
3785: default:
3786: goto illegal_insn;
3787: }
3788: }
3789: break;
3790: #if !defined(CONFIG_USER_ONLY)
3791: case 0x31: /* wrpsr, V9 saved, restored */
3792: {
1.1.1.5 root 3793: if (!supervisor(dc))
3794: goto priv_insn;
1.1 root 3795: #ifdef TARGET_SPARC64
1.1.1.5 root 3796: switch (rd) {
3797: case 0:
1.1.1.12 root 3798: gen_helper_saved(cpu_env);
1.1.1.5 root 3799: break;
3800: case 1:
1.1.1.12 root 3801: gen_helper_restored(cpu_env);
1.1.1.5 root 3802: break;
3803: case 2: /* UA2005 allclean */
3804: case 3: /* UA2005 otherw */
3805: case 4: /* UA2005 normalw */
3806: case 5: /* UA2005 invalw */
3807: // XXX
3808: default:
1.1 root 3809: goto illegal_insn;
3810: }
3811: #else
1.1.1.6 root 3812: tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2);
1.1.1.12 root 3813: gen_helper_wrpsr(cpu_env, cpu_dst);
1.1.1.7 root 3814: tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
3815: dc->cc_op = CC_OP_FLAGS;
1.1.1.6 root 3816: save_state(dc, cpu_cond);
1.1.1.2 root 3817: gen_op_next_insn();
1.1.1.6 root 3818: tcg_gen_exit_tb(0);
1.1.1.5 root 3819: dc->is_br = 1;
1.1 root 3820: #endif
3821: }
3822: break;
3823: case 0x32: /* wrwim, V9 wrpr */
3824: {
1.1.1.5 root 3825: if (!supervisor(dc))
3826: goto priv_insn;
1.1.1.6 root 3827: tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
1.1 root 3828: #ifdef TARGET_SPARC64
1.1.1.5 root 3829: switch (rd) {
3830: case 0: // tpc
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, tpc));
3838: tcg_temp_free_ptr(r_tsptr);
3839: }
1.1.1.5 root 3840: break;
3841: case 1: // tnpc
1.1.1.6 root 3842: {
3843: TCGv_ptr r_tsptr;
3844:
3845: r_tsptr = tcg_temp_new_ptr();
1.1.1.8 root 3846: gen_load_trap_state_at_tl(r_tsptr, cpu_env);
1.1.1.6 root 3847: tcg_gen_st_tl(cpu_tmp0, r_tsptr,
3848: offsetof(trap_state, tnpc));
3849: tcg_temp_free_ptr(r_tsptr);
3850: }
1.1.1.5 root 3851: break;
3852: case 2: // tstate
1.1.1.6 root 3853: {
3854: TCGv_ptr r_tsptr;
3855:
3856: r_tsptr = tcg_temp_new_ptr();
1.1.1.8 root 3857: gen_load_trap_state_at_tl(r_tsptr, cpu_env);
1.1.1.6 root 3858: tcg_gen_st_tl(cpu_tmp0, r_tsptr,
3859: offsetof(trap_state,
3860: tstate));
3861: tcg_temp_free_ptr(r_tsptr);
3862: }
1.1.1.5 root 3863: break;
3864: case 3: // tt
1.1.1.6 root 3865: {
3866: TCGv_ptr r_tsptr;
3867:
3868: r_tsptr = tcg_temp_new_ptr();
1.1.1.8 root 3869: gen_load_trap_state_at_tl(r_tsptr, cpu_env);
1.1.1.6 root 3870: tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
3871: tcg_gen_st_i32(cpu_tmp32, r_tsptr,
3872: offsetof(trap_state, tt));
3873: tcg_temp_free_ptr(r_tsptr);
3874: }
1.1.1.5 root 3875: break;
3876: case 4: // tick
1.1.1.6 root 3877: {
3878: TCGv_ptr r_tickptr;
3879:
3880: r_tickptr = tcg_temp_new_ptr();
3881: tcg_gen_ld_ptr(r_tickptr, cpu_env,
1.1.1.13! root 3882: offsetof(CPUSPARCState, tick));
1.1.1.6 root 3883: gen_helper_tick_set_count(r_tickptr,
3884: cpu_tmp0);
3885: tcg_temp_free_ptr(r_tickptr);
3886: }
1.1.1.5 root 3887: break;
3888: case 5: // tba
1.1.1.6 root 3889: tcg_gen_mov_tl(cpu_tbr, cpu_tmp0);
1.1.1.5 root 3890: break;
3891: case 6: // pstate
1.1.1.11 root 3892: {
3893: TCGv r_tmp = tcg_temp_local_new();
3894:
3895: tcg_gen_mov_tl(r_tmp, cpu_tmp0);
3896: save_state(dc, cpu_cond);
1.1.1.12 root 3897: gen_helper_wrpstate(cpu_env, r_tmp);
1.1.1.11 root 3898: tcg_temp_free(r_tmp);
3899: dc->npc = DYNAMIC_PC;
3900: }
1.1.1.5 root 3901: break;
3902: case 7: // tl
1.1.1.11 root 3903: {
3904: TCGv r_tmp = tcg_temp_local_new();
3905:
3906: tcg_gen_mov_tl(r_tmp, cpu_tmp0);
3907: save_state(dc, cpu_cond);
3908: tcg_gen_trunc_tl_i32(cpu_tmp32, r_tmp);
3909: tcg_temp_free(r_tmp);
3910: tcg_gen_st_i32(cpu_tmp32, cpu_env,
3911: offsetof(CPUSPARCState, tl));
3912: dc->npc = DYNAMIC_PC;
3913: }
1.1.1.5 root 3914: break;
3915: case 8: // pil
1.1.1.12 root 3916: gen_helper_wrpil(cpu_env, cpu_tmp0);
1.1.1.5 root 3917: break;
3918: case 9: // cwp
1.1.1.12 root 3919: gen_helper_wrcwp(cpu_env, cpu_tmp0);
1.1.1.5 root 3920: break;
3921: case 10: // cansave
1.1.1.6 root 3922: tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
3923: tcg_gen_st_i32(cpu_tmp32, cpu_env,
3924: offsetof(CPUSPARCState,
3925: cansave));
1.1.1.5 root 3926: break;
3927: case 11: // canrestore
1.1.1.6 root 3928: tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
3929: tcg_gen_st_i32(cpu_tmp32, cpu_env,
3930: offsetof(CPUSPARCState,
3931: canrestore));
1.1.1.5 root 3932: break;
3933: case 12: // cleanwin
1.1.1.6 root 3934: tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
3935: tcg_gen_st_i32(cpu_tmp32, cpu_env,
3936: offsetof(CPUSPARCState,
3937: cleanwin));
1.1.1.5 root 3938: break;
3939: case 13: // otherwin
1.1.1.6 root 3940: tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
3941: tcg_gen_st_i32(cpu_tmp32, cpu_env,
3942: offsetof(CPUSPARCState,
3943: otherwin));
1.1.1.5 root 3944: break;
3945: case 14: // wstate
1.1.1.6 root 3946: tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
3947: tcg_gen_st_i32(cpu_tmp32, cpu_env,
3948: offsetof(CPUSPARCState,
3949: wstate));
1.1.1.5 root 3950: break;
3951: case 16: // UA2005 gl
1.1.1.6 root 3952: CHECK_IU_FEATURE(dc, GL);
3953: tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
3954: tcg_gen_st_i32(cpu_tmp32, cpu_env,
3955: offsetof(CPUSPARCState, gl));
1.1.1.5 root 3956: break;
3957: case 26: // UA2005 strand status
1.1.1.6 root 3958: CHECK_IU_FEATURE(dc, HYPV);
1.1.1.5 root 3959: if (!hypervisor(dc))
3960: goto priv_insn;
1.1.1.6 root 3961: tcg_gen_mov_tl(cpu_ssr, cpu_tmp0);
1.1.1.5 root 3962: break;
3963: default:
3964: goto illegal_insn;
3965: }
1.1 root 3966: #else
1.1.1.6 root 3967: tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
3968: if (dc->def->nwindows != 32)
3969: tcg_gen_andi_tl(cpu_tmp32, cpu_tmp32,
3970: (1 << dc->def->nwindows) - 1);
3971: tcg_gen_mov_i32(cpu_wim, cpu_tmp32);
1.1 root 3972: #endif
3973: }
3974: break;
1.1.1.5 root 3975: case 0x33: /* wrtbr, UA2005 wrhpr */
1.1 root 3976: {
1.1.1.5 root 3977: #ifndef TARGET_SPARC64
3978: if (!supervisor(dc))
3979: goto priv_insn;
1.1.1.6 root 3980: tcg_gen_xor_tl(cpu_tbr, cpu_src1, cpu_src2);
1.1.1.5 root 3981: #else
1.1.1.6 root 3982: CHECK_IU_FEATURE(dc, HYPV);
1.1.1.5 root 3983: if (!hypervisor(dc))
3984: goto priv_insn;
1.1.1.6 root 3985: tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
1.1.1.5 root 3986: switch (rd) {
3987: case 0: // hpstate
3988: // XXX gen_op_wrhpstate();
1.1.1.6 root 3989: save_state(dc, cpu_cond);
1.1.1.5 root 3990: gen_op_next_insn();
1.1.1.6 root 3991: tcg_gen_exit_tb(0);
1.1.1.5 root 3992: dc->is_br = 1;
3993: break;
3994: case 1: // htstate
3995: // XXX gen_op_wrhtstate();
3996: break;
3997: case 3: // hintp
1.1.1.6 root 3998: tcg_gen_mov_tl(cpu_hintp, cpu_tmp0);
1.1.1.5 root 3999: break;
4000: case 5: // htba
1.1.1.6 root 4001: tcg_gen_mov_tl(cpu_htba, cpu_tmp0);
1.1.1.5 root 4002: break;
4003: case 31: // hstick_cmpr
1.1.1.6 root 4004: {
4005: TCGv_ptr r_tickptr;
4006:
4007: tcg_gen_mov_tl(cpu_hstick_cmpr, cpu_tmp0);
4008: r_tickptr = tcg_temp_new_ptr();
4009: tcg_gen_ld_ptr(r_tickptr, cpu_env,
1.1.1.13! root 4010: offsetof(CPUSPARCState, hstick));
1.1.1.6 root 4011: gen_helper_tick_set_limit(r_tickptr,
4012: cpu_hstick_cmpr);
4013: tcg_temp_free_ptr(r_tickptr);
4014: }
1.1.1.5 root 4015: break;
4016: case 6: // hver readonly
4017: default:
4018: goto illegal_insn;
4019: }
4020: #endif
1.1 root 4021: }
4022: break;
4023: #endif
4024: #ifdef TARGET_SPARC64
1.1.1.5 root 4025: case 0x2c: /* V9 movcc */
4026: {
4027: int cc = GET_FIELD_SP(insn, 11, 12);
4028: int cond = GET_FIELD_SP(insn, 14, 17);
1.1.1.6 root 4029: TCGv r_cond;
4030: int l1;
4031:
4032: r_cond = tcg_temp_new();
1.1.1.5 root 4033: if (insn & (1 << 18)) {
4034: if (cc == 0)
1.1.1.7 root 4035: gen_cond(r_cond, 0, cond, dc);
1.1.1.5 root 4036: else if (cc == 2)
1.1.1.7 root 4037: gen_cond(r_cond, 1, cond, dc);
1.1.1.5 root 4038: else
4039: goto illegal_insn;
4040: } else {
1.1.1.6 root 4041: gen_fcond(r_cond, cc, cond);
4042: }
4043:
4044: l1 = gen_new_label();
4045:
4046: tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
4047: if (IS_IMM) { /* immediate */
4048: TCGv r_const;
4049:
1.1.1.7 root 4050: simm = GET_FIELD_SPs(insn, 0, 10);
4051: r_const = tcg_const_tl(simm);
1.1.1.6 root 4052: gen_movl_TN_reg(rd, r_const);
4053: tcg_temp_free(r_const);
4054: } else {
4055: rs2 = GET_FIELD_SP(insn, 0, 4);
4056: gen_movl_reg_TN(rs2, cpu_tmp0);
4057: gen_movl_TN_reg(rd, cpu_tmp0);
1.1.1.5 root 4058: }
1.1.1.6 root 4059: gen_set_label(l1);
4060: tcg_temp_free(r_cond);
1.1.1.5 root 4061: break;
4062: }
4063: case 0x2d: /* V9 sdivx */
1.1.1.6 root 4064: gen_op_sdivx(cpu_dst, cpu_src1, cpu_src2);
4065: gen_movl_TN_reg(rd, cpu_dst);
1.1 root 4066: break;
1.1.1.5 root 4067: case 0x2e: /* V9 popc */
4068: {
1.1.1.6 root 4069: cpu_src2 = get_src2(insn, cpu_src2);
4070: gen_helper_popc(cpu_dst, cpu_src2);
4071: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 4072: }
4073: case 0x2f: /* V9 movr */
4074: {
4075: int cond = GET_FIELD_SP(insn, 10, 12);
1.1.1.6 root 4076: int l1;
4077:
4078: cpu_src1 = get_src1(insn, cpu_src1);
4079:
4080: l1 = gen_new_label();
4081:
4082: tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond],
4083: cpu_src1, 0, l1);
1.1.1.5 root 4084: if (IS_IMM) { /* immediate */
1.1.1.6 root 4085: TCGv r_const;
4086:
1.1.1.7 root 4087: simm = GET_FIELD_SPs(insn, 0, 9);
4088: r_const = tcg_const_tl(simm);
1.1.1.6 root 4089: gen_movl_TN_reg(rd, r_const);
4090: tcg_temp_free(r_const);
4091: } else {
1.1.1.5 root 4092: rs2 = GET_FIELD_SP(insn, 0, 4);
1.1.1.6 root 4093: gen_movl_reg_TN(rs2, cpu_tmp0);
4094: gen_movl_TN_reg(rd, cpu_tmp0);
1.1.1.3 root 4095: }
1.1.1.6 root 4096: gen_set_label(l1);
1.1.1.3 root 4097: break;
1.1.1.5 root 4098: }
4099: #endif
4100: default:
4101: goto illegal_insn;
4102: }
4103: }
4104: } else if (xop == 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */
4105: #ifdef TARGET_SPARC64
4106: int opf = GET_FIELD_SP(insn, 5, 13);
4107: rs1 = GET_FIELD(insn, 13, 17);
4108: rs2 = GET_FIELD(insn, 27, 31);
1.1.1.6 root 4109: if (gen_trap_ifnofpu(dc, cpu_cond))
1.1.1.5 root 4110: goto jmp_insn;
4111:
4112: switch (opf) {
4113: case 0x000: /* VIS I edge8cc */
1.1.1.12 root 4114: CHECK_FPU_FEATURE(dc, VIS1);
4115: gen_movl_reg_TN(rs1, cpu_src1);
4116: gen_movl_reg_TN(rs2, cpu_src2);
4117: gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 0);
4118: gen_movl_TN_reg(rd, cpu_dst);
4119: break;
1.1.1.5 root 4120: case 0x001: /* VIS II edge8n */
1.1.1.12 root 4121: CHECK_FPU_FEATURE(dc, VIS2);
4122: gen_movl_reg_TN(rs1, cpu_src1);
4123: gen_movl_reg_TN(rs2, cpu_src2);
4124: gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 0);
4125: gen_movl_TN_reg(rd, cpu_dst);
4126: break;
1.1.1.5 root 4127: case 0x002: /* VIS I edge8lcc */
1.1.1.12 root 4128: CHECK_FPU_FEATURE(dc, VIS1);
4129: gen_movl_reg_TN(rs1, cpu_src1);
4130: gen_movl_reg_TN(rs2, cpu_src2);
4131: gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 1);
4132: gen_movl_TN_reg(rd, cpu_dst);
4133: break;
1.1.1.5 root 4134: case 0x003: /* VIS II edge8ln */
1.1.1.12 root 4135: CHECK_FPU_FEATURE(dc, VIS2);
4136: gen_movl_reg_TN(rs1, cpu_src1);
4137: gen_movl_reg_TN(rs2, cpu_src2);
4138: gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 1);
4139: gen_movl_TN_reg(rd, cpu_dst);
4140: break;
1.1.1.5 root 4141: case 0x004: /* VIS I edge16cc */
1.1.1.12 root 4142: CHECK_FPU_FEATURE(dc, VIS1);
4143: gen_movl_reg_TN(rs1, cpu_src1);
4144: gen_movl_reg_TN(rs2, cpu_src2);
4145: gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 0);
4146: gen_movl_TN_reg(rd, cpu_dst);
4147: break;
1.1.1.5 root 4148: case 0x005: /* VIS II edge16n */
1.1.1.12 root 4149: CHECK_FPU_FEATURE(dc, VIS2);
4150: gen_movl_reg_TN(rs1, cpu_src1);
4151: gen_movl_reg_TN(rs2, cpu_src2);
4152: gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 0);
4153: gen_movl_TN_reg(rd, cpu_dst);
4154: break;
1.1.1.5 root 4155: case 0x006: /* VIS I edge16lcc */
1.1.1.12 root 4156: CHECK_FPU_FEATURE(dc, VIS1);
4157: gen_movl_reg_TN(rs1, cpu_src1);
4158: gen_movl_reg_TN(rs2, cpu_src2);
4159: gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 1);
4160: gen_movl_TN_reg(rd, cpu_dst);
4161: break;
1.1.1.5 root 4162: case 0x007: /* VIS II edge16ln */
1.1.1.12 root 4163: CHECK_FPU_FEATURE(dc, VIS2);
4164: gen_movl_reg_TN(rs1, cpu_src1);
4165: gen_movl_reg_TN(rs2, cpu_src2);
4166: gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 1);
4167: gen_movl_TN_reg(rd, cpu_dst);
4168: break;
1.1.1.5 root 4169: case 0x008: /* VIS I edge32cc */
1.1.1.12 root 4170: CHECK_FPU_FEATURE(dc, VIS1);
4171: gen_movl_reg_TN(rs1, cpu_src1);
4172: gen_movl_reg_TN(rs2, cpu_src2);
4173: gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 0);
4174: gen_movl_TN_reg(rd, cpu_dst);
4175: break;
1.1.1.5 root 4176: case 0x009: /* VIS II edge32n */
1.1.1.12 root 4177: CHECK_FPU_FEATURE(dc, VIS2);
4178: gen_movl_reg_TN(rs1, cpu_src1);
4179: gen_movl_reg_TN(rs2, cpu_src2);
4180: gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 0);
4181: gen_movl_TN_reg(rd, cpu_dst);
4182: break;
1.1.1.5 root 4183: case 0x00a: /* VIS I edge32lcc */
1.1.1.12 root 4184: CHECK_FPU_FEATURE(dc, VIS1);
4185: gen_movl_reg_TN(rs1, cpu_src1);
4186: gen_movl_reg_TN(rs2, cpu_src2);
4187: gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 1);
4188: gen_movl_TN_reg(rd, cpu_dst);
4189: break;
1.1.1.5 root 4190: case 0x00b: /* VIS II edge32ln */
1.1.1.12 root 4191: CHECK_FPU_FEATURE(dc, VIS2);
4192: gen_movl_reg_TN(rs1, cpu_src1);
4193: gen_movl_reg_TN(rs2, cpu_src2);
4194: gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 1);
4195: gen_movl_TN_reg(rd, cpu_dst);
4196: break;
1.1.1.5 root 4197: case 0x010: /* VIS I array8 */
1.1.1.6 root 4198: CHECK_FPU_FEATURE(dc, VIS1);
4199: cpu_src1 = get_src1(insn, cpu_src1);
4200: gen_movl_reg_TN(rs2, cpu_src2);
4201: gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
4202: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 4203: break;
4204: case 0x012: /* VIS I array16 */
1.1.1.6 root 4205: CHECK_FPU_FEATURE(dc, VIS1);
4206: cpu_src1 = get_src1(insn, cpu_src1);
4207: gen_movl_reg_TN(rs2, cpu_src2);
4208: gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
4209: tcg_gen_shli_i64(cpu_dst, cpu_dst, 1);
4210: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 4211: break;
4212: case 0x014: /* VIS I array32 */
1.1.1.6 root 4213: CHECK_FPU_FEATURE(dc, VIS1);
4214: cpu_src1 = get_src1(insn, cpu_src1);
4215: gen_movl_reg_TN(rs2, cpu_src2);
4216: gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
4217: tcg_gen_shli_i64(cpu_dst, cpu_dst, 2);
4218: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 4219: break;
4220: case 0x018: /* VIS I alignaddr */
1.1.1.6 root 4221: CHECK_FPU_FEATURE(dc, VIS1);
4222: cpu_src1 = get_src1(insn, cpu_src1);
4223: gen_movl_reg_TN(rs2, cpu_src2);
1.1.1.12 root 4224: gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 0);
1.1.1.6 root 4225: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 4226: break;
4227: case 0x01a: /* VIS I alignaddrl */
1.1.1.12 root 4228: CHECK_FPU_FEATURE(dc, VIS1);
4229: cpu_src1 = get_src1(insn, cpu_src1);
4230: gen_movl_reg_TN(rs2, cpu_src2);
4231: gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 1);
4232: gen_movl_TN_reg(rd, cpu_dst);
4233: break;
4234: case 0x019: /* VIS II bmask */
4235: CHECK_FPU_FEATURE(dc, VIS2);
4236: cpu_src1 = get_src1(insn, cpu_src1);
4237: cpu_src2 = get_src1(insn, cpu_src2);
4238: tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
4239: tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, cpu_dst, 32, 32);
4240: gen_movl_TN_reg(rd, cpu_dst);
4241: break;
1.1.1.5 root 4242: case 0x020: /* VIS I fcmple16 */
1.1.1.6 root 4243: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4244: cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4245: cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4246: gen_helper_fcmple16(cpu_dst, cpu_src1_64, cpu_src2_64);
1.1.1.11 root 4247: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 4248: break;
4249: case 0x022: /* VIS I fcmpne16 */
1.1.1.6 root 4250: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4251: cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4252: cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4253: gen_helper_fcmpne16(cpu_dst, cpu_src1_64, cpu_src2_64);
1.1.1.11 root 4254: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 4255: break;
4256: case 0x024: /* VIS I fcmple32 */
1.1.1.6 root 4257: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4258: cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4259: cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4260: gen_helper_fcmple32(cpu_dst, cpu_src1_64, cpu_src2_64);
1.1.1.11 root 4261: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 4262: break;
4263: case 0x026: /* VIS I fcmpne32 */
1.1.1.6 root 4264: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4265: cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4266: cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4267: gen_helper_fcmpne32(cpu_dst, cpu_src1_64, cpu_src2_64);
1.1.1.11 root 4268: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 4269: break;
4270: case 0x028: /* VIS I fcmpgt16 */
1.1.1.6 root 4271: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4272: cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4273: cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4274: gen_helper_fcmpgt16(cpu_dst, cpu_src1_64, cpu_src2_64);
1.1.1.11 root 4275: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 4276: break;
4277: case 0x02a: /* VIS I fcmpeq16 */
1.1.1.6 root 4278: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4279: cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4280: cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4281: gen_helper_fcmpeq16(cpu_dst, cpu_src1_64, cpu_src2_64);
1.1.1.11 root 4282: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 4283: break;
4284: case 0x02c: /* VIS I fcmpgt32 */
1.1.1.6 root 4285: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4286: cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4287: cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4288: gen_helper_fcmpgt32(cpu_dst, cpu_src1_64, cpu_src2_64);
1.1.1.11 root 4289: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 4290: break;
4291: case 0x02e: /* VIS I fcmpeq32 */
1.1.1.6 root 4292: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4293: cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4294: cpu_src2_64 = gen_load_fpr_D(dc, rs2);
4295: gen_helper_fcmpeq32(cpu_dst, cpu_src1_64, cpu_src2_64);
1.1.1.11 root 4296: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 4297: break;
4298: case 0x031: /* VIS I fmul8x16 */
1.1.1.6 root 4299: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4300: gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16);
1.1.1.5 root 4301: break;
4302: case 0x033: /* VIS I fmul8x16au */
1.1.1.6 root 4303: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4304: gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16au);
1.1.1.5 root 4305: break;
4306: case 0x035: /* VIS I fmul8x16al */
1.1.1.6 root 4307: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4308: gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16al);
1.1.1.5 root 4309: break;
4310: case 0x036: /* VIS I fmul8sux16 */
1.1.1.6 root 4311: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4312: gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8sux16);
1.1.1.5 root 4313: break;
4314: case 0x037: /* VIS I fmul8ulx16 */
1.1.1.6 root 4315: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4316: gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8ulx16);
1.1.1.5 root 4317: break;
4318: case 0x038: /* VIS I fmuld8sux16 */
1.1.1.6 root 4319: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4320: gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8sux16);
1.1.1.5 root 4321: break;
4322: case 0x039: /* VIS I fmuld8ulx16 */
1.1.1.6 root 4323: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4324: gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8ulx16);
1.1.1.5 root 4325: break;
4326: case 0x03a: /* VIS I fpack32 */
1.1.1.12 root 4327: CHECK_FPU_FEATURE(dc, VIS1);
4328: gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpack32);
4329: break;
1.1.1.5 root 4330: case 0x03b: /* VIS I fpack16 */
1.1.1.12 root 4331: CHECK_FPU_FEATURE(dc, VIS1);
4332: cpu_src1_64 = gen_load_fpr_D(dc, rs2);
4333: cpu_dst_32 = gen_dest_fpr_F();
4334: gen_helper_fpack16(cpu_dst_32, cpu_gsr, cpu_src1_64);
4335: gen_store_fpr_F(dc, rd, cpu_dst_32);
4336: break;
1.1.1.5 root 4337: case 0x03d: /* VIS I fpackfix */
1.1.1.12 root 4338: CHECK_FPU_FEATURE(dc, VIS1);
4339: cpu_src1_64 = gen_load_fpr_D(dc, rs2);
4340: cpu_dst_32 = gen_dest_fpr_F();
4341: gen_helper_fpackfix(cpu_dst_32, cpu_gsr, cpu_src1_64);
4342: gen_store_fpr_F(dc, rd, cpu_dst_32);
4343: break;
1.1.1.5 root 4344: case 0x03e: /* VIS I pdist */
1.1.1.12 root 4345: CHECK_FPU_FEATURE(dc, VIS1);
4346: gen_ne_fop_DDDD(dc, rd, rs1, rs2, gen_helper_pdist);
4347: break;
1.1.1.5 root 4348: case 0x048: /* VIS I faligndata */
1.1.1.6 root 4349: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4350: gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_faligndata);
1.1.1.5 root 4351: break;
4352: case 0x04b: /* VIS I fpmerge */
1.1.1.6 root 4353: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4354: gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpmerge);
1.1.1.5 root 4355: break;
4356: case 0x04c: /* VIS II bshuffle */
1.1.1.12 root 4357: CHECK_FPU_FEATURE(dc, VIS2);
4358: gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_bshuffle);
4359: break;
1.1.1.5 root 4360: case 0x04d: /* VIS I fexpand */
1.1.1.6 root 4361: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4362: gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fexpand);
1.1.1.5 root 4363: break;
4364: case 0x050: /* VIS I fpadd16 */
1.1.1.6 root 4365: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4366: gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd16);
1.1.1.5 root 4367: break;
4368: case 0x051: /* VIS I fpadd16s */
1.1.1.6 root 4369: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4370: gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpadd16s);
1.1.1.5 root 4371: break;
4372: case 0x052: /* VIS I fpadd32 */
1.1.1.6 root 4373: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4374: gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd32);
1.1.1.5 root 4375: break;
4376: case 0x053: /* VIS I fpadd32s */
1.1.1.6 root 4377: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4378: gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_add_i32);
1.1.1.5 root 4379: break;
4380: case 0x054: /* VIS I fpsub16 */
1.1.1.6 root 4381: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4382: gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub16);
1.1.1.5 root 4383: break;
4384: case 0x055: /* VIS I fpsub16s */
1.1.1.6 root 4385: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4386: gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpsub16s);
1.1.1.5 root 4387: break;
4388: case 0x056: /* VIS I fpsub32 */
1.1.1.6 root 4389: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4390: gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub32);
1.1.1.5 root 4391: break;
4392: case 0x057: /* VIS I fpsub32s */
1.1.1.6 root 4393: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4394: gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_sub_i32);
1.1.1.5 root 4395: break;
4396: case 0x060: /* VIS I fzero */
1.1.1.6 root 4397: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4398: cpu_dst_64 = gen_dest_fpr_D();
4399: tcg_gen_movi_i64(cpu_dst_64, 0);
4400: gen_store_fpr_D(dc, rd, cpu_dst_64);
1.1.1.5 root 4401: break;
4402: case 0x061: /* VIS I fzeros */
1.1.1.6 root 4403: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4404: cpu_dst_32 = gen_dest_fpr_F();
4405: tcg_gen_movi_i32(cpu_dst_32, 0);
4406: gen_store_fpr_F(dc, rd, cpu_dst_32);
1.1.1.5 root 4407: break;
4408: case 0x062: /* VIS I fnor */
1.1.1.6 root 4409: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4410: gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nor_i64);
1.1.1.5 root 4411: break;
4412: case 0x063: /* VIS I fnors */
1.1.1.6 root 4413: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4414: gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nor_i32);
1.1.1.5 root 4415: break;
4416: case 0x064: /* VIS I fandnot2 */
1.1.1.6 root 4417: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4418: gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_andc_i64);
1.1.1.5 root 4419: break;
4420: case 0x065: /* VIS I fandnot2s */
1.1.1.6 root 4421: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4422: gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_andc_i32);
1.1.1.5 root 4423: break;
4424: case 0x066: /* VIS I fnot2 */
1.1.1.6 root 4425: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4426: gen_ne_fop_DD(dc, rd, rs2, tcg_gen_not_i64);
1.1.1.5 root 4427: break;
4428: case 0x067: /* VIS I fnot2s */
1.1.1.6 root 4429: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4430: gen_ne_fop_FF(dc, rd, rs2, tcg_gen_not_i32);
1.1.1.5 root 4431: break;
4432: case 0x068: /* VIS I fandnot1 */
1.1.1.6 root 4433: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4434: gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_andc_i64);
1.1.1.5 root 4435: break;
4436: case 0x069: /* VIS I fandnot1s */
1.1.1.6 root 4437: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4438: gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_andc_i32);
1.1.1.5 root 4439: break;
4440: case 0x06a: /* VIS I fnot1 */
1.1.1.6 root 4441: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4442: gen_ne_fop_DD(dc, rd, rs1, tcg_gen_not_i64);
1.1.1.5 root 4443: break;
4444: case 0x06b: /* VIS I fnot1s */
1.1.1.6 root 4445: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4446: gen_ne_fop_FF(dc, rd, rs1, tcg_gen_not_i32);
1.1.1.5 root 4447: break;
4448: case 0x06c: /* VIS I fxor */
1.1.1.6 root 4449: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4450: gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_xor_i64);
1.1.1.5 root 4451: break;
4452: case 0x06d: /* VIS I fxors */
1.1.1.6 root 4453: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4454: gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_xor_i32);
1.1.1.5 root 4455: break;
4456: case 0x06e: /* VIS I fnand */
1.1.1.6 root 4457: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4458: gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nand_i64);
1.1.1.5 root 4459: break;
4460: case 0x06f: /* VIS I fnands */
1.1.1.6 root 4461: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4462: gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nand_i32);
1.1.1.5 root 4463: break;
4464: case 0x070: /* VIS I fand */
1.1.1.6 root 4465: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4466: gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_and_i64);
1.1.1.5 root 4467: break;
4468: case 0x071: /* VIS I fands */
1.1.1.6 root 4469: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4470: gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_and_i32);
1.1.1.5 root 4471: break;
4472: case 0x072: /* VIS I fxnor */
1.1.1.6 root 4473: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4474: gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_eqv_i64);
1.1.1.5 root 4475: break;
4476: case 0x073: /* VIS I fxnors */
1.1.1.6 root 4477: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4478: gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_eqv_i32);
1.1.1.5 root 4479: break;
4480: case 0x074: /* VIS I fsrc1 */
1.1.1.6 root 4481: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4482: cpu_src1_64 = gen_load_fpr_D(dc, rs1);
4483: gen_store_fpr_D(dc, rd, cpu_src1_64);
1.1.1.5 root 4484: break;
4485: case 0x075: /* VIS I fsrc1s */
1.1.1.6 root 4486: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4487: cpu_src1_32 = gen_load_fpr_F(dc, rs1);
4488: gen_store_fpr_F(dc, rd, cpu_src1_32);
1.1.1.5 root 4489: break;
4490: case 0x076: /* VIS I fornot2 */
1.1.1.6 root 4491: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4492: gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_orc_i64);
1.1.1.5 root 4493: break;
4494: case 0x077: /* VIS I fornot2s */
1.1.1.6 root 4495: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4496: gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_orc_i32);
1.1.1.5 root 4497: break;
4498: case 0x078: /* VIS I fsrc2 */
1.1.1.6 root 4499: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4500: cpu_src1_64 = gen_load_fpr_D(dc, rs2);
4501: gen_store_fpr_D(dc, rd, cpu_src1_64);
1.1.1.5 root 4502: break;
4503: case 0x079: /* VIS I fsrc2s */
1.1.1.6 root 4504: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4505: cpu_src1_32 = gen_load_fpr_F(dc, rs2);
4506: gen_store_fpr_F(dc, rd, cpu_src1_32);
1.1.1.5 root 4507: break;
4508: case 0x07a: /* VIS I fornot1 */
1.1.1.6 root 4509: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4510: gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_orc_i64);
1.1.1.5 root 4511: break;
4512: case 0x07b: /* VIS I fornot1s */
1.1.1.6 root 4513: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4514: gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_orc_i32);
1.1.1.5 root 4515: break;
4516: case 0x07c: /* VIS I for */
1.1.1.6 root 4517: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4518: gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_or_i64);
1.1.1.5 root 4519: break;
4520: case 0x07d: /* VIS I fors */
1.1.1.6 root 4521: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4522: gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_or_i32);
1.1.1.5 root 4523: break;
4524: case 0x07e: /* VIS I fone */
1.1.1.6 root 4525: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4526: cpu_dst_64 = gen_dest_fpr_D();
4527: tcg_gen_movi_i64(cpu_dst_64, -1);
4528: gen_store_fpr_D(dc, rd, cpu_dst_64);
1.1.1.5 root 4529: break;
4530: case 0x07f: /* VIS I fones */
1.1.1.6 root 4531: CHECK_FPU_FEATURE(dc, VIS1);
1.1.1.12 root 4532: cpu_dst_32 = gen_dest_fpr_F();
4533: tcg_gen_movi_i32(cpu_dst_32, -1);
4534: gen_store_fpr_F(dc, rd, cpu_dst_32);
1.1.1.5 root 4535: break;
4536: case 0x080: /* VIS I shutdown */
4537: case 0x081: /* VIS II siam */
4538: // XXX
4539: goto illegal_insn;
4540: default:
4541: goto illegal_insn;
4542: }
4543: #else
4544: goto ncp_insn;
4545: #endif
4546: } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */
4547: #ifdef TARGET_SPARC64
4548: goto illegal_insn;
4549: #else
4550: goto ncp_insn;
1.1 root 4551: #endif
4552: #ifdef TARGET_SPARC64
1.1.1.5 root 4553: } else if (xop == 0x39) { /* V9 return */
1.1.1.6 root 4554: TCGv_i32 r_const;
4555:
4556: save_state(dc, cpu_cond);
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.12 root 4569: gen_helper_restore(cpu_env);
1.1.1.6 root 4570: gen_mov_pc_npc(dc, cpu_cond);
4571: r_const = tcg_const_i32(3);
1.1.1.13! root 4572: gen_helper_check_align(cpu_env, cpu_dst, r_const);
1.1.1.6 root 4573: tcg_temp_free_i32(r_const);
4574: tcg_gen_mov_tl(cpu_npc, cpu_dst);
1.1.1.5 root 4575: dc->npc = DYNAMIC_PC;
4576: goto jmp_insn;
1.1 root 4577: #endif
1.1.1.5 root 4578: } else {
1.1.1.6 root 4579: cpu_src1 = get_src1(insn, cpu_src1);
1.1.1.5 root 4580: if (IS_IMM) { /* immediate */
1.1.1.7 root 4581: simm = GET_FIELDs(insn, 19, 31);
4582: tcg_gen_addi_tl(cpu_dst, cpu_src1, simm);
1.1.1.5 root 4583: } else { /* register */
1.1 root 4584: rs2 = GET_FIELD(insn, 27, 31);
1.1.1.5 root 4585: if (rs2) {
1.1.1.6 root 4586: gen_movl_reg_TN(rs2, cpu_src2);
4587: tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2);
4588: } else
4589: tcg_gen_mov_tl(cpu_dst, cpu_src1);
1.1 root 4590: }
1.1.1.5 root 4591: switch (xop) {
4592: case 0x38: /* jmpl */
4593: {
1.1.1.6 root 4594: TCGv r_pc;
4595: TCGv_i32 r_const;
4596:
4597: r_pc = tcg_const_tl(dc->pc);
4598: gen_movl_TN_reg(rd, r_pc);
4599: tcg_temp_free(r_pc);
4600: gen_mov_pc_npc(dc, cpu_cond);
4601: r_const = tcg_const_i32(3);
1.1.1.13! root 4602: gen_helper_check_align(cpu_env, cpu_dst, r_const);
1.1.1.6 root 4603: tcg_temp_free_i32(r_const);
1.1.1.13! root 4604: gen_address_mask(dc, cpu_dst);
1.1.1.6 root 4605: tcg_gen_mov_tl(cpu_npc, cpu_dst);
1.1.1.5 root 4606: dc->npc = DYNAMIC_PC;
4607: }
4608: goto jmp_insn;
1.1 root 4609: #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
1.1.1.5 root 4610: case 0x39: /* rett, V9 return */
4611: {
1.1.1.6 root 4612: TCGv_i32 r_const;
4613:
1.1.1.5 root 4614: if (!supervisor(dc))
4615: goto priv_insn;
1.1.1.6 root 4616: gen_mov_pc_npc(dc, cpu_cond);
4617: r_const = tcg_const_i32(3);
1.1.1.13! root 4618: gen_helper_check_align(cpu_env, cpu_dst, r_const);
1.1.1.6 root 4619: tcg_temp_free_i32(r_const);
4620: tcg_gen_mov_tl(cpu_npc, cpu_dst);
1.1.1.5 root 4621: dc->npc = DYNAMIC_PC;
1.1.1.12 root 4622: gen_helper_rett(cpu_env);
1.1.1.5 root 4623: }
4624: goto jmp_insn;
4625: #endif
4626: case 0x3b: /* flush */
1.1.1.6 root 4627: if (!((dc)->def->features & CPU_FEATURE_FLUSH))
4628: goto unimp_flush;
1.1.1.11 root 4629: /* nop */
1.1.1.5 root 4630: break;
4631: case 0x3c: /* save */
1.1.1.6 root 4632: save_state(dc, cpu_cond);
1.1.1.12 root 4633: gen_helper_save(cpu_env);
1.1.1.6 root 4634: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 4635: break;
4636: case 0x3d: /* restore */
1.1.1.6 root 4637: save_state(dc, cpu_cond);
1.1.1.12 root 4638: gen_helper_restore(cpu_env);
1.1.1.6 root 4639: gen_movl_TN_reg(rd, cpu_dst);
1.1.1.5 root 4640: break;
1.1 root 4641: #if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
1.1.1.5 root 4642: case 0x3e: /* V9 done/retry */
4643: {
4644: switch (rd) {
4645: case 0:
4646: if (!supervisor(dc))
4647: goto priv_insn;
4648: dc->npc = DYNAMIC_PC;
4649: dc->pc = DYNAMIC_PC;
1.1.1.12 root 4650: gen_helper_done(cpu_env);
1.1.1.5 root 4651: goto jmp_insn;
4652: case 1:
4653: if (!supervisor(dc))
4654: goto priv_insn;
4655: dc->npc = DYNAMIC_PC;
4656: dc->pc = DYNAMIC_PC;
1.1.1.12 root 4657: gen_helper_retry(cpu_env);
1.1.1.5 root 4658: goto jmp_insn;
4659: default:
4660: goto illegal_insn;
4661: }
4662: }
4663: break;
4664: #endif
4665: default:
4666: goto illegal_insn;
4667: }
4668: }
4669: break;
4670: }
4671: break;
4672: case 3: /* load/store instructions */
4673: {
4674: unsigned int xop = GET_FIELD(insn, 7, 12);
1.1.1.6 root 4675:
1.1.1.8 root 4676: /* flush pending conditional evaluations before exposing
4677: cpu state */
4678: if (dc->cc_op != CC_OP_FLAGS) {
4679: dc->cc_op = CC_OP_FLAGS;
1.1.1.12 root 4680: gen_helper_compute_psr(cpu_env);
1.1.1.8 root 4681: }
1.1.1.6 root 4682: cpu_src1 = get_src1(insn, cpu_src1);
4683: if (xop == 0x3c || xop == 0x3e) { // V9 casa/casxa
1.1.1.5 root 4684: rs2 = GET_FIELD(insn, 27, 31);
1.1.1.6 root 4685: gen_movl_reg_TN(rs2, cpu_src2);
4686: tcg_gen_mov_tl(cpu_addr, cpu_src1);
4687: } else if (IS_IMM) { /* immediate */
1.1.1.7 root 4688: simm = GET_FIELDs(insn, 19, 31);
4689: tcg_gen_addi_tl(cpu_addr, cpu_src1, simm);
1.1.1.5 root 4690: } else { /* register */
4691: rs2 = GET_FIELD(insn, 27, 31);
4692: if (rs2 != 0) {
1.1.1.6 root 4693: gen_movl_reg_TN(rs2, cpu_src2);
4694: tcg_gen_add_tl(cpu_addr, cpu_src1, cpu_src2);
4695: } else
4696: tcg_gen_mov_tl(cpu_addr, cpu_src1);
1.1.1.5 root 4697: }
4698: if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) ||
4699: (xop > 0x17 && xop <= 0x1d ) ||
4700: (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
4701: switch (xop) {
1.1.1.7 root 4702: case 0x0: /* ld, V9 lduw, load unsigned word */
1.1.1.6 root 4703: gen_address_mask(dc, cpu_addr);
4704: tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx);
1.1.1.5 root 4705: break;
1.1.1.7 root 4706: case 0x1: /* ldub, load unsigned byte */
1.1.1.6 root 4707: gen_address_mask(dc, cpu_addr);
4708: tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx);
1.1.1.5 root 4709: break;
1.1.1.7 root 4710: case 0x2: /* lduh, load unsigned halfword */
1.1.1.6 root 4711: gen_address_mask(dc, cpu_addr);
4712: tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx);
1.1.1.5 root 4713: break;
1.1.1.7 root 4714: case 0x3: /* ldd, load double word */
1.1.1.5 root 4715: if (rd & 1)
4716: goto illegal_insn;
1.1.1.6 root 4717: else {
4718: TCGv_i32 r_const;
4719:
4720: save_state(dc, cpu_cond);
4721: r_const = tcg_const_i32(7);
1.1.1.13! root 4722: /* XXX remove alignment check */
! 4723: gen_helper_check_align(cpu_env, cpu_addr, r_const);
1.1.1.6 root 4724: tcg_temp_free_i32(r_const);
4725: gen_address_mask(dc, cpu_addr);
4726: tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
4727: tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64);
4728: tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffffULL);
4729: gen_movl_TN_reg(rd + 1, cpu_tmp0);
4730: tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32);
4731: tcg_gen_trunc_i64_tl(cpu_val, cpu_tmp64);
4732: tcg_gen_andi_tl(cpu_val, cpu_val, 0xffffffffULL);
4733: }
1.1.1.5 root 4734: break;
1.1.1.7 root 4735: case 0x9: /* ldsb, load signed byte */
1.1.1.6 root 4736: gen_address_mask(dc, cpu_addr);
4737: tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
1.1.1.5 root 4738: break;
1.1.1.7 root 4739: case 0xa: /* ldsh, load signed halfword */
1.1.1.6 root 4740: gen_address_mask(dc, cpu_addr);
4741: tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx);
1.1.1.5 root 4742: break;
4743: case 0xd: /* ldstub -- XXX: should be atomically */
1.1.1.6 root 4744: {
4745: TCGv r_const;
4746:
4747: gen_address_mask(dc, cpu_addr);
4748: tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
4749: r_const = tcg_const_tl(0xff);
4750: tcg_gen_qemu_st8(r_const, cpu_addr, dc->mem_idx);
4751: tcg_temp_free(r_const);
4752: }
1.1.1.5 root 4753: break;
1.1.1.7 root 4754: case 0x0f: /* swap, swap register with memory. Also
1.1.1.6 root 4755: atomically */
4756: CHECK_IU_FEATURE(dc, SWAP);
4757: gen_movl_reg_TN(rd, cpu_val);
4758: gen_address_mask(dc, cpu_addr);
4759: tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
4760: tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
4761: tcg_gen_mov_tl(cpu_val, cpu_tmp0);
1.1.1.5 root 4762: break;
1.1 root 4763: #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
1.1.1.7 root 4764: case 0x10: /* lda, V9 lduwa, load word alternate */
1.1 root 4765: #ifndef TARGET_SPARC64
1.1.1.5 root 4766: if (IS_IMM)
4767: goto illegal_insn;
4768: if (!supervisor(dc))
4769: goto priv_insn;
1.1 root 4770: #endif
1.1.1.6 root 4771: save_state(dc, cpu_cond);
4772: gen_ld_asi(cpu_val, cpu_addr, insn, 4, 0);
1.1.1.5 root 4773: break;
1.1.1.7 root 4774: case 0x11: /* lduba, load unsigned byte alternate */
1.1 root 4775: #ifndef TARGET_SPARC64
1.1.1.5 root 4776: if (IS_IMM)
4777: goto illegal_insn;
4778: if (!supervisor(dc))
4779: goto priv_insn;
1.1 root 4780: #endif
1.1.1.6 root 4781: save_state(dc, cpu_cond);
4782: gen_ld_asi(cpu_val, cpu_addr, insn, 1, 0);
1.1.1.5 root 4783: break;
1.1.1.7 root 4784: case 0x12: /* lduha, load unsigned halfword alternate */
1.1 root 4785: #ifndef TARGET_SPARC64
1.1.1.5 root 4786: if (IS_IMM)
4787: goto illegal_insn;
4788: if (!supervisor(dc))
4789: goto priv_insn;
1.1 root 4790: #endif
1.1.1.6 root 4791: save_state(dc, cpu_cond);
4792: gen_ld_asi(cpu_val, cpu_addr, insn, 2, 0);
1.1.1.5 root 4793: break;
1.1.1.7 root 4794: case 0x13: /* ldda, load double word alternate */
1.1 root 4795: #ifndef TARGET_SPARC64
1.1.1.5 root 4796: if (IS_IMM)
4797: goto illegal_insn;
4798: if (!supervisor(dc))
4799: goto priv_insn;
1.1 root 4800: #endif
1.1.1.5 root 4801: if (rd & 1)
4802: goto illegal_insn;
1.1.1.6 root 4803: save_state(dc, cpu_cond);
4804: gen_ldda_asi(cpu_val, cpu_addr, insn, rd);
4805: goto skip_move;
1.1.1.7 root 4806: case 0x19: /* ldsba, load signed byte alternate */
1.1 root 4807: #ifndef TARGET_SPARC64
1.1.1.5 root 4808: if (IS_IMM)
4809: goto illegal_insn;
4810: if (!supervisor(dc))
4811: goto priv_insn;
1.1 root 4812: #endif
1.1.1.6 root 4813: save_state(dc, cpu_cond);
4814: gen_ld_asi(cpu_val, cpu_addr, insn, 1, 1);
1.1.1.5 root 4815: break;
1.1.1.7 root 4816: case 0x1a: /* ldsha, load signed halfword alternate */
1.1 root 4817: #ifndef TARGET_SPARC64
1.1.1.5 root 4818: if (IS_IMM)
4819: goto illegal_insn;
4820: if (!supervisor(dc))
4821: goto priv_insn;
1.1 root 4822: #endif
1.1.1.6 root 4823: save_state(dc, cpu_cond);
4824: gen_ld_asi(cpu_val, cpu_addr, insn, 2, 1);
1.1.1.5 root 4825: break;
4826: case 0x1d: /* ldstuba -- XXX: should be atomically */
1.1 root 4827: #ifndef TARGET_SPARC64
1.1.1.5 root 4828: if (IS_IMM)
4829: goto illegal_insn;
4830: if (!supervisor(dc))
4831: goto priv_insn;
1.1 root 4832: #endif
1.1.1.6 root 4833: save_state(dc, cpu_cond);
4834: gen_ldstub_asi(cpu_val, cpu_addr, insn);
1.1.1.5 root 4835: break;
1.1.1.7 root 4836: case 0x1f: /* swapa, swap reg with alt. memory. Also
1.1.1.6 root 4837: atomically */
4838: CHECK_IU_FEATURE(dc, SWAP);
1.1 root 4839: #ifndef TARGET_SPARC64
1.1.1.5 root 4840: if (IS_IMM)
4841: goto illegal_insn;
4842: if (!supervisor(dc))
4843: goto priv_insn;
1.1 root 4844: #endif
1.1.1.6 root 4845: save_state(dc, cpu_cond);
4846: gen_movl_reg_TN(rd, cpu_val);
4847: gen_swap_asi(cpu_val, cpu_addr, insn);
1.1.1.5 root 4848: break;
1.1 root 4849:
4850: #ifndef TARGET_SPARC64
1.1.1.5 root 4851: case 0x30: /* ldc */
4852: case 0x31: /* ldcsr */
4853: case 0x33: /* lddc */
4854: goto ncp_insn;
1.1 root 4855: #endif
4856: #endif
4857: #ifdef TARGET_SPARC64
1.1.1.5 root 4858: case 0x08: /* V9 ldsw */
1.1.1.6 root 4859: gen_address_mask(dc, cpu_addr);
4860: tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx);
1.1.1.5 root 4861: break;
4862: case 0x0b: /* V9 ldx */
1.1.1.6 root 4863: gen_address_mask(dc, cpu_addr);
4864: tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx);
1.1.1.5 root 4865: break;
4866: case 0x18: /* V9 ldswa */
1.1.1.6 root 4867: save_state(dc, cpu_cond);
4868: gen_ld_asi(cpu_val, cpu_addr, insn, 4, 1);
1.1.1.5 root 4869: break;
4870: case 0x1b: /* V9 ldxa */
1.1.1.6 root 4871: save_state(dc, cpu_cond);
4872: gen_ld_asi(cpu_val, cpu_addr, insn, 8, 0);
1.1.1.5 root 4873: break;
4874: case 0x2d: /* V9 prefetch, no effect */
4875: goto skip_move;
4876: case 0x30: /* V9 ldfa */
1.1.1.11 root 4877: if (gen_trap_ifnofpu(dc, cpu_cond)) {
4878: goto jmp_insn;
4879: }
1.1.1.6 root 4880: save_state(dc, cpu_cond);
4881: gen_ldf_asi(cpu_addr, insn, 4, rd);
1.1.1.12 root 4882: gen_update_fprs_dirty(rd);
1.1.1.5 root 4883: goto skip_move;
4884: case 0x33: /* V9 lddfa */
1.1.1.11 root 4885: if (gen_trap_ifnofpu(dc, cpu_cond)) {
4886: goto jmp_insn;
4887: }
1.1.1.6 root 4888: save_state(dc, cpu_cond);
4889: gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd));
1.1.1.12 root 4890: gen_update_fprs_dirty(DFPREG(rd));
1.1.1.5 root 4891: goto skip_move;
4892: case 0x3d: /* V9 prefetcha, no effect */
4893: goto skip_move;
4894: case 0x32: /* V9 ldqfa */
1.1.1.6 root 4895: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.11 root 4896: if (gen_trap_ifnofpu(dc, cpu_cond)) {
4897: goto jmp_insn;
4898: }
1.1.1.6 root 4899: save_state(dc, cpu_cond);
4900: gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd));
1.1.1.12 root 4901: gen_update_fprs_dirty(QFPREG(rd));
1.1.1.5 root 4902: goto skip_move;
4903: #endif
4904: default:
4905: goto illegal_insn;
4906: }
1.1.1.6 root 4907: gen_movl_TN_reg(rd, cpu_val);
4908: #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
1.1.1.5 root 4909: skip_move: ;
1.1 root 4910: #endif
1.1.1.5 root 4911: } else if (xop >= 0x20 && xop < 0x24) {
1.1.1.6 root 4912: if (gen_trap_ifnofpu(dc, cpu_cond))
1.1.1.3 root 4913: goto jmp_insn;
1.1.1.6 root 4914: save_state(dc, cpu_cond);
1.1.1.5 root 4915: switch (xop) {
1.1.1.7 root 4916: case 0x20: /* ldf, load fpreg */
1.1.1.6 root 4917: gen_address_mask(dc, cpu_addr);
4918: tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
1.1.1.12 root 4919: cpu_dst_32 = gen_dest_fpr_F();
4920: tcg_gen_trunc_tl_i32(cpu_dst_32, cpu_tmp0);
4921: gen_store_fpr_F(dc, rd, cpu_dst_32);
1.1.1.6 root 4922: break;
4923: case 0x21: /* ldfsr, V9 ldxfsr */
4924: #ifdef TARGET_SPARC64
4925: gen_address_mask(dc, cpu_addr);
4926: if (rd == 1) {
4927: tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
1.1.1.12 root 4928: gen_helper_ldxfsr(cpu_env, cpu_tmp64);
1.1.1.9 root 4929: } else {
4930: tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
4931: tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
1.1.1.12 root 4932: gen_helper_ldfsr(cpu_env, cpu_tmp32);
1.1.1.9 root 4933: }
1.1.1.6 root 4934: #else
4935: {
4936: tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx);
1.1.1.12 root 4937: gen_helper_ldfsr(cpu_env, cpu_tmp32);
1.1.1.6 root 4938: }
4939: #endif
1.1.1.5 root 4940: break;
1.1.1.7 root 4941: case 0x22: /* ldqf, load quad fpreg */
1.1.1.6 root 4942: {
4943: TCGv_i32 r_const;
4944:
4945: CHECK_FPU_FEATURE(dc, FLOAT128);
4946: r_const = tcg_const_i32(dc->mem_idx);
1.1.1.9 root 4947: gen_address_mask(dc, cpu_addr);
1.1.1.13! root 4948: gen_helper_ldqf(cpu_env, cpu_addr, r_const);
1.1.1.6 root 4949: tcg_temp_free_i32(r_const);
4950: gen_op_store_QT0_fpr(QFPREG(rd));
1.1.1.12 root 4951: gen_update_fprs_dirty(QFPREG(rd));
1.1.1.6 root 4952: }
1.1.1.5 root 4953: break;
1.1.1.7 root 4954: case 0x23: /* lddf, load double fpreg */
1.1.1.12 root 4955: gen_address_mask(dc, cpu_addr);
4956: cpu_dst_64 = gen_dest_fpr_D();
4957: tcg_gen_qemu_ld64(cpu_dst_64, cpu_addr, dc->mem_idx);
4958: gen_store_fpr_D(dc, rd, cpu_dst_64);
1.1.1.5 root 4959: break;
4960: default:
4961: goto illegal_insn;
4962: }
1.1.1.7 root 4963: } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) ||
1.1.1.5 root 4964: xop == 0xe || xop == 0x1e) {
1.1.1.6 root 4965: gen_movl_reg_TN(rd, cpu_val);
1.1.1.5 root 4966: switch (xop) {
1.1.1.7 root 4967: case 0x4: /* st, store word */
1.1.1.6 root 4968: gen_address_mask(dc, cpu_addr);
4969: tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
4970: break;
1.1.1.7 root 4971: case 0x5: /* stb, store byte */
1.1.1.6 root 4972: gen_address_mask(dc, cpu_addr);
4973: tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx);
4974: break;
1.1.1.7 root 4975: case 0x6: /* sth, store halfword */
1.1.1.6 root 4976: gen_address_mask(dc, cpu_addr);
4977: tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx);
1.1.1.5 root 4978: break;
1.1.1.7 root 4979: case 0x7: /* std, store double word */
1.1.1.5 root 4980: if (rd & 1)
4981: goto illegal_insn;
1.1.1.6 root 4982: else {
4983: TCGv_i32 r_const;
4984:
4985: save_state(dc, cpu_cond);
4986: gen_address_mask(dc, cpu_addr);
4987: r_const = tcg_const_i32(7);
1.1.1.13! root 4988: /* XXX remove alignment check */
! 4989: gen_helper_check_align(cpu_env, cpu_addr, r_const);
1.1.1.6 root 4990: tcg_temp_free_i32(r_const);
4991: gen_movl_reg_TN(rd + 1, cpu_tmp0);
4992: tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, cpu_val);
4993: tcg_gen_qemu_st64(cpu_tmp64, cpu_addr, dc->mem_idx);
4994: }
1.1.1.5 root 4995: break;
1.1 root 4996: #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
1.1.1.7 root 4997: case 0x14: /* sta, V9 stwa, store word alternate */
1.1 root 4998: #ifndef TARGET_SPARC64
1.1.1.5 root 4999: if (IS_IMM)
5000: goto illegal_insn;
5001: if (!supervisor(dc))
5002: goto priv_insn;
1.1 root 5003: #endif
1.1.1.6 root 5004: save_state(dc, cpu_cond);
5005: gen_st_asi(cpu_val, cpu_addr, insn, 4);
1.1.1.9 root 5006: dc->npc = DYNAMIC_PC;
1.1 root 5007: break;
1.1.1.7 root 5008: case 0x15: /* stba, store byte alternate */
1.1 root 5009: #ifndef TARGET_SPARC64
1.1.1.5 root 5010: if (IS_IMM)
5011: goto illegal_insn;
5012: if (!supervisor(dc))
5013: goto priv_insn;
1.1 root 5014: #endif
1.1.1.6 root 5015: save_state(dc, cpu_cond);
5016: gen_st_asi(cpu_val, cpu_addr, insn, 1);
1.1.1.9 root 5017: dc->npc = DYNAMIC_PC;
1.1 root 5018: break;
1.1.1.7 root 5019: case 0x16: /* stha, store halfword alternate */
1.1 root 5020: #ifndef TARGET_SPARC64
1.1.1.5 root 5021: if (IS_IMM)
5022: goto illegal_insn;
5023: if (!supervisor(dc))
5024: goto priv_insn;
1.1 root 5025: #endif
1.1.1.6 root 5026: save_state(dc, cpu_cond);
5027: gen_st_asi(cpu_val, cpu_addr, insn, 2);
1.1.1.9 root 5028: dc->npc = DYNAMIC_PC;
1.1 root 5029: break;
1.1.1.7 root 5030: case 0x17: /* stda, store double word alternate */
1.1 root 5031: #ifndef TARGET_SPARC64
1.1.1.5 root 5032: if (IS_IMM)
5033: goto illegal_insn;
5034: if (!supervisor(dc))
5035: goto priv_insn;
1.1 root 5036: #endif
1.1.1.5 root 5037: if (rd & 1)
5038: goto illegal_insn;
1.1.1.6 root 5039: else {
5040: save_state(dc, cpu_cond);
5041: gen_stda_asi(cpu_val, cpu_addr, insn, rd);
5042: }
1.1 root 5043: break;
5044: #endif
5045: #ifdef TARGET_SPARC64
1.1.1.5 root 5046: case 0x0e: /* V9 stx */
1.1.1.6 root 5047: gen_address_mask(dc, cpu_addr);
5048: tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx);
1.1.1.5 root 5049: break;
5050: case 0x1e: /* V9 stxa */
1.1.1.6 root 5051: save_state(dc, cpu_cond);
5052: gen_st_asi(cpu_val, cpu_addr, insn, 8);
1.1.1.9 root 5053: dc->npc = DYNAMIC_PC;
1.1.1.5 root 5054: break;
5055: #endif
5056: default:
5057: goto illegal_insn;
5058: }
5059: } else if (xop > 0x23 && xop < 0x28) {
1.1.1.6 root 5060: if (gen_trap_ifnofpu(dc, cpu_cond))
1.1.1.3 root 5061: goto jmp_insn;
1.1.1.6 root 5062: save_state(dc, cpu_cond);
1.1.1.5 root 5063: switch (xop) {
1.1.1.7 root 5064: case 0x24: /* stf, store fpreg */
1.1.1.6 root 5065: gen_address_mask(dc, cpu_addr);
1.1.1.12 root 5066: cpu_src1_32 = gen_load_fpr_F(dc, rd);
5067: tcg_gen_ext_i32_tl(cpu_tmp0, cpu_src1_32);
1.1.1.6 root 5068: tcg_gen_qemu_st32(cpu_tmp0, cpu_addr, dc->mem_idx);
1.1.1.5 root 5069: break;
5070: case 0x25: /* stfsr, V9 stxfsr */
1.1.1.6 root 5071: #ifdef TARGET_SPARC64
5072: gen_address_mask(dc, cpu_addr);
1.1.1.13! root 5073: tcg_gen_ld_i64(cpu_tmp64, cpu_env, offsetof(CPUSPARCState, fsr));
1.1.1.6 root 5074: if (rd == 1)
5075: tcg_gen_qemu_st64(cpu_tmp64, cpu_addr, dc->mem_idx);
5076: else
5077: tcg_gen_qemu_st32(cpu_tmp64, cpu_addr, dc->mem_idx);
5078: #else
1.1.1.13! root 5079: tcg_gen_ld_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, fsr));
1.1.1.6 root 5080: tcg_gen_qemu_st32(cpu_tmp32, cpu_addr, dc->mem_idx);
1.1.1.5 root 5081: #endif
5082: break;
5083: case 0x26:
5084: #ifdef TARGET_SPARC64
5085: /* V9 stqf, store quad fpreg */
1.1.1.6 root 5086: {
5087: TCGv_i32 r_const;
5088:
5089: CHECK_FPU_FEATURE(dc, FLOAT128);
5090: gen_op_load_fpr_QT0(QFPREG(rd));
5091: r_const = tcg_const_i32(dc->mem_idx);
1.1.1.9 root 5092: gen_address_mask(dc, cpu_addr);
1.1.1.13! root 5093: gen_helper_stqf(cpu_env, cpu_addr, r_const);
1.1.1.6 root 5094: tcg_temp_free_i32(r_const);
5095: }
1.1.1.5 root 5096: break;
5097: #else /* !TARGET_SPARC64 */
5098: /* stdfq, store floating point queue */
5099: #if defined(CONFIG_USER_ONLY)
5100: goto illegal_insn;
5101: #else
5102: if (!supervisor(dc))
5103: goto priv_insn;
1.1.1.6 root 5104: if (gen_trap_ifnofpu(dc, cpu_cond))
1.1.1.5 root 5105: goto jmp_insn;
5106: goto nfq_insn;
5107: #endif
5108: #endif
1.1.1.7 root 5109: case 0x27: /* stdf, store double fpreg */
1.1.1.12 root 5110: gen_address_mask(dc, cpu_addr);
5111: cpu_src1_64 = gen_load_fpr_D(dc, rd);
5112: tcg_gen_qemu_st64(cpu_src1_64, cpu_addr, dc->mem_idx);
1.1.1.5 root 5113: break;
5114: default:
5115: goto illegal_insn;
5116: }
5117: } else if (xop > 0x33 && xop < 0x3f) {
1.1.1.6 root 5118: save_state(dc, cpu_cond);
1.1.1.5 root 5119: switch (xop) {
5120: #ifdef TARGET_SPARC64
5121: case 0x34: /* V9 stfa */
1.1.1.11 root 5122: if (gen_trap_ifnofpu(dc, cpu_cond)) {
5123: goto jmp_insn;
5124: }
1.1.1.6 root 5125: gen_stf_asi(cpu_addr, insn, 4, rd);
1.1.1.5 root 5126: break;
5127: case 0x36: /* V9 stqfa */
1.1.1.6 root 5128: {
5129: TCGv_i32 r_const;
5130:
5131: CHECK_FPU_FEATURE(dc, FLOAT128);
1.1.1.11 root 5132: if (gen_trap_ifnofpu(dc, cpu_cond)) {
5133: goto jmp_insn;
5134: }
1.1.1.6 root 5135: r_const = tcg_const_i32(7);
1.1.1.13! root 5136: gen_helper_check_align(cpu_env, cpu_addr, r_const);
1.1.1.6 root 5137: tcg_temp_free_i32(r_const);
5138: gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd));
5139: }
1.1.1.5 root 5140: break;
5141: case 0x37: /* V9 stdfa */
1.1.1.11 root 5142: if (gen_trap_ifnofpu(dc, cpu_cond)) {
5143: goto jmp_insn;
5144: }
1.1.1.6 root 5145: gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd));
1.1.1.5 root 5146: break;
5147: case 0x3c: /* V9 casa */
1.1.1.6 root 5148: gen_cas_asi(cpu_val, cpu_addr, cpu_src2, insn, rd);
5149: gen_movl_TN_reg(rd, cpu_val);
1.1.1.5 root 5150: break;
5151: case 0x3e: /* V9 casxa */
1.1.1.6 root 5152: gen_casx_asi(cpu_val, cpu_addr, cpu_src2, insn, rd);
5153: gen_movl_TN_reg(rd, cpu_val);
1.1.1.5 root 5154: break;
1.1 root 5155: #else
1.1.1.5 root 5156: case 0x34: /* stc */
5157: case 0x35: /* stcsr */
5158: case 0x36: /* stdcq */
5159: case 0x37: /* stdc */
5160: goto ncp_insn;
1.1 root 5161: #endif
1.1.1.5 root 5162: default:
5163: goto illegal_insn;
5164: }
1.1.1.7 root 5165: } else
1.1.1.5 root 5166: goto illegal_insn;
5167: }
5168: break;
1.1 root 5169: }
5170: /* default case for non jump instructions */
5171: if (dc->npc == DYNAMIC_PC) {
1.1.1.5 root 5172: dc->pc = DYNAMIC_PC;
5173: gen_op_next_insn();
1.1 root 5174: } else if (dc->npc == JUMP_PC) {
5175: /* we can do a static jump */
1.1.1.6 root 5176: gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
1.1 root 5177: dc->is_br = 1;
5178: } else {
1.1.1.5 root 5179: dc->pc = dc->npc;
5180: dc->npc = dc->npc + 4;
1.1 root 5181: }
5182: jmp_insn:
1.1.1.9 root 5183: goto egress;
1.1 root 5184: illegal_insn:
1.1.1.6 root 5185: {
5186: TCGv_i32 r_const;
5187:
5188: save_state(dc, cpu_cond);
5189: r_const = tcg_const_i32(TT_ILL_INSN);
1.1.1.12 root 5190: gen_helper_raise_exception(cpu_env, r_const);
1.1.1.6 root 5191: tcg_temp_free_i32(r_const);
5192: dc->is_br = 1;
5193: }
1.1.1.9 root 5194: goto egress;
1.1.1.6 root 5195: unimp_flush:
5196: {
5197: TCGv_i32 r_const;
5198:
5199: save_state(dc, cpu_cond);
5200: r_const = tcg_const_i32(TT_UNIMP_FLUSH);
1.1.1.12 root 5201: gen_helper_raise_exception(cpu_env, r_const);
1.1.1.6 root 5202: tcg_temp_free_i32(r_const);
5203: dc->is_br = 1;
5204: }
1.1.1.9 root 5205: goto egress;
1.1 root 5206: #if !defined(CONFIG_USER_ONLY)
5207: priv_insn:
1.1.1.6 root 5208: {
5209: TCGv_i32 r_const;
5210:
5211: save_state(dc, cpu_cond);
5212: r_const = tcg_const_i32(TT_PRIV_INSN);
1.1.1.12 root 5213: gen_helper_raise_exception(cpu_env, r_const);
1.1.1.6 root 5214: tcg_temp_free_i32(r_const);
5215: dc->is_br = 1;
5216: }
1.1.1.9 root 5217: goto egress;
1.1.1.6 root 5218: #endif
1.1 root 5219: nfpu_insn:
1.1.1.6 root 5220: save_state(dc, cpu_cond);
1.1 root 5221: gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
5222: dc->is_br = 1;
1.1.1.9 root 5223: goto egress;
1.1.1.6 root 5224: #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
1.1.1.5 root 5225: nfq_insn:
1.1.1.6 root 5226: save_state(dc, cpu_cond);
1.1.1.5 root 5227: gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
5228: dc->is_br = 1;
1.1.1.9 root 5229: goto egress;
1.1.1.5 root 5230: #endif
5231: #ifndef TARGET_SPARC64
5232: ncp_insn:
1.1.1.6 root 5233: {
5234: TCGv r_const;
5235:
5236: save_state(dc, cpu_cond);
5237: r_const = tcg_const_i32(TT_NCP_INSN);
1.1.1.12 root 5238: gen_helper_raise_exception(cpu_env, r_const);
1.1.1.6 root 5239: tcg_temp_free(r_const);
5240: dc->is_br = 1;
5241: }
1.1.1.9 root 5242: goto egress;
1.1.1.5 root 5243: #endif
1.1.1.9 root 5244: egress:
5245: tcg_temp_free(cpu_tmp1);
5246: tcg_temp_free(cpu_tmp2);
1.1.1.12 root 5247: if (dc->n_t32 != 0) {
5248: int i;
5249: for (i = dc->n_t32 - 1; i >= 0; --i) {
5250: tcg_temp_free_i32(dc->t32[i]);
5251: }
5252: dc->n_t32 = 0;
5253: }
1.1 root 5254: }
5255:
1.1.1.6 root 5256: static inline void gen_intermediate_code_internal(TranslationBlock * tb,
5257: int spc, CPUSPARCState *env)
1.1 root 5258: {
5259: target_ulong pc_start, last_pc;
5260: uint16_t *gen_opc_end;
5261: DisasContext dc1, *dc = &dc1;
1.1.1.6 root 5262: CPUBreakpoint *bp;
1.1 root 5263: int j, lj = -1;
1.1.1.6 root 5264: int num_insns;
5265: int max_insns;
1.1.1.13! root 5266: unsigned int insn;
1.1 root 5267:
5268: memset(dc, 0, sizeof(DisasContext));
5269: dc->tb = tb;
5270: pc_start = tb->pc;
5271: dc->pc = pc_start;
5272: last_pc = dc->pc;
5273: dc->npc = (target_ulong) tb->cs_base;
1.1.1.7 root 5274: dc->cc_op = CC_OP_DYNAMIC;
1.1.1.5 root 5275: dc->mem_idx = cpu_mmu_index(env);
1.1.1.6 root 5276: dc->def = env->def;
1.1.1.11 root 5277: dc->fpu_enabled = tb_fpu_enabled(tb->flags);
5278: dc->address_mask_32bit = tb_am_enabled(tb->flags);
1.1.1.9 root 5279: dc->singlestep = (env->singlestep_enabled || singlestep);
1.1 root 5280: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
5281:
1.1.1.6 root 5282: cpu_tmp0 = tcg_temp_new();
5283: cpu_tmp32 = tcg_temp_new_i32();
5284: cpu_tmp64 = tcg_temp_new_i64();
5285:
5286: cpu_dst = tcg_temp_local_new();
5287:
5288: // loads and stores
5289: cpu_val = tcg_temp_local_new();
5290: cpu_addr = tcg_temp_local_new();
5291:
5292: num_insns = 0;
5293: max_insns = tb->cflags & CF_COUNT_MASK;
5294: if (max_insns == 0)
5295: max_insns = CF_COUNT_MASK;
5296: gen_icount_start();
1.1 root 5297: do {
1.1.1.8 root 5298: if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
5299: QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1.1.1.6 root 5300: if (bp->pc == dc->pc) {
1.1.1.5 root 5301: if (dc->pc != pc_start)
1.1.1.6 root 5302: save_state(dc, cpu_cond);
1.1.1.12 root 5303: gen_helper_debug(cpu_env);
1.1.1.6 root 5304: tcg_gen_exit_tb(0);
1.1.1.5 root 5305: dc->is_br = 1;
1.1 root 5306: goto exit_gen_loop;
5307: }
5308: }
5309: }
5310: if (spc) {
1.1.1.6 root 5311: qemu_log("Search PC...\n");
1.1 root 5312: j = gen_opc_ptr - gen_opc_buf;
5313: if (lj < j) {
5314: lj++;
5315: while (lj < j)
5316: gen_opc_instr_start[lj++] = 0;
5317: gen_opc_pc[lj] = dc->pc;
5318: gen_opc_npc[lj] = dc->npc;
5319: gen_opc_instr_start[lj] = 1;
1.1.1.6 root 5320: gen_opc_icount[lj] = num_insns;
1.1 root 5321: }
5322: }
1.1.1.6 root 5323: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
5324: gen_io_start();
1.1.1.5 root 5325: last_pc = dc->pc;
1.1.1.13! root 5326: insn = cpu_ldl_code(env, dc->pc);
! 5327: disas_sparc_insn(dc, insn);
1.1.1.6 root 5328: num_insns++;
1.1 root 5329:
1.1.1.5 root 5330: if (dc->is_br)
5331: break;
5332: /* if the next PC is different, we abort now */
5333: if (dc->pc != (last_pc + 4))
5334: break;
1.1 root 5335: /* if we reach a page boundary, we stop generation so that the
5336: PC of a TT_TFAULT exception is always in the right page */
5337: if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
5338: break;
5339: /* if single step mode, we generate only one instruction and
5340: generate an exception */
1.1.1.9 root 5341: if (dc->singlestep) {
1.1 root 5342: break;
5343: }
5344: } while ((gen_opc_ptr < gen_opc_end) &&
1.1.1.6 root 5345: (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) &&
5346: num_insns < max_insns);
1.1 root 5347:
5348: exit_gen_loop:
1.1.1.6 root 5349: tcg_temp_free(cpu_addr);
5350: tcg_temp_free(cpu_val);
5351: tcg_temp_free(cpu_dst);
5352: tcg_temp_free_i64(cpu_tmp64);
5353: tcg_temp_free_i32(cpu_tmp32);
5354: tcg_temp_free(cpu_tmp0);
1.1.1.12 root 5355:
1.1.1.6 root 5356: if (tb->cflags & CF_LAST_IO)
5357: gen_io_end();
1.1 root 5358: if (!dc->is_br) {
1.1.1.5 root 5359: if (dc->pc != DYNAMIC_PC &&
1.1 root 5360: (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
5361: /* static PC and NPC: we can use direct chaining */
1.1.1.6 root 5362: gen_goto_tb(dc, 0, dc->pc, dc->npc);
1.1 root 5363: } else {
5364: if (dc->pc != DYNAMIC_PC)
1.1.1.6 root 5365: tcg_gen_movi_tl(cpu_pc, dc->pc);
5366: save_npc(dc, cpu_cond);
5367: tcg_gen_exit_tb(0);
1.1 root 5368: }
5369: }
1.1.1.6 root 5370: gen_icount_end(tb, num_insns);
1.1 root 5371: *gen_opc_ptr = INDEX_op_end;
5372: if (spc) {
5373: j = gen_opc_ptr - gen_opc_buf;
5374: lj++;
5375: while (lj <= j)
5376: gen_opc_instr_start[lj++] = 0;
5377: #if 0
1.1.1.6 root 5378: log_page_dump();
1.1 root 5379: #endif
5380: gen_opc_jump_pc[0] = dc->jump_pc[0];
5381: gen_opc_jump_pc[1] = dc->jump_pc[1];
5382: } else {
5383: tb->size = last_pc + 4 - pc_start;
1.1.1.6 root 5384: tb->icount = num_insns;
1.1 root 5385: }
5386: #ifdef DEBUG_DISAS
1.1.1.6 root 5387: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
5388: qemu_log("--------------\n");
5389: qemu_log("IN: %s\n", lookup_symbol(pc_start));
5390: log_target_disas(pc_start, last_pc + 4 - pc_start, 0);
5391: qemu_log("\n");
1.1 root 5392: }
5393: #endif
5394: }
5395:
1.1.1.6 root 5396: void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
1.1 root 5397: {
1.1.1.6 root 5398: gen_intermediate_code_internal(tb, 0, env);
1.1 root 5399: }
5400:
1.1.1.6 root 5401: void gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
1.1 root 5402: {
1.1.1.6 root 5403: gen_intermediate_code_internal(tb, 1, env);
1.1.1.5 root 5404: }
5405:
1.1.1.6 root 5406: void gen_intermediate_code_init(CPUSPARCState *env)
1.1.1.5 root 5407: {
1.1.1.6 root 5408: unsigned int i;
5409: static int inited;
5410: static const char * const gregnames[8] = {
5411: NULL, // g0 not used
5412: "g1",
5413: "g2",
5414: "g3",
5415: "g4",
5416: "g5",
5417: "g6",
5418: "g7",
5419: };
1.1.1.12 root 5420: static const char * const fregnames[32] = {
5421: "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
5422: "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
5423: "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
5424: "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
1.1.1.6 root 5425: };
1.1.1.5 root 5426:
1.1.1.6 root 5427: /* init various static tables */
5428: if (!inited) {
5429: inited = 1;
5430:
5431: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
5432: cpu_regwptr = tcg_global_mem_new_ptr(TCG_AREG0,
1.1.1.13! root 5433: offsetof(CPUSPARCState, regwptr),
1.1.1.6 root 5434: "regwptr");
5435: #ifdef TARGET_SPARC64
1.1.1.13! root 5436: cpu_xcc = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, xcc),
1.1.1.6 root 5437: "xcc");
1.1.1.13! root 5438: cpu_asi = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, asi),
1.1.1.6 root 5439: "asi");
1.1.1.13! root 5440: cpu_fprs = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, fprs),
1.1.1.6 root 5441: "fprs");
1.1.1.13! root 5442: cpu_gsr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, gsr),
1.1.1.6 root 5443: "gsr");
5444: cpu_tick_cmpr = tcg_global_mem_new(TCG_AREG0,
1.1.1.13! root 5445: offsetof(CPUSPARCState, tick_cmpr),
1.1.1.6 root 5446: "tick_cmpr");
5447: cpu_stick_cmpr = tcg_global_mem_new(TCG_AREG0,
1.1.1.13! root 5448: offsetof(CPUSPARCState, stick_cmpr),
1.1.1.6 root 5449: "stick_cmpr");
5450: cpu_hstick_cmpr = tcg_global_mem_new(TCG_AREG0,
1.1.1.13! root 5451: offsetof(CPUSPARCState, hstick_cmpr),
1.1.1.6 root 5452: "hstick_cmpr");
1.1.1.13! root 5453: cpu_hintp = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, hintp),
1.1.1.6 root 5454: "hintp");
1.1.1.13! root 5455: cpu_htba = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, htba),
1.1.1.6 root 5456: "htba");
1.1.1.13! root 5457: cpu_hver = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, hver),
1.1.1.6 root 5458: "hver");
5459: cpu_ssr = tcg_global_mem_new(TCG_AREG0,
1.1.1.13! root 5460: offsetof(CPUSPARCState, ssr), "ssr");
1.1.1.6 root 5461: cpu_ver = tcg_global_mem_new(TCG_AREG0,
1.1.1.13! root 5462: offsetof(CPUSPARCState, version), "ver");
1.1.1.6 root 5463: cpu_softint = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.13! root 5464: offsetof(CPUSPARCState, softint),
1.1.1.6 root 5465: "softint");
5466: #else
1.1.1.13! root 5467: cpu_wim = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, wim),
1.1.1.6 root 5468: "wim");
5469: #endif
1.1.1.13! root 5470: cpu_cond = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, cond),
1.1.1.6 root 5471: "cond");
1.1.1.13! root 5472: cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, cc_src),
1.1.1.6 root 5473: "cc_src");
5474: cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0,
1.1.1.13! root 5475: offsetof(CPUSPARCState, cc_src2),
1.1.1.6 root 5476: "cc_src2");
1.1.1.13! root 5477: cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, cc_dst),
1.1.1.6 root 5478: "cc_dst");
1.1.1.13! root 5479: cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, cc_op),
1.1.1.7 root 5480: "cc_op");
1.1.1.13! root 5481: cpu_psr = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUSPARCState, psr),
1.1.1.6 root 5482: "psr");
1.1.1.13! root 5483: cpu_fsr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, fsr),
1.1.1.6 root 5484: "fsr");
1.1.1.13! root 5485: cpu_pc = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, pc),
1.1.1.6 root 5486: "pc");
1.1.1.13! root 5487: cpu_npc = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, npc),
1.1.1.6 root 5488: "npc");
1.1.1.13! root 5489: cpu_y = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, y), "y");
1.1.1.6 root 5490: #ifndef CONFIG_USER_ONLY
1.1.1.13! root 5491: cpu_tbr = tcg_global_mem_new(TCG_AREG0, offsetof(CPUSPARCState, tbr),
1.1.1.6 root 5492: "tbr");
1.1.1.5 root 5493: #endif
1.1.1.12 root 5494: for (i = 1; i < 8; i++) {
1.1.1.6 root 5495: cpu_gregs[i] = tcg_global_mem_new(TCG_AREG0,
1.1.1.13! root 5496: offsetof(CPUSPARCState, gregs[i]),
1.1.1.6 root 5497: gregnames[i]);
1.1.1.12 root 5498: }
5499: for (i = 0; i < TARGET_DPREGS; i++) {
5500: cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
1.1.1.13! root 5501: offsetof(CPUSPARCState, fpr[i]),
1.1.1.6 root 5502: fregnames[i]);
1.1.1.12 root 5503: }
1.1.1.5 root 5504:
1.1.1.6 root 5505: /* register helpers */
1.1.1.5 root 5506:
1.1.1.6 root 5507: #define GEN_HELPER 2
5508: #include "helper.h"
1.1.1.5 root 5509: }
5510: }
5511:
1.1.1.13! root 5512: void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb, int pc_pos)
1.1.1.5 root 5513: {
1.1.1.6 root 5514: target_ulong npc;
5515: env->pc = gen_opc_pc[pc_pos];
5516: npc = gen_opc_npc[pc_pos];
5517: if (npc == 1) {
5518: /* dynamic NPC: already stored */
5519: } else if (npc == 2) {
1.1.1.9 root 5520: /* jump PC: use 'cond' and the jump targets of the translation */
5521: if (env->cond) {
1.1.1.6 root 5522: env->npc = gen_opc_jump_pc[0];
1.1.1.9 root 5523: } else {
1.1.1.6 root 5524: env->npc = gen_opc_jump_pc[1];
1.1.1.9 root 5525: }
1.1.1.6 root 5526: } else {
5527: env->npc = npc;
1.1 root 5528: }
1.1.1.7 root 5529:
5530: /* flush pending conditional evaluations before exposing cpu state */
5531: if (CC_OP != CC_OP_FLAGS) {
1.1.1.12 root 5532: helper_compute_psr(env);
1.1.1.7 root 5533: }
1.1 root 5534: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.