summary refs log tree commit diff stats
path: root/target-sparc/op.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-sparc/op.c')
-rw-r--r--target-sparc/op.c826
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);