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