mirror of
https://github.com/ryujinx-mirror/ryujinx.git
synced 2024-12-23 17:25:50 +00:00
107 lines
2.7 KiB
C#
107 lines
2.7 KiB
C#
|
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;
|
||
|
}
|
||
|
}
|
||
|
}
|