| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- ;
- ; AngelCode Scripting Library
- ; Copyright (c) 2003-2011 Andreas Jonsson
- ;
- ; This software is provided 'as-is', without any express or implied
- ; warranty. In no event will the authors be held liable for any
- ; damages arising from the use of this software.
- ;
- ; Permission is granted to anyone to use this software for any
- ; purpose, including commercial applications, and to alter it and
- ; redistribute it freely, subject to the following restrictions:
- ;
- ; 1. The origin of this software must not be misrepresented; you
- ; must not claim that you wrote the original software. If you use
- ; this software in a product, an acknowledgment in the product
- ; documentation would be appreciated but is not required.
- ;
- ; 2. Altered source versions must be plainly marked as such, and
- ; must not be misrepresented as being the original software.
- ;
- ; 3. This notice may not be removed or altered from any source
- ; distribution.
- ;
- ; The original version of this library can be located at:
- ; http://www.angelcode.com/angelscript/
- ;
- ; Andreas Jonsson
- ; [email protected]
- ;
- .code
- PUBLIC CallX64
- ; asQWORD CallX64(const asQWORD *args, const asQWORD *floatArgs, int paramSize, asQWORD func)
- CallX64 PROC FRAME
- ; PROLOG
- ; We must save preserved registers that are used
- ; TODO: No need to save unused registers
- push rbp
- .pushreg rbp
- push rsi
- .pushreg rsi
- push r11
- .pushreg r11
- push rdi
- .pushreg rdi
- push r12
- .pushreg r12
- push r13
- .pushreg r13
- push r14
- .pushreg r14
- push r15
- .pushreg r15
- push rbx
- .pushreg rbx
- sub rsp, 050h
- .allocstack 050h
- mov rbp, rsp
- .setframe rbp, 0
- .endprolog
- ; Move function param to non-scratch register
- mov r14, r9 ; r14 = function
- ; Allocate space on the stack for the arguments
- ; Make room for at least 4 arguments even if there are less. When
- ; the compiler does optimizations for speed it may use these for
- ; temporary storage.
- mov rdi, r8
- add rdi, 32
- ; Make sure the stack pointer is 16byte aligned so the
- ; whole program optimizations will work properly
- ; TODO: optimize: Can this be optimized with fewer instructions?
- mov rsi, rsp
- sub rsi, rdi
- and rsi, 8h
- add rdi, rsi
- sub rsp, rdi
-
- ; Jump straight to calling the function if no parameters
- cmp r8d, 0 ; Compare paramSize with 0
- je callfunc ; Jump to call funtion if (paramSize == 0)
- ; Move params to non-scratch registers
- mov rsi, rcx ; rsi = pArgs
- mov r11, rdx ; r11 = pFloatArgs (can be NULL)
- mov r12d, r8d ; r12 = paramSize
-
- ; Copy arguments from script stack to application stack
- ; Order is (first to last):
- ; rcx, rdx, r8, r9 & everything else goes on stack
- mov rcx, qword ptr [rsi]
- mov rdx, qword ptr [rsi + 8]
- mov r8, qword ptr [rsi + 16]
- mov r9, qword ptr [rsi + 24]
-
- ; Negate the 4 params from the size to be copied
- sub r12d, 32
- js copyfloat ; Jump if negative result
- jz copyfloat ; Jump if zero result
-
- ; Now copy all remaining params onto stack allowing space for first four
- ; params to be flushed back to the stack if required by the callee.
-
- add rsi, 32 ; Position input pointer 4 args ahead
- mov r13, rsp ; Put the stack pointer into r13
- add r13, 32 ; Leave space for first 4 args on stack
- copyoverflow:
- mov r15, qword ptr [rsi] ; Read param from source stack into r15
- mov qword ptr [r13], r15 ; Copy param to real stack
- add r13, 8 ; Move virtual stack pointer
- add rsi, 8 ; Move source stack pointer
- sub r12d, 8 ; Decrement remaining count
- jnz copyoverflow ; Continue if more params
- copyfloat:
- ; Any floating point params?
- cmp r11, 0
- je callfunc
-
- movlpd xmm0, qword ptr [r11]
- movlpd xmm1, qword ptr [r11 + 8]
- movlpd xmm2, qword ptr [r11 + 16]
- movlpd xmm3, qword ptr [r11 + 24]
-
- callfunc:
-
- ; Call function
- call r14
-
- ; Restore the stack
- mov rsp, rbp
-
- ; EPILOG: Restore stack & preserved registers
- add rsp, 050h
- pop rbx
- pop r15
- pop r14
- pop r13
- pop r12
- pop rdi
- pop r11
- pop rsi
- pop rbp
- ; return value in RAX
- ret
- CallX64 ENDP
- PUBLIC GetReturnedFloat
- ; asDWORD GetReturnedFloat()
- GetReturnedFloat PROC FRAME
- ; PROLOG: Store registers and allocate stack space
-
- sub rsp, 8 ; We'll need 4 bytes for temporary storage (8 bytes with alignment)
- .allocstack 8
- .endprolog
- ; Move the float value from the XMM0 register to RAX register
- movss dword ptr [rsp], xmm0
- mov eax, dword ptr [rsp]
-
- ; EPILOG: Clean up
-
- add rsp, 8
- ret
- GetReturnedFloat ENDP
- PUBLIC GetReturnedDouble
- ; asDWORD GetReturnedDouble()
- GetReturnedDouble PROC FRAME
- ; PROLOG: Store registers and allocate stack space
-
- sub rsp, 8 ; We'll need 8 bytes for temporary storage
- .allocstack 8
- .endprolog
- ; Move the double value from the XMM0 register to the RAX register
- movlpd qword ptr [rsp], xmm0
- mov rax, qword ptr [rsp]
-
- ; EPILOG: Clean up
-
- add rsp, 8
-
- ret
-
- GetReturnedDouble ENDP
- END
|