]> Joshua Wise's Git repositories - snipe.git/blob - codegen/x86.sml
Initial import of l2c
[snipe.git] / codegen / x86.sml
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
7 signature X86 =
8 sig
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)
14   (* instructions
15    * a better way to do SET would be SET of cc * oper,
16    * same with JMP
17    *)
18   datatype insn =
19     DIRECTIVE of string |
20     COMMENT of string |
21     LABEL of Label.label |
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 |
27     IDIVL of oper |
28     NEG of oper |
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 |
47     CLTD |
48     RET
49   
50   val cmpoper : oper * oper -> order
51   val opereq : oper * oper -> bool
52   val regname : reg -> string
53   val regnameb : reg -> string
54   val regtonum : reg -> int
55   val numtoreg : int -> reg
56   val prettyprint_oper : oper -> string
57   val prettyprint_operb : oper -> string
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 |
69     LABEL of Label.label |
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 |
75     IDIVL of oper |
76     NEG of oper |
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 |
95     CLTD |
96     RET
97
98   (* gives name of reg *)
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"
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 *)
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
151
152   (* gives reg associated with number (color) *)
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))
168
169   (* register compare *)
170   fun regcmp (r1, r2) = Int.compare (regtonum r1, regtonum r2)
171
172   (* operand compare; arbitrary order imposed to make
173    * various things easier (e.g. liveness, for sorting)
174    *)
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
190
191   fun opereq (a, b) = cmpoper (a, b) = EQUAL
192
193   (* integer tostring, except with more - and less ~ *)
194   fun moreDifferentToString (i) =
195        if (i >= 0) then Int.toString i
196        else "-" ^ (Int.toString (~i))
197
198   (* pretty prints an operand *)  
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
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...) *)
211   fun prettyprint (DIRECTIVE(str)) = str ^ "\n"
212     | prettyprint (COMMENT(str)) = "// " ^ str ^ "\n"
213     | prettyprint (LABEL(l)) = Label.name l ^ "\n"
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"
219     | prettyprint (IDIVL(src)) = "\tIDIVL\t" ^ (prettyprint_oper src) ^ "\n"
220     | prettyprint (NEG (src)) = "\tNEG\t" ^ (prettyprint_oper src) ^ "\n"
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"
239     | prettyprint (CLTD) = "\tCLTD\n"
240     | prettyprint (RET) = "\tRET\n"
241 (*    | prettyprint _ = raise ErrorMsg.InternalError ("prettyprint: unknown instruction")*)
242 end
This page took 0.038689 seconds and 4 git commands to generate.