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/sparc/sparcinstr.sml
ViewVC logotype

Annotation of /sml/trunk/src/compiler/OldCGen/sparc/sparcinstr.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 16 - (view) (download)

1 : monnier 16 (* sparcinstr.sml
2 :     *
3 :     * Copyright 1989 by AT&T Bell Laboratories
4 :     *
5 :     * AUTHOR: John Reppy
6 :     * Cornell University
7 :     * Ithaca, NY 14853
8 :     * jhr@cs.cornell.edu
9 :     *
10 :     *)
11 :    
12 :     structure SparcInstr =
13 :     struct
14 :    
15 :     val branchDelayedArch = true
16 :    
17 :     datatype 'label info = INFO of {addrOf: 'label -> int,
18 :     nameOf: 'label->string}
19 :     datatype register = REG of int
20 :     datatype fregister = FREG of int
21 :    
22 :     datatype 'label labelexp
23 :     = LABELexp of { (* An offset relative to a label. The value of a *)
24 :     base : 'label, (* label expression is ((dst - base) + offset). *)
25 :     dst : 'label,
26 :     offset : int
27 :     }
28 :    
29 :     datatype 'label operand
30 :     = REGrand of register (* A register value *)
31 :     | IMrand of int (* A small integer constant (13 bits) *)
32 :     | LABrand of 'label labelexp (* small valued label expression (13 bits)*)
33 :     | HIrand of 'label labelexp (* The high 22 bits of a label expression *)
34 :     | LOrand of 'label labelexp (* The low 10 bits of a label expression *)
35 :    
36 :    
37 :     datatype cond_code
38 :     = CC_A | CC_E | CC_NE | CC_G | CC_GE | CC_L | CC_LE | CC_GEU |
39 :     CC_LEU | CC_GU | CC_LU
40 :    
41 :     datatype fcond_code
42 :     = FCC_A | FCC_U (* unordered *) | FCC_G | FCC_UG | FCC_L | FCC_UL
43 :     | FCC_LG | FCC_NE | FCC_E | FCC_UE | FCC_GE | FCC_UGE | FCC_LE
44 :     | FCC_ULE | FCC_O
45 :    
46 :     datatype 'label instruction
47 :     = I_nop
48 :     | I_ld of 'label ops3 (* ld: load word *)
49 :     | I_ldb of 'label ops3 (* ldb: load byte (unsigned) *)
50 :     | I_ldf of 'label fmemops (* ldf: load floating-point register *)
51 :     | I_st of 'label ops3 (* st: store word *)
52 :     | I_stb of 'label ops3 (* stb: store byte *)
53 :     | I_stf of 'label fmemops (* stf: store f-p register *)
54 :     | I_sethi of ('label operand * register) (* sethi *)
55 :     | I_bcc of (cond_code * 'label)
56 :     | I_fbcc of (fcond_code * 'label)
57 :     | I_jmpl of 'label ops3 (* jmpl: jump and link *)
58 :     | I_call2 (* call 2; used to load PC *)
59 :     | I_add of 'label ops3 (* add *)
60 :     | I_addcc of 'label ops3 (* add and set condition codes *)
61 :     | I_taddcctv of 'label ops3 (* tagged add with overflow trap *)
62 :     | I_sub of 'label ops3
63 :     | I_subcc of 'label ops3 (* subtract and set condition codes *)
64 :     | I_sll of 'label ops3
65 :     | I_srl of 'label ops3
66 :     | I_sra of 'label ops3
67 :     | I_and of 'label ops3
68 :     | I_andcc of 'label ops3 (* logical and, set condition codes *)
69 :     | I_or of 'label ops3
70 :     | I_xor of 'label ops3
71 :     | I_not of (register * register)
72 :     | I_tvs (* tvs: trap on integer overflow *)
73 :     | I_fadd of fops3 (* floating-point addition *)
74 :     | I_fsub of fops3 (* floating-point subtraction *)
75 :     | I_fmul of fops3 (* floating-point multiplication *)
76 :     | I_fdiv of fops3 (* floating-point division *)
77 :     | I_fneg of fops2 (* floating-point negation *)
78 :     | I_fabs of fops2 (* floating-point absolute value *)
79 :     | I_fcmp of fops2 (* floating-point comparison *)
80 :     | I_fmov of fops2 (* floating-point register-register move *)
81 :     | I_fitod of fops2 (* convert int to double floating-point *)
82 :     withtype 'label ops3 = (register * 'label operand * register)
83 :     and 'label fmemops = (register * 'label operand * fregister)
84 :     and fops3 = (fregister * fregister * fregister)
85 :     and fops2 = (fregister * fregister)
86 :    
87 :     datatype ikind = IK_NOP | IK_JUMP | IK_INSTR
88 :    
89 :     fun instrKind (I_nop) = IK_NOP
90 :     | instrKind (I_bcc _) = IK_JUMP
91 :     | instrKind (I_fbcc _) = IK_JUMP
92 :     | instrKind (I_jmpl _) = IK_JUMP
93 :     | instrKind _ = IK_INSTR
94 :    
95 :     val nop = I_nop
96 :    
97 :    
98 :    
99 :     (** Span dependent instructions **
100 :     * The implementation of these instructions depends on the value of the
101 :     * label expressions. The last register argument is a temporary register
102 :     * to be used in address computations (if necessary).
103 :     *)
104 :    
105 :     datatype 'label sdi
106 :     = SetBaseAddr of ('label labelexp * register)
107 :     | LoadAddr of ('label labelexp * register)
108 :     | Load of ('label labelexp * register * register)
109 :     | LoadF of ('label labelexp * fregister * register)
110 :    
111 :     fun isSdiBranch _ = false
112 :    
113 :     fun minSize (SetBaseAddr _) = 4
114 :     | minSize (LoadF _) = 8
115 :     | minSize _ = 4
116 :    
117 :     local
118 :     (* Sizes of SDIs *)
119 :     val sz0max = (true, 0) and sz12max = (true, 12)
120 :     val sz16max = (true, 16) and sz20max = (true, 20)
121 :     val sz4 = (false, 4) and sz8 = (false, 8) and sz12 = (false, 12)
122 :     in
123 :    
124 :     (* Return the size of the various span-dependent instructions. This should
125 :     * be consistent with expand in "sparccoder.sml" *)
126 :     fun sizeOf (INFO{addrOf,...}) (I,_) = let
127 :     fun span (LABELexp{base, dst, offset}) =
128 :     ((addrOf dst) + offset) - (addrOf base)
129 :     fun sizeOf' labexp = let
130 :     val x = span labexp
131 :     in
132 :     if (x < ~4096) orelse (4095 < x) then sz12max else sz4
133 :     end
134 :     in
135 :     case I
136 :     of SetBaseAddr(labexp,_) => let
137 :     val x = span labexp
138 :     in if (4095 < x)
139 :     then if (8190 < x)
140 :     then sz12max
141 :     else sz8 (* use two subtract immediates *)
142 :     else if (x < ~4096)
143 :     then sz12max
144 :     else sz4
145 :     end
146 :     | LoadAddr(labexp, _) => sizeOf' labexp
147 :     | Load(labexp, _, _) => sizeOf' labexp
148 :     | LoadF(labexp, _, _) => let
149 :     val x = span labexp
150 :     in
151 :     if (x < ~4092) orelse (4092 <= x) then sz20max else sz8
152 :     end
153 :     end
154 :    
155 :     end (* local *)
156 :    
157 :     local
158 :     val linkReg = REG 15 (* %o7 *)
159 :     val baseReg = REG 27 (* %i3 *)
160 :     val zeroR = REG 0 (* %g0 *)
161 :     val zeroRand = REGrand zeroR
162 :     in
163 :    
164 :     (* expand SDIs into real instruction sequences. *)
165 :     fun expand (INFO{addrOf,...}) =
166 :     fn (SetBaseAddr(labexp,reg), 4,_) => [
167 :     I_sub(reg, LABrand labexp, baseReg)]
168 :     | (SetBaseAddr(LABELexp{base, dst, offset},reg), 8,_) => let
169 :     val n = if (((addrOf dst) - (addrOf base)) < 0) then ~4096 else 4095
170 :     val labexp = LABELexp{base=base, dst=dst, offset=offset - n}
171 :     in [
172 :     I_sub(reg, IMrand n, baseReg),
173 :     I_sub(baseReg, LABrand labexp, baseReg)]
174 :     end
175 :     | (SetBaseAddr(labexp,reg), 12,_) => [
176 :     I_sethi(HIrand labexp, baseReg),
177 :     I_or(baseReg, LOrand labexp, baseReg),
178 :     I_sub(reg, REGrand baseReg, baseReg)]
179 :     | (LoadAddr(labexp, dst), 4,_) => [I_add(baseReg, LABrand(labexp), dst)]
180 :     | (LoadAddr(labexp, dst), 12,_) => [
181 :     I_sethi(HIrand labexp, dst),
182 :     I_or(dst, LOrand labexp, dst),
183 :     I_add(baseReg, REGrand dst, dst)]
184 :     | (Load(labexp, dst, _), 4,_) => [I_ld(baseReg, LABrand(labexp), dst)]
185 :     | (Load(labexp, dst, tmpR), 12,_) => [
186 :     I_sethi(HIrand(labexp), tmpR),
187 :     I_or(tmpR, LOrand labexp, tmpR),
188 :     I_ld(baseReg, REGrand tmpR, dst)]
189 :     | (LoadF(labexp as LABELexp{base, dst, offset}, FREG i, _), 8,_) => [
190 :     I_ldf(baseReg, LABrand(labexp), FREG i),
191 :     I_ldf(baseReg, LABrand(LABELexp{base=base, dst=dst, offset=offset+4}),
192 :     FREG(i+1))]
193 :     | (LoadF(labexp, FREG i, tmpR), 20,_) => [
194 :     I_sethi(HIrand(labexp), tmpR),
195 :     I_or(tmpR, LOrand(labexp), tmpR),
196 :     I_add(baseReg, REGrand tmpR, tmpR),
197 :     I_ldf(tmpR, zeroRand, FREG i),
198 :     I_ldf(tmpR, IMrand 4, FREG(i+1)) ]
199 :    
200 :     end (* local *)
201 :    
202 :    
203 :     (** Resource usage **
204 :     *
205 :     * The sparc resources are the condition codes, floating-point condition codes,
206 :     * registers %r1-%r31, floating-point registers (viewed as a single resource),
207 :     * the npc (next pc) and memory. We treat %g6 (the dataptr) specially. We
208 :     * assume that %g6 is only used in 'add', 'taddcctv', 'st', 'stf', and 'or' (move)
209 :     * instructions. We use %g6 to denote the "allocation" resource. This interferes
210 :     * in a non-standard way with the memory resource and with itself. Store
211 :     * instructions using %g6 as a base register don't define the memory resource, but
212 :     * the move of %g6 (using 'or') to another register is an implicit definition of
213 :     * the memory resource (since it makes the allocation visible), the move also
214 :     * defines the allocation resource, since it should only occur after the record
215 :     * has been initialized. There is an implicit use dependency between the
216 :     * 'tvs' instruction and the exnptr register. The npc resource is used to create
217 :     * a use-def dependency between trap instructions ('tvs' and 'taddcctv') and branch
218 :     * instructions. This avoids the having traps scheduled in branch shadows.
219 :     *)
220 :    
221 :     val numRegs = 31 (* %r1-%r31 *)
222 :    
223 :     val numResources = (* registers + fp regs + mem, condition codes, *)
224 :     (numRegs + 6) (* fp condition codes, npc and the stack *)
225 :    
226 :     local
227 :     val memRId = 0
228 :     val memR = [memRId]
229 :     fun addRegR (REG 0, lst) = lst
230 :     | addRegR (REG i, lst) = (i :: lst)
231 :     fun regR r = addRegR(r, nil)
232 :     val allocRId = 6 and allocR = [6] (* %g6 *)
233 :     val exnptrRId = 7 (* %g7 *)
234 :     val linkRId = 15 and linkR = [15] (* %o7 (link and base register) *)
235 :     val fregsRId = (numRegs + 1)
236 :     val ccRId = (fregsRId + 1)
237 :     val fccRId = (ccRId + 1)
238 :     val fregsR = [fregsRId]
239 :     val ccR = [ccRId] and fccR = [fccRId]
240 :     val npcRId = (fccRId + 1)
241 :     val npcR = [npcRId]
242 :     val stackRId = (npcRId + 1)
243 :     val stackR = [stackRId]
244 :     fun rUseDef3 (a, REGrand b, c) = (addRegR(a, regR b), regR c)
245 :     | rUseDef3 (a, _, c) = (regR a, regR c)
246 :     fun rUseDef3cc (a, REGrand b, c) = (addRegR(a, regR b), ccRId :: (regR c))
247 :     | rUseDef3cc (a, _, c) = (regR a, ccRId :: (regR c))
248 :     val fregUseDef = (fregsR, fregsR)
249 :     val farithUseDef = (fregsR, fregsR)
250 :     val allR = let
251 :     fun f (~1, l) = l | f (i, l) = f(i-1, i::l)
252 :     in
253 :     f (numResources-1, nil)
254 :     end
255 :     in
256 :    
257 :     fun rUseDef (I_nop) = ([], [])
258 :     | rUseDef (I_ld args) = let val (u, d) = rUseDef3 args in (memRId :: u, d) end
259 :     | rUseDef (I_ldb args) = let val (u, d) = rUseDef3 args in (memRId :: u, d) end
260 :     | rUseDef (I_ldf(a as REG 14,_,c)) = (stackRId::regR a,fregsR)
261 :     | rUseDef (I_ldf(a, REGrand b, c)) = (memRId :: addRegR(a, regR b), fregsR)
262 :     | rUseDef (I_ldf(a, _, c)) = (memRId :: regR a, fregsR)
263 :     | rUseDef (I_st(REG 6, REGrand b, c)) = (allocRId :: addRegR(b, regR c), [])
264 :     | rUseDef (I_st(REG 6, _, c)) = (allocRId :: (regR c), [])
265 :     | rUseDef (I_st(a as REG 14,_,c)) = (addRegR(a,regR c), stackR)
266 :     | rUseDef (I_st(a, REGrand b, c)) = (addRegR(a, addRegR(b, regR c)), memR)
267 :     | rUseDef (I_st(a, _, c)) = (addRegR(a, regR c), memR)
268 :     | rUseDef (I_stb(a, REGrand b, c)) = (addRegR(a, addRegR(b, regR c)), memR)
269 :     | rUseDef (I_stb(a, _, c)) = (addRegR(a, regR c), memR)
270 :     | rUseDef (I_stf(REG 6, REGrand b, c)) = (allocRId :: addRegR(b, fregsR), [])
271 :     | rUseDef (I_stf(REG 6, _, c)) = (allocRId :: fregsR, [])
272 :     | rUseDef (I_stf(a, REGrand b, c)) = (addRegR(a, addRegR(b, fregsR)), memR)
273 :     | rUseDef (I_stf(a, _, c)) = (addRegR(a, fregsR), memR)
274 :     | rUseDef (I_sethi(_, r)) = ([], regR r)
275 :     | rUseDef (I_bcc(CC_A, _)) = ([], npcR)
276 :     | rUseDef (I_bcc _) = (ccR, npcR)
277 :     | rUseDef (I_fbcc _) = (fccR, npcR)
278 :     | rUseDef (I_jmpl(a, REGrand b, c)) = (addRegR(a, regR b), addRegR(c, npcR))
279 :     | rUseDef (I_jmpl(a, _, c)) = (regR a, addRegR(c, npcR))
280 :     | rUseDef (I_call2) = (allR, allR) (* to prevent it from being moved *)
281 :     | rUseDef (I_add(REG 6, _, REG c)) = (* this completes the allocation *)
282 :     (allocR, [allocRId, c, memRId])
283 :     | rUseDef (I_add args) = rUseDef3 args
284 :     | rUseDef (I_addcc args) = rUseDef3cc args
285 :     | rUseDef (I_taddcctv _) = (allR, allR) (* GC limit check *)
286 :     | rUseDef (I_sub args) = rUseDef3 args
287 :     | rUseDef (I_subcc args) = rUseDef3cc args
288 :     | rUseDef (I_sll args) = rUseDef3 args
289 :     | rUseDef (I_sra args) = rUseDef3 args
290 :     | rUseDef (I_srl args) = rUseDef3 args
291 :     | rUseDef (I_and args) = rUseDef3 args
292 :     | rUseDef (I_andcc args) = rUseDef3cc args
293 :     | rUseDef (I_or args) = rUseDef3 args
294 :     | rUseDef (I_xor args) = rUseDef3 args
295 :     | rUseDef (I_not(a, b)) = (regR a, regR b)
296 :     | rUseDef (I_tvs) = ([memRId, ccRId, exnptrRId, npcRId, allocRId], [])
297 :     | rUseDef (I_fadd _) = farithUseDef
298 :     | rUseDef (I_fsub _) = farithUseDef
299 :     | rUseDef (I_fmul _) = farithUseDef
300 :     | rUseDef (I_fdiv _) = farithUseDef
301 :     | rUseDef (I_fneg _) = fregUseDef
302 :     | rUseDef (I_fabs _) = fregUseDef
303 :     | rUseDef (I_fcmp _) = (fregsR, fccR)
304 :     | rUseDef (I_fmov _) = fregUseDef
305 :     | rUseDef (I_fitod _) = fregUseDef
306 :     end (* local *)
307 :    
308 :     fun mayNeedNop (I_fcmp _) = 1
309 :     | mayNeedNop (I_bcc _) = 1
310 :     | mayNeedNop (I_fbcc _) = 1
311 :     | mayNeedNop (I_jmpl _) = 1
312 :     | mayNeedNop _ = 0
313 :    
314 :     fun needsNop (I_fbcc _, I_fcmp _::_) = 1
315 :     | needsNop _ = 0
316 :    
317 :     (* These numbers are true for the Fujitsu implementation *)
318 :     fun latency (I_ld _) = 2
319 :     | latency (I_ldb _) = 2
320 :     | latency (I_jmpl _) = 2
321 :     | latency (I_taddcctv _) = 2
322 :     | latency I_tvs = 2
323 :     | latency (I_ldf _) = 2
324 :     | latency (I_bcc _) = 2
325 :     | latency (I_fbcc _) = 2
326 :     (* guessing on these ... *)
327 :     | latency (I_fcmp _) = 2
328 :     | latency (I_fadd _) = 3
329 :     | latency (I_fsub _) = 3
330 :     | latency (I_fmul _) = 3
331 :     | latency (I_fdiv _) = 4
332 :     | latency _ = 1
333 :    
334 :     end (* SparcInstr *)
335 :    
336 :     (*
337 :     * $Log: sparcinstr.sml,v $
338 :     * Revision 1.3 1997/08/19 14:47:01 george
339 :     * Bug fix for 1222 (ref assignment not performed before overflow).
340 :     *
341 :     * Revision 1.2 1997/05/05 19:57:35 george
342 :     * Add the allocation pointer to the list of source registers for the
343 :     * tvs instruction. This fixed the subtle bug on interactions between
344 :     * the allocation-pointer-adjustment instruction and the addi
345 :     * instruction. -- zsh
346 :     *
347 :     * Revision 1.1.1.1 1997/01/14 01:38:46 george
348 :     * Version 109.24
349 :     *
350 :     *)

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