]>
Commit | Line | Data |
---|---|---|
0a24e44d JW |
1 | (* L2 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 | ||
12aa4087 JW |
7 | signature X86 = |
8 | sig | |
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 *) |
12aa4087 | 13 | datatype oper = REG of reg | TEMP of Temp.temp | CONST of Word32.word | REL of (reg * int) |
0a24e44d JW |
14 | (* instructions |
15 | * a better way to do SET would be SET of cc * oper, | |
16 | * same with JMP | |
17 | *) | |
12aa4087 JW |
18 | datatype insn = |
19 | DIRECTIVE of string | | |
20 | COMMENT of string | | |
0a24e44d | 21 | LABEL of Label.label | |
12aa4087 JW |
22 | MOVL of oper * oper | |
23 | SUBL of oper * oper | | |
24 | IMUL of oper * oper | | |
25 | IMUL3 of oper * oper * Word32.word | | |
26 | ADDL of oper * oper | | |
12aa4087 JW |
27 | IDIVL of oper | |
28 | NEG of oper | | |
0a24e44d JW |
29 | NOTL of oper | |
30 | SALL of oper * oper | | |
31 | SARL of oper * oper | | |
32 | ANDL of oper * oper | | |
33 | ORL of oper * oper | | |
34 | XORL of oper * oper | | |
35 | CMPL of oper * oper | | |
36 | TEST of oper * oper | | |
37 | SETNE of oper | | |
38 | SETE of oper | | |
39 | SETLE of oper | | |
40 | SETL of oper | | |
41 | SETGE of oper | | |
42 | SETG of oper | | |
43 | JMP of Label.label | | |
44 | JE of Label.label | | |
45 | JNE of Label.label | | |
46 | MOVZBL of oper * oper | | |
12aa4087 JW |
47 | CLTD | |
48 | RET | |
49 | ||
50 | val cmpoper : oper * oper -> order | |
51 | val opereq : oper * oper -> bool | |
52 | val regname : reg -> string | |
0a24e44d | 53 | val regnameb : reg -> string |
12aa4087 JW |
54 | val regtonum : reg -> int |
55 | val numtoreg : int -> reg | |
56 | val prettyprint_oper : oper -> string | |
0a24e44d | 57 | val prettyprint_operb : oper -> string |
12aa4087 JW |
58 | val prettyprint : insn -> string |
59 | end | |
60 | ||
61 | structure x86 :> X86 = | |
62 | struct | |
63 | datatype reg = | |
64 | EAX | EBX | ECX | EDX | ESI | EDI | EBP | RSP | R8D | R9D | R10D | R11D | R12D | R13D | R14D | R15D | |
65 | datatype oper = REG of reg | TEMP of Temp.temp | CONST of Word32.word | REL of (reg * int) | |
66 | datatype insn = | |
67 | DIRECTIVE of string | | |
68 | COMMENT of string | | |
0a24e44d | 69 | LABEL of Label.label | |
12aa4087 JW |
70 | MOVL of oper * oper | |
71 | SUBL of oper * oper | | |
72 | IMUL of oper * oper | | |
73 | IMUL3 of oper * oper * Word32.word | | |
74 | ADDL of oper * oper | | |
12aa4087 JW |
75 | IDIVL of oper | |
76 | NEG of oper | | |
0a24e44d JW |
77 | NOTL of oper | |
78 | SALL of oper * oper | | |
79 | SARL of oper * oper | | |
80 | ANDL of oper * oper | | |
81 | ORL of oper * oper | | |
82 | XORL of oper * oper | | |
83 | CMPL of oper * oper | | |
84 | TEST of oper * oper | | |
85 | SETNE of oper | | |
86 | SETE of oper | | |
87 | SETLE of oper | | |
88 | SETL of oper | | |
89 | SETGE of oper | | |
90 | SETG of oper | | |
91 | JMP of Label.label | | |
92 | JE of Label.label | | |
93 | JNE of Label.label | | |
94 | MOVZBL of oper * oper | | |
12aa4087 JW |
95 | CLTD | |
96 | RET | |
0a24e44d JW |
97 | |
98 | (* gives name of reg *) | |
12aa4087 JW |
99 | fun regname EAX = "eax" |
100 | | regname EBX = "ebx" | |
101 | | regname ECX = "ecx" | |
102 | | regname EDX = "edx" | |
103 | | regname ESI = "esi" | |
104 | | regname EDI = "edi" | |
105 | | regname EBP = "ebp" | |
106 | | regname RSP = "rsp" | |
107 | | regname R8D = "r8d" | |
108 | | regname R9D = "r9d" | |
109 | | regname R10D = "r10d" | |
110 | | regname R11D = "r11d" | |
111 | | regname R12D = "r12d" | |
112 | | regname R13D = "r13d" | |
113 | | regname R14D = "r14d" | |
114 | | regname R15D = "r15d" | |
0a24e44d JW |
115 | |
116 | (* like regname, but for the byte name *) | |
117 | fun regnameb EAX = "al" | |
118 | | regnameb EBX = "bl" | |
119 | | regnameb ECX = "cl" | |
120 | | regnameb EDX = "dl" | |
121 | | regnameb ESI = "sil" | |
122 | | regnameb EDI = "dil" | |
123 | | regnameb EBP = "bpl" | |
124 | | regnameb RSP = "spl" | |
125 | | regnameb R8D = "r8b" | |
126 | | regnameb R9D = "r9b" | |
127 | | regnameb R10D = "r10b" | |
128 | | regnameb R11D = "r11b" | |
129 | | regnameb R12D = "r12b" | |
130 | | regnameb R13D = "r13b" | |
131 | | regnameb R14D = "r14b" | |
132 | | regnameb R15D = "r15b" | |
133 | ||
134 | (* gives number (color) associated with reg *) | |
12aa4087 JW |
135 | fun regtonum EAX = 0 |
136 | | regtonum EBX = 1 | |
137 | | regtonum ECX = 2 | |
138 | | regtonum EDX = 3 | |
139 | | regtonum ESI = 4 | |
140 | | regtonum EDI = 5 | |
141 | | regtonum R8D = 6 | |
142 | | regtonum R9D = 7 | |
143 | | regtonum R10D = 8 | |
144 | | regtonum R11D = 9 | |
145 | | regtonum R12D = 10 | |
146 | | regtonum R13D = 11 | |
147 | | regtonum R14D = 12 | |
148 | | regtonum R15D = 13 | |
149 | | regtonum EBP = 14 (* Dummy numbers -- not permitted for allocation, but there so that we can compare *) | |
150 | | regtonum RSP = 15 | |
0a24e44d JW |
151 | |
152 | (* gives reg associated with number (color) *) | |
12aa4087 JW |
153 | fun numtoreg 0 = EAX |
154 | | numtoreg 1 = EBX | |
155 | | numtoreg 2 = ECX | |
156 | | numtoreg 3 = EDX | |
157 | | numtoreg 4 = ESI | |
158 | | numtoreg 5 = EDI | |
159 | | numtoreg 6 = R8D | |
160 | | numtoreg 7 = R9D | |
161 | | numtoreg 8 = R10D | |
162 | | numtoreg 9 = R11D | |
163 | | numtoreg 10 = R12D | |
164 | | numtoreg 11 = R13D | |
165 | | numtoreg 12 = R14D | |
166 | | numtoreg 13 = R15D | |
167 | | numtoreg n = raise ErrorMsg.InternalError ("numtoreg: Unknown register "^(Int.toString n)) | |
0a24e44d JW |
168 | |
169 | (* register compare *) | |
12aa4087 JW |
170 | fun regcmp (r1, r2) = Int.compare (regtonum r1, regtonum r2) |
171 | ||
0a24e44d JW |
172 | (* operand compare; arbitrary order imposed to make |
173 | * various things easier (e.g. liveness, for sorting) | |
174 | *) | |
12aa4087 JW |
175 | fun cmpoper (REG(reg1), REG(reg2)) = regcmp (reg1, reg2) |
176 | | cmpoper (TEMP(temp1), TEMP(temp2)) = Temp.compare (temp1,temp2) | |
177 | | cmpoper (CONST(const1), CONST(const2)) = Word32.compare (const1, const2) | |
178 | | cmpoper (REL (r1, i1), REL (r2, i2)) = | |
179 | let | |
180 | val regorder = regcmp (r1, r2) | |
181 | val intorder = Int.compare (i1, i2) | |
182 | in | |
183 | if (regorder = EQUAL) then intorder | |
184 | else regorder | |
185 | end | |
186 | | cmpoper (CONST _, _) = LESS | |
187 | | cmpoper (REG _, _) = LESS | |
188 | | cmpoper (REL _, _) = LESS | |
189 | | cmpoper (_, _) = GREATER | |
0a24e44d | 190 | |
12aa4087 | 191 | fun opereq (a, b) = cmpoper (a, b) = EQUAL |
0a24e44d JW |
192 | |
193 | (* integer tostring, except with more - and less ~ *) | |
12aa4087 JW |
194 | fun moreDifferentToString (i) = |
195 | if (i >= 0) then Int.toString i | |
196 | else "-" ^ (Int.toString (~i)) | |
0a24e44d JW |
197 | |
198 | (* pretty prints an operand *) | |
12aa4087 JW |
199 | fun prettyprint_oper (REG r) = "%" ^ (regname r) |
200 | | prettyprint_oper (TEMP t) = Temp.name t | |
201 | | prettyprint_oper (CONST c) = "$0x" ^ (Word32.toString c) | |
202 | | prettyprint_oper (REL (r, i)) = (moreDifferentToString i) ^ "(%" ^ (regname r) ^ ")" | |
203 | ||
0a24e44d JW |
204 | (* pretty prints an operand as a byte *) |
205 | fun prettyprint_operb (REG r) = "%" ^ (regnameb r) | |
206 | | prettyprint_operb (TEMP t) = Temp.name t ^ "b" | |
207 | | prettyprint_operb (CONST c) = "$0x" ^ (Word32.toString (c mod 0w32)) | |
208 | | prettyprint_operb x = prettyprint_oper x | |
209 | ||
210 | (* pretty prints (no...) *) | |
12aa4087 JW |
211 | fun prettyprint (DIRECTIVE(str)) = str ^ "\n" |
212 | | prettyprint (COMMENT(str)) = "// " ^ str ^ "\n" | |
0a24e44d | 213 | | prettyprint (LABEL(l)) = Label.name l ^ "\n" |
12aa4087 JW |
214 | | prettyprint (MOVL(src, dst)) = "\tMOVL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" |
215 | | prettyprint (SUBL(src, dst)) = "\tSUBL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" | |
216 | | prettyprint (IMUL(src, dst)) = "\tIMUL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" | |
217 | | prettyprint (IMUL3(dst, tmp, const)) = "\tIMUL\t" ^ (prettyprint_oper (CONST const)) ^ ", " ^ (prettyprint_oper tmp) ^ ", " ^ (prettyprint_oper dst) ^ "\n" | |
218 | | prettyprint (ADDL(src, dst)) = "\tADDL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" | |
12aa4087 JW |
219 | | prettyprint (IDIVL(src)) = "\tIDIVL\t" ^ (prettyprint_oper src) ^ "\n" |
220 | | prettyprint (NEG (src)) = "\tNEG\t" ^ (prettyprint_oper src) ^ "\n" | |
0a24e44d JW |
221 | | prettyprint (NOTL (src)) = "\tNOTL\t" ^ (prettyprint_oper src) ^ "\n" |
222 | | prettyprint (SALL (dst, shft)) = "\tSALL\t" ^ (prettyprint_oper dst) ^ ", " ^ (prettyprint_operb shft) ^ "\n" | |
223 | | prettyprint (SARL (dst, shft)) = "\tSARL\t" ^ (prettyprint_oper dst) ^ ", " ^ (prettyprint_operb shft) ^ "\n" | |
224 | | prettyprint (ANDL(src, dst)) = "\tANDL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" | |
225 | | prettyprint (ORL(src, dst)) = "\tORL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" | |
226 | | prettyprint (XORL(src, dst)) = "\tXORL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" | |
227 | | prettyprint (CMPL(src, dst)) = "\tCMPL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" | |
228 | | prettyprint (TEST(src, dst)) = "\tTEST\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" | |
229 | | prettyprint (SETNE(dst)) = "\tSETNE\t" ^ (prettyprint_operb dst) ^ "\n" | |
230 | | prettyprint (SETE(dst)) = "\tSETE\t" ^ (prettyprint_operb dst) ^ "\n" | |
231 | | prettyprint (SETLE(dst)) = "\tSETLE\t" ^ (prettyprint_operb dst) ^ "\n" | |
232 | | prettyprint (SETL(dst)) = "\tSETL\t" ^ (prettyprint_operb dst) ^ "\n" | |
233 | | prettyprint (SETGE(dst)) = "\tSETGE\t" ^ (prettyprint_operb dst) ^ "\n" | |
234 | | prettyprint (SETG(dst)) = "\tSETG\t" ^ (prettyprint_operb dst) ^ "\n" | |
235 | | prettyprint (JMP(label)) = "\tJMP\t" ^ (Label.name label) ^ "\n" | |
236 | | prettyprint (JE(label)) = "\tJE\t" ^ (Label.name label) ^ "\n" | |
237 | | prettyprint (JNE(label)) = "\tJNE\t" ^ (Label.name label) ^ "\n" | |
238 | | prettyprint (MOVZBL(src, dst)) = "\tMOVZBL\t" ^ (prettyprint_operb src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" | |
12aa4087 JW |
239 | | prettyprint (CLTD) = "\tCLTD\n" |
240 | | prettyprint (RET) = "\tRET\n" | |
241 | (* | prettyprint _ = raise ErrorMsg.InternalError ("prettyprint: unknown instruction")*) | |
242 | end |