|
|
1.1 root 1: (* Copyright 1989 by AT&T Bell Laboratories *)
2: functor M68CM(V : M68CODER) : CMACHINE = struct
3:
4: structure V' : sig
5: datatype Register = DataReg of int
6: | AddrReg of int
7: | FloatReg of int
8: | PC
9:
10: type Label sharing type Label = V.Label
11: datatype Size = Byte | Word | Long
12:
13: datatype EA = Direct of Register
14: | PostInc of Register
15: | PreDec of Register
16: | Displace of Register * int
17: | Index of Register * int * Register * Size
18: | Immed of int
19: | Immedlab of Label
20: | Abs of int
21: | Address of Label
22:
23: end = V
24: open V'
25:
26: datatype condition = NEQ | EQL | LEQ | GEQ | LSS | GTR
27:
28: (* +DEBUG *)
29: fun diag (s : string) f x =
30: f x handle e =>
31: (print "?exception "; print (System.exn_name e);
32: print " in m68."; print s; print "\n";
33: raise e)
34: (* -DEBUG *)
35:
36: fun defer(Direct r) = Displace(r,0)
37: | defer(Immedlab lab) = Address lab
38: | defer _ = ErrorMsg.impossible "defer in cpsm68"
39:
40: (* DEBUG *) val defer = diag "defer" defer
41:
42: val exnptr = Direct(DataReg 7)
43: val dataptr as Direct dataptr' = Direct(AddrReg 6)
44: val arithtemp as Direct arithtemp' = Direct(DataReg 1)
45: val arithtemp2 = Direct(DataReg 2)
46: val arithtemp3 = Direct(DataReg 4)
47: val storeptr = Direct(DataReg 6)
48: val standardclosure = Direct(AddrReg 2)
49: val standardarg = Direct(AddrReg 0)
50: val standardcont = Direct(AddrReg 1)
51: val miscregs = map (Direct o AddrReg) [3,4]
52: val datalimit = Direct(DataReg 5)
53:
54: val ptrtemp2 = Direct(DataReg 3)
55: val ptrtemp as Direct ptrtemp' = Direct(AddrReg 5)
56:
57: fun reg(Direct r) = r
58:
59: fun newlabel() = Immedlab(V.newlabel())
60: (* DEBUG *) val newlabel = diag "newlabel" newlabel
61: fun emitlab(i,Immedlab lab) = V.emitlab(i,lab)
62: fun define (Immedlab lab) = V.define lab
63:
64: fun beginStdFn _ = ()
65:
66: (* checkLimit (n):
67: * Generate code to check the heap limit to see if there is enough free space
68: * to allocate n bytes.
69: *)
70: fun checkLimit maxAllocSize = (
71: V.comment ("check limit, max alloc = "^(makestring maxAllocSize)^"\n");
72: (* Check the heap limit register *)
73: if (maxAllocSize <= 4096)
74: then (
75: V.cmpl(dataptr, datalimit);
76: V.trapmi())
77: else (
78: V.movl (dataptr, arithtemp3);
79: V.addl(Immed(maxAllocSize-4096), arithtemp3);
80: V.cmpl(arithtemp3, datalimit);
81: V.trapmi()))
82:
83: val align = V.align
84: val mark = V.mark
85: fun move(Immedlab l, dest as Direct(AddrReg x)) = V.lea(Address l, dest)
86: | move(Immedlab l, dest) =
87: (V.lea(Address l, ptrtemp);
88: move(ptrtemp,dest))
89: | move(Displace(DataReg(d), i), dest) =
90: (V.movl(Direct(DataReg(d)), ptrtemp);
91: move(Displace(reg(ptrtemp), i), dest))
92: (* let's hope that ptrtemp never shows up in both src and dest! *)
93: | move(src, Address l) =
94: (V.lea(Address l, ptrtemp);
95: move(src, Displace(reg(ptrtemp), 0)))
96: | move x = V.movl x
97: (* DEBUG *) val move = diag "move" move
98:
99: val emitlong = V.emitlong
100: val realconst = V.realconst
101: val emitstring = V.emitstring
102:
103: fun ashl(s as Immed k, r, d as Direct(DataReg _)) =
104: (if r<>d then move(r,d) else (); V.asll(s,d))
105: | ashl(s as Direct(DataReg _),r,d) =
106: (move(r,arithtemp3); V.asll(s,arithtemp3); move(arithtemp3,d))
107: | ashl(s as Immed k,r,d) =
108: (move(r,arithtemp3);
109: if k>8
110: then (move(s,arithtemp2); V.asll(arithtemp2,arithtemp3))
111: else V.asll(s,arithtemp3);
112: move(arithtemp3,d))
113:
114: (* DEBUG *) val ashl = diag "ashl" ashl
115:
116: fun ashr(s as Immed k, r, d as Direct(DataReg _)) =
117: (if r<>d then move(r,d) else ();
118: if k>8 then (move(s,arithtemp3); V.asrl(arithtemp3,d)) else V.asrl(s,d))
119: | ashr(s as Direct(DataReg _),r,d) =
120: (move(r,arithtemp3); V.asrl(s,arithtemp3); move(arithtemp3,d))
121: | ashr(s as Immed k,r,d) =
122: (move(r,arithtemp3);
123: if k>8
124: then (move(s,arithtemp2); V.asrl(arithtemp2,arithtemp3))
125: else V.asrl(s,arithtemp3);
126: move(arithtemp3,d))
127:
128: fun jmpindexb lab = V.jra(Index(PC,2,arithtemp',Byte))
129: (* DEBUG *) val jmpindexb = diag "jmpindexb" jmpindexb
130:
131: fun record(vl, z) =
132: let open CPS
133: fun f (Direct r, SELp(j,p)) = f(Displace(r,j*4),p)
134: | f (Immedlab l, p) = (V.lea(Address l, ptrtemp); f(ptrtemp,p))
135: | f (x,OFFp 0) = V.movl(x, PostInc dataptr')
136: | f (Direct r, OFFp j) = (V.lea(Displace(r,j*4),ptrtemp);
137: f(ptrtemp,OFFp 0))
138: | f (x,p) = (V.movl(x,ptrtemp); f(ptrtemp,p))
139: in
140: app f vl;
141: V.lea(Displace(dataptr',~4*(List.length(vl)-1)),z)
142: end
143:
144: fun select(i, Direct r, s) = move(Displace(r,i*4),s)
145: | select(0, a, s) = move(defer a,s)
146:
147: fun offset(i, Direct r, s) = V.lea(Displace(r,i*4),s)
148: (* DEBUG *) val select = diag "select" select
149: (* DEBUG *) val offset = diag "offset" offset
150:
151: exception Three
152: fun three opcode (a as Direct(AddrReg _), b as Direct(AddrReg _),
153: c as Direct(AddrReg _)) =
154: (three opcode(a,b,arithtemp3); move(arithtemp3,c))
155: | three opcode (a,b,c) =
156: if b=c then opcode(a,b)
157: else if a=c then (move(a,arithtemp3); three opcode(arithtemp3,b,c))
158: else (move(b,c); opcode(a,c))
159:
160: fun threet opcode (a,b,c as Direct(AddrReg _)) =
161: (threet opcode(a,b,arithtemp3); move(arithtemp3,c))
162: | threet opcode (a,b,c) =
163: if b=c then (opcode(a,b); V.trapv())
164: else if a=c then (move(a,arithtemp3); threet opcode(arithtemp3,b,c))
165: else (move(b,c); opcode(a,c); V.trapv())
166:
167: fun three' opcode (a as Immed _,b,c as Direct(DataReg _)) =
168: three opcode(a,b,c)
169: | three' opcode (a as Direct(AddrReg _),b,c) =
170: (move(b,arithtemp3); move(a,arithtemp2);
171: opcode(arithtemp2,arithtemp3); move(arithtemp3,c))
172: | three' opcode (a,b,c) =
173: (move(b,arithtemp3); opcode(a,arithtemp3); move(arithtemp3,c))
174:
175: fun orb(a as Immed k,b,c as Direct(DataReg _)) =
176: if k<65538
177: then if k<=0
178: then raise Match
179: else if b=c then V.orl(a,b) else (move(b,c); V.orl(a,c))
180: else (move(a,arithtemp3);
181: if b=c then V.orl(arithtemp3,b) else (move(b,c); V.orl(arithtemp3,c)))
182: | orb(a as Direct(AddrReg _),b,c) =
183: (move(b,arithtemp3); move(a,arithtemp2);
184: V.orl(arithtemp2,arithtemp3); move(arithtemp3,c))
185: | orb(a as Immed k,b,c) =
186: if k<65536
187: then if k<=0
188: then raise Match
189: else (move(b,arithtemp3); V.orl(a,arithtemp3); move(arithtemp3,c))
190: else (move(a,arithtemp2);
191: move(b,arithtemp3);
192: V.orl(arithtemp2,arithtemp3);
193: move(arithtemp3,c))
194: | orb(a,b,c) = (move(b,arithtemp3); V.orl(a,arithtemp3); move(arithtemp3,c))
195:
196: fun xorb(a as Immed k,b,c as Direct(DataReg _)) =
197: if k<65536
198: then if k<=0
199: then raise Match
200: else if b=c then V.eorl(a,b) else (move(b,c); V.eorl(a,c))
201: else (move(a,arithtemp3);
202: if b=c then V.eorl(arithtemp3,b) else (move(b,c); V.eorl(arithtemp3,c)))
203: | xorb(a as Direct(AddrReg _),b,c) =
204: (move(b,arithtemp3); move(a,arithtemp2);
205: V.eorl(arithtemp2,arithtemp3); move(arithtemp3,c))
206: | xorb(a as Immed k,b,c) =
207: if k<65538
208: then if k<=0
209: then raise Match
210: else (move(b,arithtemp3); V.eorl(a,arithtemp3); move(arithtemp3,c))
211: else (move(a,arithtemp2);
212: move(b,arithtemp3);
213: V.eorl(arithtemp2,arithtemp3);
214: move(arithtemp3,c))
215: | xorb(a,b,c) = (move(b,arithtemp3); V.eorl(a,arithtemp3); move(arithtemp3,c))
216:
217: fun notb(a,b) = (move(Immed ~1,arithtemp3); V.subl(a,arithtemp3);
218: move(arithtemp3,b))
219: val andb = three' V.andl
220: val addl3 = three V.addl
221: val addl3t = threet V.addl
222: val subl3 = three V.subl
223: val subl3t = threet V.subl
224: val mull2 = V.mull
225: fun mull2t x = (mull2 x; V.trapv())
226: val divl2 = V.divl
227:
228: exception Fetchindexb
229: fun fetchindexb(Direct x,y) = (if y=arithtemp then raise Fetchindexb else ();
230: move(Immed 0,y);
231: V.movb(Index(x,0,arithtemp',Byte),y))
232: (* DEBUG *) val fetchindexb = diag "fetchindexb" fetchindexb
233: fun storeindexb(x, Direct y) = V.movb(x,Index(y,0,arithtemp',Byte))
234: (* DEBUG *) val storeindexb = diag "storeindexb" storeindexb
235: fun fetchindexl(Direct x,y,Immed k) = move(Displace(x,k+k-2),y)
236: | fetchindexl(Direct x,y,Direct z) = move(Index(x,~2,z,Word),y)
237: | fetchindexl(Immedlab lab, y, Direct z) =
238: (* this is a hack, since it depends on lab being PC+6 *)
239: move(Index(PC,4,z,Word), y);
240: (* DEBUG *) val fetchindexl = diag "fetchindexl" fetchindexl
241: fun storeindexl(x, y, Immed 1) = move(x, defer y)
242: | storeindexl(x, Direct y, Immed k) = move(x, Displace(y,k+k-2))
243: | storeindexl(x, Direct y, Direct z) = move(x,Index(y,~2,z,Word))
244: (* DEBUG *) val storeindexl = diag "storeindexl" storeindexl
245:
246: val fp0 = FloatReg 0
247:
248: fun finishreal(c) = (V.cmpl(dataptr,datalimit);
249: V.trapmi();
250: V.movl(Immed(8*System.Tags.power_tags
251: + System.Tags.tag_string),
252: PostInc dataptr');
253: V.movl(dataptr,c);
254: V.fmoved(Direct fp0, PostInc dataptr'))
255:
256: fun float f (a,b,c) =
257: (V.fmoved(defer a, Direct fp0);
258: f(defer b, Direct fp0);
259: finishreal c)
260:
261: fun mnegg (a,c) = (V.fnegd(defer a, Direct fp0); finishreal c)
262:
263: val mulg3 = float V.fmuld
264: val divg3 = float V.fdivd
265: val addg3 = float V.faddd
266: val subg3 = float V.fsubd
267:
268: fun cbranch NEQ = V.jne
269: | cbranch EQL = V.jeq
270: | cbranch LEQ = V.jle
271: | cbranch GEQ = V.jge
272: | cbranch LSS = V.jlt
273: | cbranch GTR = V.jgt
274:
275: fun fbranch NEQ = V.fjne
276: | fbranch EQL = V.fjeq
277: | fbranch LEQ = V.fjle
278: | fbranch GEQ = V.fjge
279: | fbranch LSS = V.fjlt
280: | fbranch GTR = V.fjgt
281:
282: fun rev LEQ = GEQ
283: | rev GEQ = LEQ
284: | rev LSS = GTR
285: | rev GTR = LSS
286: | rev NEQ = NEQ
287: | rev EQL = EQL
288:
289: fun ibranch (cond, op1 as Immed _, op2, label) =
290: (V.cmpl(op1, op2); cbranch (rev cond) (defer label))
291: | ibranch (cond, op1, op2, label) =
292: (V.cmpl(op2, op1); cbranch cond (defer label))
293:
294: fun gbranch (cond, op1, op2, label) =
295: (V.fmoved(defer op1,Direct fp0);
296: V.fcmpd(defer op2, Direct fp0);
297: fbranch cond (defer label))
298:
299: fun defer' j = fn x => j(defer x)
300: val jmp = defer' V.jra
301: fun bbs (x,dest as Direct(AddrReg _) ,l) = (move(dest,ptrtemp2);
302: bbs(x,ptrtemp2,l))
303: | bbs (x,y,l) = (V.btst(x,y); V.jne(defer l))
304: (* DEBUG *) val bbs = diag "bbs" bbs
305:
306: val immed = Immed
307: fun isimmed(Immed i) = SOME i
308: | isimmed _ = NONE
309: fun isreg(Direct(AddrReg i)) = SOME i
310: | isreg(Direct(DataReg i)) = SOME(i+8)
311: | isreg _ = NONE
312:
313: fun eqreg (a: EA) b = a=b
314: (* DEBUG *) val eqreg = diag "eqreg" eqreg
315:
316: fun profile(index,incr) = V.addl(Immed incr, Displace(V.sp,4*index))
317:
318: val comment = V.comment
319: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.