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 744, Fri Dec 8 04:11:42 2000 UTC revision 815, Fri May 4 05:09:10 2001 UTC
# Line 39  Line 39 
39    
40  functor X86  functor X86
41    (structure X86Instr : X86INSTR    (structure X86Instr : X86INSTR
42     structure X86MLTree : MLTREE     structure MLTreeUtils : MLTREE_UTILS
43         where T = X86Instr.T
44     structure ExtensionComp : MLTREE_EXTENSION_COMP     structure ExtensionComp : MLTREE_EXTENSION_COMP
45       where I = X86Instr and T = X86MLTree       where I = X86Instr
      sharing X86MLTree.Region = X86Instr.Region  
      sharing X86MLTree.LabelExp = X86Instr.LabelExp  
46      datatype arch = Pentium | PentiumPro | PentiumII | PentiumIII      datatype arch = Pentium | PentiumPro | PentiumII | PentiumIII
47      val arch : arch ref      val arch : arch ref
48      val cvti2f :      val cvti2f :
49             {ty: X86Instr.T.ty,
50              src: X86Instr.operand,
51           (* source operand, guaranteed to be non-memory! *)           (* source operand, guaranteed to be non-memory! *)
52           {ty: X86MLTree.ty, src: X86Instr.operand} ->            an: Annotations.annotations ref (* cluster annotations *)
53             } ->
54           {instrs : X86Instr.instruction list,(* the instructions *)           {instrs : X86Instr.instruction list,(* the instructions *)
55            tempMem: X86Instr.operand,         (* temporary for CVTI2F *)            tempMem: X86Instr.operand,         (* temporary for CVTI2F *)
56            cleanup: X86Instr.instruction list (* cleanup code *)            cleanup: X86Instr.instruction list (* cleanup code *)
# Line 61  Line 63 
63            val rewriteMemReg : bool            val rewriteMemReg : bool
64        end =        end =
65  struct  struct
   structure T = X86MLTree  
   structure S = T.Stream  
66    structure I = X86Instr    structure I = X86Instr
67      structure T = I.T
68      structure S = T.Stream
69    structure C = I.C    structure C = I.C
70    structure Shuffle = Shuffle(I)    structure Shuffle = Shuffle(I)
71    structure W32 = Word32    structure W32 = Word32
# Line 106  Line 108 
108    
109    val ST0 = C.ST 0    val ST0 = C.ST 0
110    val ST7 = C.ST 7    val ST7 = C.ST 7
111      val one = T.I.int_1
112    
113      val opcodes8 = {INC=I.INCB,DEC=I.DECB,ADD=I.ADDB,SUB=I.SUBB,
114                      NOT=I.NOTB,NEG=I.NEGB,
115                      SHL=I.SHLB,SHR=I.SHRB,SAR=I.SARB,
116                      OR=I.ORB,AND=I.ANDB,XOR=I.XORB}
117      val opcodes16 = {INC=I.INCW,DEC=I.DECW,ADD=I.ADDW,SUB=I.SUBW,
118                       NOT=I.NOTW,NEG=I.NEGW,
119                       SHL=I.SHLW,SHR=I.SHRW,SAR=I.SARW,
120                       OR=I.ORW,AND=I.ANDW,XOR=I.XORW}
121      val opcodes32 = {INC=I.INCL,DEC=I.DECL,ADD=I.ADDL,SUB=I.SUBL,
122                       NOT=I.NOTL,NEG=I.NEGL,
123                       SHL=I.SHLL,SHR=I.SHRL,SAR=I.SARL,
124                       OR=I.ORL,AND=I.ANDL,XOR=I.XORL}
125    
126    (*    (*
127     * The code generator     * The code generator
128     *)     *)
129    fun selectInstructions    fun selectInstructions
130         (instrStream as         (instrStream as
131          S.STREAM{emit,defineLabel,entryLabel,pseudoOp,annotation,          S.STREAM{emit,defineLabel,entryLabel,pseudoOp,annotation,getAnnotations,
132                   beginCluster,endCluster,exitBlock,comment,...}) =                   beginCluster,endCluster,exitBlock,comment,...}) =
133    let exception EA    let exception EA
134    
# Line 132  Line 148 
148              case !trapLabel of              case !trapLabel of
149                NONE => let val label = Label.newLabel "trap"                NONE => let val label = Label.newLabel "trap"
150                            val jmp   = I.JCC{cond=I.O,                            val jmp   = I.JCC{cond=I.O,
151                                              opnd=I.ImmedLabel(LE.LABEL label)}                                              opnd=I.ImmedLabel(T.LABEL label)}
152                        in  trapLabel := SOME(jmp, label); jmp end                        in  trapLabel := SOME(jmp, label); jmp end
153              | SOME(jmp, _) => jmp              | SOME(jmp, _) => jmp
154        in  emit jmp end        in  emit jmp end
# Line 179  Line 195 
195        (* conversions *)        (* conversions *)
196        val itow = Word.fromInt        val itow = Word.fromInt
197        val wtoi = Word.toInt        val wtoi = Word.toInt
198        fun toInt32 i = Int32.fromLarge(Int.toLarge i)        fun toInt32 i = T.I.toInt32(32, i)
199        val w32toi32 = Word32.toLargeIntX        val w32toi32 = Word32.toLargeIntX
200        val i32tow32 = Word32.fromLargeInt        val i32tow32 = Word32.fromLargeInt
201    
# Line 191  Line 207 
207        val ecx = I.Direct(C.ecx)        val ecx = I.Direct(C.ecx)
208        val edx = I.Direct(C.edx)        val edx = I.Direct(C.edx)
209    
210        fun immedLabel lab = I.ImmedLabel(LE.LABEL lab)        fun immedLabel lab = I.ImmedLabel(T.LABEL lab)
211    
212        (* Is the expression zero? *)        (* Is the expression zero? *)
213        fun isZero(T.LI 0) = true        fun isZero(T.LI z) = T.I.isZero z
         | isZero(T.LI32 0w0) = true  
214          | isZero(T.MARK(e,a)) = isZero e          | isZero(T.MARK(e,a)) = isZero e
215          | isZero _ = false          | isZero _ = false
216         (* Does the expression set the zero bit?         (* Does the expression set the zero bit?
# Line 269  Line 284 
284          | cond T.GE = I.GE | cond T.GEU = I.AE          | cond T.GE = I.GE | cond T.GEU = I.AE
285          | cond T.GT = I.GT | cond T.GTU = I.A          | cond T.GT = I.GT | cond T.GTU = I.A
286    
287          fun zero dst = emit(I.BINARY{binOp=I.XORL, src=dst, dst=dst})
288    
289        (* Move and annotate *)        (* Move and annotate *)
290        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) =
291            if C.sameColor(s,d) then ()            if C.sameColor(s,d) then ()
292            else mark(I.COPY{dst=[d], src=[s], tmp=NONE}, an)            else mark(I.COPY{dst=[d], src=[s], tmp=NONE}, an)
293            | move'(I.Immed 0, dst as I.Direct d, an) =
294                mark(I.BINARY{binOp=I.XORL, src=dst, dst=dst}, an)
295          | 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)
296    
297        (* Move only! *)        (* Move only! *)
298        fun move(src, dst) = move'(src, dst, [])        fun move(src, dst) = move'(src, dst, [])
299    
       fun zero dst = emit(I.BINARY{binOp=I.XORL, src=dst, dst=dst})  
   
300        val readonly = I.Region.readonly        val readonly = I.Region.readonly
301    
302        (*        (*
303         * Compute an effective address.  This is a new version         * Compute an effective address.
304         *)         *)
305        fun address(ea, mem) =        fun address(ea, mem) = let
       let (* tricky way to negate without overflow! *)  
           fun neg32 w = Word32.notb w + 0w1  
   
306            (* Keep building a bigger and bigger effective address expressions            (* Keep building a bigger and bigger effective address expressions
307             * The input is a list of trees             * The input is a list of trees
308             * b -- base             * b -- base
# Line 299  Line 313 
313            fun doEA([], b, i, s, d) = makeAddressingMode(b, i, s, d)            fun doEA([], b, i, s, d) = makeAddressingMode(b, i, s, d)
314              | doEA(t::trees, b, i, s, d) =              | doEA(t::trees, b, i, s, d) =
315                (case t of                (case t of
316                   T.LI n   => doEAImmed(trees, n, b, i, s, d)                   T.LI n   => doEAImmed(trees, toInt32 n, b, i, s, d)
317                 | T.LI32 n => doEAImmedw(trees, n, b, i, s, d)                 | T.CONST _ => doEALabel(trees, t, b, i, s, d)
318                 | T.CONST c => doEALabel(trees, LE.CONST c, b, i, s, d)                 | T.LABEL _ => doEALabel(trees, t, b, i, s, d)
319                 | T.LABEL le => doEALabel(trees, le, b, i, s, d)                 | T.LABEXP le => doEALabel(trees, le, b, i, s, d)
320                 | T.ADD(32, t1, t2 as T.REG(_,r)) =>                 | T.ADD(32, t1, t2 as T.REG(_,r)) =>
321                      if isMemReg r then doEA(t2::t1::trees, b, i, s, d)                      if isMemReg r then doEA(t2::t1::trees, b, i, s, d)
322                      else doEA(t1::t2::trees, b, i, s, d)                      else doEA(t1::t2::trees, b, i, s, d)
323                 | T.ADD(32, t1, t2) => doEA(t1::t2::trees, b, i, s, d)                 | T.ADD(32, t1, t2) => doEA(t1::t2::trees, b, i, s, d)
324                 | T.SUB(32, t1, T.LI n) =>                 | T.SUB(32, t1, T.LI n) =>
325                      (* can't overflow here *)                      doEA(t1::T.LI(T.I.NEG(32,n))::trees, b, i, s, d)
326                      doEA(t1::T.LI32(neg32(Word32.fromInt n))::trees, b, i, s, d)                 | T.SLL(32, t1, T.LI n) => let
327                 | T.SUB(32, t1, T.LI32 n) =>                      val n = T.I.toInt(32, n)
328                      doEA(t1::T.LI32(neg32 n)::trees, b, i, s, d)                   in
329                 | T.SLL(32, t1, T.LI 0) => displace(trees, t1, b, i, s, d)                     case n
330                 | T.SLL(32, t1, T.LI 1) => indexed(trees, t1, t, 1, b, i, s, d)                     of 0 => displace(trees, t1, b, i, s, d)
331                 | T.SLL(32, t1, T.LI 2) => indexed(trees, t1, t, 2, b, i, s, d)                      | 1 => indexed(trees, t1, t, 1, b, i, s, d)
332                 | T.SLL(32, t1, T.LI 3) => indexed(trees, t1, t, 3, b, i, s, d)                      | 2 => indexed(trees, t1, t, 2, b, i, s, d)
333                 | T.SLL(32, t1, T.LI32 0w0) => displace(trees, t1, b, i, s, d)                      | 3 => indexed(trees, t1, t, 3, b, i, s, d)
334                 | T.SLL(32, t1, T.LI32 0w1) => indexed(trees,t1,t,1,b,i,s,d)                      | _ => displace(trees, t, b, i, s, d)
335                 | T.SLL(32, t1, T.LI32 0w2) => indexed(trees,t1,t,2,b,i,s,d)                   end
                | T.SLL(32, t1, T.LI32 0w3) => indexed(trees,t1,t,3,b,i,s,d)  
336                 | t => displace(trees, t, b, i, s, d)                 | t => displace(trees, t, b, i, s, d)
337                )                )
338    
339            (* Add an immed constant *)            (* Add an immed constant *)
340            and doEAImmed(trees, 0, b, i, s, d) = doEA(trees, b, i, s, d)            and doEAImmed(trees, 0, b, i, s, d) = doEA(trees, b, i, s, d)
341              | doEAImmed(trees, n, b, i, s, I.Immed m) =              | doEAImmed(trees, n, b, i, s, I.Immed m) =
342                   doEA(trees, b, i, s, (* no overflow! *)                   doEA(trees, b, i, s, I.Immed(n+m))
                        I.Immed(w32toi32(Word32.fromInt n + i32tow32 m)))  
343              | doEAImmed(trees, n, b, i, s, I.ImmedLabel le) =              | doEAImmed(trees, n, b, i, s, I.ImmedLabel le) =
                  doEA(trees, b, i, s, I.ImmedLabel(LE.PLUS(le,LE.INT n)))  
             | doEAImmed(trees, n, b, i, s, _) = error "doEAImmed"  
   
           (* Add an immed32 constant *)  
           and doEAImmedw(trees, 0w0, b, i, s, d) = doEA(trees, b, i, s, d)  
             | doEAImmedw(trees, n, b, i, s, I.Immed m) =  
                  (* no overflow! *)  
                  doEA(trees, b, i, s, I.Immed(w32toi32(i32tow32 m + n)))  
             | doEAImmedw(trees, n, b, i, s, I.ImmedLabel le) =  
344                   doEA(trees, b, i, s,                   doEA(trees, b, i, s,
345                        I.ImmedLabel(LE.PLUS(le,LE.INT(Word32.toIntX n)))                        I.ImmedLabel(T.ADD(32,le,T.LI(T.I.fromInt32(32, n)))))
346                        handle Overflow => error "doEAImmedw: constant too large")              | doEAImmed(trees, n, b, i, s, _) = error "doEAImmed"
             | doEAImmedw(trees, n, b, i, s, _) = error "doEAImmedw"  
347    
348            (* Add a label expression *)            (* Add a label expression *)
349            and doEALabel(trees, le, b, i, s, I.Immed 0) =            and doEALabel(trees, le, b, i, s, I.Immed 0) =
350                   doEA(trees, b, i, s, I.ImmedLabel le)                   doEA(trees, b, i, s, I.ImmedLabel le)
351              | doEALabel(trees, le, b, i, s, I.Immed m) =              | doEALabel(trees, le, b, i, s, I.Immed m) =
352                   doEA(trees, b, i, s,                   doEA(trees, b, i, s,
353                        I.ImmedLabel(LE.PLUS(le,LE.INT(Int32.toInt m)))                        I.ImmedLabel(T.ADD(32,le,T.LI(T.I.fromInt32(32, m))))
354                        handle Overflow => error "doEALabel: constant too large")                        handle Overflow => error "doEALabel: constant too large")
355              | doEALabel(trees, le, b, i, s, I.ImmedLabel le') =              | doEALabel(trees, le, b, i, s, I.ImmedLabel le') =
356                   doEA(trees, b, i, s, I.ImmedLabel(LE.PLUS(le,le')))                   doEA(trees, b, i, s, I.ImmedLabel(T.ADD(32,le,le')))
357              | doEALabel(trees, le, b, i, s, _) = error "doEALabel"              | doEALabel(trees, le, b, i, s, _) = error "doEALabel"
358    
359            and makeAddressingMode(NONE, NONE, _, disp) = disp            and makeAddressingMode(NONE, NONE, _, disp) = disp
# Line 408  Line 410 
410        end (* address *)        end (* address *)
411    
412            (* reduce an expression into an operand *)            (* reduce an expression into an operand *)
413        and operand(T.LI i) = I.Immed(toInt32 i)        and operand(T.LI i) = I.Immed(toInt32(i))
414          | operand(T.LI32 w) = I.Immed(wToInt32 w)          | operand(x as (T.CONST _ | T.LABEL _)) = I.ImmedLabel x
415          | operand(T.CONST c) = I.ImmedLabel(LE.CONST c)          | operand(T.LABEXP le) = I.ImmedLabel le
         | operand(T.LABEL lab) = I.ImmedLabel lab  
416          | operand(T.REG(_,r)) = IntReg r          | operand(T.REG(_,r)) = IntReg r
417          | operand(T.LOAD(32,ea,mem)) = address(ea, mem)          | operand(T.LOAD(32,ea,mem)) = address(ea, mem)
418          | operand(t) = I.Direct(expr t)          | operand(t) = I.Direct(expr t)
# Line 532  Line 533 
533                fun divrem(signed, overflow, e1, e2, resultReg) =                fun divrem(signed, overflow, e1, e2, resultReg) =
534                let val (opnd1, opnd2) = (operand e1, operand e2)                let val (opnd1, opnd2) = (operand e1, operand e2)
535                    val _ = move(opnd1, eax)                    val _ = move(opnd1, eax)
536                    val oper = if signed then (emit(I.CDQ); I.IDIVL)                    val oper = if signed then (emit(I.CDQ); I.IDIVL1)
537                               else (zero edx; I.DIVL)                               else (zero edx; I.DIVL1)
538                in  mark(I.MULTDIV{multDivOp=oper, src=regOrMem opnd2},an);                in  mark(I.MULTDIV{multDivOp=oper, src=regOrMem opnd2},an);
539                    move(resultReg, rdOpnd);                    move(resultReg, rdOpnd);
540                    if overflow then trap() else ()                    if overflow then trap() else ()
541                end                end
542    
543                    (* Optimize the special case for division *)                    (* Optimize the special case for division *)
544                fun divide(signed, overflow, e1, e2 as T.LI n) =                fun divide(signed, overflow, e1, e2 as T.LI n') = let
545                let fun isPowerOf2 w = Word.andb((w - 0w1), w) = 0w0                    val n = toInt32 n'
546                      val w = T.I.toWord32(32, n')
547                      fun isPowerOf2 w = W32.andb((w - 0w1), w) = 0w0
548                    fun log2 n =  (* n must be > 0!!! *)                    fun log2 n =  (* n must be > 0!!! *)
549                        let fun loop(0w1,pow) = pow                        let fun loop(0w1,pow) = pow
550                              | loop(w,pow) = loop(Word.>>(w, 0w1),pow+1)                              | loop(w,pow) = loop(W32.>>(w, 0w1),pow+1)
551                        in loop(n,0) end                        in loop(n,0) end
                   val w = Word.fromInt n  
552                in  if n > 1 andalso isPowerOf2 w then                in  if n > 1 andalso isPowerOf2 w then
553                       let val pow = T.LI(log2 w)                       let val pow = T.LI(T.I.fromInt(32,log2 w))
554                       in  if signed then                       in  if signed then
555                           (* signed; simulate round towards zero *)                           (* signed; simulate round towards zero *)
556                           let val label = Label.newLabel ""                           let val label = Label.newLabel ""
# Line 561  Line 563 
563                                       I.UNARY{unOp=I.INCL, opnd=opnd1}                                       I.UNARY{unOp=I.INCL, opnd=opnd1}
564                                    else                                    else
565                                       I.BINARY{binOp=I.ADDL,                                       I.BINARY{binOp=I.ADDL,
566                                                src=I.Immed(toInt32 n - 1),                                                src=I.Immed(n - 1),
567                                                dst=opnd1});                                                dst=opnd1});
568                               defineLabel label;                               defineLabel label;
569                               shift(I.SARL, T.REG(32, reg1), pow)                               shift(I.SARL, T.REG(32, reg1), pow)
# Line 582  Line 584 
584                fun rem(signed, overflow, e1, e2) =                fun rem(signed, overflow, e1, e2) =
585                      divrem(signed, overflow, e1, e2, edx)                      divrem(signed, overflow, e1, e2, edx)
586    
587                      (* Makes sure the destination must be a register *)
588                  fun dstMustBeReg f =
589                      if isMemReg rd then
590                      let val tmpR = newReg()
591                          val tmp  = I.Direct(tmpR)
592                      in  f(tmpR, tmp); move(tmp, rdOpnd) end
593                      else f(rd, rdOpnd)
594    
595                    (* unsigned integer multiplication *)                    (* unsigned integer multiplication *)
596                fun uMultiply(e1, e2) =                fun uMultiply(e1, e2) =
597                    (* note e2 can never be (I.Direct edx) *)                    (* note e2 can never be (I.Direct edx) *)
598                    (move(operand e1, eax);                    (move(operand e1, eax);
599                     mark(I.MULTDIV{multDivOp=I.MULL,                     mark(I.MULTDIV{multDivOp=I.MULL1,
600                                    src=regOrMem(operand e2)},an);                                    src=regOrMem(operand e2)},an);
601                     move(eax, rdOpnd)                     move(eax, rdOpnd)
602                    )                    )
# Line 595  Line 605 
605                     * The only forms that are allowed that also sets the                     * The only forms that are allowed that also sets the
606                     * OF and CF flags are:                     * OF and CF flags are:
607                     *                     *
608                       *          (dst)  (src1)  (src2)
609                     *      imul r32, r32/m32, imm8                     *      imul r32, r32/m32, imm8
610                       *          (dst)  (src)
611                     *      imul r32, imm8                     *      imul r32, imm8
612                     *      imul r32, imm32                     *      imul r32, imm32
613                       *      imul r32, r32/m32
614                       * Note: destination must be a register!
615                     *)                     *)
616                fun multiply(e1, e2) =                fun multiply(e1, e2) =
617                let fun doit(i1 as I.Immed _, i2 as I.Immed _, dstR, dst) =                dstMustBeReg(fn (rd, rdOpnd) =>
618                        (move(i1, dst);                let fun doit(i1 as I.Immed _, i2 as I.Immed _) =
619                         mark(I.MUL3{dst=dstR, src1=i2, src2=NONE},an))                        (move(i1, rdOpnd);
620                      | doit(rm, i2 as I.Immed _, dstR, dst) =                         mark(I.BINARY{binOp=I.IMULL, dst=rdOpnd, src=i2},an))
621                          doit(i2, rm, dstR, dst)                      | doit(rm, i2 as I.Immed _) = doit(i2, rm)
622                      | doit(imm as I.Immed(i), rm, dstR, dst) =                      | doit(imm as I.Immed(i), rm) =
623                         mark(I.MUL3{dst=dstR, src1=rm, src2=SOME i},an)                             mark(I.MUL3{dst=rd, src1=rm, src2=i},an)
624                      | doit(r1 as I.Direct _, r2 as I.Direct _, dstR, dst) =                      | doit(r1 as I.Direct _, r2 as I.Direct _) =
625                        (move(r1, dst);                        (move(r1, rdOpnd);
626                         mark(I.MUL3{dst=dstR, src1=r2, src2=NONE},an))                         mark(I.BINARY{binOp=I.IMULL, dst=rdOpnd, src=r2},an))
627                      | doit(r1 as I.Direct _, rm, dstR, dst) =                      | doit(r1 as I.Direct _, rm) =
628                        (move(r1, dst);                        (move(r1, rdOpnd);
629                         mark(I.MUL3{dst=dstR, src1=rm, src2=NONE},an))                         mark(I.BINARY{binOp=I.IMULL, dst=rdOpnd, src=rm},an))
630                      | doit(rm, r as I.Direct _, dstR, dst) =                      | doit(rm, r as I.Direct _) = doit(r, rm)
631                         doit(r, rm, dstR, dst)                      | doit(rm1, rm2) =
                     | doit(rm1, rm2, dstR, dst) =  
632                         if equalRd rm2 then                         if equalRd rm2 then
633                         let val tmpR = newReg()                         let val tmpR = newReg()
634                             val tmp  = I.Direct tmpR                             val tmp  = I.Direct tmpR
635                         in move(rm1, tmp);                         in move(rm1, tmp);
636                            mark(I.MUL3{dst=tmpR, src1=rm2, src2=NONE},an);                            mark(I.BINARY{binOp=I.IMULL, dst=tmp, src=rm2},an);
637                            move(tmp, dst)                            move(tmp, rdOpnd)
638                         end                         end
639                         else                         else
640                           (move(rm1, dst);                           (move(rm1, rdOpnd);
641                            mark(I.MUL3{dst=dstR, src1=rm2, src2=NONE},an)                            mark(I.BINARY{binOp=I.IMULL, dst=rdOpnd, src=rm2},an)
642                           )                           )
643                    val (opnd1, opnd2) = (operand e1, operand e2)                    val (opnd1, opnd2) = (operand e1, operand e2)
644                in  if isMemReg rd then (* destination must be a real reg *)                in  doit(opnd1, opnd2)
                   let val tmpR = newReg()  
                       val tmp  = I.Direct tmpR  
                   in  doit(opnd1, opnd2, tmpR, tmp);  
                       move(tmp, rdOpnd)  
                   end  
                   else  
                       doit(opnd1, opnd2, rd, rdOpnd)  
645                end                end
646                  )
                  (* Makes sure the destination must be a register *)  
               fun dstMustBeReg f =  
                   if isMemReg rd then  
                   let val tmpR = newReg()  
                       val tmp  = I.Direct(tmpR)  
                   in  f(tmpR, tmp); move(tmp, rdOpnd) end  
                   else f(rd, rdOpnd)  
647    
648                   (* Emit a load instruction; makes sure that the destination                   (* Emit a load instruction; makes sure that the destination
649                    * is a register                    * is a register
# Line 793  Line 792 
792                            move'(tmp, rdOpnd, [])                            move'(tmp, rdOpnd, [])
793                        end                        end
794                     else move'(IntReg rs, rdOpnd, an)                     else move'(IntReg rs, rdOpnd, an)
795               | (T.LI 0 | T.LI32 0w0) =>               | T.LI z => let
796                     val n = toInt32 z
797                   in
798                     if n=0 then
799                   (* As per Fermin's request, special optimization for rd := 0.                   (* As per Fermin's request, special optimization for rd := 0.
800                    * Currently we don't bother with the size.                    * Currently we don't bother with the size.
801                    *)                    *)
802                   if isMemReg rd then move'(I.Immed 0, rdOpnd, an)                   if isMemReg rd then move'(I.Immed 0, rdOpnd, an)
803                   else mark(I.BINARY{binOp=I.XORL, src=rdOpnd, dst=rdOpnd}, an)                   else mark(I.BINARY{binOp=I.XORL, src=rdOpnd, dst=rdOpnd}, an)
804               | T.LI n      => move'(I.Immed(toInt32 n), rdOpnd, an)                   else
805               | T.LI32 w    => move'(I.Immed(wToInt32 w), rdOpnd, an)                     move'(I.Immed(n), rdOpnd, an)
806               | T.CONST c   => move'(I.ImmedLabel(LE.CONST c), rdOpnd, an)                 end
807               | T.LABEL lab => move'(I.ImmedLabel lab, rdOpnd, an)               | (T.CONST _ | T.LABEL _) =>
808                     move'(I.ImmedLabel exp, rdOpnd, an)
809                 | T.LABEXP le => move'(I.ImmedLabel le, rdOpnd, an)
810    
811                 (* 32-bit addition *)                 (* 32-bit addition *)
812               | T.ADD(32, e, (T.LI 1|T.LI32 0w1)) => unary(I.INCL, e)               | T.ADD(32, e1, e2 as T.LI n) => let
813               | T.ADD(32, (T.LI 1|T.LI32 0w1), e) => unary(I.INCL, e)                   val n = toInt32 n
814               | T.ADD(32, e, T.LI ~1) => unary(I.DECL, e)                 in
815               | T.ADD(32, T.LI ~1, e) => unary(I.DECL, e)                   case n
816                     of 1  => unary(I.INCL, e1)
817                      | ~1 => unary(I.DECL, e1)
818                      | _ => addition(e1, e2)
819                   end
820                 | T.ADD(32, e1 as T.LI n, e2) => let
821                     val n = toInt32 n
822                   in
823                     case n
824                     of  1 => unary(I.INCL, e2)
825                      | ~1 => unary(I.DECL, e2)
826                      | _ => addition(e1, e2)
827                   end
828               | T.ADD(32, e1, e2) => addition(e1, e2)               | T.ADD(32, e1, e2) => addition(e1, e2)
829    
830                 (* 32-bit addition but set the flag!                 (* 32-bit addition but set the flag!
831                  * This is a stupid hack for now.                  * This is a stupid hack for now.
832                  *)                  *)
833               | T.ADD(0, e, (T.LI 1|T.LI32 0w1)) => unary(I.INCL, e)               | T.ADD(0, e, e1 as T.LI n) => let
834               | T.ADD(0, (T.LI 1|T.LI32 0w1), e) => unary(I.INCL, e)                   val n = T.I.toInt(32, n)
835               | T.ADD(0, e, T.LI ~1) => unary(I.DECL, e)                 in
836               | T.ADD(0, T.LI ~1, e) => unary(I.DECL, e)                   if n=1 then unary(I.INCL, e)
837                     else if n = ~1 then unary(I.DECL, e)
838                          else binaryComm(I.ADDL, e, e1)
839                   end
840                 | T.ADD(0, e1 as T.LI n, e) => let
841                     val n = T.I.toInt(32, n)
842                   in
843                     if n=1 then unary(I.INCL, e)
844                     else if n = ~1 then unary(I.DECL, e)
845                          else binaryComm(I.ADDL, e1, e)
846                   end
847               | T.ADD(0, e1, e2) => binaryComm(I.ADDL, e1, e2)               | T.ADD(0, e1, e2) => binaryComm(I.ADDL, e1, e2)
848    
849                 (* 32-bit subtraction *)                 (* 32-bit subtraction *)
850               | T.SUB(32, e, (T.LI 0 | T.LI32 0w0)) => doExpr(e, rd, an)               | T.SUB(32, e1, e2 as T.LI n) => let
851               | T.SUB(32, e, (T.LI 1 | T.LI32 0w1)) => unary(I.DECL, e)                   val n = toInt32 n
852               | T.SUB(32, e, T.LI ~1) => unary(I.INCL, e)                 in
853               | T.SUB(32, (T.LI 0 | T.LI32 0w0), e) => unary(I.NEGL, e)                   case n
854                     of 0 => doExpr(e1, rd, an)
855               (* Never mind:                    | 1 => unary(I.DECL, e1)
856                 | T.SUB(32, e1, e2 as T.LI n) =>                    | ~1 => unary(I.INCL, e1)
857                   (mark(I.LEA{r32=rd, addr=address(T.ADD(32, e1, T.LI(~n)),                    | _ => binary(I.SUBL, e1, e2)
858                                                    I.Region.readonly)}, an)                 end
859                    handle (Overflow|EA) => binary(I.SUBL, e1, e2))               | T.SUB(32, e1 as T.LI n, e2) =>
860               *)                   if T.I.isZero n then unary(I.NEGL, e2)
861                     else binary(I.SUBL, e1, e2)
862               | T.SUB(32, e1, e2) => binary(I.SUBL, e1, e2)               | T.SUB(32, e1, e2) => binary(I.SUBL, e1, e2)
863    
864               | T.MULU(32, x, y) => uMultiply(x, y)               | T.MULU(32, x, y) => uMultiply(x, y)
# Line 860  Line 887 
887               | T.LOAD(8, ea, mem) => load8(ea, mem)               | T.LOAD(8, ea, mem) => load8(ea, mem)
888               | T.LOAD(16, ea, mem) => load16(ea, mem)               | T.LOAD(16, ea, mem) => load16(ea, mem)
889               | T.LOAD(32, ea, mem) => load32(ea, mem)               | T.LOAD(32, ea, mem) => load32(ea, mem)
890               | T.SX(_,_,T.LOAD(8,ea,mem)) => load8s(ea, mem)  
891               | T.SX(_,_,T.LOAD(16,ea,mem)) => load16s(ea, mem)               | T.SX(32,8,T.LOAD(8,ea,mem)) => load8s(ea, mem)
892                 | T.SX(32,16,T.LOAD(16,ea,mem)) => load16s(ea, mem)
893                 | T.ZX(32,8,T.LOAD(8,ea,mem)) => load8(ea, mem)
894                 | T.ZX(32,16,T.LOAD(16,ea,mem)) => load16(ea, mem)
895    
896               | T.COND(32, T.CMP(ty, cc, t1, t2), T.LI yes, T.LI no) =>               | T.COND(32, T.CMP(ty, cc, t1, t2), T.LI yes, T.LI no) =>
897                   setcc(ty, cc, t1, t2, toInt32 yes, toInt32 no)                   setcc(ty, cc, t1, t2, toInt32 yes, toInt32 no)
              | T.COND(32, T.CMP(ty, cc, t1, t2), T.LI32 yes, T.LI32 no) =>  
                  setcc(ty, cc, t1, t2, Word32.toLargeIntX yes,  
                                        Word32.toLargeIntX no)  
898               | T.COND(32, T.CMP(ty, cc, t1, t2), yes, no) =>               | T.COND(32, T.CMP(ty, cc, t1, t2), yes, no) =>
899                  (case !arch of (* PentiumPro and higher has CMOVcc *)                  (case !arch of (* PentiumPro and higher has CMOVcc *)
900                     Pentium => unknownExp exp                     Pentium => unknownExp exp
# Line 935  Line 962 
962            in  mark(testopcode{lsrc=opnd1, rsrc=opnd2}, an)            in  mark(testopcode{lsrc=opnd1, rsrc=opnd2}, an)
963            end            end
964    
965              (* %eflags <- src *)
966          and moveToEflags src =
967              if C.sameColor(src, C.eflags) then ()
968              else (move(I.Direct src, eax); emit(I.LAHF))
969    
970              (* dst <- %eflags *)
971          and moveFromEflags dst =
972              if C.sameColor(dst, C.eflags) then ()
973              else (emit(I.SAHF); move(eax, I.Direct dst))
974    
975           (* generate a condition code expression           (* generate a condition code expression
976            * The zero is for setting the condition code!            * The zero is for setting the condition code!
977            * I have no idea why this is used.            * I have no idea why this is used.
978            *)            *)
979        and doCCexpr(T.CMP(ty, cc, t1, t2), rd, an) =        and doCCexpr(T.CMP(ty, cc, t1, t2), rd, an) =
980            if C.sameColor(rd, C.eflags) then            (cmp(false, ty, cc, t1, t2, an);
981               (cmp(false, ty, cc, t1, t2, an); ())             moveFromEflags rd
982              )
983            | doCCexpr(T.CC(cond,rs), rd, an) =
984              if C.sameColor(rs,C.eflags) orelse C.sameColor(rd,C.eflags) then
985                 (moveToEflags rs; moveFromEflags rd)
986            else            else
987               error "doCCexpr: cmp"               move'(I.Direct rs, I.Direct rd, an)
988          | doCCexpr(T.CCMARK(e,A.MARKREG f),rd,an) = (f rd; doCCexpr(e,rd,an))          | doCCexpr(T.CCMARK(e,A.MARKREG f),rd,an) = (f rd; doCCexpr(e,rd,an))
989          | doCCexpr(T.CCMARK(e,a), rd, an) = doCCexpr(e,rd,a::an)          | doCCexpr(T.CCMARK(e,a), rd, an) = doCCexpr(e,rd,a::an)
990          | doCCexpr(T.CCEXT e, cd, an) =          | doCCexpr(T.CCEXT e, cd, an) =
# Line 1003  Line 1044 
1044            end            end
1045    
1046            (* generate code for jumps *)            (* generate code for jumps *)
1047        and jmp(T.LABEL(lexp as LE.LABEL lab), labs, an) =        and jmp(lexp as T.LABEL lab, labs, an) =
1048               mark(I.JMP(I.ImmedLabel lexp, [lab]), an)               mark(I.JMP(I.ImmedLabel lexp, [lab]), an)
1049          | jmp(T.LABEL lexp, labs, an) = mark(I.JMP(I.ImmedLabel lexp, labs), an)          | jmp(T.LABEXP le, labs, an) = mark(I.JMP(I.ImmedLabel le, labs), an)
1050          | jmp(ea, labs, an)           = mark(I.JMP(operand ea, labs), an)          | jmp(ea, labs, an)           = mark(I.JMP(operand ea, labs), an)
1051    
1052         (* convert mlrisc to cellset:         (* convert mlrisc to cellset:
# Line 1021  Line 1062 
1062             in  g(mlrisc, C.empty) end             in  g(mlrisc, C.empty) end
1063    
1064            (* generate code for calls *)            (* generate code for calls *)
1065        and call(ea, flow, def, use, mem, an) =        and call(ea, flow, def, use, mem, cutsTo, an) =
1066            mark(I.CALL(operand ea,cellset(def),cellset(use),mem),an)        let fun return(set, []) = set
1067                | return(set, a::an) =
1068            (* generate code for integer stores *)                case #peek A.RETURN_ARG a of
1069        and store8(ea, d, mem, an) =                  SOME r => return(C.CellSet.add(r, set), an)
1070            let val src = (* movb has to use %eax as source. Stupid x86! *)                | NONE => return(set, an)
1071          in  mark(I.CALL{opnd=operand ea,defs=cellset(def),uses=cellset(use),
1072                          return=return(C.empty,an),cutsTo=cutsTo,mem=mem},an)
1073          end
1074    
1075              (* generate code for integer stores; first move data to %eax
1076               * This is mainly because we can't allocate to registers like
1077               * ah, dl, dx etc.
1078               *)
1079          and genStore(mvOp, ea, d, mem, an) =
1080              let val src =
1081                   case immedOrReg(operand d) of                   case immedOrReg(operand d) of
1082                       src as I.Direct r =>                       src as I.Direct r =>
1083                         if C.sameColor(r,C.eax)                         if C.sameColor(r,C.eax)
1084                         then src else (move(src, eax); eax)                         then src else (move(src, eax); eax)
1085                     | src => src                     | src => src
1086            in  mark(I.MOVE{mvOp=I.MOVB, src=src, dst=address(ea,mem)},an)            in  mark(I.MOVE{mvOp=mvOp, src=src, dst=address(ea,mem)},an)
1087            end            end
1088        and store16(ea, d, mem, an) = error "store16"  
1089              (* generate code for 8-bit integer stores *)
1090              (* movb has to use %eax as source. Stupid x86! *)
1091          and store8(ea, d, mem, an) = genStore(I.MOVB, ea, d, mem, an)
1092          and store16(ea, d, mem, an) = genStore(I.MOVW, ea, d, mem, an)
1093        and store32(ea, d, mem, an) =        and store32(ea, d, mem, an) =
1094              move'(immedOrReg(operand d), address(ea, mem), an)              move'(immedOrReg(operand d), address(ea, mem), an)
1095    
# Line 1144  Line 1199 
1199            in  if isMemOpnd opnd andalso (ty = 16 orelse ty = 32)            in  if isMemOpnd opnd andalso (ty = 16 orelse ty = 32)
1200                then (INTEGER, ty, opnd, [])                then (INTEGER, ty, opnd, [])
1201                else                else
1202                  let val {instrs, tempMem, cleanup} = cvti2f{ty=ty, src=opnd}                  let val {instrs, tempMem, cleanup} =
1203                            cvti2f{ty=ty, src=opnd, an=getAnnotations()}
1204                  in  emits instrs;                  in  emits instrs;
1205                      (INTEGER, 32, tempMem, cleanup)                      (INTEGER, 32, tempMem, cleanup)
1206                  end                  end
# Line 1545  Line 1601 
1601            then doFexpr''(fty, e, fd, an)            then doFexpr''(fty, e, fd, an)
1602            else doFexpr'(fty, e, fd, an)            else doFexpr'(fty, e, fd, an)
1603    
1604          (*================================================================
1605           * Optimizations for x := x op y
1606           * Special optimizations:
1607           * Generate a binary operator, result must in memory.
1608           * The source must not be in memory
1609           *================================================================*)
1610          and binaryMem(binOp, src, dst, mem, an) =
1611              mark(I.BINARY{binOp=binOp, src=immedOrReg(operand src),
1612                            dst=address(dst,mem)}, an)
1613          and unaryMem(unOp, opnd, mem, an) =
1614              mark(I.UNARY{unOp=unOp, opnd=address(opnd,mem)}, an)
1615    
1616          and isOne(T.LI n) = n = one
1617            | isOne _ = false
1618    
1619          (*
1620           * Perform optimizations based on recognizing
1621           *    x := x op y    or
1622           *    x := y op x
1623           * first.
1624           *)
1625          and store(ty, ea, d, mem, an,
1626                    {INC,DEC,ADD,SUB,NOT,NEG,SHL,SHR,SAR,OR,AND,XOR},
1627                    doStore
1628                   ) =
1629              let fun default() = doStore(ea, d, mem, an)
1630                  fun binary1(t, t', unary, binary, ea', x) =
1631                      if t = ty andalso t' = ty then
1632                         if MLTreeUtils.eqRexp(ea, ea') then
1633                            if isOne x then unaryMem(unary, ea, mem, an)
1634                            else binaryMem(binary, x, ea, mem, an)
1635                          else default()
1636                      else default()
1637                  fun unary(t,unOp, ea') =
1638                      if t = ty andalso MLTreeUtils.eqRexp(ea, ea') then
1639                         unaryMem(unOp, ea, mem, an)
1640                      else default()
1641                  fun binary(t,t',binOp,ea',x) =
1642                      if t = ty andalso t' = ty andalso
1643                         MLTreeUtils.eqRexp(ea, ea') then
1644                          binaryMem(binOp, x, ea, mem, an)
1645                      else default()
1646    
1647                  fun binaryCom1(t,unOp,binOp,x,y) =
1648                  if t = ty then
1649                  let fun again() =
1650                        case y of
1651                          T.LOAD(ty',ea',_) =>
1652                            if ty' = ty andalso MLTreeUtils.eqRexp(ea, ea') then
1653                               if isOne x then unaryMem(unOp, ea, mem, an)
1654                               else binaryMem(binOp,x,ea,mem,an)
1655                            else default()
1656                        | _ => default()
1657                  in  case x of
1658                        T.LOAD(ty',ea',_) =>
1659                          if ty' = ty andalso MLTreeUtils.eqRexp(ea, ea') then
1660                             if isOne y then unaryMem(unOp, ea, mem, an)
1661                             else binaryMem(binOp,y,ea,mem,an)
1662                          else again()
1663                      | _ => again()
1664                  end
1665                  else default()
1666    
1667                  fun binaryCom(t,binOp,x,y) =
1668                  if t = ty then
1669                  let fun again() =
1670                        case y of
1671                          T.LOAD(ty',ea',_) =>
1672                            if ty' = ty andalso MLTreeUtils.eqRexp(ea, ea') then
1673                               binaryMem(binOp,x,ea,mem,an)
1674                            else default()
1675                        | _ => default()
1676                  in  case x of
1677                        T.LOAD(ty',ea',_) =>
1678                          if ty' = ty andalso MLTreeUtils.eqRexp(ea, ea') then
1679                             binaryMem(binOp,y,ea,mem,an)
1680                          else again()
1681                      | _ => again()
1682                  end
1683                  else default()
1684    
1685              in  case d of
1686                    T.ADD(t,x,y) => binaryCom1(t,INC,ADD,x,y)
1687                  | T.SUB(t,T.LOAD(t',ea',_),x) => binary1(t,t',DEC,SUB,ea',x)
1688                  | T.ORB(t,x,y) => binaryCom(t,OR,x,y)
1689                  | T.ANDB(t,x,y) => binaryCom(t,AND,x,y)
1690                  | T.XORB(t,x,y) => binaryCom(t,XOR,x,y)
1691                  | T.SLL(t,T.LOAD(t',ea',_),x) => binary(t,t',SHL,ea',x)
1692                  | T.SRL(t,T.LOAD(t',ea',_),x) => binary(t,t',SHR,ea',x)
1693                  | T.SRA(t,T.LOAD(t',ea',_),x) => binary(t,t',SAR,ea',x)
1694                  | T.NEG(t,T.LOAD(t',ea',_)) => unary(t,NEG,ea')
1695                  | T.NOTB(t,T.LOAD(t',ea',_)) => unary(t,NOT,ea')
1696                  | _ => default()
1697              end (* store *)
1698    
1699            (* generate code for a statement *)            (* generate code for a statement *)
1700        and stmt(T.MV(_, rd, e), an) = doExpr(e, rd, an)        and stmt(T.MV(_, rd, e), an) = doExpr(e, rd, an)
1701          | 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 1553  Line 1704 
1704          | stmt(T.FCOPY(fty, dst, src), an) = fcopy(fty, dst, src, an)          | stmt(T.FCOPY(fty, dst, src), an) = fcopy(fty, dst, src, an)
1705          | stmt(T.JMP(e, labs), an) = jmp(e, labs, an)          | stmt(T.JMP(e, labs), an) = jmp(e, labs, an)
1706          | stmt(T.CALL{funct, targets, defs, uses, region, ...}, an) =          | stmt(T.CALL{funct, targets, defs, uses, region, ...}, an) =
1707               call(funct,targets,defs,uses,region,an)               call(funct,targets,defs,uses,region,[],an)
1708            | stmt(T.FLOW_TO(T.CALL{funct, targets, defs, uses, region, ...},
1709                             cutTo), an) =
1710                 call(funct,targets,defs,uses,region,cutTo,an)
1711          | stmt(T.RET _, an) = mark(I.RET NONE, an)          | stmt(T.RET _, an) = mark(I.RET NONE, an)
1712          | stmt(T.STORE(8, ea, d, mem), an) = store8(ea, d, mem, an)          | stmt(T.STORE(8, ea, d, mem), an)  =
1713          | stmt(T.STORE(16, ea, d, mem), an) = store16(ea, d, mem, an)               store(8, ea, d, mem, an, opcodes8, store8)
1714          | stmt(T.STORE(32, ea, d, mem), an) = store32(ea, d, mem, an)          | stmt(T.STORE(16, ea, d, mem), an) =
1715                 store(16, ea, d, mem, an, opcodes16, store16)
1716            | stmt(T.STORE(32, ea, d, mem), an) =
1717                 store(32, ea, d, mem, an, opcodes32, store32)
1718    
1719          | stmt(T.FSTORE(fty, ea, d, mem), an) = fstore(fty, ea, d, mem, an)          | stmt(T.FSTORE(fty, ea, d, mem), an) = fstore(fty, ea, d, mem, an)
1720          | stmt(T.BCC(cc, lab), an) = branch(cc, lab, an)          | stmt(T.BCC(cc, lab), an) = branch(cc, lab, an)
1721          | stmt(T.DEFINE l, _) = defineLabel l          | stmt(T.DEFINE l, _) = defineLabel l
# Line 1613  Line 1771 
1771               entryLabel  = entryLabel,               entryLabel  = entryLabel,
1772               comment     = comment,               comment     = comment,
1773               annotation  = annotation,               annotation  = annotation,
1774                 getAnnotations = getAnnotations,
1775               exitBlock   = fn mlrisc => exitBlock(cellset mlrisc)               exitBlock   = fn mlrisc => exitBlock(cellset mlrisc)
1776            }            }
1777    

Legend:
Removed from v.744  
changed lines
  Added in v.815

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