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 3586 - (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 : mrainey 2929
12 :     (* guaranteeing that floats are stored at 16-byte aligned addresses reduces the number of instructions *)
13 :     val floats16ByteAligned : bool
14 : mrainey 2619 ) : ARCH_SPILL_INSTR =
15 :     struct
16 :    
17 :     structure CB = CellsBasis
18 :     structure I = I
19 :     structure C = I.C
20 :    
21 :     fun error msg = MLRiscErrorMsg.impossible("AMD64Spill: "^ msg)
22 :    
23 :     fun liveKill(add, rmv) ({regs, spilled}, reg) =
24 :     {regs=rmv(reg, regs), spilled=add(reg, spilled)}
25 :     val fLiveKill = liveKill (C.addFreg, C.rmvFreg)
26 :     val rLiveKill = liveKill (C.addReg, C.rmvReg)
27 :    
28 :     val newReg = C.newReg
29 :     val newFreg = C.newFreg
30 :    
31 : mrainey 2786 fun annotate (instr,[]) = instr
32 :     | annotate (instr,a::an) = annotate(I.ANNOTATION{i=instr,a=a},an)
33 : mrainey 2619
34 : mrainey 2786 fun mark (instr, an) = annotate(I.INSTR instr, an)
35 : mrainey 2619
36 :     fun immed(I.Immed _) = true
37 : mrainey 2928 | immed(I.Immed64 _) = true
38 : mrainey 2619 | immed(I.ImmedLabel _) = true
39 :     | immed _ = false
40 :    
41 :     fun immedOrReg(I.Direct r) = true
42 :     | immedOrReg(I.Immed _) = true
43 : mrainey 2928 | immedOrReg(I.Immed64 _) = true
44 : mrainey 2619 | immedOrReg(I.ImmedLabel _) = true
45 :     | immedOrReg _ = false
46 :    
47 :     fun isMemory(I.Displace _) = true
48 :     | isMemory(I.Indexed _) = true
49 :     | isMemory(I.LabelEA _) = true
50 :     | isMemory _ = false
51 : mrainey 2786
52 :     fun mvInstr instr = let
53 : mrainey 2619 fun mvOp 8 = I.MOVB
54 :     | mvOp 16 = I.MOVW
55 :     | mvOp 32 = I.MOVL
56 :     | mvOp 64 = I.MOVQ
57 :     | mvOp _ = error "mvInstr"
58 :     val sz = Props.szOfInstr instr
59 :     in
60 : mrainey 2785 (sz, mvOp sz)
61 : mrainey 2619 end (* mvInstr *)
62 :    
63 :     fun fmvInstr instr = let
64 :     fun mvOp 32 = I.MOVSS
65 :     | mvOp 64 = I.MOVSD
66 :     | mvOp _ = error "fmvInstr"
67 :     val sz = Props.szOfFinstr instr
68 :     in
69 :     (sz, mvOp sz)
70 :     end (* fmvInstr *)
71 :    
72 :     fun spillToEA CB.GP (r, ea) = let
73 :     fun move () = {code=[I.move {mvOp=I.MOVQ, dst=ea, src=I.Direct (64, r)}],
74 :     proh=[], newReg=NONE}
75 :     in
76 :     (case ea
77 :     of ( I.Displace _ | I.Indexed _ ) => move ()
78 :     | _ => error "spillToEA"
79 :     (* end case *))
80 :     end
81 :     | spillToEA CB.FP _ = error "spillToEA: FP"
82 :     | spillToEA _ _ = error "spillToEA"
83 :    
84 :     fun reloadFromEA CB.GP (r, ea) = let
85 :     fun move () = {code=[I.move {mvOp=I.MOVQ, dst=I.Direct (64, r), src=ea}],
86 :     proh=[], newReg=NONE}
87 :     in
88 :     (case ea
89 :     of ( I.Displace _ | I.Indexed _ ) => move ()
90 :     | _ => error "reloadFromEA"
91 :     (* end case *))
92 :     end
93 :     | reloadFromEA CB.FP _ = error "reloadFromEA: FP"
94 :     | reloadFromEA _ _ = error "reloadFromEA"
95 :    
96 : mrainey 2786 (* spill a general purpose register r at instruction i to spillLoc *)
97 : mrainey 2619 fun spillR (i, r, spillLoc) = let
98 :     fun spill (instr, an) = let
99 :     fun done (instr, an) = {code=[mark (instr, an)], proh=[], newReg=NONE}
100 : mrainey 2786 val (defaultSz, defaultMov) = (64, I.MOVQ)
101 :     (* freshTmp generates a fresh temporary register, an operand with the
102 :     * instruction's operand size, and an operand with a 64-bit operand size. *)
103 :     fun freshTmp () = let
104 :     val tmpR = newReg ()
105 :     val sz = Props.szOfInstr instr
106 :     val tmpOpnd = I.Direct (sz, tmpR)
107 :     val tmpOpnd64 = I.Direct (64, tmpR)
108 :     in
109 :     (tmpR, tmpOpnd, tmpOpnd64)
110 :     end
111 : mrainey 2619 in
112 :     (case instr
113 :     of I.CALL {opnd=addr, defs, uses, return, cutsTo, mem, pops} =>
114 :     done (I.CALL {opnd=addr, defs=C.rmvReg (r, defs),
115 :     return=return, uses=uses,
116 :     cutsTo=cutsTo, mem=mem, pops=pops}, an)
117 : mrainey 2786 (* With sign or zero extended spills we use different operand sizes
118 :     * for copying to the tmp operand and for copying from the tmp operand. *)
119 : mrainey 2619 | I.MOVE {mvOp as (I.MOVZBQ|I.MOVSBQ|I.MOVZWQ|I.MOVSWQ|
120 :     I.MOVSLQ|I.MOVZBL|I.MOVSBL|I.MOVZWL|
121 :     I.MOVSWL), src, dst} => let
122 : mrainey 2786 val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp ()
123 : mrainey 2619 in
124 :     {proh=[tmpR], newReg=SOME tmpR,
125 : mrainey 2786 code=[mark (I.MOVE {mvOp=mvOp, src=src, dst=tmpOpnd}, an),
126 :     I.move {mvOp=defaultMov, src=tmpOpnd64, dst=spillLoc}]}
127 : mrainey 2619 end
128 : mrainey 2786 (* spill is unnecessary *)
129 : mrainey 2619 | I.MOVE {mvOp, src as I.Direct (_, rs), dst} =>
130 :     if CB.sameColor (rs, r) then {code=[], proh=[], newReg=NONE}
131 :     else done (I.MOVE {mvOp=mvOp, src=src, dst=spillLoc}, an)
132 :     | I.MOVE {mvOp, src, dst=I.Direct _} =>
133 :     if Props.eqOpn(src, spillLoc)
134 :     then {code=[], proh=[], newReg=NONE}
135 :     else if immed src then
136 :     done(I.MOVE{mvOp=mvOp, src=src, dst=spillLoc}, an)
137 :     else let
138 : mrainey 2786 val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp ()
139 : mrainey 2619 in
140 :     {proh=[tmpR],
141 :     newReg=SOME tmpR,
142 : mrainey 2786 code=[mark(I.MOVE {mvOp=mvOp, src=src, dst=tmpOpnd}, an),
143 :     I.move {mvOp=defaultMov, src=tmpOpnd64, dst=spillLoc}]}
144 : mrainey 2619 end
145 :     | I.LEAL {addr, r32} => let
146 :     val tmpR = newReg()
147 :     in
148 :     {proh=[tmpR], newReg=SOME tmpR,
149 :     code=[mark(I.LEAL {addr=addr, r32=tmpR}, an),
150 :     I.move{mvOp=I.MOVL, src=I.Direct (32, tmpR),
151 :     dst=spillLoc}]}
152 :     end
153 :     | I.LEAQ {addr, r64} => let
154 :     val tmpR = newReg()
155 :     in
156 :     {proh=[tmpR], newReg=SOME tmpR,
157 :     code=[mark(I.LEAQ{addr=addr, r64=tmpR}, an),
158 :     I.move{mvOp=I.MOVQ, src=I.Direct (64,tmpR),
159 :     dst=spillLoc}]}
160 :     end
161 : mrainey 2786 (* handle xorl and xorq with the special case when both operands are the
162 :     * same register *)
163 : mrainey 2619 | I.BINARY {binOp=I.XORL, src as I.Direct (_,rs),
164 :     dst=I.Direct (_,rd)} =>
165 :     if CB.sameColor (rs,rd)
166 :     then {proh=[], newReg=NONE,
167 :     code=[mark(I.MOVE{mvOp=I.MOVL, src=I.Immed 0,
168 :     dst=spillLoc}, an)]}
169 :     else
170 :     {proh=[], newReg=NONE,
171 :     code=[mark(I.BINARY{binOp=I.XORL, src=src,
172 :     dst=spillLoc}, an)]}
173 :     | I.BINARY{binOp=I.XORQ, src as I.Direct (_,rs),
174 :     dst=I.Direct (_,rd)} =>
175 :     if CB.sameColor(rs,rd)
176 :     then {proh=[], newReg=NONE,
177 :     code=[mark(I.MOVE{mvOp=I.MOVQ, src=I.Immed 0,
178 :     dst=spillLoc}, an)]}
179 :     else {proh=[], newReg=NONE,
180 :     code=[mark(I.BINARY{binOp=I.XORQ, src=src,
181 :     dst=spillLoc}, an)]}
182 :    
183 :     | I.BINARY {binOp, src, dst} => let
184 :     (* note: dst = r *)
185 :     fun multBinOp(I.MULQ|I.MULL|I.MULW|I.MULB|
186 :     I.IMULQ|I.IMULL|I.IMULW|I.IMULB) = true
187 :     | multBinOp _ = false
188 :     in
189 :     if multBinOp binOp
190 :     then let (* destination must remain a register *)
191 : mrainey 2786 val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp ()
192 : mrainey 2619 in
193 :     {proh=[tmpR], newReg=SOME tmpR,
194 : mrainey 2786 code=[I.move{mvOp=defaultMov, src=spillLoc, dst=tmpOpnd64},
195 :     I.binary{binOp=binOp, src=src, dst=tmpOpnd},
196 :     I.move{mvOp=defaultMov, src=tmpOpnd64, dst=spillLoc}]}
197 : mrainey 2619 end
198 :     else if immedOrReg src
199 :     then (* can replace the destination directly *)
200 :     done(I.BINARY{binOp=binOp, src=src, dst=spillLoc},
201 :     an)
202 :     else let (* a memory src and non multBinOp
203 :     * --- cannot have two memory operands
204 :     *)
205 : mrainey 2786 val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp ()
206 : mrainey 2619 in
207 :     { proh=[tmpR], newReg=NONE,
208 : mrainey 2786 code=[I.move{mvOp=defaultMov, src=src, dst=tmpOpnd64},
209 :     I.binary{binOp=binOp, src=tmpOpnd,
210 : mrainey 2619 dst=spillLoc}]}
211 :     end
212 :     end
213 :     | I.SHIFT {shiftOp, count=I.Direct (_, ecx), src, dst} =>
214 :     error "implement shift"
215 :     | I.SHIFT {shiftOp, count, src, dst} =>
216 :     if immedOrReg src
217 :     then done (I.SHIFT {shiftOp=shiftOp, src=src, dst=spillLoc,
218 :     count=count}, an)
219 :     else let
220 : mrainey 2786 val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp ()
221 : mrainey 2619 in
222 : mrainey 2952 {proh=[tmpR], newReg=SOME tmpR,
223 : mrainey 2786 code=[I.move {mvOp=defaultMov, src=src, dst=tmpOpnd64},
224 :     I.shift {shiftOp=shiftOp, src=tmpOpnd, dst=spillLoc,
225 : mrainey 2619 count=count}]}
226 :     end
227 :     | I.CMOV {cond, src, dst} =>
228 :     (* note: dst must be a register *)
229 :     (case spillLoc
230 :     of I.Direct (_,r) =>
231 :     {proh=[], newReg=NONE,
232 :     code=[mark(I.CMOV{cond=cond,src=src,dst=r},an)]
233 :     }
234 :     | _ => let
235 : mrainey 2786 val (tmpR, _, tmpOpnd64) = freshTmp ()
236 : mrainey 2619 in
237 :     {proh=[tmpR], newReg=SOME tmpR,
238 : mrainey 2786 code=[I.move{mvOp=I.MOVQ, src=spillLoc, dst=tmpOpnd64},
239 : mrainey 2619 mark(I.CMOV{cond=cond,src=src,dst=tmpR},an),
240 : mrainey 2786 I.move{mvOp=I.MOVQ, src=tmpOpnd64, dst=spillLoc}]}
241 : mrainey 2619 end
242 :     (* end case *))
243 : mrainey 2947 | I.XADD{lock,sz=isz,src as I.Direct (_, srcR),dst} =>
244 :     if CB.sameColor (srcR, r)
245 :     then let val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp()
246 :     in {proh=[tmpR],
247 :     code=[I.move{mvOp=I.MOVQ, src=src, dst=tmpOpnd64},
248 :     mark(I.XADD{lock=lock,sz=isz,src=tmpOpnd,dst=dst},an),
249 :     I.move{mvOp=I.MOVQ, src=tmpOpnd64, dst=spillLoc}
250 :     ],
251 :     newReg=SOME tmpR
252 :     }
253 :     end
254 : mrainey 2952 else let val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp()
255 :     in {proh=[tmpR],
256 :     code=[I.move{mvOp=I.MOVQ, src=dst, dst=tmpOpnd64},
257 :     mark(I.XADD{lock=lock,sz=isz,src=src,dst=tmpOpnd},an),
258 :     I.move{mvOp=I.MOVQ, src=tmpOpnd64, dst=spillLoc}
259 :     ],
260 :     newReg=SOME tmpR
261 :     }
262 :     end
263 : mrainey 2805 | I.CMPXCHG{lock,sz=isz,src,dst} =>
264 :     if immedOrReg src then
265 :     {proh=[],
266 :     code=[mark(I.CMPXCHG{lock=lock,sz=isz,src=src,dst=spillLoc},an)],
267 :     newReg=NONE
268 :     }
269 :     else
270 :     let val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp()
271 :     in {proh=[tmpR],
272 :     code=[I.move{mvOp=I.MOVQ, src=src, dst=tmpOpnd64},
273 :     mark(I.CMPXCHG{lock=lock,sz=isz,src=tmpOpnd,dst=spillLoc},an)],
274 :     newReg=SOME tmpR
275 :     }
276 :     end
277 : mrainey 2811 | I.XCHG{lock,sz=isz,src,dst} =>
278 :     if immedOrReg src then
279 :     {proh=[],
280 :     code=[mark(I.XCHG{lock=lock,sz=isz,src=src,dst=spillLoc},an)],
281 :     newReg=NONE
282 :     }
283 :     else
284 :     let val (tmpR, tmpOpnd, tmpOpnd64) = freshTmp()
285 :     in {proh=[tmpR],
286 :     code=[I.move{mvOp=I.MOVQ, src=src, dst=tmpOpnd64},
287 :     mark(I.XCHG{lock=lock,sz=isz,src=tmpOpnd,dst=spillLoc},an)],
288 :     newReg=SOME tmpR
289 :     }
290 :     end
291 : mrainey 3586 | I.RDTSC => error "spill: RDTSC"
292 :     | I.RDTSCP => error "spill: RDTSCP"
293 : mrainey 2619 | I.MULTDIV _ => error "spill: MULTDIV"
294 :     | I.MUL3 {src1, src2, dst} => let
295 :     val tmpR = newReg()
296 :     in
297 :     {proh=[tmpR], newReg=SOME tmpR,
298 :     code=[mark(I.MUL3{src1=src1, src2=src2, dst=tmpR}, an),
299 :     I.move{mvOp=I.MOVL, src=I.Direct (32,tmpR),
300 :     dst=spillLoc}]
301 :     }
302 :     end
303 :     | I.MULQ3 {src1, src2, dst} => let
304 :     val tmpR = newReg()
305 :     in
306 :     {proh=[tmpR], newReg=SOME tmpR,
307 :     code=[mark(I.MULQ3{src1=src1, src2=src2, dst=tmpR}, an),
308 :     I.move{mvOp=I.MOVQ, src=I.Direct (64,tmpR),
309 :     dst=spillLoc}]}
310 :     end
311 :     | I.UNARY{unOp, opnd} =>
312 :     done(I.UNARY{unOp=unOp, opnd=spillLoc}, an)
313 :     | I.SET{cond, opnd} =>
314 :     done(I.SET{cond=cond, opnd=spillLoc}, an)
315 :     | I.POP _ => done (I.POP spillLoc, an)
316 :     | _ => error "AMD64SpillInstr.spillR"
317 :     (* end case *))
318 :     end (* spill *)
319 :     fun f (i, ans) = (case i
320 :     of I.INSTR instr => spill (instr, ans)
321 :     | I.ANNOTATION {i, a} => f (i, a :: ans)
322 :     | I.KILL lk => {code=[annotate (I.KILL (rLiveKill (lk, r)), ans)],
323 :     proh=[], newReg=NONE}
324 :     | _ => error "AMD64SpillInstr.spillR"
325 :     (* end case *))
326 :     in
327 :     f (i, [])
328 :     end (* spillR *)
329 :    
330 :     fun spillF (i, r, spillLoc) = let
331 :     fun spill (instr, an) = let
332 :     val (sz, fmvOp) = fmvInstr instr
333 :     fun withTmp f = let
334 :     val tmpR = newFreg ()
335 :     val tmp = I.FDirect tmpR
336 :     in
337 :     {code=[mark (f tmpR, an),
338 :     I.fmove {fmvOp=fmvOp, src=tmp, dst=spillLoc}],
339 :     proh=[tmpR], newReg=SOME tmpR}
340 :     end (* withTmp *)
341 : mrainey 2814 fun binOpWithTmp f = let
342 :     val tmpR = newFreg ()
343 :     val tmp = I.FDirect tmpR
344 :     in
345 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
346 :     mark (f tmpR, an),
347 :     I.fmove {fmvOp=fmvOp, src=tmp, dst=spillLoc}],
348 :     proh=[tmpR], newReg=SOME tmpR}
349 :     end (* binOpWithTmp *)
350 : mrainey 2619 in
351 :     (case instr
352 :     of I.FMOVE {fmvOp, src=src as I.FDirect r', dst} =>
353 :     if CB.sameColor (r, r')
354 :     then {code=[], proh=[], newReg=NONE}
355 :     else {code=[mark (I.FMOVE {fmvOp=fmvOp, src=src,
356 :     dst=spillLoc}, an)],
357 :     proh=[], newReg=NONE}
358 :     | I.FMOVE {fmvOp, src, dst as I.FDirect _} => withTmp (fn tmpR =>
359 :     I.FMOVE {fmvOp=fmvOp, src=src, dst=I.FDirect tmpR})
360 : mrainey 2814 | I.FBINOP {binOp, src, dst} => binOpWithTmp (fn tmpR =>
361 :     I.FBINOP {binOp=binOp, src=src, dst=tmpR})
362 : mrainey 2638 | I.FSQRTS {dst, src} => withTmp (fn tmpR =>
363 :     I.FSQRTS {src=src, dst=I.FDirect tmpR})
364 :     | I.FSQRTD {dst, src} => withTmp (fn tmpR =>
365 :     I.FSQRTD {src=src, dst=I.FDirect tmpR})
366 : mrainey 2619 | I.CALL {opnd, defs, uses, return, cutsTo, mem, pops} =>
367 :     {code=[mark (I.CALL {opnd=opnd, defs=C.rmvFreg (r, defs),
368 :     return=return, uses=uses,
369 :     cutsTo=cutsTo, mem=mem, pops=pops}, an)],
370 :     proh=[], newReg=NONE}
371 :     | I.CALLQ {opnd, defs, uses, return, cutsTo, mem, pops} =>
372 :     {code=[mark (I.CALLQ {opnd=opnd, defs=C.rmvFreg (r, defs),
373 :     return=return, uses=uses,
374 :     cutsTo=cutsTo, mem=mem, pops=pops}, an)],
375 :     proh=[], newReg=NONE}
376 :     | _ => error "spillF"
377 :     (* end case *))
378 :     end (* spill *)
379 :     fun f (i, ans) = (case i
380 :     of I.INSTR instr => spill (instr, ans)
381 :     | I.ANNOTATION {i, a} => f (i, a :: ans)
382 :     | I.KILL lk => {code=[annotate (I.KILL (fLiveKill (lk, r)), ans)],
383 :     proh=[], newReg=NONE}
384 :     | _ => error "spillF"
385 :     (* end case *))
386 :     in
387 :     f (i, [])
388 :     end (* spillF *)
389 :    
390 :     fun spill CB.GP = spillR
391 :     | spill CB.FP = spillF
392 :     | spill _ = error "spill"
393 :    
394 : mrainey 3415 val comment : string -> Annotations.annotation = (#create MLRiscAnnotations.COMMENT)
395 :    
396 : mrainey 2927 (* reload a general purpose register r at instruction i from spillLoc *)
397 : mrainey 2619 fun reloadR (i, r, spillLoc) = let
398 :     fun reload (instr, an) = let
399 :     fun done (instr, an) = {code=[mark (instr, an)], proh=[], newReg=NONE}
400 : mrainey 3415 fun replace (opnd as I.Direct (sz, r')) = if CB.sameColor (r, r')
401 :     then (case spillLoc
402 :     of I.Direct (_, r) =>
403 :     (* I believe that this case occurrs when the mlrisc register allocator
404 :     * is doing something clever, as the spill location is clearly not a stack
405 :     * location. in any case, the size associated with the register r is bogus,
406 :     * which is why we use the size of the register being spilled. *)
407 :     I.Direct (sz, r)
408 :     | _ => spillLoc)
409 : mrainey 2619 else opnd
410 :     | replace opnd = opnd
411 :     fun operand (opnd, tmp) = let
412 :     fun replaceR (r', f) = if CB.sameColor (r, r')
413 :     then f tmp
414 :     else opnd
415 :     in
416 :     (case opnd
417 :     of I.Direct (opndSz, opndR) => replaceR (opndR, fn r' =>
418 :     I.Direct (opndSz, r'))
419 :     | I.Displace {base, disp, mem} => replaceR (base, fn r' =>
420 :     I.Displace {base=r', disp=disp, mem=mem})
421 :     | I.Indexed {base=NONE, index, scale, disp, mem} =>
422 :     replaceR (index, fn index' =>
423 :     I.Indexed {base=NONE, index=index', scale=scale,
424 :     disp=disp, mem=mem})
425 :     | I.Indexed {base=SOME b, index, scale, disp, mem} =>
426 : mrainey 2793 if CB.sameColor (b, r)
427 :     then operand (I.Indexed {base=SOME tmp, index=index, scale=scale, disp=disp, mem=mem}, tmp)
428 :     else if CB.sameColor (index, r)
429 :     then I.Indexed {base=SOME b, index=tmp, scale=scale, disp=disp, mem=mem}
430 :     else opnd
431 : mrainey 2619 | opnd => opnd
432 :     (* end case *))
433 :     end (* operand *)
434 :     fun operand' (I.Direct _, _) = spillLoc
435 :     | operand' (opnd, tmp) = operand (opnd, tmp)
436 :     (* assume that tmpR gets killed *)
437 :     fun withTmp' avail f = (case spillLoc
438 :     of I.Direct (_, tmpR) => if avail
439 :     then {code=[mark (f tmpR, an)], proh=[tmpR], newReg=SOME tmpR}
440 :     else {code=[mark (f tmpR, an)], proh=[], newReg=NONE}
441 :     | _ => let
442 :     val tmpR = newReg ()
443 :     in
444 : mrainey 2786 {code=[I.move {mvOp=I.MOVQ, src=spillLoc,
445 :     dst=I.Direct (64, tmpR)},
446 : mrainey 2619 mark (f tmpR, an)],
447 :     proh=[tmpR], newReg=SOME tmpR}
448 :     end
449 :     (* end case *))
450 :     val withTmp = withTmp' false
451 :     val withTmpAvail = withTmp' true
452 :     fun reloadCmp (cmp, lsrc, rsrc, an) = let
453 :     fun reload () = withTmp (fn tmp =>
454 :     cmp {lsrc=operand (lsrc, tmp), rsrc=operand (rsrc, tmp)})
455 :     in
456 :     if immedOrReg lsrc andalso immedOrReg rsrc
457 :     then let
458 :     val rsrc' = replace rsrc
459 :     val lsrc' = replace lsrc
460 :     in
461 :     if isMemory rsrc' andalso isMemory lsrc'
462 :     then reload ()
463 :     else done (cmp {lsrc=lsrc', rsrc=rsrc'}, an)
464 :     end
465 :     else reload ()
466 :     end (* reloadCmp *)
467 :     fun reloadTest (test, lsrc, rsrc, an) = let
468 :     fun reload () = withTmp (fn tmp =>
469 :     test {lsrc=operand (lsrc, tmp), rsrc=operand (rsrc, tmp)})
470 :     in
471 :     if immedOrReg lsrc andalso immedOrReg rsrc
472 :     then let
473 :     val rsrc' = replace rsrc
474 :     val lsrc' = replace lsrc
475 :     in
476 :     if isMemory rsrc'
477 :     then if isMemory lsrc'
478 :     then reload ()
479 :     else done (test {lsrc=rsrc', rsrc=lsrc'}, an)
480 :     else done (test {lsrc=lsrc', rsrc=rsrc'}, an)
481 :     end
482 :     else reload ()
483 :     end (* reloadTest *)
484 :     fun reloadBT (bitOp, lsrc, rsrc, an) =
485 :     reloadCmp (fn {lsrc,rsrc} =>
486 :     I.BITOP {bitOp=bitOp,lsrc=lsrc,rsrc=rsrc}, lsrc, rsrc, an)
487 :     fun reloadPush(push, arg as I.Direct _, an) =
488 :     done(push(replace arg), an)
489 :     | reloadPush(push, arg, an) =
490 :     withTmpAvail(fn tmpR => push (operand(arg, tmpR)))
491 :     in
492 :     (case instr
493 :     of I.JMP (opnd, labs) => withTmp (fn tmp =>
494 :     I.JMP (operand' (opnd, tmp), labs))
495 :     | I.JCC {opnd, cond} => withTmp (fn tmp =>
496 :     I.JCC {opnd=operand' (opnd, tmp), cond=cond})
497 :     | I.CALL {opnd, defs, uses, return, cutsTo, mem, pops} =>
498 :     withTmp (fn tmp =>
499 :     I.CALL {opnd=operand (opnd, tmp), defs=defs,
500 :     uses=C.rmvReg (r, uses), return=return, pops=pops,
501 :     cutsTo=cutsTo, mem=mem})
502 :     | I.MOVE {mvOp, src as I.Direct _, dst as I.Direct _} =>
503 :     done (I.MOVE {mvOp=mvOp, src=replace src, dst=dst}, an)
504 :     | I.MOVE {mvOp, src, dst as I.Direct _} => withTmpAvail (fn tmp =>
505 :     I.MOVE {mvOp=mvOp, src=operand (src, tmp), dst=dst})
506 :     | I.MOVE {mvOp, src as I.Direct _, dst} =>
507 :     if (Props.eqOpn (dst, spillLoc))
508 :     then {code=[], proh=[], newReg=NONE}
509 :     else withTmpAvail (fn tmp =>
510 :     I.MOVE {mvOp=mvOp, src=operand (src, tmp),
511 :     dst=operand (dst, tmp)})
512 :     | I.MOVE {mvOp, src, dst} => withTmpAvail (fn tmp =>
513 :     I.MOVE {mvOp=mvOp, src=operand (src, tmp),
514 :     dst=operand (dst, tmp)})
515 :     | I.LEAL {r32, addr} => withTmpAvail (fn tmp =>
516 :     I.LEAL {r32=r32, addr=operand (addr, tmp)})
517 :     | I.LEAQ {r64, addr} => withTmpAvail (fn tmp =>
518 :     I.LEAQ {r64=r64, addr=operand (addr, tmp)})
519 :     | I.CMPQ {lsrc, rsrc} => reloadCmp (I.CMPQ, lsrc, rsrc, an)
520 :     | I.CMPL {lsrc, rsrc} => reloadCmp (I.CMPL, lsrc, rsrc, an)
521 :     | I.CMPW {lsrc, rsrc} => reloadCmp (I.CMPW, lsrc, rsrc, an)
522 :     | I.CMPB {lsrc, rsrc} => reloadCmp (I.CMPB, lsrc, rsrc, an)
523 :     | I.TESTQ {lsrc, rsrc} => reloadTest (I.TESTQ, lsrc, rsrc, an)
524 :     | I.TESTL {lsrc, rsrc} => reloadTest (I.TESTL, lsrc, rsrc, an)
525 :     | I.TESTW {lsrc, rsrc} => reloadTest (I.TESTW, lsrc, rsrc, an)
526 :     | I.TESTB {lsrc, rsrc} => reloadTest (I.TESTB, lsrc, rsrc, an)
527 :     | I.BITOP{bitOp,lsrc, rsrc} => reloadBT (bitOp, lsrc, rsrc, an)
528 :     | I.BINARY{binOp, src, dst} => withTmp (fn tmp =>
529 :     I.BINARY{binOp=binOp, src=operand(src, tmp),
530 :     dst=operand(dst, tmp)})
531 :     | I.CMOV{cond, src, dst} =>
532 :     if CB.sameColor(dst,r)
533 :     then error "CMOV"
534 :     else done (I.CMOV{cond=cond, src=spillLoc, dst=dst}, an)
535 :     | I.SHIFT {shiftOp, count as I.Direct _, src, dst} =>
536 :     withTmp (fn tmp =>
537 :     I.SHIFT {shiftOp=shiftOp, count=count,
538 :     src=operand (src, tmp),
539 :     dst=operand (dst, tmp)})
540 :     | I.CMPXCHG{lock,sz,src,dst} => withTmp(fn tmpR =>
541 :     I.CMPXCHG{lock=lock, sz=sz,
542 :     src=operand(src, tmpR),
543 :     dst=operand(dst, tmpR)})
544 : mrainey 2811 | I.XCHG{lock,sz,src,dst} => withTmp(fn tmpR =>
545 :     I.XCHG{lock=lock, sz=sz,
546 :     src=operand(src, tmpR),
547 :     dst=operand(dst, tmpR)})
548 : mrainey 2947 | I.XADD{lock,sz,src,dst} => withTmp(fn tmpR =>
549 : mrainey 2805 I.XADD {lock=lock,sz=sz,
550 :     src=operand(src, tmpR),
551 :     dst=operand(dst, tmpR)})
552 : mrainey 2619 | I.MULTDIV{multDivOp, src as I.Direct _} =>
553 :     done (I.MULTDIV{multDivOp=multDivOp, src=replace src}, an)
554 :     | I.MULTDIV{multDivOp, src} => withTmp(fn tmpR =>
555 :     I.MULTDIV{multDivOp=multDivOp, src=operand(src, tmpR)})
556 :     | I.MUL3{src1, src2, dst} => withTmp (fn tmpR =>
557 :     I.MUL3{src1=operand(src1, tmpR), src2=src2,
558 :     dst=if CB.sameColor(dst,r)
559 :     then error "reload:MUL3" else dst})
560 :     | I.MULQ3{src1, src2, dst} => withTmp (fn tmpR =>
561 :     I.MULQ3{src1=operand(src1, tmpR), src2=src2,
562 :     dst=if CB.sameColor(dst,r)
563 :     then error "reload:MULQ3" else dst})
564 :     | I.UNARY{unOp, opnd} => withTmpAvail (fn tmpR =>
565 :     I.UNARY{unOp=unOp, opnd=operand(opnd, tmpR)})
566 :     | I.SET{cond, opnd} => withTmpAvail (fn tmpR =>
567 :     I.SET{cond=cond, opnd=operand(opnd, tmpR)})
568 :     | I.PUSHQ arg => reloadPush (I.PUSHQ, arg, an)
569 :     | I.PUSHL arg => reloadPush (I.PUSHL, arg, an)
570 :     | I.PUSHW arg => reloadPush (I.PUSHW, arg, an)
571 :     | I.PUSHB arg => reloadPush (I.PUSHB, arg, an)
572 :     | I.FMOVE {fmvOp, src, dst} => withTmpAvail (fn tmp =>
573 :     I.FMOVE {fmvOp=fmvOp, src=operand (src, tmp),
574 :     dst=operand (dst, tmp)})
575 :     | I.FCOM {comOp, dst, src} => withTmpAvail (fn tmp =>
576 :     I.FCOM {comOp=comOp, dst=dst, src=operand (src, tmp)})
577 : mrainey 2843 | I.FBINOP {binOp, dst, src} => withTmpAvail (fn tmp =>
578 :     I.FBINOP {binOp=binOp, dst=dst, src=operand (src, tmp)})
579 : mrainey 3586 | I.RDTSC => error "reload: RDTSC"
580 :     | I.RDTSCP => error "reload: RDTSCP"
581 : mrainey 2619 | _ => error "reloadR"
582 :     (* end case *))
583 :     end (* reload *)
584 :     fun f (i, ans) = (case i
585 :     of I.INSTR instr => reload (instr, ans)
586 :     | I.ANNOTATION {a, i} => f (i, a :: ans)
587 :     | I.LIVE lk => {code=[annotate (I.LIVE (rLiveKill (lk, r)), ans)],
588 :     proh=[], newReg=NONE}
589 :     | _ => error "reloadR"
590 :     (* end case *))
591 :     in
592 :     f (i, [])
593 :     end (* reloadR *)
594 :    
595 :     fun reloadF (i, r, spillLoc) = let
596 :     fun reload (instr, an) = let
597 :     fun replace (opnd as I.FDirect r') =
598 :     if CB.sameColor (r, r') then spillLoc else opnd
599 :     | replace opnd = opnd
600 :     val (sz, fmvOp) = fmvInstr instr
601 :     in
602 :     (case instr
603 :     of I.FMOVE {fmvOp, src, dst=dst as I.FDirect _} =>
604 :     {code=[mark (I.FMOVE {fmvOp=fmvOp, src=replace src, dst=dst},
605 :     an)],
606 :     proh=[], newReg=NONE}
607 :     | I.FMOVE {fmvOp, src, dst} => let
608 :     val tmpR = newFreg ()
609 :     val tmp = I.FDirect tmpR
610 :     in
611 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
612 :     mark (I.FMOVE {fmvOp=fmvOp, src=tmp, dst=dst}, an)],
613 :     proh=[tmpR], newReg=SOME tmpR}
614 :     end
615 : mrainey 2929 (* treat bitwise operators differently, as they require that their source operand is 16-byte aligned *)
616 : mrainey 2927 | I.FBINOP {binOp=binOp as (I.XORPS | I.XORPD | I.ANDPS | I.ANDPD | I.ORPS | I.ORPD), src, dst} => if CB.sameColor (r, dst)
617 :     then {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=I.FDirect dst},
618 :     mark (I.FBINOP {binOp=binOp, src=src, dst=dst}, an)],
619 :     proh=[], newReg=NONE}
620 : mrainey 2929 else if floats16ByteAligned
621 :     then let
622 :     val tmpR = newFreg ()
623 :     val tmp = I.FDirect tmpR
624 :     in
625 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
626 :     mark (I.FBINOP {binOp=binOp, src=tmp, dst=dst}, an)],
627 :     proh=[tmpR], newReg=SOME tmpR}
628 :     end
629 :     else {code=[mark (I.FBINOP {binOp=binOp, src=replace src, dst=dst}, an)], proh=[], newReg=NONE}
630 : mrainey 2843 | I.FBINOP {binOp, src, dst} => if CB.sameColor (r, dst)
631 :     then {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=I.FDirect dst},
632 :     mark (I.FBINOP {binOp=binOp, src=src, dst=dst}, an)],
633 :     proh=[], newReg=NONE}
634 :     else {code=[mark (I.FBINOP {binOp=binOp, src=replace src, dst=dst}, an)], proh=[], newReg=NONE}
635 : mrainey 2619 | I.FCOM {comOp, src, dst} => let
636 :     val tmpR = newFreg ()
637 :     val tmp = I.FDirect tmpR
638 : mrainey 2814 val (src, dst) = if CB.sameColor (dst, r)
639 :     then (src, tmpR)
640 :     else (tmp, dst)
641 : mrainey 2619 in
642 : mrainey 2814 {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
643 :     mark (I.FCOM {comOp=comOp, src=src, dst=dst}, an)],
644 :     proh=[tmpR], newReg=SOME tmpR}
645 :     end
646 : mrainey 2929 | I.FSQRTS {dst, src} => if floats16ByteAligned
647 :     then let
648 :     val tmpR = newFreg ()
649 :     val tmp = I.FDirect tmpR
650 :     in
651 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
652 :     mark (I.FSQRTS {src=tmp, dst=dst}, an)],
653 :     proh=[tmpR], newReg=SOME tmpR}
654 :     end
655 :     else {code=[mark (I.FSQRTS {src=spillLoc, dst=dst}, an)], proh=[], newReg=NONE}
656 :     | I.FSQRTD {dst, src} => if floats16ByteAligned
657 :     then let
658 :     val tmpR = newFreg ()
659 :     val tmp = I.FDirect tmpR
660 :     in
661 :     {code=[I.fmove {fmvOp=fmvOp, src=spillLoc, dst=tmp},
662 :     mark (I.FSQRTD {src=tmp, dst=dst}, an)],
663 :     proh=[tmpR], newReg=SOME tmpR}
664 :     end
665 :     else {code=[mark (I.FSQRTD {src=spillLoc, dst=dst}, an)], proh=[], newReg=NONE}
666 : mrainey 2619 | I.CALL {opnd, defs, uses, return, cutsTo, mem, pops} =>
667 :     {code=[mark (I.CALL {opnd=opnd, defs=C.rmvReg (r, defs),
668 :     uses=uses, return=return, cutsTo=cutsTo,
669 :     mem=mem, pops=pops}, an)],
670 :     proh=[], newReg=NONE}
671 :     | I.CALLQ {opnd, defs, uses, return, cutsTo, mem, pops} =>
672 :     {code=[mark (I.CALLQ {opnd=opnd, defs=C.rmvReg (r, defs),
673 :     uses=uses, return=return, cutsTo=cutsTo,
674 :     mem=mem, pops=pops}, an)],
675 :     proh=[], newReg=NONE}
676 :     | _ => error "reloadF"
677 :     (* end case *))
678 :     end (* reload *)
679 :     fun f (i, ans) = (case i
680 :     of I.INSTR i => reload (i, ans)
681 :     | I.ANNOTATION {i, a} => f (i, a :: ans)
682 :     | I.LIVE lk =>
683 :     {code=[annotate (I.LIVE (fLiveKill (lk, r)), ans)],
684 :     proh=[], newReg=NONE}
685 :     | _ => error "reloadF.f"
686 :     (* end case *))
687 :     in
688 :     f (i, [])
689 :     end (* reloadF *)
690 :    
691 :     fun reload CB.GP = reloadR
692 :     | reload CB.FP = reloadF
693 :     | reload _ = error "reload"
694 :    
695 : mrainey 2786 end (* AMD64SpillInstr *)

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