2  * Assembly code generator for fake x86 assembly
 
   3  * Author: Joshua Wise <jwise@andrew.cmu.edu>
 
   4  * Author: Chris Lu <czl@andrew.cmu.edu>
 
   9   val codegen : Tree.stm list -> x86.insn list
 
  12 structure Codegen :> CODEGEN = 
 
  15   structure TU = TreeUtils
 
  19   (* hasfixed : T.exp -> bool
 
  20    * true iff the given expression has an hasfixed.
 
  22   fun hasfixed (T.BINOP(T.DIV, _, _)) = true
 
  23     | hasfixed (T.BINOP(T.MOD, _, _)) = true
 
  24     | hasfixed (T.BINOP(T.LSH, _, _)) = true
 
  25     | hasfixed (T.BINOP(T.RSH, _, _)) = true
 
  26     | hasfixed (T.CALL _) = true
 
  27     | hasfixed (T.BINOP(_, a, b)) = (hasfixed a) orelse (hasfixed b)
 
  28     | hasfixed (T.UNOP (_, a)) = hasfixed a
 
  29     | hasfixed (T.ALLOC(_)) = true
 
  30     | hasfixed (T.MEMORY (m,s)) = hasfixed m
 
  31     | hasfixed (T.STMVAR _) = true
 
  34   fun offshit a b 0w4 d = [X.LEA(d, (X.REL((a, Tm.Quad), (b, Tm.Quad), 0w4), Tm.Quad))]
 
  35     | offshit a b 0w8 d = [X.LEA(d, (X.REL((a, Tm.Quad), (b, Tm.Quad), 0w8), Tm.Quad))]
 
  36     | offshit a b n d   = [X.IMUL((b, Tm.Long), (X.CONST n, Tm.Long)), X.MOV(d, (a, Tm.Quad)), X.ADD(d, (b, Tm.Quad))]
 
  38   fun binophit_c d oper e c = let val (i, s) = munch_exp d e in (i @ [oper ((d,s), (X.CONST c, s))], s) end
 
  39   and binophit_t d oper e t =
 
  41       val (i, s) = munch_exp d e
 
  43       val rs = if Tm.cmpsize (s, ts) = GREATER then s else ts
 
  45       (i @ [oper ((d, rs), (X.TEMP t, rs))], rs)
 
  47   and binophit d oper e1 e2 =
 
  49       val t = X.TEMP (Tm.new "add" Tm.Long)
 
  50       val (i1, s1) = munch_exp d e1
 
  51       val (i2, s2) = munch_exp t e2
 
  52 (*      val _ = print ("s1 = " ^ Tm.sfx s1 ^ ", s2 = " ^ Tm.sfx s2 ^ ", ") *)
 
  53       val rs = if Tm.cmpsize (s1, s2) = GREATER then s1 else s2
 
  54 (*      val _ = print ("rs = " ^ Tm.sfx rs ^ " from " ^ TU.Print.pp_exp e1 ^ " and " ^ TU.Print.pp_exp e2 ^ "\n") *)
 
  56       (i1 @ i2 @ [oper ((d,rs), (t,rs))], rs)
 
  58   and cmphit d a = let val (insns, pos, neg) = munch_cond a in (insns @ [X.SETcc (pos, (d, Tm.Byte)), X.MOVZB((d, Tm.Long), (d, Tm.Byte))], Tm.Long) end
 
  60   (* munch_exp : prex86oper -> T.exp -> prex86insn list *)
 
  62    * generates instructions to achieve d <- e
 
  63    * d must be TEMP(t) or REG(r)
 
  65   and munch_exp d (T.CONST n) = ([X.MOV((d, Tm.Long), (X.CONST n, Tm.Long))], Tm.Long)
 
  66     | munch_exp d (T.NULLPTR) = ([X.MOV((d, Tm.Quad), (X.CONST 0w0, Tm.Quad))], Tm.Quad)
 
  67     | munch_exp d (T.TEMP(t)) = ([X.MOV((d, Tm.size t), (X.TEMP t, Tm.size t))], Tm.size t)
 
  68     | munch_exp d (T.ARG(0, sz)) = ([X.MOV((d, sz), (X.REG X.EDI, sz))], sz)
 
  69     | munch_exp d (T.ARG(1, sz)) = ([X.MOV((d, sz), (X.REG X.ESI, sz))], sz)
 
  70     | munch_exp d (T.ARG(2, sz)) = ([X.MOV((d, sz), (X.REG X.EDX, sz))], sz)
 
  71     | munch_exp d (T.ARG(3, sz)) = ([X.MOV((d, sz), (X.REG X.ECX, sz))], sz)
 
  72     | munch_exp d (T.ARG(4, sz)) = ([X.MOV((d, sz), (X.REG X.R8D, sz))], sz)
 
  73     | munch_exp d (T.ARG(5, sz)) = ([X.MOV((d, sz), (X.REG X.R9D, sz))], sz)
 
  74     | munch_exp d (T.ARG(t, sz)) = ([X.MOV((d, sz), (X.STACKARG (t - 6), sz))], sz)
 
  75     | munch_exp d (T.CALL(name, l, rsz)) = (* Scary demons live here. *)
 
  78           val nstack = if (nargs <= 6)
 
  81           val stackb = nstack * 8
 
  82           fun argdest 1 = X.REG X.EDI
 
  83             | argdest 2 = X.REG X.ESI
 
  84             | argdest 3 = X.REG X.EDX
 
  85             | argdest 4 = X.REG X.ECX
 
  86             | argdest 5 = X.REG X.R8D
 
  87             | argdest 6 = X.REG X.R9D
 
  88             | argdest n = X.REL ((X.REG X.RSP, Tm.Quad), (X.CONST (Word32.fromInt (~(stackb - 8 * (n - 7)))), Tm.Quad), 0w1)
 
  90           val dests = List.tabulate (nargs, fn x => argdest (x+1))
 
  91           val (exps,_) = ListPair.unzip l
 
  92           val hf = List.map hasfixed exps
 
  93           val (d_hf, l_hf) = ListPair.unzip (ListPair.foldr
 
  94             (fn (a,b,c) => if b then a::c else c)
 
  96             (ListPair.zip (dests,l), hf)
 
  98           val (d_nohf, l_nohf) = ListPair.unzip (ListPair.foldr
 
  99             (fn (a,b,c) => if b then c else a::c)
 
 101             (ListPair.zip (dests,l), hf)
 
 103           val temps = List.map (fn (_, sz) => Temp.new ("arg") sz (* xxx? *)) l_hf
 
 104           val (argevals_hf,_) = ListPair.unzip (List.map
 
 105             (fn (t,(exp,_)) => munch_exp (X.TEMP t) exp)
 
 106             (ListPair.zip (temps, l_hf)))
 
 107           val argpushes = List.map
 
 108             (fn (dest, t) => [X.MOV ((dest, Tm.size t), (X.TEMP t, Tm.size t))])
 
 109             (ListPair.zip (d_hf, temps))
 
 110           val (argevals_nohf,_) = ListPair.unzip (List.map
 
 111             (fn (d,(exp,sz)) => munch_exp d exp)
 
 112             (ListPair.zip (d_nohf, l_nohf)))
 
 114           (List.concat argevals_hf @ 
 
 115            List.concat argpushes @
 
 116            List.concat argevals_nohf @
 
 117            [ X.SUB ((X.REG X.RSP, Tm.Quad), (X.CONST (Word32.fromInt stackb), Tm.Quad)),
 
 118              X.CALL (name, nargs),
 
 119              X.ADD ((X.REG X.RSP, Tm.Quad), (X.CONST (Word32.fromInt stackb), Tm.Quad)),
 
 120              X.MOV ((d, rsz), (X.REG X.EAX, rsz))], rsz)      (* Finally! *)
 
 122     | munch_exp d (T.BINOP(T.ADD, e1, T.CONST n)) = binophit_c d X.ADD e1 n
 
 123     | munch_exp d (T.BINOP(T.ADD, T.CONST n, e1)) = binophit_c d X.ADD e1 n
 
 124     | munch_exp d (T.BINOP(T.ADD, e1, T.TEMP t)) = binophit_t d X.ADD e1 t
 
 125     | munch_exp d (T.BINOP(T.ADD, T.TEMP t, e1)) = binophit_t d X.ADD e1 t
 
 126     | munch_exp d (T.BINOP(T.ADD, e1, e2)) = binophit d X.ADD e1 e2
 
 128     | munch_exp d (T.BINOP(T.SUB, e1, T.CONST n)) = binophit_c d X.SUB e1 n
 
 129     | munch_exp d (T.BINOP(T.SUB, e1, T.TEMP t)) = binophit_t d X.SUB e1 t
 
 130     | munch_exp d (T.BINOP(T.SUB, e1, e2)) = binophit d X.SUB e1 e2
 
 131     | munch_exp d (T.BINOP(T.MUL, T.TEMP t, T.CONST n)) = let val s = Tm.size t in ([X.IMUL3((d,s), (X.TEMP t,s), n)], Tm.size t) end
 
 132     | munch_exp d (T.BINOP(T.MUL, T.CONST n, T.TEMP t)) = let val s = Tm.size t in ([X.IMUL3((d,s), (X.TEMP t,s), n)], Tm.size t) end
 
 133     | munch_exp d (T.BINOP(T.MUL, e1, T.CONST n)) = binophit_c d X.IMUL e1 n
 
 134     | munch_exp d (T.BINOP(T.MUL, T.CONST n, e1)) = binophit_c d X.IMUL e1 n
 
 135     | munch_exp d (T.BINOP(T.MUL, e1, e2)) = binophit d X.IMUL e1 e2
 
 136     | munch_exp d (T.BINOP(T.DIV, e1, e2)) =
 
 138           val t1 = X.TEMP (Temp.new ("div") Tm.Long)
 
 139           val (i1, s1) = munch_exp t1 e1
 
 140           val (i2, s2) = munch_exp d e2
 
 142           (i1 @ i2 @ [X.MOV ((X.REG X.EAX, s1), (t1, s1)), X.CLTD, X.IDIV (d, s2), X.MOV ((d, s2), (X.REG X.EAX, s2))], Tm.Long)
 
 144     | munch_exp d (T.BINOP(T.MOD, e1, e2)) =
 
 146           val t1 = X.TEMP (Temp.new ("div") Tm.Long)
 
 147           val (i1, s1) = munch_exp t1 e1
 
 148           val (i2, s2) = munch_exp d e2
 
 150           (i1 @ i2 @ [X.MOV ((X.REG X.EAX, s1), (t1, s1)), X.CLTD, X.IDIV (d, s2), X.MOV ((d, s2), (X.REG X.EDX, s2))], Tm.Long)
 
 152     | munch_exp d (T.BINOP(T.LSH, e1, T.CONST n)) = let val (i,s) = munch_exp d e1 in (i @ [X.SAL ((d,s), (X.CONST (n mod 0w32),s))],s) end
 
 153     | munch_exp d (T.BINOP(T.LSH, e1, T.TEMP t)) =
 
 155           val (i,s) = munch_exp d e1
 
 157           (i @ [X.MOV ((X.REG X.ECX, s), (X.TEMP t, s)), X.SAL ((d,s), (X.REG X.ECX, Tm.Byte))], s)
 
 159     | munch_exp d (T.BINOP(T.LSH, e1, e2)) =
 
 161           val t = X.TEMP (Temp.new ("lsh") Tm.Long)
 
 162           val (i1, s1) = munch_exp d e1
 
 163           val (i2, s2) = munch_exp t e2
 
 165           (i1 @ i2 @ [X.MOV ((X.REG X.ECX, s1), (t, s1)), X.SAL ((d, s2), (X.REG X.ECX, Tm.Byte))], s2)
 
 167     | munch_exp d (T.BINOP(T.RSH, e1, T.CONST n)) = let val (i,s) = munch_exp d e1 in (i @ [X.SAR ((d,s), (X.CONST (n mod 0w32),s))],s) end
 
 168     | munch_exp d (T.BINOP(T.RSH, e1, T.TEMP t)) =
 
 170           val (i,s) = munch_exp d e1
 
 172           (i @ [X.MOV ((X.REG X.ECX, s), (X.TEMP t, s)), X.SAR ((d,s), (X.REG X.ECX, Tm.Byte))], s)
 
 174     | munch_exp d (T.BINOP(T.RSH, e1, e2)) =
 
 176           val t = X.TEMP (Temp.new ("lsh") Tm.Long)
 
 177           val (i1, s1) = munch_exp d e1
 
 178           val (i2, s2) = munch_exp t e2
 
 180           (i1 @ i2 @ [X.MOV ((X.REG X.ECX, s1), (t, s1)), X.SAR ((d, s2), (X.REG X.ECX, Tm.Byte))], s2)
 
 182     | munch_exp d (T.BINOP(T.BITAND, T.CONST n, e1)) = binophit_c d X.AND e1 n
 
 183     | munch_exp d (T.BINOP(T.BITAND, e1, T.CONST n)) = binophit_c d X.AND e1 n
 
 184     | munch_exp d (T.BINOP(T.BITAND, T.TEMP t, e1)) = binophit_t d X.AND e1 t
 
 185     | munch_exp d (T.BINOP(T.BITAND, e1, T.TEMP t)) = binophit_t d X.AND e1 t
 
 186     | munch_exp d (T.BINOP(T.BITAND, e1, e2)) = binophit d X.AND e1 e2
 
 188     | munch_exp d (T.BINOP(T.BITOR, T.CONST n, e1)) = binophit_c d X.OR e1 n
 
 189     | munch_exp d (T.BINOP(T.BITOR, e1, T.CONST n)) = binophit_c d X.OR e1 n
 
 190     | munch_exp d (T.BINOP(T.BITOR, T.TEMP t, e1)) = binophit_t d X.OR e1 t
 
 191     | munch_exp d (T.BINOP(T.BITOR, e1, T.TEMP t)) = binophit_t d X.OR e1 t
 
 192     | munch_exp d (T.BINOP(T.BITOR, e1, e2)) = binophit d X.OR e1 e2
 
 194     | munch_exp d (T.BINOP(T.BITXOR, T.CONST n, e1)) = binophit_c d X.XOR e1 n
 
 195     | munch_exp d (T.BINOP(T.BITXOR, e1, T.CONST n)) = binophit_c d X.XOR e1 n
 
 196     | munch_exp d (T.BINOP(T.BITXOR, T.TEMP t, e1)) = binophit_t d X.XOR e1 t
 
 197     | munch_exp d (T.BINOP(T.BITXOR, e1, T.TEMP t)) = binophit_t d X.XOR e1 t
 
 198     | munch_exp d (T.BINOP(T.BITXOR, e1, e2)) = binophit d X.XOR e1 e2
 
 200     | munch_exp d (a as T.BINOP(T.LOGAND, e1, e2)) =
 
 202           val (insn1, pos1, neg1) = munch_cond e1
 
 203           val (insn2, pos2, neg2) = munch_cond e2
 
 204           val t1 = (X.TEMP (Tm.new "logand 1" Tm.Byte), Tm.Byte)
 
 205           val t2 = (X.TEMP (Tm.new "logand 2" Tm.Byte), Tm.Byte)
 
 208           if (TU.effect e2 orelse (length insn2 > 10))
 
 210                 [X.SETcc(pos1, t1), X.Jcc (neg1, l)] @
 
 212                 [X.SETcc(pos2, t1), X.LABEL l, X.MOVZB((d, Tm.Long), t1)], Tm.Long)
 
 213           else (insn1 @ [X.SETcc (pos1, t1)] @ insn2 @ [X.SETcc (pos2, t2), X.AND(t1,t2), X.MOVZB((d, Tm.Long), t1)], Tm.Long)
 
 215     | munch_exp d (a as T.BINOP(T.LOGOR, e1, e2)) =
 
 217           val (insn1, pos1, neg1) = munch_cond e1
 
 218           val (insn2, pos2, neg2) = munch_cond e2
 
 219           val t1 = (X.TEMP (Tm.new "logand 1" Tm.Byte), Tm.Byte)
 
 220           val t2 = (X.TEMP (Tm.new "logand 2" Tm.Byte), Tm.Byte)
 
 223           if (TU.effect e2 orelse (length insn2 > 10))
 
 225                 [X.SETcc(pos1, t1), X.Jcc (pos1, l)] @
 
 227                 [X.SETcc(pos2, t1), X.LABEL l, X.MOVZB((d, Tm.Long), t1)], Tm.Long)
 
 228           else (insn1 @ [X.SETcc (pos1, t1)] @ insn2 @ [X.SETcc (pos2, t2), X.OR(t1,t2), X.MOVZB((d, Tm.Long), t1)], Tm.Long)
 
 230     | munch_exp d (a as T.BINOP(T.EQ, _, _)) = cmphit d a
 
 231     | munch_exp d (a as T.BINOP(T.NEQ, _, _)) = cmphit d a
 
 232     | munch_exp d (a as T.BINOP(T.LE, _, _)) = cmphit d a
 
 233     | munch_exp d (a as T.BINOP(T.LT, _, _)) = cmphit d a
 
 234     | munch_exp d (a as T.BINOP(T.GE, _, _)) = cmphit d a
 
 235     | munch_exp d (a as T.BINOP(T.GT, _, _)) = cmphit d a
 
 236     | munch_exp d (a as T.BINOP(T.BE, _, _)) = cmphit d a
 
 238     | munch_exp d (T.UNOP(T.NEG, e1)) = let val (i, s) = munch_exp d e1 in (i @ [X.NEG (d, Tm.Long)], s) end
 
 239     | munch_exp d (T.UNOP(T.BITNOT, e1)) = let val (i, s) = munch_exp d e1 in (i @ [X.NOT (d, Tm.Long)], s) end
 
 240     | munch_exp d (T.UNOP(T.BANG, e)) = 
 
 242           val (insns, pos, neg) = munch_cond e
 
 244           (insns @ [X.SETcc (neg, (d, Tm.Byte)), X.MOVZB((d, Tm.Long), (d, Tm.Byte))], Tm.Long)
 
 246     | munch_exp d (T.MEMORY (e1,s)) =
 
 248           val a = X.TEMP (Temp.new "addr" Tm.Quad)
 
 249           val (i, s') = munch_exp a e1
 
 250           val _ = if s' = Tm.Quad then () else raise ErrorMsg.InternalError "memory fuxed."
 
 252           (i @ [X.MOV ((d,s), (X.REL ((a, Tm.Quad), (X.CONST 0w0, Tm.Quad), 0w1), s))], s)
 
 254     | munch_exp d (T.ALLOC(exp)) =
 
 257           val t1 = Temp.new "alloc" Tm.Long
 
 259           val (einsn, _) = munch_exp (X.TEMP t1) exp
 
 260           val (insns, _) = munch_exp d (T.CALL (Symbol.symbol "calloc", [(T.TEMP t1, Tm.Long), (T.CONST 0w1, Tm.Long)], Tm.Quad))
 
 261           val rd = (d, Tm.Quad)
 
 263           (einsn @ insns, Tm.Quad)
 
 265 (*    | munch_exp d (T.COND(c, T.CONST n1, T.CONST n2)) = let val (i,p,n) = munch_cond c in ((X.MOV (d, X.CONST n1))::i) @ [X.CMOVcc (p, d, X.CONST n2)] end *)
 
 266     | munch_exp d (T.COND(c,e1,e2)) =
 
 268           val (insns, pos, neg) = munch_cond c
 
 271           val (i1, s1) = munch_exp d e1
 
 272           val (i2, s2) = munch_exp d e2
 
 273 (*          val _ = print ("cond: size " ^ Tm.sfx s1 ^ " from " ^ TU.Print.pp_exp e1 ^ ", " ^ Tm.sfx s2 ^ " from " ^ TU.Print.pp_exp e2 ^ "\n") *)
 
 275           (insns @ [X.Jcc(neg, l1)] @ i1 @ [X.JMP l2, X.LABEL l1] @ i2 @ [X.LABEL l2], if s1 = s2 then s1 else raise ErrorMsg.InternalError "condfuxed.")
 
 277     | munch_exp d (T.STMVAR (sl, e)) = let val (i, s) = munch_exp d e in (List.concat (map munch_stm sl) @ i, s) end
 
 279   and condhit_tc t c (pos, neg) = ([X.CMP((X.TEMP t, Tm.size t), (X.CONST c, Tm.size t))], pos, neg)
 
 280   and condhit_c e c (pos, neg) =
 
 282       val t = X.TEMP (Temp.new "consthit" Tm.Long)
 
 283       val (i,s) = munch_exp t e
 
 285       (i @ [X.CMP ((t,s), (X.CONST c,s))], pos, neg)
 
 287   and condhit_t e t (pos, neg) =
 
 289       val t' = X.TEMP (Temp.new "consthit" Tm.Long)
 
 290       val (i,s) = munch_exp t' e
 
 292       (i @ [X.CMP ((t',s), (X.TEMP t,s))], pos, neg)
 
 294   and condhit e1 e2 (pos, neg) =
 
 296       val t1 = X.TEMP (Temp.new ("var neq 1") Tm.Long)
 
 297       val t2 = X.TEMP (Temp.new ("var neq 2") Tm.Long)
 
 298       val (i1, s1) = munch_exp t1 e1
 
 299       val (i2, s2) = munch_exp t2 e2
 
 301       (i1 @ i2 @ [X.CMP((t1,s1),(t2,s2))], pos, neg)
 
 304   (* munch_cond : T.exp -> X.insn list * X.cond * X.cond
 
 305    * munch_cond stm generates code to set flags, and then returns a conditional
 
 306    * to test if the expression was true and for if it was false.
 
 308   and munch_cond (T.UNOP (T.BANG, e)) =
 
 310           val (insns, pos, neg) = munch_cond e
 
 314     | munch_cond (T.BINOP(T.NEQ, T.TEMP t, T.CONST n)) = condhit_tc t n (X.NE, X.E)
 
 315     | munch_cond (T.BINOP(T.NEQ, T.CONST n, T.TEMP t)) = condhit_tc t n (X.NE, X.E)
 
 316     | munch_cond (T.BINOP(T.NEQ, T.CONST n, e1)) = condhit_c e1 n (X.NE, X.E)
 
 317     | munch_cond (T.BINOP(T.NEQ, e1, T.CONST n)) = condhit_c e1 n (X.NE, X.E)
 
 318     | munch_cond (T.BINOP(T.NEQ, T.TEMP t, e1)) = condhit_t e1 t (X.NE, X.E)
 
 319     | munch_cond (T.BINOP(T.NEQ, e1, T.TEMP t)) = condhit_t e1 t (X.NE, X.E)
 
 320     | munch_cond (T.BINOP(T.NEQ, e1, e2)) = condhit e1 e2 (X.NE, X.E)
 
 322     | munch_cond (T.BINOP(T.EQ, T.TEMP t, T.CONST n)) = condhit_tc t n (X.E, X.NE)
 
 323     | munch_cond (T.BINOP(T.EQ, T.CONST n, T.TEMP t)) = condhit_tc t n (X.E, X.NE)
 
 324     | munch_cond (T.BINOP(T.EQ, T.CONST n, e1)) = condhit_c e1 n (X.E, X.NE)
 
 325     | munch_cond (T.BINOP(T.EQ, e1, T.CONST n)) = condhit_c e1 n (X.E, X.NE)
 
 326     | munch_cond (T.BINOP(T.EQ, T.TEMP t, e1)) = condhit_t e1 t (X.E, X.NE)
 
 327     | munch_cond (T.BINOP(T.EQ, e1, T.TEMP t)) = condhit_t e1 t (X.E, X.NE)
 
 328     | munch_cond (T.BINOP(T.EQ, e1, e2)) = condhit e1 e2 (X.E, X.NE)
 
 330     | munch_cond (T.BINOP(T.LE, T.TEMP t, T.CONST n)) = condhit_tc t n (X.LE, X.G)
 
 331     | munch_cond (T.BINOP(T.LE, T.CONST n, T.TEMP t)) = condhit_tc t n (X.GE, X.L)
 
 332     | munch_cond (T.BINOP(T.LE, T.CONST n, e1)) = condhit_c e1 n (X.GE, X.L)
 
 333     | munch_cond (T.BINOP(T.LE, e1, T.CONST n)) = condhit_c e1 n (X.LE, X.G)
 
 334     | munch_cond (T.BINOP(T.LE, T.TEMP t, e1)) = condhit_t e1 t (X.GE, X.L)
 
 335     | munch_cond (T.BINOP(T.LE, e1, T.TEMP t)) = condhit_t e1 t (X.LE, X.G)
 
 336     | munch_cond (T.BINOP(T.LE, e1, e2)) = condhit e1 e2 (X.LE, X.G)
 
 338     | munch_cond (T.BINOP(T.LT, T.TEMP t, T.CONST n)) = condhit_tc t n (X.L, X.GE)
 
 339     | munch_cond (T.BINOP(T.LT, T.CONST n, T.TEMP t)) = condhit_tc t n (X.G, X.LE)
 
 340     | munch_cond (T.BINOP(T.LT, T.CONST n, e1)) = condhit_c e1 n (X.G, X.LE)
 
 341     | munch_cond (T.BINOP(T.LT, e1, T.CONST n)) = condhit_c e1 n (X.L, X.GE)
 
 342     | munch_cond (T.BINOP(T.LT, T.TEMP t, e1)) = condhit_t e1 t (X.G, X.LE)
 
 343     | munch_cond (T.BINOP(T.LT, e1, T.TEMP t)) = condhit_t e1 t (X.L, X.GE)
 
 344     | munch_cond (T.BINOP(T.LT, e1, e2)) = condhit e1 e2 (X.L, X.GE)
 
 346     | munch_cond (T.BINOP(T.GT, T.TEMP t, T.CONST n)) = condhit_tc t n (X.G, X.LE)
 
 347     | munch_cond (T.BINOP(T.GT, T.CONST n, T.TEMP t)) = condhit_tc t n (X.L, X.GE)
 
 348     | munch_cond (T.BINOP(T.GT, T.CONST n, e1)) = condhit_c e1 n (X.L, X.GE)
 
 349     | munch_cond (T.BINOP(T.GT, e1, T.CONST n)) = condhit_c e1 n (X.G, X.LE)
 
 350     | munch_cond (T.BINOP(T.GT, T.TEMP t, e1)) = condhit_t e1 t (X.L, X.GE)
 
 351     | munch_cond (T.BINOP(T.GT, e1, T.TEMP t)) = condhit_t e1 t (X.G, X.LE)
 
 352     | munch_cond (T.BINOP(T.GT, e1, e2)) = condhit e1 e2 (X.G, X.LE)
 
 354     | munch_cond (T.BINOP(T.GE, T.TEMP t, T.CONST n)) = condhit_tc t n (X.GE, X.L)
 
 355     | munch_cond (T.BINOP(T.GE, T.CONST n, T.TEMP t)) = condhit_tc t n (X.LE, X.G)
 
 356     | munch_cond (T.BINOP(T.GE, T.CONST n, e1)) = condhit_c e1 n (X.LE, X.G)
 
 357     | munch_cond (T.BINOP(T.GE, e1, T.CONST n)) = condhit_c e1 n (X.GE, X.L)
 
 358     | munch_cond (T.BINOP(T.GE, T.TEMP t, e1)) = condhit_t e1 t (X.LE, X.G)
 
 359     | munch_cond (T.BINOP(T.GE, e1, T.TEMP t)) = condhit_t e1 t (X.GE, X.L)
 
 360     | munch_cond (T.BINOP(T.GE, e1, e2)) = condhit e1 e2 (X.GE, X.L)
 
 362     | munch_cond (T.BINOP(T.BE, T.TEMP t, T.CONST n)) = condhit_tc t n (X.BE, X.A)
 
 363     | munch_cond (T.BINOP(T.BE, T.CONST n, T.TEMP t)) = condhit_tc t n (X.AE, X.B)
 
 364     | munch_cond (T.BINOP(T.BE, T.CONST n, e1)) = condhit_c e1 n (X.AE, X.B)
 
 365     | munch_cond (T.BINOP(T.BE, e1, T.CONST n)) = condhit_c e1 n (X.BE, X.A)
 
 366     | munch_cond (T.BINOP(T.BE, T.TEMP t, e1)) = condhit_t e1 t (X.AE, X.B)
 
 367     | munch_cond (T.BINOP(T.BE, e1, T.TEMP t)) = condhit_t e1 t (X.BE, X.A)
 
 368     | munch_cond (T.BINOP(T.BE, e1, e2)) = condhit e1 e2 (X.BE, X.A)
 
 370     | munch_cond (T.BINOP(T.LOGOR, e1, e2)) =
 
 372           val (insn1, pos1, neg1) = munch_cond e1
 
 373           val (insn2, pos2, neg2) = munch_cond e2
 
 374           val t1 = (X.TEMP (Temp.new("logor c 1") Tm.Byte), Tm.Byte)
 
 375           val t2 = (X.TEMP (Temp.new("logor c 2") Tm.Byte), Tm.Byte)
 
 378           if (TU.effect e2 orelse (length insn2 > 10))
 
 380                 [X.SETcc (pos1, t1), X.Jcc (pos1, l)] @
 
 382                 [X.SETcc (pos2, t1), X.LABEL l, X.TEST(t1, t1)],
 
 384           else (insn1 @ [X.SETcc (pos1, t1)] @ insn2 @ [X.SETcc (pos2, t2), X.OR(t1, t2)], X.NE, X.E)
 
 386     | munch_cond (T.BINOP(T.LOGAND, e1, e2)) =
 
 388           val (insn1, pos1, neg1) = munch_cond e1
 
 389           val (insn2, pos2, neg2) = munch_cond e2
 
 390           val t1 = (X.TEMP (Temp.new("logand c 1") Tm.Byte), Tm.Byte)
 
 391           val t2 = (X.TEMP (Temp.new("logand c 2") Tm.Byte), Tm.Byte)
 
 394           if (TU.effect e2 orelse (length insn2 > 10))
 
 396                 [X.SETcc (pos1, t1), X.Jcc (neg1, l)] @
 
 398                 [X.SETcc (pos2, t1), X.LABEL l, X.TEST(t1, t1)],
 
 400           else (insn1 @ [X.SETcc (pos1, t1)] @ insn2 @ [X.SETcc (pos2, t2), X.AND(t1, t2)], X.NE, X.E)
 
 404         val t = X.TEMP (Temp.new ("munch c") Tm.Long)
 
 405         val (i, s) = munch_exp t e
 
 407         (i @ [ X.TEST ((t,s),(t,s)) ], X.NE, X.E)
 
 410   (* munch_lval : T.exp -> (X.insn list * X.operand)
 
 411    * Takes an expression that has been typechecked as being a valid lvalue, and then returns an instruction list and an operand to store your shit in.
 
 413   and munch_lval (T.TEMP t) = ([], (X.TEMP t, Tm.size t))
 
 414     | munch_lval (T.MEMORY (m,s)) = 
 
 416         val t = X.TEMP (Tm.new "lv addr" Tm.Quad)
 
 417         val (i,s') = munch_exp t m
 
 419         (i, (X.REL ((t, Tm.Quad), (X.CONST 0w0, Tm.Quad), 0w1), s))
 
 421     | munch_lval _ = raise ErrorMsg.InternalError "That wasn't really a valid lvalue..."
 
 423   (* munch_stm : T.stm -> X.insn list *)
 
 424   (* munch_stm stm generates code to execute stm *)
 
 425   and munch_stm (T.MOVE (T.TEMP t1, T.TEMP t2)) = if Tm.size t1 = Tm.size t2 then [X.MOV((X.TEMP t1, Tm.size t1), (X.TEMP t2, Tm.size t2))]
 
 426                                                                              else raise ErrorMsg.InternalError "temp to temp move fuxed."
 
 427     | munch_stm (T.MOVE (T.TEMP t, T.CONST n)) = if Tm.size t = Tm.Long then [X.MOV((X.TEMP t, Tm.size t), (X.CONST n, Tm.size t))]
 
 428                                                                         else raise ErrorMsg.InternalError "const to temp move fuxed."
 
 429     | munch_stm (T.MOVE (T.TEMP t, a as T.ARG (an, sz))) =
 
 431           val (i, s) = munch_exp (X.TEMP t) a
 
 435           else raise ErrorMsg.InternalError "arg to tmp fuxed."
 
 437     | munch_stm (T.MOVE (T.TEMP t, a as T.CALL _)) = let val (i, _) = munch_exp (X.TEMP t) a in i end
 
 438     | munch_stm (T.MOVE (a, e2)) =
 
 440           val t = X.TEMP (Temp.new ("assign") Tm.Long)
 
 441           val (m, (r,s1)) = munch_lval a
 
 442           val (i, s2) = munch_exp t e2
 
 443 (*          val _ = print ("move: size " ^ Tm.sfx s2 ^ " from " ^ TU.Print.pp_exp e2 ^ ", " ^ Tm.sfx s1 ^ " from " ^ TU.Print.pp_exp a ^ "\n") *)
 
 444           val _ = if s1 = s2 then () else raise ErrorMsg.InternalError "move generic fuxed."
 
 446           m @ i @ [X.MOV((r,s1), (t,s2))]
 
 448     | munch_stm (T.RETURN(e, sz)) =
 
 450           val t = X.TEMP (Temp.new ("retval") sz)
 
 451           val (i, s) = munch_exp t e
 
 453           i @ [X.MOV((X.REG X.EAX, sz), (t, if sz = s then sz else raise ErrorMsg.InternalError "retfuxed.")), X.RET]
 
 455     | munch_stm (T.LABEL l) = [X.LABEL l]
 
 456     | munch_stm (T.JUMP l) = [X.JMP l]
 
 457     | munch_stm (T.JUMPIFN(e, l)) =
 
 459          val (insns, pos, neg) = munch_cond e 
 
 461          insns @ [X.Jcc (neg, l)]
 
 463     | munch_stm (T.EFFECT exp) = let val t = X.TEMP (Temp.new "throwaway" Tm.Quad) val (i, _) = munch_exp t exp in i end
 
 465   fun codegen nil = nil
 
 466     | codegen (stm::stms) = munch_stm stm @ codegen stms