On Fri, Apr 06, 2007 at 08:47:57AM +0200, Blue Swirl wrote:
> >The attached patch fully implements IEEE exceptions on the SPARC target.
> 
> The patch is broken:
> gcc-3.3 -Wall -O2 -g -fno-strict-aliasing  -fno-reorder-blocks  -fno-gcse   
> -fno-optimize-sibling-calls  -fno-crossjumping  -fno-align-labels  
> -fno-align-jumps  -fno-align-functions -mpreferred-stack-boundary=2 
> -fomit-frame-pointer  -I. -I.. -I/tmp/qemu.aurel/target-sparc 
> -I/tmp/qemu.aurel -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE 
> -I/tmp/qemu.aurel/fpu -I/tmp/qemu.aurel/slirp -c -o op.o 
> /tmp/qemu.aurel/target-sparc/op.c
> /tmp/qemu.aurel/target-sparc/op.c: In function `op_clear_ieee_excp_and_FTT':
> /tmp/qemu.aurel/target-sparc/op.c:1539: error: `FSR_CEXEC_MASK' undeclared 
> (first use in this function)
> /tmp/qemu.aurel/target-sparc/op.c:1539: error: (Each undeclared identifier 
> is reported only once
> /tmp/qemu.aurel/target-sparc/op.c:1539: error: for each function it appears 
> in.)
> 

Sorry this is a small typo in my patch, please find an update patch
attached.

-- 
  .''`.  Aurelien Jarno             | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   [EMAIL PROTECTED]         | [EMAIL PROTECTED]
   `-    people.debian.org/~aurel32 | www.aurel32.net
diff -u -d -p -r1.17 exec.h
--- qemu.orig/target-sparc/exec.h	19 Mar 2007 14:47:40 -0000	1.17
+++ qemu/target-sparc/exec.h	5 Apr 2007 18:46:48 -0000
@@ -61,6 +61,8 @@ void do_fsqrts(void);
 void do_fsqrtd(void);
 void do_fcmps(void);
 void do_fcmpd(void);
+void do_fcmpes(void);
+void do_fcmped(void);
 #ifdef TARGET_SPARC64
 void do_fabsd(void);
 void do_fcmps_fcc1(void);
@@ -69,6 +71,12 @@ void do_fcmps_fcc2(void);
 void do_fcmpd_fcc2(void);
 void do_fcmps_fcc3(void);
 void do_fcmpd_fcc3(void);
+void do_fcmpes_fcc1(void);
+void do_fcmped_fcc1(void);
+void do_fcmpes_fcc2(void);
+void do_fcmped_fcc2(void);
+void do_fcmpes_fcc3(void);
+void do_fcmped_fcc3(void);
 void do_popc();
 void do_wrpstate();
 void do_done();
@@ -79,6 +87,7 @@ void do_ldd_user(target_ulong addr);
 void do_ldd_raw(target_ulong addr);
 void do_interrupt(int intno);
 void raise_exception(int tt);
+void check_ieee_exceptions();
 void memcpy32(target_ulong *dst, const target_ulong *src);
 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev);
 void dump_mmu(CPUState *env);
diff -u -d -p -r1.27 op.c
--- qemu.orig/target-sparc/op.c	1 Apr 2007 15:38:17 -0000	1.27
+++ qemu/target-sparc/op.c	5 Apr 2007 18:46:48 -0000
@@ -1534,16 +1534,25 @@ void OPPROTO op_flush_T0(void)
     helper_flush(T0);
 }
 
+void OPPROTO op_clear_ieee_excp_and_FTT(void)
+{
+    env->fsr &= ~(FSR_FTT_MASK | FSR_CEXC_MASK);;
+}
+
 #define F_OP(name, p) void OPPROTO op_f##name##p(void)
 
 #define F_BINOP(name)                                           \
     F_OP(name, s)                                               \
     {                                                           \
+	set_float_exception_flags(0, &env->fp_status);		\
         FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
+	check_ieee_exceptions();				\
     }                                                           \
     F_OP(name, d)                                               \
     {                                                           \
+	set_float_exception_flags(0, &env->fp_status);		\
         DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
+	check_ieee_exceptions();				\
     }
 
 F_BINOP(add);
@@ -1554,9 +1563,11 @@ F_BINOP(div);
 
 void OPPROTO op_fsmuld(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
                       float32_to_float64(FT1, &env->fp_status),
                       &env->fp_status);
+    check_ieee_exceptions();
 }
 
 #define F_HELPER(name)    \
@@ -1582,6 +1593,7 @@ F_OP(abs, s)
 }
 
 F_HELPER(cmp);
+F_HELPER(cmpe);
 
 #ifdef TARGET_SPARC64
 F_OP(neg, d)
@@ -1623,6 +1635,37 @@ void OPPROTO op_fcmpd_fcc3(void)
 {
     do_fcmpd_fcc3();
 }
+
+void OPPROTO op_fcmpes_fcc1(void)
+{
+    do_fcmpes_fcc1();
+}
+
+void OPPROTO op_fcmped_fcc1(void)
+{
+    do_fcmped_fcc1();
+}
+
+void OPPROTO op_fcmpes_fcc2(void)
+{
+    do_fcmpes_fcc2();
+}
+
+void OPPROTO op_fcmped_fcc2(void)
+{
+    do_fcmped_fcc2();
+}
+
+void OPPROTO op_fcmpes_fcc3(void)
+{
+    do_fcmpes_fcc3();
+}
+
+void OPPROTO op_fcmped_fcc3(void)
+{
+    do_fcmped_fcc3();
+}
+
 #endif
 
 /* Integer to float conversion.  */
@@ -1631,23 +1674,31 @@ F_HELPER(ito);
 #else
 F_OP(ito, s)
 {
+    set_float_exception_flags(0, &env->fp_status);
     FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
+    check_ieee_exceptions();
 }
 
 F_OP(ito, d)
 {
+    set_float_exception_flags(0, &env->fp_status);
     DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
+    check_ieee_exceptions();
 }
 
 #ifdef TARGET_SPARC64
 F_OP(xto, s)
 {
+    set_float_exception_flags(0, &env->fp_status);
     FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
+    check_ieee_exceptions();
 }
 
 F_OP(xto, d)
 {
+    set_float_exception_flags(0, &env->fp_status);
     DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
+    check_ieee_exceptions();
 }
 #endif
 #endif
@@ -1656,34 +1707,46 @@ F_OP(xto, d)
 /* floating point conversion */
 void OPPROTO op_fdtos(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     FT0 = float64_to_float32(DT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
 void OPPROTO op_fstod(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     DT0 = float32_to_float64(FT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
 /* Float to integer conversion.  */
 void OPPROTO op_fstoi(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
 void OPPROTO op_fdtoi(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
 #ifdef TARGET_SPARC64
 void OPPROTO op_fstox(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
 void OPPROTO op_fdtox(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
 void OPPROTO op_fmovs_cc(void)
diff -u -d -p -r1.23 op_helper.c
--- qemu.orig/target-sparc/op_helper.c	1 Apr 2007 15:15:36 -0000	1.23
+++ qemu/target-sparc/op_helper.c	5 Apr 2007 18:46:48 -0000
@@ -9,10 +9,43 @@ void raise_exception(int tt)
     cpu_loop_exit();
 }   
 
+void check_ieee_exceptions()
+{
+     T0 = get_float_exception_flags(&env->fp_status);
+     if (T0)
+     {
+	/* Copy IEEE 754 flags into FSR */
+	if (T0 & float_flag_invalid)
+	    env->fsr |= FSR_NVC;
+	if (T0 & float_flag_overflow)
+	    env->fsr |= FSR_OFC;
+	if (T0 & float_flag_underflow)
+	    env->fsr |= FSR_UFC;
+	if (T0 & float_flag_divbyzero)
+	    env->fsr |= FSR_DZC;
+	if (T0 & float_flag_inexact)
+	    env->fsr |= FSR_NXC;
+
+	if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23))
+	{
+	    /* Unmasked exception, generate a trap */
+	    env->fsr |= FSR_FTT_IEEE_EXCP;
+	    raise_exception(TT_FP_EXCP);
+	}
+	else
+	{
+	    /* Accumulate exceptions */
+	    env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
+	}
+     }
+}
+
 #ifdef USE_INT_TO_FLOAT_HELPERS
 void do_fitos(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
+    check_ieee_exceptions();
 }
 
 void do_fitod(void)
@@ -35,23 +68,29 @@ void do_fabsd(void)
 
 void do_fsqrts(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     FT0 = float32_sqrt(FT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
 void do_fsqrtd(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     DT0 = float64_sqrt(DT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
-#define GEN_FCMP(name, size, reg1, reg2, FS)                            \
+#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
     void glue(do_, name) (void)                                         \
     {                                                                   \
         env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
         switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
         case float_relation_unordered:                                  \
             T0 = (FSR_FCC1 | FSR_FCC0) << FS;                           \
-            if (env->fsr & FSR_NVM) {                                   \
+            if ((env->fsr & FSR_NVM) || TRAP) {                         \
                 env->fsr |= T0;                                         \
+                env->fsr |= FSR_NVC;                                    \
+                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
                 raise_exception(TT_FP_EXCP);                            \
             } else {                                                    \
                 env->fsr |= FSR_NVA;                                    \
@@ -70,18 +109,30 @@ void do_fsqrtd(void)
         env->fsr |= T0;                                                 \
     }
 
-GEN_FCMP(fcmps, float32, FT0, FT1, 0);
-GEN_FCMP(fcmpd, float64, DT0, DT1, 0);
+GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
+GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
+
+GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
+GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
 
 #ifdef TARGET_SPARC64
-GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22);
-GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22);
+GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
+GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
 
-GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24);
-GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24);
+GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
+GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
 
-GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26);
-GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26);
+GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
+GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
+
+GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
+GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
+
+GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
+GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
+
+GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
+GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
 #endif
 
 #if defined(CONFIG_USER_ONLY) 
diff -u -d -p -r1.46 translate.c
--- qemu.orig/target-sparc/translate.c	5 Apr 2007 18:12:08 -0000	1.46
+++ qemu/target-sparc/translate.c	5 Apr 2007 18:46:49 -0000
@@ -943,6 +943,21 @@ static GenOpFunc * const gen_fcmpd[4] = 
     gen_op_fcmpd_fcc2,
     gen_op_fcmpd_fcc3,
 };
+
+static GenOpFunc * const gen_fcmpes[4] = {
+    gen_op_fcmpes,
+    gen_op_fcmpes_fcc1,
+    gen_op_fcmpes_fcc2,
+    gen_op_fcmpes_fcc3,
+};
+
+static GenOpFunc * const gen_fcmped[4] = {
+    gen_op_fcmped,
+    gen_op_fcmped_fcc1,
+    gen_op_fcmped_fcc2,
+    gen_op_fcmped_fcc3,
+};
+
 #endif
 
 static int gen_trap_ifnofpu(DisasContext * dc)
@@ -1289,6 +1304,7 @@ static void disas_sparc_insn(DisasContex
 	    } else if (xop == 0x34) {	/* FPU Operations */
                 if (gen_trap_ifnofpu(dc))
                     goto jmp_insn;
+		gen_op_clear_ieee_excp_and_FTT();
                 rs1 = GET_FIELD(insn, 13, 17);
 	        rs2 = GET_FIELD(insn, 27, 31);
 	        xop = GET_FIELD(insn, 18, 26);
@@ -1476,6 +1492,7 @@ static void disas_sparc_insn(DisasContex
 #endif
                 if (gen_trap_ifnofpu(dc))
                     goto jmp_insn;
+		gen_op_clear_ieee_excp_and_FTT();
                 rs1 = GET_FIELD(insn, 13, 17);
 	        rs2 = GET_FIELD(insn, 27, 31);
 	        xop = GET_FIELD(insn, 18, 26);
@@ -1653,18 +1670,18 @@ static void disas_sparc_insn(DisasContex
                 	gen_op_load_fpr_FT0(rs1);
                 	gen_op_load_fpr_FT1(rs2);
 #ifdef TARGET_SPARC64
-			gen_fcmps[rd & 3]();
+			gen_fcmpes[rd & 3]();
 #else
-			gen_op_fcmps(); /* XXX should trap if qNaN or sNaN  */
+			gen_op_fcmpes();
 #endif
 			break;
 		    case 0x56: /* fcmped, V9 %fcc */
                 	gen_op_load_fpr_DT0(DFPREG(rs1));
                 	gen_op_load_fpr_DT1(DFPREG(rs2));
 #ifdef TARGET_SPARC64
-			gen_fcmpd[rd & 3]();
+			gen_fcmped[rd & 3]();
 #else
-			gen_op_fcmpd(); /* XXX should trap if qNaN or sNaN  */
+			gen_op_fcmped();
 #endif
 			break;
 		    case 0x57: /* fcmpeq */

Reply via email to