Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Diff of /sml/trunk/src/MLRISC/x86/mltree/x86.sml
ViewVC logotype

Diff of /sml/trunk/src/MLRISC/x86/mltree/x86.sml

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 730, Fri Nov 10 14:04:49 2000 UTC revision 731, Fri Nov 10 22:57:45 2000 UTC
# Line 22  Line 22 
22   *  5.  Generate testl/testb instead of andl whenever appropriate.  This   *  5.  Generate testl/testb instead of andl whenever appropriate.  This
23   *      is recommended by the Intel Optimization Guide and seems to improve   *      is recommended by the Intel Optimization Guide and seems to improve
24   *      boxity tests on SML/NJ.   *      boxity tests on SML/NJ.
25     *
26     * More changes for floating point:
27     *  A new mode is implemented which generates pseudo 3-address instructions
28     * for floating point.  These instructions are register allocated the
29     * normal way, with the virtual registers mapped onto a set of pseudo
30     * %fp registers.  These registers are then mapped onto the %st registers
31     * with a new postprocessing phase.
32     *
33   * -- Allen   * -- Allen
34   *)   *)
35  local  local
36     val rewriteMemReg = true (* should we rewrite memRegs *)     val rewriteMemReg = true (* should we rewrite memRegs *)
37       val enableFastFPMode = true (* set this to false to disable the mode *)
38  in  in
39    
40  functor X86  functor X86
# Line 44  Line 53 
53            tempMem: X86Instr.operand,         (* temporary for CVTI2F *)            tempMem: X86Instr.operand,         (* temporary for CVTI2F *)
54            cleanup: X86Instr.instruction list (* cleanup code *)            cleanup: X86Instr.instruction list (* cleanup code *)
55           }           }
56        (* When the following flag is set, we allocate floating point registers
57         * directly on the floating point stack
58         *)
59        val fast_floating_point : bool ref
60    ) : sig include MLTREECOMP    ) : sig include MLTREECOMP
61            val rewriteMemReg : bool            val rewriteMemReg : bool
62        end =        end =
# Line 76  Line 89 
89     * If this is on, we can avoid doing RewritePseudo phase entirely.     * If this is on, we can avoid doing RewritePseudo phase entirely.
90     *)     *)
91    val rewriteMemReg = rewriteMemReg    val rewriteMemReg = rewriteMemReg
92    
93      (* The following hardcoded *)
94    fun isMemReg r = rewriteMemReg andalso r >= 8 andalso r < 32    fun isMemReg r = rewriteMemReg andalso r >= 8 andalso r < 32
95      fun isFMemReg r = if enableFastFPMode andalso !fast_floating_point
96                        then r >= 32+8 andalso r < 32+32
97                        else true
98      val isAnyFMemReg = List.exists (fn r => r >= 32+8 andalso r < 32+32)
99    
100    val ST0 = C.ST 0    val ST0 = C.ST 0
101    val ST7 = C.ST 7    val ST7 = C.ST 7
# Line 93  Line 112 
112        (* label where a trap is generated -- one per cluster *)        (* label where a trap is generated -- one per cluster *)
113        val trapLabel = ref (NONE: (I.instruction * Label.label) option)        val trapLabel = ref (NONE: (I.instruction * Label.label) option)
114    
115          (* flag floating point generation *)
116          val floatingPointUsed = ref false
117    
118        (* effective address of an integer register *)        (* effective address of an integer register *)
119        fun IntReg r = if isMemReg r then MemReg r else I.Direct r        fun IntReg r = if isMemReg r then I.MemReg r else I.Direct r
120        and MemReg r =        and RealReg r = if isFMemReg r then I.FDirect r else I.FPR r
           ((* memRegsUsed := Word.orb(!memRegsUsed,  
                             Word.<<(0w1, Word.fromInt r-0w8)); *)  
            I.MemReg r  
           )  
121    
122        (* Add an overflow trap *)        (* Add an overflow trap *)
123        fun trap() =        fun trap() =
# Line 115  Line 133 
133        val newReg  = C.newReg        val newReg  = C.newReg
134        val newFreg = C.newFreg        val newFreg = C.newFreg
135    
136          fun fsize 32 = I.FP32
137            | fsize 64 = I.FP64
138            | fsize 80 = I.FP80
139            | fsize _  = error "fsize"
140    
141        (* mark an expression with a list of annotations *)        (* mark an expression with a list of annotations *)
142        fun mark'(i,[]) = i        fun mark'(i,[]) = i
143          | mark'(i,a::an) = mark'(I.ANNOTATION{i=i,a=a},an)          | mark'(i,a::an) = mark'(I.ANNOTATION{i=i,a=a},an)
# Line 122  Line 145 
145        (* annotate an expression and emit it *)        (* annotate an expression and emit it *)
146        fun mark(i,an) = emit(mark'(i,an))        fun mark(i,an) = emit(mark'(i,an))
147    
148          val emits = app emit
149    
150        (* emit parallel copies for integers        (* emit parallel copies for integers
151         * Translates parallel copies that involve memregs into         * Translates parallel copies that involve memregs into
152         * individual copies.         * individual copies.
# Line 139  Line 164 
164                      else [I.COPY{dst=[rd], src=[rs], tmp=NONE}]                      else [I.COPY{dst=[rd], src=[rs], tmp=NONE}]
165                  | mvInstr{dst, src} = [I.MOVE{mvOp=I.MOVL, src=src, dst=dst}]                  | mvInstr{dst, src} = [I.MOVE{mvOp=I.MOVL, src=src, dst=dst}]
166            in            in
167               app emit (Shuffle.shuffle{mvInstr=mvInstr, ea=IntReg}               emits (Shuffle.shuffle{mvInstr=mvInstr, ea=IntReg}
168                 {regmap=fn r => r, tmp=SOME(I.Direct(newReg())),                 {regmap=fn r => r, tmp=SOME(I.Direct(newReg())),
169                  dst=dst, src=src})                  dst=dst, src=src})
170            end            end
# Line 194  Line 219 
219          | setZeroBit2(T.MARK(e, _)) = setZeroBit2 e          | setZeroBit2(T.MARK(e, _)) = setZeroBit2 e
220          | setZeroBit2 _             = false          | setZeroBit2 _             = false
221    
222        (* emit parallel copies for floating point *)        (* emit parallel copies for floating point
223        fun fcopy(fty, [], [], _) = ()         * Normal version.
224          | fcopy(fty, dst as [_], src as [_], an) =         *)
225          fun fcopy'(fty, [], [], _) = ()
226            | fcopy'(fty, dst as [_], src as [_], an) =
227              mark(I.FCOPY{dst=dst,src=src,tmp=NONE}, an)              mark(I.FCOPY{dst=dst,src=src,tmp=NONE}, an)
228          | fcopy(fty, dst, src, an) =          | fcopy'(fty, dst, src, an) =
229              mark(I.FCOPY{dst=dst,src=src,tmp=SOME(I.FDirect(newFreg()))}, an)              mark(I.FCOPY{dst=dst,src=src,tmp=SOME(I.FDirect(newFreg()))}, an)
230    
231          (* emit parallel copies for floating point.
232           * Fast version.
233           * Translates parallel copies that involve memregs into
234           * individual copies.
235           *)
236    
237          fun fcopy''(fty, [], [], _) = ()
238            | fcopy''(fty, dst, src, an) =
239              if true orelse isAnyFMemReg dst orelse isAnyFMemReg src then
240              let val fsize = fsize fty
241                  fun mvInstr{dst, src} = [I.FMOVE{fsize=fsize, src=src, dst=dst}]
242              in
243                  emits (Shuffle.shuffle{mvInstr=mvInstr, ea=RealReg}
244                    {regmap=fn r => r,
245                     tmp=case dst of
246                           [_] => NONE
247                         |  _  => SOME(I.FPR(newReg())),
248                     dst=dst, src=src})
249              end
250              else
251                mark(I.FCOPY{dst=dst,src=src,tmp=
252                             case dst of
253                               [_] => NONE
254                             | _   => SOME(I.FPR(newFreg()))}, an)
255    
256          fun fcopy x = if enableFastFPMode andalso !fast_floating_point
257                        then fcopy'' x else fcopy' x
258    
259        (* Translates MLTREE condition code to x86 condition code *)        (* Translates MLTREE condition code to x86 condition code *)
260        fun cond T.LT = I.LT | cond T.LTU = I.B        fun cond T.LT = I.LT | cond T.LTU = I.B
261          | cond T.LE = I.LE | cond T.LEU = I.BE          | cond T.LE = I.LE | cond T.LEU = I.BE
# Line 726  Line 781 
781                 T.REG(_,rs) =>                 T.REG(_,rs) =>
782                     if isMemReg rs andalso isMemReg rd then                     if isMemReg rs andalso isMemReg rd then
783                        let val tmp = I.Direct(newReg())                        let val tmp = I.Direct(newReg())
784                        in  move'(MemReg rs, tmp, an);                        in  move'(I.MemReg rs, tmp, an);
785                            move'(tmp, rdOpnd, [])                            move'(tmp, rdOpnd, [])
786                        end                        end
787                     else move'(IntReg rs, rdOpnd, an)                     else move'(IntReg rs, rdOpnd, an)
# Line 985  Line 1040 
1040    
1041            (* generate code for floating point compare and branch *)            (* generate code for floating point compare and branch *)
1042        and fbranch(fty, fcc, t1, t2, lab, an) =        and fbranch(fty, fcc, t1, t2, lab, an) =
           let fun compare() =  
1043                let fun ignoreOrder (T.FREG _) = true                let fun ignoreOrder (T.FREG _) = true
1044                      | ignoreOrder (T.FLOAD _) = true                      | ignoreOrder (T.FLOAD _) = true
1045                      | ignoreOrder (T.FMARK(e,_)) = ignoreOrder e                      | ignoreOrder (T.FMARK(e,_)) = ignoreOrder e
1046                      | ignoreOrder _ = false                      | ignoreOrder _ = false
1047                in  if ignoreOrder t1 orelse ignoreOrder t2 then  
1048                  fun compare'() = (* Sethi-Ullman style *)
1049                      (if ignoreOrder t1 orelse ignoreOrder t2 then
1050                         (reduceFexp(fty, t2, []); reduceFexp(fty, t1, []))                         (reduceFexp(fty, t2, []); reduceFexp(fty, t1, []))
1051                    else (reduceFexp(fty, t1, []); reduceFexp(fty, t2, []);                    else (reduceFexp(fty, t1, []); reduceFexp(fty, t2, []);
1052                          emit(I.FXCH{opnd=C.ST(1)}));                          emit(I.FXCH{opnd=C.ST(1)}));
1053                    emit(I.FUCOMPP)                     emit(I.FUCOMPP);
1054                       fcc
1055                      )
1056    
1057                  fun compare''() =
1058                          (* direct style *)
1059                          (* Try to make lsrc the memory operand *)
1060                      let val lsrc = foperand(fty, t1)
1061                          val rsrc = foperand(fty, t2)
1062                          val fsize = fsize fty
1063                          fun cmp(lsrc, rsrc, fcc) =
1064                              (emit(I.FCMP{fsize=fsize,lsrc=lsrc,rsrc=rsrc}); fcc)
1065                      in  case (lsrc, rsrc) of
1066                             (I.FPR _, I.FPR _) => cmp(lsrc, rsrc, fcc)
1067                           | (I.FPR _, mem) => cmp(mem,lsrc,T.Basis.swapFcond fcc)
1068                           | (mem, I.FPR _) => cmp(lsrc, rsrc, fcc)
1069                           | (lsrc, rsrc) => (* can't be both memory! *)
1070                             let val ftmpR = newFreg()
1071                                 val ftmp  = I.FPR ftmpR
1072                             in  emit(I.FMOVE{fsize=fsize,src=rsrc,dst=ftmp});
1073                                 cmp(lsrc, ftmp, fcc)
1074                end                end
1075                      end
1076    
1077                  fun compare() =
1078                      if enableFastFPMode andalso !fast_floating_point
1079                      then compare''() else compare'()
1080    
1081                fun andil i = emit(I.BINARY{binOp=I.ANDL,src=I.Immed(i),dst=eax})                fun andil i = emit(I.BINARY{binOp=I.ANDL,src=I.Immed(i),dst=eax})
1082                fun testil i = emit(I.TESTL{lsrc=eax,rsrc=I.Immed(i)})                fun testil i = emit(I.TESTL{lsrc=eax,rsrc=I.Immed(i)})
1083                fun xoril i = emit(I.BINARY{binOp=I.XORL,src=I.Immed(i),dst=eax})                fun xoril i = emit(I.BINARY{binOp=I.XORL,src=I.Immed(i),dst=eax})
1084                fun cmpil i = emit(I.CMPL{rsrc=I.Immed(i), lsrc=eax})                fun cmpil i = emit(I.CMPL{rsrc=I.Immed(i), lsrc=eax})
1085                fun j(cc, lab) = mark(I.JCC{cond=cc, opnd=immedLabel lab},an)                fun j(cc, lab) = mark(I.JCC{cond=cc, opnd=immedLabel lab},an)
1086                fun sahf() = emit(I.SAHF)                fun sahf() = emit(I.SAHF)
1087                fun branch() =                fun branch(fcc) =
1088                    case fcc                    case fcc
1089                    of T.==   => (andil 0x4400; xoril 0x4000; j(I.EQ, lab))                    of T.==   => (andil 0x4400; xoril 0x4000; j(I.EQ, lab))
1090                     | T.?<>  => (andil 0x4400; xoril 0x4000; j(I.NE, lab))                     | T.?<>  => (andil 0x4400; xoril 0x4000; j(I.NE, lab))
# Line 1021  Line 1103 
1103                     | T.?=   => (testil 0x4400; j(I.NE,lab))                     | T.?=   => (testil 0x4400; j(I.NE,lab))
1104                     | _      => error "fbranch"                     | _      => error "fbranch"
1105                   (*esac*)                   (*esac*)
1106            in  compare(); emit I.FNSTSW; branch()                val fcc = compare()
1107              in  emit I.FNSTSW;
1108                  branch(fcc)
1109              end
1110    
1111          (*========================================================
1112           * Floating point code generation starts here.
1113           * Some generic fp routines first.
1114           *========================================================*)
1115    
1116           (* Can this tree be folded into the src operand of a floating point
1117            * operations?
1118            *)
1119          and foldableFexp(T.FREG _) = true
1120            | foldableFexp(T.FLOAD _) = true
1121            | foldableFexp(T.CVTI2F(_, (16 | 32), _)) = true
1122            | foldableFexp(T.CVTF2F(_, _, t)) = foldableFexp t
1123            | foldableFexp(T.FMARK(t, _)) = foldableFexp t
1124            | foldableFexp _ = false
1125    
1126            (* Move integer e of size ty into a memory location.
1127             * Returns a quadruple:
1128             *  (INTEGER,return ty,effect address of memory location,cleanup code)
1129             *)
1130          and convertIntToFloat(ty, e) =
1131              let val opnd = operand e
1132              in  if isMemOpnd opnd andalso (ty = 16 orelse ty = 32)
1133                  then (INTEGER, ty, opnd, [])
1134                  else
1135                    let val {instrs, tempMem, cleanup} = cvti2f{ty=ty, src=opnd}
1136                    in  emits instrs;
1137                        (INTEGER, 32, tempMem, cleanup)
1138                    end
1139            end            end
1140    
1141          (*========================================================
1142           * Sethi-Ullman based floating point code generation as
1143           * implemented by Lal
1144           *========================================================*)
1145    
1146        and fld(32, opnd) = I.FLDS opnd        and fld(32, opnd) = I.FLDS opnd
1147          | fld(64, opnd) = I.FLDL opnd          | fld(64, opnd) = I.FLDL opnd
1148          | fld(80, opnd) = I.FLDT opnd          | fld(80, opnd) = I.FLDT opnd
# Line 1043  Line 1162 
1162          | fstp _         = error "fstp"          | fstp _         = error "fstp"
1163    
1164            (* generate code for floating point stores *)            (* generate code for floating point stores *)
1165        and fstore(fty, ea, d, mem, an) =        and fstore'(fty, ea, d, mem, an) =
1166            (case d of            (case d of
1167               T.FREG(fty, fs) => emit(fld(fty, I.FDirect fs))               T.FREG(fty, fs) => emit(fld(fty, I.FDirect fs))
1168             | _ => reduceFexp(fty, d, []);             | _ => reduceFexp(fty, d, []);
1169             mark(fstp(fty, address(ea, mem)), an)             mark(fstp(fty, address(ea, mem)), an)
1170            )            )
1171    
1172        and fexpr e = (reduceFexp(64, e, []); C.ST(0))            (* generate code for floating point loads *)
1173          and fload'(fty, ea, mem, fd, an) =
1174                let val ea = address(ea, mem)
1175                in  mark(fld(fty, ea), an);
1176                    if fd = ST0 then () else emit(fstp(fty, I.FDirect fd))
1177                end
1178    
1179          and fexpr' e = (reduceFexp(64, e, []); C.ST(0))
1180    
1181            (* generate floating point expression and put the result in fd *)            (* generate floating point expression and put the result in fd *)
1182        and doFexpr(fty, T.FREG(_, fs), fd, an) =        and doFexpr'(fty, T.FREG(_, fs), fd, an) =
1183              (if fs = fd then ()              (if fs = fd then ()
1184               else mark(I.FCOPY{dst=[fd], src=[fs], tmp=NONE}, an)               else mark(I.FCOPY{dst=[fd], src=[fs], tmp=NONE}, an)
1185              )              )
1186          | doFexpr(fty, T.FLOAD(fty', ea, mem), fd, an) =          | doFexpr'(_, T.FLOAD(fty, ea, mem), fd, an) =
1187              let val ea = address(ea, mem)              fload'(fty, ea, mem, fd, an)
1188              in  mark(fld(fty', ea), an);          | doFexpr'(fty, T.FEXT fexp, fd, an) =
                 if fd = ST0 then () else emit(fstp(fty, I.FDirect fd))  
             end  
         | doFexpr(fty, T.FEXT fexp, fd, an) =  
1189              (ExtensionComp.compileFext (reducer()) {e=fexp, fd=fd, an=an};              (ExtensionComp.compileFext (reducer()) {e=fexp, fd=fd, an=an};
1190               if fd = ST0 then () else emit(fstp(fty, I.FDirect fd))               if fd = ST0 then () else emit(fstp(fty, I.FDirect fd))
1191              )              )
1192          | doFexpr(fty, e, fd, an) =          | doFexpr'(fty, e, fd, an) =
1193              (reduceFexp(fty, e, []);              (reduceFexp(fty, e, []);
1194               if fd = ST0 then () else mark(fstp(fty, I.FDirect fd), an)               if fd = ST0 then () else mark(fstp(fty, I.FDirect fd), an)
1195              )              )
# Line 1122  Line 1245 
1245                    in  (annotate(t, a), integer) end                    in  (annotate(t, a), integer) end
1246                  | suFold e = (su e, false)                  | suFold e = (su e, false)
1247    
               (* Can the tree be folded into the src operand? *)  
               and foldable(T.FREG _) = true  
                 | foldable(T.FLOAD _) = true  
                 | foldable(T.CVTI2F(_, (16 | 32), _)) = true  
                 | foldable(T.CVTF2F(_, _, t)) = foldable t  
                 | foldable(T.FMARK(t, _)) = foldable t  
                 | foldable _ = false  
   
1248                (* Form unary tree *)                (* Form unary tree *)
1249                and suUnary(fty, funary, t) =                and suUnary(fty, funary, t) =
1250                    let val t = su t                    let val t = su t
# Line 1151  Line 1266 
1266                 * This only applies to commutative operations.                 * This only applies to commutative operations.
1267                 *)                 *)
1268                and suComBinary(fty, binop, ibinop, t1, t2) =                and suComBinary(fty, binop, ibinop, t1, t2) =
1269                    let val (t1, t2) = if foldable t2 then (t1, t2) else (t2, t1)                    let val (t1, t2) = if foldableFexp t2
1270                                         then (t1, t2) else (t2, t1)
1271                    in  suBinary(fty, binop, ibinop, t1, t2) end                    in  suBinary(fty, binop, ibinop, t1, t2) end
1272    
1273                and sameTree(LEAF(_, T.FREG(t1,f1), []),                and sameTree(LEAF(_, T.FREG(t1,f1), []),
# Line 1236  Line 1352 
1352                  | leafEA(T.CVTI2F(_, 8, t))  = int2real(8, t)                  | leafEA(T.CVTI2F(_, 8, t))  = int2real(8, t)
1353                  | leafEA _ = error "leafEA"                  | leafEA _ = error "leafEA"
1354    
1355                (* Move integer t of size ty into a memory location *)                and int2real(ty, e) =
1356                and int2real(ty, t) =                    let val (_, ty, ea, cleanup) = convertIntToFloat(ty, e)
1357                    let val opnd = operand t                    in  cleanupCode := !cleanupCode @ cleanup;
1358                    in  if isMemOpnd opnd andalso (ty = 16 orelse ty = 32)                        (INTEGER, ty, ea)
                       then (INTEGER, ty, opnd)  
                       else  
                         let val {instrs, tempMem, cleanup} =  
                                    cvti2f{ty=ty, src=opnd}  
                         in  app emit instrs;  
                             cleanupCode := !cleanupCode @ cleanup;  
                             (INTEGER, 32, tempMem)  
                         end  
1359                    end                    end
1360    
1361            in  gencode(su fexp);            in  gencode(su fexp);
1362                app emit(!cleanupCode)               emits(!cleanupCode)
1363            end (*reduceFexp*)            end (*reduceFexp*)
1364    
1365           (*========================================================
1366            * This section generates 3-address style floating
1367            * point code.
1368            *========================================================*)
1369    
1370          and isize 16 = I.I16
1371            | isize 32 = I.I32
1372            | isize _  = error "isize"
1373    
1374          and fstore''(fty, ea, d, mem, an) =
1375              (floatingPointUsed := true;
1376               mark(I.FMOVE{fsize=fsize fty, dst=address(ea,mem),
1377                            src=foperand(fty, d)},
1378                    an)
1379              )
1380    
1381          and fload''(fty, ea, mem, d, an) =
1382              (floatingPointUsed := true;
1383               mark(I.FMOVE{fsize=fsize fty, src=address(ea,mem),
1384                            dst=RealReg d}, an)
1385              )
1386    
1387          and fiload''(ity, ea, d, an) =
1388              (floatingPointUsed := true;
1389               mark(I.FILOAD{isize=isize ity, ea=ea, dst=RealReg d}, an)
1390              )
1391    
1392          and fexpr''(e as T.FREG(_,f)) =
1393              if isFMemReg f then transFexpr e else f
1394            | fexpr'' e = transFexpr e
1395    
1396          and transFexpr e =
1397              let val fd = newFreg() in doFexpr''(64, e, fd, []); fd end
1398    
1399             (*
1400              * Process a floating point operand.  Put operand in register
1401              * when possible.  The operand should match the given fty.
1402              *)
1403          and foperand(fty, e as T.FREG(fty', f)) =
1404                 if fty = fty' then RealReg f else I.FPR(fexpr'' e)
1405            | foperand(fty, T.CVTF2F(_, _, e)) =
1406                 foperand(fty, e) (* nop on the x86 *)
1407            | foperand(fty, e as T.FLOAD(fty', ea, mem)) =
1408                 (* fold operand when the precison matches *)
1409                 if fty = fty' then address(ea, mem) else I.FPR(fexpr'' e)
1410            | foperand(fty, e) = I.FPR(fexpr'' e)
1411    
1412             (*
1413              * Process a floating point operand.
1414              * Try to fold in a memory operand or conversion from an integer.
1415              *)
1416          and fioperand(T.FREG(fty,f)) = (REAL, fty, RealReg f, [])
1417            | fioperand(T.FLOAD(fty, ea, mem)) =
1418                 (REAL, fty, address(ea, mem), [])
1419            | fioperand(T.CVTF2F(_, _, e)) = fioperand(e) (* nop on the x86 *)
1420            | fioperand(T.CVTI2F(_, ty, e)) = convertIntToFloat(ty, e)
1421            | fioperand(T.FMARK(e,an)) = fioperand(e) (* XXX *)
1422            | fioperand(e) = (REAL, 64, I.FPR(fexpr'' e), [])
1423    
1424              (* Generate binary operator.  Since the real binary operators
1425               * does not take memory as destination, we also ensure this
1426               * does not happen.
1427               *)
1428          and fbinop(targetFty,
1429                     binOp, binOpR, ibinOp, ibinOpR, lsrc, rsrc, fd, an) =
1430                  (* Put the mem operand in rsrc *)
1431              let val _ = floatingPointUsed := true;
1432                  fun isMemOpnd(T.FREG(_, f)) = isFMemReg f
1433                    | isMemOpnd(T.FLOAD _) = true
1434                    | isMemOpnd(T.CVTI2F(_, (16 | 32), _)) = true
1435                    | isMemOpnd(T.CVTF2F(_, _, t)) = isMemOpnd t
1436                    | isMemOpnd(T.FMARK(t, _)) = isMemOpnd t
1437                    | isMemOpnd _ = false
1438                  val (binOp, ibinOp, lsrc, rsrc) =
1439                      if isMemOpnd lsrc then (binOpR, ibinOpR, rsrc, lsrc)
1440                      else (binOp, ibinOp, lsrc, rsrc)
1441                  val lsrc = foperand(targetFty, lsrc)
1442                  val (kind, fty, rsrc, code) = fioperand(rsrc)
1443                  fun dstMustBeFreg f =
1444                      if targetFty <> 64 then
1445                      let val tmpR = newFreg()
1446                          val tmp  = I.FPR tmpR
1447                      in  mark(f tmp, an);
1448                          emit(I.FMOVE{fsize=fsize targetFty,
1449                                       src=tmp, dst=RealReg fd})
1450                      end
1451                      else mark(f(RealReg fd), an)
1452              in  case kind of
1453                    REAL =>
1454                      dstMustBeFreg(fn dst =>
1455                                       I.FBINOP{fsize=fsize fty, binOp=binOp,
1456                                                lsrc=lsrc, rsrc=rsrc, dst=dst})
1457                  | INTEGER =>
1458                      (dstMustBeFreg(fn dst =>
1459                                        I.FIBINOP{isize=isize fty, binOp=ibinOp,
1460                                                  lsrc=lsrc, rsrc=rsrc, dst=dst});
1461                       emits code
1462                      )
1463              end
1464    
1465          and funop(fty, unOp, src, fd, an) =
1466              let val src = foperand(fty, src)
1467              in  mark(I.FUNOP{fsize=fsize fty,
1468                               unOp=unOp, src=src, dst=RealReg fd},an)
1469              end
1470    
1471          and doFexpr''(fty, e, fd, an) =
1472              case e of
1473                T.FREG(_,fs) => if fs = fd then ()
1474                                else fcopy''(fty, [fd], [fs], an)
1475                (* Stupid x86 does everything as 80-bits internally. *)
1476    
1477                (* Binary operators *)
1478              | T.FADD(_, a, b) => fbinop(fty,
1479                                          I.FADDL, I.FADDL, I.FIADDL, I.FIADDL,
1480                                          a, b, fd, an)
1481              | T.FSUB(_, a, b) => fbinop(fty,
1482                                          I.FSUBL, I.FSUBRL, I.FISUBL, I.FISUBRL,
1483                                          a, b, fd, an)
1484              | T.FMUL(_, a, b) => fbinop(fty,
1485                                          I.FMULL, I.FMULL, I.FIMULL, I.FIMULL,
1486                                          a, b, fd, an)
1487              | T.FDIV(_, a, b) => fbinop(fty,
1488                                          I.FDIVL, I.FDIVRL, I.FIDIVL, I.FIDIVRL,
1489                                          a, b, fd, an)
1490    
1491                (* Unary operators *)
1492              | T.FNEG(_, a) => funop(fty, I.FCHS, a, fd, an)
1493              | T.FABS(_, a) => funop(fty, I.FABS, a, fd, an)
1494              | T.FSQRT(_, a) => funop(fty, I.FSQRT, a, fd, an)
1495    
1496                (* Load *)
1497              | T.FLOAD(fty,ea,mem) => fload''(fty, ea, mem, fd, an)
1498    
1499                (* Type conversions *)
1500              | T.CVTF2F(_, _, e) => doFexpr''(fty, e, fd, an)
1501              | T.CVTI2F(_, ty, e) =>
1502                let val (_, ty, ea, cleanup) = convertIntToFloat(ty, e)
1503                in  fiload''(ty, ea, fd, an);
1504                    emits cleanup
1505                end
1506    
1507              | T.FMARK(e,A.MARKREG f) => (f fd; doFexpr''(fty, e, fd, an))
1508              | T.FMARK(e, a) => doFexpr''(fty, e, fd, a::an)
1509              | T.FPRED(e, c) => doFexpr''(fty, e, fd, A.CTRLUSE c::an)
1510              | T.FEXT fexp =>
1511                 ExtensionComp.compileFext (reducer()) {e=fexp, fd=fd, an=an}
1512              | _ => error("doFexpr''")
1513    
1514           (*========================================================
1515            * Tie the two styles of fp code generation together
1516            *========================================================*)
1517          and fstore(fty, ea, d, mem, an) =
1518              if enableFastFPMode andalso !fast_floating_point
1519              then fstore''(fty, ea, d, mem, an)
1520              else fstore'(fty, ea, d, mem, an)
1521          and fload(fty, ea, d, mem, an) =
1522              if enableFastFPMode andalso !fast_floating_point
1523              then fload''(fty, ea, d, mem, an)
1524              else fload'(fty, ea, d, mem, an)
1525          and fexpr e =
1526              if enableFastFPMode andalso !fast_floating_point
1527              then fexpr'' e else fexpr' e
1528          and doFexpr(fty, e, fd, an) =
1529              if enableFastFPMode andalso !fast_floating_point
1530              then doFexpr''(fty, e, fd, an)
1531              else doFexpr'(fty, e, fd, an)
1532    
1533            (* generate code for a statement *)            (* generate code for a statement *)
1534        and stmt(T.MV(_, rd, e), an) = doExpr(e, rd, an)        and stmt(T.MV(_, rd, e), an) = doExpr(e, rd, an)
1535          | stmt(T.FMV(fty, fd, e), an) = doFexpr(fty, e, fd, an)          | stmt(T.FMV(fty, fd, e), an) = doFexpr(fty, e, fd, an)
# Line 1281  Line 1558 
1558           ((* Must be cleared by the client.           ((* Must be cleared by the client.
1559             * if rewriteMemReg then memRegsUsed := 0w0 else ();             * if rewriteMemReg then memRegsUsed := 0w0 else ();
1560             *)             *)
1561            trapLabel := NONE; beginCluster 0)            floatingPointUsed := false;
1562              trapLabel := NONE;
1563              beginCluster 0
1564             )
1565        and endCluster' a =        and endCluster' a =
1566           (case !trapLabel           (case !trapLabel
1567            of NONE => ()            of NONE => ()
1568             | SOME(_, lab) => (defineLabel lab; emit(I.INTO))             | SOME(_, lab) => (defineLabel lab; emit(I.INTO))
1569            (*esac*);            (*esac*);
1570              (* If floating point has been used allocate an extra
1571               * register just in case we didn't use any explicit register
1572               *)
1573              if !floatingPointUsed then (newFreg(); ())
1574              else ();
1575            endCluster(a)            endCluster(a)
1576           )           )
1577    

Legend:
Removed from v.730  
changed lines
  Added in v.731

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0