Add some draft work for supporting sysv <-> msabi interop. I wonder if we'll ever use this? I'd put it on a separate branch but it would be merge hell.
This commit is contained in:
parent
d7423d45a0
commit
1292b27163
|
@ -73,7 +73,10 @@
|
|||
<Compile Include="BizInvoke\BizExvoker.cs" />
|
||||
<Compile Include="BizInvoke\BizInvoker.cs" />
|
||||
<Compile Include="BizInvoke\BizInvokeUtilities.cs" />
|
||||
<Compile Include="BizInvoke\CallingConventionAdapter.cs" />
|
||||
<Compile Include="BizInvoke\DynamicLibraryImportResolver.cs" />
|
||||
<Compile Include="BizInvoke\MemoryBlock.cs" />
|
||||
<Compile Include="BizInvoke\WaterboxUtils.cs" />
|
||||
<Compile Include="Buffer.cs" />
|
||||
<Compile Include="Colors.cs" />
|
||||
<Compile Include="CustomCollections.cs" />
|
||||
|
|
|
@ -87,13 +87,13 @@ namespace BizHawk.Common.BizInvoke
|
|||
|
||||
private readonly List<Delegate> Delegates = new List<Delegate>();
|
||||
|
||||
public ExvokerImpl(object o, DelegateStorage d)
|
||||
public ExvokerImpl(object o, DelegateStorage d, ICallingConventionAdapter a)
|
||||
{
|
||||
foreach (var sdt in d.DelegateTypes)
|
||||
{
|
||||
var del = Delegate.CreateDelegate(sdt.DelegateType, o, sdt.Method);
|
||||
Delegates.Add(del); // prevent garbage collection of the delegate, which would invalidate the pointer
|
||||
EntryPoints.Add(sdt.EntryPointName, Marshal.GetFunctionPointerForDelegate(del));
|
||||
EntryPoints.Add(sdt.EntryPointName, a.GetFunctionPointerForDelegate(del));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ namespace BizHawk.Common.BizInvoke
|
|||
static readonly Dictionary<Type, DelegateStorage> Impls = new Dictionary<Type, DelegateStorage>();
|
||||
|
||||
|
||||
public static IImportResolver GetExvoker(object o)
|
||||
public static IImportResolver GetExvoker(object o, ICallingConventionAdapter a)
|
||||
{
|
||||
DelegateStorage ds;
|
||||
lock (Impls)
|
||||
|
@ -121,7 +121,7 @@ namespace BizHawk.Common.BizInvoke
|
|||
}
|
||||
}
|
||||
|
||||
return new ExvokerImpl(o, ds);
|
||||
return new ExvokerImpl(o, ds, a);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,17 +17,18 @@ namespace BizHawk.Common.BizInvoke
|
|||
private class InvokerImpl
|
||||
{
|
||||
public Type ImplType;
|
||||
public List<Action<object, IImportResolver>> Hooks;
|
||||
public List<Action<object, IImportResolver, ICallingConventionAdapter>> Hooks;
|
||||
public Action<object, IMonitor> ConnectMonitor;
|
||||
public Action<object, ICallingConventionAdapter> ConnectCallingConventionAdapter;
|
||||
|
||||
public object Create(IImportResolver dll, IMonitor monitor)
|
||||
public object Create(IImportResolver dll, IMonitor monitor, ICallingConventionAdapter adapter)
|
||||
{
|
||||
var ret = Activator.CreateInstance(ImplType);
|
||||
ConnectCallingConventionAdapter(ret, adapter);
|
||||
foreach (var f in Hooks)
|
||||
{
|
||||
f(ret, dll);
|
||||
f(ret, dll, adapter);
|
||||
}
|
||||
|
||||
ConnectMonitor?.Invoke(ret, monitor);
|
||||
return ret;
|
||||
}
|
||||
|
@ -59,7 +60,7 @@ namespace BizHawk.Common.BizInvoke
|
|||
/// get an implementation proxy for an interop class
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The class type that represents the DLL</typeparam>
|
||||
public static T GetInvoker<T>(IImportResolver dll)
|
||||
public static T GetInvoker<T>(IImportResolver dll, ICallingConventionAdapter adapter)
|
||||
where T : class
|
||||
{
|
||||
InvokerImpl impl;
|
||||
|
@ -78,10 +79,10 @@ namespace BizHawk.Common.BizInvoke
|
|||
throw new InvalidOperationException("Class was previously proxied with a monitor!");
|
||||
}
|
||||
|
||||
return (T)impl.Create(dll, null);
|
||||
return (T)impl.Create(dll, null, adapter);
|
||||
}
|
||||
|
||||
public static T GetInvoker<T>(IImportResolver dll, IMonitor monitor)
|
||||
public static T GetInvoker<T>(IImportResolver dll, IMonitor monitor, ICallingConventionAdapter adapter)
|
||||
where T : class
|
||||
{
|
||||
InvokerImpl impl;
|
||||
|
@ -100,7 +101,7 @@ namespace BizHawk.Common.BizInvoke
|
|||
throw new InvalidOperationException("Class was previously proxied without a monitor!");
|
||||
}
|
||||
|
||||
return (T)impl.Create(dll, monitor);
|
||||
return (T)impl.Create(dll, monitor, adapter);
|
||||
}
|
||||
|
||||
private static InvokerImpl CreateProxy(Type baseType, bool monitor)
|
||||
|
@ -153,19 +154,21 @@ namespace BizHawk.Common.BizInvoke
|
|||
}
|
||||
|
||||
// hooks that will be run on the created proxy object
|
||||
var postCreateHooks = new List<Action<object, IImportResolver>>();
|
||||
var postCreateHooks = new List<Action<object, IImportResolver, ICallingConventionAdapter>>();
|
||||
|
||||
var type = ImplModuleBuilder.DefineType("Bizhawk.BizInvokeProxy" + baseType.Name, TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed, baseType);
|
||||
|
||||
var monitorField = monitor ? type.DefineField("MonitorField", typeof(IMonitor), FieldAttributes.Public) : null;
|
||||
|
||||
var adapterField = type.DefineField("CallingConvention", typeof(ICallingConventionAdapter), FieldAttributes.Public);
|
||||
|
||||
foreach (var mi in baseMethods)
|
||||
{
|
||||
var entryPointName = mi.Attr.EntryPoint ?? mi.Info.Name;
|
||||
|
||||
var hook = mi.Attr.Compatibility
|
||||
? ImplementMethodDelegate(type, mi.Info, mi.Attr.CallingConvention, entryPointName, monitorField)
|
||||
: ImplementMethodCalli(type, mi.Info, mi.Attr.CallingConvention, entryPointName, monitorField);
|
||||
: ImplementMethodCalli(type, mi.Info, mi.Attr.CallingConvention, entryPointName, monitorField, adapterField);
|
||||
|
||||
postCreateHooks.Add(hook);
|
||||
}
|
||||
|
@ -179,6 +182,7 @@ namespace BizHawk.Common.BizInvoke
|
|||
{
|
||||
ret.ConnectMonitor = (o, m) => o.GetType().GetField(monitorField.Name).SetValue(o, m);
|
||||
}
|
||||
ret.ConnectCallingConventionAdapter = (o, a) => o.GetType().GetField(adapterField.Name).SetValue(o, a);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -186,7 +190,8 @@ namespace BizHawk.Common.BizInvoke
|
|||
/// <summary>
|
||||
/// create a method implementation that uses GetDelegateForFunctionPointer internally
|
||||
/// </summary>
|
||||
private static Action<object, IImportResolver> ImplementMethodDelegate(TypeBuilder type, MethodInfo baseMethod, CallingConvention nativeCall, string entryPointName, FieldInfo monitorField)
|
||||
private static Action<object, IImportResolver, ICallingConventionAdapter> ImplementMethodDelegate(
|
||||
TypeBuilder type, MethodInfo baseMethod, CallingConvention nativeCall, string entryPointName, FieldInfo monitorField)
|
||||
{
|
||||
// create the delegate type
|
||||
MethodBuilder delegateInvoke;
|
||||
|
@ -196,6 +201,13 @@ namespace BizHawk.Common.BizInvoke
|
|||
var paramTypes = paramInfos.Select(p => p.ParameterType).ToArray();
|
||||
var returnType = baseMethod.ReturnType;
|
||||
|
||||
if (paramTypes.Concat(new[] { returnType }).Any(typeof(Delegate).IsAssignableFrom))
|
||||
{
|
||||
// this isn't a problem if CallingConventionAdapters.Waterbox is a no-op
|
||||
if (CallingConventionAdapters.Waterbox.GetType() != CallingConventionAdapters.Native.GetType())
|
||||
throw new InvalidOperationException("Compatibility call mode cannot use ICallingConventionAdapters!");
|
||||
}
|
||||
|
||||
// define a field on the class to hold the delegate
|
||||
var field = type.DefineField(
|
||||
"DelegateField" + baseMethod.Name,
|
||||
|
@ -255,10 +267,10 @@ namespace BizHawk.Common.BizInvoke
|
|||
|
||||
type.DefineMethodOverride(method, baseMethod);
|
||||
|
||||
return (o, dll) =>
|
||||
return (o, dll, adapter) =>
|
||||
{
|
||||
var entryPtr = dll.SafeResolve(entryPointName);
|
||||
var interopDelegate = Marshal.GetDelegateForFunctionPointer(entryPtr, delegateType.CreateType());
|
||||
var interopDelegate = adapter.GetDelegateForFunctionPointer(entryPtr, delegateType.CreateType());
|
||||
o.GetType().GetField(field.Name).SetValue(o, interopDelegate);
|
||||
};
|
||||
}
|
||||
|
@ -266,7 +278,9 @@ namespace BizHawk.Common.BizInvoke
|
|||
/// <summary>
|
||||
/// create a method implementation that uses calli internally
|
||||
/// </summary>
|
||||
private static Action<object, IImportResolver> ImplementMethodCalli(TypeBuilder type, MethodInfo baseMethod, CallingConvention nativeCall, string entryPointName, FieldInfo monitorField)
|
||||
private static Action<object, IImportResolver, ICallingConventionAdapter> ImplementMethodCalli(
|
||||
TypeBuilder type, MethodInfo baseMethod,
|
||||
CallingConvention nativeCall, string entryPointName, FieldInfo monitorField, FieldInfo adapterField)
|
||||
{
|
||||
var paramInfos = baseMethod.GetParameters();
|
||||
var paramTypes = paramInfos.Select(p => p.ParameterType).ToArray();
|
||||
|
@ -304,7 +318,7 @@ namespace BizHawk.Common.BizInvoke
|
|||
for (int i = 0; i < paramTypes.Length; i++)
|
||||
{
|
||||
// arg 0 is this, so + 1
|
||||
nativeParamTypes.Add(EmitParamterLoad(il, i + 1, paramTypes[i]));
|
||||
nativeParamTypes.Add(EmitParamterLoad(il, i + 1, paramTypes[i], adapterField));
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
|
@ -342,10 +356,11 @@ namespace BizHawk.Common.BizInvoke
|
|||
|
||||
type.DefineMethodOverride(method, baseMethod);
|
||||
|
||||
return (o, dll) =>
|
||||
return (o, dll, adapter) =>
|
||||
{
|
||||
var entryPtr = dll.SafeResolve(entryPointName);
|
||||
o.GetType().GetField(field.Name).SetValue(o, entryPtr);
|
||||
o.GetType().GetField(field.Name).SetValue(
|
||||
o, adapter.GetDepartureFunctionPointer(entryPtr, new ParameterInfo(returnType, paramTypes), o));
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -394,7 +409,7 @@ namespace BizHawk.Common.BizInvoke
|
|||
/// <summary>
|
||||
/// emit a single parameter load with unmanaged conversions
|
||||
/// </summary>
|
||||
private static Type EmitParamterLoad(ILGenerator il, int idx, Type type)
|
||||
private static Type EmitParamterLoad(ILGenerator il, int idx, Type type, FieldInfo adapterField)
|
||||
{
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
|
@ -460,13 +475,15 @@ namespace BizHawk.Common.BizInvoke
|
|||
|
||||
if (typeof(Delegate).IsAssignableFrom(type))
|
||||
{
|
||||
var mi = typeof(Marshal).GetMethod("GetFunctionPointerForDelegate", new[] { typeof(Delegate) });
|
||||
var mi = typeof(ICallingConventionAdapter).GetMethod("GetFunctionPointerForDelegate");
|
||||
var end = il.DefineLabel();
|
||||
var isNull = il.DefineLabel();
|
||||
|
||||
il.Emit(OpCodes.Ldarg, (short)idx);
|
||||
il.Emit(OpCodes.Brfalse, isNull);
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, adapterField);
|
||||
il.Emit(OpCodes.Ldarg, (short)idx);
|
||||
il.Emit(OpCodes.Call, mi);
|
||||
il.Emit(OpCodes.Br, end);
|
||||
|
|
|
@ -0,0 +1,248 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BizHawk.Common.BizInvoke
|
||||
{
|
||||
/// <summary>
|
||||
/// create interop delegates and function pointers for a particular calling convention
|
||||
/// </summary>
|
||||
public interface ICallingConventionAdapter
|
||||
{
|
||||
IntPtr GetFunctionPointerForDelegate(Delegate d);
|
||||
IntPtr GetArrivalFunctionPointer(IntPtr p, ParameterInfo pp, object lifetime);
|
||||
|
||||
Delegate GetDelegateForFunctionPointer(IntPtr p, Type delegateType);
|
||||
IntPtr GetDepartureFunctionPointer(IntPtr p, ParameterInfo pp, object lifetime);
|
||||
}
|
||||
|
||||
public static class CallingConventionAdapterExtensions
|
||||
{
|
||||
public static T GetDelegateForFunctionPointer<T>(this ICallingConventionAdapter a, IntPtr p)
|
||||
where T: class
|
||||
{
|
||||
return (T)(object)a.GetDelegateForFunctionPointer(p, typeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
public class ParameterInfo
|
||||
{
|
||||
public Type ReturnType { get; }
|
||||
public IReadOnlyList<Type> ParameterTypes { get; }
|
||||
|
||||
public ParameterInfo(Type returnType, IEnumerable<Type> parameterTypes)
|
||||
{
|
||||
ReturnType = returnType;
|
||||
ParameterTypes = parameterTypes.ToList().AsReadOnly();
|
||||
}
|
||||
|
||||
public ParameterInfo(Type delegateType)
|
||||
{
|
||||
if (!typeof(Delegate).IsAssignableFrom(delegateType))
|
||||
throw new InvalidOperationException("Must be a delegate type!");
|
||||
var invoke = delegateType.GetMethod("Invoke");
|
||||
ReturnType = invoke.ReturnType;
|
||||
ParameterTypes = invoke.GetParameters().Select(p => p.ParameterType).ToList().AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
public static class CallingConventionAdapters
|
||||
{
|
||||
private class NativeConvention : ICallingConventionAdapter
|
||||
{
|
||||
public IntPtr GetArrivalFunctionPointer(IntPtr p, ParameterInfo pp, object lifetime)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
public Delegate GetDelegateForFunctionPointer(IntPtr p, Type delegateType)
|
||||
{
|
||||
return Marshal.GetDelegateForFunctionPointer(p, delegateType);
|
||||
}
|
||||
|
||||
public IntPtr GetDepartureFunctionPointer(IntPtr p, ParameterInfo pp, object lifetime)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
public IntPtr GetFunctionPointerForDelegate(Delegate d)
|
||||
{
|
||||
return Marshal.GetFunctionPointerForDelegate(d);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// native (pass-through) calling convention
|
||||
/// </summary>
|
||||
public static ICallingConventionAdapter Native { get; } = new NativeConvention();
|
||||
|
||||
/// <summary>
|
||||
/// convention appropriate for waterbox guests
|
||||
/// </summary>
|
||||
public static ICallingConventionAdapter Waterbox { get; } =
|
||||
#if true
|
||||
new NativeConvention();
|
||||
#else
|
||||
new SysVHostMsGuest();
|
||||
#endif
|
||||
|
||||
private class SysVHostMsGuest : ICallingConventionAdapter
|
||||
{
|
||||
private const ulong Placeholder = 0xdeadbeeffeedface;
|
||||
private const byte Padding = 0x06;
|
||||
private const int BlockSize = 256;
|
||||
private static readonly byte[][] Depart =
|
||||
{
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x20, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x30, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x8b, 0x55, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x48, 0x89, 0xd1, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x30, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x40, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x40, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x89, 0x4d, 0xe0, 0x48, 0x8b, 0x7d, 0xe0, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf9, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x60, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x89, 0x4d, 0xe0, 0x4c, 0x89, 0x45, 0xd8, 0x48, 0x8b, 0x7d, 0xe0, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0x8b, 0x45, 0xd8, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf9, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x60, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x89, 0x4d, 0xe0, 0x4c, 0x89, 0x45, 0xd8, 0x4c, 0x89, 0x4d, 0xd0, 0x48, 0x8b, 0x7d, 0xe0, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0x8b, 0x45, 0xd0, 0x48, 0x89, 0x44, 0x24, 0x28, 0x48, 0x8b, 0x45, 0xd8, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf9, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
};
|
||||
private static readonly byte[][] Arrive =
|
||||
{
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x20, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x30, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x8b, 0x55, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x48, 0x89, 0xd1, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x30, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x40, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x40, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x89, 0x4d, 0xe0, 0x48, 0x8b, 0x7d, 0xe0, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf9, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x60, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x89, 0x4d, 0xe0, 0x4c, 0x89, 0x45, 0xd8, 0x48, 0x8b, 0x7d, 0xe0, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0x8b, 0x45, 0xd8, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf9, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x60, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x89, 0x4d, 0xe0, 0x4c, 0x89, 0x45, 0xd8, 0x4c, 0x89, 0x4d, 0xd0, 0x48, 0x8b, 0x7d, 0xe0, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0x8b, 0x45, 0xd0, 0x48, 0x89, 0x44, 0x24, 0x28, 0x48, 0x8b, 0x45, 0xd8, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf9, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
};
|
||||
|
||||
private static readonly int[] DepartPlaceholderIndices;
|
||||
private static readonly int[] ArrivePlaceholderIndices;
|
||||
|
||||
private static int FindPlaceholderIndex(byte[] data)
|
||||
{
|
||||
return Enumerable.Range(0, data.Length - 7)
|
||||
.Single(i => BitConverter.ToUInt64(data, i) == Placeholder);
|
||||
}
|
||||
|
||||
static SysVHostMsGuest()
|
||||
{
|
||||
DepartPlaceholderIndices = Depart.Select(FindPlaceholderIndex).ToArray();
|
||||
ArrivePlaceholderIndices = Arrive.Select(FindPlaceholderIndex).ToArray();
|
||||
if (Depart.Any(b => b.Length > BlockSize) || Arrive.Any(b => b.Length > BlockSize))
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
private readonly MemoryBlock _memory;
|
||||
private readonly object _sync = new object();
|
||||
private readonly WeakReference[] _refs;
|
||||
|
||||
public SysVHostMsGuest()
|
||||
{
|
||||
int size = 4 * 1024 * 1024;
|
||||
_memory = new MemoryBlock((ulong)size);
|
||||
_memory.Activate();
|
||||
_refs = new WeakReference[size / BlockSize];
|
||||
}
|
||||
|
||||
private int FindFreeIndex()
|
||||
{
|
||||
for (int i = 0; i < _refs.Length; i++)
|
||||
{
|
||||
if (_refs[i] == null || !_refs[i].IsAlive)
|
||||
return i;
|
||||
}
|
||||
throw new InvalidOperationException("Out of Thunk memory");
|
||||
}
|
||||
|
||||
private static void VerifyParameter(Type type)
|
||||
{
|
||||
if (type == typeof(float) || type == typeof(double))
|
||||
throw new NotSupportedException("floating point not supported");
|
||||
if (type == typeof(void) || type.IsPrimitive)
|
||||
return;
|
||||
if (type.IsByRef || type.IsClass)
|
||||
return;
|
||||
throw new NotSupportedException("Unknown type. Possibly supported?");
|
||||
}
|
||||
|
||||
private static int VerifyDelegateSignature(ParameterInfo pp)
|
||||
{
|
||||
VerifyParameter(pp.ReturnType);
|
||||
foreach (var ppp in pp.ParameterTypes)
|
||||
VerifyParameter(ppp);
|
||||
return pp.ParameterTypes.Count;
|
||||
}
|
||||
|
||||
private void WriteThunk(byte[] data, int placeholderIndex, IntPtr p, int index)
|
||||
{
|
||||
_memory.Protect(_memory.Start, _memory.Size, MemoryBlock.Protection.RW);
|
||||
var ss = _memory.GetStream(_memory.Start + (ulong)index * BlockSize, BlockSize, true);
|
||||
ss.Write(data, 0, data.Length);
|
||||
for (int i = data.Length; i < BlockSize; i++)
|
||||
ss.WriteByte(Padding);
|
||||
ss.Position = placeholderIndex;
|
||||
var bw = new BinaryWriter(ss);
|
||||
bw.Write((long)p);
|
||||
_memory.Protect(_memory.Start, _memory.Size, MemoryBlock.Protection.RX);
|
||||
}
|
||||
|
||||
private IntPtr GetThunkAddress(int index)
|
||||
{
|
||||
return Z.US(_memory.Start + (ulong)index * BlockSize);
|
||||
}
|
||||
|
||||
private void SetLifetime(int index, object lifetime)
|
||||
{
|
||||
if (_refs[index] == null)
|
||||
_refs[index] = new WeakReference(lifetime);
|
||||
else
|
||||
_refs[index].Target = lifetime;
|
||||
}
|
||||
|
||||
public IntPtr GetFunctionPointerForDelegate(Delegate d)
|
||||
{
|
||||
return GetArrivalFunctionPointer(
|
||||
Marshal.GetFunctionPointerForDelegate(d), new ParameterInfo(d.GetType()), d);
|
||||
}
|
||||
|
||||
public IntPtr GetArrivalFunctionPointer(IntPtr p, ParameterInfo pp, object lifetime)
|
||||
{
|
||||
lock (_sync)
|
||||
{
|
||||
var index = FindFreeIndex();
|
||||
var count = VerifyDelegateSignature(pp);
|
||||
WriteThunk(Arrive[count], ArrivePlaceholderIndices[count], p, index);
|
||||
SetLifetime(index, lifetime);
|
||||
return GetThunkAddress(index);
|
||||
}
|
||||
}
|
||||
|
||||
public Delegate GetDelegateForFunctionPointer(IntPtr p, Type delegateType)
|
||||
{
|
||||
lock (_sync)
|
||||
{
|
||||
var index = FindFreeIndex();
|
||||
var count = VerifyDelegateSignature(new ParameterInfo(delegateType));
|
||||
WriteThunk(Depart[count], DepartPlaceholderIndices[count], p, index);
|
||||
var ret = Marshal.GetDelegateForFunctionPointer(GetThunkAddress(index), delegateType);
|
||||
SetLifetime(index, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
public IntPtr GetDepartureFunctionPointer(IntPtr p, ParameterInfo pp, object lifetime)
|
||||
{
|
||||
lock (_sync)
|
||||
{
|
||||
var index = FindFreeIndex();
|
||||
var count = VerifyDelegateSignature(pp);
|
||||
WriteThunk(Depart[count], DepartPlaceholderIndices[count], p, index);
|
||||
SetLifetime(index, lifetime);
|
||||
return GetThunkAddress(index);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ using System.Text;
|
|||
using System.Runtime.InteropServices;
|
||||
using System.IO;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Waterbox
|
||||
namespace BizHawk.Common.BizInvoke
|
||||
{
|
||||
public sealed class MemoryBlock : IDisposable
|
||||
{
|
|
@ -0,0 +1,156 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace BizHawk.Common.BizInvoke
|
||||
{
|
||||
public static class WaterboxUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// copy `len` bytes from `src` to `dest`
|
||||
/// </summary>
|
||||
/// <param name="src"></param>
|
||||
/// <param name="dst"></param>
|
||||
/// <param name="len"></param>
|
||||
public static void CopySome(Stream src, Stream dst, long len)
|
||||
{
|
||||
var buff = new byte[4096];
|
||||
while (len > 0)
|
||||
{
|
||||
int r = src.Read(buff, 0, (int)Math.Min(len, 4096));
|
||||
dst.Write(buff, 0, r);
|
||||
len -= r;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] Hash(byte[] data)
|
||||
{
|
||||
using (var h = SHA1.Create())
|
||||
{
|
||||
return h.ComputeHash(data);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] Hash(Stream s)
|
||||
{
|
||||
using (var h = SHA1.Create())
|
||||
{
|
||||
return h.ComputeHash(s);
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe void ZeroMemory(IntPtr mem, long length)
|
||||
{
|
||||
byte* p = (byte*)mem;
|
||||
byte* end = p + length;
|
||||
while (p < end)
|
||||
{
|
||||
*p++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static long Timestamp()
|
||||
{
|
||||
return DateTime.UtcNow.Ticks;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// system page size
|
||||
/// </summary>
|
||||
public static int PageSize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// bitshift corresponding to PageSize
|
||||
/// </summary>
|
||||
public static int PageShift { get; private set; }
|
||||
/// <summary>
|
||||
/// bitmask corresponding to PageSize
|
||||
/// </summary>
|
||||
public static ulong PageMask { get; private set; }
|
||||
|
||||
static WaterboxUtils()
|
||||
{
|
||||
int p = PageSize = Environment.SystemPageSize;
|
||||
while (p != 1)
|
||||
{
|
||||
p >>= 1;
|
||||
PageShift++;
|
||||
}
|
||||
PageMask = (ulong)(PageSize - 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// true if addr is aligned
|
||||
/// </summary>
|
||||
public static bool Aligned(ulong addr)
|
||||
{
|
||||
return (addr & PageMask) == 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// align address down to previous page boundary
|
||||
/// </summary>
|
||||
public static ulong AlignDown(ulong addr)
|
||||
{
|
||||
return addr & ~PageMask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// align address up to next page boundary
|
||||
/// </summary>
|
||||
public static ulong AlignUp(ulong addr)
|
||||
{
|
||||
return ((addr - 1) | PageMask) + 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// return the minimum number of pages needed to hold size
|
||||
/// </summary>
|
||||
public static int PagesNeeded(ulong size)
|
||||
{
|
||||
return (int)((size + PageMask) >> PageShift);
|
||||
}
|
||||
}
|
||||
|
||||
// C# is annoying: arithmetic operators for native ints are not exposed.
|
||||
// So we store them as long/ulong instead in many places, and use these helpers
|
||||
// to convert to IntPtr when needed
|
||||
|
||||
public static class Z
|
||||
{
|
||||
public static IntPtr US(ulong l)
|
||||
{
|
||||
if (IntPtr.Size == 8)
|
||||
return (IntPtr)(long)l;
|
||||
else
|
||||
return (IntPtr)(int)l;
|
||||
}
|
||||
|
||||
public static UIntPtr UU(ulong l)
|
||||
{
|
||||
if (UIntPtr.Size == 8)
|
||||
return (UIntPtr)l;
|
||||
else
|
||||
return (UIntPtr)(uint)l;
|
||||
}
|
||||
|
||||
public static IntPtr SS(long l)
|
||||
{
|
||||
if (IntPtr.Size == 8)
|
||||
return (IntPtr)l;
|
||||
else
|
||||
return (IntPtr)(int)l;
|
||||
}
|
||||
|
||||
public static UIntPtr SU(long l)
|
||||
{
|
||||
if (UIntPtr.Size == 8)
|
||||
return (UIntPtr)(ulong)l;
|
||||
else
|
||||
return (UIntPtr)(uint)l;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1278,7 +1278,6 @@
|
|||
<Compile Include="Waterbox\Heap.cs" />
|
||||
<Compile Include="Waterbox\LibWaterboxCore.cs" />
|
||||
<Compile Include="Waterbox\MapHeap.cs" />
|
||||
<Compile Include="Waterbox\MemoryBlock.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Sound\CDAudio.cs" />
|
||||
<Compile Include="Sound\HuC6280PSG.cs" />
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
|
|||
PlainHeapSizeKB = 16 * 1024,
|
||||
MmapHeapSizeKB = 32 * 1024
|
||||
});
|
||||
_pizza = BizInvoker.GetInvoker<LibPizza>(_exe, _exe);
|
||||
_pizza = BizInvoker.GetInvoker<LibPizza>(_exe, _exe, CallingConventionAdapters.Waterbox);
|
||||
if (!_pizza.Init(rom, rom.Length))
|
||||
{
|
||||
throw new InvalidOperationException("Core rejected the rom!");
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
|
|||
static QuickNES()
|
||||
{
|
||||
Resolver = new DynamicLibraryImportResolver(LibQuickNES.dllname);
|
||||
QN = BizInvoker.GetInvoker<LibQuickNES>(Resolver);
|
||||
QN = BizInvoker.GetInvoker<LibQuickNES>(Resolver, CallingConventionAdapters.Native);
|
||||
}
|
||||
|
||||
[CoreConstructor("NES")]
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
|||
// Marshal checks that function pointers passed to GetDelegateForFunctionPointer are
|
||||
// _currently_ valid when created, even though they don't need to be valid until
|
||||
// the delegate is later invoked. so GetInvoker needs to be acquired within a lock.
|
||||
_core = BizInvoker.GetInvoker<CoreImpl>(_exe, _exe);
|
||||
_core = BizInvoker.GetInvoker<CoreImpl>(_exe, _exe, CallingConventionAdapters.Waterbox);
|
||||
_comm = (CommStruct*)_core.DllInit().ToPointer();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -207,7 +207,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK
|
|||
_core = core;
|
||||
_push = push;
|
||||
_pull = pull;
|
||||
_exporter = BizExvoker.GetExvoker(this);
|
||||
_exporter = BizExvoker.GetExvoker(this, CallingConventionAdapters.Waterbox);
|
||||
_readcb = _exporter.SafeResolve("CommsReadCallback");
|
||||
_pollcb = _exporter.SafeResolve("CommsPollCallback");
|
||||
_writecb = _exporter.SafeResolve("CommsWriteCallback");
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
|
|||
|
||||
using (_elf.EnterExit())
|
||||
{
|
||||
Core = BizInvoker.GetInvoker<LibGPGX>(_elf, _elf);
|
||||
Core = BizInvoker.GetInvoker<LibGPGX>(_elf, _elf, CallingConventionAdapters.Waterbox);
|
||||
_syncSettings = (GPGXSyncSettings)syncSettings ?? new GPGXSyncSettings();
|
||||
_settings = (GPGXSettings)settings ?? new GPGXSettings();
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ using System.IO;
|
|||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Common.BizInvoke;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Waterbox
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Common.BizInvoke;
|
||||
using BizHawk.Emulation.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
|
|
@ -6,6 +6,7 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BizHawk.Common.BizInvoke;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Waterbox
|
||||
{
|
||||
|
|
|
@ -107,7 +107,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
throw new InvalidOperationException(s);
|
||||
};
|
||||
_traps.Add(del);
|
||||
ptr = Marshal.GetFunctionPointerForDelegate(del);
|
||||
ptr = CallingConventionAdapters.Waterbox.GetFunctionPointerForDelegate(del);
|
||||
}
|
||||
return ptr;
|
||||
}).ToArray();
|
||||
|
@ -355,7 +355,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
[BizExport(CallingConvention.Cdecl, EntryPoint = "start_main")]
|
||||
public unsafe int StartMain(IntPtr main, int argc, IntPtr argv, IntPtr libc_start_main)
|
||||
{
|
||||
//var del = (LibcStartMain)Marshal.GetDelegateForFunctionPointer(libc_start_main, typeof(LibcStartMain));
|
||||
//var del = (LibcStartMain)CallingConventionAdapters.Waterbox.GetDelegateForFunctionPointer(libc_start_main, typeof(LibcStartMain));
|
||||
// this will init, and then call user main, and then call exit()
|
||||
//del(main, argc, argv);
|
||||
//int* foobar = stackalloc int[128];
|
||||
|
@ -676,11 +676,11 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
{
|
||||
// load any predefined exports
|
||||
_psx = new Psx(this);
|
||||
_exports.Add("libpsxscl.so", BizExvoker.GetExvoker(_psx));
|
||||
_exports.Add("libpsxscl.so", BizExvoker.GetExvoker(_psx, CallingConventionAdapters.Waterbox));
|
||||
_emu = new Emu(this);
|
||||
_exports.Add("libemuhost.so", BizExvoker.GetExvoker(_emu));
|
||||
_exports.Add("libemuhost.so", BizExvoker.GetExvoker(_emu, CallingConventionAdapters.Waterbox));
|
||||
_syscalls = new Syscalls(this);
|
||||
_exports.Add("__syscalls", BizExvoker.GetExvoker(_syscalls));
|
||||
_exports.Add("__syscalls", BizExvoker.GetExvoker(_syscalls, CallingConventionAdapters.Waterbox));
|
||||
|
||||
// load and connect all modules, starting with the executable
|
||||
var todoModules = new Queue<string>();
|
||||
|
@ -730,7 +730,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
}
|
||||
|
||||
_libcpatch = new LibcPatch(this);
|
||||
_exports["libc.so"] = new PatchImportResolver(_exports["libc.so"], BizExvoker.GetExvoker(_libcpatch));
|
||||
_exports["libc.so"] = new PatchImportResolver(_exports["libc.so"], BizExvoker.GetExvoker(_libcpatch, CallingConventionAdapters.Waterbox));
|
||||
|
||||
ConnectAllImports();
|
||||
|
||||
|
@ -764,7 +764,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
var libcEnter = _exports["libc.so"].SafeResolve("__libc_entry_routine");
|
||||
var psxInit = _exports["libpsxscl.so"].SafeResolve("__psx_init");
|
||||
|
||||
var del = (LibcEntryRoutineD)Marshal.GetDelegateForFunctionPointer(libcEnter, typeof(LibcEntryRoutineD));
|
||||
var del = (LibcEntryRoutineD)CallingConventionAdapters.Waterbox.GetDelegateForFunctionPointer(libcEnter, typeof(LibcEntryRoutineD));
|
||||
// the current mmglue code doesn't use the main pointer at all, and this just returns
|
||||
del(IntPtr.Zero, psxInit, 0);
|
||||
|
||||
|
@ -811,7 +811,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
if (_exports.TryGetValue("libco.so", out libco))
|
||||
{
|
||||
Console.WriteLine("Calling co_clean()...");
|
||||
Marshal.GetDelegateForFunctionPointer<Action>(libco.SafeResolve("co_clean"))();
|
||||
CallingConventionAdapters.Waterbox.GetDelegateForFunctionPointer<Action>(libco.SafeResolve("co_clean"))();
|
||||
}
|
||||
|
||||
_sealedheap.Seal();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using BizHawk.Common;
|
||||
using BizHawk.Common.BizInvoke;
|
||||
using BizHawk.Emulation.Common;
|
||||
using PeNet;
|
||||
using System;
|
||||
|
@ -77,12 +78,12 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
|
||||
/*public bool RunDllEntry()
|
||||
{
|
||||
var entryThunk = (DllEntry)Marshal.GetDelegateForFunctionPointer(EntryPoint, typeof(DllEntry));
|
||||
var entryThunk = (DllEntry)CallingConventionAdapters.Waterbox.GetDelegateForFunctionPointer(EntryPoint, typeof(DllEntry));
|
||||
return entryThunk(Z.US(Start), 1, IntPtr.Zero); // DLL_PROCESS_ATTACH
|
||||
}
|
||||
public void RunExeEntry()
|
||||
{
|
||||
var entryThunk = (ExeEntry)Marshal.GetDelegateForFunctionPointer(EntryPoint, typeof(ExeEntry));
|
||||
var entryThunk = (ExeEntry)CallingConventionAdapters.Waterbox.GetDelegateForFunctionPointer(EntryPoint, typeof(ExeEntry));
|
||||
entryThunk();
|
||||
}*/
|
||||
public unsafe void RunGlobalCtors()
|
||||
|
@ -94,7 +95,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
IntPtr f;
|
||||
while ((f = *++p) != IntPtr.Zero) // skip 0th dummy pointer
|
||||
{
|
||||
var ctorThunk = (GlobalCtor)Marshal.GetDelegateForFunctionPointer(f, typeof(GlobalCtor));
|
||||
var ctorThunk = (GlobalCtor)CallingConventionAdapters.Waterbox.GetDelegateForFunctionPointer(f, typeof(GlobalCtor));
|
||||
//Console.WriteLine(f);
|
||||
//System.Diagnostics.Debugger.Break();
|
||||
ctorThunk();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using BizHawk.Common;
|
||||
using BizHawk.Common.BizInvoke;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
_exe = new PeRunner(options);
|
||||
using (_exe.EnterExit())
|
||||
{
|
||||
var ret = BizInvoker.GetInvoker<T>(_exe, _exe);
|
||||
var ret = BizInvoker.GetInvoker<T>(_exe, _exe, CallingConventionAdapters.Waterbox);
|
||||
_core = ret;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
gcc test.c -o test.exe -Wall
|
|
@ -0,0 +1,20 @@
|
|||
private static readonly byte[][] Depart =
|
||||
{
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x20, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x30, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x8b, 0x55, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x48, 0x89, 0xd1, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x30, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x40, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x40, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x89, 0x4d, 0xe0, 0x48, 0x8b, 0x7d, 0xe0, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf9, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x60, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x89, 0x4d, 0xe0, 0x4c, 0x89, 0x45, 0xd8, 0x48, 0x8b, 0x7d, 0xe0, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0x8b, 0x45, 0xd8, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf9, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x60, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x89, 0x4d, 0xe0, 0x4c, 0x89, 0x45, 0xd8, 0x4c, 0x89, 0x4d, 0xd0, 0x48, 0x8b, 0x7d, 0xe0, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0x8b, 0x45, 0xd0, 0x48, 0x89, 0x44, 0x24, 0x28, 0x48, 0x8b, 0x45, 0xd8, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf9, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
};
|
||||
private static readonly byte[][] Arrive =
|
||||
{
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x20, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x30, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x8b, 0x55, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x48, 0x89, 0xd1, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x30, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x40, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x40, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x89, 0x4d, 0xe0, 0x48, 0x8b, 0x7d, 0xe0, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf9, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x60, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x89, 0x4d, 0xe0, 0x4c, 0x89, 0x45, 0xd8, 0x48, 0x8b, 0x7d, 0xe0, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0x8b, 0x45, 0xd8, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf9, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
new byte[] { 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x60, 0x48, 0x89, 0x7d, 0xf8, 0x48, 0x89, 0x75, 0xf0, 0x48, 0x89, 0x55, 0xe8, 0x48, 0x89, 0x4d, 0xe0, 0x4c, 0x89, 0x45, 0xd8, 0x4c, 0x89, 0x4d, 0xd0, 0x48, 0x8b, 0x7d, 0xe0, 0x48, 0x8b, 0x75, 0xe8, 0x48, 0x8b, 0x55, 0xf0, 0x48, 0x8b, 0x4d, 0xf8, 0x48, 0x8b, 0x45, 0xd0, 0x48, 0x89, 0x44, 0x24, 0x28, 0x48, 0x8b, 0x45, 0xd8, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0xb8, 0xce, 0xfa, 0xed, 0xfe, 0xef, 0xbe, 0xad, 0xde, 0x49, 0x89, 0xf9, 0x49, 0x89, 0xf0, 0xff, 0xd0, 0xc9, 0xc3, },
|
||||
};
|
|
@ -0,0 +1,103 @@
|
|||
#include <stdint.h>
|
||||
|
||||
typedef int64_t ll;
|
||||
|
||||
__attribute__((sysv_abi)) ll Depart0(void)
|
||||
{
|
||||
return ((__attribute__((ms_abi)) ll (*)(void))0xdeadbeeffeedface)();
|
||||
}
|
||||
|
||||
__attribute__((sysv_abi)) ll Depart1(ll a)
|
||||
{
|
||||
return ((__attribute__((ms_abi)) ll (*)(ll))0xdeadbeeffeedface)(a);
|
||||
}
|
||||
|
||||
__attribute__((sysv_abi)) ll Depart2(ll a, ll b)
|
||||
{
|
||||
return ((__attribute__((ms_abi)) ll (*)(ll, ll))0xdeadbeeffeedface)(a, b);
|
||||
}
|
||||
|
||||
__attribute__((sysv_abi)) ll Depart3(ll a, ll b, ll c)
|
||||
{
|
||||
return ((__attribute__((ms_abi)) ll (*)(ll, ll, ll))0xdeadbeeffeedface)(a, b, c);
|
||||
}
|
||||
|
||||
__attribute__((sysv_abi)) ll Depart4(ll a, ll b, ll c, ll d)
|
||||
{
|
||||
return ((__attribute__((ms_abi)) ll (*)(ll, ll, ll, ll))0xdeadbeeffeedface)(a, b, c, d);
|
||||
}
|
||||
|
||||
__attribute__((sysv_abi)) ll Depart5(ll a, ll b, ll c, ll d, ll e)
|
||||
{
|
||||
return ((__attribute__((ms_abi)) ll (*)(ll, ll, ll, ll, ll))0xdeadbeeffeedface)(a, b, c, d, e);
|
||||
}
|
||||
|
||||
__attribute__((sysv_abi)) ll Depart6(ll a, ll b, ll c, ll d, ll e, ll f)
|
||||
{
|
||||
return ((__attribute__((ms_abi)) ll (*)(ll, ll, ll, ll, ll, ll))0xdeadbeeffeedface)(a, b, c, d, e, f);
|
||||
}
|
||||
|
||||
__attribute__((ms_abi)) ll Arrive0(void)
|
||||
{
|
||||
return ((__attribute__((sysv_abi)) ll (*)(void))0xdeadbeeffeedface)();
|
||||
}
|
||||
|
||||
__attribute__((ms_abi)) ll Arrive1(ll a)
|
||||
{
|
||||
return ((__attribute__((sysv_abi)) ll (*)(ll))0xdeadbeeffeedface)(a);
|
||||
}
|
||||
|
||||
__attribute__((ms_abi)) ll Arrive2(ll a, ll b)
|
||||
{
|
||||
return ((__attribute__((sysv_abi)) ll (*)(ll, ll))0xdeadbeeffeedface)(a, b);
|
||||
}
|
||||
|
||||
__attribute__((ms_abi)) ll Arrive3(ll a, ll b, ll c)
|
||||
{
|
||||
return ((__attribute__((sysv_abi)) ll (*)(ll, ll, ll))0xdeadbeeffeedface)(a, b, c);
|
||||
}
|
||||
|
||||
__attribute__((ms_abi)) ll Arrive4(ll a, ll b, ll c, ll d)
|
||||
{
|
||||
return ((__attribute__((sysv_abi)) ll (*)(ll, ll, ll, ll))0xdeadbeeffeedface)(a, b, c, d);
|
||||
}
|
||||
|
||||
__attribute__((ms_abi)) ll Arrive5(ll a, ll b, ll c, ll d, ll e)
|
||||
{
|
||||
return ((__attribute__((sysv_abi)) ll (*)(ll, ll, ll, ll, ll))0xdeadbeeffeedface)(a, b, c, d, e);
|
||||
}
|
||||
|
||||
__attribute__((ms_abi)) ll Arrive6(ll a, ll b, ll c, ll d, ll e, ll f)
|
||||
{
|
||||
return ((__attribute__((sysv_abi)) ll (*)(ll, ll, ll, ll, ll, ll))0xdeadbeeffeedface)(a, b, c, d, e, f);
|
||||
}
|
||||
|
||||
void End(void)
|
||||
{
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
const void* ptrs[] = { Depart0, Depart1, Depart2, Depart3, Depart4, Depart5, Depart6,
|
||||
Arrive0, Arrive1, Arrive2, Arrive3, Arrive4, Arrive5, Arrive6, End };
|
||||
|
||||
void print(const char* name, int offs)
|
||||
{
|
||||
printf("private static readonly byte[][] %s =\n{\n", name);
|
||||
for (int i = offs; i < offs + 7; i++)
|
||||
{
|
||||
printf("\tnew byte[] { ");
|
||||
const uint8_t* start = ptrs[i];
|
||||
const uint8_t* end = ptrs[i + 1];
|
||||
while (start < end)
|
||||
printf("0x%02x, ", *start++);
|
||||
printf("},\n");
|
||||
}
|
||||
printf("};\n");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
print("Depart", 0);
|
||||
print("Arrive", 0);
|
||||
return 0;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,682 @@
|
|||
.file "test.c"
|
||||
.text
|
||||
.globl Depart0
|
||||
.def Depart0; .scl 2; .type 32; .endef
|
||||
Depart0:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
subq $32, %rsp
|
||||
movabsq $-2401053088335136050, %rax
|
||||
call *%rax
|
||||
leave
|
||||
ret
|
||||
.globl Depart1
|
||||
.def Depart1; .scl 2; .type 32; .endef
|
||||
Depart1:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
subq $48, %rsp
|
||||
movq %rdi, -8(%rbp)
|
||||
movq -8(%rbp), %rdx
|
||||
movabsq $-2401053088335136050, %rax
|
||||
movq %rdx, %rcx
|
||||
call *%rax
|
||||
leave
|
||||
ret
|
||||
.globl Depart2
|
||||
.def Depart2; .scl 2; .type 32; .endef
|
||||
Depart2:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
subq $48, %rsp
|
||||
movq %rdi, -8(%rbp)
|
||||
movq %rsi, -16(%rbp)
|
||||
movq -16(%rbp), %rdx
|
||||
movq -8(%rbp), %rcx
|
||||
movabsq $-2401053088335136050, %rax
|
||||
call *%rax
|
||||
leave
|
||||
ret
|
||||
.globl Depart3
|
||||
.def Depart3; .scl 2; .type 32; .endef
|
||||
Depart3:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
subq $64, %rsp
|
||||
movq %rdi, -8(%rbp)
|
||||
movq %rsi, -16(%rbp)
|
||||
movq %rdx, -24(%rbp)
|
||||
movq -24(%rbp), %rsi
|
||||
movq -16(%rbp), %rdx
|
||||
movq -8(%rbp), %rcx
|
||||
movabsq $-2401053088335136050, %rax
|
||||
movq %rsi, %r8
|
||||
call *%rax
|
||||
leave
|
||||
ret
|
||||
.globl Depart4
|
||||
.def Depart4; .scl 2; .type 32; .endef
|
||||
Depart4:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
subq $64, %rsp
|
||||
movq %rdi, -8(%rbp)
|
||||
movq %rsi, -16(%rbp)
|
||||
movq %rdx, -24(%rbp)
|
||||
movq %rcx, -32(%rbp)
|
||||
movq -32(%rbp), %rdi
|
||||
movq -24(%rbp), %rsi
|
||||
movq -16(%rbp), %rdx
|
||||
movq -8(%rbp), %rcx
|
||||
movabsq $-2401053088335136050, %rax
|
||||
movq %rdi, %r9
|
||||
movq %rsi, %r8
|
||||
call *%rax
|
||||
leave
|
||||
ret
|
||||
.globl Depart5
|
||||
.def Depart5; .scl 2; .type 32; .endef
|
||||
Depart5:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
subq $96, %rsp
|
||||
movq %rdi, -8(%rbp)
|
||||
movq %rsi, -16(%rbp)
|
||||
movq %rdx, -24(%rbp)
|
||||
movq %rcx, -32(%rbp)
|
||||
movq %r8, -40(%rbp)
|
||||
movq -32(%rbp), %rdi
|
||||
movq -24(%rbp), %rsi
|
||||
movq -16(%rbp), %rdx
|
||||
movq -8(%rbp), %rcx
|
||||
movq -40(%rbp), %rax
|
||||
movq %rax, 32(%rsp)
|
||||
movabsq $-2401053088335136050, %rax
|
||||
movq %rdi, %r9
|
||||
movq %rsi, %r8
|
||||
call *%rax
|
||||
leave
|
||||
ret
|
||||
.globl Depart6
|
||||
.def Depart6; .scl 2; .type 32; .endef
|
||||
Depart6:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
subq $96, %rsp
|
||||
movq %rdi, -8(%rbp)
|
||||
movq %rsi, -16(%rbp)
|
||||
movq %rdx, -24(%rbp)
|
||||
movq %rcx, -32(%rbp)
|
||||
movq %r8, -40(%rbp)
|
||||
movq %r9, -48(%rbp)
|
||||
movq -32(%rbp), %rdi
|
||||
movq -24(%rbp), %rsi
|
||||
movq -16(%rbp), %rdx
|
||||
movq -8(%rbp), %rcx
|
||||
movq -48(%rbp), %rax
|
||||
movq %rax, 40(%rsp)
|
||||
movq -40(%rbp), %rax
|
||||
movq %rax, 32(%rsp)
|
||||
movabsq $-2401053088335136050, %rax
|
||||
movq %rdi, %r9
|
||||
movq %rsi, %r8
|
||||
call *%rax
|
||||
leave
|
||||
ret
|
||||
.globl Arrive0
|
||||
.def Arrive0; .scl 2; .type 32; .endef
|
||||
.seh_proc Arrive0
|
||||
Arrive0:
|
||||
pushq %rbp
|
||||
.seh_pushreg %rbp
|
||||
pushq %rdi
|
||||
.seh_pushreg %rdi
|
||||
pushq %rsi
|
||||
.seh_pushreg %rsi
|
||||
movq %rsp, %rbp
|
||||
.seh_setframe %rbp, 0
|
||||
subq $160, %rsp
|
||||
.seh_stackalloc 160
|
||||
movaps %xmm6, (%rsp)
|
||||
.seh_savexmm %xmm6, 0
|
||||
movaps %xmm7, 16(%rsp)
|
||||
.seh_savexmm %xmm7, 16
|
||||
movaps %xmm8, -128(%rbp)
|
||||
.seh_savexmm %xmm8, 32
|
||||
movaps %xmm9, -112(%rbp)
|
||||
.seh_savexmm %xmm9, 48
|
||||
movaps %xmm10, -96(%rbp)
|
||||
.seh_savexmm %xmm10, 64
|
||||
movaps %xmm11, -80(%rbp)
|
||||
.seh_savexmm %xmm11, 80
|
||||
movaps %xmm12, -64(%rbp)
|
||||
.seh_savexmm %xmm12, 96
|
||||
movaps %xmm13, -48(%rbp)
|
||||
.seh_savexmm %xmm13, 112
|
||||
movaps %xmm14, -32(%rbp)
|
||||
.seh_savexmm %xmm14, 128
|
||||
movaps %xmm15, -16(%rbp)
|
||||
.seh_savexmm %xmm15, 144
|
||||
.seh_endprologue
|
||||
movabsq $-2401053088335136050, %rax
|
||||
call *%rax
|
||||
movaps (%rsp), %xmm6
|
||||
movaps 16(%rsp), %xmm7
|
||||
movaps -128(%rbp), %xmm8
|
||||
movaps -112(%rbp), %xmm9
|
||||
movaps -96(%rbp), %xmm10
|
||||
movaps -80(%rbp), %xmm11
|
||||
movaps -64(%rbp), %xmm12
|
||||
movaps -48(%rbp), %xmm13
|
||||
movaps -32(%rbp), %xmm14
|
||||
movaps -16(%rbp), %xmm15
|
||||
addq $160, %rsp
|
||||
popq %rsi
|
||||
popq %rdi
|
||||
popq %rbp
|
||||
ret
|
||||
.seh_endproc
|
||||
.globl Arrive1
|
||||
.def Arrive1; .scl 2; .type 32; .endef
|
||||
.seh_proc Arrive1
|
||||
Arrive1:
|
||||
pushq %rbp
|
||||
.seh_pushreg %rbp
|
||||
pushq %rdi
|
||||
.seh_pushreg %rdi
|
||||
pushq %rsi
|
||||
.seh_pushreg %rsi
|
||||
movq %rsp, %rbp
|
||||
.seh_setframe %rbp, 0
|
||||
subq $160, %rsp
|
||||
.seh_stackalloc 160
|
||||
movaps %xmm6, (%rsp)
|
||||
.seh_savexmm %xmm6, 0
|
||||
movaps %xmm7, 16(%rsp)
|
||||
.seh_savexmm %xmm7, 16
|
||||
movaps %xmm8, -128(%rbp)
|
||||
.seh_savexmm %xmm8, 32
|
||||
movaps %xmm9, -112(%rbp)
|
||||
.seh_savexmm %xmm9, 48
|
||||
movaps %xmm10, -96(%rbp)
|
||||
.seh_savexmm %xmm10, 64
|
||||
movaps %xmm11, -80(%rbp)
|
||||
.seh_savexmm %xmm11, 80
|
||||
movaps %xmm12, -64(%rbp)
|
||||
.seh_savexmm %xmm12, 96
|
||||
movaps %xmm13, -48(%rbp)
|
||||
.seh_savexmm %xmm13, 112
|
||||
movaps %xmm14, -32(%rbp)
|
||||
.seh_savexmm %xmm14, 128
|
||||
movaps %xmm15, -16(%rbp)
|
||||
.seh_savexmm %xmm15, 144
|
||||
.seh_endprologue
|
||||
movq %rcx, 32(%rbp)
|
||||
movabsq $-2401053088335136050, %rax
|
||||
movq 32(%rbp), %rdi
|
||||
call *%rax
|
||||
movaps (%rsp), %xmm6
|
||||
movaps 16(%rsp), %xmm7
|
||||
movaps -128(%rbp), %xmm8
|
||||
movaps -112(%rbp), %xmm9
|
||||
movaps -96(%rbp), %xmm10
|
||||
movaps -80(%rbp), %xmm11
|
||||
movaps -64(%rbp), %xmm12
|
||||
movaps -48(%rbp), %xmm13
|
||||
movaps -32(%rbp), %xmm14
|
||||
movaps -16(%rbp), %xmm15
|
||||
addq $160, %rsp
|
||||
popq %rsi
|
||||
popq %rdi
|
||||
popq %rbp
|
||||
ret
|
||||
.seh_endproc
|
||||
.globl Arrive2
|
||||
.def Arrive2; .scl 2; .type 32; .endef
|
||||
.seh_proc Arrive2
|
||||
Arrive2:
|
||||
pushq %rbp
|
||||
.seh_pushreg %rbp
|
||||
pushq %rdi
|
||||
.seh_pushreg %rdi
|
||||
pushq %rsi
|
||||
.seh_pushreg %rsi
|
||||
movq %rsp, %rbp
|
||||
.seh_setframe %rbp, 0
|
||||
subq $160, %rsp
|
||||
.seh_stackalloc 160
|
||||
movaps %xmm6, (%rsp)
|
||||
.seh_savexmm %xmm6, 0
|
||||
movaps %xmm7, 16(%rsp)
|
||||
.seh_savexmm %xmm7, 16
|
||||
movaps %xmm8, -128(%rbp)
|
||||
.seh_savexmm %xmm8, 32
|
||||
movaps %xmm9, -112(%rbp)
|
||||
.seh_savexmm %xmm9, 48
|
||||
movaps %xmm10, -96(%rbp)
|
||||
.seh_savexmm %xmm10, 64
|
||||
movaps %xmm11, -80(%rbp)
|
||||
.seh_savexmm %xmm11, 80
|
||||
movaps %xmm12, -64(%rbp)
|
||||
.seh_savexmm %xmm12, 96
|
||||
movaps %xmm13, -48(%rbp)
|
||||
.seh_savexmm %xmm13, 112
|
||||
movaps %xmm14, -32(%rbp)
|
||||
.seh_savexmm %xmm14, 128
|
||||
movaps %xmm15, -16(%rbp)
|
||||
.seh_savexmm %xmm15, 144
|
||||
.seh_endprologue
|
||||
movq %rcx, 32(%rbp)
|
||||
movq %rdx, 40(%rbp)
|
||||
movq 40(%rbp), %rdx
|
||||
movabsq $-2401053088335136050, %rax
|
||||
movq %rdx, %rsi
|
||||
movq 32(%rbp), %rdi
|
||||
call *%rax
|
||||
movaps (%rsp), %xmm6
|
||||
movaps 16(%rsp), %xmm7
|
||||
movaps -128(%rbp), %xmm8
|
||||
movaps -112(%rbp), %xmm9
|
||||
movaps -96(%rbp), %xmm10
|
||||
movaps -80(%rbp), %xmm11
|
||||
movaps -64(%rbp), %xmm12
|
||||
movaps -48(%rbp), %xmm13
|
||||
movaps -32(%rbp), %xmm14
|
||||
movaps -16(%rbp), %xmm15
|
||||
addq $160, %rsp
|
||||
popq %rsi
|
||||
popq %rdi
|
||||
popq %rbp
|
||||
ret
|
||||
.seh_endproc
|
||||
.globl Arrive3
|
||||
.def Arrive3; .scl 2; .type 32; .endef
|
||||
.seh_proc Arrive3
|
||||
Arrive3:
|
||||
pushq %rbp
|
||||
.seh_pushreg %rbp
|
||||
pushq %rdi
|
||||
.seh_pushreg %rdi
|
||||
pushq %rsi
|
||||
.seh_pushreg %rsi
|
||||
movq %rsp, %rbp
|
||||
.seh_setframe %rbp, 0
|
||||
subq $160, %rsp
|
||||
.seh_stackalloc 160
|
||||
movaps %xmm6, (%rsp)
|
||||
.seh_savexmm %xmm6, 0
|
||||
movaps %xmm7, 16(%rsp)
|
||||
.seh_savexmm %xmm7, 16
|
||||
movaps %xmm8, -128(%rbp)
|
||||
.seh_savexmm %xmm8, 32
|
||||
movaps %xmm9, -112(%rbp)
|
||||
.seh_savexmm %xmm9, 48
|
||||
movaps %xmm10, -96(%rbp)
|
||||
.seh_savexmm %xmm10, 64
|
||||
movaps %xmm11, -80(%rbp)
|
||||
.seh_savexmm %xmm11, 80
|
||||
movaps %xmm12, -64(%rbp)
|
||||
.seh_savexmm %xmm12, 96
|
||||
movaps %xmm13, -48(%rbp)
|
||||
.seh_savexmm %xmm13, 112
|
||||
movaps %xmm14, -32(%rbp)
|
||||
.seh_savexmm %xmm14, 128
|
||||
movaps %xmm15, -16(%rbp)
|
||||
.seh_savexmm %xmm15, 144
|
||||
.seh_endprologue
|
||||
movq %rcx, 32(%rbp)
|
||||
movq %rdx, 40(%rbp)
|
||||
movq %r8, 48(%rbp)
|
||||
movq 48(%rbp), %rdx
|
||||
movq 40(%rbp), %rcx
|
||||
movabsq $-2401053088335136050, %rax
|
||||
movq %rcx, %rsi
|
||||
movq 32(%rbp), %rdi
|
||||
call *%rax
|
||||
movaps (%rsp), %xmm6
|
||||
movaps 16(%rsp), %xmm7
|
||||
movaps -128(%rbp), %xmm8
|
||||
movaps -112(%rbp), %xmm9
|
||||
movaps -96(%rbp), %xmm10
|
||||
movaps -80(%rbp), %xmm11
|
||||
movaps -64(%rbp), %xmm12
|
||||
movaps -48(%rbp), %xmm13
|
||||
movaps -32(%rbp), %xmm14
|
||||
movaps -16(%rbp), %xmm15
|
||||
addq $160, %rsp
|
||||
popq %rsi
|
||||
popq %rdi
|
||||
popq %rbp
|
||||
ret
|
||||
.seh_endproc
|
||||
.globl Arrive4
|
||||
.def Arrive4; .scl 2; .type 32; .endef
|
||||
.seh_proc Arrive4
|
||||
Arrive4:
|
||||
pushq %rbp
|
||||
.seh_pushreg %rbp
|
||||
pushq %rdi
|
||||
.seh_pushreg %rdi
|
||||
pushq %rsi
|
||||
.seh_pushreg %rsi
|
||||
movq %rsp, %rbp
|
||||
.seh_setframe %rbp, 0
|
||||
subq $160, %rsp
|
||||
.seh_stackalloc 160
|
||||
movaps %xmm6, (%rsp)
|
||||
.seh_savexmm %xmm6, 0
|
||||
movaps %xmm7, 16(%rsp)
|
||||
.seh_savexmm %xmm7, 16
|
||||
movaps %xmm8, -128(%rbp)
|
||||
.seh_savexmm %xmm8, 32
|
||||
movaps %xmm9, -112(%rbp)
|
||||
.seh_savexmm %xmm9, 48
|
||||
movaps %xmm10, -96(%rbp)
|
||||
.seh_savexmm %xmm10, 64
|
||||
movaps %xmm11, -80(%rbp)
|
||||
.seh_savexmm %xmm11, 80
|
||||
movaps %xmm12, -64(%rbp)
|
||||
.seh_savexmm %xmm12, 96
|
||||
movaps %xmm13, -48(%rbp)
|
||||
.seh_savexmm %xmm13, 112
|
||||
movaps %xmm14, -32(%rbp)
|
||||
.seh_savexmm %xmm14, 128
|
||||
movaps %xmm15, -16(%rbp)
|
||||
.seh_savexmm %xmm15, 144
|
||||
.seh_endprologue
|
||||
movq %rcx, 32(%rbp)
|
||||
movq %rdx, 40(%rbp)
|
||||
movq %r8, 48(%rbp)
|
||||
movq %r9, 56(%rbp)
|
||||
movq 56(%rbp), %rcx
|
||||
movq 48(%rbp), %rdx
|
||||
movq 40(%rbp), %r8
|
||||
movabsq $-2401053088335136050, %rax
|
||||
movq %r8, %rsi
|
||||
movq 32(%rbp), %rdi
|
||||
call *%rax
|
||||
movaps (%rsp), %xmm6
|
||||
movaps 16(%rsp), %xmm7
|
||||
movaps -128(%rbp), %xmm8
|
||||
movaps -112(%rbp), %xmm9
|
||||
movaps -96(%rbp), %xmm10
|
||||
movaps -80(%rbp), %xmm11
|
||||
movaps -64(%rbp), %xmm12
|
||||
movaps -48(%rbp), %xmm13
|
||||
movaps -32(%rbp), %xmm14
|
||||
movaps -16(%rbp), %xmm15
|
||||
addq $160, %rsp
|
||||
popq %rsi
|
||||
popq %rdi
|
||||
popq %rbp
|
||||
ret
|
||||
.seh_endproc
|
||||
.globl Arrive5
|
||||
.def Arrive5; .scl 2; .type 32; .endef
|
||||
.seh_proc Arrive5
|
||||
Arrive5:
|
||||
pushq %rbp
|
||||
.seh_pushreg %rbp
|
||||
pushq %rdi
|
||||
.seh_pushreg %rdi
|
||||
pushq %rsi
|
||||
.seh_pushreg %rsi
|
||||
movq %rsp, %rbp
|
||||
.seh_setframe %rbp, 0
|
||||
subq $160, %rsp
|
||||
.seh_stackalloc 160
|
||||
movaps %xmm6, (%rsp)
|
||||
.seh_savexmm %xmm6, 0
|
||||
movaps %xmm7, 16(%rsp)
|
||||
.seh_savexmm %xmm7, 16
|
||||
movaps %xmm8, -128(%rbp)
|
||||
.seh_savexmm %xmm8, 32
|
||||
movaps %xmm9, -112(%rbp)
|
||||
.seh_savexmm %xmm9, 48
|
||||
movaps %xmm10, -96(%rbp)
|
||||
.seh_savexmm %xmm10, 64
|
||||
movaps %xmm11, -80(%rbp)
|
||||
.seh_savexmm %xmm11, 80
|
||||
movaps %xmm12, -64(%rbp)
|
||||
.seh_savexmm %xmm12, 96
|
||||
movaps %xmm13, -48(%rbp)
|
||||
.seh_savexmm %xmm13, 112
|
||||
movaps %xmm14, -32(%rbp)
|
||||
.seh_savexmm %xmm14, 128
|
||||
movaps %xmm15, -16(%rbp)
|
||||
.seh_savexmm %xmm15, 144
|
||||
.seh_endprologue
|
||||
movq %rcx, 32(%rbp)
|
||||
movq %rdx, 40(%rbp)
|
||||
movq %r8, 48(%rbp)
|
||||
movq %r9, 56(%rbp)
|
||||
movq 64(%rbp), %r8
|
||||
movq 56(%rbp), %rcx
|
||||
movq 48(%rbp), %rdx
|
||||
movq 40(%rbp), %r9
|
||||
movabsq $-2401053088335136050, %rax
|
||||
movq %r9, %rsi
|
||||
movq 32(%rbp), %rdi
|
||||
call *%rax
|
||||
movaps (%rsp), %xmm6
|
||||
movaps 16(%rsp), %xmm7
|
||||
movaps -128(%rbp), %xmm8
|
||||
movaps -112(%rbp), %xmm9
|
||||
movaps -96(%rbp), %xmm10
|
||||
movaps -80(%rbp), %xmm11
|
||||
movaps -64(%rbp), %xmm12
|
||||
movaps -48(%rbp), %xmm13
|
||||
movaps -32(%rbp), %xmm14
|
||||
movaps -16(%rbp), %xmm15
|
||||
addq $160, %rsp
|
||||
popq %rsi
|
||||
popq %rdi
|
||||
popq %rbp
|
||||
ret
|
||||
.seh_endproc
|
||||
.globl Arrive6
|
||||
.def Arrive6; .scl 2; .type 32; .endef
|
||||
.seh_proc Arrive6
|
||||
Arrive6:
|
||||
pushq %rbp
|
||||
.seh_pushreg %rbp
|
||||
pushq %rdi
|
||||
.seh_pushreg %rdi
|
||||
pushq %rsi
|
||||
.seh_pushreg %rsi
|
||||
movq %rsp, %rbp
|
||||
.seh_setframe %rbp, 0
|
||||
subq $160, %rsp
|
||||
.seh_stackalloc 160
|
||||
movaps %xmm6, (%rsp)
|
||||
.seh_savexmm %xmm6, 0
|
||||
movaps %xmm7, 16(%rsp)
|
||||
.seh_savexmm %xmm7, 16
|
||||
movaps %xmm8, -128(%rbp)
|
||||
.seh_savexmm %xmm8, 32
|
||||
movaps %xmm9, -112(%rbp)
|
||||
.seh_savexmm %xmm9, 48
|
||||
movaps %xmm10, -96(%rbp)
|
||||
.seh_savexmm %xmm10, 64
|
||||
movaps %xmm11, -80(%rbp)
|
||||
.seh_savexmm %xmm11, 80
|
||||
movaps %xmm12, -64(%rbp)
|
||||
.seh_savexmm %xmm12, 96
|
||||
movaps %xmm13, -48(%rbp)
|
||||
.seh_savexmm %xmm13, 112
|
||||
movaps %xmm14, -32(%rbp)
|
||||
.seh_savexmm %xmm14, 128
|
||||
movaps %xmm15, -16(%rbp)
|
||||
.seh_savexmm %xmm15, 144
|
||||
.seh_endprologue
|
||||
movq %rcx, 32(%rbp)
|
||||
movq %rdx, 40(%rbp)
|
||||
movq %r8, 48(%rbp)
|
||||
movq %r9, 56(%rbp)
|
||||
movq 72(%rbp), %r9
|
||||
movq 64(%rbp), %r8
|
||||
movq 56(%rbp), %rcx
|
||||
movq 48(%rbp), %rdx
|
||||
movq 40(%rbp), %r10
|
||||
movabsq $-2401053088335136050, %rax
|
||||
movq %r10, %rsi
|
||||
movq 32(%rbp), %rdi
|
||||
call *%rax
|
||||
movaps (%rsp), %xmm6
|
||||
movaps 16(%rsp), %xmm7
|
||||
movaps -128(%rbp), %xmm8
|
||||
movaps -112(%rbp), %xmm9
|
||||
movaps -96(%rbp), %xmm10
|
||||
movaps -80(%rbp), %xmm11
|
||||
movaps -64(%rbp), %xmm12
|
||||
movaps -48(%rbp), %xmm13
|
||||
movaps -32(%rbp), %xmm14
|
||||
movaps -16(%rbp), %xmm15
|
||||
addq $160, %rsp
|
||||
popq %rsi
|
||||
popq %rdi
|
||||
popq %rbp
|
||||
ret
|
||||
.seh_endproc
|
||||
.globl End
|
||||
.def End; .scl 2; .type 32; .endef
|
||||
.seh_proc End
|
||||
End:
|
||||
pushq %rbp
|
||||
.seh_pushreg %rbp
|
||||
movq %rsp, %rbp
|
||||
.seh_setframe %rbp, 0
|
||||
.seh_endprologue
|
||||
nop
|
||||
popq %rbp
|
||||
ret
|
||||
.seh_endproc
|
||||
.globl ptrs
|
||||
.data
|
||||
.align 32
|
||||
ptrs:
|
||||
.quad Depart0
|
||||
.quad Depart1
|
||||
.quad Depart2
|
||||
.quad Depart3
|
||||
.quad Depart4
|
||||
.quad Depart5
|
||||
.quad Depart6
|
||||
.quad Arrive0
|
||||
.quad Arrive1
|
||||
.quad Arrive2
|
||||
.quad Arrive3
|
||||
.quad Arrive4
|
||||
.quad Arrive5
|
||||
.quad Arrive6
|
||||
.quad End
|
||||
.section .rdata,"dr"
|
||||
.align 8
|
||||
.LC0:
|
||||
.ascii "private static readonly byte[][] %s =\12{\12\0"
|
||||
.LC1:
|
||||
.ascii "\11new byte[] { \0"
|
||||
.LC2:
|
||||
.ascii "0x%02x, \0"
|
||||
.LC3:
|
||||
.ascii "},\0"
|
||||
.LC4:
|
||||
.ascii "};\0"
|
||||
.text
|
||||
.globl print
|
||||
.def print; .scl 2; .type 32; .endef
|
||||
.seh_proc print
|
||||
print:
|
||||
pushq %rbp
|
||||
.seh_pushreg %rbp
|
||||
movq %rsp, %rbp
|
||||
.seh_setframe %rbp, 0
|
||||
subq $64, %rsp
|
||||
.seh_stackalloc 64
|
||||
.seh_endprologue
|
||||
movq %rcx, 16(%rbp)
|
||||
movl %edx, 24(%rbp)
|
||||
movq 16(%rbp), %rdx
|
||||
leaq .LC0(%rip), %rcx
|
||||
call printf
|
||||
movl 24(%rbp), %eax
|
||||
movl %eax, -4(%rbp)
|
||||
jmp .L31
|
||||
.L34:
|
||||
leaq .LC1(%rip), %rcx
|
||||
call printf
|
||||
movl -4(%rbp), %eax
|
||||
cltq
|
||||
leaq 0(,%rax,8), %rdx
|
||||
leaq ptrs(%rip), %rax
|
||||
movq (%rdx,%rax), %rax
|
||||
movq %rax, -16(%rbp)
|
||||
movl -4(%rbp), %eax
|
||||
addl $1, %eax
|
||||
cltq
|
||||
leaq 0(,%rax,8), %rdx
|
||||
leaq ptrs(%rip), %rax
|
||||
movq (%rdx,%rax), %rax
|
||||
movq %rax, -24(%rbp)
|
||||
jmp .L32
|
||||
.L33:
|
||||
movq -16(%rbp), %rax
|
||||
leaq 1(%rax), %rdx
|
||||
movq %rdx, -16(%rbp)
|
||||
movzbl (%rax), %eax
|
||||
movzbl %al, %eax
|
||||
movl %eax, %edx
|
||||
leaq .LC2(%rip), %rcx
|
||||
call printf
|
||||
.L32:
|
||||
movq -16(%rbp), %rax
|
||||
cmpq -24(%rbp), %rax
|
||||
jb .L33
|
||||
leaq .LC3(%rip), %rcx
|
||||
call puts
|
||||
addl $1, -4(%rbp)
|
||||
.L31:
|
||||
movl 24(%rbp), %eax
|
||||
addl $7, %eax
|
||||
cmpl -4(%rbp), %eax
|
||||
jg .L34
|
||||
leaq .LC4(%rip), %rcx
|
||||
call puts
|
||||
nop
|
||||
addq $64, %rsp
|
||||
popq %rbp
|
||||
ret
|
||||
.seh_endproc
|
||||
.def __main; .scl 2; .type 32; .endef
|
||||
.section .rdata,"dr"
|
||||
.LC5:
|
||||
.ascii "Depart\0"
|
||||
.LC6:
|
||||
.ascii "Arrive\0"
|
||||
.text
|
||||
.globl main
|
||||
.def main; .scl 2; .type 32; .endef
|
||||
.seh_proc main
|
||||
main:
|
||||
pushq %rbp
|
||||
.seh_pushreg %rbp
|
||||
movq %rsp, %rbp
|
||||
.seh_setframe %rbp, 0
|
||||
subq $32, %rsp
|
||||
.seh_stackalloc 32
|
||||
.seh_endprologue
|
||||
call __main
|
||||
movl $0, %edx
|
||||
leaq .LC5(%rip), %rcx
|
||||
call print
|
||||
movl $0, %edx
|
||||
leaq .LC6(%rip), %rcx
|
||||
call print
|
||||
movl $0, %eax
|
||||
addq $32, %rsp
|
||||
popq %rbp
|
||||
ret
|
||||
.seh_endproc
|
||||
.ident "GCC: (Rev2, Built by MSYS2 project) 5.3.0"
|
||||
.def printf; .scl 2; .type 32; .endef
|
||||
.def puts; .scl 2; .type 32; .endef
|
Loading…
Reference in New Issue