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/ra/amd64SpillInstr.sml
ViewVC logotype

Annotation of /MLRISC/trunk/amd64/ra/amd64SpillInstr.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2619 - (view) (download)

1 : mrainey 2619 (* amd64SpillInstr.sml
2 :     *
3 :     * This functor contains callback functions for spilling and reloading
4 :     * instructions.
5 :     *)
6 :    
7 :     functor AMD64SpillInstr (
8 :     structure I : AMD64INSTR
9 :     structure Props : AMD64INSN_PROPERTIES
10 :     where I = I
11 :     ) : ARCH_SPILL_INSTR =
12 :     struct
13 :    
14 :     structure CB = CellsBasis
15 :     structure I = I
16 :     structure C = I.C
17 :    
18 :     fun error msg = MLRiscErrorMsg.impossible("AMD64Spill: "^ msg)
19 :    
20 :     fun liveKill(add, rmv) ({regs, spilled}, reg) =
21 :     {regs=rmv(reg, regs), spilled=add(reg, spilled)}
22 :     val fLiveKill = liveKill (C.addFreg, C.rmvFreg)
23 :     val rLiveKill = liveKill (C.addReg, C.rmvReg)
24 :    
25 :     val newReg = C.newReg
26 :     val newFreg = C.newFreg
27 :    
28 :     fun annotate(instr,[]) = instr
29 :     | annotate(instr,a::an) = annotate(I.ANNOTATION{i=instr,a=a},an)
30 :    
31 :     fun mark(instr, an) = annotate(I.INSTR instr, an)
32 :    
33 :     fun immed(I.Immed _) = true
34 :     | immed(I.ImmedLabel _) = true
35 :     | immed _ = false
36 :    
37 :     fun immedOrReg(I.Direct r) = true
38 :     | immedOrReg(I.Immed _) = true
39 :     | immedOrReg(I.ImmedLabel _) = true
40 :     | immedOrReg _ = false
41 :    
42 :     fun isMemory(I.Displace _) = true
43 :     | isMemory(I.Indexed _) = true
44 :     | isMemory(I.LabelEA _) = true
45 :     | isMemory _ = false
46 :    
47 :     fun mvInstr instr = let
48 :     fun mvOp 8 = I.MOVB
49 :     | mvOp 16 = I.MOVW
50 :     | mvOp 32 = I.MOVL
51 :     | mvOp 64 = I.MOVQ
52 :     | mvOp _ = error "mvInstr"
53 :     val sz = Props.szOfInstr instr
54 :     in
55 :     (sz, mvOp sz)
56 :     end (* mvInstr *)
57 :    
58 :     fun fmvInstr instr = let
59 :     fun mvOp 32 = I.MOVSS
60 :     | mvOp 64 = I.MOVSD
61 :     | mvOp _ = error "fmvInstr"
62 :     val sz = Props.szOfFinstr instr
63 :     in
64 :     (sz, mvOp sz)
65 :     end (* fmvInstr *)
66 :    
67 :     fun spillToEA CB.GP (r, ea) = let
68 :     fun move () = {code=[I.move {mvOp=I.MOVQ, dst=ea, src=I.Direct (64, r)}],
69 :     proh=[], newReg=NONE}
70 :     in
71 :     (case ea
72 :     of ( I.Displace _ | I.Indexed _ ) => move ()
73 :     | _ => error "spillToEA"
74 :     (* end case *))
75 :     end
76 :     | spillToEA CB.FP _ = error "spillToEA: FP"
77 :     | spillToEA _ _ = error "spillToEA"
78 :    
79 :     fun reloadFromEA CB.GP (r, ea) = let
80 :     fun move () = {code=[I.move {mvOp=I.MOVQ, dst=I.Direct (64, r), src=ea}],
81 :     proh=[], newReg=NONE}
82 :     in
83 :     (case ea
84 :     of ( I.Displace _ | I.Indexed _ ) => move ()
85 :     | _ => error "reloadFromEA"
86 :     (* end case *))
87 :     end
88 :     | reloadFromEA CB.FP _ = error "reloadFromEA: FP"
89 :     | reloadFromEA _ _ = error "reloadFromEA"
90 :    
91 :     fun spillR (i, r, spillLoc) = let
92 :     fun spill (instr, an) = let
93 :     fun done (instr, an) = {code=[mark (instr, an)], proh=[], newReg=NONE}
94 :     val (sz, sMvOp) = mvInstr instr
95 :     in
96 :     (case instr
97 :     of I.CALL {opnd=addr, defs, uses, return, cutsTo, mem, pops} =>
98 :     done (I.CALL {opnd=addr, defs=C.rmvReg (r, defs),
99 :     return=return, uses=uses,
100 :     cutsTo=cutsTo, mem=mem, pops=pops}, an)
101 :     | I.MOVE {mvOp as (I.MOVZBQ|I.MOVSBQ|I.MOVZWQ|I.MOVSWQ|
102 :     I.MOVSLQ|I.MOVZBL|I.MOVSBL|I.MOVZWL|
103 :     I.MOVSWL), src, dst} => let
104 :     val tmpR = newReg ()
105 :     val tmp = I.Direct (sz, tmpR)
106 :     in
107 :     {proh=[tmpR], newReg=SOME tmpR,
108 :     code=[mark (I.MOVE {mvOp=mvOp, src=src, dst=tmp}, an),
109 :     I.move {mvOp=sMvOp, src=tmp, dst=spillLoc}]}
110 :     end
111 :     | I.MOVE {mvOp, src as I.Direct (_, rs), dst} =>
112 :     if CB.sameColor (rs, r) then {code=[], proh=[], newReg=NONE}
113 :     else done (I.MOVE {mvOp=mvOp, src=src, dst=spillLoc}, an)
114 :     | I.MOVE {mvOp, src, dst=I.Direct _} =>
115 :     if Props.eqOpn(src, spillLoc)
116 :     then {code=[], proh=[], newReg=NONE}
117 :     else if immed src then
118 :     done(I.MOVE{mvOp=mvOp, src=src, dst=spillLoc}, an)
119 :     else let
120 :     val tmpR = newReg ()
121 :     val tmp = I.Direct (sz, tmpR)
122 :     in
123 :     {proh=[tmpR],
124 :     newReg=SOME tmpR,
125 :     code=[mark(I.MOVE {mvOp=mvOp, src=src, dst=tmp}, an),
126 :     I.move {mvOp=sMvOp, src=tmp, dst=spillLoc}]}
127 :     end
128 :     | I.LEAL {addr, r32} => let
129 :     val tmpR = newReg()
130 :     in
131 :     {proh=[tmpR], newReg=SOME tmpR,
132 :     code=[mark(I.LEAL {addr=addr, r32=tmpR}, an),
133 :     I.move{mvOp=I.MOVL, src=I.Direct (32, tmpR),
134 :     dst=spillLoc}]}
135 :     end
136 :     | I.LEAQ {addr, r64} => let
137 :     val tmpR = newReg()
138 :     in
139 :     {proh=[tmpR], newReg=SOME tmpR,
140 :     code=[mark(I.LEAQ{addr=addr, r64=tmpR}, an),
141 :     I.move{mvOp=I.MOVQ, src=I.Direct (64,tmpR),
142 :     dst=spillLoc}]}
143 :     end
144 :     | I.BINARY {binOp=I.XORL, src as I.Direct (_,rs),
145 :     dst=I.Direct (_,rd)} =>
146 :     if CB.sameColor (rs,rd)
147 :     then {proh=[], newReg=NONE,
148 :     code=[mark(I.MOVE{mvOp=I.MOVL, src=I.Immed 0,
149 :     dst=spillLoc}, an)]}
150 :     else
151 :     {proh=[], newReg=NONE,
152 :     code=[mark(I.BINARY{binOp=I.XORL, src=src,
153 :     dst=spillLoc}, an)]}
154 :     | I.BINARY{binOp=I.XORQ, src as I.Direct (_,rs),
155 :     dst=I.Direct (_,rd)} =>
156 :     if CB.sameColor(rs,rd)
157 :     then {proh=[], newReg=NONE,
158 :     code=[mark(I.MOVE{mvOp=I.MOVQ, src=I.Immed 0,
159 :     dst=spillLoc}, an)]}
160 :     else {proh=[], newReg=NONE,
161 :     code=[mark(I.BINARY{binOp=I.XORQ, src=src,
162 :     dst=spillLoc}, an)]}
163 :    
164 :     | I.BINARY {binOp, src, dst} => let
165 :     (* note: dst = r *)
166 :     fun multBinOp(I.MULQ|I.MULL|I.MULW|I.MULB|
167 :     I.IMULQ|I.IMULL|I.IMULW|I.IMULB) = true
168 :     | multBinOp _ = false
169 :     in
170 :     if multBinOp binOp
171 :     then let (* destination must remain a register *)
172 :     val tmpR = newReg()
173 :     val tmp = I.Direct (sz,tmpR)
174 :     in
175 :     {proh=[tmpR], newReg=SOME tmpR,
176 :     code=[I.move{mvOp=sMvOp, src=spillLoc, dst=tmp},
177 :     I.binary{binOp=binOp, src=src, dst=tmp},
178 :     I.move{mvOp=sMvOp, src=tmp, dst=spillLoc}]}
179 :     end
180 :     else if immedOrReg src
181 :     then (* can replace the destination directly *)
182 :     done(I.BINARY{binOp=binOp, src=src, dst=spillLoc},
183 :     an)
184 :     else let (* a memory src and non multBinOp
185 :     * --- cannot have two memory operands
186 :     *)
187 :     val tmpR = newReg()
188 :     val tmp = I.Direct (sz,tmpR)
189 :     in
190 :     { proh=[tmpR], newReg=NONE,
191 :     code=[I.move{mvOp=sMvOp, src=src, dst=tmp},
192 :     I.binary{binOp=binOp, src=tmp,
193 :     dst=spillLoc}]}
194 :     end
195 :     end
196 :     | I.SHIFT {shiftOp, count=I.Direct (_, ecx), src, dst} =>
197 :     error "implement shift"
198 :     | I.SHIFT {shiftOp, count, src, dst} =>
199 :     if immedOrReg src
200 :     then done (I.SHIFT {shiftOp=shiftOp, src=src, dst=spillLoc,
201 :     count=count}, an)
202 :     else let
203 :     val tmpR = newReg ()
204 :     val tmp = I.Direct (sz, tmpR)
205 :     in
206 :     {proh=[tmpR], newReg=NONE,
207 :     code=[I.move {mvOp=sMvOp, src=src, dst=tmp},
208 :     I.shift {shiftOp=shiftOp, src=tmp, dst=spillLoc,
209 :     count=count}]}
210 :     end
211 :     | I.CMOV {cond, src, dst} =>
212 :     (* note: dst must be a register *)
213 :     (case spillLoc
214 :     of I.Direct (_,r) =>
215 :     {proh=[], newReg=NONE,
216 :     code=[mark(I.CMOV{cond=cond,src=src,dst=r},an)]
217 :     }
218 :     | _ => let
219 :     val tmpR = newReg()
220 :     val tmp = I.Direct (sz, tmpR)
221 :     in
222 :     {proh=[tmpR], newReg=SOME tmpR,
223 :     code=[I.move{mvOp=I.MOVQ, src=spillLoc, dst=tmp},
224 :     mark(I.CMOV{cond=cond,src=src,dst=tmpR},an),
225 :     I.move{mvOp=I.MOVQ, src=tmp, dst=spillLoc}]}
226 :     end
227 :     (* end case *))
228 :     | I.CMPXCHG{lock,sz=isz,src,dst} =>
229 :     if immedOrReg src
230 :     then {proh=[], newReg=NONE,
231 :     code=[mark(I.CMPXCHG{lock=lock,sz=isz,src=src,
232 :     dst=spillLoc},an)]}
233 :     else let
234 :     val tmpR = newReg()
235 :     val tmp = I.Direct (sz, tmpR)
236 :     in
237 :     {proh=[], newReg=NONE,
238 :     code=[I.move{mvOp=I.MOVQ, src=src, dst=tmp},
239 :     mark(I.CMPXCHG{lock=lock,sz=isz,src=tmp,
240 :     dst=spillLoc},an)]}
241 :     end
242 :     | I.MULTDIV _ => error "spill: MULTDIV"
243 :     | I.MUL3 {src1, src2, dst} => let
244 :     val tmpR = newReg()
245 :     in
246 :     {proh=[tmpR], newReg=SOME tmpR,
247 :     code=[mark(I.MUL3{src1=src1, src2=src2, dst=tmpR}, an),
248 :     I.move{mvOp=I.MOVL, src=I.Direct (32,tmpR),
249 :     dst=spillLoc}]
250 :     }
251 :     end
252 :     | I.MULQ3 {src1, src2, dst} => let
253 :     val tmpR = newReg()
254 :     in
255 :     {proh=[tmpR], newReg=SOME tmpR,
256 :     code=[mark(I.MULQ3{src1=src1, src2=src2, dst=tmpR}, an),
257 :     I.move{mvOp=I.MOVQ, src=I.Direct (64,tmpR),
258 :     dst=spillLoc}]}
259 :     end
260 :     | I.UNARY{unOp, opnd} =>
261 :     done(I.UNARY{unOp=unOp, opnd=spillLoc}, an)
262 :     | I.SET{cond, opnd} =>
263 :     done(I.SET{cond=cond, opnd=spillLoc}, an)
264 :     | I.POP _ => done (I.POP spillLoc, an)
265 :     | _ => error "AMD64SpillInstr.spillR"
266 :     (* end case *))
267 :     end (* spill *)
268 :     fun f (i, ans) = (case i
269 :     of I.INSTR instr => spill (instr, ans)
270 :     | I.ANNOTATION {i, a} => f (i, a :: ans)
271 :     | I.KILL lk => {code=[annotate (I.KILL (rLiveKill (lk, r)), ans)],
272 :     proh=[], newReg=NONE}
273 :     | _ => error "AMD64SpillInstr.spillR"
274 :     (* end case *))
275 :     in
276 :     f (i, [])
277 :     end (* spillR *)
278 :    
279 :     fun spillF (i, r, spillLoc) = let
280 :     fun spill (instr, an) = let
281 :     val (sz, fmvOp) = fmvInstr instr
282 :     fun withTmp f = let
283 :     val tmpR = newFreg ()
284 :     val tmp = I.FDirect tmpR
285 :     in
286 :     {code=[mark (f tmpR, an),
287 :     I.fmove {fmvOp=fmvOp, src=tmp, dst=spillLoc}],
288 :     proh=[tmpR], newReg=SOME tmpR}
289 :     end (* withTmp *)
290 :     fun inTmpR (I.FDirect r) = (r, [])
291 :     | inTmpR opnd = let
292 :     val tmp = newFreg ()
293 :     in
294 :     (tmp, [I.FMOVE {fmvOp=fmvOp, src=opnd, dst=I.FDirect tmp}])
295 :     end
296 :     in
297 :     (case instr
298 :     of I.FMOVE {fmvOp, src=src as I.FDirect r', dst} =>
299 :     if CB.sameColor (r, r')
300 :     then {code=[], proh=[], newReg=NONE}
301 :     else {code=[mark (I.FMOVE {fmvOp=fmvOp, src=src,
302 :     dst=spillLoc}, an)],
303 :     proh=[], newReg=NONE}
304 :     | I.FMOVE {fmvOp, src, dst as I.FDirect _} => withTmp (fn tmpR =>
305 :     I.FMOVE {fmvOp=fmvOp, src=src, dst=I.FDirect tmpR})
306 :     | I.FBINOP {binOp, src, dst} => withTmp (fn tmpR =>
307 :     I.FBINOP {binOp=binOp, src=src, dst=tmpR})
308 :     | I.FCOM {comOp, dst, src} => withTmp (fn tmpR =>
309 :     I.FCOM {comOp=comOp, src=src, dst=tmpR})
310 :     | I.CALL {opnd, defs, uses, return, cutsTo, mem, pops} =>
311 :     {code=[mark (I.CALL {opnd=opnd, defs=C.rmvFreg (r, defs),
312 :     return=return, uses=uses,
313 :     cutsTo=cutsTo, mem=mem, pops=pops}, an)],
314 :     proh=[], newReg=NONE}
315 :     | I.CALLQ {opnd, defs, uses, return, cutsTo, mem, pops} =>
316 :     {code=[mark (I.CALLQ {opnd=opnd, defs=C.rmvFreg (r, defs),
317 :     return=return, uses=uses,
318 :     cutsTo=cutsTo, mem=mem, pops=pops}, an)],
319 :     proh=[], newReg=NONE}
320 :     | _ => error "spillF"
321 :     (* end case *))
322 :     end (* spill *)
323 :     fun f (i, ans) = (case i
324 :     of I.INSTR instr => spill (instr, ans)
325 :     | I.ANNOTATION {i, a} => f (i, a :: ans)
326 :     | I.KILL lk => {code=[annotate (I.KILL (fLiveKill (lk, r)), ans)],
327 :     proh=[], newReg=NONE}
328 :     | _ => error "spillF"
329 :     (* end case *))
330 :     in
331 :     f (i, [])
332 :     end (* spillF *)
333 :    
334 :     fun spill CB.GP = spillR
335 :     | spill CB.FP = spillF
336 :     | spill _ = error "spill"
337 :    
338 :     fun reloadR (i, r, spillLoc) = let
339 :     fun reload (instr, an) = let
340 :     val (sz, rMvOp) = mvInstr instr
341 :     fun done (instr, an) = {code=[mark (instr, an)], proh=[], newReg=NONE}
342 :     fun replace (opnd as I.Direct (_, r')) = if CB.sameColor (r, r')
343 :     then spillLoc
344 :     else opnd
345 :     | replace opnd = opnd
346 :     fun operand (opnd, tmp) = let
347 :     fun replaceR (r', f) = if CB.sameColor (r, r')
348 :     then f tmp
349 :     else opnd
350 :     in
351 :     (case opnd
352 :     of I.Direct (opndSz, opndR) => replaceR (opndR, fn r' =>
353 :     I.Direct (opndSz, r'))
354 :     | I.Displace {base, disp, mem} => replaceR (base, fn r' =>
355 :     I.Displace {base=r', disp=disp, mem=mem})
356 :     | I.Indexed {base=NONE, index, scale, disp, mem} =>
357 :     replaceR (index, fn index' =>
358 :     I.Indexed {base=NONE, index=index', scale=scale,
359 :     disp=disp, mem=mem})
360 :     | I.Indexed {base=SOME b, index, scale, disp, mem} =>
361 :     replaceR (b, fn b' =>
362 :     replaceR (index, fn index' =>
363 :     I.Indexed {base=SOME b', index=index', scale=scale,
364 :     disp=disp, mem=mem}))
365 :     | opnd => opnd
366 :     (* end case *))
367 :     end (* operand *)
368 :     fun operand' (I.Direct _, _) = spillLoc
369 :     | operand' (opnd, tmp) = operand (opnd, tmp)
370 :     (* assume that tmpR gets killed *)
371 :     fun withTmp' avail f = (case spillLoc
372 :     of I.Direct (_, tmpR) => if avail
373 :     then {code=[mark (f tmpR, an)], proh=[tmpR], newReg=SOME tmpR}
374 :     else {code=[mark (f tmpR, an)], proh=[], newReg=NONE}
375 :     | _ => let
376 :     val tmpR = newReg ()
377 :     in
378 :     {code=[I.move {mvOp=rMvOp, src=spillLoc,
379 :     dst=I.Direct (sz, tmpR)},
380 :     mark (f tmpR, an)],
381 :     proh=[tmpR], newReg=SOME tmpR}
382 :     end
383 :     (* end case *))
384 :     val withTmp = withTmp' false
385 :     val withTmpAvail = withTmp' true
386 :     fun reloadCmp (cmp, lsrc, rsrc, an) = let
387 :     fun reload () = withTmp (fn tmp =>
388 :     cmp {lsrc=operand (lsrc, tmp), rsrc=operand (rsrc, tmp)})
389 :     in
390 :     if immedOrReg lsrc andalso immedOrReg rsrc
391 :     then let
392 :     val rsrc' = replace rsrc
393 :     val lsrc' = replace lsrc
394 :     in
395 :     if isMemory rsrc' andalso isMemory lsrc'
396 :     then reload ()
397 :     else done (cmp {lsrc=lsrc', rsrc=rsrc'}, an)
398 :     end
399 :     else reload ()
400 :     end (* reloadCmp *)
401 :     fun reloadTest (test, lsrc, rsrc, an) = let
402 :     fun reload () = withTmp (fn tmp =>
403 :     test {lsrc=operand (lsrc, tmp), rsrc=operand (rsrc, tmp)})
404 :     in
405 :     if immedOrReg lsrc andalso immedOrReg rsrc
406 :     then let
407 :     val rsrc' = replace rsrc
408 :     val lsrc' = replace lsrc
409 :     in
410 :     if isMemory rsrc'
411 :     then if isMemory lsrc'
412 :     then reload ()
413 :     else done (test {lsrc=rsrc', rsrc=lsrc'}, an)
414 :     else done (test {lsrc=lsrc', rsrc=rsrc'}, an)
415 :     end
416 :     else reload ()
417 :     end (* reloadTest *)
418 :     fun reloadBT (bitOp, lsrc, rsrc, an) =
419 :     reloadCmp (fn {lsrc,rsrc} =>
420 :     I.BITOP {bitOp=bitOp,lsrc=lsrc,rsrc=rsrc}, lsrc, rsrc, an)
421 :     fun reloadPush(push, arg as I.Direct _, an) =
422 :     done(push(replace arg), an)
423 :     | reloadPush(push, arg, an) =
424 :     withTmpAvail(fn tmpR => push (operand(arg, tmpR)))
425 :     in
426 :     (case instr
427 :     of I.JMP (opnd, labs) => withTmp (fn tmp =>
428 :     I.JMP (operand' (opnd, tmp), labs))
429 :     | I.JCC {opnd, cond} => withTmp (fn tmp =>
430 :     I.JCC {opnd=operand' (opnd, tmp), cond=cond})
431 :     | I.CALL {opnd, defs, uses, return, cutsTo, mem, pops} =>
432 :     withTmp (fn tmp =>
433 :     I.CALL {opnd=operand (opnd, tmp), defs=defs,
434 :     uses=C.rmvReg (r, uses), return=return, pops=pops,
435 :     cutsTo=cutsTo, mem=mem})
436 :     | I.MOVE {mvOp, src as I.Direct _, dst as I.Direct _} =>
437 :     done (I.MOVE {mvOp=mvOp, src=replace src, dst=dst}, an)
438 :     | I.MOVE {mvOp, src, dst as I.Direct _} => withTmpAvail (fn tmp =>
439 :     I.MOVE {mvOp=mvOp, src=operand (src, tmp), dst=dst})
440 :     | I.MOVE {mvOp, src as I.Direct _, dst} =>
441 :     if (Props.eqOpn (dst, spillLoc))
442 :     then {code=[], proh=[], newReg=NONE}
443 :     else withTmpAvail (fn tmp =>
444 :     I.MOVE {mvOp=mvOp, src=operand (src, tmp),
445 :     dst=operand (dst, tmp)})
446 :     | I.MOVE {mvOp, src, dst} => withTmpAvail (fn tmp =>
447 :     I.MOVE {mvOp=mvOp, src=operand (src, tmp),
448 :     dst=operand (dst, tmp)})
449 :     | I.LEAL {r32, addr} => withTmpAvail (fn tmp =>
450 :     I.LEAL {r32=r32, addr=operand (addr, tmp)})
451 :     | I.LEAQ {r64, addr} => withTmpAvail (fn tmp =>
452 :     I.LEAQ {r64=r64, addr=operand (addr, tmp)})
453 :     | I.CMPQ {lsrc, rsrc} => reloadCmp (I.CMPQ, lsrc, rsrc, an)
454 :     | I.CMPL {lsrc, rsrc} => reloadCmp (I.CMPL, lsrc, rsrc, an)
455 :     | I.CMPW {lsrc, rsrc} => reloadCmp (I.CMPW, lsrc, rsrc, an)
456 :     | I.CMPB {lsrc, rsrc} => reloadCmp (I.CMPB, lsrc, rsrc, an)
457 :     | I.TESTQ {lsrc, rsrc} => reloadTest (I.TESTQ, lsrc, rsrc, an)
458 :     | I.TESTL {lsrc, rsrc} => reloadTest (I.TESTL, lsrc, rsrc, an)
459 :     | I.TESTW {lsrc, rsrc} => reloadTest (I.TESTW, lsrc, rsrc, an)
460 :     | I.TESTB {lsrc, rsrc} => reloadTest (I.TESTB, lsrc, rsrc, an)
461 :     | I.BITOP{bitOp,lsrc, rsrc} => reloadBT (bitOp, lsrc, rsrc, an)
462 :     | I.BINARY{binOp, src, dst} => withTmp (fn tmp =>
463 :     I.BINARY{binOp=binOp, src=operand(src, tmp),
464 :     dst=operand(dst, tmp)})
465 :     | I.CMOV{cond, src, dst} =>
466 :     if CB.sameColor(dst,r)
467 :     then error "CMOV"
468 :     else done (I.CMOV{cond=cond, src=spillLoc, dst=dst}, an)
469 :     | I.CMOVQ{cond, src, dst} =>
470 :     if CB.sameColor(dst,r)
471 :     then error "CMOV"
472 :     else done (I.CMOVQ{cond=cond, src=spillLoc, dst=dst}, an)
473 :     | I.SHIFT {shiftOp, count as I.Direct _, src, dst} =>
474 :     withTmp (fn tmp =>
475 :     I.SHIFT {shiftOp=shiftOp, count=count,
476 :     src=operand (src, tmp),
477 :     dst=operand (dst, tmp)})
478 :     | I.CMPXCHG{lock,sz,src,dst} => withTmp(fn tmpR =>
479 :     I.CMPXCHG{lock=lock, sz=sz,
480 :     src=operand(src, tmpR),
481 :     dst=operand(dst, tmpR)})
482 :     | I.MULTDIV{multDivOp, src as I.Direct _} =>
483 :     done (I.MULTDIV{multDivOp=multDivOp, src=replace src}, an)
484 :     | I.MULTDIV{multDivOp, src} => withTmp(fn tmpR =>
485 :     I.MULTDIV{multDivOp=multDivOp, src=operand(src, tmpR)})
486 :     | I.MUL3{src1, src2, dst} => withTmp (fn tmpR =>
487 :     I.MUL3{src1=operand(src1, tmpR), src2=src2,
488 :     dst=if CB.sameColor(dst,r)
489 :     then error "reload:MUL3" else dst})
490 :     | I.MULQ3{src1, src2, dst} => withTmp (fn tmpR =>
491 :     I.MULQ3{src1=operand(src1, tmpR), src2=src2,
492 :     dst=if CB.sameColor(dst,r)
493 :     then error "reload:MULQ3" else dst})
494 :     | I.UNARY{unOp, opnd} => withTmpAvail (fn tmpR =>
495 :     I.UNARY{unOp=unOp, opnd=operand(opnd, tmpR)})
496 :     | I.SET{cond, opnd} => withTmpAvail (fn tmpR =>
497 :     I.SET{cond=cond, opnd=operand(opnd, tmpR)})
498 :     | I.PUSHQ arg => reloadPush (I.PUSHQ, arg, an)
499 :     | I.PUSHL arg => reloadPush (I.PUSHL, arg, an)
500 :     | I.PUSHW arg => reloadPush (I.PUSHW, arg, an)
501 :     | I.PUSHB arg => reloadPush (I.PUSHB, arg, an)
502 :     | I.FMOVE {fmvOp, src, dst} => withTmpAvail (fn tmp =>
503 :     I.FMOVE {fmvOp=fmvOp, src=operand (src, tmp),
504 :     dst=operand (dst, tmp)})
505 :     | I.FCOM {comOp, dst, src} => withTmpAvail (fn tmp =>
506 :     I.FCOM {comOp=comOp, dst=dst, src=operand (src, tmp)})
507 :     | _ => error "reloadR"
508 :     (* end case *))
509 :     end (* reload *)
510 :     fun f (i, ans) = (case i
511 :     of I.INSTR instr => reload (instr, ans)
512 :     | I.ANNOTATION {a, i} => f (i, a :: ans)
513 :     | I.LIVE lk => {code=[annotate (I.LIVE (rLiveKill (lk, r)), ans)],
514 :     proh=[], newReg=NONE}
515 :     | _ => error "reloadR"
516 :     (* end case *))
517 :     in
518 :     f (i, [])
519 :     end (* reloadR *)
520 :    
521 :     fun reloadF (i, r, spillLoc) = let
522 :     fun reload (instr, an) = let
523 :     fun replace (opnd as I.FDirect r') =
524 :     if CB.sameColor (r, r') then spillLoc else opnd
525 :     | replace opnd = opnd
526 :     val (sz, fmvOp) = fmvInstr instr
527 :     in
528 :     (case instr
529 :     of I.FMOVE {fmvOp, src, dst=dst as I.FDirect _} =>
530 :     {code=[mark (I.FMOVE {fmvOp=fmvOp, src=replace src, dst=dst},
531 :     an)],
532 :     proh=[], newReg=NONE}
533 :     | I.FMOVE {fmvOp, src, dst} => let
534 :     val tmpR = newFreg ()
535 :     val tmp = I.FDirect tmpR
536 :     in
537 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
538 :     mark (I.FMOVE {fmvOp=fmvOp, src=tmp, dst=dst}, an)],
539 :     proh=[tmpR], newReg=SOME tmpR}
540 :     end
541 :     | I.FBINOP {binOp, src, dst} => let
542 :     val tmpR = newFreg ()
543 :     val tmp = I.FDirect tmpR
544 :     in
545 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
546 :     mark (I.FBINOP {binOp=binOp, src=tmpR, dst=dst}, an)],
547 :     proh=[tmpR], newReg=SOME tmpR}
548 :     end
549 :     | I.FCOM {comOp, src, dst} => let
550 :     val tmpR = newFreg ()
551 :     val tmp = I.FDirect tmpR
552 :     in
553 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
554 :     mark (I.FCOM {comOp=comOp, src=tmp, dst=dst}, an)],
555 :     proh=[tmpR], newReg=SOME tmpR}
556 :     end
557 :     | I.CALL {opnd, defs, uses, return, cutsTo, mem, pops} =>
558 :     {code=[mark (I.CALL {opnd=opnd, defs=C.rmvReg (r, defs),
559 :     uses=uses, return=return, cutsTo=cutsTo,
560 :     mem=mem, pops=pops}, an)],
561 :     proh=[], newReg=NONE}
562 :     | I.CALLQ {opnd, defs, uses, return, cutsTo, mem, pops} =>
563 :     {code=[mark (I.CALLQ {opnd=opnd, defs=C.rmvReg (r, defs),
564 :     uses=uses, return=return, cutsTo=cutsTo,
565 :     mem=mem, pops=pops}, an)],
566 :     proh=[], newReg=NONE}
567 :     | _ => error "reloadF"
568 :     (* end case *))
569 :     end (* reload *)
570 :     fun f (i, ans) = (case i
571 :     of I.INSTR i => reload (i, ans)
572 :     | I.ANNOTATION {i, a} => f (i, a :: ans)
573 :     | I.LIVE lk =>
574 :     {code=[annotate (I.LIVE (fLiveKill (lk, r)), ans)],
575 :     proh=[], newReg=NONE}
576 :     | _ => error "reloadF.f"
577 :     (* end case *))
578 :     in
579 :     f (i, [])
580 :     end (* reloadF *)
581 :    
582 :     fun reload CB.GP = reloadR
583 :     | reload CB.FP = reloadF
584 :     | reload _ = error "reload"
585 :    
586 :     end (* AMD64SpillInstr *)

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