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/compiler/OldCGen/mips/mips.sml
ViewVC logotype

Annotation of /sml/trunk/src/compiler/OldCGen/mips/mips.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 16 - (view) (download)

1 : monnier 16 (* mips.sml
2 :     *
3 :     * Copyright (c) 1992 by AT&T Bell Laboratories
4 :     *
5 :     *)
6 :    
7 :     functor MipsCM(structure C: CODER
8 :     where type 'a instruction = 'a MipsInstrSet.instruction
9 :     and type 'a sdi = 'a MipsInstrSet.sdi
10 :     structure E: ENDIAN
11 :     structure MachSpec: MACH_SPEC) : CMACHINE =
12 :     struct
13 :    
14 :     structure D = MachSpec.ObjDesc
15 :     val dtoi = LargeWord.toInt (* convert descriptors to int *)
16 :    
17 :     structure M = MipsInstrSet
18 :     open M
19 :     type EA = C.label M.EA
20 :    
21 :     val error = ErrorMsg.impossible
22 :    
23 :     val wtoi = Word.toIntX
24 :    
25 :     exception BadReal = C.BadReal
26 :     val align = fn () => ()
27 :     val mark = C.mark
28 :     val emitlong = C.emitLong
29 :     val realconst = C.emitReal
30 :     val emitstring = C.emitString
31 :     val newlabel = M.ImmedLab o C.newLabel
32 :     val immed = M.Immed
33 :     val emitSDI = C.emitSDI
34 :     val emit = C.emit
35 :    
36 :     fun emitlab(k,ImmedLab lab) = C.emitLabel(lab,k)
37 :     | emitlab _ = error "MipsCM.emitlab"
38 :    
39 :     fun define(ImmedLab lab) = C.define lab
40 :     | define _ = error "MipsCM.define"
41 :    
42 :    
43 :     (* Register Map
44 :     Reg gc desc
45 :     -------------------------------------
46 :     0 n zero
47 :     1 n temporary reg
48 :     2 y standard arg
49 :     3 y standard continuation
50 :     4 y standard closure
51 :     5 y standard link
52 :     6-18 y misc regs
53 :     19 n limit reg
54 :     20 n var pointer
55 :     21 n temporary reg & heapExhausted reg.
56 :     22 n store pointer
57 :     23 n allocation pointer
58 :     24 n base reg
59 :     25 n temporary reg & maskReg
60 :     26-27 n reserved for OS kernel
61 :     28 n C global pointer
62 :     29 n C stack pointer
63 :     30 y exnptr
64 :     31 n temporary reg & gclink register
65 :     *)
66 :     val varptr_indexable = true
67 :     val standardlink : EA = Direct(Reg 5)
68 :     val standardarg : EA = Direct(Reg 2)
69 :     val standardcont : EA = Direct(Reg 3)
70 :     val standardclosure : EA = Direct(Reg 4)
71 :     val miscregs : EA list = map (Direct o Reg)
72 :     [6,7,8,9,10,11,12,13,14,15,16,17,18]
73 :    
74 :     val limit as Direct limit' : EA = Direct(M.limitReg)
75 :     val varptr : EA = Direct(Reg 20)
76 :     val stackptr' = (Reg 29)
77 :    
78 :     val storeptr as Direct storeptr' : EA = Direct(Reg 22)
79 :     val dataptr as Direct dataptr' : EA = Direct(M.allocReg)
80 :    
81 :     val exnptr = Direct(M.exnptrReg)
82 :    
83 :     val floatregs: EA list = map (Direct o Freg)
84 :     [0,2,4,6,8,10,12,14,16,18]
85 :     val savedfpregs: EA list = map (Direct o Freg) [20,22,24,26,28]
86 :    
87 :     val arithtemps: EA list = []
88 :    
89 :     local
90 :     exception NoTmpRegs
91 :     val tmpRegs = [M.heapExhaustedReg,M.maskReg,M.linkReg,Reg 1]
92 :     val queue = ref tmpRegs
93 :     in
94 :     fun getTmpReg() = case !queue
95 :     of hd :: rest => (queue := rest; hd)
96 :     | _ => raise NoTmpRegs
97 :     fun freeTmpReg reg = queue := !queue @ [reg]
98 :    
99 :     (*** should be cleaned up in the future ***)
100 :     val tmpfpreg = (Freg 30)
101 :    
102 :     end
103 :    
104 :    
105 :     fun emitBRANCH(cond,rs,rt,lab) =
106 :     let val flabel = C.newLabel()
107 :     val tmpR = getTmpReg()
108 :     in
109 :     emitSDI(M.BRANCH(cond,rs,rt,lab,tmpR,flabel));
110 :     C.define flabel;
111 :     freeTmpReg tmpR
112 :     end
113 :    
114 :     fun emitBRANCH_COP1(cond,lab) =
115 :     let val flabel = C.newLabel()
116 :     val tmpR = getTmpReg()
117 :     in
118 :     emitSDI(M.BRANCH_COP1(cond,lab,tmpR,flabel));
119 :     C.define flabel;
120 :     freeTmpReg tmpR
121 :     end
122 :    
123 :    
124 :     datatype immedSize = IMMED16 | IMMED32
125 :    
126 :     fun immed_size n = if (~32764<=n) andalso (n<=32764)
127 :     then IMMED16
128 :     else IMMED32
129 :    
130 :     val immed32 = M.Immed32
131 :    
132 :     fun load_immed(n,r) =
133 :     case (immed_size n)
134 :     of IMMED16 => emit(M.ADD(r,Reg 0,Immed16Op n))
135 :     | IMMED32 => let val (hi,lo) = M.split n
136 :     in emit (M.LUI(r,Immed16Off(wtoi hi)));
137 :     emit (M.ADD(r,r,Immed16Op(wtoi lo)))
138 :     end
139 :    
140 :     local
141 :     structure W = Word32
142 :     in
143 :     fun load_immed32(w, rd) = let
144 :     val lo = W.andb(w, 0w65535)
145 :     val hi = W.~>>(w, 0w16)
146 :     in emit(M.LUI(rd, Immed16Off(W.toIntX hi)));
147 :     emit(M.OR(rd, rd, Immed16Op(W.toInt lo)))
148 :     end
149 :     end
150 :    
151 :     fun do_immed_arith(instr,rt,rs,n) =
152 :     case (immed_size n)
153 :     of IMMED16 => emit(instr(rt,rs,Immed16Op n))
154 :     | IMMED32 => let
155 :     val (hi,lo) = M.split n
156 :     val tmpR = getTmpReg()
157 :     in
158 :     emit (M.LUI(tmpR,Immed16Off(wtoi hi)));
159 :     emit (M.ADD(tmpR,tmpR,Immed16Op(wtoi lo)));
160 :     emit (instr(rt,rs,RegOp tmpR));
161 :     freeTmpReg tmpR
162 :     end
163 :    
164 :     fun do_immed_mem(instr,rt,base,n) =
165 :     case (immed_size n)
166 :     of IMMED16 => emit(instr(rt,base,Immed16Off n))
167 :     | IMMED32 => let
168 :     val (hi,lo) = M.split n
169 :     val tmpR = getTmpReg()
170 :     in
171 :     emit (M.LUI(tmpR,Immed16Off(wtoi hi)));
172 :     emit (M.ADD(tmpR,tmpR,RegOp base));
173 :     emit (instr(rt,tmpR,Immed16Off(wtoi lo)));
174 :     freeTmpReg tmpR
175 :     end
176 :    
177 :     fun do_immed_logical(instr,rt,rs,n) =
178 :     if n >=0 andalso n < 65536 then
179 :     emit(instr(rt,rs,Immed16Op n))
180 :     else let val tmpR = getTmpReg()
181 :     in
182 :     load_immed(n,tmpR);
183 :     emit(instr(rt,rs,RegOp tmpR));
184 :     freeTmpReg tmpR
185 :     end
186 :    
187 :     (*
188 :     * move(a,b) means b <- a
189 :     *)
190 :     val Reg0 = Reg 0
191 :     val RegOp0 : C.label M.arithOpnd = RegOp(Reg 0)
192 :    
193 :     fun move(Direct a, Direct b) =
194 :     (case (reg_rep a, reg_rep b)
195 :     of (Freg' _, Freg' _) => emit(M.MOV_DOUBLE(b,a))
196 :     | (Freg' _, _) => error "MipsCM.move: destination not a float reg"
197 :     | (_, Freg' _) => error "MipsCM.move: source not a float reg"
198 :     | (Reg' a', Reg' b') => if a'=b' then ()
199 :     else emit(M.ADD(b,a,RegOp0)))
200 :     | move(ImmedLab lab, Direct dst) = emitSDI(LOADADDR(dst,lab,0))
201 :     | move(Immed n, Direct dst) = load_immed(n,dst)
202 :     | move(Immed32 w, rd as Direct dst) = load_immed32(w,dst)
203 :     | move _ = error "MipsCM.move"
204 :    
205 :     fun jmp (Direct r) = emit(M.JUMP r)
206 :     | jmp (ImmedLab lab) = emitBRANCH(true,Reg0,Reg0,lab)
207 :     | jmp _ = error "MipsCM.jmp: bad target"
208 :    
209 :     (* stackptr' is the stack pointer; pregs_offset is the stack offset
210 :     * of pseudo registers, it should be consistent with the offset in
211 :     * the MIPS.prim.asm file.
212 :     *)
213 :     val pregs_offset = 16
214 :    
215 :     fun loadpseudo (Direct x,Immed i) =
216 :     do_immed_mem(M.LW,x,stackptr',2*(i-1)+pregs_offset)
217 :     | loadpseudo (Direct x,Direct y) = (* this case is never used *)
218 :     let val tmpR = getTmpReg()
219 :     in emit(M.SLL(tmpR,y,Int5 1));
220 :     emit(M.ADD(tmpR,stackptr',RegOp tmpR));
221 :     emit(M.LW(x,tmpR,Immed16Off (pregs_offset-2)));
222 :     freeTmpReg tmpR
223 :     end
224 :     | loadpseudo _ = error "[loadpseudo]"
225 :    
226 :     fun storepseudo(Direct x,Immed i) =
227 :     do_immed_mem(M.SW,x,stackptr',2*(i-1)+pregs_offset)
228 :     | storepseudo(Direct x,Direct y) = (* this case is never used *)
229 :     let val tmpR = getTmpReg()
230 :     in emit (M.SLL(tmpR,y,Int5 1));
231 :     emit (M.ADD(tmpR,tmpR,RegOp stackptr'));
232 :     emit (M.SW(x,tmpR,Immed16Off (pregs_offset-2)));
233 :     freeTmpReg tmpR
234 :     end
235 :     | storepseudo _ = error "[storepseudo]"
236 :    
237 :    
238 :     (*
239 :     * jmpindexb(x,y) means pc <- (x+y)
240 :     *)
241 :     fun jmpindexb(ImmedLab lab,Direct y) =
242 :     let val tmpR = getTmpReg()
243 :     in
244 :     emitSDI(LOADADDR(tmpR,lab,0));
245 :     emit(M.ADD(tmpR,y,RegOp tmpR));
246 :     emit(M.JUMP tmpR);
247 :     freeTmpReg tmpR
248 :     end
249 :     | jmpindexb _ = error "MipsCM.jmpindexb"
250 :    
251 :    
252 :     (* should be rewritten to use all the temp registers *)
253 :     fun record(vl, Direct z) = let
254 :     open CPS
255 :     val len = List.length vl
256 :     fun f(_,i,nil) = ()
257 :     | f((t1,t2),i,(Direct r, SELp(j,p))::rest) =
258 :     (* follow ptrs to get the item *)
259 :     (emit(M.LW(t1,r,Immed16Off(j*4)));
260 :     f((t2,t1),i,(Direct t1,p)::rest))
261 :     | f(t,i,(Direct r,OFFp 0)::rest) =
262 :     (* simple store, last first *)
263 :     (emit(M.SW(r,dataptr',Immed16Off(i*4))); f(t,i-1,rest))
264 :     | f((t1,t2),i,(Direct r, OFFp j)::rest) =
265 :     (emit(M.ADD(t1,r,Immed16Op(4*j)));
266 :     f((t2,t1),i,(Direct t1,OFFp 0)::rest))
267 :     | f((t1,t2),i,(ea,p)::rest) =
268 :     (* convert to register-based *)
269 :     (move(ea,Direct t1); f((t2,t1),i,(Direct t1,p)::rest))
270 :     val tmpR1 = getTmpReg()
271 :     val tmpR2 = getTmpReg()
272 :     in
273 :     (* store first word in 0(dataptr') *)
274 :     f((tmpR1,tmpR2),len-1,rev vl);
275 :     freeTmpReg tmpR1;
276 :     freeTmpReg tmpR2;
277 :     emit (M.ADD(z,dataptr',Immed16Op 4));
278 :     do_immed_arith(M.ADD,dataptr',dataptr',4*len)
279 :     end
280 :     | record _ = error "MipsCM.record: result not a register"
281 :    
282 :    
283 :     (* should be rewritten to use all the temp registers *)
284 :     fun recordcont(vl, Direct z, n) = let
285 :     open CPS
286 :     val len = List.length vl
287 :     val _ = if (len > n)
288 :     then error "continuation records is larger than framesize"
289 :     else ()
290 :     fun f(_,i,nil) = ()
291 :     | f((t1,t2),i,(Direct r, SELp(j,p))::rest) =
292 :     (* follow ptrs to get the item *)
293 :     (emit(M.LW(t1,r,Immed16Off(j*4)));
294 :     f((t2,t1),i,(Direct t1,p)::rest))
295 :     | f(t,i,(Direct r,OFFp 0)::rest) =
296 :     (* simple store, last first *)
297 :     (emit(M.SW(r,dataptr',Immed16Off(i*4))); f(t,i-1,rest))
298 :     | f((t1,t2),i,(Direct r, OFFp j)::rest) =
299 :     (emit(M.ADD(t1,r,Immed16Op(4*j)));
300 :     f((t2,t1),i,(Direct t1,OFFp 0)::rest))
301 :     | f((t1,t2),i,(ea,p)::rest) =
302 :     (* convert to register-based *)
303 :     (move(ea,Direct t1); f((t2,t1),i,(Direct t1,p)::rest))
304 :     val tmpR1 = getTmpReg()
305 :     val tmpR2 = getTmpReg()
306 :     in
307 :     (* store first word in 0(dataptr') *)
308 :     f((tmpR1,tmpR2),len-1,rev vl);
309 :     freeTmpReg tmpR1;
310 :     freeTmpReg tmpR2;
311 :     emit (M.ADD(z,dataptr',Immed16Op 4));
312 :     do_immed_arith(M.ADD,dataptr',dataptr',4*n)
313 :     end
314 :     | recordcont _ = error "MipsCM.record: result not a register"
315 :    
316 :    
317 :     (* recordStore(x, y, alwaysBoxed) records a store operation into mem[x+2*(y-1)].
318 :     * The flag alwaysBoxed is true if the value stored is guaranteed to be boxed.
319 :     *)
320 :     fun recordStore (x, y, _) = let
321 :     fun storeListUpdate r = (
322 :     emit (M.SW(r, dataptr', Immed16Off 0));
323 :     emit (M.SW(storeptr', dataptr', Immed16Off 4));
324 :     emit (M.ADD(storeptr', dataptr', RegOp0));
325 :     emit (M.ADD(dataptr', dataptr', Immed16Op 8)))
326 :     in
327 :     case (x, y)
328 :     of (Direct r, Immed 1) => storeListUpdate r
329 :     | (Direct r, Immed i) => let val tmpR = getTmpReg()
330 :     in
331 :     do_immed_arith (M.ADD, tmpR, r, 2*(i-1));
332 :     storeListUpdate tmpR;
333 :     freeTmpReg tmpR
334 :     end
335 :     | (Direct r1, Direct r2) => let val tmpR = getTmpReg()
336 :     in
337 :     emit (M.ADD(tmpR, r2, Immed16Op ~1));
338 :     emit (M.ADD(tmpR, tmpR, RegOp tmpR));
339 :     emit (M.ADD(tmpR, tmpR, RegOp r1));
340 :     storeListUpdate tmpR;
341 :     freeTmpReg tmpR
342 :     end
343 :     | _ => ErrorMsg.impossible "[MipsCM.recordStore]"
344 :     (* end case *)
345 :     end (* recordStore *)
346 :     (*** STOREPTR
347 :     fun recordStore (x, y, alwaysBoxed) = let
348 :     (* NOTE: eventually we can optimize the case where alwaysBoxed = false *)
349 :     fun storeVectorUpdate r = (
350 :     emit (M.SW(r, M.limitReg, Immed16Off 4092));
351 :     emit (M.ADD(M.limitReg, M.limitReg, Immed16Op ~4)))
352 :     in
353 :     case (x, y)
354 :     of (Direct r, Immed 1) => storeVectorUpdate r
355 :     | (Direct r, Immed i) => let val tmpR = getTmpReg()
356 :     in
357 :     do_immed_arith (M.ADD, tmpR, r, 2*(i-1));
358 :     storeVectorUpdate tmpR;
359 :     freeTmpReg tmpR
360 :     end
361 :     | (Direct r1, Direct r2) => let val tmpR = getTmpReg()
362 :     in
363 :     emit (M.ADD(tmpR, r2, Immed16Op ~1));
364 :     emit (M.ADD(tmpR, tmpR, RegOp tmpR));
365 :     emit (M.ADD(tmpR, tmpR, RegOp r1));
366 :     storeVectorUpdate tmpR;
367 :     freeTmpReg tmpR
368 :     end
369 :     | _ => ErrorMsg.impossible "[MipsCM.recordStore]"
370 :     (* end case *)
371 :     end (* recordStore *)
372 :     ***)
373 :     (*** STOREPTR
374 :     fun recordStore (x, y, _) = record ([
375 :     (Immed(dtoi(D.makeDesc(3, dtoi D.tag_record))), CPS.OFFp 0),
376 :     (x, CPS.OFFp 0), (y, CPS.OFFp 0), (storeptr, CPS.OFFp 0)
377 :     ], storeptr)
378 :     ***)
379 :    
380 :    
381 :     fun select(i,Direct v',Direct w) = do_immed_mem(M.LW,w,v',i*4)
382 :     | select(i,ImmedLab lab,Direct w) = emitSDI(LOAD(w,lab,i*4))
383 :     | select _ = error "MipsCM.select: bad dst"
384 :    
385 :    
386 :     fun offset(i,v,Direct w) =
387 :     (case v
388 :     of Direct v' => do_immed_arith(M.ADD,w,v',i*4)
389 :     | ImmedLab lab => let val tmpR = getTmpReg()
390 :     in
391 :     emitSDI(LOADADDR(tmpR,lab,0));
392 :     do_immed_arith(M.ADD,w,tmpR,i*4);
393 :     freeTmpReg tmpR
394 :     end
395 :     | _ => error "MipsCM.offset: bad src")
396 :     | offset _ = error "MipsCM.offset: bad dst"
397 :    
398 :    
399 :     (* fetchindexb(x,y,z) fetches a byte: y <- mem[x+z],
400 :     * where y is not x or z
401 :     *)
402 :     fun fetchindexb(Direct x,Direct y,Immed indx) = do_immed_mem(M.LBU,y,x,indx)
403 :     | fetchindexb(Direct x,Direct y,Direct indx) = let
404 :     val tmpR = getTmpReg()
405 :     in
406 :     emit (M.ADD(tmpR,indx,RegOp x));
407 :     emit (M.LBU(y,tmpR,Immed16Off 0));
408 :     freeTmpReg tmpR
409 :     end
410 :     | fetchindexb _ = error "MipsCM.fetchindexb"
411 :    
412 :    
413 :     (*
414 :     * storeindexb(x,y,z) stores a byte: mem[y+z] <- x.
415 :     *)
416 :     fun storeindexb(Immed xi,y,z) =
417 :     let val tmpR = getTmpReg()
418 :     in
419 :     do_immed_arith(M.ADD,tmpR,Reg0,xi);
420 :     storeindexb(Direct tmpR,y,z);
421 :     freeTmpReg tmpR
422 :     end
423 :     | storeindexb(Direct x,Direct y,Direct indx) =
424 :     let val tmpR = getTmpReg()
425 :     in
426 :     emit (M.ADD(tmpR,y,RegOp indx));
427 :     emit (M.SB(x,tmpR,Immed16Off 0));
428 :     freeTmpReg tmpR
429 :     end
430 :     | storeindexb(Direct x,Direct y,Immed indx) = do_immed_mem(M.SB,x,y,indx)
431 :     | storeindexb _ = error "MipsCM.storeindexb"
432 :    
433 :    
434 :     (*
435 :     * fetchindexl(x,y,z) fetches a word: y <- mem[x+2*(z-1)]
436 :     *)
437 :     fun fetchindexl(x,Direct y,Direct z') =
438 :     let val tmpR = getTmpReg()
439 :     in
440 :     emit(M.SLL(tmpR,z',Int5 1));
441 :     (case x
442 :     of Direct x' => (emit (M.ADD(tmpR,x',RegOp tmpR));
443 :     emit (M.LW(y,tmpR,Immed16Off ~2)))
444 :     | Immed n => do_immed_mem(M.LW,y,tmpR,n-2)
445 :     | ImmedLab lab =>
446 :     let val tmpR2 = getTmpReg()
447 :     in
448 :     emitSDI(M.LOADADDR(tmpR2,lab,0));
449 :     emit(M.ADD(tmpR,tmpR,RegOp tmpR2));
450 :     freeTmpReg tmpR2;
451 :     emit(M.LW(y,tmpR,Immed16Off ~2))
452 :     end);
453 :     freeTmpReg tmpR
454 :     end
455 :     | fetchindexl(x,Direct y,Immed z') =
456 :     (case x
457 :     of Direct x' => do_immed_mem(M.LW,y,x',2*(z'-1))
458 :     | Immed n => do_immed_mem(M.LW,y,Reg0,n+2*(z'-1))
459 :     | ImmedLab lab => emitSDI(LOAD(y,lab,2*(z'-1))))
460 :     | fetchindexl _ = error "MipsCM.fetchindexl"
461 :    
462 :    
463 :     (*
464 :     * storeindexl(x,y,z) stores a word: mem[y+2*(z-1)] <- x
465 :     *)
466 :     fun storeindexl(Direct x,Direct y,Direct z) =
467 :     let val tmpR = getTmpReg()
468 :     in
469 :     emit (M.SLL(tmpR,z,Int5 1));
470 :     emit (M.ADD(tmpR,tmpR,RegOp y));
471 :     emit (M.SW(x,tmpR,Immed16Off ~2));
472 :     freeTmpReg tmpR
473 :     end
474 :     | storeindexl(Direct x,Direct y,Immed zi) = do_immed_mem(M.SW,x,y,2*(zi-1))
475 :     | storeindexl(Immed xi,y,z) = let val tmpR = getTmpReg()
476 :     in
477 :     load_immed(xi,tmpR);
478 :     storeindexl(Direct tmpR,y,z);
479 :     freeTmpReg tmpR
480 :     end
481 :     | storeindexl(ImmedLab lab,y,z) = let val tmpR = getTmpReg()
482 :     in
483 :     emitSDI(M.LOADADDR(tmpR,lab,0));
484 :     storeindexl(Direct tmpR,y,z);
485 :     freeTmpReg tmpR
486 :     end
487 :     | storeindexl _ = error "MipsCM.storeindexl: bad args"
488 :    
489 :    
490 :     (*
491 :     * three - can *only* be used for commutative operators
492 :     *)
493 :     fun three f (do_immed, x as Direct x', y as Direct y', ea) =
494 :     (case ea
495 :     of Immed zi => do_immed(f,x',y',zi)
496 :     | Immed32 w => let val tmpR = getTmpReg()
497 :     in load_immed32(w,tmpR);
498 :     three f (do_immed, x, y, Direct tmpR);
499 :     freeTmpReg tmpR
500 :     end
501 :     | Direct z' => emit(f(x',y',RegOp z'))
502 :     | ImmedLab lab => let val tmpR = getTmpReg()
503 :     in
504 :     emitSDI(M.LOADADDR(tmpR,lab,0));
505 :     emit(f(x',y',RegOp tmpR));
506 :     freeTmpReg tmpR
507 :     end)
508 :    
509 :     | three f (do_immed,Direct x', ea, Direct z') =
510 :     three f (do_immed,Direct x',Direct z',ea)
511 :     | three f (do_immed,x, Immed yi,z) = let val tmpR = getTmpReg()
512 :     in
513 :     load_immed(yi,tmpR);
514 :     three f (do_immed,x,Direct tmpR,z);
515 :     freeTmpReg tmpR
516 :     end
517 :     | three f (do_immed,x, Immed32 w,z) = let val tmpR = getTmpReg()
518 :     in
519 :     load_immed32(w,tmpR);
520 :     three f (do_immed,x,Direct tmpR,z);
521 :     freeTmpReg tmpR
522 :     end
523 :     | three _ _ = error "MipsCM.three: bad args"
524 :    
525 :     fun add(x,y,z) = three M.ADDU (do_immed_arith,z,x,y)
526 :     fun orb(x,y,z) = three M.OR (do_immed_logical,z,x,y)
527 :     fun andb(x,y,z) = three M.AND (do_immed_logical,z,x,y)
528 :     fun xorb(x,y,z) = three M.XOR (do_immed_logical,z,x,y)
529 :    
530 :     (* Subtraction may appear a bit odd.
531 :     * The MIPS machine instruction and MIPSCODER.sub both subtract
532 :     * their second operand from their first operand.
533 :     * The CMACHINE.sub subtracts the first operand from the second.
534 :     * This will certainly lead to endless confusion.
535 :     *
536 :     * sub(a,b,c) mean c <- b-a
537 :     *)
538 :     fun sub (Direct x,Direct y,Direct z) = emit(M.SUBU(z,y,x))
539 :     | sub (Immed xi,y,z) = let val tmpR = getTmpReg()
540 :     in load_immed(xi,tmpR);
541 :     sub (Direct tmpR,y,z);
542 :     freeTmpReg tmpR
543 :     end
544 :     | sub (Immed32 w,y,z) = let val tmpR = getTmpReg()
545 :     in load_immed32(w,tmpR);
546 :     sub(Direct tmpR, y, z);
547 :     freeTmpReg tmpR
548 :     end
549 :     | sub (x,Immed 0,dest) = sub (x, Direct(Reg0), dest)
550 :     | sub (x,Immed y,z) = let val tmpR = getTmpReg()
551 :     in load_immed(y,tmpR);
552 :     sub (x,Direct tmpR,z);
553 :     freeTmpReg tmpR
554 :     end
555 :     | sub (x, Immed32 w, z) = let val tmpR = getTmpReg()
556 :     in load_immed32(w,tmpR);
557 :     sub(x, Direct tmpR, z);
558 :     freeTmpReg tmpR
559 :     end
560 :     | sub _ = error "MipsCM.sub: mismatched args"
561 :    
562 :     fun notb(a,b) = sub (a, Immed ~1, b)
563 :    
564 :    
565 :     (*
566 :     * integer arithmetic with overflow trapping - addt subt mult divt
567 :     *)
568 :     fun addt (Immed ai, Immed bi, Direct rd) =
569 :     (load_immed(ai,rd); do_immed_arith(M.ADD,rd,rd,bi))
570 :     | addt (Immed32 aw, b, c as Direct rd) =
571 :     (load_immed32(aw,rd); addt(b, c, c))
572 :     | addt (x, y, z) = three M.ADD (do_immed_arith,z,x,y)
573 :    
574 :     fun subt (Immed xi,y,z) = addt(y,Immed (~xi),z)
575 :     | subt (Direct x,Direct y,Direct z)= emit(M.SUB(z,y,x))
576 :     | subt (x,Immed 0,dest) = subt (x, Direct(Reg0), dest)
577 :     | subt (x,Immed k,dest) = let val tmpR = getTmpReg()
578 :     in
579 :     do_immed_arith(M.ADD,tmpR,Reg0,k);
580 :     subt (x,Direct tmpR,dest);
581 :     freeTmpReg tmpR
582 :     end
583 :     | subt (Immed32 x, y, z) = let val tmpR = getTmpReg()
584 :     in
585 :     load_immed32(x, tmpR);
586 :     subt(Direct tmpR, y, z);
587 :     freeTmpReg tmpR
588 :     end
589 :     | subt (x, Immed32 y, z) = let val tmpR = getTmpReg()
590 :     in
591 :     load_immed32(y, tmpR);
592 :     subt(x, Direct tmpR, z);
593 :     freeTmpReg tmpR
594 :     end
595 :    
596 :     | subt _ = error "MipsCM.subt: mismatched args"
597 :    
598 :     (* The Mips multiplies two 32-bit quantities to get a 64-bit result.
599 :     * That result fits in 32 bits if and only if the high-order word is zero
600 :     * or negative one, and it has the same sign as the low order word.
601 :     * Thus, we can add the sign bit of the low order word to the high order
602 :     * word, and we have overflow if and only if the result is nonzero.
603 :     *)
604 :     fun mult(ea,y as Direct y') =
605 :     let val tmpR = getTmpReg()
606 :     in
607 :     (case ea
608 :     of Immed xi =>
609 :     (do_immed_arith(M.ADD,tmpR,Reg0, xi); mult(Direct tmpR,y))
610 :     | Immed32 wi =>
611 :     (load_immed32(wi, tmpR); mult(Direct tmpR, y))
612 :     | Direct x' =>
613 :     let val ok = C.newLabel()
614 :     in emit (M.MULT(x',y'));
615 :     emit (M.MFLO y');
616 :     emit (M.SLT(y',y',RegOp (Reg0)));
617 :     emit (M.MFHI tmpR);
618 :     emit (M.ADD(tmpR,y',RegOp tmpR));
619 :     emit (M.MFLO y');
620 :     emitBRANCH(true,tmpR,Reg0,ok);
621 :     emit (M.LUI(tmpR,Immed16Off 32767));
622 :     emit (M.ADD(tmpR,tmpR,RegOp tmpR));
623 :     C.define ok
624 :     end
625 :     | _ => error "MipsCM.mult");
626 :     freeTmpReg tmpR
627 :     end
628 :     | mult _ = error "MipsCM.mult: result not a register"
629 :    
630 :     fun mulu(Direct x,Direct y) =
631 :     (emit(M.MULTU(x,y)); emit(M.MFLO y))
632 :     | mulu(Immed32 xi,y) = let val tmpR = getTmpReg()
633 :     in
634 :     load_immed32(xi,tmpR);
635 :     mulu(Direct tmpR,y);
636 :     freeTmpReg tmpR
637 :     end
638 :     | mulu _ = error "mulu"
639 :    
640 :    
641 :     (*
642 :     * divt(a,b) means b <- b div a
643 :     *)
644 :     fun divt(Direct x',Direct y') =
645 :     let val oklabel = C.newLabel()
646 :     in
647 :     (* emit (M.DIV(y',x')); *)
648 :     emitBRANCH(false,Reg0,x',oklabel);
649 :     emit(M.BREAK 7);
650 :     C.define oklabel;
651 :     emit (M.DIV(y',x'));
652 :     emit (M.MFLO y')
653 :     end
654 :     | divt(Immed xi, y) =
655 :     let val tmpR = getTmpReg()
656 :     in
657 :     do_immed_arith(M.ADD,tmpR,Reg0,xi);
658 :     divt(Direct tmpR,y);
659 :     freeTmpReg tmpR
660 :     end
661 :     | divt(Immed32 xi, y) =
662 :     let val tmpR = getTmpReg()
663 :     in
664 :     load_immed32(xi, tmpR);
665 :     divt(Direct tmpR, y);
666 :     freeTmpReg tmpR
667 :     end
668 :     | divt _ = error "MipsCM.divt: mismatched args"
669 :    
670 :     fun divtu(Direct x',Direct y') = let
671 :     val oklabel = C.newLabel()
672 :     in
673 :     emitBRANCH(false,Reg0,x',oklabel);
674 :     emit(M.BREAK 7);
675 :     C.define oklabel;
676 :     emit (M.DIVU(y',x'));
677 :     emit (M.MFLO y')
678 :     end
679 :     | divtu(Immed32 w,y) = let
680 :     val tmpR = getTmpReg()
681 :     in
682 :     load_immed32(w,tmpR);
683 :     divtu(Direct tmpR,y);
684 :     freeTmpReg tmpR
685 :     end
686 :    
687 :    
688 :     fun ashr(shamt,Direct rt,Direct rd) =
689 :     (case shamt
690 :     of Direct rs => emit(M.SRAV(rd,rt,rs))
691 :     | Immed n =>
692 :     if n >= 32 orelse n < 0 then
693 :     error "MipsCM.ashr: Too large a shift distance"
694 :     else
695 :     emit(M.SRA(rd,rt,Int5 n))
696 :     | _ => error "MipsCM.ashr")
697 :     | ashr(shamt,Immed n,dst) = let val tmpR = getTmpReg()
698 :     in
699 :     load_immed(n,tmpR);
700 :     ashr(shamt,Direct tmpR,dst);
701 :     freeTmpReg tmpR
702 :     end
703 :     | ashr(shamt, Immed32 w, dst) = let val tmpR = getTmpReg()
704 :     in load_immed32(w,tmpR);
705 :     ashr(shamt, Direct tmpR, dst);
706 :     freeTmpReg tmpR
707 :     end
708 :     | ashr _ = error "MipsCM.ashr: bad args"
709 :    
710 :     fun lshr(shamt,Direct rt,Direct rd) =
711 :     (case shamt
712 :     of Direct rs => emit(M.SRLV(rd,rt,rs))
713 :     | Immed n =>
714 :     if n >= 32 orelse n < 0 then
715 :     error "MipsCM.lshr: bad shift distance"
716 :     else
717 :     emit(M.SRL(rd,rt,Int5 n))
718 :     | _ => error "MipsCM.ashr")
719 :     | lshr(shamt,Immed n,dst) = let val tmpR = getTmpReg()
720 :     in
721 :     load_immed(n,tmpR);
722 :     lshr(shamt,Direct tmpR,dst);
723 :     freeTmpReg tmpR
724 :     end
725 :     | lshr(shamt, Immed32 w, dst) = let val tmpR = getTmpReg()
726 :     in
727 :     load_immed32(w,tmpR);
728 :     lshr(shamt,Direct tmpR,dst);
729 :     freeTmpReg tmpR
730 :     end
731 :    
732 :     | lshr _ = error "MipsCM.ashr: bad args"
733 :    
734 :     fun ashl(shamt,Direct rt,Direct rd) =
735 :     (case shamt
736 :     of Direct rs => emit(M.SLLV(rd,rt,rs))
737 :     | Immed n =>
738 :     if n >= 32 orelse n < 0 then
739 :     error "MipsCM.ashl: Too large a shift distance"
740 :     else
741 :     emit(M.SLL(rd,rt,Int5 n))
742 :     | _ => error "MipsCM.ashl")
743 :     | ashl(shamt,Immed n,dst) = let val tmpR = getTmpReg()
744 :     in
745 :     load_immed(n,tmpR);
746 :     ashl(shamt,Direct tmpR,dst);
747 :     freeTmpReg tmpR
748 :     end
749 :     | ashl(shamt,Immed32 w,dst) = let val tmpR = getTmpReg()
750 :     in
751 :     load_immed32(w,tmpR);
752 :     ashl(shamt,Direct tmpR,dst);
753 :     freeTmpReg tmpR
754 :     end
755 :     | ashl _ = error "MipsCM.ashl: bad args"
756 :    
757 :     datatype condition = NEQ | EQL | LEQ | GEQ | LSS | GTR
758 :     | GEU | GTU | LTU | LEU
759 :    
760 :     (** NOTE: these optimizations ought to be done in the CPS phase!!!
761 :     ** ALSO: maybe we want to add a "wbranch" function and get rid of the
762 :     ** unsigned condition codes.
763 :     **)
764 :     fun ibranch(cond,Immed a,Immed b,ImmedLab lab) = let
765 :     val condVal = (case cond
766 :     of EQL => a=b | NEQ => a<>b | LSS => a<b
767 :     | LEQ => a<=b | GTR => a>b | GEQ => a>=b
768 :     | GTU => (Word.fromInt a > Word.fromInt b)
769 :     | GEU => (Word.fromInt a >= Word.fromInt b)
770 :     | LTU => (Word.fromInt a < Word.fromInt b)
771 :     | LEU => (Word.fromInt a <= Word.fromInt b)
772 :     (* end case *))
773 :     in
774 :     if condVal then emitBRANCH(true,Reg0,Reg0,lab) else ()
775 :     end
776 :     | ibranch(cond,Immed32 a,Immed32 b,ImmedLab lab) = let
777 :     val wtoi = Int32.fromLarge o Word32.toLargeIntX
778 :     fun cmpi32(cmp, a, b) = cmp(wtoi a, wtoi b)
779 :     in
780 :     if (case cond
781 :     of EQL => a = b
782 :     | NEQ => a <> b
783 :     | GEU => Word32.>=(a,b)
784 :     | GTU => Word32.>(a,b)
785 :     | LTU => Word32.<(a,b)
786 :     | LEU => Word32.<=(a,b)
787 :     | LEQ => cmpi32(Int32.<=, a, b)
788 :     | LSS => cmpi32(Int32.<, a, b)
789 :     | GEQ => cmpi32(Int32.>=, a, b)
790 :     | GTR => cmpi32(Int32.>, a, b))
791 :     then emitBRANCH(true, Reg0, Reg0, lab)
792 :     else ()
793 :     end
794 :     | ibranch(cond,Immed32 a,b,lab) = let val tmpR = getTmpReg()
795 :     in load_immed32(a,tmpR);
796 :     ibranch(cond,Direct tmpR,b,lab);
797 :     freeTmpReg tmpR
798 :     end
799 :     | ibranch(cond,a,Immed32 b,lab) = let val tmpR = getTmpReg()
800 :     in load_immed32(b,tmpR);
801 :     ibranch(cond,a,Direct tmpR,lab);
802 :     freeTmpReg tmpR
803 :     end
804 :     | ibranch(cond,Immed n,Direct t,label) =
805 :     let val tmpR = getTmpReg()
806 :     in
807 :     load_immed(n,tmpR);
808 :     ibranch(cond,Direct tmpR,Direct t,label);
809 :     freeTmpReg tmpR
810 :     end
811 :     | ibranch(cond,Direct rs,Immed n,label) =
812 :     (*
813 :     * could do a better job of this case (ref.G.Kane, table C.2)
814 :     *)
815 :     let val tmpR = getTmpReg()
816 :     in
817 :     load_immed(n,tmpR);
818 :     ibranch(cond,Direct rs,Direct tmpR,label);
819 :     freeTmpReg tmpR
820 :     end
821 :     | ibranch(cond,Direct rs,Direct rt,ImmedLab lab) = let val tmpR = getTmpReg()
822 :     in
823 :     case cond
824 :     of NEQ => emitBRANCH(false,rs,rt,lab)
825 :     | EQL => emitBRANCH(true,rs,rt,lab)
826 :     | LEQ => (emit(M.SLT(tmpR,rt,RegOp rs));
827 :     emitBRANCH(true,tmpR,Reg0,lab))
828 :     | GEQ => (emit(M.SLT(tmpR,rs,RegOp rt));
829 :     emitBRANCH(true,tmpR,Reg0,lab))
830 :     | LSS => (emit(M.SLT(tmpR,rs,RegOp rt));
831 :     emitBRANCH(false,tmpR,Reg0,lab))
832 :     | GTR => (emit(M.SLT(tmpR,rt,RegOp rs));
833 :     emitBRANCH(false,tmpR,Reg0,lab))
834 :     | GEU => (emit(M.SLTU(tmpR,rs,RegOp rt));
835 :     emitBRANCH(true,tmpR,Reg0,lab))
836 :     | GTU => (emit(M.SLTU(tmpR,rt,RegOp rs));
837 :     emitBRANCH(false,tmpR,Reg0,lab))
838 :     | LTU => (emit(M.SLTU(tmpR,rs,RegOp rt));
839 :     emitBRANCH(false,tmpR,Reg0,lab))
840 :     | LEU => (emit(M.SLTU(tmpR,rt,RegOp rs));
841 :     emitBRANCH(true,tmpR,Reg0,lab))
842 :     (*esac*);
843 :     freeTmpReg tmpR
844 :     end
845 :     | ibranch _ = error "MipsCM.ibranch: bad args"
846 :    
847 :     (*
848 :     * bbs - branch on bit set.
849 :     *)
850 :     fun bbs(Immed k, Direct y, ImmedLab label) =
851 :     let val tmpR = getTmpReg()
852 :     in
853 :     do_immed_logical(M.AND,tmpR,y,
854 :     Word.toIntX(Word.<<(0w1, Word.fromInt k)));
855 :     emitBRANCH(false,tmpR,Reg0,label);
856 :     freeTmpReg tmpR
857 :     end
858 :     | bbs _ = error "MipsCM.bbs: bad args"
859 :    
860 :    
861 :     fun floatreg (Direct fpr) =
862 :     (case reg_rep fpr
863 :     of Freg' _ => fpr
864 :     | _ => error "MipsCM.floatreg: expected floatreg")
865 :     | floatreg _ = error "MipsCM.floatreg: expected floatreg"
866 :    
867 :     local
868 :     val real_tag = dtoi D.desc_reald
869 :     val lowOff = E.low_order_offset
870 :    
871 :     fun store_float(n',dst,offset) =
872 :     case (reg_rep n', dst)
873 :     of (Freg' n, Direct dst') =>
874 :     if n mod 2 <> 0 then
875 :     error "MipsCM.store_float: bad float reg"
876 :     else (do_immed_mem (M.SWC1,Freg(n+1-lowOff),dst',offset+4);
877 :     do_immed_mem (M.SWC1,Freg(n+lowOff),dst',offset))
878 :     | _ => error "MipsCM.store_float: bad args"
879 :    
880 :     fun load_float(dest',src,offset) =
881 :     case reg_rep dest'
882 :     of Freg' dest =>
883 :     if dest mod 2 <> 0 then error "MipsCM.load_float.1"
884 :     else
885 :     (case src
886 :     of Direct src' =>
887 :     (do_immed_mem(M.LWC1,Freg(dest+lowOff),src',offset);
888 :     do_immed_mem(M.LWC1,Freg(dest+1-lowOff),src',offset+4))
889 :     | ImmedLab lab =>
890 :     let val tmpR = getTmpReg()
891 :     in emitSDI(LOADF(Freg dest,lab,offset,tmpR));
892 :     freeTmpReg tmpR
893 :     end
894 :     | _ => error "MipsCM.load_float.3")
895 :     | _ => error "MipsCM.load_float.2"
896 :    
897 :     in
898 :     fun storefloat(src,Direct dst) =
899 :     (case reg_rep dst
900 :     of Reg' result =>
901 :     (store_float(floatreg src,dataptr,4);
902 :     let val tmpR = getTmpReg()
903 :     in
904 :     emit (M.ADD(tmpR,Reg0,Immed16Op real_tag));
905 :     emit (M.SW(tmpR,dataptr',Immed16Off 0));
906 :     emit (M.ADD(Reg result,dataptr',Immed16Op 4));
907 :     emit (M.ADD(dataptr',dataptr',Immed16Op 12));
908 :     freeTmpReg tmpR
909 :     end)
910 :     | _ => error "MipsCM.storefloat: bad args")
911 :     | storefloat _ = error "MipsCM.storefloat: bad args.2"
912 :    
913 :     fun loadfloat(src, dst) = load_float(floatreg dst,src,0)
914 :     (* y <- mem[x+4*(z-1)] *)
915 :     fun fetchindexd(Direct x, y, z) =
916 :     (case z
917 :     of Immed i => load_float(floatreg y, Direct x, 4*(i-1))
918 :     | Direct z' => let val tmpR = getTmpReg()
919 :     in
920 :     emit (M.SLL(tmpR,z',Int5 2));
921 :     emit (M.ADD(tmpR,x,RegOp tmpR));
922 :     load_float(floatreg y, Direct tmpR, ~4);
923 :     freeTmpReg tmpR
924 :     end
925 :     | _ => error "MipsCM.fetchindexd")
926 :     | fetchindexd _ = error "MipsCM.fetchindexd"
927 :    
928 :     (* mem[y+4*(z-1)] <- x *)
929 :     fun storeindexd(x, Direct y, z) =
930 :     (case z
931 :     of Immed i => store_float(floatreg x,Direct y, 4*(i-1))
932 :     | Direct z' => let val tmpR = getTmpReg()
933 :     in
934 :     emit (M.SLL(tmpR,z',Int5 2));
935 :     emit (M.ADD(tmpR,y,RegOp tmpR));
936 :     store_float(floatreg x,Direct tmpR,~4);
937 :     freeTmpReg tmpR
938 :     end
939 :     | _ => error "MipsCM.storeindexd")
940 :     | storeindexd _ = error "MipsCM.storeindexd"
941 :    
942 :     fun fprecord(tag, vl, Direct z) =
943 :     let open CPS
944 :     val len = (List.length vl) * 8 + 4
945 :     fun f(_,_,_,i,nil) = ()
946 :     | f(t1,t2,f1,i,(Direct r, SELp(j,OFFp 0))::rest) =
947 :     (case (reg_rep r, reg_rep f1)
948 :     of (Reg' src, Freg' dest) =>
949 :     (do_immed_mem(M.LWC1,Freg(dest+lowOff),r,j*8);
950 :     do_immed_mem(M.LWC1,Freg(dest+1-lowOff),r,j*8+4);
951 :     f(t1,t2,f1,i,(Direct f1, OFFp 0)::rest))
952 :     | _ => error "wrong register assignment1 in mips.sml")
953 :     | f(t1,t2,f1,i,(Direct r, SELp(j,p))::rest) =
954 :     (case reg_rep r
955 :     of (Reg' src) =>
956 :     (do_immed_mem(M.LW,t1,r,j*4);
957 :     f(t2,t1,f1,i,(Direct t1,p)::rest))
958 :     | _ => error "wrong register assignment3 in mips.sml")
959 :     | f(t1,t2,f1,i,(Direct r, OFFp 0)::rest) =
960 :     (case reg_rep r
961 :     of (Freg' n) =>
962 :     (do_immed_mem(M.SWC1,Freg(n+1-lowOff),dataptr',i+4);
963 :     do_immed_mem(M.SWC1,Freg(n+lowOff),dataptr',i);
964 :     f(t1,t2,f1,i-8,rest))
965 :     | _ => error "wrong register assignment2 in mips.sml")
966 :     | f(t1,t2,f1,i,(Direct r, OFFp j)::rest) =
967 :     error "non-zero offset elements in fprecord in mips.sml"
968 :     | f(t1,t2,f1,i,(ea, p)::rest) =
969 :     (move(ea,Direct t1); f(t2,t1,f1,i,(Direct t1,p)::rest))
970 :    
971 :     val tmpR1 = getTmpReg()
972 :     val tmpR2 = getTmpReg()
973 :     val tmpF1 = tmpfpreg
974 :     in
975 :     orb(dataptr,Immed 4,dataptr); (* align *)
976 :     move(tag,Direct tmpR1);
977 :     emit(M.SW(tmpR1,dataptr',Immed16Off 0));
978 :     f(tmpR1,tmpR2,tmpF1,len-8,rev vl);
979 :     freeTmpReg tmpR1;
980 :     freeTmpReg tmpR2;
981 :     emit (M.ADD(z,dataptr',Immed16Op 4));
982 :     do_immed_arith(M.ADD,dataptr',dataptr',len)
983 :     end
984 :     | fprecord _ = error "MipsCM.fprecord: result not a register"
985 :    
986 :     end
987 :    
988 :     (* Note: mipsdepend will ensure that nothing generated here gets reordered.
989 :     * Also note that an unsigned comparison is necessary, since this is a pointer
990 :     * comparison.
991 :     *)
992 :     fun testLimit() = emit(M.SLTU(M.heapExhaustedReg,dataptr',RegOp(limit')))
993 :     fun decLimit n = do_immed_arith(M.ADD,limit',limit',~n) (* for polling *)
994 :    
995 :     val startgc_offset = MachSpec.startgcOffset
996 :    
997 :     fun checkLimit(max_allocation, lab, mask, rlab, fregs) =
998 :     (* NOTE: THIS CODE USES TEMP REGS BY ALIASES.
999 :     Thus it is important that none of the emitted pseudo-instructions
1000 :     below uses getTmpReg(), directly or indirectly. *)
1001 :     let val lab' = C.newLabel()
1002 :     val _ = if max_allocation > 4096 then
1003 :     (do_immed_arith(M.ADD,M.heapExhaustedReg,dataptr',
1004 :     max_allocation - 4096);
1005 :     emit(M.SLTU(M.heapExhaustedReg,M.heapExhaustedReg,
1006 :     RegOp(limit'))))
1007 :     else ()
1008 :     val _ = emitBRANCH(false,M.heapExhaustedReg, Reg0, lab')
1009 :     in (case fregs
1010 :     of [] => (do_immed_mem(M.LW,M.heapExhaustedReg,stackptr',
1011 :     startgc_offset);
1012 :     move(mask, Direct M.maskReg);
1013 :     move(lab, Direct M.linkReg);
1014 :     emit(M.JUMP M.heapExhaustedReg))
1015 :     | _ => (let val k = length fregs
1016 :     val lowOff = E.low_order_offset
1017 :     val desc = dtoi(D.makeDesc(k * 8, D.tag_string))
1018 :     val retlab = C.newLabel()
1019 :    
1020 :     fun deposit([], _) = ()
1021 :     | deposit((Direct x)::r, i) =
1022 :     (case (reg_rep x)
1023 :     of (Freg' n) =>
1024 :     (do_immed_mem(M.SWC1,Freg(n+1-lowOff),
1025 :     dataptr',i+4);
1026 :     do_immed_mem(M.SWC1,Freg(n+lowOff),
1027 :     dataptr',i);
1028 :     deposit(r, i+8))
1029 :     | _ => error "wrong register checkLimit")
1030 :    
1031 :     fun restore(s, [], _) = ()
1032 :     | restore(s, (Direct x)::r, i) =
1033 :     (case (reg_rep x)
1034 :     of (Freg' n) =>
1035 :     (do_immed_mem(M.LWC1,Freg(n+1-lowOff),
1036 :     s,i+4);
1037 :     do_immed_mem(M.LWC1,Freg(n+lowOff),
1038 :     s,i);
1039 :     restore(s, r, i+8))
1040 :     | _ => error "wrong register checkLimit")
1041 :    
1042 :     in deposit(fregs,4);
1043 :     move(immed desc, Direct M.heapExhaustedReg);
1044 :     (* orb(dataptr,Immed 4,dataptr);*) (* align *)
1045 :     emit(M.SW(M.heapExhaustedReg, dataptr', Immed16Off 0));
1046 :     emit(M.ADD(M.maskReg, dataptr', Immed16Op 4));
1047 :     do_immed_arith(M.ADD,dataptr',dataptr',k*8+4);
1048 :     do_immed_mem(M.SW,M.maskReg,stackptr',4+pregs_offset);
1049 :     (* I am using pseudo register #2 here !!! *)
1050 :    
1051 :     do_immed_mem(M.LW,M.heapExhaustedReg,stackptr',
1052 :     startgc_offset);
1053 :     move(mask, Direct M.maskReg);
1054 :     move(ImmedLab retlab, Direct M.linkReg);
1055 :     emit(M.JUMP M.heapExhaustedReg);
1056 :    
1057 :     C.define retlab;
1058 :     do_immed_mem(M.LW,M.maskReg,stackptr',4+pregs_offset);
1059 :     (* I am using pseudo register #2 here !!! *)
1060 :     move(rlab, Direct M.linkReg);
1061 :     restore(M.maskReg, fregs, 0);
1062 :     emit(M.JUMP M.linkReg)
1063 :     end));
1064 :     C.define lab'
1065 :     end
1066 :    
1067 :     fun beginStdFn(ImmedLab lab, Direct reg) = emitSDI(M.SETBASEADDR(lab,reg))
1068 :    
1069 :     local
1070 :     structure P = CPS.P
1071 :     fun floating_arith f (x,y,z) = emit(f(floatreg x,floatreg y,floatreg z))
1072 :     in
1073 :     fun fmuld(x,y,z) = floating_arith M.MUL_DOUBLE (z,x,y)
1074 :     fun fdivd(x,y,z) = floating_arith M.DIV_DOUBLE (z,x,y)
1075 :     fun faddd(x,y,z) = floating_arith M.ADD_DOUBLE (z,x,y)
1076 :     fun fsubd(x,y,z) = floating_arith M.SUB_DOUBLE (z,x,y)
1077 :     fun fnegd(op1,result) = emit(M.NEG_DOUBLE(floatreg result,floatreg op1))
1078 :     fun fabsd(op1,result) = emit(M.ABS_DOUBLE(floatreg result,floatreg op1))
1079 :    
1080 :     fun fbranchd (cond, op1, op2, ImmedLab label) = let
1081 :     fun compare P.fEQ = (M.EQ, true)
1082 :     | compare P.fULG = (M.EQ, false)
1083 :     | compare P.fGT = (M.NGT, false)
1084 :     | compare P.fGE = (M.NGE, false)
1085 :     | compare P.fLT = (M.LT, true)
1086 :     | compare P.fLE = (M.LE, true)
1087 :     | compare P.fLG = (M.UEQ, false)
1088 :     | compare P.fLEG = (M.NGLE, false)
1089 :     | compare P.fUGT = (M.LE, false)
1090 :     | compare P.fUGE = (M.LT, false)
1091 :     | compare P.fULT = (M.ULT, true)
1092 :     | compare P.fULE = (M.ULE, true)
1093 :     | compare P.fUE = (M.UEQ, true)
1094 :     | compare P.fUN = (M.EQ, true)
1095 :    
1096 :     val (cmp, test) = compare cond
1097 :     in
1098 :     emit(M.FCMP(cmp, floatreg op1, floatreg op2));
1099 :     emitBRANCH_COP1(test, label)
1100 :     end
1101 :     | fbranchd _ = error "MipsCM.fbranchd: insane target"
1102 :     end
1103 :    
1104 :    
1105 :     fun cvti2d(Direct src,dst as Direct dst') =
1106 :     (case (reg_rep src, reg_rep dst')
1107 :     of (Reg' _, Freg' _) => (emit (M.MTC1(src, dst'));
1108 :     emit (M.CVTI2D(dst', dst'))))
1109 :     | cvti2d(Immed n, dst) =
1110 :     let val tmpR = getTmpReg()
1111 :     in do_immed_arith(M.ADD,tmpR,Reg0,n);
1112 :     cvti2d(Direct tmpR,dst);
1113 :     freeTmpReg tmpR
1114 :     end
1115 :    
1116 :     val comment = C.comment
1117 :     end
1118 :    
1119 :    
1120 :    
1121 :    
1122 :    
1123 :    
1124 :    
1125 :     (*
1126 :     * $Log: mips.sml,v $
1127 :     * Revision 1.5 1998/02/12 20:48:38 jhr
1128 :     * Removed references to System.Tags.
1129 :     *
1130 :     * Revision 1.4 1998/01/15 10:44:43 george
1131 :     * Fix for bug 1335.
1132 :     * ibranch did not deal with signed comparisions when the arguments
1133 :     * were 32 bit words.
1134 :     *
1135 :     * Revision 1.3 1997/12/03 19:04:55 george
1136 :     * removed rangeChk
1137 :     *
1138 :     * Revision 1.2 1997/05/20 12:22:18 dbm
1139 :     * SML '97 sharing, where structure.
1140 :     *
1141 :     * Revision 1.1.1.1 1997/01/14 01:38:38 george
1142 :     * Version 109.24
1143 :     *
1144 :     *)

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