// vim: set sts=2 ts=8 sw=2 tw=99 et: // // Copyright (C) 2006-2015 AlliedModders LLC // // This file is part of SourcePawn. SourcePawn is free software: you can // redistribute it and/or modify it under the terms of the GNU General Public // License as published by the Free Software Foundation, either version 3 of // the License, or (at your option) any later version. // // You should have received a copy of the GNU General Public License along with // SourcePawn. If not, see http://www.gnu.org/licenses/. // #include #include "code-stubs.h" #include "x86-utils.h" #include "jit_shared.h" #include "jit_x86.h" using namespace sp; using namespace SourcePawn; #define __ masm. bool CodeStubs::InitializeFeatureDetection() { MacroAssemblerX86 masm; MacroAssemblerX86::GenerateFeatureDetection(masm); void *code = LinkCode(env_, masm); if (!code) return false; MacroAssemblerX86::RunFeatureDetection(code); return true; } bool CodeStubs::CompileInvokeStub() { AssemblerX86 masm; __ push(ebp); __ movl(ebp, esp); __ push(esi); // ebp - 4 __ push(edi); // ebp - 8 __ push(ebx); // ebp - 12 __ push(esp); // ebp - 16 __ movl(ebx, Operand(ebp, 8 + 4 * 0)); __ movl(eax, Operand(ebp, 8 + 4 * 1)); __ movl(ecx, Operand(ebp, 8 + 4 * 2)); // Set up run-time registers. __ movl(edi, Operand(ebx, offsetof(sp_context_t, sp))); __ addl(edi, eax); __ movl(esi, eax); __ movl(ebx, edi); // Align the stack. __ andl(esp, 0xfffffff0); // Call into plugin (align the stack first). __ call(ecx); // Get input context, store rval. __ movl(ecx, Operand(ebp, 8 + 4 * 0)); __ movl(Operand(ecx, offsetof(sp_context_t, rval)), pri); // Set no error. __ movl(eax, SP_ERROR_NONE); // Store latest stk. If we have an error code, we'll jump directly to here, // so eax will already be set. Label ret; __ bind(&ret); __ subl(stk, dat); __ movl(Operand(ecx, offsetof(sp_context_t, sp)), stk); // Restore stack. __ movl(esp, Operand(ebp, -16)); // Restore registers and gtfo. __ pop(ebx); __ pop(edi); __ pop(esi); __ pop(ebp); __ ret(); // The universal emergency return will jump to here. Label error; __ bind(&error); __ movl(ecx, Operand(ebp, 8 + 4 * 0)); // ret-path expects ecx = ctx __ jmp(&ret); Label timeout; __ bind(&timeout); __ movl(eax, SP_ERROR_TIMEOUT); __ jmp(&error); invoke_stub_ = LinkCode(env_, masm); if (!invoke_stub_) return false; return_stub_ = reinterpret_cast(invoke_stub_) + error.offset(); timeout_stub_ = reinterpret_cast(invoke_stub_) + timeout.offset(); return true; } SPVM_NATIVE_FUNC CodeStubs::CreateFakeNativeStub(SPVM_FAKENATIVE_FUNC callback, void *pData) { AssemblerX86 masm; __ push(ebx); __ push(edi); __ push(esi); __ movl(edi, Operand(esp, 16)); // store ctx __ movl(esi, Operand(esp, 20)); // store params __ movl(ebx, esp); __ andl(esp, 0xfffffff0); __ subl(esp, 4); __ push(intptr_t(pData)); __ push(esi); __ push(edi); __ call(ExternalAddress((void *)callback)); __ movl(esp, ebx); __ pop(esi); __ pop(edi); __ pop(ebx); __ ret(); return (SPVM_NATIVE_FUNC)LinkCode(env_, masm); }