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