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 651 - (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 : george 545 GP "r" = 32 cells of 32 bits in cellset called "register"
31 :     assembly as
32 :     (fn (0,8) => "%al"
33 :     | (0,16) => "%ax"
34 :     | (0,32) => "%eax"
35 :     | (1,8) => "%cl"
36 :     | (1,16) => "%cx"
37 :     | (1,32) => "%ecx"
38 :     | (2,8) => "%dl"
39 :     | (2,16) => "%dx"
40 :     | (2,32) => "%edx"
41 :     | (3,8) => "%bl"
42 :     | (3,16) => "%bx"
43 :     | (3,32) => "%ebx"
44 :     | (4,16) => "%sp"
45 :     | (4,32) => "%esp"
46 :     | (5,16) => "%bp"
47 :     | (5,32) => "%ebp"
48 :     | (6,16) => "%si"
49 :     | (6,32) => "%esi"
50 :     | (7,16) => "%di"
51 :     | (7,32) => "%edi"
52 :     | (r,_) => "%"^Int.toString r
53 : monnier 409 )
54 : george 545 | FP "f" = 32 cells of 80 bits in cellset called "floating point register"
55 : leunga 565 assembly as (fn (0,_) => "%st"
56 :     | (f,_) =>
57 :     if f < 8 then "%st("^Int.toString f^")"
58 :     else "%f"^Int.toString f
59 :     (* pseudo register *)
60 : george 545 )
61 :     | CC "cc" = cells of 32 bits in cellset called "condition code register"
62 :     assembly as "cc"
63 :     | MEM "m" = cells of 8 bits called "memory"
64 :     assembly as (fn (r,_) => "m"^Int.toString r)
65 :     | CTRL "ctrl" = cells of 8 bits called "control"
66 :     assembly as (fn (r,_) => "ctrl"^Int.toString r)
67 :    
68 : monnier 409 locations
69 :     eax = $GP[0]
70 :     and ecx = $GP[1]
71 :     and edx = $GP[2]
72 :     and ebx = $GP[3]
73 :     and esp = $GP[4]
74 :     and ebp = $GP[5]
75 :     and esi = $GP[6]
76 :     and edi = $GP[7]
77 : monnier 429 and stackptrR = $GP[4]
78 : george 545 and ST(x) = $FP[x]
79 : monnier 409 and asmTmpR = ~1 (* not used *)
80 :     and fasmTmp = ~1 (* not used *)
81 :    
82 : george 545 structure RTL =
83 : monnier 409 struct
84 : george 545 end
85 : monnier 409
86 :     structure Instruction = struct
87 :     (* An effective address can be any combination of
88 :     * base + index*scale + disp
89 :     * or
90 :     * B + I*SCALE + DISP
91 :     *
92 :     * where any component is optional. The operand datatype captures
93 :     * all these combinations.
94 :     *
95 :     * DISP == Immed | ImmedLabel | Const
96 :     * B == Displace{base=B, disp=0}
97 :     * B+DISP == Displace{base=B, disp=DISP}
98 :     * I*SCALE+DISP == Indexed{base=NONE, index=I, scale=SCALE, disp=D}
99 :     * B+I*SCALE+DISP == Indexed{base=SOME B, index=I, scale=SCALE, disp=DISP}
100 :     *
101 :     * Note1: The index register cannot be EBP.
102 :     * The disp field must be one of Immed, ImmedLabel, or Const.
103 :     *)
104 :    
105 :     (* Note: Relative is only generated after sdi resolution *)
106 :     datatype operand =
107 :     Immed of Int32.int
108 :     | ImmedLabel of LabelExp.labexp
109 :     | Relative of int
110 :     | LabelEA of LabelExp.labexp
111 :     | Direct of $GP
112 :     | FDirect of $FP
113 : george 555 | ST of $FP
114 : monnier 498 | MemReg of int (* pseudo memory register *)
115 : monnier 409 | Displace of {base: $GP, disp:operand, mem:Region.region}
116 :     | Indexed of {base: $GP option, index: $GP, scale:int, disp:operand,
117 :     mem:Region.region}
118 : george 545
119 :     type addressing_mode = operand
120 : monnier 409
121 :     type ea = operand
122 :    
123 : george 545 datatype cond! =
124 :     EQ "e" | NE | LT "l" | LE | GT "g" | GE
125 :     | B | BE (* below *) | A | AE (* above *)
126 :     | C | NC (* if carry *)| P | NP (* if parity *)
127 :     | O | NO (* overflow *)
128 : monnier 409
129 : leunga 646 (* LOCK can only be used in front of
130 :     * (Intel ordering, not gasm ordering)
131 :     * ADC, ADD, AND, BT mem, reg/imm
132 :     * BTS, BTR, BTC, OR mem, reg/imm
133 :     * SBB, SUB, XOR mem, reg/imm
134 :     * XCHG reg, mem
135 :     * XCHG mem, reg
136 :     * DEC, INC, NEG, NOT mem
137 :     *)
138 :    
139 : george 545 datatype binaryOp! =
140 :     ADDL | SUBL | ANDL | ORL | XORL | SHLL | SARL | SHRL | ADCL | SBBL
141 :     | ADDW | SUBW | ANDW | ORW | XORW | SHLW | SARW | SHRW
142 :     | ADDB | SUBB | ANDB | ORB | XORB | SHLB | SARB | SHRB
143 : leunga 646 | BTSW | BTCW | BTRW | BTSL | BTCL | BTRL
144 :     | ROLW | RORW | ROLL | RORL
145 :     | XCHGB | XCHGW | XCHGL
146 : george 545
147 : leunga 646 | LOCK_ADCW "lock\n\tadcw"
148 :     | LOCK_ADCL "lock\n\tadcl"
149 :     | LOCK_ADDW "lock\n\taddw"
150 :     | LOCK_ADDL "lock\n\taddl"
151 :     | LOCK_ANBW "lock\n\tanbw"
152 :     | LOCK_ANBL "lock\n\tanbl"
153 :     | LOCK_ANDW "lock\n\tandw"
154 :     | LOCK_ANDL "lock\n\tandl"
155 :     | LOCK_BTSW "lock\n\tbtsw"
156 :     | LOCK_BTSL "lock\n\tbtsl"
157 :     | LOCK_BTRW "lock\n\tbtrw"
158 :     | LOCK_BTRL "lock\n\tbtrl"
159 :     | LOCK_BTCW "lock\n\tbtcw"
160 :     | LOCK_BTCL "lock\n\tbtcl"
161 :     | LOCK_ORW "lock\n\torw"
162 :     | LOCK_ORL "lock\n\torl"
163 :     | LOCK_SBBW "lock\n\tsbbw"
164 :     | LOCK_SBBL "lock\n\tsbbl"
165 :     | LOCK_SUBW "lock\n\tsubw"
166 :     | LOCK_SUBL "lock\n\tsubl"
167 :     | LOCK_XORW "lock\n\txorw"
168 :     | LOCK_XORL "lock\n\txorl"
169 :     | LOCK_XCHGB "lock\n\txchgb"
170 :     | LOCK_XCHGW "lock\n\txchgw"
171 :     | LOCK_XCHGL "lock\n\txchgl"
172 :    
173 : leunga 606 datatype multDivOp! = MULL | IDIVL | DIVL
174 : monnier 409
175 : leunga 646 datatype unaryOp! = DECL | INCL | NEGL | NOTL | NOTW | NOTB
176 :     | LOCK_DECL "lock\n\tdecl"
177 :     | LOCK_INCL "lock\n\tincl"
178 :     | LOCK_NEGL "lock\n\tnegl"
179 :     | LOCK_NOTL "lock\n\tnotl"
180 : monnier 409
181 : leunga 646 datatype bitOp! = BTW | BTL
182 :     | LOCK_BTW "lock\n\tbtw"
183 :     | LOCK_BTL "lock\n\tbtl"
184 :    
185 : george 545 datatype move! = MOVL
186 :     | MOVB
187 :     | MOVW
188 :     | MOVSWL | MOVZWL (* word -> long *)
189 :     | MOVSBL | MOVZBL (* byte -> long *)
190 : monnier 409
191 :     (* The Intel manual is incorrect on the description of FDIV and FDIVR *)
192 :     datatype fbinOp! =
193 : leunga 565 FADDP | FADDS
194 :     | FMULP | FMULS
195 :     | FCOMS
196 :     | FCOMPS
197 :     | FSUBP | FSUBS (* ST(1) := ST-ST(1); [pop] *)
198 :     | FSUBRP | FSUBRS (* ST(1) := ST(1)-ST; [pop] *)
199 :     | FDIVP | FDIVS (* ST(1) := ST/ST(1); [pop] *)
200 :     | FDIVRP | FDIVRS (* ST(1) := ST(1)/ST; [pop] *)
201 :     | FADDL
202 :     | FMULL
203 :     | FCOML
204 :     | FCOMPL
205 :     | FSUBL (* ST(1) := ST-ST(1); [pop] *)
206 :     | FSUBRL (* ST(1) := ST(1)-ST; [pop] *)
207 :     | FDIVL (* ST(1) := ST/ST(1); [pop] *)
208 :     | FDIVRL (* ST(1) := ST(1)/ST; [pop] *)
209 : monnier 409
210 : leunga 565 datatype fibinOp! =
211 :     FIADDS | FIMULS | FICOMS | FICOMPS
212 :     | FISUBS | FISUBRS | FIDIVS | FIDIVRS
213 :     | FIADDL | FIMULL | FICOML | FICOMPL
214 :     | FISUBL | FISUBRL | FIDIVL | FIDIVRL
215 :    
216 : monnier 409 datatype funOp! = FABS | FCHS
217 : george 545 | FSIN | FCOS | FTAN
218 :     | FSCALE | FRNDINT | FSQRT
219 :     | FTST | FXAM
220 :     | FINCSTP | FDECSTP
221 : monnier 409
222 : george 545 datatype fenvOp! = FLDENV | FNLDENV | FSTENV | FNSTENV
223 :    
224 : monnier 409 end (* struct Instruction *)
225 :    
226 : leunga 583 (*
227 :     * Instruction encoding on the x86
228 :     * Because of variable width instructions.
229 :     * We decompose each byte field into a seperate format first, then combine
230 :     * then to form the real instructions
231 :     *)
232 :     instruction formats 8 bits
233 :     modrm{mod:2, reg:3, rm:3}
234 :     | sib{ss:2, index:3, base:3}
235 :     | immed8{imm:8}
236 :    
237 :     instruction formats 32 bits
238 :     immed32{imm:32}
239 :    
240 : monnier 409 (* A bunch of routines for emitting assembly *)
241 :     functor Assembly
242 :     (structure MemRegs : MEMORY_REGISTERS where I = Instr) =
243 :     struct
244 :     val memReg = MemRegs.memReg regmap
245 : monnier 429 fun emitInt32 i =
246 :     let val s = Int32.toString i
247 :     val s = if i >= 0 then s else "-"^String.substring(s,1,size s-1)
248 :     in emit s end
249 :    
250 : monnier 409 fun emitScale 0 = emit "1"
251 :     | emitScale 1 = emit "2"
252 :     | emitScale 2 = emit "4"
253 :     | emitScale 3 = emit "8"
254 :     | emitScale _ = error "emitScale"
255 :    
256 :     and eImmed(I.Immed (i)) = emitInt32 i
257 :     | eImmed(I.ImmedLabel lexp) = emit_labexp lexp
258 :     | eImmed _ = error "eImmed"
259 :    
260 :     and emit_operand opn =
261 :     case opn of
262 :     I.Immed i => (emit "$"; emitInt32 i)
263 :     | I.ImmedLabel lexp => (emit "$"; emit_labexp lexp)
264 :     | I.LabelEA le => emit_labexp le
265 :     | I.Relative _ => error "emit_operand"
266 :     | I.Direct r => emit_GP r
267 : monnier 498 | I.MemReg r => emit_operand(memReg opn)
268 : george 555 | I.ST f => emit_FP f
269 :     | I.FDirect f => emit_operand(memReg opn)
270 : monnier 409 | I.Displace{base,disp,mem,...} =>
271 : george 545 (emit_disp disp; emit "("; emit_GP base; emit ")";
272 : monnier 409 emit_region mem)
273 : leunga 576 | I.Indexed{base,index,scale,disp,mem,...} =>
274 :     (emit_disp disp; emit "(";
275 :     case base of
276 :     NONE => ()
277 :     | SOME base => emit_GP base;
278 :     comma();
279 :     emit_GP index; comma();
280 : george 545 emitScale scale; emit ")"; emit_region mem)
281 : monnier 409
282 : george 545 and emit_disp(I.Immed 0) = ()
283 :     | emit_disp(I.Immed i) = emitInt32 i
284 :     | emit_disp(I.ImmedLabel lexp) = emit_labexp lexp
285 :     | emit_disp _ = error "emit_disp"
286 :    
287 : monnier 409 (* The gas assembler does not like the "$" prefix for immediate
288 :     * labels in certain instructions.
289 :     *)
290 :     fun stupidGas(I.ImmedLabel lexp) = emit_labexp lexp
291 : leunga 594 | stupidGas opnd = (emit "*"; emit_operand opnd)
292 : monnier 409
293 : george 555 (* Display the floating point binary opcode *)
294 :     fun isMemOpnd(I.MemReg _) = true
295 :     | isMemOpnd(I.FDirect f) = true
296 :     | isMemOpnd(I.LabelEA _) = true
297 :     | isMemOpnd(I.Displace _) = true
298 :     | isMemOpnd(I.Indexed _) = true
299 :     | isMemOpnd _ = false
300 : leunga 565 fun chop fbinOp =
301 : george 555 let val n = size fbinOp
302 : leunga 565 in case Char.toLower(String.sub(fbinOp,n-1)) of
303 :     (#"s" | #"l") => String.substring(fbinOp,0,n-1)
304 : george 555 | _ => fbinOp
305 : leunga 565 end
306 : george 555
307 : monnier 409 val emit_dst = emit_operand
308 :     val emit_src = emit_operand
309 :     val emit_opnd = emit_operand
310 :     val emit_rsrc = emit_operand
311 :     val emit_lsrc = emit_operand
312 :     val emit_addr = emit_operand
313 : george 545 val emit_src1 = emit_operand
314 :     end (* Instruction *)
315 : monnier 409
316 :     (* many of these instructions imply certain register usages *)
317 :     instruction
318 :     NOP
319 :     ``nop''
320 :    
321 :     | JMP of operand * Label.label list
322 :     ``jmp\t<stupidGas operand>''
323 :    
324 :     | JCC of {cond:cond, opnd:operand}
325 : george 545 ``j<cond>\t<stupidGas opnd>''
326 : monnier 409
327 :     | CALL of operand * C.cellset * C.cellset * Region.region
328 : monnier 498 ``call\t<stupidGas operand><region><
329 :     emit_defs(cellset1)><
330 :     emit_uses(cellset2)>''
331 : monnier 409
332 : leunga 594 | ENTER of {src1:operand, src2:operand}
333 :     ``enter\t<emit_operand src1>, <emit_operand src2>''
334 : leunga 593
335 : george 545 | LEAVE
336 :     ``leave''
337 :    
338 : monnier 429 | RET of operand option
339 :     ``ret<case operand of NONE => ()
340 :     | SOME e => (emit "\t"; emit_operand e)>''
341 : monnier 409
342 :     (* integer *)
343 :     | MOVE of {mvOp:move, src:operand, dst:operand}
344 :     ``<mvOp>\t<src>, <dst>''
345 :    
346 :     | LEA of {r32: $GP, addr: operand}
347 :     ``leal\t<addr>, <r32>''
348 :    
349 : george 545 | CMPL of {lsrc: operand, rsrc: operand}
350 : monnier 409 ``cmpl\t<rsrc>, <lsrc>''
351 :    
352 : george 545 | CMPW of {lsrc: operand, rsrc: operand}
353 :     ``cmpb\t<rsrc>, <lsrc>''
354 :    
355 :     | CMPB of {lsrc: operand, rsrc: operand}
356 :     ``cmpb\t<rsrc>, <lsrc>''
357 :    
358 :     | TESTL of {lsrc: operand, rsrc: operand}
359 :     ``testl\t<rsrc>, <lsrc>''
360 :    
361 :     | TESTW of {lsrc: operand, rsrc: operand}
362 :     ``testw\t<rsrc>, <lsrc>''
363 :    
364 :     | TESTB of {lsrc: operand, rsrc: operand}
365 :     ``testb\t<rsrc>, <lsrc>''
366 :    
367 : leunga 646 | BITOP of {bitOp:bitOp, lsrc: operand, rsrc: operand}
368 :     ``<bitOp>\t<rsrc>, <lsrc>''
369 :    
370 : monnier 409 | BINARY of {binOp:binaryOp, src:operand, dst:operand}
371 : george 545 asm: (case (src,binOp) of
372 :     (I.Direct _,
373 :     (I.SARL | I.SHRL | I.SHLL |
374 :     I.SARW | I.SHRW | I.SHLW |
375 :     I.SARB | I.SHRB | I.SHLB)) => ``<binOp>\t%cl, <dst>''
376 :     | _ => ``<binOp>\t<src>, <dst>''
377 :     )
378 : monnier 409
379 :     | MULTDIV of {multDivOp:multDivOp, src:operand}
380 : leunga 606 ``<multDivOp>\t<src>''
381 : monnier 409
382 : george 545 | MUL3 of {dst: $GP, src2: Int32.int option, src1:operand}
383 :     (* Fermin: constant operand must go first *)
384 :     asm: (case src2 of
385 :     NONE => ``imul\t<src1>, <dst>''
386 :     | SOME i => ``imul\t$<emitInt32 i>, <src1>, <dst>''
387 :     )
388 : monnier 409
389 :     | UNARY of {unOp:unaryOp, opnd:operand}
390 : george 545 ``<unOp>\t<opnd>''
391 : monnier 409
392 : george 545 (* set byte on condition code; note that
393 :     * this only sets the low order byte, so it also
394 :     * uses its operand.
395 :     *)
396 :     | SET of {cond:cond, opnd:operand}
397 :     ``set<cond>\t<opnd>''
398 :    
399 :     (* conditional move; Pentium Pro or higher only
400 :     * Destination must be a register.
401 :     *)
402 :     | CMOV of {cond:cond, src:operand, dst: $GP}
403 :     ``cmov<cond>\t<src>, <dst>''
404 :    
405 :     | PUSHL of operand
406 : monnier 409 ``pushl\t<operand>''
407 :    
408 : george 545 | PUSHW of operand
409 :     ``pushw\t<operand>''
410 :    
411 :     | PUSHB of operand
412 :     ``pushb\t<operand>''
413 :    
414 : monnier 409 | POP of operand
415 :     ``popl\t<operand>''
416 :    
417 :     | CDQ
418 :     ``cdq''
419 :    
420 :     | INTO
421 :     ``into''
422 :    
423 :     (* parallel copies *)
424 :     | COPY of {dst: $GP list, src: $GP list, tmp:operand option}
425 : george 545 asm: emitInstrs (Shuffle.shuffle{regmap,tmp,dst,src})
426 :    
427 : monnier 409 | FCOPY of {dst: $FP list, src: $FP list, tmp:operand option}
428 : george 545 asm: emitInstrs (Shuffle.shufflefp{regmap,tmp,dst,src})
429 : monnier 409
430 :     (* floating *)
431 :     | FBINARY of {binOp:fbinOp, src:operand, dst:operand}
432 : leunga 565 asm: (if isMemOpnd src then ``<binOp>\t<src>''
433 :     else ``<emit(chop(asm_fbinOp binOp))>\t<src>, <dst>''
434 :     )
435 : monnier 409
436 : leunga 565 | FIBINARY of {binOp:fibinOp, src:operand}
437 :     asm: ``<binOp>\t<src>'' (* the implied destination is %ST(0) *)
438 :    
439 : monnier 409 | FUNARY of funOp
440 :     ``<funOp>''
441 :    
442 :     | FUCOMPP
443 :     ``fucompp''
444 :    
445 : george 545 | FCOMPP
446 :     ``fcompp''
447 : monnier 409
448 : george 545 | FXCH of {opnd: $FP}
449 :     asm: (``fxch\t''; if opnd = C.ST(1) then () else ``<opnd>'')
450 : monnier 409
451 : george 545 | FSTPL of operand
452 :     ``fstpl\t<operand>''
453 :    
454 :     | FSTPS of operand
455 :     ``fstps\t<operand>''
456 :    
457 : george 555 | FSTPT of operand
458 :     ``fstps\t<operand>''
459 :    
460 : leunga 579 | FSTL of operand
461 :     ``fstl\t<operand>''
462 :    
463 :     | FSTS of operand
464 :     ``fsts\t<operand>''
465 :    
466 : leunga 565 | FLD1
467 :     ``fld1''
468 :    
469 :     | FLDL2E
470 :     ``fldl2e''
471 :    
472 :     | FLDL2T
473 :     ``fldl2t''
474 :    
475 :     | FLDLG2
476 :     ``fldlg2''
477 :    
478 :     | FLDLN2
479 :     ``fldln2''
480 :    
481 :     | FLDPI
482 :     ``fldpi''
483 :    
484 :     | FLDZ
485 :     ``fldz''
486 :    
487 : george 545 | FLDL of operand
488 :     ``fldl\t<operand>''
489 :    
490 :     | FLDS of operand
491 :     ``flds\t<operand>''
492 :    
493 : george 555 | FLDT of operand
494 :     ``fldt\t<operand>''
495 :    
496 : monnier 409 | FILD of operand
497 :     ``fild\t<operand>''
498 :    
499 : leunga 565 | FILDL of operand
500 :     ``fildl\t<operand>''
501 :    
502 :     | FILDLL of operand
503 :     ``fildll\t<operand>''
504 :    
505 : monnier 409 | FNSTSW
506 :     ``fnstsw''
507 :    
508 : george 545 | FENV of {fenvOp:fenvOp, opnd:operand} (* load/store environment *)
509 :     ``<fenvOp>\t<opnd>''
510 :    
511 : monnier 409 (* misc *)
512 :     | SAHF
513 :     ``sahf''
514 :    
515 :     (* annotations *)
516 :     | ANNOTATION of {i:instruction, a:Annotations.annotation}
517 : leunga 624 asm: (comment(Annotations.toString a); nl(); emitInstr i)
518 :    
519 :     | SOURCE of {}
520 :     asm: ``source''
521 :     mc: ()
522 :    
523 :     | SINK of {}
524 :     asm: ``sink''
525 :     mc: ()
526 :    
527 :     | PHI of {}
528 :     asm: ``phi''
529 :     mc: ()
530 :    
531 : monnier 409 end
532 :    

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