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/branches/SMLNJ/src/MLRISC/sparc/mltree/sparc.sml
ViewVC logotype

Annotation of /sml/branches/SMLNJ/src/MLRISC/sparc/mltree/sparc.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 475 - (view) (download)

1 : monnier 245 (*
2 : monnier 411 * This is a new instruction selection module for Sparc,
3 :     * using the new instruction representation and the new MLTREE representation.
4 :     * Support for V9 has been added.
5 : monnier 245 *
6 : monnier 411 * The cc bit in arithmetic op are now embedded within the arithmetic
7 :     * opcode. This should save some space.
8 : monnier 245 *
9 : monnier 411 * -- Allen
10 : monnier 245 *)
11 :    
12 :     functor Sparc
13 :     (structure SparcInstr : SPARCINSTR
14 : monnier 411 structure SparcMLTree : MLTREE
15 :     structure PseudoInstrs : SPARC_PSEUDO_INSTR
16 : monnier 475 sharing SparcMLTree.Region = SparcInstr.Region
17 :     sharing SparcMLTree.Constant = SparcInstr.Constant
18 :     sharing PseudoInstrs.I = SparcInstr
19 : monnier 411 (*
20 :     * The client should also specify these parameters.
21 :     * These are the estimated cost of these instructions.
22 :     * The code generator will use alternative sequences that are
23 :     * cheaper when their costs are lower.
24 :     *)
25 :     val muluCost : int ref (* cost of unsigned multiplication in cycles *)
26 :     val divuCost : int ref (* cost of unsigned division in cycles *)
27 :     val multCost : int ref (* cost of trapping/signed multiplication in cycles *)
28 :     val divtCost : int ref (* cost of trapping/signed division in cycles *)
29 :    
30 :     (*
31 :     * If you don't want to use register windows at all, set this to false.
32 :     *)
33 :     val registerwindow : bool ref (* should we use register windows? *)
34 :    
35 :     val V9 : bool (* should we use V9 instruction set? *)
36 :     val useBR : bool ref
37 :     (* should we use the BR instruction (when in V9)?
38 :     * I think it is a good idea to use it.
39 :     *)
40 : monnier 245 ) : MLTREECOMP =
41 :     struct
42 : monnier 411 structure T = SparcMLTree
43 : monnier 429 structure S = T.Stream
44 : monnier 411 structure R = SparcMLTree.Region
45 :     structure I = SparcInstr
46 :     structure C = I.C
47 : monnier 245 structure LE = LabelExp
48 :     structure W = Word32
49 :     structure P = PseudoInstrs
50 :    
51 : monnier 411 structure Gen = MLTreeGen(structure T = T
52 :     val intTy = if V9 then 64 else 32
53 :     val naturalWidths = if V9 then [32,64] else [32]
54 : monnier 429 datatype rep = SE | ZE | NEITHER
55 :     val rep = NEITHER
56 : monnier 411 )
57 : monnier 245
58 : monnier 411 functor Multiply32 = MLTreeMult
59 :     (structure I = I
60 :     structure T = T
61 : monnier 429 type arg = {r1:C.cell,r2:C.cell,d:C.cell}
62 :     type argi = {r:C.cell,i:int,d:C.cell}
63 : monnier 411
64 :     val intTy = 32
65 :     fun mov{r,d} = I.COPY{dst=[d],src=[r],tmp=NONE,impl=ref NONE}
66 :     fun add{r1,r2,d} = I.ARITH{a=I.ADD,r=r1,i=I.REG r2,d=d}
67 :     fun slli{r,i,d} = [I.SHIFT{s=I.SLL,r=r,i=I.IMMED i,d=d}]
68 :     fun srli{r,i,d} = [I.SHIFT{s=I.SRL,r=r,i=I.IMMED i,d=d}]
69 :     fun srai{r,i,d} = [I.SHIFT{s=I.SRA,r=r,i=I.IMMED i,d=d}]
70 :     )
71 : monnier 245
72 : monnier 411 functor Multiply64 = MLTreeMult
73 :     (structure I = I
74 :     structure T = T
75 : monnier 429 type arg = {r1:C.cell,r2:C.cell,d:C.cell}
76 :     type argi = {r:C.cell,i:int,d:C.cell}
77 : monnier 411
78 :     val intTy = 64
79 :     fun mov{r,d} = I.COPY{dst=[d],src=[r],tmp=NONE,impl=ref NONE}
80 :     fun add{r1,r2,d} = I.ARITH{a=I.ADD,r=r1,i=I.REG r2,d=d}
81 :     fun slli{r,i,d} = [I.SHIFT{s=I.SLLX,r=r,i=I.IMMED i,d=d}]
82 :     fun srli{r,i,d} = [I.SHIFT{s=I.SRLX,r=r,i=I.IMMED i,d=d}]
83 :     fun srai{r,i,d} = [I.SHIFT{s=I.SRAX,r=r,i=I.IMMED i,d=d}]
84 :     )
85 : monnier 245
86 : monnier 411 (* signed, trapping version of multiply and divide *)
87 :     structure Mult32 = Multiply32
88 :     (val trapping = true
89 :     val multCost = multCost
90 :     fun addv{r1,r2,d} =
91 :     I.ARITH{a=I.ADDCC,r=r1,i=I.REG r2,d=d}::PseudoInstrs.overflowtrap32
92 :     fun subv{r1,r2,d} =
93 :     I.ARITH{a=I.SUBCC,r=r1,i=I.REG r2,d=d}::PseudoInstrs.overflowtrap32
94 :     val sh1addv = NONE
95 :     val sh2addv = NONE
96 :     val sh3addv = NONE
97 :     )
98 : monnier 429 (val signed = true)
99 : monnier 245
100 : monnier 411 (* unsigned, non-trapping version of multiply and divide *)
101 :     structure Mulu32 = Multiply32
102 :     (val trapping = false
103 :     val multCost = muluCost
104 :     fun addv{r1,r2,d} = [I.ARITH{a=I.ADD,r=r1,i=I.REG r2,d=d}]
105 :     fun subv{r1,r2,d} = [I.ARITH{a=I.SUB,r=r1,i=I.REG r2,d=d}]
106 :     val sh1addv = NONE
107 :     val sh2addv = NONE
108 :     val sh3addv = NONE
109 :     )
110 : monnier 429 (val signed = false)
111 : monnier 245
112 : monnier 411 (* signed, trapping version of multiply and divide *)
113 :     structure Mult64 = Multiply64
114 :     (val trapping = true
115 :     val multCost = multCost
116 :     fun addv{r1,r2,d} =
117 :     I.ARITH{a=I.ADDCC,r=r1,i=I.REG r2,d=d}::PseudoInstrs.overflowtrap64
118 :     fun subv{r1,r2,d} =
119 :     I.ARITH{a=I.SUBCC,r=r1,i=I.REG r2,d=d}::PseudoInstrs.overflowtrap64
120 :     val sh1addv = NONE
121 :     val sh2addv = NONE
122 :     val sh3addv = NONE
123 :     )
124 : monnier 429 (val signed = true)
125 : monnier 245
126 : monnier 411 (* unsigned, non-trapping version of multiply and divide *)
127 :     structure Mulu64 = Multiply64
128 :     (val trapping = false
129 :     val multCost = muluCost
130 :     fun addv{r1,r2,d} = [I.ARITH{a=I.ADD,r=r1,i=I.REG r2,d=d}]
131 :     fun subv{r1,r2,d} = [I.ARITH{a=I.SUB,r=r1,i=I.REG r2,d=d}]
132 :     val sh1addv = NONE
133 :     val sh2addv = NONE
134 :     val sh3addv = NONE
135 :     )
136 : monnier 429 (val signed = false)
137 : monnier 245
138 : monnier 411 datatype commutative = COMMUTE | NOCOMMUTE
139 :     datatype cc = REG (* write to register *)
140 :     | CC (* set condition code *)
141 :     | CC_REG (* do both *)
142 : monnier 245
143 : monnier 411 fun error msg = MLRiscErrorMsg.error("Sparc",msg)
144 : monnier 245
145 : monnier 411 fun selectInstructions
146 : monnier 469 (S.STREAM{emit,defineLabel,entryLabel,pseudoOp,annotation,
147 : monnier 429 beginCluster,endCluster,exitBlock,alias,phi,comment,...}) =
148 : monnier 411 let
149 :     (* Flags *)
150 :     val useBR = !useBR
151 :     val registerwindow = !registerwindow
152 : monnier 245
153 : monnier 411 val trap32 = PseudoInstrs.overflowtrap32
154 :     val trap64 = PseudoInstrs.overflowtrap64
155 :     val newReg = C.newReg
156 :     val newFreg = C.newFreg
157 :     fun immed13 n = ~4096 <= n andalso n < 4096
158 :     fun immed13w w = let val x = W.~>>(w,0w12)
159 :     in x = 0w0 orelse (W.notb x) = 0w0 end
160 :     fun splitw w = {hi=W.toInt(W.>>(w,0w10)),lo=W.toInt(W.andb(w,0wx3ff))}
161 :     fun split n = splitw(W.fromInt n)
162 : monnier 245
163 : monnier 411
164 :     val zeroOpn = I.REG 0 (* zero value operand *)
165 :     val _ = if C.psr <> 65 then error "Wrong encoding for psr" else ()
166 : monnier 245
167 : monnier 411 fun cond T.LT = I.BL
168 :     | cond T.LTU = I.BCS
169 :     | cond T.LE = I.BLE
170 :     | cond T.LEU = I.BLEU
171 :     | cond T.EQ = I.BE
172 :     | cond T.NE = I.BNE
173 :     | cond T.GE = I.BGE
174 :     | cond T.GEU = I.BCC
175 :     | cond T.GT = I.BG
176 :     | cond T.GTU = I.BGU
177 : monnier 245
178 : monnier 411 fun rcond T.LT = I.RLZ
179 :     | rcond T.LE = I.RLEZ
180 :     | rcond T.EQ = I.RZ
181 :     | rcond T.NE = I.RNZ
182 :     | rcond T.GE = I.RGEZ
183 :     | rcond T.GT = I.RGZ
184 :     | rcond _ = error "rcond"
185 : monnier 245
186 : monnier 411 fun signedCmp(T.LT | T.LE | T.EQ | T.NE | T.GE | T.GT) = true
187 :     | signedCmp _ = false
188 : monnier 245
189 : monnier 411 fun fcond T.== = I.FBE
190 :     | fcond T.?<> = I.FBNE
191 :     | fcond T.? = I.FBU
192 :     | fcond T.<=> = I.FBO
193 :     | fcond T.> = I.FBG
194 :     | fcond T.>= = I.FBGE
195 :     | fcond T.?> = I.FBUG
196 :     | fcond T.?>= = I.FBUGE
197 :     | fcond T.< = I.FBL
198 :     | fcond T.<= = I.FBLE
199 :     | fcond T.?< = I.FBUL
200 :     | fcond T.?<= = I.FBULE
201 :     | fcond T.<> = I.FBLG
202 :     | fcond T.?= = I.FBUE
203 : monnier 475 | fcond fc = error("fcond "^T.Util.fcondToString fc)
204 : monnier 245
205 : monnier 411 fun mark'(i,[]) = i
206 :     | mark'(i,a::an) = mark'(I.ANNOTATION{i=i,a=a},an)
207 : monnier 245
208 : monnier 411 fun mark(i,an) = emit(mark'(i,an))
209 : monnier 245
210 : monnier 411 (* convert an operand into a register *)
211 :     fun reduceOpn(I.REG r) = r
212 :     | reduceOpn(I.IMMED 0) = 0
213 :     | reduceOpn i =
214 :     let val d = newReg()
215 :     in emit(I.ARITH{a=I.OR,r=0,i=i,d=d}); d end
216 : monnier 245
217 : monnier 411 (* emit parallel copies *)
218 :     fun copy(dst,src,an) =
219 :     mark(I.COPY{dst=dst,src=src,impl=ref NONE,
220 :     tmp=case dst of [_] => NONE
221 :     | _ => SOME(I.Direct(newReg()))},an)
222 :     fun fcopy(dst,src,an) =
223 :     mark(I.FCOPY{dst=dst,src=src,impl=ref NONE,
224 :     tmp=case dst of [_] => NONE
225 :     | _ => SOME(I.FDirect(newFreg()))},an)
226 : monnier 245
227 : monnier 411 (* move register s to register d *)
228 :     fun move(s,d,an) =
229 :     if s = d orelse d = 0 then ()
230 :     else mark(I.COPY{dst=[d],src=[s],tmp=NONE,impl=ref NONE},an)
231 :    
232 :     (* move floating point register s to register d *)
233 :     fun fmoved(s,d,an) =
234 :     if s = d then ()
235 :     else mark(I.FCOPY{dst=[d],src=[s],tmp=NONE,impl=ref NONE},an)
236 : monnier 475 fun fmoves(s,d,an) = fmoved(s,d,an) (* error "fmoves" for now!!! XXX *)
237 : monnier 411 fun fmoveq(s,d,an) = error "fmoveq"
238 :    
239 :     (* load word constant *)
240 :     fun loadImmedw(w,d,cc,an) =
241 :     let val or = if cc <> REG then I.ORCC else I.OR
242 :     in if immed13w w then
243 :     mark(I.ARITH{a=or,r=0,i=I.IMMED(W.toIntX w),d=d},an)
244 :     else let val {hi,lo} = splitw w
245 :     in if lo = 0 then
246 :     (mark(I.SETHI{i=hi,d=d},an); genCmp0(cc,d))
247 :     else let val t = newReg()
248 :     in emit(I.SETHI{i=hi,d=t});
249 :     mark(I.ARITH{a=or,r=t,i=I.IMMED lo,d=d},an)
250 :     end
251 :     end
252 : monnier 245 end
253 :    
254 : monnier 411 (* load immediate *)
255 :     and loadImmed(n,d,cc,an) =
256 :     let val or = if cc <> REG then I.ORCC else I.OR
257 :     in if immed13 n then mark(I.ARITH{a=or,r=0,i=I.IMMED n,d=d},an)
258 :     else let val {hi,lo} = split n
259 :     in if lo = 0 then
260 :     (mark(I.SETHI{i=hi,d=d},an); genCmp0(cc,d))
261 :     else let val t = newReg()
262 :     in emit(I.SETHI{i=hi,d=t});
263 :     mark(I.ARITH{a=or,r=t,i=I.IMMED lo,d=d},an)
264 :     end
265 :     end
266 :     end
267 : monnier 245
268 : monnier 411 (* load constant *)
269 :     and loadConst(c,d,cc,an) =
270 :     let val or = if cc <> REG then I.ORCC else I.OR
271 :     in mark(I.ARITH{a=or,r=0,i=I.CONST c,d=d},an) end
272 : monnier 245
273 : monnier 411 (* load label expression *)
274 :     and loadLabel(lab,d,cc,an) =
275 :     let val or = if cc <> REG then I.ORCC else I.OR
276 :     in mark(I.ARITH{a=or,r=0,i=I.LAB lab,d=d},an) end
277 : monnier 245
278 : monnier 411 (* emit an arithmetic op *)
279 :     and arith(a,acc,e1,e2,d,cc,comm,trap,an) =
280 :     let val (a,d) = case cc of
281 :     REG => (a,d)
282 :     | CC => (acc,0)
283 :     | CC_REG => (acc,d)
284 :     in case (opn e1,opn e2,comm) of
285 :     (i,I.REG r,COMMUTE)=> mark(I.ARITH{a=a,r=r,i=i,d=d},an)
286 :     | (I.REG r,i,_) => mark(I.ARITH{a=a,r=r,i=i,d=d},an)
287 :     | (r,i,_) => mark(I.ARITH{a=a,r=reduceOpn r,i=i,d=d},an)
288 :     ;
289 :     case trap of [] => () | _ => app emit trap
290 :     end
291 : monnier 245
292 : monnier 411 (* emit a shift op *)
293 :     and shift(s,e1,e2,d,cc,an) =
294 :     (mark(I.SHIFT{s=s,r=expr e1,i=opn e2,d=d},an);
295 :     genCmp0(cc,d)
296 :     )
297 : monnier 245
298 : monnier 411 (* emit externally defined multiply or division operation (V8) *)
299 :     and extarith(gen,genConst,e1,e2,d,cc,comm) =
300 :     let fun nonconst(e1,e2) =
301 :     case (opn e1,opn e2,comm) of
302 :     (i,I.REG r,COMMUTE) => gen({r=r,i=i,d=d},reduceOpn)
303 :     | (I.REG r,i,_) => gen({r=r,i=i,d=d},reduceOpn)
304 :     | (r,i,_) => gen({r=reduceOpn r,i=i,d=d},reduceOpn)
305 :     fun const(e,i) =
306 :     let val r = expr e
307 :     in genConst{r=r,i=i,d=d}
308 :     handle _ => gen({r=r,i=opn(T.LI i),d=d},reduceOpn)
309 :     end
310 :     fun constw(e,i) = const(e,Word32.toInt i)
311 :     handle _ => nonconst(e,T.LI32 i)
312 :     val instrs =
313 :     case (comm,e1,e2) of
314 :     (_,e1,T.LI i) => const(e1,i)
315 :     | (_,e1,T.LI32 i) => constw(e1,i)
316 :     | (COMMUTE,T.LI i,e2) => const(e2,i)
317 :     | (COMMUTE,T.LI32 i,e2) => constw(e2,i)
318 :     | _ => nonconst(e1,e2)
319 :     in app emit instrs;
320 :     genCmp0(cc,d)
321 :     end
322 : monnier 245
323 : monnier 411 (* emit 64-bit multiply or division operation (V9) *)
324 :     and muldiv64(a,genConst,e1,e2,d,cc,comm,an) =
325 :     let fun nonconst(e1,e2) =
326 :     [mark'(
327 :     case (opn e1,opn e2,comm) of
328 :     (i,I.REG r,COMMUTE) => I.ARITH{a=a,r=r,i=i,d=d}
329 :     | (I.REG r,i,_) => I.ARITH{a=a,r=r,i=i,d=d}
330 :     | (r,i,_) => I.ARITH{a=a,r=reduceOpn r,i=i,d=d},an)
331 :     ]
332 :     fun const(e,i) =
333 :     let val r = expr e
334 :     in genConst{r=r,i=i,d=d}
335 :     handle _ => [mark'(I.ARITH{a=a,r=r,i=opn(T.LI i),d=d},an)]
336 :     end
337 :     fun constw(e,i) = const(e,Word32.toInt i)
338 :     handle _ => nonconst(e,T.LI32 i)
339 :     val instrs =
340 :     case (comm,e1,e2) of
341 :     (_,e1,T.LI i) => const(e1,i)
342 :     | (_,e1,T.LI32 i) => constw(e1,i)
343 :     | (COMMUTE,T.LI i,e2) => const(e2,i)
344 :     | (COMMUTE,T.LI32 i,e2) => constw(e2,i)
345 :     | _ => nonconst(e1,e2)
346 :     in app emit instrs;
347 :     genCmp0(cc,d)
348 :     end
349 :    
350 :     (* divisions *)
351 :     and divu32 x = Mulu32.divide{mode=T.TO_ZERO,roundToZero=roundToZero} x
352 :     and divt32 x = Mult32.divide{mode=T.TO_ZERO,roundToZero=roundToZero} x
353 :     and divu64 x = Mulu64.divide{mode=T.TO_ZERO,roundToZero=roundToZero} x
354 :     and divt64 x = Mult64.divide{mode=T.TO_ZERO,roundToZero=roundToZero} x
355 :    
356 :     and roundToZero{ty,r,i,d} =
357 :     let val L = Label.newLabel ""
358 :     in doStmt(T.MV(ty,d,T.REG(ty,r)));
359 :     doStmt(T.BCC(T.GE,T.CMP(ty,T.GE,T.REG(ty,d),T.LI 0),L));
360 :     doStmt(T.MV(ty,d,T.ADD(ty,T.REG(ty,d),T.LI i)));
361 :     defineLabel L
362 :     end
363 :    
364 :     (* emit an unary floating point op *)
365 :     and funary(a,e,d,an) = mark(I.FPop1{a=a,r=fexpr e,d=d},an)
366 :    
367 :     (* emit a binary floating point op *)
368 :     and farith(a,e1,e2,d,an) =
369 :     mark(I.FPop2{a=a,r1=fexpr e1,r2=fexpr e2,d=d},an)
370 :    
371 :     (* convert an expression into an addressing mode *)
372 :     and addr(T.ADD(_,e,T.LI n)) =
373 :     if immed13 n then (expr e,I.IMMED n)
374 :     else let val d = newReg()
375 :     in loadImmed(n,d,REG,[]); (d,opn e) end
376 :     | addr(T.ADD(_,e,T.CONST c)) = (expr e,I.CONST c)
377 :     | addr(T.ADD(_,e,T.LABEL l)) = (expr e,I.LAB l)
378 :     | addr(T.ADD(ty,i as T.LI _,e)) = addr(T.ADD(ty,e,i))
379 :     | addr(T.ADD(_,T.CONST c,e)) = (expr e,I.CONST c)
380 :     | addr(T.ADD(_,T.LABEL l,e)) = (expr e,I.LAB l)
381 :     | addr(T.ADD(_,e1,e2)) = (expr e1,I.REG(expr e2))
382 :     | addr(T.SUB(ty,e,T.LI n)) = addr(T.ADD(ty,e,T.LI(~n)))
383 :     | addr(T.LABEL l) = (0,I.LAB l)
384 :     | addr a = (expr a,zeroOpn)
385 :    
386 :     (* emit an integer load *)
387 :     and load(l,a,d,mem,cc,an) =
388 :     let val (r,i) = addr a
389 :     in mark(I.LOAD{l=l,r=r,i=i,d=d,mem=mem},an);
390 :     genCmp0(cc,d)
391 :     end
392 :    
393 :     (* emit an integer store *)
394 :     and store(s,a,d,mem,an) =
395 :     let val (r,i) = addr a
396 :     in mark(I.STORE{s=s,r=r,i=i,d=expr d,mem=mem},an) end
397 :     (*and storecc(a,d,mem,an) =
398 :     let val (r,i) = addr a
399 :     in mark(I.STORE{s=I.ST,r=r,i=i,d=ccExpr d,mem=mem},an) end*)
400 :    
401 :     (* emit a floating point load *)
402 :     and fload(l,a,d,mem,an) =
403 :     let val (r,i) = addr a
404 :     in mark(I.FLOAD{l=l,r=r,i=i,d=d,mem=mem},an) end
405 :    
406 :     (* emit a floating point store *)
407 :     and fstore(s,a,d,mem,an) =
408 :     let val (r,i) = addr a
409 :     in mark(I.FSTORE{s=s,r=r,i=i,d=fexpr d,mem=mem},an) end
410 :    
411 :     (* emit a jump *)
412 :     and jmp(a,labs,an) =
413 :     let val (r,i) = addr a
414 :     in mark(I.JMP{r=r,i=i,labs=labs,nop=true},an) end
415 :    
416 :     (* emit a function call *)
417 :     and call(a,defs,uses,mem,an) =
418 :     let val (r,i) = addr a
419 : monnier 245 fun live([],acc) = acc
420 : monnier 475 | live(T.GPR(T.REG(_,r))::regs,acc) = live(regs, C.addReg(r,acc))
421 :     | live(T.FPR(T.FREG(_,f))::regs,acc) = live(regs, C.addFreg(f,acc))
422 : monnier 411 | live(T.CCR(T.CC 65)::regs,acc) = live(regs, C.addPSR(65,acc))
423 : monnier 245 | live(T.CCR(T.CC cc)::regs,acc) = live(regs, C.addReg(cc,acc))
424 : monnier 411 | live(T.GPR _::_,_) = error "live:GPR"
425 :     | live(T.FPR _::_,_) = error "live:FPR"
426 : monnier 245 | live(_::regs, acc) = live(regs, acc)
427 :     val defs=live(defs,C.empty)
428 :     val uses=live(uses,C.empty)
429 :     in case (r,i) of
430 :     (0,I.LAB(LE.LABEL l)) =>
431 : monnier 411 mark(I.CALL{label=l,defs=C.addReg(C.linkReg,defs),uses=uses,
432 :     mem=mem,nop=true},an)
433 :     | _ => mark(I.JMPL{r=r,i=i,d=C.linkReg,defs=defs,uses=uses,mem=mem,
434 :     nop=true},an)
435 : monnier 245 end
436 :    
437 : monnier 411 (* emit an integer branch instruction *)
438 :     and branch(_,T.CMP(ty,cond,a,b),lab,an) =
439 :     let val (cond,a,b) =
440 :     case a of
441 :     (T.LI _ | T.LI32 _ | T.CONST _ | T.LABEL _) =>
442 : monnier 475 (T.Util.swapCond cond,b,a)
443 : monnier 411 | _ => (cond,a,b)
444 :     in if V9 then
445 :     branchV9(cond,a,b,lab,an)
446 :     else
447 :     (doExpr(T.SUB(ty,a,b),newReg(),CC,[]); br(cond,lab,an))
448 :     end
449 :     | branch(cond,T.CC 65,lab,an) = br(cond,lab,an)
450 :     | branch(cond,T.CC r,lab,an) = (genCmp0(CC,r); br(cond,lab,an))
451 :     | branch _ = error "branch"
452 : monnier 245
453 : monnier 411 and branchV9(cond,a,b,lab,an) =
454 :     let val size = Gen.size a
455 :     in if useBR andalso signedCmp cond then
456 :     let val r = newReg()
457 :     in doExpr(T.SUB(size,a,b),r,REG,[]);
458 :     brcond(cond,r,lab,an)
459 :     end
460 :     else
461 :     let val cc = case size of 32 => I.ICC
462 :     | 64 => I.XCC
463 :     | _ => error "branchV9"
464 :     in doExpr(T.SUB(size,a,b),newReg(),CC,[]);
465 :     bp(cond,cc,lab,an)
466 :     end
467 :     end
468 : monnier 245
469 : monnier 411 and br(c,lab,an) = mark(I.Bicc{b=cond c,a=true,label=lab,nop=true},an)
470 : monnier 245
471 : monnier 411 and brcond(c,r,lab,an) =
472 :     mark(I.BR{rcond=rcond c,r=r,p=I.PT,a=true,label=lab,nop=true},an)
473 : monnier 245
474 : monnier 411 and bp(c,cc,lab,an) =
475 :     mark(I.BP{b=cond c,cc=cc,p=I.PT,a=true,label=lab,nop=true},an)
476 : monnier 245
477 : monnier 411 (* emit a floating point branch instruction *)
478 :     and fbranch(c,T.FCMP(fty,cond,a,b),lab,an) =
479 :     let val cmp = case fty of
480 :     32 => I.FCMPs
481 :     | 64 => I.FCMPd
482 :     | _ => error "fbranch"
483 :     in emit(I.FCMP{cmp=cmp,r1=fexpr a,r2=fexpr b,nop=true});
484 :     mark(I.FBfcc{b=fcond cond,a=false,label=lab,nop=true},an)
485 :     end
486 :     | fbranch _ = error "fbranch"
487 :    
488 :     (* generate code for a statement *)
489 :     and stmt(T.MV(_,d,e),an) = doExpr(e,d,REG,an)
490 :     | stmt(T.FMV(_,d,e),an) = doFexpr(e,d,an)
491 :     | stmt(T.CCMV(d,e),an) = doCCexpr(e,d,an)
492 :     | stmt(T.COPY(_,dst,src),an) = copy(dst,src,an)
493 : monnier 475 | stmt(T.FCOPY(_,dst,src),an) = fcopy(dst,src,an)
494 : monnier 411 | stmt(T.JMP(T.LABEL(LE.LABEL l),_),an) =
495 :     mark(I.Bicc{b=I.BA,a=true,label=l,nop=false},an)
496 :     | stmt(T.JMP(e,labs),an) = jmp(e,labs,an)
497 :     | stmt(T.CALL(e,def,use,mem),an) = call(e,def,use,mem,an)
498 :     | stmt(T.RET,an) = mark(I.RET{leaf=not registerwindow,nop=true},an)
499 :     | stmt(T.STORE(8,a,d,mem),an) = store(I.STB,a,d,mem,an)
500 :     | stmt(T.STORE(16,a,d,mem),an) = store(I.STH,a,d,mem,an)
501 :     | stmt(T.STORE(32,a,d,mem),an) = store(I.ST,a,d,mem,an)
502 :     | stmt(T.STORE(64,a,d,mem),an) =
503 :     store(if V9 then I.STX else I.STD,a,d,mem,an)
504 :     | stmt(T.FSTORE(32,a,d,mem),an) = fstore(I.STF,a,d,mem,an)
505 :     | stmt(T.FSTORE(64,a,d,mem),an) = fstore(I.STDF,a,d,mem,an)
506 :     | stmt(T.BCC(cond,cc,lab),an) = branch(cond,cc,lab,an)
507 :     | stmt(T.FBCC(cond,cc,lab),an) = fbranch(cond,cc,lab,an)
508 :     | stmt(T.ANNOTATION(s,a),an) = stmt(s,a::an)
509 :     | stmt _ = error "stmt"
510 : monnier 245
511 : monnier 411 and doStmt s = stmt(s,[])
512 : monnier 245
513 :    
514 : monnier 411 (* convert an expression into a register *)
515 :     and expr(T.REG(_,r)) = r
516 :     | expr(T.LI 0) = 0
517 :     | expr(T.LI32 0w0) = 0
518 :     | expr e = let val d = newReg()
519 :     in doExpr(e,d,REG,[]); d end
520 : monnier 245
521 : monnier 411 (* compute an integer expression and put the result in register d
522 :     * If cc is set then set the condition code with the result.
523 :     *)
524 :     and doExpr(e,d,cc,an) =
525 :     case e of
526 :     T.REG(_,r) => (move(r,d,an); genCmp0(cc,r))
527 :     | T.LI n => loadImmed(n,d,cc,an)
528 :     | T.LI32 w => loadImmedw(w,d,cc,an)
529 :     | T.LABEL l => loadLabel(l,d,cc,an)
530 :     | T.CONST c => loadConst(c,d,cc,an)
531 : monnier 245
532 : monnier 411 (* generic 32/64 bit support *)
533 :     | T.ADD(_,a,b) => arith(I.ADD,I.ADDCC,a,b,d,cc,COMMUTE,[],an)
534 :     | T.SUB(_,a,T.LI 0) => doExpr(a,d,cc,an)
535 :     | T.SUB(_,a,T.LI32 0w0) => doExpr(a,d,cc,an)
536 :     | T.SUB(_,a,b) => arith(I.SUB,I.SUBCC,a,b,d,cc,NOCOMMUTE,[],an)
537 :    
538 :     | T.ANDB(_,a,T.NOTB(_,b)) =>
539 :     arith(I.ANDN,I.ANDNCC,a,b,d,cc,NOCOMMUTE,[],an)
540 :     | T.ORB(_,a,T.NOTB(_,b)) =>
541 :     arith(I.ORN,I.ORNCC,a,b,d,cc,NOCOMMUTE,[],an)
542 :     | T.XORB(_,a,T.NOTB(_,b)) =>
543 :     arith(I.XNOR,I.XNORCC,a,b,d,cc,COMMUTE,[],an)
544 :     | T.ANDB(_,T.NOTB(_,a),b) =>
545 :     arith(I.ANDN,I.ANDNCC,b,a,d,cc,NOCOMMUTE,[],an)
546 :     | T.ORB(_,T.NOTB(_,a),b) =>
547 :     arith(I.ORN,I.ORNCC,b,a,d,cc,NOCOMMUTE,[],an)
548 :     | T.XORB(_,T.NOTB(_,a),b) =>
549 :     arith(I.XNOR,I.XNORCC,b,a,d,cc,COMMUTE,[],an)
550 :     | T.NOTB(_,T.XORB(_,a,b)) =>
551 :     arith(I.XNOR,I.XNORCC,a,b,d,cc,COMMUTE,[],an)
552 : monnier 245
553 : monnier 411 | T.ANDB(_,a,b) => arith(I.AND,I.ANDCC,a,b,d,cc,COMMUTE,[],an)
554 :     | T.ORB(_,a,b) => arith(I.OR,I.ORCC,a,b,d,cc,COMMUTE,[],an)
555 :     | T.XORB(_,a,b) => arith(I.XOR,I.XORCC,a,b,d,cc,COMMUTE,[],an)
556 :     | T.NOTB(_,a) => arith(I.XNOR,I.XNORCC,a,T.LI 0,d,cc,COMMUTE,[],an)
557 : monnier 245
558 : monnier 411 (* 32 bit support *)
559 :     | T.SRA(32,a,b) => shift(I.SRA,a,b,d,cc,an)
560 :     | T.SRL(32,a,b) => shift(I.SRL,a,b,d,cc,an)
561 :     | T.SLL(32,a,b) => shift(I.SLL,a,b,d,cc,an)
562 :     | T.ADDT(32,a,b)=>
563 :     arith(I.ADDCC,I.ADDCC,a,b,d,CC_REG,COMMUTE,trap32,an)
564 :     | T.SUBT(32,a,b)=>
565 :     arith(I.SUBCC,I.SUBCC,a,b,d,CC_REG,NOCOMMUTE,trap32,an)
566 :     | T.MULU(32,a,b) => extarith(P.umul,Mulu32.multiply,a,b,d,cc,COMMUTE)
567 :     | T.MULT(32,a,b) => extarith(P.smul,Mult32.multiply,a,b,d,cc,COMMUTE)
568 :     | T.DIVU(32,a,b) => extarith(P.udiv,divu32,a,b,d,cc,NOCOMMUTE)
569 :     | T.DIVT(32,a,b) => extarith(P.sdiv,divt32,a,b,d,cc,NOCOMMUTE)
570 : monnier 245
571 : monnier 411 (* 64 bit support *)
572 :     | T.SRA(64,a,b) => shift(I.SRAX,a,b,d,cc,an)
573 :     | T.SRL(64,a,b) => shift(I.SRLX,a,b,d,cc,an)
574 :     | T.SLL(64,a,b) => shift(I.SLLX,a,b,d,cc,an)
575 :     | T.ADDT(64,a,b)=>
576 :     arith(I.ADDCC,I.ADDCC,a,b,d,CC_REG,COMMUTE,trap64,an)
577 :     | T.SUBT(64,a,b)=>
578 :     arith(I.SUBCC,I.SUBCC,a,b,d,CC_REG,NOCOMMUTE,trap64,an)
579 :     | T.MULU(64,a,b) =>
580 :     muldiv64(I.MULX,Mulu64.multiply,a,b,d,cc,COMMUTE,an)
581 :     | T.MULT(64,a,b) =>
582 :     (muldiv64(I.MULX,Mult64.multiply,a,b,d,CC_REG,COMMUTE,an);
583 :     app emit trap64)
584 :     | T.DIVU(64,a,b) => muldiv64(I.UDIVX,divu64,a,b,d,cc,NOCOMMUTE,an)
585 :     | T.DIVT(64,a,b) => muldiv64(I.SDIVX,divt64,a,b,d,cc,NOCOMMUTE,an)
586 : monnier 245
587 : monnier 411 (* loads *)
588 :     | T.LOAD(8,a,mem) => load(I.LDUB,a,d,mem,cc,an)
589 : monnier 475 | T.CVTI2I(_,T.SIGN_EXTEND,_,T.LOAD(8,a,mem)) =>
590 : monnier 411 load(I.LDSB,a,d,mem,cc,an)
591 :     | T.LOAD(16,a,mem) => load(I.LDUH,a,d,mem,cc,an)
592 : monnier 475 | T.CVTI2I(_,T.SIGN_EXTEND,_,T.LOAD(16,a,mem)) =>
593 : monnier 411 load(I.LDSH,a,d,mem,cc,an)
594 :     | T.LOAD(32,a,mem) => load(I.LD,a,d,mem,cc,an)
595 :     | T.LOAD(64,a,mem) => load(if V9 then I.LDX else I.LDD,a,d,mem,cc,an)
596 : monnier 245
597 : monnier 411 (* conditional expression *)
598 :     | T.COND exp =>
599 :     Gen.compileCond{exp=exp,stm=stmt,defineLabel=defineLabel,
600 :     annotations=an,rd=d}
601 :    
602 :     (* misc *)
603 :     | T.SEQ(s,e) => (doStmt s; doExpr(e,d,cc,an))
604 :     | T.MARK(e,a) => doExpr(e,d,cc,a::an)
605 :     | e => doExpr(Gen.compile e,d,cc,an)
606 :    
607 :     (* generate a comparison with zero *)
608 :     and genCmp0(REG,_) = ()
609 :     | genCmp0(_,d) = emit(I.ARITH{a=I.SUBCC,r=d,i=zeroOpn,d=0})
610 :    
611 :     (* convert an expression into a floating point register *)
612 :     and fexpr(T.FREG(_,r)) = r
613 :     | fexpr e = let val d = newFreg() in doFexpr(e,d,[]); d end
614 :    
615 :     (* compute a floating point expression and put the result in d *)
616 :     and doFexpr(e,d,an) =
617 :     case e of
618 :     (* single precision *)
619 :     T.FREG(32,r) => fmoves(r,d,an)
620 :     | T.FLOAD(32,ea,mem) => fload(I.LDF,ea,d,mem,an)
621 :     | T.FLOAD_UNALIGNED(32,ea,mem) => fload(I.LDF,ea,d,mem,an)
622 :     | T.FADD(32,a,b) => farith(I.FADDs,a,b,d,an)
623 :     | T.FSUB(32,a,b) => farith(I.FSUBs,a,b,d,an)
624 :     | T.FMUL(32,a,b) => farith(I.FMULs,a,b,d,an)
625 :     | T.FDIV(32,a,b) => farith(I.FDIVs,a,b,d,an)
626 :     | T.FABS(32,a) => funary(I.FABSs,a,d,an)
627 :     | T.FNEG(32,a) => funary(I.FNEGs,a,d,an)
628 :     | T.FSQRT(32,a) => funary(I.FSQRTs,a,d,an)
629 :    
630 :     (* double precision *)
631 :     | T.FREG(64,r) => fmoved(r,d,an)
632 :     | T.FLOAD(64,ea,mem) => fload(I.LDDF,ea,d,mem,an)
633 :     | T.FLOAD_UNALIGNED(64,ea,mem) => fload(I.LDDF,ea,d,mem,an)
634 :     | T.FADD(64,a,b) => farith(I.FADDd,a,b,d,an)
635 :     | T.FSUB(64,a,b) => farith(I.FSUBd,a,b,d,an)
636 :     | T.FMUL(64,a,b) => farith(I.FMULd,a,b,d,an)
637 :     | T.FDIV(64,a,b) => farith(I.FDIVd,a,b,d,an)
638 :     | T.FABS(64,a) => funary(I.FABSd,a,d,an)
639 :     | T.FNEG(64,a) => funary(I.FNEGd,a,d,an)
640 :     | T.FSQRT(64,a) => funary(I.FSQRTd,a,d,an)
641 :    
642 :     (* quad precision *)
643 :     | T.FREG(128,r) => fmoveq(r,d,an)
644 :     | T.FADD(128,a,b) => farith(I.FADDq,a,b,d,an)
645 :     | T.FSUB(128,a,b) => farith(I.FSUBq,a,b,d,an)
646 :     | T.FMUL(128,a,b) => farith(I.FMULq,a,b,d,an)
647 :     | T.FDIV(128,a,b) => farith(I.FDIVq,a,b,d,an)
648 :     | T.FABS(128,a) => funary(I.FABSq,a,d,an)
649 :     | T.FNEG(128,a) => funary(I.FNEGq,a,d,an)
650 :     | T.FSQRT(128,a) => funary(I.FSQRTq,a,d,an)
651 :    
652 :     (* floating point to floating point *)
653 : monnier 475 | T.CVTF2F(ty,_,ty',e) =>
654 :     (case (ty,ty') of
655 :     (32,32) => doFexpr(e,d,an)
656 :     | (64,32) => funary(I.FsTOd,e,d,an)
657 : monnier 411 | (128,32) => funary(I.FsTOq,e,d,an)
658 : monnier 475 | (32,64) => funary(I.FdTOs,e,d,an)
659 :     | (64,64) => doFexpr(e,d,an)
660 : monnier 411 | (128,64) => funary(I.FdTOq,e,d,an)
661 :     | (32,128) => funary(I.FqTOs,e,d,an)
662 :     | (64,128) => funary(I.FqTOd,e,d,an)
663 :     | (128,128) => doFexpr(e,d,an)
664 :     | _ => error "CVTF2F"
665 :     )
666 :    
667 :     (* integer to floating point *)
668 : monnier 475 | T.CVTI2F(32,T.SIGN_EXTEND,_,e) =>
669 : monnier 411 app emit (P.cvti2s({i=opn e,d=d},reduceOpn))
670 : monnier 475 | T.CVTI2F(64,T.SIGN_EXTEND,_,e) =>
671 : monnier 411 app emit (P.cvti2d({i=opn e,d=d},reduceOpn))
672 : monnier 475 | T.CVTI2F(128,T.SIGN_EXTEND,_,e) =>
673 : monnier 411 app emit (P.cvti2q({i=opn e,d=d},reduceOpn))
674 :    
675 :     | T.FSEQ(s,e) => (doStmt s; doFexpr(e,d,an))
676 :     | T.FMARK(e,a) => doFexpr(e,d,a::an)
677 :     | _ => error "doFexpr"
678 :    
679 :     and doCCexpr(T.CMP(ty,cond,e1,e2),65,an) =
680 :     doExpr(T.SUB(ty,e1,e2),newReg(),CC,an)
681 :     | doCCexpr(T.CMP _,d,an) = error "doCCexpr"
682 :     | doCCexpr(_,65,an) = error "doCCexpr"
683 :     | doCCexpr(T.CC 65,d,an) = error "doCCexpr"
684 :     | doCCexpr(T.CC r,d,an) = move(r,d,an)
685 :     | doCCexpr(T.CCMARK(e,a),d,an) = doCCexpr(e,d,a::an)
686 :     | doCCexpr e = error "doCCexpr"
687 :    
688 :     and ccExpr e = let val d = newReg() in doCCexpr(e,d,[]); d end
689 :    
690 :     (* convert an expression into an operand *)
691 :     and opn(T.LI 0) = zeroOpn
692 :     | opn(T.LI32 0w0) = zeroOpn
693 :     | opn(T.CONST c) = I.CONST c
694 :     | opn(T.LABEL l) = I.LAB l
695 :     | opn(e as T.LI n) = if immed13 n then I.IMMED n else I.REG(expr e)
696 :     | opn(e as T.LI32 n) =
697 :     if immed13w n then I.IMMED(W.toIntX n) else I.REG(expr e)
698 :     | opn e = I.REG(expr e)
699 :    
700 :    
701 : monnier 429 fun cc((r as T.CCR(T.CC 65))::l) = r::cc l
702 :     | cc(T.CCR(T.CC r)::l) = T.GPR(T.REG(32,r))::cc l
703 :     | cc(r::l) = r::cc l
704 :     | cc [] = []
705 :     in S.STREAM
706 :     { beginCluster= beginCluster,
707 :     endCluster = endCluster,
708 :     emit = doStmt,
709 :     pseudoOp = pseudoOp,
710 :     defineLabel = defineLabel,
711 :     entryLabel = entryLabel,
712 :     comment = comment,
713 :     annotation = annotation,
714 :     exitBlock = fn regs => exitBlock(cc regs),
715 :     alias = alias,
716 :     phi = phi
717 : monnier 411 }
718 : monnier 245 end
719 :    
720 :     end
721 :    
722 : monnier 411 (*
723 :     * Machine code generator for SPARC.
724 : monnier 245 *
725 : monnier 411 * The SPARC architecture has 32 general purpose registers (%g0 is always 0)
726 :     * and 32 single precision floating point registers.
727 : monnier 245 *
728 : monnier 411 * Some Ugliness: double precision floating point registers are
729 :     * register pairs. There are no double precision moves, negation and absolute
730 :     * values. These require two single precision operations. I've created
731 :     * composite instructions FMOVd, FNEGd and FABSd to stand for these.
732 : monnier 245 *
733 : monnier 411 * All integer arithmetic instructions can optionally set the condition
734 :     * code register. We use this to simplify certain comparisons with zero.
735 : monnier 245 *
736 : monnier 411 * Integer multiplication, division and conversion from integer to floating
737 :     * go thru the pseudo instruction interface, since older sparcs do not
738 :     * implement these instructions in hardware.
739 : monnier 245 *
740 : monnier 411 * In addition, the trap instruction for detecting overflow is a parameter.
741 :     * This allows different trap vectors to be used.
742 : monnier 245 *
743 : monnier 411 * -- Allen
744 :     *)

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