More instructions

This commit is contained in:
gdkchan 2019-06-21 17:31:13 -03:00
parent 9f8fbc1d8a
commit c306809b0b
12 changed files with 1039 additions and 130 deletions

View file

@ -599,7 +599,14 @@ namespace ARMeilleure.CodeGen.X86
X86MemoryOperand memOp = new X86MemoryOperand(dest.Type, Register(X86Register.Rsp), null, Scale.x1, offs);
context.Assembler.Mov(dest, memOp);
if (dest.GetRegister().Type == RegisterType.Integer)
{
context.Assembler.Mov(dest, memOp);
}
else
{
context.Assembler.Movdqu(dest, memOp);
}
}
private static void GenerateLoad(CodeGenContext context, Operation operation)

View file

@ -80,7 +80,7 @@ namespace ARMeilleure.Decoders
SetA64("x0111010010xxxxxxxxx00xxxxx0xxxx", InstName.Ccmn, InstEmit.Ccmn, typeof(OpCodeCcmpReg));
SetA64("x1111010010xxxxxxxxx10xxxxx0xxxx", InstName.Ccmp, InstEmit.Ccmp, typeof(OpCodeCcmpImm));
SetA64("x1111010010xxxxxxxxx00xxxxx0xxxx", InstName.Ccmp, InstEmit.Ccmp, typeof(OpCodeCcmpReg));
SetA64("11010101000000110011xxxx01011111", InstName.Clrex, null, typeof(OpCodeSystem));
SetA64("11010101000000110011xxxx01011111", InstName.Clrex, InstEmit.Clrex, typeof(OpCodeSystem));
SetA64("x101101011000000000101xxxxxxxxxx", InstName.Cls, InstEmit.Cls, typeof(OpCodeAlu));
SetA64("x101101011000000000100xxxxxxxxxx", InstName.Clz, InstEmit.Clz, typeof(OpCodeAlu));
SetA64("00011010110xxxxx010000xxxxxxxxxx", InstName.Crc32b, InstEmit.Crc32b, typeof(OpCodeAluBinary));
@ -95,8 +95,8 @@ namespace ARMeilleure.Decoders
SetA64("x0011010100xxxxxxxxx01xxxxxxxxxx", InstName.Csinc, InstEmit.Csinc, typeof(OpCodeCsel));
SetA64("x1011010100xxxxxxxxx00xxxxxxxxxx", InstName.Csinv, InstEmit.Csinv, typeof(OpCodeCsel));
SetA64("x1011010100xxxxxxxxx01xxxxxxxxxx", InstName.Csneg, InstEmit.Csneg, typeof(OpCodeCsel));
SetA64("11010101000000110011xxxx10111111", InstName.Dmb, null, typeof(OpCodeSystem));
SetA64("11010101000000110011xxxx10011111", InstName.Dsb, null, typeof(OpCodeSystem));
SetA64("11010101000000110011xxxx10111111", InstName.Dmb, InstEmit.Dmb, typeof(OpCodeSystem));
SetA64("11010101000000110011xxxx10011111", InstName.Dsb, InstEmit.Dsb, typeof(OpCodeSystem));
SetA64("01001010xx1xxxxx0xxxxxxxxxxxxxxx", InstName.Eon, InstEmit.Eon, typeof(OpCodeAluRs));
SetA64("11001010xx1xxxxxxxxxxxxxxxxxxxxx", InstName.Eon, InstEmit.Eon, typeof(OpCodeAluRs));
SetA64("0101001000xxxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit.Eor, typeof(OpCodeAluImm));
@ -105,11 +105,11 @@ namespace ARMeilleure.Decoders
SetA64("11001010xx0xxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit.Eor, typeof(OpCodeAluRs));
SetA64("00010011100xxxxx0xxxxxxxxxxxxxxx", InstName.Extr, InstEmit.Extr, typeof(OpCodeAluRs));
SetA64("10010011110xxxxxxxxxxxxxxxxxxxxx", InstName.Extr, InstEmit.Extr, typeof(OpCodeAluRs));
SetA64("11010101000000110010xxxxxxx11111", InstName.Hint, null, typeof(OpCodeSystem));
SetA64("11010101000000110011xxxx11011111", InstName.Isb, null, typeof(OpCodeSystem));
SetA64("xx001000110xxxxx1xxxxxxxxxxxxxxx", InstName.Ldar, null, typeof(OpCodeMemEx));
SetA64("1x001000011xxxxx1xxxxxxxxxxxxxxx", InstName.Ldaxp, null, typeof(OpCodeMemEx));
SetA64("xx001000010xxxxx1xxxxxxxxxxxxxxx", InstName.Ldaxr, null, typeof(OpCodeMemEx));
SetA64("11010101000000110010xxxxxxx11111", InstName.Hint, InstEmit.Hint, typeof(OpCodeSystem));
SetA64("11010101000000110011xxxx11011111", InstName.Isb, InstEmit.Isb, typeof(OpCodeSystem));
SetA64("xx001000110xxxxx1xxxxxxxxxxxxxxx", InstName.Ldar, InstEmit.Ldar, typeof(OpCodeMemEx));
SetA64("1x001000011xxxxx1xxxxxxxxxxxxxxx", InstName.Ldaxp, InstEmit.Ldaxp, typeof(OpCodeMemEx));
SetA64("xx001000010xxxxx1xxxxxxxxxxxxxxx", InstName.Ldaxr, InstEmit.Ldaxr, typeof(OpCodeMemEx));
SetA64("<<10100xx1xxxxxxxxxxxxxxxxxxxxxx", InstName.Ldp, InstEmit.Ldp, typeof(OpCodeMemPair));
SetA64("xx111000010xxxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit.Ldr, typeof(OpCodeMemImm));
SetA64("xx11100101xxxxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit.Ldr, typeof(OpCodeMemImm));
@ -121,8 +121,8 @@ namespace ARMeilleure.Decoders
SetA64("1011100110xxxxxxxxxxxxxxxxxxxxxx", InstName.Ldrs, InstEmit.Ldrs, typeof(OpCodeMemImm));
SetA64("0x1110001x1xxxxxxxxx10xxxxxxxxxx", InstName.Ldrs, InstEmit.Ldrs, typeof(OpCodeMemReg));
SetA64("10111000101xxxxxxxxx10xxxxxxxxxx", InstName.Ldrs, InstEmit.Ldrs, typeof(OpCodeMemReg));
SetA64("xx001000010xxxxx0xxxxxxxxxxxxxxx", InstName.Ldxr, null, typeof(OpCodeMemEx));
SetA64("1x001000011xxxxx0xxxxxxxxxxxxxxx", InstName.Ldxp, null, typeof(OpCodeMemEx));
SetA64("xx001000010xxxxx0xxxxxxxxxxxxxxx", InstName.Ldxr, InstEmit.Ldxr, typeof(OpCodeMemEx));
SetA64("1x001000011xxxxx0xxxxxxxxxxxxxxx", InstName.Ldxp, InstEmit.Ldxp, typeof(OpCodeMemEx));
SetA64("x0011010110xxxxx001000xxxxxxxxxx", InstName.Lslv, InstEmit.Lslv, typeof(OpCodeAluRs));
SetA64("x0011010110xxxxx001001xxxxxxxxxx", InstName.Lsrv, InstEmit.Lsrv, typeof(OpCodeAluRs));
SetA64("x0011011000xxxxx0xxxxxxxxxxxxxxx", InstName.Madd, InstEmit.Madd, typeof(OpCodeMul));
@ -132,19 +132,19 @@ namespace ARMeilleure.Decoders
SetA64("100100101xxxxxxxxxxxxxxxxxxxxxxx", InstName.Movn, InstEmit.Movn, typeof(OpCodeMov));
SetA64("0101001010xxxxxxxxxxxxxxxxxxxxxx", InstName.Movz, InstEmit.Movz, typeof(OpCodeMov));
SetA64("110100101xxxxxxxxxxxxxxxxxxxxxxx", InstName.Movz, InstEmit.Movz, typeof(OpCodeMov));
SetA64("110101010011xxxxxxxxxxxxxxxxxxxx", InstName.Mrs, null, typeof(OpCodeSystem));
SetA64("110101010001xxxxxxxxxxxxxxxxxxxx", InstName.Msr, null, typeof(OpCodeSystem));
SetA64("110101010011xxxxxxxxxxxxxxxxxxxx", InstName.Mrs, InstEmit.Mrs, typeof(OpCodeSystem));
SetA64("110101010001xxxxxxxxxxxxxxxxxxxx", InstName.Msr, InstEmit.Msr, typeof(OpCodeSystem));
SetA64("x0011011000xxxxx1xxxxxxxxxxxxxxx", InstName.Msub, InstEmit.Msub, typeof(OpCodeMul));
SetA64("11010101000000110010000000011111", InstName.Nop, null, typeof(OpCodeSystem));
SetA64("11010101000000110010000000011111", InstName.Nop, InstEmit.Nop, typeof(OpCodeSystem));
SetA64("00101010xx1xxxxx0xxxxxxxxxxxxxxx", InstName.Orn, InstEmit.Orn, typeof(OpCodeAluRs));
SetA64("10101010xx1xxxxxxxxxxxxxxxxxxxxx", InstName.Orn, InstEmit.Orn, typeof(OpCodeAluRs));
SetA64("0011001000xxxxxxxxxxxxxxxxxxxxxx", InstName.Orr, InstEmit.Orr, typeof(OpCodeAluImm));
SetA64("101100100xxxxxxxxxxxxxxxxxxxxxxx", InstName.Orr, InstEmit.Orr, typeof(OpCodeAluImm));
SetA64("00101010xx0xxxxx0xxxxxxxxxxxxxxx", InstName.Orr, InstEmit.Orr, typeof(OpCodeAluRs));
SetA64("10101010xx0xxxxxxxxxxxxxxxxxxxxx", InstName.Orr, InstEmit.Orr, typeof(OpCodeAluRs));
SetA64("1111100110xxxxxxxxxxxxxxxxxxxxxx", InstName.Pfrm, null, typeof(OpCodeMemImm));
SetA64("11111000100xxxxxxxxx00xxxxxxxxxx", InstName.Pfrm, null, typeof(OpCodeMemImm));
SetA64("11011000xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pfrm, null, typeof(OpCodeMemLit));
SetA64("1111100110xxxxxxxxxxxxxxxxxxxxxx", InstName.Pfrm, InstEmit.Pfrm, typeof(OpCodeMemImm));
SetA64("11111000100xxxxxxxxx00xxxxxxxxxx", InstName.Pfrm, InstEmit.Pfrm, typeof(OpCodeMemImm));
SetA64("11011000xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pfrm, InstEmit.Pfrm, typeof(OpCodeMemLit));
SetA64("x101101011000000000000xxxxxxxxxx", InstName.Rbit, InstEmit.Rbit, typeof(OpCodeAlu));
SetA64("1101011001011111000000xxxxx00000", InstName.Ret, InstEmit.Ret, typeof(OpCodeBReg));
SetA64("x101101011000000000001xxxxxxxxxx", InstName.Rev16, InstEmit.Rev16, typeof(OpCodeAlu));
@ -159,15 +159,15 @@ namespace ARMeilleure.Decoders
SetA64("10011011001xxxxx0xxxxxxxxxxxxxxx", InstName.Smaddl, InstEmit.Smaddl, typeof(OpCodeMul));
SetA64("10011011001xxxxx1xxxxxxxxxxxxxxx", InstName.Smsubl, InstEmit.Smsubl, typeof(OpCodeMul));
SetA64("10011011010xxxxx0xxxxxxxxxxxxxxx", InstName.Smulh, InstEmit.Smulh, typeof(OpCodeMul));
SetA64("xx001000100xxxxx1xxxxxxxxxxxxxxx", InstName.Stlr, null, typeof(OpCodeMemEx));
SetA64("1x001000001xxxxx1xxxxxxxxxxxxxxx", InstName.Stlxp, null, typeof(OpCodeMemEx));
SetA64("xx001000000xxxxx1xxxxxxxxxxxxxxx", InstName.Stlxr, null, typeof(OpCodeMemEx));
SetA64("xx001000100xxxxx1xxxxxxxxxxxxxxx", InstName.Stlr, InstEmit.Stlr, typeof(OpCodeMemEx));
SetA64("1x001000001xxxxx1xxxxxxxxxxxxxxx", InstName.Stlxp, InstEmit.Stlxp, typeof(OpCodeMemEx));
SetA64("xx001000000xxxxx1xxxxxxxxxxxxxxx", InstName.Stlxr, InstEmit.Stlxr, typeof(OpCodeMemEx));
SetA64("x010100xx0xxxxxxxxxxxxxxxxxxxxxx", InstName.Stp, InstEmit.Stp, typeof(OpCodeMemPair));
SetA64("xx111000000xxxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeMemImm));
SetA64("xx11100100xxxxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeMemImm));
SetA64("xx111000001xxxxxxxxx10xxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeMemReg));
SetA64("1x001000001xxxxx0xxxxxxxxxxxxxxx", InstName.Stxp, null, typeof(OpCodeMemEx));
SetA64("xx001000000xxxxx0xxxxxxxxxxxxxxx", InstName.Stxr, null, typeof(OpCodeMemEx));
SetA64("1x001000001xxxxx0xxxxxxxxxxxxxxx", InstName.Stxp, InstEmit.Stxp, typeof(OpCodeMemEx));
SetA64("xx001000000xxxxx0xxxxxxxxxxxxxxx", InstName.Stxr, InstEmit.Stxr, typeof(OpCodeMemEx));
SetA64("x10100010xxxxxxxxxxxxxxxxxxxxxxx", InstName.Sub, InstEmit.Sub, typeof(OpCodeAluImm));
SetA64("01001011<<0xxxxx0xxxxxxxxxxxxxxx", InstName.Sub, InstEmit.Sub, typeof(OpCodeAluRs));
SetA64("11001011<<0xxxxxxxxxxxxxxxxxxxxx", InstName.Sub, InstEmit.Sub, typeof(OpCodeAluRs));
@ -179,7 +179,7 @@ namespace ARMeilleure.Decoders
SetA64("x1101011001xxxxxxxx0xxxxxxxxxxxx", InstName.Subs, InstEmit.Subs, typeof(OpCodeAluRx));
SetA64("x1101011001xxxxxxxx100xxxxxxxxxx", InstName.Subs, InstEmit.Subs, typeof(OpCodeAluRx));
SetA64("11010100000xxxxxxxxxxxxxxxx00001", InstName.Svc, InstEmit.Svc, typeof(OpCodeException));
SetA64("1101010100001xxxxxxxxxxxxxxxxxxx", InstName.Sys, null, typeof(OpCodeSystem));
SetA64("1101010100001xxxxxxxxxxxxxxxxxxx", InstName.Sys, InstEmit.Sys, typeof(OpCodeSystem));
SetA64("x0110111xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tbnz, InstEmit.Tbnz, typeof(OpCodeBImmTest));
SetA64("x0110110xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tbz, InstEmit.Tbz, typeof(OpCodeBImmTest));
SetA64("01010011000xxxxx0xxxxxxxxxxxxxxx", InstName.Ubfm, InstEmit.Ubfm, typeof(OpCodeBfm));
@ -362,17 +362,17 @@ namespace ARMeilleure.Decoders
SetA64("0>0011101<1xxxxx110101xxxxxxxxxx", InstName.Fsub_V, InstEmit.Fsub_V, typeof(OpCodeSimdReg));
SetA64("01001110000xxxxx000111xxxxxxxxxx", InstName.Ins_Gp, InstEmit.Ins_Gp, typeof(OpCodeSimdIns));
SetA64("01101110000xxxxx0xxxx1xxxxxxxxxx", InstName.Ins_V, InstEmit.Ins_V, typeof(OpCodeSimdIns));
SetA64("0x00110001000000xxxxxxxxxxxxxxxx", InstName.Ld__Vms, null, typeof(OpCodeSimdMemMs));
SetA64("0x001100110xxxxxxxxxxxxxxxxxxxxx", InstName.Ld__Vms, null, typeof(OpCodeSimdMemMs));
SetA64("0x00110101x00000xxxxxxxxxxxxxxxx", InstName.Ld__Vss, null, typeof(OpCodeSimdMemSs));
SetA64("0x00110111xxxxxxxxxxxxxxxxxxxxxx", InstName.Ld__Vss, null, typeof(OpCodeSimdMemSs));
SetA64("xx10110xx1xxxxxxxxxxxxxxxxxxxxxx", InstName.Ldp, null, typeof(OpCodeSimdMemPair));
SetA64("xx111100x10xxxxxxxxx00xxxxxxxxxx", InstName.Ldr, null, typeof(OpCodeSimdMemImm));
SetA64("xx111100x10xxxxxxxxx01xxxxxxxxxx", InstName.Ldr, null, typeof(OpCodeSimdMemImm));
SetA64("xx111100x10xxxxxxxxx11xxxxxxxxxx", InstName.Ldr, null, typeof(OpCodeSimdMemImm));
SetA64("xx111101x1xxxxxxxxxxxxxxxxxxxxxx", InstName.Ldr, null, typeof(OpCodeSimdMemImm));
SetA64("xx111100x11xxxxxxxxx10xxxxxxxxxx", InstName.Ldr, null, typeof(OpCodeSimdMemReg));
SetA64("xx011100xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ldr_Literal, null, typeof(OpCodeSimdMemLit));
SetA64("0x00110001000000xxxxxxxxxxxxxxxx", InstName.Ld__Vms, InstEmit.Ld__Vms, typeof(OpCodeSimdMemMs));
SetA64("0x001100110xxxxxxxxxxxxxxxxxxxxx", InstName.Ld__Vms, InstEmit.Ld__Vms, typeof(OpCodeSimdMemMs));
SetA64("0x00110101x00000xxxxxxxxxxxxxxxx", InstName.Ld__Vss, InstEmit.Ld__Vss, typeof(OpCodeSimdMemSs));
SetA64("0x00110111xxxxxxxxxxxxxxxxxxxxxx", InstName.Ld__Vss, InstEmit.Ld__Vss, typeof(OpCodeSimdMemSs));
SetA64("xx10110xx1xxxxxxxxxxxxxxxxxxxxxx", InstName.Ldp, InstEmit.Ldp, typeof(OpCodeSimdMemPair));
SetA64("xx111100x10xxxxxxxxx00xxxxxxxxxx", InstName.Ldr, InstEmit.Ldr, typeof(OpCodeSimdMemImm));
SetA64("xx111100x10xxxxxxxxx01xxxxxxxxxx", InstName.Ldr, InstEmit.Ldr, typeof(OpCodeSimdMemImm));
SetA64("xx111100x10xxxxxxxxx11xxxxxxxxxx", InstName.Ldr, InstEmit.Ldr, typeof(OpCodeSimdMemImm));
SetA64("xx111101x1xxxxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit.Ldr, typeof(OpCodeSimdMemImm));
SetA64("xx111100x11xxxxxxxxx10xxxxxxxxxx", InstName.Ldr, InstEmit.Ldr, typeof(OpCodeSimdMemReg));
SetA64("xx011100xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ldr_Literal, InstEmit.Ldr_Literal, typeof(OpCodeSimdMemLit));
SetA64("0x001110<<1xxxxx100101xxxxxxxxxx", InstName.Mla_V, InstEmit.Mla_V, typeof(OpCodeSimdReg));
SetA64("0x101111xxxxxxxx0000x0xxxxxxxxxx", InstName.Mla_Ve, InstEmit.Mla_Ve, typeof(OpCodeSimdRegElem));
SetA64("0x101110<<1xxxxx100101xxxxxxxxxx", InstName.Mls_V, InstEmit.Mls_V, typeof(OpCodeSimdReg));
@ -496,16 +496,16 @@ namespace ARMeilleure.Decoders
SetA64("0100111101xxxxxx000101xxxxxxxxxx", InstName.Ssra_V, InstEmit.Ssra_V, typeof(OpCodeSimdShImm));
SetA64("0x001110<<1xxxxx001000xxxxxxxxxx", InstName.Ssubl_V, InstEmit.Ssubl_V, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx001100xxxxxxxxxx", InstName.Ssubw_V, InstEmit.Ssubw_V, typeof(OpCodeSimdReg));
SetA64("0x00110000000000xxxxxxxxxxxxxxxx", InstName.St__Vms, null, typeof(OpCodeSimdMemMs));
SetA64("0x001100100xxxxxxxxxxxxxxxxxxxxx", InstName.St__Vms, null, typeof(OpCodeSimdMemMs));
SetA64("0x00110100x00000xxxxxxxxxxxxxxxx", InstName.St__Vss, null, typeof(OpCodeSimdMemSs));
SetA64("0x00110110xxxxxxxxxxxxxxxxxxxxxx", InstName.St__Vss, null, typeof(OpCodeSimdMemSs));
SetA64("xx10110xx0xxxxxxxxxxxxxxxxxxxxxx", InstName.Stp, null, typeof(OpCodeSimdMemPair));
SetA64("xx111100x00xxxxxxxxx00xxxxxxxxxx", InstName.Str, null, typeof(OpCodeSimdMemImm));
SetA64("xx111100x00xxxxxxxxx01xxxxxxxxxx", InstName.Str, null, typeof(OpCodeSimdMemImm));
SetA64("xx111100x00xxxxxxxxx11xxxxxxxxxx", InstName.Str, null, typeof(OpCodeSimdMemImm));
SetA64("xx111101x0xxxxxxxxxxxxxxxxxxxxxx", InstName.Str, null, typeof(OpCodeSimdMemImm));
SetA64("xx111100x01xxxxxxxxx10xxxxxxxxxx", InstName.Str, null, typeof(OpCodeSimdMemReg));
SetA64("0x00110000000000xxxxxxxxxxxxxxxx", InstName.St__Vms, InstEmit.St__Vms, typeof(OpCodeSimdMemMs));
SetA64("0x001100100xxxxxxxxxxxxxxxxxxxxx", InstName.St__Vms, InstEmit.St__Vms, typeof(OpCodeSimdMemMs));
SetA64("0x00110100x00000xxxxxxxxxxxxxxxx", InstName.St__Vss, InstEmit.St__Vss, typeof(OpCodeSimdMemSs));
SetA64("0x00110110xxxxxxxxxxxxxxxxxxxxxx", InstName.St__Vss, InstEmit.St__Vss, typeof(OpCodeSimdMemSs));
SetA64("xx10110xx0xxxxxxxxxxxxxxxxxxxxxx", InstName.Stp, InstEmit.Stp, typeof(OpCodeSimdMemPair));
SetA64("xx111100x00xxxxxxxxx00xxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeSimdMemImm));
SetA64("xx111100x00xxxxxxxxx01xxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeSimdMemImm));
SetA64("xx111100x00xxxxxxxxx11xxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeSimdMemImm));
SetA64("xx111101x0xxxxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeSimdMemImm));
SetA64("xx111100x01xxxxxxxxx10xxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeSimdMemReg));
SetA64("01111110111xxxxx100001xxxxxxxxxx", InstName.Sub_S, InstEmit.Sub_S, typeof(OpCodeSimdReg));
SetA64("0>101110<<1xxxxx100001xxxxxxxxxx", InstName.Sub_V, InstEmit.Sub_V, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx011000xxxxxxxxxx", InstName.Subhn_V, InstEmit.Subhn_V, typeof(OpCodeSimdReg));

View file

@ -102,7 +102,7 @@ namespace ARMeilleure.Instructions
Operand address = GetAddress(context);
EmitStore(context, address, op.Rt, op.Size);
InstEmitMemoryHelper.EmitStore(context, address, op.Rt, op.Size);
EmitWBackIfNeeded(context, address);
}
@ -115,8 +115,8 @@ namespace ARMeilleure.Instructions
Operand address2 = context.Add(address, Const(1L << op.Size));
EmitStore(context, address, op.Rt, op.Size);
EmitStore(context, address2, op.Rt2, op.Size);
InstEmitMemoryHelper.EmitStore(context, address, op.Rt, op.Size);
InstEmitMemoryHelper.EmitStore(context, address2, op.Rt2, op.Size);
EmitWBackIfNeeded(context, address);
}
@ -129,7 +129,7 @@ namespace ARMeilleure.Instructions
{
case OpCodeMemImm op:
{
address = GetIntOrSP(op, op.Rn);
address = context.Copy(GetIntOrSP(op, op.Rn));
//Pre-indexing.
if (!op.PostIdx)

View file

@ -0,0 +1,268 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System;
using System.Diagnostics;
using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
namespace ARMeilleure.Instructions
{
static partial class InstEmit
{
[Flags]
private enum AccessType
{
None = 0,
Ordered = 1,
Exclusive = 2,
OrderedEx = Ordered | Exclusive
}
public static void Clrex(EmitterContext context)
{
MethodInfo info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ClearExclusive));
context.Call(info);
}
public static void Dmb(EmitterContext context) => EmitBarrier(context);
public static void Dsb(EmitterContext context) => EmitBarrier(context);
public static void Ldar(EmitterContext context) => EmitLdr(context, AccessType.Ordered);
public static void Ldaxr(EmitterContext context) => EmitLdr(context, AccessType.OrderedEx);
public static void Ldxr(EmitterContext context) => EmitLdr(context, AccessType.Exclusive);
public static void Ldxp(EmitterContext context) => EmitLdp(context, AccessType.Exclusive);
public static void Ldaxp(EmitterContext context) => EmitLdp(context, AccessType.OrderedEx);
private static void EmitLdr(EmitterContext context, AccessType accType)
{
EmitLoadEx(context, accType, pair: false);
}
private static void EmitLdp(EmitterContext context, AccessType accType)
{
EmitLoadEx(context, accType, pair: true);
}
private static void EmitLoadEx(EmitterContext context, AccessType accType, bool pair)
{
OpCodeMemEx op = (OpCodeMemEx)context.CurrOp;
bool ordered = (accType & AccessType.Ordered) != 0;
bool exclusive = (accType & AccessType.Exclusive) != 0;
if (ordered)
{
EmitBarrier(context);
}
Operand address = context.Copy(GetIntOrSP(op, op.Rn));
if (pair)
{
//Exclusive loads should be atomic. For pairwise loads, we need to
//read all the data at once. For a 32-bits pairwise load, we do a
//simple 64-bits load, for a 128-bits load, we need to call a special
//method to read 128-bits atomically.
if (op.Size == 2)
{
Operand value = EmitLoad(context, address, exclusive, 3);
Operand valueLow = context.Copy(Local(OperandType.I32), value);
valueLow = context.Copy(Local(OperandType.I64), valueLow);
Operand valueHigh = context.ShiftRightUI(value, Const(32));
SetIntOrZR(context, op.Rt, valueLow);
SetIntOrZR(context, op.Rt2, valueHigh);
}
else if (op.Size == 3)
{
Operand value = EmitLoad(context, address, exclusive, 4);
Operand valueLow = context.VectorExtract(value, Local(OperandType.I64), 0);
Operand valueHigh = context.VectorExtract(value, Local(OperandType.I64), 1);
SetIntOrZR(context, op.Rt, valueLow);
SetIntOrZR(context, op.Rt2, valueHigh);
}
else
{
throw new InvalidOperationException($"Invalid load size of {1 << op.Size} bytes.");
}
}
else
{
//8, 16, 32 or 64-bits (non-pairwise) load.
Operand value = EmitLoad(context, address, exclusive, op.Size);
SetIntOrZR(context, op.Rt, value);
}
}
private static Operand EmitLoad(
EmitterContext context,
Operand address,
bool exclusive,
int size)
{
string fallbackMethodName = null;
if (exclusive)
{
switch (size)
{
case 0: fallbackMethodName = nameof(NativeInterface.ReadByteExclusive); break;
case 1: fallbackMethodName = nameof(NativeInterface.ReadUInt16Exclusive); break;
case 2: fallbackMethodName = nameof(NativeInterface.ReadUInt32Exclusive); break;
case 3: fallbackMethodName = nameof(NativeInterface.ReadUInt64Exclusive); break;
case 4: fallbackMethodName = nameof(NativeInterface.ReadVector128Exclusive); break;
}
}
else
{
switch (size)
{
case 0: fallbackMethodName = nameof(NativeInterface.ReadByte); break;
case 1: fallbackMethodName = nameof(NativeInterface.ReadUInt16); break;
case 2: fallbackMethodName = nameof(NativeInterface.ReadUInt32); break;
case 3: fallbackMethodName = nameof(NativeInterface.ReadUInt64); break;
case 4: fallbackMethodName = nameof(NativeInterface.ReadVector128); break;
}
}
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
return context.Call(info, address);
}
public static void Pfrm(EmitterContext context)
{
//Memory Prefetch, execute as no-op.
}
public static void Stlr(EmitterContext context) => EmitStr(context, AccessType.Ordered);
public static void Stlxr(EmitterContext context) => EmitStr(context, AccessType.OrderedEx);
public static void Stxr(EmitterContext context) => EmitStr(context, AccessType.Exclusive);
public static void Stxp(EmitterContext context) => EmitStp(context, AccessType.Exclusive);
public static void Stlxp(EmitterContext context) => EmitStp(context, AccessType.OrderedEx);
private static void EmitStr(EmitterContext context, AccessType accType)
{
EmitStoreEx(context, accType, pair: false);
}
private static void EmitStp(EmitterContext context, AccessType accType)
{
EmitStoreEx(context, accType, pair: true);
}
private static void EmitStoreEx(EmitterContext context, AccessType accType, bool pair)
{
OpCodeMemEx op = (OpCodeMemEx)context.CurrOp;
bool ordered = (accType & AccessType.Ordered) != 0;
bool exclusive = (accType & AccessType.Exclusive) != 0;
if (ordered)
{
EmitBarrier(context);
}
Operand address = context.Copy(GetIntOrSP(op, op.Rn));
Operand t = GetIntOrZR(op, op.Rt);
Operand s = null;
if (pair)
{
Debug.Assert(op.Size == 2 || op.Size == 3, "Invalid size for pairwise store.");
Operand t2 = GetIntOrZR(op, op.Rt2);
Operand value;
if (op.Size == 2)
{
value = context.BitwiseOr(t, context.ShiftLeft(t2, Const(32)));
}
else /* if (op.Size == 3) */
{
value = context.VectorInsert(context.VectorZero(), t, 0);
value = context.VectorInsert(value, t2, 1);
}
s = EmitStore(context, address, value, exclusive, op.Size + 1);
}
else
{
s = EmitStore(context, address, t, exclusive, op.Size);
}
if (s != null)
{
//This is only needed for exclusive stores. The function returns 0
//when the store is successful, and 1 otherwise.
SetIntOrZR(context, op.Rs, s);
}
}
private static Operand EmitStore(
EmitterContext context,
Operand address,
Operand value,
bool exclusive,
int size)
{
if (size < 3)
{
value = context.Copy(Local(OperandType.I32), value);
}
string fallbackMethodName = null;
if (exclusive)
{
switch (size)
{
case 0: fallbackMethodName = nameof(NativeInterface.WriteByteExclusive); break;
case 1: fallbackMethodName = nameof(NativeInterface.WriteUInt16Exclusive); break;
case 2: fallbackMethodName = nameof(NativeInterface.WriteUInt32Exclusive); break;
case 3: fallbackMethodName = nameof(NativeInterface.WriteUInt64Exclusive); break;
case 4: fallbackMethodName = nameof(NativeInterface.WriteVector128Exclusive); break;
}
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
return context.Call(info, address, value);
}
else
{
switch (size)
{
case 0: fallbackMethodName = nameof(NativeInterface.WriteByte); break;
case 1: fallbackMethodName = nameof(NativeInterface.WriteUInt16); break;
case 2: fallbackMethodName = nameof(NativeInterface.WriteUInt32); break;
case 3: fallbackMethodName = nameof(NativeInterface.WriteUInt64); break;
case 4: fallbackMethodName = nameof(NativeInterface.WriteVector128); break;
}
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
return null;
}
}
private static void EmitBarrier(EmitterContext context)
{
//Note: This barrier is most likely not necessary, and probably
//doesn't make any difference since we need to do a ton of stuff
//(software MMU emulation) to read or write anything anyway.
}
}
}

View file

@ -50,11 +50,11 @@ namespace ARMeilleure.Instructions
{
if (ForceFallback || !Optimizations.UseSse2 || size < 2)
{
EmitReadVectorFallback(context, address, rt, size);
EmitReadVectorFallback(context, address, context.VectorZero(), rt, 0, size);
}
else
{
EmitReadVector(context, address, rt, size);
EmitReadVector(context, address, context.VectorZero(), rt, 0, size);
}
}
else
@ -92,6 +92,24 @@ namespace ARMeilleure.Instructions
}
}
public static void EmitLoadSimd(
EmitterContext context,
Operand address,
Operand vector,
int rt,
int elem,
int size)
{
if (ForceFallback || !Optimizations.UseSse2 || size < 2)
{
EmitReadVectorFallback(context, address, vector, rt, elem, size);
}
else
{
EmitReadVector(context, address, vector, rt, elem, size);
}
}
public static void EmitStore(EmitterContext context, Operand address, int rt, int size)
{
bool isSimd = IsSimd(context);
@ -105,11 +123,11 @@ namespace ARMeilleure.Instructions
{
if (ForceFallback || !Optimizations.UseSse2 || size < 2)
{
EmitWriteVectorFallback(context, address, rt, size);
EmitWriteVectorFallback(context, address, rt, 0, size);
}
else
{
EmitWriteVector(context, address, rt, size);
EmitWriteVector(context, address, rt, 0, size);
}
}
else
@ -125,6 +143,23 @@ namespace ARMeilleure.Instructions
}
}
public static void EmitStoreSimd(
EmitterContext context,
Operand address,
int rt,
int elem,
int size)
{
if (ForceFallback || !Optimizations.UseSse2 || size < 2)
{
EmitWriteVectorFallback(context, address, rt, elem, size);
}
else
{
EmitWriteVector(context, address, rt, elem, size);
}
}
private static bool IsSimd(EmitterContext context)
{
return context.CurrOp is IOpCodeSimd &&
@ -167,7 +202,13 @@ namespace ARMeilleure.Instructions
context.MarkLabel(lblEnd);
}
private static void EmitReadVector(EmitterContext context, Operand address, int rt, int size)
private static void EmitReadVector(
EmitterContext context,
Operand address,
Operand vector,
int rt,
int elem,
int size)
{
Operand isUnalignedAddr = EmitAddressCheck(context, address, size);
@ -179,7 +220,7 @@ namespace ARMeilleure.Instructions
context.MarkLabel(lblSlowPath);
EmitReadVectorFallback(context, address, rt, size);
EmitReadVectorFallback(context, address, vector, rt, elem, size);
context.Branch(lblEnd);
@ -250,7 +291,12 @@ namespace ARMeilleure.Instructions
context.MarkLabel(lblEnd);
}
private static void EmitWriteVector(EmitterContext context, Operand address, int rt, int size)
private static void EmitWriteVector(
EmitterContext context,
Operand address,
int rt,
int elem,
int size)
{
Operand isUnalignedAddr = EmitAddressCheck(context, address, size);
@ -262,7 +308,7 @@ namespace ARMeilleure.Instructions
context.MarkLabel(lblSlowPath);
EmitWriteVectorFallback(context, address, rt, size);
EmitWriteVectorFallback(context, address, rt, elem, size);
context.Branch(lblEnd);
@ -346,35 +392,46 @@ namespace ARMeilleure.Instructions
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
{
address = context.Copy(Local(OperandType.I64), address);
}
context.Copy(GetT(context, rt), context.Call(info, address));
}
private static void EmitReadVectorFallback(EmitterContext context, Operand address, int rt, int size)
private static void EmitReadVectorFallback(
EmitterContext context,
Operand address,
Operand vector,
int rt,
int elem,
int size)
{
string fallbackMethodName = null;
switch (size)
{
case 0: fallbackMethodName = nameof(NativeInterface.ReadVector8); break;
case 1: fallbackMethodName = nameof(NativeInterface.ReadVector16); break;
case 2: fallbackMethodName = nameof(NativeInterface.ReadVector32); break;
case 3: fallbackMethodName = nameof(NativeInterface.ReadVector64); break;
case 0: fallbackMethodName = nameof(NativeInterface.ReadByte); break;
case 1: fallbackMethodName = nameof(NativeInterface.ReadUInt16); break;
case 2: fallbackMethodName = nameof(NativeInterface.ReadUInt32); break;
case 3: fallbackMethodName = nameof(NativeInterface.ReadUInt64); break;
case 4: fallbackMethodName = nameof(NativeInterface.ReadVector128); break;
}
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
Operand value = context.Call(info, address);
if (size < 3)
{
address = context.Copy(Local(OperandType.I64), address);
value = context.Copy(Local(OperandType.I32), value);
}
context.Copy(GetVec(rt), context.Call(info, address));
switch (size)
{
case 0: value = context.VectorInsert8 (vector, value, elem); break;
case 1: value = context.VectorInsert16(vector, value, elem); break;
case 2: value = context.VectorInsert (vector, value, elem); break;
case 3: value = context.VectorInsert (vector, value, elem); break;
}
context.Copy(GetVec(rt), value);
}
private static void EmitWriteIntFallback(EmitterContext context, Operand address, int rt, int size)
@ -391,11 +448,6 @@ namespace ARMeilleure.Instructions
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
{
address = context.Copy(Local(OperandType.I64), address);
}
Operand value = GetT(context, rt);
if (size < 3)
@ -406,27 +458,44 @@ namespace ARMeilleure.Instructions
context.Call(info, address, value);
}
private static void EmitWriteVectorFallback(EmitterContext context, Operand address, int rt, int size)
private static void EmitWriteVectorFallback(
EmitterContext context,
Operand address,
int rt,
int elem,
int size)
{
string fallbackMethodName = null;
switch (size)
{
case 0: fallbackMethodName = nameof(NativeInterface.WriteVector8); break;
case 1: fallbackMethodName = nameof(NativeInterface.WriteVector16); break;
case 2: fallbackMethodName = nameof(NativeInterface.WriteVector32); break;
case 3: fallbackMethodName = nameof(NativeInterface.WriteVector64); break;
case 0: fallbackMethodName = nameof(NativeInterface.WriteByte); break;
case 1: fallbackMethodName = nameof(NativeInterface.WriteUInt16); break;
case 2: fallbackMethodName = nameof(NativeInterface.WriteUInt32); break;
case 3: fallbackMethodName = nameof(NativeInterface.WriteUInt64); break;
case 4: fallbackMethodName = nameof(NativeInterface.WriteVector128); break;
}
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
{
address = context.Copy(Local(OperandType.I64), address);
}
Operand value;
Operand value = GetVec(rt);
if (size < 4)
{
value = Local(size == 3 ? OperandType.I64 : OperandType.I32);
switch (size)
{
case 0: context.VectorExtract8 (GetVec(rt), value, elem); break;
case 1: context.VectorExtract16(GetVec(rt), value, elem); break;
case 2: context.VectorExtract (GetVec(rt), value, elem); break;
case 3: context.VectorExtract (GetVec(rt), value, elem); break;
}
}
else
{
value = GetVec(rt);
}
context.Call(info, address, value);
}

View file

@ -160,7 +160,7 @@ namespace ARMeilleure.Instructions
if (Optimizations.UsePopCnt)
{
de = context.AddIntrinsic(Instruction.X86Popcnt, ne);
de = context.AddIntrinsicLong(Instruction.X86Popcnt, ne);
}
else
{

View file

@ -1440,8 +1440,7 @@ namespace ARMeilleure.Instructions
{
ThrowIfInvalid(index, size);
Operand res = Local(size == 3 ? OperandType.I64
: OperandType.I32);
Operand res = Local(size == 3 ? OperandType.I64 : OperandType.I32);
switch (size)
{

View file

@ -0,0 +1,160 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
using System.Diagnostics;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitMemoryHelper;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
namespace ARMeilleure.Instructions
{
static partial class InstEmit
{
public static void Ld__Vms(EmitterContext context)
{
EmitSimdMemMs(context, isLoad: true);
}
public static void Ld__Vss(EmitterContext context)
{
EmitSimdMemSs(context, isLoad: true);
}
public static void St__Vms(EmitterContext context)
{
EmitSimdMemMs(context, isLoad: false);
}
public static void St__Vss(EmitterContext context)
{
EmitSimdMemSs(context, isLoad: false);
}
private static void EmitSimdMemMs(EmitterContext context, bool isLoad)
{
OpCodeSimdMemMs op = (OpCodeSimdMemMs)context.CurrOp;
Operand n = GetIntOrSP(op, op.Rn);
long offset = 0;
for (int rep = 0; rep < op.Reps; rep++)
for (int elem = 0; elem < op.Elems; elem++)
for (int sElem = 0; sElem < op.SElems; sElem++)
{
int rtt = (op.Rt + rep + sElem) & 0x1f;
Operand tt = GetVec(rtt);
Operand address = context.Add(n, Const(offset));
if (isLoad)
{
EmitLoadSimd(context, address, tt, rtt, elem, op.Size);
if (op.RegisterSize == RegisterSize.Simd64 && elem == op.Elems - 1)
{
context.Copy(tt, context.VectorZeroUpper64(tt));
}
}
else
{
EmitStoreSimd(context, address, rtt, elem, op.Size);
}
offset += 1 << op.Size;
}
if (op.WBack)
{
EmitSimdMemWBack(context, offset);
}
}
private static void EmitSimdMemSs(EmitterContext context, bool isLoad)
{
OpCodeSimdMemSs op = (OpCodeSimdMemSs)context.CurrOp;
Operand n = GetIntOrSP(op, op.Rn);
long offset = 0;
if (op.Replicate)
{
//Only loads uses the replicate mode.
Debug.Assert(isLoad, "Replicate mode is not valid for stores.");
int elems = op.GetBytesCount() >> op.Size;
for (int sElem = 0; sElem < op.SElems; sElem++)
{
int rt = (op.Rt + sElem) & 0x1f;
Operand t = GetVec(rt);
Operand address = context.Add(n, Const(offset));
for (int index = 0; index < elems; index++)
{
EmitLoadSimd(context, address, t, rt, index, op.Size);
}
if (op.RegisterSize == RegisterSize.Simd64)
{
context.Copy(t, context.VectorZeroUpper64(t));
}
offset += 1 << op.Size;
}
}
else
{
for (int sElem = 0; sElem < op.SElems; sElem++)
{
int rt = (op.Rt + sElem) & 0x1f;
Operand t = GetVec(rt);
Operand address = context.Add(n, Const(offset));
if (isLoad)
{
EmitLoadSimd(context, address, t, rt, op.Index, op.Size);
}
else
{
EmitStoreSimd(context, address, rt, op.Index, op.Size);
}
offset += 1 << op.Size;
}
}
if (op.WBack)
{
EmitSimdMemWBack(context, offset);
}
}
private static void EmitSimdMemWBack(EmitterContext context, long offset)
{
OpCodeMemReg op = (OpCodeMemReg)context.CurrOp;
Operand n = GetIntOrSP(op, op.Rn);
Operand m;
if (op.Rm != RegisterAlias.Zr)
{
m = GetIntOrZR(op, op.Rm);
}
else
{
m = Const(offset);
}
context.Copy(n, context.Add(n, m));
}
}
}

View file

@ -0,0 +1,121 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System;
using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
namespace ARMeilleure.Instructions
{
static partial class InstEmit
{
private const int DczSizeLog2 = 4;
public static void Hint(EmitterContext context)
{
//Execute as no-op.
}
public static void Isb(EmitterContext context)
{
//Execute as no-op.
}
public static void Mrs(EmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
string name;
switch (GetPackedId(op))
{
case 0b11_011_0000_0000_001: name = nameof(NativeInterface.GetCtrEl0); break;
case 0b11_011_0000_0000_111: name = nameof(NativeInterface.GetDczidEl0); break;
case 0b11_011_0100_0100_000: name = nameof(NativeInterface.GetFpcr); break;
case 0b11_011_0100_0100_001: name = nameof(NativeInterface.GetFpsr); break;
case 0b11_011_1101_0000_010: name = nameof(NativeInterface.GetTpidrEl0); break;
case 0b11_011_1101_0000_011: name = nameof(NativeInterface.GetTpidr); break;
case 0b11_011_1110_0000_000: name = nameof(NativeInterface.GetCntfrqEl0); break;
case 0b11_011_1110_0000_001: name = nameof(NativeInterface.GetCntpctEl0); break;
default: throw new NotImplementedException($"Unknown MRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
}
MethodInfo info = typeof(NativeInterface).GetMethod(name);
SetIntOrZR(context, op.Rt, context.Call(info));
}
public static void Msr(EmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
string name;
switch (GetPackedId(op))
{
case 0b11_011_0100_0100_000: name = nameof(NativeInterface.SetFpcr); break;
case 0b11_011_0100_0100_001: name = nameof(NativeInterface.SetFpsr); break;
case 0b11_011_1101_0000_010: name = nameof(NativeInterface.SetTpidrEl0); break;
default: throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
}
MethodInfo info = typeof(NativeInterface).GetMethod(name);
context.Call(info, GetIntOrZR(op, op.Rt));
}
public static void Nop(EmitterContext context)
{
//Do nothing.
}
public static void Sys(EmitterContext context)
{
//This instruction is used to do some operations on the CPU like cache invalidation,
//address translation and the like.
//We treat it as no-op here since we don't have any cache being emulated anyway.
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
switch (GetPackedId(op))
{
case 0b11_011_0111_0100_001:
{
//DC ZVA
Operand t = GetIntOrZR(op, op.Rt);
MethodInfo info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64));
for (long offset = 0; offset < (4 << DczSizeLog2); offset += 8)
{
Operand address = context.Add(t, Const(offset));
context.Call(info, address, Const(0L));
}
break;
}
//No-op
case 0b11_011_0111_1110_001: //DC CIVAC
break;
}
}
private static int GetPackedId(OpCodeSystem op)
{
int id;
id = op.Op2 << 0;
id |= op.CRm << 3;
id |= op.CRn << 7;
id |= op.Op1 << 11;
id |= op.Op0 << 14;
return id;
}
}
}

View file

@ -8,15 +8,23 @@ namespace ARMeilleure.Instructions
{
static class NativeInterface
{
private struct ThreadContext
private const int ErgSizeLog2 = 4;
private class ThreadContext
{
public ExecutionContext Context { get; }
public MemoryManager Memory { get; }
public ulong ExclusiveAddress { get; set; }
public ulong ExclusiveValueLow { get; set; }
public ulong ExclusiveValueHigh { get; set; }
public ThreadContext(ExecutionContext context, MemoryManager memory)
{
Context = context;
Memory = memory;
ExclusiveAddress = ulong.MaxValue;
}
}
@ -52,6 +60,64 @@ namespace ARMeilleure.Instructions
GetContext().OnUndefined(address, opCode);
}
#region "System registers"
public static ulong GetCtrEl0()
{
return (ulong)GetContext().CtrEl0;
}
public static ulong GetDczidEl0()
{
return (ulong)GetContext().DczidEl0;
}
public static ulong GetFpcr()
{
return (ulong)GetContext().Fpcr;
}
public static ulong GetFpsr()
{
return (ulong)GetContext().Fpsr;
}
public static ulong GetTpidrEl0()
{
return (ulong)GetContext().TpidrEl0;
}
public static ulong GetTpidr()
{
return (ulong)GetContext().Tpidr;
}
public static ulong GetCntfrqEl0()
{
return GetContext().CntfrqEl0;
}
public static ulong GetCntpctEl0()
{
return GetContext().CntpctEl0;
}
public static void SetFpcr(ulong value)
{
GetContext().Fpcr = (FPCR)value;
}
public static void SetFpsr(ulong value)
{
GetContext().Fpsr = (FPSR)value;
}
public static void SetTpidrEl0(ulong value)
{
GetContext().TpidrEl0 = (long)value;
}
#endregion
#region "Read"
public static byte ReadByte(ulong address)
{
return GetMemoryManager().ReadByte((long)address);
@ -72,31 +138,80 @@ namespace ARMeilleure.Instructions
return GetMemoryManager().ReadUInt64((long)address);
}
public static V128 ReadVector8(ulong address)
{
return new V128(0); //TODO
}
public static V128 ReadVector16(ulong address)
{
return new V128(0); //TODO
}
public static V128 ReadVector32(ulong address)
{
return new V128(0); //TODO
}
public static V128 ReadVector64(ulong address)
{
return new V128(0); //TODO
}
public static V128 ReadVector128(ulong address)
{
return new V128(0); //TODO
return GetMemoryManager().ReadVector128((long)address);
}
#endregion
#region "Read exclusive"
public static byte ReadByteExclusive(ulong address)
{
ThreadContext context = GetCurrentContext();
byte value = context.Memory.ReadByte((long)address);
context.ExclusiveAddress = GetMaskedExclusiveAddress(address);
context.ExclusiveValueLow = value;
context.ExclusiveValueHigh = 0;
return value;
}
public static ushort ReadUInt16Exclusive(ulong address)
{
ThreadContext context = GetCurrentContext();
ushort value = context.Memory.ReadUInt16((long)address);
context.ExclusiveAddress = GetMaskedExclusiveAddress(address);
context.ExclusiveValueLow = value;
context.ExclusiveValueHigh = 0;
return value;
}
public static uint ReadUInt32Exclusive(ulong address)
{
ThreadContext context = GetCurrentContext();
uint value = context.Memory.ReadUInt32((long)address);
context.ExclusiveAddress = GetMaskedExclusiveAddress(address);
context.ExclusiveValueLow = value;
context.ExclusiveValueHigh = 0;
return value;
}
public static ulong ReadUInt64Exclusive(ulong address)
{
ThreadContext context = GetCurrentContext();
ulong value = context.Memory.ReadUInt64((long)address);
context.ExclusiveAddress = GetMaskedExclusiveAddress(address);
context.ExclusiveValueLow = value;
context.ExclusiveValueHigh = 0;
return value;
}
public static V128 ReadVector128Exclusive(ulong address)
{
ThreadContext context = GetCurrentContext();
V128 value = context.Memory.ReadVector128((long)address);
context.ExclusiveAddress = GetMaskedExclusiveAddress(address);
context.ExclusiveValueLow = value.GetUInt64(0);
context.ExclusiveValueHigh = value.GetUInt64(1);
return value;
}
#endregion
#region "Write"
public static void WriteByte(ulong address, byte value)
{
GetMemoryManager().WriteByte((long)address, value);
@ -117,29 +232,139 @@ namespace ARMeilleure.Instructions
GetMemoryManager().WriteUInt64((long)address, value);
}
public static void WriteVector8(ulong address, V128 value)
{
//TODO
}
public static void WriteVector16(ulong address, V128 value)
{
//TODO
}
public static void WriteVector32(ulong address, V128 value)
{
//TODO
}
public static void WriteVector64(ulong address, V128 value)
{
//TODO
}
public static void WriteVector128(ulong address, V128 value)
{
//TODO
GetMemoryManager().WriteVector128((long)address, value);
}
#endregion
#region "Write exclusive"
public static int WriteByteExclusive(ulong address, byte value)
{
ThreadContext context = GetCurrentContext();
bool success = context.ExclusiveAddress == GetMaskedExclusiveAddress(address);
if (success)
{
success = context.Memory.AtomicCompareExchangeByte(
(long)address,
(byte)value,
(byte)context.ExclusiveValueLow);
if (success)
{
ClearExclusive();
}
}
return success ? 0 : 1;
}
public static int WriteUInt16Exclusive(ulong address, ushort value)
{
ThreadContext context = GetCurrentContext();
bool success = context.ExclusiveAddress == GetMaskedExclusiveAddress(address);
if (success)
{
success = context.Memory.AtomicCompareExchangeInt16(
(long)address,
(short)value,
(short)context.ExclusiveValueLow);
if (success)
{
ClearExclusive();
}
}
return success ? 0 : 1;
}
public static int WriteUInt32Exclusive(ulong address, uint value)
{
ThreadContext context = GetCurrentContext();
bool success = context.ExclusiveAddress == GetMaskedExclusiveAddress(address);
if (success)
{
success = context.Memory.AtomicCompareExchangeInt32(
(long)address,
(int)value,
(int)context.ExclusiveValueLow);
if (success)
{
ClearExclusive();
}
}
return success ? 0 : 1;
}
public static int WriteUInt64Exclusive(ulong address, ulong value)
{
ThreadContext context = GetCurrentContext();
bool success = context.ExclusiveAddress == GetMaskedExclusiveAddress(address);
if (success)
{
success = context.Memory.AtomicCompareExchangeInt64(
(long)address,
(long)value,
(long)context.ExclusiveValueLow);
if (success)
{
ClearExclusive();
}
}
return success ? 0 : 1;
}
public static int WriteVector128Exclusive(ulong address, V128 value)
{
ThreadContext context = GetCurrentContext();
bool success = context.ExclusiveAddress == GetMaskedExclusiveAddress(address);
if (success)
{
success = context.Memory.AtomicCompareExchangeInt128(
(long)address,
value.GetUInt64(0),
value.GetUInt64(1),
context.ExclusiveValueLow,
context.ExclusiveValueHigh);
if (success)
{
ClearExclusive();
}
}
return success ? 0 : 1;
}
#endregion
private static ulong GetMaskedExclusiveAddress(ulong address)
{
return address & ~((4UL << ErgSizeLog2) - 1);
}
public static void ClearExclusive()
{
GetCurrentContext().ExclusiveAddress = ulong.MaxValue;
}
private static ThreadContext GetCurrentContext()
{
return _contexts[Thread.CurrentThread];
}
public static ExecutionContext GetContext()

View file

@ -1,3 +1,4 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
using System.Threading;
@ -466,6 +467,23 @@ namespace ARMeilleure.Memory
return Interlocked.CompareExchange(ref *ptr, desired, expected) == expected;
}
internal bool AtomicCompareExchangeInt128(
long position,
ulong expectedLow,
ulong expectedHigh,
ulong desiredLow,
ulong desiredHigh)
{
if ((position & 0xf) != 0)
{
AbortWithAlignmentFault(position);
}
IntPtr ptr = TranslateWrite(position);
throw new NotImplementedException();
}
public int AtomicIncrementInt32(long position)
{
if ((position & 3) != 0)
@ -560,6 +578,11 @@ namespace ARMeilleure.Memory
}
}
public V128 ReadVector128(long position)
{
return new V128(ReadUInt64(position), ReadUInt64(position + 8));
}
public byte[] ReadBytes(long position, long size)
{
long endAddr = position + size;
@ -697,6 +720,12 @@ namespace ARMeilleure.Memory
}
}
public void WriteVector128(long position, V128 value)
{
WriteUInt64(position + 0, value.GetUInt64(0));
WriteUInt64(position + 8, value.GetUInt64(1));
}
public void WriteBytes(long position, byte[] data)
{
long endAddr = position + data.Length;

View file

@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
namespace ARMeilleure.State
{
@ -8,6 +9,27 @@ namespace ARMeilleure.State
internal IntPtr NativeContextPtr => _nativeContext.BasePtr;
private static Stopwatch _tickCounter;
private static double _hostTickFreq;
public uint CtrEl0 => 0x8444c004;
public uint DczidEl0 => 0x00000004;
public ulong CntfrqEl0 { get; set; }
public ulong CntpctEl0
{
get
{
double ticks = _tickCounter.ElapsedTicks * _hostTickFreq;
return (ulong)(ticks * CntfrqEl0);
}
}
public long TpidrEl0 { get; set; }
public long Tpidr { get; set; }
public FPCR Fpcr { get; set; }
public FPSR Fpsr { get; set; }
@ -15,6 +37,15 @@ namespace ARMeilleure.State
public event EventHandler<InstExceptionEventArgs> SupervisorCall;
public event EventHandler<InstUndefinedEventArgs> Undefined;
static ExecutionContext()
{
_hostTickFreq = 1.0 / Stopwatch.Frequency;
_tickCounter = new Stopwatch();
_tickCounter.Start();
}
public ExecutionContext()
{
_nativeContext = new NativeContext();