#ifndef _ARCH_I386_ASM_HELP_H_
#define _ARCH_I386_ASM_HELP_H_
#include <architecture/i386/reg_help.h>
#ifdef __ASSEMBLER__
#define ALIGN \
.align 2, 0x90
#define ROUND_TO_STACK(len) \
(((len) + STACK_INCR - 1) / STACK_INCR * STACK_INCR)
#ifdef notdef
#if defined(__i386__)
#define CALL_MCOUNT \
pushl %ebp ;\
movl %esp, %ebp ;\
.data ;\
1: .long 0 ;\
.text ;\
lea 9b,%edx ;\
call mcount ;\
popl %ebp ;
#elif defined(__x86_64__)
#define CALL_MCOUNT \
pushq %rbp ;\
movq %rsp, %rbp ;\
.data ;\
1: .quad 0 ;\
.text ;\
lea 9b,%r13 ;\
call mcount ;\
popq %rbp ;
#endif
#else
#define CALL_MCOUNT
#endif
#if defined(__i386__)
#define NESTED_FUNCTION_PROLOGUE(localvarsize) \
.set L__framesize,ROUND_TO_STACK(localvarsize) ;\
.set L__nested_function, 1 ;\
CALL_MCOUNT \
.if L__framesize ;\
pushl %ebp ;\
movl %esp, %ebp ;\
subl $L__framesize, %esp ;\
.endif ;\
pushl %edi ;\
pushl %esi ;\
pushl %ebx
#elif defined(__x86_64__)
#define NESTED_FUNCTION_PROLOGUE(localvarsize) \
.set L__framesize,ROUND_TO_STACK(localvarsize) ;\
.set L__nested_function, 1 ;\
CALL_MCOUNT \
.if L__framesize ;\
pushq %rbp ;\
movq %rsp, %rbp ;\
subq $L__framesize, %rsp ;\
.endif ;
#endif
#if defined(__i386__)
#define LEAF_FUNCTION_PROLOGUE(localvarsize) \
.set L__framesize,ROUND_TO_STACK(localvarsize) ;\
.set L__nested_function, 0 ;\
CALL_MCOUNT \
.if L__framesize ;\
pushl %ebp ;\
movl %esp, %ebp ;\
subl $L__framesize, %esp ;\
.endif
#elif defined(__x86_64__)
#define LEAF_FUNCTION_PROLOGUE(localvarsize) \
.set L__framesize,ROUND_TO_STACK(localvarsize) ;\
.set L__nested_function, 0 ;\
CALL_MCOUNT \
.if L__framesize ;\
pushq %rbp ;\
movq %rsp, %rbp ;\
subq $L__framesize, %rsp ;\
.endif
#endif
#if defined(__i386__)
#define FUNCTION_EPILOGUE \
.if L__nested_function ;\
popl %ebx ;\
popl %esi ;\
popl %edi ;\
.endif ;\
.if L__framesize ;\
movl %ebp, %esp ;\
popl %ebp ;\
.endif ;\
ret
#elif defined(__x86_64__)
#define FUNCTION_EPILOGUE \
.if L__framesize ;\
movq %rbp, %rsp ;\
popq %rbp ;\
.endif ;\
ret
#endif
#define TEXT \
.text
#define DATA \
.data
#define LEAF(name, localvarsize) \
.globl name ;\
ALIGN ;\
name: ;\
LEAF_FUNCTION_PROLOGUE(localvarsize)
#define X_LEAF(name, value) \
.globl name ;\
.set name,value
#define P_LEAF(name, localvarsize) \
ALIGN ;\
name: ;\
LEAF_FUNCTION_PROLOGUE(localvarsize)
#define LABEL(name) \
.globl name ;\
name:
#define NESTED(name, localvarsize) \
.globl name ;\
ALIGN ;\
name: ;\
NESTED_FUNCTION_PROLOGUE(localvarsize)
#define X_NESTED(name, value) \
.globl name ;\
.set name,value
#define P_NESTED(name, localvarsize) \
ALIGN ;\
name: ;\
NESTED_FUNCTION_PROLOGUE(localvarsize)
#define END(name) \
FUNCTION_EPILOGUE
#define IMPORT(name) \
.reference name
#define ABS(name, value) \
.globl name ;\
.set name,value
#define P_ABS(name, value) \
.set name,value
#define EXPORT(name) \
.globl name ;\
name:
#define BSS(name,size) \
.comm name,size
#define P_BSS(name,size) \
.lcomm name,size
#if defined(__DYNAMIC__)
#if defined(__i386__)
#define PICIFY(var) \
call 1f ; \
1: ; \
popl %edx ; \
movl L ## var ## __non_lazy_ptr-1b(%edx),%edx
#elif defined(__x86_64__)
#define PICIFY(var) \
movq var@GOTPCREL(%rip),%r11
#endif
#if defined(__i386__)
#define CALL_EXTERN_AGAIN(func) \
PICIFY(func) ; \
call *%edx
#elif defined(__x86_64__)
#define CALL_EXTERN_AGAIN(func) \
call func
#endif
#if defined(__i386__)
#define NON_LAZY_STUB(var) \
.section __IMPORT,__pointers,non_lazy_symbol_pointers ; \
L ## var ## __non_lazy_ptr: ; \
.indirect_symbol var ; \
.long 0 ; \
.text
#elif defined(__x86_64__)
#define NON_LAZY_STUB(var)
#endif
#define CALL_EXTERN(func) \
CALL_EXTERN_AGAIN(func) ; \
NON_LAZY_STUB(func)
#if defined(__i386__)
#define BRANCH_EXTERN(func) \
PICIFY(func) ; \
jmp *%edx ; \
NON_LAZY_STUB(func)
#elif defined(__x86_64__)
#define BRANCH_EXTERN(func) \
jmp func
#endif
#if defined(__i386__)
#define PUSH_EXTERN(var) \
PICIFY(var) ; \
movl (%edx),%edx ; \
pushl %edx ; \
NON_LAZY_STUB(var)
#endif
#if defined(__i386__)
#define REG_TO_EXTERN(reg, var) \
PICIFY(var) ; \
movl reg, (%edx) ; \
NON_LAZY_STUB(var)
#elif defined(__x86_64__)
#define REG_TO_EXTERN(reg, var) \
PICIFY(var) ; \
mov reg, (%r11)
#endif
#if defined(__i386__)
#define EXTERN_TO_REG(var, reg) \
call 1f ; \
1: ; \
popl %edx ; \
movl L ## var ##__non_lazy_ptr-1b(%edx),reg ; \
NON_LAZY_STUB(var)
#elif defined(__x86_64__)
#define EXTERN_TO_REG(var, reg) \
PICIFY(var) ; \
mov (%r11), reg
#endif
#else
#define BRANCH_EXTERN(func) jmp func
#define PUSH_EXTERN(var) push var
#define CALL_EXTERN(func) call func
#define CALL_EXTERN_AGAIN(func) call func
#if defined(__i386__)
#define REG_TO_EXTERN(reg, var) mov reg, var
#define EXTERN_TO_REG(var, reg) mov $ ## var, reg
#elif defined(__x86_64__)
#define REG_TO_EXTERN(reg, var) mov reg, var ## (%rip)
#define EXTERN_TO_REG(var, reg) mov var ## (%rip), reg
#endif
#endif
#endif
#endif