;;;;;;;;;;;;;;;;;;;; ;; asm_funcs.nasm ;; ;;;;;;;;;;;;;;;;;;;; ;; GOAL Runtime assembly functions. These exist only in the x86 version of GOAL. SECTION .text ;; Call C++ code on linux, from GOAL, using Linux calling convention. global _arg_call_linux _arg_call_linux: pop rax push r10 push r11 sub rsp, 8 ; xmm stuff sub rsp, 128 movaps [rsp], xmm8 movaps [rsp + 16], xmm9 movaps [rsp + 32], xmm10 movaps [rsp + 48], xmm11 movaps [rsp + 64], xmm12 movaps [rsp + 80], xmm13 movaps [rsp + 96], xmm14 movaps [rsp + 112], xmm15 call rax movaps xmm8, [rsp] movaps xmm9, [rsp + 16] movaps xmm10, [rsp + 32] movaps xmm11, [rsp + 48] movaps xmm12, [rsp + 64] movaps xmm13, [rsp + 80] movaps xmm14, [rsp + 96] movaps xmm15, [rsp + 112] add rsp, 128 add rsp, 8 pop r11 pop r10 ret ;; Call C++ code on linux, from GOAL. Pug arguments on the stack and put a pointer to this array in the first arg. ;; this function pushes all 8 OpenGOAL registers into a stack array. ;; then it calls the function pointed to by rax with a pointer to this array. ;; it returns the return value of the called function. global _stack_call_linux _stack_call_linux: pop rax ; align stack sub rsp, 8 sub rsp, 128 movaps [rsp], xmm8 movaps [rsp + 16], xmm9 movaps [rsp + 32], xmm10 movaps [rsp + 48], xmm11 movaps [rsp + 64], xmm12 movaps [rsp + 80], xmm13 movaps [rsp + 96], xmm14 movaps [rsp + 112], xmm15 ; create stack array of arguments push r11 push r10 push r9 push r8 push rcx push rdx push rsi push rdi ; set first argument mov rdi, rsp ; call function call rax ; restore arguments (probably don't need to really do this...) pop rdi pop rsi pop rdx pop rcx pop r8 pop r9 pop r10 pop r11 movaps xmm8, [rsp] movaps xmm9, [rsp + 16] movaps xmm10, [rsp + 32] movaps xmm11, [rsp + 48] movaps xmm12, [rsp + 64] movaps xmm13, [rsp + 80] movaps xmm14, [rsp + 96] movaps xmm15, [rsp + 112] add rsp, 128 ; restore stack add rsp, 8 ; return! ret ;; Call c++ code through mips2c. ;; GOAL will call a dynamically generated trampoline. ;; The trampoline will have pushed the exec function and stack offset onto the stack global _mips2c_call_linux _mips2c_call_linux: ;; grab the address to call and put it in xmm0 sub rsp, 8 movaps xmm0, [rsp + 16] ;; grab the stack offset mov rax, [rsp + 8] ;; first, save xmms sub rsp, 128 movaps [rsp], xmm8 movaps [rsp + 16], xmm9 movaps [rsp + 32], xmm10 movaps [rsp + 48], xmm11 movaps [rsp + 64], xmm12 movaps [rsp + 80], xmm13 movaps [rsp + 96], xmm14 movaps [rsp + 112], xmm15 push r10 push r11 ;; oof sub rsp, 1280 mov [rsp + 64], rdi ;; arg0 mov [rsp + 80], rsi ;; arg1 mov [rsp + 96], rdx ;; arg2 mov [rsp + 112], rcx ;; arg3 mov [rsp + 128], r8 ;; arg4 mov [rsp + 144], r9 ;; arg5 mov [rsp + 160], r10 ;; arg6 mov [rsp + 176], r11 ;; arg7 mov [rsp + 352], r13 ;; s6 (pp) mov [rsp + 368], r14 ;; s7 (st) mov rdi, rsp sub rdi, r15 mov [rsp + 464], rdi ;; mip2c code's MIPS stack mov rdi, rsp sub rsp, rax ;; allocate space on the stack for GOAL fake stack push rax ;; and remember this so we can find our way back push rax movq rax, xmm0 call rax ;; call! ;; unallocate pop rax pop rax add rsp, rax mov rax, [rsp + 32] add rsp, 1280 pop r11 pop r10 movaps xmm8, [rsp] movaps xmm9, [rsp + 16] movaps xmm10, [rsp + 32] movaps xmm11, [rsp + 48] movaps xmm12, [rsp + 64] movaps xmm13, [rsp + 80] movaps xmm14, [rsp + 96] movaps xmm15, [rsp + 112] add rsp, 152 ;; 128 for xmm's + 16 for the stuff pushed by trampoline + 8 for stack alignment undo ret global _mips2c_call_windows _mips2c_call_windows: ;; grab the address to call and put it in xmm0 sub rsp, 8 movaps xmm0, [rsp + 16] ;; grab the stack offset mov rax, [rsp + 8] ;; first, save xmms sub rsp, 128 movaps [rsp], xmm8 movaps [rsp + 16], xmm9 movaps [rsp + 32], xmm10 movaps [rsp + 48], xmm11 movaps [rsp + 64], xmm12 movaps [rsp + 80], xmm13 movaps [rsp + 96], xmm14 movaps [rsp + 112], xmm15 push r10 push r11 ;; oof sub rsp, 1280 mov [rsp + 64], rdi ;; arg0 mov [rsp + 80], rsi ;; arg1 mov [rsp + 96], rdx ;; arg2 mov [rsp + 112], rcx ;; arg3 mov [rsp + 128], r8 ;; arg4 mov [rsp + 144], r9 ;; arg5 mov [rsp + 160], r10 ;; arg6 mov [rsp + 176], r11 ;; arg7 mov [rsp + 352], r13 ;; s6 (pp) mov [rsp + 368], r14 ;; s7 (st) mov rdi, rsp sub rdi, r15 mov [rsp + 464], rdi ;; mip2c code's MIPS stack mov rcx, rsp sub rsp, rax ;; allocate space on the stack for GOAL fake stack push rax ;; and remember this so we can find our way back push rax movq rax, xmm0 sub rsp, 32 call rax ;; call! add rsp, 32 ;; unallocate pop rax pop rax add rsp, rax mov rax, [rsp + 32] add rsp, 1280 pop r11 pop r10 movaps xmm8, [rsp] movaps xmm9, [rsp + 16] movaps xmm10, [rsp + 32] movaps xmm11, [rsp + 48] movaps xmm12, [rsp + 64] movaps xmm13, [rsp + 80] movaps xmm14, [rsp + 96] movaps xmm15, [rsp + 112] add rsp, 152 ;; 128 for xmm's + 16 for the stuff pushed by trampoline + 8 for stack alignment undo ret ;; Call C++ code on windows, from GOAL. Pug arguments on the stack and put a pointer to this array in the first arg. global _stack_call_win32 _stack_call_win32: pop rax ; to make sure the stack frame is aligned sub rsp, 8 sub rsp, 128 movaps [rsp], xmm8 movaps [rsp + 16], xmm9 movaps [rsp + 32], xmm10 movaps [rsp + 48], xmm11 movaps [rsp + 64], xmm12 movaps [rsp + 80], xmm13 movaps [rsp + 96], xmm14 movaps [rsp + 112], xmm15 ; push all registers and create the register array on the stack push r11 push r10 push r9 push r8 push rcx push rdx push rsi push rdi ; set the first argument register to the stack argument array mov rcx, rsp sub rsp, 32 ; call C function to do format, result will go in RAX call rax add rsp, 32 ; restore ; (note - this could probably just be add rsp 72, we don't care about the value of these register) pop rdi pop rsi pop rdx pop rcx pop r8 pop r9 pop r10 pop r11 movaps xmm8, [rsp] movaps xmm9, [rsp + 16] movaps xmm10, [rsp + 32] movaps xmm11, [rsp + 48] movaps xmm12, [rsp + 64] movaps xmm13, [rsp + 80] movaps xmm14, [rsp + 96] movaps xmm15, [rsp + 112] add rsp, 128 add rsp, 8 ret ;; The _call_goal_asm function is used to call a GOAL function from C. ;; It calls on the parent stack, which is a bad idea if your stack is not already a GOAL stack. ;; It supports up to 3 arguments and a return value. ;; This should be called with the arguments: ;; - first goal arg ;; - second goal arg ;; - third goal arg ;; - address of function to call ;; - address of the symbol table ;; - GOAL memory space offset global _call_goal_asm_linux _call_goal_asm_linux: ;; x86 saved registers we need to modify for GOAL should be saved push r13 push r14 push r15 ;; RDI - first arg ;; RSI - second arg ;; RDX - third arg ;; RCX - function pointer (goes in r13) ;; R8 - st (goes in r14) ;; R9 - off (goes in r15) ;; set GOAL function pointer mov r13, rcx ;; offset mov r14, r8 ;; symbol table mov r15, r9 ;; call GOAL by function pointer call r13 ;; retore x86 registers. pop r15 pop r14 pop r13 ret global _call_goal8_asm_linux _call_goal8_asm_linux: ;; x86 saved registers we need to modify for GOAL should be saved push r13 push r14 push r15 ;; RDI - first arg (func) ;; RSI - second arg (arg array) ;; RDX - third arg (0) ;; RCX - pp (goes in r13) ;; R8 - st (goes in r14) ;; R9 - off (goes in r15) ;; set GOAL function pointer mov r13, rcx ;; st mov r14, r8 ;; offset mov r15, r9 ;; move function to temp mov rax, rdi ;; extract arguments mov rdi, [rsi + 0] ;; 0 mov rdx, [rsi + 16] ;; 2 mov rcx, [rsi + 24] ;; 3 mov r8, [rsi + 32] ;; 4 mov r9, [rsi + 40] ;; 5 mov r10, [rsi + 48] ;; 6 mov r11, [rsi + 56] ;; 7 mov rsi, [rsi + 8] ;; 1 (do this last) ;; call GOAL by function pointer call rax ;; retore x86 registers. pop r15 pop r14 pop r13 ret ;; Call goal, but switch stacks. global _call_goal_on_stack_asm_linux _call_goal_on_stack_asm_linux: ;; RDI - stack pointer ;; RSI - unused ;; RDX - unused ;; RCX - function pointer (goes in r13) ;; R8 - st (goes in r14) ;; R9 - off (goes in r15) ;; x86 saved registers we need to modify for GOAL should be saved push r13 push r14 push r15 ;; stash current stack pointer in rsi mov rsi, rsp ;; switch to new stack mov rsp, rdi ;; back up old stack pointer push rsi ;; set GOAL function pointer mov r13, rcx ;; offset mov r14, r8 ;; symbol table mov r15, r9 ;; call GOAL by function pointer call r13 ;; get old stack pointer pop rsi mov rsp, rsi ;; retore x86 registers. pop r15 pop r14 pop r13 ret ;; The _call_goal_asm function is used to call a GOAL function from C. ;; It supports up to 3 arguments and a return value. ;; This should be called with the arguments: ;; - first goal arg ;; - second goal arg ;; - third goal arg ;; - address of function to call ;; - address of the symbol table ;; - GOAL memory space offset global _call_goal_asm_win32 _call_goal_asm_win32: push rdx ; 8 push rbx ; 16 push rbp ; 24 push rsi ; 32 push rdi ; 40 push r8 ; 48 push r9 ; 56 push r10 ; 64 push r11 ; 72 push r12 ; 80 push r13 ; 88 push r14 ; 96 push r15 ; 104 sub rsp, 16 movups [rsp], xmm6 sub rsp, 16 movups [rsp], xmm7 mov rdi, rcx ;; rdi is GOAL first argument, rcx is windows first argument mov rsi, rdx ;; rsi is GOAL second argument, rdx is windows second argument mov rdx, r8 ;; rdx is GOAL third argument, r8 is windows third argument mov r13, r9 ;; r13 is GOAL fp, r9 is windows fourth argument mov r15, [rsp + 184] ;; symbol table mov r14, [rsp + 176] ;; offset call r13 movups xmm7, [rsp] add rsp, 16 movups xmm6, [rsp] add rsp, 16 pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop r8 pop rdi pop rsi pop rbp pop rbx pop rdx ret global _call_goal8_asm_win32 _call_goal8_asm_win32: push rdx ; 8 push rbx ; 16 push rbp ; 24 push rsi ; 32 push rdi ; 40 push r8 ; 48 push r9 ; 56 push r10 ; 64 push r11 ; 72 push r12 ; 80 push r13 ; 88 push r14 ; 96 push r15 ; 104 sub rsp, 16 movups [rsp], xmm6 sub rsp, 16 movups [rsp], xmm7 ;; mov rdi, rcx ;; rdi is GOAL first argument, rcx is windows first argument ;; mov rsi, rdx ;; rsi is GOAL second argument, rdx is windows second argument ;; mov rdx, r8 ;; rdx is GOAL third argument, r8 is windows third argument ;; mov r13, r9 ;; r13 is GOAL fp, r9 is windows fourth argument ;; mov r15, [rsp + 184] ;; symbol table ;; mov r14, [rsp + 176] ;; offset ;; call r13 mov r13, r9 ;; pp mov r15, [rsp + 184] ;; symbol table mov r14, [rsp + 176] ;; offset mov rax, rcx ;; func temp mov rsi, rdx ;; arg table mov rdi, [rsi + 0] ;; 0 mov rdx, [rsi + 16] ;; 2 mov rcx, [rsi + 24] ;; 3 mov r8, [rsi + 32] ;; 4 mov r9, [rsi + 40] ;; 5 mov r10, [rsi + 48] ;; 6 mov r11, [rsi + 56] ;; 7 mov rsi, [rsi + 8] ;; 1 (do this last) ;; call GOAL by function pointer call rax movups xmm7, [rsp] add rsp, 16 movups xmm6, [rsp] add rsp, 16 pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop r8 pop rdi pop rsi pop rbp pop rbx pop rdx ret global _call_goal_on_stack_asm_win32 _call_goal_on_stack_asm_win32: ;; arg0 (rcx) stack ;; arg1 (rdx) fp ;; arg2 (r8) st ;; arg3 (r9) off push rdx ; 8 push rbx ; 16 push rbp ; 24 push rsi ; 32 push rdi ; 40 push r8 ; 48 push r9 ; 56 push r10 ; 64 push r11 ; 72 push r12 ; 80 push r13 ; 88 push r14 ; 96 push r15 ; 104 sub rsp, 160 movaps [rsp], xmm8 movaps [rsp + 16], xmm9 movaps [rsp + 32], xmm10 movaps [rsp + 48], xmm11 movaps [rsp + 64], xmm12 movaps [rsp + 80], xmm13 movaps [rsp + 96], xmm14 movaps [rsp + 112], xmm15 movaps [rsp + 128], xmm7 movaps [rsp + 144], xmm6 ;; stack swap mov rsi, rsp mov rsp, rcx push rsi mov r13, rdx ;; fp mov r14, r8 ;; st mov r15, r9 ;; offset call r13 ;; restore stack pop rsi mov rsp, rsi movaps xmm8, [rsp] movaps xmm9, [rsp + 16] movaps xmm10, [rsp + 32] movaps xmm11, [rsp + 48] movaps xmm12, [rsp + 64] movaps xmm13, [rsp + 80] movaps xmm14, [rsp + 96] movaps xmm15, [rsp + 112] movaps xmm7, [rsp + 128] movaps xmm6, [rsp + 144] add rsp, 160 pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop r8 pop rdi pop rsi pop rbp pop rbx pop rdx ret