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 2786 - (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 : mrainey 2786 fun annotate (instr,[]) = instr
29 :     | annotate (instr,a::an) = annotate(I.ANNOTATION{i=instr,a=a},an)
30 : mrainey 2619
31 : mrainey 2786 fun mark (instr, an) = annotate(I.INSTR instr, an)
32 : mrainey 2619
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 : mrainey 2786
47 :     fun mvInstr instr = let
48 : mrainey 2619 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 : mrainey 2785 (sz, mvOp sz)
56 : mrainey 2619 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 : mrainey 2786 (* spill a general purpose register r at instruction i to spillLoc *)
92 : mrainey 2619 fun spillR (i, r, spillLoc) = let
93 :     fun spill (instr, an) = let
94 :     fun done (instr, an) = {code=[mark (instr, an)], proh=[], newReg=NONE}
95 : mrainey 2786 val (defaultSz, defaultMov) = (64, I.MOVQ)
96 :     (* freshTmp generates a fresh temporary register, an operand with the
97 :     * instruction's operand size, and an operand with a 64-bit operand size. *)
98 :     fun freshTmp () = let
99 :     val tmpR = newReg ()
100 :     val sz = Props.szOfInstr instr
101 :     val tmpOpnd = I.Direct (sz, tmpR)
102 :     val tmpOpnd64 = I.Direct (64, tmpR)
103 :     in
104 :     (tmpR, tmpOpnd, tmpOpnd64)
105 :     end
106 : mrainey 2619 in
107 :     (case instr
108 :     of I.CALL {opnd=addr, defs, uses, return, cutsTo, mem, pops} =>
109 :     done (I.CALL {opnd=addr, defs=C.rmvReg (r, defs),
110 :     return=return, uses=uses,
111 :     cutsTo=cutsTo, mem=mem, pops=pops}, an)
112 : mrainey 2786 (* With sign or zero extended spills we use different operand sizes
113 :     * for copying to the tmp operand and for copying from the tmp operand. *)
114 : mrainey 2619 | I.MOVE {mvOp as (I.MOVZBQ|I.MOVSBQ|I.MOVZWQ|I.MOVSWQ|
115 :     I.MOVSLQ|I.MOVZBL|I.MOVSBL|I.MOVZWL|
116 :     I.MOVSWL), src, dst} => let
117 : mrainey 2786 val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp ()
118 : mrainey 2619 in
119 :     {proh=[tmpR], newReg=SOME tmpR,
120 : mrainey 2786 code=[mark (I.MOVE {mvOp=mvOp, src=src, dst=tmpOpnd}, an),
121 :     I.move {mvOp=defaultMov, src=tmpOpnd64, dst=spillLoc}]}
122 : mrainey 2619 end
123 : mrainey 2786 (* spill is unnecessary *)
124 : mrainey 2619 | I.MOVE {mvOp, src as I.Direct (_, rs), dst} =>
125 :     if CB.sameColor (rs, r) then {code=[], proh=[], newReg=NONE}
126 :     else done (I.MOVE {mvOp=mvOp, src=src, dst=spillLoc}, an)
127 :     | I.MOVE {mvOp, src, dst=I.Direct _} =>
128 :     if Props.eqOpn(src, spillLoc)
129 :     then {code=[], proh=[], newReg=NONE}
130 :     else if immed src then
131 :     done(I.MOVE{mvOp=mvOp, src=src, dst=spillLoc}, an)
132 :     else let
133 : mrainey 2786 val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp ()
134 : mrainey 2619 in
135 :     {proh=[tmpR],
136 :     newReg=SOME tmpR,
137 : mrainey 2786 code=[mark(I.MOVE {mvOp=mvOp, src=src, dst=tmpOpnd}, an),
138 :     I.move {mvOp=defaultMov, src=tmpOpnd64, dst=spillLoc}]}
139 : mrainey 2619 end
140 :     | I.LEAL {addr, r32} => let
141 :     val tmpR = newReg()
142 :     in
143 :     {proh=[tmpR], newReg=SOME tmpR,
144 :     code=[mark(I.LEAL {addr=addr, r32=tmpR}, an),
145 :     I.move{mvOp=I.MOVL, src=I.Direct (32, tmpR),
146 :     dst=spillLoc}]}
147 :     end
148 :     | I.LEAQ {addr, r64} => let
149 :     val tmpR = newReg()
150 :     in
151 :     {proh=[tmpR], newReg=SOME tmpR,
152 :     code=[mark(I.LEAQ{addr=addr, r64=tmpR}, an),
153 :     I.move{mvOp=I.MOVQ, src=I.Direct (64,tmpR),
154 :     dst=spillLoc}]}
155 :     end
156 : mrainey 2786 (* handle xorl and xorq with the special case when both operands are the
157 :     * same register *)
158 : mrainey 2619 | I.BINARY {binOp=I.XORL, src as I.Direct (_,rs),
159 :     dst=I.Direct (_,rd)} =>
160 :     if CB.sameColor (rs,rd)
161 :     then {proh=[], newReg=NONE,
162 :     code=[mark(I.MOVE{mvOp=I.MOVL, src=I.Immed 0,
163 :     dst=spillLoc}, an)]}
164 :     else
165 :     {proh=[], newReg=NONE,
166 :     code=[mark(I.BINARY{binOp=I.XORL, src=src,
167 :     dst=spillLoc}, an)]}
168 :     | I.BINARY{binOp=I.XORQ, src as I.Direct (_,rs),
169 :     dst=I.Direct (_,rd)} =>
170 :     if CB.sameColor(rs,rd)
171 :     then {proh=[], newReg=NONE,
172 :     code=[mark(I.MOVE{mvOp=I.MOVQ, src=I.Immed 0,
173 :     dst=spillLoc}, an)]}
174 :     else {proh=[], newReg=NONE,
175 :     code=[mark(I.BINARY{binOp=I.XORQ, src=src,
176 :     dst=spillLoc}, an)]}
177 :    
178 :     | I.BINARY {binOp, src, dst} => let
179 :     (* note: dst = r *)
180 :     fun multBinOp(I.MULQ|I.MULL|I.MULW|I.MULB|
181 :     I.IMULQ|I.IMULL|I.IMULW|I.IMULB) = true
182 :     | multBinOp _ = false
183 :     in
184 :     if multBinOp binOp
185 :     then let (* destination must remain a register *)
186 : mrainey 2786 val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp ()
187 : mrainey 2619 in
188 :     {proh=[tmpR], newReg=SOME tmpR,
189 : mrainey 2786 code=[I.move{mvOp=defaultMov, src=spillLoc, dst=tmpOpnd64},
190 :     I.binary{binOp=binOp, src=src, dst=tmpOpnd},
191 :     I.move{mvOp=defaultMov, src=tmpOpnd64, dst=spillLoc}]}
192 : mrainey 2619 end
193 :     else if immedOrReg src
194 :     then (* can replace the destination directly *)
195 :     done(I.BINARY{binOp=binOp, src=src, dst=spillLoc},
196 :     an)
197 :     else let (* a memory src and non multBinOp
198 :     * --- cannot have two memory operands
199 :     *)
200 : mrainey 2786 val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp ()
201 : mrainey 2619 in
202 :     { proh=[tmpR], newReg=NONE,
203 : mrainey 2786 code=[I.move{mvOp=defaultMov, src=src, dst=tmpOpnd64},
204 :     I.binary{binOp=binOp, src=tmpOpnd,
205 : mrainey 2619 dst=spillLoc}]}
206 :     end
207 :     end
208 :     | I.SHIFT {shiftOp, count=I.Direct (_, ecx), src, dst} =>
209 :     error "implement shift"
210 :     | I.SHIFT {shiftOp, count, src, dst} =>
211 :     if immedOrReg src
212 :     then done (I.SHIFT {shiftOp=shiftOp, src=src, dst=spillLoc,
213 :     count=count}, an)
214 :     else let
215 : mrainey 2786 val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp ()
216 : mrainey 2619 in
217 :     {proh=[tmpR], newReg=NONE,
218 : mrainey 2786 code=[I.move {mvOp=defaultMov, src=src, dst=tmpOpnd64},
219 :     I.shift {shiftOp=shiftOp, src=tmpOpnd, dst=spillLoc,
220 : mrainey 2619 count=count}]}
221 :     end
222 :     | I.CMOV {cond, src, dst} =>
223 :     (* note: dst must be a register *)
224 :     (case spillLoc
225 :     of I.Direct (_,r) =>
226 :     {proh=[], newReg=NONE,
227 :     code=[mark(I.CMOV{cond=cond,src=src,dst=r},an)]
228 :     }
229 :     | _ => let
230 : mrainey 2786 val (tmpR, _, tmpOpnd64) = freshTmp ()
231 : mrainey 2619 in
232 :     {proh=[tmpR], newReg=SOME tmpR,
233 : mrainey 2786 code=[I.move{mvOp=I.MOVQ, src=spillLoc, dst=tmpOpnd64},
234 : mrainey 2619 mark(I.CMOV{cond=cond,src=src,dst=tmpR},an),
235 : mrainey 2786 I.move{mvOp=I.MOVQ, src=tmpOpnd64, dst=spillLoc}]}
236 : mrainey 2619 end
237 :     (* end case *))
238 :     | I.CMPXCHG{lock,sz=isz,src,dst} =>
239 :     if immedOrReg src
240 :     then {proh=[], newReg=NONE,
241 :     code=[mark(I.CMPXCHG{lock=lock,sz=isz,src=src,
242 :     dst=spillLoc},an)]}
243 :     else let
244 : mrainey 2786 val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp ()
245 : mrainey 2619 in
246 :     {proh=[], newReg=NONE,
247 : mrainey 2786 code=[I.move{mvOp=I.MOVQ, src=src, dst=tmpOpnd64},
248 :     mark(I.CMPXCHG{lock=lock,sz=isz,src=tmpOpnd,
249 :     dst=spillLoc},an)]}
250 : mrainey 2619 end
251 :     | I.MULTDIV _ => error "spill: MULTDIV"
252 :     | I.MUL3 {src1, src2, dst} => let
253 :     val tmpR = newReg()
254 :     in
255 :     {proh=[tmpR], newReg=SOME tmpR,
256 :     code=[mark(I.MUL3{src1=src1, src2=src2, dst=tmpR}, an),
257 :     I.move{mvOp=I.MOVL, src=I.Direct (32,tmpR),
258 :     dst=spillLoc}]
259 :     }
260 :     end
261 :     | I.MULQ3 {src1, src2, dst} => let
262 :     val tmpR = newReg()
263 :     in
264 :     {proh=[tmpR], newReg=SOME tmpR,
265 :     code=[mark(I.MULQ3{src1=src1, src2=src2, dst=tmpR}, an),
266 :     I.move{mvOp=I.MOVQ, src=I.Direct (64,tmpR),
267 :     dst=spillLoc}]}
268 :     end
269 :     | I.UNARY{unOp, opnd} =>
270 :     done(I.UNARY{unOp=unOp, opnd=spillLoc}, an)
271 :     | I.SET{cond, opnd} =>
272 :     done(I.SET{cond=cond, opnd=spillLoc}, an)
273 :     | I.POP _ => done (I.POP spillLoc, an)
274 :     | _ => error "AMD64SpillInstr.spillR"
275 :     (* end case *))
276 :     end (* spill *)
277 :     fun f (i, ans) = (case i
278 :     of I.INSTR instr => spill (instr, ans)
279 :     | I.ANNOTATION {i, a} => f (i, a :: ans)
280 :     | I.KILL lk => {code=[annotate (I.KILL (rLiveKill (lk, r)), ans)],
281 :     proh=[], newReg=NONE}
282 :     | _ => error "AMD64SpillInstr.spillR"
283 :     (* end case *))
284 :     in
285 :     f (i, [])
286 :     end (* spillR *)
287 :    
288 :     fun spillF (i, r, spillLoc) = let
289 :     fun spill (instr, an) = let
290 :     val (sz, fmvOp) = fmvInstr instr
291 :     fun withTmp f = let
292 :     val tmpR = newFreg ()
293 :     val tmp = I.FDirect tmpR
294 :     in
295 :     {code=[mark (f tmpR, an),
296 :     I.fmove {fmvOp=fmvOp, src=tmp, dst=spillLoc}],
297 :     proh=[tmpR], newReg=SOME tmpR}
298 :     end (* withTmp *)
299 :     fun inTmpR (I.FDirect r) = (r, [])
300 :     | inTmpR opnd = let
301 :     val tmp = newFreg ()
302 :     in
303 :     (tmp, [I.FMOVE {fmvOp=fmvOp, src=opnd, dst=I.FDirect tmp}])
304 :     end
305 :     in
306 :     (case instr
307 :     of I.FMOVE {fmvOp, src=src as I.FDirect r', dst} =>
308 :     if CB.sameColor (r, r')
309 :     then {code=[], proh=[], newReg=NONE}
310 :     else {code=[mark (I.FMOVE {fmvOp=fmvOp, src=src,
311 :     dst=spillLoc}, an)],
312 :     proh=[], newReg=NONE}
313 :     | I.FMOVE {fmvOp, src, dst as I.FDirect _} => withTmp (fn tmpR =>
314 :     I.FMOVE {fmvOp=fmvOp, src=src, dst=I.FDirect tmpR})
315 :     | I.FBINOP {binOp, src, dst} => withTmp (fn tmpR =>
316 :     I.FBINOP {binOp=binOp, src=src, dst=tmpR})
317 :     | I.FCOM {comOp, dst, src} => withTmp (fn tmpR =>
318 :     I.FCOM {comOp=comOp, src=src, dst=tmpR})
319 : mrainey 2638 | I.FSQRTS {dst, src} => withTmp (fn tmpR =>
320 :     I.FSQRTS {src=src, dst=I.FDirect tmpR})
321 :     | I.FSQRTD {dst, src} => withTmp (fn tmpR =>
322 :     I.FSQRTD {src=src, dst=I.FDirect tmpR})
323 : mrainey 2619 | I.CALL {opnd, defs, uses, return, cutsTo, mem, pops} =>
324 :     {code=[mark (I.CALL {opnd=opnd, defs=C.rmvFreg (r, defs),
325 :     return=return, uses=uses,
326 :     cutsTo=cutsTo, mem=mem, pops=pops}, an)],
327 :     proh=[], newReg=NONE}
328 :     | I.CALLQ {opnd, defs, uses, return, cutsTo, mem, pops} =>
329 :     {code=[mark (I.CALLQ {opnd=opnd, defs=C.rmvFreg (r, defs),
330 :     return=return, uses=uses,
331 :     cutsTo=cutsTo, mem=mem, pops=pops}, an)],
332 :     proh=[], newReg=NONE}
333 :     | _ => error "spillF"
334 :     (* end case *))
335 :     end (* spill *)
336 :     fun f (i, ans) = (case i
337 :     of I.INSTR instr => spill (instr, ans)
338 :     | I.ANNOTATION {i, a} => f (i, a :: ans)
339 :     | I.KILL lk => {code=[annotate (I.KILL (fLiveKill (lk, r)), ans)],
340 :     proh=[], newReg=NONE}
341 :     | _ => error "spillF"
342 :     (* end case *))
343 :     in
344 :     f (i, [])
345 :     end (* spillF *)
346 :    
347 :     fun spill CB.GP = spillR
348 :     | spill CB.FP = spillF
349 :     | spill _ = error "spill"
350 :    
351 : mrainey 2786 (* reload a general purpose register r at instruction i from spillLoc*)
352 : mrainey 2619 fun reloadR (i, r, spillLoc) = let
353 :     fun reload (instr, an) = let
354 :     fun done (instr, an) = {code=[mark (instr, an)], proh=[], newReg=NONE}
355 :     fun replace (opnd as I.Direct (_, r')) = if CB.sameColor (r, r')
356 :     then spillLoc
357 :     else opnd
358 :     | replace opnd = opnd
359 :     fun operand (opnd, tmp) = let
360 :     fun replaceR (r', f) = if CB.sameColor (r, r')
361 :     then f tmp
362 :     else opnd
363 :     in
364 :     (case opnd
365 :     of I.Direct (opndSz, opndR) => replaceR (opndR, fn r' =>
366 :     I.Direct (opndSz, r'))
367 :     | I.Displace {base, disp, mem} => replaceR (base, fn r' =>
368 :     I.Displace {base=r', disp=disp, mem=mem})
369 :     | I.Indexed {base=NONE, index, scale, disp, mem} =>
370 :     replaceR (index, fn index' =>
371 :     I.Indexed {base=NONE, index=index', scale=scale,
372 :     disp=disp, mem=mem})
373 :     | I.Indexed {base=SOME b, index, scale, disp, mem} =>
374 :     replaceR (b, fn b' =>
375 :     replaceR (index, fn index' =>
376 :     I.Indexed {base=SOME b', index=index', scale=scale,
377 :     disp=disp, mem=mem}))
378 :     | opnd => opnd
379 :     (* end case *))
380 :     end (* operand *)
381 :     fun operand' (I.Direct _, _) = spillLoc
382 :     | operand' (opnd, tmp) = operand (opnd, tmp)
383 :     (* assume that tmpR gets killed *)
384 :     fun withTmp' avail f = (case spillLoc
385 :     of I.Direct (_, tmpR) => if avail
386 :     then {code=[mark (f tmpR, an)], proh=[tmpR], newReg=SOME tmpR}
387 :     else {code=[mark (f tmpR, an)], proh=[], newReg=NONE}
388 :     | _ => let
389 :     val tmpR = newReg ()
390 :     in
391 : mrainey 2786 {code=[I.move {mvOp=I.MOVQ, src=spillLoc,
392 :     dst=I.Direct (64, tmpR)},
393 : mrainey 2619 mark (f tmpR, an)],
394 :     proh=[tmpR], newReg=SOME tmpR}
395 :     end
396 :     (* end case *))
397 :     val withTmp = withTmp' false
398 :     val withTmpAvail = withTmp' true
399 :     fun reloadCmp (cmp, lsrc, rsrc, an) = let
400 :     fun reload () = withTmp (fn tmp =>
401 :     cmp {lsrc=operand (lsrc, tmp), rsrc=operand (rsrc, tmp)})
402 :     in
403 :     if immedOrReg lsrc andalso immedOrReg rsrc
404 :     then let
405 :     val rsrc' = replace rsrc
406 :     val lsrc' = replace lsrc
407 :     in
408 :     if isMemory rsrc' andalso isMemory lsrc'
409 :     then reload ()
410 :     else done (cmp {lsrc=lsrc', rsrc=rsrc'}, an)
411 :     end
412 :     else reload ()
413 :     end (* reloadCmp *)
414 :     fun reloadTest (test, lsrc, rsrc, an) = let
415 :     fun reload () = withTmp (fn tmp =>
416 :     test {lsrc=operand (lsrc, tmp), rsrc=operand (rsrc, tmp)})
417 :     in
418 :     if immedOrReg lsrc andalso immedOrReg rsrc
419 :     then let
420 :     val rsrc' = replace rsrc
421 :     val lsrc' = replace lsrc
422 :     in
423 :     if isMemory rsrc'
424 :     then if isMemory lsrc'
425 :     then reload ()
426 :     else done (test {lsrc=rsrc', rsrc=lsrc'}, an)
427 :     else done (test {lsrc=lsrc', rsrc=rsrc'}, an)
428 :     end
429 :     else reload ()
430 :     end (* reloadTest *)
431 :     fun reloadBT (bitOp, lsrc, rsrc, an) =
432 :     reloadCmp (fn {lsrc,rsrc} =>
433 :     I.BITOP {bitOp=bitOp,lsrc=lsrc,rsrc=rsrc}, lsrc, rsrc, an)
434 :     fun reloadPush(push, arg as I.Direct _, an) =
435 :     done(push(replace arg), an)
436 :     | reloadPush(push, arg, an) =
437 :     withTmpAvail(fn tmpR => push (operand(arg, tmpR)))
438 :     in
439 :     (case instr
440 :     of I.JMP (opnd, labs) => withTmp (fn tmp =>
441 :     I.JMP (operand' (opnd, tmp), labs))
442 :     | I.JCC {opnd, cond} => withTmp (fn tmp =>
443 :     I.JCC {opnd=operand' (opnd, tmp), cond=cond})
444 :     | I.CALL {opnd, defs, uses, return, cutsTo, mem, pops} =>
445 :     withTmp (fn tmp =>
446 :     I.CALL {opnd=operand (opnd, tmp), defs=defs,
447 :     uses=C.rmvReg (r, uses), return=return, pops=pops,
448 :     cutsTo=cutsTo, mem=mem})
449 :     | I.MOVE {mvOp, src as I.Direct _, dst as I.Direct _} =>
450 :     done (I.MOVE {mvOp=mvOp, src=replace src, dst=dst}, an)
451 :     | I.MOVE {mvOp, src, dst as I.Direct _} => withTmpAvail (fn tmp =>
452 :     I.MOVE {mvOp=mvOp, src=operand (src, tmp), dst=dst})
453 :     | I.MOVE {mvOp, src as I.Direct _, dst} =>
454 :     if (Props.eqOpn (dst, spillLoc))
455 :     then {code=[], proh=[], newReg=NONE}
456 :     else withTmpAvail (fn tmp =>
457 :     I.MOVE {mvOp=mvOp, src=operand (src, tmp),
458 :     dst=operand (dst, tmp)})
459 :     | I.MOVE {mvOp, src, dst} => withTmpAvail (fn tmp =>
460 :     I.MOVE {mvOp=mvOp, src=operand (src, tmp),
461 :     dst=operand (dst, tmp)})
462 :     | I.LEAL {r32, addr} => withTmpAvail (fn tmp =>
463 :     I.LEAL {r32=r32, addr=operand (addr, tmp)})
464 :     | I.LEAQ {r64, addr} => withTmpAvail (fn tmp =>
465 :     I.LEAQ {r64=r64, addr=operand (addr, tmp)})
466 :     | I.CMPQ {lsrc, rsrc} => reloadCmp (I.CMPQ, lsrc, rsrc, an)
467 :     | I.CMPL {lsrc, rsrc} => reloadCmp (I.CMPL, lsrc, rsrc, an)
468 :     | I.CMPW {lsrc, rsrc} => reloadCmp (I.CMPW, lsrc, rsrc, an)
469 :     | I.CMPB {lsrc, rsrc} => reloadCmp (I.CMPB, lsrc, rsrc, an)
470 :     | I.TESTQ {lsrc, rsrc} => reloadTest (I.TESTQ, lsrc, rsrc, an)
471 :     | I.TESTL {lsrc, rsrc} => reloadTest (I.TESTL, lsrc, rsrc, an)
472 :     | I.TESTW {lsrc, rsrc} => reloadTest (I.TESTW, lsrc, rsrc, an)
473 :     | I.TESTB {lsrc, rsrc} => reloadTest (I.TESTB, lsrc, rsrc, an)
474 :     | I.BITOP{bitOp,lsrc, rsrc} => reloadBT (bitOp, lsrc, rsrc, an)
475 :     | I.BINARY{binOp, src, dst} => withTmp (fn tmp =>
476 :     I.BINARY{binOp=binOp, src=operand(src, tmp),
477 :     dst=operand(dst, tmp)})
478 :     | I.CMOV{cond, src, dst} =>
479 :     if CB.sameColor(dst,r)
480 :     then error "CMOV"
481 :     else done (I.CMOV{cond=cond, src=spillLoc, dst=dst}, an)
482 :     | I.SHIFT {shiftOp, count as I.Direct _, src, dst} =>
483 :     withTmp (fn tmp =>
484 :     I.SHIFT {shiftOp=shiftOp, count=count,
485 :     src=operand (src, tmp),
486 :     dst=operand (dst, tmp)})
487 :     | I.CMPXCHG{lock,sz,src,dst} => withTmp(fn tmpR =>
488 :     I.CMPXCHG{lock=lock, sz=sz,
489 :     src=operand(src, tmpR),
490 :     dst=operand(dst, tmpR)})
491 :     | I.MULTDIV{multDivOp, src as I.Direct _} =>
492 :     done (I.MULTDIV{multDivOp=multDivOp, src=replace src}, an)
493 :     | I.MULTDIV{multDivOp, src} => withTmp(fn tmpR =>
494 :     I.MULTDIV{multDivOp=multDivOp, src=operand(src, tmpR)})
495 :     | I.MUL3{src1, src2, dst} => withTmp (fn tmpR =>
496 :     I.MUL3{src1=operand(src1, tmpR), src2=src2,
497 :     dst=if CB.sameColor(dst,r)
498 :     then error "reload:MUL3" else dst})
499 :     | I.MULQ3{src1, src2, dst} => withTmp (fn tmpR =>
500 :     I.MULQ3{src1=operand(src1, tmpR), src2=src2,
501 :     dst=if CB.sameColor(dst,r)
502 :     then error "reload:MULQ3" else dst})
503 :     | I.UNARY{unOp, opnd} => withTmpAvail (fn tmpR =>
504 :     I.UNARY{unOp=unOp, opnd=operand(opnd, tmpR)})
505 :     | I.SET{cond, opnd} => withTmpAvail (fn tmpR =>
506 :     I.SET{cond=cond, opnd=operand(opnd, tmpR)})
507 :     | I.PUSHQ arg => reloadPush (I.PUSHQ, arg, an)
508 :     | I.PUSHL arg => reloadPush (I.PUSHL, arg, an)
509 :     | I.PUSHW arg => reloadPush (I.PUSHW, arg, an)
510 :     | I.PUSHB arg => reloadPush (I.PUSHB, arg, an)
511 :     | I.FMOVE {fmvOp, src, dst} => withTmpAvail (fn tmp =>
512 :     I.FMOVE {fmvOp=fmvOp, src=operand (src, tmp),
513 :     dst=operand (dst, tmp)})
514 :     | I.FCOM {comOp, dst, src} => withTmpAvail (fn tmp =>
515 :     I.FCOM {comOp=comOp, dst=dst, src=operand (src, tmp)})
516 :     | _ => error "reloadR"
517 :     (* end case *))
518 :     end (* reload *)
519 :     fun f (i, ans) = (case i
520 :     of I.INSTR instr => reload (instr, ans)
521 :     | I.ANNOTATION {a, i} => f (i, a :: ans)
522 :     | I.LIVE lk => {code=[annotate (I.LIVE (rLiveKill (lk, r)), ans)],
523 :     proh=[], newReg=NONE}
524 :     | _ => error "reloadR"
525 :     (* end case *))
526 :     in
527 :     f (i, [])
528 :     end (* reloadR *)
529 :    
530 :     fun reloadF (i, r, spillLoc) = let
531 :     fun reload (instr, an) = let
532 :     fun replace (opnd as I.FDirect r') =
533 :     if CB.sameColor (r, r') then spillLoc else opnd
534 :     | replace opnd = opnd
535 :     val (sz, fmvOp) = fmvInstr instr
536 :     in
537 :     (case instr
538 :     of I.FMOVE {fmvOp, src, dst=dst as I.FDirect _} =>
539 :     {code=[mark (I.FMOVE {fmvOp=fmvOp, src=replace src, dst=dst},
540 :     an)],
541 :     proh=[], newReg=NONE}
542 :     | I.FMOVE {fmvOp, src, dst} => let
543 :     val tmpR = newFreg ()
544 :     val tmp = I.FDirect tmpR
545 :     in
546 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
547 :     mark (I.FMOVE {fmvOp=fmvOp, src=tmp, dst=dst}, an)],
548 :     proh=[tmpR], newReg=SOME tmpR}
549 :     end
550 :     | I.FBINOP {binOp, src, dst} => let
551 :     val tmpR = newFreg ()
552 :     val tmp = I.FDirect tmpR
553 :     in
554 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
555 :     mark (I.FBINOP {binOp=binOp, src=tmpR, dst=dst}, an)],
556 :     proh=[tmpR], newReg=SOME tmpR}
557 :     end
558 :     | I.FCOM {comOp, src, dst} => let
559 :     val tmpR = newFreg ()
560 :     val tmp = I.FDirect tmpR
561 :     in
562 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
563 :     mark (I.FCOM {comOp=comOp, src=tmp, dst=dst}, an)],
564 :     proh=[tmpR], newReg=SOME tmpR}
565 :     end
566 : mrainey 2638 | I.FSQRTS {dst, src} => let
567 :     val tmpR = newFreg ()
568 :     val tmp = I.FDirect tmpR
569 :     in
570 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
571 :     mark (I.FSQRTS {src=tmp, dst=dst}, an)],
572 :     proh=[tmpR], newReg=SOME tmpR}
573 :     end
574 :     | I.FSQRTD {dst, src} => let
575 :     val tmpR = newFreg ()
576 :     val tmp = I.FDirect tmpR
577 :     in
578 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
579 :     mark (I.FSQRTD {src=tmp, dst=dst}, an)],
580 :     proh=[tmpR], newReg=SOME tmpR}
581 :     end
582 : mrainey 2619 | I.CALL {opnd, defs, uses, return, cutsTo, mem, pops} =>
583 :     {code=[mark (I.CALL {opnd=opnd, defs=C.rmvReg (r, defs),
584 :     uses=uses, return=return, cutsTo=cutsTo,
585 :     mem=mem, pops=pops}, an)],
586 :     proh=[], newReg=NONE}
587 :     | I.CALLQ {opnd, defs, uses, return, cutsTo, mem, pops} =>
588 :     {code=[mark (I.CALLQ {opnd=opnd, defs=C.rmvReg (r, defs),
589 :     uses=uses, return=return, cutsTo=cutsTo,
590 :     mem=mem, pops=pops}, an)],
591 :     proh=[], newReg=NONE}
592 :     | _ => error "reloadF"
593 :     (* end case *))
594 :     end (* reload *)
595 :     fun f (i, ans) = (case i
596 :     of I.INSTR i => reload (i, ans)
597 :     | I.ANNOTATION {i, a} => f (i, a :: ans)
598 :     | I.LIVE lk =>
599 :     {code=[annotate (I.LIVE (fLiveKill (lk, r)), ans)],
600 :     proh=[], newReg=NONE}
601 :     | _ => error "reloadF.f"
602 :     (* end case *))
603 :     in
604 :     f (i, [])
605 :     end (* reloadF *)
606 :    
607 :     fun reload CB.GP = reloadR
608 :     | reload CB.FP = reloadF
609 :     | reload _ = error "reload"
610 :    
611 : mrainey 2786 end (* AMD64SpillInstr *)

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