changecom(`/*', `*/')dnl /* * %CopyrightBegin% * * Copyright Ericsson AB 2002-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * %CopyrightEnd% */ `#ifndef HIPE_X86_ASM_H #define HIPE_X86_ASM_H' /* * Tunables. */ define(LEAF_WORDS,24)dnl number of stack words for leaf functions define(NR_ARG_REGS,3)dnl admissible values are 0 to 5, inclusive define(HP_IN_ESI,1)dnl change to 0 to not reserve a global register for HP define(SIMULATE_NSP,0)dnl change to 1 to simulate call/ret insns `#define X86_LEAF_WORDS 'LEAF_WORDS `#define LEAF_WORDS 'LEAF_WORDS /* * Workarounds for Darwin. */ ifelse(OPSYS,darwin,`` /* Darwin */ #define TEXT .text #define JOIN(X,Y) X##Y #define CSYM(NAME) JOIN(_,NAME) #define ASYM(NAME) CSYM(NAME) #define GLOBAL(NAME) .globl NAME #define SET_SIZE(NAME) /*empty*/ #define TYPE_FUNCTION(NAME) /*empty*/ '',`` /* Not Darwin */ #define TEXT .section ".text" #define CSYM(NAME) NAME #define ASYM(NAME) NAME #define GLOBAL(NAME) .global NAME #define SET_SIZE(NAME) .size NAME,.-NAME #define TYPE_FUNCTION(NAME) .type NAME,@function '')dnl /* * Reserved registers. */ `#define P %ebp' `#define X86_HP_IN_ESI 'HP_IN_ESI `#if X86_HP_IN_ESI #define SAVE_HP movl %esi, P_HP(P) #define RESTORE_HP movl P_HP(P), %esi #else #define SAVE_HP /*empty*/ #define RESTORE_HP /*empty*/ #endif' `#define NSP %esp #define SAVE_CSP movl %esp, P_CSP(P) #define RESTORE_CSP movl P_CSP(P), %esp' `#define X86_SIMULATE_NSP 'SIMULATE_NSP /* * Context switching macros. */ `#define SWITCH_C_TO_ERLANG_QUICK \ SAVE_CSP; \ movl P_NSP(P), NSP' `#define SWITCH_ERLANG_TO_C_QUICK \ movl NSP, P_NSP(P); \ RESTORE_CSP' `#define SAVE_CACHED_STATE \ SAVE_HP' `#define RESTORE_CACHED_STATE \ RESTORE_HP' `#define SWITCH_C_TO_ERLANG \ RESTORE_CACHED_STATE; \ SWITCH_C_TO_ERLANG_QUICK' `#define SWITCH_ERLANG_TO_C \ SAVE_CACHED_STATE; \ SWITCH_ERLANG_TO_C_QUICK' /* * Argument (parameter) registers. */ `#define X86_NR_ARG_REGS 'NR_ARG_REGS `#define NR_ARG_REGS 'NR_ARG_REGS ifelse(eval(NR_ARG_REGS >= 1),0,, ``#define ARG0 %eax '')dnl ifelse(eval(NR_ARG_REGS >= 2),0,, ``#define ARG1 %edx '')dnl ifelse(eval(NR_ARG_REGS >= 3),0,, ``#define ARG2 %ecx '')dnl ifelse(eval(NR_ARG_REGS >= 4),0,, ``#define ARG3 %ebx '')dnl ifelse(eval(NR_ARG_REGS >= 5),0,, ``#define ARG4 %edi '')dnl /* * TEMP_RV: * Used in nbif_stack_trap_ra to preserve the return value. * Must be a C callee-save register. * Must be otherwise unused in the return path. */ `#define TEMP_RV %ebx' /* * TEMP_NSP: * Used in BIF wrappers to permit copying stacked parameter from * the native stack to the C stack. * Set up by NBIF_COPY_NSP(arity) and used by NBIF_ARG(arity,argno). * TEMP_NSP may alias the last BIF argument register. * NBIF_COPY_NSP and NBIF_ARG currently fail if ARITY > NR_ARG_REGS! */ `#define TEMP_NSP %edi' dnl XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX dnl X X dnl X hipe_x86_glue.S support X dnl X X dnl XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX dnl dnl LOAD_ARG_REGS dnl define(LAR_1,`movl P_ARG$1(P), ARG$1 ; ')dnl define(LAR_N,`ifelse(eval($1 >= 0),0,,`LAR_N(eval($1-1))LAR_1($1)')')dnl define(LOAD_ARG_REGS,`LAR_N(eval(NR_ARG_REGS-1))')dnl `#define LOAD_ARG_REGS 'LOAD_ARG_REGS dnl dnl STORE_ARG_REGS dnl define(SAR_1,`movl ARG$1, P_ARG$1(P) ; ')dnl define(SAR_N,`ifelse(eval($1 >= 0),0,,`SAR_N(eval($1-1))SAR_1($1)')')dnl define(STORE_ARG_REGS,`SAR_N(eval(NR_ARG_REGS-1))')dnl `#define STORE_ARG_REGS 'STORE_ARG_REGS dnl dnl NSP_CALL(FUN) dnl Emit a CALL FUN instruction, or simulate it. dnl FUN must not be an NSP-based memory operand. dnl ifelse(eval(SIMULATE_NSP),0, ``#define NSP_CALL(FUN) call FUN'', ``#define NSP_CALL(FUN) subl $4,NSP; movl $1f,(NSP); jmp FUN; 1:'')dnl dnl dnl NSP_RETN(NPOP) dnl Emit a RET $NPOP instruction, or simulate it. dnl NPOP should be non-zero. dnl ifelse(eval(SIMULATE_NSP),0, ``#define NSP_RETN(NPOP) ret $NPOP'', ``#define NSP_RETN(NPOP) movl (NSP),TEMP_RV; addl $4+NPOP,NSP; jmp *TEMP_RV'')dnl dnl dnl NSP_RET0 dnl Emit a RET instruction, or simulate it. dnl ifelse(eval(SIMULATE_NSP),0, ``#define NSP_RET0 ret'', ``#define NSP_RET0 movl (NSP),TEMP_RV; addl $4,NSP; jmp *TEMP_RV'')dnl dnl XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX dnl X X dnl X hipe_x86_bifs.m4 support X dnl X X dnl XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX dnl dnl NBIF_COPY_NSP(ARITY) dnl if ARITY > NR_ARG_REGS then TEMP_NSP := %esp. dnl Allows the stacked formals to be referenced via TEMP_NSP after the stack switch. dnl define(NBIF_COPY_NSP,`ifelse(eval($1 > NR_ARG_REGS),0,,`movl %esp, TEMP_NSP')')dnl `/* #define NBIF_COPY_NSP_0 'NBIF_COPY_NSP(0)` */' `/* #define NBIF_COPY_NSP_1 'NBIF_COPY_NSP(1)` */' `/* #define NBIF_COPY_NSP_2 'NBIF_COPY_NSP(2)` */' `/* #define NBIF_COPY_NSP_3 'NBIF_COPY_NSP(3)` */' `/* #define NBIF_COPY_NSP_5 'NBIF_COPY_NSP(5)` */' dnl dnl BASE_OFFSET(N) dnl Generates a base-register offset operand for the value N. dnl When N is zero the offset becomes the empty string, as this dnl may allow the assembler to choose a more compat encoding. dnl define(BASE_OFFSET,`ifelse(eval($1),0,`',`$1')')dnl dnl dnl NBIF_ARG_OPND(ARITY,ARGNO) dnl Generates an operand for this formal parameter. dnl It will be a register operand when 0 <= ARGNO < NR_ARG_REGS. dnl It will be a memory operand via TEMP_NSP when ARGNO >= NR_ARG_REGS. dnl define(NBIF_ARG_OPND,`ifelse(eval($2 >= NR_ARG_REGS),0,`ARG'$2,BASE_OFFSET(eval(($1-NR_ARG_REGS)*4-($2-NR_ARG_REGS)*4))`(TEMP_NSP)')')dnl `/* #define NBIF_ARG_OPND_1_0 'NBIF_ARG_OPND(1,0)` */' `/* #define NBIF_ARG_OPND_2_0 'NBIF_ARG_OPND(2,0)` */' `/* #define NBIF_ARG_OPND_2_1 'NBIF_ARG_OPND(2,1)` */' `/* #define NBIF_ARG_OPND_3_0 'NBIF_ARG_OPND(3,0)` */' `/* #define NBIF_ARG_OPND_3_1 'NBIF_ARG_OPND(3,1)` */' `/* #define NBIF_ARG_OPND_3_2 'NBIF_ARG_OPND(3,2)` */' `/* #define NBIF_ARG_OPND_5_0 'NBIF_ARG_OPND(5,0)` */' `/* #define NBIF_ARG_OPND_5_1 'NBIF_ARG_OPND(5,1)` */' `/* #define NBIF_ARG_OPND_5_2 'NBIF_ARG_OPND(5,2)` */' `/* #define NBIF_ARG_OPND_5_3 'NBIF_ARG_OPND(5,3)` */' `/* #define NBIF_ARG_OPND_5_4 'NBIF_ARG_OPND(5,4)` */' dnl dnl NBIF_ARG_REG(CARGNO,REG) dnl Generates code to move REG to C argument number CARGNO. dnl define(NBIF_ARG_REG,`movl $2,BASE_OFFSET(eval(4*$1))(%esp)')dnl `/* #define NBIF_ARG_REG_0_P 'NBIF_ARG_REG(0,P)` */' dnl dnl NBIF_ARG(CARGNO,ARITY,ARGNO) dnl Generates code to move Erlang parameter number ARGNO dnl in a BIF of arity ARITY to C parameter number CARGNO. dnl dnl This must be called after NBIF_COPY_NSP(ARITY). dnl dnl NBIF_ARG(_,_,ARGNO2) must be called after NBIF_ARG(_,_,ARGNO1) dnl if ARGNO2 > ARGNO1. (ARG0 may be reused as a temporary register dnl for Erlang parameters passed on the stack.) dnl define(NBIF_ARG_MEM,`movl NBIF_ARG_OPND($2,$3),%eax; NBIF_ARG_REG($1,%eax)')dnl define(NBIF_ARG,`ifelse(eval($3 >= NR_ARG_REGS),0,`NBIF_ARG_REG($1,`ARG'$3)',`NBIF_ARG_MEM($1,$2,$3)')')dnl dnl dnl NBIF_RET(ARITY) dnl Generates a return from a native BIF, taking care to pop dnl any stacked formal parameters. dnl define(RET_POP,`ifelse(eval($1 > NR_ARG_REGS),0,0,eval(4*($1 - NR_ARG_REGS)))')dnl define(NBIF_RET_N,`ifelse(eval($1),0,`NSP_RET0',`NSP_RETN($1)')')dnl define(NBIF_RET,`NBIF_RET_N(eval(RET_POP($1)))')dnl `/* #define NBIF_RET_0 'NBIF_RET(0)` */' `/* #define NBIF_RET_1 'NBIF_RET(1)` */' `/* #define NBIF_RET_2 'NBIF_RET(2)` */' `/* #define NBIF_RET_3 'NBIF_RET(3)` */' `/* #define NBIF_RET_5 'NBIF_RET(5)` */' dnl dnl STORE_CALLER_SAVE dnl LOAD_CALLER_SAVE dnl Used to save and restore C caller-save argument registers around dnl calls to hipe_inc_nstack. The first 3 arguments registers are C dnl caller-save, remaining ones are C callee-save. dnl define(NBIF_MIN,`ifelse(eval($1 > $2),0,$1,$2)')dnl define(NR_CALLER_SAVE,NBIF_MIN(NR_ARG_REGS,3))dnl define(STORE_CALLER_SAVE,`SAR_N(eval(NR_CALLER_SAVE-1))')dnl define(LOAD_CALLER_SAVE,`LAR_N(eval(NR_CALLER_SAVE-1))')dnl `#define STORE_CALLER_SAVE 'STORE_CALLER_SAVE `#define LOAD_CALLER_SAVE 'LOAD_CALLER_SAVE `#endif /* HIPE_X86_ASM_H */'