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 1003, Fri Dec 7 02:45:32 2001 UTC revision 1185, Mon Apr 1 22:06:47 2002 UTC
# Line 1  Line 1 
1  (*  (* x86.sml
2   *   *
3   * COPYRIGHT (c) 1998 Bell Laboratories.   * COPYRIGHT (c) 1998 Bell Laboratories.
4   *   *
# Line 12  Line 12 
12   *   *
13   * Some changes:   * Some changes:
14   *   *
15   *  1.  REMU/REMS/REMT are now supported   *  1.  REMU/REMS are now supported
16   *  2.  COND is supported by generating SETcc and/or CMOVcc; this   *  2.  COND is supported by generating SETcc and/or CMOVcc; this
17   *      may require at least a Pentium II to work.   *      may require at least a Pentium II to work.
18   *  3.  Division by a constant has been optimized.   Division by   *  3.  Division by a constant has been optimized.   Division by
# Line 82  Line 82 
82    
83    structure Gen = MLTreeGen    structure Gen = MLTreeGen
84       (structure T = T       (structure T = T
85          structure Cells = C
86        val intTy = 32        val intTy = 32
87        val naturalWidths = [32]        val naturalWidths = [32]
88        datatype rep = SE | ZE | NEITHER        datatype rep = SE | ZE | NEITHER
# Line 149  Line 150 
150    
151        (* Add an overflow trap *)        (* Add an overflow trap *)
152        fun trap() =        fun trap() =
153        let val jmp =        let
154              val jmp =
155              case !trapLabel of              case !trapLabel of
156                NONE => let val label = Label.label "trap" ()                NONE => let val label = Label.label "trap" ()
157                            val jmp   = I.jcc{cond=I.O,                            val jmp   =
158                                              opnd=I.ImmedLabel(T.LABEL label)}                                I.ANNOTATION{i=I.jcc{cond=I.O,
159                                                       opnd=I.ImmedLabel(T.LABEL label)},
160                                               a=MLRiscAnnotations.BRANCHPROB (Probability.unlikely)}
161                        in  trapLabel := SOME(jmp, label); jmp end                        in  trapLabel := SOME(jmp, label); jmp end
162              | SOME(jmp, _) => jmp              | SOME(jmp, _) => jmp
163        in  emitInstruction jmp end        in  emitInstruction jmp end
# Line 167  Line 171 
171          | fsize _  = error "fsize"          | fsize _  = error "fsize"
172    
173        (* mark an expression with a list of annotations *)        (* mark an expression with a list of annotations *)
174        fun mark'(i,[]) = i        fun mark'(i,[]) = emitInstruction(i)
175          | mark'(i,a::an) = mark'(I.ANNOTATION{i=i,a=a},an)          | mark'(i,a::an) = mark'(I.ANNOTATION{i=i,a=a},an)
176    
177        (* annotate an expression and emit it *)        (* annotate an expression and emit it *)
178        fun mark(i,an) = emitInstruction(mark'(I.INSTR i,an))        fun mark(i,an) = mark'(I.INSTR i,an)
179    
180        val emits = app emitInstruction        val emits = app emitInstruction
181    
# Line 189  Line 193 
193                    end                    end
194                  | mvInstr{dst=I.Direct rd, src=I.Direct rs} =                  | mvInstr{dst=I.Direct rd, src=I.Direct rs} =
195                      if CB.sameColor(rd,rs) then []                      if CB.sameColor(rd,rs) then []
196                      else [I.copy{dst=[rd], src=[rs], tmp=NONE}]                      else [I.COPY{k=CB.GP, sz=32, dst=[rd], src=[rs], tmp=NONE}]
197                  | mvInstr{dst, src} = [I.move{mvOp=I.MOVL, src=src, dst=dst}]                  | mvInstr{dst, src} = [I.move{mvOp=I.MOVL, src=src, dst=dst}]
198            in            in
199               emits (Shuffle.shuffle{mvInstr=mvInstr, ea=IntReg}               emits (Shuffle.shuffle{mvInstr=mvInstr, ea=IntReg}
# Line 251  Line 255 
255         *)         *)
256        fun fcopy'(fty, [], [], _) = ()        fun fcopy'(fty, [], [], _) = ()
257          | fcopy'(fty, dst as [_], src as [_], an) =          | fcopy'(fty, dst as [_], src as [_], an) =
258              mark(I.FCOPY{dst=dst,src=src,tmp=NONE}, an)              mark'(I.COPY{k=CB.FP, sz=fty, dst=dst,src=src,tmp=NONE}, an)
259          | fcopy'(fty, dst, src, an) =          | fcopy'(fty, dst, src, an) =
260              mark(I.FCOPY{dst=dst,src=src,tmp=SOME(I.FDirect(newFreg()))}, an)              mark'(I.COPY{k=CB.FP, sz=fty, dst=dst,src=src,tmp=SOME(I.FDirect(newFreg()))}, an)
261    
262        (* emit parallel copies for floating point.        (* emit parallel copies for floating point.
263         * Fast version.         * Fast version.
# Line 274  Line 278 
278                   dst=dst, src=src})                   dst=dst, src=src})
279            end            end
280            else            else
281              mark(I.FCOPY{dst=dst,src=src,tmp=              mark'(I.COPY{k=CB.FP, sz=fty, dst=dst,
282                            src=src,tmp=
283                           case dst of                           case dst of
284                             [_] => NONE                             [_] => NONE
285                           | _   => SOME(I.FPR(newFreg()))}, an)                           | _   => SOME(I.FPR(newFreg()))}, an)
# Line 288  Line 293 
293          | cond T.EQ = I.EQ | cond T.NE  = I.NE          | cond T.EQ = I.EQ | cond T.NE  = I.NE
294          | cond T.GE = I.GE | cond T.GEU = I.AE          | cond T.GE = I.GE | cond T.GEU = I.AE
295          | cond T.GT = I.GT | cond T.GTU = I.A          | cond T.GT = I.GT | cond T.GTU = I.A
296            | cond cc = error(concat["cond(", T.Basis.condToString cc, ")"])
297    
298        fun zero dst = emit(I.BINARY{binOp=I.XORL, src=dst, dst=dst})        fun zero dst = emit(I.BINARY{binOp=I.XORL, src=dst, dst=dst})
299    
300        (* Move and annotate *)        (* Move and annotate *)
301        fun move'(src as I.Direct s, dst as I.Direct d, an) =        fun move'(src as I.Direct s, dst as I.Direct d, an) =
302            if CB.sameColor(s,d) then ()            if CB.sameColor(s,d) then ()
303            else mark(I.COPY{dst=[d], src=[s], tmp=NONE}, an)            else mark'(I.COPY{k=CB.GP, sz=32, dst=[d], src=[s], tmp=NONE}, an)
304          | move'(I.Immed 0, dst as I.Direct d, an) =          | move'(I.Immed 0, dst as I.Direct d, an) =
305              mark(I.BINARY{binOp=I.XORL, src=dst, dst=dst}, an)              mark(I.BINARY{binOp=I.XORL, src=dst, dst=dst}, an)
306          | move'(src, dst, an) = mark(I.MOVE{mvOp=I.MOVL, src=src, dst=dst}, an)          | move'(src, dst, an) = mark(I.MOVE{mvOp=I.MOVL, src=src, dst=dst}, an)
# Line 545  Line 551 
551                    if overflow then trap() else ()                    if overflow then trap() else ()
552                end                end
553    
554                  (* division with rounding towards negative infinity *)
555                  fun divinf0 (overflow, e1, e2) = let
556                      val o1 = operand e1
557                      val o2 = operand e2
558                      val l = Label.anon ()
559                  in
560                      move (o1, eax);
561                      emit I.CDQ;
562                      mark (I.MULTDIV { multDivOp = I.IDIVL1, src = regOrMem o2 },
563                            an);
564                      if overflow then trap() else ();
565                      app emit [I.CMPL { lsrc = edx, rsrc = I.Immed 0 },
566                                I.JCC { cond = I.EQ, opnd = immedLabel l },
567                                I.BINARY { binOp = I.XORL,
568                                           src = regOrMem o2,
569                                           dst = edx },
570                                I.JCC { cond = I.GE, opnd = immedLabel l },
571                                I.UNARY { unOp = I.DECL, opnd = eax }];
572                      defineLabel l;
573                      move (eax, rdOpnd)
574                  end
575    
576                  (* analyze for power-of-two-ness *)
577                  fun analyze i' = let
578                      val i = toInt32 i'
579                  in
580                      let val (isneg, a, w) =
581                              if i >= 0 then (false, i, T.I.toWord32 (32, i'))
582                              else (true, ~i, T.I.toWord32 (32, T.I.NEG (32,  i')))
583                          fun log2 (0w1, p) = p
584                            | log2 (w, p) = log2 (W32.>> (w, 0w1), p + 1)
585                      in
586                          if w > 0w1 andalso W32.andb (w - 0w1, w) = 0w0 then
587                              (i, SOME (isneg, a,
588                                        T.LI (T.I.fromInt32 (32, log2 (w, 0)))))
589                          else (i, NONE)
590                      end handle _ => (i, NONE)
591                  end
592    
593                  (* Division by a power of two when rounding to neginf is the
594                   * same as an arithmetic right shift. *)
595                  fun divinf (overflow, e1, e2 as T.LI n') =
596                      (case analyze n' of
597                           (_, NONE) => divinf0 (overflow, e1, e2)
598                         | (_, SOME (false, _, p)) =>
599                           shift (I.SARL, T.REG (32, expr e1), p)
600                         | (_, SOME (true, _, p)) => let
601                               val reg = expr e1
602                           in
603                              emit(I.UNARY { unOp = I.NEGL, opnd = I.Direct reg });
604                              shift (I.SARL, T.REG (32, reg), p)
605                           end)
606                    | divinf (overflow, e1, e2) = divinf0 (overflow, e1, e2)
607    
608                  fun reminf0 (e1, e2) = let
609                      val o1 = operand e1
610                      val o2 = operand e2
611                      val l = Label.anon ()
612                  in
613                      move (o1, eax);
614                      emit I.CDQ;
615                      mark (I.MULTDIV { multDivOp = I.IDIVL1, src = regOrMem o2 },
616                            an);
617                      app emit [I.CMPL { lsrc = edx, rsrc = I.Immed 0 },
618                                I.JCC { cond = I.EQ, opnd = immedLabel l }];
619                      move (edx, eax);
620                      app emit [I.BINARY { binOp = I.XORL,
621                                           src = regOrMem o2, dst = eax },
622                                I.JCC { cond = I.GE, opnd = immedLabel l },
623                                I.BINARY { binOp = I.ADDL,
624                                           src = regOrMem o2, dst = edx }];
625                      defineLabel l;
626                      move (edx, rdOpnd)
627                  end
628    
629                  (* n mod (power-of-2) corresponds to a bitmask (AND).
630                   * If the power is negative, then we must first negate
631                   * the argument and then again negate the result. *)
632                  fun reminf (e1, e2 as T.LI n') =
633                      (case analyze n' of
634                           (_, NONE) => reminf0 (e1, e2)
635                         | (_, SOME (false, a, _)) =>
636                           binaryComm (I.ANDL, e1,
637                                               T.LI (T.I.fromInt32 (32, a - 1)))
638                         | (_, SOME (true, a, _)) => let
639                               val r1 = expr e1
640                               val o1 = I.Direct r1
641                           in
642                               emit (I.UNARY { unOp = I.NEGL, opnd = o1 });
643                               emit (I.BINARY { binOp = I.ANDL,
644                                                src = I.Immed (a - 1),
645                                                dst = o1 });
646                               unary (I.NEGL, T.REG (32, r1))
647                           end)
648                    | reminf (e1, e2) = reminf0 (e1, e2)
649    
650                    (* Optimize the special case for division *)                    (* Optimize the special case for division *)
651                fun divide(signed, overflow, e1, e2 as T.LI n') = let                fun divide (signed, overflow, e1, e2 as T.LI n') =
652                    val n = toInt32 n'                    (case analyze n' of
653                    val w = T.I.toWord32(32, n')                         (n, SOME (isneg, a, p)) =>
654                    fun isPowerOf2 w = W32.andb((w - 0w1), w) = 0w0                         if signed then
                   fun log2 n =  (* n must be > 0!!! *)  
                       let fun loop(0w1,pow) = pow  
                             | loop(w,pow) = loop(W32.>>(w, 0w1),pow+1)  
                       in loop(n,0) end  
               in  if n > 1 andalso isPowerOf2 w then  
                      let val pow = T.LI(T.I.fromInt(32,log2 w))  
                      in  if signed then  
                          (* signed; simulate round towards zero *)  
655                           let val label = Label.anon()                           let val label = Label.anon()
656                               val reg1  = expr e1                               val reg1  = expr e1
657                               val opnd1 = I.Direct reg1                               val opnd1 = I.Direct reg1
658                           in  if setZeroBit e1 then ()                             in
659                               else emit(I.CMPL{lsrc=opnd1, rsrc=I.Immed 0});                                 if isneg then
660                               emit(I.JCC{cond=I.GE, opnd=immedLabel label});                                     emit (I.UNARY { unOp = I.NEGL,
661                               emit(if n = 2 then                                                     opnd = opnd1 })
662                                       I.UNARY{unOp=I.INCL, opnd=opnd1}                                 else if setZeroBit e1 then ()
663                                   else emit (I.CMPL { lsrc = opnd1,
664                                                       rsrc = I.Immed 0 });
665                                   emit (I.JCC { cond = I.GE,
666                                                 opnd = immedLabel label });
667                                   emit (if a = 2 then
668                                             I.UNARY { unOp = I.INCL,
669                                                       opnd = opnd1 }
670                                    else                                    else
671                                       I.BINARY{binOp=I.ADDL,                                       I.BINARY{binOp=I.ADDL,
672                                                src=I.Immed(n - 1),                                                      src = I.Immed (a - 1),
673                                                dst=opnd1});                                                dst=opnd1});
674                               defineLabel label;                               defineLabel label;
675                               shift(I.SARL, T.REG(32, reg1), pow)                                 shift (I.SARL, T.REG (32, reg1), p)
676                           end                           end
677                           else (* unsigned *)                         else shift (I.SHRL, e1, p)
678                              shift(I.SHRL, e1, pow)                       | (n, NONE) =>
                      end  
                   else  
                        (* note the only way we can overflow is if  
                         * n = 0 or n = -1  
                         *)  
679                       divrem(signed, overflow andalso (n = ~1 orelse n = 0),                       divrem(signed, overflow andalso (n = ~1 orelse n = 0),
680                              e1, e2, eax)                                e1, e2, eax))
               end  
681                  | divide(signed, overflow, e1, e2) =                  | divide(signed, overflow, e1, e2) =
682                      divrem(signed, overflow, e1, e2, eax)                      divrem(signed, overflow, e1, e2, eax)
683    
684                fun rem(signed, overflow, e1, e2) =                (* rem never causes overflow *)
685                      divrem(signed, overflow, e1, e2, edx)                fun rem (signed, e1, e2 as T.LI n') =
686                      (case analyze n' of
687                           (n, SOME (isneg, a, _)) =>
688                           if signed then
689                               (* The following logic should work uniformely
690                                * for both isneg and not isneg.  It only uses
691                                * the absolute value (a) of the divisor.
692                                * Here is the formula:
693                                *    let p be a power of two and a = abs(p):
694                                *
695                                *    x % p = x - ((x < 0 ? x + a - 1 : x) & (-a))
696                                *
697                                * (That's what GCC seems to do.)
698                                *)
699                               let val r1 = expr e1
700                                   val o1 = I.Direct r1
701                                   val rt = newReg ()
702                                   val tmp = I.Direct rt
703                                   val l = Label.anon ()
704                               in
705                                   move (o1, tmp);
706                                   if setZeroBit e1 then ()
707                                   else emit (I.CMPL { lsrc = o1,
708                                                       rsrc = I.Immed 0 });
709                                   emit (I.JCC { cond = I.GE,
710                                                 opnd = immedLabel l });
711                                   emit (I.BINARY { binOp = I.ADDL,
712                                                    src = I.Immed (a - 1),
713                                                    dst = tmp });
714                                   defineLabel l;
715                                   emit (I.BINARY { binOp = I.ANDL,
716                                                    src = I.Immed (~a),
717                                                    dst = tmp });
718                                   binary (I.SUBL, T.REG (32, rt), T.REG (32, r1))
719                               end
720                           else
721                               if isneg then
722                                   (* this is really strange... *)
723                                   divrem (false, false, e1, e2, edx)
724                               else
725                                   binaryComm (I.ANDL, e1,
726                                               T.LI (T.I.fromInt32 (32, n - 1)))
727                         | (_, NONE) => divrem (signed, false, e1, e2, edx))
728                    | rem(signed, e1, e2) =
729                      divrem(signed, false, e1, e2, edx)
730    
731                    (* Makes sure the destination must be a register *)                    (* Makes sure the destination must be a register *)
732                fun dstMustBeReg f =                fun dstMustBeReg f =
# Line 598  Line 737 
737                    else f(rd, rdOpnd)                    else f(rd, rdOpnd)
738    
739                    (* unsigned integer multiplication *)                    (* unsigned integer multiplication *)
740                fun uMultiply(e1, e2) =                fun uMultiply0 (e1, e2) =
741                    (* note e2 can never be (I.Direct edx) *)                    (* note e2 can never be (I.Direct edx) *)
742                    (move(operand e1, eax);                    (move(operand e1, eax);
743                     mark(I.MULTDIV{multDivOp=I.MULL1,                     mark(I.MULTDIV{multDivOp=I.MULL1,
# Line 606  Line 745 
745                     move(eax, rdOpnd)                     move(eax, rdOpnd)
746                    )                    )
747    
748                  fun uMultiply (e1, e2 as T.LI n') =
749                      (case analyze n' of
750                           (_, SOME (false, _, p)) => shift (I.SHLL, e1, p)
751                         | _ => uMultiply0 (e1, e2))
752                    | uMultiply (e1 as T.LI _, e2) = uMultiply (e2, e1)
753                    | uMultiply (e1, e2) = uMultiply0 (e1, e2)
754    
755                    (* signed integer multiplication:                    (* signed integer multiplication:
756                     * The only forms that are allowed that also sets the                     * The only forms that are allowed that also sets the
757                     * OF and CF flags are:                     * OF and CF flags are:
# Line 650  Line 796 
796                end                end
797                )                )
798    
799                  fun multiply_notrap (e1, e2 as T.LI n') =
800                      (case analyze n' of
801                           (_, SOME (isneg, _, p)) => let
802                               val r1 = expr e1
803                               val o1 = I.Direct r1
804                           in
805                               if isneg then
806                                   emit (I.UNARY { unOp = I.NEGL, opnd = o1 })
807                               else ();
808                               shift (I.SHLL, T.REG (32, r1), p)
809                           end
810                         | _ => multiply (e1, e2))
811                    | multiply_notrap (e1 as T.LI _, e2) = multiply_notrap (e2, e1)
812                    | multiply_notrap (e1, e2) = multiply (e1, e2)
813    
814                   (* Emit a load instruction; makes sure that the destination                   (* Emit a load instruction; makes sure that the destination
815                    * is a register                    * is a register
816                    *)                    *)
# Line 759  Line 920 
920                let fun genCmov(dstR, _) =                let fun genCmov(dstR, _) =
921                    let val _ = doExpr(no, dstR, []) (* false branch *)                    let val _ = doExpr(no, dstR, []) (* false branch *)
922                        val cc = cmp(true, ty, cc, t1, t2, [])  (* compare *)                        val cc = cmp(true, ty, cc, t1, t2, [])  (* compare *)
923                    in  mark(I.CMOV{cond=cond cc, src=operand yes, dst=dstR}, an)                    in  mark(I.CMOV{cond=cond cc, src=regOrMem(operand yes),
924                                      dst=dstR}, an)
925                    end                    end
926                in  dstMustBeReg genCmov                in  dstMustBeReg genCmov
927                end                end
# Line 868  Line 1030 
1030    
1031               | T.MULU(32, x, y) => uMultiply(x, y)               | T.MULU(32, x, y) => uMultiply(x, y)
1032               | T.DIVU(32, x, y) => divide(false, false, x, y)               | T.DIVU(32, x, y) => divide(false, false, x, y)
1033               | T.REMU(32, x, y) => rem(false, false, x, y)               | T.REMU(32, x, y) => rem(false, x, y)
1034    
1035               | T.MULS(32, x, y) => multiply(x, y)               | T.MULS(32, x, y) => multiply_notrap (x, y)
1036               | T.DIVS(32, x, y) => divide(true, false, x, y)               | T.DIVS(T.DIV_TO_ZERO, 32, x, y) => divide(true, false, x, y)
1037               | T.REMS(32, x, y) => rem(true, false, x, y)               | T.DIVS(T.DIV_TO_NEGINF, 32, x, y) => divinf (false, x, y)
1038                 | T.REMS(T.DIV_TO_ZERO, 32, x, y) => rem(true, x, y)
1039                 | T.REMS(T.DIV_TO_NEGINF, 32, x, y) => reminf (x, y)
1040    
1041               | T.ADDT(32, x, y) => (binaryComm(I.ADDL, x, y); trap())               | T.ADDT(32, x, y) => (binaryComm(I.ADDL, x, y); trap())
1042               | T.SUBT(32, x, y) => (binary(I.SUBL, x, y); trap())               | T.SUBT(32, x, y) => (binary(I.SUBL, x, y); trap())
1043               | T.MULT(32, x, y) => (multiply(x, y); trap())               | T.MULT(32, x, y) => (multiply(x, y); trap())
1044               | T.DIVT(32, x, y) => divide(true, true, x, y)               | T.DIVT(T.DIV_TO_ZERO, 32, x, y) => divide(true, true, x, y)
1045               | T.REMT(32, x, y) => rem(true, true, x, y)               | T.DIVT(T.DIV_TO_NEGINF, 32, x, y) => divinf (true, x, y)
1046    
1047               | T.ANDB(32, x, y) => binaryComm(I.ANDL, x, y)               | T.ANDB(32, x, y) => binaryComm(I.ANDL, x, y)
1048               | T.ORB(32, x, y)  => binaryComm(I.ORL, x, y)               | T.ORB(32, x, y)  => binaryComm(I.ORL, x, y)
# Line 898  Line 1062 
1062               | T.ZX(32,8,T.LOAD(8,ea,mem)) => load8(ea, mem)               | T.ZX(32,8,T.LOAD(8,ea,mem)) => load8(ea, mem)
1063               | T.ZX(32,16,T.LOAD(16,ea,mem)) => load16(ea, mem)               | T.ZX(32,16,T.LOAD(16,ea,mem)) => load16(ea, mem)
1064    
1065               | T.COND(32, T.CMP(ty, cc, t1, t2), T.LI yes, T.LI no) =>               | T.COND(32, T.CMP(ty, cc, t1, t2), y as T.LI yes, n as T.LI no) =>
1066                   setcc(ty, cc, t1, t2, toInt32 yes, toInt32 no)                  (case !arch of (* PentiumPro and higher has CMOVcc *)
1067                      Pentium => setcc(ty, cc, t1, t2, toInt32 yes, toInt32 no)
1068                    | _ => cmovcc(ty, cc, t1, t2, y, n)
1069                    )
1070               | T.COND(32, T.CMP(ty, cc, t1, t2), yes, no) =>               | T.COND(32, T.CMP(ty, cc, t1, t2), yes, no) =>
1071                  (case !arch of (* PentiumPro and higher has CMOVcc *)                  (case !arch of (* PentiumPro and higher has CMOVcc *)
1072                     Pentium => unknownExp exp                     Pentium => unknownExp exp
# Line 1115  Line 1282 
1282    
1283            (* generate code for floating point compare and branch *)            (* generate code for floating point compare and branch *)
1284        and fbranch(fty, fcc, t1, t2, lab, an) =        and fbranch(fty, fcc, t1, t2, lab, an) =
1285              let fun j cc = mark(I.JCC{cond=cc, opnd=immedLabel lab},an)
1286              in  fbranching(fty, fcc, t1, t2, j)
1287              end
1288    
1289          and fbranching(fty, fcc, t1, t2, j) =
1290            let fun ignoreOrder (T.FREG _) = true            let fun ignoreOrder (T.FREG _) = true
1291                  | ignoreOrder (T.FLOAD _) = true                  | ignoreOrder (T.FLOAD _) = true
1292                  | ignoreOrder (T.FMARK(e,_)) = ignoreOrder e                  | ignoreOrder (T.FMARK(e,_)) = ignoreOrder e
# Line 1136  Line 1308 
1308                        val rsrc = foperand(fty, t2)                        val rsrc = foperand(fty, t2)
1309                        val fsize = fsize fty                        val fsize = fsize fty
1310                        fun cmp(lsrc, rsrc, fcc) =                        fun cmp(lsrc, rsrc, fcc) =
1311                            (emit(I.FCMP{fsize=fsize,lsrc=lsrc,rsrc=rsrc}); fcc)                        let val i = !arch <> Pentium
1312                          in  emit(I.FCMP{i=i,fsize=fsize,lsrc=lsrc,rsrc=rsrc});
1313                              fcc
1314                          end
1315                    in  case (lsrc, rsrc) of                    in  case (lsrc, rsrc) of
1316                           (I.FPR _, I.FPR _) => cmp(lsrc, rsrc, fcc)                           (I.FPR _, I.FPR _) => cmp(lsrc, rsrc, fcc)
1317                         | (I.FPR _, mem) => cmp(mem,lsrc,T.Basis.swapFcond fcc)                         | (I.FPR _, mem) => cmp(mem,lsrc,T.Basis.swapFcond fcc)
# Line 1157  Line 1332 
1332                fun testil i = emit(I.TESTL{lsrc=eax,rsrc=I.Immed(i)})                fun testil i = emit(I.TESTL{lsrc=eax,rsrc=I.Immed(i)})
1333                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})
1334                fun cmpil i = emit(I.CMPL{rsrc=I.Immed(i), lsrc=eax})                fun cmpil i = emit(I.CMPL{rsrc=I.Immed(i), lsrc=eax})
               fun j(cc, lab) = mark(I.JCC{cond=cc, opnd=immedLabel lab},an)  
1335                fun sahf() = emit(I.SAHF)                fun sahf() = emit(I.SAHF)
1336                fun branch(fcc) =                fun branch(fcc) =
1337                    case fcc                    case fcc
1338                    of T.==   => (andil 0x4400; xoril 0x4000; j(I.EQ, lab))                    of T.==   => (andil 0x4400; xoril 0x4000; j(I.EQ))
1339                     | T.?<>  => (andil 0x4400; xoril 0x4000; j(I.NE, lab))                     | T.?<>  => (andil 0x4400; xoril 0x4000; j(I.NE))
1340                     | T.?    => (sahf(); j(I.P,lab))                     | T.?    => (sahf(); j(I.P))
1341                     | T.<=>  => (sahf(); j(I.NP,lab))                     | T.<=>  => (sahf(); j(I.NP))
1342                     | T.>    => (testil 0x4500;  j(I.EQ,lab))                     | T.>    => (testil 0x4500;  j(I.EQ))
1343                     | T.?<=  => (testil 0x4500;  j(I.NE,lab))                     | T.?<=  => (testil 0x4500;  j(I.NE))
1344                     | T.>=   => (testil 0x500; j(I.EQ,lab))                     | T.>=   => (testil 0x500; j(I.EQ))
1345                     | T.?<   => (testil 0x500; j(I.NE,lab))                     | T.?<   => (testil 0x500; j(I.NE))
1346                     | T.<    => (andil 0x4500; cmpil 0x100; j(I.EQ,lab))                     | T.<    => (andil 0x4500; cmpil 0x100; j(I.EQ))
1347                     | T.?>=  => (andil 0x4500; cmpil 0x100; j(I.NE,lab))                     | T.?>=  => (andil 0x4500; cmpil 0x100; j(I.NE))
1348                     | T.<=   => (andil 0x4100; cmpil 0x100; j(I.EQ,lab);                     | T.<=   => (andil 0x4100; cmpil 0x100; j(I.EQ);
1349                                  cmpil 0x4000; j(I.EQ,lab))                                  cmpil 0x4000; j(I.EQ))
1350                     | T.?>   => (sahf(); j(I.P,lab); testil 0x4100; j(I.EQ,lab))                     | T.?>   => (sahf(); j(I.P); testil 0x4100; j(I.EQ))
1351                     | T.<>   => (testil 0x4400; j(I.EQ,lab))                     | T.<>   => (testil 0x4400; j(I.EQ))
1352                     | T.?=   => (testil 0x4400; j(I.NE,lab))                     | T.?=   => (testil 0x4400; j(I.NE))
1353                     | _      => error "fbranch"                     | _      => error(concat[
1354                                      "fbranch(", T.Basis.fcondToString fcc, ")"
1355                                    ])
1356                     (*esac*)
1357    
1358                  (*
1359                   *             P  Z  C
1360                   * x < y       0  0  1
1361                   * x > y       0  0  0
1362                   * x = y       0  1  0
1363                   * unordered   1  1  1
1364                   * When it's unordered, all three flags, P, Z, C are set.
1365                   *)
1366    
1367                  fun fast_branch(fcc) =
1368                      case fcc
1369                      of T.==   => orderedOnly(I.EQ)
1370                       | T.?<>  => (j(I.P); j(I.NE))
1371                       | T.?    => j(I.P)
1372                       | T.<=>  => j(I.NP)
1373                       | T.>    => orderedOnly(I.A)
1374                       | T.?<=  => j(I.BE)
1375                       | T.>=   => orderedOnly(I.AE)
1376                       | T.?<   => j(I.B)
1377                       | T.<    => orderedOnly(I.B)
1378                       | T.?>=  => (j(I.P); j(I.AE))
1379                       | T.<=   => orderedOnly(I.BE)
1380                       | T.?>   => (j(I.P); j(I.A))
1381                       | T.<>   => orderedOnly(I.NE)
1382                       | T.?=   => j(I.EQ)
1383                       | _      => error(concat[
1384                                      "fbranch(", T.Basis.fcondToString fcc, ")"
1385                                    ])
1386                   (*esac*)                   (*esac*)
1387                  and orderedOnly fcc =
1388                  let val label = Label.anon()
1389                  in  emit(I.JCC{cond=I.P, opnd=immedLabel label});
1390                      j fcc;
1391                      defineLabel label
1392                  end
1393    
1394                val fcc = compare()                val fcc = compare()
1395            in  emit I.FNSTSW;            in  if !arch <> Pentium andalso
1396                     (enableFastFPMode andalso !fast_floating_point) then
1397                    fast_branch(fcc)
1398                  else
1399                    (emit I.FNSTSW;
1400                branch(fcc)                branch(fcc)
1401                    )
1402            end            end
1403    
1404        (*========================================================        (*========================================================
# Line 1258  Line 1476 
1476            (* generate floating point expression and put the result in fd *)            (* generate floating point expression and put the result in fd *)
1477        and doFexpr'(fty, T.FREG(_, fs), fd, an) =        and doFexpr'(fty, T.FREG(_, fs), fd, an) =
1478              (if CB.sameColor(fs,fd) then ()              (if CB.sameColor(fs,fd) then ()
1479               else mark(I.FCOPY{dst=[fd], src=[fs], tmp=NONE}, an)               else mark'(I.COPY{k=CB.FP, sz=64, dst=[fd], src=[fs], tmp=NONE}, an)
1480              )              )
1481          | doFexpr'(_, T.FLOAD(fty, ea, mem), fd, an) =          | doFexpr'(_, T.FLOAD(fty, ea, mem), fd, an) =
1482              fload'(fty, ea, mem, fd, an)              fload'(fty, ea, mem, fd, an)
# Line 1507  Line 1725 
1725        and fbinop(targetFty,        and fbinop(targetFty,
1726                   binOp, binOpR, ibinOp, ibinOpR, lsrc, rsrc, fd, an) =                   binOp, binOpR, ibinOp, ibinOpR, lsrc, rsrc, fd, an) =
1727                (* Put the mem operand in rsrc *)                (* Put the mem operand in rsrc *)
1728            let val _ = floatingPointUsed := true;            let
1729                fun isMemOpnd(T.FREG(_, f)) = isFMemReg f                fun isMemOpnd(T.FREG(_, f)) = isFMemReg f
1730                  | isMemOpnd(T.FLOAD _) = true                  | isMemOpnd(T.FLOAD _) = true
1731                  | isMemOpnd(T.CVTI2F(_, (16 | 32), _)) = true                  | isMemOpnd(T.CVTI2F(_, (16 | 32), _)) = true
# Line 1548  Line 1766 
1766            end            end
1767    
1768        and doFexpr''(fty, e, fd, an) =        and doFexpr''(fty, e, fd, an) =
1769             (floatingPointUsed := true;
1770            case e of            case e of
1771              T.FREG(_,fs) => if CB.sameColor(fs,fd) then ()              T.FREG(_,fs) => if CB.sameColor(fs,fd) then ()
1772                              else fcopy''(fty, [fd], [fs], an)                              else fcopy''(fty, [fd], [fs], an)
# Line 1589  Line 1808 
1808            | T.FEXT fexp =>            | T.FEXT fexp =>
1809               ExtensionComp.compileFext (reducer()) {e=fexp, fd=fd, an=an}               ExtensionComp.compileFext (reducer()) {e=fexp, fd=fd, an=an}
1810            | _ => error("doFexpr''")            | _ => error("doFexpr''")
1811             )
1812    
1813         (*========================================================         (*========================================================
1814          * Tie the two styles of fp code generation together          * Tie the two styles of fp code generation together
# Line 1764  Line 1984 
1984                      operand       = operand,                      operand       = operand,
1985                      reduceOperand = reduceOpnd,                      reduceOperand = reduceOpnd,
1986                      addressOf     = fn e => address(e, I.Region.memory), (*XXX*)                      addressOf     = fn e => address(e, I.Region.memory), (*XXX*)
1987                      emit          = emitInstruction o mark',                      emit          = mark',
1988                      instrStream   = instrStream,                      instrStream   = instrStream,
1989                      mltreeStream  = self()                      mltreeStream  = self()
1990                     }                     }

Legend:
Removed from v.1003  
changed lines
  Added in v.1185

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