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/MLRISC/hppa/hppa.mdl
ViewVC logotype

Annotation of /sml/trunk/src/MLRISC/hppa/hppa.mdl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1033 - (view) (download)

1 : leunga 746 (*
2 :     * This is the new machine description language.
3 :     *
4 :     *)
5 :    
6 :     architecture Hppa =
7 :     struct
8 :    
9 :     superscalar
10 :    
11 :     big endian
12 :    
13 :     lowercase assembly
14 :    
15 :     (*========================================================================
16 :     * On the HP, handling of delay slots is quite complicated:
17 :     *
18 :     * For conditional branches:
19 :     * -------------------------
20 :     * Branch direction
21 :     * Forward Backward
22 :     * Nullify bit on Nullify if branch taken Nullify if branch not-taken
23 :     * Nullify bit off Delay slot active Delay slot active
24 :     *
25 :     * For unconditional branches:
26 :     * ---------------------------
27 :     *
28 :     * Nullify bit on Delay slot nullified
29 :     * Nullify bit off Delay slot active
30 :     *========================================================================*)
31 :    
32 :    
33 :     (* debug MC *)
34 :    
35 :     (*========================================================================
36 :     * Storage types definitions
37 :     *========================================================================*)
38 :     storage
39 :     GP = $r[32] of 32 bits where $r[0] = 0
40 :     asm: (fn (r,_) => "%r"^Int.toString r)
41 :     | FP = $f[32] of 64 bits where $f[0] = 0
42 :     asm: (fn (f,_) => "%f"^Int.toString f)
43 :     | CR = $cr[32] of 32 bits asm: (fn (cr,_) => "%cr"^Int.toString cr)
44 :     | CC = $cc[] of 32 bits aliasing GP asm: "cc"
45 :     | MEM = $m[] of 8 aggregable bits asm: (fn (r,_) => "m"^Int.toString r)
46 :     | CTRL = $ctrl[] asm: (fn (r,_) => "ctrl"^Int.toString r)
47 :    
48 :     locations
49 :     returnPtr = $r[2]
50 :     and stackptrR = $r[30]
51 :     and asmTmpR = $r[29]
52 :     and fasmTmp = $f[31]
53 :     and sar = $cr[11]
54 :     and r0 = $r[0]
55 :     and f0 = $f[0]
56 :    
57 :     (*========================================================================
58 :     * RTL specification.
59 :     *========================================================================*)
60 :     structure RTL =
61 :     struct
62 :     include "Tools/basis.mdl"
63 :     open Basis
64 :     infix 1 ||
65 :     infix 2 :=
66 :     infix 5 + -
67 :     infix 6 << >> ~>>
68 :     infix 6 * div mod
69 :    
70 :     fun %% l = (l : #32 bits)
71 :    
72 :     rtl NOP{} = ()
73 :    
74 :     (* Integer loads *)
75 :     (* On the HP, addressing modes can be scaled and/or autoincrement *)
76 :     fun disp(r,i) = $r[r] + i
77 :     fun fdisp(r,d) = $r[r] + d
78 :     fun indexed(r1,r2) = $r[r1] + $r[r2]
79 :     fun scaled(r1,r2,scale) = $r[r1] << scale + $r[r2]
80 :     fun autoinc(r,i) = $r[r] := $r[r] + i
81 :     fun overflowtrap{} = ()
82 :    
83 :     fun byte x = (x : #8 bits)
84 :     fun half x = (x : #16 bits)
85 :     fun word x = (x : #32 bits)
86 :     fun quad x = (x : #64 bits)
87 :     fun % x = word x
88 :    
89 :     rtl LDO{b,i,t} = $r[t] := $r[b] + %i
90 :     rtl LDO2{i,t} = $r[t] := i
91 :     rtl LDIL{i,t} = $r[t] := i << 11
92 :     rtl MTCTL{r,t} = $cr[t] := $r[r]
93 :    
94 :     rtl LDW{r,i,t,mem} = $r[t] := $m[disp(r,i) : mem]
95 :     rtl LDH{r,i,t,mem} = $r[t] := zx(half $m[disp(r,i):mem])
96 :     rtl LDB{r,i,t,mem} = $r[t] := zx(byte $m[disp(r,i):mem])
97 :     rtl LDWX{r1,r2,t,mem} = $r[t] := $m[indexed(r1,r2):mem]
98 :     rtl LDWX_S{r1,r2,t,mem} = $r[t] := $m[scaled(r1,r2,2):mem]
99 :     rtl LDWX_M{r1,r2,t,mem} = $r[t] := $m[indexed(r1,r2):mem] || autoinc(r1,1)
100 :     rtl LDWX_SM{r1,r2,t,mem} = $r[t] := $m[scaled(r1,r2,2):mem] || autoinc(r1,4)
101 :     rtl LDHX{r1,r2,t,mem} = $r[t] := zx(half $m[indexed(r1,r2):mem])
102 :     rtl LDHX_S{r1,r2,t,mem} = $r[t] := zx(half $m[scaled(r1,r2,1):mem])
103 :     rtl LDHX_M{r1,r2,t,mem} = $r[t] := zx(half $m[indexed(r1,r2):mem]) ||
104 :     autoinc(r1,1)
105 :     rtl LDHX_SM{r1,r2,t,mem} = $r[t] := zx(half $m[scaled(r1,r2,1):mem]) ||
106 :     autoinc(r1,2)
107 :     rtl LDBX{r1,r2,t,mem} = $r[t] := zx(byte $m[indexed(r1,r2):mem])
108 :     rtl LDBX_M{r1,r2,t,mem} = $r[t] := zx(byte $m[indexed(r1,r2):mem]) ||
109 :     autoinc(r1,1)
110 :    
111 :     (* Integer stores *)
112 :     rtl STW{b,d,r,mem} = $m[disp(b,d):mem] := $r[r]
113 :     rtl STH{b,d,r,mem} = $m[disp(b,d):mem] := half(zx $r[r])
114 :     rtl STB{b,d,r,mem} = $m[disp(b,d):mem] := byte(zx $r[r])
115 :    
116 :     (* Integer opcodes *)
117 :     rtl ADD{r1,r2,t} = $r[t] := $r[r1] + $r[r2]
118 :     rtl ADDL{r1,r2,t} = $r[t] := $r[r1] + $r[r2]
119 :     rtl ADDO{r1,r2,t} = $r[t] := addt($r[r1], $r[r2])
120 :     rtl SUB{r1,r2,t} = $r[t] := $r[r1] - $r[r2]
121 :     rtl SUBO{r1,r2,t} = $r[t] := subt($r[r1], $r[r2])
122 :     rtl SH1ADD{r1,r2,t} = $r[t] := $r[r1] << 1 + $r[r2]
123 :     rtl SH2ADD{r1,r2,t} = $r[t] := $r[r1] << 2 + $r[r2]
124 :     rtl SH3ADD{r1,r2,t} = $r[t] := $r[r1] << 3 + $r[r2]
125 :     rtl SH1ADDL{r1,r2,t} = $r[t] := $r[r1] << 1 + $r[r2]
126 :     rtl SH2ADDL{r1,r2,t} = $r[t] := $r[r1] << 2 + $r[r2]
127 :     rtl SH3ADDL{r1,r2,t} = $r[t] := $r[r1] << 3 + $r[r2]
128 :     rtl SH1ADDO{r1,r2,t} = $r[t] := addt($r[r1] << 1, $r[r2])
129 :     rtl SH2ADDO{r1,r2,t} = $r[t] := addt($r[r1] << 2, $r[r2])
130 :     rtl SH3ADDO{r1,r2,t} = $r[t] := addt($r[r1] << 3, $r[r2])
131 :     rtl OR{r1,r2,t} = $r[t] := orb($r[r1], $r[r2])
132 :     rtl AND{r1,r2,t} = $r[t] := andb($r[r1], $r[r2])
133 :     rtl XOR{r1,r2,t} = $r[t] := xorb($r[r1], $r[r2])
134 :     rtl ANDCM{r1,r2,t} = $r[t] := andb($r[r1], notb($r[r2]))
135 :    
136 :     rtl ADDI{r,i,t} = $r[t] := $r[r] + i
137 :     rtl ADDIO{r,i,t} = $r[t] := addt($r[r], i)
138 :     rtl ADDIL{r,i,t} = $r[t] := $r[r] + i
139 :     rtl SUBI{r,i,t} = $r[t] := $r[r] + i
140 :     rtl SUBIO{r,i,t} = $r[t] := subt($r[r], i)
141 :    
142 :     (* Shifts *)
143 :     rtl extru extrs zdep : #n bits * #n bits * #n bits -> #n bits
144 :     val sar = $cr[11]
145 :     rtl VEXTRU{r, len, t} = $r[t] := extru($r[r], sar, len)
146 :     rtl VEXTRS{r, len, t} = $r[t] := extrs($r[r], sar, len)
147 :     rtl ZVDEP{r, len, t} = $r[t] := zdep($r[r], sar, len)
148 :     rtl EXTRU{r, p, len, t} = $r[t] := extru($r[r], p, len)
149 :     rtl EXTRS{r, p, len, t} = $r[t] := extrs($r[r], p, len)
150 :     rtl ZDEP{r, p, len, t} = $r[t] := zdep($r[r], p, len)
151 :    
152 :     val comparisons =
153 :     [(==), (<), (<=),
154 :     (ltu), (leu), (<>),
155 :     (>=), (>), (gtu), (geu)]
156 :    
157 :     (* COMCLR/LDO composite instruction:
158 :     * COMCLR,cc r1, r2, t1
159 :     * LDO i(b), t2
160 :     *)
161 :     fun COMCLR_LDO cc {r1,r2,t1,i,b,t2} =
162 :     if cc($r[r1],$r[r2]) then $r[t1] := 0 else $r[t2] := $r[b] + i
163 :     rtl COMCLR_LDO_ ^^ [EQ, LT, LE, LTU, LEU, NE, GE, GT, GTU, GEU] =
164 :     map COMCLR_LDO comparisons
165 :    
166 :     (* COMCLR/LDO composite instruction:
167 :     * COMCLR,cc r1, r2, t
168 :     * LDO i(b), t
169 :     * This version assumes that t1 = t2.
170 :     *)
171 :     fun COMCLR_LDO2 cc {r1,r2,t1,i,b} =
172 :     if cc($r[r1],$r[r2]) then $r[t1] := 0 else $r[t1] := $r[b] + i
173 :     rtl COMCLR_LDO2_ ^^ [EQ, LT, LE, LTU, LEU, NE, GE, GT, GTU, GEU] =
174 :     map COMCLR_LDO2 comparisons
175 :    
176 :     (* COMCLR/LDO composite instruction:
177 :     * COMCLR,cc r1, r2, %r0
178 :     * LDO i(b), t
179 :     * This version assumes that t1 = %r0.
180 :     *)
181 :     fun COMCLR_LDO3 cc {r1,r2,t2,i,b} =
182 :     if cc($r[r1],$r[r2]) then () else $r[t2] := $r[b] + i
183 :     rtl COMCLR_LDO3_ ^^ [EQ, LT, LE, LTU, LEU, NE, GE, GT, GTU, GEU] =
184 :     map COMCLR_LDO3 comparisons
185 :    
186 :     (* COMICLR/LDO composite instruction:
187 :     * COMICLR,cc i1, r2, t1
188 :     * LDO i(b), t2
189 :     *)
190 :     fun COMICLR_LDO cc {i1,r2,t1,i2,b,t2} =
191 :     if cc(%i1,$r[r2]) then $r[t1] := 0 else $r[t2] := $r[b] + i2
192 :     rtl COMICLR_LDO_ ^^ [EQ, LT, LE, LTU, LEU, NE, GE, GT, GTU, GEU] =
193 :     map COMICLR_LDO comparisons
194 :    
195 :     (* COMICLR/LDO composite instruction:
196 :     * COMICLR,cc i1, r2, t
197 :     * LDO i(b), t
198 :     * This version assumes that t1 = t2.
199 :     *)
200 :     fun COMICLR_LDO2 cc {i1,r2,t1,i2,b} =
201 :     if cc(i1,$r[r2]) then $r[t1] := 0 else $r[t1] := $r[b] + i2
202 :     rtl COMICLR_LDO2_ ^^ [EQ, LT, LE, LTU, LEU, NE, GE, GT, GTU, GEU] =
203 :     map COMICLR_LDO2 comparisons
204 :    
205 :     (* COMICLR/LDO composite instruction:
206 :     * COMICLR,cc i1, r2, %r0
207 :     * LDO i(b), t
208 :     * This version assumes that t1 = %r0.
209 :     *)
210 :     fun COMICLR_LDO3 cc {i1,r2,t2,i2,b} =
211 :     if cc(%i1,$r[r2]) then () else $r[t2] := $r[b] + i2
212 :     rtl COMICLR_LDO3_ ^^ [EQ, LT, LE, LTU, LEU, NE, GE, GT, GTU, GEU] =
213 :     map COMICLR_LDO3 comparisons
214 :    
215 :     (* Integer branching instructions *)
216 :     fun COMBT cmp {r1,r2,t} =
217 :     (if cmp($r[r1],$r[r2]) then Jmp(%%t) else ()) || $ctrl[0] := ???
218 :     fun COMBF cmp {r1,r2,t} =
219 :     (if cmp($r[r1],$r[r2]) then () else Jmp(%%t)) || $ctrl[0] := ???
220 :     fun COMIBT cmp {i,r2,t} =
221 :     (if cmp(%i,$r[r2]) then Jmp(%%t) else ()) || $ctrl[0] := ???
222 :     fun COMIBF cmp {i,r2,t} =
223 :     (if cmp(%i,$r[r2]) then () else Jmp(%%t)) || $ctrl[0] := ???
224 :     rtl COMBT_ ^^ [EQ, LT, LE, LTU, LEU, NE, GE, GT, GTU, GEU] =
225 :     map COMBT comparisons
226 :     rtl COMBF_ ^^ [EQ, LT, LE, LTU, LEU, NE, GE, GT, GTU, GEU] =
227 :     map COMBF comparisons
228 :     rtl COMIBT_ ^^ [EQ, LT, LE, LTU, LEU, NE, GE, GT, GTU, GEU] =
229 :     map COMIBT comparisons
230 :     rtl COMIBF_ ^^ [EQ, LT, LE, LTU, LEU, NE, GE, GT, GTU, GEU] =
231 :     map COMIBF comparisons
232 :    
233 :     rtl B{lab} = Jmp(%% lab)
234 :     rtl BV{x,b} = Jmp($r[x] << 2 + $r[b])
235 :     (* BB,< branch on bit set *)
236 :     rtl BB_BSET{p,r,t} =
237 :     (if andb($r[r],1 << (31 - p)) <> 0 then Jmp(%%t) else ())
238 :     || $ctrl[0] := ???
239 :     (* BB,>= branch on bit clear *)
240 :     rtl BB_BCLR{p,r,t} =
241 :     (if andb($r[r],1 << (31 - p)) == 0 then Jmp(%%t) else ())
242 :     || $ctrl[0] := ???
243 :    
244 :     rtl BLE{d,b,defs,uses} =
245 :     Call($r[b] + d) || (* call *)
246 :     Kill $r[31] || (* return address *)
247 :     Kill $cellset[defs] ||
248 :     Use $cellset[uses]
249 :    
250 :     (* Floating point loads *)
251 :     rtl FLDDS{b,d,t,mem} = $f[t] := $m[fdisp(b,d):mem]
252 :     rtl FLDWS{b,d,t,mem} = $f[t] := $m[fdisp(b,d):mem]
253 :     rtl FLDDX{b,x,t,mem} = $f[t] := $m[indexed(b,x):mem]
254 :     rtl FLDDX_S{b,x,t,mem} = $f[t] := $m[scaled(b,x,3):mem]
255 :     rtl FLDDX_M{b,x,t,mem} = $f[t] := $m[indexed(b,x):mem] || autoinc(b,8)
256 :     rtl FLDDX_SM{b,x,t,mem} = $f[t] := $m[scaled(b,x,3):mem] || autoinc(b,8)
257 :     rtl FLDWX{b,x,t,mem} = $f[t] := $m[indexed(b,x):mem]
258 :     rtl FLDWX_S{b,x,t,mem} = $f[t] := $m[scaled(b,x,2):mem]
259 :     rtl FLDWX_M{b,x,t,mem} = $f[t] := $m[indexed(b,x):mem] || autoinc(b,4)
260 :     rtl FLDWX_SM{b,x,t,mem} = $f[t] := $m[scaled(b,x,2):mem] || autoinc(b,4)
261 :    
262 :     (* Floating point stores *)
263 :     rtl FSTDS{b,d,r,mem} = $m[fdisp(b,d):mem] := $f[r]
264 :     rtl FSTWS{b,d,r,mem} = $m[fdisp(b,d):mem] := $f[r]
265 :     rtl FSTDX{b,x,r,mem} = $m[indexed(b,x):mem] := $f[r]
266 :     rtl FSTDX_S{b,x,r,mem} = $m[scaled(b,x,3):mem] := $f[r]
267 :     rtl FSTDX_M{b,x,r,mem} = $m[indexed(b,x):mem] := $f[r] || autoinc(b,8)
268 :     rtl FSTDX_SM{b,x,r,mem} = $m[scaled(b,x,3):mem] := $f[r] || autoinc(b,8)
269 :     rtl FSTWX{b,x,r,mem} = $m[indexed(b,x):mem] := $f[r]
270 :     rtl FSTWX_S{b,x,r,mem} = $m[scaled(b,x,2):mem] := $f[r]
271 :     rtl FSTWX_M{b,x,r,mem} = $m[indexed(b,x):mem] := $f[r] || autoinc(b,4)
272 :     rtl FSTWX_SM{b,x,r,mem} = $m[scaled(b,x,2):mem] := $f[r] || autoinc(b,4)
273 :    
274 :     (* Floating point binary operators *)
275 :     rtl FADD_S{r1,r2,t} = $f[t] := fadd($f[r1], $f[r2])
276 :     rtl FADD_D{r1,r2,t} = $f[t] := fadd($f[r1], $f[r2])
277 :     rtl FADD_Q{r1,r2,t} = $f[t] := fadd($f[r1], $f[r2])
278 :     rtl FSUB_S{r1,r2,t} = $f[t] := fsub($f[r1], $f[r2])
279 :     rtl FSUB_D{r1,r2,t} = $f[t] := fsub($f[r1], $f[r2])
280 :     rtl FSUB_Q{r1,r2,t} = $f[t] := fsub($f[r1], $f[r2])
281 :     rtl FMPY_S{r1,r2,t} = $f[t] := fsub($f[r1], $f[r2])
282 :     rtl FMPY_D{r1,r2,t} = $f[t] := fmul($f[r1], $f[r2])
283 :     rtl FMPY_Q{r1,r2,t} = $f[t] := fmul($f[r1], $f[r2])
284 :     rtl FDIV_S{r1,r2,t} = $f[t] := fdiv($f[r1], $f[r2])
285 :     rtl FDIV_D{r1,r2,t} = $f[t] := fdiv($f[r1], $f[r2])
286 :     rtl FDIV_Q{r1,r2,t} = $f[t] := fdiv($f[r1], $f[r2])
287 :     rtl XMPYU{r1,r2,t} = $f[t] := muls($f[r1], $f[r2])
288 :    
289 :     (* Floating point unary operators *)
290 :     rtl cvtf2i : #n bits -> #m bits
291 :     rtl fsqrt : #n bits -> #n bits
292 :     rtl FCPY_S{f,t} = $f[t] := $f[f]
293 :     rtl FCPY_D{f,t} = $f[t] := $f[f]
294 :     rtl FCPY_Q{f,t} = $f[t] := $f[f]
295 :     rtl FABS_S{f,t} = $f[t] := fabs($f[f])
296 :     rtl FABS_D{f,t} = $f[t] := fabs($f[f])
297 :     rtl FABS_Q{f,t} = $f[t] := fabs($f[f])
298 :     rtl FSQRT_S{f,t} = $f[t] := fsqrt($f[f])
299 :     rtl FSQRT_D{f,t} = $f[t] := fsqrt($f[f])
300 :     rtl FSQRT_Q{f,t} = $f[t] := fsqrt($f[f])
301 :     rtl FRND_S{f,t} = $f[t] := cvtf2i($f[f])
302 :     rtl FRND_D{f,t} = $f[t] := cvtf2i($f[f])
303 :     rtl FRND_Q{f,t} = $f[t] := cvtf2i($f[f])
304 :    
305 :     (* Floating point/fix point conversion operators *)
306 :     rtl fcnvff_sd fcnvff_sq fcnvff_ds fcnvff_dq
307 :     fcnvff_qs fcnvff_qd fcnvxf_s fcnvxf_d
308 :     fcnvxf_q fcnvfx_s fcnvfx_d fcnvfx_q
309 :     fcnvfxt_s fcnvfxt_d fcnvfxt_q
310 :     : #n bits -> #n bits
311 :    
312 :     rtl FCNVFF_SD{f,t} = $f[t] := fcnvff_sd $f[f]
313 :     rtl FCNVFF_SQ{f,t} = $f[t] := fcnvff_sq $f[f]
314 :     rtl FCNVFF_DS{f,t} = $f[t] := fcnvff_ds $f[f]
315 :     rtl FCNVFF_DQ{f,t} = $f[t] := fcnvff_dq $f[f]
316 :     rtl FCNVFF_QS{f,t} = $f[t] := fcnvff_qs $f[f]
317 :     rtl FCNVFF_QD{f,t} = $f[t] := fcnvff_qd $f[f]
318 :     (* fixed point -> floating point *)
319 :     rtl FCNVXF_S{f,t} = $f[t] := fcnvxf_s $f[f]
320 :     rtl FCNVXF_D{f,t} = $f[t] := fcnvxf_d $f[f]
321 :     rtl FCNVXF_Q{f,t} = $f[t] := fcnvxf_q $f[f]
322 :     (* floating point -> fixed point (use current rounding mode?) *)
323 :     rtl FCNVFX_S{f,t} = $f[t] := fcnvfx_s $f[f]
324 :     rtl FCNVFX_D{f,t} = $f[t] := fcnvfx_d $f[f]
325 :     rtl FCNVFX_Q{f,t} = $f[t] := fcnvfx_q $f[f]
326 :     (* floating point -> fixed point (and truncate) *)
327 :     rtl FCNVFXT_S{f,t} = $f[t] := fcnvfxt_s $f[f]
328 :     rtl FCNVFXT_D{f,t} = $f[t] := fcnvfxt_d $f[f]
329 :     rtl FCNVFXT_Q{f,t} = $f[t] := fcnvfxt_q $f[f]
330 :    
331 :     (* Floating point branch *)
332 :     fun FBRANCH cmp {f1,f2,t} =
333 :     if cmp($f[f1],$f[f2]) then Jmp(%%t) else ()
334 :    
335 :     rtl FBRANCH_ ^^
336 :     [?, !<=>, ==, ?=, !<>, !?>=, <, ?<,
337 :     !>=, !?>, <=, ?<=, !>, !?<=, >, ?>,
338 :     !<=, !?<, >=, ?>=, !<, !?=, <>, !=,
339 :     !?, <=>, ?<>] =
340 :     map FBRANCH
341 :     [|?|, |!<=>|, |==|, |?=|, |!<>|, |!?>=|, |<|, |?<|,
342 :     |!>=|, |!?>|, |<=|, |?<=|, |!>|, |!?<=|, |>|, |?>|,
343 :     |!<=|, |!?<|, |>=|, |?>=|, |!<|, |!?=|, |<>|, |!=|,
344 :     |!?|, |<=>|, |?<>|]
345 :    
346 :     end (* RTL *)
347 :    
348 :     (*========================================================================
349 :     * Instruction representation
350 :     *========================================================================*)
351 :     structure Instruction =
352 :     struct
353 :    
354 :     datatype fmt! = SGL 0w0 | DBL 0w1 | QUAD 0w3
355 :    
356 :     datatype loadi :Op! = LDW 0x12 (* p5-28 *)
357 :     | LDH 0x11 (* p5-29 *)
358 :     | LDB 0x10 (* p5-30 *)
359 :    
360 :     datatype store :Op! = STW 0x1A (* p5-31 *)
361 :     | STH 0x19 (* p5-32 *)
362 :     | STB 0x18 (* p5-33 *)
363 :    
364 :     (* addressing mode
365 :     * when the u bit is set, the index "x" is scaled by the size
366 :     * when the m bit is set, the base is also auto-incremented
367 :     *)
368 :    
369 :     datatype load :ext4! =
370 :     (* ext4, u, m *)
371 :     LDWX "ldwx" (0w2,0w0,0w0) (* p5-36 *)
372 :     | LDWX_S "ldwx,s" (0w2,0w1,0w0)
373 :     | LDWX_M "ldwx,m" (0w2,0w0,0w1)
374 :     | LDWX_SM "ldwx,sm" (0w2,0w1,0w1)
375 :     | LDHX "ldhx" (0w1,0w0,0w0) (* p5-37 *)
376 :     | LDHX_S "ldhx,s" (0w1,0w1,0w0)
377 :     | LDHX_M "ldhx,m" (0w1,0w0,0w1)
378 :     | LDHX_SM "ldhx,sm" (0w1,0w1,0w1)
379 :     | LDBX "ldbx" (0w0,0w0,0w0) (* p5-38 *)
380 :     | LDBX_M "ldbx,m" (0w0,0w0,0w1)
381 :    
382 :     (* All branching is done with nullification *)
383 :     datatype cmp! = COMBT 0wx20
384 :     | COMBF 0wx22
385 :    
386 :     datatype cmpi! = COMIBT 0wx21
387 :     | COMIBF 0wx23
388 :    
389 :     datatype arith! =
390 :     ADD 0x18 (* p5-83 *)
391 :     | ADDL 0x28 (* p5-84 *)
392 :     | ADDO 0x38 (* p5-85 *)
393 :     | SH1ADD 0x19 (* p5-88 *)
394 :     | SH1ADDL 0x29 (* p5-89 *)
395 :     | SH1ADDO 0x39 (* p5-90 *)
396 :     | SH2ADD 0x1A (* p5-91 *)
397 :     | SH2ADDL 0x2A (* p5-92 *)
398 :     | SH2ADDO 0x3A (* p5-93 *)
399 :     | SH3ADD 0x1B (* p5-94 *)
400 :     | SH3ADDL 0x2B (* p5-95 *)
401 :     | SH3ADDO 0x3B (* p5-96 *)
402 :     | SUB 0x10 (* p5-97 *)
403 :     | SUBO 0x30 (* p5-98 *)
404 :     | OR 0x09 (* p5-105 *)
405 :     | XOR 0x0A (* p5-106 *)
406 :     | AND 0x08 (* p5-107 *)
407 :     | ANDCM 0x00 (* p5-108 *)
408 :    
409 :     datatype arithi! =
410 :     ADDI (0wx2d,0w0)
411 :     | ADDIO (0wx2d,0w1)
412 :     | ADDIL
413 :     | SUBI (0wx25,0w0)
414 :     | SUBIO (0wx25,0w1)
415 :    
416 :     datatype shiftv! = VEXTRU | VEXTRS | ZVDEP
417 :    
418 :     datatype shift! = EXTRU | EXTRS | ZDEP
419 :    
420 :     datatype farith! = (* sop, fmt *)
421 :     FADD_S "fadd,sgl" (0w0, 0w0)
422 :     | FADD_D "fadd,dbl" (0w0, 0w1)
423 :     | FADD_Q "fadd,quad" (0w0, 0w3)
424 :    
425 :     | FSUB_S "fsub,sgl" (0w1, 0w0)
426 :     | FSUB_D "fsub,dbl" (0w1, 0w1)
427 :     | FSUB_Q "fsub,quad" (0w1, 0w3)
428 :    
429 :     | FMPY_S "fmpy,sgl" (0w2, 0w0)
430 :     | FMPY_D "fmpy,dbl" (0w2, 0w1)
431 :     | FMPY_Q "fmpy,quad" (0w2, 0w3)
432 :    
433 :     | FDIV_S "fdiv,sgl" (0w3, 0w0)
434 :     | FDIV_D "fdiv,dbl" (0w3, 0w1)
435 :     | FDIV_Q "fdiv,quad" (0w3, 0w3)
436 :    
437 :     | XMPYU (* ok *)
438 :    
439 :     datatype funary! = (* sop, fmt *)
440 :     (* copy *)
441 :     FCPY_S "fcpy,sgl" (0w2,0w0)
442 :     | FCPY_D "fcpy,dbl" (0w2,0w1)
443 :     | FCPY_Q "fcpy,quad" (0w2,0w3)
444 :    
445 :     | FABS_S "fabs,sgl" (0w3,0w0)
446 :     | FABS_D "fabs,dbl" (0w3,0w1)
447 :     | FABS_Q "fabs,quad" (0w3,0w3)
448 :    
449 :     | FSQRT_S "fsqrt,sgl" (0w4,0w0)
450 :     | FSQRT_D "fsqrt,dbl" (0w4,0w1)
451 :     | FSQRT_Q "fsqrt,quad" (0w4,0w3)
452 :    
453 :     (* round float to integer *)
454 :     | FRND_S "frnd,sgl" (0w5,0w0)
455 :     | FRND_D "frnd,dbl" (0w5,0w1)
456 :     | FRND_Q "frnd,quad" (0w5,0w3)
457 :    
458 :     (* FCNVXF --- the source is the LHS single precision floating register *)
459 :     datatype fcnv = (* sop, sf, df *)
460 :     (* floating point -> floating point *)
461 :     FCNVFF_SD "fcnvff,sgl,dbl" (0w0,0w0,0w1)
462 :     | FCNVFF_SQ "fcnvff,sgl,quad" (0w0,0w0,0w3)
463 :     | FCNVFF_DS "fcnvff,dbl,sgl" (0w0,0w1,0w0)
464 :     | FCNVFF_DQ "fcnvff,dbl,quad" (0w0,0w1,0w3)
465 :     | FCNVFF_QS "fcnvff,quad,sgl" (0w0,0w3,0w0)
466 :     | FCNVFF_QD "fcnvff,quad,dbl" (0w0,0w3,0w1)
467 :    
468 :     (* fixed point -> floating point *)
469 :     | FCNVXF_S "fcnvxf,,sgl" (0w1,0w0,0w0)
470 :     | FCNVXF_D "fcnvxf,,dbl" (0w1,0w0,0w1)
471 :     | FCNVXF_Q "fcnvxf,,quad" (0w1,0w0,0w3)
472 :    
473 :     (* floating point -> fixed point (use current rounding mode?) *)
474 :     | FCNVFX_S "fcnvfx,sgl," (0w2,0w0,0w0)
475 :     | FCNVFX_D "fcnvfx,dbl," (0w2,0w1,0w0)
476 :     | FCNVFX_Q "fcnvfx,quad," (0w2,0w3,0w0)
477 :    
478 :     (* floating point -> fixed point (and truncate) *)
479 :     | FCNVFXT_S "fcnvfxt,sgl," (0w3,0w0,0w0)
480 :     | FCNVFXT_D "fcnvfxt,dbl," (0w3,0w1,0w0)
481 :     | FCNVFXT_Q "fcnvfxt,quad," (0w3,0w3,0w0)
482 :    
483 :     datatype fstore! = FSTDS
484 :     | FSTWS
485 :     (* Op, uid, u, m *)
486 :     datatype fstorex! = FSTDX "fstdx" (0wxb,0w0,0w0,0w0)
487 :     | FSTDX_S "fstdx,s" (0wxb,0w0,0w1,0w0)
488 :     | FSTDX_M "fstdx,m" (0wxb,0w0,0w0,0w1)
489 :     | FSTDX_SM "fstdx,sm" (0wxb,0w0,0w1,0w1)
490 :     | FSTWX "fstwx" (0wx9,0w1,0w0,0w0)
491 :     | FSTWX_S "fstwx,s" (0wx9,0w1,0w1,0w0)
492 :     | FSTWX_M "fstwx,m" (0wx9,0w1,0w0,0w1)
493 :     | FSTWX_SM "fstwx,sm" (0wx9,0w1,0w1,0w1)
494 :    
495 :     (* FLDWX and FLDWS -- loads the RHS of the floating register *)
496 :     (* Op, uid, u, m *)
497 :     datatype floadx! = FLDDX "flddx" (0wxb,0w0,0w0,0w0)
498 :     | FLDDX_S "flddx,s" (0wxb,0w0,0w1,0w0)
499 :     | FLDDX_M "flddx,m" (0wxb,0w0,0w0,0w1)
500 :     | FLDDX_SM "flddx,sm" (0wxb,0w0,0w1,0w1)
501 :     | FLDWX "fldwx" (0wx9,0w1,0w0,0w0)
502 :     | FLDWX_S "fldwx,s" (0wx9,0w1,0w1,0w0)
503 :     | FLDWX_M "fldwx,m" (0wx9,0w1,0w0,0w1)
504 :     | FLDWX_SM "fldwx,sm" (0wx9,0w1,0w1,0w1)
505 :    
506 :     datatype fload! = FLDDS
507 :     | FLDWS
508 :    
509 :     (* page 5-5. fields for (c,f) *)
510 :     datatype bcond! = EQ "=" 0w1
511 :     | LT "<" 0w2
512 :     | LE "<=" 0w3
513 :     | LTU "<<" 0w4
514 :     | LEU "<<=" 0w5
515 :     | NE "<>" (* unimplemented *)
516 :     | GE ">=" (* ... *)
517 :     | GT ">"
518 :     | GTU ">>"
519 :     | GEU ">>="
520 :    
521 :     (* table 5-7 *)
522 :     datatype bitcond! = BSET "<" 0w2 (* bit is 1 *)
523 :     | BCLR ">=" 0w6 (* bit is 0 *)
524 :    
525 :     (* table 6-13 *)
526 :     datatype fcond [0..31] =
527 :     False_ "false?" | False "false" | ? | !<=> | == | EQT "=T" | ?= | !<>
528 :     | !?>= | < | ?< | !>= | !?> | <= | ?<= | !>
529 :     | !?<= | > | ?> | !<= | !?< | >= | ?>=
530 :     | !< | !?= | <> | != | NET "!=T" | !? | <=> | True_ "true?" | True "true"
531 :    
532 :     datatype scond = ALL_ZERO | LEFTMOST_ONE | LEFTMOST_ZERO | RIGHTMOST_ONE
533 :     | RIGHTMOST_ZERO
534 :    
535 :     datatype field_selector = F
536 :     | S
537 :     | D
538 :     | R
539 :     | T
540 :     | P
541 :    
542 :     datatype ea =
543 :     Direct of $GP
544 :     | FDirect of $GP
545 : george 1033 | Displace of {base: $GP, disp: T.labexp, mem: Region.region}
546 : leunga 746
547 :     datatype operand =
548 :     (* this is used only during instruction selection *)
549 :     REG of $GP rtl: $r[GP]
550 :     | IMMED of int ``<int>'' rtl: int
551 : leunga 775 | LabExp of T.labexp * field_selector ``<labexp>'' rtl: labexp
552 :     | HILabExp of T.labexp * field_selector ``<labexp>''
553 :     | LOLabExp of T.labexp * field_selector ``<labexp>''
554 : leunga 746
555 :     datatype addressing_mode =
556 : george 889 DISPea of CellsBasis.cell * operand (* displacement *)
557 :     | INDXea of CellsBasis.cell * CellsBasis.cell (* indexed *)
558 :     | INDXSCALEDea of CellsBasis.cell * CellsBasis.cell (* indexed with scaling (b,x) *)
559 : leunga 746
560 :     end (* Instruction *)
561 :    
562 :     (* ========================= Instruction Encoding =========================
563 :     *
564 :     * HP has 41 different instruction formats.
565 :     * The instruction encoding is, for the lack of a better phrase,
566 :     * all fucked up.
567 :     *
568 :     * See Appendix C.
569 :     *========================================================================*)
570 :     instruction formats 32 bits
571 :     (* sr=0 for load store, why? *)
572 :     Load{Op:6,b:GP 5,t:GP 5,s:2=0,im14:signed 14}
573 :     | Store{st:store 6,b:GP 5,r:GP 5,s:2=0,im14:signed 14}
574 :    
575 :     (* sr=3, m=0 no modify, cc=0 *)
576 :     | IndexedLoad{Op:6,b:GP 5,x:GP 5,s:2=3,u:1,_:1=0,cc:2=0,ext4:4,m:1,t:GP 5}
577 :    
578 :     | ShortDispLoad{Op:6,b:GP 5,im5:signed 5,s:2,a:1,_:1=1,cc:2,ext4:4,m:1,t:GP 5}
579 :     | ShoftDispShort{Op:6,b:5,r:5,s:2,a:1,_:1=1,cc:2,ext4:4,m:1,im5:signed 5}
580 :    
581 :     | LongImmed{Op:6,r:GP 5,im21:signed 21}
582 :    
583 :     | Arith{Op:6=0x2,r2:GP 5,r1:GP 5,c:3=0,f:1=0,a:arith 6,_:1=0,t:GP 5}
584 :     | Arithi{Op:6,r:GP 5,t:GP 5,c:3=0,f:1=0,e:1,im11:signed 11}
585 :    
586 :     | Extract{Op:6,r:GP 5,t:GP 5,c:3=0,ext3:3,p:int 5,clen:int 5}
587 :    
588 :     | Deposit{Op:6,t:GP 5,r:GP 5,c:3=0,ext3:3,cp:int 5,clen:int 5}
589 :    
590 :     | Shift{Op:6,r2:GP 5,r1:GP 5,c:3=0,ext3:3,cp:5,t:GP 5}
591 :     | ConditionalBranch{Op:6,r2:GP 5,r1:GP 5,c:bcond 3,w1:11,n:bool 1,w:1}
592 :     | ConditionalBranchi{Op:6,r2:GP 5,im5:5,c:bcond 3,w1:11,n:bool 1,w:1}
593 :     | BranchExternal{Op:6,b:GP 5,w1:5,s:3,w2:11,n:bool 1,w:1}
594 :     | BranchAndLink{Op:6,t:GP 5,w1:5,ext3:3,w2:11,n:bool 1,w:1}
595 :     | BranchVectored{Op:6,t:GP 5,x:GP 5,ext3:3,_:11=0,n:bool 1,w:1=0}
596 :     | Break{Op:6,im13:signed 13,ext8:8,im5:signed 5}
597 :     | BranchOnBit{Op:6=0x31,p:int 5,r:GP 5,c:3,w1:11,n:bool 1,w:1}
598 :    
599 :     | MoveToControlReg{Op:6,t:CR 5,r:GP 5,rv:3,ext8:8,_:5=0}
600 :     | CompareClear{Op:6=0wx2,r2:GP 5,r1:GP 5,c:3,f:1,ext:6,_:1=0,t:GP 5}
601 :     | CompareImmClear{Op:6=0wx24,r:GP 5,t:GP 5,c:3,f:1,_:1=0,im11:signed 11}
602 :    
603 :     (* floating point loads and stores *)
604 :     | CoProcShort{Op:6,b:GP 5,im5:5,s:2,a:1,_:1=1,cc:2=0,
605 :     ls:1,uid:3,m:1=0,rt:FP 5}
606 :     | CoProcIndexed{Op:6,b:GP 5,x:GP 5,s:2,u:1,_:1=0,cc:2=0,
607 :     ls:1,uid:3,m:1,rt:FP 5}
608 :    
609 :     (* OR r0,r0,r0 *)
610 :     | NOP{Op:6=0x2,r2:5=0,r1:5=0,c:3=0,f:1=0,a:6=0x9,_:1=0,t:5=0}
611 :    
612 :     | Nop{nop} = if nop then NOP{} else ()
613 :    
614 :     (* floating point ops *)
615 :     | FloatOp0Maj0C{Op:6=0x0C,r:FP 5,_:5=0,sop:3,fmt:2,_:6=0,t:FP 5}
616 :     | FloatOp1Maj0C{Op:6=0x0C,r:FP 5,_:4=0,sop:2,df:2,sf:2,_:2=1,_:4=0,t:FP 5}
617 :     | FloatOp2Maj0C{Op:6=0x0C,r1:FP 5,r2:FP 5,sop:3,fmt:2,_:2=2,_:3=0,n:1,c:5}
618 :     | FloatOp3Maj0C{Op:6=0x0C,r1:FP 5,r2:FP 5,sop:3,fmt:2,_:2=3,_:3=0,n:1,t:FP 5}
619 :    
620 :     | FloatOp0Maj0E{Op:6=0x0E,r:FP 5,_:5=0,sop:3,fmt:2,_:3=0,r2:1,t2:1,_:1=0,
621 :     t:FP 5}
622 :     | FloatOp1Maj0E{Op:6=0x0E,r:FP 5,_:4=0,sop:2,df:2,sf:2,_:2=1,_:1=0,r2:1,t2:1,
623 :     _:1=0,t:FP 5}
624 :     | FloatOp2Maj0E{Op:6=0x0E,r1:FP 5,r2:FP 5,sop:3,r22:1,f:1,_:2=2,_:1=0,
625 :     r11:1,_:2=0,c:5}
626 :     | FloatOp3Maj0E{Op:6=0x0E,r1:FP 5,r2:FP 5,sop:3,r22:1,f:1,_:2=3,_:1=0,
627 :     r11:1,_:2=0,t:FP 5}
628 :     | FloatMultiOp{Op:6=0x0E,rm1:5,rm2:5,ta:5,ra:5,f:1,tm:5}
629 :    
630 :     (* page 6-62 *)
631 :     | FTest{Op:6=0x0C,r1:5=0,r2:5=0,sop:3=1,_:2=0,_:2=2,_:3=0,_:1=1,c:5=0}
632 :    
633 :     structure Assembly =
634 :     struct
635 :     fun emit_n false = () | emit_n true = emit ",n"
636 :     fun emit_nop false = () | emit_nop true = emit "\n\tnop"
637 :     end
638 :    
639 :     (*========================================================================
640 :     * Various utility functions for emitting assembly code
641 :     *========================================================================*)
642 :     structure MC =
643 :     struct
644 : george 889 val zeroR = Option.valOf(C.zeroReg CellsBasis.GP)
645 : leunga 746 fun opn opnd =
646 :     let fun hi21 n = (itow n) >> 0w11
647 :     fun hi21X n = (itow n) ~>> 0w11
648 :     fun lo11 n = (itow n) && 0wx7ff
649 :     (* BUG: should respect the field selectors instead of ignoring them *)
650 :     in case opnd of
651 : george 984 I.HILabExp(lexp, _) => hi21X(MLTreeEval.valueOf lexp)
652 :     | I.LOLabExp(lexp, _) => lo11(MLTreeEval.valueOf lexp)
653 :     | I.LabExp(lexp, _) => itow(MLTreeEval.valueOf lexp)
654 : leunga 746 | I.IMMED i => itow i
655 :     | I.REG _ => error "REG"
656 :     end
657 :    
658 :     (* compute displacement address *)
659 :     fun disp lab = itow((Label.addrOf lab) - !loc - 8) ~>> 0w2
660 :     fun low_sign_ext_im14 n = ((n &&0wx1fff) << 0w1)||((n && 0wx2000) >> 0w13)
661 :     fun low_sign_ext_im11 n = ((n && 0wx3ff) << 0w1)||((n && 0wx400) >> 0w10)
662 :     fun low_sign_ext_im5 n = ((n && 0wxf) << 0w1)||((n && 0wx10) >> 0w4)
663 :    
664 :     fun assemble_3 n =
665 :     let val w1 = (n && 0w4) >> 0w2
666 :     val w2 = (n && 0w3) << 0w1
667 :     in w1 || w2 end
668 :    
669 :     fun assemble_12 n =
670 :     let val w = (n && 0wx800) >> 0w11
671 :     val w1 = ((n && 0wx3ff) << 0w1) || ((n && 0wx400) >> 0w10)
672 :     in (w1, w) end
673 :    
674 :     fun assemble_17 n =
675 :     let val w = (n && 0wx10000) >> 0w16
676 :     val w1 = (n && 0wxf800) >> 0w11
677 :     val w2 = (((n && 0wx3ff) << 0w1) || ((n && 0wx400) >> 0w10))
678 :     in (w, w1, w2) end
679 :    
680 :     fun assemble_21 disp =
681 :     let val w =
682 :     (((disp && 0wx000003) << 0w12) ||
683 :     ((disp && 0wx00007c) << 0w14) ||
684 :     ((disp && 0wx000180) << 0w7) ||
685 :     ((disp && 0wx0ffe00) >> 0w8) ||
686 :     ((disp && 0wx100000) >> 0w20))
687 :     in w end
688 :    
689 :     fun branchLink(Op,t,lab,ext3,n) =
690 :     let val (w,w1,w2) = assemble_17(disp lab)
691 :     in BranchAndLink{Op,t,w1,w2,w,ext3,n} end
692 :    
693 :     fun bcond(cmp,bc,r1,r2,n,t,nop) =
694 :     let val (w1,w) = assemble_12(disp t)
695 :     in ConditionalBranch{Op=emit_cmp cmp,c=bc,r1,r2,n,w,w1}; Nop{nop} end
696 :    
697 :     fun bcondi(cmpi,bc,i,r2,n,t,nop) =
698 :     let val (w1,w) = assemble_12(disp t)
699 :     in ConditionalBranchi{Op=emit_cmpi cmpi,c=bc,
700 :     im5=low_sign_ext_im5(itow i),r2,n,w,w1}; Nop{nop}
701 :     end
702 :     fun branchOnBit(bc,r,p,n,t,nop) =
703 :     let val (w1,w) = assemble_12(disp t)
704 :     in BranchOnBit{p=p,r=r,c=emit_bitcond bc,w1=w1,n=n,w=w}; Nop{nop}
705 :     end
706 :    
707 :     fun cmpCond cond =
708 :     case cond of
709 :     I.EQ => (0w1,0w0)
710 :     | I.LT => (0w2,0w0)
711 :     | I.LE => (0w3,0w0)
712 :     | I.LTU => (0w4,0w0)
713 :     | I.LEU => (0w5,0w0)
714 :     | I.NE => (0w1,0w1)
715 :     | I.GE => (0w2,0w1)
716 :     | I.GT => (0w3,0w1)
717 :     | I.GTU => (0w4,0w1)
718 :     | I.GEU => (0w5,0w1)
719 :    
720 :     end (* MC *)
721 :    
722 :     (*========================================================================
723 :     * Reservation tables and pipeline definitions for scheduling.
724 :     * All information are (uneducated) guesses.
725 :     * But see http://www.cpus.hp.com/techreports/parisc.shtml
726 :     *========================================================================*)
727 :    
728 :     (*
729 :     * Function units.
730 :     *
731 :     *)
732 :     resource mem (* load/store *)
733 :     and alu (* integer alu *)
734 :     and falu (* floating point alu *)
735 :     and fmul (* floating point multiplier *)
736 :     and fdiv (* floating point divider (also sqrt on the HP) *)
737 :     and branch (* branch unit *)
738 :    
739 :     (*
740 :     * Different implementations of cpus.
741 :     * Max
742 :     * Name Aliases Issues Function units
743 :     *)
744 :     cpu PA_700 2 [1 mem, 1 alu, 1 falu, 1 fmul, 1 branch]
745 :     and PA_7100 2 [1 mem, 1 alu, 2 fmul, 2 falu, 1 fdiv, 1 branch]
746 :     and PA_7100LC 2 [1 mem, 1 alu, 2 fmul, 2 falu, 1 fdiv, 1 branch]
747 :     and PA_7200 2 [1 mem, 1 alu, 2 fmul, 2 falu, 1 fdiv, 1 branch]
748 :     and PA_8000 4 [2 mem, 2 alu, 2 fmul, 2 falu, 2 fdiv, 1 branch]
749 :     and PA_8200 "default" 4 [2 mem, 2 alu, 2 fmul, 2 falu, 2 fdiv, 1 branch]
750 :     and PA_8500 4 [2 mem, 2 alu, 2 fmul, 2 falu, 2 fdiv, 1 branch]
751 :    
752 :     (* Definitions of various reservation tables *)
753 :     pipeline NOP _ = []
754 :     and ARITH (PA_700 | PA_7100 | PA_7100LC | PA_7200) = [alu]
755 :     | ARITH (PA_8000 | PA_8200 | PA_8500) = [alu]
756 :     and LOAD _ = [mem]
757 :     and STORE _ = [mem]
758 :     and FARITH (PA_700 | PA_7100 | PA_7100LC | PA_7200) = [falu,falu]
759 :     | FARITH (PA_8000 | PA_8200 | PA_8500) = [falu]
760 :     and FMPY (PA_700 | PA_7100 | PA_7100LC | PA_7200) = [fmul,fmul]
761 :     | FMPY (PA_8000 | PA_8200 | PA_8500) = [fmul]
762 :     (* division is apparently non-pipelined, so we have to
763 :     * hog up the pipeline for a bunch of cycles
764 :     *)
765 :     and FDIV PA_700 = [fmul*10] (* multiplier does division too *)
766 :     | FDIV (PA_7100 | PA_7100LC | PA_7200) = [fdiv*15]
767 :     | FDIV (PA_8000 | PA_8200 | PA_8500) = [fdiv,fdiv*14]
768 :     and BRANCH (PA_700 | PA_7100 | PA_7100LC | PA_7200) = [branch,branch]
769 :     | BRANCH (PA_8000 | PA_8200 | PA_8500) = [branch,branch]
770 :    
771 :     (*
772 :     * Latencies
773 :     * Note: the number refers the *additional* delay, so 0 means that
774 :     * the result computed in cycle t is available in cycle t+1.
775 :     *)
776 :     latency NOP _ = 0
777 :     and ARITH _ = 0
778 :     and LOAD _ = 1
779 :     and FARITH PA_700 = 2
780 :     | FARITH _ = 1
781 :     and FMPY PA_700 = 2
782 :     | FMPY PA_7100 = 2
783 :     | FMPY _ = 2
784 :     and FDIV PA_700 = 9
785 :     | FDIV PA_7100 = 14
786 :     | FDIV _ = 14
787 :     and FSQRT PA_700 = 17
788 :     | FSQRT PA_7100 = 14
789 :     | FSQRT _ = 14
790 :    
791 :     (*========================================================================
792 :     * Instruction definitions
793 :     *========================================================================*)
794 :     (* FLDWS, FLDWX = define the R half of the FP register.
795 :     * FSTWS = uses the R half of the FP register.
796 :     *)
797 :     instruction
798 :     LOADI of {li:loadi, r: $GP, i:operand, t: $GP, mem:Region.region}
799 :     asm: ``<li>\t<i>(<r>), <t><mem>''
800 :     mc: Load{Op=emit_loadi li,b=r,im14=low_sign_ext_im14(opn i),t=t}
801 :     rtl: ``<li>''
802 :     latency: LOAD
803 :     pipeline: LOAD
804 :    
805 :     | LOAD of {l:load, r1: $GP, r2: $GP, t: $GP, mem:Region.region}
806 :     asm: ``<l>\t<r2>(<r1>), <t><mem>''
807 :     mc: let val (ext4,u,m) = emit_load l
808 :     in IndexedLoad{Op=0w3,b=r1,x=r2,ext4,u,t,m}
809 :     end
810 :     rtl: ``<l>''
811 :     latency: LOAD
812 :     pipeline: LOAD
813 :    
814 :     | STORE of {st:store,b: $GP,d:operand,r: $GP, mem:Region.region}
815 :     asm: ``<st>\t<r>, <d>(<b>)<mem>''
816 :     mc: Store{st,b=b,im14=low_sign_ext_im14(opn d),r=r}
817 :     rtl: ``<st>''
818 :     pipeline: STORE
819 :    
820 :     | ARITH of {a:arith,r1: $GP, r2: $GP, t: $GP}
821 :     asm: ``<a>\t<r1>, <r2>, <t>''
822 :     mc: Arith{a,r1,r2,t}
823 :     rtl: ``<a>''
824 :     latency: ARITH
825 :     pipeline: ARITH
826 :    
827 :     | ARITHI of {ai:arithi, i:operand, r: $GP, t: $GP}
828 :     asm: ``<ai>\t<i>, <r>, <t>''
829 :     mc: (case ai of
830 :     I.ADDIL => LongImmed{Op=0wxa,r=r,im21=assemble_21(opn i)}
831 :     | _ => let val (Op,e) = emit_arithi ai
832 :     in Arithi{Op,r,t,im11=low_sign_ext_im11(opn i),e}
833 :     end
834 :     )
835 :     rtl: ``<ai>''
836 :     latency: ARITH
837 :     pipeline: ARITH
838 :    
839 :     (* This is a composite instruction.
840 :     * The effect is the same as t <- if r1 cc r2 then i+b else 0
841 :     * if t1 = t2
842 :     * COMCLR,cc r1, r2, t1
843 :     * LDO i(b), t2
844 :     *)
845 :     | COMCLR_LDO of {cc:bcond, r1: $GP, r2: $GP, t1 : $GP,
846 :     i:int, b: $GP, t2: $GP}
847 :     asm: (``comclr,<cc>\t<r1>, <r2>, <t1>\n\t'';
848 :     ``ldo\t<i>(<b>), <t2>''
849 :     )
850 :     mc: let val (c,f) = cmpCond cc
851 :     in CompareClear{r1,r2,t=t1,c,f,ext=0wx22};
852 :     Load{Op=0wx0d,b,im14=low_sign_ext_im14(itow i),t=t2}
853 :     end
854 :     rtl: if t1 = t2 then ``COMCLR_LDO2_<cc>''
855 :     else if t1 = 0 then ``COMCLR_LDO3_<cc>''
856 :     else ``<COMCLR_LDO_<cc>''
857 :     latency: ARITH
858 :     pipeline: ARITH
859 :    
860 :     | COMICLR_LDO of {cc:bcond, i1:operand, r2: $GP, t1 : $GP,
861 :     i2:int, b: $GP, t2: $GP}
862 :     asm: (``comiclr,<cc>\t<r2>, <i1>, <t1>\n\t'';
863 :     ``ldo\t<i2>(<b>), <t2>''
864 :     )
865 :     mc: let val (c,f) = cmpCond cc
866 :     in CompareImmClear{r=r2,t=t1,c,f,im11=low_sign_ext_im11(opn i1)};
867 :     Load{Op=0wx0d,b,im14=low_sign_ext_im14(itow i2),t=t2}
868 :     end
869 :     rtl: if t1 = t2 then ``COMICLR_LDO2_<cc>''
870 :     else if t1 = 0 then ``COMICLR_LDO3_<cc>''
871 :     else ``COMICLR_LDO_<cc>''
872 :     latency: ARITH
873 :     pipeline: ARITH
874 :    
875 :     | SHIFTV of {sv:shiftv, r: $GP, len:int, t: $GP}
876 :     asm: ``<sv>\t<r>, <len>, <t>''
877 :     mc: (case sv of
878 :     I.VEXTRU => Extract{Op=0wx34,r,t,ext3=0w4,p=0,clen=32-len}
879 :     | I.VEXTRS => Extract{Op=0wx34,r,t,ext3=0w5,p=0,clen=32-len}
880 :     | I.ZVDEP => Deposit{Op=0wx35,t,r,ext3=0w0,cp=0,clen=32-len}
881 :     )
882 :     rtl: ``<sv>''
883 :     latency: ARITH
884 :     pipeline: ARITH
885 :    
886 :     | SHIFT of {s:shift, r: $GP, p:int, len:int, t: $GP}
887 :     asm: ``<s>\t<r>, <p>, <len>, <t>''
888 :     mc: (case s of
889 :     I.EXTRU => Extract{Op=0wx34,r,t,ext3=0w6,p=p,clen=32-len}
890 :     | I.EXTRS => Extract{Op=0wx34,r,t,ext3=0w7,p=p,clen=32-len}
891 :     | I.ZDEP => Deposit{Op=0wx35,t,r,ext3=0w2,cp=31-p,clen=32-len}
892 :     )
893 :     rtl: ``<s>''
894 :     latency: ARITH
895 :     pipeline: ARITH
896 :    
897 :     | BCOND of {cmp: cmp, bc:bcond,r1: $GP,r2: $GP,n:bool,nop:bool,
898 :     t:Label.label, f:Label.label}
899 :     asm: ``<cmp>,<bc><n>\t<r1>, <r2>, <t><nop>''
900 :     mc: bcond(cmp,bc,r1,r2,n,t,nop)
901 :     rtl: ``<cmp>_<bc>''
902 :     padding: nop = true
903 :     nullified: n = true
904 :     delayslot: not nullified orelse
905 :     (branching forwards andalso taken orelse
906 :     branching backwards andalso not taken
907 :     )
908 :     delayslot candidate: false
909 :     pipeline: BRANCH
910 :    
911 :     | BCONDI of {cmpi: cmpi, bc:bcond, i:int, r2: $GP, n:bool, nop:bool,
912 :     t:Label.label, f:Label.label}
913 :     asm: ``<cmpi>,<bc><n>\t<i>, <r2>, <t><nop>''
914 :     mc: bcondi(cmpi,bc,i,r2,n,t,nop)
915 :     rtl: ``<cmpi>_<bc>''
916 :     padding: nop = true
917 :     nullified: n = true
918 :     delayslot: not nullified orelse
919 :     (branching forwards andalso taken orelse
920 :     branching backwards andalso not taken
921 :     )
922 :     delayslot candidate: false
923 :     pipeline: BRANCH
924 :    
925 :     (* bc must be either < or >= *)
926 :     | BB of {bc:bitcond,r: $GP, p:int, n:bool, nop:bool,
927 :     t:Label.label, f:Label.label}
928 :     asm: ``bb,<bc><n>\t<r>, <p>, <t><nop>''
929 :     mc: branchOnBit(bc,r,p,n,t,nop)
930 :     rtl: ``BB_<bc>''
931 :     padding: nop = true
932 :     nullified: n = true
933 :     delayslot: not nullified orelse
934 :     (branching forwards andalso taken orelse
935 :     branching backwards andalso not taken
936 :     )
937 :     delayslot candidate: false
938 :     pipeline: BRANCH
939 :    
940 :     | B of {lab:Label.label, n:bool}
941 :     asm: ``b<n>\t<lab>''
942 :     mc: branchLink(0wx3a,zeroR,lab,0w0,n)
943 :     rtl: ``B''
944 :     nullified: n = true
945 :     delayslot candidate: false
946 :     pipeline: BRANCH
947 :    
948 :     (*
949 :     * This composite instruction is generated only during span dependence
950 :     * resolution when trying to resolve conditional branches.
951 :     * The expanded sequence is 12 bytes long.
952 :     * Basically, the branch and link instruction jumps directly to
953 :     * the next instruction at tmpLab, and put the address of tmpLab + 4
954 :     * into register tmp. The offset computation in addil computes the
955 :     * actual address of lab.
956 :     *)
957 :     | LONGJUMP of {lab:Label.label, n:bool, tmp: $GP, tmpLab:Label.label}
958 :     asm: (``bl,n\t<tmpLab>, <tmp>\n'';
959 :     ``<tmpLab>:\n\t'';
960 :     ``addil <lab>-(<tmpLab>+4), <tmp>\n\t'';
961 :     ``bv<n>\t%r0(<tmp>)''
962 :     )
963 :     mc: let val offset =
964 : leunga 775 T.SUB(32,T.LABEL lab,
965 :     T.ADD(32,T.LABEL tmpLab, T.LI(IntInf.fromInt 4)))
966 : leunga 746 in (* set the location of tmpLab *)
967 :     Label.setAddr(tmpLab, !loc+4);
968 :     branchLink(0wx3a,tmp,tmpLab,0w0,n);
969 :     LongImmed{Op=0wxa,r=tmp,
970 : george 984 im21=assemble_21(itow(MLTreeEval.valueOf offset))};
971 : leunga 746 BranchVectored{Op=0wx3a,t=tmp,x=zeroR,ext3=0w6,n=n}
972 :     end
973 :     rtl: ``B''
974 :     nullified: n = true
975 :     delayslot candidate: false
976 :     pipeline: BRANCH
977 :    
978 :     | BE of {b: $GP, d:operand, sr:int, n:bool, labs: Label.label list}
979 :     asm: ``be<n>\t<d>(<sr>,<b>)''
980 :     mc: let val (w,w1,w2) = assemble_17(opn d)
981 :     in BranchExternal{Op=0wx38,b=b,w1=w1,s=assemble_3(itow sr),
982 :     w2=w2,n=n,w=w}
983 :     end
984 :     nullified: n = true
985 :     delayslot candidate: false
986 :     pipeline: BRANCH
987 :    
988 :     | BV of {x: $GP, b: $GP, labs: Label.label list, n:bool}
989 :     asm: ``bv<n>\t<x>(<b>)''
990 :     mc: BranchVectored{Op=0wx3a,t=b,x=x,ext3=0w6,n=n}
991 :     rtl: ``BV''
992 :     nullified: n = true
993 :     delayslot candidate: false
994 :     pipeline: BRANCH
995 :    
996 :     | BLR of {x: $GP, t: $GP, labs: Label.label list, n:bool}
997 :     asm: ``blr<n>\t<x>(<t>)''
998 :     mc: BranchVectored{Op=0wx3a,t=t,x=x,ext3=0w2,n=n}
999 :     nullified: n = true
1000 :     delayslot candidate: false
1001 :     pipeline: BRANCH
1002 :    
1003 :     | BL of {lab:Label.label ,t: $GP, defs: $cellset, uses: $cellset,
1004 : leunga 796 cutsTo: Label.label list, mem:Region.region, n:bool}
1005 :     asm: ``bl<n>\t<lab>, <t><mem><emit_defs(defs)><emit_uses(uses)><emit_cutsTo cutsTo>''
1006 : leunga 746 mc: branchLink(0wx3a,t,lab,0w0,n)
1007 :     nullified: n = true
1008 :     delayslot candidate: false
1009 :     pipeline: BRANCH
1010 :    
1011 :     | BLE of {d:operand,b: $GP, sr:int, t: $GP,
1012 : leunga 796 defs: $cellset, uses: $cellset, cutsTo: Label.label list,
1013 :     mem:Region.region}
1014 : leunga 746 asm: ``ble\t<d>(<emit_int sr>,<b>)<mem><
1015 : leunga 796 emit_defs(defs)><emit_uses(uses)><emit_cutsTo cutsTo>''
1016 : george 889 mc: (case (d,CellsBasis.registerId t) of
1017 : leunga 746 (I.IMMED 0,31) =>
1018 :     BranchExternal{Op=0wx39,b=b,w1=0w0,s=assemble_3(itow sr),
1019 :     w2=0w0,n=true,w=0w0}
1020 :     | _ => error "BLE: not implemented"
1021 :     )
1022 :     rtl: ``BLE''
1023 :     nullified: false
1024 :     delayslot candidate: false
1025 :     pipeline: BRANCH
1026 :    
1027 :     (* BLE implicitly defines %r31. The destination register t
1028 :     * is assigned in the delay slot.
1029 :     *)
1030 :     | LDIL of {i:operand, t: $GP}
1031 :     asm: ``ldil\t<i>, <t>''
1032 :     mc: LongImmed{Op=0wx8,r=t,im21=assemble_21(opn i)}
1033 :     rtl: ``LDIL''
1034 :     latency: ARITH
1035 :     pipeline: ARITH
1036 :    
1037 :     | LDO of {i:operand, b: $GP, t: $GP}
1038 :     asm: ``ldo\t<i>(<b>), <t>''
1039 :     mc: Load{Op=0wx0d,b,im14=low_sign_ext_im14(opn i),t=t}
1040 :     rtl: if b = 0 then ``LDO2'' else ``LDO''
1041 :     latency: ARITH
1042 :     pipeline: ARITH
1043 :    
1044 :     | MTCTL of {r: $GP, t: $CR}
1045 :     asm: ``mtctl\t<r>, <t>''
1046 :     mc: MoveToControlReg{Op=0w0,t,r,rv=0w0,ext8=0wxc2}
1047 :     rtl: ``MTCTL''
1048 :     latency: ARITH
1049 :     pipeline: ARITH
1050 :    
1051 :     | FSTORE of {fst:fstore,b: $GP, d:int, r: $FP,mem:Region.region}
1052 :     asm: ``<fst>\t<r>, <d>(<b>)<mem>''
1053 :     mc: (case fst of
1054 :     I.FSTDS => CoProcShort{Op=0wxb,b,im5=low_sign_ext_im5(itow d),
1055 :     s=0w0,a=0w0,ls=0w1,uid=0w0,rt=r}
1056 :     | I.FSTWS => CoProcShort{Op=0wx9,b,im5=low_sign_ext_im5(itow d),
1057 :     s=0w0,a=0w0,ls=0w1,uid=0w1,rt=r}
1058 :     )
1059 :     rtl: ``<fst>''
1060 :     pipeline: STORE
1061 :    
1062 :     | FSTOREX of {fstx:fstorex, b: $GP, x: $GP,r: $FP,mem:Region.region}
1063 :     asm: ``<fstx>\t<r>, <x>(<b>)<mem>''
1064 :     mc: let val (Op,uid,u,m) = emit_fstorex fstx
1065 :     in CoProcIndexed{Op=Op,b,x,s=0w0,u,m,ls=0w1,uid=uid,rt=r}
1066 :     end
1067 :     rtl: ``<fstx>''
1068 :     pipeline: STORE
1069 :    
1070 :     | FLOAD of {fl:fload, b: $GP, d:int, t: $FP, mem:Region.region}
1071 :     asm: ``<fl>\t<d>(<b>), <t><mem>''
1072 :     mc: (case fl of
1073 :     I.FLDDS => CoProcShort{Op=0wxb,b,im5=low_sign_ext_im5(itow d),
1074 :     s=0w0,a=0w0,ls=0w0,uid=0w0,rt=t}
1075 :     | I.FLDWS => CoProcShort{Op=0wx9,b,im5=low_sign_ext_im5(itow d),
1076 :     s=0w0,a=0w0,ls=0w0,uid=0w1,rt=t}
1077 :     )
1078 :     rtl: ``<fl>''
1079 :     latency: LOAD
1080 :     pipeline: LOAD
1081 :    
1082 :     | FLOADX of {flx:floadx, b: $GP, x: $GP, t: $FP, mem:Region.region}
1083 :     asm: ``<flx>\t<x>(<b>), <t><mem>''
1084 :     mc: let val (Op,uid,u,m) = emit_floadx flx
1085 :     in CoProcIndexed{Op=Op,b,x,s=0w0,u,m,ls=0w0,uid=uid,rt=t}
1086 :     end
1087 :     rtl: ``<flx>''
1088 :     latency: LOAD
1089 :     pipeline: LOAD
1090 :    
1091 :     | FARITH of {fa:farith,r1: $FP, r2: $FP,t: $FP}
1092 :     asm: ``<fa>\t<r1>, <r2>, <t>''
1093 :     mc: (case fa of
1094 :     I.XMPYU => FloatOp3Maj0E{sop=0w2,f=0w1,r1,r2,t,r11=0w0,r22=0w0}
1095 :     | _ => let val (sop,fmt) = emit_farith fa
1096 :     in FloatOp3Maj0C{sop,r1,r2,t,n=0w0,fmt} end
1097 :     )
1098 :     rtl: ``<fa>''
1099 :     latency: (case fa of
1100 :     (I.FMPY_S | I.FMPY_D | I.FMPY_Q) => FMPY
1101 :     | (I.FDIV_S | I.FDIV_D | I.FDIV_Q) => FDIV
1102 :     | _ => FARITH
1103 :     )
1104 :     pipeline: (case fa of
1105 :     (I.FMPY_S | I.FMPY_D | I.FMPY_Q) => FMPY
1106 :     | (I.FDIV_S | I.FDIV_D | I.FDIV_Q) => FDIV
1107 :     | _ => FARITH
1108 :     )
1109 :    
1110 :     | FUNARY of {fu:funary,f: $FP, t: $FP}
1111 :     asm: ``<fu>\t<f>, <t>''
1112 :     mc: let val (sop,fmt) = emit_funary fu
1113 :     in FloatOp0Maj0C{r=f,t=t,sop=sop,fmt=fmt}
1114 :     end
1115 :     rtl: ``<fu>''
1116 :     latency: FARITH
1117 :     pipeline: FARITH
1118 :    
1119 :     | FCNV of {fcnv:fcnv, f: $FP, t: $FP}
1120 :     asm: ``<fcnv>\t<f>, <t>''
1121 :     mc: let val (sop,sf,df) = emit_fcnv fcnv
1122 :     in FloatOp1Maj0E{r=f,t=t,sop=sop,sf=sf,df=df,r2=0w1,t2=0w0}
1123 :     end
1124 :     rtl: ``<fcnv>''
1125 :     latency: FARITH
1126 :     pipeline: FARITH
1127 :    
1128 :     (* The following three instructions have been replaced by FBRANCH.
1129 :     This make life much easier for instruction schedulers.
1130 :     | FCMP of fcond * int * int
1131 :     | FTEST
1132 :     | FBCC of {t:Label.label, f:Label.label, n:bool}
1133 :     *)
1134 :     | FBRANCH of {cc:fcond, fmt:fmt, f1: $FP, f2: $FP,
1135 :     t:Label.label, f:Label.label, n:bool, long:bool}
1136 :     asm: (``fcmp,<fmt>,<cc>\t<f1>, <f2>\n\t'';
1137 :     ``ftest\n\t'';
1138 :     ``b<n>\t<t>''
1139 :     )
1140 :     (* fmt = 1 means double precision; will have to extend later *)
1141 :     mc: (FloatOp2Maj0C{r1=f1,r2=f2,sop=0w0,fmt=emit_fmt fmt,
1142 :     n=0w0,c=emit_fcond cc};
1143 :     FTest{};
1144 :     branchLink(0wx3a,zeroR,t,0w0,n) (* B,n t *)
1145 :     )
1146 :     rtl: ``FBRANCH_<cc>''
1147 :     nullified: n
1148 :     delayslot candidate: false
1149 :     pipeline: BRANCH
1150 :    
1151 :     | BREAK of {code1:int, code2:int}
1152 :     asm: ``break\t<code1>, <code2>''
1153 :     delayslot candidate: false
1154 :    
1155 :     | NOP
1156 :     asm: ``nop''
1157 :     mc: NOP{}
1158 :     rtl: ``NOP''
1159 :     pipeline: NOP
1160 :    
1161 :     | SOURCE of {}
1162 :     asm: ``source''
1163 :     mc: ()
1164 :    
1165 :     | SINK of {}
1166 :     asm: ``sink''
1167 :     mc: ()
1168 :    
1169 :     | PHI of {}
1170 :     asm: ``phi''
1171 :     mc: ()
1172 :    
1173 :     structure SSA =
1174 :     struct
1175 :    
1176 :     fun operand(ty,I.REG r) = T.REG(ty, r)
1177 : leunga 775 | operand(ty,I.IMMED i) = T.LI(IntInf.fromInt i)
1178 : leunga 746 (*| operand(ty,I.LabExp(le,_)) = T.LABEL le*)
1179 :     | operand _ = error "operand"
1180 :    
1181 :     end
1182 :    
1183 :     end

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