Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: nmacros.h | |
5 | * Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved | |
6 | * 4150 Network Circle, Santa Clara, California 95054, U.S.A. | |
7 | * | |
8 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License as published by | |
12 | * the Free Software Foundation; version 2 of the License. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
22 | * | |
23 | * For the avoidance of doubt, and except that if any non-GPL license | |
24 | * choice is available it will apply instead, Sun elects to use only | |
25 | * the General Public License version 2 (GPLv2) at this time for any | |
26 | * software where a choice of GPL license versions is made | |
27 | * available with the language indicating that GPLv2 or any later version | |
28 | * may be used, or where a choice of which version of the GPL is applied is | |
29 | * otherwise unspecified. | |
30 | * | |
31 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
32 | * CA 95054 USA or visit www.sun.com if you need additional information or | |
33 | * have any questions. | |
34 | * | |
35 | * | |
36 | * ========== Copyright Header End ============================================ | |
37 | */ | |
38 | #ifndef __NMACROS_H__ | |
39 | #define __NMACROS_H__ | |
40 | /****************** STRCAT(str1, str2, ...., str9) *************************** | |
41 | ||
42 | This is a support macro used to concatenate upto 9 strings (arguments) | |
43 | ||
44 | ******************************************************************************/ | |
45 | ||
46 | define(STRCAT, $1$2$3$4$5$6$7$8$9) | |
47 | ||
48 | /***************************** INIT_DW_REG(val, reg) ************************** | |
49 | ||
50 | This macro expands incrementally, depending on the size of the 'val' argument, | |
51 | to initialize the integer register 'reg'. No temporary register is required. | |
52 | ||
53 | ******************************************************************************/ | |
54 | ||
55 | define(INIT_DW_REG, | |
56 | `define(`hi_val', substr($1, 0, 10)) dnl | |
57 | define(`lo_val2', STRCAT(0x, substr($1, 10, 2))) dnl | |
58 | define(`lo_val1', STRCAT(0x, substr($1, 12, 3))) dnl | |
59 | define(`lo_val0', STRCAT(0x, substr($1, 15))) | |
60 | set hi_val, $2 | |
61 | sllx $2, eval(len(lo_val2)*4-8), $2 | |
62 | or $2, lo_val2, $2 | |
63 | ifelse(lo_val1,0x,, | |
64 | `sllx $2, eval(len(lo_val1)*4-8), $2 | |
65 | or $2, lo_val1, $2') | |
66 | ifelse(lo_val0,0x,, | |
67 | `sllx $2, eval(len(lo_val0)*4-8), $2 | |
68 | or $2, lo_val0, $2')') | |
69 | ||
70 | /************************** INIT_INT_REG(reg, val) **************************** | |
71 | ||
72 | This is a general purpose macro to initialize any 64 bit integer register | |
73 | without having to use a temporary register. It uses `INIT_DW_REG' defined | |
74 | above. This macro forms the basis of all initialization/comparison macros | |
75 | defined below. | |
76 | ||
77 | ******************************************************************************/ | |
78 | ||
79 | define(INIT_INT_REG, | |
80 | `ifelse(substr($2,0,1),%,`mov $2, $1', | |
81 | `ifelse(eval(len($2)>10),1,`INIT_DW_REG($2, $1)',` set $2, $1')')') | |
82 | ||
83 | /*************************** CMP_INT_REG(reg, val) **************************** | |
84 | ||
85 | This macro compares 'val' with the contents of the integer register 'reg'. It | |
86 | uses %g4 as scratch register. Only one scratch register is required | |
87 | irrespective of the size of 'val'. Note that the macro can replace ALL | |
88 | existing (integer) result checking macros with potentially fewer instructions | |
89 | for values > 32 bits and uses only ONE scratch register in all cases. | |
90 | ||
91 | ******************************************************************************/ | |
92 | ||
93 | define(CMP_INT_REG, | |
94 | `INIT_INT_REG(%g4, $2) | |
95 | sub $1, %g4, %g4 | |
96 | brz,pt %g4, 1f | |
97 | nop | |
98 | ta BAD_TRAP | |
99 | 1:') | |
100 | ||
101 | ||
102 | ||
103 | /****************** MEM_STORE(val, dest_addr, offset) ************************* | |
104 | ||
105 | This is a support macro used by the FP macros defined below. As evident from | |
106 | it's syntax, it stores 'val' at optional offset 'offset' from a base address | |
107 | 'dest_addr'. %g4 and %g5 are used as scratch registers. | |
108 | ||
109 | ******************************************************************************/ | |
110 | ||
111 | define(MEM_STORE, | |
112 | `INIT_INT_REG(%g4, $1) | |
113 | set $2, %g5 | |
114 | ifelse(eval(len($3)>0),1,`add %g5, $3, %g5') | |
115 | ifelse(eval(len($1)>10),1,`stx %g4, [%g5]',`st %g4, [%g5]')') | |
116 | ||
117 | ||
118 | /************************* INIT_FP_REG(freg, val1, val2) ********************* | |
119 | ||
120 | This macro initializes the FP register 'freg' with a SP/DP/QP number. 'val2' | |
121 | is optional and should only be supplied for QP numbers. Note that the syntax | |
122 | is similar to the macro `INIT_INT_REG' defined above for initializing an | |
123 | integer register. | |
124 | ||
125 | The macro uses %g4 and %g5 as scratch registers and a predefined area in | |
126 | memory labeled 'scratch_area' for temporary storage. | |
127 | ||
128 | ******************************************************************************/ | |
129 | ||
130 | define(INIT_FP_REG, | |
131 | `MEM_STORE($2, scratch_area) | |
132 | ifelse(eval(len($3)>0),1,`MEM_STORE($3, scratch_area, 8)') | |
133 | set scratch_area, %g5 | |
134 | ifelse(eval(len($3)>0),1,`ldq [%g5], $1', | |
135 | eval(len($2)>10),1,`ldd [%g5], $1',`ld [%g5], $1')') | |
136 | ||
137 | ||
138 | /****************** INIT_TH_FP_REG(memptr, freg, val) ************************ | |
139 | ||
140 | This macro initializes the FP register 'freg' with a SP/DP/QP number. 'val2' | |
141 | is optional and should only be supplied for QP numbers. Note that the syntax | |
142 | is similar to the macro `INIT_INT_REG' defined above for initializing an | |
143 | integer register. | |
144 | ||
145 | The macro uses %g4 and %g5 as scratch registers and a predefined area in | |
146 | memory pointed by memptr for temporary storage. | |
147 | ||
148 | ******************************************************************************/ | |
149 | ||
150 | define(INIT_TH_FP_REG, | |
151 | `setx $3, %g4, %g5 | |
152 | stx %g5, [$1] | |
153 | ldd [$1], $2') | |
154 | ||
155 | ||
156 | ||
157 | /************************ COPY_REG(reg, copy_inst) ************************** | |
158 | ||
159 | This macro copies register 'reg' to/from memory. The caller supplies the | |
160 | the instruction type for the desired data transfer. %g4 is assumed to contain | |
161 | the memory address for the source/destination for the copy operation. | |
162 | ||
163 | *****************************************************************************/ | |
164 | ||
165 | define(COPY_REG, | |
166 | `ifelse(substr($2, 0, 2),ld,`$2 [%g4], $1',`$2 $1, [%g4]')') | |
167 | ||
168 | ||
169 | /************************* CMP_FP_REG(freg, val1, val2) ********************** | |
170 | ||
171 | This macro compares a SP/DP/QP number in 'val1, val2' with the contents of | |
172 | the FP register 'freg'. 'val2' is optional and should only be specified for | |
173 | comparing QP values. Note the similarity in synatx with this macro's integer | |
174 | counterpart defined above in `CMP_INT_REG'. Also note that it can replace ALL | |
175 | result checking macros for FP values with potentially fewer instructions for | |
176 | DP and QP numbers. | |
177 | ||
178 | The macro uses %g4 and %g5 as scratch registers and a predefined area in | |
179 | memory labeled 'scratch_area' for temporary storage. | |
180 | ||
181 | ||
182 | *****************************************************************************/ | |
183 | ||
184 | define(CMP_FP_REG, | |
185 | ` set scratch_area, %g4 | |
186 | ifelse(eval(len($3)>0),1,`COPY_REG($1, stq)', | |
187 | eval(len($2)>10),1,`COPY_REG($1, std)',`COPY_REG($1, st)') | |
188 | ifelse(eval(len($2)>10),1,`COPY_REG(%g5, ldx)',`COPY_REG(%g5, ld)') | |
189 | INIT_INT_REG(%g4, $2) | |
190 | sub %g4, %g5, %g4 | |
191 | brz,pt %g4, 1f | |
192 | nop | |
193 | ta BAD_TRAP | |
194 | 1: | |
195 | ifelse(eval(len($3)>0),1, | |
196 | `set scratch_area+8, %g4 | |
197 | COPY_REG(%g5, ldx) | |
198 | INIT_INT_REG(%g4, $3) | |
199 | sub %g4, %g5 | |
200 | brz,pt %g4, 2f | |
201 | nop | |
202 | ta BAD_TRAP | |
203 | 2:') | |
204 | nop') | |
205 | ||
206 | ||
207 | /************************ INIT_REG(any_reg, val1, val2) ************************* | |
208 | ||
209 | This is a truly generic macro for initializing any integer or FP register | |
210 | without having to use separate macros. 'val2' is optional ans should only | |
211 | be supplied for QP (FP) numbers. The macro calls one of the two initialization | |
212 | macros defined above based on the register 'any_reg'. | |
213 | ||
214 | For initializing a FP register, the macro uses %g4 and %g5 as scratch registers | |
215 | and a predefined area in memory called 'scratch_area' for temporary storage. | |
216 | ||
217 | ||
218 | *******************************************************************************/ | |
219 | define(INIT_REG, | |
220 | `ifelse(eval(len($3)>0),1,`define(`argc', 3)',`define(`argc', 3)') | |
221 | define(`reg_id', substr($1, 0, 2)) | |
222 | ifelse(reg_id,%f,`define(`reg_id', FPR)', | |
223 | reg_id,%d,`define(`reg_id', FPR)', | |
224 | reg_id,%q,`define(`reg_id', FPR)',`define(`reg_id', IR)') | |
225 | ifelse(reg_id,FPR,`ifelse(argc,2,`INIT_FP_REG($1, $2)',`INIT_FP_REG($1, $2, $3)')',`INIT_INT_REG($1, $2)')') | |
226 | ||
227 | ||
228 | /************************ CMP_REG(any_reg, val1, val2) ************************* | |
229 | ||
230 | This is a truly generic macro for comparing any integer or FP register with a | |
231 | value without having to use separate macros. 'val2' is optional and should only | |
232 | be supplied for QP (FP) numbers. The macro calls one of the two comparison | |
233 | macros defined above based on the register 'any_reg'. | |
234 | ||
235 | For initializing a FP register, the macro uses %f16, %g4 and %g5 as scratch | |
236 | registers and a predefined area in memory called 'scratch_area' for temporary | |
237 | storage. Only %g4 is used as a scratch register for comparing an integer register. | |
238 | ||
239 | *******************************************************************************/ | |
240 | define(CMP_REG, | |
241 | `ifelse(eval(len($3)>0),1,`define(`argc', 3)',`define(`argc', 3)') | |
242 | define(`reg_id', substr($1, 0, 2)) | |
243 | ifelse(reg_id,%f,`define(`reg_id', FPR)', | |
244 | reg_id,%d,`define(`reg_id', FPR)', | |
245 | reg_id,%q,`define(`reg_id', FPR)',`define(`reg_id', IR)') | |
246 | ifelse(reg_id,FPR,`ifelse(argc,2,`CMP_FP_REG($1, $2)',`CMP_FP_REG($1, $2, $3)')',`CMP_INT_REG($1, $2)')') | |
247 | ||
248 | ||
249 | define(CLR_GLOBALS, | |
250 | `clr %g1 | |
251 | clr %g2 | |
252 | clr %g3 | |
253 | clr %g4 | |
254 | clr %g5 | |
255 | clr %g6 | |
256 | clr %g7') | |
257 | ||
258 | define(CLR_LOCALS, | |
259 | `clr %l0 | |
260 | clr %l1 | |
261 | clr %l2 | |
262 | clr %l3 | |
263 | clr %l4 | |
264 | clr %l5 | |
265 | clr %l6 | |
266 | clr %l7') | |
267 | ||
268 | define(CLR_OUTS, | |
269 | `clr %o0 | |
270 | clr %o1 | |
271 | clr %o2 | |
272 | clr %o3 | |
273 | clr %o4 | |
274 | clr %o5 | |
275 | clr %o6 | |
276 | clr %o7') | |
277 | ||
278 | define(CLR_INS, | |
279 | `clr %i0 | |
280 | clr %i1 | |
281 | clr %i2 | |
282 | clr %i3 | |
283 | clr %i4 | |
284 | clr %i5 | |
285 | clr %i6 | |
286 | clr %i7') | |
287 | ||
288 | define(CLR_FPRF, | |
289 | `INIT_REG(%d0, 0x0000000000000000) | |
290 | fmovd %d0, %d2 | |
291 | fmovd %d0, %d4 | |
292 | fmovd %d0, %d6 | |
293 | fmovd %d0, %d8 | |
294 | fmovd %d0, %d10 | |
295 | fmovd %d0, %d12 | |
296 | fmovd %d0, %d14 | |
297 | fmovd %d0, %d16 | |
298 | fmovd %d0, %d18 | |
299 | fmovd %d0, %d20 | |
300 | fmovd %d0, %d22 | |
301 | fmovd %d0, %d24 | |
302 | fmovd %d0, %d26 | |
303 | fmovd %d0, %d28 | |
304 | fmovd %d0, %d30') | |
305 | ||
306 | ||
307 | define(CLR_DIAG_REGS, | |
308 | `CLR_GLOBALS | |
309 | CLR_LOCALS | |
310 | CLR_OUTS | |
311 | CLR_INS | |
312 | CLR_FPRF') | |
313 | ||
314 | define(CLR_1WIN1_LOCALS, | |
315 | `rdpr %cwp, %g1 | |
316 | inc %g1 | |
317 | wrpr %g1, %cwp | |
318 | CLR_LOCALS | |
319 | dec %g1 | |
320 | dec %g1 | |
321 | wrpr %g1, %cwp | |
322 | CLR_LOCALS | |
323 | inc %g1 | |
324 | wrpr %g1, %cwp') | |
325 | ||
326 | ||
327 | ||
328 | define(LDST_OP, | |
329 | `ifelse(substr($1, 0, 2),ca,`$1 $2, $3, $4',`ifelse(substr($1, 0, 2),st,`$1 $3, $2',`$1 $2, $3')')') | |
330 | ||
331 | ||
332 | ||
333 | define(MAKE_DATA_PA, | |
334 | `INIT_REG(%g4, $1) | |
335 | mov $2, $3 | |
336 | sllx $3, 51, $3 | |
337 | srlx $3, 51, $3 | |
338 | add %g4, $3, $3 | |
339 | srlx $3, 3, $3 | |
340 | sllx $3, 3, $3 | |
341 | mov 1, %g4 | |
342 | sllx %g4, 39, %g4 | |
343 | or %g4, $3, $3') | |
344 | ||
345 | define(MAKE_TAG_PA, | |
346 | `INIT_REG(%g4, $1) | |
347 | mov $2, $3 | |
348 | sllx $3, 51, $3 | |
349 | srlx $3, 51, $3 | |
350 | add %g4, $3, $3 | |
351 | srlx $3, 6, $3 | |
352 | sllx $3, 6, $3 | |
353 | mov 2, %g4 | |
354 | sllx %g4, 39, %g4 | |
355 | or %g4, $3, $3') | |
356 | ||
357 | ||
358 | define(UPSHIFT_INST, | |
359 | `ld [$1], %g4 | |
360 | swap [$1-4], %g4 | |
361 | st %g4, [$1] | |
362 | sub $1, 4, $1 ! New inst addr | |
363 | srlx $1, 3, %g4 | |
364 | sllx %g4, 3, %g4 ! DW flush addr at/before inst after move | |
365 | flush %g4 | |
366 | add %g4, 8, %g5 ! Next dW addr | |
367 | flush %g5') ! Needed in case inst was moved to word addr | |
368 | ||
369 | ||
370 | define(ZERO_MEM, | |
371 | `mov $1, %g4 ! Starting MEM addr | |
372 | set $2, %g5 ! ST count | |
373 | 1: | |
374 | $3 %g0, [%g4] ! Zero fill | |
375 | add %g4, $4, %g4 ! Next addr | |
376 | dec %g5 ! Done? | |
377 | brnz,a %g5, 1b ! No: Continue | |
378 | nop') | |
379 | ||
380 | ||
381 | ||
382 | define(NOPS, | |
383 | `define( `NOP_COUNT', eval($1)) | |
384 | define( `IT_COUNT', 1) | |
385 | GEN_INSTS') | |
386 | ||
387 | define(GEN_INSTS, | |
388 | `nop dnl | |
389 | define(`IT_COUNT', incr(IT_COUNT)) | |
390 | ifelse(eval(IT_COUNT>NOP_COUNT),1,,`GEN_INSTS')') | |
391 | ||
392 | ||
393 | define(BREAK_GROUP, | |
394 | `mov %y, %g0') | |
395 | ||
396 | ||
397 | #endif |