More instructions
This commit is contained in:
parent
9f8fbc1d8a
commit
c306809b0b
12 changed files with 1039 additions and 130 deletions
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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)
|
||||
|
|
268
ARMeilleure/Instructions/InstEmitMemoryEx.cs
Normal file
268
ARMeilleure/Instructions/InstEmitMemoryEx.cs
Normal 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.
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (Optimizations.UsePopCnt)
|
||||
{
|
||||
de = context.AddIntrinsic(Instruction.X86Popcnt, ne);
|
||||
de = context.AddIntrinsicLong(Instruction.X86Popcnt, ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
160
ARMeilleure/Instructions/InstEmitSimdMemory.cs
Normal file
160
ARMeilleure/Instructions/InstEmitSimdMemory.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
121
ARMeilleure/Instructions/InstEmitSystem.cs
Normal file
121
ARMeilleure/Instructions/InstEmitSystem.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue