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 /MLRISC/trunk/amd64/amd64MC.sml
ViewVC logotype

Annotation of /MLRISC/trunk/amd64/amd64MC.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2619 - (view) (download)

1 : mrainey 2619 functor AMD64MCEmitter
2 :     (structure Instr : AMD64INSTR
3 :     structure Shuffle : AMD64SHUFFLE where I = Instr
4 :     structure MLTreeEval : MLTREE_EVAL where T = Instr.T
5 :     structure AsmEmitter : INSTRUCTION_EMITTER where I = Instr) : MC_EMIT =
6 :     struct
7 :     structure I = Instr
8 :     structure C = I.C
9 :     structure Const = I.Constant
10 :     structure W32 = Word32
11 :     structure W8 = Word8
12 :     structure W = LargeWord
13 :     structure CB = CellsBasis
14 :     structure LE = MLTreeEval
15 :    
16 :     val println = print o (fn s => s^"\n")
17 :     val i2s = Int.toString
18 :     val print_int = println o i2s
19 :    
20 :     val itow = Word.fromInt
21 :     val wtoi = Word.toInt
22 :    
23 :     fun error msg = MLRiscErrorMsg.impossible ("AMD64MCEmitter." ^ msg)
24 :    
25 :     (*
26 :     * Sanity check!
27 :     *)
28 :    
29 :     val eax = 0 val esp = 4
30 :     val ecx = 1 val ebp = 5
31 :     val edx = 2 val esi = 6
32 :     val ebx = 3 val edi = 7
33 :    
34 :     val opnd16Prefix = 0x66
35 :    
36 :     fun const c = Int32.fromInt (Const.valueOf c)
37 :     fun lexp le = Int32.fromInt (LE.valueOf le)
38 :    
39 :     val toWord8 = Word8.fromLargeWord o LargeWord.fromLargeInt o Int32.toLarge
40 :     val eBytes = Word8Vector.fromList
41 :     fun eByte i = eBytes [W8.fromInt i]
42 :     local
43 :     val toLWord = (W.fromLargeInt o Int32.toLarge)
44 :     fun shift (w,cnt) = W8.fromLargeWord(W.>>(w, cnt))
45 :     in
46 :     fun eShort i16 =
47 :     let val w = toLWord i16
48 :     in [shift(w, 0w0), shift(w,0w8)]
49 :     end
50 :     fun eLong i32 =
51 :     let val w = toLWord i32
52 :     in [shift(w, 0w0), shift(w,0w8), shift(w,0w16), shift(w,0w24)] end
53 :     end
54 :    
55 :     fun emitInstrs instrs = Word8Vector.concat(map emitInstr instrs)
56 :    
57 :     and emitAMD64Instr instr =
58 :     let val error =
59 :     fn msg =>
60 :     let val AsmEmitter.S.STREAM{emit,...} = AsmEmitter.makeStream []
61 :     in emit (I.INSTR instr); error msg end
62 :    
63 :     datatype reg_or_opc = REG of int | OPC of int
64 :     val reg = REG and opcode = OPC
65 :     fun rMask r = r mod 8
66 :     fun getRO (REG r) = rMask r
67 :     | getRO (OPC oc) = oc
68 :     val rNum' = rMask o CB.physicalRegisterNum
69 :     val rNum = CB.physicalRegisterNum
70 :     val fNum = CB.physicalRegisterNum
71 :     val isExtReg = (fn x => x > 7) o rNum
72 :     fun isExtReg' (REG r) = r > 7
73 :     | isExtReg' _ = false
74 :    
75 :     datatype size = Zero | Bits8 | Bits32
76 :     fun size i =
77 :     if i = 0 then Zero
78 :     else if Int32.<(i, 128) andalso Int32.<=(~128, i) then Bits8
79 :     else Bits32
80 :    
81 :     fun immedOpnd (I.Immed i32) = i32
82 :     | immedOpnd (I.ImmedLabel le) = lexp le
83 :     | immedOpnd (I.LabelEA le) = lexp le
84 :     | immedOpnd _ = error "immedOpnd"
85 :    
86 :     nonfix mod
87 :    
88 :     fun scale(n, m) = Word.toIntX(Word.<<(Word.fromInt n, Word.fromInt m))
89 :     fun modrm{mod, reg, rm} = W8.fromInt(scale(mod,6) + scale(reg,3) + rm)
90 :     fun sib{ss, index, base} = W8.fromInt(scale(ss,6) + scale(index,3) + base)
91 :     fun eREXRegs (r, x, b) =
92 :     let val rb1 = if r then 0wx4 else 0wx0
93 :     val rb2 = if x then rb1 + 0wx2 else rb1
94 :     val rb3 = if b then rb2 + 0wx1 else rb2
95 :     in
96 :     if r orelse x orelse b then SOME rb3 else NONE
97 :     end (* rex *)
98 :     fun eREX rb = 0wx40 + rb
99 :     fun eREX64 rb = eREX rb + 0wx8
100 :    
101 :     fun eImmedExt (r', I.Direct (_, r)) =
102 :     ( (isExtReg' r', false, isExtReg r),
103 :     [modrm{mod=3, reg=getRO r', rm=rNum' r}] )
104 :     | eImmedExt (r', I.Displace{base=base', disp, ...}) =
105 :     let val base = rNum' base'
106 :     val immed = immedOpnd disp
107 :     val rex = (isExtReg' r', false, isExtReg base')
108 :     val r' = getRO r'
109 :     fun displace(mod, eDisp) =
110 :     if base = esp then
111 :     modrm{mod=mod, reg=r', rm=4}::
112 :     sib{ss=0, index=4, base=esp}::eDisp immed
113 :     else
114 :     modrm{mod=mod, reg=r', rm=base} :: eDisp immed
115 :     in
116 :     (rex,
117 :     (case size immed
118 :     of Zero =>
119 :     if base = esp then
120 :     [modrm{mod=0, reg=r', rm=4}, sib{ss=0,index=4,base=esp}]
121 :     else if base = ebp then
122 :     [modrm{mod=1, reg=r', rm=ebp}, 0w0]
123 :     else
124 :     [modrm{mod=0, reg=r', rm=base}]
125 :     | Bits8 => displace (1, fn i => [toWord8 i])
126 :     | Bits32 => displace (2, eLong)
127 :     (*esac*)) )
128 :     end
129 :     | eImmedExt (r', I.Indexed {base=NONE, index, scale, disp, ...}) =
130 :     let val rex = (isExtReg' r', isExtReg index, false)
131 :     val r' = getRO r'
132 :     in
133 :     (rex,
134 :     (modrm{mod=0, reg=r', rm=4} ::
135 :     sib{base=5, ss=scale, index=rNum' index} ::
136 :     eLong (immedOpnd disp)) )
137 :     end
138 :     | eImmedExt(r', I.Indexed {base=SOME b, index, scale, disp, ...}) =
139 :     let val rex = (isExtReg' r', isExtReg index, isExtReg b)
140 :     val r' = getRO r'
141 :     val index = rNum' index
142 :     val base = rNum' b
143 :     val immed = immedOpnd disp
144 :     fun indexed (mod, eDisp) =
145 :     modrm{mod=mod, reg=r', rm=4} ::
146 :     sib{ss=scale, index=index, base=base} :: eDisp immed
147 :     in
148 :     (rex,
149 :     (case size immed
150 :     of Zero =>
151 :     if base=ebp then
152 :     [modrm{mod=1, reg=r', rm=4},
153 :     sib{ss=scale, index=index, base=5}, 0w0]
154 :     else
155 :     [modrm{mod=0, reg=r', rm=4},
156 :     sib{ss=scale, index=index, base=base}]
157 :     | Bits8 => indexed(1, fn i => [toWord8 i])
158 :     | Bits32 => indexed(2, eLong)
159 :     (*esac*)) )
160 :     end
161 :     | eImmedExt(_, I.Immed _) = error "eImmedExt: Immed"
162 :     | eImmedExt(_, I.ImmedLabel _) = error "eImmedExt: ImmedLabel"
163 :     | eImmedExt(_, I.Relative _) = error "eImmedExt: Relative"
164 :     | eImmedExt(_, I.LabelEA _) = error "eImmedExt: LabelEA"
165 :    
166 :     fun encode32' (bytes, r', opnd) =
167 :     let val (rex, e) = eImmedExt (r', opnd)
168 :     in
169 :     (case eREXRegs rex
170 :     of SOME rexByte => (eREX rexByte) :: bytes @ e
171 :     | NONE => bytes @ e
172 :     (* esac *))
173 :     end (* encode32' *)
174 :     fun encode64' (bytes, r', opnd) =
175 :     let val (rex, e) = eImmedExt (r', opnd)
176 :     in
177 :     (case eREXRegs rex
178 :     of SOME rexByte => (eREX64 rexByte) :: bytes @ e
179 :     | NONE => (eREX64 0wx0) :: bytes @ e
180 :     (* esac *))
181 :     end (* encode64' *)
182 :     fun encode32 (byte1, r', opnd) = eBytes (encode32' ([byte1], r', opnd))
183 :     fun encode64 (byte1, r', opnd) = eBytes (encode64' ([byte1], r', opnd))
184 :     fun encode sz = if sz = 64 then encode64 else encode32
185 :     fun encodeReg32 (byte1, r, opnd) = encode32 (byte1, reg (rNum r), opnd)
186 :     fun encodeReg64 (byte1, r, opnd) = encode64 (byte1, reg (rNum r), opnd)
187 :     fun encodeReg sz = if sz = 64 then encodeReg64 else encodeReg32
188 :     fun encodeLongImm32 (byte1, r', opnd, i) =
189 :     eBytes ((encode32' ([byte1], r', opnd)) @ eLong i)
190 :     fun encodeLongImm64 (byte1, r', opnd, i) =
191 :     eBytes ((encode64' ([byte1], r', opnd)) @ eLong i)
192 :     fun encodeLongImm sz = if sz = 64 then encodeLongImm64 else encodeLongImm32
193 :     fun encodeShortImm32 (byte1, r', opnd, w) =
194 :     eBytes ((encode32' ([byte1], r', opnd)) @ eShort w)
195 :     fun encodeShortImm64 (byte1, r', opnd, w) =
196 :     eBytes ((encode64' ([byte1], r', opnd)) @ eShort w)
197 :     fun encodeShortImm sz = if sz = 64 then encodeShortImm64 else encodeShortImm32
198 :     fun encodeByteImm32 (byte1, r', opnd, b) =
199 :     eBytes ((encode32' ([byte1], r', opnd)) @ [toWord8 b])
200 :     fun encodeByteImm64 (byte1, r', opnd, b) =
201 :     eBytes ((encode64' ([byte1], r', opnd)) @ [toWord8 b])
202 :     fun encodeByteImm sz = if sz = 64 then encodeByteImm64 else encodeByteImm32
203 :     fun encodeST (byte1, opc, STn) =
204 :     let fun reg{opc, reg} = W8.fromInt (scale (opc,3) + reg)
205 :     in eBytes [byte1, reg{opc=opc,reg=fNum STn}] end
206 :    
207 :     (* arith: only 5 cases need be considered:
208 :     * dst, src
209 :     * -----------
210 :     * EAX, imm32
211 :     * r/m32, imm32
212 :     * r/m32, imm8
213 :     * r/m32, r32
214 :     * r32, r/m32
215 :     *)
216 :     fun arith (sz, opc1, opc2) =
217 :     let fun f (I.ImmedLabel le, dst) = f(I.Immed(lexp le), dst)
218 :     | f (I.LabelEA le, dst) = f(I.Immed(lexp le), dst)
219 :     | f (I.Immed(i), dst) =
220 :     (case size i
221 :     of Bits32 =>
222 :     (case dst
223 :     of I.Direct (_, r) =>
224 :     if CB.physicalRegisterNum r = eax then
225 :     (if sz = 32
226 :     then eBytes (W8.fromInt (8 * (getRO opc2) + 5) :: eLong(i))
227 :     else eBytes (eREX64 0w0 :: W8.fromInt(8 * (getRO opc2) + 5)
228 :     :: eLong(i)))
229 :     else
230 :     encodeLongImm sz (0wx81, opc2, dst, i)
231 :     | _ => encodeLongImm sz (0wx81, opc2, dst, i)
232 :     (*esac*))
233 :     | _ => encodeByteImm sz (0wx83, opc2, dst, i) (* 83 /digit ib *)
234 :     (*esac*))
235 :     | f(src, I.Direct (_, r)) = encodeReg sz (opc1+0w3, r, src)
236 :     | f(I.Direct (_, r), dst) = encodeReg sz (opc1+0w1, r, dst)
237 :     | f _ = error "arith.f"
238 :     in f end (* arith *)
239 :    
240 :     fun condCode cond =
241 :     (case cond
242 :     of I.EQ => 0w4 | I.NE => 0w5
243 :     | I.LT => 0w12 | I.LE => 0w14
244 :     | I.GT => 0w15 | I.GE => 0w13
245 :     | I.A => 0w7 | I.AE => 0w3
246 :     | I.B => 0w2 | I.BE => 0w6
247 :     | I.C => 0w2 | I.NC => 0w3
248 :     | I.P => 0wxa | I.NP => 0wxb
249 :     | I.O => 0w0 | I.NO => 0w1
250 :     (*esac*))
251 :    
252 :     (* test: the following cases need be considered:
253 :     * lsrc, rsrc
254 :     * -----------
255 :     * AL, imm8 opc1 A8
256 :     * EAX, imm32 opc1 A9
257 :     * r/m8, imm8 opc2 F6/0 ib
258 :     * r/m32, imm32 opc2 F7/0 id
259 :     * r/m8, r8 opc3 84/r
260 :     * r/m32, r32 opc3 85/r
261 :     *)
262 :     fun test(sz, I.ImmedLabel le, lsrc) = test(sz, I.Immed(lexp le), lsrc)
263 :     | test(sz, I.LabelEA le, lsrc) = test(sz, I.Immed(lexp le), lsrc)
264 :     | test(sz, I.Immed(i), lsrc) =
265 :     (case (lsrc, i >= 0 andalso i < 255) of
266 :     (I.Direct (_, r), false) =>
267 :     if CB.physicalRegisterNum r = eax then eBytes(0wxA9 :: eLong i)
268 :     else encodeLongImm sz (0wxF7, opcode 0, lsrc, i)
269 :     | (_, false) => encodeLongImm sz (0wxF7, opcode 0, lsrc, i)
270 :     | (I.Direct (_, r), true) => (* 8 bit *)
271 :     let val r = CB.physicalRegisterNum r
272 :     in if r = eax then eBytes[0wxA8, toWord8 i]
273 :     else if r < 4 then
274 :     (* unfortunately, only CL, DL, BL can be encoded *)
275 :     encodeByteImm sz (0wxF6, opcode 0, lsrc, i)
276 :     else if sz = 8 then error "test.8"
277 :     else encodeLongImm sz (0wxF7, opcode 0, lsrc, i)
278 :     end
279 :     | (_, true) => encodeByteImm sz (0wxF6, opcode 0, lsrc, i)
280 :     )
281 :     | test(8, rsrc as I.Direct (_, r), lsrc) =
282 :     if rNum r < 4 then encodeReg32 (0wx84, r, lsrc)
283 :     else error "test.8"
284 :     | test(sz, I.Direct (_, r), lsrc) = encodeReg sz (0wx85, r, lsrc)
285 :     | test _ = error "test"
286 :    
287 :     in
288 :     (case instr
289 :     of I.UNARY{unOp, opnd} =>
290 :     (case unOp
291 :     of I.INCL => encode32 (0wxff, opcode 0, opnd)
292 :     | I.INCQ => encode64 (0wxff, opcode 0, opnd)
293 :     | I.DECL => encode32 (0wxff, opcode 1, opnd)
294 :     | I.DECQ => encode64 (0wxff, opcode 1, opnd)
295 :     | I.NOTL => encode32 (0wxff, opcode 2, opnd)
296 :     | I.NOTQ => encode64 (0wxff, opcode 2, opnd)
297 :     | I.NEGL => encode32 (0wxff, opcode 3, opnd)
298 :     | I.NEGQ => encode64 (0wxff, opcode 3, opnd)
299 :     | _ => error "UNARY is not in DEC/INC/NEG,NOT"
300 :     (* esac *))
301 :     | I.BINARY{binOp, src, dst} => let
302 :     fun shift (sz, code, src) =
303 :     (case src
304 :     of I.Immed (1) => encode sz (0wxd1, opcode code, dst)
305 :     | I.Immed (n) => encodeByteImm sz (0wxc1, opcode code, dst, n)
306 :     | I.Direct (_, r) =>
307 :     if rNum r <> ecx then error "shift: Direct"
308 :     else encode sz (0wxd3, opcode code, dst)
309 :     (* | I.MemReg _ => shift(code, memReg src)*)
310 :     | _ => error "shift"
311 :     (*esac*))
312 :     in
313 :     case binOp
314 :     of I.ADDL => arith(32, 0w0, opcode 0) (src, dst)
315 :     | I.SUBL => arith(32, 0wx28, opcode 5) (src, dst)
316 :     | I.ANDL => arith(32, 0wx20, opcode 4) (src, dst)
317 :     | I.ORL => arith(32, 0w8, opcode 1) (src, dst)
318 :     | I.XORL => arith(32, 0wx30, opcode 6) (src, dst)
319 :     | I.SHLL => shift(32, 4, src)
320 :     | I.SARL => shift(32, 7, src)
321 :     | I.SHRL => shift(32, 5, src)
322 :     | I.ADDQ => arith(64, 0w0, opcode 0) (src, dst)
323 :     | I.SUBQ => arith(64, 0wx28, opcode 5) (src, dst)
324 :     | I.ANDQ => arith(64, 0wx20, opcode 4) (src, dst)
325 :     | I.ORQ => arith(64, 0w8, opcode 1) (src, dst)
326 :     | I.XORQ => arith(64, 0wx30, opcode 6) (src, dst)
327 :     | I.SHLQ => shift(64, 4, src)
328 :     | I.SARQ => shift(64, 7, src)
329 :     | I.SHRQ => shift(64, 5, src)
330 :     | (I.IMULL | I.MULQ) =>
331 :     let val sz = if binOp = I.IMULQ then 64 else 32
332 :     in (case (src, dst)
333 :     of (I.Immed(i), I.Direct (_, dstR)) =>
334 :     (case size i
335 :     of Bits32 =>
336 :     encodeLongImm sz (0wx69, reg (rNum dstR), dst, i)
337 :     | _ => encodeByteImm sz (0wx6b, reg (rNum dstR), dst, i)
338 :     (* esac *))
339 :     | (_, I.Direct (_, dstR)) =>
340 :     eBytes (encode32' ([0wx0f, 0wxaf], reg (rNum dstR), src))
341 :     | _ => error "imul"
342 :     (* esac *))
343 :     end
344 :     | _ => error "binary"
345 :     end
346 :     | I.MULTDIV{multDivOp, src} =>
347 :     let val (mulOp, sz) =
348 :     (case multDivOp of
349 :     I.MULL1 => (4, 32) | I.IDIVL1 => (7, 32) | I.DIVL1 => (6, 32)
350 :     | I.MULQ1 => (4, 64) | I.IDIVQ1 => (7, 64) | I.DIVQ1 => (6, 64)
351 :     | I.IMULL1 => error "imull1"
352 :     | I.IMULQ1 => error "imulq1"
353 :     (* esac *))
354 :     in encode sz (0wxf7, opcode mulOp, src)
355 :     end
356 :     | I.MUL3{dst, src1, src2=i} =>
357 :     (case src1
358 :     of I.Immed _ => error "mul3: Immed"
359 :     | I.ImmedLabel _ => error "mul3: ImmedLabel"
360 :     | _ =>
361 :     (case size i
362 :     of Bits32 => encodeLongImm32(0wx69, reg (rNum dst), src1, i)
363 :     | _ => encodeByteImm32(0wx6b, reg (rNum dst), src1, i)
364 :     (*esac*))
365 :     (*esac*))
366 :     | I.MULQ3{dst, src1, src2=i} =>
367 :     (case src1
368 :     of I.Immed _ => error "mul3: Immed"
369 :     | I.ImmedLabel _ => error "mul3: ImmedLabel"
370 :     | _ =>
371 :     (case size i
372 :     of Bits32 => encodeLongImm64(0wx69, reg (rNum dst), src1, i)
373 :     | _ => encodeByteImm64(0wx6b, reg (rNum dst), src1, i)
374 :     (*esac*))
375 :     (*esac*))
376 :    
377 :     | I.RET NONE => eByte 0xc3
378 :     | I.NOP => eByte 0x90
379 :     | I.INTO => eByte(0xcd+4)
380 :     | I.CDQ => eByte(0x99)
381 :     | I.SAHF => eByte(0x9e)
382 :     | ( I.PUSHL (I.Immed i) | I.PUSHQ (I.Immed i) )=>
383 :     (case size i
384 :     of Bits32 => eBytes(0wx68 :: eLong(i))
385 :     | _ => eBytes [0wx6a, toWord8 i]
386 :     (* esac *))
387 :     | ( I.PUSHL (I.Direct (_, r)) |
388 :     I.PUSHQ (I.Direct (_, r)) ) => eByte (0x50+rNum r)
389 :     | ( I.PUSHL opnd | I.PUSHQ opnd ) => encode32 (0wxff, opcode 6, opnd)
390 :     | I.POP (I.Direct (_, r)) => eByte (0x58+rNum r)
391 :     | I.POP opnd => encode32 (0wx8f, opcode 0, opnd)
392 :     | I.LEAL{r32, addr} => encodeReg32(0wx8d, r32, addr)
393 :     | I.LEAQ{r64, addr} => encodeReg64(0wx8d, r64, addr)
394 :     | I.MOVE{mvOp=mvOp as (I.MOVL | I.MOVQ), src, dst} =>
395 :     let val sz = case mvOp of I.MOVL => 32 | I.MOVQ => 64
396 :     fun mv(I.Immed(i), I.Direct (_, r)) =
397 :     eBytes(Word8.+(0wxb8, Word8.fromInt(rNum r))::eLong(i))
398 :     | mv(I.Immed(i), _) = encodeLongImm sz (0wxc7, opcode 0, dst, i)
399 :     | mv(I.ImmedLabel le,dst) = mv(I.Immed(lexp le),dst)
400 :     | mv(I.LabelEA le,dst) = error "MOVL: LabelEA"
401 :     | mv(src,dst) = arith(sz, 0wx88, opcode 0) (src, dst)
402 :     in mv(src,dst) end
403 :     | I.MOVE{mvOp=I.MOVB, dst, src=I.Immed(i)} =>
404 :     (case size i
405 :     of Bits32 => error "MOVE: MOVB: imm8"
406 :     | _ => encodeByteImm32 (0wxc6, opcode 0, dst, i)
407 :     (*esac*))
408 :     | I.MOVE{mvOp=I.MOVB, dst, src=I.Direct (_, r)} =>
409 :     encodeReg32 (0wx88, r, dst)
410 :     | I.MOVE{mvOp=I.MOVB, dst=I.Direct (_, r), src} =>
411 :     encodeReg32 (0wx8a, r, src)
412 :     | I.MOVE{mvOp, src=I.Immed _, ...} => error "MOVE: Immed"
413 :     | I.MOVE{mvOp, src, dst=I.Direct (_, r)} =>
414 :     let val byte2 =
415 :     case mvOp of
416 :     I.MOVZBL => 0wxb6
417 :     | I.MOVZWL => 0wxb7
418 :     | I.MOVSBL => 0wxbe
419 :     | I.MOVSWL => 0wxbf
420 :     | _ => error "MOV[SZ]X"
421 :     in eBytes (encode32' ([0wx0f, byte2], reg (rNum r), src)) end
422 :     | I.MOVE _ => error "MOVE"
423 :     | I.CMOV{cond,src,dst} =>
424 :     eBytes (encode32' ([0wx0f, Word8.+(condCode cond,0wx40)],
425 :     reg (rNum dst), src))
426 :     | I.JMP(I.Relative i, _) => ((
427 :     let fun shortJmp () = eBytes [0wxeb, Word8.fromInt (i-2)]
428 :     in
429 :     (case size (Int32.fromInt (i-2))
430 :     of Bits32 => eBytes (0wxe9 :: eLong (Int32.fromInt (i-5)))
431 :     | _ => shortJmp ()
432 :     (*esac*))
433 :     end
434 :     ) handle e => (print "JMP\n"; raise e))
435 :     | I.JMP(opnd, _) => encode32(0wxff, opcode 4, opnd)
436 :     | I.JCC{cond, opnd=I.Relative i} =>
437 :     let val code = condCode cond
438 :     in case size (Int32.fromInt(i-2))
439 :     of Bits32 =>
440 :     eBytes(0wx0f :: Word8.+(0wx80, code) ::
441 :     eLong(Int32.fromInt(i-6)))
442 :     | _ =>
443 :     eBytes[Word8.+(0wx70,code), Word8.fromInt(i-2)]
444 :     end
445 :     | I.CALL{opnd=I.Relative i,...} =>
446 :     eBytes (0wxe8 :: eLong (Int32.fromInt (i-5)))
447 :     (* FIXME: add CALLQ *)
448 :     | I.CALL{opnd, ...} => encode32 (0wxff, opcode 2, opnd)
449 :     | I.CMPL{lsrc, rsrc} => arith(32, 0wx38, opcode 7) (rsrc, lsrc)
450 :     | I.CMPQ{lsrc, rsrc} => arith(64, 0wx38, opcode 7) (rsrc, lsrc)
451 :     | (I.CMPW _ | I.CMPB _) => error "CMP"
452 :     | I.TESTQ{lsrc, rsrc} => test(64, rsrc, lsrc)
453 :     | I.TESTL{lsrc, rsrc} => test(32, rsrc, lsrc)
454 :     | I.TESTB{lsrc, rsrc} => test(8, rsrc, lsrc)
455 :     | I.TESTW _ => error "TEST"
456 :     | I.SET{cond,opnd} =>
457 :     eBytes (encode32' ([0wx0f, Word8.+(0wx90,condCode cond)],
458 :     reg 0, opnd))
459 :    
460 :     | _ => error "emitInstr"
461 :     (* esac *))
462 :     end (* emitAMD64Instr *)
463 :    
464 :     and emitInstr (I.LIVE _) = Word8Vector.fromList []
465 :     | emitInstr (I.KILL _) = Word8Vector.fromList []
466 :     | emitInstr(I.COPY{k, dst, src, tmp, ...}) =
467 :     (case k
468 :     of CB.GP => emitInstrs (Shuffle.shuffle {tmp=tmp, dst=dst, src=src})
469 :     | CB.FP => emitInstrs (Shuffle.shufflefp {tmp=tmp, dst=dst, src=src})
470 :     | _ => error "COPY"
471 :     (*esac*))
472 :     | emitInstr (I.INSTR instr) = emitAMD64Instr instr
473 :     | emitInstr (I.ANNOTATION{i,...}) = emitInstr i
474 :    
475 :     end (* AMD64MCEmitter *)

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