fix libretrobridge to be 64bit only (and fix it for 64bit)

This commit is contained in:
zeromus 2017-06-12 02:31:47 -05:00
parent 39433e509e
commit 0246c540bb
11 changed files with 178 additions and 560 deletions

View File

@ -33,7 +33,7 @@ namespace BizHawk.Emulation.Cores.Libretro
delegate void MessageApi(eMessage msg);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void BufferApi(BufId id, void* ptr, int size);
delegate void BufferApi(BufId id, void* ptr, ulong size); //size_t
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void SetVariableApi(string key, string value);
@ -106,7 +106,7 @@ namespace BizHawk.Emulation.Cores.Libretro
public void CopyAscii(BufId id, string str)
{
fixed (char* cp = str)
_copyBuffer(id, cp, str.Length + 1);
_copyBuffer(id, cp, (ulong)str.Length + 1);
}
/// <summary>
@ -115,7 +115,7 @@ namespace BizHawk.Emulation.Cores.Libretro
public void CopyBytes(BufId id, byte[] bytes)
{
fixed (byte* bp = bytes)
_copyBuffer(id, bp, bytes.Length);
_copyBuffer(id, bp, (ulong)bytes.Length);
}
/// <summary>
@ -129,7 +129,7 @@ namespace BizHawk.Emulation.Cores.Libretro
{
fixed (byte* bp = bytes)
{
_setBuffer(id, bp, bytes.Length);
_setBuffer(id, bp, (ulong)bytes.Length);
andThen();
}
}
@ -141,7 +141,7 @@ namespace BizHawk.Emulation.Cores.Libretro
{
fixed (byte* cp = System.Text.Encoding.ASCII.GetBytes(str+"\0"))
{
_setBuffer(id, cp, str.Length + 1);
_setBuffer(id, cp, (ulong)str.Length + 1);
andThen();
}
}
@ -150,7 +150,7 @@ namespace BizHawk.Emulation.Cores.Libretro
{
public retro_system_info retro_system_info;
public retro_system_av_info retro_system_av_info;
public uint retro_serialize_size; //size_t :(
public ulong retro_serialize_size; //size_t actually
public uint retro_region;
public uint retro_api_version;
public retro_pixel_format pixel_format; //default is 0 -- RETRO_PIXEL_FORMAT_0RGB1555
@ -196,8 +196,8 @@ namespace BizHawk.Emulation.Cores.Libretro
public CommStructEnv env;
//this should always be used in pairs
public fixed uint buf[(int)BufId.BufId_Num]; //ACTUALLY A POINTER but can't marshal it :(
public fixed int buf_size[(int)BufId.BufId_Num];
public fixed ulong buf[(int)BufId.BufId_Num]; //actually a pointer, but can't marshal IntPtr, so dumb
public fixed ulong buf_size[(int)BufId.BufId_Num]; //actually a size_t
//utilities
public bool GetBoolValue() { return value != 0; } //should this be here or by the other helpers? I dont know

View File

@ -6,11 +6,11 @@ namespace BizHawk.Emulation.Cores.Libretro
{
unsafe partial class LibretroApi
{
public Tuple<IntPtr, int> QUERY_GetMemory(RETRO_MEMORY mem)
public Tuple<IntPtr, ulong> QUERY_GetMemory(RETRO_MEMORY mem)
{
comm->value = (uint)mem;
Message(eMessage.QUERY_GetMemory);
return Tuple.Create(new IntPtr(comm->buf[(int)BufId.Param0]), comm->buf_size[(int)BufId.Param0]);
return Tuple.Create(new IntPtr((long)comm->buf[(int)BufId.Param0]), comm->buf_size[(int)BufId.Param0]);
}
}
}

View File

@ -32,7 +32,7 @@ namespace BizHawk.Emulation.Cores.Libretro
case eMessage.SIG_SampleBatch:
{
void* samples = (void*)comm->buf[(int)BufId.Param0];
core.retro_audio_sample_batch(samples, comm->buf_size[(int)BufId.Param0]/4);
core.retro_audio_sample_batch(samples, (int)comm->buf_size[(int)BufId.Param0]/4);
}
break;

View File

@ -316,7 +316,7 @@ namespace BizHawk.Emulation.Cores.Libretro
var mem = api.QUERY_GetMemory(LibretroApi.RETRO_MEMORY.SAVE_RAM);
var buf = new byte[mem.Item2];
Marshal.Copy(mem.Item1, buf, 0, mem.Item2);
Marshal.Copy(mem.Item1, buf, 0, (int)mem.Item2);
return buf;
}
@ -328,7 +328,7 @@ namespace BizHawk.Emulation.Cores.Libretro
if (mem.Item2 == 0)
return;
Marshal.Copy(data, 0, mem.Item1, mem.Item2);
Marshal.Copy(data, 0, mem.Item1, (int)mem.Item2);
}
public bool SaveRamModified

View File

@ -170,7 +170,7 @@ struct CommStruct
//always used in pairs
void* buf[BufId_Num];
s32 buf_size[BufId_Num];
size_t buf_size[BufId_Num];
//===========================================================
//private stuff
@ -185,7 +185,7 @@ struct CommStruct
size_t len = strlen(str);
CopyBuffer(id, (void*)str, len+1);
}
void CopyBuffer(int id, void* ptr, s32 size)
void CopyBuffer(int id, void* ptr, size_t size)
{
if (privbuf[id]) free(privbuf[id]);
buf[id] = privbuf[id] = malloc(size);
@ -193,7 +193,7 @@ struct CommStruct
buf_size[id] = size;
}
void SetBuffer(int id, void* ptr, s32 size)
void SetBuffer(int id, void* ptr, size_t size)
{
buf[id] = ptr;
buf_size[id] = size;

View File

@ -7,14 +7,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibretroBridge", "LibretroB
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AEACAA89-FDA2-40C6-910C-85AEB9726452}.Debug|x86.ActiveCfg = Debug|Win32
{AEACAA89-FDA2-40C6-910C-85AEB9726452}.Debug|x86.Build.0 = Debug|Win32
{AEACAA89-FDA2-40C6-910C-85AEB9726452}.Release|x86.ActiveCfg = Release|Win32
{AEACAA89-FDA2-40C6-910C-85AEB9726452}.Release|x86.Build.0 = Release|Win32
{AEACAA89-FDA2-40C6-910C-85AEB9726452}.Debug|x64.ActiveCfg = Debug|x64
{AEACAA89-FDA2-40C6-910C-85AEB9726452}.Debug|x64.Build.0 = Debug|x64
{AEACAA89-FDA2-40C6-910C-85AEB9726452}.Release|x64.ActiveCfg = Release|x64
{AEACAA89-FDA2-40C6-910C-85AEB9726452}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,14 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
@ -19,14 +11,26 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="features_cpu.c" />
<ClCompile Include="libco\sjlj-multi.c" />
<ClCompile Include="LibretroBridge.cpp" />
<ClCompile Include="features_cpu.c">
<EnableEnhancedInstructionSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</EnableEnhancedInstructionSet>
</ClCompile>
<ClCompile Include="libco\amd64.c">
<EnableEnhancedInstructionSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotSet</EnableEnhancedInstructionSet>
<EnableEnhancedInstructionSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotSet</EnableEnhancedInstructionSet>
</ClCompile>
<ClCompile Include="LibretroBridge.cpp">
<EnableEnhancedInstructionSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotSet</EnableEnhancedInstructionSet>
<EnableEnhancedInstructionSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotSet</EnableEnhancedInstructionSet>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="libco\libco.h" />
<ClInclude Include="libretro.h" />
</ItemGroup>
<ItemGroup>
<MASM Include="libco\coswap.asm" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{AEACAA89-FDA2-40C6-910C-85AEB9726452}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
@ -34,20 +38,6 @@
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
@ -64,15 +54,10 @@
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
@ -80,44 +65,16 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>..\..\output\dll\</OutDir>
<IntDir>.obj\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>..\..\output\dll\</OutDir>
<IntDir>.obj\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>..\..\output\dll\</OutDir>
<IntDir>.obj\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>..\..\output\dll\</OutDir>
<IntDir>.obj\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBRETRO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
<WholeProgramOptimization>false</WholeProgramOptimization>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
@ -136,27 +93,6 @@
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>false</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBRETRO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalOptions>/pdbaltpath:%_PDB% %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
@ -180,6 +116,7 @@
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
</ImportGroup>
<ProjectExtensions>
<VisualStudio>

View File

@ -1,104 +1,82 @@
/*
libco.amd64 (2009-10-12)
author: byuu
license: public domain
*/
#define LIBCO_C
#include "libco.h"
#include <assert.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
static thread_local long long co_active_buffer[64];
static thread_local cothread_t co_active_handle = 0;
static void (*co_swap)(cothread_t, cothread_t) = 0;
#ifdef _WIN32
//ABI: Win64
static unsigned char co_swap_function[] = {
0x48, 0x89, 0x22, 0x48, 0x8B, 0x21, 0x58, 0x48, 0x89, 0x6A, 0x08, 0x48, 0x89, 0x72, 0x10, 0x48,
0x89, 0x7A, 0x18, 0x48, 0x89, 0x5A, 0x20, 0x4C, 0x89, 0x62, 0x28, 0x4C, 0x89, 0x6A, 0x30, 0x4C,
0x89, 0x72, 0x38, 0x4C, 0x89, 0x7A, 0x40, 0x48, 0x81, 0xC2, 0x80, 0x00, 0x00, 0x00, 0x48, 0x83,
0xE2, 0xF0, 0x0F, 0x29, 0x32, 0x0F, 0x29, 0x7A, 0x10, 0x44, 0x0F, 0x29, 0x42, 0x20, 0x44, 0x0F,
0x29, 0x4A, 0x30, 0x44, 0x0F, 0x29, 0x52, 0x40, 0x44, 0x0F, 0x29, 0x5A, 0x50, 0x44, 0x0F, 0x29,
0x62, 0x60, 0x44, 0x0F, 0x29, 0x6A, 0x70, 0x44, 0x0F, 0x29, 0xB2, 0x80, 0x00, 0x00, 0x00, 0x44,
0x0F, 0x29, 0xBA, 0x90, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x69, 0x08, 0x48, 0x8B, 0x71, 0x10, 0x48,
0x8B, 0x79, 0x18, 0x48, 0x8B, 0x59, 0x20, 0x4C, 0x8B, 0x61, 0x28, 0x4C, 0x8B, 0x69, 0x30, 0x4C,
0x8B, 0x71, 0x38, 0x4C, 0x8B, 0x79, 0x40, 0x48, 0x81, 0xC1, 0x80, 0x00, 0x00, 0x00, 0x48, 0x83,
0xE1, 0xF0, 0x0F, 0x29, 0x31, 0x0F, 0x29, 0x79, 0x10, 0x44, 0x0F, 0x29, 0x41, 0x20, 0x44, 0x0F,
0x29, 0x49, 0x30, 0x44, 0x0F, 0x29, 0x51, 0x40, 0x44, 0x0F, 0x29, 0x59, 0x50, 0x44, 0x0F, 0x29,
0x61, 0x60, 0x44, 0x0F, 0x29, 0x69, 0x70, 0x44, 0x0F, 0x29, 0xB1, 0x80, 0x00, 0x00, 0x00, 0x44,
0x0F, 0x29, 0xB9, 0x90, 0x00, 0x00, 0x00, 0xFF, 0xE0,
};
#include <windows.h>
void co_init() {
DWORD old_privileges;
VirtualProtect(co_swap_function, sizeof co_swap_function, PAGE_EXECUTE_READWRITE, &old_privileges);
}
#else
//ABI: SystemV
static unsigned char co_swap_function[] = {
0x48, 0x89, 0x26, 0x48, 0x8B, 0x27, 0x58, 0x48, 0x89, 0x6E, 0x08, 0x48, 0x89, 0x5E, 0x10, 0x4C,
0x89, 0x66, 0x18, 0x4C, 0x89, 0x6E, 0x20, 0x4C, 0x89, 0x76, 0x28, 0x4C, 0x89, 0x7E, 0x30, 0x48,
0x8B, 0x6F, 0x08, 0x48, 0x8B, 0x5F, 0x10, 0x4C, 0x8B, 0x67, 0x18, 0x4C, 0x8B, 0x6F, 0x20, 0x4C,
0x8B, 0x77, 0x28, 0x4C, 0x8B, 0x7F, 0x30, 0xFF, 0xE0,
};
#include <unistd.h>
#include <sys/mman.h>
void co_init() {
unsigned long long addr = (unsigned long long)co_swap_function;
unsigned long long base = addr - (addr % sysconf(_SC_PAGESIZE));
unsigned long long size = (addr - base) + sizeof co_swap_function;
mprotect((void*)base, size, PROT_READ | PROT_WRITE | PROT_EXEC);
}
#endif
static void crash() {
assert(0); /* called only if cothread_t entrypoint returns */
}
cothread_t co_active() {
if(!co_active_handle) co_active_handle = &co_active_buffer;
return co_active_handle;
}
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
cothread_t handle;
if(!co_swap) {
co_init();
co_swap = (void (*)(cothread_t, cothread_t))co_swap_function;
}
if(!co_active_handle) co_active_handle = &co_active_buffer;
size += 512; /* allocate additional space for storage */
size &= ~15; /* align stack to 16-byte boundary */
if(handle = (cothread_t)malloc(size)) {
long long *p = (long long*)((char*)handle + size); /* seek to top of stack */
*--p = (long long)crash; /* crash if entrypoint returns */
*--p = (long long)entrypoint; /* start of function */
*(long long*)handle = (long long)p; /* stack pointer */
}
return handle;
}
void co_delete(cothread_t handle) {
free(handle);
}
void co_switch(cothread_t handle) {
register cothread_t co_previous_handle = co_active_handle;
co_swap(co_active_handle = handle, co_previous_handle);
}
#ifdef __cplusplus
}
#endif
/*
libco.amd64 (2016-09-14)
author: byuu
license: public domain
*/
#define LIBCO_C
#include "libco.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
static long long co_active_buffer[64];
static cothread_t co_active_handle = 0;
static void* smalloc(size_t size)
{
char* ret = malloc(size + 16);
if (ret)
{
*(size_t*)ret = size;
return ret + 16;
}
return NULL;
}
static void sfree(void* ptr)
{
char* original = (char*)ptr - 16;
size_t size = *(size_t*)original + 16;
memset(original, 0, size);
free(original);
}
extern void co_swap(cothread_t, cothread_t);
static void crash() {
assert(0); /* called only if cothread_t entrypoint returns */
}
void co_clean() {
memset(co_active_buffer, 0, sizeof(co_active_buffer));
}
cothread_t co_active() {
if (!co_active_handle) co_active_handle = &co_active_buffer;
return co_active_handle;
}
cothread_t co_create(unsigned int size, void(*entrypoint)(void)) {
cothread_t handle;
if (!co_active_handle) co_active_handle = &co_active_buffer;
size += 512; /* allocate additional space for storage */
size &= ~15; /* align stack to 16-byte boundary */
if (handle = (cothread_t)smalloc(size)) {
long long *p = (long long*)((char*)handle + size); /* seek to top of stack */
*--p = (long long)crash; /* crash if entrypoint returns */
*--p = (long long)entrypoint; /* start of function */
*(long long*)handle = (long long)p; /* stack pointer */
}
return handle;
}
void co_delete(cothread_t handle) {
sfree(handle);
}
void co_switch(cothread_t handle) {
register cothread_t co_previous_handle = co_active_handle;
co_swap(co_active_handle = handle, co_previous_handle);
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,57 @@
_TEXT SEGMENT
PUBLIC co_swap
co_swap PROC
mov [rdx],rsp
mov rsp,[rcx]
pop rax
mov [rdx+ 8],rbp
mov [rdx+16],rsi
mov [rdx+24],rdi
mov [rdx+32],rbx
mov [rdx+40],r12
mov [rdx+48],r13
mov [rdx+56],r14
mov [rdx+64],r15
movaps [rdx+ 80],xmm6
movaps [rdx+ 96],xmm7
movaps [rdx+112],xmm8
add rdx,112
movaps [rdx+ 16],xmm9
movaps [rdx+ 32],xmm10
movaps [rdx+ 48],xmm11
movaps [rdx+ 64],xmm12
movaps [rdx+ 80],xmm13
movaps [rdx+ 96],xmm14
movaps [rdx+112],xmm15
mov rbp,[rcx+ 8]
mov rsi,[rcx+16]
mov rdi,[rcx+24]
mov rbx,[rcx+32]
mov r12,[rcx+40]
mov r13,[rcx+48]
mov r14,[rcx+56]
mov r15,[rcx+64]
movaps xmm6, [rcx+ 80]
movaps xmm7, [rcx+ 96]
movaps xmm8, [rcx+112]
add rcx,112
movaps xmm9, [rcx+ 16]
movaps xmm10,[rcx+ 32]
movaps xmm11,[rcx+ 48]
movaps xmm12,[rcx+ 64]
movaps xmm13,[rcx+ 80]
movaps xmm14,[rcx+ 96]
movaps xmm15,[rcx+112]
jmp rax
co_swap ENDP
_TEXT ENDS
END

View File

@ -1,237 +0,0 @@
/*
original author: Nach
license: public domain
additional work: zeromus
note: more ARM compilers are supported here (check the ifdefs in _JUMP_BUFFER)
and: work has been done to make this coexist more peaceably with .net
*/
#define LIBCO_C
#include "libco.h"
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
jmp_buf context;
coentry_t coentry;
void *stack;
unsigned long seh_frame, stack_top, stack_bottom;
cothread_t caller;
int ownstack;
} cothread_struct;
static thread_local cothread_struct _co_primary;
static thread_local cothread_struct *co_running = 0;
cothread_t co_primary() { return (cothread_t)&_co_primary; }
//-------------------
#ifdef _MSC_VER
//links of interest
//http://connect.microsoft.com/VisualStudio/feedback/details/100319/really-wierd-behaviour-in-crt-io-coupled-with-some-inline-assembly
//http://en.wikipedia.org/wiki/Thread_Information_Block
//http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/72093e46-4524-4f54-9f36-c7e8a309d1db/ //FS warning
#define WINVER 0x0400
#define _WIN32_WINNT 0x0400
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#pragma warning(disable:4733)
#pragma warning(disable:4311)
static void capture_fs(cothread_struct* rec)
{
int temp;
__asm mov eax, dword ptr fs:[0];
__asm mov temp, eax;
rec->seh_frame = temp;
__asm mov eax, dword ptr fs:[4];
__asm mov temp, eax;
rec->stack_top = temp;
__asm mov eax, dword ptr fs:[8];
__asm mov temp, eax;
rec->stack_bottom = temp;
}
static void restore_fs(cothread_struct* rec)
{
int temp;
temp = rec->seh_frame;
__asm mov eax, temp;
__asm mov dword ptr fs:[0], eax
temp = rec->stack_top;
__asm mov eax, temp;
__asm mov dword ptr fs:[4], eax
temp = rec->stack_bottom;
__asm mov eax, temp;
__asm mov dword ptr fs:[8], eax
}
static void os_co_wrapper()
{
cothread_struct* rec = (cothread_struct*)co_active();
__try
{
rec->coentry();
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
//unhandled win32 exception in coroutine.
//this coroutine will now be suspended permanently and control will be yielded to caller, for lack of anything better to do.
//perhaps the process should just terminate.
for(;;)
{
//dead coroutine
co_switch(rec->caller);
}
}
}
static void os_co_create(cothread_struct* rec, unsigned int size, coentry_t coentry)
{
_JUMP_BUFFER* jb = (_JUMP_BUFFER*)&rec->context;
cothread_struct temp;
jb->Esp = (unsigned long)rec->stack + size - 4;
jb->Eip = (unsigned long)os_co_wrapper;
rec->stack_top = jb->Esp + 4;
rec->stack_bottom = (unsigned long)rec->stack;
//wild assumption about SEH frame.. seems to work
capture_fs(&temp);
rec->seh_frame = temp.seh_frame;
}
static void os_pre_setjmp(cothread_t target)
{
cothread_struct* rec = (cothread_struct*)target;
capture_fs(co_running);
rec->caller = co_running;
}
static void os_pre_longjmp(cothread_struct* rec)
{
restore_fs(rec);
}
#elif defined(__ARM_EABI__) || defined(__ARMCC_VERSION)
//http://sourceware.org/cgi-bin/cvsweb.cgi/src/newlib/libc/machine/arm/setjmp.S?rev=1.5&content-type=text/x-cvsweb-markup&cvsroot=src
typedef struct
{
#ifdef LIBCO_ARM_JUMBLED
int r8,r9,r10,r11,lr,r4,r5,r6,r7,sp;
#else
int r4,r5,r6,r7,r8,r9,r10,fp;
#ifndef LIBCO_ARM_NOIP
int ip;
#endif
int sp,lr;
#endif
} _JUMP_BUFFER;
static void os_co_create(cothread_struct* rec, unsigned int size, coentry_t coentry)
{
_JUMP_BUFFER* jb = (_JUMP_BUFFER*)&rec->context;
jb->sp = (unsigned long)rec->stack + size - 4;
jb->lr = (unsigned long)coentry;
}
static void os_pre_setjmp(cothread_t target)
{
cothread_struct* rec = (cothread_struct*)target;
rec->caller = co_running;
}
static void os_pre_longjmp(cothread_struct* rec)
{
}
#else
#error "sjlj-multi: unsupported processor, compiler or operating system"
#endif
//-------------------
cothread_t co_active()
{
if(!co_running) co_running = &_co_primary;
return (cothread_t)co_running;
}
void* co_getstack(cothread_t cothread)
{
return ((cothread_struct*)cothread)->stack;
}
cothread_t co_create(unsigned int stacksize, coentry_t coentry)
{
cothread_struct* ret = (cothread_struct*)co_create_withstack(malloc(stacksize), stacksize, coentry);
if(ret)
ret->ownstack = 1;
return (cothread_t)ret;
}
cothread_t co_create_withstack(void* stack, int stacksize, coentry_t coentry)
{
cothread_struct *thread;
if(!co_running) co_running = &_co_primary;
thread = (cothread_struct*)malloc(sizeof(cothread_struct));
if(thread)
{
thread->coentry = coentry;
thread->stack = stack;
{
setjmp(thread->context);
os_co_create(thread,stacksize,coentry);
}
thread->ownstack = 0;
}
return (cothread_t)thread;
}
void co_delete(cothread_t cothread)
{
if(cothread)
{
cothread_struct* thread = (cothread_struct*)cothread;
if (thread->ownstack)
free(thread->stack);
free(cothread);
}
}
void co_switch(cothread_t cothread)
{
os_pre_setjmp(cothread);
if(!setjmp(co_running->context))
{
co_running = (cothread_struct*)cothread;
os_pre_longjmp(co_running);
longjmp(co_running->context,0);
}
}
#ifdef __cplusplus
}
#endif

View File

@ -1,117 +0,0 @@
/*
libco.x86 (2009-10-12)
author: byuu
license: public domain
*/
#define LIBCO_C
#include "libco.h"
#include <assert.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(_MSC_VER)
#define fastcall __fastcall
#elif defined(__GNUC__)
#define fastcall __attribute__((fastcall))
#else
#error "libco: please define fastcall macro"
#endif
static thread_local long co_active_buffer[64];
static thread_local cothread_t co_active_handle = 0;
static void (fastcall *co_swap)(cothread_t, cothread_t) = 0;
//ABI: fastcall
static unsigned char co_swap_function[] = {
0x89, 0x22, /* mov [edx],esp */
0x8b, 0x21, /* mov esp,[ecx] */
0x58, /* pop eax */
0x89, 0x6a, 0x04, /* mov [edx+0x04],ebp */
0x89, 0x72, 0x08, /* mov [edx+0x08],esi */
0x89, 0x7a, 0x0c, /* mov [edx+0x0c],edi */
0x89, 0x5a, 0x10, /* mov [edx+0x10],ebx */
0x8b, 0x69, 0x04, /* mov ebp,[ecx+0x04] */
0x8b, 0x71, 0x08, /* mov esi,[ecx+0x08] */
0x8b, 0x79, 0x0c, /* mov edi,[ecx+0x0c] */
0x8b, 0x59, 0x10, /* mov ebx,[ecx+0x10] */
0xff, 0xe0, /* jmp eax */
};
#ifdef _WIN32
#include <windows.h>
void co_init(void)
{
DWORD old_privileges;
VirtualProtect(co_swap_function,
sizeof co_swap_function, PAGE_EXECUTE_READWRITE, &old_privileges);
}
#else
#include <unistd.h>
#include <sys/mman.h>
void co_init(void)
{
unsigned long addr = (unsigned long)co_swap_function;
unsigned long base = addr - (addr % sysconf(_SC_PAGESIZE));
unsigned long size = (addr - base) + sizeof co_swap_function;
mprotect((void*)base, size, PROT_READ | PROT_WRITE | PROT_EXEC);
}
#endif
static void crash(void)
{
assert(0); /* called only if cothread_t entrypoint returns */
}
cothread_t co_active(void)
{
if(!co_active_handle)
co_active_handle = &co_active_buffer;
return co_active_handle;
}
cothread_t co_create(unsigned int size, void (*entrypoint)(void))
{
cothread_t handle;
if(!co_swap)
{
co_init();
co_swap = (void (fastcall*)(cothread_t, cothread_t))co_swap_function;
}
if(!co_active_handle)
co_active_handle = &co_active_buffer;
size += 256; /* allocate additional space for storage */
size &= ~15; /* align stack to 16-byte boundary */
if((handle = (cothread_t)malloc(size)))
{
long *p = (long*)((char*)handle + size); /* seek to top of stack */
*--p = (long)crash; /* crash if entrypoint returns */
*--p = (long)entrypoint; /* start of function */
*(long*)handle = (long)p; /* stack pointer */
}
return handle;
}
void co_delete(cothread_t handle)
{
free(handle);
}
void co_switch(cothread_t handle)
{
register cothread_t co_previous_handle = co_active_handle;
co_swap(co_active_handle = handle, co_previous_handle);
}
#ifdef __cplusplus
}
#endif