1changecom(`/*', `*/')dnl 2/* 3 * %CopyrightBegin% 4 * 5 * Copyright Ericsson AB 2002-2016. All Rights Reserved. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 * %CopyrightEnd% 20 */ 21 22 23`#ifndef HIPE_X86_ASM_H 24#define HIPE_X86_ASM_H' 25 26/* 27 * Tunables. 28 */ 29define(LEAF_WORDS,24)dnl number of stack words for leaf functions 30define(NR_ARG_REGS,3)dnl admissible values are 0 to 5, inclusive 31define(HP_IN_ESI,1)dnl change to 0 to not reserve a global register for HP 32define(SIMULATE_NSP,0)dnl change to 1 to simulate call/ret insns 33 34`#define X86_LEAF_WORDS 'LEAF_WORDS 35`#define LEAF_WORDS 'LEAF_WORDS 36 37`#define X86_NR_ARG_REGS 'NR_ARG_REGS 38`#define NR_ARG_REGS 'NR_ARG_REGS 39 40`#define X86_HP_IN_ESI 'HP_IN_ESI 41`#define X86_SIMULATE_NSP 'SIMULATE_NSP 42 43 44`#ifdef ASM' 45/* 46 * Only assembler stuff from here on (when included from *.S) 47 */ 48 49/* 50 * Workarounds for Darwin. 51 */ 52ifelse(OPSYS,darwin,`` 53/* Darwin */ 54#define TEXT .text 55#define JOIN(X,Y) X##Y 56#define CSYM(NAME) JOIN(_,NAME) 57#define ASYM(NAME) CSYM(NAME) 58#define GLOBAL(NAME) .globl NAME 59#define SET_SIZE(NAME) /*empty*/ 60#define TYPE_FUNCTION(NAME) /*empty*/ 61'',`` 62/* Not Darwin */ 63#define TEXT .section ".text" 64#define CSYM(NAME) NAME 65#define ASYM(NAME) NAME 66#define GLOBAL(NAME) .global NAME 67#define SET_SIZE(NAME) .size NAME,.-NAME 68#define TYPE_FUNCTION(NAME) .type NAME,@function 69'')dnl 70 71/* 72 * Reserved registers. 73 */ 74`#define P %ebp' 75 76`#if X86_HP_IN_ESI 77#define SAVE_HP movl %esi, P_HP(P) 78#define RESTORE_HP movl P_HP(P), %esi 79#else 80#define SAVE_HP /*empty*/ 81#define RESTORE_HP /*empty*/ 82#endif' 83 84`#define NSP %esp 85#define SAVE_CSP movl %esp, P_CSP(P) 86#define RESTORE_CSP movl P_CSP(P), %esp' 87 88 89/* 90 * Context switching macros. 91 */ 92`#define SWITCH_C_TO_ERLANG_QUICK \ 93 SAVE_CSP; \ 94 movl P_NSP(P), NSP' 95 96`#define SWITCH_ERLANG_TO_C_QUICK \ 97 movl NSP, P_NSP(P); \ 98 RESTORE_CSP' 99 100`#define SAVE_CACHED_STATE \ 101 SAVE_HP' 102 103`#define RESTORE_CACHED_STATE \ 104 RESTORE_HP' 105 106`#define SWITCH_C_TO_ERLANG \ 107 RESTORE_CACHED_STATE; \ 108 SWITCH_C_TO_ERLANG_QUICK' 109 110`#define SWITCH_ERLANG_TO_C \ 111 SAVE_CACHED_STATE; \ 112 SWITCH_ERLANG_TO_C_QUICK' 113 114 115/* 116 * Argument (parameter) registers. 117 */ 118ifelse(eval(NR_ARG_REGS >= 1),0,, 119``#define ARG0 %eax 120'')dnl 121ifelse(eval(NR_ARG_REGS >= 2),0,, 122``#define ARG1 %edx 123'')dnl 124ifelse(eval(NR_ARG_REGS >= 3),0,, 125``#define ARG2 %ecx 126'')dnl 127ifelse(eval(NR_ARG_REGS >= 4),0,, 128``#define ARG3 %ebx 129'')dnl 130ifelse(eval(NR_ARG_REGS >= 5),0,, 131``#define ARG4 %edi 132'')dnl 133 134/* 135 * TEMP_RV: 136 * Used in nbif_stack_trap_ra to preserve the return value. 137 * Must be a C callee-save register. 138 * Must be otherwise unused in the return path. 139 */ 140`#define TEMP_RV %ebx' 141 142/* 143 * TEMP_NSP: 144 * Used in BIF wrappers to permit copying stacked parameter from 145 * the native stack to the C stack. 146 * Set up by NBIF_COPY_NSP(arity) and used by NBIF_ARG(arity,argno). 147 * TEMP_NSP may alias the last BIF argument register. 148 * NBIF_COPY_NSP and NBIF_ARG currently fail if ARITY > NR_ARG_REGS! 149 */ 150`#define TEMP_NSP %edi' 151 152dnl XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 153dnl X X 154dnl X hipe_x86_glue.S support X 155dnl X X 156dnl XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 157 158dnl 159dnl LOAD_ARG_REGS 160dnl 161define(LAR_1,`movl P_ARG$1(P), ARG$1 ; ')dnl 162define(LAR_N,`ifelse(eval($1 >= 0),0,,`LAR_N(eval($1-1))LAR_1($1)')')dnl 163define(LOAD_ARG_REGS,`LAR_N(eval(NR_ARG_REGS-1))')dnl 164`#define LOAD_ARG_REGS 'LOAD_ARG_REGS 165 166dnl 167dnl STORE_ARG_REGS 168dnl 169define(SAR_1,`movl ARG$1, P_ARG$1(P) ; ')dnl 170define(SAR_N,`ifelse(eval($1 >= 0),0,,`SAR_N(eval($1-1))SAR_1($1)')')dnl 171define(STORE_ARG_REGS,`SAR_N(eval(NR_ARG_REGS-1))')dnl 172`#define STORE_ARG_REGS 'STORE_ARG_REGS 173 174dnl 175dnl NSP_CALL(FUN) 176dnl Emit a CALL FUN instruction, or simulate it. 177dnl FUN must not be an NSP-based memory operand. 178dnl 179ifelse(eval(SIMULATE_NSP),0, 180``#define NSP_CALL(FUN) call FUN'', 181``#define NSP_CALL(FUN) subl $4,NSP; movl $1f,(NSP); jmp FUN; 1:'')dnl 182 183dnl 184dnl NSP_RETN(NPOP) 185dnl Emit a RET $NPOP instruction, or simulate it. 186dnl NPOP should be non-zero. 187dnl 188ifelse(eval(SIMULATE_NSP),0, 189``#define NSP_RETN(NPOP) ret $NPOP'', 190``#define NSP_RETN(NPOP) movl (NSP),TEMP_RV; addl $4+NPOP,NSP; jmp *TEMP_RV'')dnl 191 192dnl 193dnl NSP_RET0 194dnl Emit a RET instruction, or simulate it. 195dnl 196ifelse(eval(SIMULATE_NSP),0, 197``#define NSP_RET0 ret'', 198``#define NSP_RET0 movl (NSP),TEMP_RV; addl $4,NSP; jmp *TEMP_RV'')dnl 199 200dnl XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 201dnl X X 202dnl X hipe_x86_bifs.m4 support X 203dnl X X 204dnl XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 205 206dnl 207dnl NBIF_COPY_NSP(ARITY) 208dnl if ARITY > NR_ARG_REGS then TEMP_NSP := %esp. 209dnl Allows the stacked formals to be referenced via TEMP_NSP after the stack switch. 210dnl 211define(NBIF_COPY_NSP,`ifelse(eval($1 > NR_ARG_REGS),0,,`movl %esp, TEMP_NSP')')dnl 212`/* #define NBIF_COPY_NSP_0 'NBIF_COPY_NSP(0)` */' 213`/* #define NBIF_COPY_NSP_1 'NBIF_COPY_NSP(1)` */' 214`/* #define NBIF_COPY_NSP_2 'NBIF_COPY_NSP(2)` */' 215`/* #define NBIF_COPY_NSP_3 'NBIF_COPY_NSP(3)` */' 216`/* #define NBIF_COPY_NSP_4 'NBIF_COPY_NSP(4)` */' 217`/* #define NBIF_COPY_NSP_5 'NBIF_COPY_NSP(5)` */' 218 219dnl 220dnl BASE_OFFSET(N) 221dnl Generates a base-register offset operand for the value N. 222dnl When N is zero the offset becomes the empty string, as this 223dnl may allow the assembler to choose a more compat encoding. 224dnl 225define(BASE_OFFSET,`ifelse(eval($1),0,`',`$1')')dnl 226 227dnl 228dnl NBIF_ARG_OPND(ARITY,ARGNO) 229dnl Generates an operand for this formal parameter. 230dnl It will be a register operand when 0 <= ARGNO < NR_ARG_REGS. 231dnl It will be a memory operand via TEMP_NSP when ARGNO >= NR_ARG_REGS. 232dnl 233define(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 234`/* #define NBIF_ARG_OPND_1_0 'NBIF_ARG_OPND(1,0)` */' 235`/* #define NBIF_ARG_OPND_2_0 'NBIF_ARG_OPND(2,0)` */' 236`/* #define NBIF_ARG_OPND_2_1 'NBIF_ARG_OPND(2,1)` */' 237`/* #define NBIF_ARG_OPND_3_0 'NBIF_ARG_OPND(3,0)` */' 238`/* #define NBIF_ARG_OPND_3_1 'NBIF_ARG_OPND(3,1)` */' 239`/* #define NBIF_ARG_OPND_3_2 'NBIF_ARG_OPND(3,2)` */' 240`/* #define NBIF_ARG_OPND_4_0 'NBIF_ARG_OPND(4,0)` */' 241`/* #define NBIF_ARG_OPND_4_1 'NBIF_ARG_OPND(4,1)` */' 242`/* #define NBIF_ARG_OPND_4_2 'NBIF_ARG_OPND(4,2)` */' 243`/* #define NBIF_ARG_OPND_4_3 'NBIF_ARG_OPND(4,3)` */' 244`/* #define NBIF_ARG_OPND_5_0 'NBIF_ARG_OPND(5,0)` */' 245`/* #define NBIF_ARG_OPND_5_1 'NBIF_ARG_OPND(5,1)` */' 246`/* #define NBIF_ARG_OPND_5_2 'NBIF_ARG_OPND(5,2)` */' 247`/* #define NBIF_ARG_OPND_5_3 'NBIF_ARG_OPND(5,3)` */' 248`/* #define NBIF_ARG_OPND_5_4 'NBIF_ARG_OPND(5,4)` */' 249 250dnl 251dnl NBIF_ARG_REG(CARGNO,REG) 252dnl Generates code to move REG to C argument number CARGNO. 253dnl 254define(NBIF_ARG_REG,`movl $2,BASE_OFFSET(eval(4*$1))(%esp)')dnl 255`/* #define NBIF_ARG_REG_0_P 'NBIF_ARG_REG(0,P)` */' 256 257dnl 258dnl NBIF_ARG(CARGNO,ARITY,ARGNO) 259dnl Generates code to move Erlang parameter number ARGNO 260dnl in a BIF of arity ARITY to C parameter number CARGNO. 261dnl 262dnl This must be called after NBIF_COPY_NSP(ARITY). 263dnl 264dnl NBIF_ARG(_,_,ARGNO2) must be called after NBIF_ARG(_,_,ARGNO1) 265dnl if ARGNO2 > ARGNO1. (ARG0 may be reused as a temporary register 266dnl for Erlang parameters passed on the stack.) 267dnl 268define(NBIF_ARG_MEM,`movl NBIF_ARG_OPND($2,$3),%eax; NBIF_ARG_REG($1,%eax)')dnl 269define(NBIF_ARG,`ifelse(eval($3 >= NR_ARG_REGS),0,`NBIF_ARG_REG($1,`ARG'$3)',`NBIF_ARG_MEM($1,$2,$3)')')dnl 270 271dnl 272dnl NBIF_RET(ARITY) 273dnl Generates a return from a native BIF, taking care to pop 274dnl any stacked formal parameters. 275dnl 276define(RET_POP,`ifelse(eval($1 > NR_ARG_REGS),0,0,eval(4*($1 - NR_ARG_REGS)))')dnl 277define(NBIF_RET_N,`ifelse(eval($1),0,`NSP_RET0',`NSP_RETN($1)')')dnl 278define(NBIF_RET,`NBIF_RET_N(eval(RET_POP($1)))')dnl 279`/* #define NBIF_RET_0 'NBIF_RET(0)` */' 280`/* #define NBIF_RET_1 'NBIF_RET(1)` */' 281`/* #define NBIF_RET_2 'NBIF_RET(2)` */' 282`/* #define NBIF_RET_3 'NBIF_RET(3)` */' 283`/* #define NBIF_RET_4 'NBIF_RET(4)` */' 284`/* #define NBIF_RET_5 'NBIF_RET(5)` */' 285 286dnl 287dnl STORE_CALLER_SAVE 288dnl LOAD_CALLER_SAVE 289dnl Used to save and restore C caller-save argument registers around 290dnl calls to hipe_inc_nstack. The first 3 arguments registers are C 291dnl caller-save, remaining ones are C callee-save. 292dnl 293define(NBIF_MIN,`ifelse(eval($1 > $2),0,$1,$2)')dnl 294define(NR_CALLER_SAVE,NBIF_MIN(NR_ARG_REGS,3))dnl 295define(STORE_CALLER_SAVE,`SAR_N(eval(NR_CALLER_SAVE-1))')dnl 296define(LOAD_CALLER_SAVE,`LAR_N(eval(NR_CALLER_SAVE-1))')dnl 297`#define STORE_CALLER_SAVE 'STORE_CALLER_SAVE 298`#define LOAD_CALLER_SAVE 'LOAD_CALLER_SAVE 299 300`#endif /* ASM */' 301 302`#endif /* HIPE_X86_ASM_H */' 303