blob: 1d8c1076bca907d467364dc975484d5d4d307cfd [file] [log] [blame]
/* **********************************************************
* Copyright (c) 2011-2014 Google, Inc. All rights reserved.
* Copyright (c) 2008-2009 VMware, Inc. All rights reserved.
* ********************************************************** */
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of VMware, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
#ifndef _ASM_DEFINES_ASM_
#define _ASM_DEFINES_ASM_ 1
/* Preprocessor macro definitions shared among all .asm files.
* Since cpp macros can't generate newlines we have a later
* script replace @N@ for us.
*/
#include "configure.h"
#if defined(X86_64) && !defined(X64)
# define X64
#endif
#ifdef ARM
# ifdef X64
# error 64-bit ARM is not supported
# endif
# ifdef WINDOWS
# error ARM on Windows is not supported
# endif
#endif
/****************************************************/
#if defined(ASSEMBLE_WITH_GAS)
# define START_FILE .text
# define END_FILE /* nothing */
# define DECLARE_FUNC(symbol) \
.align 0 @N@\
.global symbol @N@\
.hidden symbol @N@\
.type symbol, %function
# define DECLARE_EXPORTED_FUNC(symbol) \
.align 0 @N@\
.global symbol @N@\
.type symbol, %function
# define END_FUNC(symbol) /* nothing */
# define DECLARE_GLOBAL(symbol) \
.global symbol @N@\
.hidden symbol
# define GLOBAL_LABEL(label) label
# define ADDRTAKEN_LABEL(label) label
# define GLOBAL_REF(label) label
# define BYTE byte ptr
# define WORD word ptr
# define DWORD dword ptr
# define QWORD qword ptr
# define MMWORD qword ptr
# define XMMWORD oword ptr
# define YMMWORD ymmword ptr
# ifdef X64
/* w/o the rip, gas won't use rip-rel and adds relocs that ld trips over */
# define SYMREF(sym) [rip + sym]
# else
# define SYMREF(sym) [sym]
# endif
# define HEX(n) 0x##n
# define SEGMEM(seg,mem) [seg:mem]
# define DECL_EXTERN(symbol) /* nothing */
/* include newline so we can put multiple on one line */
# define RAW(n) .byte HEX(n) @N@
# define DECLARE_FUNC_SEH(symbol) DECLARE_FUNC(symbol)
# define PUSH_SEH(reg) push reg
# define PUSH_NONCALLEE_SEH(reg) push reg
# define END_PROLOG /* nothing */
/* PR 212290: avoid text relocations.
* @GOT returns the address and is for extern vars; @GOTOFF gets the value.
* Note that using ## to paste =>
* "error: pasting "initstack_mutex" and "@" does not give a valid preprocessing token"
* but whitespace separation seems fine.
*/
# define ADDR_VIA_GOT(base, sym) [sym @GOT + base]
# define VAR_VIA_GOT(base, sym) [sym @GOTOFF + base]
/****************************************************/
#elif defined(ASSEMBLE_WITH_MASM)
# ifdef X64
# define START_FILE \
/* We add blank lines to match the 32-bit line count */ \
/* match .686 */ @N@\
/* match .XMM */ @N@\
/* match .MODEL */@N@\
/* match ASSUME */@N@\
.CODE
# else
# define START_FILE \
.686 /* default is 8086! need 686 for sysenter */ @N@\
.XMM /* needed for fnclex and fxrstor */ @N@\
.MODEL flat, c @N@\
ASSUME fs:_DATA @N@\
.CODE
# endif
# define END_FILE END
/* we don't seem to need EXTERNDEF or GLOBAL */
# define DECLARE_FUNC(symbol) symbol PROC
# define DECLARE_EXPORTED_FUNC(symbol) symbol PROC EXPORT
# define END_FUNC(symbol) symbol ENDP
# define DECLARE_GLOBAL(symbol) PUBLIC symbol
/* XXX: this should be renamed FUNC_ENTRY_LABEL */
# define GLOBAL_LABEL(label)
/* use double colon (param always has its own colon) to make label visible outside proc */
# define ADDRTAKEN_LABEL(label) label:
# define GLOBAL_REF(label) label
# define BYTE byte ptr
# define WORD word ptr
# define DWORD dword ptr
# define QWORD qword ptr
# define MMWORD mmword ptr
# define XMMWORD xmmword ptr
# define YMMWORD ymmword ptr /* added in VS 2010 */
/* ml64 uses rip-rel automatically */
# define SYMREF(sym) [sym]
# define HEX(n) 0##n##h
# define SEGMEM(seg,mem) seg:[mem]
# define DECL_EXTERN(symbol) EXTERN symbol:PROC
/* include newline so we can put multiple on one line */
# define RAW(n) DB HEX(n) @N@
# ifdef X64
/* 64-bit SEH directives */
/* Declare non-leaf function (adjusts stack; makes calls; saves non-volatile regs): */
# define DECLARE_FUNC_SEH(symbol) symbol PROC FRAME
/* Push a non-volatile register in prolog: */
# define PUSH_SEH(reg) push reg @N@ .pushreg reg
/* Push a volatile register or an immed in prolog: */
# define PUSH_NONCALLEE_SEH(reg) push reg @N@ .allocstack 8
# define END_PROLOG .endprolog
# else
# define DECLARE_FUNC_SEH(symbol) DECLARE_FUNC(symbol)
# define PUSH_SEH(reg) push reg @N@ /* add a line to match x64 line count */
# define PUSH_NONCALLEE_SEH(reg) push reg @N@ /* add a line to match x64 line count */
# define END_PROLOG /* nothing */
# endif
/****************************************************/
#elif defined(ASSEMBLE_WITH_NASM)
# define START_FILE SECTION .text
# define END_FILE /* nothing */
/* for MacOS, at least, we have to add _ ourselves */
# define DECLARE_FUNC(symbol) global _##symbol
# define DECLARE_EXPORTED_FUNC(symbol) global _##symbol
# define END_FUNC(symbol) /* nothing */
# define DECLARE_GLOBAL(symbol) global _##symbol
# define GLOBAL_LABEL(label) _##label
# define ADDRTAKEN_LABEL(label) _##label
# define GLOBAL_REF(label) _##label
# define BYTE byte
# define WORD word
# define DWORD dword
# define QWORD qword
# define MMWORD qword
# define XMMWORD oword
# define YMMWORD yword
# ifdef X64
# define SYMREF(sym) [rel GLOBAL_REF(sym)]
# else
# define SYMREF(sym) [GLOBAL_REF(sym)]
# endif
# define HEX(n) 0x##n
# define SEGMEM(seg,mem) [seg:mem]
# define DECL_EXTERN(symbol) EXTERN GLOBAL_REF(symbol)
# define RAW(n) DB HEX(n) @N@
# define DECLARE_FUNC_SEH(symbol) DECLARE_FUNC(symbol)
# define PUSH_SEH(reg) push reg
# define PUSH_NONCALLEE_SEH(reg) push reg
# define END_PROLOG /* nothing */
/****************************************************/
#else
# error Unknown assembler: set one of the ASSEMBLE_WITH_{GAS,MASM,NASM} defines
#endif
/****************************************************/
/* Macros for writing cross-platform 64-bit + 32-bit code */
/* register set */
#ifdef ARM
# ifdef X64
# define REG_R0 x0
# define REG_R1 x1
# define REG_R2 x2
# define REG_R3 x3
# define REG_R4 x4
# define REG_R5 x5
# define REG_R6 x6
# define REG_R7 x7
# define REG_R8 x8
# define REG_R9 x9
# define REG_R10 x10
# define REG_R11 x11
# define REG_R12 x12
/* skip [x16..x30], only available on AArch64 */
# else /* 32-bit */
# define REG_R0 r0
# define REG_R1 r1
# define REG_R2 r2
# define REG_R3 r3
# define REG_R4 r4
# define REG_R5 r5
# define REG_R6 r6
# define REG_R7 r7
# define REG_R8 r8
# define REG_R9 r9
# define REG_R10 r10
# define REG_R11 r11
# define REG_R12 r12
/* {r13, r14, r15} are used for {sp, lr, pc} on AArch32 */
# endif /* 64/32-bit */
#else /* Intel X86 */
# ifdef X64
# define REG_XAX rax
# define REG_XBX rbx
# define REG_XCX rcx
# define REG_XDX rdx
# define REG_XSI rsi
# define REG_XDI rdi
# define REG_XBP rbp
# define REG_XSP rsp
/* skip [r8..r15], only available on AMD64 */
# define SEG_TLS gs /* keep in sync w/ {linux,win32}/os_exports.h defines */
# else /* 32-bit */
# define REG_XAX eax
# define REG_XBX ebx
# define REG_XCX ecx
# define REG_XDX edx
# define REG_XSI esi
# define REG_XDI edi
# define REG_XBP ebp
# define REG_XSP esp
# define SEG_TLS fs /* keep in sync w/ {linux,win32}/os_exports.h defines */
# endif /* 64/32-bit */
#endif /* ARM/X86 */
/* calling convention */
#ifdef X64
# define ARG_SZ 8
# define PTRSZ QWORD
#else /* 32-bit */
# define ARG_SZ 4
# define PTRSZ DWORD
#endif
#ifdef ARM
/* ARM AArch64 calling convention:
* SP: stack pointer
* x30(LR): link register
* x29(FP): frame pointer
* x19..x28: callee-saved registers
* x18: platform register if needed, otherwise, temp register
* x17(IP1): the 2nd intra-procedure-call temp reg (for call veneers and PLT code)
* x16(IP0): the 1st intra-procedure-call temp reg (for call veneers and PLT code)
* x9..x15: temp registers
* x8: indirect result location register
* x0..x7: parameter/result registers
*
* ARM AArch32 calling convention:
* r15(PC): program counter
* r14(LR): link register
* r13(SP): stack pointer
* r12: the Intra-Procedure-call scratch register
* r4..r11: callee-saved registers
* r0..r3: parameter/result registers
* r0: indirect result location register
*/
# define ARG1 REG_R0
# define ARG2 REG_R1
# define ARG3 REG_R2
# define ARG4 REG_R3
# ifdef X64
# define ARG5 REG_R4
# define ARG6 REG_R5
# define ARG7 REG_R6
# define ARG8 REG_R7
/* Arguments are passed on stack right-to-left. */
# define ARG9 QWORD [0*ARG_SZ + REG_SP] /* no ret addr */
# define ARG10 QWORD [1*ARG_SZ + REG_SP]
# else /* 32-bit */
# define ARG5 DWORD [0*ARG_SZ + REG_SP] /* no ret addr */
# define ARG6 DWORD [1*ARG_SZ + REG_SP]
# define ARG7 DWORD [2*ARG_SZ + REG_SP]
# define ARG8 DWORD [3*ARG_SZ + REG_SP]
# define ARG9 DWORD [4*ARG_SZ + REG_SP]
# define ARG10 DWORD [5*ARG_SZ + REG_SP]
# endif /* 64/32-bit */
# define ARG1_NORETADDR ARG1
# define ARG2_NORETADDR ARG2
# define ARG3_NORETADDR ARG3
# define ARG4_NORETADDR ARG4
# define ARG5_NORETADDR ARG5
# define ARG6_NORETADDR ARG6
# define ARG7_NORETADDR ARG7
# define ARG8_NORETADDR ARG8
# define ARG9_NORETADDR ARG9
# define ARG10_NORETADDR ARG10
#else /* Intel X86 */
# ifdef X64
# ifdef WINDOWS
/* Arguments are passed in: rcx, rdx, r8, r9, then on stack right-to-left, but
* leaving space on stack for the 1st 4.
*/
# define ARG1 rcx
# define ARG2 rdx
# define ARG3 r8
# define ARG4 r9
# define ARG5 QWORD [5*ARG_SZ + REG_XSP] /* includes ret addr */
# define ARG6 QWORD [6*ARG_SZ + REG_XSP]
# define ARG7 QWORD [7*ARG_SZ + REG_XSP]
# define ARG8 QWORD [8*ARG_SZ + REG_XSP]
# define ARG9 QWORD [9*ARG_SZ + REG_XSP]
# define ARG10 QWORD [10*ARG_SZ + REG_XSP]
# define ARG1_NORETADDR ARG1
# define ARG2_NORETADDR ARG2
# define ARG3_NORETADDR ARG3
# define ARG4_NORETADDR ARG4
# define ARG5_NORETADDR QWORD [4*ARG_SZ + REG_XSP]
# define ARG6_NORETADDR QWORD [5*ARG_SZ + REG_XSP]
# define ARG7_NORETADDR QWORD [6*ARG_SZ + REG_XSP]
# define ARG8_NORETADDR QWORD [7*ARG_SZ + REG_XSP]
# define ARG9_NORETADDR QWORD [8*ARG_SZ + REG_XSP]
# define ARG10_NORETADDR QWORD [9*ARG_SZ + REG_XSP]
# else /* UNIX */
/* Arguments are passed in: rdi, rsi, rdx, rcx, r8, r9, then on stack right-to-left,
* without leaving any space on stack for the 1st 6.
*/
# define ARG1 rdi
# define ARG2 rsi
# define ARG3 rdx
# define ARG4 rcx
# define ARG5 r8
# define ARG6 r9
# define ARG7 QWORD [1*ARG_SZ + rsp] /* includes ret addr */
# define ARG8 QWORD [2*ARG_SZ + rsp]
# define ARG9 QWORD [3*ARG_SZ + rsp]
# define ARG10 QWORD [4*ARG_SZ + rsp]
# define ARG1_NORETADDR ARG1
# define ARG2_NORETADDR ARG2
# define ARG3_NORETADDR ARG3
# define ARG4_NORETADDR ARG4
# define ARG5_NORETADDR ARG5
# define ARG6_NORETADDR ARG6
# define ARG7_NORETADDR QWORD [0*ARG_SZ + rsp]
# define ARG8_NORETADDR QWORD [1*ARG_SZ + rsp]
# define ARG9_NORETADDR QWORD [2*ARG_SZ + rsp]
# define ARG10_NORETADDR QWORD [3*ARG_SZ + rsp]
# endif /* WINDOWS/UNIX */
# else /* 32-bit */
/* Arguments are passed on stack right-to-left. */
# define ARG1 DWORD [ 1*ARG_SZ + esp] /* includes ret addr */
# define ARG2 DWORD [ 2*ARG_SZ + esp]
# define ARG3 DWORD [ 3*ARG_SZ + esp]
# define ARG4 DWORD [ 4*ARG_SZ + esp]
# define ARG5 DWORD [ 5*ARG_SZ + esp]
# define ARG6 DWORD [ 6*ARG_SZ + esp]
# define ARG7 DWORD [ 7*ARG_SZ + esp]
# define ARG8 DWORD [ 8*ARG_SZ + esp]
# define ARG9 DWORD [ 9*ARG_SZ + esp]
# define ARG10 DWORD [10*ARG_SZ + esp]
# define ARG1_NORETADDR DWORD [0*ARG_SZ + esp]
# define ARG2_NORETADDR DWORD [1*ARG_SZ + esp]
# define ARG3_NORETADDR DWORD [2*ARG_SZ + esp]
# define ARG4_NORETADDR DWORD [3*ARG_SZ + esp]
# define ARG5_NORETADDR DWORD [4*ARG_SZ + esp]
# define ARG6_NORETADDR DWORD [5*ARG_SZ + esp]
# define ARG7_NORETADDR DWORD [6*ARG_SZ + esp]
# define ARG8_NORETADDR DWORD [7*ARG_SZ + esp]
# define ARG9_NORETADDR DWORD [8*ARG_SZ + esp]
# define ARG10_NORETADDR DWORD [9*ARG_SZ + esp]
# endif /* 64/32-bit */
#endif /* ARM/X86 */
/* Keep in sync with arch_exports.h. */
#define FRAME_ALIGNMENT 16
/* From globals_shared.h, but we can't include that into asm code. */
#ifdef X64
# define IF_X64(x) x
# define IF_X64_ELSE(x, y) x
# define IF_NOT_X64(x)
#else
# define IF_X64(x)
# define IF_X64_ELSE(x, y) y
# define IF_NOT_X64(x) x
#endif
#ifdef X64
# define PUSHF pushfq
# define POPF popfq
# ifdef WINDOWS
# define STACK_PAD(tot, gt4, mod4) \
lea REG_XSP, [-32 - ARG_SZ*gt4 + REG_XSP]
# define STACK_PAD_NOPUSH(tot, gt4, mod4) STACK_PAD(tot, gt4, mod4)
# define STACK_UNPAD(tot, gt4, mod4) \
lea REG_XSP, [32 + ARG_SZ*gt4 + REG_XSP]
/* we split these out just to avoid nop lea for x64 linux */
# define STACK_PAD_LE4(tot, mod4) STACK_PAD(0/*doesn't matter*/, 0, mod4)
# define STACK_UNPAD_LE4(tot, mod4) STACK_UNPAD(tot, 0, mod4)
# else /* UNIX */
# define STACK_PAD(tot, gt4, mod4) \
lea REG_XSP, [-ARG_SZ*gt4 + REG_XSP]
# define STACK_PAD_NOPUSH(tot, gt4, mod4) STACK_PAD(tot, gt4, mod4)
# define STACK_UNPAD(tot, gt4, mod4) \
lea REG_XSP, [ARG_SZ*gt4 + REG_XSP]
# define STACK_PAD_LE4(tot, mod4) /* nothing */
# define STACK_UNPAD_LE4(tot, mod4) /* nothing */
# endif /* Win/UNIX */
/* we split these out just to avoid nop lea for x86 mac */
# define STACK_PAD_ZERO STACK_PAD_LE4(0, 4)
# define STACK_UNPAD_ZERO STACK_UNPAD_LE4(0, 4)
# define SETARG(argoffs, argreg, p) \
mov argreg, p
#else /* 32-bit */
# define PUSHF pushfd
# define POPF popfd
# ifdef MACOS
/* Mac requires 32-bit to have 16-byte stack alignment (at call site)
* Pass 4 instead of 0 for mod4 to avoid wasting stack space.
*/
# define STACK_PAD(tot, gt4, mod4) \
lea REG_XSP, [-ARG_SZ*((tot) + 4 - (mod4)) + REG_XSP]
# define STACK_PAD_NOPUSH(tot, gt4, mod4) STACK_PAD(tot, gt4, mod4)
# define STACK_UNPAD(tot, gt4, mod4) \
lea REG_XSP, [ARG_SZ*((tot) + 4 - (mod4)) + REG_XSP]
# define STACK_PAD_LE4(tot, mod4) STACK_PAD(tot, 0, mod4)
# define STACK_UNPAD_LE4(tot, mod4) STACK_UNPAD(tot, 0, mod4)
# define STACK_PAD_ZERO /* nothing */
# define STACK_UNPAD_ZERO /* nothing */
/* p cannot be a memory operand, naturally */
# define SETARG(argoffs, argreg, p) \
mov PTRSZ [ARG_SZ*argoffs + REG_XSP], p
# else /* !MACOS */
# define STACK_PAD(tot, gt4, mod4) /* nothing */
# define STACK_PAD_NOPUSH(tot, gt4, mod4) \
lea REG_XSP, [-ARG_SZ*tot + REG_XSP]
# define STACK_UNPAD(tot, gt4, mod4) \
lea REG_XSP, [ARG_SZ*tot + REG_XSP]
# define STACK_PAD_LE4(tot, mod4) /* nothing */
# define STACK_UNPAD_LE4(tot, mod4) STACK_UNPAD(tot, 0, mod4)
# define STACK_PAD_ZERO /* nothing */
# define STACK_UNPAD_ZERO /* nothing */
/* SETARG usage is order-dependent on 32-bit. we could avoid that
* by having STACK_PAD allocate the stack space and do a mov here.
*/
# define SETARG(argoffs, argreg, p) \
push p
# endif /* !MACOS */
#endif /* 64/32-bit */
/* CALLC* are for C calling convention callees only.
* Caller must ensure that if params are passed in regs there are no conflicts.
* Caller can rely on us storing each parameter in reverse order.
* For x64, caller must arrange for 16-byte alignment at end of arg setup.
*/
#define CALLC0(callee) \
STACK_PAD_ZERO @N@\
call callee @N@\
STACK_UNPAD_ZERO
#define CALLC1(callee, p1) \
STACK_PAD_LE4(1, 1) @N@\
SETARG(0, ARG1, p1) @N@\
call callee @N@\
STACK_UNPAD_LE4(1, 1)
#define CALLC2(callee, p1, p2) \
STACK_PAD_LE4(2, 2) @N@\
SETARG(1, ARG2, p2) @N@\
SETARG(0, ARG1, p1) @N@\
call callee @N@\
STACK_UNPAD_LE4(2, 2)
#define CALLC3(callee, p1, p2, p3) \
STACK_PAD_LE4(3, 3) @N@\
SETARG(2, ARG3, p3) @N@\
SETARG(1, ARG2, p2) @N@\
SETARG(0, ARG1, p1) @N@\
call callee @N@\
STACK_UNPAD_LE4(3, 3)
#define CALLC4(callee, p1, p2, p3, p4) \
STACK_PAD_LE4(4, 4) @N@\
SETARG(3, ARG4, p4) @N@\
SETARG(2, ARG3, p3) @N@\
SETARG(1, ARG2, p2) @N@\
SETARG(0, ARG1, p1) @N@\
call callee @N@\
STACK_UNPAD_LE4(4, 4)
#define CALLC5(callee, p1, p2, p3, p4, p5) \
STACK_PAD(5, 1, 1) @N@\
SETARG(4, ARG5_NORETADDR, p5) @N@\
SETARG(3, ARG4, p4) @N@\
SETARG(2, ARG3, p3) @N@\
SETARG(1, ARG2, p2) @N@\
SETARG(0, ARG1, p1) @N@\
call callee @N@\
STACK_UNPAD(5, 1, 1)
#define CALLC6(callee, p1, p2, p3, p4, p5, p6)\
STACK_PAD(6, 2, 2) @N@\
SETARG(5, ARG6_NORETADDR, p6) @N@\
SETARG(4, ARG5_NORETADDR, p5) @N@\
SETARG(3, ARG4, p4) @N@\
SETARG(2, ARG3, p3) @N@\
SETARG(1, ARG2, p2) @N@\
SETARG(0, ARG1, p1) @N@\
call callee @N@\
STACK_UNPAD(6, 2, 2)
#define CALLC7(callee, p1, p2, p3, p4, p5, p6, p7)\
STACK_PAD(7, 3, 3) @N@\
SETARG(6, ARG7_NORETADDR, p7) @N@\
SETARG(5, ARG6_NORETADDR, p6) @N@\
SETARG(4, ARG5_NORETADDR, p5) @N@\
SETARG(3, ARG4, p4) @N@\
SETARG(2, ARG3, p3) @N@\
SETARG(1, ARG2, p2) @N@\
SETARG(0, ARG1, p1) @N@\
call callee @N@\
STACK_UNPAD(7, 3, 3)
/* Versions to help with Mac stack aligmnment. _FRESH means that the
* stack has not been changed since function entry and thus for Mac 32-bit
* esp ends in 0xc. We simply add 1 to the # args the pad code should assume,
* resulting in correct alignment when combined with the retaddr.
*/
#define CALLC1_FRESH(callee, p1) \
STACK_PAD_LE4(1, 2) @N@\
SETARG(0, ARG1, p1) @N@\
call callee @N@\
STACK_UNPAD_LE4(1, 2)
#define CALLC2_FRESH(callee, p1, p2) \
STACK_PAD_LE4(2, 3) @N@\
SETARG(1, ARG2, p2) @N@\
SETARG(0, ARG1, p1) @N@\
call callee @N@\
STACK_UNPAD_LE4(2, 3)
/* For stdcall callees */
#ifdef X64
# define CALLWIN0 CALLC0
# define CALLWIN1 CALLC1
# define CALLWIN2 CALLC2
#else
# define CALLWIN0(callee) \
STACK_PAD_ZERO @N@\
call callee
# define CALLWIN1(callee, p1) \
STACK_PAD_LE4(1, 1) @N@\
SETARG(0, ARG1, p1) @N@\
call callee
# define CALLWIN2(callee, p1, p2) \
STACK_PAD_LE4(2, 2) @N@\
SETARG(1, ARG2, p2) @N@\
SETARG(0, ARG1, p1) @N@\
call callee
#endif
#ifdef X86
# define JUMP jmp
#elif defined(ARM)
# define JUMP b
#endif /* X86/ARM */
#endif /* _ASM_DEFINES_ASM_ */