]> Joshua Wise's Git repositories - snipe.git/blame - codegen/x86.sml
Initial import of l4c
[snipe.git] / codegen / x86.sml
CommitLineData
6ade8b0a 1(* L3 compiler
0a24e44d
JW
2 * X86 instruction/operand internal representation and manipulation
3 * Author: Joshua Wise <jwise@andrew.cmu.edu>
4 * Author: Chris Lu <czl@andrew.cmu.edu>
5 *)
6
12aa4087
JW
7signature X86 =
8sig
0a24e44d 9 (* register type *)
12aa4087
JW
10 datatype reg =
11 EAX | EBX | ECX | EDX | ESI | EDI | EBP | RSP | R8D | R9D | R10D | R11D | R12D | R13D | R14D | R15D
0a24e44d 12 (* operands to instructions *)
6ade8b0a 13 datatype size = Byte | Word | Long | Qword
1144856b
JW
14 datatype oper = REG of reg | TEMP of Temp.temp | CONST of Word32.word | REL of (oper * oper) | STACKARG of int | OSIZE of (size * oper)
15 datatype cc = E | NE | GE | LE | L | G
6ade8b0a 16 (* instructions *)
12aa4087
JW
17 datatype insn =
18 DIRECTIVE of string |
19 COMMENT of string |
0a24e44d 20 LABEL of Label.label |
6ade8b0a 21 MOV of oper * oper |
1144856b 22 LEA of oper * oper |
6ade8b0a 23 SUB of oper * oper |
12aa4087
JW
24 IMUL of oper * oper |
25 IMUL3 of oper * oper * Word32.word |
6ade8b0a
JW
26 ADD of oper * oper |
27 IDIV of oper |
12aa4087 28 NEG of oper |
6ade8b0a
JW
29 NOT of oper |
30 SAL of oper * oper |
31 SAR of oper * oper |
32 AND of oper * oper |
33 OR of oper * oper |
34 XOR of oper * oper |
35 CMP of oper * oper |
0a24e44d 36 TEST of oper * oper |
6ade8b0a 37 SETcc of cc * oper |
0a24e44d 38 JMP of Label.label |
6ade8b0a
JW
39 Jcc of cc * Label.label |
40 CALL of Symbol.symbol * int |
41 MOVZB of oper * oper |
12aa4087 42 CLTD |
6ade8b0a 43 LIVEIGN of insn |
12aa4087
JW
44 RET
45
6ade8b0a
JW
46 structure OperSet : ORD_SET
47 where type Key.ord_key = oper;
48 structure LiveMap : ORD_MAP
49 where type Key.ord_key = int;
50
1144856b
JW
51 val sts : int -> size
52 val sizeoper : oper -> size * oper
53 val stripsize : oper -> oper
54 val osize : oper -> size
12aa4087
JW
55 val cmpoper : oper * oper -> order
56 val opereq : oper * oper -> bool
6ade8b0a 57 val regname : size -> reg -> string
12aa4087
JW
58 val regtonum : reg -> int
59 val numtoreg : int -> reg
6ade8b0a
JW
60 val ccname : cc -> string
61 val opsused : insn list -> OperSet.set
62 val prettyprint_oper : size -> oper -> string
1144856b 63 val prettyprint : insn -> string
12aa4087
JW
64end
65
66structure x86 :> X86 =
67struct
6ade8b0a
JW
68
69
12aa4087
JW
70 datatype reg =
71 EAX | EBX | ECX | EDX | ESI | EDI | EBP | RSP | R8D | R9D | R10D | R11D | R12D | R13D | R14D | R15D
6ade8b0a 72 datatype size = Byte | Word | Long | Qword
1144856b
JW
73 datatype oper = REG of reg | TEMP of Temp.temp | CONST of Word32.word | REL of (oper * oper) | STACKARG of int | OSIZE of (size * oper)
74 datatype cc = E | NE | GE | LE | L | G
12aa4087
JW
75 datatype insn =
76 DIRECTIVE of string |
77 COMMENT of string |
0a24e44d 78 LABEL of Label.label |
6ade8b0a 79 MOV of oper * oper |
1144856b 80 LEA of oper * oper |
6ade8b0a 81 SUB of oper * oper |
12aa4087
JW
82 IMUL of oper * oper |
83 IMUL3 of oper * oper * Word32.word |
6ade8b0a
JW
84 ADD of oper * oper |
85 IDIV of oper |
12aa4087 86 NEG of oper |
6ade8b0a
JW
87 NOT of oper |
88 SAL of oper * oper |
89 SAR of oper * oper |
90 AND of oper * oper |
91 OR of oper * oper |
92 XOR of oper * oper |
93 CMP of oper * oper |
0a24e44d 94 TEST of oper * oper |
6ade8b0a 95 SETcc of cc * oper |
0a24e44d 96 JMP of Label.label |
6ade8b0a
JW
97 Jcc of cc * Label.label |
98 CALL of Symbol.symbol * int |
99 MOVZB of oper * oper |
12aa4087 100 CLTD |
6ade8b0a 101 LIVEIGN of insn |
12aa4087 102 RET
6ade8b0a
JW
103
104 type func = Ast.ident * insn list
0a24e44d
JW
105
106 (* gives name of reg *)
6ade8b0a
JW
107 val regnames =
108 [ (EAX, ("al", "ax", "eax", "rax")),
109 (EBX, ("bl", "bx", "ebx", "rbx")),
110 (ECX, ("cl", "cx", "ecx", "rcx")),
111 (EDX, ("dl", "dx", "edx", "rdx")),
112 (ESI, ("sil", "si", "esi", "rsi")),
113 (EDI, ("dil", "di", "edi", "rdi")),
114 (EBP, ("bpl", "bp", "ebp", "rbp")),
115 (RSP, ("spl", "sp", "esp", "rsp")),
116 (R8D, ("r8b", "r8w", "r8d", "r8")),
117 (R9D, ("r9b", "r9w", "r9d", "r9")),
118 (R10D, ("r10b", "r10w", "r10d", "r10")),
119 (R11D, ("r11b", "r11w", "r11d", "r11")),
120 (R12D, ("r12b", "r12w", "r12d", "r12")),
121 (R13D, ("r13b", "r13w", "r13d", "r13")),
122 (R14D, ("r14b", "r14w", "r14d", "r14")),
123 (R15D, ("r15b", "r15w", "r15d", "r15")) ];
0a24e44d 124
6ade8b0a
JW
125 fun regname sz reg =
126 let
127 val (n, (b, w, l, q)) = valOf (List.find (fn (r, _) => r = reg) regnames)
128 in
129 case sz
130 of Byte => b
131 | Word => w
132 | Long => l
133 | Qword => q
134 end
135
136 fun ccname E = "e"
137 | ccname NE = "ne"
138 | ccname GE = "ge"
139 | ccname LE = "le"
140 | ccname G = "g"
141 | ccname L = "l"
0a24e44d
JW
142
143 (* gives number (color) associated with reg *)
12aa4087 144 fun regtonum EAX = 0
6ade8b0a
JW
145 | regtonum ESI = 1
146 | regtonum EDI = 2
147 | regtonum ECX = 3
148 | regtonum R8D = 4
149 | regtonum R9D = 5
150 | regtonum EDX = 6
151 | regtonum R10D = 7
152 | regtonum R11D = 8
153 | regtonum EBX = 9
12aa4087
JW
154 | regtonum R12D = 10
155 | regtonum R13D = 11
156 | regtonum R14D = 12
157 | regtonum R15D = 13
158 | regtonum EBP = 14 (* Dummy numbers -- not permitted for allocation, but there so that we can compare *)
159 | regtonum RSP = 15
0a24e44d
JW
160
161 (* gives reg associated with number (color) *)
12aa4087 162 fun numtoreg 0 = EAX
6ade8b0a
JW
163 | numtoreg 1 = ESI
164 | numtoreg 2 = EDI
165 | numtoreg 3 = ECX
166 | numtoreg 4 = R8D
167 | numtoreg 5 = R9D
168 | numtoreg 6 = EDX
169 | numtoreg 7 = R10D
170 | numtoreg 8 = R11D
171 | numtoreg 9 = EBX
12aa4087
JW
172 | numtoreg 10 = R12D
173 | numtoreg 11 = R13D
174 | numtoreg 12 = R14D
175 | numtoreg 13 = R15D
176 | numtoreg n = raise ErrorMsg.InternalError ("numtoreg: Unknown register "^(Int.toString n))
0a24e44d
JW
177
178 (* register compare *)
12aa4087
JW
179 fun regcmp (r1, r2) = Int.compare (regtonum r1, regtonum r2)
180
0a24e44d
JW
181 (* operand compare; arbitrary order imposed to make
182 * various things easier (e.g. liveness, for sorting)
183 *)
12aa4087
JW
184 fun cmpoper (REG(reg1), REG(reg2)) = regcmp (reg1, reg2)
185 | cmpoper (TEMP(temp1), TEMP(temp2)) = Temp.compare (temp1,temp2)
186 | cmpoper (CONST(const1), CONST(const2)) = Word32.compare (const1, const2)
187 | cmpoper (REL (r1, i1), REL (r2, i2)) =
188 let
1144856b
JW
189 val order1 = cmpoper (r1, r2)
190 val order2 = cmpoper (i1, i2)
12aa4087 191 in
1144856b
JW
192 if (order1 = EQUAL) then order2
193 else order1
12aa4087
JW
194 end
195 | cmpoper (CONST _, _) = LESS
196 | cmpoper (REG _, _) = LESS
197 | cmpoper (REL _, _) = LESS
198 | cmpoper (_, _) = GREATER
0a24e44d 199
6ade8b0a
JW
200 fun opereq (REG a, REG b) = a = b
201 | opereq (TEMP a, TEMP b) = Temp.eq (a, b)
202 | opereq (CONST a, CONST b) = a = b
1144856b
JW
203 | opereq (REL (a1, b1), REL (a2, b2)) = opereq (a1,a2) andalso opereq (b1,b2)
204(* | opereq (OSIZE (s1, o1), OSIZE (s2, o2)) = (s1 = s2) andalso opereq (o1, o2)*) (* This breaks the peepholer, shit *)
6ade8b0a
JW
205 | opereq (_, _) = false
206
207 structure OperSet = ListSetFn (
208 struct
209 type ord_key = oper
210 val compare = cmpoper
211 end)
212
213 structure LiveMap = SplayMapFn(struct
214 type ord_key = int
215 val compare = Int.compare
216 end)
217
218 fun opsused nil = OperSet.empty
219 | opsused ((DIRECTIVE _)::l) = opsused l
220 | opsused ((COMMENT _)::l) = opsused l
221 | opsused ((LABEL _)::l) = opsused l
222 | opsused ((MOV (dst, src))::l) = OperSet.addList (opsused l, [dst, src])
1144856b 223 | opsused ((LEA (dst, src))::l) = OperSet.addList (opsused l, [dst, src])
6ade8b0a
JW
224 | opsused ((SUB (dst, src))::l) = OperSet.addList (opsused l, [dst, src])
225 | opsused ((IMUL (dst, src))::l) = OperSet.addList (opsused l, [dst, src])
226 | opsused ((IMUL3 (dst, src, _))::l) = OperSet.addList (opsused l, [dst, src])
227 | opsused ((ADD (dst, src))::l) = OperSet.addList (opsused l, [dst, src])
228 | opsused ((IDIV (src))::l) = OperSet.addList (opsused l, [src, REG EDX, REG EAX])
229 | opsused ((NEG (dst))::l) = OperSet.addList (opsused l, [dst])
230 | opsused ((NOT (dst))::l) = OperSet.addList (opsused l, [dst])
231 | opsused ((SAL (dst, shft))::l) = OperSet.addList (opsused l, [dst, shft])
232 | opsused ((SAR (dst, shft))::l) = OperSet.addList (opsused l, [dst, shft])
233 | opsused ((AND (dst, src))::l) = OperSet.addList (opsused l, [dst, src])
234 | opsused ((OR (dst, src))::l) = OperSet.addList (opsused l, [dst, src])
235 | opsused ((XOR (dst, src))::l) = OperSet.addList (opsused l, [dst, src])
236 | opsused ((CMP (dst, src))::l) = OperSet.addList (opsused l, [dst, src])
237 | opsused ((TEST (dst, src))::l) = OperSet.addList (opsused l, [dst, src])
238 | opsused ((SETcc (c, dst))::l) = OperSet.addList (opsused l, [dst])
239 | opsused ((JMP _)::l) = opsused l
240 | opsused ((Jcc _)::l) = opsused l
241 | opsused ((CALL _)::l) = opsused l
242 | opsused ((MOVZB (dst, src))::l) = OperSet.addList (opsused l, [dst, src])
243 | opsused ((CLTD)::l) = opsused l
244 | opsused ((RET)::l) = opsused l
245 | opsused ((LIVEIGN i)::l) = opsused (i::l)
0a24e44d 246
1144856b
JW
247 fun sts 8 = Qword
248 | sts 4 = Long
249 | sts 2 = Word
250 | sts 1 = Byte
251 | sts _ = raise ErrorMsg.InternalError "invalid size"
0a24e44d
JW
252
253 (* pretty prints an operand *)
6ade8b0a
JW
254 fun sfx Byte = "b"
255 | sfx Word = "w"
256 | sfx Long = "l"
257 | sfx Qword = "q"
1144856b
JW
258
259 fun osize (OSIZE (s, _)) = s
260 | osize _ = Long
261
262 fun stripsize (OSIZE (_, oo)) = stripsize oo
263 | stripsize oo = oo
264
265 fun sizeoper (OSIZE (s, oo)) = (s, stripsize oo)
266 | sizeoper oo = (Long, oo)
267
6ade8b0a 268 fun prettyprint_oper s (REG r) = "%" ^ (regname s r)
1144856b 269 | prettyprint_oper _ (TEMP t) = (Temp.name t) ^ (sfx (sts (Temp.size t)))
6ade8b0a 270 | prettyprint_oper _ (CONST c) = "$0x" ^ (Word32.toString c)
1144856b
JW
271 | prettyprint_oper _ (REL (r, CONST n)) = (Word32Signed.toString n) ^ "(" ^ (prettyprint_oper Qword r) ^ ")"
272 | prettyprint_oper s (REL (r1, r2)) = "(" ^ (prettyprint_oper Qword (stripsize r1)) ^ "," ^ (prettyprint_oper Qword (stripsize r2)) ^ ")"
6ade8b0a 273 | prettyprint_oper _ (STACKARG i) = "arg#"^Int.toString i
1144856b 274 | prettyprint_oper _ (OSIZE (s, oo)) = prettyprint_oper s (stripsize oo)
0a24e44d
JW
275
276 (* pretty prints (no...) *)
1144856b
JW
277 fun prettyprint (DIRECTIVE(str)) = str ^ "\n"
278 | prettyprint (COMMENT(str)) = "// " ^ str ^ "\n"
279 | prettyprint (LABEL(l)) = Label.name l ^ ":\n"
280 | prettyprint (LEA(dst, src)) = "\tlea" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper (osize dst) (stripsize src)) ^ ", " ^ (prettyprint_oper Long dst) ^ "\n"
281 | prettyprint (MOV(dst, src)) = "\tmov" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper (osize dst) (stripsize src)) ^ ", " ^ (prettyprint_oper Long dst) ^ "\n"
282 | prettyprint (SUB(dst, src)) = "\tsub" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper (osize dst) (stripsize src)) ^ ", " ^ (prettyprint_oper Long dst) ^ "\n"
283 | prettyprint (IMUL(dst, src)) = "\timul" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper (osize dst) (stripsize src)) ^ ", " ^ (prettyprint_oper Long dst) ^ "\n"
284 | prettyprint (IMUL3(dst, tmp, const)) = "\timul" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper (osize dst) (CONST const)) ^ ", " ^ (prettyprint_oper (osize dst) (stripsize tmp)) ^ ", " ^ (prettyprint_oper (osize dst) dst) ^ "\n"
285 | prettyprint (ADD(dst, src)) = "\tadd" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper (osize dst) (stripsize src)) ^ ", " ^ (prettyprint_oper Long dst) ^ "\n"
286 | prettyprint (IDIV(src)) = "\tidiv" ^ (sfx (osize src)) ^ "\t" ^ (prettyprint_oper (osize src) src) ^ "\n"
287 | prettyprint (NEG (dst)) = "\tneg" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper Long dst) ^ "\n"
288 | prettyprint (NOT (dst)) = "\tnot" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper Long dst) ^ "\n"
289 | prettyprint (SAL (dst, shft)) = "\tsal" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper Byte shft) ^ ", " ^ (prettyprint_oper Long dst) ^ "\n"
290 | prettyprint (SAR (dst, shft)) = "\tsar" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper Byte shft) ^ ", " ^ (prettyprint_oper Long dst) ^ "\n"
291 | prettyprint (AND (dst, src)) = "\tand" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper (osize dst) (stripsize src)) ^ ", " ^ (prettyprint_oper Long dst) ^ "\n"
292 | prettyprint (OR (dst, src)) = "\tor" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper (osize dst) (stripsize src)) ^ ", " ^ (prettyprint_oper Long dst) ^ "\n"
293 | prettyprint (XOR (dst, src)) = "\txor" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper (osize dst) (stripsize src)) ^ ", " ^ (prettyprint_oper Long dst) ^ "\n"
294 | prettyprint (CMP (dst, src)) = "\tcmp" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper (osize dst) (stripsize src)) ^ ", " ^ (prettyprint_oper Long dst) ^ "\n"
295 | prettyprint (TEST (dst, src)) = "\ttest" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper (osize dst) (stripsize src)) ^ ", " ^ (prettyprint_oper Long dst) ^ "\n"
296 | prettyprint (SETcc (c, dst)) = "\tset" ^ (ccname c) ^ "\t" ^ (prettyprint_oper Byte (stripsize dst)) ^ "\n"
297 | prettyprint (JMP (label)) = "\tjmp\t" ^ (Label.name label) ^ "\n"
298 | prettyprint (Jcc (c,label)) = "\tj" ^ (ccname c) ^ "\t" ^ (Label.name label) ^ "\n"
299 | prettyprint (CALL (l,n)) = "\tcall\t" ^ Symbol.name l ^ "\t # (" ^ Int.toString n ^ "args)\n"
300 | prettyprint (MOVZB (dst, src)) = "\tmovzb" ^ (sfx (osize dst)) ^ "\t" ^ (prettyprint_oper Byte (stripsize src)) ^ ", " ^ (prettyprint_oper Long dst) ^ "\n"
301 | prettyprint (CLTD) = "\tcltd\n"
302 | prettyprint (RET) = "\tret\n"
303 | prettyprint (LIVEIGN i) = prettyprint i
6ade8b0a 304(* | prettyprint _ = raise ErrorMsg.InternalError ("prettyprint: Type A? Hatchar de coneccion?")*)
12aa4087 305end
This page took 0.050288 seconds and 4 git commands to generate.