1/* 2 3 Package: dyncall 4 Library: dyncallback 5 File: dyncallback/dyncall_callback_x64.S 6 Description: Callback Thunk entry for x64 (portasm version) 7 License: 8 9 Copyright (c) 2011-2018 Daniel Adler <dadler@uni-goettingen.de> 10 11 Permission to use, copy, modify, and distribute this software for any 12 purpose with or without fee is hereby granted, provided that the above 13 copyright notice and this permission notice appear in all copies. 14 15 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 16 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 23*/ 24 25 26 27#include "../portasm/portasm-x64.S" 28 29/* structure sizes */ 30 31SET(DCThunk_size,24) 32SET(DCArgs_size_win64,80) 33SET(DCArgs_size_sysv,128) 34SET(DCValue_size,8) 35 36/* frame local variable offsets relative to %rbp*/ 37 38SET(FRAME_arg0_win64,48) 39SET(FRAME_arg0_sysv,16) 40SET(FRAME_return,8) 41SET(FRAME_parent,0) 42SET(FRAME_DCArgs_sysv,-128) 43SET(FRAME_DCValue_sysv,-136) 44SET(FRAME_DCArgs_win64,-80) 45SET(FRAME_DCValue_win64,-80) 46 47/* struct DCCallback */ 48 49SET(CTX_thunk,0) 50SET(CTX_handler,24) 51SET(CTX_userdata,32) 52SET(DCCallback_size,40) 53 54 55 56GLOBAL(dcCallback_x64_sysv) 57BEGIN_PROC(dcCallback_x64_sysv) 58 59 PUSH(RBP) 60 MOV(RSP,RBP) 61 62 /* initialize DCArgs */ 63 64 /* float parameters (8 registers spill to DCArgs) */ 65 66 SUB(LIT(8*8),RSP) 67 68 MOVSD(XMM7, QWORD(RSP,8*7)) /* struct offset 120: float parameter 7 */ 69 MOVSD(XMM6, QWORD(RSP,8*6)) /* struct offset 112: float parameter 6 */ 70 MOVSD(XMM5, QWORD(RSP,8*5)) /* struct offset 104: float parameter 5 */ 71 MOVSD(XMM4, QWORD(RSP,8*4)) /* struct offset 96: float parameter 4 */ 72 MOVSD(XMM3, QWORD(RSP,8*3)) /* struct offset 88: float parameter 3 */ 73 MOVSD(XMM2, QWORD(RSP,8*2)) /* struct offset 80: float parameter 2 */ 74 MOVSD(XMM1, QWORD(RSP,8*1)) /* struct offset 72: float parameter 1 */ 75 MOVSD(XMM0, QWORD(RSP,8*0)) /* struct offset 64: float parameter 0 */ 76 77 /* integer parameters (6 registers spill to DCArgs) */ 78 79 PUSH(R9) /* struct offset 56: parameter 5 */ 80 PUSH(R8) /* struct offset 48: parameter 4 */ 81 PUSH(RCX) /* struct offset 40: parameter 3 */ 82 PUSH(RDX) /* struct offset 32: parameter 2 */ 83 PUSH(RSI) /* struct offset 24: parameter 1 */ 84 PUSH(RDI) /* struct offset 16: parameter 0 */ 85 86 /* register counts for integer/pointer and float regs */ 87 88 PUSH(LIT(0)) /* struct offset 12: fcount */ 89 /* struct offset 8: icount */ 90 91 LEA(QWORD(RBP,FRAME_arg0_sysv),RDX) /* struct offset 0: stack pointer */ 92 PUSH(RDX) 93 94 MOV(RSP,RSI) /* arg 1 RSI : DCArgs* */ 95 96 /* initialize DCValue */ 97 98 PUSH(LIT(0)) /* struct offset 0: return value (max long long) */ 99 100 /* call handler( *ctx, *args, *value, *userdata) */ 101 102 MOV(RAX,RDI) /* arg 0 RDI : DCCallback* (RAX) */ 103 MOV(QWORD(RDI,CTX_userdata),RCX) /* arg 3 RCX : userdata* */ 104 MOV(RSP,RDX) /* arg 2 RDX : DCValue* */ 105 PUSH(LIT(0)) /* align to 16 bytes */ 106 CALL_REG(QWORD(RAX,CTX_handler)) 107 108 /* pass return type via registers, handle ints and floats */ 109 110 MOV(QWORD(RBP,FRAME_DCValue_sysv),RAX) 111 MOVD(RAX,XMM0) 112 113 MOV(RBP,RSP) 114 POP(RBP) 115 RET() 116 117END_PROC(dcCallback_x64_sysv) 118 119GLOBAL(dcCallback_x64_win64) 120BEGIN_PROC(dcCallback_x64_win64) 121 122 PUSH(RBP) 123 MOV(RSP,RBP) 124 125 /* initialize DCArgs */ 126 127 /* float parameters (4 registers spill to DCArgs) */ 128 129 SUB(LIT(4*8),RSP) 130 131 MOVSD(XMM3, QWORD(RSP,8*3)) /* struct offset 72: float parameter 3 */ 132 MOVSD(XMM2, QWORD(RSP,8*2)) /* struct offset 64: float parameter 2 */ 133 MOVSD(XMM1, QWORD(RSP,8*1)) /* struct offset 56: float parameter 1 */ 134 MOVSD(XMM0, QWORD(RSP,8*0)) /* struct offset 48: float parameter 0 */ 135 136 /* integer parameters (4 registers spill to DCArgs) */ 137 138 PUSH(R9) /* struct offset 40: parameter 3 */ 139 PUSH(R8) /* struct offset 32: parameter 2 */ 140 PUSH(RDX) /* struct offset 24: parameter 1 */ 141 PUSH(RCX) /* struct offset 16: parameter 0 */ 142 143 /* register counts for integer/pointer and float regs */ 144 145 PUSH(LIT(0)) /* struct offset 12: fcount */ 146 /* struct offset 8: icount */ 147 148 LEA(QWORD(RBP,FRAME_arg0_win64),RDX) /* struct offset 0: stack pointer */ 149 PUSH(RDX) 150 151 MOV(RSP,RDX) /* arg 1 RDX : DCArgs* */ 152 153 /* initialize DCValue */ 154 155 // PUSHQ(LIT(0)) /* struct offset 0: return value (max long long) */ 156 157 /* call handler( *ctx, *args, *value, *userdata) */ 158 159 MOV(RAX,RCX) /* arg 0 RCX : DCCallback* (RAX) */ 160 MOV(QWORD(RAX,CTX_userdata),R9) /* arg 3 R9 : userdata* */ 161 MOV(RSP,R8) /* arg 2 R8 : DCValue* */ 162 SUB(LIT(4*8),RSP) /* make room for spill area and call */ 163 CALL_REG(QWORD(RAX,CTX_handler)) 164 165 /* pass return type via registers, handle ints and floats */ 166 167 MOV(QWORD(RBP,FRAME_DCValue_win64),RAX) 168 MOVD(RAX,XMM0) 169 170 MOV(RBP,RSP) 171 POP(RBP) 172 RET() 173 174END_PROC(dcCallback_x64_win64) 175 176END_ASM 177 178