Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * Hypervisor Software File: util.h | |
5 | * | |
6 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
7 | * | |
8 | * - Do no alter or remove copyright notices | |
9 | * | |
10 | * - Redistribution and use of this software in source and binary forms, with | |
11 | * or without modification, are permitted provided that the following | |
12 | * conditions are met: | |
13 | * | |
14 | * - Redistribution of source code must retain the above copyright notice, | |
15 | * this list of conditions and the following disclaimer. | |
16 | * | |
17 | * - Redistribution in binary form must reproduce the above copyright notice, | |
18 | * this list of conditions and the following disclaimer in the | |
19 | * documentation and/or other materials provided with the distribution. | |
20 | * | |
21 | * Neither the name of Sun Microsystems, Inc. or the names of contributors | |
22 | * may be used to endorse or promote products derived from this software | |
23 | * without specific prior written permission. | |
24 | * | |
25 | * This software is provided "AS IS," without a warranty of any kind. | |
26 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
27 | * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
28 | * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
29 | * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
30 | * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
31 | * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
32 | * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
33 | * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
34 | * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
35 | * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
36 | * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
37 | * | |
38 | * You acknowledge that this software is not designed, licensed or | |
39 | * intended for use in the design, construction, operation or maintenance of | |
40 | * any nuclear facility. | |
41 | * | |
42 | * ========== Copyright Header End ============================================ | |
43 | */ | |
44 | /* | |
45 | * Copyright 2007 Sun Microsystems, Inc. All rights reserved. | |
46 | * Use is subject to license terms. | |
47 | */ | |
48 | ||
49 | #ifndef _UTIL_H | |
50 | #define _UTIL_H | |
51 | ||
52 | #pragma ident "@(#)util.h 1.22 07/09/11 SMI" | |
53 | ||
54 | #ifdef __cplusplus | |
55 | extern "C" { | |
56 | #endif | |
57 | ||
58 | #include <vcpu.h> | |
59 | #include <abort.h> | |
60 | #include <strand.h> | |
61 | #include <platform/util.h> | |
62 | ||
63 | /* | |
64 | * Size generation constants | |
65 | */ | |
66 | #define KB * 1024 | |
67 | #define MB * 1024LL KB | |
68 | #define GB * 1024LL MB | |
69 | ||
70 | /* | |
71 | * Time constants | |
72 | */ | |
73 | #define MHZ * 1000000 | |
74 | #define NS_PER_S 1000000000 | |
75 | #define MS_PER_NS 1000000 | |
76 | ||
77 | /* | |
78 | * L2$ line state | |
79 | */ | |
80 | #define L2_LINE_CLEAN 0 | |
81 | #define L2_LINE_DIRTY 1 | |
82 | #define L2_LINE_INVALID 2 | |
83 | #define L2_LINE_NOT_FOUND 3 | |
84 | ||
85 | /* | |
86 | * prefetch function to invalidate an L2$ line | |
87 | */ | |
88 | #define INVALIDATE_CACHE_LINE 0x18 | |
89 | ||
90 | /* BEGIN CSTYLED */ | |
91 | ||
92 | /* | |
93 | * VCPU2GUEST_STRUCT - get the current guestp from a vcpup | |
94 | * | |
95 | * Delay Slot: safe in a delay slot | |
96 | * Register overlap: vcpu and root may be the same register | |
97 | */ | |
98 | #define VCPU2GUEST_STRUCT(vcpu, guest) \ | |
99 | ldx [vcpu + CPU_GUEST], guest | |
100 | ||
101 | ||
102 | /* FIXME: do we ever use the following? */ | |
103 | /* | |
104 | * VCPU2ROOT_STRUCT - get the rootp from a vcpup | |
105 | * | |
106 | * Delay Slot: safe in a delay slot if vcpup is valid | |
107 | * Register overlap: vcpu and root may be the same register | |
108 | */ | |
109 | #define VCPU2ROOT_STRUCT(vcpu, root) \ | |
110 | ldx [vcpu + CPU_ROOT], root | |
111 | ||
112 | ||
113 | /* | |
114 | * VCPU2STRAND_STRUCT - get the current strandp from a vcpup | |
115 | * | |
116 | * Delay Slot: safe in a delay slot | |
117 | * Register overlap: vcpu and strand may be the same register | |
118 | */ | |
119 | #define VCPU2STRAND_STRUCT(vcpu, strand) \ | |
120 | ldx [vcpu + CPU_STRAND], strand | |
121 | ||
122 | ||
123 | #define HSCRATCH_STRAND_STRUCT HSCRATCH0 | |
124 | #define HSCRATCH_VCPU_STRUCT HSCRATCH1 | |
125 | #define SCRATCHPAD_MEMBAR /* nothing for niagara */ | |
126 | ||
127 | /* | |
128 | * VCPU_STRUCT - get the current vcpup from scratch | |
129 | * | |
130 | * Delay Slot: not safe in a delay slot | |
131 | */ | |
132 | #define VCPU_STRUCT(vcpu) \ | |
133 | mov HSCRATCH_VCPU_STRUCT, vcpu ;\ | |
134 | ldxa [vcpu]ASI_HSCRATCHPAD, vcpu | |
135 | ||
136 | /* | |
137 | * SET_VCPU_STRUCT - set the vcpup into scratch | |
138 | */ | |
139 | #define SET_VCPU_STRUCT(vcpu, scr1) \ | |
140 | mov HSCRATCH_VCPU_STRUCT, scr1 ;\ | |
141 | stxa vcpu, [scr1]ASI_HSCRATCHPAD ;\ | |
142 | SCRATCHPAD_MEMBAR | |
143 | ||
144 | /* | |
145 | * STRAND_STRUCT - get the current strandp from scratch | |
146 | * | |
147 | * Delay Slot: not safe in a delay slot | |
148 | */ | |
149 | #define STRAND_STRUCT(strand) \ | |
150 | mov HSCRATCH_STRAND_STRUCT, strand ;\ | |
151 | ldxa [strand]ASI_HSCRATCHPAD, strand | |
152 | ||
153 | /* | |
154 | * SET_STRAND_STRUCT - set the strandp into scratch | |
155 | */ | |
156 | #define SET_STRAND_STRUCT(strand, scr1) \ | |
157 | mov HSCRATCH_STRAND_STRUCT, scr1 ;\ | |
158 | stxa strand, [scr1]ASI_HSCRATCHPAD ;\ | |
159 | SCRATCHPAD_MEMBAR | |
160 | ||
161 | /* | |
162 | * STRAND2CONFIG_STRUCT - get the current configp from strandp | |
163 | */ | |
164 | #define STRAND2CONFIG_STRUCT(strand, configp) \ | |
165 | ldx [strand + STRAND_CONFIGP], configp | |
166 | ||
167 | /* | |
168 | * CONFIG_STRUCT - get the current configp from scratch | |
169 | * | |
170 | * Delay Slot: safe in a delay slot | |
171 | */ | |
172 | #define CONFIG_STRUCT(configp) \ | |
173 | STRAND_STRUCT(configp) ;\ | |
174 | STRAND2CONFIG_STRUCT(configp, configp) | |
175 | ||
176 | /* For the moment alias */ | |
177 | #define ROOT_STRUCT(configp) CONFIG_STRUCT(configp) | |
178 | ||
179 | /* | |
180 | * LOCK_ADDR - get the lock address from scratch | |
181 | * | |
182 | * Delay Slot: not safe in a delay slot | |
183 | */ | |
184 | #define LOCK_ADDR(LOCK, addr) \ | |
185 | CONFIG_STRUCT(addr) ;\ | |
186 | inc LOCK, addr | |
187 | ||
188 | ||
189 | /* | |
190 | * VCPU_GUEST_STRUCT - get both the current vcpup and guestp from scratch | |
191 | * | |
192 | * Delay Slot: not safe in a delay slot | |
193 | * Register overlap: if vcpu and guest are the same then only the guest | |
194 | * is returned, see GUEST_STRUCT | |
195 | */ | |
196 | #define VCPU_GUEST_STRUCT(vcpu, guest) \ | |
197 | VCPU_STRUCT(vcpu) ;\ | |
198 | VCPU2GUEST_STRUCT(vcpu, guest) | |
199 | ||
200 | ||
201 | /* | |
202 | * GUEST_STRUCT - get the current guestp from scratch | |
203 | * | |
204 | * Delay Slot: safe in a delay slot | |
205 | */ | |
206 | #define GUEST_STRUCT(guest) \ | |
207 | VCPU_GUEST_STRUCT(guest, guest) | |
208 | ||
209 | ||
210 | /* | |
211 | * CTRL_DOMAIN - returns the service domain guest structure ptr | |
212 | * | |
213 | * Delay Slot: Safe in a delay slot | |
214 | */ | |
215 | #define CTRL_DOMAIN(guestp, scr1, scr2) \ | |
216 | CONFIG_STRUCT(scr1) ;\ | |
217 | ldx [scr1 + CONFIG_HVCTL_LDC], scr2 ;\ | |
218 | mulx scr2, LDC_ENDPOINT_SIZE, scr2 ;\ | |
219 | ldx [scr1 + CONFIG_HV_LDCS], guestp ;\ | |
220 | add guestp, scr2, guestp ;\ | |
221 | ldx [guestp + LDC_TARGET_GUEST], guestp | |
222 | ||
223 | /* | |
224 | * PID2CPUP - convert physical cpu number to a pointer to the vcpu | |
225 | * cpu structure thats currently running on it. | |
226 | * FIXME: This needs removing .. including all uses | |
227 | * because it's just rubbish! | |
228 | */ | |
229 | #define PID2VCPUP(pid, cpup, scr1, scr2) \ | |
230 | .pushlocals ;\ | |
231 | mov %g0, scr2 ;\ | |
232 | 1: ;\ | |
233 | cmp scr2, (NVCPUS - 1) ;\ | |
234 | bg,a 2f ;\ | |
235 | mov %g0, cpup ;\ | |
236 | set VCPU_SIZE, scr1 ;\ | |
237 | mulx scr2, scr1, cpup ;\ | |
238 | CONFIG_STRUCT(scr1) ;\ | |
239 | ldx [scr1 + CONFIG_VCPUS], scr1 ;\ | |
240 | add scr1, cpup, cpup ;\ | |
241 | VCPU2STRAND_STRUCT(cpup, scr1) ;\ | |
242 | ldub [scr1 + STRAND_ID], scr1 ;\ | |
243 | cmp scr1, pid ;\ | |
244 | bne,a %icc, 1b ;\ | |
245 | inc scr2 ;\ | |
246 | 2: ;\ | |
247 | .poplocals | |
248 | ||
249 | ||
250 | /* the VCPUID2CPUP macro below assumes the array step is 8 */ | |
251 | #if GUEST_VCPUS_INCR != 8 | |
252 | #error "GUEST_VCPUS_INCR is not 8" | |
253 | #endif | |
254 | ||
255 | #define GUEST_VCPUS_SHIFT 3 | |
256 | ||
257 | /* | |
258 | * VCPUID2CPUP - convert a guest virtual cpu number to a pointer | |
259 | * to the corresponding virtual cpu struct | |
260 | * | |
261 | * Register overlap: vcpuid and cpup may be the same register | |
262 | * Delay Slot: safe in a delay slot | |
263 | */ | |
264 | #define VCPUID2CPUP(guestp, vcpuid, cpup, fail_label, scr1) \ | |
265 | cmp vcpuid, NVCPUS ;\ | |
266 | bgeu,pn %xcc, fail_label ;\ | |
267 | sllx vcpuid, GUEST_VCPUS_SHIFT, cpup ;\ | |
268 | set GUEST_VCPUS, scr1 ;\ | |
269 | add cpup, scr1, cpup ;\ | |
270 | ldx [guestp + cpup], cpup ;\ | |
271 | brz,pn cpup, fail_label ;\ | |
272 | nop | |
273 | ||
274 | ||
275 | /* | |
276 | * PCPUID2COREID - derive core id from physical cpu id | |
277 | * | |
278 | * Register overlap: pid and coreid may be the same register | |
279 | * Delay slot: safe and complete in a delay slot | |
280 | */ | |
281 | #define PCPUID2COREID(pid, coreid) \ | |
282 | srlx pid, CPUID_2_COREID_SHIFT, coreid | |
283 | ||
284 | ||
285 | /* | |
286 | * Standard return-from-hcall with status "errno" | |
287 | */ | |
288 | #define HCALL_RET(errno) \ | |
289 | mov errno, %o0 ;\ | |
290 | done | |
291 | ||
292 | /* | |
293 | * HVCALL - make a subroutine call | |
294 | * HVJMP - jmp to subroutine in reg | |
295 | * HVRET - return from a subroutine call | |
296 | * | |
297 | * This hypervisor has a convention of using %g7 as the the | |
298 | * return address. | |
299 | */ | |
300 | #define HVCALL(x) \ | |
301 | ba,pt %xcc, x ;\ | |
302 | rd %pc, %g7 | |
303 | ||
304 | #define HVJMP(reg, pc) \ | |
305 | jmpl reg, pc ;\ | |
306 | nop | |
307 | ||
308 | #define HVRET \ | |
309 | jmp %g7 + SZ_INSTR ;\ | |
310 | nop | |
311 | ||
312 | /* | |
313 | * Strand stack operations | |
314 | * | |
315 | * These macros are deprecated, but aliased for back compatibility | |
316 | * CPU_PUSH - push a val into the stack | |
317 | * CPU_POP - pop val from the stack | |
318 | * These macros temporarily push and pop values that need storing | |
319 | * STRAND_PUSH - push a val into the stack | |
320 | * STRAND_POP - pop val from the stack | |
321 | * | |
322 | */ | |
323 | ||
324 | #define CPU_PUSH(val, scr1, scr2, scr3) \ | |
325 | STRAND_PUSH(val, scr1, scr2) | |
326 | ||
327 | #define CPU_POP(val, scr1, scr2, scr3) \ | |
328 | STRAND_POP(val, scr1) | |
329 | ||
330 | /* Stack is empty if ptr = 0 */ | |
331 | ||
332 | #define STRAND_PUSH(val, scr1, scr2) \ | |
333 | STRAND_STRUCT(scr1) ;\ | |
334 | add scr1, STRAND_MINI_STACK, scr1 ;\ | |
335 | ldx [scr1 + MINI_STACK_PTR], scr2 /* get stack ptr */ ;\ | |
336 | cmp scr2, MINI_STACK_VAL_INCR*MINI_STACK_DEPTH ;\ | |
337 | bge,a,pn %xcc, hvabort ;\ | |
338 | rd %pc, %g1 ;\ | |
339 | add scr2, MINI_STACK_VAL_INCR, scr2 /* next element */ ;\ | |
340 | stx scr2, [scr1 + MINI_STACK_PTR] ;\ | |
341 | add scr2, scr1, scr2 ;\ | |
342 | /* store at previous ptr value */ ;\ | |
343 | stx val, [scr2 + MINI_STACK_VAL - MINI_STACK_VAL_INCR] | |
344 | ||
345 | ||
346 | #define STRAND_POP(val, scr1) \ | |
347 | STRAND_STRUCT(scr1) ;\ | |
348 | add scr1, STRAND_MINI_STACK, scr1 ;\ | |
349 | ldx [scr1 + MINI_STACK_PTR], val ;\ | |
350 | brlez,a,pn val, hvabort ;\ | |
351 | rd %pc, %g1 ;\ | |
352 | sub val, MINI_STACK_VAL_INCR, val ;\ | |
353 | stx val, [scr1 + MINI_STACK_PTR] ;\ | |
354 | add scr1, val, scr1 ;\ | |
355 | ldx [scr1 + MINI_STACK_VAL], val | |
356 | ||
357 | ||
358 | /* | |
359 | * ATOMIC_OR_64 - atomically logical-or a value in a memory location | |
360 | */ | |
361 | #define ATOMIC_OR_64(addr, value, scr1, scr2) \ | |
362 | .pushlocals ;\ | |
363 | ldx [addr], scr1 ;\ | |
364 | 0: or scr1, value, scr2 ;\ | |
365 | casx [addr], scr1, scr2 ;\ | |
366 | cmp scr1, scr2 ;\ | |
367 | bne,a,pn %xcc, 0b ;\ | |
368 | mov scr2, scr1 ;\ | |
369 | .poplocals | |
370 | ||
371 | /* | |
372 | * ATOMIC_ANDN_64 - atomically logical-andn a value in a memory location | |
373 | * Returns oldvalue | |
374 | */ | |
375 | #define ATOMIC_ANDN_64(addr, value, oldvalue, scr2) \ | |
376 | .pushlocals ;\ | |
377 | ldx [addr], oldvalue ;\ | |
378 | 0: andn oldvalue, value, scr2 ;\ | |
379 | casx [addr], oldvalue, scr2 ;\ | |
380 | cmp oldvalue, scr2 ;\ | |
381 | bne,a,pn %xcc, 0b ;\ | |
382 | mov scr2, oldvalue ;\ | |
383 | .poplocals | |
384 | ||
385 | /* | |
386 | * ATOMIC_SWAP_64 - swaps the value at addr with newvalue, returns | |
387 | * the previous contents of addr as oldvalue | |
388 | */ | |
389 | #define ATOMIC_SWAP_64(addr, newvalue, oldvalue, scr2) \ | |
390 | .pushlocals ;\ | |
391 | ldx [addr], scr2 ;\ | |
392 | 0: mov newvalue, oldvalue ;\ | |
393 | casx [addr], scr2, oldvalue ;\ | |
394 | cmp scr2, oldvalue ;\ | |
395 | bne,a,pn %xcc, 0b ;\ | |
396 | mov oldvalue, scr2 ;\ | |
397 | .poplocals | |
398 | ||
399 | /* | |
400 | * ATOMIC_ADD_64 - atomically add to a value stored in memory | |
401 | */ | |
402 | #define ATOMIC_ADD_64(addr, value, newvalue, scr2) \ | |
403 | .pushlocals ;\ | |
404 | ldx [addr], newvalue ;\ | |
405 | 0: add newvalue, value, scr2 ;\ | |
406 | casx [addr], newvalue, scr2 ;\ | |
407 | cmp newvalue, scr2 ;\ | |
408 | bne,a,pn %xcc, 0b ;\ | |
409 | mov scr2, newvalue ;\ | |
410 | add newvalue, value, newvalue ;\ | |
411 | .poplocals | |
412 | ||
413 | ||
414 | /* | |
415 | * Locking primitives | |
416 | */ | |
417 | #define MEMBAR_ENTER \ | |
418 | /* membar #StoreLoad|#StoreStore not necessary on Niagara */ | |
419 | #define MEMBAR_EXIT \ | |
420 | /* membar #LoadStore|#StoreStore not necessary on Niagara */ | |
421 | ||
422 | /* | |
423 | * SPINLOCK_ENTER - claim lock by setting it to cpu#+1 spinning until it is | |
424 | * free | |
425 | */ | |
426 | #define SPINLOCK_ENTER(lock, scr1, scr2) \ | |
427 | .pushlocals ;\ | |
428 | STRAND_STRUCT(scr1) ;\ | |
429 | ldub [scr1 + STRAND_ID], scr2 /* my ID */ ;\ | |
430 | inc scr2 /* lockID = cpuid + 1 */ ;\ | |
431 | mov 0, scr1 ;\ | |
432 | 1: ;\ | |
433 | brz,pn scr1, 2f ;\ | |
434 | nop ;\ | |
435 | ;\ | |
436 | be,a %xcc, hvabort ;\ | |
437 | rd %pc, %g1 ;\ | |
438 | 2: ;\ | |
439 | mov scr2, scr1 ;\ | |
440 | casx [lock], %g0, scr1 /* if zero, write my lockID */ ;\ | |
441 | brnz,a,pn scr1, 1b ;\ | |
442 | cmp scr2, scr1 ;\ | |
443 | MEMBAR_ENTER ;\ | |
444 | .poplocals | |
445 | ||
446 | /* | |
447 | * SPINLOCK_EXIT - release lock | |
448 | */ | |
449 | #define SPINLOCK_EXIT(lock) ;\ | |
450 | MEMBAR_EXIT ;\ | |
451 | stx %g0, [lock] | |
452 | ||
453 | #define IS_CPU_IN_ERROR(cpup, scr1) \ | |
454 | ldx [cpup + CPU_STATUS], scr1 ;\ | |
455 | cmp scr1, CPU_STATE_ERROR | |
456 | ||
457 | /* | |
458 | * LABEL_ADDRESS(label, reg) | |
459 | * | |
460 | * Args: | |
461 | * label - assembler label | |
462 | * reg - will hold the address of the label | |
463 | * | |
464 | * Calculate the (relocated) address of the target label. Only | |
465 | * works if the target label is no more than 4092 bytes away from | |
466 | * the current assembly origin. Also requires that the label be | |
467 | * in the same source file, and in the same section as the macro | |
468 | * invokation. | |
469 | */ | |
470 | #define LABEL_ADDRESS(label, reg) \ | |
471 | .pushlocals ;\ | |
472 | 0: rd %pc, reg ;\ | |
473 | add reg, (label) - 0b, reg ;\ | |
474 | .poplocals | |
475 | ||
476 | ||
477 | /* | |
478 | * RELOC_OFFSET(scr, reg) | |
479 | * | |
480 | * Args: | |
481 | * scr - scratch register, different from "reg" | |
482 | * reg - will hold the value of the relocation offset | |
483 | * | |
484 | * Calculates the offset of the current image relative to the | |
485 | * address assigned by the linker. The returned offset value can be | |
486 | * subtracted from labels calcuated with "setx" to obtain the actual | |
487 | * address after relocation. | |
488 | */ | |
489 | #define RELOC_OFFSET(scr, reg) \ | |
490 | .pushlocals ;\ | |
491 | setx 0f, scr, reg /* reg = linker */ ;\ | |
492 | 0: rd %pc, scr /* scr = actual */ ;\ | |
493 | sub reg, scr, reg /* reg = l - a */ ;\ | |
494 | .poplocals | |
495 | ||
496 | #define DELAY_SECS(scr1, scr2, SECS) \ | |
497 | CPU_STRUCT(scr1) ;\ | |
498 | CPU2ROOT_STRUCT(scr1, scr2) ;\ | |
499 | ldx [scr2 + CONFIG_STICKFREQUENCY], scr2 ;\ | |
500 | mulx scr2, SECS, scr2 ;\ | |
501 | rd STICK, scr1 ;\ | |
502 | add scr1, scr2, scr1 ;\ | |
503 | 0: ;\ | |
504 | rd STICK, scr2 ;\ | |
505 | cmp scr2, scr1 ;\ | |
506 | blu %xcc, 0b ;\ | |
507 | nop | |
508 | ||
509 | /* | |
510 | * SMALL_COPY_MACRO - byte-wise copy a small region of memory. | |
511 | * | |
512 | * Args: | |
513 | * src - starting address | |
514 | * len - length of region to copy | |
515 | * dest - destination address | |
516 | * scr - scratch | |
517 | * | |
518 | * All arguments are clobbered. | |
519 | */ | |
520 | #define SMALL_COPY_MACRO(src, len, dest, scr) \ | |
521 | .pushlocals ;\ | |
522 | 1: ldub [src], scr ;\ | |
523 | inc src ;\ | |
524 | deccc len ;\ | |
525 | stb scr, [dest] ;\ | |
526 | bnz,pt %xcc, 1b ;\ | |
527 | inc dest ;\ | |
528 | .poplocals | |
529 | ||
530 | /* | |
531 | * SMALL_ZERO_MACRO - byte-wise zero a small region of memory. | |
532 | * | |
533 | * Args: | |
534 | * addr - starting address | |
535 | * len - length of region to copy | |
536 | * | |
537 | * All arguments are clobbered. | |
538 | */ | |
539 | #define SMALL_ZERO_MACRO(addr, len) \ | |
540 | .pushlocals ;\ | |
541 | brz,pn len, 2f ;\ | |
542 | nop ;\ | |
543 | 1: stb %g0, [addr] ;\ | |
544 | deccc len ;\ | |
545 | bnz,pt %xcc, 1b ;\ | |
546 | inc addr ;\ | |
547 | 2: ;\ | |
548 | .poplocals | |
549 | ||
550 | /* | |
551 | * Cstyle macro for minimum | |
552 | */ | |
553 | #define MIN(x, y) \ | |
554 | ((x) < (y) ? (x) : (y)) \ | |
555 | ||
556 | /* END CSTYLED */ | |
557 | ||
558 | #ifdef __cplusplus | |
559 | } | |
560 | #endif | |
561 | ||
562 | #endif /* _UTIL_H */ |