1 /* 2 * Copyright (c) 2021 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 /* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved. 29 * 30 * File: architecture/i386/asm_help.h 31 * Author: Mike DeMoney, NeXT Computer, Inc. 32 * Modified for i386 by: Bruce Martin, NeXT Computer, Inc. 33 * 34 * This header file defines macros useful when writing assembly code 35 * for the Intel i386 family processors. 36 * 37 * HISTORY 38 * 10-Mar-92 Bruce Martin ([email protected]) 39 * Adapted to i386 40 * 23-Jan-91 Mike DeMoney ([email protected]) 41 * Created. 42 */ 43 44 #ifndef _ARCH_I386_ASM_HELP_H_ 45 #define _ARCH_I386_ASM_HELP_H_ 46 47 #include <architecture/i386/reg_help.h> 48 49 #ifdef __ASSEMBLER__ 50 51 /* Unwind Prologue added to each function to indicate the start of the unwind information. */ 52 #define UNWIND_PROLOGUE \ 53 .cfi_sections .eh_frame ;\ 54 .cfi_startproc ; 55 56 /* Unwind Epilogue added to each function to indicate the end of the unwind information */ 57 #define UNWIND_EPILOGUE .cfi_endproc 58 59 #define ALIGN \ 60 .align 2, 0x90 61 62 #define ROUND_TO_STACK(len) \ 63 (((len) + STACK_INCR - 1) / STACK_INCR * STACK_INCR) 64 65 #ifdef notdef 66 #if defined(__i386__) 67 #define CALL_MCOUNT \ 68 pushl %ebp ;\ 69 movl %esp, %ebp ;\ 70 .data ;\ 71 1: .long 0 ;\ 72 .text ;\ 73 lea 9b,%edx ;\ 74 call mcount ;\ 75 popl %ebp ; 76 #elif defined(__x86_64__) 77 #define CALL_MCOUNT \ 78 pushq %rbp ;\ 79 movq %rsp, %rbp ;\ 80 .data ;\ 81 1: .quad 0 ;\ 82 .text ;\ 83 lea 9b,%r13 ;\ 84 call mcount ;\ 85 popq %rbp ; 86 #endif 87 #else 88 #define CALL_MCOUNT 89 #endif 90 91 /* 92 * Prologue for functions that may call other functions. Saves 93 * registers and sets up a C frame. 94 */ 95 #if defined(__i386__) 96 #define NESTED_FUNCTION_PROLOGUE(localvarsize) \ 97 .set L__framesize,ROUND_TO_STACK(localvarsize) ;\ 98 .set L__nested_function, 1 ;\ 99 CALL_MCOUNT \ 100 .if L__framesize ;\ 101 pushl %ebp ;\ 102 movl %esp, %ebp ;\ 103 subl $L__framesize, %esp ;\ 104 .endif ;\ 105 pushl %edi ;\ 106 pushl %esi ;\ 107 pushl %ebx 108 #elif defined(__x86_64__) 109 #define NESTED_FUNCTION_PROLOGUE(localvarsize) \ 110 UNWIND_PROLOGUE ;\ 111 .set L__framesize,ROUND_TO_STACK(localvarsize) ;\ 112 .set L__nested_function, 1 ;\ 113 CALL_MCOUNT \ 114 .if L__framesize ;\ 115 pushq %rbp ;\ 116 movq %rsp, %rbp ;\ 117 subq $L__framesize, %rsp ;\ 118 .endif ; 119 #endif 120 121 /* 122 * Prologue for functions that do not call other functions. Does not 123 * save registers (this is the functions responsibility). Does set 124 * up a C frame. 125 */ 126 #if defined(__i386__) 127 #define LEAF_FUNCTION_PROLOGUE(localvarsize) \ 128 .set L__framesize,ROUND_TO_STACK(localvarsize) ;\ 129 .set L__nested_function, 0 ;\ 130 CALL_MCOUNT \ 131 .if L__framesize ;\ 132 pushl %ebp ;\ 133 movl %esp, %ebp ;\ 134 subl $L__framesize, %esp ;\ 135 .endif 136 #elif defined(__x86_64__) 137 #define LEAF_FUNCTION_PROLOGUE(localvarsize) \ 138 UNWIND_PROLOGUE ;\ 139 .set L__framesize,ROUND_TO_STACK(localvarsize) ;\ 140 .set L__nested_function, 0 ;\ 141 CALL_MCOUNT \ 142 .if L__framesize ;\ 143 pushq %rbp ;\ 144 movq %rsp, %rbp ;\ 145 subq $L__framesize, %rsp ;\ 146 .endif 147 #endif 148 149 /* 150 * Epilogue for any function. 151 * 152 * We assume that all Leaf functions will be responsible for saving any 153 * local registers they clobber. 154 */ 155 #if defined(__i386__) 156 #define FUNCTION_EPILOGUE \ 157 .if L__nested_function ;\ 158 popl %ebx ;\ 159 popl %esi ;\ 160 popl %edi ;\ 161 .endif ;\ 162 .if L__framesize ;\ 163 movl %ebp, %esp ;\ 164 popl %ebp ;\ 165 .endif ;\ 166 ret 167 #elif defined(__x86_64__) 168 #define FUNCTION_EPILOGUE \ 169 .if L__framesize ;\ 170 movq %rbp, %rsp ;\ 171 popq %rbp ;\ 172 .endif ;\ 173 ret ;\ 174 UNWIND_EPILOGUE 175 #endif 176 177 /* 178 * Macros for declaring procedures 179 * 180 * Use of these macros allows ctags to have a predictable way 181 * to find various types of declarations. They also simplify 182 * inserting appropriate symbol table information. 183 * 184 * NOTE: these simple stubs will be replaced with more 185 * complicated versions once we know what the linker and gdb 186 * will require as far as register use masks and frame declarations. 187 * These macros may also be ifdef'ed in the future to contain profiling 188 * code. 189 * 190 */ 191 192 /* 193 * TEXT -- declare start of text segment 194 */ 195 #define TEXT \ 196 .text 197 198 /* 199 * DATA -- declare start of data segment 200 */ 201 #define DATA \ 202 .data 203 204 /* 205 * LEAF -- declare global leaf procedure 206 * NOTE: Control SHOULD NOT FLOW into a LEAF! A LEAF should only 207 * be jumped to. (A leaf may do an align.) Use a LABEL() if you 208 * need control to flow into the label. 209 */ 210 #define LEAF(name, localvarsize) \ 211 .globl name ;\ 212 ALIGN ;\ 213 name: ;\ 214 LEAF_FUNCTION_PROLOGUE(localvarsize) 215 216 /* 217 * X_LEAF -- declare alternate global label for leaf 218 */ 219 #define X_LEAF(name, value) \ 220 .globl name ;\ 221 .set name,value 222 223 /* 224 * P_LEAF -- declare private leaf procedure 225 */ 226 #define P_LEAF(name, localvarsize) \ 227 ALIGN ;\ 228 name: ;\ 229 LEAF_FUNCTION_PROLOGUE(localvarsize) 230 231 /* 232 * LABEL -- declare a global code label 233 * MUST be used (rather than LEAF, NESTED, etc) if control 234 * "flows into" the label. 235 */ 236 #define LABEL(name) \ 237 .globl name ;\ 238 name: 239 240 /* 241 * NESTED -- declare procedure that invokes other procedures 242 */ 243 #define NESTED(name, localvarsize) \ 244 .globl name ;\ 245 ALIGN ;\ 246 name: ;\ 247 NESTED_FUNCTION_PROLOGUE(localvarsize) 248 249 /* 250 * X_NESTED -- declare alternate global label for nested proc 251 */ 252 #define X_NESTED(name, value) \ 253 .globl name ;\ 254 .set name,value 255 256 /* 257 * P_NESTED -- declare private nested procedure 258 */ 259 #define P_NESTED(name, localvarsize) \ 260 ALIGN ;\ 261 name: ;\ 262 NESTED_FUNCTION_PROLOGUE(localvarsize) 263 264 /* 265 * END -- mark end of procedure 266 */ 267 #define END(name) \ 268 FUNCTION_EPILOGUE 269 270 271 /* 272 * Storage definition macros 273 * The main purpose of these is to allow an easy handle for ctags 274 */ 275 276 /* 277 * IMPORT -- import symbol 278 */ 279 #define IMPORT(name) \ 280 .reference name 281 282 /* 283 * ABS -- declare global absolute symbol 284 */ 285 #define ABS(name, value) \ 286 .globl name ;\ 287 .set name,value 288 289 /* 290 * P_ABS -- declare private absolute symbol 291 */ 292 #define P_ABS(name, value) \ 293 .set name,value 294 295 /* 296 * EXPORT -- declare global label for data 297 */ 298 #define EXPORT(name) \ 299 .globl name ;\ 300 name: 301 302 /* 303 * BSS -- declare global zero'ed storage 304 */ 305 #define BSS(name,size) \ 306 .comm name,size 307 308 309 /* 310 * P_BSS -- declare private zero'ed storage 311 */ 312 #define P_BSS(name,size) \ 313 .lcomm name,size 314 315 /* 316 * dynamic/PIC macros for routines which reference external symbols 317 */ 318 319 #if defined(__DYNAMIC__) 320 #if defined(__i386__) 321 #define PICIFY(var) \ 322 call 1f ; \ 323 1: ; \ 324 popl %edx ; \ 325 movl L ## var ## __non_lazy_ptr-1b(%edx),%edx 326 #elif defined(__x86_64__) 327 #define PICIFY(var) \ 328 movq var@GOTPCREL(%rip),%r11 329 #endif 330 331 #if defined(__i386__) 332 #define CALL_EXTERN_AGAIN(func) \ 333 PICIFY(func) ; \ 334 call *%edx 335 #elif defined(__x86_64__) 336 #define CALL_EXTERN_AGAIN(func) \ 337 call func 338 #endif 339 340 #if defined(__i386__) 341 #define NON_LAZY_STUB(var) \ 342 .section __IMPORT,__pointers,non_lazy_symbol_pointers ; \ 343 L ## var ## __non_lazy_ptr: ; \ 344 .indirect_symbol var ; \ 345 .long 0 ; \ 346 .text 347 #elif defined(__x86_64__) 348 #define NON_LAZY_STUB(var) 349 #endif 350 351 #define CALL_EXTERN(func) \ 352 CALL_EXTERN_AGAIN(func) ; \ 353 NON_LAZY_STUB(func) 354 355 #if defined(__i386__) 356 #define BRANCH_EXTERN(func) \ 357 PICIFY(func) ; \ 358 jmp *%edx ; \ 359 NON_LAZY_STUB(func) 360 #elif defined(__x86_64__) 361 #define BRANCH_EXTERN(func) \ 362 jmp func 363 #endif 364 365 #if defined(__i386__) 366 #define PUSH_EXTERN(var) \ 367 PICIFY(var) ; \ 368 movl (%edx),%edx ; \ 369 pushl %edx ; \ 370 NON_LAZY_STUB(var) 371 #endif 372 373 #if defined(__i386__) 374 #define REG_TO_EXTERN(reg, var) \ 375 PICIFY(var) ; \ 376 movl reg, (%edx) ; \ 377 NON_LAZY_STUB(var) 378 #elif defined(__x86_64__) 379 #define REG_TO_EXTERN(reg, var) \ 380 PICIFY(var) ; \ 381 mov reg, (%r11) 382 #endif 383 384 #if defined(__i386__) 385 #define EXTERN_TO_REG(var, reg) \ 386 call 1f ; \ 387 1: ; \ 388 popl %edx ; \ 389 movl L ## var ##__non_lazy_ptr-1b(%edx),reg ; \ 390 NON_LAZY_STUB(var) 391 #elif defined(__x86_64__) 392 #define EXTERN_TO_REG(var, reg) \ 393 PICIFY(var) ; \ 394 mov (%r11), reg 395 #endif 396 397 #else 398 #define BRANCH_EXTERN(func) jmp func 399 #define PUSH_EXTERN(var) push var 400 #define CALL_EXTERN(func) call func 401 #define CALL_EXTERN_AGAIN(func) call func 402 #if defined(__i386__) 403 #define REG_TO_EXTERN(reg, var) mov reg, var 404 #define EXTERN_TO_REG(var, reg) mov $ ## var, reg 405 #elif defined(__x86_64__) 406 #define REG_TO_EXTERN(reg, var) mov reg, var ## (%rip) 407 #define EXTERN_TO_REG(var, reg) mov var ## (%rip), reg 408 #endif 409 #endif 410 411 #endif /* __ASSEMBLER__ */ 412 413 #endif /* _ARCH_I386_ASM_HELP_H_ */ 414