@@ -41,33 +41,33 @@ DEF_HELPER_1(store_fpcr, void, i64)
DEF_HELPER_1(f_to_memory, i32, i64)
DEF_HELPER_1(memory_to_f, i64, i32)
-DEF_HELPER_2(addf, i64, i64, i64)
-DEF_HELPER_2(subf, i64, i64, i64)
-DEF_HELPER_2(mulf, i64, i64, i64)
-DEF_HELPER_2(divf, i64, i64, i64)
-DEF_HELPER_1(sqrtf, i64, i64)
+DEF_HELPER_3(addf, i64, i64, i64, i32)
+DEF_HELPER_3(subf, i64, i64, i64, i32)
+DEF_HELPER_3(mulf, i64, i64, i64, i32)
+DEF_HELPER_3(divf, i64, i64, i64, i32)
+DEF_HELPER_2(sqrtf, i64, i64, i32)
DEF_HELPER_1(g_to_memory, i64, i64)
DEF_HELPER_1(memory_to_g, i64, i64)
-DEF_HELPER_2(addg, i64, i64, i64)
-DEF_HELPER_2(subg, i64, i64, i64)
-DEF_HELPER_2(mulg, i64, i64, i64)
-DEF_HELPER_2(divg, i64, i64, i64)
-DEF_HELPER_1(sqrtg, i64, i64)
+DEF_HELPER_3(addg, i64, i64, i64, i32)
+DEF_HELPER_3(subg, i64, i64, i64, i32)
+DEF_HELPER_3(mulg, i64, i64, i64, i32)
+DEF_HELPER_3(divg, i64, i64, i64, i32)
+DEF_HELPER_2(sqrtg, i64, i64, i32)
DEF_HELPER_1(s_to_memory, i32, i64)
DEF_HELPER_1(memory_to_s, i64, i32)
-DEF_HELPER_2(adds, i64, i64, i64)
-DEF_HELPER_2(subs, i64, i64, i64)
-DEF_HELPER_2(muls, i64, i64, i64)
-DEF_HELPER_2(divs, i64, i64, i64)
-DEF_HELPER_1(sqrts, i64, i64)
-
-DEF_HELPER_2(addt, i64, i64, i64)
-DEF_HELPER_2(subt, i64, i64, i64)
-DEF_HELPER_2(mult, i64, i64, i64)
-DEF_HELPER_2(divt, i64, i64, i64)
-DEF_HELPER_1(sqrtt, i64, i64)
+DEF_HELPER_3(adds, i64, i64, i64, i32)
+DEF_HELPER_3(subs, i64, i64, i64, i32)
+DEF_HELPER_3(muls, i64, i64, i64, i32)
+DEF_HELPER_3(divs, i64, i64, i64, i32)
+DEF_HELPER_2(sqrts, i64, i64, i32)
+
+DEF_HELPER_3(addt, i64, i64, i64, i32)
+DEF_HELPER_3(subt, i64, i64, i64, i32)
+DEF_HELPER_3(mult, i64, i64, i64, i32)
+DEF_HELPER_3(divt, i64, i64, i64, i32)
+DEF_HELPER_2(sqrtt, i64, i64, i32)
DEF_HELPER_2(cmptun, i64, i64, i64)
DEF_HELPER_2(cmpteq, i64, i64, i64)
@@ -81,15 +81,15 @@ DEF_HELPER_2(cpys, i64, i64, i64)
DEF_HELPER_2(cpysn, i64, i64, i64)
DEF_HELPER_2(cpyse, i64, i64, i64)
-DEF_HELPER_1(cvtts, i64, i64)
-DEF_HELPER_1(cvtst, i64, i64)
-DEF_HELPER_1(cvttq, i64, i64)
-DEF_HELPER_1(cvtqs, i64, i64)
-DEF_HELPER_1(cvtqt, i64, i64)
-DEF_HELPER_1(cvtqf, i64, i64)
-DEF_HELPER_1(cvtgf, i64, i64)
-DEF_HELPER_1(cvtgq, i64, i64)
-DEF_HELPER_1(cvtqg, i64, i64)
+DEF_HELPER_2(cvtts, i64, i64, i32)
+DEF_HELPER_2(cvtst, i64, i64, i32)
+DEF_HELPER_2(cvttq, i64, i64, i32)
+DEF_HELPER_2(cvtqs, i64, i64, i32)
+DEF_HELPER_2(cvtqt, i64, i64, i32)
+DEF_HELPER_2(cvtqf, i64, i64, i32)
+DEF_HELPER_2(cvtgf, i64, i64, i32)
+DEF_HELPER_2(cvtgq, i64, i64, i32)
+DEF_HELPER_2(cvtqg, i64, i64, i32)
DEF_HELPER_1(cvtlq, i64, i64)
DEF_HELPER_1(cvtql, i64, i64)
DEF_HELPER_1(cvtqlv, i64, i64)
@@ -370,6 +370,85 @@ uint64_t helper_unpkbw (uint64_t op1)
/* Floating point helpers */
+/* If the floating-point qualifiers specified a rounding mode,
+ set that rounding mode and remember the original mode for
+ resetting at the end of the instruction. */
+static inline uint32_t begin_quals_roundmode(uint32_t qual)
+{
+ uint32_t rm = FP_STATUS.float_rounding_mode, old_rm = rm;
+
+ switch (qual & 0xc0) {
+ case 0x80:
+ rm = float_round_nearest_even;
+ break;
+ case 0x00:
+ rm = float_round_to_zero;
+ break;
+ case 0x40:
+ rm = float_round_down;
+ break;
+ case 0xc0:
+ return old_rm;
+ }
+ set_float_rounding_mode(rm, &FP_STATUS);
+ return old_rm;
+}
+
+/* If the floating-point qualifiers specified extra exception processing
+ (i.e. /u or /su), zero the exception flags so that we can determine if
+ the current instruction raises any exceptions. Save the old acrued
+ exception status so that we can restore them at the end of the insn. */
+static inline uint32_t begin_quals_exception(uint32_t qual)
+{
+ uint32_t old_exc = 0;
+ if (qual & 0x500) {
+ old_exc = (uint32_t)FP_STATUS.float_exception_flags << 8;
+ set_float_exception_flags(0, &FP_STATUS);
+ }
+ return old_exc;
+}
+
+/* Begin processing an fp operation. Return a token that should be passed
+ when completing the fp operation. */
+static inline uint32_t begin_fp(uint32_t quals)
+{
+ uint32_t ret = 0;
+
+ ret |= begin_quals_roundmode(quals);
+ ret |= begin_quals_exception(quals);
+
+ return ret;
+}
+
+/* End processing an fp operation. */
+static inline void end_fp(uint32_t quals, uint32_t orig)
+{
+ uint8_t exc = FP_STATUS.float_exception_flags;
+
+ set_float_exception_flags(exc | (orig >> 8), &FP_STATUS);
+ set_float_rounding_mode(orig & 0xff, &FP_STATUS);
+
+ /* TODO: check quals and exc and raise any exceptions needed. */
+}
+
+/* Raise any exceptions needed for using F, given the insn qualifiers. */
+static inline void float32_input(uint32_t quals, float32 f)
+{
+ /* If /s is used, no exceptions are raised immediately. */
+ /* ??? This for userspace only. If we are emulating the real hw, then
+ we may well need to trap to the kernel for software emulation. */
+ /* ??? Shouldn't we raise an exception for SNAN? */
+ if (quals & 0x500)
+ return;
+ /* TODO: Check for inf, nan, denormal and trap. */
+}
+
+static inline void float64_input(uint32_t quals, float64 f)
+{
+ /* TODO: Exactly like above, except for float64. */
+}
+
+
/* F floating (VAX) */
static inline uint64_t float32_to_f(float32 fa)
{
@@ -447,52 +526,86 @@ uint64_t helper_memory_to_f (uint32_t a)
return r;
}
-uint64_t helper_addf (uint64_t a, uint64_t b)
+uint64_t helper_addf (uint64_t a, uint64_t b, uint32_t quals)
{
float32 fa, fb, fr;
+ uint32_t token;
fa = f_to_float32(a);
fb = f_to_float32(b);
+
+ token = begin_fp(quals);
+ float32_input(quals, fa);
+ float32_input(quals, fb);
fr = float32_add(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float32_to_f(fr);
}
-uint64_t helper_subf (uint64_t a, uint64_t b)
+uint64_t helper_subf (uint64_t a, uint64_t b, uint32_t quals)
{
float32 fa, fb, fr;
+ uint32_t token;
fa = f_to_float32(a);
fb = f_to_float32(b);
+
+ token = begin_fp(quals);
+ float32_input(quals, fa);
+ float32_input(quals, fb);
fr = float32_sub(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float32_to_f(fr);
}
-uint64_t helper_mulf (uint64_t a, uint64_t b)
+uint64_t helper_mulf (uint64_t a, uint64_t b, uint32_t quals)
{
float32 fa, fb, fr;
+ uint32_t token;
fa = f_to_float32(a);
fb = f_to_float32(b);
+
+ token = begin_fp(quals);
+ float32_input(quals, fa);
+ float32_input(quals, fb);
fr = float32_mul(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float32_to_f(fr);
}
-uint64_t helper_divf (uint64_t a, uint64_t b)
+uint64_t helper_divf (uint64_t a, uint64_t b, uint32_t quals)
{
float32 fa, fb, fr;
+ uint32_t token;
fa = f_to_float32(a);
fb = f_to_float32(b);
+
+ token = begin_fp(quals);
+ float32_input(quals, fa);
+ float32_input(quals, fb);
fr = float32_div(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float32_to_f(fr);
}
-uint64_t helper_sqrtf (uint64_t t)
+uint64_t helper_sqrtf (uint64_t t, uint32_t quals)
{
float32 ft, fr;
+ uint32_t token;
ft = f_to_float32(t);
+
+ token = begin_fp(quals);
+ float32_input(quals, ft);
fr = float32_sqrt(ft, &FP_STATUS);
+ end_fp(quals, token);
+
return float32_to_f(fr);
}
@@ -574,52 +687,86 @@ uint64_t helper_memory_to_g (uint64_t a)
return r;
}
-uint64_t helper_addg (uint64_t a, uint64_t b)
+uint64_t helper_addg (uint64_t a, uint64_t b, uint32_t quals)
{
float64 fa, fb, fr;
+ uint32_t token;
fa = g_to_float64(a);
fb = g_to_float64(b);
+
+ token = begin_fp(quals);
+ float64_input(quals, fa);
+ float64_input(quals, fb);
fr = float64_add(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float64_to_g(fr);
}
-uint64_t helper_subg (uint64_t a, uint64_t b)
+uint64_t helper_subg (uint64_t a, uint64_t b, uint32_t quals)
{
float64 fa, fb, fr;
+ uint32_t token;
fa = g_to_float64(a);
fb = g_to_float64(b);
+
+ token = begin_fp(quals);
+ float64_input(quals, fa);
+ float64_input(quals, fb);
fr = float64_sub(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float64_to_g(fr);
}
-uint64_t helper_mulg (uint64_t a, uint64_t b)
+uint64_t helper_mulg (uint64_t a, uint64_t b, uint32_t quals)
{
float64 fa, fb, fr;
-
+ uint32_t token;
+
fa = g_to_float64(a);
fb = g_to_float64(b);
+
+ token = begin_fp(quals);
+ float64_input(quals, fa);
+ float64_input(quals, fb);
fr = float64_mul(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float64_to_g(fr);
}
-uint64_t helper_divg (uint64_t a, uint64_t b)
+uint64_t helper_divg (uint64_t a, uint64_t b, uint32_t quals)
{
float64 fa, fb, fr;
+ uint32_t token;
fa = g_to_float64(a);
fb = g_to_float64(b);
+
+ token = begin_fp(quals);
+ float64_input(quals, fa);
+ float64_input(quals, fb);
fr = float64_div(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float64_to_g(fr);
}
-uint64_t helper_sqrtg (uint64_t a)
+uint64_t helper_sqrtg (uint64_t a, uint32_t quals)
{
float64 fa, fr;
+ uint32_t token;
fa = g_to_float64(a);
+
+ token = begin_fp(quals);
+ float64_input(quals, fa);
fr = float64_sqrt(fa, &FP_STATUS);
+ end_fp(quals, token);
+
return float64_to_g(fr);
}
@@ -678,52 +825,86 @@ uint64_t helper_memory_to_s (uint32_t a)
return float32_to_s_int(a);
}
-uint64_t helper_adds (uint64_t a, uint64_t b)
+uint64_t helper_adds (uint64_t a, uint64_t b, uint32_t quals)
{
float32 fa, fb, fr;
+ uint32_t token;
fa = s_to_float32(a);
fb = s_to_float32(b);
+
+ token = begin_fp(quals);
+ float32_input(quals, fa);
+ float32_input(quals, fb);
fr = float32_add(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float32_to_s(fr);
}
-uint64_t helper_subs (uint64_t a, uint64_t b)
+uint64_t helper_subs (uint64_t a, uint64_t b, uint32_t quals)
{
float32 fa, fb, fr;
+ uint32_t token;
fa = s_to_float32(a);
fb = s_to_float32(b);
+
+ token = begin_fp(quals);
+ float32_input(quals, fa);
+ float32_input(quals, fb);
fr = float32_sub(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float32_to_s(fr);
}
-uint64_t helper_muls (uint64_t a, uint64_t b)
+uint64_t helper_muls (uint64_t a, uint64_t b, uint32_t quals)
{
float32 fa, fb, fr;
+ uint32_t token;
fa = s_to_float32(a);
fb = s_to_float32(b);
+
+ token = begin_fp(quals);
+ float32_input(quals, fa);
+ float32_input(quals, fb);
fr = float32_mul(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float32_to_s(fr);
}
-uint64_t helper_divs (uint64_t a, uint64_t b)
+uint64_t helper_divs (uint64_t a, uint64_t b, uint32_t quals)
{
float32 fa, fb, fr;
+ uint32_t token;
fa = s_to_float32(a);
fb = s_to_float32(b);
+
+ token = begin_fp(quals);
+ float32_input(quals, fa);
+ float32_input(quals, fb);
fr = float32_div(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float32_to_s(fr);
}
-uint64_t helper_sqrts (uint64_t a)
+uint64_t helper_sqrts (uint64_t a, uint32_t quals)
{
float32 fa, fr;
+ uint32_t token;
fa = s_to_float32(a);
+
+ token = begin_fp(quals);
+ float32_input(quals, fa);
fr = float32_sqrt(fa, &FP_STATUS);
+ end_fp(quals, token);
+
return float32_to_s(fr);
}
@@ -745,52 +926,86 @@ static inline uint64_t float64_to_t(float64 fa)
return r.ll;
}
-uint64_t helper_addt (uint64_t a, uint64_t b)
+uint64_t helper_addt (uint64_t a, uint64_t b, uint32_t quals)
{
float64 fa, fb, fr;
+ uint32_t token;
fa = t_to_float64(a);
fb = t_to_float64(b);
+
+ token = begin_fp(quals);
+ float64_input(quals, fa);
+ float64_input(quals, fb);
fr = float64_add(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float64_to_t(fr);
}
-uint64_t helper_subt (uint64_t a, uint64_t b)
+uint64_t helper_subt (uint64_t a, uint64_t b, uint32_t quals)
{
float64 fa, fb, fr;
+ uint32_t token;
fa = t_to_float64(a);
fb = t_to_float64(b);
+
+ token = begin_fp(quals);
+ float64_input(quals, fa);
+ float64_input(quals, fb);
fr = float64_sub(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float64_to_t(fr);
}
-uint64_t helper_mult (uint64_t a, uint64_t b)
+uint64_t helper_mult (uint64_t a, uint64_t b, uint32_t quals)
{
float64 fa, fb, fr;
+ uint32_t token;
fa = t_to_float64(a);
fb = t_to_float64(b);
+
+ token = begin_fp(quals);
+ float64_input(quals, fa);
+ float64_input(quals, fb);
fr = float64_mul(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float64_to_t(fr);
}
-uint64_t helper_divt (uint64_t a, uint64_t b)
+uint64_t helper_divt (uint64_t a, uint64_t b, uint32_t quals)
{
float64 fa, fb, fr;
+ uint32_t token;
fa = t_to_float64(a);
fb = t_to_float64(b);
+
+ token = begin_fp(quals);
+ float64_input(quals, fa);
+ float64_input(quals, fb);
fr = float64_div(fa, fb, &FP_STATUS);
+ end_fp(quals, token);
+
return float64_to_t(fr);
}
-uint64_t helper_sqrtt (uint64_t a)
+uint64_t helper_sqrtt (uint64_t a, uint32_t quals)
{
float64 fa, fr;
+ uint32_t token;
fa = t_to_float64(a);
+
+ token = begin_fp(quals);
+ float64_input(quals, fa);
fr = float64_sqrt(fa, &FP_STATUS);
+ end_fp(quals, token);
+
return float64_to_t(fr);
}
@@ -905,70 +1120,131 @@ uint64_t helper_cmpglt(uint64_t a, uint64_t b)
}
/* Floating point format conversion */
-uint64_t helper_cvtts (uint64_t a)
+uint64_t helper_cvtts (uint64_t a, uint32_t quals)
{
float64 fa;
float32 fr;
+ uint32_t token;
fa = t_to_float64(a);
+
+ token = begin_fp(quals);
+ float64_input(quals, fa);
fr = float64_to_float32(fa, &FP_STATUS);
+ end_fp(quals, token);
+
return float32_to_s(fr);
}
-uint64_t helper_cvtst (uint64_t a)
+uint64_t helper_cvtst (uint64_t a, uint32_t quals)
{
float32 fa;
float64 fr;
+ uint32_t token;
fa = s_to_float32(a);
+
+ token = begin_fp(quals);
+ float32_input(quals, fa);
fr = float32_to_float64(fa, &FP_STATUS);
+ end_fp(quals, token);
+
return float64_to_t(fr);
}
-uint64_t helper_cvtqs (uint64_t a)
+uint64_t helper_cvtqs (uint64_t a, uint32_t quals)
{
- float32 fr = int64_to_float32(a, &FP_STATUS);
+ float32 fr;
+ uint32_t token;
+
+ token = begin_fp(quals);
+ fr = int64_to_float32(a, &FP_STATUS);
+ end_fp(quals, token);
+
return float32_to_s(fr);
}
-uint64_t helper_cvttq (uint64_t a)
+uint64_t helper_cvttq (uint64_t a, uint32_t quals)
{
- float64 fa = t_to_float64(a);
- return float64_to_int64_round_to_zero(fa, &FP_STATUS);
+ float64 fa;
+ uint64_t ret;
+ uint32_t token;
+
+ fa = t_to_float64(a);
+
+ token = begin_fp(quals);
+ float64_input(quals, fa);
+ ret = float64_to_int64(fa, &FP_STATUS);
+ end_fp(quals, token);
+
+ return ret;
}
-uint64_t helper_cvtqt (uint64_t a)
+uint64_t helper_cvtqt (uint64_t a, uint32_t quals)
{
- float64 fr = int64_to_float64(a, &FP_STATUS);
+ float64 fr;
+ uint32_t token;
+
+ token = begin_fp(quals);
+ fr = int64_to_float64(a, &FP_STATUS);
+ end_fp(quals, token);
+
return float64_to_t(fr);
}
-uint64_t helper_cvtqf (uint64_t a)
+uint64_t helper_cvtqf (uint64_t a, uint32_t quals)
{
- float32 fr = int64_to_float32(a, &FP_STATUS);
+ float32 fr;
+ uint32_t token;
+
+ token = begin_fp(quals);
+ fr = int64_to_float32(a, &FP_STATUS);
+ end_fp(quals, token);
+
return float32_to_f(fr);
}
-uint64_t helper_cvtgf (uint64_t a)
+uint64_t helper_cvtgf (uint64_t a, uint32_t quals)
{
float64 fa;
float32 fr;
+ uint32_t token;
fa = g_to_float64(a);
+
+ token = begin_fp(quals);
+ float64_input(quals, fa);
fr = float64_to_float32(fa, &FP_STATUS);
+ end_fp(quals, token);
+
return float32_to_f(fr);
}
-uint64_t helper_cvtgq (uint64_t a)
+uint64_t helper_cvtgq (uint64_t a, uint32_t quals)
{
- float64 fa = g_to_float64(a);
- return float64_to_int64_round_to_zero(fa, &FP_STATUS);
+ float64 fa;
+ uint64_t ret;
+ uint32_t token;
+
+ fa = g_to_float64(a);
+
+ token = begin_fp(quals);
+ float64_input(quals, fa);
+ ret = float64_to_int64(fa, &FP_STATUS);
+ end_fp(quals, token);
+
+ return ret;
}
-uint64_t helper_cvtqg (uint64_t a)
+uint64_t helper_cvtqg (uint64_t a, uint32_t quals)
{
float64 fr;
+ uint32_t token;
+
+ token = begin_fp(quals);
fr = int64_to_float64(a, &FP_STATUS);
+ end_fp(quals, token);
+
return float64_to_g(fr);
}
@@ -442,81 +442,79 @@ static void gen_fcmov(TCGCond inv_cond, int ra, int rb, int rc)
gen_set_label(l1);
}
-#define FARITH2(name) \
-static inline void glue(gen_f, name)(int rb, int rc) \
-{ \
- if (unlikely(rc == 31)) \
- return; \
- \
- if (rb != 31) \
- gen_helper_ ## name (cpu_fir[rc], cpu_fir[rb]); \
- else { \
- TCGv tmp = tcg_const_i64(0); \
- gen_helper_ ## name (cpu_fir[rc], tmp); \
- tcg_temp_free(tmp); \
- } \
+#define FARITH2(name) \
+static inline void glue(gen_f, name)(int rb, int rc) \
+{ \
+ if (unlikely(rc == 31)) \
+ return; \
+ \
+ if (rb != 31) \
+ gen_helper_ ## name (cpu_fir[rc], cpu_fir[rb]); \
+ else { \
+ TCGv tmp = tcg_const_i64(0); \
+ gen_helper_ ## name (cpu_fir[rc], tmp); \
+ tcg_temp_free(tmp); \
+ } \
}
-FARITH2(sqrts)
-FARITH2(sqrtf)
-FARITH2(sqrtg)
-FARITH2(sqrtt)
-FARITH2(cvtgf)
-FARITH2(cvtgq)
-FARITH2(cvtqf)
-FARITH2(cvtqg)
-FARITH2(cvtst)
-FARITH2(cvtts)
-FARITH2(cvttq)
-FARITH2(cvtqs)
-FARITH2(cvtqt)
FARITH2(cvtlq)
FARITH2(cvtql)
FARITH2(cvtqlv)
FARITH2(cvtqlsv)
-#define FARITH3(name) \
-static inline void glue(gen_f, name)(int ra, int rb, int rc) \
-{ \
- if (unlikely(rc == 31)) \
- return; \
- \
- if (ra != 31) { \
- if (rb != 31) \
- gen_helper_ ## name (cpu_fir[rc], cpu_fir[ra], cpu_fir[rb]); \
- else { \
- TCGv tmp = tcg_const_i64(0); \
- gen_helper_ ## name (cpu_fir[rc], cpu_fir[ra], tmp); \
- tcg_temp_free(tmp); \
- } \
- } else { \
- TCGv tmp = tcg_const_i64(0); \
- if (rb != 31) \
- gen_helper_ ## name (cpu_fir[rc], tmp, cpu_fir[rb]); \
- else \
- gen_helper_ ## name (cpu_fir[rc], tmp, tmp); \
- tcg_temp_free(tmp); \
- } \
+#define QFARITH2(name) \
+static inline void glue(gen_f, name)(int rb, int rc, int opc) \
+{ \
+ TCGv_i32 quals; \
+ if (unlikely(rc == 31)) \
+ return; \
+ quals = tcg_const_i32(opc & ~0x3f); \
+ if (rb != 31) \
+ gen_helper_ ## name (cpu_fir[rc], cpu_fir[rb], quals); \
+ else { \
+ TCGv tmp = tcg_const_i64(0); \
+ gen_helper_ ## name (cpu_fir[rc], tmp, quals); \
+ tcg_temp_free(tmp); \
+ } \
+ tcg_temp_free_i32(quals); \
+}
+QFARITH2(sqrts)
+QFARITH2(sqrtf)
+QFARITH2(sqrtg)
+QFARITH2(sqrtt)
+QFARITH2(cvtgf)
+QFARITH2(cvtgq)
+QFARITH2(cvtqf)
+QFARITH2(cvtqg)
+QFARITH2(cvtst)
+QFARITH2(cvtts)
+QFARITH2(cvttq)
+QFARITH2(cvtqs)
+QFARITH2(cvtqt)
+
+#define FARITH3(name) \
+static inline void glue(gen_f, name)(int ra, int rb, int rc) \
+{ \
+ TCGv zero, ta, tb; \
+ if (unlikely(rc == 31)) \
+ return; \
+ ta = cpu_fir[ra]; \
+ tb = cpu_fir[rb]; \
+ if (unlikely(ra == 31)) { \
+ zero = tcg_const_i64(0); \
+ ta = zero; \
+ } \
+ if (unlikely(rb == 31)) { \
+ if (ra != 31) \
+ zero = tcg_const_i64(0); \
+ tb = zero; \
+ } \
+ gen_helper_ ## name (cpu_fir[rc], ta, tb); \
+ if (ra == 31 || rb == 31) \
+ tcg_temp_free(zero); \
}
-
-FARITH3(addf)
-FARITH3(subf)
-FARITH3(mulf)
-FARITH3(divf)
-FARITH3(addg)
-FARITH3(subg)
-FARITH3(mulg)
-FARITH3(divg)
FARITH3(cmpgeq)
FARITH3(cmpglt)
FARITH3(cmpgle)
-FARITH3(adds)
-FARITH3(subs)
-FARITH3(muls)
-FARITH3(divs)
-FARITH3(addt)
-FARITH3(subt)
-FARITH3(mult)
-FARITH3(divt)
FARITH3(cmptun)
FARITH3(cmpteq)
FARITH3(cmptlt)
@@ -525,6 +523,47 @@ FARITH3(cpys)
FARITH3(cpysn)
FARITH3(cpyse)
+#define QFARITH3(name) \
+static inline void glue(gen_f, name)(int ra, int rb, int rc, int opc) \
+{ \
+ TCGv zero, ta, tb; \
+ TCGv_i32 quals; \
+ if (unlikely(rc == 31)) \
+ return; \
+ ta = cpu_fir[ra]; \
+ tb = cpu_fir[rb]; \
+ if (unlikely(ra == 31)) { \
+ zero = tcg_const_i64(0); \
+ ta = zero; \
+ } \
+ if (unlikely(rb == 31)) { \
+ if (ra != 31) \
+ zero = tcg_const_i64(0); \
+ tb = zero; \
+ } \
+ quals = tcg_const_i32(opc & ~0x3f); \
+ gen_helper_ ## name (cpu_fir[rc], ta, tb, quals); \
+ tcg_temp_free_i32(quals); \
+ if (ra == 31 || rb == 31) \
+ tcg_temp_free(zero); \
+}
+QFARITH3(addf)
+QFARITH3(subf)
+QFARITH3(mulf)
+QFARITH3(divf)
+QFARITH3(addg)
+QFARITH3(subg)
+QFARITH3(mulg)
+QFARITH3(divg)
+QFARITH3(adds)
+QFARITH3(subs)
+QFARITH3(muls)
+QFARITH3(divs)
+QFARITH3(addt)
+QFARITH3(subt)
+QFARITH3(mult)
+QFARITH3(divt)
+
static inline uint64_t zapnot_mask(uint8_t lit)
{
uint64_t mask = 0;
@@ -1607,7 +1646,7 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
}
break;
case 0x14:
- switch (fpfn) { /* f11 & 0x3F */
+ switch (fpfn) { /* fn11 & 0x3F */
case 0x04:
/* ITOFS */
if (!(ctx->amask & AMASK_FIX))
@@ -1626,13 +1665,13 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
/* SQRTF */
if (!(ctx->amask & AMASK_FIX))
goto invalid_opc;
- gen_fsqrtf(rb, rc);
+ gen_fsqrtf(rb, rc, fn11);
break;
case 0x0B:
/* SQRTS */
if (!(ctx->amask & AMASK_FIX))
goto invalid_opc;
- gen_fsqrts(rb, rc);
+ gen_fsqrts(rb, rc, fn11);
break;
case 0x14:
/* ITOFF */
@@ -1663,13 +1702,13 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
/* SQRTG */
if (!(ctx->amask & AMASK_FIX))
goto invalid_opc;
- gen_fsqrtg(rb, rc);
+ gen_fsqrtg(rb, rc, fn11);
break;
case 0x02B:
/* SQRTT */
if (!(ctx->amask & AMASK_FIX))
goto invalid_opc;
- gen_fsqrtt(rb, rc);
+ gen_fsqrtt(rb, rc, fn11);
break;
default:
goto invalid_opc;
@@ -1677,47 +1716,42 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x15:
/* VAX floating point */
- /* XXX: rounding mode and trap are ignored (!) */
- switch (fpfn) { /* f11 & 0x3F */
+ switch (fpfn) { /* fn11 & 0x3F */
case 0x00:
/* ADDF */
- gen_faddf(ra, rb, rc);
+ gen_faddf(ra, rb, rc, fn11);
break;
case 0x01:
/* SUBF */
- gen_fsubf(ra, rb, rc);
+ gen_fsubf(ra, rb, rc, fn11);
break;
case 0x02:
/* MULF */
- gen_fmulf(ra, rb, rc);
+ gen_fmulf(ra, rb, rc, fn11);
break;
case 0x03:
/* DIVF */
- gen_fdivf(ra, rb, rc);
+ gen_fdivf(ra, rb, rc, fn11);
break;
case 0x1E:
/* CVTDG */
-#if 0 // TODO
- gen_fcvtdg(rb, rc);
-#else
+ /* TODO */
goto invalid_opc;
-#endif
- break;
case 0x20:
/* ADDG */
- gen_faddg(ra, rb, rc);
+ gen_faddg(ra, rb, rc, fn11);
break;
case 0x21:
/* SUBG */
- gen_fsubg(ra, rb, rc);
+ gen_fsubg(ra, rb, rc, fn11);
break;
case 0x22:
/* MULG */
- gen_fmulg(ra, rb, rc);
+ gen_fmulg(ra, rb, rc, fn11);
break;
case 0x23:
/* DIVG */
- gen_fdivg(ra, rb, rc);
+ gen_fdivg(ra, rb, rc, fn11);
break;
case 0x25:
/* CMPGEQ */
@@ -1733,27 +1767,23 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x2C:
/* CVTGF */
- gen_fcvtgf(rb, rc);
+ gen_fcvtgf(rb, rc, fn11);
break;
case 0x2D:
/* CVTGD */
-#if 0 // TODO
- gen_fcvtgd(rb, rc);
-#else
+ /* TODO */
goto invalid_opc;
-#endif
- break;
case 0x2F:
/* CVTGQ */
- gen_fcvtgq(rb, rc);
+ gen_fcvtgq(rb, rc, fn11);
break;
case 0x3C:
/* CVTQF */
- gen_fcvtqf(rb, rc);
+ gen_fcvtqf(rb, rc, fn11);
break;
case 0x3E:
/* CVTQG */
- gen_fcvtqg(rb, rc);
+ gen_fcvtqg(rb, rc, fn11);
break;
default:
goto invalid_opc;
@@ -1761,39 +1791,38 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x16:
/* IEEE floating-point */
- /* XXX: rounding mode and traps are ignored (!) */
- switch (fpfn) { /* f11 & 0x3F */
+ switch (fpfn) { /* fn11 & 0x3F */
case 0x00:
/* ADDS */
- gen_fadds(ra, rb, rc);
+ gen_fadds(ra, rb, rc, fn11);
break;
case 0x01:
/* SUBS */
- gen_fsubs(ra, rb, rc);
+ gen_fsubs(ra, rb, rc, fn11);
break;
case 0x02:
/* MULS */
- gen_fmuls(ra, rb, rc);
+ gen_fmuls(ra, rb, rc, fn11);
break;
case 0x03:
/* DIVS */
- gen_fdivs(ra, rb, rc);
+ gen_fdivs(ra, rb, rc, fn11);
break;
case 0x20:
/* ADDT */
- gen_faddt(ra, rb, rc);
+ gen_faddt(ra, rb, rc, fn11);
break;
case 0x21:
/* SUBT */
- gen_fsubt(ra, rb, rc);
+ gen_fsubt(ra, rb, rc, fn11);
break;
case 0x22:
/* MULT */
- gen_fmult(ra, rb, rc);
+ gen_fmult(ra, rb, rc, fn11);
break;
case 0x23:
/* DIVT */
- gen_fdivt(ra, rb, rc);
+ gen_fdivt(ra, rb, rc, fn11);
break;
case 0x24:
/* CMPTUN */
@@ -1812,26 +1841,25 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
gen_fcmptle(ra, rb, rc);
break;
case 0x2C:
- /* XXX: incorrect */
if (fn11 == 0x2AC || fn11 == 0x6AC) {
/* CVTST */
- gen_fcvtst(rb, rc);
+ gen_fcvtst(rb, rc, fn11);
} else {
/* CVTTS */
- gen_fcvtts(rb, rc);
+ gen_fcvtts(rb, rc, fn11);
}
break;
case 0x2F:
/* CVTTQ */
- gen_fcvttq(rb, rc);
+ gen_fcvttq(rb, rc, fn11);
break;
case 0x3C:
/* CVTQS */
- gen_fcvtqs(rb, rc);
+ gen_fcvtqs(rb, rc, fn11);
break;
case 0x3E:
/* CVTQT */
- gen_fcvtqt(rb, rc);
+ gen_fcvtqt(rb, rc, fn11);
break;
default:
goto invalid_opc;