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 235 - (view) (download)

1 : monnier 225 (*
2 :     * Machine code generator for SPARC.
3 :     *
4 :     * The SPARC architecture has 32 general purpose registers (%g0 is always 0)
5 :     * and 32 single precision floating point registers.
6 :     *
7 :     * Some Ugliness: double precision floating point registers are
8 :     * register pairs. There are no double precision moves, negation and absolute
9 :     * values. These require two single precision operations. I've created
10 :     * composite instructions FMOVd, FNEGd and FABSd to stand for these.
11 :     *
12 :     * All integer arithmetic instructions can optionally set the condition
13 :     * code register. We use this to simplify certain comparisons with zero.
14 :     *
15 :     * Integer multiplication, division and conversion from integer to floating
16 :     * go thru the pseudo instruction interface, since older sparcs do not
17 :     * implement these instructions in hardware.
18 :     *
19 :     * In addition, the trap instruction for detecting overflow is a parameter.
20 :     * This allows different trap vectors to be used.
21 :     *
22 :     * The virtual register 65 is used to represent the %psr register.
23 :     *
24 :     * -- Allen
25 :     *)
26 :    
27 :     functor Sparc
28 :     (structure SparcInstr : SPARCINSTR
29 :     structure SparcMLTree : MLTREE where Region = SparcInstr.Region
30 :     and Constant = SparcInstr.Constant
31 :     structure Flowgen : FLOWGRAPH_GEN where I = SparcInstr
32 :     and T = SparcMLTree
33 :     and B = SparcMLTree.BNames
34 :     structure PseudoInstrs : SPARC_PSEUDO_INSTR where I = SparcInstr
35 :     (* DBM: sharing/defn conflict:
36 :     sharing SparcInstr.Region = SparcMLTree.Region
37 :     sharing Flowgen.I=PseudoInstrs.I=SparcInstr
38 :     sharing Flowgen.T=SparcMLTree
39 :     sharing SparcMLTree.Constant = SparcInstr.Constant
40 :     sharing SparcMLTree.BNames = Flowgen.B
41 :     *)
42 :     val overflowtrap : SparcInstr.instruction list
43 :     ) : MLTREECOMP =
44 :     struct
45 :     structure F = Flowgen
46 :     structure T = SparcMLTree
47 :     structure R = SparcMLTree.Region
48 :     structure I = SparcInstr
49 :     structure C = SparcInstr.C
50 :     structure LE = LabelExp
51 :     structure W = Word32
52 :     structure P = PseudoInstrs
53 :    
54 :     datatype trapping = TRAPS | SILENT
55 :     datatype commutative = COMMUTE | DONTCOMMUTE
56 :     datatype target =
57 :     CC (* condition code only *)
58 :     | REG (* register only *)
59 :     | CC_REG (* conditional code and register *)
60 :    
61 :     fun error msg = MLRiscErrorMsg.impossible ("Sparc." ^ msg)
62 :    
63 :     val emitInstr = F.emitInstr
64 :     val emit = F.emitInstr
65 :     fun newReg () = C.newReg()
66 :     fun newFreg() = C.newFreg()
67 :    
68 :     (* load/store has 13 bits sign extended immediates *)
69 :     fun immed13 n = ~4096 <= n andalso n < 4096
70 : monnier 235 fun immed13w w = let
71 :     val x = W.~>>(w,0w12)
72 :     in x=0w0 orelse (W.notb x)=0w0
73 :     end
74 : monnier 225
75 :     (* split into 22 high bits/10 low bits *)
76 :    
77 :     fun splitw w =
78 :     {hi=W.toInt(W.>>(w,0w10)), lo=W.toInt(W.andb(w,0wx3ff))}
79 :    
80 :     fun split n = splitw(W.fromInt n)
81 :    
82 :     (* load immediate *)
83 :     fun loadImmed(n,d) =
84 :     if immed13 n then emit(I.ARITH{a=I.OR,r=0,i=I.IMMED n,cc=false,d=d})
85 :     else let
86 :     val t = newReg()
87 :     val {hi,lo} = split n
88 :     in
89 :     if lo = 0 then emit(I.SETHI{i=hi,d=d})
90 :     else
91 :     (emit(I.SETHI{i=hi,d=t});
92 :     emit(I.ARITH{a=I.OR,r=t,i=I.IMMED lo,cc=false,d=d}))
93 :     end
94 :    
95 :     (* load word constant *)
96 :     fun loadImmed32(w,d) =
97 :     if immed13w w then
98 :     emit(I.ARITH{a=I.OR,r=0,i=I.IMMED(W.toIntX w),cc=false,d=d})
99 :     else let
100 :     val t = newReg()
101 :     val {hi,lo} = splitw w
102 :     in
103 :     if lo = 0 then emit(I.SETHI{i=hi,d=d})
104 :     else
105 :     (emit(I.SETHI{i=hi,d=t});
106 :     emit(I.ARITH{a=I.OR,r=t,i=I.IMMED lo,cc=false,d=d}))
107 :     end
108 :    
109 :     (* load constant *)
110 :     fun loadConst(c,d) = emit(I.ARITH{a=I.OR,r=0,i=I.CONST c,cc=false,d=d})
111 :    
112 :     (* load label expression *)
113 :     fun loadLabel(lab,d) = emit(I.ARITH{a=I.OR,r=0,i=I.LAB lab,cc=false,d=d})
114 :    
115 :     (* emit parallel copies *)
116 :     fun copy(dst,src) =
117 :     emit(I.COPY{dst=dst, src=src, impl=ref NONE,
118 :     tmp=case dst
119 :     of [_] => NONE
120 :     | _ => SOME(I.Direct(newReg()))})
121 :    
122 :     fun fcopy(dst,src) =
123 :     emit(I.FCOPY{dst=dst, src=src, impl=ref NONE,
124 :     tmp=case dst
125 :     of [_] => NONE
126 :     | _ => SOME(I.FDirect(newReg()))})
127 :    
128 :     (* move register s to register d *)
129 :     fun move(s,d) =
130 :     if s = d orelse d = 0 then ()
131 :     else emit(I.COPY{dst=[d],src=[s],tmp=NONE, impl=ref NONE})
132 :    
133 :     (* move floating point register s to register d *)
134 :     fun fmove(s,d) =
135 :     if s = d then ()
136 :     else emit(I.FCOPY{dst=[d],src=[s],tmp=NONE,impl=ref NONE})
137 :    
138 :     (* order the generation of instructions *)
139 :     fun order(gen,e1,e2,T.LR) = (gen e1, gen e2)
140 :     | order(gen,e1,e2,T.RL) = let
141 :     val y = gen e2
142 :     in (gen e1, y)
143 :     end
144 :    
145 :     (* generate arithmetic *)
146 :     fun arith(opcode,e1,e2,ord,d,cc,commutative,checkOverflow) =
147 :     let val d = case cc of
148 :     CC => 0
149 :     | _ => d
150 :     val cc = case cc of
151 :     CC => true
152 :     | CC_REG => true
153 :     | REG => false
154 :     in case (order(genOperand,e1,e2,ord),commutative) of
155 :     ((i,I.REG r),COMMUTE) => emit(I.ARITH{a=opcode,r=r,i=i,d=d,cc=cc})
156 :     | ((I.REG r,i),_) => emit(I.ARITH{a=opcode,r=r,i=i,d=d,cc=cc})
157 :     | ((a,i),_) =>
158 :     let val r = newReg()
159 :     in emit(I.ARITH{a=I.OR,r=0,i=a,d=r,cc=false});
160 :     emit(I.ARITH{a=opcode,r=r,i=i,d=d,cc=cc})
161 :     end;
162 :     case checkOverflow of
163 :     TRAPS => app emit overflowtrap
164 :     | SILENT => ()
165 :     end
166 :    
167 :     (* generate shift *)
168 :     and shift(opcode,e1,e2,ord,d) =
169 :     case order(genOperand,e1,e2,ord) of
170 :     (I.REG r,i) => emit(I.SHIFT{s=opcode,r=r,i=i,d=d})
171 :     | (a,i) => let val r = newReg()
172 :     in emit(I.ARITH{a=I.OR,r=0,i=a,d=r,cc=false});
173 :     emit(I.SHIFT{s=opcode,r=r,i=i,d=d})
174 :     end
175 :    
176 :     (* generate external arithmetic operation *)
177 :     and externalarith(gen,e1,e2,ord,d,cc,commutative) =
178 :     let val instrs =
179 :     case (order(genOperand,e1,e2,ord),commutative) of
180 :     ((i,I.REG r),COMMUTE) => gen({r=r,i=i,d=d},reduceOperand)
181 :     | ((I.REG r,i),_) => gen({r=r,i=i,d=d},reduceOperand)
182 :     | ((a,i),_) => let val r = newReg()
183 :     in emit(I.ARITH{a=I.OR,r=0,i=a,d=r,cc=false});
184 :     gen({r=r,i=i,d=d},reduceOperand)
185 :     end
186 :     in app emit instrs;
187 :     genCmp0(cc,d)
188 :     end
189 :    
190 :     (* Convert an operand into a register *)
191 :     and reduceOperand(I.REG r) = r
192 :     | reduceOperand(I.IMMED 0) = 0 (* %g0 *)
193 :     | reduceOperand i = let val d = newReg()
194 :     in emit(I.ARITH{a=I.OR,r=0,i=i,d=d,cc=false}); d end
195 :    
196 :     (* floating point arithmetic *)
197 :     and funary(opcode,e,d) = emit(I.FPop1{a=opcode,r=genFexpr e,d=d})
198 :    
199 :     and farith(opcode,e1,e2,d,ord) =
200 :     let val (r1,r2) = order(genFexpr,e1,e2,ord)
201 :     in emit(I.FPop2{a=opcode,r1=r1,r2=r2,d=d})
202 :     end
203 :    
204 :     (* compute addressing mode
205 :     * Sparc has only two addressing modes: displacement and indexed.
206 :     *)
207 :     and addrMode(T.ADD(e,T.LI n)) =
208 :     if immed13 n then (genExpr e,I.IMMED n)
209 :     else let val t = newReg()
210 :     val _ = loadImmed(n,t)
211 :     in (t,genOperand e) end
212 :     | addrMode(T.ADD(e,T.CONST c)) = (genExpr e,I.CONST c)
213 :     | addrMode(T.ADD(e,T.LABEL l)) = (genExpr e,I.LAB l)
214 :     | addrMode(T.ADD(i as T.LI _,e)) = addrMode(T.ADD(e,i))
215 :     | addrMode(T.ADD(T.CONST c,e)) = (genExpr e,I.CONST c)
216 :     | addrMode(T.ADD(T.LABEL l,e)) = (genExpr e,I.LAB l)
217 :     | addrMode(T.ADD(e1,e2)) = (genExpr e1,I.REG(genExpr e2))
218 :     | addrMode(T.SUB(e,T.LI n,_)) = addrMode(T.ADD(e,T.LI(~n)))
219 :     | addrMode(T.LABEL l) = (0,I.LAB l)
220 :     | addrMode addr = (genExpr addr,I.IMMED 0)
221 :    
222 :     (* load integer values *)
223 :     and load(opcode,addr,mem,d) =
224 :     let val (r,i) = addrMode addr
225 :     in emit(I.LOAD{l=opcode,r=r,i=i,d=d,mem=mem}) end
226 :    
227 :     (* store integer values *)
228 :     and store(opcode,addr,data,mem) =
229 :     let val (r,i) = addrMode addr
230 :     in emit(I.STORE{s=opcode,d=data,r=r,i=i,mem=mem}) end
231 :    
232 :     (* load floating point value *)
233 :     and fload(opcode,addr,mem,d) =
234 :     let val (r,i) = addrMode addr
235 :     in emit(I.FLOAD{l=opcode,r=r,i=i,d=d,mem=mem}) end
236 :    
237 :     (* store floating point value *)
238 :     and fstore(opcode,addr,data,mem) =
239 :     let val (r,i) = addrMode addr
240 :     in emit(I.FSTORE{s=opcode,d=data,r=r,i=i,mem=mem}) end
241 :    
242 :     and jmp(addr,labs) =
243 :     let val (r,i) = addrMode addr
244 :     in emit(I.JMP{r=r,i=i,labs=labs,nop=true}) end
245 :    
246 :     and call(addr,defs,uses) =
247 :     let val (r,i) = addrMode addr
248 :     fun live([],acc) = acc
249 :     | live(T.GPR(T.REG r)::regs,acc) = live(regs, C.addReg(r,acc))
250 :     | live(T.CCR(T.CC 65)::regs,acc) = live(regs, acc)
251 :     | live(T.CCR(T.CC cc)::regs,acc) = live(regs, C.addReg(cc,acc))
252 :     | live(T.FPR(T.FREG f)::regs,acc) = live(regs, C.addFreg(f,acc))
253 :     | live(_::regs, acc) = live(regs, acc)
254 :     val defs=live(defs,C.empty)
255 :     val uses=live(uses,C.empty)
256 :     in case (r,i) of
257 :     (0,I.LAB(LE.LABEL l)) =>
258 :     emit(I.CALL{label=l,defs=C.addReg(C.linkReg,defs),uses=uses,
259 :     nop=true})
260 :     | _ => emit(I.JMPL{r=r,i=i,d=C.linkReg,defs=defs,uses=uses,nop=true})
261 :     end
262 :    
263 :     (* Generate code for a statement *)
264 :     and doStmt stmt =
265 :     case stmt of
266 :     T.MV(d,e) => doExpr(e,d,REG)
267 :     | T.FMV(d,e) => doFexpr(e,d)
268 :     | T.CCMV(d,e) => doCCexpr(e,d)
269 :     | T.COPY(dst,src) => copy(dst,src)
270 :     | T.FCOPY(dst,src) => fcopy(dst,src)
271 :     | T.JMP(T.LABEL(LE.LABEL l),_) =>
272 :     emit(I.Bicc{b=I.BA,a=true,label=l,nop=false})
273 :     | T.JMP(e,labs) => jmp(e,labs)
274 :     | T.CALL(e,def,use) => call(e,def,use)
275 :     | T.RET => emit(I.RET{leaf=false,nop=true})
276 :     | T.STORE8(addr,data,mem) => store(I.STB,addr,genExpr data,mem)
277 :     | T.STORE32(addr,data,mem) => store(I.ST,addr,genExpr data,mem)
278 :     | T.STORED(addr,data,mem) => fstore(I.STDF,addr,genFexpr data,mem)
279 :     | T.STORECC(addr,data,mem) => store(I.ST,addr,genCCexpr data,mem)
280 :     | T.BCC(cond,cc,lab) => branch(cond,cc,lab)
281 :     | T.FBCC(cond,cc,lab) => fbranch(cond,cc,lab)
282 :    
283 :     (*
284 :     * generate conditional branches
285 :     * Perform a subtract (with cc), then branch on cc.
286 :     * Note: when we are comparing with zero, do something smarter.
287 :     *)
288 :     and branch(_,T.CMP(cond,e1,e2,order),lab) =
289 :     let val (cond,e1,e2) =
290 :     case e1 of
291 :     (T.LI _ | T.LI32 _ | T.CONST _ | T.LABEL _) => (flip cond,e2,e1)
292 :     | _ => (cond,e1,e2)
293 :     in doExpr(T.SUB(e1,e2,order),newReg(),CC); br(cond,lab)
294 :     end
295 :     | branch(cond,T.CC 65,lab) = (* psr *)
296 :     br(cond,lab)
297 :     | branch(cond,T.CC r,lab) =
298 :     (genCmp0(CC,r); br(cond,lab))
299 :     | branch _ = error "branch"
300 :    
301 :     and cond T.LT = I.BL
302 :     | cond T.LTU = I.BCS
303 :     | cond T.LE = I.BLE
304 :     | cond T.LEU = I.BLEU
305 :     | cond T.EQ = I.BE
306 :     | cond T.NEQ = I.BNE
307 :     | cond T.GE = I.BGE
308 :     | cond T.GEU = I.BCC
309 :     | cond T.GT = I.BG
310 :     | cond T.GTU = I.BGU
311 :    
312 :     (* exchange the order of the arguments to a comparison *)
313 :     and flip T.LT = T.GT
314 :     | flip T.LTU = T.GTU
315 :     | flip T.LE = T.GE
316 :     | flip T.LEU = T.GEU
317 :     | flip T.EQ = T.EQ
318 :     | flip T.NEQ = T.NEQ
319 :     | flip T.GE = T.LE
320 :     | flip T.GEU = T.LEU
321 :     | flip T.GT = T.LT
322 :     | flip T.GTU = T.LTU
323 :    
324 :     and fcond T.== = I.FBE
325 :     | fcond T.?<> = I.FBNE
326 :     | fcond T.? = I.FBU
327 :     | fcond T.<=> = I.FBO
328 :     | fcond T.> = I.FBG
329 :     | fcond T.>= = I.FBGE
330 :     | fcond T.?> = I.FBUG
331 :     | fcond T.?>= = I.FBUGE
332 :     | fcond T.< = I.FBL
333 :     | fcond T.<= = I.FBLE
334 :     | fcond T.?< = I.FBUL
335 :     | fcond T.?<= = I.FBULE
336 :     | fcond T.<> = I.FBLG
337 :     | fcond T.?= = I.FBUE
338 :    
339 :     and br(c,lab) = emit(I.Bicc{b=cond c,a=true,label=lab,nop=true})
340 :    
341 :     and fbranch(_,T.FCMP(cond,e1,e2,ord),lab) =
342 :     let val (r1,r2) = order(genFexpr,e1,e2,ord)
343 :     in emit(I.FCMP{cmp=I.FCMPd,r1=r1,r2=r2,nop=true});
344 :     emit(I.FBfcc{b=fcond cond,a=false,label=lab,nop=true})
345 :     end
346 :     | fbranch _ = error "fbranch"
347 :    
348 :     (* compute expr and write the result to register d,
349 :     * optionally set the condition code register.
350 :     *)
351 :     and doExpr(expr,d,cc) =
352 :     case expr of
353 :     T.REG r => (move(r,d); genCmp0(cc,r))
354 :     | T.LI n => (loadImmed(n,d); genCmp0(cc,d))
355 :     | T.LI32 w => (loadImmed32(w,d); genCmp0(cc,d))
356 :     | T.LABEL lab => (loadLabel(lab,d); genCmp0(cc,d))
357 :     | T.CONST c => (loadConst(c,d); genCmp0(cc,d))
358 :     | T.ADD(e1,e2) => arith(I.ADD,e1,e2,T.LR,d,cc,COMMUTE,SILENT)
359 :     | T.SUB(e1,T.LI 0,_) => doExpr(e1,d,cc)
360 :     | T.SUB(e1,T.LI32 0w0,_) => doExpr(e1,d,cc)
361 :     | T.SUB(e1,e2,ord) => arith(I.SUB,e1,e2,ord,d,cc,DONTCOMMUTE,SILENT)
362 :     | T.ADDT(e1,e2) => arith(I.ADD,e1,e2,T.LR,d,CC_REG,COMMUTE,TRAPS)
363 :     | T.SUBT(e1,e2,ord)=> arith(I.SUB,e1,e2,ord,d,CC_REG,DONTCOMMUTE,TRAPS)
364 :     | T.ANDB(e1,e2) => arith(I.AND,e1,e2,T.LR,d,cc,COMMUTE,SILENT)
365 :     | T.ORB(e1,e2) => arith(I.OR,e1,e2,T.LR,d,cc,COMMUTE,SILENT)
366 :     | T.XORB(e1,e2) => arith(I.XOR,e1,e2,T.LR,d,cc,COMMUTE,SILENT)
367 :     | T.SRA(e1,e2,ord) => (shift(I.SRA,e1,e2,ord,d); genCmp0(cc,d))
368 :     | T.SRL(e1,e2,ord) => (shift(I.SRL,e1,e2,ord,d); genCmp0(cc,d))
369 :     | T.SLL(e1,e2,ord) => (shift(I.SLL,e1,e2,ord,d); genCmp0(cc,d))
370 :     | T.LOAD8(addr,mem) => (load(I.LDUB,addr,mem,d); genCmp0(cc,d))
371 :     | T.LOAD32(addr,mem) => (load(I.LD,addr,mem,d); genCmp0(cc,d))
372 :     | T.SEQ(stmt,e) => (doStmt stmt; doExpr(e,d,cc))
373 :     | T.MULU(e1,e2) => externalarith(P.umul,e1,e2,T.LR,d,cc,COMMUTE)
374 :     | T.MULT(e1,e2) => externalarith(P.smul,e1,e2,T.LR,d,cc,COMMUTE)
375 :     | T.DIVU(e1,e2,ord)=> externalarith(P.udiv,e1,e2,ord,d,cc,DONTCOMMUTE)
376 :     | T.DIVT(e1,e2,ord)=> externalarith(P.sdiv,e1,e2,ord,d,cc,DONTCOMMUTE)
377 :    
378 :     (* Compare with zero if cc is set *)
379 :     and genCmp0(cc,d) =
380 :     case cc of
381 :     REG => ()
382 :     | _ => emit(I.ARITH{a=I.SUB,r=d,i=I.IMMED 0,d=0,cc=true})
383 :    
384 :     and doFexpr(expr,d) =
385 :     case expr of
386 :     T.FREG r => fmove(r,d)
387 :     | T.LOADD(addr,mem) => fload(I.LDDF,addr,mem,d)
388 :     | T.FADDD(e1,e2) => farith(I.FADDd,e1,e2,d,T.LR)
389 :     | T.FMULD(e1,e2) => farith(I.FMULd,e1,e2,d,T.LR)
390 :     | T.FSUBD(e1,e2,ord) => farith(I.FSUBd,e1,e2,d,ord)
391 :     | T.FDIVD(e1,e2,ord) => farith(I.FDIVd,e1,e2,d,ord)
392 :     | T.FABSD e => funary(I.FABSd,e,d)
393 :     | T.FNEGD e => funary(I.FNEGd,e,d)
394 :     | T.CVTI2D e => app emit
395 :     (P.cvti2d({i=genOperand e,d=d},reduceOperand))
396 :     | T.FSEQ(stmt,e) => (doStmt stmt; doFexpr(e,d))
397 :    
398 :     and doCCexpr(T.CMP(cond,e1,e2,ord),65) = (* psr *)
399 :     doExpr(T.SUB(e1,e2,ord),newReg(),CC)
400 :     | doCCexpr(_,65) = error "doCCexpr 65"
401 :     | doCCexpr(expr,d) =
402 :     case expr of
403 :     T.CC r => move(r,d)
404 :     | T.LOADCC(addr,mem) => load(I.LD,addr,mem,d)
405 :     | _ => error "doCCexpr"
406 :    
407 :     (*
408 :     * generate an expression and return the register that holds its value
409 :     *)
410 :     and genExpr(T.LI 0) = 0 (* register %g0 *)
411 :     | genExpr(T.LI32 0w0) = 0 (* register %g0 *)
412 :     | genExpr(T.REG r) = r
413 :     | genExpr expr = let val r = newReg() in doExpr(expr,r,REG); r end
414 :    
415 :     and genFexpr(T.FREG r) = r
416 :     | genFexpr expr = let val r = newFreg() in doFexpr(expr,r); r end
417 :    
418 :     and genCCexpr(T.CC 65) = error "genCCexpr"
419 :     | genCCexpr(T.CC r) = r
420 :     | genCCexpr expr = let val r = newReg() in doCCexpr(expr,r); r end
421 :    
422 :     (*
423 :     * generate an expression and returns it as an operand
424 :     *)
425 :     and genOperand(T.LI 0) = I.REG 0
426 :     | genOperand(T.LI32 0w0) = I.REG 0
427 :     | genOperand(e as T.LI n) =
428 :     if immed13 n then I.IMMED n else I.REG(genExpr e)
429 :     | genOperand(e as T.LI32 w) =
430 :     if immed13w w then I.IMMED(W.toIntX w) else I.REG(genExpr e)
431 :     | genOperand(T.CONST c) = I.CONST c
432 :     | genOperand(T.LABEL l) = I.LAB l
433 :     | genOperand(e) = I.REG(genExpr e)
434 :    
435 :     fun mltreeComp mltree =
436 :     let (* condition code registers are mapped onto general registers *)
437 :     fun cc (x as T.CCR(T.CC 65),l) = l
438 :     | cc (T.CCR(T.CC cc),l) = T.GPR(T.REG cc)::l
439 :     | cc (x,l) = x::l
440 :     fun comp(T.BEGINCLUSTER) = F.beginCluster()
441 :     | comp(T.PSEUDO_OP p) = F.pseudoOp p
442 :     | comp(T.DEFINELABEL lab) = F.defineLabel lab
443 :     | comp(T.ENTRYLABEL lab) = F.entryLabel lab
444 :     | comp(T.CODE stmts) = app doStmt stmts
445 :     | comp(T.BLOCK_NAME name) = F.blockName name
446 :     | comp(T.ORDERED mltrees) = F.ordered mltrees
447 :     | comp(T.ESCAPEBLOCK regs) = F.exitBlock(foldl cc [] regs)
448 :     | comp(T.ENDCLUSTER regmap) = F.endCluster regmap
449 :     in comp mltree
450 :     end
451 :    
452 :     val mlriscComp = doStmt
453 :    
454 :     end
455 :    
456 :     (*
457 :     * $Log: sparc.sml,v $
458 : monnier 235 * Revision 1.1.1.1 1999/01/04 21:56:27 george
459 :     * Version 110.12
460 :     *
461 : monnier 225 * Revision 1.4 1998/09/30 19:36:54 dbm
462 :     * fixing sharing/defspec conflict
463 :     *
464 :     * Revision 1.3 1998/08/12 13:36:15 leunga
465 :     *
466 :     *
467 :     * Fixed the 2.0 + 2.0 == nan bug by treating FCMP as instrs with delay slots
468 :     *
469 :     * Revision 1.2 1998/08/11 14:03:25 george
470 :     * Exposed emitInstr in MLTREECOMP to allow a client to directly
471 :     * inject native instructions into the flowgraph.
472 :     *
473 :     * Revision 1.1.1.1 1998/08/05 19:38:49 george
474 :     * Release 110.7.4
475 :     *
476 :     *)

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