1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _IA32_SYS_ASM_LINKAGE_H 28 #define _IA32_SYS_ASM_LINKAGE_H 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include <sys/stack.h> 33 #include <sys/trap.h> 34 35 #ifdef __cplusplus 36 extern "C" { 37 #endif 38 39 #ifdef _ASM /* The remainder of this file is only for assembly files */ 40 41 /* 42 * make annoying differences in assembler syntax go away 43 */ 44 45 /* 46 * D16 and A16 are used to insert instructions prefixes; the 47 * macros help the assembler code be slightly more portable. 48 */ 49 #if !defined(__GNUC_AS__) 50 /* 51 * /usr/ccs/bin/as prefixes are parsed as separate instructions 52 */ 53 #define D16 data16; 54 #define A16 addr16; 55 56 /* 57 * (There are some weird constructs in constant expressions) 58 */ 59 #define _CONST(const) [const] 60 #define _BITNOT(const) -1!_CONST(const) 61 #define _MUL(a, b) _CONST(a \* b) 62 63 #else 64 /* 65 * Why not use the 'data16' and 'addr16' prefixes .. well, the 66 * assembler doesn't quite believe in real mode, and thus argues with 67 * us about what we're trying to do. 68 */ 69 #define D16 .byte 0x66; 70 #define A16 .byte 0x67; 71 72 #define _CONST(const) (const) 73 #define _BITNOT(const) ~_CONST(const) 74 #define _MUL(a, b) _CONST(a * b) 75 76 #endif 77 78 /* 79 * C pointers are different sizes between i386 and amd64. 80 * These constants can be used to compute offsets into pointer arrays. 81 */ 82 #if defined(__amd64) 83 #define CLONGSHIFT 3 84 #define CLONGSIZE 8 85 #define CLONGMASK 7 86 #elif defined(__i386) 87 #define CLONGSHIFT 2 88 #define CLONGSIZE 4 89 #define CLONGMASK 3 90 #endif 91 92 /* 93 * Since we know we're either ILP32 or LP64 .. 94 */ 95 #define CPTRSHIFT CLONGSHIFT 96 #define CPTRSIZE CLONGSIZE 97 #define CPTRMASK CLONGMASK 98 99 #if CPTRSIZE != (1 << CPTRSHIFT) || CLONGSIZE != (1 << CLONGSHIFT) 100 #error "inconsistent shift constants" 101 #endif 102 103 #if CPTRMASK != (CPTRSIZE - 1) || CLONGMASK != (CLONGSIZE - 1) 104 #error "inconsistent mask constants" 105 #endif 106 107 #define ASM_ENTRY_ALIGN 16 108 109 /* 110 * SSE register alignment and save areas 111 */ 112 113 #define XMM_SIZE 16 114 #define XMM_ALIGN 16 115 116 #if defined(__amd64) 117 118 #define SAVE_XMM_PROLOG(sreg, nreg) \ 119 subq $_CONST(_MUL(XMM_SIZE, nreg)), %rsp; \ 120 movq %rsp, sreg 121 122 #define RSTOR_XMM_EPILOG(sreg, nreg) \ 123 addq $_CONST(_MUL(XMM_SIZE, nreg)), %rsp 124 125 #elif defined(__i386) 126 127 #define SAVE_XMM_PROLOG(sreg, nreg) \ 128 subl $_CONST(_MUL(XMM_SIZE, nreg) + XMM_ALIGN), %esp; \ 129 movl %esp, sreg; \ 130 addl $XMM_ALIGN, sreg; \ 131 andl $_BITNOT(XMM_ALIGN-1), sreg 132 133 #define RSTOR_XMM_EPILOG(sreg, nreg) \ 134 addl $_CONST(_MUL(XMM_SIZE, nreg) + XMM_ALIGN), %esp; 135 136 #endif /* __i386 */ 137 138 /* 139 * profiling causes definitions of the MCOUNT and RTMCOUNT 140 * particular to the type 141 */ 142 #ifdef GPROF 143 144 #define MCOUNT(x) \ 145 pushl %ebp; \ 146 movl %esp, %ebp; \ 147 call _mcount; \ 148 popl %ebp 149 150 #endif /* GPROF */ 151 152 #ifdef PROF 153 154 #define MCOUNT(x) \ 155 /* CSTYLED */ \ 156 .lcomm .L_/**/x/**/1, 4, 4; \ 157 pushl %ebp; \ 158 movl %esp, %ebp; \ 159 /* CSTYLED */ \ 160 movl $.L_/**/x/**/1, %edx; \ 161 call _mcount; \ 162 popl %ebp 163 164 #endif /* PROF */ 165 166 /* 167 * if we are not profiling, MCOUNT should be defined to nothing 168 */ 169 #if !defined(PROF) && !defined(GPROF) 170 #define MCOUNT(x) 171 #endif /* !defined(PROF) && !defined(GPROF) */ 172 173 #define RTMCOUNT(x) MCOUNT(x) 174 175 /* 176 * Macro to define weak symbol aliases. These are similar to the ANSI-C 177 * #pragma weak name = _name 178 * except a compiler can determine type. The assembler must be told. Hence, 179 * the second parameter must be the type of the symbol (i.e.: function,...) 180 */ 181 #define ANSI_PRAGMA_WEAK(sym, stype) \ 182 .weak sym; \ 183 .type sym, @stype; \ 184 /* CSTYLED */ \ 185 sym = _/**/sym 186 187 /* 188 * Like ANSI_PRAGMA_WEAK(), but for unrelated names, as in: 189 * #pragma weak sym1 = sym2 190 */ 191 #define ANSI_PRAGMA_WEAK2(sym1, sym2, stype) \ 192 .weak sym1; \ 193 .type sym1, @stype; \ 194 sym1 = sym2 195 196 /* 197 * ENTRY provides the standard procedure entry code and an easy way to 198 * insert the calls to mcount for profiling. ENTRY_NP is identical, but 199 * never calls mcount. 200 */ 201 #define ENTRY(x) \ 202 .text; \ 203 .align ASM_ENTRY_ALIGN; \ 204 .globl x; \ 205 .type x, @function; \ 206 x: MCOUNT(x) 207 208 #define ENTRY_NP(x) \ 209 .text; \ 210 .align ASM_ENTRY_ALIGN; \ 211 .globl x; \ 212 .type x, @function; \ 213 x: 214 215 #define RTENTRY(x) \ 216 .text; \ 217 .align ASM_ENTRY_ALIGN; \ 218 .globl x; \ 219 .type x, @function; \ 220 x: RTMCOUNT(x) 221 222 /* 223 * ENTRY2 is identical to ENTRY but provides two labels for the entry point. 224 */ 225 #define ENTRY2(x, y) \ 226 .text; \ 227 .align ASM_ENTRY_ALIGN; \ 228 .globl x, y; \ 229 .type x, @function; \ 230 .type y, @function; \ 231 /* CSTYLED */ \ 232 x: ; \ 233 y: MCOUNT(x) 234 235 #define ENTRY_NP2(x, y) \ 236 .text; \ 237 .align ASM_ENTRY_ALIGN; \ 238 .globl x, y; \ 239 .type x, @function; \ 240 .type y, @function; \ 241 /* CSTYLED */ \ 242 x: ; \ 243 y: 244 245 246 /* 247 * ALTENTRY provides for additional entry points. 248 */ 249 #define ALTENTRY(x) \ 250 .globl x; \ 251 .type x, @function; \ 252 x: 253 254 /* 255 * DGDEF and DGDEF2 provide global data declarations. 256 * 257 * DGDEF provides a word aligned word of storage. 258 * 259 * DGDEF2 allocates "sz" bytes of storage with **NO** alignment. This 260 * implies this macro is best used for byte arrays. 261 * 262 * DGDEF3 allocates "sz" bytes of storage with "algn" alignment. 263 */ 264 #define DGDEF2(name, sz) \ 265 .data; \ 266 .globl name; \ 267 .type name, @object; \ 268 .size name, sz; \ 269 name: 270 271 #define DGDEF3(name, sz, algn) \ 272 .data; \ 273 .align algn; \ 274 .globl name; \ 275 .type name, @object; \ 276 .size name, sz; \ 277 name: 278 279 #define DGDEF(name) DGDEF3(name, 4, 4) 280 281 /* 282 * SET_SIZE trails a function and set the size for the ELF symbol table. 283 */ 284 #define SET_SIZE(x) \ 285 .size x, [.-x] 286 287 /* 288 * NWORD provides native word value. 289 */ 290 #if defined(__amd64) 291 292 /*CSTYLED*/ 293 #define NWORD quad 294 295 #elif defined(__i386) 296 297 #define NWORD long 298 299 #endif /* __i386 */ 300 301 #endif /* _ASM */ 302 303 #ifdef __cplusplus 304 } 305 #endif 306 307 #endif /* _IA32_SYS_ASM_LINKAGE_H */ 308