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 1183, Fri Mar 29 19:09:48 2002 UTC revision 1185, Mon Apr 1 22:06:47 2002 UTC
# Line 551  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)
                          end  
                          else (* unsigned *)  
                             shift(I.SHRL, e1, pow)  
676                       end                       end
677                    else                         else shift (I.SHRL, e1, p)
678                         (* note the only way we can overflow is if                       | (n, NONE) =>
                         * 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                (* rem never causes overflow *)                (* rem never causes overflow *)
685                fun rem(signed, e1, e2) =                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)                      divrem(signed, false, e1, e2, edx)
730    
731                    (* Makes sure the destination must be a register *)                    (* Makes sure the destination must be a register *)
# Line 605  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 613  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 657  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 878  Line 1032 
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, 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(T.DIV_TO_ZERO, 32, x, y) => divide(true, false, x, y)               | T.DIVS(T.DIV_TO_ZERO, 32, x, y) => divide(true, false, x, y)
1037                 | 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)               | 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(T.DIV_TO_ZERO, 32, x, y) => divide(true, true, x, y)               | T.DIVT(T.DIV_TO_ZERO, 32, x, y) => divide(true, true, x, y)
1045                 | 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)

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

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