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 (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   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.
  12  *
  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]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2008 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 /* CSTYLED */ \
 183         .weak   _/**/sym; \
 184 /* CSTYLED */ \
 185         .type   _/**/sym, @stype; \
 186 /* CSTYLED */ \
 187 _/**/sym = sym
 188 
 189 /*
 190  * Like ANSI_PRAGMA_WEAK(), but for unrelated names, as in:
 191  *      #pragma weak sym1 = sym2
 192  */
 193 #define ANSI_PRAGMA_WEAK2(sym1, sym2, stype)    \
 194         .weak   sym1; \
 195         .type sym1, @stype; \
 196 sym1    = sym2
 197 
 198 /*
 199  * ENTRY provides the standard procedure entry code and an easy way to
 200  * insert the calls to mcount for profiling. ENTRY_NP is identical, but
 201  * never calls mcount.
 202  */
 203 #define ENTRY(x) \
 204         .text; \
 205         .align  ASM_ENTRY_ALIGN; \
 206         .globl  x; \
 207         .type   x, @function; \
 208 x:      MCOUNT(x)
 209 
 210 #define ENTRY_NP(x) \
 211         .text; \
 212         .align  ASM_ENTRY_ALIGN; \
 213         .globl  x; \
 214         .type   x, @function; \
 215 x:
 216 
 217 #define RTENTRY(x) \
 218         .text; \
 219         .align  ASM_ENTRY_ALIGN; \
 220         .globl  x; \
 221         .type   x, @function; \
 222 x:      RTMCOUNT(x)
 223 
 224 /*
 225  * ENTRY2 is identical to ENTRY but provides two labels for the entry point.
 226  */
 227 #define ENTRY2(x, y) \
 228         .text; \
 229         .align  ASM_ENTRY_ALIGN; \
 230         .globl  x, y; \
 231         .type   x, @function; \
 232         .type   y, @function; \
 233 /* CSTYLED */ \
 234 x:      ; \
 235 y:      MCOUNT(x)
 236 
 237 #define ENTRY_NP2(x, y) \
 238         .text; \
 239         .align  ASM_ENTRY_ALIGN; \
 240         .globl  x, y; \
 241         .type   x, @function; \
 242         .type   y, @function; \
 243 /* CSTYLED */ \
 244 x:      ; \
 245 y:
 246 
 247 
 248 /*
 249  * ALTENTRY provides for additional entry points.
 250  */
 251 #define ALTENTRY(x) \
 252         .globl x; \
 253         .type   x, @function; \
 254 x:
 255 
 256 /*
 257  * DGDEF and DGDEF2 provide global data declarations.
 258  *
 259  * DGDEF provides a word aligned word of storage.
 260  *
 261  * DGDEF2 allocates "sz" bytes of storage with **NO** alignment.  This
 262  * implies this macro is best used for byte arrays.
 263  *
 264  * DGDEF3 allocates "sz" bytes of storage with "algn" alignment.
 265  */
 266 #define DGDEF2(name, sz) \
 267         .data; \
 268         .globl  name; \
 269         .type   name, @object; \
 270         .size   name, sz; \
 271 name:
 272 
 273 #define DGDEF3(name, sz, algn) \
 274         .data; \
 275         .align  algn; \
 276         .globl  name; \
 277         .type   name, @object; \
 278         .size   name, sz; \
 279 name:
 280 
 281 #define DGDEF(name)     DGDEF3(name, 4, 4)
 282 
 283 /*
 284  * SET_SIZE trails a function and set the size for the ELF symbol table.
 285  */
 286 #define SET_SIZE(x) \
 287         .size   x, [.-x]
 288 
 289 /*
 290  * NWORD provides native word value.
 291  */
 292 #if defined(__amd64)
 293 
 294 /*CSTYLED*/
 295 #define NWORD   quad
 296 
 297 #elif defined(__i386)
 298 
 299 #define NWORD   long
 300 
 301 #endif  /* __i386 */
 302 
 303 #endif /* _ASM */
 304 
 305 #ifdef  __cplusplus
 306 }
 307 #endif
 308 
 309 #endif  /* _IA32_SYS_ASM_LINKAGE_H */