Adjust naming conventions for Ryujinx and ChocolArm64 projects (#484)
* Change naming convention for Ryujinx project * Change naming convention for ChocolArm64 project * Fix NaN * Remove unneeded this. from Ryujinx project * Adjust naming from new PRs * Name changes based on feedback * How did this get removed? * Rebasing fix * Change FP enum case * Remove prefix from ChocolArm64 classes - Part 1 * Remove prefix from ChocolArm64 classes - Part 2 * Fix alignment from last commit's renaming * Rename namespaces * Rename stragglers * Fix alignment * Rename OpCode class * Missed a few * Adjust alignment
This commit is contained in:
parent
5a87e58183
commit
9cb57fb4bb
@ -1,49 +0,0 @@
|
|||||||
namespace ChocolArm64
|
|
||||||
{
|
|
||||||
static class ABitUtils
|
|
||||||
{
|
|
||||||
public static int HighestBitSet32(int Value)
|
|
||||||
{
|
|
||||||
for (int Bit = 31; Bit >= 0; Bit--)
|
|
||||||
{
|
|
||||||
if (((Value >> Bit) & 1) != 0)
|
|
||||||
{
|
|
||||||
return Bit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly sbyte[] HbsNibbleTbl = { -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 };
|
|
||||||
|
|
||||||
public static int HighestBitSetNibble(int Value) => HbsNibbleTbl[Value & 0b1111];
|
|
||||||
|
|
||||||
public static long Replicate(long Bits, int Size)
|
|
||||||
{
|
|
||||||
long Output = 0;
|
|
||||||
|
|
||||||
for (int Bit = 0; Bit < 64; Bit += Size)
|
|
||||||
{
|
|
||||||
Output |= Bits << Bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Output;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long FillWithOnes(int Bits)
|
|
||||||
{
|
|
||||||
return Bits == 64 ? -1L : (1L << Bits) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long RotateRight(long Bits, int Shift, int Size)
|
|
||||||
{
|
|
||||||
return (long)RotateRight((ulong)Bits, Shift, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ulong RotateRight(ulong Bits, int Shift, int Size)
|
|
||||||
{
|
|
||||||
return (Bits >> Shift) | (Bits << (Size - Shift));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,713 +0,0 @@
|
|||||||
using ChocolArm64.Decoder;
|
|
||||||
using ChocolArm64.Decoder32;
|
|
||||||
using ChocolArm64.Instruction;
|
|
||||||
using ChocolArm64.Instruction32;
|
|
||||||
using ChocolArm64.State;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace ChocolArm64
|
|
||||||
{
|
|
||||||
static class AOpCodeTable
|
|
||||||
{
|
|
||||||
static AOpCodeTable()
|
|
||||||
{
|
|
||||||
#region "OpCode Table (AArch32)"
|
|
||||||
//Integer
|
|
||||||
SetA32("<<<<1010xxxxxxxxxxxxxxxxxxxxxxxx", A32InstInterpret.B, typeof(A32OpCodeBImmAl));
|
|
||||||
SetA32("<<<<1011xxxxxxxxxxxxxxxxxxxxxxxx", A32InstInterpret.Bl, typeof(A32OpCodeBImmAl));
|
|
||||||
SetA32("1111101xxxxxxxxxxxxxxxxxxxxxxxxx", A32InstInterpret.Blx, typeof(A32OpCodeBImmAl));
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region "OpCode Table (AArch64)"
|
|
||||||
//Integer
|
|
||||||
SetA64("x0011010000xxxxx000000xxxxxxxxxx", AInstEmit.Adc, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("x0111010000xxxxx000000xxxxxxxxxx", AInstEmit.Adcs, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("x00100010xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluImm));
|
|
||||||
SetA64("00001011<<0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("10001011<<0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("x0001011001xxxxxxxx0xxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRx));
|
|
||||||
SetA64("x0001011001xxxxxxxx100xxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRx));
|
|
||||||
SetA64("x01100010xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluImm));
|
|
||||||
SetA64("00101011<<0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("10101011<<0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("x0101011001xxxxxxxx0xxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluRx));
|
|
||||||
SetA64("x0101011001xxxxxxxx100xxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluRx));
|
|
||||||
SetA64("0xx10000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adr, typeof(AOpCodeAdr));
|
|
||||||
SetA64("1xx10000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adrp, typeof(AOpCodeAdr));
|
|
||||||
SetA64("0001001000xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.And, typeof(AOpCodeAluImm));
|
|
||||||
SetA64("100100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.And, typeof(AOpCodeAluImm));
|
|
||||||
SetA64("00001010xx0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.And, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("10001010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.And, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("0111001000xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ands, typeof(AOpCodeAluImm));
|
|
||||||
SetA64("111100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ands, typeof(AOpCodeAluImm));
|
|
||||||
SetA64("01101010xx0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Ands, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("11101010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ands, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("x0011010110xxxxx001010xxxxxxxxxx", AInstEmit.Asrv, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("000101xxxxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.B, typeof(AOpCodeBImmAl));
|
|
||||||
SetA64("01010100xxxxxxxxxxxxxxxxxxx0xxxx", AInstEmit.B_Cond, typeof(AOpCodeBImmCond));
|
|
||||||
SetA64("00110011000xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Bfm, typeof(AOpCodeBfm));
|
|
||||||
SetA64("1011001101xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Bfm, typeof(AOpCodeBfm));
|
|
||||||
SetA64("00001010xx1xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Bic, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("10001010xx1xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Bic, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("01101010xx1xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Bics, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("11101010xx1xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Bics, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("100101xxxxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Bl, typeof(AOpCodeBImmAl));
|
|
||||||
SetA64("1101011000111111000000xxxxx00000", AInstEmit.Blr, typeof(AOpCodeBReg));
|
|
||||||
SetA64("1101011000011111000000xxxxx00000", AInstEmit.Br, typeof(AOpCodeBReg));
|
|
||||||
SetA64("11010100001xxxxxxxxxxxxxxxx00000", AInstEmit.Brk, typeof(AOpCodeException));
|
|
||||||
SetA64("x0110101xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Cbnz, typeof(AOpCodeBImmCmp));
|
|
||||||
SetA64("x0110100xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Cbz, typeof(AOpCodeBImmCmp));
|
|
||||||
SetA64("x0111010010xxxxxxxxx10xxxxx0xxxx", AInstEmit.Ccmn, typeof(AOpCodeCcmpImm));
|
|
||||||
SetA64("x0111010010xxxxxxxxx00xxxxx0xxxx", AInstEmit.Ccmn, typeof(AOpCodeCcmpReg));
|
|
||||||
SetA64("x1111010010xxxxxxxxx10xxxxx0xxxx", AInstEmit.Ccmp, typeof(AOpCodeCcmpImm));
|
|
||||||
SetA64("x1111010010xxxxxxxxx00xxxxx0xxxx", AInstEmit.Ccmp, typeof(AOpCodeCcmpReg));
|
|
||||||
SetA64("11010101000000110011xxxx01011111", AInstEmit.Clrex, typeof(AOpCodeSystem));
|
|
||||||
SetA64("x101101011000000000101xxxxxxxxxx", AInstEmit.Cls, typeof(AOpCodeAlu));
|
|
||||||
SetA64("x101101011000000000100xxxxxxxxxx", AInstEmit.Clz, typeof(AOpCodeAlu));
|
|
||||||
SetA64("00011010110xxxxx010000xxxxxxxxxx", AInstEmit.Crc32b, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("00011010110xxxxx010001xxxxxxxxxx", AInstEmit.Crc32h, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("00011010110xxxxx010010xxxxxxxxxx", AInstEmit.Crc32w, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("10011010110xxxxx010011xxxxxxxxxx", AInstEmit.Crc32x, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("00011010110xxxxx010100xxxxxxxxxx", AInstEmit.Crc32cb, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("00011010110xxxxx010101xxxxxxxxxx", AInstEmit.Crc32ch, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("00011010110xxxxx010110xxxxxxxxxx", AInstEmit.Crc32cw, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("10011010110xxxxx010111xxxxxxxxxx", AInstEmit.Crc32cx, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("x0011010100xxxxxxxxx00xxxxxxxxxx", AInstEmit.Csel, typeof(AOpCodeCsel));
|
|
||||||
SetA64("x0011010100xxxxxxxxx01xxxxxxxxxx", AInstEmit.Csinc, typeof(AOpCodeCsel));
|
|
||||||
SetA64("x1011010100xxxxxxxxx00xxxxxxxxxx", AInstEmit.Csinv, typeof(AOpCodeCsel));
|
|
||||||
SetA64("x1011010100xxxxxxxxx01xxxxxxxxxx", AInstEmit.Csneg, typeof(AOpCodeCsel));
|
|
||||||
SetA64("11010101000000110011xxxx10111111", AInstEmit.Dmb, typeof(AOpCodeSystem));
|
|
||||||
SetA64("11010101000000110011xxxx10011111", AInstEmit.Dsb, typeof(AOpCodeSystem));
|
|
||||||
SetA64("01001010xx1xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Eon, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("11001010xx1xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eon, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("0101001000xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluImm));
|
|
||||||
SetA64("110100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluImm));
|
|
||||||
SetA64("01001010xx0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("11001010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("00010011100xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Extr, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("10010011110xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Extr, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("11010101000000110010xxxxxxx11111", AInstEmit.Hint, typeof(AOpCodeSystem));
|
|
||||||
SetA64("11010101000000110011xxxx11011111", AInstEmit.Isb, typeof(AOpCodeSystem));
|
|
||||||
SetA64("xx001000110xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldar, typeof(AOpCodeMemEx));
|
|
||||||
SetA64("1x001000011xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldaxp, typeof(AOpCodeMemEx));
|
|
||||||
SetA64("xx001000010xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldaxr, typeof(AOpCodeMemEx));
|
|
||||||
SetA64("<<10100xx1xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldp, typeof(AOpCodeMemPair));
|
|
||||||
SetA64("xx111000010xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeMemImm));
|
|
||||||
SetA64("xx11100101xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeMemImm));
|
|
||||||
SetA64("xx111000011xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeMemReg));
|
|
||||||
SetA64("xx011000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.LdrLit, typeof(AOpCodeMemLit));
|
|
||||||
SetA64("0x1110001x0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemImm));
|
|
||||||
SetA64("0x1110011xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemImm));
|
|
||||||
SetA64("10111000100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemImm));
|
|
||||||
SetA64("1011100110xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemImm));
|
|
||||||
SetA64("0x1110001x1xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemReg));
|
|
||||||
SetA64("10111000101xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemReg));
|
|
||||||
SetA64("xx001000010xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Ldxr, typeof(AOpCodeMemEx));
|
|
||||||
SetA64("1x001000011xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Ldxp, typeof(AOpCodeMemEx));
|
|
||||||
SetA64("x0011010110xxxxx001000xxxxxxxxxx", AInstEmit.Lslv, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("x0011010110xxxxx001001xxxxxxxxxx", AInstEmit.Lsrv, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("x0011011000xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Madd, typeof(AOpCodeMul));
|
|
||||||
SetA64("0111001010xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Movk, typeof(AOpCodeMov));
|
|
||||||
SetA64("111100101xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Movk, typeof(AOpCodeMov));
|
|
||||||
SetA64("0001001010xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Movn, typeof(AOpCodeMov));
|
|
||||||
SetA64("100100101xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Movn, typeof(AOpCodeMov));
|
|
||||||
SetA64("0101001010xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Movz, typeof(AOpCodeMov));
|
|
||||||
SetA64("110100101xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Movz, typeof(AOpCodeMov));
|
|
||||||
SetA64("110101010011xxxxxxxxxxxxxxxxxxxx", AInstEmit.Mrs, typeof(AOpCodeSystem));
|
|
||||||
SetA64("110101010001xxxxxxxxxxxxxxxxxxxx", AInstEmit.Msr, typeof(AOpCodeSystem));
|
|
||||||
SetA64("x0011011000xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Msub, typeof(AOpCodeMul));
|
|
||||||
SetA64("11010101000000110010000000011111", AInstEmit.Nop, typeof(AOpCodeSystem));
|
|
||||||
SetA64("00101010xx1xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Orn, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("10101010xx1xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Orn, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("0011001000xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Orr, typeof(AOpCodeAluImm));
|
|
||||||
SetA64("101100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Orr, typeof(AOpCodeAluImm));
|
|
||||||
SetA64("00101010xx0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Orr, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("10101010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Orr, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("1111100110xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Pfrm, typeof(AOpCodeMemImm));
|
|
||||||
SetA64("11111000100xxxxxxxxx00xxxxxxxxxx", AInstEmit.Pfrm, typeof(AOpCodeMemImm));
|
|
||||||
SetA64("11011000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Pfrm, typeof(AOpCodeMemLit));
|
|
||||||
SetA64("x101101011000000000000xxxxxxxxxx", AInstEmit.Rbit, typeof(AOpCodeAlu));
|
|
||||||
SetA64("1101011001011111000000xxxxx00000", AInstEmit.Ret, typeof(AOpCodeBReg));
|
|
||||||
SetA64("x101101011000000000001xxxxxxxxxx", AInstEmit.Rev16, typeof(AOpCodeAlu));
|
|
||||||
SetA64("x101101011000000000010xxxxxxxxxx", AInstEmit.Rev32, typeof(AOpCodeAlu));
|
|
||||||
SetA64("1101101011000000000011xxxxxxxxxx", AInstEmit.Rev64, typeof(AOpCodeAlu));
|
|
||||||
SetA64("x0011010110xxxxx001011xxxxxxxxxx", AInstEmit.Rorv, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("x1011010000xxxxx000000xxxxxxxxxx", AInstEmit.Sbc, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("x1111010000xxxxx000000xxxxxxxxxx", AInstEmit.Sbcs, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("00010011000xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Sbfm, typeof(AOpCodeBfm));
|
|
||||||
SetA64("1001001101xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sbfm, typeof(AOpCodeBfm));
|
|
||||||
SetA64("x0011010110xxxxx000011xxxxxxxxxx", AInstEmit.Sdiv, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("10011011001xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Smaddl, typeof(AOpCodeMul));
|
|
||||||
SetA64("10011011001xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Smsubl, typeof(AOpCodeMul));
|
|
||||||
SetA64("10011011010xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Smulh, typeof(AOpCodeMul));
|
|
||||||
SetA64("xx001000100xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Stlr, typeof(AOpCodeMemEx));
|
|
||||||
SetA64("1x001000001xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Stlxp, typeof(AOpCodeMemEx));
|
|
||||||
SetA64("xx001000000xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Stlxr, typeof(AOpCodeMemEx));
|
|
||||||
SetA64("x010100xx0xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Stp, typeof(AOpCodeMemPair));
|
|
||||||
SetA64("xx111000000xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeMemImm));
|
|
||||||
SetA64("xx11100100xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeMemImm));
|
|
||||||
SetA64("xx111000001xxxxxxxxx10xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeMemReg));
|
|
||||||
SetA64("1x001000001xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Stxp, typeof(AOpCodeMemEx));
|
|
||||||
SetA64("xx001000000xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Stxr, typeof(AOpCodeMemEx));
|
|
||||||
SetA64("x10100010xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluImm));
|
|
||||||
SetA64("01001011<<0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("11001011<<0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("x1001011001xxxxxxxx0xxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluRx));
|
|
||||||
SetA64("x1001011001xxxxxxxx100xxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluRx));
|
|
||||||
SetA64("x11100010xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluImm));
|
|
||||||
SetA64("01101011<<0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("11101011<<0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("x1101011001xxxxxxxx0xxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluRx));
|
|
||||||
SetA64("x1101011001xxxxxxxx100xxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluRx));
|
|
||||||
SetA64("11010100000xxxxxxxxxxxxxxxx00001", AInstEmit.Svc, typeof(AOpCodeException));
|
|
||||||
SetA64("1101010100001xxxxxxxxxxxxxxxxxxx", AInstEmit.Sys, typeof(AOpCodeSystem));
|
|
||||||
SetA64("x0110111xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Tbnz, typeof(AOpCodeBImmTest));
|
|
||||||
SetA64("x0110110xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Tbz, typeof(AOpCodeBImmTest));
|
|
||||||
SetA64("01010011000xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Ubfm, typeof(AOpCodeBfm));
|
|
||||||
SetA64("1101001101xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ubfm, typeof(AOpCodeBfm));
|
|
||||||
SetA64("x0011010110xxxxx000010xxxxxxxxxx", AInstEmit.Udiv, typeof(AOpCodeAluRs));
|
|
||||||
SetA64("10011011101xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Umaddl, typeof(AOpCodeMul));
|
|
||||||
SetA64("10011011101xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Umsubl, typeof(AOpCodeMul));
|
|
||||||
SetA64("10011011110xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Umulh, typeof(AOpCodeMul));
|
|
||||||
|
|
||||||
//Vector
|
|
||||||
SetA64("0101111011100000101110xxxxxxxxxx", AInstEmit.Abs_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>001110<<100000101110xxxxxxxxxx", AInstEmit.Abs_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("01011110111xxxxx100001xxxxxxxxxx", AInstEmit.Add_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>001110<<1xxxxx100001xxxxxxxxxx", AInstEmit.Add_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<1xxxxx010000xxxxxxxxxx", AInstEmit.Addhn_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0101111011110001101110xxxxxxxxxx", AInstEmit.Addp_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>001110<<1xxxxx101111xxxxxxxxxx", AInstEmit.Addp_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("000011100x110001101110xxxxxxxxxx", AInstEmit.Addv_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("01001110<<110001101110xxxxxxxxxx", AInstEmit.Addv_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0100111000101000010110xxxxxxxxxx", AInstEmit.Aesd_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0100111000101000010010xxxxxxxxxx", AInstEmit.Aese_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0100111000101000011110xxxxxxxxxx", AInstEmit.Aesimc_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0100111000101000011010xxxxxxxxxx", AInstEmit.Aesmc_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x001110001xxxxx000111xxxxxxxxxx", AInstEmit.And_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110011xxxxx000111xxxxxxxxxx", AInstEmit.Bic_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x10111100000xxx<<x101xxxxxxxxxx", AInstEmit.Bic_Vi, typeof(AOpCodeSimdImm));
|
|
||||||
SetA64("0x101110111xxxxx000111xxxxxxxxxx", AInstEmit.Bif_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110101xxxxx000111xxxxxxxxxx", AInstEmit.Bit_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110011xxxxx000111xxxxxxxxxx", AInstEmit.Bsl_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<100000010010xxxxxxxxxx", AInstEmit.Cls_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x101110<<100000010010xxxxxxxxxx", AInstEmit.Clz_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("01111110111xxxxx100011xxxxxxxxxx", AInstEmit.Cmeq_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0101111011100000100110xxxxxxxxxx", AInstEmit.Cmeq_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>101110<<1xxxxx100011xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>001110<<100000100110xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("01011110111xxxxx001111xxxxxxxxxx", AInstEmit.Cmge_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0111111011100000100010xxxxxxxxxx", AInstEmit.Cmge_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>001110<<1xxxxx001111xxxxxxxxxx", AInstEmit.Cmge_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>101110<<100000100010xxxxxxxxxx", AInstEmit.Cmge_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("01011110111xxxxx001101xxxxxxxxxx", AInstEmit.Cmgt_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0101111011100000100010xxxxxxxxxx", AInstEmit.Cmgt_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>001110<<1xxxxx001101xxxxxxxxxx", AInstEmit.Cmgt_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>001110<<100000100010xxxxxxxxxx", AInstEmit.Cmgt_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("01111110111xxxxx001101xxxxxxxxxx", AInstEmit.Cmhi_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>101110<<1xxxxx001101xxxxxxxxxx", AInstEmit.Cmhi_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("01111110111xxxxx001111xxxxxxxxxx", AInstEmit.Cmhs_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>101110<<1xxxxx001111xxxxxxxxxx", AInstEmit.Cmhs_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0111111011100000100110xxxxxxxxxx", AInstEmit.Cmle_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>101110<<100000100110xxxxxxxxxx", AInstEmit.Cmle_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0101111011100000101010xxxxxxxxxx", AInstEmit.Cmlt_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>001110<<100000101010xxxxxxxxxx", AInstEmit.Cmlt_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("01011110111xxxxx100011xxxxxxxxxx", AInstEmit.Cmtst_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>001110<<1xxxxx100011xxxxxxxxxx", AInstEmit.Cmtst_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x00111000100000010110xxxxxxxxxx", AInstEmit.Cnt_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x001110000xxxxx000011xxxxxxxxxx", AInstEmit.Dup_Gp, typeof(AOpCodeSimdIns));
|
|
||||||
SetA64("01011110000xxxxx000001xxxxxxxxxx", AInstEmit.Dup_S, typeof(AOpCodeSimdIns));
|
|
||||||
SetA64("0x001110000xxxxx000001xxxxxxxxxx", AInstEmit.Dup_V, typeof(AOpCodeSimdIns));
|
|
||||||
SetA64("0x101110001xxxxx000111xxxxxxxxxx", AInstEmit.Eor_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>101110000xxxxx0<xxx0xxxxxxxxxx", AInstEmit.Ext_V, typeof(AOpCodeSimdExt));
|
|
||||||
SetA64("011111101x1xxxxx110101xxxxxxxxxx", AInstEmit.Fabd_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("000111100x100000110000xxxxxxxxxx", AInstEmit.Fabs_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>0011101<100000111110xxxxxxxxxx", AInstEmit.Fabs_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("000111100x1xxxxx001010xxxxxxxxxx", AInstEmit.Fadd_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>0011100<1xxxxx110101xxxxxxxxxx", AInstEmit.Fadd_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("011111100x110000110110xxxxxxxxxx", AInstEmit.Faddp_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>1011100<1xxxxx110101xxxxxxxxxx", AInstEmit.Faddp_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("000111100x1xxxxxxxxx01xxxxx0xxxx", AInstEmit.Fccmp_S, typeof(AOpCodeSimdFcond));
|
|
||||||
SetA64("000111100x1xxxxxxxxx01xxxxx1xxxx", AInstEmit.Fccmpe_S, typeof(AOpCodeSimdFcond));
|
|
||||||
SetA64("010111100x1xxxxx111001xxxxxxxxxx", AInstEmit.Fcmeq_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("010111101x100000110110xxxxxxxxxx", AInstEmit.Fcmeq_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>0011100<1xxxxx111001xxxxxxxxxx", AInstEmit.Fcmeq_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>0011101<100000110110xxxxxxxxxx", AInstEmit.Fcmeq_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("011111100x1xxxxx111001xxxxxxxxxx", AInstEmit.Fcmge_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("011111101x100000110010xxxxxxxxxx", AInstEmit.Fcmge_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>1011100<1xxxxx111001xxxxxxxxxx", AInstEmit.Fcmge_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>1011101<100000110010xxxxxxxxxx", AInstEmit.Fcmge_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("011111101x1xxxxx111001xxxxxxxxxx", AInstEmit.Fcmgt_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("010111101x100000110010xxxxxxxxxx", AInstEmit.Fcmgt_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>1011101<1xxxxx111001xxxxxxxxxx", AInstEmit.Fcmgt_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>0011101<100000110010xxxxxxxxxx", AInstEmit.Fcmgt_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("011111101x100000110110xxxxxxxxxx", AInstEmit.Fcmle_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>1011101<100000110110xxxxxxxxxx", AInstEmit.Fcmle_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("010111101x100000111010xxxxxxxxxx", AInstEmit.Fcmlt_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>0011101<100000111010xxxxxxxxxx", AInstEmit.Fcmlt_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("000111100x1xxxxx001000xxxxx0x000", AInstEmit.Fcmp_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("000111100x1xxxxx001000xxxxx1x000", AInstEmit.Fcmpe_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("000111100x1xxxxxxxxx11xxxxxxxxxx", AInstEmit.Fcsel_S, typeof(AOpCodeSimdFcond));
|
|
||||||
SetA64("000111100x10001xx10000xxxxxxxxxx", AInstEmit.Fcvt_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("x00111100x100100000000xxxxxxxxxx", AInstEmit.Fcvtas_Gp, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("x00111100x100101000000xxxxxxxxxx", AInstEmit.Fcvtau_Gp, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("0x0011100x100001011110xxxxxxxxxx", AInstEmit.Fcvtl_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("x00111100x110000000000xxxxxxxxxx", AInstEmit.Fcvtms_Gp, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("x00111100x110001000000xxxxxxxxxx", AInstEmit.Fcvtmu_Gp, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("0x0011100x100001011010xxxxxxxxxx", AInstEmit.Fcvtn_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("010111100x100001101010xxxxxxxxxx", AInstEmit.Fcvtns_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>0011100<100001101010xxxxxxxxxx", AInstEmit.Fcvtns_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("011111100x100001101010xxxxxxxxxx", AInstEmit.Fcvtnu_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>1011100<100001101010xxxxxxxxxx", AInstEmit.Fcvtnu_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("x00111100x101000000000xxxxxxxxxx", AInstEmit.Fcvtps_Gp, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("x00111100x101001000000xxxxxxxxxx", AInstEmit.Fcvtpu_Gp, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("x00111100x111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_Gp, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("x00111100x011000xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzs_Gp_Fix, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("010111101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>0011101<100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x0011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("x00111100x111001000000xxxxxxxxxx", AInstEmit.Fcvtzu_Gp, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("x00111100x011001xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzu_Gp_Fix, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("011111101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzu_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>1011101<100001101110xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x1011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("000111100x1xxxxx000110xxxxxxxxxx", AInstEmit.Fdiv_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>1011100<1xxxxx111111xxxxxxxxxx", AInstEmit.Fdiv_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("000111110x0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Fmadd_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("000111100x1xxxxx010010xxxxxxxxxx", AInstEmit.Fmax_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>0011100<1xxxxx111101xxxxxxxxxx", AInstEmit.Fmax_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("000111100x1xxxxx011010xxxxxxxxxx", AInstEmit.Fmaxnm_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>0011100<1xxxxx110001xxxxxxxxxx", AInstEmit.Fmaxnm_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>1011100<1xxxxx111101xxxxxxxxxx", AInstEmit.Fmaxp_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("000111100x1xxxxx010110xxxxxxxxxx", AInstEmit.Fmin_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>0011101<1xxxxx111101xxxxxxxxxx", AInstEmit.Fmin_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("000111100x1xxxxx011110xxxxxxxxxx", AInstEmit.Fminnm_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>0011101<1xxxxx110001xxxxxxxxxx", AInstEmit.Fminnm_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>1011101<1xxxxx111101xxxxxxxxxx", AInstEmit.Fminp_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("010111111xxxxxxx0001x0xxxxxxxxxx", AInstEmit.Fmla_Se, typeof(AOpCodeSimdRegElemF));
|
|
||||||
SetA64("0>0011100<1xxxxx110011xxxxxxxxxx", AInstEmit.Fmla_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>0011111<xxxxxx0001x0xxxxxxxxxx", AInstEmit.Fmla_Ve, typeof(AOpCodeSimdRegElemF));
|
|
||||||
SetA64("010111111xxxxxxx0101x0xxxxxxxxxx", AInstEmit.Fmls_Se, typeof(AOpCodeSimdRegElemF));
|
|
||||||
SetA64("0>0011101<1xxxxx110011xxxxxxxxxx", AInstEmit.Fmls_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>0011111<xxxxxx0101x0xxxxxxxxxx", AInstEmit.Fmls_Ve, typeof(AOpCodeSimdRegElemF));
|
|
||||||
SetA64("000111100x100000010000xxxxxxxxxx", AInstEmit.Fmov_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("00011110xx1xxxxxxxx100xxxxxxxxxx", AInstEmit.Fmov_Si, typeof(AOpCodeSimdFmov));
|
|
||||||
SetA64("0xx0111100000xxx111101xxxxxxxxxx", AInstEmit.Fmov_V, typeof(AOpCodeSimdImm));
|
|
||||||
SetA64("x00111100x100110000000xxxxxxxxxx", AInstEmit.Fmov_Ftoi, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("x00111100x100111000000xxxxxxxxxx", AInstEmit.Fmov_Itof, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("1001111010101110000000xxxxxxxxxx", AInstEmit.Fmov_Ftoi1, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("1001111010101111000000xxxxxxxxxx", AInstEmit.Fmov_Itof1, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("000111110x0xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Fmsub_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("000111100x1xxxxx000010xxxxxxxxxx", AInstEmit.Fmul_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("010111111xxxxxxx1001x0xxxxxxxxxx", AInstEmit.Fmul_Se, typeof(AOpCodeSimdRegElemF));
|
|
||||||
SetA64("0>1011100<1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>0011111<xxxxxx1001x0xxxxxxxxxx", AInstEmit.Fmul_Ve, typeof(AOpCodeSimdRegElemF));
|
|
||||||
SetA64("010111100x1xxxxx110111xxxxxxxxxx", AInstEmit.Fmulx_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("011111111xxxxxxx1001x0xxxxxxxxxx", AInstEmit.Fmulx_Se, typeof(AOpCodeSimdRegElemF));
|
|
||||||
SetA64("0>0011100<1xxxxx110111xxxxxxxxxx", AInstEmit.Fmulx_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>1011111<xxxxxx1001x0xxxxxxxxxx", AInstEmit.Fmulx_Ve, typeof(AOpCodeSimdRegElemF));
|
|
||||||
SetA64("000111100x100001010000xxxxxxxxxx", AInstEmit.Fneg_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>1011101<100000111110xxxxxxxxxx", AInstEmit.Fneg_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("000111110x1xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Fnmadd_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("000111110x1xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Fnmsub_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("000111100x1xxxxx100010xxxxxxxxxx", AInstEmit.Fnmul_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("010111101x100001110110xxxxxxxxxx", AInstEmit.Frecpe_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>0011101<100001110110xxxxxxxxxx", AInstEmit.Frecpe_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("010111100x1xxxxx111111xxxxxxxxxx", AInstEmit.Frecps_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>0011100<1xxxxx111111xxxxxxxxxx", AInstEmit.Frecps_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("010111101x100001111110xxxxxxxxxx", AInstEmit.Frecpx_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("000111100x100110010000xxxxxxxxxx", AInstEmit.Frinta_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>1011100<100001100010xxxxxxxxxx", AInstEmit.Frinta_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("000111100x100111110000xxxxxxxxxx", AInstEmit.Frinti_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>1011101<100001100110xxxxxxxxxx", AInstEmit.Frinti_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("000111100x100101010000xxxxxxxxxx", AInstEmit.Frintm_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>0011100<100001100110xxxxxxxxxx", AInstEmit.Frintm_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("000111100x100100010000xxxxxxxxxx", AInstEmit.Frintn_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>0011100<100001100010xxxxxxxxxx", AInstEmit.Frintn_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("000111100x100100110000xxxxxxxxxx", AInstEmit.Frintp_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>0011101<100001100010xxxxxxxxxx", AInstEmit.Frintp_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("000111100x100111010000xxxxxxxxxx", AInstEmit.Frintx_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>1011100<100001100110xxxxxxxxxx", AInstEmit.Frintx_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("011111101x100001110110xxxxxxxxxx", AInstEmit.Frsqrte_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>1011101<100001110110xxxxxxxxxx", AInstEmit.Frsqrte_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("010111101x1xxxxx111111xxxxxxxxxx", AInstEmit.Frsqrts_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>0011101<1xxxxx111111xxxxxxxxxx", AInstEmit.Frsqrts_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("000111100x100001110000xxxxxxxxxx", AInstEmit.Fsqrt_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>1011101<100001111110xxxxxxxxxx", AInstEmit.Fsqrt_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("000111100x1xxxxx001110xxxxxxxxxx", AInstEmit.Fsub_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>0011101<1xxxxx110101xxxxxxxxxx", AInstEmit.Fsub_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("01001110000xxxxx000111xxxxxxxxxx", AInstEmit.Ins_Gp, typeof(AOpCodeSimdIns));
|
|
||||||
SetA64("01101110000xxxxx0xxxx1xxxxxxxxxx", AInstEmit.Ins_V, typeof(AOpCodeSimdIns));
|
|
||||||
SetA64("0x00110001000000xxxxxxxxxxxxxxxx", AInstEmit.Ld__Vms, typeof(AOpCodeSimdMemMs));
|
|
||||||
SetA64("0x001100110xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ld__Vms, typeof(AOpCodeSimdMemMs));
|
|
||||||
SetA64("0x00110101x00000xxxxxxxxxxxxxxxx", AInstEmit.Ld__Vss, typeof(AOpCodeSimdMemSs));
|
|
||||||
SetA64("0x00110111xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ld__Vss, typeof(AOpCodeSimdMemSs));
|
|
||||||
SetA64("xx10110xx1xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldp, typeof(AOpCodeSimdMemPair));
|
|
||||||
SetA64("xx111100x10xxxxxxxxx00xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
|
||||||
SetA64("xx111100x10xxxxxxxxx01xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
|
||||||
SetA64("xx111100x10xxxxxxxxx11xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
|
||||||
SetA64("xx111101x1xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
|
||||||
SetA64("xx111100x11xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemReg));
|
|
||||||
SetA64("xx011100xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.LdrLit, typeof(AOpCodeSimdMemLit));
|
|
||||||
SetA64("0x001110<<1xxxxx100101xxxxxxxxxx", AInstEmit.Mla_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101111xxxxxxxx0000x0xxxxxxxxxx", AInstEmit.Mla_Ve, typeof(AOpCodeSimdRegElem));
|
|
||||||
SetA64("0x101110<<1xxxxx100101xxxxxxxxxx", AInstEmit.Mls_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101111xxxxxxxx0100x0xxxxxxxxxx", AInstEmit.Mls_Ve, typeof(AOpCodeSimdRegElem));
|
|
||||||
SetA64("0x00111100000xxx0xx001xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
|
|
||||||
SetA64("0x00111100000xxx10x001xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
|
|
||||||
SetA64("0x00111100000xxx110x01xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
|
|
||||||
SetA64("0xx0111100000xxx111001xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
|
|
||||||
SetA64("0x001110<<1xxxxx100111xxxxxxxxxx", AInstEmit.Mul_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001111xxxxxxxx1000x0xxxxxxxxxx", AInstEmit.Mul_Ve, typeof(AOpCodeSimdRegElem));
|
|
||||||
SetA64("0x10111100000xxx0xx001xxxxxxxxxx", AInstEmit.Mvni_V, typeof(AOpCodeSimdImm));
|
|
||||||
SetA64("0x10111100000xxx10x001xxxxxxxxxx", AInstEmit.Mvni_V, typeof(AOpCodeSimdImm));
|
|
||||||
SetA64("0x10111100000xxx110x01xxxxxxxxxx", AInstEmit.Mvni_V, typeof(AOpCodeSimdImm));
|
|
||||||
SetA64("0111111011100000101110xxxxxxxxxx", AInstEmit.Neg_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>101110<<100000101110xxxxxxxxxx", AInstEmit.Neg_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x10111000100000010110xxxxxxxxxx", AInstEmit.Not_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x001110111xxxxx000111xxxxxxxxxx", AInstEmit.Orn_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110101xxxxx000111xxxxxxxxxx", AInstEmit.Orr_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x00111100000xxx<<x101xxxxxxxxxx", AInstEmit.Orr_Vi, typeof(AOpCodeSimdImm));
|
|
||||||
SetA64("0x101110<<1xxxxx010000xxxxxxxxxx", AInstEmit.Raddhn_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x10111001100000010110xxxxxxxxxx", AInstEmit.Rbit_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x00111000100000000110xxxxxxxxxx", AInstEmit.Rev16_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x1011100x100000000010xxxxxxxxxx", AInstEmit.Rev32_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x001110<<100000000010xxxxxxxxxx", AInstEmit.Rev64_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x00111100>>>xxx100011xxxxxxxxxx", AInstEmit.Rshrn_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x101110<<1xxxxx011000xxxxxxxxxx", AInstEmit.Rsubhn_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<1xxxxx011111xxxxxxxxxx", AInstEmit.Saba_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<1xxxxx010100xxxxxxxxxx", AInstEmit.Sabal_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<1xxxxx011101xxxxxxxxxx", AInstEmit.Sabd_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<1xxxxx011100xxxxxxxxxx", AInstEmit.Sabdl_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<100000011010xxxxxxxxxx", AInstEmit.Sadalp_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x001110<<1xxxxx000000xxxxxxxxxx", AInstEmit.Saddl_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<100000001010xxxxxxxxxx", AInstEmit.Saddlp_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x001110<<1xxxxx000100xxxxxxxxxx", AInstEmit.Saddw_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("x0011110xx100010000000xxxxxxxxxx", AInstEmit.Scvtf_Gp, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("010111100x100001110110xxxxxxxxxx", AInstEmit.Scvtf_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x0011100x100001110110xxxxxxxxxx", AInstEmit.Scvtf_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("01011110000xxxxx000000xxxxxxxxxx", AInstEmit.Sha1c_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0101111000101000000010xxxxxxxxxx", AInstEmit.Sha1h_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("01011110000xxxxx001000xxxxxxxxxx", AInstEmit.Sha1m_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("01011110000xxxxx000100xxxxxxxxxx", AInstEmit.Sha1p_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("01011110000xxxxx001100xxxxxxxxxx", AInstEmit.Sha1su0_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0101111000101000000110xxxxxxxxxx", AInstEmit.Sha1su1_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("01011110000xxxxx010000xxxxxxxxxx", AInstEmit.Sha256h_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("01011110000xxxxx010100xxxxxxxxxx", AInstEmit.Sha256h2_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0101111000101000001010xxxxxxxxxx", AInstEmit.Sha256su0_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("01011110000xxxxx011000xxxxxxxxxx", AInstEmit.Sha256su1_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<1xxxxx000001xxxxxxxxxx", AInstEmit.Shadd_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0101111101xxxxxx010101xxxxxxxxxx", AInstEmit.Shl_S, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x00111100>>>xxx010101xxxxxxxxxx", AInstEmit.Shl_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0100111101xxxxxx010101xxxxxxxxxx", AInstEmit.Shl_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x101110<<100001001110xxxxxxxxxx", AInstEmit.Shll_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x00111100>>>xxx100001xxxxxxxxxx", AInstEmit.Shrn_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x001110<<1xxxxx001001xxxxxxxxxx", AInstEmit.Shsub_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x1011110>>>>xxx010101xxxxxxxxxx", AInstEmit.Sli_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x001110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Smax_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<1xxxxx101001xxxxxxxxxx", AInstEmit.Smaxp_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<1xxxxx101011xxxxxxxxxx", AInstEmit.Sminp_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<1xxxxx100000xxxxxxxxxx", AInstEmit.Smlal_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<1xxxxx101000xxxxxxxxxx", AInstEmit.Smlsl_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110000xxxxx001011xxxxxxxxxx", AInstEmit.Smov_S, typeof(AOpCodeSimdIns));
|
|
||||||
SetA64("0x001110<<1xxxxx110000xxxxxxxxxx", AInstEmit.Smull_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("01011110xx100000011110xxxxxxxxxx", AInstEmit.Sqabs_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>001110<<100000011110xxxxxxxxxx", AInstEmit.Sqabs_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("01011110xx1xxxxx000011xxxxxxxxxx", AInstEmit.Sqadd_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>001110<<1xxxxx000011xxxxxxxxxx", AInstEmit.Sqadd_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("01011110011xxxxx101101xxxxxxxxxx", AInstEmit.Sqdmulh_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("01011110101xxxxx101101xxxxxxxxxx", AInstEmit.Sqdmulh_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110011xxxxx101101xxxxxxxxxx", AInstEmit.Sqdmulh_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110101xxxxx101101xxxxxxxxxx", AInstEmit.Sqdmulh_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("01111110xx100000011110xxxxxxxxxx", AInstEmit.Sqneg_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>101110<<100000011110xxxxxxxxxx", AInstEmit.Sqneg_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("01111110011xxxxx101101xxxxxxxxxx", AInstEmit.Sqrdmulh_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("01111110101xxxxx101101xxxxxxxxxx", AInstEmit.Sqrdmulh_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110011xxxxx101101xxxxxxxxxx", AInstEmit.Sqrdmulh_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110101xxxxx101101xxxxxxxxxx", AInstEmit.Sqrdmulh_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0101111100>>>xxx100111xxxxxxxxxx", AInstEmit.Sqrshrn_S, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x00111100>>>xxx100111xxxxxxxxxx", AInstEmit.Sqrshrn_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0111111100>>>xxx100011xxxxxxxxxx", AInstEmit.Sqrshrun_S, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x10111100>>>xxx100011xxxxxxxxxx", AInstEmit.Sqrshrun_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0101111100>>>xxx100101xxxxxxxxxx", AInstEmit.Sqshrn_S, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x00111100>>>xxx100101xxxxxxxxxx", AInstEmit.Sqshrn_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0111111100>>>xxx100001xxxxxxxxxx", AInstEmit.Sqshrun_S, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x10111100>>>xxx100001xxxxxxxxxx", AInstEmit.Sqshrun_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("01011110xx1xxxxx001011xxxxxxxxxx", AInstEmit.Sqsub_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>001110<<1xxxxx001011xxxxxxxxxx", AInstEmit.Sqsub_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("01011110<<100001010010xxxxxxxxxx", AInstEmit.Sqxtn_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x001110<<100001010010xxxxxxxxxx", AInstEmit.Sqxtn_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("01111110<<100001001010xxxxxxxxxx", AInstEmit.Sqxtun_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x101110<<100001001010xxxxxxxxxx", AInstEmit.Sqxtun_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x001110<<1xxxxx000101xxxxxxxxxx", AInstEmit.Srhadd_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0101111101xxxxxx001001xxxxxxxxxx", AInstEmit.Srshr_S, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x00111100>>>xxx001001xxxxxxxxxx", AInstEmit.Srshr_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0100111101xxxxxx001001xxxxxxxxxx", AInstEmit.Srshr_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0101111101xxxxxx001101xxxxxxxxxx", AInstEmit.Srsra_S, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x00111100>>>xxx001101xxxxxxxxxx", AInstEmit.Srsra_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0100111101xxxxxx001101xxxxxxxxxx", AInstEmit.Srsra_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0>001110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Sshl_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0101111101xxxxxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x00111100>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0100111101xxxxxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0101111101xxxxxx000101xxxxxxxxxx", AInstEmit.Ssra_S, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x00111100>>>xxx000101xxxxxxxxxx", AInstEmit.Ssra_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0100111101xxxxxx000101xxxxxxxxxx", AInstEmit.Ssra_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x001110<<1xxxxx001000xxxxxxxxxx", AInstEmit.Ssubl_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<1xxxxx001100xxxxxxxxxx", AInstEmit.Ssubw_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x00110000000000xxxxxxxxxxxxxxxx", AInstEmit.St__Vms, typeof(AOpCodeSimdMemMs));
|
|
||||||
SetA64("0x001100100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.St__Vms, typeof(AOpCodeSimdMemMs));
|
|
||||||
SetA64("0x00110100x00000xxxxxxxxxxxxxxxx", AInstEmit.St__Vss, typeof(AOpCodeSimdMemSs));
|
|
||||||
SetA64("0x00110110xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.St__Vss, typeof(AOpCodeSimdMemSs));
|
|
||||||
SetA64("xx10110xx0xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Stp, typeof(AOpCodeSimdMemPair));
|
|
||||||
SetA64("xx111100x00xxxxxxxxx00xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
|
||||||
SetA64("xx111100x00xxxxxxxxx01xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
|
||||||
SetA64("xx111100x00xxxxxxxxx11xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
|
||||||
SetA64("xx111101x0xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
|
||||||
SetA64("xx111100x01xxxxxxxxx10xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemReg));
|
|
||||||
SetA64("01111110111xxxxx100001xxxxxxxxxx", AInstEmit.Sub_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>101110<<1xxxxx100001xxxxxxxxxx", AInstEmit.Sub_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<1xxxxx011000xxxxxxxxxx", AInstEmit.Subhn_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("01011110xx100000001110xxxxxxxxxx", AInstEmit.Suqadd_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>001110<<100000001110xxxxxxxxxx", AInstEmit.Suqadd_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x001110000xxxxx0xx000xxxxxxxxxx", AInstEmit.Tbl_V, typeof(AOpCodeSimdTbl));
|
|
||||||
SetA64("0>001110<<0xxxxx001010xxxxxxxxxx", AInstEmit.Trn1_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>001110<<0xxxxx011010xxxxxxxxxx", AInstEmit.Trn2_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110<<1xxxxx011111xxxxxxxxxx", AInstEmit.Uaba_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110<<1xxxxx010100xxxxxxxxxx", AInstEmit.Uabal_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110<<1xxxxx011101xxxxxxxxxx", AInstEmit.Uabd_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110<<1xxxxx011100xxxxxxxxxx", AInstEmit.Uabdl_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110<<100000011010xxxxxxxxxx", AInstEmit.Uadalp_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x101110<<1xxxxx000000xxxxxxxxxx", AInstEmit.Uaddl_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110<<100000001010xxxxxxxxxx", AInstEmit.Uaddlp_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("001011100x110000001110xxxxxxxxxx", AInstEmit.Uaddlv_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("01101110<<110000001110xxxxxxxxxx", AInstEmit.Uaddlv_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x101110<<1xxxxx000100xxxxxxxxxx", AInstEmit.Uaddw_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("x0011110xx100011000000xxxxxxxxxx", AInstEmit.Ucvtf_Gp, typeof(AOpCodeSimdCvt));
|
|
||||||
SetA64("011111100x100001110110xxxxxxxxxx", AInstEmit.Ucvtf_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x1011100x100001110110xxxxxxxxxx", AInstEmit.Ucvtf_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x101110<<1xxxxx000001xxxxxxxxxx", AInstEmit.Uhadd_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110<<1xxxxx001001xxxxxxxxxx", AInstEmit.Uhsub_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Umax_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110<<1xxxxx101001xxxxxxxxxx", AInstEmit.Umaxp_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Umin_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110<<1xxxxx101011xxxxxxxxxx", AInstEmit.Uminp_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110<<1xxxxx100000xxxxxxxxxx", AInstEmit.Umlal_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110<<1xxxxx101000xxxxxxxxxx", AInstEmit.Umlsl_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110000xxxxx001111xxxxxxxxxx", AInstEmit.Umov_S, typeof(AOpCodeSimdIns));
|
|
||||||
SetA64("0x101110<<1xxxxx110000xxxxxxxxxx", AInstEmit.Umull_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("01111110xx1xxxxx000011xxxxxxxxxx", AInstEmit.Uqadd_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>101110<<1xxxxx000011xxxxxxxxxx", AInstEmit.Uqadd_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0111111100>>>xxx100111xxxxxxxxxx", AInstEmit.Uqrshrn_S, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x10111100>>>xxx100111xxxxxxxxxx", AInstEmit.Uqrshrn_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0111111100>>>xxx100101xxxxxxxxxx", AInstEmit.Uqshrn_S, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x10111100>>>xxx100101xxxxxxxxxx", AInstEmit.Uqshrn_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("01111110xx1xxxxx001011xxxxxxxxxx", AInstEmit.Uqsub_S, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>101110<<1xxxxx001011xxxxxxxxxx", AInstEmit.Uqsub_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("01111110<<100001010010xxxxxxxxxx", AInstEmit.Uqxtn_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x101110<<100001010010xxxxxxxxxx", AInstEmit.Uqxtn_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0x101110<<1xxxxx000101xxxxxxxxxx", AInstEmit.Urhadd_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0111111101xxxxxx001001xxxxxxxxxx", AInstEmit.Urshr_S, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x10111100>>>xxx001001xxxxxxxxxx", AInstEmit.Urshr_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0110111101xxxxxx001001xxxxxxxxxx", AInstEmit.Urshr_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0111111101xxxxxx001101xxxxxxxxxx", AInstEmit.Ursra_S, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x10111100>>>xxx001101xxxxxxxxxx", AInstEmit.Ursra_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0110111101xxxxxx001101xxxxxxxxxx", AInstEmit.Ursra_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0>101110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Ushl_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x10111100>>>xxx101001xxxxxxxxxx", AInstEmit.Ushll_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0111111101xxxxxx000001xxxxxxxxxx", AInstEmit.Ushr_S, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x10111100>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0110111101xxxxxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("01111110xx100000001110xxxxxxxxxx", AInstEmit.Usqadd_S, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>101110<<100000001110xxxxxxxxxx", AInstEmit.Usqadd_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0111111101xxxxxx000101xxxxxxxxxx", AInstEmit.Usra_S, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x10111100>>>xxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0110111101xxxxxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm));
|
|
||||||
SetA64("0x101110<<1xxxxx001000xxxxxxxxxx", AInstEmit.Usubl_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x101110<<1xxxxx001100xxxxxxxxxx", AInstEmit.Usubw_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>001110<<0xxxxx000110xxxxxxxxxx", AInstEmit.Uzp1_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>001110<<0xxxxx010110xxxxxxxxxx", AInstEmit.Uzp2_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0x001110<<100001001010xxxxxxxxxx", AInstEmit.Xtn_V, typeof(AOpCodeSimd));
|
|
||||||
SetA64("0>001110<<0xxxxx001110xxxxxxxxxx", AInstEmit.Zip1_V, typeof(AOpCodeSimdReg));
|
|
||||||
SetA64("0>001110<<0xxxxx011110xxxxxxxxxx", AInstEmit.Zip2_V, typeof(AOpCodeSimdReg));
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region "Generate InstA64FastLookup Table (AArch64)"
|
|
||||||
var Tmp = new List<InstInfo>[FastLookupSize];
|
|
||||||
for (int i = 0; i < FastLookupSize; i++)
|
|
||||||
{
|
|
||||||
Tmp[i] = new List<InstInfo>();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var Inst in AllInstA64)
|
|
||||||
{
|
|
||||||
int Mask = ToFastLookupIndex(Inst.Mask);
|
|
||||||
int Value = ToFastLookupIndex(Inst.Value);
|
|
||||||
|
|
||||||
for (int i = 0; i < FastLookupSize; i++)
|
|
||||||
{
|
|
||||||
if ((i & Mask) == Value)
|
|
||||||
{
|
|
||||||
Tmp[i].Add(Inst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < FastLookupSize; i++)
|
|
||||||
{
|
|
||||||
InstA64FastLookup[i] = Tmp[i].ToArray();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
||||||
private class InstInfo
|
|
||||||
{
|
|
||||||
public int Mask;
|
|
||||||
public int Value;
|
|
||||||
|
|
||||||
public AInst Inst;
|
|
||||||
|
|
||||||
public InstInfo(int Mask, int Value, AInst Inst)
|
|
||||||
{
|
|
||||||
this.Mask = Mask;
|
|
||||||
this.Value = Value;
|
|
||||||
this.Inst = Inst;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<InstInfo> AllInstA32 = new List<InstInfo>();
|
|
||||||
private static List<InstInfo> AllInstA64 = new List<InstInfo>();
|
|
||||||
|
|
||||||
private static int FastLookupSize = 0x1000;
|
|
||||||
private static InstInfo[][] InstA64FastLookup = new InstInfo[FastLookupSize][];
|
|
||||||
|
|
||||||
private static void SetA32(string Encoding, AInstInterpreter Interpreter, Type Type)
|
|
||||||
{
|
|
||||||
Set(Encoding, new AInst(Interpreter, null, Type), AExecutionMode.AArch32);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SetA64(string Encoding, AInstEmitter Emitter, Type Type)
|
|
||||||
{
|
|
||||||
Set(Encoding, new AInst(null, Emitter, Type), AExecutionMode.AArch64);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Set(string Encoding, AInst Inst, AExecutionMode Mode)
|
|
||||||
{
|
|
||||||
int Bit = Encoding.Length - 1;
|
|
||||||
int Value = 0;
|
|
||||||
int XMask = 0;
|
|
||||||
int XBits = 0;
|
|
||||||
|
|
||||||
int[] XPos = new int[Encoding.Length];
|
|
||||||
|
|
||||||
int Blacklisted = 0;
|
|
||||||
|
|
||||||
for (int Index = 0; Index < Encoding.Length; Index++, Bit--)
|
|
||||||
{
|
|
||||||
//Note: < and > are used on special encodings.
|
|
||||||
//The < means that we should never have ALL bits with the '<' set.
|
|
||||||
//So, when the encoding has <<, it means that 00, 01, and 10 are valid,
|
|
||||||
//but not 11. <<< is 000, 001, ..., 110 but NOT 111, and so on...
|
|
||||||
//For >, the invalid value is zero. So, for >> 01, 10 and 11 are valid,
|
|
||||||
//but 00 isn't.
|
|
||||||
char Chr = Encoding[Index];
|
|
||||||
|
|
||||||
if (Chr == '1')
|
|
||||||
{
|
|
||||||
Value |= 1 << Bit;
|
|
||||||
}
|
|
||||||
else if (Chr == 'x')
|
|
||||||
{
|
|
||||||
XMask |= 1 << Bit;
|
|
||||||
}
|
|
||||||
else if (Chr == '>')
|
|
||||||
{
|
|
||||||
XPos[XBits++] = Bit;
|
|
||||||
}
|
|
||||||
else if (Chr == '<')
|
|
||||||
{
|
|
||||||
XPos[XBits++] = Bit;
|
|
||||||
|
|
||||||
Blacklisted |= 1 << Bit;
|
|
||||||
}
|
|
||||||
else if (Chr != '0')
|
|
||||||
{
|
|
||||||
throw new ArgumentException(nameof(Encoding));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XMask = ~XMask;
|
|
||||||
|
|
||||||
if (XBits == 0)
|
|
||||||
{
|
|
||||||
InsertInst(XMask, Value, Inst, Mode);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int Index = 0; Index < (1 << XBits); Index++)
|
|
||||||
{
|
|
||||||
int Mask = 0;
|
|
||||||
|
|
||||||
for (int X = 0; X < XBits; X++)
|
|
||||||
{
|
|
||||||
Mask |= ((Index >> X) & 1) << XPos[X];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Mask != Blacklisted)
|
|
||||||
{
|
|
||||||
InsertInst(XMask, Value | Mask, Inst, Mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void InsertInst(
|
|
||||||
int XMask,
|
|
||||||
int Value,
|
|
||||||
AInst Inst,
|
|
||||||
AExecutionMode Mode)
|
|
||||||
{
|
|
||||||
InstInfo Info = new InstInfo(XMask, Value, Inst);
|
|
||||||
|
|
||||||
if (Mode == AExecutionMode.AArch64)
|
|
||||||
{
|
|
||||||
AllInstA64.Add(Info);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AllInstA32.Add(Info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AInst GetInstA32(int OpCode)
|
|
||||||
{
|
|
||||||
return GetInstFromList(AllInstA32, OpCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AInst GetInstA64(int OpCode)
|
|
||||||
{
|
|
||||||
return GetInstFromList(InstA64FastLookup[ToFastLookupIndex(OpCode)], OpCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int ToFastLookupIndex(int Value)
|
|
||||||
{
|
|
||||||
return ((Value >> 10) & 0x00F) | ((Value >> 18) & 0xFF0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static AInst GetInstFromList(IEnumerable<InstInfo> InstList, int OpCode)
|
|
||||||
{
|
|
||||||
foreach (var Node in InstList)
|
|
||||||
{
|
|
||||||
if ((OpCode & Node.Mask) == Node.Value)
|
|
||||||
{
|
|
||||||
return Node.Inst;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return AInst.Undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
using System.Runtime.Intrinsics.X86;
|
|
||||||
|
|
||||||
public static class AOptimizations
|
|
||||||
{
|
|
||||||
internal static bool FastFP = true;
|
|
||||||
|
|
||||||
private static bool UseAllSseIfAvailable = true;
|
|
||||||
|
|
||||||
private static bool UseSseIfAvailable = true;
|
|
||||||
private static bool UseSse2IfAvailable = true;
|
|
||||||
private static bool UseSse41IfAvailable = true;
|
|
||||||
private static bool UseSse42IfAvailable = true;
|
|
||||||
|
|
||||||
internal static bool UseSse = (UseAllSseIfAvailable && UseSseIfAvailable) && Sse.IsSupported;
|
|
||||||
internal static bool UseSse2 = (UseAllSseIfAvailable && UseSse2IfAvailable) && Sse2.IsSupported;
|
|
||||||
internal static bool UseSse41 = (UseAllSseIfAvailable && UseSse41IfAvailable) && Sse41.IsSupported;
|
|
||||||
internal static bool UseSse42 = (UseAllSseIfAvailable && UseSse42IfAvailable) && Sse42.IsSupported;
|
|
||||||
}
|
|
@ -1,150 +0,0 @@
|
|||||||
using ChocolArm64.Memory;
|
|
||||||
using ChocolArm64.State;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Reflection.Emit;
|
|
||||||
|
|
||||||
namespace ChocolArm64
|
|
||||||
{
|
|
||||||
class ATranslatedSub
|
|
||||||
{
|
|
||||||
private delegate long AA64Subroutine(AThreadState Register, AMemory Memory);
|
|
||||||
|
|
||||||
private const int MinCallCountForReJit = 250;
|
|
||||||
|
|
||||||
private AA64Subroutine ExecDelegate;
|
|
||||||
|
|
||||||
public static int StateArgIdx { get; private set; }
|
|
||||||
public static int MemoryArgIdx { get; private set; }
|
|
||||||
|
|
||||||
public static Type[] FixedArgTypes { get; private set; }
|
|
||||||
|
|
||||||
public DynamicMethod Method { get; private set; }
|
|
||||||
|
|
||||||
public ReadOnlyCollection<ARegister> Params { get; private set; }
|
|
||||||
|
|
||||||
private HashSet<long> Callers;
|
|
||||||
|
|
||||||
private ATranslatedSubType Type;
|
|
||||||
|
|
||||||
private int CallCount;
|
|
||||||
|
|
||||||
private bool NeedsReJit;
|
|
||||||
|
|
||||||
public ATranslatedSub(DynamicMethod Method, List<ARegister> Params)
|
|
||||||
{
|
|
||||||
if (Method == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(Method));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Params == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(Params));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Method = Method;
|
|
||||||
this.Params = Params.AsReadOnly();
|
|
||||||
|
|
||||||
Callers = new HashSet<long>();
|
|
||||||
|
|
||||||
PrepareDelegate();
|
|
||||||
}
|
|
||||||
|
|
||||||
static ATranslatedSub()
|
|
||||||
{
|
|
||||||
MethodInfo MthdInfo = typeof(AA64Subroutine).GetMethod("Invoke");
|
|
||||||
|
|
||||||
ParameterInfo[] Params = MthdInfo.GetParameters();
|
|
||||||
|
|
||||||
FixedArgTypes = new Type[Params.Length];
|
|
||||||
|
|
||||||
for (int Index = 0; Index < Params.Length; Index++)
|
|
||||||
{
|
|
||||||
Type ParamType = Params[Index].ParameterType;
|
|
||||||
|
|
||||||
FixedArgTypes[Index] = ParamType;
|
|
||||||
|
|
||||||
if (ParamType == typeof(AThreadState))
|
|
||||||
{
|
|
||||||
StateArgIdx = Index;
|
|
||||||
}
|
|
||||||
else if (ParamType == typeof(AMemory))
|
|
||||||
{
|
|
||||||
MemoryArgIdx = Index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PrepareDelegate()
|
|
||||||
{
|
|
||||||
string Name = $"{Method.Name}_Dispatch";
|
|
||||||
|
|
||||||
DynamicMethod Mthd = new DynamicMethod(Name, typeof(long), FixedArgTypes);
|
|
||||||
|
|
||||||
ILGenerator Generator = Mthd.GetILGenerator();
|
|
||||||
|
|
||||||
Generator.EmitLdargSeq(FixedArgTypes.Length);
|
|
||||||
|
|
||||||
foreach (ARegister Reg in Params)
|
|
||||||
{
|
|
||||||
Generator.EmitLdarg(StateArgIdx);
|
|
||||||
|
|
||||||
Generator.Emit(OpCodes.Ldfld, Reg.GetField());
|
|
||||||
}
|
|
||||||
|
|
||||||
Generator.Emit(OpCodes.Call, Method);
|
|
||||||
Generator.Emit(OpCodes.Ret);
|
|
||||||
|
|
||||||
ExecDelegate = (AA64Subroutine)Mthd.CreateDelegate(typeof(AA64Subroutine));
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ShouldReJit()
|
|
||||||
{
|
|
||||||
if (NeedsReJit && CallCount < MinCallCountForReJit)
|
|
||||||
{
|
|
||||||
CallCount++;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NeedsReJit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long Execute(AThreadState ThreadState, AMemory Memory)
|
|
||||||
{
|
|
||||||
return ExecDelegate(ThreadState, Memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddCaller(long Position)
|
|
||||||
{
|
|
||||||
lock (Callers)
|
|
||||||
{
|
|
||||||
Callers.Add(Position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public long[] GetCallerPositions()
|
|
||||||
{
|
|
||||||
lock (Callers)
|
|
||||||
{
|
|
||||||
return Callers.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetType(ATranslatedSubType Type)
|
|
||||||
{
|
|
||||||
this.Type = Type;
|
|
||||||
|
|
||||||
if (Type == ATranslatedSubType.SubTier0)
|
|
||||||
{
|
|
||||||
NeedsReJit = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MarkForReJit() => NeedsReJit = true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,165 +0,0 @@
|
|||||||
using ChocolArm64.Decoder;
|
|
||||||
using ChocolArm64.Events;
|
|
||||||
using ChocolArm64.Memory;
|
|
||||||
using ChocolArm64.State;
|
|
||||||
using ChocolArm64.Translation;
|
|
||||||
using System;
|
|
||||||
using System.Reflection.Emit;
|
|
||||||
|
|
||||||
namespace ChocolArm64
|
|
||||||
{
|
|
||||||
public class ATranslator
|
|
||||||
{
|
|
||||||
private ATranslatorCache Cache;
|
|
||||||
|
|
||||||
public event EventHandler<ACpuTraceEventArgs> CpuTrace;
|
|
||||||
|
|
||||||
public bool EnableCpuTrace { get; set; }
|
|
||||||
|
|
||||||
public ATranslator()
|
|
||||||
{
|
|
||||||
Cache = new ATranslatorCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void ExecuteSubroutine(AThread Thread, long Position)
|
|
||||||
{
|
|
||||||
//TODO: Both the execute A32/A64 methods should be merged on the future,
|
|
||||||
//when both ISAs are implemented with the interpreter and JIT.
|
|
||||||
//As of now, A32 only has a interpreter and A64 a JIT.
|
|
||||||
AThreadState State = Thread.ThreadState;
|
|
||||||
AMemory Memory = Thread.Memory;
|
|
||||||
|
|
||||||
if (State.ExecutionMode == AExecutionMode.AArch32)
|
|
||||||
{
|
|
||||||
ExecuteSubroutineA32(State, Memory);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ExecuteSubroutineA64(State, Memory, Position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ExecuteSubroutineA32(AThreadState State, AMemory Memory)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
AOpCode OpCode = ADecoder.DecodeOpCode(State, Memory, State.R15);
|
|
||||||
|
|
||||||
OpCode.Interpreter(State, Memory, OpCode);
|
|
||||||
}
|
|
||||||
while (State.R15 != 0 && State.Running);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ExecuteSubroutineA64(AThreadState State, AMemory Memory, long Position)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (EnableCpuTrace)
|
|
||||||
{
|
|
||||||
CpuTrace?.Invoke(this, new ACpuTraceEventArgs(Position));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Cache.TryGetSubroutine(Position, out ATranslatedSub Sub))
|
|
||||||
{
|
|
||||||
Sub = TranslateTier0(State, Memory, Position);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Sub.ShouldReJit())
|
|
||||||
{
|
|
||||||
TranslateTier1(State, Memory, Position);
|
|
||||||
}
|
|
||||||
|
|
||||||
Position = Sub.Execute(State, Memory);
|
|
||||||
}
|
|
||||||
while (Position != 0 && State.Running);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal bool HasCachedSub(long Position)
|
|
||||||
{
|
|
||||||
return Cache.HasSubroutine(Position);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ATranslatedSub TranslateTier0(AThreadState State, AMemory Memory, long Position)
|
|
||||||
{
|
|
||||||
ABlock Block = ADecoder.DecodeBasicBlock(State, Memory, Position);
|
|
||||||
|
|
||||||
ABlock[] Graph = new ABlock[] { Block };
|
|
||||||
|
|
||||||
string SubName = GetSubroutineName(Position);
|
|
||||||
|
|
||||||
AILEmitterCtx Context = new AILEmitterCtx(Cache, Graph, Block, SubName);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Context.EmitOpCode();
|
|
||||||
}
|
|
||||||
while (Context.AdvanceOpCode());
|
|
||||||
|
|
||||||
ATranslatedSub Subroutine = Context.GetSubroutine();
|
|
||||||
|
|
||||||
Subroutine.SetType(ATranslatedSubType.SubTier0);
|
|
||||||
|
|
||||||
Cache.AddOrUpdate(Position, Subroutine, Block.OpCodes.Count);
|
|
||||||
|
|
||||||
AOpCode LastOp = Block.GetLastOp();
|
|
||||||
|
|
||||||
return Subroutine;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TranslateTier1(AThreadState State, AMemory Memory, long Position)
|
|
||||||
{
|
|
||||||
(ABlock[] Graph, ABlock Root) = ADecoder.DecodeSubroutine(Cache, State, Memory, Position);
|
|
||||||
|
|
||||||
string SubName = GetSubroutineName(Position);
|
|
||||||
|
|
||||||
AILEmitterCtx Context = new AILEmitterCtx(Cache, Graph, Root, SubName);
|
|
||||||
|
|
||||||
if (Context.CurrBlock.Position != Position)
|
|
||||||
{
|
|
||||||
Context.Emit(OpCodes.Br, Context.GetLabel(Position));
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Context.EmitOpCode();
|
|
||||||
}
|
|
||||||
while (Context.AdvanceOpCode());
|
|
||||||
|
|
||||||
//Mark all methods that calls this method for ReJiting,
|
|
||||||
//since we can now call it directly which is faster.
|
|
||||||
if (Cache.TryGetSubroutine(Position, out ATranslatedSub OldSub))
|
|
||||||
{
|
|
||||||
foreach (long CallerPos in OldSub.GetCallerPositions())
|
|
||||||
{
|
|
||||||
if (Cache.TryGetSubroutine(Position, out ATranslatedSub CallerSub))
|
|
||||||
{
|
|
||||||
CallerSub.MarkForReJit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ATranslatedSub Subroutine = Context.GetSubroutine();
|
|
||||||
|
|
||||||
Subroutine.SetType(ATranslatedSubType.SubTier1);
|
|
||||||
|
|
||||||
Cache.AddOrUpdate(Position, Subroutine, GetGraphInstCount(Graph));
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetSubroutineName(long Position)
|
|
||||||
{
|
|
||||||
return $"Sub{Position:x16}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetGraphInstCount(ABlock[] Graph)
|
|
||||||
{
|
|
||||||
int Size = 0;
|
|
||||||
|
|
||||||
foreach (ABlock Block in Graph)
|
|
||||||
{
|
|
||||||
Size += Block.OpCodes.Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,165 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace ChocolArm64
|
|
||||||
{
|
|
||||||
class ATranslatorCache
|
|
||||||
{
|
|
||||||
//Maximum size of the cache, in bytes, measured in ARM code size.
|
|
||||||
private const int MaxTotalSize = 4 * 1024 * 256;
|
|
||||||
|
|
||||||
//Minimum time required in milliseconds for a method to be eligible for deletion.
|
|
||||||
private const int MinTimeDelta = 2 * 60000;
|
|
||||||
|
|
||||||
//Minimum number of calls required to update the timestamp.
|
|
||||||
private const int MinCallCountForUpdate = 250;
|
|
||||||
|
|
||||||
private class CacheBucket
|
|
||||||
{
|
|
||||||
public ATranslatedSub Subroutine { get; private set; }
|
|
||||||
|
|
||||||
public LinkedListNode<long> Node { get; private set; }
|
|
||||||
|
|
||||||
public int CallCount { get; set; }
|
|
||||||
|
|
||||||
public int Size { get; private set; }
|
|
||||||
|
|
||||||
public long Timestamp { get; private set; }
|
|
||||||
|
|
||||||
public CacheBucket(ATranslatedSub Subroutine, LinkedListNode<long> Node, int Size)
|
|
||||||
{
|
|
||||||
this.Subroutine = Subroutine;
|
|
||||||
this.Size = Size;
|
|
||||||
|
|
||||||
UpdateNode(Node);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateNode(LinkedListNode<long> Node)
|
|
||||||
{
|
|
||||||
this.Node = Node;
|
|
||||||
|
|
||||||
Timestamp = GetTimestamp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ConcurrentDictionary<long, CacheBucket> Cache;
|
|
||||||
|
|
||||||
private LinkedList<long> SortedCache;
|
|
||||||
|
|
||||||
private int TotalSize;
|
|
||||||
|
|
||||||
public ATranslatorCache()
|
|
||||||
{
|
|
||||||
Cache = new ConcurrentDictionary<long, CacheBucket>();
|
|
||||||
|
|
||||||
SortedCache = new LinkedList<long>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddOrUpdate(long Position, ATranslatedSub Subroutine, int Size)
|
|
||||||
{
|
|
||||||
ClearCacheIfNeeded();
|
|
||||||
|
|
||||||
TotalSize += Size;
|
|
||||||
|
|
||||||
lock (SortedCache)
|
|
||||||
{
|
|
||||||
LinkedListNode<long> Node = SortedCache.AddLast(Position);
|
|
||||||
|
|
||||||
CacheBucket NewBucket = new CacheBucket(Subroutine, Node, Size);
|
|
||||||
|
|
||||||
Cache.AddOrUpdate(Position, NewBucket, (Key, Bucket) =>
|
|
||||||
{
|
|
||||||
TotalSize -= Bucket.Size;
|
|
||||||
|
|
||||||
SortedCache.Remove(Bucket.Node);
|
|
||||||
|
|
||||||
return NewBucket;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HasSubroutine(long Position)
|
|
||||||
{
|
|
||||||
return Cache.ContainsKey(Position);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public bool TryGetSubroutine(long Position, out ATranslatedSub Subroutine)
|
|
||||||
{
|
|
||||||
if (Cache.TryGetValue(Position, out CacheBucket Bucket))
|
|
||||||
{
|
|
||||||
if (Bucket.CallCount++ > MinCallCountForUpdate)
|
|
||||||
{
|
|
||||||
if (Monitor.TryEnter(SortedCache))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Bucket.CallCount = 0;
|
|
||||||
|
|
||||||
SortedCache.Remove(Bucket.Node);
|
|
||||||
|
|
||||||
Bucket.UpdateNode(SortedCache.AddLast(Position));
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Monitor.Exit(SortedCache);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Subroutine = Bucket.Subroutine;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Subroutine = default(ATranslatedSub);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ClearCacheIfNeeded()
|
|
||||||
{
|
|
||||||
long Timestamp = GetTimestamp();
|
|
||||||
|
|
||||||
while (TotalSize > MaxTotalSize)
|
|
||||||
{
|
|
||||||
lock (SortedCache)
|
|
||||||
{
|
|
||||||
LinkedListNode<long> Node = SortedCache.First;
|
|
||||||
|
|
||||||
if (Node == null)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
CacheBucket Bucket = Cache[Node.Value];
|
|
||||||
|
|
||||||
long TimeDelta = Timestamp - Bucket.Timestamp;
|
|
||||||
|
|
||||||
if (TimeDelta <= MinTimeDelta)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Cache.TryRemove(Node.Value, out Bucket))
|
|
||||||
{
|
|
||||||
TotalSize -= Bucket.Size;
|
|
||||||
|
|
||||||
SortedCache.Remove(Bucket.Node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static long GetTimestamp()
|
|
||||||
{
|
|
||||||
long timestamp = Stopwatch.GetTimestamp();
|
|
||||||
|
|
||||||
return timestamp / (Stopwatch.Frequency / 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
49
ChocolArm64/BitUtils.cs
Normal file
49
ChocolArm64/BitUtils.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
namespace ChocolArm64
|
||||||
|
{
|
||||||
|
static class BitUtils
|
||||||
|
{
|
||||||
|
public static int HighestBitSet32(int value)
|
||||||
|
{
|
||||||
|
for (int bit = 31; bit >= 0; bit--)
|
||||||
|
{
|
||||||
|
if (((value >> bit) & 1) != 0)
|
||||||
|
{
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly sbyte[] HbsNibbleTbl = { -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 };
|
||||||
|
|
||||||
|
public static int HighestBitSetNibble(int value) => HbsNibbleTbl[value & 0b1111];
|
||||||
|
|
||||||
|
public static long Replicate(long bits, int size)
|
||||||
|
{
|
||||||
|
long output = 0;
|
||||||
|
|
||||||
|
for (int bit = 0; bit < 64; bit += size)
|
||||||
|
{
|
||||||
|
output |= bits << bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long FillWithOnes(int bits)
|
||||||
|
{
|
||||||
|
return bits == 64 ? -1L : (1L << bits) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long RotateRight(long bits, int shift, int size)
|
||||||
|
{
|
||||||
|
return (long)RotateRight((ulong)bits, shift, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ulong RotateRight(ulong bits, int shift, int size)
|
||||||
|
{
|
||||||
|
return (bits >> shift) | (bits << (size - shift));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,35 +5,35 @@ using System.Threading;
|
|||||||
|
|
||||||
namespace ChocolArm64
|
namespace ChocolArm64
|
||||||
{
|
{
|
||||||
public class AThread
|
public class CpuThread
|
||||||
{
|
{
|
||||||
public AThreadState ThreadState { get; private set; }
|
public CpuThreadState ThreadState { get; private set; }
|
||||||
public AMemory Memory { get; private set; }
|
public MemoryManager Memory { get; private set; }
|
||||||
|
|
||||||
private ATranslator Translator;
|
private Translator _translator;
|
||||||
|
|
||||||
public Thread Work;
|
public Thread Work;
|
||||||
|
|
||||||
public event EventHandler WorkFinished;
|
public event EventHandler WorkFinished;
|
||||||
|
|
||||||
private int IsExecuting;
|
private int _isExecuting;
|
||||||
|
|
||||||
public AThread(ATranslator Translator, AMemory Memory, long EntryPoint)
|
public CpuThread(Translator translator, MemoryManager memory, long entryPoint)
|
||||||
{
|
{
|
||||||
this.Translator = Translator;
|
_translator = translator;
|
||||||
this.Memory = Memory;
|
Memory = memory;
|
||||||
|
|
||||||
ThreadState = new AThreadState();
|
ThreadState = new CpuThreadState();
|
||||||
|
|
||||||
ThreadState.ExecutionMode = AExecutionMode.AArch64;
|
ThreadState.ExecutionMode = ExecutionMode.AArch64;
|
||||||
|
|
||||||
ThreadState.Running = true;
|
ThreadState.Running = true;
|
||||||
|
|
||||||
Work = new Thread(delegate()
|
Work = new Thread(delegate()
|
||||||
{
|
{
|
||||||
Translator.ExecuteSubroutine(this, EntryPoint);
|
translator.ExecuteSubroutine(this, entryPoint);
|
||||||
|
|
||||||
Memory.RemoveMonitor(ThreadState.Core);
|
memory.RemoveMonitor(ThreadState.Core);
|
||||||
|
|
||||||
WorkFinished?.Invoke(this, EventArgs.Empty);
|
WorkFinished?.Invoke(this, EventArgs.Empty);
|
||||||
});
|
});
|
||||||
@ -41,7 +41,7 @@ namespace ChocolArm64
|
|||||||
|
|
||||||
public bool Execute()
|
public bool Execute()
|
||||||
{
|
{
|
||||||
if (Interlocked.Exchange(ref IsExecuting, 1) == 1)
|
if (Interlocked.Exchange(ref _isExecuting, 1) == 1)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
@ -1,35 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class ABlock
|
|
||||||
{
|
|
||||||
public long Position { get; set; }
|
|
||||||
public long EndPosition { get; set; }
|
|
||||||
|
|
||||||
public ABlock Next { get; set; }
|
|
||||||
public ABlock Branch { get; set; }
|
|
||||||
|
|
||||||
public List<AOpCode> OpCodes { get; private set; }
|
|
||||||
|
|
||||||
public ABlock()
|
|
||||||
{
|
|
||||||
OpCodes = new List<AOpCode>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ABlock(long Position) : this()
|
|
||||||
{
|
|
||||||
this.Position = Position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AOpCode GetLastOp()
|
|
||||||
{
|
|
||||||
if (OpCodes.Count > 0)
|
|
||||||
{
|
|
||||||
return OpCodes[OpCodes.Count - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
enum ACond
|
|
||||||
{
|
|
||||||
Eq = 0,
|
|
||||||
Ne = 1,
|
|
||||||
Ge_Un = 2,
|
|
||||||
Lt_Un = 3,
|
|
||||||
Mi = 4,
|
|
||||||
Pl = 5,
|
|
||||||
Vs = 6,
|
|
||||||
Vc = 7,
|
|
||||||
Gt_Un = 8,
|
|
||||||
Le_Un = 9,
|
|
||||||
Ge = 10,
|
|
||||||
Lt = 11,
|
|
||||||
Gt = 12,
|
|
||||||
Le = 13,
|
|
||||||
Al = 14,
|
|
||||||
Nv = 15
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,239 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
using ChocolArm64.Memory;
|
|
||||||
using ChocolArm64.State;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection.Emit;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
static class ADecoder
|
|
||||||
{
|
|
||||||
private delegate object OpActivator(AInst Inst, long Position, int OpCode);
|
|
||||||
|
|
||||||
private static ConcurrentDictionary<Type, OpActivator> OpActivators;
|
|
||||||
|
|
||||||
static ADecoder()
|
|
||||||
{
|
|
||||||
OpActivators = new ConcurrentDictionary<Type, OpActivator>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ABlock DecodeBasicBlock(AThreadState State, AMemory Memory, long Start)
|
|
||||||
{
|
|
||||||
ABlock Block = new ABlock(Start);
|
|
||||||
|
|
||||||
FillBlock(State, Memory, Block);
|
|
||||||
|
|
||||||
return Block;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static (ABlock[] Graph, ABlock Root) DecodeSubroutine(
|
|
||||||
ATranslatorCache Cache,
|
|
||||||
AThreadState State,
|
|
||||||
AMemory Memory,
|
|
||||||
long Start)
|
|
||||||
{
|
|
||||||
Dictionary<long, ABlock> Visited = new Dictionary<long, ABlock>();
|
|
||||||
Dictionary<long, ABlock> VisitedEnd = new Dictionary<long, ABlock>();
|
|
||||||
|
|
||||||
Queue<ABlock> Blocks = new Queue<ABlock>();
|
|
||||||
|
|
||||||
ABlock Enqueue(long Position)
|
|
||||||
{
|
|
||||||
if (!Visited.TryGetValue(Position, out ABlock Output))
|
|
||||||
{
|
|
||||||
Output = new ABlock(Position);
|
|
||||||
|
|
||||||
Blocks.Enqueue(Output);
|
|
||||||
|
|
||||||
Visited.Add(Position, Output);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Output;
|
|
||||||
}
|
|
||||||
|
|
||||||
ABlock Root = Enqueue(Start);
|
|
||||||
|
|
||||||
while (Blocks.Count > 0)
|
|
||||||
{
|
|
||||||
ABlock Current = Blocks.Dequeue();
|
|
||||||
|
|
||||||
FillBlock(State, Memory, Current);
|
|
||||||
|
|
||||||
//Set child blocks. "Branch" is the block the branch instruction
|
|
||||||
//points to (when taken), "Next" is the block at the next address,
|
|
||||||
//executed when the branch is not taken. For Unconditional Branches
|
|
||||||
//(except BL/BLR that are sub calls) or end of executable, Next is null.
|
|
||||||
if (Current.OpCodes.Count > 0)
|
|
||||||
{
|
|
||||||
bool HasCachedSub = false;
|
|
||||||
|
|
||||||
AOpCode LastOp = Current.GetLastOp();
|
|
||||||
|
|
||||||
if (LastOp is AOpCodeBImm Op)
|
|
||||||
{
|
|
||||||
if (Op.Emitter == AInstEmit.Bl)
|
|
||||||
{
|
|
||||||
HasCachedSub = Cache.HasSubroutine(Op.Imm);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Current.Branch = Enqueue(Op.Imm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!((LastOp is AOpCodeBImmAl) ||
|
|
||||||
(LastOp is AOpCodeBReg)) || HasCachedSub)
|
|
||||||
{
|
|
||||||
Current.Next = Enqueue(Current.EndPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//If we have on the graph two blocks with the same end position,
|
|
||||||
//then we need to split the bigger block and have two small blocks,
|
|
||||||
//the end position of the bigger "Current" block should then be == to
|
|
||||||
//the position of the "Smaller" block.
|
|
||||||
while (VisitedEnd.TryGetValue(Current.EndPosition, out ABlock Smaller))
|
|
||||||
{
|
|
||||||
if (Current.Position > Smaller.Position)
|
|
||||||
{
|
|
||||||
ABlock Temp = Smaller;
|
|
||||||
|
|
||||||
Smaller = Current;
|
|
||||||
Current = Temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
Current.EndPosition = Smaller.Position;
|
|
||||||
Current.Next = Smaller;
|
|
||||||
Current.Branch = null;
|
|
||||||
|
|
||||||
Current.OpCodes.RemoveRange(
|
|
||||||
Current.OpCodes.Count - Smaller.OpCodes.Count,
|
|
||||||
Smaller.OpCodes.Count);
|
|
||||||
|
|
||||||
VisitedEnd[Smaller.EndPosition] = Smaller;
|
|
||||||
}
|
|
||||||
|
|
||||||
VisitedEnd.Add(Current.EndPosition, Current);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Make and sort Graph blocks array by position.
|
|
||||||
ABlock[] Graph = new ABlock[Visited.Count];
|
|
||||||
|
|
||||||
while (Visited.Count > 0)
|
|
||||||
{
|
|
||||||
ulong FirstPos = ulong.MaxValue;
|
|
||||||
|
|
||||||
foreach (ABlock Block in Visited.Values)
|
|
||||||
{
|
|
||||||
if (FirstPos > (ulong)Block.Position)
|
|
||||||
FirstPos = (ulong)Block.Position;
|
|
||||||
}
|
|
||||||
|
|
||||||
ABlock Current = Visited[(long)FirstPos];
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Graph[Graph.Length - Visited.Count] = Current;
|
|
||||||
|
|
||||||
Visited.Remove(Current.Position);
|
|
||||||
|
|
||||||
Current = Current.Next;
|
|
||||||
}
|
|
||||||
while (Current != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (Graph, Root);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void FillBlock(AThreadState State, AMemory Memory, ABlock Block)
|
|
||||||
{
|
|
||||||
long Position = Block.Position;
|
|
||||||
|
|
||||||
AOpCode OpCode;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
//TODO: This needs to be changed to support both AArch32 and AArch64,
|
|
||||||
//once JIT support is introduced on AArch32 aswell.
|
|
||||||
OpCode = DecodeOpCode(State, Memory, Position);
|
|
||||||
|
|
||||||
Block.OpCodes.Add(OpCode);
|
|
||||||
|
|
||||||
Position += 4;
|
|
||||||
}
|
|
||||||
while (!(IsBranch(OpCode) || IsException(OpCode)));
|
|
||||||
|
|
||||||
Block.EndPosition = Position;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsBranch(AOpCode OpCode)
|
|
||||||
{
|
|
||||||
return OpCode is AOpCodeBImm ||
|
|
||||||
OpCode is AOpCodeBReg;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsException(AOpCode OpCode)
|
|
||||||
{
|
|
||||||
return OpCode.Emitter == AInstEmit.Brk ||
|
|
||||||
OpCode.Emitter == AInstEmit.Svc ||
|
|
||||||
OpCode.Emitter == AInstEmit.Und;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AOpCode DecodeOpCode(AThreadState State, AMemory Memory, long Position)
|
|
||||||
{
|
|
||||||
int OpCode = Memory.ReadInt32(Position);
|
|
||||||
|
|
||||||
AInst Inst;
|
|
||||||
|
|
||||||
if (State.ExecutionMode == AExecutionMode.AArch64)
|
|
||||||
{
|
|
||||||
Inst = AOpCodeTable.GetInstA64(OpCode);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//TODO: Thumb support.
|
|
||||||
Inst = AOpCodeTable.GetInstA32(OpCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
AOpCode DecodedOpCode = new AOpCode(AInst.Undefined, Position, OpCode);
|
|
||||||
|
|
||||||
if (Inst.Type != null)
|
|
||||||
{
|
|
||||||
DecodedOpCode = MakeOpCode(Inst.Type, Inst, Position, OpCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return DecodedOpCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static AOpCode MakeOpCode(Type Type, AInst Inst, long Position, int OpCode)
|
|
||||||
{
|
|
||||||
if (Type == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(Type));
|
|
||||||
}
|
|
||||||
|
|
||||||
OpActivator CreateInstance = OpActivators.GetOrAdd(Type, CacheOpActivator);
|
|
||||||
|
|
||||||
return (AOpCode)CreateInstance(Inst, Position, OpCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static OpActivator CacheOpActivator(Type Type)
|
|
||||||
{
|
|
||||||
Type[] ArgTypes = new Type[] { typeof(AInst), typeof(long), typeof(int) };
|
|
||||||
|
|
||||||
DynamicMethod Mthd = new DynamicMethod($"Make{Type.Name}", Type, ArgTypes);
|
|
||||||
|
|
||||||
ILGenerator Generator = Mthd.GetILGenerator();
|
|
||||||
|
|
||||||
Generator.Emit(OpCodes.Ldarg_0);
|
|
||||||
Generator.Emit(OpCodes.Ldarg_1);
|
|
||||||
Generator.Emit(OpCodes.Ldarg_2);
|
|
||||||
Generator.Emit(OpCodes.Newobj, Type.GetConstructor(ArgTypes));
|
|
||||||
Generator.Emit(OpCodes.Ret);
|
|
||||||
|
|
||||||
return (OpActivator)Mthd.CreateDelegate(typeof(OpActivator));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,107 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
static class ADecoderHelper
|
|
||||||
{
|
|
||||||
public struct BitMask
|
|
||||||
{
|
|
||||||
public long WMask;
|
|
||||||
public long TMask;
|
|
||||||
public int Pos;
|
|
||||||
public int Shift;
|
|
||||||
public bool IsUndefined;
|
|
||||||
|
|
||||||
public static BitMask Invalid => new BitMask { IsUndefined = true };
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BitMask DecodeBitMask(int OpCode, bool Immediate)
|
|
||||||
{
|
|
||||||
int ImmS = (OpCode >> 10) & 0x3f;
|
|
||||||
int ImmR = (OpCode >> 16) & 0x3f;
|
|
||||||
|
|
||||||
int N = (OpCode >> 22) & 1;
|
|
||||||
int SF = (OpCode >> 31) & 1;
|
|
||||||
|
|
||||||
int Length = ABitUtils.HighestBitSet32((~ImmS & 0x3f) | (N << 6));
|
|
||||||
|
|
||||||
if (Length < 1 || (SF == 0 && N != 0))
|
|
||||||
{
|
|
||||||
return BitMask.Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Size = 1 << Length;
|
|
||||||
|
|
||||||
int Levels = Size - 1;
|
|
||||||
|
|
||||||
int S = ImmS & Levels;
|
|
||||||
int R = ImmR & Levels;
|
|
||||||
|
|
||||||
if (Immediate && S == Levels)
|
|
||||||
{
|
|
||||||
return BitMask.Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
long WMask = ABitUtils.FillWithOnes(S + 1);
|
|
||||||
long TMask = ABitUtils.FillWithOnes(((S - R) & Levels) + 1);
|
|
||||||
|
|
||||||
if (R > 0)
|
|
||||||
{
|
|
||||||
WMask = ABitUtils.RotateRight(WMask, R, Size);
|
|
||||||
WMask &= ABitUtils.FillWithOnes(Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new BitMask()
|
|
||||||
{
|
|
||||||
WMask = ABitUtils.Replicate(WMask, Size),
|
|
||||||
TMask = ABitUtils.Replicate(TMask, Size),
|
|
||||||
|
|
||||||
Pos = ImmS,
|
|
||||||
Shift = ImmR
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long DecodeImm8Float(long Imm, int Size)
|
|
||||||
{
|
|
||||||
int E = 0, F = 0;
|
|
||||||
|
|
||||||
switch (Size)
|
|
||||||
{
|
|
||||||
case 0: E = 8; F = 23; break;
|
|
||||||
case 1: E = 11; F = 52; break;
|
|
||||||
|
|
||||||
default: throw new ArgumentOutOfRangeException(nameof(Size));
|
|
||||||
}
|
|
||||||
|
|
||||||
long Value = (Imm & 0x3f) << F - 4;
|
|
||||||
|
|
||||||
long EBit = (Imm >> 6) & 1;
|
|
||||||
long SBit = (Imm >> 7) & 1;
|
|
||||||
|
|
||||||
if (EBit != 0)
|
|
||||||
{
|
|
||||||
Value |= (1L << E - 3) - 1 << F + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value |= (EBit ^ 1) << F + E - 1;
|
|
||||||
Value |= SBit << F + E;
|
|
||||||
|
|
||||||
return Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long DecodeImm26_2(int OpCode)
|
|
||||||
{
|
|
||||||
return ((long)OpCode << 38) >> 36;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long DecodeImmS19_2(int OpCode)
|
|
||||||
{
|
|
||||||
return (((long)OpCode << 40) >> 43) & ~3;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long DecodeImmS14_2(int OpCode)
|
|
||||||
{
|
|
||||||
return (((long)OpCode << 45) >> 48) & ~3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
using ChocolArm64.State;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCode : IAOpCode
|
|
||||||
{
|
|
||||||
public long Position { get; private set; }
|
|
||||||
public int RawOpCode { get; private set; }
|
|
||||||
|
|
||||||
public AInstEmitter Emitter { get; protected set; }
|
|
||||||
public AInstInterpreter Interpreter { get; protected set; }
|
|
||||||
public ARegisterSize RegisterSize { get; protected set; }
|
|
||||||
|
|
||||||
public AOpCode(AInst Inst, long Position, int OpCode)
|
|
||||||
{
|
|
||||||
this.Position = Position;
|
|
||||||
this.RawOpCode = OpCode;
|
|
||||||
|
|
||||||
RegisterSize = ARegisterSize.Int64;
|
|
||||||
|
|
||||||
Emitter = Inst.Emitter;
|
|
||||||
Interpreter = Inst.Interpreter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetBitsCount()
|
|
||||||
{
|
|
||||||
switch (RegisterSize)
|
|
||||||
{
|
|
||||||
case ARegisterSize.Int32: return 32;
|
|
||||||
case ARegisterSize.Int64: return 64;
|
|
||||||
case ARegisterSize.SIMD64: return 64;
|
|
||||||
case ARegisterSize.SIMD128: return 128;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InvalidOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeAdr : AOpCode
|
|
||||||
{
|
|
||||||
public int Rd { get; private set; }
|
|
||||||
public long Imm { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeAdr(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Rd = OpCode & 0x1f;
|
|
||||||
|
|
||||||
Imm = ADecoderHelper.DecodeImmS19_2(OpCode);
|
|
||||||
Imm |= ((long)OpCode >> 29) & 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
using ChocolArm64.State;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeAlu : AOpCode, IAOpCodeAlu
|
|
||||||
{
|
|
||||||
public int Rd { get; protected set; }
|
|
||||||
public int Rn { get; private set; }
|
|
||||||
|
|
||||||
public ADataOp DataOp { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeAlu(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Rd = (OpCode >> 0) & 0x1f;
|
|
||||||
Rn = (OpCode >> 5) & 0x1f;
|
|
||||||
DataOp = (ADataOp)((OpCode >> 24) & 0x3);
|
|
||||||
|
|
||||||
RegisterSize = (OpCode >> 31) != 0
|
|
||||||
? ARegisterSize.Int64
|
|
||||||
: ARegisterSize.Int32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeAluImm : AOpCodeAlu, IAOpCodeAluImm
|
|
||||||
{
|
|
||||||
public long Imm { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeAluImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
if (DataOp == ADataOp.Arithmetic)
|
|
||||||
{
|
|
||||||
Imm = (OpCode >> 10) & 0xfff;
|
|
||||||
|
|
||||||
int Shift = (OpCode >> 22) & 3;
|
|
||||||
|
|
||||||
Imm <<= Shift * 12;
|
|
||||||
}
|
|
||||||
else if (DataOp == ADataOp.Logical)
|
|
||||||
{
|
|
||||||
var BM = ADecoderHelper.DecodeBitMask(OpCode, true);
|
|
||||||
|
|
||||||
if (BM.IsUndefined)
|
|
||||||
{
|
|
||||||
Emitter = AInstEmit.Und;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Imm = BM.WMask;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new ArgumentException(nameof(OpCode));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeAluRs : AOpCodeAlu, IAOpCodeAluRs
|
|
||||||
{
|
|
||||||
public int Shift { get; private set; }
|
|
||||||
public int Rm { get; private set; }
|
|
||||||
|
|
||||||
public AShiftType ShiftType { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeAluRs(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
int Shift = (OpCode >> 10) & 0x3f;
|
|
||||||
|
|
||||||
if (Shift >= GetBitsCount())
|
|
||||||
{
|
|
||||||
Emitter = AInstEmit.Und;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Shift = Shift;
|
|
||||||
|
|
||||||
Rm = (OpCode >> 16) & 0x1f;
|
|
||||||
ShiftType = (AShiftType)((OpCode >> 22) & 0x3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeAluRx : AOpCodeAlu, IAOpCodeAluRx
|
|
||||||
{
|
|
||||||
public int Shift { get; private set; }
|
|
||||||
public int Rm { get; private set; }
|
|
||||||
|
|
||||||
public AIntType IntType { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeAluRx(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Shift = (OpCode >> 10) & 0x7;
|
|
||||||
IntType = (AIntType)((OpCode >> 13) & 0x7);
|
|
||||||
Rm = (OpCode >> 16) & 0x1f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeBImm : AOpCode
|
|
||||||
{
|
|
||||||
public long Imm { get; protected set; }
|
|
||||||
|
|
||||||
public AOpCodeBImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) { }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeBImmAl : AOpCodeBImm
|
|
||||||
{
|
|
||||||
public AOpCodeBImmAl(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Imm = Position + ADecoderHelper.DecodeImm26_2(OpCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
using ChocolArm64.State;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeBImmCmp : AOpCodeBImm
|
|
||||||
{
|
|
||||||
public int Rt { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeBImmCmp(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Rt = OpCode & 0x1f;
|
|
||||||
|
|
||||||
Imm = Position + ADecoderHelper.DecodeImmS19_2(OpCode);
|
|
||||||
|
|
||||||
RegisterSize = (OpCode >> 31) != 0
|
|
||||||
? ARegisterSize.Int64
|
|
||||||
: ARegisterSize.Int32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeBImmCond : AOpCodeBImm, IAOpCodeCond
|
|
||||||
{
|
|
||||||
public ACond Cond { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeBImmCond(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
int O0 = (OpCode >> 4) & 1;
|
|
||||||
|
|
||||||
if (O0 != 0)
|
|
||||||
{
|
|
||||||
Emitter = AInstEmit.Und;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Cond = (ACond)(OpCode & 0xf);
|
|
||||||
|
|
||||||
Imm = Position + ADecoderHelper.DecodeImmS19_2(OpCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeBImmTest : AOpCodeBImm
|
|
||||||
{
|
|
||||||
public int Rt { get; private set; }
|
|
||||||
public int Pos { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeBImmTest(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Rt = OpCode & 0x1f;
|
|
||||||
|
|
||||||
Imm = Position + ADecoderHelper.DecodeImmS14_2(OpCode);
|
|
||||||
|
|
||||||
Pos = (OpCode >> 19) & 0x1f;
|
|
||||||
Pos |= (OpCode >> 26) & 0x20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeBReg : AOpCode
|
|
||||||
{
|
|
||||||
public int Rn { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeBReg(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
int Op4 = (OpCode >> 0) & 0x1f;
|
|
||||||
int Op2 = (OpCode >> 16) & 0x1f;
|
|
||||||
|
|
||||||
if (Op2 != 0b11111 || Op4 != 0b00000)
|
|
||||||
{
|
|
||||||
Emitter = AInstEmit.Und;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rn = (OpCode >> 5) & 0x1f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeBfm : AOpCodeAlu
|
|
||||||
{
|
|
||||||
public long WMask { get; private set; }
|
|
||||||
public long TMask { get; private set; }
|
|
||||||
public int Pos { get; private set; }
|
|
||||||
public int Shift { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeBfm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
var BM = ADecoderHelper.DecodeBitMask(OpCode, false);
|
|
||||||
|
|
||||||
if (BM.IsUndefined)
|
|
||||||
{
|
|
||||||
Emitter = AInstEmit.Und;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WMask = BM.WMask;
|
|
||||||
TMask = BM.TMask;
|
|
||||||
Pos = BM.Pos;
|
|
||||||
Shift = BM.Shift;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
using ChocolArm64.State;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeCcmp : AOpCodeAlu, IAOpCodeCond
|
|
||||||
{
|
|
||||||
public int NZCV { get; private set; }
|
|
||||||
protected int RmImm;
|
|
||||||
|
|
||||||
public ACond Cond { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeCcmp(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
int O3 = (OpCode >> 4) & 1;
|
|
||||||
|
|
||||||
if (O3 != 0)
|
|
||||||
{
|
|
||||||
Emitter = AInstEmit.Und;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NZCV = (OpCode >> 0) & 0xf;
|
|
||||||
Cond = (ACond)((OpCode >> 12) & 0xf);
|
|
||||||
RmImm = (OpCode >> 16) & 0x1f;
|
|
||||||
|
|
||||||
Rd = AThreadState.ZRIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeCcmpImm : AOpCodeCcmp, IAOpCodeAluImm
|
|
||||||
{
|
|
||||||
public long Imm => RmImm;
|
|
||||||
|
|
||||||
public AOpCodeCcmpImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) { }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeCcmpReg : AOpCodeCcmp, IAOpCodeAluRs
|
|
||||||
{
|
|
||||||
public int Rm => RmImm;
|
|
||||||
|
|
||||||
public int Shift => 0;
|
|
||||||
|
|
||||||
public AShiftType ShiftType => AShiftType.Lsl;
|
|
||||||
|
|
||||||
public AOpCodeCcmpReg(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) { }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeCsel : AOpCodeAlu, IAOpCodeCond
|
|
||||||
{
|
|
||||||
public int Rm { get; private set; }
|
|
||||||
|
|
||||||
public ACond Cond { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeCsel(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Rm = (OpCode >> 16) & 0x1f;
|
|
||||||
Cond = (ACond)((OpCode >> 12) & 0xf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeException : AOpCode
|
|
||||||
{
|
|
||||||
public int Id { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeException(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Id = (OpCode >> 5) & 0xffff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeMem : AOpCode
|
|
||||||
{
|
|
||||||
public int Rt { get; protected set; }
|
|
||||||
public int Rn { get; protected set; }
|
|
||||||
public int Size { get; protected set; }
|
|
||||||
public bool Extend64 { get; protected set; }
|
|
||||||
|
|
||||||
public AOpCodeMem(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Rt = (OpCode >> 0) & 0x1f;
|
|
||||||
Rn = (OpCode >> 5) & 0x1f;
|
|
||||||
Size = (OpCode >> 30) & 0x3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeMemEx : AOpCodeMem
|
|
||||||
{
|
|
||||||
public int Rt2 { get; private set; }
|
|
||||||
public int Rs { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeMemEx(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Rt2 = (OpCode >> 10) & 0x1f;
|
|
||||||
Rs = (OpCode >> 16) & 0x1f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeMemPair : AOpCodeMemImm
|
|
||||||
{
|
|
||||||
public int Rt2 { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeMemPair(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Rt2 = (OpCode >> 10) & 0x1f;
|
|
||||||
WBack = ((OpCode >> 23) & 0x1) != 0;
|
|
||||||
PostIdx = ((OpCode >> 23) & 0x3) == 1;
|
|
||||||
Extend64 = ((OpCode >> 30) & 0x3) == 1;
|
|
||||||
Size = ((OpCode >> 31) & 0x1) | 2;
|
|
||||||
|
|
||||||
DecodeImm(OpCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void DecodeImm(int OpCode)
|
|
||||||
{
|
|
||||||
Imm = ((long)(OpCode >> 15) << 57) >> (57 - Size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeMemReg : AOpCodeMem
|
|
||||||
{
|
|
||||||
public bool Shift { get; private set; }
|
|
||||||
public int Rm { get; private set; }
|
|
||||||
|
|
||||||
public AIntType IntType { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeMemReg(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Shift = ((OpCode >> 12) & 0x1) != 0;
|
|
||||||
IntType = (AIntType)((OpCode >> 13) & 0x7);
|
|
||||||
Rm = (OpCode >> 16) & 0x1f;
|
|
||||||
Extend64 = ((OpCode >> 22) & 0x3) == 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
using ChocolArm64.State;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeMov : AOpCode
|
|
||||||
{
|
|
||||||
public int Rd { get; private set; }
|
|
||||||
public long Imm { get; private set; }
|
|
||||||
public int Pos { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeMov(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
int P1 = (OpCode >> 22) & 1;
|
|
||||||
int SF = (OpCode >> 31) & 1;
|
|
||||||
|
|
||||||
if (SF == 0 && P1 != 0)
|
|
||||||
{
|
|
||||||
Emitter = AInstEmit.Und;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rd = (OpCode >> 0) & 0x1f;
|
|
||||||
Imm = (OpCode >> 5) & 0xffff;
|
|
||||||
Pos = (OpCode >> 21) & 0x3;
|
|
||||||
|
|
||||||
Pos <<= 4;
|
|
||||||
Imm <<= Pos;
|
|
||||||
|
|
||||||
RegisterSize = (OpCode >> 31) != 0
|
|
||||||
? ARegisterSize.Int64
|
|
||||||
: ARegisterSize.Int32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeMul : AOpCodeAlu
|
|
||||||
{
|
|
||||||
public int Rm { get; private set; }
|
|
||||||
public int Ra { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeMul(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Ra = (OpCode >> 10) & 0x1f;
|
|
||||||
Rm = (OpCode >> 16) & 0x1f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
using ChocolArm64.State;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimd : AOpCode, IAOpCodeSimd
|
|
||||||
{
|
|
||||||
public int Rd { get; private set; }
|
|
||||||
public int Rn { get; private set; }
|
|
||||||
public int Opc { get; private set; }
|
|
||||||
public int Size { get; protected set; }
|
|
||||||
|
|
||||||
public AOpCodeSimd(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Rd = (OpCode >> 0) & 0x1f;
|
|
||||||
Rn = (OpCode >> 5) & 0x1f;
|
|
||||||
Opc = (OpCode >> 15) & 0x3;
|
|
||||||
Size = (OpCode >> 22) & 0x3;
|
|
||||||
|
|
||||||
RegisterSize = ((OpCode >> 30) & 1) != 0
|
|
||||||
? ARegisterSize.SIMD128
|
|
||||||
: ARegisterSize.SIMD64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
using ChocolArm64.State;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdCvt : AOpCodeSimd
|
|
||||||
{
|
|
||||||
public int FBits { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeSimdCvt(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
//TODO:
|
|
||||||
//Und of Fixed Point variants.
|
|
||||||
int Scale = (OpCode >> 10) & 0x3f;
|
|
||||||
int SF = (OpCode >> 31) & 0x1;
|
|
||||||
|
|
||||||
/*if (Type != SF && !(Type == 2 && SF == 1))
|
|
||||||
{
|
|
||||||
Emitter = AInstEmit.Und;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
FBits = 64 - Scale;
|
|
||||||
|
|
||||||
RegisterSize = SF != 0
|
|
||||||
? ARegisterSize.Int64
|
|
||||||
: ARegisterSize.Int32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdExt : AOpCodeSimdReg
|
|
||||||
{
|
|
||||||
public int Imm4 { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeSimdExt(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Imm4 = (OpCode >> 11) & 0xf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdFcond : AOpCodeSimdReg, IAOpCodeCond
|
|
||||||
{
|
|
||||||
public int NZCV { get; private set; }
|
|
||||||
|
|
||||||
public ACond Cond { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeSimdFcond(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
NZCV = (OpCode >> 0) & 0xf;
|
|
||||||
Cond = (ACond)((OpCode >> 12) & 0xf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdFmov : AOpCode, IAOpCodeSimd
|
|
||||||
{
|
|
||||||
public int Rd { get; private set; }
|
|
||||||
public long Imm { get; private set; }
|
|
||||||
public int Size { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeSimdFmov(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
int Imm5 = (OpCode >> 5) & 0x1f;
|
|
||||||
int Type = (OpCode >> 22) & 0x3;
|
|
||||||
|
|
||||||
if (Imm5 != 0b00000 || Type > 1)
|
|
||||||
{
|
|
||||||
Emitter = AInstEmit.Und;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Size = Type;
|
|
||||||
|
|
||||||
long Imm;
|
|
||||||
|
|
||||||
Rd = (OpCode >> 0) & 0x1f;
|
|
||||||
Imm = (OpCode >> 13) & 0xff;
|
|
||||||
|
|
||||||
this.Imm = ADecoderHelper.DecodeImm8Float(Imm, Type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,101 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
using ChocolArm64.State;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdImm : AOpCode, IAOpCodeSimd
|
|
||||||
{
|
|
||||||
public int Rd { get; private set; }
|
|
||||||
public long Imm { get; private set; }
|
|
||||||
public int Size { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeSimdImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Rd = OpCode & 0x1f;
|
|
||||||
|
|
||||||
int CMode = (OpCode >> 12) & 0xf;
|
|
||||||
int Op = (OpCode >> 29) & 0x1;
|
|
||||||
|
|
||||||
int ModeLow = CMode & 1;
|
|
||||||
int ModeHigh = CMode >> 1;
|
|
||||||
|
|
||||||
long Imm;
|
|
||||||
|
|
||||||
Imm = ((uint)OpCode >> 5) & 0x1f;
|
|
||||||
Imm |= ((uint)OpCode >> 11) & 0xe0;
|
|
||||||
|
|
||||||
if (ModeHigh == 0b111)
|
|
||||||
{
|
|
||||||
Size = ModeLow != 0 ? Op : 3;
|
|
||||||
|
|
||||||
switch (Op | (ModeLow << 1))
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
//64-bits Immediate.
|
|
||||||
//Transform abcd efgh into abcd efgh abcd efgh ...
|
|
||||||
Imm = (long)((ulong)Imm * 0x0101010101010101);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
//64-bits Immediate.
|
|
||||||
//Transform abcd efgh into aaaa aaaa bbbb bbbb ...
|
|
||||||
Imm = (Imm & 0xf0) >> 4 | (Imm & 0x0f) << 4;
|
|
||||||
Imm = (Imm & 0xcc) >> 2 | (Imm & 0x33) << 2;
|
|
||||||
Imm = (Imm & 0xaa) >> 1 | (Imm & 0x55) << 1;
|
|
||||||
|
|
||||||
Imm = (long)((ulong)Imm * 0x8040201008040201);
|
|
||||||
Imm = (long)((ulong)Imm & 0x8080808080808080);
|
|
||||||
|
|
||||||
Imm |= Imm >> 4;
|
|
||||||
Imm |= Imm >> 2;
|
|
||||||
Imm |= Imm >> 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
case 3:
|
|
||||||
//Floating point Immediate.
|
|
||||||
Imm = ADecoderHelper.DecodeImm8Float(Imm, Size);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((ModeHigh & 0b110) == 0b100)
|
|
||||||
{
|
|
||||||
//16-bits shifted Immediate.
|
|
||||||
Size = 1; Imm <<= (ModeHigh & 1) << 3;
|
|
||||||
}
|
|
||||||
else if ((ModeHigh & 0b100) == 0b000)
|
|
||||||
{
|
|
||||||
//32-bits shifted Immediate.
|
|
||||||
Size = 2; Imm <<= ModeHigh << 3;
|
|
||||||
}
|
|
||||||
else if ((ModeHigh & 0b111) == 0b110)
|
|
||||||
{
|
|
||||||
//32-bits shifted Immediate (fill with ones).
|
|
||||||
Size = 2; Imm = ShlOnes(Imm, 8 << ModeLow);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//8 bits without shift.
|
|
||||||
Size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Imm = Imm;
|
|
||||||
|
|
||||||
RegisterSize = ((OpCode >> 30) & 1) != 0
|
|
||||||
? ARegisterSize.SIMD128
|
|
||||||
: ARegisterSize.SIMD64;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static long ShlOnes(long Value, int Shift)
|
|
||||||
{
|
|
||||||
if (Shift != 0)
|
|
||||||
{
|
|
||||||
return Value << Shift | (long)(ulong.MaxValue >> (64 - Shift));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdIns : AOpCodeSimd
|
|
||||||
{
|
|
||||||
public int SrcIndex { get; private set; }
|
|
||||||
public int DstIndex { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeSimdIns(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
int Imm4 = (OpCode >> 11) & 0xf;
|
|
||||||
int Imm5 = (OpCode >> 16) & 0x1f;
|
|
||||||
|
|
||||||
if (Imm5 == 0b10000)
|
|
||||||
{
|
|
||||||
Emitter = AInstEmit.Und;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Size = Imm5 & -Imm5;
|
|
||||||
|
|
||||||
switch (Size)
|
|
||||||
{
|
|
||||||
case 1: Size = 0; break;
|
|
||||||
case 2: Size = 1; break;
|
|
||||||
case 4: Size = 2; break;
|
|
||||||
case 8: Size = 3; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
SrcIndex = Imm4 >> Size;
|
|
||||||
DstIndex = Imm5 >> (Size + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdMemImm : AOpCodeMemImm, IAOpCodeSimd
|
|
||||||
{
|
|
||||||
public AOpCodeSimdMemImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Size |= (OpCode >> 21) & 4;
|
|
||||||
|
|
||||||
if (!WBack && !Unscaled && Size >= 4)
|
|
||||||
{
|
|
||||||
Imm <<= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
Extend64 = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdMemLit : AOpCode, IAOpCodeSimd, IAOpCodeLit
|
|
||||||
{
|
|
||||||
public int Rt { get; private set; }
|
|
||||||
public long Imm { get; private set; }
|
|
||||||
public int Size { get; private set; }
|
|
||||||
public bool Signed => false;
|
|
||||||
public bool Prefetch => false;
|
|
||||||
|
|
||||||
public AOpCodeSimdMemLit(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
int Opc = (OpCode >> 30) & 3;
|
|
||||||
|
|
||||||
if (Opc == 3)
|
|
||||||
{
|
|
||||||
Emitter = AInstEmit.Und;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rt = OpCode & 0x1f;
|
|
||||||
|
|
||||||
Imm = Position + ADecoderHelper.DecodeImmS19_2(OpCode);
|
|
||||||
|
|
||||||
Size = Opc + 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdMemPair : AOpCodeMemPair, IAOpCodeSimd
|
|
||||||
{
|
|
||||||
public AOpCodeSimdMemPair(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Size = ((OpCode >> 30) & 3) + 2;
|
|
||||||
|
|
||||||
Extend64 = false;
|
|
||||||
|
|
||||||
DecodeImm(OpCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdMemReg : AOpCodeMemReg, IAOpCodeSimd
|
|
||||||
{
|
|
||||||
public AOpCodeSimdMemReg(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Size |= (OpCode >> 21) & 4;
|
|
||||||
|
|
||||||
Extend64 = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
using ChocolArm64.State;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdMemSs : AOpCodeMemReg, IAOpCodeSimd
|
|
||||||
{
|
|
||||||
public int SElems { get; private set; }
|
|
||||||
public int Index { get; private set; }
|
|
||||||
public bool Replicate { get; private set; }
|
|
||||||
public bool WBack { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeSimdMemSs(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
int Size = (OpCode >> 10) & 3;
|
|
||||||
int S = (OpCode >> 12) & 1;
|
|
||||||
int SElems = (OpCode >> 12) & 2;
|
|
||||||
int Scale = (OpCode >> 14) & 3;
|
|
||||||
int L = (OpCode >> 22) & 1;
|
|
||||||
int Q = (OpCode >> 30) & 1;
|
|
||||||
|
|
||||||
SElems |= (OpCode >> 21) & 1;
|
|
||||||
|
|
||||||
SElems++;
|
|
||||||
|
|
||||||
int Index = (Q << 3) | (S << 2) | Size;
|
|
||||||
|
|
||||||
switch (Scale)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
if ((Size & 1) != 0)
|
|
||||||
{
|
|
||||||
Inst = AInst.Undefined;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Index >>= 1;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
if ((Size & 2) != 0 ||
|
|
||||||
((Size & 1) != 0 && S != 0))
|
|
||||||
{
|
|
||||||
Inst = AInst.Undefined;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((Size & 1) != 0)
|
|
||||||
{
|
|
||||||
Index >>= 3;
|
|
||||||
|
|
||||||
Scale = 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Index >>= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
if (L == 0 || S != 0)
|
|
||||||
{
|
|
||||||
Inst = AInst.Undefined;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Scale = Size;
|
|
||||||
|
|
||||||
Replicate = true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Index = Index;
|
|
||||||
this.SElems = SElems;
|
|
||||||
this.Size = Scale;
|
|
||||||
|
|
||||||
Extend64 = false;
|
|
||||||
|
|
||||||
WBack = ((OpCode >> 23) & 1) != 0;
|
|
||||||
|
|
||||||
RegisterSize = Q != 0
|
|
||||||
? ARegisterSize.SIMD128
|
|
||||||
: ARegisterSize.SIMD64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdReg : AOpCodeSimd
|
|
||||||
{
|
|
||||||
public bool Bit3 { get; private set; }
|
|
||||||
public int Ra { get; private set; }
|
|
||||||
public int Rm { get; protected set; }
|
|
||||||
|
|
||||||
public AOpCodeSimdReg(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Bit3 = ((OpCode >> 3) & 0x1) != 0;
|
|
||||||
Ra = (OpCode >> 10) & 0x1f;
|
|
||||||
Rm = (OpCode >> 16) & 0x1f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdRegElem : AOpCodeSimdReg
|
|
||||||
{
|
|
||||||
public int Index { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeSimdRegElem(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
switch (Size)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
Index = (OpCode >> 20) & 3 |
|
|
||||||
(OpCode >> 9) & 4;
|
|
||||||
|
|
||||||
Rm &= 0xf;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
Index = (OpCode >> 21) & 1 |
|
|
||||||
(OpCode >> 10) & 2;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: Emitter = AInstEmit.Und; return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdRegElemF : AOpCodeSimdReg
|
|
||||||
{
|
|
||||||
public int Index { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeSimdRegElemF(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
switch ((OpCode >> 21) & 3) // sz:L
|
|
||||||
{
|
|
||||||
case 0: // H:0
|
|
||||||
Index = (OpCode >> 10) & 2; // 0, 2
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: // H:1
|
|
||||||
Index = (OpCode >> 10) & 2;
|
|
||||||
Index++; // 1, 3
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2: // H
|
|
||||||
Index = (OpCode >> 11) & 1; // 0, 1
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: Emitter = AInstEmit.Und; return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdShImm : AOpCodeSimd
|
|
||||||
{
|
|
||||||
public int Imm { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeSimdShImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Imm = (OpCode >> 16) & 0x7f;
|
|
||||||
|
|
||||||
Size = ABitUtils.HighestBitSetNibble(Imm >> 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSimdTbl : AOpCodeSimdReg
|
|
||||||
{
|
|
||||||
public AOpCodeSimdTbl(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Size = ((OpCode >> 13) & 3) + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
class AOpCodeSystem : AOpCode
|
|
||||||
{
|
|
||||||
public int Rt { get; private set; }
|
|
||||||
public int Op2 { get; private set; }
|
|
||||||
public int CRm { get; private set; }
|
|
||||||
public int CRn { get; private set; }
|
|
||||||
public int Op1 { get; private set; }
|
|
||||||
public int Op0 { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeSystem(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Rt = (OpCode >> 0) & 0x1f;
|
|
||||||
Op2 = (OpCode >> 5) & 0x7;
|
|
||||||
CRm = (OpCode >> 8) & 0xf;
|
|
||||||
CRn = (OpCode >> 12) & 0xf;
|
|
||||||
Op1 = (OpCode >> 16) & 0x7;
|
|
||||||
Op0 = ((OpCode >> 19) & 0x1) | 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
using ChocolArm64.State;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
interface IAOpCode
|
|
||||||
{
|
|
||||||
long Position { get; }
|
|
||||||
|
|
||||||
AInstEmitter Emitter { get; }
|
|
||||||
ARegisterSize RegisterSize { get; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
interface IAOpCodeAlu : IAOpCode
|
|
||||||
{
|
|
||||||
int Rd { get; }
|
|
||||||
int Rn { get; }
|
|
||||||
|
|
||||||
ADataOp DataOp { get; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
interface IAOpCodeAluImm : IAOpCodeAlu
|
|
||||||
{
|
|
||||||
long Imm { get; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
interface IAOpCodeAluRs : IAOpCodeAlu
|
|
||||||
{
|
|
||||||
int Shift { get; }
|
|
||||||
int Rm { get; }
|
|
||||||
|
|
||||||
AShiftType ShiftType { get; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
interface IAOpCodeAluRx : IAOpCodeAlu
|
|
||||||
{
|
|
||||||
int Shift { get; }
|
|
||||||
int Rm { get; }
|
|
||||||
|
|
||||||
AIntType IntType { get; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
interface IAOpCodeCond : IAOpCode
|
|
||||||
{
|
|
||||||
ACond Cond { get; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
namespace ChocolArm64.Decoder
|
|
||||||
{
|
|
||||||
interface IAOpCodeSimd : IAOpCode
|
|
||||||
{
|
|
||||||
int Size { get; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
using ChocolArm64.Decoder;
|
|
||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder32
|
|
||||||
{
|
|
||||||
class A32OpCode : AOpCode
|
|
||||||
{
|
|
||||||
public ACond Cond { get; private set; }
|
|
||||||
|
|
||||||
public A32OpCode(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Cond = (ACond)((uint)OpCode >> 28);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
using ChocolArm64.Instruction;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder32
|
|
||||||
{
|
|
||||||
class A32OpCodeBImmAl : A32OpCode
|
|
||||||
{
|
|
||||||
public int Imm;
|
|
||||||
public int H;
|
|
||||||
|
|
||||||
public A32OpCodeBImmAl(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
|
||||||
{
|
|
||||||
Imm = (OpCode << 8) >> 6;
|
|
||||||
H = (OpCode >> 23) & 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
35
ChocolArm64/Decoders/Block.cs
Normal file
35
ChocolArm64/Decoders/Block.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class Block
|
||||||
|
{
|
||||||
|
public long Position { get; set; }
|
||||||
|
public long EndPosition { get; set; }
|
||||||
|
|
||||||
|
public Block Next { get; set; }
|
||||||
|
public Block Branch { get; set; }
|
||||||
|
|
||||||
|
public List<OpCode64> OpCodes { get; private set; }
|
||||||
|
|
||||||
|
public Block()
|
||||||
|
{
|
||||||
|
OpCodes = new List<OpCode64>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block(long position) : this()
|
||||||
|
{
|
||||||
|
Position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OpCode64 GetLastOp()
|
||||||
|
{
|
||||||
|
if (OpCodes.Count > 0)
|
||||||
|
{
|
||||||
|
return OpCodes[OpCodes.Count - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
ChocolArm64/Decoders/Cond.cs
Normal file
22
ChocolArm64/Decoders/Cond.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
enum Cond
|
||||||
|
{
|
||||||
|
Eq = 0,
|
||||||
|
Ne = 1,
|
||||||
|
GeUn = 2,
|
||||||
|
LtUn = 3,
|
||||||
|
Mi = 4,
|
||||||
|
Pl = 5,
|
||||||
|
Vs = 6,
|
||||||
|
Vc = 7,
|
||||||
|
GtUn = 8,
|
||||||
|
LeUn = 9,
|
||||||
|
Ge = 10,
|
||||||
|
Lt = 11,
|
||||||
|
Gt = 12,
|
||||||
|
Le = 13,
|
||||||
|
Al = 14,
|
||||||
|
Nv = 15
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
namespace ChocolArm64.Decoder
|
namespace ChocolArm64.Decoders
|
||||||
{
|
{
|
||||||
enum ADataOp
|
enum DataOp
|
||||||
{
|
{
|
||||||
Adr = 0,
|
Adr = 0,
|
||||||
Arithmetic = 1,
|
Arithmetic = 1,
|
239
ChocolArm64/Decoders/Decoder.cs
Normal file
239
ChocolArm64/Decoders/Decoder.cs
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
using ChocolArm64.Memory;
|
||||||
|
using ChocolArm64.State;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection.Emit;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
static class Decoder
|
||||||
|
{
|
||||||
|
private delegate object OpActivator(Inst inst, long position, int opCode);
|
||||||
|
|
||||||
|
private static ConcurrentDictionary<Type, OpActivator> _opActivators;
|
||||||
|
|
||||||
|
static Decoder()
|
||||||
|
{
|
||||||
|
_opActivators = new ConcurrentDictionary<Type, OpActivator>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Block DecodeBasicBlock(CpuThreadState state, MemoryManager memory, long start)
|
||||||
|
{
|
||||||
|
Block block = new Block(start);
|
||||||
|
|
||||||
|
FillBlock(state, memory, block);
|
||||||
|
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static (Block[] Graph, Block Root) DecodeSubroutine(
|
||||||
|
TranslatorCache cache,
|
||||||
|
CpuThreadState state,
|
||||||
|
MemoryManager memory,
|
||||||
|
long start)
|
||||||
|
{
|
||||||
|
Dictionary<long, Block> visited = new Dictionary<long, Block>();
|
||||||
|
Dictionary<long, Block> visitedEnd = new Dictionary<long, Block>();
|
||||||
|
|
||||||
|
Queue<Block> blocks = new Queue<Block>();
|
||||||
|
|
||||||
|
Block Enqueue(long position)
|
||||||
|
{
|
||||||
|
if (!visited.TryGetValue(position, out Block output))
|
||||||
|
{
|
||||||
|
output = new Block(position);
|
||||||
|
|
||||||
|
blocks.Enqueue(output);
|
||||||
|
|
||||||
|
visited.Add(position, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block root = Enqueue(start);
|
||||||
|
|
||||||
|
while (blocks.Count > 0)
|
||||||
|
{
|
||||||
|
Block current = blocks.Dequeue();
|
||||||
|
|
||||||
|
FillBlock(state, memory, current);
|
||||||
|
|
||||||
|
//Set child blocks. "Branch" is the block the branch instruction
|
||||||
|
//points to (when taken), "Next" is the block at the next address,
|
||||||
|
//executed when the branch is not taken. For Unconditional Branches
|
||||||
|
//(except BL/BLR that are sub calls) or end of executable, Next is null.
|
||||||
|
if (current.OpCodes.Count > 0)
|
||||||
|
{
|
||||||
|
bool hasCachedSub = false;
|
||||||
|
|
||||||
|
OpCode64 lastOp = current.GetLastOp();
|
||||||
|
|
||||||
|
if (lastOp is OpCodeBImm64 op)
|
||||||
|
{
|
||||||
|
if (op.Emitter == InstEmit.Bl)
|
||||||
|
{
|
||||||
|
hasCachedSub = cache.HasSubroutine(op.Imm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current.Branch = Enqueue(op.Imm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!((lastOp is OpCodeBImmAl64) ||
|
||||||
|
(lastOp is OpCodeBReg64)) || hasCachedSub)
|
||||||
|
{
|
||||||
|
current.Next = Enqueue(current.EndPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//If we have on the graph two blocks with the same end position,
|
||||||
|
//then we need to split the bigger block and have two small blocks,
|
||||||
|
//the end position of the bigger "Current" block should then be == to
|
||||||
|
//the position of the "Smaller" block.
|
||||||
|
while (visitedEnd.TryGetValue(current.EndPosition, out Block smaller))
|
||||||
|
{
|
||||||
|
if (current.Position > smaller.Position)
|
||||||
|
{
|
||||||
|
Block temp = smaller;
|
||||||
|
|
||||||
|
smaller = current;
|
||||||
|
current = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
current.EndPosition = smaller.Position;
|
||||||
|
current.Next = smaller;
|
||||||
|
current.Branch = null;
|
||||||
|
|
||||||
|
current.OpCodes.RemoveRange(
|
||||||
|
current.OpCodes.Count - smaller.OpCodes.Count,
|
||||||
|
smaller.OpCodes.Count);
|
||||||
|
|
||||||
|
visitedEnd[smaller.EndPosition] = smaller;
|
||||||
|
}
|
||||||
|
|
||||||
|
visitedEnd.Add(current.EndPosition, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Make and sort Graph blocks array by position.
|
||||||
|
Block[] graph = new Block[visited.Count];
|
||||||
|
|
||||||
|
while (visited.Count > 0)
|
||||||
|
{
|
||||||
|
ulong firstPos = ulong.MaxValue;
|
||||||
|
|
||||||
|
foreach (Block block in visited.Values)
|
||||||
|
{
|
||||||
|
if (firstPos > (ulong)block.Position)
|
||||||
|
firstPos = (ulong)block.Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block current = visited[(long)firstPos];
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
graph[graph.Length - visited.Count] = current;
|
||||||
|
|
||||||
|
visited.Remove(current.Position);
|
||||||
|
|
||||||
|
current = current.Next;
|
||||||
|
}
|
||||||
|
while (current != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (graph, root);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FillBlock(CpuThreadState state, MemoryManager memory, Block block)
|
||||||
|
{
|
||||||
|
long position = block.Position;
|
||||||
|
|
||||||
|
OpCode64 opCode;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
//TODO: This needs to be changed to support both AArch32 and AArch64,
|
||||||
|
//once JIT support is introduced on AArch32 aswell.
|
||||||
|
opCode = DecodeOpCode(state, memory, position);
|
||||||
|
|
||||||
|
block.OpCodes.Add(opCode);
|
||||||
|
|
||||||
|
position += 4;
|
||||||
|
}
|
||||||
|
while (!(IsBranch(opCode) || IsException(opCode)));
|
||||||
|
|
||||||
|
block.EndPosition = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsBranch(OpCode64 opCode)
|
||||||
|
{
|
||||||
|
return opCode is OpCodeBImm64 ||
|
||||||
|
opCode is OpCodeBReg64;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsException(OpCode64 opCode)
|
||||||
|
{
|
||||||
|
return opCode.Emitter == InstEmit.Brk ||
|
||||||
|
opCode.Emitter == InstEmit.Svc ||
|
||||||
|
opCode.Emitter == InstEmit.Und;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OpCode64 DecodeOpCode(CpuThreadState state, MemoryManager memory, long position)
|
||||||
|
{
|
||||||
|
int opCode = memory.ReadInt32(position);
|
||||||
|
|
||||||
|
Inst inst;
|
||||||
|
|
||||||
|
if (state.ExecutionMode == ExecutionMode.AArch64)
|
||||||
|
{
|
||||||
|
inst = OpCodeTable.GetInstA64(opCode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//TODO: Thumb support.
|
||||||
|
inst = OpCodeTable.GetInstA32(opCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
OpCode64 decodedOpCode = new OpCode64(Inst.Undefined, position, opCode);
|
||||||
|
|
||||||
|
if (inst.Type != null)
|
||||||
|
{
|
||||||
|
decodedOpCode = MakeOpCode(inst.Type, inst, position, opCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return decodedOpCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static OpCode64 MakeOpCode(Type type, Inst inst, long position, int opCode)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
OpActivator createInstance = _opActivators.GetOrAdd(type, CacheOpActivator);
|
||||||
|
|
||||||
|
return (OpCode64)createInstance(inst, position, opCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static OpActivator CacheOpActivator(Type type)
|
||||||
|
{
|
||||||
|
Type[] argTypes = new Type[] { typeof(Inst), typeof(long), typeof(int) };
|
||||||
|
|
||||||
|
DynamicMethod mthd = new DynamicMethod($"Make{type.Name}", type, argTypes);
|
||||||
|
|
||||||
|
ILGenerator generator = mthd.GetILGenerator();
|
||||||
|
|
||||||
|
generator.Emit(OpCodes.Ldarg_0);
|
||||||
|
generator.Emit(OpCodes.Ldarg_1);
|
||||||
|
generator.Emit(OpCodes.Ldarg_2);
|
||||||
|
generator.Emit(OpCodes.Newobj, type.GetConstructor(argTypes));
|
||||||
|
generator.Emit(OpCodes.Ret);
|
||||||
|
|
||||||
|
return (OpActivator)mthd.CreateDelegate(typeof(OpActivator));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
107
ChocolArm64/Decoders/DecoderHelper.cs
Normal file
107
ChocolArm64/Decoders/DecoderHelper.cs
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
static class DecoderHelper
|
||||||
|
{
|
||||||
|
public struct BitMask
|
||||||
|
{
|
||||||
|
public long WMask;
|
||||||
|
public long TMask;
|
||||||
|
public int Pos;
|
||||||
|
public int Shift;
|
||||||
|
public bool IsUndefined;
|
||||||
|
|
||||||
|
public static BitMask Invalid => new BitMask { IsUndefined = true };
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BitMask DecodeBitMask(int opCode, bool immediate)
|
||||||
|
{
|
||||||
|
int immS = (opCode >> 10) & 0x3f;
|
||||||
|
int immR = (opCode >> 16) & 0x3f;
|
||||||
|
|
||||||
|
int n = (opCode >> 22) & 1;
|
||||||
|
int sf = (opCode >> 31) & 1;
|
||||||
|
|
||||||
|
int length = BitUtils.HighestBitSet32((~immS & 0x3f) | (n << 6));
|
||||||
|
|
||||||
|
if (length < 1 || (sf == 0 && n != 0))
|
||||||
|
{
|
||||||
|
return BitMask.Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int size = 1 << length;
|
||||||
|
|
||||||
|
int levels = size - 1;
|
||||||
|
|
||||||
|
int s = immS & levels;
|
||||||
|
int r = immR & levels;
|
||||||
|
|
||||||
|
if (immediate && s == levels)
|
||||||
|
{
|
||||||
|
return BitMask.Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
long wMask = BitUtils.FillWithOnes(s + 1);
|
||||||
|
long tMask = BitUtils.FillWithOnes(((s - r) & levels) + 1);
|
||||||
|
|
||||||
|
if (r > 0)
|
||||||
|
{
|
||||||
|
wMask = BitUtils.RotateRight(wMask, r, size);
|
||||||
|
wMask &= BitUtils.FillWithOnes(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BitMask()
|
||||||
|
{
|
||||||
|
WMask = BitUtils.Replicate(wMask, size),
|
||||||
|
TMask = BitUtils.Replicate(tMask, size),
|
||||||
|
|
||||||
|
Pos = immS,
|
||||||
|
Shift = immR
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long DecodeImm8Float(long imm, int size)
|
||||||
|
{
|
||||||
|
int e = 0, f = 0;
|
||||||
|
|
||||||
|
switch (size)
|
||||||
|
{
|
||||||
|
case 0: e = 8; f = 23; break;
|
||||||
|
case 1: e = 11; f = 52; break;
|
||||||
|
|
||||||
|
default: throw new ArgumentOutOfRangeException(nameof(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
long value = (imm & 0x3f) << f - 4;
|
||||||
|
|
||||||
|
long eBit = (imm >> 6) & 1;
|
||||||
|
long sBit = (imm >> 7) & 1;
|
||||||
|
|
||||||
|
if (eBit != 0)
|
||||||
|
{
|
||||||
|
value |= (1L << e - 3) - 1 << f + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
value |= (eBit ^ 1) << f + e - 1;
|
||||||
|
value |= sBit << f + e;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long DecodeImm26_2(int opCode)
|
||||||
|
{
|
||||||
|
return ((long)opCode << 38) >> 36;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long DecodeImmS19_2(int opCode)
|
||||||
|
{
|
||||||
|
return (((long)opCode << 40) >> 43) & ~3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long DecodeImmS14_2(int opCode)
|
||||||
|
{
|
||||||
|
return (((long)opCode << 45) >> 48) & ~3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
ChocolArm64/Decoders/IOpCode64.cs
Normal file
13
ChocolArm64/Decoders/IOpCode64.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
interface IOpCode64
|
||||||
|
{
|
||||||
|
long Position { get; }
|
||||||
|
|
||||||
|
InstEmitter Emitter { get; }
|
||||||
|
RegisterSize RegisterSize { get; }
|
||||||
|
}
|
||||||
|
}
|
10
ChocolArm64/Decoders/IOpCodeAlu64.cs
Normal file
10
ChocolArm64/Decoders/IOpCodeAlu64.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
interface IOpCodeAlu64 : IOpCode64
|
||||||
|
{
|
||||||
|
int Rd { get; }
|
||||||
|
int Rn { get; }
|
||||||
|
|
||||||
|
DataOp DataOp { get; }
|
||||||
|
}
|
||||||
|
}
|
7
ChocolArm64/Decoders/IOpCodeAluImm64.cs
Normal file
7
ChocolArm64/Decoders/IOpCodeAluImm64.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
interface IOpCodeAluImm64 : IOpCodeAlu64
|
||||||
|
{
|
||||||
|
long Imm { get; }
|
||||||
|
}
|
||||||
|
}
|
10
ChocolArm64/Decoders/IOpCodeAluRs64.cs
Normal file
10
ChocolArm64/Decoders/IOpCodeAluRs64.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
interface IOpCodeAluRs64 : IOpCodeAlu64
|
||||||
|
{
|
||||||
|
int Shift { get; }
|
||||||
|
int Rm { get; }
|
||||||
|
|
||||||
|
ShiftType ShiftType { get; }
|
||||||
|
}
|
||||||
|
}
|
10
ChocolArm64/Decoders/IOpCodeAluRx64.cs
Normal file
10
ChocolArm64/Decoders/IOpCodeAluRx64.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
interface IOpCodeAluRx64 : IOpCodeAlu64
|
||||||
|
{
|
||||||
|
int Shift { get; }
|
||||||
|
int Rm { get; }
|
||||||
|
|
||||||
|
IntType IntType { get; }
|
||||||
|
}
|
||||||
|
}
|
7
ChocolArm64/Decoders/IOpCodeCond64.cs
Normal file
7
ChocolArm64/Decoders/IOpCodeCond64.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
interface IOpCodeCond64 : IOpCode64
|
||||||
|
{
|
||||||
|
Cond Cond { get; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
namespace ChocolArm64.Decoder
|
namespace ChocolArm64.Decoders
|
||||||
{
|
{
|
||||||
interface IAOpCodeLit : IAOpCode
|
interface IOpCodeLit64 : IOpCode64
|
||||||
{
|
{
|
||||||
int Rt { get; }
|
int Rt { get; }
|
||||||
long Imm { get; }
|
long Imm { get; }
|
7
ChocolArm64/Decoders/IOpCodeSimd64.cs
Normal file
7
ChocolArm64/Decoders/IOpCodeSimd64.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
interface IOpCodeSimd64 : IOpCode64
|
||||||
|
{
|
||||||
|
int Size { get; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
namespace ChocolArm64.Decoder
|
namespace ChocolArm64.Decoders
|
||||||
{
|
{
|
||||||
enum AIntType
|
enum IntType
|
||||||
{
|
{
|
||||||
UInt8 = 0,
|
UInt8 = 0,
|
||||||
UInt16 = 1,
|
UInt16 = 1,
|
40
ChocolArm64/Decoders/OpCode64.cs
Normal file
40
ChocolArm64/Decoders/OpCode64.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
using ChocolArm64.State;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCode64 : IOpCode64
|
||||||
|
{
|
||||||
|
public long Position { get; private set; }
|
||||||
|
public int RawOpCode { get; private set; }
|
||||||
|
|
||||||
|
public InstEmitter Emitter { get; protected set; }
|
||||||
|
public InstInterpreter Interpreter { get; protected set; }
|
||||||
|
public RegisterSize RegisterSize { get; protected set; }
|
||||||
|
|
||||||
|
public OpCode64(Inst inst, long position, int opCode)
|
||||||
|
{
|
||||||
|
Position = position;
|
||||||
|
RawOpCode = opCode;
|
||||||
|
|
||||||
|
RegisterSize = RegisterSize.Int64;
|
||||||
|
|
||||||
|
Emitter = inst.Emitter;
|
||||||
|
Interpreter = inst.Interpreter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetBitsCount()
|
||||||
|
{
|
||||||
|
switch (RegisterSize)
|
||||||
|
{
|
||||||
|
case RegisterSize.Int32: return 32;
|
||||||
|
case RegisterSize.Int64: return 64;
|
||||||
|
case RegisterSize.Simd64: return 64;
|
||||||
|
case RegisterSize.Simd128: return 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
ChocolArm64/Decoders/OpCodeAdr64.cs
Normal file
18
ChocolArm64/Decoders/OpCodeAdr64.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeAdr64 : OpCode64
|
||||||
|
{
|
||||||
|
public int Rd { get; private set; }
|
||||||
|
public long Imm { get; private set; }
|
||||||
|
|
||||||
|
public OpCodeAdr64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
Rd = opCode & 0x1f;
|
||||||
|
|
||||||
|
Imm = DecoderHelper.DecodeImmS19_2(opCode);
|
||||||
|
Imm |= ((long)opCode >> 29) & 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
ChocolArm64/Decoders/OpCodeAlu64.cs
Normal file
24
ChocolArm64/Decoders/OpCodeAlu64.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeAlu64 : OpCode64, IOpCodeAlu64
|
||||||
|
{
|
||||||
|
public int Rd { get; protected set; }
|
||||||
|
public int Rn { get; private set; }
|
||||||
|
|
||||||
|
public DataOp DataOp { get; private set; }
|
||||||
|
|
||||||
|
public OpCodeAlu64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
Rd = (opCode >> 0) & 0x1f;
|
||||||
|
Rn = (opCode >> 5) & 0x1f;
|
||||||
|
DataOp = (DataOp)((opCode >> 24) & 0x3);
|
||||||
|
|
||||||
|
RegisterSize = (opCode >> 31) != 0
|
||||||
|
? State.RegisterSize.Int64
|
||||||
|
: State.RegisterSize.Int32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
ChocolArm64/Decoders/OpCodeAluImm64.cs
Normal file
39
ChocolArm64/Decoders/OpCodeAluImm64.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeAluImm64 : OpCodeAlu64, IOpCodeAluImm64
|
||||||
|
{
|
||||||
|
public long Imm { get; private set; }
|
||||||
|
|
||||||
|
public OpCodeAluImm64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
if (DataOp == DataOp.Arithmetic)
|
||||||
|
{
|
||||||
|
Imm = (opCode >> 10) & 0xfff;
|
||||||
|
|
||||||
|
int shift = (opCode >> 22) & 3;
|
||||||
|
|
||||||
|
Imm <<= shift * 12;
|
||||||
|
}
|
||||||
|
else if (DataOp == DataOp.Logical)
|
||||||
|
{
|
||||||
|
var bm = DecoderHelper.DecodeBitMask(opCode, true);
|
||||||
|
|
||||||
|
if (bm.IsUndefined)
|
||||||
|
{
|
||||||
|
Emitter = InstEmit.Und;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Imm = bm.WMask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException(nameof(opCode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
ChocolArm64/Decoders/OpCodeAluRs64.cs
Normal file
29
ChocolArm64/Decoders/OpCodeAluRs64.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeAluRs64 : OpCodeAlu64, IOpCodeAluRs64
|
||||||
|
{
|
||||||
|
public int Shift { get; private set; }
|
||||||
|
public int Rm { get; private set; }
|
||||||
|
|
||||||
|
public ShiftType ShiftType { get; private set; }
|
||||||
|
|
||||||
|
public OpCodeAluRs64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
int shift = (opCode >> 10) & 0x3f;
|
||||||
|
|
||||||
|
if (shift >= GetBitsCount())
|
||||||
|
{
|
||||||
|
Emitter = InstEmit.Und;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Shift = shift;
|
||||||
|
|
||||||
|
Rm = (opCode >> 16) & 0x1f;
|
||||||
|
ShiftType = (ShiftType)((opCode >> 22) & 0x3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
ChocolArm64/Decoders/OpCodeAluRx64.cs
Normal file
19
ChocolArm64/Decoders/OpCodeAluRx64.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeAluRx64 : OpCodeAlu64, IOpCodeAluRx64
|
||||||
|
{
|
||||||
|
public int Shift { get; private set; }
|
||||||
|
public int Rm { get; private set; }
|
||||||
|
|
||||||
|
public IntType IntType { get; private set; }
|
||||||
|
|
||||||
|
public OpCodeAluRx64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
Shift = (opCode >> 10) & 0x7;
|
||||||
|
IntType = (IntType)((opCode >> 13) & 0x7);
|
||||||
|
Rm = (opCode >> 16) & 0x1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
ChocolArm64/Decoders/OpCodeBImm64.cs
Normal file
11
ChocolArm64/Decoders/OpCodeBImm64.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeBImm64 : OpCode64
|
||||||
|
{
|
||||||
|
public long Imm { get; protected set; }
|
||||||
|
|
||||||
|
public OpCodeBImm64(Inst inst, long position, int opCode) : base(inst, position, opCode) { }
|
||||||
|
}
|
||||||
|
}
|
12
ChocolArm64/Decoders/OpCodeBImmAl64.cs
Normal file
12
ChocolArm64/Decoders/OpCodeBImmAl64.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeBImmAl64 : OpCodeBImm64
|
||||||
|
{
|
||||||
|
public OpCodeBImmAl64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
Imm = position + DecoderHelper.DecodeImm26_2(opCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
ChocolArm64/Decoders/OpCodeBImmCmp64.cs
Normal file
21
ChocolArm64/Decoders/OpCodeBImmCmp64.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeBImmCmp64 : OpCodeBImm64
|
||||||
|
{
|
||||||
|
public int Rt { get; private set; }
|
||||||
|
|
||||||
|
public OpCodeBImmCmp64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
Rt = opCode & 0x1f;
|
||||||
|
|
||||||
|
Imm = position + DecoderHelper.DecodeImmS19_2(opCode);
|
||||||
|
|
||||||
|
RegisterSize = (opCode >> 31) != 0
|
||||||
|
? State.RegisterSize.Int64
|
||||||
|
: State.RegisterSize.Int32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
ChocolArm64/Decoders/OpCodeBImmCond64.cs
Normal file
25
ChocolArm64/Decoders/OpCodeBImmCond64.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeBImmCond64 : OpCodeBImm64, IOpCodeCond64
|
||||||
|
{
|
||||||
|
public Cond Cond { get; private set; }
|
||||||
|
|
||||||
|
public OpCodeBImmCond64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
int o0 = (opCode >> 4) & 1;
|
||||||
|
|
||||||
|
if (o0 != 0)
|
||||||
|
{
|
||||||
|
Emitter = InstEmit.Und;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cond = (Cond)(opCode & 0xf);
|
||||||
|
|
||||||
|
Imm = position + DecoderHelper.DecodeImmS19_2(opCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
ChocolArm64/Decoders/OpCodeBImmTest64.cs
Normal file
20
ChocolArm64/Decoders/OpCodeBImmTest64.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeBImmTest64 : OpCodeBImm64
|
||||||
|
{
|
||||||
|
public int Rt { get; private set; }
|
||||||
|
public int Pos { get; private set; }
|
||||||
|
|
||||||
|
public OpCodeBImmTest64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
Rt = opCode & 0x1f;
|
||||||
|
|
||||||
|
Imm = position + DecoderHelper.DecodeImmS14_2(opCode);
|
||||||
|
|
||||||
|
Pos = (opCode >> 19) & 0x1f;
|
||||||
|
Pos |= (opCode >> 26) & 0x20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
ChocolArm64/Decoders/OpCodeBReg64.cs
Normal file
24
ChocolArm64/Decoders/OpCodeBReg64.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeBReg64 : OpCode64
|
||||||
|
{
|
||||||
|
public int Rn { get; private set; }
|
||||||
|
|
||||||
|
public OpCodeBReg64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
int op4 = (opCode >> 0) & 0x1f;
|
||||||
|
int op2 = (opCode >> 16) & 0x1f;
|
||||||
|
|
||||||
|
if (op2 != 0b11111 || op4 != 0b00000)
|
||||||
|
{
|
||||||
|
Emitter = InstEmit.Und;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rn = (opCode >> 5) & 0x1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
ChocolArm64/Decoders/OpCodeBfm64.cs
Normal file
29
ChocolArm64/Decoders/OpCodeBfm64.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeBfm64 : OpCodeAlu64
|
||||||
|
{
|
||||||
|
public long WMask { get; private set; }
|
||||||
|
public long TMask { get; private set; }
|
||||||
|
public int Pos { get; private set; }
|
||||||
|
public int Shift { get; private set; }
|
||||||
|
|
||||||
|
public OpCodeBfm64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
var bm = DecoderHelper.DecodeBitMask(opCode, false);
|
||||||
|
|
||||||
|
if (bm.IsUndefined)
|
||||||
|
{
|
||||||
|
Emitter = InstEmit.Und;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WMask = bm.WMask;
|
||||||
|
TMask = bm.TMask;
|
||||||
|
Pos = bm.Pos;
|
||||||
|
Shift = bm.Shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
ChocolArm64/Decoders/OpCodeCcmp64.cs
Normal file
31
ChocolArm64/Decoders/OpCodeCcmp64.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeCcmp64 : OpCodeAlu64, IOpCodeCond64
|
||||||
|
{
|
||||||
|
public int Nzcv { get; private set; }
|
||||||
|
protected int RmImm;
|
||||||
|
|
||||||
|
public Cond Cond { get; private set; }
|
||||||
|
|
||||||
|
public OpCodeCcmp64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
int o3 = (opCode >> 4) & 1;
|
||||||
|
|
||||||
|
if (o3 != 0)
|
||||||
|
{
|
||||||
|
Emitter = InstEmit.Und;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Nzcv = (opCode >> 0) & 0xf;
|
||||||
|
Cond = (Cond)((opCode >> 12) & 0xf);
|
||||||
|
RmImm = (opCode >> 16) & 0x1f;
|
||||||
|
|
||||||
|
Rd = CpuThreadState.ZrIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
ChocolArm64/Decoders/OpCodeCcmpImm64.cs
Normal file
11
ChocolArm64/Decoders/OpCodeCcmpImm64.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeCcmpImm64 : OpCodeCcmp64, IOpCodeAluImm64
|
||||||
|
{
|
||||||
|
public long Imm => RmImm;
|
||||||
|
|
||||||
|
public OpCodeCcmpImm64(Inst inst, long position, int opCode) : base(inst, position, opCode) { }
|
||||||
|
}
|
||||||
|
}
|
15
ChocolArm64/Decoders/OpCodeCcmpReg64.cs
Normal file
15
ChocolArm64/Decoders/OpCodeCcmpReg64.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeCcmpReg64 : OpCodeCcmp64, IOpCodeAluRs64
|
||||||
|
{
|
||||||
|
public int Rm => RmImm;
|
||||||
|
|
||||||
|
public int Shift => 0;
|
||||||
|
|
||||||
|
public ShiftType ShiftType => ShiftType.Lsl;
|
||||||
|
|
||||||
|
public OpCodeCcmpReg64(Inst inst, long position, int opCode) : base(inst, position, opCode) { }
|
||||||
|
}
|
||||||
|
}
|
17
ChocolArm64/Decoders/OpCodeCsel64.cs
Normal file
17
ChocolArm64/Decoders/OpCodeCsel64.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeCsel64 : OpCodeAlu64, IOpCodeCond64
|
||||||
|
{
|
||||||
|
public int Rm { get; private set; }
|
||||||
|
|
||||||
|
public Cond Cond { get; private set; }
|
||||||
|
|
||||||
|
public OpCodeCsel64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
Rm = (opCode >> 16) & 0x1f;
|
||||||
|
Cond = (Cond)((opCode >> 12) & 0xf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
ChocolArm64/Decoders/OpCodeException64.cs
Normal file
14
ChocolArm64/Decoders/OpCodeException64.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeException64 : OpCode64
|
||||||
|
{
|
||||||
|
public int Id { get; private set; }
|
||||||
|
|
||||||
|
public OpCodeException64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
Id = (opCode >> 5) & 0xffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
ChocolArm64/Decoders/OpCodeMem64.cs
Normal file
19
ChocolArm64/Decoders/OpCodeMem64.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeMem64 : OpCode64
|
||||||
|
{
|
||||||
|
public int Rt { get; protected set; }
|
||||||
|
public int Rn { get; protected set; }
|
||||||
|
public int Size { get; protected set; }
|
||||||
|
public bool Extend64 { get; protected set; }
|
||||||
|
|
||||||
|
public OpCodeMem64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
Rt = (opCode >> 0) & 0x1f;
|
||||||
|
Rn = (opCode >> 5) & 0x1f;
|
||||||
|
Size = (opCode >> 30) & 0x3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
ChocolArm64/Decoders/OpCodeMemEx64.cs
Normal file
16
ChocolArm64/Decoders/OpCodeMemEx64.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeMemEx64 : OpCodeMem64
|
||||||
|
{
|
||||||
|
public int Rt2 { get; private set; }
|
||||||
|
public int Rs { get; private set; }
|
||||||
|
|
||||||
|
public OpCodeMemEx64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
Rt2 = (opCode >> 10) & 0x1f;
|
||||||
|
Rs = (opCode >> 16) & 0x1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,8 @@
|
|||||||
using ChocolArm64.Instruction;
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
namespace ChocolArm64.Decoders
|
||||||
{
|
{
|
||||||
class AOpCodeMemImm : AOpCodeMem
|
class OpCodeMemImm64 : OpCodeMem64
|
||||||
{
|
{
|
||||||
public long Imm { get; protected set; }
|
public long Imm { get; protected set; }
|
||||||
public bool WBack { get; protected set; }
|
public bool WBack { get; protected set; }
|
||||||
@ -18,18 +18,18 @@ namespace ChocolArm64.Decoder
|
|||||||
Unsigned
|
Unsigned
|
||||||
}
|
}
|
||||||
|
|
||||||
public AOpCodeMemImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
public OpCodeMemImm64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
{
|
{
|
||||||
Extend64 = ((OpCode >> 22) & 3) == 2;
|
Extend64 = ((opCode >> 22) & 3) == 2;
|
||||||
WBack = ((OpCode >> 24) & 1) == 0;
|
WBack = ((opCode >> 24) & 1) == 0;
|
||||||
|
|
||||||
//The type is not valid for the Unsigned Immediate 12-bits encoding,
|
//The type is not valid for the Unsigned Immediate 12-bits encoding,
|
||||||
//because the bits 11:10 are used for the larger Immediate offset.
|
//because the bits 11:10 are used for the larger Immediate offset.
|
||||||
MemOp Type = WBack ? (MemOp)((OpCode >> 10) & 3) : MemOp.Unsigned;
|
MemOp type = WBack ? (MemOp)((opCode >> 10) & 3) : MemOp.Unsigned;
|
||||||
|
|
||||||
PostIdx = Type == MemOp.PostIndexed;
|
PostIdx = type == MemOp.PostIndexed;
|
||||||
Unscaled = Type == MemOp.Unscaled ||
|
Unscaled = type == MemOp.Unscaled ||
|
||||||
Type == MemOp.Unprivileged;
|
type == MemOp.Unprivileged;
|
||||||
|
|
||||||
//Unscaled and Unprivileged doesn't write back,
|
//Unscaled and Unprivileged doesn't write back,
|
||||||
//but they do use the 9-bits Signed Immediate.
|
//but they do use the 9-bits Signed Immediate.
|
||||||
@ -41,12 +41,12 @@ namespace ChocolArm64.Decoder
|
|||||||
if (WBack || Unscaled)
|
if (WBack || Unscaled)
|
||||||
{
|
{
|
||||||
//9-bits Signed Immediate.
|
//9-bits Signed Immediate.
|
||||||
Imm = (OpCode << 43) >> 55;
|
Imm = (opCode << 43) >> 55;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//12-bits Unsigned Immediate.
|
//12-bits Unsigned Immediate.
|
||||||
Imm = ((OpCode >> 10) & 0xfff) << Size;
|
Imm = ((opCode >> 10) & 0xfff) << Size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
using ChocolArm64.Instruction;
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
namespace ChocolArm64.Decoders
|
||||||
{
|
{
|
||||||
class AOpCodeMemLit : AOpCode, IAOpCodeLit
|
class OpCodeMemLit64 : OpCode64, IOpCodeLit64
|
||||||
{
|
{
|
||||||
public int Rt { get; private set; }
|
public int Rt { get; private set; }
|
||||||
public long Imm { get; private set; }
|
public long Imm { get; private set; }
|
||||||
@ -10,13 +10,13 @@ namespace ChocolArm64.Decoder
|
|||||||
public bool Signed { get; private set; }
|
public bool Signed { get; private set; }
|
||||||
public bool Prefetch { get; private set; }
|
public bool Prefetch { get; private set; }
|
||||||
|
|
||||||
public AOpCodeMemLit(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
public OpCodeMemLit64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
{
|
{
|
||||||
Rt = OpCode & 0x1f;
|
Rt = opCode & 0x1f;
|
||||||
|
|
||||||
Imm = Position + ADecoderHelper.DecodeImmS19_2(OpCode);
|
Imm = position + DecoderHelper.DecodeImmS19_2(opCode);
|
||||||
|
|
||||||
switch ((OpCode >> 30) & 3)
|
switch ((opCode >> 30) & 3)
|
||||||
{
|
{
|
||||||
case 0: Size = 2; Signed = false; Prefetch = false; break;
|
case 0: Size = 2; Signed = false; Prefetch = false; break;
|
||||||
case 1: Size = 3; Signed = false; Prefetch = false; break;
|
case 1: Size = 3; Signed = false; Prefetch = false; break;
|
25
ChocolArm64/Decoders/OpCodeMemPair64.cs
Normal file
25
ChocolArm64/Decoders/OpCodeMemPair64.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using ChocolArm64.Instructions;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeMemPair64 : OpCodeMemImm64
|
||||||
|
{
|
||||||
|
public int Rt2 { get; private set; }
|
||||||
|
|
||||||
|
public OpCodeMemPair64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
|
{
|
||||||
|
Rt2 = (opCode >> 10) & 0x1f;
|
||||||
|
WBack = ((opCode >> 23) & 0x1) != 0;
|
||||||
|
PostIdx = ((opCode >> 23) & 0x3) == 1;
|
||||||
|
Extend64 = ((opCode >> 30) & 0x3) == 1;
|
||||||
|
Size = ((opCode >> 31) & 0x1) | 2;
|
||||||
|
|
||||||
|
DecodeImm(opCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void DecodeImm(int opCode)
|
||||||
|
{
|
||||||
|
Imm = ((long)(opCode >> 15) << 57) >> (57 - Size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user