changeset 17028:dc293c1d969c

[SPARC] Fixing conversions of l2d l2f i2d i2f ... Adding assertions for usage of float/double registers to get rid of using wrong encoding in registers
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Tue, 02 Sep 2014 17:22:16 -0700
parents b44535d38d64
children 790e5e5072a2
files graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java
diffstat 3 files changed, 152 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Tue Sep 02 17:19:53 2014 -0700
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Tue Sep 02 17:22:16 2014 -0700
@@ -1998,6 +1998,7 @@
         public Movwtos(Register src, Register dst) {
             /* VIS3 only */
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movwtos, g0, src, dst);
+            assert isSingleFloatRegister(dst);
         }
     }
 
@@ -2012,6 +2013,7 @@
         public Movxtod(Register src, Register dst) {
             /* VIS3 only */
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movxtod, g0, src, dst);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -2019,6 +2021,7 @@
         public Movdtox(Register src, Register dst) {
             /* VIS3 only */
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movdtox, g0, src, dst);
+            assert isDoubleFloatRegister(src);
         }
     }
 
@@ -2026,6 +2029,7 @@
         public Movstosw(Register src, Register dst) {
             /* VIS3 only */
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movstosw, g0, src, dst);
+            assert isSingleFloatRegister(src);
         }
     }
 
@@ -2033,6 +2037,7 @@
         public Movstouw(Register src, Register dst) {
             /* VIS3 only */
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movstouw, g0, src, dst);
+            assert isSingleFloatRegister(src);
         }
     }
 
@@ -2040,6 +2045,8 @@
         public Fdtos(Register src, Register dst) {
             /* VIS3 only */
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fdtos, g0, src, dst);
+            assert isSingleFloatRegister(dst);
+            assert isDoubleFloatRegister(src);
         }
     }
 
@@ -2804,6 +2811,10 @@
 
         public Fmsubs(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
             super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fmsubs.getValue(), src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+            assert isSingleFloatRegister(src1);
+            assert isSingleFloatRegister(src2);
+            assert isSingleFloatRegister(src3);
+            assert isSingleFloatRegister(dst);
         }
     }
 
@@ -2811,6 +2822,10 @@
 
         public Fmsubd(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
             super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fmsubd.getValue(), src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+            assert isDoubleFloatRegister(src1);
+            assert isDoubleFloatRegister(src2);
+            assert isDoubleFloatRegister(src3);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -2818,6 +2833,8 @@
 
         public Fmovs(Register src, Register dst) {
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fmovs, g0, src, dst);
+            assert isSingleFloatRegister(src);
+            assert isSingleFloatRegister(dst);
         }
     }
 
@@ -2825,6 +2842,11 @@
 
         public Fmovd(Register src, Register dst) {
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fmovd, g0, src, dst);
+            // Except for argument register it is not allowed to use f registers for double values
+            // assert !(src == f0 || src == f2 || src == f4 || src == f6) ||
+// isDoubleFloatRegister(src);
+            // When we move return value to d0 we may use f0 for it
+            // assert f0 != dst || isDoubleFloatRegister(dst);
         }
     }
 
@@ -2832,6 +2854,9 @@
 
         public Fmuls(Register src1, Register src2, Register dst) {
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fmuls, src1, src2, dst);
+            assert isSingleFloatRegister(src1);
+            assert isSingleFloatRegister(src2);
+            assert isSingleFloatRegister(dst);
         }
     }
 
@@ -2839,6 +2864,9 @@
 
         public Fmuld(Register src1, Register src2, Register dst) {
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fmuld, src1, src2, dst);
+            assert isDoubleFloatRegister(src1);
+            assert isDoubleFloatRegister(src2);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -2846,6 +2874,9 @@
 
         public Fsmuld(Register src1, Register src2, Register dst) {
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fsmuld, src1, src2, dst);
+            assert isSingleFloatRegister(src1);
+            assert isSingleFloatRegister(src2);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -2910,6 +2941,9 @@
         public Fnadds(Register src1, Register src2, Register dst) {
             /* VIS3 only */
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fnadds, src1, src2, dst);
+            assert isSingleFloatRegister(src1);
+            assert isSingleFloatRegister(src2);
+            assert isSingleFloatRegister(dst);
         }
     }
 
@@ -2918,6 +2952,9 @@
         public Fnaddd(Register src1, Register src2, Register dst) {
             /* VIS3 only */
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fnaddd, src1, src2, dst);
+            assert isDoubleFloatRegister(src1);
+            assert isDoubleFloatRegister(src2);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -2925,6 +2962,8 @@
 
         public Fnegs(Register src2, Register dst) {
             super(Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fnegs.getValue(), src2.encoding(), dst.encoding());
+            assert isSingleFloatRegister(src2);
+            assert isSingleFloatRegister(dst);
         }
     }
 
@@ -2932,6 +2971,8 @@
 
         public Fnegd(Register src2, Register dst) {
             super(Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fnegd.getValue(), src2.encoding(), dst.encoding());
+            assert isDoubleFloatRegister(src2);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -2940,6 +2981,9 @@
         public Fnhadds(Register src1, Register src2, Register dst) {
             /* VIS3 only */
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fnhadds, src1, src2, dst);
+            assert isSingleFloatRegister(src1);
+            assert isSingleFloatRegister(src2);
+            assert isSingleFloatRegister(dst);
         }
     }
 
@@ -2948,6 +2992,9 @@
         public Fnhaddd(Register src1, Register src2, Register dst) {
             /* VIS3 only */
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fnhaddd, src1, src2, dst);
+            assert isDoubleFloatRegister(src1);
+            assert isDoubleFloatRegister(src2);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -2955,6 +3002,10 @@
 
         public Fnmadds(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
             super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fnmadds.getValue(), src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+            assert isSingleFloatRegister(src1);
+            assert isSingleFloatRegister(src2);
+            assert isSingleFloatRegister(src3);
+            assert isSingleFloatRegister(dst);
         }
     }
 
@@ -2962,6 +3013,10 @@
 
         public Fnmaddd(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
             super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fnmaddd.getValue(), src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+            assert isDoubleFloatRegister(src1);
+            assert isDoubleFloatRegister(src2);
+            assert isDoubleFloatRegister(src3);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -2969,6 +3024,10 @@
 
         public Fnmsubs(SPARCAssembler masm, Register src1, Register src2, Register src3, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fnmsubs.getValue(), src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+            assert isSingleFloatRegister(src1);
+            assert isSingleFloatRegister(src2);
+            assert isSingleFloatRegister(src3);
+            assert isSingleFloatRegister(dst);
         }
     }
 
@@ -2976,6 +3035,10 @@
 
         public Fnmsubd(SPARCAssembler masm, Register src1, Register src2, Register src3, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), Op5s.Fnmsubd.getValue(), src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+            assert isDoubleFloatRegister(src1);
+            assert isDoubleFloatRegister(src2);
+            assert isDoubleFloatRegister(src3);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -2984,6 +3047,9 @@
         public Fnmuls(Register src1, Register src2, Register dst) {
             /* VIS3 only */
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fnmuls, src1, src2, dst);
+            assert isSingleFloatRegister(src1);
+            assert isSingleFloatRegister(src2);
+            assert isSingleFloatRegister(dst);
         }
     }
 
@@ -2992,6 +3058,9 @@
         public Fnmuld(Register src1, Register src2, Register dst) {
             /* VIS3 only */
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fnmuld, src1, src2, dst);
+            assert isDoubleFloatRegister(src1);
+            assert isDoubleFloatRegister(src2);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -3000,6 +3069,9 @@
         public Fnsmuld(Register src1, Register src2, Register dst) {
             /* VIS3 only */
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fnsmuld, src1, src2, dst);
+            assert isDoubleFloatRegister(src1);
+            assert isDoubleFloatRegister(src2);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -3007,6 +3079,8 @@
 
         public Fstoi(Register src2, Register dst) {
             super(Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fstoi.getValue(), src2.encoding(), dst.encoding());
+            assert isSingleFloatRegister(dst);
+            assert isSingleFloatRegister(src2);
         }
     }
 
@@ -3014,6 +3088,8 @@
 
         public Fstox(Register src2, Register dst) {
             super(Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fstox.getValue(), src2.encoding(), dst.encoding());
+            assert isDoubleFloatRegister(dst);
+            assert isSingleFloatRegister(src2);
         }
     }
 
@@ -3021,6 +3097,8 @@
 
         public Fdtox(Register src2, Register dst) {
             super(Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fdtox.getValue(), src2.encoding(), dst.encoding());
+            assert isDoubleFloatRegister(src2);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -3028,6 +3106,8 @@
 
         public Fstod(Register src2, Register dst) {
             super(Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fstod.getValue(), src2.encoding(), dst.encoding());
+            assert isDoubleFloatRegister(dst);
+            assert isSingleFloatRegister(src2);
         }
     }
 
@@ -3038,6 +3118,8 @@
 
         public Fdtoi(Register src2, Register dst) {
             super(Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fdtoi.getValue(), src2.encoding(), dst.encoding());
+            assert isDoubleFloatRegister(src2);
+            assert isSingleFloatRegister(dst);
         }
     }
 
@@ -3045,6 +3127,8 @@
 
         public Fitos(Register src2, Register dst) {
             super(Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fitos.getValue(), src2.encoding(), dst.encoding());
+            assert isSingleFloatRegister(src2);
+            assert isSingleFloatRegister(dst);
         }
     }
 
@@ -3052,6 +3136,8 @@
 
         public Fitod(Register src2, Register dst) {
             super(Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fitod.getValue(), src2.encoding(), dst.encoding());
+            assert isSingleFloatRegister(src2);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -3059,6 +3145,8 @@
 
         public Fxtod(Register src2, Register dst) {
             super(Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fxtod.getValue(), src2.encoding(), dst.encoding());
+            assert isDoubleFloatRegister(src2);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -3097,6 +3185,10 @@
 
         public Fpmaddx(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
             super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), 0, src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+            assert isDoubleFloatRegister(src1);
+            assert isDoubleFloatRegister(src2);
+            assert isDoubleFloatRegister(src3);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -3104,6 +3196,10 @@
 
         public Fpmaddxhi(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) {
             super(asm, Ops.ArithOp.getValue(), Op3s.Impdep2.getValue(), 4, src1.encoding(), src2.encoding(), src3.encoding(), dst.encoding());
+            assert isDoubleFloatRegister(src1);
+            assert isDoubleFloatRegister(src2);
+            assert isDoubleFloatRegister(src3);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -3112,6 +3208,9 @@
         public Fpmerge(Register src1, Register src2, Register dst) {
             /* VIS1 only */
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.Fpmerge, src1, src2, dst);
+            assert isSingleFloatRegister(src1);
+            assert isSingleFloatRegister(src2);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -3230,6 +3329,9 @@
 
         public Fsubs(Register src1, Register src2, Register dst) {
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fsubs, src1, src2, dst);
+            assert isSingleFloatRegister(src1);
+            assert isSingleFloatRegister(src2);
+            assert isSingleFloatRegister(dst);
         }
     }
 
@@ -3237,6 +3339,9 @@
 
         public Fsubd(Register src1, Register src2, Register dst) {
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fsubd, src1, src2, dst);
+            assert isDoubleFloatRegister(src1);
+            assert isDoubleFloatRegister(src2);
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -3252,6 +3357,7 @@
         public Fzeros(Register dst) {
             /* VIS1 only */
             super(Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fzeros.getValue(), 0, dst.encoding());
+            assert isSingleFloatRegister(dst);
         }
     }
 
@@ -3260,6 +3366,7 @@
         public Fzerod(Register dst) {
             /* VIS1 only */
             super(Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fzerod.getValue(), 0, dst.encoding());
+            assert isDoubleFloatRegister(dst);
         }
     }
 
@@ -3267,6 +3374,8 @@
 
         public Fcmp(CC cc, Opfs opf, Register r1, Register r2) {
             super(Ops.ArithOp, cc, 0b110101, opf, r1, r2);
+            assert opf != Opfs.Fcmpd || (isDoubleFloatRegister(r1) && isDoubleFloatRegister(r2));
+            assert opf != Opfs.Fcmps || (isSingleFloatRegister(r1) && isSingleFloatRegister(r2));
         }
     }
 
@@ -3452,10 +3561,12 @@
 
         public Lddf(SPARCAddress src, Register dst) {
             super(Op3s.Lddf, src, dst);
+            assert dst == f0 || dst == f2 || dst == f4 || dst == f6 || isDoubleFloatRegister(dst);
         }
 
         public Lddf(Register src, Register dst) {
             super(Op3s.Lddf, src, dst);
+            assert dst == f0 || dst == f2 || dst == f4 || dst == f6 || isDoubleFloatRegister(dst);
         }
     }
 
@@ -3463,10 +3574,12 @@
 
         public Ldf(SPARCAddress src, Register dst) {
             super(Op3s.Ldf, src, dst);
+            assert isSingleFloatRegister(dst);
         }
 
         public Ldf(Register src, Register dst) {
             super(Op3s.Ldf, src, dst);
+            assert isSingleFloatRegister(dst);
         }
     }
 
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Tue Sep 02 17:19:53 2014 -0700
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Tue Sep 02 17:22:16 2014 -0700
@@ -834,39 +834,40 @@
         switch (op) {
             case D2F:
                 return emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Float), D2F, input);
-            case D2I:
-                fromRegisterKind = Kind.Double;
-                toRegisterKind = Kind.Int;
-                conversionInstruction = D2I;
-                break;
-            case F2L:
-                Variable v = newVariable(LIRKind.derive(inputVal).changeType(Kind.Double));
-                emitMove(v, input);
-                input = v;
-            case D2L:
-                fromRegisterKind = Kind.Double;
-                toRegisterKind = Kind.Long;
-                conversionInstruction = D2L;
-                break;
             case F2D:
                 return emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Double), F2D, input);
-            case F2I:
-                fromRegisterKind = Kind.Float;
-                toRegisterKind = Kind.Int;
-                conversionInstruction = F2I;
-                break;
-            case I2D:
-            // Implemented in two steps, as this consists of sign extension and then move the
-            // bits over to the double register and then convert to double, in fact this does
-            // not generate any overhead in generated code
-            {
-                AllocatableValue tmp = emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Long), I2L, input);
-                return emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Double), L2D, tmp);
-            }
             case I2F:
                 return emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Float), I2F, input);
             case L2D:
                 return emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Double), L2D, input);
+            case D2I: {
+                AllocatableValue convertedFloatReg = emitConvert2Op(LIRKind.derive(input).changeType(Kind.Float), D2I, input);
+                AllocatableValue convertedIntReg = newVariable(LIRKind.derive(convertedFloatReg).changeType(Kind.Int));
+                emitMove(convertedIntReg, convertedFloatReg);
+                return convertedIntReg;
+            }
+            case F2L: {
+                AllocatableValue convertedDoubleReg = emitConvert2Op(LIRKind.derive(input).changeType(Kind.Double), F2L, input);
+                AllocatableValue convertedLongReg = newVariable(LIRKind.derive(convertedDoubleReg).changeType(Kind.Long));
+                emitMove(convertedLongReg, convertedDoubleReg);
+                return convertedLongReg;
+            }
+            case F2I: {
+                AllocatableValue convertedFloatReg = emitConvert2Op(LIRKind.derive(input).changeType(Kind.Float), F2I, input);
+                AllocatableValue convertedIntReg = newVariable(LIRKind.derive(convertedFloatReg).changeType(Kind.Int));
+                emitMove(convertedIntReg, convertedFloatReg);
+                return convertedIntReg;
+            }
+            case D2L: {
+                AllocatableValue convertedDoubleReg = emitConvert2Op(LIRKind.derive(input).changeType(Kind.Double), D2L, input);
+                AllocatableValue convertedLongReg = newVariable(LIRKind.derive(convertedDoubleReg).changeType(Kind.Long));
+                emitMove(convertedLongReg, convertedDoubleReg);
+                return convertedLongReg;
+            }
+            case I2D: {
+                AllocatableValue tmp = emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Long), I2L, input);
+                return emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Double), L2D, tmp);
+            }
             case L2F: {
                 AllocatableValue tmp = emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Double), L2D, input);
                 return emitConvert2Op(LIRKind.derive(inputVal).changeType(Kind.Float), D2F, tmp);
@@ -874,13 +875,6 @@
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
-        if (fromRegisterKind != null) {
-            AllocatableValue var = newVariable(LIRKind.derive(inputVal).changeType(toRegisterKind));
-            emitMove(var, emitConvert2Op(LIRKind.derive(inputVal).changeType(fromRegisterKind), conversionInstruction, input));
-            return var;
-        } else {
-            throw GraalInternalError.shouldNotReachHere();
-        }
     }
 
     @Override
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Tue Sep 02 17:19:53 2014 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Tue Sep 02 17:22:16 2014 -0700
@@ -68,7 +68,7 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            emit(crb, masm, opcode, result, x, null);
+            emitUnary(crb, masm, opcode, result, x, null);
         }
     }
 
@@ -86,7 +86,7 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            emit(crb, masm, opcode, result, x, null);
+            emitUnary(crb, masm, opcode, result, x, null);
         }
     }
 
@@ -689,7 +689,7 @@
         }
     }
 
-    public static void emit(CompilationResultBuilder crb, SPARCAssembler masm, SPARCArithmetic opcode, Value dst, Value src, LIRFrameState info) {
+    public static void emitUnary(CompilationResultBuilder crb, SPARCAssembler masm, SPARCArithmetic opcode, Value dst, Value src, LIRFrameState info) {
         int exceptionOffset = -1;
         Label notOrdered = new Label();
         if (isRegister(src)) {
@@ -756,15 +756,14 @@
                     break;
                 case F2L:
                     new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(src), asFloatReg(src)).emit(masm);
-                    new Fbo(false, notOrdered).emit(masm);
-                    new Fstox(asFloatReg(src), asFloatReg(dst)).emit(masm);
-                    new Fitos(asFloatReg(dst), asFloatReg(dst)).emit(masm);
-                    new Fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)).emit(masm);
+                    new Fbo(true, notOrdered).emit(masm);
+                    new Fstox(asFloatReg(src), asDoubleReg(dst)).emit(masm);
+                    new Fsubd(asDoubleReg(dst), asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
                     masm.bind(notOrdered);
                     break;
                 case F2I:
                     new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(src), asFloatReg(src)).emit(masm);
-                    new Fbo(false, notOrdered).emit(masm);
+                    new Fbo(true, notOrdered).emit(masm);
                     new Fstoi(asFloatReg(src), asFloatReg(dst)).emit(masm);
                     new Fitos(asFloatReg(dst), asFloatReg(dst)).emit(masm);
                     new Fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)).emit(masm);
@@ -792,10 +791,10 @@
                     break;
                 case D2I:
                     new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(src), asDoubleReg(src)).emit(masm);
-                    new Fbo(false, notOrdered).emit(masm);
-                    new Fdtoi(asDoubleReg(src), asDoubleReg(dst)).emit(masm);
-                    new Fitod(asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
-                    new Fsubd(asDoubleReg(dst), asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
+                    new Fbo(true, notOrdered).emit(masm);
+                    new Fdtoi(asDoubleReg(src), asFloatReg(dst)).emit(masm);
+                    new Fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)).emit(masm);
+                    new Fstoi(asFloatReg(dst), asFloatReg(dst)).emit(masm);
                     masm.bind(notOrdered);
                     break;
                 case FNEG: