Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /sml/trunk/src/MLRISC/x86/x86.md
ViewVC logotype

Annotation of /sml/trunk/src/MLRISC/x86/x86.md

Parent Directory Parent Directory | Revision Log Revision Log


Revision 499 - (view) (download)

1 : monnier 409 (*
2 :     * 32bit, x86 instruction set.
3 :     *)
4 :     architecture X86 =
5 :     struct
6 :    
7 :     name "X86"
8 :    
9 :     superscalar
10 :    
11 :     little endian (* is this right??? *)
12 :    
13 :     lowercase assembly
14 :    
15 :     (*
16 :     * Assembly note:
17 :     * Note: we are using the AT&T syntax (for Linux) and not the intel syntax
18 :     * memory operands have the form:
19 :     * section:disp(base, index, scale)
20 :     * Most of the complication is actually in emiting the correct
21 :     * operand syntax.
22 :     *)
23 :    
24 :     (* Note: While the x86 has only 8 integer and 8 floating point registers,
25 :     * the SMLNJ compiler fakes it by assuming that it has 32 integer
26 :     * and 32 floating point registers. That's why we
27 :     *)
28 :    
29 :     storage
30 :     GP = 32 cells of 32 bits in cellset called "register"
31 :     assembly as
32 :     (fn 0 => "%eax"
33 :     | 1 => "%ecx"
34 :     | 2 => "%edx"
35 :     | 3 => "%ebx"
36 :     | 4 => "%esp"
37 :     | 5 => "%ebp"
38 :     | 6 => "%esi"
39 :     | 7 => "%edi"
40 :     | r => "%"^Int.toString r
41 :     )
42 :     | FP = 32 cells of 80 bits in cellset called "floating point register"
43 :     assembly as (fn f => if f >= 0 andalso f < 8
44 :     then "%st("^Int.toString f^")"
45 :     else "%f"^Int.toString f (* fake register *)
46 :     )
47 :     | CC = cells of 32 bits in cellset called "condition code register"
48 :     assembly as "cc"
49 :     locations
50 :     eax = $GP[0]
51 :     and ecx = $GP[1]
52 :     and edx = $GP[2]
53 :     and ebx = $GP[3]
54 :     and esp = $GP[4]
55 :     and ebp = $GP[5]
56 :     and esi = $GP[6]
57 :     and edi = $GP[7]
58 : monnier 429 and stackptrR = $GP[4]
59 : monnier 409 and asmTmpR = ~1 (* not used *)
60 :     and fasmTmp = ~1 (* not used *)
61 :    
62 :     structure Cells =
63 :     struct
64 :     fun zeroReg _ = NONE
65 :     end
66 :    
67 :    
68 :     (*
69 :     semantics X86 =
70 :     struct
71 :     include "MD++/basis.md"
72 :     open Basis
73 :     structure Int32 = struct type int end
74 :     type 'a option
75 :     end *)
76 :    
77 :     structure Instruction = struct
78 :     (* An effective address can be any combination of
79 :     * base + index*scale + disp
80 :     * or
81 :     * B + I*SCALE + DISP
82 :     *
83 :     * where any component is optional. The operand datatype captures
84 :     * all these combinations.
85 :     *
86 :     * DISP == Immed | ImmedLabel | Const
87 :     * B == Displace{base=B, disp=0}
88 :     * B+DISP == Displace{base=B, disp=DISP}
89 :     * I*SCALE+DISP == Indexed{base=NONE, index=I, scale=SCALE, disp=D}
90 :     * B+I*SCALE+DISP == Indexed{base=SOME B, index=I, scale=SCALE, disp=DISP}
91 :     *
92 :     * Note1: The index register cannot be EBP.
93 :     * The disp field must be one of Immed, ImmedLabel, or Const.
94 :     *)
95 :    
96 :     (* Note: Relative is only generated after sdi resolution *)
97 :     datatype operand =
98 :     Immed of Int32.int
99 :     | Const of Constant.const
100 :     | ImmedLabel of LabelExp.labexp
101 :     | Relative of int
102 :     | LabelEA of LabelExp.labexp
103 :     | Direct of $GP
104 :     | FDirect of $FP
105 : monnier 498 | MemReg of int (* pseudo memory register *)
106 : monnier 409 | Displace of {base: $GP, disp:operand, mem:Region.region}
107 :     | Indexed of {base: $GP option, index: $GP, scale:int, disp:operand,
108 :     mem:Region.region}
109 :    
110 :     type ea = operand
111 :    
112 :     datatype binaryOp! = ADD | SUB | AND | OR | XOR | SHL | SAR | SHR
113 :    
114 :     datatype multDivOp! = UMUL | IDIV | UDIV
115 :    
116 :     datatype unaryOp! = DEC | INC | NEG | NOT
117 :    
118 :     datatype move! = MOVL | MOVZX | MOVB
119 :    
120 :     datatype cond! =
121 :     EQ | NE | LT | LE | GT | GE
122 :     | B | BE (* below *) | A | AE (* above *)
123 :     | C | NC (* if carry *)| P | NP (* if parity *)
124 :     | O | NO (* overflow *)
125 :    
126 :     (* The Intel manual is incorrect on the description of FDIV and FDIVR *)
127 :     datatype fbinOp! =
128 :     FADDP | FADD
129 :     | FMULP | FMUL
130 :     | FSUBP | FSUB (* ST(1) := ST-ST(1); [pop] *)
131 :     | FSUBRP | FSUBR (* ST(1) := ST(1)-ST; [pop] *)
132 :     | FDIVP | FDIV (* ST(1) := ST/ST(1); [pop] *)
133 :     | FDIVRP | FDIVR (* ST(1) := ST(1)/ST; [pop] *)
134 :    
135 :     datatype funOp! = FABS | FCHS
136 :    
137 :     end (* struct Instruction *)
138 :    
139 :     (* A bunch of routines for emitting assembly *)
140 :     functor Assembly
141 :     (structure MemRegs : MEMORY_REGISTERS where I = Instr) =
142 :     struct
143 :     val memReg = MemRegs.memReg regmap
144 : monnier 429 fun emitInt32 i =
145 :     let val s = Int32.toString i
146 :     val s = if i >= 0 then s else "-"^String.substring(s,1,size s-1)
147 :     in emit s end
148 :    
149 : monnier 409 fun emit_src2 NONE = ()
150 :     | emit_src2(SOME i) = (emit "$"; emitInt32 i; emit ", ")
151 :    
152 :     fun emitScale 0 = emit "1"
153 :     | emitScale 1 = emit "2"
154 :     | emitScale 2 = emit "4"
155 :     | emitScale 3 = emit "8"
156 :     | emitScale _ = error "emitScale"
157 :    
158 :     and eImmed(I.Immed (i)) = emitInt32 i
159 :     | eImmed(I.Const c) = emit_const c
160 :     | eImmed(I.ImmedLabel lexp) = emit_labexp lexp
161 :     | eImmed _ = error "eImmed"
162 :    
163 :     and emit_operand opn =
164 :     case opn of
165 :     I.Immed i => (emit "$"; emitInt32 i)
166 :     | I.Const c => emit_const c
167 :     | I.ImmedLabel lexp => (emit "$"; emit_labexp lexp)
168 :     | I.LabelEA le => emit_labexp le
169 :     | I.Relative _ => error "emit_operand"
170 :     | I.Direct r => emit_GP r
171 : monnier 498 | I.MemReg r => emit_operand(memReg opn)
172 : monnier 409 | I.FDirect f =>
173 :     let val f' = regmap f
174 :     in if f' < (32+8) then emit_FP f' else emit_operand(memReg opn) end
175 :     | I.Displace{base,disp=I.Immed(0),mem,...} =>
176 :     (emit "("; emit_GP base; emit ")"; emit_region mem)
177 :     | I.Displace{base,disp,mem,...} =>
178 :     (eImmed disp; emit "("; emit_GP base; emit ")";
179 :     emit_region mem)
180 :     | I.Indexed{base=NONE,index,scale,disp,mem,...} =>
181 :     (emit "("; emit_GP index; comma(); emitScale scale; emit ")";
182 :     emit_region mem)
183 :     | I.Indexed{base=SOME base,index,scale,disp,mem,...} =>
184 :     (eOptionalDisp disp; emit "("; emit_GP base;
185 : monnier 429 comma(); emit_GP index; comma(); emitScale scale; emit ")";
186 : monnier 409 emit_region mem)
187 :     and eOptionalDisp(I.Immed 0) = ()
188 :     | eOptionalDisp(I.Const c) = emit(Constant.toString c)
189 :     | eOptionalDisp(I.Immed i) = emitInt32 i
190 :     | eOptionalDisp _ = error "eOptionalDisp"
191 :    
192 :     (* The gas assembler does not like the "$" prefix for immediate
193 :     * labels in certain instructions.
194 :     *)
195 :     fun stupidGas(I.ImmedLabel lexp) = emit_labexp lexp
196 :     | stupidGas(I.LabelEA _) = error "stupidGas"
197 :     | stupidGas opnd = emit_operand opnd
198 :    
199 :     val emit_dst = emit_operand
200 :     val emit_src = emit_operand
201 :     val emit_opnd = emit_operand
202 :     val emit_src1 = emit_operand
203 :     val emit_rsrc = emit_operand
204 :     val emit_lsrc = emit_operand
205 :     val emit_addr = emit_operand
206 :     end
207 :    
208 :     (* many of these instructions imply certain register usages *)
209 :     instruction
210 :     NOP
211 :     ``nop''
212 :    
213 :     | JMP of operand * Label.label list
214 :     ``jmp\t<stupidGas operand>''
215 :    
216 :     | JCC of {cond:cond, opnd:operand}
217 :     ``j<cond>, <stupidGas opnd>''
218 :    
219 :     | CALL of operand * C.cellset * C.cellset * Region.region
220 : monnier 498 ``call\t<stupidGas operand><region><
221 :     emit_defs(cellset1)><
222 :     emit_uses(cellset2)>''
223 : monnier 409
224 : monnier 429 | RET of operand option
225 :     ``ret<case operand of NONE => ()
226 :     | SOME e => (emit "\t"; emit_operand e)>''
227 : monnier 409
228 :     (* integer *)
229 :     | MOVE of {mvOp:move, src:operand, dst:operand}
230 :     ``<mvOp>\t<src>, <dst>''
231 :    
232 :     | LEA of {r32: $GP, addr: operand}
233 :     ``leal\t<addr>, <r32>''
234 :    
235 :     | CMP of {lsrc: operand, rsrc: operand}
236 :     ``cmpl\t<rsrc>, <lsrc>''
237 :    
238 :     | BINARY of {binOp:binaryOp, src:operand, dst:operand}
239 :     ``<binOp>l\t<src>, <dst>''
240 :    
241 :     | MULTDIV of {multDivOp:multDivOp, src:operand}
242 :     ``<multDivOp>l\t<src>''
243 :    
244 :     | MUL3 of {dst:int, src1:operand, src2: Int32.int option}
245 :     ``imul\t<src1>, <emit_src2 src2><dst>''
246 :    
247 :     | UNARY of {unOp:unaryOp, opnd:operand}
248 :     ``<unOp>l\t<opnd>''
249 :    
250 :     | PUSH of operand
251 :     ``pushl\t<operand>''
252 :    
253 :     | POP of operand
254 :     ``popl\t<operand>''
255 :    
256 :     | CDQ
257 :     ``cdq''
258 :    
259 :     | INTO
260 :     ``into''
261 :    
262 :     (* parallel copies *)
263 :     | COPY of {dst: $GP list, src: $GP list, tmp:operand option}
264 :     ``<emitInstrs (Shuffle.shuffle{regmap,tmp,dst,src})>''
265 :     | FCOPY of {dst: $FP list, src: $FP list, tmp:operand option}
266 :     ``<emitInstrs (Shuffle.shufflefp{regmap,tmp,dst,src})>''
267 :    
268 :    
269 :     (* floating *)
270 :     | FBINARY of {binOp:fbinOp, src:operand, dst:operand}
271 :     ``<binOp>\t<src>, <dst>''
272 :    
273 :     | FUNARY of funOp
274 :     ``<funOp>''
275 :    
276 :     | FUCOMPP
277 :     ``fucompp''
278 :    
279 :     | FXCH
280 :     ``fxch''
281 :    
282 :     | FSTP of operand
283 :     ``fstp\t<operand>''
284 :    
285 :     | FLD of operand
286 :     ``fld\t<operand>''
287 :    
288 :     | FILD of operand
289 :     ``fild\t<operand>''
290 :    
291 :     | FNSTSW
292 :     ``fnstsw''
293 :    
294 :     (* misc *)
295 :     | SAHF
296 :     ``sahf''
297 :    
298 :     (* annotations *)
299 :     | ANNOTATION of {i:instruction, a:Annotations.annotation}
300 :     ``<(emitInstr i; comment(Annotations.toString a))>''
301 :    
302 :     | GROUP of Annotations.annotation
303 :     ``<comment(Annotations.toString annotation)>''
304 :    
305 :     end
306 :    

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0