2 * X86 instruction/operand internal representation and manipulation
3 * Author: Joshua Wise <jwise@andrew.cmu.edu>
4 * Author: Chris Lu <czl@andrew.cmu.edu>
11 EAX | EBX | ECX | EDX | ESI | EDI | EBP | RSP | R8D | R9D | R10D | R11D | R12D | R13D | R14D | R15D
12 (* operands to instructions *)
13 datatype basicop = REG of reg |
15 CONST of Word32.word |
16 REL of ((basicop * Temp.size) * (basicop * Temp.size) * Word32.word) |
18 type oper = basicop * Temp.size
19 datatype cc = E | NE | GE | LE | L | G | B | BE | A | AE
24 LABEL of Label.label |
26 MOVSC of oper * oper |
30 IMUL3 of oper * oper * Word32.word |
43 CMOVcc of cc * oper * oper |
45 Jcc of cc * Label.label |
46 CALL of Symbol.symbol * int |
47 MOVZB of oper * oper |
52 structure OperSet : ORD_SET
53 where type Key.ord_key = basicop;
54 structure LiveMap : ORD_MAP
55 where type Key.ord_key = int;
57 val resize : Temp.size -> oper -> oper
58 val regcmp : reg * reg -> order
59 val getop : oper -> basicop
60 val osize : oper -> Temp.size
61 val cmpoper : oper * oper -> order
62 val cmpbasic : basicop * basicop -> order
63 val opereq : oper * oper -> bool
64 val basiceq : basicop * basicop -> bool
65 val regname : Temp.size -> reg -> string
66 val regtonum : reg -> int
67 val numtoreg : int -> reg
68 val ccname : cc -> string
69 val opsused : insn list -> OperSet.set
70 val pp_oper : oper -> string
71 val print : insn -> string
74 structure x86 :> X86 =
78 EAX | EBX | ECX | EDX | ESI | EDI | EBP | RSP | R8D | R9D | R10D | R11D | R12D | R13D | R14D | R15D
79 (* operands to instructions *)
80 datatype basicop = REG of reg |
82 CONST of Word32.word |
83 REL of ((basicop * Temp.size) * (basicop * Temp.size) * Word32.word) |
85 datatype cc = E | NE | GE | LE | L | G | B | BE | A | AE
86 type oper = basicop * Temp.size
90 LABEL of Label.label |
92 MOVSC of oper * oper |
96 IMUL3 of oper * oper * Word32.word |
107 TEST of oper * oper |
109 CMOVcc of cc * oper * oper |
111 Jcc of cc * Label.label |
112 CALL of Symbol.symbol * int |
113 MOVZB of oper * oper |
118 type func = Ast.ident * insn list
120 (* gives name of reg *)
122 [ (EAX, ("al", "ax", "eax", "rax")),
123 (EBX, ("bl", "bx", "ebx", "rbx")),
124 (ECX, ("cl", "cx", "ecx", "rcx")),
125 (EDX, ("dl", "dx", "edx", "rdx")),
126 (ESI, ("sil", "si", "esi", "rsi")),
127 (EDI, ("dil", "di", "edi", "rdi")),
128 (EBP, ("bpl", "bp", "ebp", "rbp")),
129 (RSP, ("spl", "sp", "esp", "rsp")),
130 (R8D, ("r8b", "r8w", "r8d", "r8")),
131 (R9D, ("r9b", "r9w", "r9d", "r9")),
132 (R10D, ("r10b", "r10w", "r10d", "r10")),
133 (R11D, ("r11b", "r11w", "r11d", "r11")),
134 (R12D, ("r12b", "r12w", "r12d", "r12")),
135 (R13D, ("r13b", "r13w", "r13d", "r13")),
136 (R14D, ("r14b", "r14w", "r14d", "r14")),
137 (R15D, ("r15b", "r15w", "r15d", "r15")) ];
141 val (n, (b, w, l, q)) = valOf (List.find (fn (r, _) => r = reg) regnames)
161 (* gives number (color) associated with reg *)
179 (* gives reg associated with number (color) *)
195 | numtoreg n = raise ErrorMsg.InternalError ("numtoreg: Invalid register "^(Int.toString n))
197 (* register compare *)
198 fun regcmp (r1, r2) = Int.compare (regtonum r1, regtonum r2)
200 fun resize ss (a,_) = (a,ss)
203 (* operand compare; arbitrary order imposed to make
204 * various things easier (e.g. liveness, for sorting)
206 fun cmpbasic (REG reg1, REG reg2) = regcmp (reg1, reg2)
207 | cmpbasic (TEMP temp1, TEMP temp2) = Temp.compare (temp1,temp2)
208 | cmpbasic (CONST(const1), CONST(const2)) = Word32.compare (const1, const2)
209 | cmpbasic (REL (r1, i1, m1), REL (r2, i2, m2)) =
211 val orderm = Word32.compare (m1,m2)
212 val order1 = cmpbasic (getop r1, getop r2)
213 val order2 = cmpbasic (getop i1, getop i2)
214 val o1 = if(order1 = EQUAL) then order2 else order1
216 if (o1 = EQUAL) then orderm
219 | cmpbasic (CONST _, _) = LESS
220 | cmpbasic (REG _, _) = LESS
221 | cmpbasic (REL _, _) = LESS
222 | cmpbasic (_, _) = GREATER
224 fun cmpoper ((o1,s1),(o2,s2)) = (case (cmpbasic (o1,o2)) of EQUAL => Temp.cmpsize (s1,s2) | a => a)
226 fun basiceq (REG a, REG b) = a = b
227 | basiceq (TEMP a, TEMP b) = Temp.eq (a, b)
228 | basiceq (CONST a, CONST b) = a = b
229 | basiceq (REL (a1, b1, m1), REL (a2, b2, m2)) = m1 = m2 andalso basiceq (getop a1, getop a2) andalso basiceq (getop b1, getop b2)
230 | basiceq (_, _) = false
232 fun opereq ((o1,s1),(o2,s2)) = basiceq (o1,o2) andalso s1 = s2
234 structure OperSet = ListSetFn (
236 type ord_key = basicop
237 val compare = cmpbasic
240 structure LiveMap = SplayMapFn(struct
242 val compare = Int.compare
245 fun opsused nil = OperSet.empty
246 | opsused ((DIRECTIVE _)::l) = opsused l
247 | opsused ((COMMENT _)::l) = opsused l
248 | opsused ((LABEL _)::l) = opsused l
249 | opsused ((MOV ((dst,_), (src,_)))::l) = OperSet.addList (opsused l, [dst, src])
250 | opsused ((MOVSC((dst,_), (src,_)))::l) = OperSet.addList (opsused l, [dst, src])
251 | opsused ((LEA ((dst,_), (src,_)))::l) = OperSet.addList (opsused l, [dst, src])
252 | opsused ((SUB ((dst,_), (src,_)))::l) = OperSet.addList (opsused l, [dst, src])
253 | opsused ((IMUL ((dst,_), (src,_)))::l) = OperSet.addList (opsused l, [dst, src])
254 | opsused ((IMUL3 ((dst,_), (src,_), _))::l) = OperSet.addList (opsused l, [dst, src])
255 | opsused ((ADD ((dst,_), (src,_)))::l) = OperSet.addList (opsused l, [dst, src])
256 | opsused ((IDIV (src,_))::l) = OperSet.addList (opsused l, [src, REG EDX, REG EAX])
257 | opsused ((NEG (dst,_))::l) = OperSet.addList (opsused l, [dst])
258 | opsused ((NOT (dst,_))::l) = OperSet.addList (opsused l, [dst])
259 | opsused ((SAL ((dst,_), (shft,_)))::l) = OperSet.addList (opsused l, [dst, shft])
260 | opsused ((SAR ((dst,_), (shft,_)))::l) = OperSet.addList (opsused l, [dst, shft])
261 | opsused ((AND ((dst,_), (src,_)))::l) = OperSet.addList (opsused l, [dst, src])
262 | opsused ((OR ((dst,_), (src,_)))::l) = OperSet.addList (opsused l, [dst, src])
263 | opsused ((XOR ((dst,_), (src,_)))::l) = OperSet.addList (opsused l, [dst, src])
264 | opsused ((CMP ((dst,_), (src,_)))::l) = OperSet.addList (opsused l, [dst, src])
265 | opsused ((TEST ((dst,_), (src,_)))::l) = OperSet.addList (opsused l, [dst, src])
266 | opsused ((SETcc (c, (dst,_)))::l) = OperSet.addList (opsused l, [dst])
267 | opsused ((CMOVcc (c, (dst,_), (src,_)))::l) = OperSet.addList (opsused l, [dst, src])
268 | opsused ((JMP _)::l) = opsused l
269 | opsused ((Jcc _)::l) = opsused l
270 | opsused ((CALL _)::l) = opsused l
271 | opsused ((MOVZB ((dst,_), (src,_)))::l) = OperSet.addList (opsused l, [dst, src])
272 | opsused ((CLTD)::l) = opsused l
273 | opsused ((RET)::l) = opsused l
274 | opsused ((LIVEIGN i)::l) = opsused (i::l)
277 fun pp_oper (REG r, s) = "%" ^ (regname s r)
278 | pp_oper (TEMP t, _) = (Temp.name t) ^ (Temp.sfx (Temp.size t))
279 | pp_oper (CONST c, _) = "$" ^ Word32Signed.toString c
280 | pp_oper (REL ((CONST n, _), _, _), _) = Word32Signed.toString n
281 | pp_oper (REL (r, (CONST n, _), _), _) = (Word32Signed.toString n) ^ "(" ^ (pp_oper r) ^ ")"
282 | pp_oper (REL (r1, r2, m), _) = "(" ^ (pp_oper r1) ^ "," ^ (pp_oper r2) ^ "," ^
283 (Word32.toString m) ^ ")"
284 | pp_oper (STACKARG i, _) = "arg#"^Int.toString i
286 (* pretty prints the asm *)
287 fun print (DIRECTIVE(str)) = str ^ "\n"
288 | print (COMMENT(str)) = "// " ^ str ^ "\n"
289 | print (LABEL(l)) = Label.name l ^ ":\n"
290 | print (LEA(dst, src)) = "\tlea" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper src) ^ ", " ^ (pp_oper dst) ^ "\n"
291 | print (MOV(dst, src)) = "\tmov" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper src) ^ ", " ^ (pp_oper dst) ^ "\n"
292 | print (MOVSC((d,Temp.Long), (s,Temp.Quad))) = "\tmov" ^ (Temp.sfx Temp.Long) ^ "\t" ^ (pp_oper (s,Temp.Long)) ^ ", " ^ (pp_oper (d,Temp.Long)) ^ " // sex change\n"
293 | print (MOVSC((d,Temp.Quad), (s,Temp.Long))) = "\tmov" ^ (Temp.sfx Temp.Long) ^ "\t" ^ (pp_oper (s,Temp.Long)) ^ ", " ^ (pp_oper (d,Temp.Long)) ^ " // sex change\n"
294 | print (MOVSC(_,_)) = raise ErrorMsg.InternalError "invalid size change"
295 | print (SUB(dst, src)) = "\tsub" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper src) ^ ", " ^ (pp_oper dst) ^ "\n"
296 | print (IMUL(dst, src)) = "\timul" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper src) ^ ", " ^ (pp_oper dst) ^ "\n"
297 | print (IMUL3(dst, tmp, const)) = "\timul" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper (CONST const, Temp.Long)) ^ ", " ^ (pp_oper tmp) ^ ", " ^ (pp_oper dst) ^ "\n"
298 | print (ADD(dst, src)) = "\tadd" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper src) ^ ", " ^ (pp_oper dst) ^ "\n"
299 | print (IDIV(src)) = "\tidiv" ^ (Temp.sfx (osize src)) ^ "\t" ^ (pp_oper src) ^ "\n"
300 | print (NEG (dst)) = "\tneg" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper dst) ^ "\n"
301 | print (NOT (dst)) = "\tnot" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper dst) ^ "\n"
302 | print (SAL (dst, shft)) = "\tsal" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper shft) ^ ", " ^ (pp_oper dst) ^ "\n"
303 | print (SAR (dst, shft)) = "\tsar" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper shft) ^ ", " ^ (pp_oper dst) ^ "\n"
304 | print (AND (dst, src)) = "\tand" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper src) ^ ", " ^ (pp_oper dst) ^ "\n"
305 | print (OR (dst, src)) = "\tor" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper src) ^ ", " ^ (pp_oper dst) ^ "\n"
306 | print (XOR (dst, src)) = "\txor" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper src) ^ ", " ^ (pp_oper dst) ^ "\n"
307 | print (CMP (dst, src)) = "\tcmp" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper src) ^ ", " ^ (pp_oper dst) ^ "\n"
308 | print (TEST (dst, src)) = "\ttest" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper src) ^ ", " ^ (pp_oper dst) ^ "\n"
309 | print (SETcc (c, dst)) = "\tset" ^ (ccname c) ^ "\t" ^ (pp_oper dst) ^ "\n"
310 | print (CMOVcc (c, dst, src)) = "\tcmov" ^ (ccname c) ^ "\t" ^ (pp_oper src) ^ ", " ^ (pp_oper dst) ^ "\n"
311 | print (JMP (label)) = "\tjmp\t" ^ (Label.name label) ^ "\n"
312 | print (Jcc (c,label)) = "\tj" ^ (ccname c) ^ "\t" ^ (Label.name label) ^ "\n"
313 | print (CALL (l,n)) = "\tcall\t" ^ Symbol.name l ^ "\t # (" ^ Int.toString n ^ "args)\n"
314 | print (MOVZB (dst, src)) = "\tmovzb" ^ (Temp.sfx (osize dst)) ^ "\t" ^ (pp_oper src) ^ ", " ^ (pp_oper dst) ^ "\n"
315 | print (CLTD) = "\tcltd\n"
316 | print (RET) = "\tret\n"
317 | print (LIVEIGN i) = print i