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 /sml/trunk/src/MLRISC/x86/ra/x86SpillInstr.sml
ViewVC logotype

Annotation of /sml/trunk/src/MLRISC/x86/ra/x86SpillInstr.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1156 - (view) (download)

1 : george 1033 (* X86Spill.sml
2 :     *
3 :     * X86 spilling is complicated business.
4 :     * Allen: and it just got more complicated; now we have to recognize the regmap.
5 :     * I've also improved the spilling code so that more instructions are
6 :     * recognized. Addressing modes are now folded into the existing instruction
7 :     * whenever possible. This eliminates some redundant temporaries which were
8 :     * introduced before.
9 :     *)
10 :     functor X86SpillInstr(structure Instr: X86INSTR
11 :     structure Props: INSN_PROPERTIES where I = Instr
12 :     ) : ARCH_SPILL_INSTR = struct
13 :    
14 :     structure I = Instr
15 :     structure C = I.C
16 :     structure CB = CellsBasis
17 :    
18 :     fun error msg = MLRiscErrorMsg.impossible("X86Spill: "^ msg)
19 :    
20 :     fun immed(I.Immed _) = true
21 :     | immed(I.ImmedLabel _) = true
22 :     | immed _ = false
23 :    
24 :     fun immedOrReg(I.Direct r) = true
25 :     | immedOrReg(I.Immed _) = true
26 :     | immedOrReg(I.ImmedLabel _) = true
27 :     | immedOrReg _ = false
28 :    
29 :     fun isMemory(I.MemReg _) = true
30 :     | isMemory(I.Displace _) = true
31 :     | isMemory(I.Indexed _) = true
32 :     | isMemory(I.LabelEA _) = true
33 :     | isMemory _ = false
34 :    
35 :     (* Annotate instruction *)
36 :     fun annotate(instr,[]) = instr
37 :     | annotate(instr,a::an) = annotate(I.ANNOTATION{i=instr,a=a},an)
38 :    
39 :     fun mark(instr, an) = annotate(I.INSTR instr, an)
40 :    
41 :     fun liveKill(add, rmv) ({regs, spilled}, reg) =
42 :     {regs=rmv(reg, regs), spilled=add(reg, spilled)}
43 :    
44 :     val fLiveKill = liveKill (C.addFreg, C.rmvFreg)
45 :     val rLiveKill = liveKill (C.addReg, C.rmvReg)
46 :    
47 :     val newReg = C.newReg
48 :    
49 :    
50 :     fun spillR(instr, reg, spillLoc) = let
51 :     fun x86Spill(instr, an) = let
52 :     fun done(instr, an) = {code=[mark(instr, an)], proh=[], newReg=NONE}
53 :     in
54 :     case instr of
55 :     I.CALL{opnd=addr, defs, uses, return, cutsTo, mem, pops} =>
56 :     done(I.CALL{opnd=addr, defs=C.rmvReg(reg,defs),
57 :     return=return, uses=uses,
58 :     cutsTo=cutsTo, mem=mem, pops=pops}, an)
59 :     | I.MOVE{mvOp as (I.MOVZBL|I.MOVSBL|I.MOVZWL|I.MOVSWL), src, dst} =>
60 :     let val tmpR = newReg() val tmp = I.Direct tmpR
61 :     in {proh=[tmpR], newReg=SOME tmpR,
62 :     code=[mark(I.MOVE{mvOp=mvOp, src=src, dst=tmp}, an),
63 :     I.move{mvOp=I.MOVL, src=tmp, dst=spillLoc}]
64 :     }
65 :     end
66 :     | I.MOVE{mvOp, src as I.Direct rs, dst} =>
67 :     if CB.sameColor(rs,reg) then {code=[], proh=[], newReg=NONE}
68 :     else done(I.MOVE{mvOp=mvOp, src=src, dst=spillLoc}, an)
69 :     | I.MOVE{mvOp, src, dst=I.Direct _} =>
70 :     if Props.eqOpn(src, spillLoc) then {code=[], proh=[], newReg=NONE}
71 :     else if immed src then
72 :     done(I.MOVE{mvOp=mvOp, src=src, dst=spillLoc}, an)
73 :     else
74 :     let val tmpR = newReg()
75 :     val tmp = I.Direct tmpR
76 :     in {proh=[tmpR],
77 :     newReg=SOME tmpR,
78 :     code=[mark(I.MOVE{mvOp=mvOp, src=src, dst=tmp}, an),
79 :     I.move{mvOp=mvOp, src=tmp, dst=spillLoc}]
80 :     }
81 :     end
82 :     | I.LEA{addr, r32} =>
83 :     let val tmpR = newReg()
84 :     in {proh=[tmpR],
85 :     newReg=SOME tmpR,
86 :     code=[mark(I.LEA{addr=addr, r32=tmpR}, an),
87 :     I.move{mvOp=I.MOVL, src=I.Direct tmpR, dst=spillLoc}]
88 :     }
89 :     end
90 :     | I.BINARY{binOp=I.XORL, src as I.Direct rs, dst=I.Direct rd} =>
91 :     if CB.sameColor(rs,rd) then
92 :     {proh=[],
93 :     code=[mark(I.MOVE{mvOp=I.MOVL, src=I.Immed 0, dst=spillLoc}, an)],
94 :     newReg=NONE
95 :     }
96 :     else
97 :     {proh=[],
98 :     code=[mark(I.BINARY{binOp=I.XORL, src=src, dst=spillLoc}, an)],
99 :     newReg=NONE
100 :     }
101 :     | I.BINARY{binOp, src, dst} => let (* note: dst = reg *)
102 :     fun multBinOp(I.MULL|I.MULW|I.MULB|I.IMULL|I.IMULW|I.IMULB) = true
103 :     | multBinOp _ = false
104 :     in
105 :     if multBinOp binOp then let
106 :     (* destination must remain a register *)
107 :     val tmpR = newReg()
108 :     val tmp = I.Direct tmpR
109 :     in
110 :     {proh=[tmpR],
111 :     code= [I.move{mvOp=I.MOVL, src=spillLoc, dst=tmp},
112 :     I.binary{binOp=binOp, src=src, dst=tmp},
113 :     I.move{mvOp=I.MOVL, src=tmp, dst=spillLoc}],
114 :     newReg=SOME tmpR
115 :     }
116 :     end
117 :     else if immedOrReg src then
118 :     (* can replace the destination directly *)
119 :     done(I.BINARY{binOp=binOp, src=src, dst=spillLoc}, an)
120 :     else let
121 :     (* a memory src and non multBinOp
122 :     * --- cannot have two memory operands
123 :     *)
124 :     val tmpR = newReg()
125 :     val tmp = I.Direct tmpR
126 :     in
127 :     { proh=[tmpR],
128 :     code=[I.move{mvOp=I.MOVL, src=src, dst=tmp},
129 :     I.binary{binOp=binOp, src=tmp, dst=spillLoc}],
130 :     newReg=NONE
131 :     }
132 :     end
133 :     end
134 : leunga 1156 | I.SHIFT{shiftOp, count, src, dst} => error "go and implement SHIFT"
135 :     | I.CMOV{cond, src, dst} =>
136 :     (* note: dst must be a register *)
137 :     (case spillLoc of
138 :     I.Direct r =>
139 :     {proh=[],
140 :     newReg=NONE,
141 :     code=[mark(I.CMOV{cond=cond,src=src,dst=r},an)]
142 :     }
143 :     | _ =>
144 :     let val tmpR = newReg()
145 :     val tmp = I.Direct tmpR
146 :     in {proh=[tmpR],
147 :     newReg=SOME tmpR,
148 :     code=[I.move{mvOp=I.MOVL, src=spillLoc, dst=tmp},
149 :     mark(I.CMOV{cond=cond,src=src,dst=tmpR},an),
150 :     I.move{mvOp=I.MOVL, src=tmp, dst=spillLoc}]
151 :     }
152 :     end
153 :     )
154 :    
155 : george 1033 | I.CMPXCHG{lock,sz,src,dst} =>
156 :     if immedOrReg src then
157 :     {proh=[],
158 :     code=[mark(I.CMPXCHG{lock=lock,sz=sz,src=src,dst=spillLoc},an)],
159 :     newReg=NONE
160 :     }
161 :     else
162 :     let val tmpR = newReg()
163 :     val tmp = I.Direct tmpR
164 :     in {proh=[],
165 :     code=[I.move{mvOp=I.MOVL, src=src, dst=tmp},
166 :     mark(I.CMPXCHG{lock=lock,sz=sz,src=tmp,dst=spillLoc},an)],
167 :     newReg=NONE
168 :     }
169 :     end
170 :     | I.MULTDIV _ => error "spill: MULTDIV"
171 :     | I.MUL3{src1, src2, dst} =>
172 :     let val tmpR = newReg()
173 :     in {proh=[tmpR], newReg=SOME tmpR,
174 :     code=[mark(I.MUL3{src1=src1, src2=src2, dst=tmpR}, an),
175 :     I.move{mvOp=I.MOVL, src=I.Direct tmpR, dst=spillLoc}]
176 :     }
177 :     end
178 :     | I.UNARY{unOp, opnd} => done(I.UNARY{unOp=unOp, opnd=spillLoc}, an)
179 :     | I.SET{cond, opnd} => done(I.SET{cond=cond, opnd=spillLoc}, an)
180 :     | I.POP _ => done(I.POP spillLoc, an)
181 :     | I.FNSTSW => error "spill: FNSTSW"
182 :     | _ => error "spill"
183 :     end (* x86Spill *)
184 :    
185 :     fun f(I.INSTR instr, an) = x86Spill(instr, an)
186 :     | f(I.ANNOTATION{a, i}, an) = f(i, a::an)
187 :     | f(I.KILL lk, an) =
188 :     {code=[annotate(I.KILL(rLiveKill (lk, reg)), an)],
189 :     proh=[],
190 :     newReg=NONE}
191 :     | f _ = error "spill:f"
192 :     in f(instr, [])
193 :     end
194 :    
195 :     fun reloadR(instr, reg, spillLoc) = let
196 :     fun x86Reload(instr, reg, spillLoc, an) = let
197 :     fun operand(rt, opnd) =
198 :     (case opnd
199 :     of I.Direct r => if CB.sameColor(r,reg) then I.Direct rt else opnd
200 :     | I.Displace{base, disp, mem} =>
201 :     if CB.sameColor(base,reg)
202 :     then I.Displace{base=rt, disp=disp, mem=mem}
203 :     else opnd
204 :     | I.Indexed{base=NONE, index, scale, disp, mem=mem} =>
205 :     if CB.sameColor(index,reg) then
206 :     I.Indexed{base=NONE, index=rt, scale=scale, disp=disp, mem=mem}
207 :     else opnd
208 :     | I.Indexed{base as SOME b, index, scale, disp, mem=mem} =>
209 :     if CB.sameColor(b,reg) then
210 :     operand(rt, I.Indexed{base=SOME rt, index=index,
211 :     scale=scale, disp=disp, mem=mem})
212 :     else if CB.sameColor(index,reg) then
213 :     I.Indexed{base=base, index=rt, scale=scale, disp=disp, mem=mem}
214 :     else opnd
215 :     | opnd => opnd
216 :     (*esac*))
217 :    
218 :     fun done(instr, an) = {code=[mark(instr, an)], proh=[], newReg=NONE}
219 :    
220 : leunga 1156 fun isReloading (I.Direct r) = CB.sameColor(r,reg)
221 :     | isReloading _ = false
222 :    
223 : george 1033 (* This version assumes that the value of tmpR is killed *)
224 :     fun withTmp(f, an) =
225 :     case spillLoc of
226 :     I.Direct tmpR =>
227 :     {newReg=NONE,
228 :     proh=[],
229 :     code=[mark(f tmpR, an)]
230 :     }
231 :     | _ =>
232 :     let val tmpR = newReg()
233 :     in {newReg=NONE,
234 :     proh=[tmpR],
235 :     code=[I.move{mvOp=I.MOVL, src=spillLoc, dst=I.Direct tmpR},
236 :     mark(f tmpR, an)
237 :     ]
238 :     }
239 :     end
240 :    
241 :     (* This version assumes that the value of tmpR is available afterwards *)
242 :     fun withTmpAvail(f, an) =
243 :     case spillLoc of
244 :     I.Direct tmpR =>
245 :     {newReg=SOME tmpR,
246 :     proh=[tmpR],
247 :     code=[mark(f tmpR, an)]
248 :     }
249 :     | _ =>
250 :     let val tmpR = newReg()
251 :     val tmp = I.Direct tmpR
252 :     in {newReg=SOME tmpR,
253 :     proh=[tmpR],
254 :     code=[I.move{mvOp=I.MOVL, src=spillLoc, dst=I.Direct tmpR},
255 :     mark(f tmpR, an)
256 :     ]
257 :     }
258 :     end
259 :    
260 :     fun replace(opn as I.Direct r) =
261 :     if CB.sameColor(r,reg) then spillLoc else opn
262 :     | replace opn = opn
263 :    
264 :     (* Fold in a memory operand if possible. Makes sure that both operands
265 :     * are not in memory. lsrc cannot be immediate.
266 :     *)
267 :     fun reloadCmp(cmp, lsrc, rsrc, an) =
268 :     let fun reloadIt() =
269 :     withTmp(fn tmpR =>
270 :     cmp{lsrc=operand(tmpR, lsrc), rsrc=operand(tmpR, rsrc)}, an)
271 :     in if immedOrReg lsrc andalso immedOrReg rsrc then
272 :     let val lsrc' = replace lsrc
273 :     val rsrc' = replace rsrc
274 :     in if isMemory lsrc' andalso isMemory rsrc' then
275 :     reloadIt()
276 :     else
277 :     done(cmp{lsrc=lsrc', rsrc=rsrc'}, an)
278 :     end
279 :     else reloadIt()
280 :     end
281 :    
282 :     fun reloadBT(bitOp, lsrc, rsrc, an) =
283 :     reloadCmp(fn {lsrc,rsrc} => I.BITOP{bitOp=bitOp,lsrc=lsrc,rsrc=rsrc},
284 :     lsrc, rsrc, an)
285 :    
286 :     (* Fold in a memory operand if possible. Makes sure that the right
287 :     * operand is not in memory and left operand is not an immediate.
288 :     * lsrc rsrc
289 :     * AL, imm8 opc1 A8
290 :     * EAX, imm32 opc1 A9
291 :     * r/m8, imm8 opc2 F6/0 ib
292 :     * r/m32, imm32 opc2 F7/0 id
293 :     * r/m32, r32 opc3 85/r
294 :     *)
295 :     fun reloadTest(test, lsrc, rsrc, an) =
296 :     let fun reloadIt() =
297 :     withTmp(fn tmpR =>
298 :     test{lsrc=operand(tmpR, lsrc), rsrc=operand(tmpR, rsrc)}, an)
299 :     in if immedOrReg lsrc andalso immedOrReg rsrc then
300 :     let val lsrc = replace lsrc
301 :     val rsrc = replace rsrc
302 :     in if isMemory rsrc then
303 :     if isMemory lsrc then reloadIt()
304 :     else (* it is commutative! *)
305 :     done(test{lsrc=rsrc, rsrc=lsrc}, an)
306 :     else
307 :     done(test{lsrc=lsrc, rsrc=rsrc}, an)
308 :     end
309 :     else reloadIt()
310 :     end
311 :    
312 :     fun reloadPush(push, arg as I.Direct _, an) =
313 :     done(push(replace arg), an)
314 :     | reloadPush(push, arg, an) =
315 :     withTmpAvail(fn tmpR => push(operand(tmpR, arg)), an)
316 :    
317 :     fun reloadReal(realOp, opnd, an) =
318 :     withTmpAvail(fn tmpR => realOp(operand(tmpR, opnd)), an)
319 :     in
320 :     case instr
321 :     of I.JMP(I.Direct _, labs) => done(I.JMP(spillLoc, labs), an)
322 :     | I.JMP(opnd, labs) => withTmp(fn t => I.JMP(operand(t, opnd), labs), an)
323 :     | I.JCC{opnd=I.Direct _, cond} => done(I.JCC{opnd=spillLoc, cond=cond}, an)
324 :     | I.JCC{opnd, cond} =>
325 :     withTmp(fn t => I.JCC{opnd=operand(t,opnd), cond=cond}, an)
326 :     | I.CALL{opnd, defs, uses, return, cutsTo, mem, pops} =>
327 :     withTmp(fn t =>
328 :     I.CALL{opnd=operand(t, opnd), defs=defs, return=return,pops=pops,
329 :     uses=C.rmvReg(reg, uses), cutsTo=cutsTo, mem=mem}, an)
330 :     | I.MOVE{mvOp, src as I.Direct _, dst as I.Direct _} =>
331 :     done(I.MOVE{mvOp=mvOp, src=replace src, dst=dst},an)
332 :     | I.MOVE{mvOp, src, dst as I.Direct _} =>
333 :     withTmpAvail(fn t =>I.MOVE{mvOp=mvOp, src=operand(t, src), dst=dst},an)
334 :     | I.MOVE{mvOp, src as I.Direct _, dst} =>
335 :     if Props.eqOpn(dst, spillLoc) then {code=[], proh=[], newReg=NONE}
336 :     else withTmpAvail (* dst is not the spill reg *)
337 :     (fn t =>
338 :     I.MOVE{mvOp=mvOp, src=operand(t, src), dst=operand(t, dst)}, an)
339 :     | I.MOVE{mvOp, src, dst} =>
340 :     withTmpAvail (* dst is not the spill reg *)
341 :     (fn t =>
342 :     I.MOVE{mvOp=mvOp, src=operand(t, src), dst=operand(t, dst)}, an)
343 :     | I.LEA{r32, addr} =>
344 :     withTmpAvail(fn tmpR => I.LEA{r32=r32, addr=operand(tmpR, addr)}, an)
345 :     | I.CMPL{lsrc, rsrc} => reloadCmp(I.CMPL, lsrc, rsrc, an)
346 :     | I.CMPW{lsrc, rsrc} => reloadCmp(I.CMPW, lsrc, rsrc, an)
347 :     | I.CMPB{lsrc, rsrc} => reloadCmp(I.CMPB, lsrc, rsrc, an)
348 :     | I.TESTL{lsrc, rsrc} => reloadTest(I.TESTL, lsrc, rsrc, an)
349 :     | I.TESTW{lsrc, rsrc} => reloadTest(I.TESTW, lsrc, rsrc, an)
350 :     | I.TESTB{lsrc, rsrc} => reloadTest(I.TESTB, lsrc, rsrc, an)
351 :     | I.BITOP{bitOp,lsrc, rsrc} => reloadBT(bitOp, lsrc, rsrc, an)
352 :     | I.BINARY{binOp, src, dst as I.Direct _} =>
353 :     (case src of
354 :     I.Direct _ =>
355 :     done(I.BINARY{binOp=binOp, src=replace src, dst=dst},an)
356 :     | _ => withTmp(fn tmpR =>
357 :     I.BINARY{binOp=binOp, src=operand(tmpR, src), dst=dst}, an)
358 :     )
359 :     | I.BINARY{binOp, src, dst} =>
360 :     withTmp(fn tmpR => I.BINARY{binOp=binOp, src=operand(tmpR, src),
361 :     dst=operand(tmpR, dst)}, an)
362 : leunga 1156 | I.CMOV{cond, src, dst} =>
363 :     if CB.sameColor(dst,reg) then
364 :     error "CMOV"
365 :     else
366 :     done(I.CMOV{cond=cond, src=spillLoc, dst=dst}, an)
367 :     | I.SHIFT{shiftOp, count, src, dst} => error "go and implement SHIFT"
368 : george 1033 | I.CMPXCHG{lock,sz,src,dst} =>
369 :     withTmp(fn tmpR => I.CMPXCHG{lock=lock, sz=sz,
370 :     src=operand(tmpR, src),
371 :     dst=operand(tmpR, dst)},an)
372 :     | I.MULTDIV{multDivOp, src as I.Direct _} =>
373 :     done(I.MULTDIV{multDivOp=multDivOp, src=replace src}, an)
374 :     | I.MULTDIV{multDivOp, src} =>
375 :     withTmp(fn tmpR =>
376 :     I.MULTDIV{multDivOp=multDivOp, src=operand(tmpR, src)}, an)
377 :     | I.MUL3{src1, src2, dst} =>
378 :     withTmp(fn tmpR =>
379 :     I.MUL3{src1=operand(tmpR, src1), src2=src2,
380 :     dst=if CB.sameColor(dst,reg)
381 :     then error "reload:MUL3" else dst}, an)
382 :     | I.UNARY{unOp, opnd} =>
383 :     withTmpAvail
384 :     (fn tmpR => I.UNARY{unOp=unOp, opnd=operand(tmpR, opnd)}, an)
385 :     | I.SET{cond, opnd} =>
386 :     withTmpAvail(fn tmpR => I.SET{cond=cond, opnd=operand(tmpR, opnd)}, an)
387 :     | I.PUSHL arg => reloadPush(I.PUSHL, arg, an)
388 :     | I.PUSHW arg => reloadPush(I.PUSHW, arg, an)
389 :     | I.PUSHB arg => reloadPush(I.PUSHB, arg, an)
390 :     | I.FILD opnd => reloadReal(I.FILD, opnd, an)
391 :     | I.FILDL opnd => reloadReal(I.FILDL, opnd, an)
392 :     | I.FILDLL opnd => reloadReal(I.FILDLL, opnd, an)
393 :     | I.FLDT opnd => reloadReal(I.FLDT, opnd, an)
394 :     | I.FLDL opnd => reloadReal(I.FLDL, opnd, an)
395 :     | I.FLDS opnd => reloadReal(I.FLDS, opnd, an)
396 :     | I.FSTPT opnd => reloadReal(I.FSTPT, opnd, an)
397 :     | I.FSTPL opnd => reloadReal(I.FSTPL, opnd, an)
398 :     | I.FSTPS opnd => reloadReal(I.FSTPS, opnd, an)
399 :     | I.FSTL opnd => reloadReal(I.FSTL, opnd, an)
400 :     | I.FSTS opnd => reloadReal(I.FSTS, opnd, an)
401 :     | I.FUCOM opnd => reloadReal(I.FUCOM, opnd, an)
402 :     | I.FUCOMP opnd => reloadReal(I.FUCOMP, opnd, an)
403 : leunga 1156 | I.FCOMI opnd => reloadReal(I.FCOMI, opnd, an)
404 :     | I.FCOMIP opnd => reloadReal(I.FCOMIP, opnd, an)
405 :     | I.FUCOMI opnd => reloadReal(I.FUCOMI, opnd, an)
406 :     | I.FUCOMIP opnd => reloadReal(I.FUCOMIP, opnd, an)
407 : george 1033 | I.FENV{fenvOp, opnd} => reloadReal(fn opnd =>
408 :     I.FENV{fenvOp=fenvOp,opnd=opnd}, opnd, an)
409 :     | I.FBINARY{binOp, src, dst} =>
410 :     withTmpAvail(fn tmpR =>
411 :     I.FBINARY{binOp=binOp, src=operand(tmpR, src), dst=dst}, an)
412 :     | I.FIBINARY{binOp, src} =>
413 :     withTmpAvail
414 :     (fn tmpR => I.FIBINARY{binOp=binOp, src=operand(tmpR, src)}, an)
415 :    
416 :     (* Pseudo fp instrctions *)
417 :     | I.FMOVE{fsize,src,dst} =>
418 :     withTmpAvail
419 :     (fn tmpR => I.FMOVE{fsize=fsize, src=operand(tmpR, src),
420 :     dst=operand(tmpR, dst)}, an)
421 :     | I.FILOAD{isize,ea,dst} =>
422 :     withTmpAvail
423 :     (fn tmpR => I.FILOAD{isize=isize, ea=operand(tmpR, ea),
424 :     dst=operand(tmpR, dst)}, an)
425 :     | I.FBINOP{fsize,binOp,lsrc,rsrc,dst} =>
426 :     withTmpAvail(fn tmpR =>
427 :     I.FBINOP{fsize=fsize, binOp=binOp, lsrc=operand(tmpR, lsrc),
428 :     rsrc=operand(tmpR, rsrc), dst=operand(tmpR, dst)}, an)
429 :     | I.FIBINOP{isize,binOp,lsrc,rsrc,dst} =>
430 :     withTmpAvail(fn tmpR =>
431 :     I.FIBINOP{isize=isize, binOp=binOp, lsrc=operand(tmpR, lsrc),
432 :     rsrc=operand(tmpR, rsrc), dst=operand(tmpR, dst)}, an)
433 :     | I.FUNOP{fsize,unOp,src,dst} =>
434 :     withTmpAvail(fn tmpR =>
435 :     I.FUNOP{fsize=fsize, unOp=unOp, src=operand(tmpR, src),
436 :     dst=operand(tmpR, dst)}, an)
437 : leunga 1156 | I.FCMP{i,fsize,lsrc,rsrc} =>
438 : george 1033 withTmpAvail(fn tmpR =>
439 : leunga 1156 I.FCMP{i=i,fsize=fsize,
440 : george 1033 lsrc=operand(tmpR, lsrc), rsrc=operand(tmpR, rsrc)
441 :     }, an)
442 :    
443 :     | _ => error "reload"
444 :     end (*x86Reload*)
445 :    
446 :     fun f(I.ANNOTATION{a, i}, an) = f(i, a::an)
447 :     | f(I.INSTR i, an) = x86Reload(i, reg, spillLoc, an)
448 :     | f(I.LIVE lk, an) =
449 :     {code=[annotate(I.LIVE(rLiveKill (lk, reg)), an)],
450 :     proh=[],
451 :     newReg=NONE}
452 :     | f _ = error "reload: f"
453 :     in f(instr, [])
454 :     end (* reload *)
455 :    
456 :    
457 :    
458 :    
459 :     fun spillF(instr, reg, spillLoc) = let
460 :     fun x86Fspill(instr, reg, spillLoc, an) = let
461 :     fun withTmp(f, fsize, an) = let
462 :     val tmpR = C.newFreg()
463 :     val tmp = I.FPR tmpR
464 :     in
465 :     { proh=[tmpR],
466 :     code=[mark(f tmp, an),
467 :     I.fmove{fsize=fsize, src=tmp, dst=spillLoc}],
468 :     newReg=SOME tmpR (* XXX Should we propagate the definition? *)
469 :     }
470 :     end
471 :     in
472 :     case instr
473 :     of I.FSTPL _ => {proh=[], code=[mark(I.FSTPL spillLoc, an)], newReg=NONE}
474 :     | I.FSTPS _ => {proh=[], code=[mark(I.FSTPS spillLoc, an)], newReg=NONE}
475 :     | I.FSTPT _ => {proh=[], code=[mark(I.FSTPT spillLoc, an)], newReg=NONE}
476 :     | I.FSTL _ => {proh=[], code=[mark(I.FSTL spillLoc, an)], newReg=NONE}
477 :     | I.FSTS _ => {proh=[], code=[mark(I.FSTS spillLoc, an)], newReg=NONE}
478 :     | I.CALL{opnd, defs, uses, return, cutsTo, mem, pops} =>
479 :     {proh=[],
480 :     code=[mark(I.CALL{opnd=opnd, defs=C.rmvFreg(reg,defs),
481 :     return=return, uses=uses,
482 :     cutsTo=cutsTo, mem=mem, pops=pops}, an)],
483 :     newReg=NONE}
484 :    
485 :     (* Pseudo fp instrctions *)
486 :     | I.FMOVE{fsize as I.FP64,src,dst} =>
487 :     if Props.eqOpn(src,spillLoc) then
488 :     {proh=[], code=[], newReg=NONE}
489 :     else
490 :     {proh=[],code=[mark(I.FMOVE{fsize=fsize,src=src,dst=spillLoc},an)],
491 :     newReg=NONE} (* XXX bad for single precision *)
492 :     | I.FMOVE _ => error "non-double precision not yet supported"
493 :     | I.FILOAD{isize,ea,dst} =>
494 :     {proh=[],code=[mark(I.FILOAD{isize=isize,ea=ea,dst=spillLoc},an)],
495 :     newReg=NONE} (* XXX bad for single precision *)
496 :     | I.FBINOP{fsize as I.FP64,binOp,lsrc,rsrc,dst} =>
497 :     {proh=[],code=[mark(I.FBINOP{fsize=fsize,binOp=binOp,
498 :     lsrc=lsrc, rsrc=rsrc,
499 :     dst=spillLoc},an)],
500 :     newReg=NONE}
501 :     | I.FBINOP{fsize,binOp,lsrc,rsrc,dst} =>
502 :     withTmp(fn tmpR =>
503 :     I.FBINOP{fsize=fsize, binOp=binOp,
504 :     lsrc=lsrc, rsrc=rsrc, dst=tmpR},
505 :     fsize, an)
506 :     | I.FIBINOP{isize,binOp,lsrc,rsrc,dst} =>
507 :     withTmp(fn tmpR =>
508 :     I.FIBINOP{isize=isize, binOp=binOp,
509 :     lsrc=lsrc, rsrc=rsrc, dst=tmpR},
510 :     I.FP64, an) (* XXX *)
511 :     | I.FUNOP{fsize,unOp,src,dst} =>
512 :     {proh=[],code=[mark(I.FUNOP{fsize=fsize,unOp=unOp,
513 :     src=src,dst=spillLoc},an)],
514 :     newReg=NONE}
515 :     | _ => error "fspill"
516 :     (*esac*)
517 :     end (* x86Fspill *)
518 :     fun f(I.ANNOTATION{a,i}, an) = f(i, a::an)
519 :     | f(I.INSTR(i), an) = x86Fspill(i, reg, spillLoc, an)
520 :     | f(I.KILL lk, an) =
521 :     {code=[annotate(I.KILL(fLiveKill (lk, reg)), an)],
522 :     proh=[],
523 :     newReg=NONE}
524 :     | f _ = error "fspill:f"
525 :     in f(instr, [])
526 :     end
527 :    
528 :    
529 :     fun reloadF(instr, reg, spillLoc) = let
530 :     fun x86Freload(instr, reg, spillLoc, an) = let
531 :     fun rename(src as I.FDirect f) =
532 :     if CB.sameColor(f,reg) then spillLoc else src
533 :     | rename(src as I.FPR f) =
534 :     if CB.sameColor(f,reg) then spillLoc else src
535 :     | rename src = src
536 :    
537 :     fun withTmp(fsize, f, an) =
538 :     case spillLoc of
539 :     I.FDirect _ => {newReg=NONE, proh=[], code=[mark(f spillLoc, an)]}
540 :     | I.FPR _ => {newReg=NONE, proh=[], code=[mark(f spillLoc, an)]}
541 :     | _ =>
542 :     let val ftmpR = C.newFreg()
543 :     val ftmp = I.FPR(ftmpR)
544 :     in {newReg=NONE,
545 :     proh=[ftmpR],
546 :     code=[I.fmove{fsize=fsize, src=spillLoc, dst=ftmp},
547 :     mark(f ftmp, an)
548 :     ]
549 :     }
550 :     end
551 :     in
552 :     (case instr of
553 :     I.FLDT opnd => {code=[mark(I.FLDT spillLoc, an)], proh=[], newReg=NONE}
554 :     | I.FLDL opnd => {code=[mark(I.FLDL spillLoc, an)], proh=[], newReg=NONE}
555 :     | I.FLDS opnd => {code=[mark(I.FLDS spillLoc, an)], proh=[], newReg=NONE}
556 :     | I.FUCOM opnd => {code=[mark(I.FUCOM spillLoc, an)],proh=[],newReg=NONE}
557 :     | I.FUCOMP opnd => {code=[mark(I.FUCOMP spillLoc, an)],proh=[],newReg=NONE}
558 : leunga 1156 | I.FCOMI opnd => {code=[mark(I.FCOMI spillLoc, an)],proh=[],newReg=NONE}
559 :     | I.FCOMIP opnd => {code=[mark(I.FCOMIP spillLoc, an)],proh=[],newReg=NONE}
560 :     | I.FUCOMI opnd => {code=[mark(I.FUCOMI spillLoc, an)],proh=[],newReg=NONE}
561 :     | I.FUCOMIP opnd => {code=[mark(I.FUCOMIP spillLoc, an)],proh=[],newReg=NONE}
562 : george 1033 | I.FBINARY{binOp, src=I.FDirect f, dst} =>
563 :     if CB.sameColor(f,reg) then
564 :     {code=[mark(I.FBINARY{binOp=binOp, src=spillLoc, dst=dst}, an)],
565 :     proh=[],
566 :     newReg=NONE}
567 :     else error "reloadF:FBINARY"
568 :    
569 :     (* Pseudo fp instructions.
570 :     *)
571 :     | I.FMOVE{fsize as I.FP64,src,dst} =>
572 :     if Props.eqOpn(dst,spillLoc) then
573 :     {code=[], proh=[], newReg=NONE}
574 :     else
575 :     {code=[mark(I.FMOVE{fsize=fsize,src=spillLoc,dst=dst},an)],
576 :     proh=[], newReg=NONE}
577 :     | I.FMOVE _ => error "non-double precision not yet supported"
578 :     | I.FBINOP{fsize,binOp,lsrc,rsrc,dst} =>
579 :     {code=[mark(I.FBINOP{fsize=fsize,binOp=binOp,
580 :     lsrc=rename lsrc, rsrc=rename rsrc,dst=dst},an)],
581 :     proh=[], newReg=NONE}
582 :     | I.FIBINOP{isize,binOp,lsrc,rsrc,dst} =>
583 :     {code=[mark(I.FIBINOP{isize=isize,binOp=binOp,
584 :     lsrc=rename lsrc,rsrc=rename rsrc,dst=dst},an)],
585 :     proh=[], newReg=NONE}
586 :     | I.FUNOP{fsize,unOp,src,dst} =>
587 :     {code=[mark(I.FUNOP{fsize=fsize,unOp=unOp,
588 :     src=rename src, dst=dst},an)],
589 :     proh=[], newReg=NONE}
590 : leunga 1156 | I.FCMP{i,fsize,lsrc,rsrc} =>
591 : george 1033 (* Make sure that both the lsrc and rsrc cannot be in memory *)
592 :     (case (lsrc, rsrc) of
593 :     (I.FPR fs1, I.FPR fs2) =>
594 :     (case (CB.sameColor(fs1,reg), CB.sameColor(fs2,reg)) of
595 :     (true, true) =>
596 :     withTmp(fsize,
597 : leunga 1156 fn tmp => I.FCMP{i=i,fsize=fsize,lsrc=tmp, rsrc=tmp}, an)
598 : george 1033 | (true, false) =>
599 : leunga 1156 {code=[mark(I.FCMP{i=i,fsize=fsize,lsrc=spillLoc,rsrc=rsrc},an)],
600 : george 1033 proh=[], newReg=NONE}
601 :     | (false, true) =>
602 : leunga 1156 {code=[mark(I.FCMP{i=i,fsize=fsize,lsrc=lsrc,rsrc=spillLoc},an)],
603 : george 1033 proh=[], newReg=NONE}
604 :     | _ => error "fcmp.1"
605 :     )
606 :     | (I.FPR _, _) =>
607 :     withTmp(fsize,
608 : leunga 1156 fn tmp => I.FCMP{i=i,fsize=fsize,lsrc=tmp, rsrc=rsrc}, an)
609 : george 1033 | (_, I.FPR _) =>
610 :     withTmp(fsize,
611 : leunga 1156 fn tmp => I.FCMP{i=i,fsize=fsize,lsrc=rsrc, rsrc=tmp}, an)
612 : george 1033 | _ => error "fcmp.2"
613 :     )
614 :     | I.CALL{opnd, defs, uses, return, cutsTo, mem, pops} =>
615 :     {proh=[],
616 :     code=[mark(I.CALL{opnd=opnd, defs=C.rmvFreg(reg,defs),
617 :     return=return, pops=pops,
618 :     uses=uses, cutsTo=cutsTo, mem=mem}, an)],
619 :     newReg=NONE}
620 :     | _ => error "reloadF"
621 :     (*esac*))
622 :     end (* x86Freload *)
623 :    
624 :     fun f(I.ANNOTATION{a, i}, an) = f(i, a::an)
625 :     | f(I.INSTR i, an) = x86Freload(i, reg, spillLoc, an)
626 :     | f(I.LIVE lk, an) =
627 :     {code=[annotate(I.LIVE(fLiveKill (lk, reg)), an)],
628 :     proh=[],
629 :     newReg=NONE}
630 :     | f _ = error "freload.f"
631 :    
632 :     in f(instr, [])
633 :     end
634 :    
635 :     fun spillToEA CB.GP (reg, ea) = let
636 :     fun returnMove() =
637 :     {code=[I.move{mvOp=I.MOVL, src=I.Direct reg, dst=ea}],
638 :     proh=[], newReg=NONE}
639 :     in
640 :     case ea
641 :     of I.MemReg _ => returnMove()
642 :     | I.Displace _ => returnMove()
643 :     | I.Indexed _ => returnMove()
644 :     | _ => error "spillToEA: GP"
645 :     end
646 :     | spillToEA CB.FP (freg, ea) = error "spillToEA: FP"
647 :     | spillToEA _ _ = error "spillToEA"
648 :    
649 :     fun reloadFromEA CB.GP (reg, ea) = let
650 :     fun returnMove() =
651 :     {code=[I.move{mvOp=I.MOVL, dst=I.Direct reg, src=ea}],
652 :     proh=[],
653 :     newReg=NONE}
654 :     in
655 :     case ea
656 :     of I.MemReg _ => returnMove()
657 :     | I.Displace _ => returnMove()
658 :     | I.Indexed _ => returnMove()
659 :     | _ => error "reloadFromEA: GP"
660 :     end
661 :     | reloadFromEA CB.FP (freg, ea) = error "spillToEA: FP"
662 :     | reloadFromEA _ _ = error "spillToEA"
663 :    
664 :    
665 :     fun reload CB.GP = reloadR
666 :     | reload CB.FP = reloadF
667 :     | reload _ = error "reload"
668 :    
669 :     fun spill CB.GP = spillR
670 :     | spill CB.FP = spillF
671 :     | spill _ = error "spill"
672 :     end

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