diff options
Diffstat (limited to 'target-sparc/op.c')
-rw-r--r-- | target-sparc/op.c | 826 |
1 files changed, 710 insertions, 116 deletions
diff --git a/target-sparc/op.c b/target-sparc/op.c index 281917a7f1..86c45c7093 100644 --- a/target-sparc/op.c +++ b/target-sparc/op.c @@ -46,76 +46,76 @@ #define REG (env->gregs[7]) #include "op_template.h" #define REGNAME i0 -#define REG (env->regwptr[16]) +#define REG (REGWPTR[16]) #include "op_template.h" #define REGNAME i1 -#define REG (env->regwptr[17]) +#define REG (REGWPTR[17]) #include "op_template.h" #define REGNAME i2 -#define REG (env->regwptr[18]) +#define REG (REGWPTR[18]) #include "op_template.h" #define REGNAME i3 -#define REG (env->regwptr[19]) +#define REG (REGWPTR[19]) #include "op_template.h" #define REGNAME i4 -#define REG (env->regwptr[20]) +#define REG (REGWPTR[20]) #include "op_template.h" #define REGNAME i5 -#define REG (env->regwptr[21]) +#define REG (REGWPTR[21]) #include "op_template.h" #define REGNAME i6 -#define REG (env->regwptr[22]) +#define REG (REGWPTR[22]) #include "op_template.h" #define REGNAME i7 -#define REG (env->regwptr[23]) +#define REG (REGWPTR[23]) #include "op_template.h" #define REGNAME l0 -#define REG (env->regwptr[8]) +#define REG (REGWPTR[8]) #include "op_template.h" #define REGNAME l1 -#define REG (env->regwptr[9]) +#define REG (REGWPTR[9]) #include "op_template.h" #define REGNAME l2 -#define REG (env->regwptr[10]) +#define REG (REGWPTR[10]) #include "op_template.h" #define REGNAME l3 -#define REG (env->regwptr[11]) +#define REG (REGWPTR[11]) #include "op_template.h" #define REGNAME l4 -#define REG (env->regwptr[12]) +#define REG (REGWPTR[12]) #include "op_template.h" #define REGNAME l5 -#define REG (env->regwptr[13]) +#define REG (REGWPTR[13]) #include "op_template.h" #define REGNAME l6 -#define REG (env->regwptr[14]) +#define REG (REGWPTR[14]) #include "op_template.h" #define REGNAME l7 -#define REG (env->regwptr[15]) +#define REG (REGWPTR[15]) #include "op_template.h" #define REGNAME o0 -#define REG (env->regwptr[0]) +#define REG (REGWPTR[0]) #include "op_template.h" #define REGNAME o1 -#define REG (env->regwptr[1]) +#define REG (REGWPTR[1]) #include "op_template.h" #define REGNAME o2 -#define REG (env->regwptr[2]) +#define REG (REGWPTR[2]) #include "op_template.h" #define REGNAME o3 -#define REG (env->regwptr[3]) +#define REG (REGWPTR[3]) #include "op_template.h" #define REGNAME o4 -#define REG (env->regwptr[4]) +#define REG (REGWPTR[4]) #include "op_template.h" #define REGNAME o5 -#define REG (env->regwptr[5]) +#define REG (REGWPTR[5]) #include "op_template.h" #define REGNAME o6 -#define REG (env->regwptr[6]) +#define REG (REGWPTR[6]) #include "op_template.h" #define REGNAME o7 -#define REG (env->regwptr[7]) +#define REG (REGWPTR[7]) #include "op_template.h" #define REGNAME f0 @@ -215,10 +215,106 @@ #define REG (env->fpr[31]) #include "fop_template.h" +#ifdef TARGET_SPARC64 +#define REGNAME f32 +#define REG (env->fpr[32]) +#include "fop_template.h" +#define REGNAME f34 +#define REG (env->fpr[34]) +#include "fop_template.h" +#define REGNAME f36 +#define REG (env->fpr[36]) +#include "fop_template.h" +#define REGNAME f38 +#define REG (env->fpr[38]) +#include "fop_template.h" +#define REGNAME f40 +#define REG (env->fpr[40]) +#include "fop_template.h" +#define REGNAME f42 +#define REG (env->fpr[42]) +#include "fop_template.h" +#define REGNAME f44 +#define REG (env->fpr[44]) +#include "fop_template.h" +#define REGNAME f46 +#define REG (env->fpr[46]) +#include "fop_template.h" +#define REGNAME f48 +#define REG (env->fpr[47]) +#include "fop_template.h" +#define REGNAME f50 +#define REG (env->fpr[50]) +#include "fop_template.h" +#define REGNAME f52 +#define REG (env->fpr[52]) +#include "fop_template.h" +#define REGNAME f54 +#define REG (env->fpr[54]) +#include "fop_template.h" +#define REGNAME f56 +#define REG (env->fpr[56]) +#include "fop_template.h" +#define REGNAME f58 +#define REG (env->fpr[58]) +#include "fop_template.h" +#define REGNAME f60 +#define REG (env->fpr[60]) +#include "fop_template.h" +#define REGNAME f62 +#define REG (env->fpr[62]) +#include "fop_template.h" +#endif + +#ifdef TARGET_SPARC64 +#undef JUMP_TB +#define JUMP_TB(opname, tbparam, n, eip) \ + do { \ + GOTO_TB(opname, tbparam, n); \ + T0 = (long)(tbparam) + (n); \ + env->pc = (eip) & 0xffffffff; \ + EXIT_TB(); \ + } while (0) + +#ifdef WORDS_BIGENDIAN +typedef union UREG64 { + struct { uint16_t v3, v2, v1, v0; } w; + struct { uint32_t v1, v0; } l; + uint64_t q; +} UREG64; +#else +typedef union UREG64 { + struct { uint16_t v0, v1, v2, v3; } w; + struct { uint32_t v0, v1; } l; + uint64_t q; +} UREG64; +#endif + +#define PARAMQ1 \ +({\ + UREG64 __p;\ + __p.l.v1 = PARAM1;\ + __p.l.v0 = PARAM2;\ + __p.q;\ +}) + +void OPPROTO op_movq_T0_im64(void) +{ + T0 = PARAMQ1; +} + +void OPPROTO op_movq_T1_im64(void) +{ + T1 = PARAMQ1; +} + +#define XFLAG_SET(x) ((env->xcc&x)?1:0) + +#else #define EIP (env->pc) +#endif #define FLAG_SET(x) ((env->psr&x)?1:0) -#define FFLAG_SET(x) ((env->fsr&x)?1:0) void OPPROTO op_movl_T0_0(void) { @@ -227,17 +323,52 @@ void OPPROTO op_movl_T0_0(void) void OPPROTO op_movl_T0_im(void) { - T0 = PARAM1; + T0 = (uint32_t)PARAM1; } void OPPROTO op_movl_T1_im(void) { - T1 = PARAM1; + T1 = (uint32_t)PARAM1; } void OPPROTO op_movl_T2_im(void) { - T2 = PARAM1; + T2 = (uint32_t)PARAM1; +} + +void OPPROTO op_movl_T0_sim(void) +{ + T0 = (int32_t)PARAM1; +} + +void OPPROTO op_movl_T1_sim(void) +{ + T1 = (int32_t)PARAM1; +} + +void OPPROTO op_movl_T2_sim(void) +{ + T2 = (int32_t)PARAM1; +} + +void OPPROTO op_movl_T0_env(void) +{ + T0 = *(uint32_t *)((char *)env + PARAM1); +} + +void OPPROTO op_movl_env_T0(void) +{ + *(uint32_t *)((char *)env + PARAM1) = T0; +} + +void OPPROTO op_movtl_T0_env(void) +{ + T0 = *(target_ulong *)((char *)env + PARAM1); +} + +void OPPROTO op_movtl_env_T0(void) +{ + *(target_ulong *)((char *)env + PARAM1) = T0; } void OPPROTO op_add_T1_T0(void) @@ -252,6 +383,27 @@ void OPPROTO op_add_T1_T0_cc(void) src1 = T0; T0 += T1; env->psr = 0; +#ifdef TARGET_SPARC64 + if (!(T0 & 0xffffffff)) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + if ((T0 & 0xffffffff) < (src1 & 0xffffffff)) + env->psr |= PSR_CARRY; + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) & + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) + env->psr |= PSR_OVF; + + env->xcc = 0; + if (!T0) + env->xcc |= PSR_ZERO; + if ((int64_t) T0 < 0) + env->xcc |= PSR_NEG; + if (T0 < src1) + env->xcc |= PSR_CARRY; + if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63)) + env->xcc |= PSR_OVF; +#else if (!T0) env->psr |= PSR_ZERO; if ((int32_t) T0 < 0) @@ -260,7 +412,7 @@ void OPPROTO op_add_T1_T0_cc(void) env->psr |= PSR_CARRY; if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31)) env->psr |= PSR_OVF; - /* V9 xcc */ +#endif FORCE_RET(); } @@ -276,6 +428,27 @@ void OPPROTO op_addx_T1_T0_cc(void) src1 = T0; T0 += T1 + FLAG_SET(PSR_CARRY); env->psr = 0; +#ifdef TARGET_SPARC64 + if (!(T0 & 0xffffffff)) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + if ((T0 & 0xffffffff) < (src1 & 0xffffffff)) + env->psr |= PSR_CARRY; + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) & + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) + env->psr |= PSR_OVF; + + env->xcc = 0; + if (!T0) + env->xcc |= PSR_ZERO; + if ((int64_t) T0 < 0) + env->xcc |= PSR_NEG; + if (T0 < src1) + env->xcc |= PSR_CARRY; + if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63)) + env->xcc |= PSR_OVF; +#else if (!T0) env->psr |= PSR_ZERO; if ((int32_t) T0 < 0) @@ -284,7 +457,7 @@ void OPPROTO op_addx_T1_T0_cc(void) env->psr |= PSR_CARRY; if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31)) env->psr |= PSR_OVF; - /* V9 xcc */ +#endif FORCE_RET(); } @@ -300,6 +473,27 @@ void OPPROTO op_sub_T1_T0_cc(void) src1 = T0; T0 -= T1; env->psr = 0; +#ifdef TARGET_SPARC64 + if (!(T0 & 0xffffffff)) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + if ((T0 & 0xffffffff) < (src1 & 0xffffffff)) + env->psr |= PSR_CARRY; + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) & + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) + env->psr |= PSR_OVF; + + env->xcc = 0; + if (!T0) + env->xcc |= PSR_ZERO; + if ((int64_t) T0 < 0) + env->xcc |= PSR_NEG; + if (T0 < src1) + env->xcc |= PSR_CARRY; + if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63)) + env->xcc |= PSR_OVF; +#else if (!T0) env->psr |= PSR_ZERO; if ((int32_t) T0 < 0) @@ -308,7 +502,7 @@ void OPPROTO op_sub_T1_T0_cc(void) env->psr |= PSR_CARRY; if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31)) env->psr |= PSR_OVF; - /* V9 xcc */ +#endif FORCE_RET(); } @@ -324,6 +518,27 @@ void OPPROTO op_subx_T1_T0_cc(void) src1 = T0; T0 -= T1 + FLAG_SET(PSR_CARRY); env->psr = 0; +#ifdef TARGET_SPARC64 + if (!(T0 & 0xffffffff)) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + if ((T0 & 0xffffffff) < (src1 & 0xffffffff)) + env->psr |= PSR_CARRY; + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) & + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) + env->psr |= PSR_OVF; + + env->xcc = 0; + if (!T0) + env->xcc |= PSR_ZERO; + if ((int64_t) T0 < 0) + env->xcc |= PSR_NEG; + if (T0 < src1) + env->xcc |= PSR_CARRY; + if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63)) + env->xcc |= PSR_OVF; +#else if (!T0) env->psr |= PSR_ZERO; if ((int32_t) T0 < 0) @@ -332,7 +547,7 @@ void OPPROTO op_subx_T1_T0_cc(void) env->psr |= PSR_CARRY; if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31)) env->psr |= PSR_OVF; - /* V9 xcc */ +#endif FORCE_RET(); } @@ -449,24 +664,73 @@ void OPPROTO op_sdiv_T1_T0(void) void OPPROTO op_div_cc(void) { env->psr = 0; +#ifdef TARGET_SPARC64 + if (!T0) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + if (T1) + env->psr |= PSR_OVF; + + env->xcc = 0; + if (!T0) + env->xcc |= PSR_ZERO; + if ((int64_t) T0 < 0) + env->xcc |= PSR_NEG; +#else if (!T0) env->psr |= PSR_ZERO; if ((int32_t) T0 < 0) env->psr |= PSR_NEG; if (T1) env->psr |= PSR_OVF; - /* V9 xcc */ +#endif FORCE_RET(); } +#ifdef TARGET_SPARC64 +void OPPROTO op_mulx_T1_T0(void) +{ + T0 *= T1; + FORCE_RET(); +} + +void OPPROTO op_udivx_T1_T0(void) +{ + T0 /= T1; + FORCE_RET(); +} + +void OPPROTO op_sdivx_T1_T0(void) +{ + if (T0 == INT64_MIN && T1 == -1) + T0 = INT64_MIN; + else + T0 /= (target_long) T1; + FORCE_RET(); +} +#endif + void OPPROTO op_logic_T0_cc(void) { env->psr = 0; +#ifdef TARGET_SPARC64 + if (!(T0 & 0xffffffff)) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + + env->xcc = 0; + if (!T0) + env->xcc |= PSR_ZERO; + if ((int64_t) T0 < 0) + env->xcc |= PSR_NEG; +#else if (!T0) env->psr |= PSR_ZERO; if ((int32_t) T0 < 0) env->psr |= PSR_NEG; - /* V9 xcc */ +#endif FORCE_RET(); } @@ -475,6 +739,27 @@ void OPPROTO op_sll(void) T0 <<= T1; } +#ifdef TARGET_SPARC64 +void OPPROTO op_srl(void) +{ + T0 = (T0 & 0xffffffff) >> T1; +} + +void OPPROTO op_srlx(void) +{ + T0 >>= T1; +} + +void OPPROTO op_sra(void) +{ + T0 = ((int32_t) (T0 & 0xffffffff)) >> T1; +} + +void OPPROTO op_srax(void) +{ + T0 = ((int64_t) T0) >> T1; +} +#else void OPPROTO op_srl(void) { T0 >>= T1; @@ -484,6 +769,7 @@ void OPPROTO op_sra(void) { T0 = ((int32_t) T0) >> T1; } +#endif /* Load and store */ #define MEMSUFFIX _raw @@ -498,62 +784,137 @@ void OPPROTO op_sra(void) void OPPROTO op_ldfsr(void) { - env->fsr = *((uint32_t *) &FT0); + PUT_FSR32(env, *((uint32_t *) &FT0)); helper_ldfsr(); } void OPPROTO op_stfsr(void) { - *((uint32_t *) &FT0) = env->fsr; + *((uint32_t *) &FT0) = GET_FSR32(env); } -void OPPROTO op_wry(void) +#ifndef TARGET_SPARC64 +void OPPROTO op_rdpsr(void) { - env->y = T0; + do_rdpsr(); } -void OPPROTO op_rdy(void) +void OPPROTO op_wrpsr(void) { - T0 = env->y; + do_wrpsr(); + FORCE_RET(); } -void OPPROTO op_rdwim(void) +void OPPROTO op_rett(void) { - T0 = env->wim; + helper_rett(); + FORCE_RET(); } -void OPPROTO op_wrwim(void) +/* XXX: use another pointer for %iN registers to avoid slow wrapping + handling ? */ +void OPPROTO op_save(void) { - env->wim = T0; + uint32_t cwp; + cwp = (env->cwp - 1) & (NWINDOWS - 1); + if (env->wim & (1 << cwp)) { + raise_exception(TT_WIN_OVF); + } + set_cwp(cwp); FORCE_RET(); } -void OPPROTO op_rdpsr(void) +void OPPROTO op_restore(void) { - do_rdpsr(); + uint32_t cwp; + cwp = (env->cwp + 1) & (NWINDOWS - 1); + if (env->wim & (1 << cwp)) { + raise_exception(TT_WIN_UNF); + } + set_cwp(cwp); + FORCE_RET(); +} +#else +void OPPROTO op_rdccr(void) +{ + T0 = GET_CCR(env); } -void OPPROTO op_wrpsr(void) +void OPPROTO op_wrccr(void) { - do_wrpsr(); - FORCE_RET(); + PUT_CCR(env, T0); } -void OPPROTO op_rdtbr(void) +void OPPROTO op_rdtick(void) { - T0 = env->tbr; + T0 = 0; // XXX read cycle counter and bit 31 } -void OPPROTO op_wrtbr(void) +void OPPROTO op_wrtick(void) { - env->tbr = T0; - FORCE_RET(); + // XXX write cycle counter and bit 31 } -void OPPROTO op_rett(void) +void OPPROTO op_rdtpc(void) { - helper_rett(); - FORCE_RET(); + T0 = env->tpc[env->tl]; +} + +void OPPROTO op_wrtpc(void) +{ + env->tpc[env->tl] = T0; +} + +void OPPROTO op_rdtnpc(void) +{ + T0 = env->tnpc[env->tl]; +} + +void OPPROTO op_wrtnpc(void) +{ + env->tnpc[env->tl] = T0; +} + +void OPPROTO op_rdtstate(void) +{ + T0 = env->tstate[env->tl]; +} + +void OPPROTO op_wrtstate(void) +{ + env->tstate[env->tl] = T0; +} + +void OPPROTO op_rdtt(void) +{ + T0 = env->tt[env->tl]; +} + +void OPPROTO op_wrtt(void) +{ + env->tt[env->tl] = T0; +} + +void OPPROTO op_rdpstate(void) +{ + T0 = env->pstate; +} + +void OPPROTO op_wrpstate(void) +{ + env->pstate = T0 & 0x1f; +} + +// CWP handling is reversed in V9, but we still use the V8 register +// order. +void OPPROTO op_rdcwp(void) +{ + T0 = NWINDOWS - 1 - env->cwp; +} + +void OPPROTO op_wrcwp(void) +{ + env->cwp = NWINDOWS - 1 - T0; } /* XXX: use another pointer for %iN registers to avoid slow wrapping @@ -562,10 +923,20 @@ void OPPROTO op_save(void) { uint32_t cwp; cwp = (env->cwp - 1) & (NWINDOWS - 1); - if (env->wim & (1 << cwp)) { - raise_exception(TT_WIN_OVF); + if (env->cansave == 0) { + raise_exception(TT_SPILL | (env->otherwin != 0 ? + (TT_WOTHER | ((env->wstate & 0x38) >> 1)): + ((env->wstate & 0x7) << 2))); + } else { + if (env->cleanwin - env->canrestore == 0) { + // XXX Clean windows without trap + raise_exception(TT_CLRWIN); + } else { + env->cansave--; + env->canrestore++; + set_cwp(cwp); + } } - set_cwp(cwp); FORCE_RET(); } @@ -573,12 +944,18 @@ void OPPROTO op_restore(void) { uint32_t cwp; cwp = (env->cwp + 1) & (NWINDOWS - 1); - if (env->wim & (1 << cwp)) { - raise_exception(TT_WIN_UNF); + if (env->canrestore == 0) { + raise_exception(TT_FILL | (env->otherwin != 0 ? + (TT_WOTHER | ((env->wstate & 0x38) >> 1)): + ((env->wstate & 0x7) << 2))); + } else { + env->cansave++; + env->canrestore--; + set_cwp(cwp); } - set_cwp(cwp); FORCE_RET(); } +#endif void OPPROTO op_exception(void) { @@ -629,6 +1006,11 @@ void OPPROTO op_exit_tb(void) EXIT_TB(); } +void OPPROTO op_eval_ba(void) +{ + T2 = 1; +} + void OPPROTO op_eval_be(void) { T2 = FLAG_SET(PSR_ZERO); @@ -665,6 +1047,11 @@ void OPPROTO op_eval_bvs(void) T2 = FLAG_SET(PSR_OVF); } +void OPPROTO op_eval_bn(void) +{ + T2 = 0; +} + void OPPROTO op_eval_bneg(void) { T2 = FLAG_SET(PSR_NEG); @@ -711,101 +1098,156 @@ void OPPROTO op_eval_bvc(void) T2 = !FLAG_SET(PSR_OVF); } -/* FCC1:FCC0: 0 =, 1 <, 2 >, 3 u */ +#ifdef TARGET_SPARC64 +void OPPROTO op_eval_xbe(void) +{ + T2 = XFLAG_SET(PSR_ZERO); +} -void OPPROTO op_eval_fbne(void) +void OPPROTO op_eval_xble(void) { -// !0 - T2 = (env->fsr & (FSR_FCC1 | FSR_FCC0)); /* L or G or U */ + target_ulong Z = XFLAG_SET(PSR_ZERO), N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF); + + T2 = Z | (N ^ V); } -void OPPROTO op_eval_fblg(void) +void OPPROTO op_eval_xbl(void) { -// 1 or 2 - T2 = FFLAG_SET(FSR_FCC0) ^ FFLAG_SET(FSR_FCC1); + target_ulong N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF); + + T2 = N ^ V; } -void OPPROTO op_eval_fbul(void) +void OPPROTO op_eval_xbleu(void) { -// 1 or 3 - T2 = FFLAG_SET(FSR_FCC0); + target_ulong Z = XFLAG_SET(PSR_ZERO), C = XFLAG_SET(PSR_CARRY); + + T2 = C | Z; } -void OPPROTO op_eval_fbl(void) +void OPPROTO op_eval_xbcs(void) { -// 1 - T2 = FFLAG_SET(FSR_FCC0) & !FFLAG_SET(FSR_FCC1); + T2 = XFLAG_SET(PSR_CARRY); } -void OPPROTO op_eval_fbug(void) +void OPPROTO op_eval_xbvs(void) { -// 2 or 3 - T2 = FFLAG_SET(FSR_FCC1); + T2 = XFLAG_SET(PSR_OVF); } -void OPPROTO op_eval_fbg(void) +void OPPROTO op_eval_xbneg(void) { -// 2 - T2 = !FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1); + T2 = XFLAG_SET(PSR_NEG); } -void OPPROTO op_eval_fbu(void) +void OPPROTO op_eval_xbne(void) { -// 3 - T2 = FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1); + T2 = !XFLAG_SET(PSR_ZERO); } -void OPPROTO op_eval_fbe(void) +void OPPROTO op_eval_xbg(void) { -// 0 - T2 = !FFLAG_SET(FSR_FCC0) & !FFLAG_SET(FSR_FCC1); + target_ulong Z = XFLAG_SET(PSR_ZERO), N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF); + + T2 = !(Z | (N ^ V)); } -void OPPROTO op_eval_fbue(void) +void OPPROTO op_eval_xbge(void) { -// 0 or 3 - T2 = !(FFLAG_SET(FSR_FCC1) ^ FFLAG_SET(FSR_FCC0)); - FORCE_RET(); + target_ulong N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF); + + T2 = !(N ^ V); +} + +void OPPROTO op_eval_xbgu(void) +{ + target_ulong Z = XFLAG_SET(PSR_ZERO), C = XFLAG_SET(PSR_CARRY); + + T2 = !(C | Z); +} + +void OPPROTO op_eval_xbcc(void) +{ + T2 = !XFLAG_SET(PSR_CARRY); +} + +void OPPROTO op_eval_xbpos(void) +{ + T2 = !XFLAG_SET(PSR_NEG); +} + +void OPPROTO op_eval_xbvc(void) +{ + T2 = !XFLAG_SET(PSR_OVF); +} +#endif + +#define FCC +#define FFLAG_SET(x) (env->fsr & x? 1: 0) +#include "fbranch_template.h" + +#ifdef TARGET_SPARC64 +#define FCC _fcc1 +#define FFLAG_SET(x) ((env->fsr & ((uint64_t)x >> 32))? 1: 0) +#include "fbranch_template.h" +#define FCC _fcc2 +#define FFLAG_SET(x) ((env->fsr & ((uint64_t)x >> 34))? 1: 0) +#include "fbranch_template.h" +#define FCC _fcc3 +#define FFLAG_SET(x) ((env->fsr & ((uint64_t)x >> 36))? 1: 0) +#include "fbranch_template.h" +#endif + +#ifdef TARGET_SPARC64 +void OPPROTO op_eval_brz(void) +{ + T2 = T0; } -void OPPROTO op_eval_fbge(void) +void OPPROTO op_eval_brnz(void) { -// 0 or 2 - T2 = !FFLAG_SET(FSR_FCC0); + T2 = !T0; } -void OPPROTO op_eval_fbuge(void) +void OPPROTO op_eval_brlz(void) { -// !1 - T2 = !(FFLAG_SET(FSR_FCC0) & !FFLAG_SET(FSR_FCC1)); + T2 = ((int64_t)T0 < 0); } -void OPPROTO op_eval_fble(void) +void OPPROTO op_eval_brlez(void) { -// 0 or 1 - T2 = !FFLAG_SET(FSR_FCC1); + T2 = ((int64_t)T0 <= 0); } -void OPPROTO op_eval_fbule(void) +void OPPROTO op_eval_brgz(void) { -// !2 - T2 = !(!FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1)); + T2 = ((int64_t)T0 > 0); } -void OPPROTO op_eval_fbo(void) +void OPPROTO op_eval_brgez(void) { -// !3 - T2 = !(FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1)); + T2 = ((int64_t)T0 >= 0); } +void OPPROTO op_jmp_im64(void) +{ + env->pc = PARAMQ1; +} + +void OPPROTO op_movq_npc_im64(void) +{ + env->npc = PARAMQ1; +} +#endif + void OPPROTO op_jmp_im(void) { - env->pc = PARAM1; + env->pc = (uint32_t)PARAM1; } void OPPROTO op_movl_npc_im(void) { - env->npc = PARAM1; + env->npc = (uint32_t)PARAM1; } void OPPROTO op_movl_npc_T0(void) @@ -826,17 +1268,17 @@ void OPPROTO op_next_insn(void) void OPPROTO op_branch(void) { - env->npc = PARAM3; /* XXX: optimize */ + env->npc = (uint32_t)PARAM3; /* XXX: optimize */ JUMP_TB(op_branch, PARAM1, 0, PARAM2); } void OPPROTO op_branch2(void) { if (T2) { - env->npc = PARAM2 + 4; + env->npc = (uint32_t)PARAM2 + 4; JUMP_TB(op_branch2, PARAM1, 0, PARAM2); } else { - env->npc = PARAM3 + 4; + env->npc = (uint32_t)PARAM3 + 4; JUMP_TB(op_branch2, PARAM1, 1, PARAM3); } FORCE_RET(); @@ -845,10 +1287,10 @@ void OPPROTO op_branch2(void) void OPPROTO op_branch_a(void) { if (T2) { - env->npc = PARAM2; /* XXX: optimize */ + env->npc = (uint32_t)PARAM2; /* XXX: optimize */ JUMP_TB(op_branch_a, PARAM1, 0, PARAM3); } else { - env->npc = PARAM3 + 8; /* XXX: optimize */ + env->npc = (uint32_t)PARAM3 + 8; /* XXX: optimize */ JUMP_TB(op_branch_a, PARAM1, 1, PARAM3 + 4); } FORCE_RET(); @@ -857,9 +1299,9 @@ void OPPROTO op_branch_a(void) void OPPROTO op_generic_branch(void) { if (T2) { - env->npc = PARAM1; + env->npc = (uint32_t)PARAM1; } else { - env->npc = PARAM2; + env->npc = (uint32_t)PARAM2; } FORCE_RET(); } @@ -879,6 +1321,18 @@ void OPPROTO op_fabss(void) do_fabss(); } +#ifdef TARGET_SPARC64 +void OPPROTO op_fnegd(void) +{ + DT0 = -DT1; +} + +void OPPROTO op_fabsd(void) +{ + do_fabsd(); +} +#endif + void OPPROTO op_fsqrts(void) { do_fsqrts(); @@ -944,6 +1398,38 @@ void OPPROTO op_fcmpd(void) do_fcmpd(); } +#ifdef TARGET_SPARC64 +void OPPROTO op_fcmps_fcc1(void) +{ + do_fcmps_fcc1(); +} + +void OPPROTO op_fcmpd_fcc1(void) +{ + do_fcmpd_fcc1(); +} + +void OPPROTO op_fcmps_fcc2(void) +{ + do_fcmps_fcc2(); +} + +void OPPROTO op_fcmpd_fcc2(void) +{ + do_fcmpd_fcc2(); +} + +void OPPROTO op_fcmps_fcc3(void) +{ + do_fcmps_fcc3(); +} + +void OPPROTO op_fcmpd_fcc3(void) +{ + do_fcmpd_fcc3(); +} +#endif + #ifdef USE_INT_TO_FLOAT_HELPERS void OPPROTO op_fitos(void) { @@ -964,6 +1450,18 @@ void OPPROTO op_fitod(void) { DT0 = (double) *((int32_t *)&FT1); } + +#ifdef TARGET_SPARC64 +void OPPROTO op_fxtos(void) +{ + FT0 = (float) *((int64_t *)&DT1); +} + +void OPPROTO op_fxtod(void) +{ + DT0 = (double) *((int64_t *)&DT1); +} +#endif #endif void OPPROTO op_fdtos(void) @@ -986,6 +1484,102 @@ void OPPROTO op_fdtoi(void) *((int32_t *)&FT0) = (int32_t) DT1; } +#ifdef TARGET_SPARC64 +void OPPROTO op_fstox(void) +{ + *((int64_t *)&DT0) = (int64_t) FT1; +} + +void OPPROTO op_fdtox(void) +{ + *((int64_t *)&DT0) = (int64_t) DT1; +} + +void OPPROTO op_fmovs_cc(void) +{ + if (T2) + FT0 = FT1; +} + +void OPPROTO op_fmovd_cc(void) +{ + if (T2) + DT0 = DT1; +} + +void OPPROTO op_mov_cc(void) +{ + if (T2) + T0 = T1; +} + +void OPPROTO op_flushw(void) +{ + if (env->cansave != NWINDOWS - 2) { + raise_exception(TT_SPILL | (env->otherwin != 0 ? + (TT_WOTHER | ((env->wstate & 0x38) >> 1)): + ((env->wstate & 0x7) << 2))); + } +} + +void OPPROTO op_saved(void) +{ + env->cansave++; + if (env->otherwin == 0) + env->canrestore--; +} + +void OPPROTO op_restored(void) +{ + env->canrestore++; + if (env->cleanwin < NWINDOWS - 1) + env->cleanwin++; + if (env->otherwin == 0) + env->cansave--; + else + env->otherwin--; +} + +void OPPROTO op_popc(void) +{ + do_popc(); +} + +void OPPROTO op_done(void) +{ + env->pc = env->tnpc[env->tl]; + env->npc = env->tnpc[env->tl] + 4; + env->pstate = env->tstate[env->tl]; + env->tl--; +} + +void OPPROTO op_retry(void) +{ + env->pc = env->tpc[env->tl]; + env->npc = env->tnpc[env->tl]; + env->pstate = env->tstate[env->tl]; + env->tl--; +} + +void OPPROTO op_sir(void) +{ + // XXX + +} + +void OPPROTO op_ld_asi_reg() +{ + T0 += PARAM1; + helper_ld_asi(env->asi, PARAM2, PARAM3); +} + +void OPPROTO op_st_asi_reg() +{ + T0 += PARAM1; + helper_st_asi(env->asi, PARAM2, PARAM3); +} +#endif + void OPPROTO op_ld_asi() { helper_ld_asi(PARAM1, PARAM2, PARAM3); |