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 545, Thu Feb 24 13:56:44 2000 UTC revision 717, Sun Nov 5 15:07:51 2000 UTC
# Line 1  Line 1 
1  (* X86.sml -- pattern matching version of x86 instruction set generation.  (*
2   *   *
3   * COPYRIGHT (c) 1998 Bell Laboratories.   * COPYRIGHT (c) 1998 Bell Laboratories.
4   *   *
# Line 31  Line 31 
31  functor X86  functor X86
32    (structure X86Instr : X86INSTR    (structure X86Instr : X86INSTR
33     structure X86MLTree : MLTREE     structure X86MLTree : MLTREE
34    (* structure PseudoInstrs : X86_PSEUDO_INSTR *)     structure ExtensionComp : MLTREE_EXTENSION_COMP
35         where I = X86Instr and T = X86MLTree
36       sharing X86MLTree.Region = X86Instr.Region       sharing X86MLTree.Region = X86Instr.Region
37       sharing X86MLTree.LabelExp = X86Instr.LabelExp       sharing X86MLTree.LabelExp = X86Instr.LabelExp
      (* sharing PseudoInstrs.I = X86Instr  
      sharing PseudoInstrs.T = X86MLTree *)  
38      datatype arch = Pentium | PentiumPro | PentiumII | PentiumIII      datatype arch = Pentium | PentiumPro | PentiumII | PentiumIII
39      val arch : arch ref      val arch : arch ref
40      val tempMem : X86Instr.operand (* temporary for CVTI2F *)      val cvti2f :
41      (* val memRegsUsed : word ref *)    (* bit mask of memRegs used *)           (* source operand, guaranteed to be non-memory! *)
42             {ty: X86MLTree.ty, src: X86Instr.operand} ->
43             {instrs : X86Instr.instruction list,(* the instructions *)
44              tempMem: X86Instr.operand,         (* temporary for CVTI2F *)
45              cleanup: X86Instr.instruction list (* cleanup code *)
46             }
47    ) : sig include MLTREECOMP    ) : sig include MLTREECOMP
48            val rewriteMemReg : bool            val rewriteMemReg : bool
49        end =        end =
# Line 54  Line 58 
58    structure A = MLRiscAnnotations    structure A = MLRiscAnnotations
59    
60    type instrStream = (I.instruction,C.regmap,C.cellset) T.stream    type instrStream = (I.instruction,C.regmap,C.cellset) T.stream
61    type ('s,'r,'f,'c) mltreeStream =    type mltreeStream = (T.stm,C.regmap,T.mlrisc list) T.stream
62       (('s,'r,'f,'c) T.stm,C.regmap,('s,'r,'f,'c) T.mlrisc list) T.stream  
63    type ('s,'r,'f,'c) reducer =    datatype kind = REAL | INTEGER
      (I.instruction,C.regmap,C.cellset,I.operand,I.addressing_mode,'s,'r,'f,'c)  
        T.reducer  
   type ('s,'r,'f,'c) extender =  
      (I.instruction,C.regmap,C.cellset,I.operand,I.addressing_mode,'s,'r,'f,'c)  
        T.extender  
64    
65    structure Gen = MLTreeGen    structure Gen = MLTreeGen
66       (structure T = T       (structure T = T
# Line 79  Line 78 
78    val rewriteMemReg = rewriteMemReg    val rewriteMemReg = rewriteMemReg
79    fun isMemReg r = rewriteMemReg andalso r >= 8 andalso r < 32    fun isMemReg r = rewriteMemReg andalso r >= 8 andalso r < 32
80    
81      val ST0 = C.ST 0
82      val ST7 = C.ST 7
83    
84    (*    (*
85     * The code generator     * The code generator
86     *)     *)
87    fun selectInstructions    fun selectInstructions
        (T.EXTENDER{compileStm,compileRexp,compileFexp,compileCCexp,...})  
88         (instrStream as         (instrStream as
89          S.STREAM{emit,defineLabel,entryLabel,pseudoOp,annotation,          S.STREAM{emit,defineLabel,entryLabel,pseudoOp,annotation,
90                   beginCluster,endCluster,exitBlock,alias,phi,comment,...}) =                   beginCluster,endCluster,exitBlock,alias,phi,comment,...}) =
# Line 174  Line 175 
175          | setZeroBit(T.SRA _)      = true          | setZeroBit(T.SRA _)      = true
176          | setZeroBit(T.SRL _)      = true          | setZeroBit(T.SRL _)      = true
177          | setZeroBit(T.SLL _)      = true          | setZeroBit(T.SLL _)      = true
178            | setZeroBit(T.SUB _)      = true
179            | setZeroBit(T.ADDT _)     = true
180            | setZeroBit(T.SUBT _)     = true
181          | setZeroBit(T.MARK(e, _)) = setZeroBit e          | setZeroBit(T.MARK(e, _)) = setZeroBit e
182          | setZeroBit _             = false          | setZeroBit _             = false
183    
184          fun setZeroBit2(T.ANDB _)     = true
185            | setZeroBit2(T.ORB _)      = true
186            | setZeroBit2(T.XORB _)     = true
187            | setZeroBit2(T.SRA _)      = true
188            | setZeroBit2(T.SRL _)      = true
189            | setZeroBit2(T.SLL _)      = true
190            | setZeroBit2(T.ADD(32, _, _)) = true (* can't use leal! *)
191            | setZeroBit2(T.SUB _)      = true
192            | setZeroBit2(T.ADDT _)     = true
193            | setZeroBit2(T.SUBT _)     = true
194            | setZeroBit2(T.MARK(e, _)) = setZeroBit2 e
195            | setZeroBit2 _             = false
196    
197        (* emit parallel copies for floating point *)        (* emit parallel copies for floating point *)
198        fun fcopy(fty, [], [], _) = ()        fun fcopy(fty, [], [], _) = ()
199          | fcopy(fty, dst as [_], src as [_], an) =          | fcopy(fty, dst as [_], src as [_], an) =
# Line 368  Line 385 
385            | I.Indexed _  => true            | I.Indexed _  => true
386            | I.MemReg _   => true            | I.MemReg _   => true
387            | I.LabelEA _  => true            | I.LabelEA _  => true
388              | I.FDirect f  => true
389            | _            => false            | _            => false
390            )            )
391    
# Line 453  Line 471 
471                fun divrem(signed, overflow, e1, e2, resultReg) =                fun divrem(signed, overflow, e1, e2, resultReg) =
472                let val (opnd1, opnd2) = (operand e1, operand e2)                let val (opnd1, opnd2) = (operand e1, operand e2)
473                    val _ = move(opnd1, eax)                    val _ = move(opnd1, eax)
474                    val oper = if signed then (emit(I.CDQ); I.IDIV)                    val oper = if signed then (emit(I.CDQ); I.IDIVL)
475                               else (zero edx; I.UDIV)                               else (zero edx; I.DIVL)
476                in  mark(I.MULTDIV{multDivOp=oper, src=regOrMem opnd2},an);                in  mark(I.MULTDIV{multDivOp=oper, src=regOrMem opnd2},an);
477                    move(resultReg, rdOpnd);                    move(resultReg, rdOpnd);
478                    if overflow then trap() else ()                    if overflow then trap() else ()
# Line 507  Line 525 
525                fun uMultiply(e1, e2) =                fun uMultiply(e1, e2) =
526                    (* note e2 can never be (I.Direct edx) *)                    (* note e2 can never be (I.Direct edx) *)
527                    (move(operand e1, eax);                    (move(operand e1, eax);
528                     mark(I.MULTDIV{multDivOp=I.UMUL,                     mark(I.MULTDIV{multDivOp=I.MULL,
529                                    src=regOrMem(operand e2)},an);                                    src=regOrMem(operand e2)},an);
530                     move(eax, rdOpnd)                     move(eax, rdOpnd)
531                    )                    )
# Line 585  Line 603 
603    
604                   (* Generate setcc instruction:                   (* Generate setcc instruction:
605                    *  semantics:  MV(rd, COND(_, T.CMP(ty, cc, t1, t2), yes, no))                    *  semantics:  MV(rd, COND(_, T.CMP(ty, cc, t1, t2), yes, no))
606                      * Bug, if eax is either t1 or t2 then problem will occur!!!
607                      * Note that we have to use eax as the destination of the
608                      * setcc because it only works on the registers
609                      * %al, %bl, %cl, %dl and %[abcd]h.  The last four registers
610                      * are inaccessible in 32 bit mode.
611                    *)                    *)
612                fun setcc(ty, cc, t1, t2, yes, no) =                fun setcc(ty, cc, t1, t2, yes, no) =
613                let val tmpR = newReg()                let val (cc, yes, no) =
614                    val tmp = I.Direct tmpR                           if yes > no then (cc, yes, no)
615                    (* We create a temporary here just in                           else (T.Basis.negateCond cc, no, yes)
                    * case t1 or t2 contains a use of rd.  
                    *)  
616                in  (* Clear the destination first.                in  (* Clear the destination first.
617                     * This this because stupid SETcc                     * This this because stupid SETcc
618                     * only writes to the low order                     * only writes to the low order
619                     * byte.  That's Intel architecture, folks.                     * byte.  That's Intel architecture, folks.
620                     *)                     *)
621                    zero tmp;                    case (yes, no, cc) of
622                    case (yes, no) of                      (1, 0, T.LT) =>
623                      (1, 0) => (* normal case *)                       let val tmp = I.Direct(expr(T.SUB(32,t1,t2)))
624                         in  move(tmp, rdOpnd);
625                             emit(I.BINARY{binOp=I.SHRL,src=I.Immed 31,dst=rdOpnd})
626                         end
627                      | (1, 0, T.GT) =>
628                         let val tmp = I.Direct(expr(T.SUB(32,t1,t2)))
629                         in  emit(I.UNARY{unOp=I.NOTL,opnd=tmp});
630                             move(tmp, rdOpnd);
631                             emit(I.BINARY{binOp=I.SHRL,src=I.Immed 31,dst=rdOpnd})
632                         end
633                      | (1, 0, _) => (* normal case *)
634                      let val cc = cmp(true, ty, cc, t1, t2, [])                      let val cc = cmp(true, ty, cc, t1, t2, [])
635                      in  mark(I.SET{cond=cond cc, opnd=tmp}, an) end                      in  mark(I.SET{cond=cond cc, opnd=eax}, an);
636                    | (0, 1) => (* flip *)                          emit(I.BINARY{binOp=I.ANDL,src=I.Immed 255, dst=eax});
637                      let val cc = cmp(true, ty,                          move(eax, rdOpnd)
638                                       T.Basis.negateCond cc, t1, t2, [])                      end
639                      in  mark(I.SET{cond=cond cc, opnd=tmp}, an) end                    | (C1, C2, _)  =>
                   | (C1, C2)  =>  
640                      (* general case;                      (* general case;
641                       * from the Intel optimization guide p3-5 *)                       * from the Intel optimization guide p3-5
642                      let val C1 = toInt32 C1                       *)
643                          val C2 = toInt32 C2                      let val _  = zero eax;
644                          val cc = cmp(true, ty, cc, t1, t2, [])                          val cc = cmp(true, ty, cc, t1, t2, [])
645                      in  emit(I.SET{cond=cond cc, opnd=tmp});                      in  case C1-C2 of
646                          case Int32.abs(C1-C2)-1 of                            D as (1 | 2 | 3 | 4 | 5 | 8 | 9) =>
647                            D as (1 | 2 | 4 | 8) =>                            let val (base,scale) =
648                            let val addr = I.Indexed{base=SOME tmpR,                                    case D of
649                                                     index=tmpR,                                      1 => (NONE, 0)
650                                                     scale=Int32.toInt D,                                    | 2 => (NONE, 1)
651                                                     disp=I.Immed(C1-C2),                                    | 3 => (SOME C.eax, 1)
652                                      | 4 => (NONE, 2)
653                                      | 5 => (SOME C.eax, 2)
654                                      | 8 => (NONE, 3)
655                                      | 9 => (SOME C.eax, 3)
656                                  val addr = I.Indexed{base=base,
657                                                       index=C.eax,
658                                                       scale=scale,
659                                                       disp=I.Immed C2,
660                                                     mem=readonly}                                                     mem=readonly}
661                            in  mark(I.LEA{r32=tmpR, addr=addr}, an) end                                val tmpR = newReg()
662                          | _ =>                                val tmp  = I.Direct tmpR
663                           (emit(I.UNARY{unOp=I.DECL, opnd=tmp});                            in  emit(I.SET{cond=cond cc, opnd=eax});
664                                  mark(I.LEA{r32=tmpR, addr=addr}, an);
665                                  move(tmp, rdOpnd)
666                              end
667                            | D =>
668                               (emit(I.SET{cond=cond(T.Basis.negateCond cc),
669                                           opnd=eax});
670                                emit(I.UNARY{unOp=I.DECL, opnd=eax});
671                            emit(I.BINARY{binOp=I.ANDL,                            emit(I.BINARY{binOp=I.ANDL,
672                                          src=I.Immed(C2-C1), dst=tmp});                                            src=I.Immed D, dst=eax});
673                            mark(I.BINARY{binOp=I.ADDL,                              if C2 = 0 then
674                                          src=I.Immed(Int32.min(C1,C2)),                                 move(eax, rdOpnd)
675                                          dst=tmp}, an)                              else
676                           )                                 let val tmpR = newReg()
677                      end;                                     val tmp  = I.Direct tmpR
678                                   in  mark(I.LEA{addr=
679                                             I.Displace{
680                                                 base=C.eax,
681                                                 disp=I.Immed C2,
682                                                 mem=readonly},
683                                                 r32=tmpR}, an);
684                    move(tmp, rdOpnd)                    move(tmp, rdOpnd)
685                                    end
686                               )
687                        end
688                end (* setcc *)                end (* setcc *)
689    
690                    (* Generate cmovcc instruction.                    (* Generate cmovcc instruction.
# Line 647  Line 701 
701    
702                fun unknownExp exp = doExpr(Gen.compileRexp exp, rd, an)                fun unknownExp exp = doExpr(Gen.compileRexp exp, rd, an)
703    
704                      (* Add n to rd *)
705                  fun addN n =
706                  let val n = operand n
707                      val src = if isMemReg rd then immedOrReg n else n
708                  in  mark(I.BINARY{binOp=I.ADDL, src=src, dst=rdOpnd}, an) end
709    
710                    (* Generate addition *)                    (* Generate addition *)
711                fun addition(e1, e2) =                fun addition(e1, e2) =
712                      case e1 of
713                        T.REG(_,rs) => if rs = rd then addN e2 else addition1(e1,e2)
714                      | _ => addition1(e1,e2)
715                  and addition1(e1, e2) =
716                      case e2 of
717                        T.REG(_,rs) => if rs = rd then addN e1 else addition2(e1,e2)
718                      | _ => addition2(e1,e2)
719                  and addition2(e1,e2) =
720                  (dstMustBeReg(fn (dstR, _) =>                  (dstMustBeReg(fn (dstR, _) =>
721                      mark(I.LEA{r32=dstR, addr=address(exp, readonly)}, an))                      mark(I.LEA{r32=dstR, addr=address(exp, readonly)}, an))
722                  handle EA => binaryComm(I.ADDL, e1, e2))                  handle EA => binaryComm(I.ADDL, e1, e2))
723    
                   (* Add n to rd *)  
               fun addN n =  
                 mark(I.BINARY{binOp=I.ADDL, src=I.Immed(toInt32 n),  
                               dst=rdOpnd}, an)  
724    
725            in  case exp of            in  case exp of
726                 T.REG(_,rs) =>                 T.REG(_,rs) =>
# Line 682  Line 746 
746               | T.ADD(32, (T.LI 1|T.LI32 0w1), e) => unary(I.INCL, e)               | T.ADD(32, (T.LI 1|T.LI32 0w1), e) => unary(I.INCL, e)
747               | T.ADD(32, e, T.LI ~1) => unary(I.DECL, e)               | T.ADD(32, e, T.LI ~1) => unary(I.DECL, e)
748               | T.ADD(32, T.LI ~1, e) => unary(I.DECL, e)               | T.ADD(32, T.LI ~1, e) => unary(I.DECL, e)
              | T.ADD(32, e1 as T.REG(_, rs), e2 as T.LI n) =>  
                   if rs = rd then addN n else addition(e1, e2)  
              | T.ADD(32, e1 as T.LI n, e2 as T.REG(_, rs)) =>  
                   if rs = rd then addN n else addition(e1, e2)  
749               | T.ADD(32, e1, e2) => addition(e1, e2)               | T.ADD(32, e1, e2) => addition(e1, e2)
750    
751                   (* 32-bit addition but set the flag!
752                    * This is a stupid hack for now.
753                    *)
754                 | T.ADD(0, e, (T.LI 1|T.LI32 0w1)) => unary(I.INCL, e)
755                 | T.ADD(0, (T.LI 1|T.LI32 0w1), e) => unary(I.INCL, e)
756                 | T.ADD(0, e, T.LI ~1) => unary(I.DECL, e)
757                 | T.ADD(0, T.LI ~1, e) => unary(I.DECL, e)
758                 | T.ADD(0, e1, e2) => binaryComm(I.ADDL, e1, e2)
759    
760                 (* 32-bit subtraction *)                 (* 32-bit subtraction *)
761                 | T.SUB(32, e, (T.LI 0 | T.LI32 0w0)) => doExpr(e, rd, an)
762               | T.SUB(32, e, (T.LI 1 | T.LI32 0w1)) => unary(I.DECL, e)               | T.SUB(32, e, (T.LI 1 | T.LI32 0w1)) => unary(I.DECL, e)
763               | T.SUB(32, e, T.LI ~1) => unary(I.INCL, e)               | T.SUB(32, e, T.LI ~1) => unary(I.INCL, e)
764               | T.SUB(32, (T.LI 0 | T.LI32 0w0), e) => unary(I.NEGL, e)               | T.SUB(32, (T.LI 0 | T.LI32 0w0), e) => unary(I.NEGL, e)
# Line 731  Line 801 
801               | T.CVTI2I(_,T.SIGN_EXTEND,_,T.LOAD(16,ea,mem)) => load16s(ea, mem)               | T.CVTI2I(_,T.SIGN_EXTEND,_,T.LOAD(16,ea,mem)) => load16s(ea, mem)
802    
803               | 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) =>
804                   setcc(ty, cc, t1, t2, yes, no)                   setcc(ty, cc, t1, t2, toInt32 yes, toInt32 no)
805                 | T.COND(32, T.CMP(ty, cc, t1, t2), T.LI32 yes, T.LI32 no) =>
806                     setcc(ty, cc, t1, t2, Word32.toLargeIntX yes,
807                                           Word32.toLargeIntX no)
808               | T.COND(32, T.CMP(ty, cc, t1, t2), yes, no) =>               | T.COND(32, T.CMP(ty, cc, t1, t2), yes, no) =>
809                  (case !arch of (* PentiumPro and higher has CMOVcc *)                  (case !arch of (* PentiumPro and higher has CMOVcc *)
810                     Pentium => unknownExp exp                     Pentium => unknownExp exp
# Line 741  Line 814 
814               | T.MARK(e, A.MARKREG f) => (f rd; doExpr(e, rd, an))               | T.MARK(e, A.MARKREG f) => (f rd; doExpr(e, rd, an))
815               | T.MARK(e, a) => doExpr(e, rd, a::an)               | T.MARK(e, a) => doExpr(e, rd, a::an)
816               | T.PRED(e,c) => doExpr(e, rd, A.CTRLUSE c::an)               | T.PRED(e,c) => doExpr(e, rd, A.CTRLUSE c::an)
817               | T.REXT e => compileRexp (reducer()) {e=e, rd=rd, an=an}               | T.REXT e =>
818                     ExtensionComp.compileRext (reducer()) {e=e, rd=rd, an=an}
819                 (* simplify and try again *)                 (* simplify and try again *)
820               | exp => unknownExp exp               | exp => unknownExp exp
821            end (* doExpr *)            end (* doExpr *)
# Line 761  Line 835 
835            * On the x86, TEST is superior to AND for doing the same thing,            * On the x86, TEST is superior to AND for doing the same thing,
836            * since it doesn't need to write out the result in a register.            * since it doesn't need to write out the result in a register.
837            *)            *)
838       and cmpWithZero(cc as (T.EQ | T.NE), e as T.ANDB(ty, a, b))  =       and cmpWithZero(cc as (T.EQ | T.NE), e as T.ANDB(ty, a, b), an) =
839              (case ty of              (case ty of
840                 8 =>  test(I.TESTB, a, b)                 8  => test(I.TESTB, a, b, an)
841               | 16 => test(I.TESTW, a, b)               | 16 => test(I.TESTW, a, b, an)
842               | 32 => test(I.TESTL, a, b)               | 32 => test(I.TESTL, a, b, an)
843               | _  => (expr e; ())               | _  => doExpr(e, newReg(), an);
844               ; cc)               cc)
845          | cmpWithZero(cc, e) = (expr e; cc)          | cmpWithZero(cc, e, an) =
846              let val e =
847                    case e of (* hack to disable the lea optimization XXX *)
848                      T.ADD(_, a, b) => T.ADD(0, a, b)
849                    | e => e
850              in  doExpr(e, newReg(), an); cc end
851    
852            (* Emit a test.            (* Emit a test.
853             *   The available modes are             *   The available modes are
# Line 785  Line 864 
864             * are one of EAX, ECX, EBX, or EDX, replace the TESTL instruction             * are one of EAX, ECX, EBX, or EDX, replace the TESTL instruction
865             * by TESTB.             * by TESTB.
866             *)             *)
867        and test(testopcode, a, b) =        and test(testopcode, a, b, an) =
868            let val (_, opnd1, opnd2) = commuteComparison(T.EQ, true, a, b)            let val (_, opnd1, opnd2) = commuteComparison(T.EQ, true, a, b)
869                (* translate r, r/m => r/m, r *)                (* translate r, r/m => r/m, r *)
870                val (opnd1, opnd2) =                val (opnd1, opnd2) =
871                     if isMemOpnd opnd2 then (opnd2, opnd1) else (opnd1, opnd2)                     if isMemOpnd opnd2 then (opnd2, opnd1) else (opnd1, opnd2)
872            in  emit(testopcode{lsrc=opnd1, rsrc=opnd2})            in  mark(testopcode{lsrc=opnd1, rsrc=opnd2}, an)
873            end            end
874    
875           (* generate a condition code expression           (* generate a condition code expression
# Line 802  Line 881 
881          | 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))
882          | doCCexpr(T.CCMARK(e,a), rd, an) = doCCexpr(e,rd,a::an)          | doCCexpr(T.CCMARK(e,a), rd, an) = doCCexpr(e,rd,a::an)
883          | doCCexpr(T.CCEXT e, cd, an) =          | doCCexpr(T.CCEXT e, cd, an) =
884             compileCCexp (reducer()) {e=e, cd=cd, an=an}             ExtensionComp.compileCCext (reducer()) {e=e, ccd=cd, an=an}
885          | doCCexpr _ = error "doCCexpr"          | doCCexpr _ = error "doCCexpr"
886    
887       and ccExpr e = error "ccExpr"       and ccExpr e = error "ccExpr"
# Line 812  Line 891 
891             * we can also reorder the operands.             * we can also reorder the operands.
892             *)             *)
893        and cmp(swapable, ty, cc, t1, t2, an) =        and cmp(swapable, ty, cc, t1, t2, an) =
894            (case cc of                 (* == and <> can be always be reordered *)
895               (T.EQ | T.NE) =>            let val swapable = swapable orelse cc = T.EQ orelse cc = T.NE
896                (* Sometimes the comparison is not necessary because            in (* Sometimes the comparison is not necessary because
897                 * the bits are already set!                 * the bits are already set!
898                 *)                 *)
899                if isZero t1 andalso setZeroBit t2 then cmpWithZero(cc, t2)               if isZero t1 andalso setZeroBit2 t2 then
900                else if isZero t2 andalso setZeroBit t1 then cmpWithZero(cc, t1)                   if swapable then
901                     (* == and <> can be reordered *)                      cmpWithZero(T.Basis.swapCond cc, t2, an)
902                else genCmp(ty, true, cc, t1, t2, an)                   else (* can't reorder the comparison! *)
903             |  _ => genCmp(ty, swapable, cc, t1, t2, an)                      genCmp(ty, false, cc, t1, t2, an)
904            )               else if isZero t2 andalso setZeroBit2 t1 then
905                    cmpWithZero(cc, t1, an)
906                 else genCmp(ty, swapable, cc, t1, t2, an)
907              end
908    
909            (* Give a and b which are the operands to a comparison (or test)            (* Give a and b which are the operands to a comparison (or test)
910             * Return the appropriate condition code and operands.             * Return the appropriate condition code and operands.
# Line 915  Line 997 
997                    emit(I.FUCOMPP)                    emit(I.FUCOMPP)
998                end                end
999                fun andil i = emit(I.BINARY{binOp=I.ANDL,src=I.Immed(i),dst=eax})                fun andil i = emit(I.BINARY{binOp=I.ANDL,src=I.Immed(i),dst=eax})
1000                  fun testil i = emit(I.TESTL{lsrc=eax,rsrc=I.Immed(i)})
1001                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})
1002                fun cmpil i = emit(I.CMPL{rsrc=I.Immed(i), lsrc=eax})                fun cmpil i = emit(I.CMPL{rsrc=I.Immed(i), lsrc=eax})
1003                fun j(cc, lab) = mark(I.JCC{cond=cc, opnd=immedLabel lab},an)                fun j(cc, lab) = mark(I.JCC{cond=cc, opnd=immedLabel lab},an)
# Line 925  Line 1008 
1008                     | T.?<>  => (andil 0x4400; xoril 0x4000; j(I.NE, lab))                     | T.?<>  => (andil 0x4400; xoril 0x4000; j(I.NE, lab))
1009                     | T.?    => (sahf(); j(I.P,lab))                     | T.?    => (sahf(); j(I.P,lab))
1010                     | T.<=>  => (sahf(); j(I.NP,lab))                     | T.<=>  => (sahf(); j(I.NP,lab))
1011                     | T.>    => (andil 0x4500;  j(I.EQ,lab))                     | T.>    => (testil 0x4500;  j(I.EQ,lab))
1012                     | T.?<=  => (andil 0x4500;  j(I.NE,lab))                     | T.?<=  => (testil 0x4500;  j(I.NE,lab))
1013                     | T.>=   => (andil 0x500; j(I.EQ,lab))                     | T.>=   => (testil 0x500; j(I.EQ,lab))
1014                     | T.?<   => (andil 0x500; j(I.NE,lab))                     | T.?<   => (testil 0x500; j(I.NE,lab))
1015                     | T.<    => (andil 0x4500; cmpil 0x100; j(I.EQ,lab))                     | T.<    => (andil 0x4500; cmpil 0x100; j(I.EQ,lab))
1016                     | T.?>=  => (andil 0x4500; cmpil 0x100; j(I.NE,lab))                     | T.?>=  => (andil 0x4500; cmpil 0x100; j(I.NE,lab))
1017                     | T.<=   => (andil 0x4100; cmpil 0x100; j(I.EQ,lab);                     | T.<=   => (andil 0x4100; cmpil 0x100; j(I.EQ,lab);
1018                                  cmpil 0x4000; j(I.EQ,lab))                                  cmpil 0x4000; j(I.EQ,lab))
1019                     | T.?>   => (sahf(); j(I.P,lab); andil 0x4100; j(I.EQ,lab))                     | T.?>   => (sahf(); j(I.P,lab); testil 0x4100; j(I.EQ,lab))
1020                     | T.<>   => (andil 0x4400; j(I.EQ,lab))                     | T.<>   => (testil 0x4400; j(I.EQ,lab))
1021                     | T.?=   => (andil 0x4400; j(I.NE,lab))                     | T.?=   => (testil 0x4400; j(I.NE,lab))
1022                     | _      => error "fbranch"                     | _      => error "fbranch"
1023                   (*esac*)                   (*esac*)
1024            in  compare(); emit I.FNSTSW; branch()            in  compare(); emit I.FNSTSW; branch()
# Line 943  Line 1026 
1026    
1027        and fld(32, opnd) = I.FLDS opnd        and fld(32, opnd) = I.FLDS opnd
1028          | fld(64, opnd) = I.FLDL opnd          | fld(64, opnd) = I.FLDL opnd
1029            | fld(80, opnd) = I.FLDT opnd
1030          | fld _         = error "fld"          | fld _         = error "fld"
1031    
1032          and fild(16, opnd) = I.FILD opnd
1033            | fild(32, opnd) = I.FILDL opnd
1034            | fild(64, opnd) = I.FILDLL opnd
1035            | fild _         = error "fild"
1036    
1037          and fxld(INTEGER, ty, opnd) = fild(ty, opnd)
1038            | fxld(REAL, fty, opnd) = fld(fty, opnd)
1039    
1040        and fstp(32, opnd) = I.FSTPS opnd        and fstp(32, opnd) = I.FSTPS opnd
1041          | fstp(64, opnd) = I.FSTPL opnd          | fstp(64, opnd) = I.FSTPL opnd
1042            | fstp(80, opnd) = I.FSTPT opnd
1043          | fstp _         = error "fstp"          | fstp _         = error "fstp"
1044    
1045            (* generate code for floating point stores *)            (* generate code for floating point stores *)
# Line 957  Line 1050 
1050             mark(fstp(fty, address(ea, mem)), an)             mark(fstp(fty, address(ea, mem)), an)
1051            )            )
1052    
1053        and fexpr e = error "fexpr"        and fexpr e = (reduceFexp(64, e, []); C.ST(0))
1054    
1055            (* generate floating point expression and put the result in fd *)            (* generate floating point expression and put the result in fd *)
1056        and doFexpr(fty, T.FREG(_, fs), fd, an) =        and doFexpr(fty, T.FREG(_, fs), fd, an) =
# Line 967  Line 1060 
1060          | doFexpr(fty, T.FLOAD(fty', ea, mem), fd, an) =          | doFexpr(fty, T.FLOAD(fty', ea, mem), fd, an) =
1061              let val ea = address(ea, mem)              let val ea = address(ea, mem)
1062              in  mark(fld(fty', ea), an);              in  mark(fld(fty', ea), an);
1063                  emit(fstp(fty, I.FDirect fd))                  if fd = ST0 then () else emit(fstp(fty, I.FDirect fd))
1064              end              end
1065            | doFexpr(fty, T.FEXT fexp, fd, an) =
1066                (ExtensionComp.compileFext (reducer()) {e=fexp, fd=fd, an=an};
1067                 if fd = ST0 then () else emit(fstp(fty, I.FDirect fd))
1068                )
1069          | doFexpr(fty, e, fd, an) =          | doFexpr(fty, e, fd, an) =
1070              (reduceFexp(fty, e, []);              (reduceFexp(fty, e, []);
1071               mark(fstp(fty, I.FDirect fd), an)               if fd = ST0 then () else mark(fstp(fty, I.FDirect fd), an)
1072              )              )
1073    
1074            (*            (*
# Line 980  Line 1077 
1077             * and put result in %ST(0).             * and put result in %ST(0).
1078             *)             *)
1079        and reduceFexp(fty, fexp, an)  =        and reduceFexp(fty, fexp, an)  =
1080            let val ST = I.FDirect(C.ST 0)            let val ST = I.ST(C.ST 0)
1081                val ST1 = I.FDirect(C.ST 1)                val ST1 = I.ST(C.ST 1)
1082                  val cleanupCode = ref [] : I.instruction list ref
1083                datatype su_numbers =  
1084                  LEAF of int                datatype su_tree =
1085                | BINARY of int * su_numbers * su_numbers                  LEAF of int * T.fexp * ans
1086                | UNARY of int * su_numbers                | BINARY of int * T.fty * fbinop * su_tree * su_tree * ans
1087                  | UNARY of int * T.fty * I.funOp * su_tree * ans
1088                datatype direction = LEFT | RIGHT                and fbinop = FADD | FSUB | FMUL | FDIV
1089                             | FIADD | FISUB | FIMUL | FIDIV
1090                fun label(LEAF n) = n                withtype ans = Annotations.annotations
1091                  | label(BINARY(n, _, _)) = n  
1092                  | label(UNARY(n, _)) = n                fun label(LEAF(n, _, _)) = n
1093                    | label(BINARY(n, _, _, _, _, _)) = n
1094               (* Generate tree of sethi-ullman numbers *)                  | label(UNARY(n, _, _, _, _)) = n
1095                fun suBinary(t1, t2) =  
1096                    let val su1 = suNumbering(t1, LEFT)                fun annotate(LEAF(n, x, an), a)  = LEAF(n,x,a::an)
1097                        val su2 = suNumbering(t2, RIGHT)                  | annotate(BINARY(n,t,b,x,y,an), a) = BINARY(n,t,b,x,y,a::an)
1098                        val n1 = label su1                  | annotate(UNARY(n,t,u,x,an), a) = UNARY(n,t,u,x,a::an)
1099                        val n2 = label su2  
1100                    in  BINARY(if n1=n2 then n1+1 else Int.max(n1, n2), su1, su2)                (* Generate expression tree with sethi-ullman numbers *)
1101                    end                fun su(e as T.FREG _)       = LEAF(1, e, [])
1102                    | su(e as T.FLOAD _)      = LEAF(1, e, [])
1103                and suUnary(t) =                  | su(e as T.CVTI2F _)     = LEAF(1, e, [])
1104                    let val su = suNumbering(t, LEFT)                  | su(T.CVTF2F(_, _, t))   = su t
1105                    in  UNARY(label su, su)                  | su(T.FMARK(t, a))       = annotate(su t, a)
1106                    end                  | su(T.FABS(fty, t))      = suUnary(fty, I.FABS, t)
1107                    | su(T.FNEG(fty, t))      = suUnary(fty, I.FCHS, t)
1108                and suNumbering(T.FREG _, LEFT) = LEAF 1                  | su(T.FSQRT(fty, t))     = suUnary(fty, I.FSQRT, t)
1109                  | suNumbering(T.FREG _, RIGHT) = LEAF 0                  | su(T.FADD(fty, t1, t2)) = suComBinary(fty,FADD,FIADD,t1,t2)
1110                  | suNumbering(T.FLOAD _, LEFT) = LEAF 1                  | su(T.FMUL(fty, t1, t2)) = suComBinary(fty,FMUL,FIMUL,t1,t2)
1111                  | suNumbering(T.FLOAD _, RIGHT) = LEAF 0                  | su(T.FSUB(fty, t1, t2)) = suBinary(fty,FSUB,FISUB,t1,t2)
1112                  | suNumbering(T.FADD(_, t1, t2), _) = suBinary(t1, t2)                  | su(T.FDIV(fty, t1, t2)) = suBinary(fty,FDIV,FIDIV,t1,t2)
1113                  | suNumbering(T.FMUL(_, t1, t2), _) = suBinary(t1, t2)                  | su _ = error "su"
1114                  | suNumbering(T.FSUB(_, t1, t2), _) = suBinary(t1, t2)  
1115                  | suNumbering(T.FDIV(_, t1, t2), _) = suBinary(t1, t2)                (* Try to fold the the memory operand or integer conversion *)
1116                  | suNumbering(T.FABS(_,t), _) = suUnary(t)                and suFold(e as T.FREG _) = (LEAF(0, e, []), false)
1117                  | suNumbering(T.FNEG(_,t), _) = suUnary(t)                  | suFold(e as T.FLOAD _) = (LEAF(0, e, []), false)
1118                  | suNumbering(T.CVTI2F _, _) = UNARY(1, LEAF 0)                  | suFold(e as T.CVTI2F(_,(16 | 32),_)) = (LEAF(0, e, []), true)
1119                  | suNumbering(T.CVTF2F(_,_,t), _) = suUnary t                  | suFold(T.CVTF2F(_, _, t)) = suFold t
1120                  | suNumbering(T.FMARK(e,a),x) = suNumbering(e,x)                  | suFold(T.FMARK(t, a)) =
1121                  | suNumbering _ = error "suNumbering"                    let val (t, integer) = suFold t
1122                      in  (annotate(t, a), integer) end
1123                fun leafEA(T.FREG(fty, f)) = (fty, I.FDirect f)                  | suFold e = (su e, false)
1124                  | leafEA(T.FLOAD(fty, ea, mem)) = (fty, address(ea, mem))  
1125                  | leafEA _ = error "leafEA"                (* Can the tree be folded into the src operand? *)
1126                  and foldable(T.FREG _) = true
1127                fun cvti2d(t,an) =                  | foldable(T.FLOAD _) = true
1128                let val opnd = operand t                  | foldable(T.CVTI2F(_, (16 | 32), _)) = true
1129                    fun doMemOpnd () =                  | foldable(T.CVTF2F(_, _, t)) = foldable t
1130                        (emit(I.MOVE{mvOp=I.MOVL, src=opnd, dst=tempMem});                  | foldable(T.FMARK(t, _)) = foldable t
1131                         mark(I.FILD tempMem,an))                  | foldable _ = false
1132                in  case opnd of  
1133                      I.Direct _ => doMemOpnd()                (* Form unary tree *)
1134                    | I.Immed _ => doMemOpnd()                and suUnary(fty, funary, t) =
1135                    | _ => mark(I.FILD opnd, an)                    let val t = su t
1136                end                    in  UNARY(label t, fty, funary, t, [])
1137                      end
1138                (* traverse expression and su-number tree *)  
1139                fun gencode(_, LEAF 0, an) = ()                (* Form binary tree *)
1140                  | gencode(T.FMARK(e,a), x, an) = gencode(e, x, a::an)                and suBinary(fty, binop, ibinop, t1, t2) =
1141                  | gencode(f, LEAF 1, an) = mark(fld(leafEA f), an)                    let val t1 = su t1
1142                  | gencode(t, BINARY(_, su1, LEAF 0), an) =                        val (t2, integer) = suFold t2
1143                    let (* optimize the common case when both operands                        val n1 = label t1
1144                         * are equal *)                        val n2 = label t2
1145                        fun sameEA(T.FREG(t1, f1), T.FREG(t2, f2)) =                        val n  = if n1=n2 then n1+1 else Int.max(n1,n2)
1146                              t1 = t2 andalso f1 = f2                        val myOp = if integer then ibinop else binop
1147                          | sameEA _ = false                    in  BINARY(n, fty, myOp, t1, t2, [])
1148                        fun doit(oper, t1, t2) =                    end
1149                           (gencode(t1, su1, []);  
1150                            mark(I.FBINARY{binOp=oper,                (* Try to fold in the operand if possible.
1151                                           src=if sameEA(t1, t2) then ST                 * This only applies to commutative operations.
1152                                               else #2(leafEA t2),                 *)
1153                                           dst=ST}, an)                and suComBinary(fty, binop, ibinop, t1, t2) =
1154                           )                    let val (t1, t2) = if foldable t2 then (t1, t2) else (t2, t1)
1155                    in                    in  suBinary(fty, binop, ibinop, t1, t2) end
1156                      case t of  
1157                         T.FADD(_, t1, t2) => doit(I.FADD, t1, t2)                and sameTree(LEAF(_, T.FREG(t1,f1), []),
1158                       | T.FMUL(_, t1, t2) => doit(I.FMUL, t1, t2)                             LEAF(_, T.FREG(t2,f2), [])) = t1=t2 andalso f1=f2
1159                       | T.FSUB(_, t1, t2) => doit(I.FSUB, t1, t2)                  | sameTree _ = false
1160                       | T.FDIV(_, t1, t2) => doit(I.FDIV, t1, t2)  
1161                       | _ => error "gencode.BINARY"                (* Traverse tree and generate code *)
1162                    end                fun gencode(LEAF(_, t, an)) = mark(fxld(leafEA t), an)
1163                  | gencode(fexp, BINARY(fty, su1, su2), an) =                  | gencode(BINARY(_, _, binop, x, t2 as LEAF(0, y, a1), a2)) =
1164                    let fun doit(t1, t2, oper, operP, operRP) = let                    let val _          = gencode x
1165                       (* oper[P] =>  ST(1) := ST oper ST(1); [pop]                        val (_, fty, src) = leafEA y
1166                          fun gen(code) = mark(code, a1 @ a2)
1167                          fun binary(oper32, oper64) =
1168                              if sameTree(x, t2) then
1169                                 gen(I.FBINARY{binOp=oper64, src=ST, dst=ST})
1170                              else
1171                                 let val oper =
1172                                       if isMemOpnd src then
1173                                          case fty of
1174                                            32 => oper32
1175                                          | 64 => oper64
1176                                          | _  => error "gencode: BINARY"
1177                                       else oper64
1178                                 in gen(I.FBINARY{binOp=oper, src=src, dst=ST}) end
1179                          fun ibinary(oper16, oper32) =
1180                              let val oper = case fty of
1181                                               16 => oper16
1182                                             | 32 => oper32
1183                                             | _  => error "gencode: IBINARY"
1184                              in  gen(I.FIBINARY{binOp=oper, src=src}) end
1185                      in  case binop of
1186                            FADD => binary(I.FADDS, I.FADDL)
1187                          | FSUB => binary(I.FDIVS, I.FSUBL)
1188                          | FMUL => binary(I.FMULS, I.FMULL)
1189                          | FDIV => binary(I.FDIVS, I.FDIVL)
1190                          | FIADD => ibinary(I.FIADDS, I.FIADDL)
1191                          | FISUB => ibinary(I.FIDIVS, I.FISUBL)
1192                          | FIMUL => ibinary(I.FIMULS, I.FIMULL)
1193                          | FIDIV => ibinary(I.FIDIVS, I.FIDIVL)
1194                      end
1195                    | gencode(BINARY(_, fty, binop, t1, t2, an)) =
1196                      let fun doit(t1, t2, oper, operP, operRP) =
1197                          let (* oper[P] =>  ST(1) := ST oper ST(1); [pop]
1198                        * operR[P] => ST(1) := ST(1) oper ST; [pop]                        * operR[P] => ST(1) := ST(1) oper ST; [pop]
1199                        *)                        *)
1200                        val n1 = label su1                             val n1 = label t1
1201                        val n2 = label su2                             val n2 = label t2
1202                      in                        in if n1 < n2 andalso n1 <= 7 then
1203                        if n1 < n2 andalso n1 <= 7 then                             (gencode t2;
1204                          (gencode(t2, su2, []);                              gencode t1;
                          gencode(t1, su1, []);  
1205                           mark(I.FBINARY{binOp=operP, src=ST, dst=ST1}, an))                           mark(I.FBINARY{binOp=operP, src=ST, dst=ST1}, an))
1206                        else if n2 <= n1 andalso n2 <= 7 then                        else if n2 <= n1 andalso n2 <= 7 then
1207                          (gencode(t1, su1, []);                             (gencode t1;
1208                           gencode(t2, su2, []);                              gencode t2;
1209                           mark(I.FBINARY{binOp=operRP, src=ST, dst=ST1}, an))                           mark(I.FBINARY{binOp=operRP, src=ST, dst=ST1}, an))
1210                        else let (* both labels > 7 *)                           else
1211                             let (* both labels > 7 *)
1212                            val fs = I.FDirect(newFreg())                            val fs = I.FDirect(newFreg())
1213                          in                           in  gencode t2;
                           gencode (t2, su2, []);  
1214                            emit(fstp(fty, fs));                            emit(fstp(fty, fs));
1215                            gencode (t1, su1, []);                               gencode t1;
1216                            mark(I.FBINARY{binOp=oper, src=fs, dst=ST}, an)                            mark(I.FBINARY{binOp=oper, src=fs, dst=ST}, an)
1217                          end                          end
1218                      end                      end
1219                    in                    in case binop of
1220                      case fexp                         FADD => doit(t1,t2,I.FADDL,I.FADDP,I.FADDP)
1221                      of T.FADD(_, t1, t2) => doit(t1, t2,I.FADD,I.FADDP,I.FADDP)                       | FMUL => doit(t1,t2,I.FMULL,I.FMULP,I.FMULP)
1222                       | T.FMUL(_, t1, t2) => doit(t1, t2,I.FMUL,I.FMULP,I.FMULP)                       | FSUB => doit(t1,t2,I.FSUBL,I.FSUBP,I.FSUBRP)
1223                       | T.FSUB(_, t1, t2) => doit(t1, t2,I.FSUB,I.FSUBP,I.FSUBRP)                       | FDIV => doit(t1,t2,I.FDIVL,I.FDIVP,I.FDIVRP)
                      | T.FDIV(_, t1, t2) => doit(t1, t2,I.FDIV,I.FDIVP,I.FDIVRP)  
1224                       | _ => error "gencode.BINARY"                       | _ => error "gencode.BINARY"
1225                    end                    end
1226                  | gencode(fexp, UNARY(_, LEAF 0), an) =                  | gencode(UNARY(_, _, unaryOp, su, an)) =
1227                    (case fexp                     (gencode(su); mark(I.FUNARY(unaryOp),an))
                     of T.FABS(fty, t) =>  
                          (emit(fld(leafEA t)); mark(I.FUNARY(I.FABS),an))  
                      | T.FNEG(fty, t) =>  
                          (emit(fld(leafEA t)); mark(I.FUNARY(I.FCHS),an))  
                      | T.CVTI2F(_,_,t) => cvti2d(t,an) (* XXX *)  
                      | _ => error "gencode.UNARY"  
                    (*esac*))  
                 | gencode(fexp, UNARY(_, su), an) =  
                   let fun doit(oper, t) =  
                        (gencode(t, su, []); mark(I.FUNARY(oper),an))  
                   in case fexp  
                      of T.FABS(_, t) => doit(I.FABS, t)  
                       | T.FNEG(_, t) => doit(I.FCHS, t)  
                       | T.CVTF2F(_,_,t) => gencode(t, su, an)  
                       | T.CVTI2F _ => error "gencode:UNARY:cvti2f"  
                       | _ => error "gencode.UNARY"  
                   end  
                 | gencode _ = error "gencode"  
1228    
1229                val labels = suNumbering(fexp, LEFT)                (* Generate code for a leaf.
1230            in  gencode(fexp, labels, an)                 * Returns the type and an effective address
1231                   *)
1232                  and leafEA(T.FREG(fty, f)) = (REAL, fty, I.FDirect f)
1233                    | leafEA(T.FLOAD(fty, ea, mem)) = (REAL, fty, address(ea, mem))
1234                    | leafEA(T.CVTI2F(_, 32, t)) = int2real(32, t)
1235                    | leafEA(T.CVTI2F(_, 16, t)) = int2real(16, t)
1236                    | leafEA(T.CVTI2F(_, 8, t))  = int2real(8, t)
1237                    | leafEA _ = error "leafEA"
1238    
1239                  (* Move integer t of size ty into a memory location *)
1240                  and int2real(ty, t) =
1241                      let val opnd = operand t
1242                      in  if isMemOpnd opnd andalso (ty = 16 orelse ty = 32)
1243                          then (INTEGER, ty, opnd)
1244                          else
1245                            let val {instrs, tempMem, cleanup} =
1246                                       cvti2f{ty=ty, src=opnd}
1247                            in  app emit instrs;
1248                                cleanupCode := !cleanupCode @ cleanup;
1249                                (INTEGER, 32, tempMem)
1250                            end
1251                      end
1252              in  gencode(su fexp);
1253                  app emit(!cleanupCode)
1254            end (*reduceFexp*)            end (*reduceFexp*)
1255    
1256            (* generate code for a statement *)            (* generate code for a statement *)
# Line 1128  Line 1260 
1260          | stmt(T.COPY(_, dst, src), an) = copy(dst, src, an)          | stmt(T.COPY(_, dst, src), an) = copy(dst, src, an)
1261          | stmt(T.FCOPY(fty, dst, src), an) = fcopy(fty, dst, src, an)          | stmt(T.FCOPY(fty, dst, src), an) = fcopy(fty, dst, src, an)
1262          | stmt(T.JMP(ctrl, e, labs), an) = jmp(e, labs, an)          | stmt(T.JMP(ctrl, e, labs), an) = jmp(e, labs, an)
1263          | stmt(T.CALL(e, flow, def, use, cdef, cuse, mem), an) =          | stmt(T.CALL{funct, targets, defs, uses, cdefs, cuses, region}, an) =
1264               call(e,flow,def,use,mem,an)               call(funct,targets,defs,uses,region,an)
1265          | stmt(T.RET _, an) = mark(I.RET NONE, an)          | stmt(T.RET _, an) = mark(I.RET NONE, an)
1266          | stmt(T.STORE(8, ea, d, mem), an) = store8(ea, d, mem, an)          | stmt(T.STORE(8, ea, d, mem), an) = store8(ea, d, mem, an)
1267          | stmt(T.STORE(16, ea, d, mem), an) = store16(ea, d, mem, an)          | stmt(T.STORE(16, ea, d, mem), an) = store16(ea, d, mem, an)
# Line 1138  Line 1270 
1270          | stmt(T.BCC(ctrl, cc, lab), an) = branch(cc, lab, an)          | stmt(T.BCC(ctrl, cc, lab), an) = branch(cc, lab, an)
1271          | stmt(T.DEFINE l, _) = defineLabel l          | stmt(T.DEFINE l, _) = defineLabel l
1272          | stmt(T.ANNOTATION(s, a), an) = stmt(s, a::an)          | stmt(T.ANNOTATION(s, a), an) = stmt(s, a::an)
1273            | stmt(T.EXT s, an) =
1274                 ExtensionComp.compileSext (reducer()) {stm=s, an=an}
1275          | stmt(s, _) = doStmts(Gen.compileStm s)          | stmt(s, _) = doStmts(Gen.compileStm s)
1276    
1277        and doStmt s = stmt(s, [])        and doStmt s = stmt(s, [])

Legend:
Removed from v.545  
changed lines
  Added in v.717

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