8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / uts / sun4u / ml / mach_subr_asm.s
bloba49efc30f7049e032408204a416ce9209cdc5800
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * General machine architecture & implementation specific
28 * assembly language routines.
30 #if defined(lint)
31 #include <sys/types.h>
32 #include <sys/t_lock.h>
33 #else /* lint */
34 #include "assym.h"
35 #endif /* lint */
37 #include <sys/asm_linkage.h>
38 #include <sys/machsystm.h>
39 #include <sys/machthread.h>
40 #include <sys/privregs.h>
41 #include <sys/cmpregs.h>
42 #include <sys/clock.h>
43 #include <sys/fpras.h>
45 #if defined(lint)
47 uint64_t
48 ultra_gettick(void)
49 { return (0); }
51 #else /* lint */
54 * This isn't the routine you're looking for.
56 * The routine simply returns the value of %tick on the *current* processor.
57 * Most of the time, gettick() [which in turn maps to %stick on platforms
58 * that have different CPU %tick rates] is what you want.
61 ENTRY(ultra_gettick)
62 retl
63 rdpr %tick, %o0
64 SET_SIZE(ultra_gettick)
66 #endif /* lint */
68 #if defined(lint)
70 /*ARGSUSED*/
71 int
72 getprocessorid(void)
73 { return (0); }
75 #else /* lint */
78 * Get the processor ID.
79 * === MID reg as specified in 15dec89 sun4u spec, sec 5.4.3
82 ENTRY(getprocessorid)
83 CPU_INDEX(%o0, %o1)
84 retl
85 nop
86 SET_SIZE(getprocessorid)
88 #endif /* lint */
90 #if defined(lint)
91 /*ARGSUSED*/
92 void
93 set_error_enable_tl1(uint64_t neer, uint64_t action)
96 /* ARGSUSED */
97 void
98 set_error_enable(uint64_t neer)
101 uint64_t
102 get_error_enable()
104 return ((uint64_t)0);
106 #else /* lint */
108 ENTRY(set_error_enable_tl1)
109 cmp %g2, EER_SET_ABSOLUTE
110 be %xcc, 1f
112 ldxa [%g0]ASI_ESTATE_ERR, %g3
113 membar #Sync
114 cmp %g2, EER_SET_SETBITS
115 be,a %xcc, 1f
116 or %g3, %g1, %g1
117 andn %g3, %g1, %g1 /* EER_SET_CLRBITS */
119 stxa %g1, [%g0]ASI_ESTATE_ERR /* ecache error enable reg */
120 membar #Sync
121 retry
122 SET_SIZE(set_error_enable_tl1)
124 ENTRY(set_error_enable)
125 stxa %o0, [%g0]ASI_ESTATE_ERR /* ecache error enable reg */
126 membar #Sync
127 retl
129 SET_SIZE(set_error_enable)
131 ENTRY(get_error_enable)
132 retl
133 ldxa [%g0]ASI_ESTATE_ERR, %o0 /* ecache error enable reg */
134 SET_SIZE(get_error_enable)
136 #endif /* lint */
138 #if defined(lint)
139 void
140 get_asyncflt(uint64_t *afsr)
142 afsr = afsr;
144 #else /* lint */
146 ENTRY(get_asyncflt)
147 ldxa [%g0]ASI_AFSR, %o1 ! afsr reg
148 retl
149 stx %o1, [%o0]
150 SET_SIZE(get_asyncflt)
152 #endif /* lint */
154 #if defined(lint)
155 void
156 set_asyncflt(uint64_t afsr)
158 afsr = afsr;
160 #else /* lint */
162 ENTRY(set_asyncflt)
163 stxa %o0, [%g0]ASI_AFSR ! afsr reg
164 membar #Sync
165 retl
167 SET_SIZE(set_asyncflt)
169 #endif /* lint */
171 #if defined(lint)
172 void
173 get_asyncaddr(uint64_t *afar)
175 afar = afar;
177 #else /* lint */
179 ENTRY(get_asyncaddr)
180 ldxa [%g0]ASI_AFAR, %o1 ! afar reg
181 retl
182 stx %o1, [%o0]
183 SET_SIZE(get_asyncaddr)
185 #endif /* lint */
187 #if defined(lint) || defined(__lint)
189 /* ARGSUSED */
190 hrtime_t
191 tick2ns(hrtime_t tick, uint_t cpuid)
192 { return 0; }
194 #else /* lint */
196 ENTRY_NP(tick2ns)
197 sethi %hi(cpunodes), %o4
198 or %o4, %lo(cpunodes), %o4 ! %o4 = &cpunodes
199 ! Register usage:
201 ! o0 = timestamp
202 ! o2 = byte offset into cpunodes for tick_nsec_scale of this CPU
203 ! o4 = &cpunodes
205 mulx %o1, CPU_NODE_SIZE, %o2 ! %o2 = byte offset into cpunodes
206 add %o2, TICK_NSEC_SCALE, %o2
207 ld [%o4 + %o2], %o2 ! %o2 = cpunodes[cpuid].tick_nsec_scale
208 NATIVE_TIME_TO_NSEC_SCALE(%o0, %o2, %o3, TICK_NSEC_SHIFT)
209 retl
211 SET_SIZE(tick2ns)
213 #endif /* lint */
215 #if defined(lint)
217 /* ARGSUSED */
218 void
219 set_cmp_error_steering(void)
222 #else /* lint */
224 ENTRY(set_cmp_error_steering)
225 membar #Sync
226 set ASI_CORE_ID, %o0 ! %o0 = ASI_CORE_ID
227 ldxa [%o0]ASI_CMP_PER_CORE, %o0 ! get ASI_CORE_ID
228 and %o0, COREID_MASK, %o0
229 set ASI_CMP_ERROR_STEERING, %o1 ! %o1 = ERROR_STEERING_REG
230 stxa %o0, [%o1]ASI_CMP_SHARED ! this core now hadles
231 membar #Sync ! non-core specific errors
232 retl
234 SET_SIZE(set_cmp_error_steering)
236 #endif /* lint */
238 #if defined(lint)
240 /* ARGSUSED */
241 uint64_t
242 ultra_getver(void)
244 return (0);
247 #else /* lint */
249 ENTRY(ultra_getver)
250 retl
251 rdpr %ver, %o0
252 SET_SIZE(ultra_getver)
254 #endif /* lint */
256 #if defined(lint)
259 fpras_chkfn_type1(void)
260 { return 0; }
262 #else /* lint */
265 * Check instructions using just the AX pipelines, designed by
266 * C.B. Liaw of PNP.
268 * This function must match a struct fpras_chkfn and must be
269 * block aligned. A zero return means all was well. These
270 * instructions are chosen to be sensitive to bit corruptions
271 * on the fpras rewrite, so if a bit corruption still produces
272 * a valid instruction we should still get an incorrect result
273 * here. This function is never called directly - it is copied
274 * into per-cpu and per-operation buffers; it must therefore
275 * be absolutely position independent. If an illegal instruction
276 * is encountered then the trap handler trampolines to the final
277 * three instructions of this function.
279 * We want two instructions that are complements of one another,
280 * and which can perform a calculation with a known result.
282 * SETHI:
284 * | 0 0 | rd | 1 0 0 | imm22 |
285 * 31 30 29 25 24 22 21 0
287 * ADDCCC with two source registers:
289 * | 1 0 | rd | 0 1 1 0 0 0 | rs1 | 0 | - | rs2 |
290 * 31 30 29 25 24 19 18 14 13 12 5 4 0
292 * We can choose rd and imm2 of the SETHI and rd, rs1 and rs2 of
293 * the ADDCCC to obtain instructions that are complements in all but
294 * bit 30.
296 * Registers are numbered as follows:
298 * r[31] %i7
299 * r[30] %i6
300 * r[29] %i5
301 * r[28] %i4
302 * r[27] %i3
303 * r[26] %i2
304 * r[25] %i1
305 * r[24] %i0
306 * r[23] %l7
307 * r[22] %l6
308 * r[21] %l5
309 * r[20] %l4
310 * r[19] %l3
311 * r[18] %l2
312 * r[17] %l1
313 * r[16] %l0
314 * r[15] %o7
315 * r[14] %o6
316 * r[13] %o5
317 * r[12] %o4
318 * r[11] %o3
319 * r[10] %o2
320 * r[9] %o1
321 * r[8] %o0
322 * r[7] %g7
323 * r[6] %g6
324 * r[5] %g5
325 * r[4] %g4
326 * r[3] %g3
327 * r[2] %g2
328 * r[1] %g1
329 * r[0] %g0
331 * For register r[n], register r[31-n] is the complement. We must
332 * avoid use of %i6/%i7 and %o6/%o7 as well as %g7. Clearly we need
333 * to use a local or input register as one half of the pair, which
334 * requires us to obtain our own register window or take steps
335 * to preserve any local or input we choose to use. We choose
336 * %o1 as rd for the SETHI, so rd of the ADDCCC must be %l6.
337 * We'll use %o1 as rs1 and %l6 as rs2 of the ADDCCC, which then
338 * requires that imm22 be 0b111 10110 1 11111111 01001 or 0x3dbfe9,
339 * or %hi(0xf6ffa400). This determines the value of the constant
340 * CBV2 below.
342 * The constant CBV1 is chosen such that an initial subcc %g0, CBV1
343 * will set the carry bit and every addccc thereafter will continue
344 * to generate a carry. Other values are possible for CBV1 - this
345 * is just one that works this way.
347 * Finally CBV3 is the expected answer when we perform our repeated
348 * calculations on CBV1 and CBV2 - it is not otherwise specially
349 * derived. If this result is not obtained then a corruption has
350 * occured during the FPRAS_REWRITE of one of the two blocks of
351 * 16 instructions. A corruption could also result in an illegal
352 * instruction or other unexpected trap - we catch illegal
353 * instruction traps in the PC range and trampoline to the
354 * last instructions of the function to return a failure indication.
358 #define CBV1 0xc11
359 #define CBV2 0xf6ffa400
360 #define CBV3 0x66f9d800
361 #define CBR1 %o1
362 #define CBR2 %l6
363 #define CBO2 %o2
364 #define SETHI_CBV2_CBR1 sethi %hi(CBV2), CBR1
365 #define ADDCCC_CBR1_CBR2_CBR2 addccc CBR1, CBR2, CBR2
367 .align 64
368 ENTRY_NP(fpras_chkfn_type1)
369 mov CBR2, CBO2 ! 1, preserve CBR2 of (callers) window
370 mov FPRAS_OK, %o0 ! 2, default return value
371 ba,pt %icc, 1f ! 3
372 subcc %g0, CBV1, CBR2 ! 4
373 ! 5 - 16
374 .align 64
375 1: SETHI_CBV2_CBR1 ! 1
376 ADDCCC_CBR1_CBR2_CBR2 ! 2
377 SETHI_CBV2_CBR1 ! 3
378 ADDCCC_CBR1_CBR2_CBR2 ! 4
379 SETHI_CBV2_CBR1 ! 5
380 ADDCCC_CBR1_CBR2_CBR2 ! 6
381 SETHI_CBV2_CBR1 ! 7
382 ADDCCC_CBR1_CBR2_CBR2 ! 8
383 SETHI_CBV2_CBR1 ! 9
384 ADDCCC_CBR1_CBR2_CBR2 ! 10
385 SETHI_CBV2_CBR1 ! 11
386 ADDCCC_CBR1_CBR2_CBR2 ! 12
387 SETHI_CBV2_CBR1 ! 13
388 ADDCCC_CBR1_CBR2_CBR2 ! 14
389 SETHI_CBV2_CBR1 ! 15
390 ADDCCC_CBR1_CBR2_CBR2 ! 16
392 ADDCCC_CBR1_CBR2_CBR2 ! 1
393 SETHI_CBV2_CBR1 ! 2
394 ADDCCC_CBR1_CBR2_CBR2 ! 3
395 SETHI_CBV2_CBR1 ! 4
396 ADDCCC_CBR1_CBR2_CBR2 ! 5
397 SETHI_CBV2_CBR1 ! 6
398 ADDCCC_CBR1_CBR2_CBR2 ! 7
399 SETHI_CBV2_CBR1 ! 8
400 ADDCCC_CBR1_CBR2_CBR2 ! 9
401 SETHI_CBV2_CBR1 ! 10
402 ADDCCC_CBR1_CBR2_CBR2 ! 11
403 SETHI_CBV2_CBR1 ! 12
404 ADDCCC_CBR1_CBR2_CBR2 ! 13
405 SETHI_CBV2_CBR1 ! 14
406 ADDCCC_CBR1_CBR2_CBR2 ! 15
407 SETHI_CBV2_CBR1 ! 16
409 addc CBR1, CBR2, CBR2 ! 1
410 sethi %hi(CBV3), CBR1 ! 2
411 cmp CBR1, CBR2 ! 3
412 movnz %icc, FPRAS_BADCALC, %o0! 4, how detected
413 retl ! 5
414 mov CBO2, CBR2 ! 6, restore borrowed register
415 .skip 4*(13-7+1) ! 7 - 13
417 ! illegal instr'n trap comes here
419 mov CBO2, CBR2 ! 14, restore borrowed register
420 retl ! 15
421 mov FPRAS_BADTRAP, %o0 ! 16, how detected
422 SET_SIZE(fpras_chkfn_type1)
424 #endif /* lint */
427 * fp_zero() - clear all fp data registers and the fsr
430 #if defined(lint) || defined(__lint)
432 void
433 fp_zero(void)
436 #else /* lint */
438 ENTRY_NP(fp_zero)
439 std %g0, [%sp + ARGPUSH + STACK_BIAS]
440 fzero %f0
441 fzero %f2
442 ldd [%sp + ARGPUSH + STACK_BIAS], %fsr
443 faddd %f0, %f2, %f4
444 fmuld %f0, %f2, %f6
445 faddd %f0, %f2, %f8
446 fmuld %f0, %f2, %f10
447 faddd %f0, %f2, %f12
448 fmuld %f0, %f2, %f14
449 faddd %f0, %f2, %f16
450 fmuld %f0, %f2, %f18
451 faddd %f0, %f2, %f20
452 fmuld %f0, %f2, %f22
453 faddd %f0, %f2, %f24
454 fmuld %f0, %f2, %f26
455 faddd %f0, %f2, %f28
456 fmuld %f0, %f2, %f30
457 faddd %f0, %f2, %f32
458 fmuld %f0, %f2, %f34
459 faddd %f0, %f2, %f36
460 fmuld %f0, %f2, %f38
461 faddd %f0, %f2, %f40
462 fmuld %f0, %f2, %f42
463 faddd %f0, %f2, %f44
464 fmuld %f0, %f2, %f46
465 faddd %f0, %f2, %f48
466 fmuld %f0, %f2, %f50
467 faddd %f0, %f2, %f52
468 fmuld %f0, %f2, %f54
469 faddd %f0, %f2, %f56
470 fmuld %f0, %f2, %f58
471 faddd %f0, %f2, %f60
472 retl
473 fmuld %f0, %f2, %f62
474 SET_SIZE(fp_zero)
476 #endif /* lint */