1changecom(`/*', `*/')dnl 2/* 3 * %CopyrightBegin% 4 * 5 * Copyright Ericsson AB 2004-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_AMD64_ASM_H 24#define HIPE_AMD64_ASM_H' 25 26dnl 27dnl Tunables. 28dnl 29define(LEAF_WORDS,24)dnl number of stack words for leaf functions 30define(NR_ARG_REGS,4)dnl admissible values are 0 to 6, inclusive 31define(HP_IN_REGISTER,1)dnl 1 to reserve a global register for HP 32define(FCALLS_IN_REGISTER,0)dnl 1 to reserve global register for FCALLS 33define(HEAP_LIMIT_IN_REGISTER,0)dnl global for HL 34define(SIMULATE_NSP,0)dnl change to 1 to simulate call/ret insns 35 36`#define AMD64_LEAF_WORDS 'LEAF_WORDS 37`#define LEAF_WORDS 'LEAF_WORDS 38`#define AMD64_NR_ARG_REGS 'NR_ARG_REGS 39`#define NR_ARG_REGS 'NR_ARG_REGS 40 41`#define AMD64_HP_IN_REGISTER 'HP_IN_REGISTER 42`#if AMD64_HP_IN_REGISTER' 43`#define AMD64_HEAP_POINTER 15' 44define(HP,%r15)dnl Only change this together with above 45`#endif' 46 47`#define AMD64_FCALLS_IN_REGISTER 'FCALLS_IN_REGISTER 48`#if AMD64_FCALLS_IN_REGISTER' 49`#define AMD64_FCALLS_REGISTER 11' 50define(FCALLS,%r11)dnl This goes together with line above 51`#endif' 52 53`#define AMD64_HEAP_LIMIT_IN_REGISTER 'HEAP_LIMIT_IN_REGISTER 54`#if AMD64_HEAP_LIMIT_IN_REGISTER' 55`#define AMD64_HEAP_LIMIT_REGISTER 12' 56define(HEAP_LIMIT,%r12)dnl Change this together with line above 57`#endif' 58 59`#define AMD64_SIMULATE_NSP 'SIMULATE_NSP 60 61 62`#ifdef ASM' 63/* 64 * Only assembler stuff from here on (when included from *.S) 65 */ 66 67/* 68 * Workarounds for Darwin. 69 */ 70ifelse(OPSYS,darwin,`` 71/* Darwin */ 72#define TEXT .text 73#define JOIN(X,Y) X##Y 74#define CSYM(NAME) JOIN(_,NAME) 75#define ASYM(NAME) CSYM(NAME) 76#define GLOBAL(NAME) .globl NAME 77#define SET_SIZE(NAME) /*empty*/ 78#define TYPE_FUNCTION(NAME) /*empty*/ 79'',`` 80/* Not Darwin */ 81#define TEXT .section ".text" 82#define CSYM(NAME) NAME 83#define ASYM(NAME) NAME 84#define GLOBAL(NAME) .global NAME 85#define SET_SIZE(NAME) .size NAME,.-NAME 86#define TYPE_FUNCTION(NAME) .type NAME,@function 87'')dnl 88 89 90/* 91 * Reserved registers. 92 */ 93`#define P %rbp' 94 95`#if AMD64_HP_IN_REGISTER 96#define SAVE_HP movq 'HP`, P_HP(P) 97#define RESTORE_HP movq P_HP(P), 'HP` 98#else 99#define SAVE_HP /*empty*/ 100#define RESTORE_HP /*empty*/ 101#endif' 102 103`#if AMD64_FCALLS_IN_REGISTER 104#define SAVE_FCALLS movq 'FCALLS`, P_FCALLS(P) 105#define RESTORE_FCALLS movq P_FCALLS(P), 'FCALLS` 106#else 107#define SAVE_FCALLS /*empty*/ 108#define RESTORE_FCALLS /*empty*/ 109#endif' 110 111`#if AMD64_HEAP_LIMIT_IN_REGISTER 112#define RESTORE_HEAP_LIMIT movq P_HP_LIMIT(P), 'HEAP_LIMIT` 113#else 114#define RESTORE_HEAP_LIMIT /*empty*/ 115#endif' 116 117define(NSP,%rsp)dnl 118`#define NSP 'NSP 119`#define SAVE_CSP movq %rsp, P_CSP(P) 120#define RESTORE_CSP movq P_CSP(P), %rsp' 121 122 123/* 124 * Debugging macros 125 * 126 * Keeps track of whether context has been saved in the debug build, allowing us 127 * to detect when the garbage collector is called when it shouldn't. 128 */ 129`#ifdef DEBUG 130# define SET_GC_UNSAFE \ 131 movq $1, P_GCUNSAFE(P) 132# define SET_GC_SAFE \ 133 movq $0, P_GCUNSAFE(P) 134#else 135# define SET_GC_UNSAFE 136# define SET_GC_SAFE 137#endif' 138 139/* 140 * Context switching macros. 141 */ 142`#define SWITCH_C_TO_ERLANG_QUICK \ 143 SAVE_CSP; \ 144 movq P_NSP(P), NSP' 145 146`#define SWITCH_ERLANG_TO_C_QUICK \ 147 movq NSP, P_NSP(P); \ 148 RESTORE_CSP' 149 150`#define SAVE_CACHED_STATE \ 151 SAVE_HP; \ 152 SAVE_FCALLS; \ 153 SET_GC_SAFE' 154 155`#define RESTORE_CACHED_STATE \ 156 RESTORE_HP; \ 157 RESTORE_HEAP_LIMIT; \ 158 RESTORE_FCALLS; \ 159 SET_GC_UNSAFE' 160 161`#define SWITCH_C_TO_ERLANG \ 162 RESTORE_CACHED_STATE; \ 163 SWITCH_C_TO_ERLANG_QUICK' 164 165`#define SWITCH_ERLANG_TO_C \ 166 SAVE_CACHED_STATE; \ 167 SWITCH_ERLANG_TO_C_QUICK' 168 169/* 170 * Argument (parameter) registers. 171 */ 172 173define(defarg,`define(ARG$1,`$2')dnl 174#`define ARG'$1 $2' 175)dnl 176 177ifelse(eval(NR_ARG_REGS >= 1),0,, 178`defarg(0,`%rsi')')dnl 179ifelse(eval(NR_ARG_REGS >= 2),0,, 180`defarg(1,`%rdx')')dnl 181ifelse(eval(NR_ARG_REGS >= 3),0,, 182`defarg(2,`%rcx')')dnl 183ifelse(eval(NR_ARG_REGS >= 4),0,, 184`defarg(3,`%r8')')dnl 185ifelse(eval(NR_ARG_REGS >= 5),0,, 186`defarg(4,`%r9')')dnl 187ifelse(eval(NR_ARG_REGS >= 6),0,, 188`defarg(5,`%rdi')')dnl 189 190/* 191 * TEMP_RV: 192 * Used in nbif_stack_trap_ra to preserve the return value. 193 * Must be a C callee-save register. 194 * Must be otherwise unused in the return path. 195 */ 196`#define TEMP_RV %rbx' 197 198dnl XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 199dnl X X 200dnl X hipe_amd64_glue.S support X 201dnl X X 202dnl XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 203 204dnl 205dnl LOAD_ARG_REGS 206dnl (identical to x86 version except for movq) 207dnl 208define(LAR_1,`movq P_ARG$1(P), ARG$1 ; ')dnl 209define(LAR_N,`ifelse(eval($1 >= 0),0,,`LAR_N(eval($1-1))LAR_1($1)')')dnl 210define(LOAD_ARG_REGS,`LAR_N(eval(NR_ARG_REGS-1))')dnl 211`#define LOAD_ARG_REGS 'LOAD_ARG_REGS 212 213dnl 214dnl STORE_ARG_REGS 215dnl (identical to x86 version except for movq) 216dnl 217define(SAR_1,`movq ARG$1, P_ARG$1(P) ; ')dnl 218define(SAR_N,`ifelse(eval($1 >= 0),0,,`SAR_N(eval($1-1))SAR_1($1)')')dnl 219define(STORE_ARG_REGS,`SAR_N(eval(NR_ARG_REGS-1))')dnl 220`#define STORE_ARG_REGS 'STORE_ARG_REGS 221 222dnl 223dnl NSP_CALL(FUN) 224dnl Emit a CALL FUN instruction, or simulate it. 225dnl FUN must not be an NSP-based memory operand. 226dnl 227ifelse(eval(SIMULATE_NSP),0, 228``#define NSP_CALL(FUN) call FUN'', 229``#define NSP_CALL(FUN) subq $8,NSP; leaq 1f(%rip),%rax; movq %rax,(NSP); jmp FUN; 1:'')dnl 230 231dnl 232dnl NSP_RETN(NPOP) 233dnl Emit a RET $NPOP instruction, or simulate it. 234dnl NPOP should be non-zero. 235dnl 236ifelse(eval(SIMULATE_NSP),0, 237``#define NSP_RETN(NPOP) ret $NPOP'', 238``#define NSP_RETN(NPOP) movq (NSP),TEMP_RV; addq $8+NPOP,NSP; jmp *TEMP_RV'')dnl 239 240dnl 241dnl NSP_RET0 242dnl Emit a RET instruction, or simulate it. 243dnl 244ifelse(eval(SIMULATE_NSP),0, 245``#define NSP_RET0 ret'', 246``#define NSP_RET0 movq (NSP),TEMP_RV; addq $8,NSP; jmp *TEMP_RV'')dnl 247 248dnl XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 249dnl X X 250dnl X hipe_amd64_bifs.m4 support X 251dnl X X 252dnl XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 253 254dnl 255dnl NBIF_ARG(DST,ARITY,ARGNO) 256dnl Access a formal parameter. 257dnl It will be a memory load via NSP when ARGNO >= NR_ARG_REGS. 258dnl It will be a register move when 0 <= ARGNO < NR_ARG_REGS; if 259dnl the source and destination are the same, the move is suppressed. 260dnl 261dnl This must be called before SWITCH_ERLANG_TO_C{,QUICK}. 262dnl This must not be called if the C BIF's arity > 6. 263dnl 264define(NBIF_MOVE_REG,`ifelse($1,$2,`# movq $2, $1',`movq $2, $1')')dnl 265define(NBIF_REG_ARG,`NBIF_MOVE_REG($1,ARG$2)')dnl 266define(NBIF_STK_LOAD,`movq $2(NSP), $1')dnl 267define(NBIF_STK_ARG,`NBIF_STK_LOAD($1,eval(8*($2-$3)))')dnl 268define(NBIF_ARG,`ifelse(eval($3 >= NR_ARG_REGS),0,`NBIF_REG_ARG($1,$3)',`NBIF_STK_ARG($1,$2,$3)')')dnl 269`/* #define NBIF_ARG_1_0 'NBIF_ARG(%rsi,1,0)` */' 270`/* #define NBIF_ARG_2_0 'NBIF_ARG(%rsi,2,0)` */' 271`/* #define NBIF_ARG_2_1 'NBIF_ARG(%rdx,2,1)` */' 272`/* #define NBIF_ARG_3_0 'NBIF_ARG(%rsi,3,0)` */' 273`/* #define NBIF_ARG_3_1 'NBIF_ARG(%rdx,3,1)` */' 274`/* #define NBIF_ARG_3_2 'NBIF_ARG(%rcx,3,2)` */' 275`/* #define NBIF_ARG_4_0 'NBIF_ARG(%rsi,4,0)` */' 276`/* #define NBIF_ARG_4_1 'NBIF_ARG(%rdx,4,1)` */' 277`/* #define NBIF_ARG_4_2 'NBIF_ARG(%rcx,4,2)` */' 278`/* #define NBIF_ARG_4_3 'NBIF_ARG(%r8,4,3)` */' 279`/* #define NBIF_ARG_5_0 'NBIF_ARG(%rsi,5,0)` */' 280`/* #define NBIF_ARG_5_1 'NBIF_ARG(%rdx,5,1)` */' 281`/* #define NBIF_ARG_5_2 'NBIF_ARG(%rcx,5,2)` */' 282`/* #define NBIF_ARG_5_3 'NBIF_ARG(%r8,5,3)` */' 283`/* #define NBIF_ARG_5_4 'NBIF_ARG(%r9,5,4)` */' 284 285dnl XXX: For >6 arity C BIFs, we need: 286dnl NBIF_COPY_NSP(ARITY) 287dnl SWITCH_ERLANG_TO_C 288dnl NBIF_GE6_ARG_MOVE(DSTREG,ARITY,ARGNO) 289dnl pushq NBIF_GE6_ARG_OPND(ARITY,ARGNO) <-- uses NSP copied above 290 291dnl 292dnl NBIF_RET(ARITY) 293dnl Generates a return from a native BIF, taking care to pop 294dnl any stacked formal parameters. 295dnl 296define(RET_POP,`ifelse(eval($1 > NR_ARG_REGS),0,0,eval(8*($1 - NR_ARG_REGS)))')dnl 297define(NBIF_RET_N,`ifelse(eval($1),0,`NSP_RET0',`NSP_RETN($1)')')dnl 298define(NBIF_RET,`NBIF_RET_N(eval(RET_POP($1)))')dnl 299`/* #define NBIF_RET_0 'NBIF_RET(0)` */' 300`/* #define NBIF_RET_1 'NBIF_RET(1)` */' 301`/* #define NBIF_RET_2 'NBIF_RET(2)` */' 302`/* #define NBIF_RET_3 'NBIF_RET(3)` */' 303`/* #define NBIF_RET_4 'NBIF_RET(4)` */' 304`/* #define NBIF_RET_5 'NBIF_RET(5)` */' 305 306`#endif /* ASM */' 307 308`#endif /* HIPE_AMD64_ASM_H */' 309