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 2805 - (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 : mrainey 2805 | I.XADD{lock,sz=isz,src as I.Direct (_, srcR),dst} =>
239 :     if CB.sameColor (r, srcR)
240 :     then raise Fail "cannot spill src for XADD"
241 : mrainey 2619 else let
242 : mrainey 2786 val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp ()
243 : mrainey 2805 in {proh=[tmpR],
244 :     newReg=SOME tmpR,
245 :     code=[mark (I.XADD{lock=lock,sz=isz,src=src,dst=spillLoc}, an)]}
246 : mrainey 2793 end
247 : mrainey 2805 | I.CMPXCHG{lock,sz=isz,src,dst} =>
248 :     if immedOrReg src then
249 :     {proh=[],
250 :     code=[mark(I.CMPXCHG{lock=lock,sz=isz,src=src,dst=spillLoc},an)],
251 :     newReg=NONE
252 :     }
253 :     else
254 :     let val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp()
255 :     in {proh=[tmpR],
256 :     code=[I.move{mvOp=I.MOVQ, src=src, dst=tmpOpnd64},
257 :     mark(I.CMPXCHG{lock=lock,sz=isz,src=tmpOpnd,dst=spillLoc},an)],
258 :     newReg=SOME tmpR
259 :     }
260 :     end
261 : mrainey 2619 | I.MULTDIV _ => error "spill: MULTDIV"
262 :     | I.MUL3 {src1, src2, dst} => let
263 :     val tmpR = newReg()
264 :     in
265 :     {proh=[tmpR], newReg=SOME tmpR,
266 :     code=[mark(I.MUL3{src1=src1, src2=src2, dst=tmpR}, an),
267 :     I.move{mvOp=I.MOVL, src=I.Direct (32,tmpR),
268 :     dst=spillLoc}]
269 :     }
270 :     end
271 :     | I.MULQ3 {src1, src2, dst} => let
272 :     val tmpR = newReg()
273 :     in
274 :     {proh=[tmpR], newReg=SOME tmpR,
275 :     code=[mark(I.MULQ3{src1=src1, src2=src2, dst=tmpR}, an),
276 :     I.move{mvOp=I.MOVQ, src=I.Direct (64,tmpR),
277 :     dst=spillLoc}]}
278 :     end
279 :     | I.UNARY{unOp, opnd} =>
280 :     done(I.UNARY{unOp=unOp, opnd=spillLoc}, an)
281 :     | I.SET{cond, opnd} =>
282 :     done(I.SET{cond=cond, opnd=spillLoc}, an)
283 :     | I.POP _ => done (I.POP spillLoc, an)
284 :     | _ => error "AMD64SpillInstr.spillR"
285 :     (* end case *))
286 :     end (* spill *)
287 :     fun f (i, ans) = (case i
288 :     of I.INSTR instr => spill (instr, ans)
289 :     | I.ANNOTATION {i, a} => f (i, a :: ans)
290 :     | I.KILL lk => {code=[annotate (I.KILL (rLiveKill (lk, r)), ans)],
291 :     proh=[], newReg=NONE}
292 :     | _ => error "AMD64SpillInstr.spillR"
293 :     (* end case *))
294 :     in
295 :     f (i, [])
296 :     end (* spillR *)
297 :    
298 :     fun spillF (i, r, spillLoc) = let
299 :     fun spill (instr, an) = let
300 :     val (sz, fmvOp) = fmvInstr instr
301 :     fun withTmp f = let
302 :     val tmpR = newFreg ()
303 :     val tmp = I.FDirect tmpR
304 :     in
305 :     {code=[mark (f tmpR, an),
306 :     I.fmove {fmvOp=fmvOp, src=tmp, dst=spillLoc}],
307 :     proh=[tmpR], newReg=SOME tmpR}
308 :     end (* withTmp *)
309 :     fun inTmpR (I.FDirect r) = (r, [])
310 :     | inTmpR opnd = let
311 :     val tmp = newFreg ()
312 :     in
313 :     (tmp, [I.FMOVE {fmvOp=fmvOp, src=opnd, dst=I.FDirect tmp}])
314 :     end
315 :     in
316 :     (case instr
317 :     of I.FMOVE {fmvOp, src=src as I.FDirect r', dst} =>
318 :     if CB.sameColor (r, r')
319 :     then {code=[], proh=[], newReg=NONE}
320 :     else {code=[mark (I.FMOVE {fmvOp=fmvOp, src=src,
321 :     dst=spillLoc}, an)],
322 :     proh=[], newReg=NONE}
323 :     | I.FMOVE {fmvOp, src, dst as I.FDirect _} => withTmp (fn tmpR =>
324 :     I.FMOVE {fmvOp=fmvOp, src=src, dst=I.FDirect tmpR})
325 :     | I.FBINOP {binOp, src, dst} => withTmp (fn tmpR =>
326 :     I.FBINOP {binOp=binOp, src=src, dst=tmpR})
327 :     | I.FCOM {comOp, dst, src} => withTmp (fn tmpR =>
328 :     I.FCOM {comOp=comOp, src=src, dst=tmpR})
329 : mrainey 2638 | I.FSQRTS {dst, src} => withTmp (fn tmpR =>
330 :     I.FSQRTS {src=src, dst=I.FDirect tmpR})
331 :     | I.FSQRTD {dst, src} => withTmp (fn tmpR =>
332 :     I.FSQRTD {src=src, dst=I.FDirect tmpR})
333 : mrainey 2619 | I.CALL {opnd, defs, uses, return, cutsTo, mem, pops} =>
334 :     {code=[mark (I.CALL {opnd=opnd, defs=C.rmvFreg (r, defs),
335 :     return=return, uses=uses,
336 :     cutsTo=cutsTo, mem=mem, pops=pops}, an)],
337 :     proh=[], newReg=NONE}
338 :     | I.CALLQ {opnd, defs, uses, return, cutsTo, mem, pops} =>
339 :     {code=[mark (I.CALLQ {opnd=opnd, defs=C.rmvFreg (r, defs),
340 :     return=return, uses=uses,
341 :     cutsTo=cutsTo, mem=mem, pops=pops}, an)],
342 :     proh=[], newReg=NONE}
343 :     | _ => error "spillF"
344 :     (* end case *))
345 :     end (* spill *)
346 :     fun f (i, ans) = (case i
347 :     of I.INSTR instr => spill (instr, ans)
348 :     | I.ANNOTATION {i, a} => f (i, a :: ans)
349 :     | I.KILL lk => {code=[annotate (I.KILL (fLiveKill (lk, r)), ans)],
350 :     proh=[], newReg=NONE}
351 :     | _ => error "spillF"
352 :     (* end case *))
353 :     in
354 :     f (i, [])
355 :     end (* spillF *)
356 :    
357 :     fun spill CB.GP = spillR
358 :     | spill CB.FP = spillF
359 :     | spill _ = error "spill"
360 :    
361 : mrainey 2786 (* reload a general purpose register r at instruction i from spillLoc*)
362 : mrainey 2619 fun reloadR (i, r, spillLoc) = let
363 :     fun reload (instr, an) = let
364 :     fun done (instr, an) = {code=[mark (instr, an)], proh=[], newReg=NONE}
365 :     fun replace (opnd as I.Direct (_, r')) = if CB.sameColor (r, r')
366 :     then spillLoc
367 :     else opnd
368 :     | replace opnd = opnd
369 :     fun operand (opnd, tmp) = let
370 :     fun replaceR (r', f) = if CB.sameColor (r, r')
371 :     then f tmp
372 :     else opnd
373 :     in
374 :     (case opnd
375 :     of I.Direct (opndSz, opndR) => replaceR (opndR, fn r' =>
376 :     I.Direct (opndSz, r'))
377 :     | I.Displace {base, disp, mem} => replaceR (base, fn r' =>
378 :     I.Displace {base=r', disp=disp, mem=mem})
379 :     | I.Indexed {base=NONE, index, scale, disp, mem} =>
380 :     replaceR (index, fn index' =>
381 :     I.Indexed {base=NONE, index=index', scale=scale,
382 :     disp=disp, mem=mem})
383 :     | I.Indexed {base=SOME b, index, scale, disp, mem} =>
384 : mrainey 2793 if CB.sameColor (b, r)
385 :     then operand (I.Indexed {base=SOME tmp, index=index, scale=scale, disp=disp, mem=mem}, tmp)
386 :     else if CB.sameColor (index, r)
387 :     then I.Indexed {base=SOME b, index=tmp, scale=scale, disp=disp, mem=mem}
388 :     else opnd
389 : mrainey 2619 | opnd => opnd
390 :     (* end case *))
391 :     end (* operand *)
392 :     fun operand' (I.Direct _, _) = spillLoc
393 :     | operand' (opnd, tmp) = operand (opnd, tmp)
394 :     (* assume that tmpR gets killed *)
395 :     fun withTmp' avail f = (case spillLoc
396 :     of I.Direct (_, tmpR) => if avail
397 :     then {code=[mark (f tmpR, an)], proh=[tmpR], newReg=SOME tmpR}
398 :     else {code=[mark (f tmpR, an)], proh=[], newReg=NONE}
399 :     | _ => let
400 :     val tmpR = newReg ()
401 :     in
402 : mrainey 2786 {code=[I.move {mvOp=I.MOVQ, src=spillLoc,
403 :     dst=I.Direct (64, tmpR)},
404 : mrainey 2619 mark (f tmpR, an)],
405 :     proh=[tmpR], newReg=SOME tmpR}
406 :     end
407 :     (* end case *))
408 :     val withTmp = withTmp' false
409 :     val withTmpAvail = withTmp' true
410 :     fun reloadCmp (cmp, lsrc, rsrc, an) = let
411 :     fun reload () = withTmp (fn tmp =>
412 :     cmp {lsrc=operand (lsrc, tmp), rsrc=operand (rsrc, tmp)})
413 :     in
414 :     if immedOrReg lsrc andalso immedOrReg rsrc
415 :     then let
416 :     val rsrc' = replace rsrc
417 :     val lsrc' = replace lsrc
418 :     in
419 :     if isMemory rsrc' andalso isMemory lsrc'
420 :     then reload ()
421 :     else done (cmp {lsrc=lsrc', rsrc=rsrc'}, an)
422 :     end
423 :     else reload ()
424 :     end (* reloadCmp *)
425 :     fun reloadTest (test, lsrc, rsrc, an) = let
426 :     fun reload () = withTmp (fn tmp =>
427 :     test {lsrc=operand (lsrc, tmp), rsrc=operand (rsrc, tmp)})
428 :     in
429 :     if immedOrReg lsrc andalso immedOrReg rsrc
430 :     then let
431 :     val rsrc' = replace rsrc
432 :     val lsrc' = replace lsrc
433 :     in
434 :     if isMemory rsrc'
435 :     then if isMemory lsrc'
436 :     then reload ()
437 :     else done (test {lsrc=rsrc', rsrc=lsrc'}, an)
438 :     else done (test {lsrc=lsrc', rsrc=rsrc'}, an)
439 :     end
440 :     else reload ()
441 :     end (* reloadTest *)
442 :     fun reloadBT (bitOp, lsrc, rsrc, an) =
443 :     reloadCmp (fn {lsrc,rsrc} =>
444 :     I.BITOP {bitOp=bitOp,lsrc=lsrc,rsrc=rsrc}, lsrc, rsrc, an)
445 :     fun reloadPush(push, arg as I.Direct _, an) =
446 :     done(push(replace arg), an)
447 :     | reloadPush(push, arg, an) =
448 :     withTmpAvail(fn tmpR => push (operand(arg, tmpR)))
449 :     in
450 :     (case instr
451 :     of I.JMP (opnd, labs) => withTmp (fn tmp =>
452 :     I.JMP (operand' (opnd, tmp), labs))
453 :     | I.JCC {opnd, cond} => withTmp (fn tmp =>
454 :     I.JCC {opnd=operand' (opnd, tmp), cond=cond})
455 :     | I.CALL {opnd, defs, uses, return, cutsTo, mem, pops} =>
456 :     withTmp (fn tmp =>
457 :     I.CALL {opnd=operand (opnd, tmp), defs=defs,
458 :     uses=C.rmvReg (r, uses), return=return, pops=pops,
459 :     cutsTo=cutsTo, mem=mem})
460 :     | I.MOVE {mvOp, src as I.Direct _, dst as I.Direct _} =>
461 :     done (I.MOVE {mvOp=mvOp, src=replace src, dst=dst}, an)
462 :     | I.MOVE {mvOp, src, dst as I.Direct _} => withTmpAvail (fn tmp =>
463 :     I.MOVE {mvOp=mvOp, src=operand (src, tmp), dst=dst})
464 :     | I.MOVE {mvOp, src as I.Direct _, dst} =>
465 :     if (Props.eqOpn (dst, spillLoc))
466 :     then {code=[], proh=[], newReg=NONE}
467 :     else withTmpAvail (fn tmp =>
468 :     I.MOVE {mvOp=mvOp, src=operand (src, tmp),
469 :     dst=operand (dst, tmp)})
470 :     | I.MOVE {mvOp, src, dst} => withTmpAvail (fn tmp =>
471 :     I.MOVE {mvOp=mvOp, src=operand (src, tmp),
472 :     dst=operand (dst, tmp)})
473 :     | I.LEAL {r32, addr} => withTmpAvail (fn tmp =>
474 :     I.LEAL {r32=r32, addr=operand (addr, tmp)})
475 :     | I.LEAQ {r64, addr} => withTmpAvail (fn tmp =>
476 :     I.LEAQ {r64=r64, addr=operand (addr, tmp)})
477 :     | I.CMPQ {lsrc, rsrc} => reloadCmp (I.CMPQ, lsrc, rsrc, an)
478 :     | I.CMPL {lsrc, rsrc} => reloadCmp (I.CMPL, lsrc, rsrc, an)
479 :     | I.CMPW {lsrc, rsrc} => reloadCmp (I.CMPW, lsrc, rsrc, an)
480 :     | I.CMPB {lsrc, rsrc} => reloadCmp (I.CMPB, lsrc, rsrc, an)
481 :     | I.TESTQ {lsrc, rsrc} => reloadTest (I.TESTQ, lsrc, rsrc, an)
482 :     | I.TESTL {lsrc, rsrc} => reloadTest (I.TESTL, lsrc, rsrc, an)
483 :     | I.TESTW {lsrc, rsrc} => reloadTest (I.TESTW, lsrc, rsrc, an)
484 :     | I.TESTB {lsrc, rsrc} => reloadTest (I.TESTB, lsrc, rsrc, an)
485 :     | I.BITOP{bitOp,lsrc, rsrc} => reloadBT (bitOp, lsrc, rsrc, an)
486 :     | I.BINARY{binOp, src, dst} => withTmp (fn tmp =>
487 :     I.BINARY{binOp=binOp, src=operand(src, tmp),
488 :     dst=operand(dst, tmp)})
489 :     | I.CMOV{cond, src, dst} =>
490 :     if CB.sameColor(dst,r)
491 :     then error "CMOV"
492 :     else done (I.CMOV{cond=cond, src=spillLoc, dst=dst}, an)
493 :     | I.SHIFT {shiftOp, count as I.Direct _, src, dst} =>
494 :     withTmp (fn tmp =>
495 :     I.SHIFT {shiftOp=shiftOp, count=count,
496 :     src=operand (src, tmp),
497 :     dst=operand (dst, tmp)})
498 :     | I.CMPXCHG{lock,sz,src,dst} => withTmp(fn tmpR =>
499 :     I.CMPXCHG{lock=lock, sz=sz,
500 :     src=operand(src, tmpR),
501 :     dst=operand(dst, tmpR)})
502 : mrainey 2805 | I.XADD{lock,sz,src,dst} => withTmp(fn tmpR =>
503 :     I.XADD {lock=lock,sz=sz,
504 :     src=operand(src, tmpR),
505 :     dst=operand(dst, tmpR)})
506 : mrainey 2619 | I.MULTDIV{multDivOp, src as I.Direct _} =>
507 :     done (I.MULTDIV{multDivOp=multDivOp, src=replace src}, an)
508 :     | I.MULTDIV{multDivOp, src} => withTmp(fn tmpR =>
509 :     I.MULTDIV{multDivOp=multDivOp, src=operand(src, tmpR)})
510 :     | I.MUL3{src1, src2, dst} => withTmp (fn tmpR =>
511 :     I.MUL3{src1=operand(src1, tmpR), src2=src2,
512 :     dst=if CB.sameColor(dst,r)
513 :     then error "reload:MUL3" else dst})
514 :     | I.MULQ3{src1, src2, dst} => withTmp (fn tmpR =>
515 :     I.MULQ3{src1=operand(src1, tmpR), src2=src2,
516 :     dst=if CB.sameColor(dst,r)
517 :     then error "reload:MULQ3" else dst})
518 :     | I.UNARY{unOp, opnd} => withTmpAvail (fn tmpR =>
519 :     I.UNARY{unOp=unOp, opnd=operand(opnd, tmpR)})
520 :     | I.SET{cond, opnd} => withTmpAvail (fn tmpR =>
521 :     I.SET{cond=cond, opnd=operand(opnd, tmpR)})
522 :     | I.PUSHQ arg => reloadPush (I.PUSHQ, arg, an)
523 :     | I.PUSHL arg => reloadPush (I.PUSHL, arg, an)
524 :     | I.PUSHW arg => reloadPush (I.PUSHW, arg, an)
525 :     | I.PUSHB arg => reloadPush (I.PUSHB, arg, an)
526 :     | I.FMOVE {fmvOp, src, dst} => withTmpAvail (fn tmp =>
527 :     I.FMOVE {fmvOp=fmvOp, src=operand (src, tmp),
528 :     dst=operand (dst, tmp)})
529 :     | I.FCOM {comOp, dst, src} => withTmpAvail (fn tmp =>
530 :     I.FCOM {comOp=comOp, dst=dst, src=operand (src, tmp)})
531 :     | _ => error "reloadR"
532 :     (* end case *))
533 :     end (* reload *)
534 :     fun f (i, ans) = (case i
535 :     of I.INSTR instr => reload (instr, ans)
536 :     | I.ANNOTATION {a, i} => f (i, a :: ans)
537 :     | I.LIVE lk => {code=[annotate (I.LIVE (rLiveKill (lk, r)), ans)],
538 :     proh=[], newReg=NONE}
539 :     | _ => error "reloadR"
540 :     (* end case *))
541 :     in
542 :     f (i, [])
543 :     end (* reloadR *)
544 :    
545 :     fun reloadF (i, r, spillLoc) = let
546 :     fun reload (instr, an) = let
547 :     fun replace (opnd as I.FDirect r') =
548 :     if CB.sameColor (r, r') then spillLoc else opnd
549 :     | replace opnd = opnd
550 :     val (sz, fmvOp) = fmvInstr instr
551 :     in
552 :     (case instr
553 :     of I.FMOVE {fmvOp, src, dst=dst as I.FDirect _} =>
554 :     {code=[mark (I.FMOVE {fmvOp=fmvOp, src=replace src, dst=dst},
555 :     an)],
556 :     proh=[], newReg=NONE}
557 :     | I.FMOVE {fmvOp, src, dst} => let
558 :     val tmpR = newFreg ()
559 :     val tmp = I.FDirect tmpR
560 :     in
561 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
562 :     mark (I.FMOVE {fmvOp=fmvOp, src=tmp, dst=dst}, an)],
563 :     proh=[tmpR], newReg=SOME tmpR}
564 :     end
565 :     | I.FBINOP {binOp, src, dst} => let
566 :     val tmpR = newFreg ()
567 :     val tmp = I.FDirect tmpR
568 :     in
569 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
570 :     mark (I.FBINOP {binOp=binOp, src=tmpR, dst=dst}, an)],
571 :     proh=[tmpR], newReg=SOME tmpR}
572 :     end
573 :     | I.FCOM {comOp, src, dst} => let
574 :     val tmpR = newFreg ()
575 :     val tmp = I.FDirect tmpR
576 :     in
577 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
578 :     mark (I.FCOM {comOp=comOp, src=tmp, dst=dst}, an)],
579 :     proh=[tmpR], newReg=SOME tmpR}
580 :     end
581 : mrainey 2638 | I.FSQRTS {dst, src} => let
582 :     val tmpR = newFreg ()
583 :     val tmp = I.FDirect tmpR
584 :     in
585 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
586 :     mark (I.FSQRTS {src=tmp, dst=dst}, an)],
587 :     proh=[tmpR], newReg=SOME tmpR}
588 :     end
589 :     | I.FSQRTD {dst, src} => let
590 :     val tmpR = newFreg ()
591 :     val tmp = I.FDirect tmpR
592 :     in
593 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
594 :     mark (I.FSQRTD {src=tmp, dst=dst}, an)],
595 :     proh=[tmpR], newReg=SOME tmpR}
596 :     end
597 : mrainey 2619 | I.CALL {opnd, defs, uses, return, cutsTo, mem, pops} =>
598 :     {code=[mark (I.CALL {opnd=opnd, defs=C.rmvReg (r, defs),
599 :     uses=uses, return=return, cutsTo=cutsTo,
600 :     mem=mem, pops=pops}, an)],
601 :     proh=[], newReg=NONE}
602 :     | I.CALLQ {opnd, defs, uses, return, cutsTo, mem, pops} =>
603 :     {code=[mark (I.CALLQ {opnd=opnd, defs=C.rmvReg (r, defs),
604 :     uses=uses, return=return, cutsTo=cutsTo,
605 :     mem=mem, pops=pops}, an)],
606 :     proh=[], newReg=NONE}
607 :     | _ => error "reloadF"
608 :     (* end case *))
609 :     end (* reload *)
610 :     fun f (i, ans) = (case i
611 :     of I.INSTR i => reload (i, ans)
612 :     | I.ANNOTATION {i, a} => f (i, a :: ans)
613 :     | I.LIVE lk =>
614 :     {code=[annotate (I.LIVE (fLiveKill (lk, r)), ans)],
615 :     proh=[], newReg=NONE}
616 :     | _ => error "reloadF.f"
617 :     (* end case *))
618 :     in
619 :     f (i, [])
620 :     end (* reloadF *)
621 :    
622 :     fun reload CB.GP = reloadR
623 :     | reload CB.FP = reloadF
624 :     | reload _ = error "reload"
625 :    
626 : mrainey 2786 end (* AMD64SpillInstr *)

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