sourcemod/sourcepawn/jit/x86/code-stubs-x86.cpp
2015-02-24 02:03:58 -08:00

136 lines
3.2 KiB
C++

// 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 <sp_vm_api.h>
#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<uint8_t *>(invoke_stub_) + error.offset();
timeout_stub_ = reinterpret_cast<uint8_t *>(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);
}