Add curly braces back to the if statements

This commit is contained in:
Kenny van Vulpen 2018-10-26 07:09:27 +02:00
parent c934bc47d5
commit 2019baffc4
No known key found for this signature in database
GPG key ID: BBD011B8B9C45F87
218 changed files with 7140 additions and 1387 deletions

View file

@ -6,7 +6,10 @@ namespace ChocolArm64
{
int count = 0;
for (int bit = 0; bit < 64; bit++) count += (int)(value >> bit) & 1;
for (int bit = 0; bit < 64; bit++)
{
count += (int)(value >> bit) & 1;
}
return count;
}
@ -14,7 +17,12 @@ namespace ChocolArm64
public static int HighestBitSet32(int value)
{
for (int bit = 31; bit >= 0; bit--)
if (((value >> bit) & 1) != 0) return bit;
{
if (((value >> bit) & 1) != 0)
{
return bit;
}
}
return -1;
}
@ -30,7 +38,10 @@ namespace ChocolArm64
{
long output = 0;
for (int bit = 0; bit < 64; bit += size) output |= bits << bit;
for (int bit = 0; bit < 64; bit += size)
{
output |= bits << bit;
}
return output;
}

View file

@ -530,7 +530,10 @@ namespace ChocolArm64
#region "Generate InstA64FastLookup Table (AArch64)"
var tmp = new List<InstInfo>[_fastLookupSize];
for (int i = 0; i < _fastLookupSize; i++) tmp[i] = new List<InstInfo>();
for (int i = 0; i < _fastLookupSize; i++)
{
tmp[i] = new List<InstInfo>();
}
foreach (var inst in _allInstA64)
{
@ -538,10 +541,18 @@ namespace ChocolArm64
int value = ToFastLookupIndex(inst.Value);
for (int i = 0; i < _fastLookupSize; i++)
if ((i & mask) == value) tmp[i].Add(inst);
{
if ((i & mask) == value)
{
tmp[i].Add(inst);
}
}
}
for (int i = 0; i < _fastLookupSize; i++) _instA64FastLookup[i] = tmp[i].ToArray();
for (int i = 0; i < _fastLookupSize; i++)
{
_instA64FastLookup[i] = tmp[i].ToArray();
}
#endregion
}
@ -635,9 +646,15 @@ namespace ChocolArm64
{
int mask = 0;
for (int x = 0; x < xBits; x++) mask |= ((index >> x) & 1) << xPos[x];
for (int x = 0; x < xBits; x++)
{
mask |= ((index >> x) & 1) << xPos[x];
}
if (mask != blacklisted) InsertInst(xMask, value | mask, inst, mode);
if (mask != blacklisted)
{
InsertInst(xMask, value | mask, inst, mode);
}
}
}
@ -650,9 +667,13 @@ namespace ChocolArm64
InstInfo info = new InstInfo(xMask, value, inst);
if (mode == AExecutionMode.AArch64)
{
_allInstA64.Add(info);
}
else
{
_allInstA32.Add(info);
}
}
public static AInst GetInstA32(int opCode)
@ -673,7 +694,12 @@ namespace ChocolArm64
private static AInst GetInstFromList(IEnumerable<InstInfo> instList, int opCode)
{
foreach (var node in instList)
if ((opCode & node.Mask) == node.Value) return node.Inst;
{
if ((opCode & node.Mask) == node.Value)
{
return node.Inst;
}
}
return AInst.Undefined;
}

View file

@ -41,7 +41,10 @@ namespace ChocolArm64
public bool Execute()
{
if (Interlocked.Exchange(ref _isExecuting, 1) == 1) return false;
if (Interlocked.Exchange(ref _isExecuting, 1) == 1)
{
return false;
}
Work.Start();

View file

@ -36,9 +36,15 @@ namespace ChocolArm64
public ATranslatedSub(DynamicMethod method, List<ARegister> Params)
{
if (method == null) throw new ArgumentNullException(nameof(method));
if (method == null)
{
throw new ArgumentNullException(nameof(method));
}
if (Params == null) throw new ArgumentNullException(nameof(Params));
if (Params == null)
{
throw new ArgumentNullException(nameof(Params));
}
Method = method;
this.Params = Params.AsReadOnly();
@ -63,8 +69,13 @@ namespace ChocolArm64
FixedArgTypes[index] = paramType;
if (paramType == typeof(AThreadState))
{
StateArgIdx = index;
else if (paramType == typeof(AMemory)) MemoryArgIdx = index;
}
else if (paramType == typeof(AMemory))
{
MemoryArgIdx = index;
}
}
}
@ -128,7 +139,10 @@ namespace ChocolArm64
{
_type = type;
if (type == ATranslatedSubType.SubTier0) _needsReJit = true;
if (type == ATranslatedSubType.SubTier0)
{
_needsReJit = true;
}
}
public void MarkForReJit()

View file

@ -30,9 +30,13 @@ namespace ChocolArm64
AMemory memory = thread.Memory;
if (state.ExecutionMode == AExecutionMode.AArch32)
{
ExecuteSubroutineA32(state, memory);
}
else
{
ExecuteSubroutineA64(state, memory, position);
}
}
private void ExecuteSubroutineA32(AThreadState state, AMemory memory)
@ -50,11 +54,20 @@ namespace ChocolArm64
{
do
{
if (EnableCpuTrace) CpuTrace?.Invoke(this, new ACpuTraceEventArgs(position));
if (EnableCpuTrace)
{
CpuTrace?.Invoke(this, new ACpuTraceEventArgs(position));
}
if (!_cache.TryGetSubroutine(position, out ATranslatedSub sub)) sub = TranslateTier0(state, memory, position);
if (!_cache.TryGetSubroutine(position, out ATranslatedSub sub))
{
sub = TranslateTier0(state, memory, position);
}
if (sub.ShouldReJit()) TranslateTier1(state, memory, position);
if (sub.ShouldReJit())
{
TranslateTier1(state, memory, position);
}
position = sub.Execute(state, memory);
}
@ -101,7 +114,10 @@ namespace ChocolArm64
AILEmitterCtx context = new AILEmitterCtx(_cache, graph, root, subName);
if (context.CurrBlock.Position != position) context.Emit(OpCodes.Br, context.GetLabel(position));
if (context.CurrBlock.Position != position)
{
context.Emit(OpCodes.Br, context.GetLabel(position));
}
do
{
@ -112,8 +128,15 @@ namespace ChocolArm64
//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();
{
if (_cache.TryGetSubroutine(position, out ATranslatedSub callerSub))
{
callerSub.MarkForReJit();
}
}
}
ATranslatedSub subroutine = context.GetSubroutine();
@ -131,7 +154,10 @@ namespace ChocolArm64
{
int size = 0;
foreach (ABlock block in graph) size += block.OpCodes.Count;
foreach (ABlock block in graph)
{
size += block.OpCodes.Count;
}
return size;
}

View file

@ -92,7 +92,9 @@ namespace ChocolArm64
if (_cache.TryGetValue(position, out CacheBucket bucket))
{
if (bucket.CallCount++ > MinCallCountForUpdate)
{
if (Monitor.TryEnter(_sortedCache))
{
try
{
bucket.CallCount = 0;
@ -105,6 +107,8 @@ namespace ChocolArm64
{
Monitor.Exit(_sortedCache);
}
}
}
subroutine = bucket.Subroutine;
@ -121,17 +125,24 @@ namespace ChocolArm64
int timestamp = Environment.TickCount;
while (_totalSize > MaxTotalSize)
{
lock (_sortedCache)
{
LinkedListNode<long> node = _sortedCache.First;
if (node == null) break;
if (node == null)
{
break;
}
CacheBucket bucket = _cache[node.Value];
int timeDelta = RingDelta(bucket.Timestamp, timestamp);
if ((uint)timeDelta <= (uint)MinTimeDelta) break;
if ((uint)timeDelta <= (uint)MinTimeDelta)
{
break;
}
if (_cache.TryRemove(node.Value, out bucket))
{
@ -140,14 +151,19 @@ namespace ChocolArm64
_sortedCache.Remove(bucket.Node);
}
}
}
}
private static int RingDelta(int old, int New)
{
if ((uint)New < (uint)old)
{
return New + ~old + 1;
}
else
{
return New - old;
}
}
}
}

View file

@ -24,7 +24,10 @@ namespace ChocolArm64.Decoder
public AOpCode GetLastOp()
{
if (OpCodes.Count > 0) return OpCodes[OpCodes.Count - 1];
if (OpCodes.Count > 0)
{
return OpCodes[OpCodes.Count - 1];
}
return null;
}

View file

@ -74,14 +74,20 @@ namespace ChocolArm64.Decoder
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,
@ -120,8 +126,12 @@ namespace ChocolArm64.Decoder
ulong firstPos = ulong.MaxValue;
foreach (ABlock block in visited.Values)
{
if (firstPos > (ulong)block.Position)
{
firstPos = (ulong)block.Position;
}
}
ABlock current = visited[(long)firstPos];
@ -180,20 +190,30 @@ namespace ChocolArm64.Decoder
AInst inst;
if (state.ExecutionMode == AExecutionMode.AArch64)
{
inst = AOpCodeTable.GetInstA64(opCode);
}
else
{
inst = AOpCodeTable.GetInstA32(opCode);
}
AOpCode decodedOpCode = new AOpCode(AInst.Undefined, position, opCode);
if (inst.Type != null) decodedOpCode = MakeOpCode(inst.Type, inst, 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));
if (type == null)
{
throw new ArgumentNullException(nameof(type));
}
OpActivator createInstance = _opActivators.GetOrAdd(type, CacheOpActivator);

View file

@ -25,7 +25,10 @@ namespace ChocolArm64.Decoder
int length = ABitUtils.HighestBitSet32((~immS & 0x3f) | (n << 6));
if (length < 1 || sf == 0 && n != 0) return BitMask.Invalid;
if (length < 1 || sf == 0 && n != 0)
{
return BitMask.Invalid;
}
int size = 1 << length;
@ -34,7 +37,10 @@ namespace ChocolArm64.Decoder
int s = immS & levels;
int r = immR & levels;
if (immediate && s == levels) return BitMask.Invalid;
if (immediate && s == levels)
{
return BitMask.Invalid;
}
long wMask = ABitUtils.FillWithOnes(s + 1);
long mask = ABitUtils.FillWithOnes(((s - r) & levels) + 1);
@ -72,7 +78,10 @@ namespace ChocolArm64.Decoder
long eBit = (imm >> 6) & 1;
long sBit = (imm >> 7) & 1;
if (eBit != 0) value |= ((1L << (e - 3)) - 1) << (f + 2);
if (eBit != 0)
{
value |= ((1L << (e - 3)) - 1) << (f + 2);
}
value |= (eBit ^ 1) << (f + e - 1);
value |= sBit << (f + e);

View file

@ -33,12 +33,19 @@ namespace ChocolArm64.Decoder
//Unscaled and Unprivileged doesn't write back,
//but they do use the 9-bits Signed Immediate.
if (Unscaled) WBack = false;
if (Unscaled)
{
WBack = false;
}
if (WBack || Unscaled)
{
Imm = (opCode << 43) >> 55;
}
else
{
Imm = ((opCode >> 10) & 0xfff) << Size;
}
}
}
}

View file

@ -89,9 +89,13 @@ namespace ChocolArm64.Decoder
private static long ShlOnes(long value, int shift)
{
if (shift != 0)
{
return (value << shift) | (long)(ulong.MaxValue >> (64 - shift));
}
else
{
return value;
}
}
}
}

View file

@ -8,7 +8,10 @@ namespace ChocolArm64.Decoder
{
Size |= (opCode >> 21) & 4;
if (!WBack && !Unscaled && Size >= 4) Imm <<= 4;
if (!WBack && !Unscaled && Size >= 4)
{
Imm <<= 4;
}
Extend64 = false;
}

View file

@ -208,7 +208,10 @@ namespace ChocolArm64.Instruction
FromVectorToByteArray(inState, ref op);
for (int idx = 0; idx <= 15; idx++) outState[_isrPerm[idx]] = inState[idx];
for (int idx = 0; idx <= 15; idx++)
{
outState[_isrPerm[idx]] = inState[idx];
}
FromByteArrayToVector(outState, ref op);
@ -222,7 +225,10 @@ namespace ChocolArm64.Instruction
FromVectorToByteArray(inState, ref op);
for (int idx = 0; idx <= 15; idx++) outState[idx] = _invSBox[inState[idx]];
for (int idx = 0; idx <= 15; idx++)
{
outState[idx] = _invSBox[inState[idx]];
}
FromByteArrayToVector(outState, ref op);
@ -263,7 +269,10 @@ namespace ChocolArm64.Instruction
FromVectorToByteArray(inState, ref op);
for (int idx = 0; idx <= 15; idx++) outState[_srPerm[idx]] = inState[idx];
for (int idx = 0; idx <= 15; idx++)
{
outState[_srPerm[idx]] = inState[idx];
}
FromByteArrayToVector(outState, ref op);
@ -277,7 +286,10 @@ namespace ChocolArm64.Instruction
FromVectorToByteArray(inState, ref op);
for (int idx = 0; idx <= 15; idx++) outState[idx] = _sBox[inState[idx]];
for (int idx = 0; idx <= 15; idx++)
{
outState[idx] = _sBox[inState[idx]];
}
FromByteArrayToVector(outState, ref op);
@ -301,7 +313,10 @@ namespace ChocolArm64.Instruction
private static void FromByteArrayToVector(byte[] state, ref Vector128<float> op)
{
if (!Sse2.IsSupported) throw new PlatformNotSupportedException();
if (!Sse2.IsSupported)
{
throw new PlatformNotSupportedException();
}
op = Sse.StaticCast<byte, float>(Sse2.SetVector128(
state[15], state[14], state[13], state[12],

View file

@ -36,7 +36,10 @@ namespace ChocolArm64.Instruction
context.EmitCall(mthdInfo);
if (context.CurrOp.RegisterSize != ARegisterSize.Int32) context.Emit(OpCodes.Conv_U8);
if (context.CurrOp.RegisterSize != ARegisterSize.Int32)
{
context.Emit(OpCodes.Conv_U8);
}
context.Emit(OpCodes.Add);
@ -230,7 +233,10 @@ namespace ChocolArm64.Instruction
context.Emit(OpCodes.Xor);
if (context.CurrOp.RegisterSize != ARegisterSize.Int32) context.Emit(OpCodes.Conv_U8);
if (context.CurrOp.RegisterSize != ARegisterSize.Int32)
{
context.Emit(OpCodes.Conv_U8);
}
context.Emit(OpCodes.Sub);
@ -308,9 +314,13 @@ namespace ChocolArm64.Instruction
context.EmitLdintzr(op.Rn);
if (op.RegisterSize == ARegisterSize.Int32)
{
ASoftFallback.EmitCall(context, name32);
}
else
{
ASoftFallback.EmitCall(context, name64);
}
context.EmitStintzr(op.Rd);
}
@ -434,7 +444,10 @@ namespace ChocolArm64.Instruction
//we need to cast it to a 32-bits integer. This is fine because we
//AND the value and only keep the lower 5 or 6 bits anyway -- it
//could very well fit on a byte.
if (context.CurrOp.RegisterSize != ARegisterSize.Int32) context.Emit(OpCodes.Conv_I4);
if (context.CurrOp.RegisterSize != ARegisterSize.Int32)
{
context.Emit(OpCodes.Conv_I4);
}
}
private static void EmitZeroCvFlags(AILEmitterCtx context)

View file

@ -136,9 +136,13 @@ namespace ChocolArm64.Instruction
IAOpCodeAlu op = (IAOpCodeAlu)context.CurrOp;
if (op.DataOp == ADataOp.Logical || op is IAOpCodeAluRs)
{
context.EmitLdintzr(op.Rn);
}
else
{
context.EmitLdint(op.Rn);
}
}
public static void EmitDataLoadOper2(AILEmitterCtx context)
@ -184,9 +188,13 @@ namespace ChocolArm64.Instruction
IAOpCodeAlu op = (IAOpCodeAlu)context.CurrOp;
if (setFlags || op is IAOpCodeAluRs)
{
context.EmitStintzr(op.Rd);
}
else
{
context.EmitStint(op.Rd);
}
}
public static void EmitSetNzcv(AILEmitterCtx context, int nzcv)

View file

@ -125,9 +125,13 @@ namespace ChocolArm64.Instruction
context.EmitLsl(op.GetBitsCount() - width);
if (signed)
{
context.EmitAsr(op.Shift - width);
}
else
{
context.EmitLsr(op.Shift - width);
}
context.EmitStintzr(op.Rd);
}
@ -151,9 +155,11 @@ namespace ChocolArm64.Instruction
context.Emit(ilOp);
if (op.RegisterSize != ARegisterSize.Int32)
{
context.Emit(signed
? OpCodes.Conv_I8
: OpCodes.Conv_U8);
}
context.EmitStintzr(op.Rd);
}

View file

@ -32,33 +32,49 @@ namespace ChocolArm64.Instruction
public static void Crc32Cb(AILEmitterCtx context)
{
if (AOptimizations.UseSse42)
{
EmitSse42Crc32(context, typeof(uint), typeof(byte));
}
else
{
EmitCrc32(context, nameof(ASoftFallback.Crc32Cb));
}
}
public static void Crc32Ch(AILEmitterCtx context)
{
if (AOptimizations.UseSse42)
{
EmitSse42Crc32(context, typeof(uint), typeof(ushort));
}
else
{
EmitCrc32(context, nameof(ASoftFallback.Crc32Ch));
}
}
public static void Crc32Cw(AILEmitterCtx context)
{
if (AOptimizations.UseSse42)
{
EmitSse42Crc32(context, typeof(uint), typeof(uint));
}
else
{
EmitCrc32(context, nameof(ASoftFallback.Crc32Cw));
}
}
public static void Crc32Cx(AILEmitterCtx context)
{
if (AOptimizations.UseSse42)
{
EmitSse42Crc32(context, typeof(ulong), typeof(ulong));
}
else
{
EmitCrc32(context, nameof(ASoftFallback.Crc32Cx));
}
}
private static void EmitSse42Crc32(AILEmitterCtx context, Type crc, Type data)
@ -79,13 +95,19 @@ namespace ChocolArm64.Instruction
context.EmitLdintzr(op.Rn);
if (op.RegisterSize != ARegisterSize.Int32) context.Emit(OpCodes.Conv_U4);
if (op.RegisterSize != ARegisterSize.Int32)
{
context.Emit(OpCodes.Conv_U4);
}
context.EmitLdintzr(op.Rm);
ASoftFallback.EmitCall(context, name);
if (op.RegisterSize != ARegisterSize.Int32) context.Emit(OpCodes.Conv_U8);
if (op.RegisterSize != ARegisterSize.Int32)
{
context.Emit(OpCodes.Conv_U8);
}
context.EmitStintzr(op.Rd);
}

View file

@ -43,16 +43,26 @@ namespace ChocolArm64.Instruction
EmitLoadAddress(context);
if (signed && op.Extend64)
{
EmitReadSx64Call(context, op.Size);
}
else if (signed)
{
EmitReadSx32Call(context, op.Size);
}
else
{
EmitReadZxCall(context, op.Size);
}
if (op is IAOpCodeSimd)
{
context.EmitStvec(op.Rt);
}
else
{
context.EmitStintzr(op.Rt);
}
EmitWBackIfNeeded(context);
}
@ -61,20 +71,31 @@ namespace ChocolArm64.Instruction
{
IAOpCodeLit op = (IAOpCodeLit)context.CurrOp;
if (op.Prefetch) return;
if (op.Prefetch)
{
return;
}
context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
context.EmitLdc_I8(op.Imm);
if (op.Signed)
{
EmitReadSx64Call(context, op.Size);
}
else
{
EmitReadZxCall(context, op.Size);
}
if (op is IAOpCodeSimd)
{
context.EmitStvec(op.Rt);
}
else
{
context.EmitStint(op.Rt);
}
}
public static void Ldp(AILEmitterCtx context)
@ -84,14 +105,22 @@ namespace ChocolArm64.Instruction
void EmitReadAndStore(int rt)
{
if (op.Extend64)
{
EmitReadSx64Call(context, op.Size);
}
else
{
EmitReadZxCall(context, op.Size);
}
if (op is IAOpCodeSimd)
{
context.EmitStvec(rt);
}
else
{
context.EmitStintzr(rt);
}
}
context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
@ -120,9 +149,13 @@ namespace ChocolArm64.Instruction
EmitLoadAddress(context);
if (op is IAOpCodeSimd)
{
context.EmitLdvec(op.Rt);
}
else
{
context.EmitLdintzr(op.Rt);
}
EmitWriteCall(context, op.Size);
@ -138,9 +171,13 @@ namespace ChocolArm64.Instruction
EmitLoadAddress(context);
if (op is IAOpCodeSimd)
{
context.EmitLdvec(op.Rt);
}
else
{
context.EmitLdintzr(op.Rt);
}
EmitWriteCall(context, op.Size);
@ -151,9 +188,13 @@ namespace ChocolArm64.Instruction
context.Emit(OpCodes.Add);
if (op is IAOpCodeSimd)
{
context.EmitLdvec(op.Rt2);
}
else
{
context.EmitLdintzr(op.Rt2);
}
EmitWriteCall(context, op.Size);
@ -181,7 +222,10 @@ namespace ChocolArm64.Instruction
context.EmitLdintzr(op.Rm);
context.EmitCast(op.IntType);
if (op.Shift) context.EmitLsl(op.Size);
if (op.Shift)
{
context.EmitLsl(op.Size);
}
context.Emit(OpCodes.Add);
break;

View file

@ -78,9 +78,15 @@ namespace ChocolArm64.Instruction
bool ordered = (accType & AccessType.Ordered) != 0;
bool exclusive = (accType & AccessType.Exclusive) != 0;
if (ordered) EmitBarrier(context);
if (ordered)
{
EmitBarrier(context);
}
if (exclusive) EmitMemoryCall(context, nameof(AMemory.SetExclusive), op.Rn);
if (exclusive)
{
EmitMemoryCall(context, nameof(AMemory.SetExclusive), op.Rn);
}
context.EmitLdint(op.Rn);
context.EmitSttmp();
@ -153,7 +159,10 @@ namespace ChocolArm64.Instruction
bool ordered = (accType & AccessType.Ordered) != 0;
bool exclusive = (accType & AccessType.Exclusive) != 0;
if (ordered) EmitBarrier(context);
if (ordered)
{
EmitBarrier(context);
}
AILLabel lblEx = new AILLabel();
AILLabel lblEnd = new AILLabel();
@ -209,7 +218,10 @@ namespace ChocolArm64.Instruction
context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Core));
if (rn != -1) context.EmitLdint(rn);
if (rn != -1)
{
context.EmitLdint(rn);
}
context.EmitCall(typeof(AMemory), name);
}

View file

@ -36,9 +36,13 @@ namespace ChocolArm64.Instruction
string name = null;
if (size < 0 || size > (isSimd ? 4 : 3)) throw new ArgumentOutOfRangeException(nameof(size));
if (size < 0 || size > (isSimd ? 4 : 3))
{
throw new ArgumentOutOfRangeException(nameof(size));
}
if (isSimd)
{
switch (size)
{
case 0: name = nameof(AMemory.ReadVector8); break;
@ -47,7 +51,9 @@ namespace ChocolArm64.Instruction
case 3: name = nameof(AMemory.ReadVector64); break;
case 4: name = nameof(AMemory.ReadVector128); break;
}
}
else
{
switch (size)
{
case 0: name = nameof(AMemory.ReadByte); break;
@ -55,6 +61,7 @@ namespace ChocolArm64.Instruction
case 2: name = nameof(AMemory.ReadUInt32); break;
case 3: name = nameof(AMemory.ReadUInt64); break;
}
}
context.EmitCall(typeof(AMemory), name);
@ -62,17 +69,21 @@ namespace ChocolArm64.Instruction
{
if (ext == Extension.Sx32 ||
ext == Extension.Sx64)
{
switch (size)
{
case 0: context.Emit(OpCodes.Conv_I1); break;
case 1: context.Emit(OpCodes.Conv_I2); break;
case 2: context.Emit(OpCodes.Conv_I4); break;
}
}
if (size < 3)
{
context.Emit(ext == Extension.Sx64
? OpCodes.Conv_I8
: OpCodes.Conv_U8);
}
}
}
@ -82,11 +93,18 @@ namespace ChocolArm64.Instruction
string name = null;
if (size < 0 || size > (isSimd ? 4 : 3)) throw new ArgumentOutOfRangeException(nameof(size));
if (size < 0 || size > (isSimd ? 4 : 3))
{
throw new ArgumentOutOfRangeException(nameof(size));
}
if (size < 3 && !isSimd) context.Emit(OpCodes.Conv_I4);
if (size < 3 && !isSimd)
{
context.Emit(OpCodes.Conv_I4);
}
if (isSimd)
{
switch (size)
{
case 0: name = nameof(AMemory.WriteVector8); break;
@ -95,7 +113,9 @@ namespace ChocolArm64.Instruction
case 3: name = nameof(AMemory.WriteVector64); break;
case 4: name = nameof(AMemory.WriteVector128); break;
}
}
else
{
switch (size)
{
case 0: name = nameof(AMemory.WriteByte); break;
@ -103,6 +123,7 @@ namespace ChocolArm64.Instruction
case 2: name = nameof(AMemory.WriteUInt32); break;
case 3: name = nameof(AMemory.WriteUInt64); break;
}
}
context.EmitCall(typeof(AMemory), name);
}

View file

@ -33,9 +33,13 @@ namespace ChocolArm64.Instruction
public static void Add_V(AILEmitterCtx context)
{
if (AOptimizations.UseSse2)
{
EmitSse2Op(context, nameof(Sse2.Add));
}
else
{
EmitVectorBinaryOpZx(context, () => context.Emit(OpCodes.Add));
}
}
public static void Addhn_V(AILEmitterCtx context)
@ -99,7 +103,10 @@ namespace ChocolArm64.Instruction
EmitVectorInsert(context, op.Rd, index, op.Size);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void Clz_V(AILEmitterCtx context)
@ -133,7 +140,10 @@ namespace ChocolArm64.Instruction
EmitVectorInsert(context, op.Rd, index, op.Size);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void Cnt_V(AILEmitterCtx context)
@ -147,14 +157,21 @@ namespace ChocolArm64.Instruction
EmitVectorExtractZx(context, op.Rn, index, 0);
if (Popcnt.IsSupported)
{
context.EmitCall(typeof(Popcnt).GetMethod(nameof(Popcnt.PopCount), new Type[] { typeof(ulong) }));
}
else
{
ASoftFallback.EmitCall(context, nameof(ASoftFallback.CountSetBits8));
}
EmitVectorInsert(context, op.Rd, index, 0);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void Fabd_S(AILEmitterCtx context)
@ -187,24 +204,32 @@ namespace ChocolArm64.Instruction
{
if (AOptimizations.FastFp && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitScalarSseOrSse2OpF(context, nameof(Sse.AddScalar));
}
else
{
EmitScalarBinaryOpF(context, () =>
{
EmitSoftFloatCall(context, nameof(ASoftFloat_32.FpAdd));
});
}
}
public static void Fadd_V(AILEmitterCtx context)
{
if (AOptimizations.FastFp && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitVectorSseOrSse2OpF(context, nameof(Sse.Add));
}
else
{
EmitVectorBinaryOpF(context, () =>
{
EmitSoftFloatCall(context, nameof(ASoftFloat_32.FpAdd));
});
}
}
public static void Faddp_S(AILEmitterCtx context)
@ -230,24 +255,32 @@ namespace ChocolArm64.Instruction
{
if (AOptimizations.FastFp && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitScalarSseOrSse2OpF(context, nameof(Sse.DivideScalar));
}
else
{
EmitScalarBinaryOpF(context, () =>
{
EmitSoftFloatCall(context, nameof(ASoftFloat_32.FpDiv));
});
}
}
public static void Fdiv_V(AILEmitterCtx context)
{
if (AOptimizations.FastFp && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitVectorSseOrSse2OpF(context, nameof(Sse.Divide));
}
else
{
EmitVectorBinaryOpF(context, () =>
{
EmitSoftFloatCall(context, nameof(ASoftFloat_32.FpDiv));
});
}
}
public static void Fmadd_S(AILEmitterCtx context)
@ -300,24 +333,32 @@ namespace ChocolArm64.Instruction
{
if (AOptimizations.FastFp && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitScalarSseOrSse2OpF(context, nameof(Sse.MaxScalar));
}
else
{
EmitScalarBinaryOpF(context, () =>
{
EmitSoftFloatCall(context, nameof(ASoftFloat_32.FpMax));
});
}
}
public static void Fmax_V(AILEmitterCtx context)
{
if (AOptimizations.FastFp && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitVectorSseOrSse2OpF(context, nameof(Sse.Max));
}
else
{
EmitVectorBinaryOpF(context, () =>
{
EmitSoftFloatCall(context, nameof(ASoftFloat_32.FpMax));
});
}
}
public static void Fmaxnm_S(AILEmitterCtx context)
@ -348,24 +389,32 @@ namespace ChocolArm64.Instruction
{
if (AOptimizations.FastFp && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitScalarSseOrSse2OpF(context, nameof(Sse.MinScalar));
}
else
{
EmitScalarBinaryOpF(context, () =>
{
EmitSoftFloatCall(context, nameof(ASoftFloat_32.FpMin));
});
}
}
public static void Fmin_V(AILEmitterCtx context)
{
if (AOptimizations.FastFp && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitVectorSseOrSse2OpF(context, nameof(Sse.Min));
}
else
{
EmitVectorBinaryOpF(context, () =>
{
EmitSoftFloatCall(context, nameof(ASoftFloat_32.FpMin));
});
}
}
public static void Fminnm_S(AILEmitterCtx context)
@ -496,12 +545,16 @@ namespace ChocolArm64.Instruction
{
if (AOptimizations.FastFp && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitScalarSseOrSse2OpF(context, nameof(Sse.MultiplyScalar));
}
else
{
EmitScalarBinaryOpF(context, () =>
{
EmitSoftFloatCall(context, nameof(ASoftFloat_32.FpMul));
});
}
}
public static void Fmul_Se(AILEmitterCtx context)
@ -513,12 +566,16 @@ namespace ChocolArm64.Instruction
{
if (AOptimizations.FastFp && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitVectorSseOrSse2OpF(context, nameof(Sse.Multiply));
}
else
{
EmitVectorBinaryOpF(context, () =>
{
EmitSoftFloatCall(context, nameof(ASoftFloat_32.FpMul));
});
}
}
public static void Fmul_Ve(AILEmitterCtx context)
@ -710,7 +767,10 @@ namespace ChocolArm64.Instruction
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else /* if (SizeF == 1) */
{
@ -774,11 +834,17 @@ namespace ChocolArm64.Instruction
context.EmitLdarg(ATranslatedSub.StateArgIdx);
if (op.Size == 0)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.RoundF));
}
else if (op.Size == 1)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.Round));
}
else
{
throw new InvalidOperationException();
}
});
}
@ -793,11 +859,17 @@ namespace ChocolArm64.Instruction
context.EmitLdarg(ATranslatedSub.StateArgIdx);
if (sizeF == 0)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.RoundF));
}
else if (sizeF == 1)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.Round));
}
else
{
throw new InvalidOperationException();
}
});
}
@ -861,11 +933,17 @@ namespace ChocolArm64.Instruction
context.EmitLdarg(ATranslatedSub.StateArgIdx);
if (op.Size == 0)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.RoundF));
}
else if (op.Size == 1)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.Round));
}
else
{
throw new InvalidOperationException();
}
});
}
@ -878,11 +956,17 @@ namespace ChocolArm64.Instruction
context.EmitLdarg(ATranslatedSub.StateArgIdx);
if (op.Size == 0)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.RoundF));
}
else if (op.Size == 1)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.Round));
}
else
{
throw new InvalidOperationException();
}
});
}
@ -992,7 +1076,10 @@ namespace ChocolArm64.Instruction
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else /* if (SizeF == 1) */
{
@ -1028,48 +1115,64 @@ namespace ChocolArm64.Instruction
{
if (AOptimizations.FastFp && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitScalarSseOrSse2OpF(context, nameof(Sse.SqrtScalar));
}
else
{
EmitScalarUnaryOpF(context, () =>
{
EmitSoftFloatCall(context, nameof(ASoftFloat_32.FpSqrt));
});
}
}
public static void Fsqrt_V(AILEmitterCtx context)
{
if (AOptimizations.FastFp && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitVectorSseOrSse2OpF(context, nameof(Sse.Sqrt));
}
else
{
EmitVectorUnaryOpF(context, () =>
{
EmitSoftFloatCall(context, nameof(ASoftFloat_32.FpSqrt));
});
}
}
public static void Fsub_S(AILEmitterCtx context)
{
if (AOptimizations.FastFp && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitScalarSseOrSse2OpF(context, nameof(Sse.SubtractScalar));
}
else
{
EmitScalarBinaryOpF(context, () =>
{
EmitSoftFloatCall(context, nameof(ASoftFloat_32.FpSub));
});
}
}
public static void Fsub_V(AILEmitterCtx context)
{
if (AOptimizations.FastFp && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitVectorSseOrSse2OpF(context, nameof(Sse.Subtract));
}
else
{
EmitVectorBinaryOpF(context, () =>
{
EmitSoftFloatCall(context, nameof(ASoftFloat_32.FpSub));
});
}
}
public static void Mla_V(AILEmitterCtx context)
@ -1267,7 +1370,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithSignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -1314,7 +1420,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithSignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -1582,7 +1691,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithSignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -1653,9 +1765,13 @@ namespace ChocolArm64.Instruction
public static void Sub_V(AILEmitterCtx context)
{
if (AOptimizations.UseSse2)
{
EmitSse2Op(context, nameof(Sse2.Subtract));
}
else
{
EmitVectorBinaryOpZx(context, () => context.Emit(OpCodes.Sub));
}
}
public static void Subhn_V(AILEmitterCtx context)
@ -1821,7 +1937,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -1854,7 +1973,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -2056,7 +2178,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -2171,7 +2296,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
private static void EmitDoublingMultiplyHighHalf(AILEmitterCtx context, bool round)
@ -2250,7 +2378,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (part == 0) EmitVectorZeroUpper(context, op.Rd);
if (part == 0)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
}
}

View file

@ -22,11 +22,17 @@ namespace ChocolArm64.Instruction
if (context.CurrOp is AOpCodeSimdReg op)
{
if (op.Size < 3 && AOptimizations.UseSse2)
{
EmitSse2Op(context, nameof(Sse2.CompareEqual));
}
else if (op.Size == 3 && AOptimizations.UseSse41)
{
EmitSse41Op(context, nameof(Sse41.CompareEqual));
}
else
{
EmitCmp(context, OpCodes.Beq_S, false);
}
}
else
{
@ -54,11 +60,17 @@ namespace ChocolArm64.Instruction
if (context.CurrOp is AOpCodeSimdReg op)
{
if (op.Size < 3 && AOptimizations.UseSse2)
{
EmitSse2Op(context, nameof(Sse2.CompareGreaterThan));
}
else if (op.Size == 3 && AOptimizations.UseSse42)
{
EmitSse42Op(context, nameof(Sse42.CompareGreaterThan));
}
else
{
EmitCmp(context, OpCodes.Bgt_S, false);
}
}
else
{
@ -145,54 +157,78 @@ namespace ChocolArm64.Instruction
{
if (context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitScalarSseOrSse2OpF(context, nameof(Sse.CompareEqualScalar));
}
else
{
EmitScalarFcmp(context, OpCodes.Beq_S);
}
}
public static void Fcmeq_V(AILEmitterCtx context)
{
if (context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitVectorSseOrSse2OpF(context, nameof(Sse.CompareEqual));
}
else
{
EmitVectorFcmp(context, OpCodes.Beq_S);
}
}
public static void Fcmge_S(AILEmitterCtx context)
{
if (context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitScalarSseOrSse2OpF(context, nameof(Sse.CompareGreaterThanOrEqualScalar));
}
else
{
EmitScalarFcmp(context, OpCodes.Bge_S);
}
}
public static void Fcmge_V(AILEmitterCtx context)
{
if (context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitVectorSseOrSse2OpF(context, nameof(Sse.CompareGreaterThanOrEqual));
}
else
{
EmitVectorFcmp(context, OpCodes.Bge_S);
}
}
public static void Fcmgt_S(AILEmitterCtx context)
{
if (context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitScalarSseOrSse2OpF(context, nameof(Sse.CompareGreaterThanScalar));
}
else
{
EmitScalarFcmp(context, OpCodes.Bgt_S);
}
}
public static void Fcmgt_V(AILEmitterCtx context)
{
if (context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitVectorSseOrSse2OpF(context, nameof(Sse.CompareGreaterThan));
}
else
{
EmitVectorFcmp(context, OpCodes.Bgt_S);
}
}
public static void Fcmle_S(AILEmitterCtx context)
@ -247,9 +283,13 @@ namespace ChocolArm64.Instruction
if (cmpWithZero)
{
if (op.Size == 0)
{
context.EmitLdc_R4(0f);
}
else /* if (Op.Size == 1) */
{
context.EmitLdc_R8(0d);
}
}
else
{
@ -306,11 +346,17 @@ namespace ChocolArm64.Instruction
EmitVectorExtractF(context, reg, 0, op.Size);
if (op.Size == 0)
{
context.EmitCall(typeof(float), nameof(float.IsNaN));
}
else if (op.Size == 1)
{
context.EmitCall(typeof(double), nameof(double.IsNaN));
}
else
{
throw new InvalidOperationException();
}
}
private static void EmitCmp(AILEmitterCtx context, OpCode ilOp, bool scalar)
@ -327,9 +373,13 @@ namespace ChocolArm64.Instruction
EmitVectorExtractSx(context, op.Rn, index, op.Size);
if (op is AOpCodeSimdReg binOp)
{
EmitVectorExtractSx(context, binOp.Rm, index, op.Size);
}
else
{
context.EmitLdc_I8(0L);
}
AILLabel lblTrue = new AILLabel();
AILLabel lblEnd = new AILLabel();
@ -347,7 +397,10 @@ namespace ChocolArm64.Instruction
context.MarkLabel(lblEnd);
}
if (op.RegisterSize == ARegisterSize.Simd64 || scalar) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64 || scalar)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
private static void EmitCmtst(AILEmitterCtx context, bool scalar)
@ -384,7 +437,10 @@ namespace ChocolArm64.Instruction
context.MarkLabel(lblEnd);
}
if (op.RegisterSize == ARegisterSize.Simd64 || scalar) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64 || scalar)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
private static void EmitScalarFcmp(AILEmitterCtx context, OpCode ilOp)
@ -401,9 +457,15 @@ namespace ChocolArm64.Instruction
int bytes = op.GetBitsCount() >> 3;
int elems = bytes >> (sizeF + 2);
for (int index = 0; index < elems; index++) EmitFcmp(context, ilOp, index, false);
for (int index = 0; index < elems; index++)
{
EmitFcmp(context, ilOp, index, false);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
private static void EmitFcmp(AILEmitterCtx context, OpCode ilOp, int index, bool scalar)
@ -417,11 +479,17 @@ namespace ChocolArm64.Instruction
EmitVectorExtractF(context, op.Rn, index, sizeF);
if (op is AOpCodeSimdReg binOp)
{
EmitVectorExtractF(context, binOp.Rm, index, sizeF);
}
else if (sizeF == 0)
{
context.EmitLdc_R4(0f);
}
else /* if (SizeF == 1) */
{
context.EmitLdc_R8(0d);
}
AILLabel lblTrue = new AILLabel();
AILLabel lblEnd = new AILLabel();
@ -429,9 +497,13 @@ namespace ChocolArm64.Instruction
context.Emit(ilOp, lblTrue);
if (scalar)
{
EmitVectorZeroAll(context, op.Rd);
}
else
{
EmitVectorInsert(context, op.Rd, index, sizeF + 2, 0);
}
context.Emit(OpCodes.Br_S, lblEnd);

View file

@ -155,7 +155,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (part == 0) EmitVectorZeroUpper(context, op.Rd);
if (part == 0)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void Fcvtns_S(AILEmitterCtx context)
@ -234,7 +237,10 @@ namespace ChocolArm64.Instruction
context.EmitLdintzr(op.Rn);
if (context.CurrOp.RegisterSize == ARegisterSize.Int32) context.Emit(OpCodes.Conv_U4);
if (context.CurrOp.RegisterSize == ARegisterSize.Int32)
{
context.Emit(OpCodes.Conv_U4);
}
EmitFloatCast(context, op.Size);
@ -263,7 +269,10 @@ namespace ChocolArm64.Instruction
context.EmitLdintzr(op.Rn);
if (context.CurrOp.RegisterSize == ARegisterSize.Int32) context.Emit(OpCodes.Conv_U4);
if (context.CurrOp.RegisterSize == ARegisterSize.Int32)
{
context.Emit(OpCodes.Conv_U4);
}
context.Emit(OpCodes.Conv_R_Un);
@ -292,7 +301,10 @@ namespace ChocolArm64.Instruction
private static int GetFBits(AILEmitterCtx context)
{
if (context.CurrOp is AOpCodeSimdShImm op) return GetImmShr(op);
if (context.CurrOp is AOpCodeSimdShImm op)
{
return GetImmShr(op);
}
return 0;
}
@ -300,11 +312,17 @@ namespace ChocolArm64.Instruction
private static void EmitFloatCast(AILEmitterCtx context, int size)
{
if (size == 0)
{
context.Emit(OpCodes.Conv_R4);
}
else if (size == 1)
{
context.Emit(OpCodes.Conv_R8);
}
else
{
throw new ArgumentOutOfRangeException(nameof(size));
}
}
private static void EmitFcvtn(AILEmitterCtx context, bool signed, bool scalar)
@ -317,7 +335,10 @@ namespace ChocolArm64.Instruction
int bytes = op.GetBitsCount() >> 3;
int elems = !scalar ? bytes >> sizeI : 1;
if (scalar && sizeF == 0) EmitVectorZeroLowerTmp(context);
if (scalar && sizeF == 0)
{
EmitVectorZeroLowerTmp(context);
}
for (int index = 0; index < elems; index++)
{
@ -346,7 +367,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64 || scalar) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64 || scalar)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
private static void EmitFcvt_s_Gp(AILEmitterCtx context, Action emit)
@ -368,11 +392,18 @@ namespace ChocolArm64.Instruction
emit();
if (signed)
{
EmitScalarFcvts(context, op.Size, 0);
}
else
{
EmitScalarFcvtu(context, op.Size, 0);
}
if (context.CurrOp.RegisterSize == ARegisterSize.Int32) context.Emit(OpCodes.Conv_U8);
if (context.CurrOp.RegisterSize == ARegisterSize.Int32)
{
context.Emit(OpCodes.Conv_U8);
}
context.EmitStintzr(op.Rd);
}
@ -394,11 +425,18 @@ namespace ChocolArm64.Instruction
EmitVectorExtractF(context, op.Rn, 0, op.Size);
if (signed)
{
EmitScalarFcvts(context, op.Size, op.FBits);
}
else
{
EmitScalarFcvtu(context, op.Size, op.FBits);
}
if (context.CurrOp.RegisterSize == ARegisterSize.Int32) context.Emit(OpCodes.Conv_U8);
if (context.CurrOp.RegisterSize == ARegisterSize.Int32)
{
context.Emit(OpCodes.Conv_U8);
}
context.EmitStintzr(op.Rd);
}
@ -429,7 +467,10 @@ namespace ChocolArm64.Instruction
{
EmitVectorExtract(context, op.Rn, index, sizeI, signed);
if (!signed) context.Emit(OpCodes.Conv_R_Un);
if (!signed)
{
context.Emit(OpCodes.Conv_R_Un);
}
context.Emit(sizeF == 0
? OpCodes.Conv_R4
@ -440,7 +481,10 @@ namespace ChocolArm64.Instruction
EmitVectorInsertF(context, op.Rd, index, sizeF);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
private static void EmitScalarFcvtzs(AILEmitterCtx context)
@ -467,15 +511,22 @@ namespace ChocolArm64.Instruction
EmitF2iFBitsMul(context, sizeF, fBits);
if (sizeF == 0)
{
AVectorHelper.EmitCall(context, signed
? nameof(AVectorHelper.SatF32ToS32)
: nameof(AVectorHelper.SatF32ToU32));
}
else /* if (SizeF == 1) */
{
AVectorHelper.EmitCall(context, signed
? nameof(AVectorHelper.SatF64ToS64)
: nameof(AVectorHelper.SatF64ToU64));
}
if (sizeF == 0) context.Emit(OpCodes.Conv_U8);
if (sizeF == 0)
{
context.Emit(OpCodes.Conv_U8);
}
EmitScalarSet(context, op.Rd, sizeI);
}
@ -509,63 +560,95 @@ namespace ChocolArm64.Instruction
EmitF2iFBitsMul(context, sizeF, fBits);
if (sizeF == 0)
{
AVectorHelper.EmitCall(context, signed
? nameof(AVectorHelper.SatF32ToS32)
: nameof(AVectorHelper.SatF32ToU32));
}
else /* if (SizeF == 1) */
{
AVectorHelper.EmitCall(context, signed
? nameof(AVectorHelper.SatF64ToS64)
: nameof(AVectorHelper.SatF64ToU64));
}
if (sizeF == 0) context.Emit(OpCodes.Conv_U8);
if (sizeF == 0)
{
context.Emit(OpCodes.Conv_U8);
}
EmitVectorInsert(context, op.Rd, index, sizeI);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
private static void EmitScalarFcvts(AILEmitterCtx context, int size, int fBits)
{
if (size < 0 || size > 1) throw new ArgumentOutOfRangeException(nameof(size));
if (size < 0 || size > 1)
{
throw new ArgumentOutOfRangeException(nameof(size));
}
EmitF2iFBitsMul(context, size, fBits);
if (context.CurrOp.RegisterSize == ARegisterSize.Int32)
{
if (size == 0)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.SatF32ToS32));
}
else /* if (Size == 1) */
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.SatF64ToS32));
}
}
else
{
if (size == 0)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.SatF32ToS64));
}
else /* if (Size == 1) */
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.SatF64ToS64));
}
}
}
private static void EmitScalarFcvtu(AILEmitterCtx context, int size, int fBits)
{
if (size < 0 || size > 1) throw new ArgumentOutOfRangeException(nameof(size));
if (size < 0 || size > 1)
{
throw new ArgumentOutOfRangeException(nameof(size));
}
EmitF2iFBitsMul(context, size, fBits);
if (context.CurrOp.RegisterSize == ARegisterSize.Int32)
{
if (size == 0)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.SatF32ToU32));
}
else /* if (Size == 1) */
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.SatF64ToU32));
}
}
else
{
if (size == 0)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.SatF32ToU64));
}
else /* if (Size == 1) */
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.SatF64ToU64));
}
}
}
@ -574,11 +657,17 @@ namespace ChocolArm64.Instruction
if (fBits != 0)
{
if (size == 0)
{
context.EmitLdc_R4(MathF.Pow(2f, fBits));
}
else if (size == 1)
{
context.EmitLdc_R8(Math.Pow(2d, fBits));
}
else
{
throw new ArgumentOutOfRangeException(nameof(size));
}
context.Emit(OpCodes.Mul);
}
@ -589,11 +678,17 @@ namespace ChocolArm64.Instruction
if (fBits != 0)
{
if (size == 0)
{
context.EmitLdc_R4(1f / MathF.Pow(2f, fBits));
}
else if (size == 1)
{
context.EmitLdc_R8(1d / Math.Pow(2d, fBits));
}
else
{
throw new ArgumentOutOfRangeException(nameof(size));
}
context.Emit(OpCodes.Mul);
}

View file

@ -103,7 +103,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithSignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void EmitLdvecWithSignedCast(AILEmitterCtx context, int reg, int size)
@ -200,7 +203,10 @@ namespace ChocolArm64.Instruction
{
context.EmitLdvec(reg);
if (sizeF == 1) AVectorHelper.EmitCall(context, nameof(AVectorHelper.VectorSingleToDouble));
if (sizeF == 1)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.VectorSingleToDouble));
}
}
Ldvec(op.Rn);
@ -230,16 +236,23 @@ namespace ChocolArm64.Instruction
context.EmitCall(type.GetMethod(name, new Type[] { baseType }));
}
if (sizeF == 1) AVectorHelper.EmitCall(context, nameof(AVectorHelper.VectorDoubleToSingle));
if (sizeF == 1)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.VectorDoubleToSingle));
}
context.EmitStvec(op.Rd);
if (scalar)
{
if (sizeF == 0)
{
EmitVectorZero32_128(context, op.Rd);
}
else /* if (SizeF == 1) */
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else if (op.RegisterSize == ARegisterSize.Simd64)
{
@ -256,9 +269,13 @@ namespace ChocolArm64.Instruction
MethodInfo mthdInfo;
if (sizeF == 0)
{
mthdInfo = typeof(MathF).GetMethod(name, new Type[] { typeof(float) });
}
else /* if (SizeF == 1) */
{
mthdInfo = typeof(Math).GetMethod(name, new Type[] { typeof(double) });
}
context.EmitCall(mthdInfo);
}
@ -272,9 +289,13 @@ namespace ChocolArm64.Instruction
MethodInfo mthdInfo;
if (sizeF == 0)
{
mthdInfo = typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(float) });
}
else /* if (SizeF == 1) */
{
mthdInfo = typeof(Math).GetMethod(name, new Type[] { typeof(double), typeof(double) });
}
context.EmitCall(mthdInfo);
}
@ -288,9 +309,13 @@ namespace ChocolArm64.Instruction
MethodInfo mthdInfo;
if (sizeF == 0)
{
mthdInfo = typeof(MathF).GetMethod(nameof(MathF.Round), new Type[] { typeof(float), typeof(MidpointRounding) });
}
else /* if (SizeF == 1) */
{
mthdInfo = typeof(Math).GetMethod(nameof(Math.Round), new Type[] { typeof(double), typeof(MidpointRounding) });
}
context.EmitLdc_I4((int)roundMode);
@ -306,9 +331,13 @@ namespace ChocolArm64.Instruction
MethodInfo mthdInfo;
if (sizeF == 0)
{
mthdInfo = typeof(ASoftFloat).GetMethod(name, new Type[] { typeof(float) });
}
else /* if (SizeF == 1) */
{
mthdInfo = typeof(ASoftFloat).GetMethod(name, new Type[] { typeof(double) });
}
context.EmitCall(mthdInfo);
}
@ -346,7 +375,10 @@ namespace ChocolArm64.Instruction
int sizeF = op.Size & 1;
if (ternary) EmitVectorExtractF(context, op.Rd, 0, sizeF);
if (ternary)
{
EmitVectorExtractF(context, op.Rd, 0, sizeF);
}
EmitVectorExtractF(context, op.Rn, 0, sizeF);
EmitVectorExtractF(context, op.Rm, elem, sizeF);
@ -389,11 +421,20 @@ namespace ChocolArm64.Instruction
bool rn = (opers & OperFlags.Rn) != 0;
bool rm = (opers & OperFlags.Rm) != 0;
if (rd) EmitVectorExtract(context, op.Rd, 0, op.Size, signed);
if (rd)
{
EmitVectorExtract(context, op.Rd, 0, op.Size, signed);
}
if (rn) EmitVectorExtract(context, op.Rn, 0, op.Size, signed);
if (rn)
{
EmitVectorExtract(context, op.Rn, 0, op.Size, signed);
}
if (rm) EmitVectorExtract(context, ((AOpCodeSimdReg)op).Rm, 0, op.Size, signed);
if (rm)
{
EmitVectorExtract(context, ((AOpCodeSimdReg)op).Rm, 0, op.Size, signed);
}
emit();
@ -425,11 +466,20 @@ namespace ChocolArm64.Instruction
bool rn = (opers & OperFlags.Rn) != 0;
bool rm = (opers & OperFlags.Rm) != 0;
if (ra) EmitVectorExtractF(context, ((AOpCodeSimdReg)op).Ra, 0, sizeF);
if (ra)
{
EmitVectorExtractF(context, ((AOpCodeSimdReg)op).Ra, 0, sizeF);
}
if (rn) EmitVectorExtractF(context, op.Rn, 0, sizeF);
if (rn)
{
EmitVectorExtractF(context, op.Rn, 0, sizeF);
}
if (rm) EmitVectorExtractF(context, ((AOpCodeSimdReg)op).Rm, 0, sizeF);
if (rm)
{
EmitVectorExtractF(context, ((AOpCodeSimdReg)op).Rm, 0, sizeF);
}
emit();
@ -466,18 +516,30 @@ namespace ChocolArm64.Instruction
for (int index = 0; index < elems; index++)
{
if (rd) EmitVectorExtractF(context, op.Rd, index, sizeF);
if (rd)
{
EmitVectorExtractF(context, op.Rd, index, sizeF);
}
if (rn) EmitVectorExtractF(context, op.Rn, index, sizeF);
if (rn)
{
EmitVectorExtractF(context, op.Rn, index, sizeF);
}
if (rm) EmitVectorExtractF(context, ((AOpCodeSimdReg)op).Rm, index, sizeF);
if (rm)
{
EmitVectorExtractF(context, ((AOpCodeSimdReg)op).Rm, index, sizeF);
}
emit();
EmitVectorInsertF(context, op.Rd, index, sizeF);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void EmitVectorBinaryOpByElemF(AILEmitterCtx context, Action emit)
@ -505,7 +567,10 @@ namespace ChocolArm64.Instruction
for (int index = 0; index < elems; index++)
{
if (ternary) EmitVectorExtractF(context, op.Rd, index, sizeF);
if (ternary)
{
EmitVectorExtractF(context, op.Rd, index, sizeF);
}
EmitVectorExtractF(context, op.Rn, index, sizeF);
EmitVectorExtractF(context, op.Rm, elem, sizeF);
@ -518,7 +583,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void EmitVectorUnaryOpSx(AILEmitterCtx context, Action emit)
@ -564,18 +632,30 @@ namespace ChocolArm64.Instruction
for (int index = 0; index < elems; index++)
{
if (rd) EmitVectorExtract(context, op.Rd, index, op.Size, signed);
if (rd)
{
EmitVectorExtract(context, op.Rd, index, op.Size, signed);
}
if (rn) EmitVectorExtract(context, op.Rn, index, op.Size, signed);
if (rn)
{
EmitVectorExtract(context, op.Rn, index, op.Size, signed);
}
if (rm) EmitVectorExtract(context, ((AOpCodeSimdReg)op).Rm, index, op.Size, signed);
if (rm)
{
EmitVectorExtract(context, ((AOpCodeSimdReg)op).Rm, index, op.Size, signed);
}
emit();
EmitVectorInsert(context, op.Rd, index, op.Size);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void EmitVectorBinaryOpByElemSx(AILEmitterCtx context, Action emit)
@ -611,7 +691,10 @@ namespace ChocolArm64.Instruction
for (int index = 0; index < elems; index++)
{
if (ternary) EmitVectorExtract(context, op.Rd, index, op.Size, signed);
if (ternary)
{
EmitVectorExtract(context, op.Rd, index, op.Size, signed);
}
EmitVectorExtract(context, op.Rn, index, op.Size, signed);
context.EmitLdtmp();
@ -624,7 +707,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void EmitVectorImmUnaryOp(AILEmitterCtx context, Action emit)
@ -646,7 +732,10 @@ namespace ChocolArm64.Instruction
for (int index = 0; index < elems; index++)
{
if (binary) EmitVectorExtractZx(context, op.Rd, index, op.Size);
if (binary)
{
EmitVectorExtractZx(context, op.Rd, index, op.Size);
}
context.EmitLdc_I8(op.Imm);
@ -655,7 +744,10 @@ namespace ChocolArm64.Instruction
EmitVectorInsert(context, op.Rd, index, op.Size);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void EmitVectorWidenRmBinaryOpSx(AILEmitterCtx context, Action emit)
@ -720,7 +812,10 @@ namespace ChocolArm64.Instruction
for (int index = 0; index < elems; index++)
{
if (ternary) EmitVectorExtract(context, op.Rd, index, op.Size + 1, signed);
if (ternary)
{
EmitVectorExtract(context, op.Rd, index, op.Size + 1, signed);
}
EmitVectorExtract(context, op.Rn, part + index, op.Size, signed);
EmitVectorExtract(context, op.Rm, part + index, op.Size, signed);
@ -772,7 +867,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void EmitVectorPairwiseOpF(AILEmitterCtx context, Action emit)
@ -805,7 +903,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
[Flags]
@ -845,7 +946,10 @@ namespace ChocolArm64.Instruction
int bytes = op.GetBitsCount() >> 3;
int elems = !scalar ? bytes >> op.Size : 1;
if (scalar) EmitVectorZeroLowerTmp(context);
if (scalar)
{
EmitVectorZeroLowerTmp(context);
}
for (int index = 0; index < elems; index++)
{
@ -854,9 +958,13 @@ namespace ChocolArm64.Instruction
emit();
if (op.Size <= 2)
{
EmitSatQ(context, op.Size, true, true);
}
else /* if (Op.Size == 3) */
{
EmitUnarySignedSatQAbsOrNeg(context);
}
EmitVectorInsertTmp(context, index, op.Size);
}
@ -864,7 +972,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64 || scalar) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64 || scalar)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void EmitScalarSaturatingBinaryOpSx(AILEmitterCtx context, SaturatingFlags flags)
@ -902,9 +1013,13 @@ namespace ChocolArm64.Instruction
int bytes = op.GetBitsCount() >> 3;
int elems = !scalar ? bytes >> op.Size : 1;
if (scalar) EmitVectorZeroLowerTmp(context);
if (scalar)
{
EmitVectorZeroLowerTmp(context);
}
if (add || sub)
{
for (int index = 0; index < elems; index++)
{
EmitVectorExtract(context, op.Rn, index, op.Size, signed);
@ -919,14 +1034,20 @@ namespace ChocolArm64.Instruction
else /* if (Op.Size == 3) */
{
if (add)
{
EmitBinarySatQAdd(context, signed);
}
else /* if (Sub) */
{
EmitBinarySatQSub(context, signed);
}
}
EmitVectorInsertTmp(context, index, op.Size);
}
}
else if (accumulate)
{
for (int index = 0; index < elems; index++)
{
EmitVectorExtract(context, op.Rn, index, op.Size, !signed);
@ -945,7 +1066,9 @@ namespace ChocolArm64.Instruction
EmitVectorInsertTmp(context, index, op.Size);
}
}
else
{
for (int index = 0; index < elems; index++)
{
EmitVectorExtract(context, op.Rn, index, op.Size, signed);
@ -957,11 +1080,15 @@ namespace ChocolArm64.Instruction
EmitVectorInsertTmp(context, index, op.Size);
}
}
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64 || scalar) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64 || scalar)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
[Flags]
@ -992,7 +1119,10 @@ namespace ChocolArm64.Instruction
int part = !scalar && op.RegisterSize == ARegisterSize.Simd128 ? elems : 0;
if (scalar) EmitVectorZeroLowerTmp(context);
if (scalar)
{
EmitVectorZeroLowerTmp(context);
}
if (part != 0)
{
@ -1012,7 +1142,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (part == 0) EmitVectorZeroUpper(context, op.Rd);
if (part == 0)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
// TSrc (16bit, 32bit, 64bit; signed, unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned).
@ -1022,25 +1155,35 @@ namespace ChocolArm64.Instruction
bool signedSrc,
bool signedDst)
{
if (sizeDst > 2) throw new ArgumentOutOfRangeException(nameof(sizeDst));
if (sizeDst > 2)
{
throw new ArgumentOutOfRangeException(nameof(sizeDst));
}
context.EmitLdc_I4(sizeDst);
context.EmitLdarg(ATranslatedSub.StateArgIdx);
if (signedSrc)
{
ASoftFallback.EmitCall(context, signedDst
? nameof(ASoftFallback.SignedSrcSignedDstSatQ)
: nameof(ASoftFallback.SignedSrcUnsignedDstSatQ));
}
else
{
ASoftFallback.EmitCall(context, signedDst
? nameof(ASoftFallback.UnsignedSrcSignedDstSatQ)
: nameof(ASoftFallback.UnsignedSrcUnsignedDstSatQ));
}
}
// TSrc (64bit) == TDst (64bit); signed.
public static void EmitUnarySignedSatQAbsOrNeg(AILEmitterCtx context)
{
if (((AOpCodeSimd)context.CurrOp).Size < 3) throw new InvalidOperationException();
if (((AOpCodeSimd)context.CurrOp).Size < 3)
{
throw new InvalidOperationException();
}
context.EmitLdarg(ATranslatedSub.StateArgIdx);
@ -1050,7 +1193,10 @@ namespace ChocolArm64.Instruction
// TSrcs (64bit) == TDst (64bit); signed, unsigned.
public static void EmitBinarySatQAdd(AILEmitterCtx context, bool signed)
{
if (((AOpCodeSimdReg)context.CurrOp).Size < 3) throw new InvalidOperationException();
if (((AOpCodeSimdReg)context.CurrOp).Size < 3)
{
throw new InvalidOperationException();
}
context.EmitLdarg(ATranslatedSub.StateArgIdx);
@ -1062,7 +1208,10 @@ namespace ChocolArm64.Instruction
// TSrcs (64bit) == TDst (64bit); signed, unsigned.
public static void EmitBinarySatQSub(AILEmitterCtx context, bool signed)
{
if (((AOpCodeSimdReg)context.CurrOp).Size < 3) throw new InvalidOperationException();
if (((AOpCodeSimdReg)context.CurrOp).Size < 3)
{
throw new InvalidOperationException();
}
context.EmitLdarg(ATranslatedSub.StateArgIdx);
@ -1074,7 +1223,10 @@ namespace ChocolArm64.Instruction
// TSrcs (64bit) == TDst (64bit); signed, unsigned.
public static void EmitBinarySatQAccumulate(AILEmitterCtx context, bool signed)
{
if (((AOpCodeSimd)context.CurrOp).Size < 3) throw new InvalidOperationException();
if (((AOpCodeSimd)context.CurrOp).Size < 3)
{
throw new InvalidOperationException();
}
context.EmitLdarg(ATranslatedSub.StateArgIdx);
@ -1139,11 +1291,17 @@ namespace ChocolArm64.Instruction
context.EmitLdc_I4(index);
if (size == 0)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.VectorExtractSingle));
}
else if (size == 1)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.VectorExtractDouble));
}
else
{
throw new ArgumentOutOfRangeException(nameof(size));
}
}
public static void EmitVectorZeroAll(AILEmitterCtx context, int rd)
@ -1270,11 +1428,17 @@ namespace ChocolArm64.Instruction
context.EmitLdc_I4(index);
if (size == 0)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.VectorInsertSingle));
}
else if (size == 1)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.VectorInsertDouble));
}
else
{
throw new ArgumentOutOfRangeException(nameof(size));
}
context.EmitStvec(reg);
}
@ -1287,27 +1451,45 @@ namespace ChocolArm64.Instruction
context.EmitLdc_I4(index);
if (size == 0)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.VectorInsertSingle));
}
else if (size == 1)
{
AVectorHelper.EmitCall(context, nameof(AVectorHelper.VectorInsertDouble));
}
else
{
throw new ArgumentOutOfRangeException(nameof(size));
}
context.EmitStvectmp();
}
private static void ThrowIfInvalid(int index, int size)
{
if ((uint)size > 3u) throw new ArgumentOutOfRangeException(nameof(size));
if ((uint)size > 3u)
{
throw new ArgumentOutOfRangeException(nameof(size));
}
if ((uint)index >= 16u >> size) throw new ArgumentOutOfRangeException(nameof(index));
if ((uint)index >= 16u >> size)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
}
private static void ThrowIfInvalidF(int index, int size)
{
if ((uint)size > 1u) throw new ArgumentOutOfRangeException(nameof(size));
if ((uint)size > 1u)
{
throw new ArgumentOutOfRangeException(nameof(size));
}
if ((uint)index >= 4u >> size) throw new ArgumentOutOfRangeException(nameof(index));
if ((uint)index >= 4u >> size)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
}
}
}

View file

@ -14,9 +14,13 @@ namespace ChocolArm64.Instruction
public static void And_V(AILEmitterCtx context)
{
if (AOptimizations.UseSse2)
{
EmitSse2Op(context, nameof(Sse2.And));
}
else
{
EmitVectorBinaryOpZx(context, () => context.Emit(OpCodes.And));
}
}
public static void Bic_V(AILEmitterCtx context)
@ -38,7 +42,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -97,7 +104,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -113,7 +123,10 @@ namespace ChocolArm64.Instruction
EmitVectorExtractZx(context, op.Rm, index, op.Size);
if (notRm) context.Emit(OpCodes.Not);
if (notRm)
{
context.Emit(OpCodes.Not);
}
context.Emit(OpCodes.And);
@ -124,7 +137,10 @@ namespace ChocolArm64.Instruction
EmitVectorInsert(context, op.Rd, index, op.Size);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
}
@ -155,7 +171,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -177,9 +196,13 @@ namespace ChocolArm64.Instruction
public static void Eor_V(AILEmitterCtx context)
{
if (AOptimizations.UseSse2)
{
EmitSse2Op(context, nameof(Sse2.Xor));
}
else
{
EmitVectorBinaryOpZx(context, () => context.Emit(OpCodes.Xor));
}
}
public static void Not_V(AILEmitterCtx context)
@ -199,9 +222,13 @@ namespace ChocolArm64.Instruction
public static void Orr_V(AILEmitterCtx context)
{
if (AOptimizations.UseSse2)
{
EmitSse2Op(context, nameof(Sse2.Or));
}
else
{
EmitVectorBinaryOpZx(context, () => context.Emit(OpCodes.Or));
}
}
public static void Orr_Vi(AILEmitterCtx context)
@ -228,7 +255,10 @@ namespace ChocolArm64.Instruction
EmitVectorInsert(context, op.Rd, index, 0);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void Rev16_V(AILEmitterCtx context)
@ -250,7 +280,10 @@ namespace ChocolArm64.Instruction
{
AOpCodeSimd op = (AOpCodeSimd)context.CurrOp;
if (op.Size >= containerSize) throw new InvalidOperationException();
if (op.Size >= containerSize)
{
throw new InvalidOperationException();
}
int bytes = op.GetBitsCount() >> 3;
int elems = bytes >> op.Size;
@ -269,7 +302,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
}
}

View file

@ -38,8 +38,10 @@ namespace ChocolArm64.Instruction
int offset = 0;
for (int rep = 0; rep < op.Reps; rep++)
for (int elem = 0; elem < op.Elems; elem++)
for (int sElem = 0; sElem < op.SElems; sElem++)
{
for (int elem = 0; elem < op.Elems; elem++)
{
for (int sElem = 0; sElem < op.SElems; sElem++)
{
int rtt = (op.Rt + rep + sElem) & 0x1f;
@ -55,8 +57,11 @@ namespace ChocolArm64.Instruction
EmitVectorInsert(context, rtt, elem, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64 && elem == op.Elems - 1) EmitVectorZeroUpper(context, rtt);
}
if (op.RegisterSize == ARegisterSize.Simd64 && elem == op.Elems - 1)
{
EmitVectorZeroUpper(context, rtt);
}
}
else
{
context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
@ -72,8 +77,13 @@ namespace ChocolArm64.Instruction
offset += 1 << op.Size;
}
}
}
if (op.WBack) EmitSimdMemWBack(context, offset);
if (op.WBack)
{
EmitSimdMemWBack(context, offset);
}
}
private static void EmitSimdMemSs(AILEmitterCtx context, bool isLoad)
@ -94,7 +104,10 @@ namespace ChocolArm64.Instruction
if (op.Replicate)
{
//Only loads uses the replicate mode.
if (!isLoad) throw new InvalidOperationException();
if (!isLoad)
{
throw new InvalidOperationException();
}
int bytes = op.GetBitsCount() >> 3;
int elems = bytes >> op.Size;
@ -112,7 +125,10 @@ namespace ChocolArm64.Instruction
EmitVectorInsert(context, rt, index, op.Size);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, rt);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, rt);
}
offset += 1 << op.Size;
}
@ -144,7 +160,10 @@ namespace ChocolArm64.Instruction
}
}
if (op.WBack) EmitSimdMemWBack(context, offset);
if (op.WBack)
{
EmitSimdMemWBack(context, offset);
}
}
private static void EmitSimdMemWBack(AILEmitterCtx context, int offset)
@ -154,9 +173,13 @@ namespace ChocolArm64.Instruction
context.EmitLdint(op.Rn);
if (op.Rm != AThreadState.ZrIndex)
{
context.EmitLdint(op.Rm);
}
else
{
context.EmitLdc_I8(offset);
}
context.Emit(OpCodes.Add);

View file

@ -32,7 +32,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -46,7 +49,10 @@ namespace ChocolArm64.Instruction
EmitVectorInsert(context, op.Rd, index, op.Size);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
}
@ -73,7 +79,10 @@ namespace ChocolArm64.Instruction
EmitVectorInsert(context, op.Rd, index, op.Size);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void Ext_V(AILEmitterCtx context)
@ -91,7 +100,10 @@ namespace ChocolArm64.Instruction
{
int reg = op.Imm4 + index < bytes ? op.Rn : op.Rm;
if (position == bytes) position = 0;
if (position == bytes)
{
position = 0;
}
EmitVectorExtractZx(context, reg, position++, 0);
EmitVectorInsertTmp(context, index, 0);
@ -100,7 +112,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void Fcsel_S(AILEmitterCtx context)
@ -200,7 +215,10 @@ namespace ChocolArm64.Instruction
EmitVectorInsert(context, op.Rd, index, op.Size + 2);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void Ins_Gp(AILEmitterCtx context)
@ -248,7 +266,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvec(op.Rm);
for (int index = 0; index < op.Size; index++) context.EmitLdvec((op.Rn + index) & 0x1f);
for (int index = 0; index < op.Size; index++)
{
context.EmitLdvec((op.Rn + index) & 0x1f);
}
switch (op.Size)
{
@ -324,7 +345,10 @@ namespace ChocolArm64.Instruction
//For XTN, first operand is source, second operand is 0.
//For XTN2, first operand is 0, second operand is source.
if (part != 0) EmitZeroVector();
if (part != 0)
{
EmitZeroVector();
}
EmitLdvecWithSignedCast(context, op.Rn, op.Size + 1);
@ -345,7 +369,10 @@ namespace ChocolArm64.Instruction
context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), wideTypes));
if (part == 0) EmitZeroVector();
if (part == 0)
{
EmitZeroVector();
}
//Pack values with signed saturation, the signed saturation shouldn't
//saturate anything since the upper bits were masked off.
@ -386,7 +413,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (part == 0) EmitVectorZeroUpper(context, op.Rd);
if (part == 0)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
}
@ -431,7 +461,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
private static void EmitVectorUnzip(AILEmitterCtx context, int part)
@ -455,7 +488,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
private static void EmitVectorZip(AILEmitterCtx context, int part)
@ -490,7 +526,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64 && part == 0) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64 && part == 0)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -513,7 +552,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
}
}

View file

@ -45,7 +45,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -101,7 +104,10 @@ namespace ChocolArm64.Instruction
EmitVectorInsert(context, op.Rd, index, op.Size);
}
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
public static void Sqrshrn_S(AILEmitterCtx context)
@ -182,7 +188,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithSignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -230,7 +239,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithSignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -271,7 +283,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithSignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -304,7 +319,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithSignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -369,7 +387,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -416,7 +437,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -456,7 +480,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -488,7 +515,10 @@ namespace ChocolArm64.Instruction
EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
if (op.RegisterSize == ARegisterSize.Simd64) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
else
{
@ -550,9 +580,13 @@ namespace ChocolArm64.Instruction
};
if (signed)
{
EmitVectorBinaryOpSx(context, emit);
}
else
{
EmitVectorBinaryOpZx(context, emit);
}
}
[Flags]
@ -642,7 +676,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64 || scalar) EmitVectorZeroUpper(context, op.Rd);
if (op.RegisterSize == ARegisterSize.Simd64 || scalar)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
private static void EmitVectorShrImmNarrowOpZx(AILEmitterCtx context, bool round)
@ -684,7 +721,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (part == 0) EmitVectorZeroUpper(context, op.Rd);
if (part == 0)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
[Flags]
@ -727,7 +767,10 @@ namespace ChocolArm64.Instruction
int part = !scalar && op.RegisterSize == ARegisterSize.Simd128 ? elems : 0;
if (scalar) EmitVectorZeroLowerTmp(context);
if (scalar)
{
EmitVectorZeroLowerTmp(context);
}
if (part != 0)
{
@ -765,7 +808,10 @@ namespace ChocolArm64.Instruction
context.EmitLdvectmp();
context.EmitStvec(op.Rd);
if (part == 0) EmitVectorZeroUpper(context, op.Rd);
if (part == 0)
{
EmitVectorZeroUpper(context, op.Rd);
}
}
// Dst_64 = (Int(Src_64, Signed) + RoundConst) >> Shift;

View file

@ -42,7 +42,9 @@ namespace ChocolArm64.Instruction
if (propInfo.PropertyType != typeof(long) &&
propInfo.PropertyType != typeof(ulong))
{
context.Emit(OpCodes.Conv_U8);
}
context.EmitStintzr(op.Rt);
}
@ -69,7 +71,9 @@ namespace ChocolArm64.Instruction
if (propInfo.PropertyType != typeof(long) &&
propInfo.PropertyType != typeof(ulong))
{
context.Emit(OpCodes.Conv_U4);
}
context.EmitCallPropSet(typeof(AThreadState), propName);
}

View file

@ -28,9 +28,13 @@ namespace ChocolArm64.Instruction
else /* if (Shift == 64) */
{
if (value < 0L)
{
return -1L;
}
else
{
return 0L;
}
}
}
else /* if (RoundConst == 1L << (Shift - 1)) */
@ -40,9 +44,13 @@ namespace ChocolArm64.Instruction
long add = value + roundConst;
if ((~value & (value ^ add)) < 0L)
{
return (long)((ulong)add >> shift);
}
else
{
return add >> shift;
}
}
else /* if (Shift == 64) */
{
@ -56,9 +64,13 @@ namespace ChocolArm64.Instruction
if (roundConst == 0L)
{
if (shift <= 63)
{
return value >> shift;
}
else /* if (Shift == 64) */
{
return 0UL;
}
}
else /* if (RoundConst == 1L << (Shift - 1)) */
{
@ -67,16 +79,24 @@ namespace ChocolArm64.Instruction
if (add < value && add < (ulong)roundConst)
{
if (shift <= 63)
{
return (add >> shift) | (0x8000000000000000UL >> (shift - 1));
}
else /* if (Shift == 64) */
{
return 1UL;
}
}
else
{
if (shift <= 63)
{
return add >> shift;
}
else /* if (Shift == 64) */
{
return 0UL;
}
}
}
}
@ -192,9 +212,13 @@ namespace ChocolArm64.Instruction
state.SetFpsrFlag(FPSR.Qc);
if (op1 < 0L)
{
return long.MinValue;
}
else
{
return long.MaxValue;
}
}
else
{
@ -227,9 +251,13 @@ namespace ChocolArm64.Instruction
state.SetFpsrFlag(FPSR.Qc);
if (op1 < 0L)
{
return long.MinValue;
}
else
{
return long.MaxValue;
}
}
else
{
@ -358,7 +386,12 @@ namespace ChocolArm64.Instruction
int highBit = size - 2;
for (int bit = highBit; bit >= 0; bit--)
if (((value >> bit) & 0b1) != 0) return (ulong)(highBit - bit);
{
if (((value >> bit) & 0b1) != 0)
{
return (ulong)(highBit - bit);
}
}
return (ulong)(size - 1);
}
@ -367,7 +400,10 @@ namespace ChocolArm64.Instruction
public static ulong CountLeadingZeros(ulong value, int size) // Size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
if (value == 0ul) return (ulong)size;
if (value == 0ul)
{
return (ulong)size;
}
int nibbleIdx = size;
int preCount, count = 0;
@ -385,7 +421,10 @@ namespace ChocolArm64.Instruction
public static ulong CountSetBits8(ulong value) // "Size" is 8 (SIMD&FP Inst.).
{
if (value == 0xfful) return 8ul;
if (value == 0xfful)
{
return 8ul;
}
value = ((value >> 1) & 0x55ul) + (value & 0x55ul);
value = ((value >> 2) & 0x33ul) + (value & 0x33ul);
@ -489,7 +528,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> Decrypt(Vector128<float> value, Vector128<float> roundKey)
{
if (!Sse.IsSupported) throw new PlatformNotSupportedException();
if (!Sse.IsSupported)
{
throw new PlatformNotSupportedException();
}
return ACryptoHelper.AesInvSubBytes(ACryptoHelper.AesInvShiftRows(Sse.Xor(value, roundKey)));
}
@ -497,7 +539,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> Encrypt(Vector128<float> value, Vector128<float> roundKey)
{
if (!Sse.IsSupported) throw new PlatformNotSupportedException();
if (!Sse.IsSupported)
{
throw new PlatformNotSupportedException();
}
return ACryptoHelper.AesSubBytes(ACryptoHelper.AesShiftRows(Sse.Xor(value, roundKey)));
}
@ -610,7 +655,10 @@ namespace ChocolArm64.Instruction
private static void Rol32_256(ref Vector128<float> y, ref Vector128<float> x)
{
if (!Sse2.IsSupported) throw new PlatformNotSupportedException();
if (!Sse2.IsSupported)
{
throw new PlatformNotSupportedException();
}
uint yE3 = (uint)VectorExtractIntZx(y, (byte)3, 2);
uint xE3 = (uint)VectorExtractIntZx(x, (byte)3, 2);
@ -726,15 +774,24 @@ namespace ChocolArm64.Instruction
{
value = ((value & 0xff00ff00ff00ff00) >> 8) | ((value & 0x00ff00ff00ff00ff) << 8);
if (size == RevSize.Rev16) return value;
if (size == RevSize.Rev16)
{
return value;
}
value = ((value & 0xffff0000ffff0000) >> 16) | ((value & 0x0000ffff0000ffff) << 16);
if (size == RevSize.Rev32) return value;
if (size == RevSize.Rev32)
{
return value;
}
value = ((value & 0xffffffff00000000) >> 32) | ((value & 0x00000000ffffffff) << 32);
if (size == RevSize.Rev64) return value;
if (size == RevSize.Rev64)
{
return value;
}
throw new ArgumentException(nameof(size));
}
@ -744,8 +801,15 @@ namespace ChocolArm64.Instruction
public static long SMulHi128(long lhs, long rhs)
{
long result = (long)UMulHi128((ulong)lhs, (ulong)rhs);
if (lhs < 0) result -= rhs;
if (rhs < 0) result -= lhs;
if (lhs < 0)
{
result -= rhs;
}
if (rhs < 0)
{
result -= lhs;
}
return result;
}

View file

@ -39,12 +39,20 @@ namespace ChocolArm64.Instruction
{
ulong a = index;
if (a < 256)
{
a = (a << 1) + 1;
}
else
{
a = (a | 1) << 1;
}
ulong b = 256;
while (a * (b + 1) * (b + 1) < 1ul << 28) b++;
while (a * (b + 1) * (b + 1) < 1ul << 28)
{
b++;
}
b = (b + 1) >> 1;
table[index] = (byte)(b & 0xFF);
@ -67,7 +75,10 @@ namespace ChocolArm64.Instruction
if (xExp >= 2045)
{
if (xExp == 0x7ff && scaled != 0) return BitConverter.Int64BitsToDouble((long)(xBits | 0x0008000000000000));
if (xExp == 0x7ff && scaled != 0)
{
return BitConverter.Int64BitsToDouble((long)(xBits | 0x0008000000000000));
}
// Infinity, or Out of range -> Zero
return BitConverter.Int64BitsToDouble((long)xSign);
@ -75,7 +86,10 @@ namespace ChocolArm64.Instruction
if (xExp == 0)
{
if (scaled == 0) return BitConverter.Int64BitsToDouble((long)(xSign | 0x7FF0000000000000));
if (scaled == 0)
{
return BitConverter.Int64BitsToDouble((long)(xSign | 0x7FF0000000000000));
}
// Denormal
if ((scaled & (1ul << 51)) == 0)
@ -125,11 +139,17 @@ namespace ChocolArm64.Instruction
long xExp = (long)((xBits >> 52) & 0x7FF);
ulong scaled = xBits & ((1ul << 52) - 1);
if (xExp == 0x7FF && scaled != 0) return BitConverter.Int64BitsToDouble((long)(xBits | 0x0008000000000000));
if (xExp == 0x7FF && scaled != 0)
{
return BitConverter.Int64BitsToDouble((long)(xBits | 0x0008000000000000));
}
if (xExp == 0)
{
if (scaled == 0) return BitConverter.Int64BitsToDouble((long)(xSign | 0x7FF0000000000000));
if (scaled == 0)
{
return BitConverter.Int64BitsToDouble((long)(xSign | 0x7FF0000000000000));
}
// Denormal
while ((scaled & (1 << 51)) == 0)
@ -140,9 +160,15 @@ namespace ChocolArm64.Instruction
scaled <<= 1;
}
if (xSign != 0) return BitConverter.Int64BitsToDouble((long)0x7FF8000000000000);
if (xSign != 0)
{
return BitConverter.Int64BitsToDouble((long)0x7FF8000000000000);
}
if (xExp == 0x7ff && scaled == 0) return BitConverter.Int64BitsToDouble((long)xSign);
if (xExp == 0x7ff && scaled == 0)
{
return BitConverter.Int64BitsToDouble((long)xSign);
}
if (((ulong)xExp & 1) == 1)
{
@ -179,11 +205,18 @@ namespace ChocolArm64.Instruction
if (type == FPType.SnaN || type == FPType.QnaN)
{
if (state.GetFpcrFlag(FPCR.Dn))
{
result = FpDefaultNaN();
}
else
{
result = FpConvertNaN(valueBits);
}
if (type == FPType.SnaN) FpProcessException(FPExc.InvalidOp, state);
if (type == FPType.SnaN)
{
FpProcessException(FPExc.InvalidOp, state);
}
}
else if (type == FPType.Infinity)
{
@ -309,12 +342,18 @@ namespace ChocolArm64.Instruction
uint biasedExp = (uint)Math.Max(exponent - minimumExp + 1, 0);
if (biasedExp == 0u) mantissa /= Math.Pow(2d, minimumExp - exponent);
if (biasedExp == 0u)
{
mantissa /= Math.Pow(2d, minimumExp - exponent);
}
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, f));
double error = mantissa * Math.Pow(2d, f) - (double)intMant;
if (biasedExp == 0u && (error != 0d || state.GetFpcrFlag(FPCR.Ufe))) FpProcessException(FPExc.Underflow, state);
if (biasedExp == 0u && (error != 0d || state.GetFpcrFlag(FPCR.Ufe)))
{
FpProcessException(FPExc.Underflow, state);
}
bool overflowToInf;
bool roundUp;
@ -347,7 +386,10 @@ namespace ChocolArm64.Instruction
{
intMant++;
if (intMant == (uint)Math.Pow(2d, f)) biasedExp = 1u;
if (intMant == (uint)Math.Pow(2d, f))
{
biasedExp = 1u;
}
if (intMant == (uint)Math.Pow(2d, f + 1))
{
@ -372,7 +414,10 @@ namespace ChocolArm64.Instruction
(int)(((sign ? 1u : 0u) << 31) | ((biasedExp & 0xFFu) << 23) | (intMant & 0x007FFFFFu)));
}
if (error != 0d) FpProcessException(FPExc.Inexact, state);
if (error != 0d)
{
FpProcessException(FPExc.Inexact, state);
}
return result;
}
@ -388,9 +433,13 @@ namespace ChocolArm64.Instruction
int enable = (int)exc + 8;
if ((state.Fpcr & (1 << enable)) != 0)
{
throw new NotImplementedException("floating-point trap handling");
}
else
{
state.Fpsr |= 1 << (int)exc;
}
}
}
@ -409,13 +458,22 @@ namespace ChocolArm64.Instruction
if (type == FPType.SnaN || type == FPType.QnaN)
{
if (altHp)
{
resultBits = FpZero(sign);
}
else if (state.GetFpcrFlag(FPCR.Dn))
{
resultBits = FpDefaultNaN();
}
else
{
resultBits = FpConvertNaN(valueBits);
}
if (type == FPType.SnaN || altHp) FpProcessException(FPExc.InvalidOp, state);
if (type == FPType.SnaN || altHp)
{
FpProcessException(FPExc.InvalidOp, state);
}
}
else if (type == FPType.Infinity)
{
@ -480,7 +538,10 @@ namespace ChocolArm64.Instruction
type = FPType.Zero;
real = 0d;
if (frac32 != 0u) FpProcessException(FPExc.InputDenorm, state);
if (frac32 != 0u)
{
FpProcessException(FPExc.InputDenorm, state);
}
}
else
{
@ -547,12 +608,18 @@ namespace ChocolArm64.Instruction
uint biasedExp = (uint)Math.Max(exponent - minimumExp + 1, 0);
if (biasedExp == 0u) mantissa /= Math.Pow(2d, minimumExp - exponent);
if (biasedExp == 0u)
{
mantissa /= Math.Pow(2d, minimumExp - exponent);
}
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, f));
double error = mantissa * Math.Pow(2d, f) - (double)intMant;
if (biasedExp == 0u && (error != 0d || state.GetFpcrFlag(FPCR.Ufe))) FpProcessException(FPExc.Underflow, state);
if (biasedExp == 0u && (error != 0d || state.GetFpcrFlag(FPCR.Ufe)))
{
FpProcessException(FPExc.Underflow, state);
}
bool overflowToInf;
bool roundUp;
@ -585,7 +652,10 @@ namespace ChocolArm64.Instruction
{
intMant++;
if (intMant == (uint)Math.Pow(2d, f)) biasedExp = 1u;
if (intMant == (uint)Math.Pow(2d, f))
{
biasedExp = 1u;
}
if (intMant == (uint)Math.Pow(2d, f + 1))
{
@ -627,7 +697,10 @@ namespace ChocolArm64.Instruction
}
}
if (error != 0d) FpProcessException(FPExc.Inexact, state);
if (error != 0d)
{
FpProcessException(FPExc.Inexact, state);
}
return resultBits;
}
@ -642,9 +715,13 @@ namespace ChocolArm64.Instruction
int enable = (int)exc + 8;
if ((state.Fpcr & (1 << enable)) != 0)
{
throw new NotImplementedException("floating-point trap handling");
}
else
{
state.Fpsr |= 1 << (int)exc;
}
}
}
@ -715,7 +792,10 @@ namespace ChocolArm64.Instruction
{
result = FpInfinity(sign1 ^ sign2);
if (!inf1) FpProcessException(FPExc.DivideByZero, state);
if (!inf1)
{
FpProcessException(FPExc.DivideByZero, state);
}
}
else if (zero1 || inf2)
{
@ -744,20 +824,32 @@ namespace ChocolArm64.Instruction
if (value1 > value2)
{
if (type1 == FPType.Infinity)
{
result = FpInfinity(sign1);
}
else if (type1 == FPType.Zero)
{
result = FpZero(sign1 && sign2);
}
else
{
result = value1;
}
}
else
{
if (type2 == FPType.Infinity)
{
result = FpInfinity(sign2);
}
else if (type2 == FPType.Zero)
{
result = FpZero(sign1 && sign2);
}
else
{
result = value2;
}
}
}
@ -772,8 +864,13 @@ namespace ChocolArm64.Instruction
value2.FpUnpack(out FPType type2, out _, out _);
if (type1 == FPType.QnaN && type2 != FPType.QnaN)
{
value1 = FpInfinity(true);
else if (type1 != FPType.QnaN && type2 == FPType.QnaN) value2 = FpInfinity(true);
}
else if (type1 != FPType.QnaN && type2 == FPType.QnaN)
{
value2 = FpInfinity(true);
}
return FpMax(value1, value2, state);
}
@ -792,20 +889,32 @@ namespace ChocolArm64.Instruction
if (value1 < value2)
{
if (type1 == FPType.Infinity)
{
result = FpInfinity(sign1);
}
else if (type1 == FPType.Zero)
{
result = FpZero(sign1 || sign2);
}
else
{
result = value1;
}
}
else
{
if (type2 == FPType.Infinity)
{
result = FpInfinity(sign2);
}
else if (type2 == FPType.Zero)
{
result = FpZero(sign1 || sign2);
}
else
{
result = value2;
}
}
}
@ -820,8 +929,13 @@ namespace ChocolArm64.Instruction
value2.FpUnpack(out FPType type2, out _, out _);
if (type1 == FPType.QnaN && type2 != FPType.QnaN)
{
value1 = FpInfinity(false);
else if (type1 != FPType.QnaN && type2 == FPType.QnaN) value2 = FpInfinity(false);
}
else if (type1 != FPType.QnaN && type2 == FPType.QnaN)
{
value2 = FpInfinity(false);
}
return FpMin(value1, value2, state);
}
@ -946,13 +1060,21 @@ namespace ChocolArm64.Instruction
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
if (inf1 && zero2 || zero1 && inf2)
{
result = FpTwo(sign1 ^ sign2);
}
else if (inf1 || inf2)
{
result = FpInfinity(sign1 ^ sign2);
}
else if (zero1 || zero2)
{
result = FpZero(sign1 ^ sign2);
}
else
{
result = value1 * value2;
}
}
return result;
@ -975,11 +1097,17 @@ namespace ChocolArm64.Instruction
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
if (inf1 && zero2 || zero1 && inf2)
{
result = FpTwo(false);
}
else if (inf1 || inf2)
{
result = FpInfinity(sign1 ^ sign2);
}
else
{
result = 2f + value1 * value2;
}
}
return result;
@ -1026,11 +1154,17 @@ namespace ChocolArm64.Instruction
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
if (inf1 && zero2 || zero1 && inf2)
{
result = FpOnePointFive(false);
}
else if (inf1 || inf2)
{
result = FpInfinity(sign1 ^ sign2);
}
else
{
result = (3f + value1 * value2) / 2f;
}
}
return result;
@ -1150,9 +1284,13 @@ namespace ChocolArm64.Instruction
if ((valueBits & 0x7F800000u) == 0u)
{
if ((valueBits & 0x007FFFFFu) == 0u)
{
type = FPType.Zero;
}
else
{
type = FPType.Nonzero;
}
}
else if ((~valueBits & 0x7F800000u) == 0u)
{
@ -1188,12 +1326,21 @@ namespace ChocolArm64.Instruction
done = true;
if (type1 == FPType.SnaN)
{
return FpProcessNaN(type1, op1, state);
}
else if (type2 == FPType.SnaN)
{
return FpProcessNaN(type2, op2, state);
}
else if (type1 == FPType.QnaN)
{
return FpProcessNaN(type1, op1, state);
else if (type2 == FPType.QnaN) return FpProcessNaN(type2, op2, state);
}
else if (type2 == FPType.QnaN)
{
return FpProcessNaN(type2, op2, state);
}
done = false;
@ -1213,16 +1360,29 @@ namespace ChocolArm64.Instruction
done = true;
if (type1 == FPType.SnaN)
{
return FpProcessNaN(type1, op1, state);
}
else if (type2 == FPType.SnaN)
{
return FpProcessNaN(type2, op2, state);
}
else if (type3 == FPType.SnaN)
{
return FpProcessNaN(type3, op3, state);
}
else if (type1 == FPType.QnaN)
{
return FpProcessNaN(type1, op1, state);
}
else if (type2 == FPType.QnaN)
{
return FpProcessNaN(type2, op2, state);
else if (type3 == FPType.QnaN) return FpProcessNaN(type3, op3, state);
}
else if (type3 == FPType.QnaN)
{
return FpProcessNaN(type3, op3, state);
}
done = false;
@ -1238,7 +1398,10 @@ namespace ChocolArm64.Instruction
FpProcessException(FPExc.InvalidOp, state);
}
if (state.GetFpcrFlag(FPCR.Dn)) return FpDefaultNaN();
if (state.GetFpcrFlag(FPCR.Dn))
{
return FpDefaultNaN();
}
return BitConverter.Int32BitsToSingle((int)op);
}
@ -1248,9 +1411,13 @@ namespace ChocolArm64.Instruction
int enable = (int)exc + 8;
if ((state.Fpcr & (1 << enable)) != 0)
{
throw new NotImplementedException("floating-point trap handling");
}
else
{
state.Fpsr |= 1 << (int)exc;
}
}
}
@ -1321,7 +1488,10 @@ namespace ChocolArm64.Instruction
{
result = FpInfinity(sign1 ^ sign2);
if (!inf1) FpProcessException(FPExc.DivideByZero, state);
if (!inf1)
{
FpProcessException(FPExc.DivideByZero, state);
}
}
else if (zero1 || inf2)
{
@ -1350,20 +1520,32 @@ namespace ChocolArm64.Instruction
if (value1 > value2)
{
if (type1 == FPType.Infinity)
{
result = FpInfinity(sign1);
}
else if (type1 == FPType.Zero)
{
result = FpZero(sign1 && sign2);
}
else
{
result = value1;
}
}
else
{
if (type2 == FPType.Infinity)
{
result = FpInfinity(sign2);
}
else if (type2 == FPType.Zero)
{
result = FpZero(sign1 && sign2);
}
else
{
result = value2;
}
}
}
@ -1378,8 +1560,13 @@ namespace ChocolArm64.Instruction
value2.FpUnpack(out FPType type2, out _, out _);
if (type1 == FPType.QnaN && type2 != FPType.QnaN)
{
value1 = FpInfinity(true);
else if (type1 != FPType.QnaN && type2 == FPType.QnaN) value2 = FpInfinity(true);
}
else if (type1 != FPType.QnaN && type2 == FPType.QnaN)
{
value2 = FpInfinity(true);
}
return FpMax(value1, value2, state);
}
@ -1398,20 +1585,32 @@ namespace ChocolArm64.Instruction
if (value1 < value2)
{
if (type1 == FPType.Infinity)
{
result = FpInfinity(sign1);
}
else if (type1 == FPType.Zero)
{
result = FpZero(sign1 || sign2);
}
else
{
result = value1;
}
}
else
{
if (type2 == FPType.Infinity)
{
result = FpInfinity(sign2);
}
else if (type2 == FPType.Zero)
{
result = FpZero(sign1 || sign2);
}
else
{
result = value2;
}
}
}
@ -1426,8 +1625,13 @@ namespace ChocolArm64.Instruction
value2.FpUnpack(out FPType type2, out _, out _);
if (type1 == FPType.QnaN && type2 != FPType.QnaN)
{
value1 = FpInfinity(false);
else if (type1 != FPType.QnaN && type2 == FPType.QnaN) value2 = FpInfinity(false);
}
else if (type1 != FPType.QnaN && type2 == FPType.QnaN)
{
value2 = FpInfinity(false);
}
return FpMin(value1, value2, state);
}
@ -1552,13 +1756,21 @@ namespace ChocolArm64.Instruction
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
if (inf1 && zero2 || zero1 && inf2)
{
result = FpTwo(sign1 ^ sign2);
}
else if (inf1 || inf2)
{
result = FpInfinity(sign1 ^ sign2);
}
else if (zero1 || zero2)
{
result = FpZero(sign1 ^ sign2);
}
else
{
result = value1 * value2;
}
}
return result;
@ -1581,11 +1793,17 @@ namespace ChocolArm64.Instruction
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
if (inf1 && zero2 || zero1 && inf2)
{
result = FpTwo(false);
}
else if (inf1 || inf2)
{
result = FpInfinity(sign1 ^ sign2);
}
else
{
result = 2d + value1 * value2;
}
}
return result;
@ -1632,11 +1850,17 @@ namespace ChocolArm64.Instruction
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
if (inf1 && zero2 || zero1 && inf2)
{
result = FpOnePointFive(false);
}
else if (inf1 || inf2)
{
result = FpInfinity(sign1 ^ sign2);
}
else
{
result = (3d + value1 * value2) / 2d;
}
}
return result;
@ -1756,9 +1980,13 @@ namespace ChocolArm64.Instruction
if ((valueBits & 0x7FF0000000000000ul) == 0ul)
{
if ((valueBits & 0x000FFFFFFFFFFFFFul) == 0ul)
{
type = FPType.Zero;
}
else
{
type = FPType.Nonzero;
}
}
else if ((~valueBits & 0x7FF0000000000000ul) == 0ul)
{
@ -1794,12 +2022,21 @@ namespace ChocolArm64.Instruction
done = true;
if (type1 == FPType.SnaN)
{
return FpProcessNaN(type1, op1, state);
}
else if (type2 == FPType.SnaN)
{
return FpProcessNaN(type2, op2, state);
}
else if (type1 == FPType.QnaN)
{
return FpProcessNaN(type1, op1, state);
else if (type2 == FPType.QnaN) return FpProcessNaN(type2, op2, state);
}
else if (type2 == FPType.QnaN)
{
return FpProcessNaN(type2, op2, state);
}
done = false;
@ -1819,16 +2056,29 @@ namespace ChocolArm64.Instruction
done = true;
if (type1 == FPType.SnaN)
{
return FpProcessNaN(type1, op1, state);
}
else if (type2 == FPType.SnaN)
{
return FpProcessNaN(type2, op2, state);
}
else if (type3 == FPType.SnaN)
{
return FpProcessNaN(type3, op3, state);
}
else if (type1 == FPType.QnaN)
{
return FpProcessNaN(type1, op1, state);
}
else if (type2 == FPType.QnaN)
{
return FpProcessNaN(type2, op2, state);
else if (type3 == FPType.QnaN) return FpProcessNaN(type3, op3, state);
}
else if (type3 == FPType.QnaN)
{
return FpProcessNaN(type3, op3, state);
}
done = false;
@ -1844,7 +2094,10 @@ namespace ChocolArm64.Instruction
FpProcessException(FPExc.InvalidOp, state);
}
if (state.GetFpcrFlag(FPCR.Dn)) return FpDefaultNaN();
if (state.GetFpcrFlag(FPCR.Dn))
{
return FpDefaultNaN();
}
return BitConverter.Int64BitsToDouble((long)op);
}
@ -1854,9 +2107,13 @@ namespace ChocolArm64.Instruction
int enable = (int)exc + 8;
if ((state.Fpcr & (1 << enable)) != 0)
{
throw new NotImplementedException("floating-point trap handling");
}
else
{
state.Fpsr |= 1 << (int)exc;
}
}
}
}

View file

@ -13,7 +13,10 @@ namespace ChocolArm64.Instruction
static AVectorHelper()
{
if (!Sse2.IsSupported) throw new PlatformNotSupportedException();
if (!Sse2.IsSupported)
{
throw new PlatformNotSupportedException();
}
_zero32_128Mask = Sse.StaticCast<uint, float>(Sse2.SetVector128(0, 0, 0, 0xffffffff));
}
@ -33,7 +36,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int SatF32ToS32(float value)
{
if (float.IsNaN(value)) return 0;
if (float.IsNaN(value))
{
return 0;
}
return value > int.MaxValue ? int.MaxValue :
value < int.MinValue ? int.MinValue : (int)value;
@ -42,7 +48,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long SatF32ToS64(float value)
{
if (float.IsNaN(value)) return 0;
if (float.IsNaN(value))
{
return 0;
}
return value > long.MaxValue ? long.MaxValue :
value < long.MinValue ? long.MinValue : (long)value;
@ -51,7 +60,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint SatF32ToU32(float value)
{
if (float.IsNaN(value)) return 0;
if (float.IsNaN(value))
{
return 0;
}
return value > uint.MaxValue ? uint.MaxValue :
value < uint.MinValue ? uint.MinValue : (uint)value;
@ -60,7 +72,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong SatF32ToU64(float value)
{
if (float.IsNaN(value)) return 0;
if (float.IsNaN(value))
{
return 0;
}
return value > ulong.MaxValue ? ulong.MaxValue :
value < ulong.MinValue ? ulong.MinValue : (ulong)value;
@ -69,7 +84,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int SatF64ToS32(double value)
{
if (double.IsNaN(value)) return 0;
if (double.IsNaN(value))
{
return 0;
}
return value > int.MaxValue ? int.MaxValue :
value < int.MinValue ? int.MinValue : (int)value;
@ -78,7 +96,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long SatF64ToS64(double value)
{
if (double.IsNaN(value)) return 0;
if (double.IsNaN(value))
{
return 0;
}
return value > long.MaxValue ? long.MaxValue :
value < long.MinValue ? long.MinValue : (long)value;
@ -87,7 +108,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint SatF64ToU32(double value)
{
if (double.IsNaN(value)) return 0;
if (double.IsNaN(value))
{
return 0;
}
return value > uint.MaxValue ? uint.MaxValue :
value < uint.MinValue ? uint.MinValue : (uint)value;
@ -96,7 +120,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong SatF64ToU64(double value)
{
if (double.IsNaN(value)) return 0;
if (double.IsNaN(value))
{
return 0;
}
return value > ulong.MaxValue ? ulong.MaxValue :
value < ulong.MinValue ? ulong.MinValue : (ulong)value;
@ -203,14 +230,21 @@ namespace ChocolArm64.Instruction
byte[] table = new byte[tb.Length * 16];
for (byte index = 0; index < tb.Length; index++)
for (byte index2 = 0; index2 < 16; index2++)
table[index * 16 + index2] = (byte)VectorExtractIntZx(tb[index], index2, 0);
{
for (byte index2 = 0; index2 < 16; index2++)
{
table[index * 16 + index2] = (byte)VectorExtractIntZx(tb[index], index2, 0);
}
}
for (byte index = 0; index < bytes; index++)
{
byte tblIdx = (byte)VectorExtractIntZx(vector, index, 0);
if (tblIdx < table.Length) res = VectorInsertInt(table[tblIdx], res, index, 0);
if (tblIdx < table.Length)
{
res = VectorInsertInt(table[tblIdx], res, index, 0);
}
}
return res;
@ -220,8 +254,13 @@ namespace ChocolArm64.Instruction
public static double VectorExtractDouble(Vector128<float> vector, byte index)
{
if (Sse41.IsSupported)
{
return BitConverter.Int64BitsToDouble(Sse41.Extract(Sse.StaticCast<float, long>(vector), index));
else if (Sse2.IsSupported) return BitConverter.Int64BitsToDouble((long)VectorExtractIntZx(vector, index, 3));
}
else if (Sse2.IsSupported)
{
return BitConverter.Int64BitsToDouble((long)VectorExtractIntZx(vector, index, 3));
}
throw new PlatformNotSupportedException();
}
@ -232,28 +271,48 @@ namespace ChocolArm64.Instruction
if (Sse41.IsSupported)
{
if (size == 0)
{
return (sbyte)Sse41.Extract(Sse.StaticCast<float, byte>(vector), index);
}
else if (size == 1)
{
return (short)Sse2.Extract(Sse.StaticCast<float, ushort>(vector), index);
}
else if (size == 2)
{
return Sse41.Extract(Sse.StaticCast<float, int>(vector), index);
}
else if (size == 3)
{
return Sse41.Extract(Sse.StaticCast<float, long>(vector), index);
}
else
{
throw new ArgumentOutOfRangeException(nameof(size));
}
}
else if (Sse2.IsSupported)
{
if (size == 0)
{
return (sbyte)VectorExtractIntZx(vector, index, size);
}
else if (size == 1)
{
return (short)VectorExtractIntZx(vector, index, size);
}
else if (size == 2)
{
return (int)VectorExtractIntZx(vector, index, size);
}
else if (size == 3)
{
return (long)VectorExtractIntZx(vector, index, size);
}
else
{
throw new ArgumentOutOfRangeException(nameof(size));
}
}
throw new PlatformNotSupportedException();
@ -265,15 +324,25 @@ namespace ChocolArm64.Instruction
if (Sse41.IsSupported)
{
if (size == 0)
{
return Sse41.Extract(Sse.StaticCast<float, byte>(vector), index);
}
else if (size == 1)
{
return Sse2.Extract(Sse.StaticCast<float, ushort>(vector), index);
}
else if (size == 2)
{
return Sse41.Extract(Sse.StaticCast<float, uint>(vector), index);
}
else if (size == 3)
{
return Sse41.Extract(Sse.StaticCast<float, ulong>(vector), index);
}
else
{
throw new ArgumentOutOfRangeException(nameof(size));
}
}
else if (Sse2.IsSupported)
{
@ -295,7 +364,10 @@ namespace ChocolArm64.Instruction
{
ushort value1 = Sse2.Extract(Sse.StaticCast<float, ushort>(vector), (byte)(shortIdx + 1));
if (size == 2) return (uint)(value | (value1 << 16));
if (size == 2)
{
return (uint)(value | (value1 << 16));
}
ushort value2 = Sse2.Extract(Sse.StaticCast<float, ushort>(vector), (byte)(shortIdx + 2));
ushort value3 = Sse2.Extract(Sse.StaticCast<float, ushort>(vector), (byte)(shortIdx + 3));
@ -346,15 +418,25 @@ namespace ChocolArm64.Instruction
if (Sse41.IsSupported)
{
if (size == 0)
{
return Sse.StaticCast<byte, float>(Sse41.Insert(Sse.StaticCast<float, byte>(vector), (byte)value, index));
}
else if (size == 1)
{
return Sse.StaticCast<ushort, float>(Sse2.Insert(Sse.StaticCast<float, ushort>(vector), (ushort)value, index));
}
else if (size == 2)
{
return Sse.StaticCast<uint, float>(Sse41.Insert(Sse.StaticCast<float, uint>(vector), (uint)value, index));
}
else if (size == 3)
{
return Sse.StaticCast<ulong, float>(Sse41.Insert(Sse.StaticCast<float, ulong>(vector), value, index));
}
else
{
throw new ArgumentOutOfRangeException(nameof(size));
}
}
else if (Sse2.IsSupported)
{
@ -411,15 +493,25 @@ namespace ChocolArm64.Instruction
//produce a single INSERTPS instruction instead of the
//jump table fallback.
if (index == 0)
{
return Sse41.Insert(vector, value, 0x00);
}
else if (index == 1)
{
return Sse41.Insert(vector, value, 0x10);
}
else if (index == 2)
{
return Sse41.Insert(vector, value, 0x20);
}
else if (index == 3)
{
return Sse41.Insert(vector, value, 0x30);
}
else
{
throw new ArgumentOutOfRangeException(nameof(index));
}
}
else if (Sse2.IsSupported)
{
@ -449,7 +541,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<sbyte> VectorSByteZero()
{
if (Sse2.IsSupported) return Sse2.SetZeroVector128<sbyte>();
if (Sse2.IsSupported)
{
return Sse2.SetZeroVector128<sbyte>();
}
throw new PlatformNotSupportedException();
}
@ -457,7 +552,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<short> VectorInt16Zero()
{
if (Sse2.IsSupported) return Sse2.SetZeroVector128<short>();
if (Sse2.IsSupported)
{
return Sse2.SetZeroVector128<short>();
}
throw new PlatformNotSupportedException();
}
@ -465,7 +563,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<int> VectorInt32Zero()
{
if (Sse2.IsSupported) return Sse2.SetZeroVector128<int>();
if (Sse2.IsSupported)
{
return Sse2.SetZeroVector128<int>();
}
throw new PlatformNotSupportedException();
}
@ -473,7 +574,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<long> VectorInt64Zero()
{
if (Sse2.IsSupported) return Sse2.SetZeroVector128<long>();
if (Sse2.IsSupported)
{
return Sse2.SetZeroVector128<long>();
}
throw new PlatformNotSupportedException();
}
@ -481,7 +585,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> VectorSingleZero()
{
if (Sse.IsSupported) return Sse.SetZeroVector128();
if (Sse.IsSupported)
{
return Sse.SetZeroVector128();
}
throw new PlatformNotSupportedException();
}
@ -489,7 +596,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<double> VectorDoubleZero()
{
if (Sse2.IsSupported) return Sse2.SetZeroVector128<double>();
if (Sse2.IsSupported)
{
return Sse2.SetZeroVector128<double>();
}
throw new PlatformNotSupportedException();
}
@ -497,7 +607,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> VectorZero32_128(Vector128<float> vector)
{
if (Sse.IsSupported) return Sse.And(vector, _zero32_128Mask);
if (Sse.IsSupported)
{
return Sse.And(vector, _zero32_128Mask);
}
throw new PlatformNotSupportedException();
}
@ -505,7 +618,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<sbyte> VectorSingleToSByte(Vector128<float> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<float, sbyte>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<float, sbyte>(vector);
}
throw new PlatformNotSupportedException();
}
@ -513,7 +629,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<short> VectorSingleToInt16(Vector128<float> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<float, short>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<float, short>(vector);
}
throw new PlatformNotSupportedException();
}
@ -521,7 +640,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<int> VectorSingleToInt32(Vector128<float> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<float, int>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<float, int>(vector);
}
throw new PlatformNotSupportedException();
}
@ -529,7 +651,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<long> VectorSingleToInt64(Vector128<float> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<float, long>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<float, long>(vector);
}
throw new PlatformNotSupportedException();
}
@ -537,7 +662,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<byte> VectorSingleToByte(Vector128<float> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<float, byte>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<float, byte>(vector);
}
throw new PlatformNotSupportedException();
}
@ -545,7 +673,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<ushort> VectorSingleToUInt16(Vector128<float> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<float, ushort>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<float, ushort>(vector);
}
throw new PlatformNotSupportedException();
}
@ -553,7 +684,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<uint> VectorSingleToUInt32(Vector128<float> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<float, uint>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<float, uint>(vector);
}
throw new PlatformNotSupportedException();
}
@ -561,7 +695,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<ulong> VectorSingleToUInt64(Vector128<float> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<float, ulong>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<float, ulong>(vector);
}
throw new PlatformNotSupportedException();
}
@ -569,7 +706,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<double> VectorSingleToDouble(Vector128<float> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<float, double>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<float, double>(vector);
}
throw new PlatformNotSupportedException();
}
@ -577,7 +717,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> VectorSByteToSingle(Vector128<sbyte> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<sbyte, float>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<sbyte, float>(vector);
}
throw new PlatformNotSupportedException();
}
@ -585,7 +728,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> VectorInt16ToSingle(Vector128<short> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<short, float>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<short, float>(vector);
}
throw new PlatformNotSupportedException();
}
@ -593,7 +739,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> VectorInt32ToSingle(Vector128<int> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<int, float>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<int, float>(vector);
}
throw new PlatformNotSupportedException();
}
@ -601,7 +750,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> VectorInt64ToSingle(Vector128<long> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<long, float>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<long, float>(vector);
}
throw new PlatformNotSupportedException();
}
@ -609,7 +761,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> VectorByteToSingle(Vector128<byte> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<byte, float>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<byte, float>(vector);
}
throw new PlatformNotSupportedException();
}
@ -617,7 +772,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> VectorUInt16ToSingle(Vector128<ushort> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<ushort, float>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<ushort, float>(vector);
}
throw new PlatformNotSupportedException();
}
@ -625,7 +783,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> VectorUInt32ToSingle(Vector128<uint> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<uint, float>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<uint, float>(vector);
}
throw new PlatformNotSupportedException();
}
@ -633,7 +794,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> VectorUInt64ToSingle(Vector128<ulong> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<ulong, float>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<ulong, float>(vector);
}
throw new PlatformNotSupportedException();
}
@ -641,7 +805,10 @@ namespace ChocolArm64.Instruction
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> VectorDoubleToSingle(Vector128<double> vector)
{
if (Sse.IsSupported) return Sse.StaticCast<double, float>(vector);
if (Sse.IsSupported)
{
return Sse.StaticCast<double, float>(vector);
}
throw new PlatformNotSupportedException();
}

View file

@ -13,7 +13,10 @@ namespace ChocolArm64.Instruction32
{
A32OpCodeBImmAl op = (A32OpCodeBImmAl)opCode;
if (IsConditionTrue(state, op.Cond)) BranchWritePc(state, GetPc(state) + (uint)op.Imm);
if (IsConditionTrue(state, op.Cond))
{
BranchWritePc(state, GetPc(state) + (uint)op.Imm);
}
}
public static void Bl(AThreadState state, AMemory memory, AOpCode opCode)
@ -35,13 +38,23 @@ namespace ChocolArm64.Instruction32
uint pc = GetPc(state);
if (state.Thumb)
{
state.R14 = pc | 1;
}
else
{
state.R14 = pc - 4U;
}
if (x) state.Thumb = !state.Thumb;
if (x)
{
state.Thumb = !state.Thumb;
}
if (!state.Thumb) pc &= ~3U;
if (!state.Thumb)
{
pc &= ~3U;
}
BranchWritePc(state, pc + (uint)op.Imm);
}

View file

@ -31,7 +31,10 @@ namespace ChocolArm64.Instruction32
public static unsafe uint GetReg(AThreadState state, int reg)
{
if ((uint)reg > 15) throw new ArgumentOutOfRangeException(nameof(reg));
if ((uint)reg > 15)
{
throw new ArgumentOutOfRangeException(nameof(reg));
}
fixed (uint* ptr = &state.R0)
{
@ -41,7 +44,10 @@ namespace ChocolArm64.Instruction32
public static unsafe void SetReg(AThreadState state, int reg, uint value)
{
if ((uint)reg > 15) throw new ArgumentOutOfRangeException(nameof(reg));
if ((uint)reg > 15)
{
throw new ArgumentOutOfRangeException(nameof(reg));
}
fixed (uint* ptr = &state.R0)
{

View file

@ -66,7 +66,10 @@ namespace ChocolArm64.Memory
_pageTable = (byte***)Marshal.AllocHGlobal(PtLvl0Size * IntPtr.Size);
for (int l0 = 0; l0 < PtLvl0Size; l0++) _pageTable[l0] = null;
for (int l0 = 0; l0 < PtLvl0Size; l0++)
{
_pageTable[l0] = null;
}
}
public void RemoveMonitor(int core)
@ -86,7 +89,12 @@ namespace ChocolArm64.Memory
lock (_monitors)
{
foreach (ArmMonitor mon in _monitors.Values)
if (mon.Position == position && mon.ExState) mon.ExState = false;
{
if (mon.Position == position && mon.ExState)
{
mon.ExState = false;
}
}
if (!_monitors.TryGetValue(core, out ArmMonitor threadMon))
{
@ -108,18 +116,27 @@ namespace ChocolArm64.Memory
Monitor.Enter(_monitors);
if (!_monitors.TryGetValue(core, out ArmMonitor threadMon)) return false;
if (!_monitors.TryGetValue(core, out ArmMonitor threadMon))
{
return false;
}
bool exState = threadMon.HasExclusiveAccess(position);
if (!exState) Monitor.Exit(_monitors);
if (!exState)
{
Monitor.Exit(_monitors);
}
return exState;
}
public void ClearExclusiveForStore(int core)
{
if (_monitors.TryGetValue(core, out ArmMonitor threadMon)) threadMon.ExState = false;
if (_monitors.TryGetValue(core, out ArmMonitor threadMon))
{
threadMon.ExState = false;
}
Monitor.Exit(_monitors);
}
@ -128,7 +145,10 @@ namespace ChocolArm64.Memory
{
lock (_monitors)
{
if (_monitors.TryGetValue(core, out ArmMonitor threadMon)) threadMon.ExState = false;
if (_monitors.TryGetValue(core, out ArmMonitor threadMon))
{
threadMon.ExState = false;
}
}
}
@ -139,7 +159,12 @@ namespace ChocolArm64.Memory
lock (_monitors)
{
foreach (ArmMonitor mon in _monitors.Values)
if (mon.Position == maskedPosition && mon.ExState) mon.ExState = false;
{
if (mon.Position == maskedPosition && mon.ExState)
{
mon.ExState = false;
}
}
WriteInt32(position, value);
}
@ -188,50 +213,73 @@ namespace ChocolArm64.Memory
public Vector128<float> ReadVector8(long position)
{
if (Sse2.IsSupported)
{
return Sse.StaticCast<byte, float>(Sse2.SetVector128(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ReadByte(position)));
}
else
{
throw new PlatformNotSupportedException();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector128<float> ReadVector16(long position)
{
if (Sse2.IsSupported)
{
return Sse.StaticCast<ushort, float>(Sse2.Insert(Sse2.SetZeroVector128<ushort>(), ReadUInt16(position), 0));
}
else
{
throw new PlatformNotSupportedException();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector128<float> ReadVector32(long position)
{
if (Sse.IsSupported)
{
return Sse.LoadScalarVector128((float*)Translate(position));
}
else
{
throw new PlatformNotSupportedException();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector128<float> ReadVector64(long position)
{
if (Sse2.IsSupported)
{
return Sse.StaticCast<double, float>(Sse2.LoadScalarVector128((double*)Translate(position)));
}
else
{
throw new PlatformNotSupportedException();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector128<float> ReadVector128(long position)
{
if (Sse.IsSupported)
{
return Sse.LoadVector128((float*)Translate(position));
}
else
{
throw new PlatformNotSupportedException();
}
}
public byte[] ReadBytes(long position, long size)
{
if ((uint)size > int.MaxValue) throw new ArgumentOutOfRangeException(nameof(size));
if ((uint)size > int.MaxValue)
{
throw new ArgumentOutOfRangeException(nameof(size));
}
EnsureRangeIsValid(position, size);
@ -294,47 +342,69 @@ namespace ChocolArm64.Memory
public void WriteVector8(long position, Vector128<float> value)
{
if (Sse41.IsSupported)
{
WriteByte(position, Sse41.Extract(Sse.StaticCast<float, byte>(value), 0));
}
else if (Sse2.IsSupported)
{
WriteByte(position, (byte)Sse2.Extract(Sse.StaticCast<float, ushort>(value), 0));
}
else
{
throw new PlatformNotSupportedException();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void WriteVector16(long position, Vector128<float> value)
{
if (Sse2.IsSupported)
{
WriteUInt16(position, Sse2.Extract(Sse.StaticCast<float, ushort>(value), 0));
}
else
{
throw new PlatformNotSupportedException();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void WriteVector32(long position, Vector128<float> value)
{
if (Sse.IsSupported)
{
Sse.StoreScalar((float*)TranslateWrite(position), value);
}
else
{
throw new PlatformNotSupportedException();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void WriteVector64(long position, Vector128<float> value)
{
if (Sse2.IsSupported)
{
Sse2.StoreScalar((double*)TranslateWrite(position), Sse.StaticCast<float, double>(value));
}
else
{
throw new PlatformNotSupportedException();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void WriteVector128(long position, Vector128<float> value)
{
if (Sse.IsSupported)
{
Sse.Store((float*)TranslateWrite(position), value);
}
else
{
throw new PlatformNotSupportedException();
}
}
public void WriteBytes(long position, byte[] data)
@ -379,12 +449,18 @@ namespace ChocolArm64.Memory
public bool IsMapped(long position)
{
if (!IsValidPosition(position)) return false;
if (!IsValidPosition(position))
{
return false;
}
long l0 = (position >> PtLvl0Bit) & PtLvl0Mask;
long l1 = (position >> PtLvl1Bit) & PtLvl1Mask;
if (_pageTable[l0] == null) return false;
if (_pageTable[l0] == null)
{
return false;
}
return _pageTable[l0][l1] != null || _observedPages.ContainsKey(position >> PtPageBits);
}
@ -405,15 +481,24 @@ namespace ChocolArm64.Memory
byte** lvl1 = _pageTable[l0];
if (position >> (PtLvl0Bit + PtLvl0Bits) != 0) goto Unmapped;
if (position >> (PtLvl0Bit + PtLvl0Bits) != 0)
{
goto Unmapped;
}
if (lvl1 == null) goto Unmapped;
if (lvl1 == null)
{
goto Unmapped;
}
position &= PageMask;
byte* ptr = lvl1[l1];
if (ptr == null) goto Unmapped;
if (ptr == null)
{
goto Unmapped;
}
return ptr + position;
@ -425,7 +510,10 @@ Unmapped:
{
long key = position >> PtPageBits;
if (_observedPages.TryGetValue(key, out IntPtr ptr)) return (byte*)ptr + (position & PageMask);
if (_observedPages.TryGetValue(key, out IntPtr ptr))
{
return (byte*)ptr + (position & PageMask);
}
InvalidAccess?.Invoke(this, new AInvalidAccessEventArgs(position));
@ -441,15 +529,24 @@ Unmapped:
byte** lvl1 = _pageTable[l0];
if (position >> (PtLvl0Bit + PtLvl0Bits) != 0) goto Unmapped;
if (position >> (PtLvl0Bit + PtLvl0Bits) != 0)
{
goto Unmapped;
}
if (lvl1 == null) goto Unmapped;
if (lvl1 == null)
{
goto Unmapped;
}
position &= PageMask;
byte* ptr = lvl1[l1];
if (ptr == null) goto Unmapped;
if (ptr == null)
{
goto Unmapped;
}
return ptr + position;
@ -483,13 +580,19 @@ Unmapped:
va += PageSize;
if (ptr != null) ptr += PageSize;
if (ptr != null)
{
ptr += PageSize;
}
}
}
private void SetPtEntry(long position, byte* ptr)
{
if (!IsValidPosition(position)) throw new ArgumentOutOfRangeException(nameof(position));
if (!IsValidPosition(position))
{
throw new ArgumentOutOfRangeException(nameof(position));
}
long l0 = (position >> PtLvl0Bit) & PtLvl0Mask;
long l1 = (position >> PtLvl1Bit) & PtLvl1Mask;
@ -498,7 +601,10 @@ Unmapped:
{
byte** lvl1 = (byte**)Marshal.AllocHGlobal(PtLvl1Size * IntPtr.Size);
for (int zl1 = 0; zl1 < PtLvl1Size; zl1++) lvl1[zl1] = null;
for (int zl1 = 0; zl1 < PtLvl1Size; zl1++)
{
lvl1[zl1] = null;
}
Thread.MemoryBarrier();
@ -540,7 +646,12 @@ Unmapped:
byte** lvl1 = _pageTable[l0];
if (lvl1 != null)
if (modified[page] = lvl1[l1] != null) count++;
{
if (modified[page] = lvl1[l1] != null)
{
count++;
}
}
}
SetPtEntry(position, null);
@ -560,7 +671,10 @@ Unmapped:
{
lock (_observedPages)
{
if (_observedPages.TryRemove(position >> PtPageBits, out IntPtr ptr)) SetPtEntry(position, (byte*)ptr);
if (_observedPages.TryRemove(position >> PtPageBits, out IntPtr ptr))
{
SetPtEntry(position, (byte*)ptr);
}
}
position += PageSize;
@ -586,7 +700,10 @@ Unmapped:
{
long pa = GetPhysicalAddress(position);
if (pa != expectedPa) throw new VmmAccessException(position, size);
if (pa != expectedPa)
{
throw new VmmAccessException(position, size);
}
position += PageSize;
expectedPa += PageSize;
@ -605,11 +722,17 @@ Unmapped:
protected virtual void Dispose(bool disposing)
{
if (_pageTable == null) return;
if (_pageTable == null)
{
return;
}
for (int l0 = 0; l0 < PtLvl0Size; l0++)
{
if (_pageTable[l0] != null) Marshal.FreeHGlobal((IntPtr)_pageTable[l0]);
if (_pageTable[l0] != null)
{
Marshal.FreeHGlobal((IntPtr)_pageTable[l0]);
}
_pageTable[l0] = null;
}

View file

@ -11,9 +11,15 @@ namespace ChocolArm64.Memory
{
int size8 = size & ~(8 - 1);
for (int offs = 0; offs < size8; offs += 8) memory.WriteInt64(position + offs, 0);
for (int offs = 0; offs < size8; offs += 8)
{
memory.WriteInt64(position + offs, 0);
}
for (int offs = size8; offs < size - size8; offs++) memory.WriteByte(position + offs, 0);
for (int offs = size8; offs < size - size8; offs++)
{
memory.WriteByte(position + offs, 0);
}
}
public static unsafe T Read<T>(AMemory memory, long position) where T : struct
@ -46,7 +52,10 @@ namespace ChocolArm64.Memory
{
byte value = (byte)memory.ReadByte(position + offs);
if (value == 0) break;
if (value == 0)
{
break;
}
ms.WriteByte(value);
}

View file

@ -99,7 +99,10 @@ namespace ChocolArm64.State
//do it after a given number of instructions has executed.
_syncCount += bbWeight;
if (_syncCount >= MinInstForCheck) CheckInterrupt();
if (_syncCount >= MinInstForCheck)
{
CheckInterrupt();
}
return Running;
}

View file

@ -47,14 +47,19 @@ namespace ChocolArm64.Translation
else if (ilEmitter is AILOpCodeStore st)
{
if (AILEmitter.IsRegIndex(st.Index))
{
switch (st.IoType)
{
case AIoType.Flag: IntOutputs |= 1L << st.Index << 32; break;
case AIoType.Int: IntOutputs |= 1L << st.Index; break;
case AIoType.Vector: VecOutputs |= 1L << st.Index; break;
}
}
if (st.IoType == AIoType.Fields) HasStateStore = true;
if (st.IoType == AIoType.Fields)
{
HasStateStore = true;
}
}
IlEmitters.Add(ilEmitter);
@ -62,7 +67,10 @@ namespace ChocolArm64.Translation
public void Emit(AILEmitter context)
{
foreach (IAilEmit ilEmitter in IlEmitters) ilEmitter.Emit(context);
foreach (IAilEmit ilEmitter in IlEmitters)
{
ilEmitter.Emit(context);
}
}
}
}

View file

@ -35,9 +35,15 @@ namespace ChocolArm64.Translation
AILBlock GetBlock(int index)
{
if (index < 0 || index >= _ilBlocks.Length) return null;
if (index < 0 || index >= _ilBlocks.Length)
{
return null;
}
if (_ilBlocks[index] == null) _ilBlocks[index] = new AILBlock();
if (_ilBlocks[index] == null)
{
_ilBlocks[index] = new AILBlock();
}
return _ilBlocks[index];
}
@ -65,7 +71,10 @@ namespace ChocolArm64.Translation
InitSubroutine();
InitLocals();
foreach (AILBlock ilBlock in _ilBlocks) ilBlock.Emit(this);
foreach (AILBlock ilBlock in _ilBlocks)
{
ilBlock.Emit(this);
}
return _subroutine;
}
@ -80,7 +89,10 @@ namespace ChocolArm64.Translation
{
long mask = 1L << bit;
if ((inputs & mask) != 0) Params.Add(GetRegFromBit(bit, baseType));
if ((inputs & mask) != 0)
{
Params.Add(GetRegFromBit(bit, baseType));
}
}
}
@ -119,7 +131,10 @@ namespace ChocolArm64.Translation
int typeIdx = fixedArgs.Length;
for (int index = 0; index < Params.Count; index++) output[typeIdx++] = GetFieldType(Params[index].Type);
for (int index = 0; index < Params.Count; index++)
{
output[typeIdx++] = GetFieldType(Params[index].Type);
}
return output;
}
@ -158,11 +173,17 @@ namespace ChocolArm64.Translation
public static ARegister GetRegFromBit(int bit, ARegisterType baseType)
{
if (bit < 32)
{
return new ARegister(bit, baseType);
}
else if (baseType == ARegisterType.Int)
{
return new ARegister(bit & 0x1f, ARegisterType.Flag);
}
else
{
throw new ArgumentOutOfRangeException(nameof(bit));
}
}
public static bool IsRegIndex(int index)

View file

@ -58,7 +58,10 @@ namespace ChocolArm64.Translation
_opcIndex = -1;
if (graph.Length == 0 || !AdvanceOpCode()) throw new ArgumentException(nameof(graph));
if (graph.Length == 0 || !AdvanceOpCode())
{
throw new ArgumentException(nameof(graph));
}
}
public ATranslatedSub GetSubroutine()
@ -70,7 +73,9 @@ namespace ChocolArm64.Translation
{
if (_opcIndex + 1 == CurrBlock.OpCodes.Count &&
_blkIndex + 1 == _graph.Length)
{
return false;
}
while (++_opcIndex >= (CurrBlock?.OpCodes.Count ?? 0))
{
@ -123,21 +128,35 @@ namespace ChocolArm64.Translation
public bool TryOptEmitSubroutineCall()
{
if (CurrBlock.Next == null) return false;
if (CurrBlock.Next == null)
{
return false;
}
if (CurrOp.Emitter != AInstEmit.Bl) return false;
if (CurrOp.Emitter != AInstEmit.Bl)
{
return false;
}
if (!_cache.TryGetSubroutine(((AOpCodeBImmAl)CurrOp).Imm, out ATranslatedSub subroutine)) return false;
if (!_cache.TryGetSubroutine(((AOpCodeBImmAl)CurrOp).Imm, out ATranslatedSub subroutine))
{
return false;
}
for (int index = 0; index < ATranslatedSub.FixedArgTypes.Length; index++) EmitLdarg(index);
for (int index = 0; index < ATranslatedSub.FixedArgTypes.Length; index++)
{
EmitLdarg(index);
}
foreach (ARegister reg in subroutine.Params)
{
switch (reg.Type)
{
case ARegisterType.Flag: Ldloc(reg.Index, AIoType.Flag); break;
case ARegisterType.Int: Ldloc(reg.Index, AIoType.Int); break;
case ARegisterType.Vector: Ldloc(reg.Index, AIoType.Vector); break;
}
}
EmitCall(subroutine.Method);
@ -250,14 +269,20 @@ namespace ChocolArm64.Translation
if (sz64 == (intType == AIntType.UInt64 ||
intType == AIntType.Int64))
{
return;
}
if (sz64)
{
Emit(intType >= AIntType.Int8
? OpCodes.Conv_I8
: OpCodes.Conv_U8);
}
else
{
Emit(OpCodes.Conv_U4);
}
}
public void EmitLsl(int amount)
@ -345,17 +370,25 @@ namespace ChocolArm64.Translation
public void EmitLdintzr(int index)
{
if (index != AThreadState.ZrIndex)
{
EmitLdint(index);
}
else
{
EmitLdc_I(0);
}
}
public void EmitStintzr(int index)
{
if (index != AThreadState.ZrIndex)
{
EmitStint(index);
}
else
{
Emit(OpCodes.Pop);
}
}
public void EmitLoadState(ABlock retBlk)
@ -447,43 +480,70 @@ namespace ChocolArm64.Translation
public void EmitCallPropGet(Type objType, string propName)
{
if (objType == null) throw new ArgumentNullException(nameof(objType));
if (objType == null)
{
throw new ArgumentNullException(nameof(objType));
}
if (propName == null) throw new ArgumentNullException(nameof(propName));
if (propName == null)
{
throw new ArgumentNullException(nameof(propName));
}
EmitCall(objType.GetMethod($"get_{propName}"));
}
public void EmitCallPropSet(Type objType, string propName)
{
if (objType == null) throw new ArgumentNullException(nameof(objType));
if (objType == null)
{
throw new ArgumentNullException(nameof(objType));
}
if (propName == null) throw new ArgumentNullException(nameof(propName));
if (propName == null)
{
throw new ArgumentNullException(nameof(propName));
}
EmitCall(objType.GetMethod($"set_{propName}"));
}
public void EmitCall(Type objType, string mthdName)
{
if (objType == null) throw new ArgumentNullException(nameof(objType));
if (objType == null)
{
throw new ArgumentNullException(nameof(objType));
}
if (mthdName == null) throw new ArgumentNullException(nameof(mthdName));
if (mthdName == null)
{
throw new ArgumentNullException(nameof(mthdName));
}
EmitCall(objType.GetMethod(mthdName));
}
public void EmitPrivateCall(Type objType, string mthdName)
{
if (objType == null) throw new ArgumentNullException(nameof(objType));
if (objType == null)
{
throw new ArgumentNullException(nameof(objType));
}
if (mthdName == null) throw new ArgumentNullException(nameof(mthdName));
if (mthdName == null)
{
throw new ArgumentNullException(nameof(mthdName));
}
EmitCall(objType.GetMethod(mthdName, BindingFlags.Instance | BindingFlags.NonPublic));
}
public void EmitCall(MethodInfo mthdInfo)
{
if (mthdInfo == null) throw new ArgumentNullException(nameof(mthdInfo));
if (mthdInfo == null)
{
throw new ArgumentNullException(nameof(mthdInfo));
}
_ilBlock.Add(new AILOpCodeCall(mthdInfo));
}
@ -491,9 +551,13 @@ namespace ChocolArm64.Translation
public void EmitLdc_I(long value)
{
if (CurrOp.RegisterSize == ARegisterSize.Int32)
{
EmitLdc_I4((int)value);
}
else
{
EmitLdc_I8(value);
}
}
public void EmitLdc_I4(int value)
@ -527,7 +591,10 @@ namespace ChocolArm64.Translation
Emit(OpCodes.Dup);
Emit(OpCodes.Ldc_I4_0);
if (CurrOp.RegisterSize != ARegisterSize.Int32) Emit(OpCodes.Conv_I8);
if (CurrOp.RegisterSize != ARegisterSize.Int32)
{
Emit(OpCodes.Conv_I8);
}
Emit(ilCmpOp);

View file

@ -67,7 +67,9 @@ namespace ChocolArm64.Translation
if (registerType == ARegisterType.Int &&
RegisterSize == ARegisterSize.Int32)
{
context.Generator.Emit(OpCodes.Conv_U4);
}
}
}
}

View file

@ -65,7 +65,9 @@ namespace ChocolArm64.Translation
if (registerType == ARegisterType.Int &&
RegisterSize == ARegisterSize.Int32)
{
context.Generator.Emit(OpCodes.Conv_U8);
}
context.Generator.EmitStloc(context.GetLocalIndex(reg));
}

View file

@ -24,16 +24,25 @@ namespace ChocolArm64.Translation
public void Set(AILBlock root, long inputs, long outputs)
{
if (!_allInputs.TryAdd(root, inputs)) _allInputs[root] |= inputs;
if (!_allInputs.TryAdd(root, inputs))
{
_allInputs[root] |= inputs;
}
if (!_cmnOutputs.TryAdd(root, outputs)) _cmnOutputs[root] &= outputs;
if (!_cmnOutputs.TryAdd(root, outputs))
{
_cmnOutputs[root] &= outputs;
}
_allOutputs |= outputs;
}
public long GetInputs(AILBlock root)
{
if (_allInputs.TryGetValue(root, out long inputs)) return inputs | (_allOutputs & ~_cmnOutputs[root]);
if (_allInputs.TryGetValue(root, out long inputs))
{
return inputs | (_allOutputs & ~_cmnOutputs[root]);
}
return 0;
}
@ -67,9 +76,13 @@ namespace ChocolArm64.Translation
if (graph.Length > 1 &&
graph.Length < MaxOptGraphLength)
{
InitializeOptimal(graph, root);
}
else
{
InitializeFast(graph);
}
}
private void InitializeOptimal(AILBlock[] graph, AILBlock root)
@ -117,9 +130,15 @@ namespace ChocolArm64.Translation
if (current.Block.Next == null &&
current.Block.Branch == null || current.Block.HasStateStore)
{
if (!_intPaths.TryGetValue(current.Block, out PathIo intPath)) _intPaths.Add(current.Block, intPath = new PathIo());
if (!_intPaths.TryGetValue(current.Block, out PathIo intPath))
{
_intPaths.Add(current.Block, intPath = new PathIo());
}
if (!_vecPaths.TryGetValue(current.Block, out PathIo vecPath)) _vecPaths.Add(current.Block, vecPath = new PathIo());
if (!_vecPaths.TryGetValue(current.Block, out PathIo vecPath))
{
_vecPaths.Add(current.Block, vecPath = new PathIo());
}
intPath.Set(current.Entry, current.IntInputs, current.IntOutputs);
vecPath.Set(current.Entry, current.VecInputs, current.VecOutputs);
@ -145,9 +164,15 @@ namespace ChocolArm64.Translation
Enqueue(blkIo);
}
if (current.Block.Next != null) EnqueueFromCurrent(current.Block.Next, current.Block.HasStateStore);
if (current.Block.Next != null)
{
EnqueueFromCurrent(current.Block.Next, current.Block.HasStateStore);
}
if (current.Block.Branch != null) EnqueueFromCurrent(current.Block.Branch, false);
if (current.Block.Branch != null)
{
EnqueueFromCurrent(current.Block.Branch, false);
}
}
}
@ -197,7 +222,10 @@ namespace ChocolArm64.Translation
{
long inputs = 0;
foreach (PathIo path in values) inputs |= path.GetInputs(root);
foreach (PathIo path in values)
{
inputs |= path.GetInputs(root);
}
return inputs;
}

View file

@ -35,11 +35,18 @@ namespace ChocolArm64
default:
if ((uint)index <= byte.MaxValue)
{
generator.Emit(OpCodes.Ldarg_S, (byte)index);
}
else if ((uint)index < ushort.MaxValue)
{
generator.Emit(OpCodes.Ldarg, (short)index);
}
else
{
throw new ArgumentOutOfRangeException(nameof(index));
}
break;
}
}
@ -47,11 +54,17 @@ namespace ChocolArm64
public static void EmitStarg(this ILGenerator generator, int index)
{
if ((uint)index <= byte.MaxValue)
{
generator.Emit(OpCodes.Starg_S, (byte)index);
}
else if ((uint)index < ushort.MaxValue)
{
generator.Emit(OpCodes.Starg, (short)index);
}
else
{
throw new ArgumentOutOfRangeException(nameof(index));
}
}
public static void EmitLdloc(this ILGenerator generator, int index)
@ -65,11 +78,18 @@ namespace ChocolArm64
default:
if ((uint)index <= byte.MaxValue)
{
generator.Emit(OpCodes.Ldloc_S, (byte)index);
}
else if ((uint)index < ushort.MaxValue)
{
generator.Emit(OpCodes.Ldloc, (short)index);
}
else
{
throw new ArgumentOutOfRangeException(nameof(index));
}
break;
}
}
@ -85,18 +105,28 @@ namespace ChocolArm64
default:
if ((uint)index <= byte.MaxValue)
{
generator.Emit(OpCodes.Stloc_S, (byte)index);
}
else if ((uint)index < ushort.MaxValue)
{
generator.Emit(OpCodes.Stloc, (short)index);
}
else
{
throw new ArgumentOutOfRangeException(nameof(index));
}
break;
}
}
public static void EmitLdargSeq(this ILGenerator generator, int count)
{
for (int index = 0; index < count; index++) generator.EmitLdarg(index);
for (int index = 0; index < count; index++)
{
generator.EmitLdarg(index);
}
}
}
}

View file

@ -30,7 +30,10 @@ namespace Ryujinx.Audio.Adpcm
int frameSamples = SamplesPerFrame;
if (frameSamples > samples) frameSamples = samples;
if (frameSamples > samples)
{
frameSamples = samples;
}
int value = 0;

View file

@ -5,10 +5,14 @@ namespace Ryujinx.Audio.Adpcm
public static short Saturate(int value)
{
if (value > short.MaxValue)
{
value = short.MaxValue;
}
if (value < short.MinValue)
{
value = short.MinValue;
}
return (short)value;
}

View file

@ -56,7 +56,12 @@ namespace Ryujinx.Audio.OpenAL
public bool ContainsBuffer(long tag)
{
foreach (long queuedTag in _queuedTagsQueue)
if (queuedTag == tag) return true;
{
if (queuedTag == tag)
{
return true;
}
}
return false;
}
@ -67,11 +72,17 @@ namespace Ryujinx.Audio.OpenAL
releasedCount += _releasedTagsQueue.Count;
if (count > releasedCount) count = releasedCount;
if (count > releasedCount)
{
count = releasedCount;
}
List<long> tags = new List<long>();
while (count-- > 0 && _releasedTagsQueue.TryDequeue(out long tag)) tags.Add(tag);
while (count-- > 0 && _releasedTagsQueue.TryDequeue(out long tag))
{
tags.Add(tag);
}
while (count-- > 0 && _queuedTagsQueue.TryDequeue(out long tag))
{
@ -85,7 +96,10 @@ namespace Ryujinx.Audio.OpenAL
public int AppendBuffer(long tag)
{
if (_disposed) throw new ObjectDisposedException(nameof(Track));
if (_disposed)
{
throw new ObjectDisposedException(nameof(Track));
}
int id = AL.GenBuffer();
@ -135,7 +149,10 @@ namespace Ryujinx.Audio.OpenAL
AL.DeleteSource(SourceId);
foreach (int id in _buffers.Values) AL.DeleteBuffer(id);
foreach (int id in _buffers.Values)
{
AL.DeleteBuffer(id);
}
}
}
}
@ -164,17 +181,22 @@ namespace Ryujinx.Audio.OpenAL
do
{
foreach (Track td in _tracks.Values)
{
lock (td)
{
td.CallReleaseCallbackIfNeeded();
}
}
//If it's not slept it will waste cycles.
Thread.Sleep(10);
}
while (_keepPolling);
foreach (Track td in _tracks.Values) td.Dispose();
foreach (Track td in _tracks.Values)
{
td.Dispose();
}
_tracks.Clear();
}
@ -184,7 +206,12 @@ namespace Ryujinx.Audio.OpenAL
Track td = new Track(sampleRate, GetAlFormat(channels), callback);
for (int id = 0; id < MaxTracks; id++)
if (_tracks.TryAdd(id, td)) return id;
{
if (_tracks.TryAdd(id, td))
{
return id;
}
}
return -1;
}
@ -204,19 +231,23 @@ namespace Ryujinx.Audio.OpenAL
public void CloseTrack(int track)
{
if (_tracks.TryRemove(track, out Track td))
{
lock (td)
{
td.Dispose();
}
}
}
public bool ContainsBuffer(int track, long tag)
{
if (_tracks.TryGetValue(track, out Track td))
{
lock (td)
{
return td.ContainsBuffer(tag);
}
}
return false;
}
@ -224,10 +255,12 @@ namespace Ryujinx.Audio.OpenAL
public long[] GetReleasedBuffers(int track, int maxCount)
{
if (_tracks.TryGetValue(track, out Track td))
{
lock (td)
{
return td.GetReleasedBuffers(maxCount);
}
}
return null;
}
@ -235,6 +268,7 @@ namespace Ryujinx.Audio.OpenAL
public void AppendBuffer<T>(int track, long tag, T[] buffer) where T : struct
{
if (_tracks.TryGetValue(track, out Track td))
{
lock (td)
{
int bufferId = td.AppendBuffer(tag);
@ -247,17 +281,20 @@ namespace Ryujinx.Audio.OpenAL
StartPlaybackIfNeeded(td);
}
}
}
public void Start(int track)
{
if (_tracks.TryGetValue(track, out Track td))
{
lock (td)
{
td.State = PlaybackState.Playing;
StartPlaybackIfNeeded(td);
}
}
}
private void StartPlaybackIfNeeded(Track td)
@ -266,23 +303,31 @@ namespace Ryujinx.Audio.OpenAL
ALSourceState state = (ALSourceState)stateInt;
if (state != ALSourceState.Playing && td.State == PlaybackState.Playing) AL.SourcePlay(td.SourceId);
if (state != ALSourceState.Playing && td.State == PlaybackState.Playing)
{
AL.SourcePlay(td.SourceId);
}
}
public void Stop(int track)
{
if (_tracks.TryGetValue(track, out Track td))
{
lock (td)
{
td.State = PlaybackState.Stopped;
AL.SourceStop(td.SourceId);
}
}
}
public PlaybackState GetState(int track)
{
if (_tracks.TryGetValue(track, out Track td)) return td.State;
if (_tracks.TryGetValue(track, out Track td))
{
return td.State;
}
return PlaybackState.Stopped;
}
@ -294,7 +339,10 @@ namespace Ryujinx.Audio.OpenAL
protected virtual void Dispose(bool disposing)
{
if (disposing) _keepPolling = false;
if (disposing)
{
_keepPolling = false;
}
}
}
}

View file

@ -23,7 +23,10 @@ namespace Ryujinx.Common.Logging
_enabledLevels[(int)LogLevel.Warning] = true;
_enabledLevels[(int)LogLevel.Error] = true;
for (int index = 0; index < _enabledClasses.Length; index++) _enabledClasses[index] = true;
for (int index = 0; index < _enabledClasses.Length; index++)
{
_enabledClasses[index] = true;
}
_time = new Stopwatch();
@ -67,7 +70,10 @@ namespace Ryujinx.Common.Logging
private static void Print(LogLevel level, LogClass Class, string message)
{
if (_enabledLevels[(int)level] && _enabledClasses[(int)Class]) Updated?.Invoke(null, new LogEventArgs(level, _time.Elapsed, message));
if (_enabledLevels[(int)level] && _enabledClasses[(int)Class])
{
Updated?.Invoke(null, new LogEventArgs(level, _time.Elapsed, message));
}
}
private static string GetFormattedMessage(LogClass Class, string message, string caller)

View file

@ -47,11 +47,15 @@ namespace Ryujinx.Graphics.Gal
{
if (ImageUtils.GetBytesPerPixel(Format) !=
ImageUtils.GetBytesPerPixel(image.Format))
{
return false;
}
if (ImageUtils.GetAlignedWidth(this) !=
ImageUtils.GetAlignedWidth(image))
{
return false;
}
return Height == image.Height;
}

View file

@ -84,7 +84,10 @@
{
ConstBufferKeys = new long[Stages][];
for (int stage = 0; stage < Stages; stage++) ConstBufferKeys[stage] = new long[ConstBuffersPerStage];
for (int stage = 0; stage < Stages; stage++)
{
ConstBufferKeys[stage] = new long[ConstBuffersPerStage];
}
ColorMasks = new ColorMaskRgba[RenderTargetsCount];
}

View file

@ -42,7 +42,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public OGLCachedResource(DeleteValue deleteValueCallback)
{
if (deleteValueCallback == null) throw new ArgumentNullException(nameof(deleteValueCallback));
if (deleteValueCallback == null)
{
throw new ArgumentNullException(nameof(deleteValueCallback));
}
_deleteValueCallback = deleteValueCallback;
@ -62,14 +65,20 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
_locked = false;
while (_deletePending.TryDequeue(out T value)) _deleteValueCallback(value);
while (_deletePending.TryDequeue(out T value))
{
_deleteValueCallback(value);
}
ClearCacheIfNeeded();
}
public void AddOrUpdate(long key, T value, long size)
{
if (!_locked) ClearCacheIfNeeded();
if (!_locked)
{
ClearCacheIfNeeded();
}
LinkedListNode<long> node = _sortedCache.AddLast(key);
@ -78,9 +87,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL
if (_cache.TryGetValue(key, out CacheBucket bucket))
{
if (_locked)
{
_deletePending.Enqueue(bucket.Value);
}
else
{
_deleteValueCallback(bucket.Value);
}
_sortedCache.Remove(bucket.Node);
@ -136,13 +149,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
LinkedListNode<long> node = _sortedCache.First;
if (node == null) break;
if (node == null)
{
break;
}
CacheBucket bucket = _cache[node.Value];
int timeDelta = RingDelta(bucket.Timestamp, timestamp);
if ((uint)timeDelta <= (uint)MaxTimeDelta) break;
if ((uint)timeDelta <= (uint)MaxTimeDelta)
{
break;
}
_sortedCache.Remove(node);
@ -155,9 +174,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private int RingDelta(int old, int New)
{
if ((uint)New < (uint)old)
{
return New + ~old + 1;
}
else
{
return New - old;
}
}
}
}

View file

@ -36,7 +36,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void SetData(long key, long size, IntPtr hostAddress)
{
if (_cache.TryGetValue(key, out OGLStreamBuffer buffer)) buffer.SetData(size, hostAddress);
if (_cache.TryGetValue(key, out OGLStreamBuffer buffer))
{
buffer.SetData(size, hostAddress);
}
}
public bool TryGetUbo(long key, out int uboHandle)

View file

@ -50,7 +50,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
//Looks like the GPU can take it's own values (described in GalComparisonOp) and OpenGL values alike
if ((int)func >= (int)DepthFunction.Never &&
(int)func <= (int)DepthFunction.Always)
{
return (DepthFunction)func;
}
switch (func)
{
@ -229,19 +231,23 @@ namespace Ryujinx.Graphics.Gal.OpenGL
}
if (OGLExtension.TextureMirrorClamp)
{
switch (wrap)
{
case GalTextureWrap.MirrorClampToEdge: return (TextureWrapMode)ExtTextureMirrorClamp.MirrorClampToEdgeExt;
case GalTextureWrap.MirrorClampToBorder: return (TextureWrapMode)ExtTextureMirrorClamp.MirrorClampToBorderExt;
case GalTextureWrap.MirrorClamp: return (TextureWrapMode)ExtTextureMirrorClamp.MirrorClampExt;
}
}
else
{
switch (wrap)
{
case GalTextureWrap.MirrorClampToEdge: return TextureWrapMode.ClampToEdge;
case GalTextureWrap.MirrorClampToBorder: return TextureWrapMode.ClampToBorder;
case GalTextureWrap.MirrorClamp: return TextureWrapMode.Clamp;
}
}
throw new ArgumentException(nameof(wrap) + " \"" + wrap + "\" is not valid!");
}

View file

@ -18,7 +18,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
int numExtensions = GL.GetInteger(GetPName.NumExtensions);
for (int extension = 0; extension < numExtensions; extension++)
if (GL.GetString(StringNameIndexed.Extensions, extension) == name) return true;
{
if (GL.GetString(StringNameIndexed.Extensions, extension) == name)
{
return true;
}
}
return false;
}

View file

@ -135,7 +135,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
PrimitiveRestartIndex = 0
};
for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++) _old.ColorMasks[index] = ColorMaskRgba.Default;
for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++)
{
_old.ColorMasks[index] = ColorMaskRgba.Default;
}
}
public void Bind(GalPipelineState New)
@ -144,9 +147,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL
BindVertexLayout(New);
if (New.FramebufferSrgb != _old.FramebufferSrgb) Enable(EnableCap.FramebufferSrgb, New.FramebufferSrgb);
if (New.FramebufferSrgb != _old.FramebufferSrgb)
{
Enable(EnableCap.FramebufferSrgb, New.FramebufferSrgb);
}
if (New.FlipX != _old.FlipX || New.FlipY != _old.FlipY || New.Instance != _old.Instance) _shader.SetExtraData(New.FlipX, New.FlipY, New.Instance);
if (New.FlipX != _old.FlipX || New.FlipY != _old.FlipY || New.Instance != _old.Instance)
{
_shader.SetExtraData(New.FlipX, New.FlipY, New.Instance);
}
//Note: Uncomment SetFrontFace and SetCullFace when flipping issues are solved
@ -168,65 +177,101 @@ namespace Ryujinx.Graphics.Gal.OpenGL
// }
//}
if (New.DepthTestEnabled != _old.DepthTestEnabled) Enable(EnableCap.DepthTest, New.DepthTestEnabled);
if (New.DepthTestEnabled != _old.DepthTestEnabled)
{
Enable(EnableCap.DepthTest, New.DepthTestEnabled);
}
if (New.DepthWriteEnabled != _old.DepthWriteEnabled) GL.DepthMask(New.DepthWriteEnabled);
if (New.DepthWriteEnabled != _old.DepthWriteEnabled)
{
GL.DepthMask(New.DepthWriteEnabled);
}
if (New.DepthTestEnabled)
if (New.DepthFunc != _old.DepthFunc) GL.DepthFunc(OGLEnumConverter.GetDepthFunc(New.DepthFunc));
{
if (New.DepthFunc != _old.DepthFunc)
{
GL.DepthFunc(OGLEnumConverter.GetDepthFunc(New.DepthFunc));
}
}
if (New.DepthRangeNear != _old.DepthRangeNear ||
New.DepthRangeFar != _old.DepthRangeFar)
{
GL.DepthRange(New.DepthRangeNear, New.DepthRangeFar);
}
if (New.StencilTestEnabled != _old.StencilTestEnabled) Enable(EnableCap.StencilTest, New.StencilTestEnabled);
if (New.StencilTestEnabled != _old.StencilTestEnabled)
{
Enable(EnableCap.StencilTest, New.StencilTestEnabled);
}
if (New.StencilTwoSideEnabled != _old.StencilTwoSideEnabled) Enable((EnableCap)All.StencilTestTwoSideExt, New.StencilTwoSideEnabled);
if (New.StencilTwoSideEnabled != _old.StencilTwoSideEnabled)
{
Enable((EnableCap)All.StencilTestTwoSideExt, New.StencilTwoSideEnabled);
}
if (New.StencilTestEnabled)
{
if (New.StencilBackFuncFunc != _old.StencilBackFuncFunc ||
New.StencilBackFuncRef != _old.StencilBackFuncRef ||
New.StencilBackFuncMask != _old.StencilBackFuncMask)
{
GL.StencilFuncSeparate(
StencilFace.Back,
OGLEnumConverter.GetStencilFunc(New.StencilBackFuncFunc),
New.StencilBackFuncRef,
New.StencilBackFuncMask);
}
if (New.StencilBackOpFail != _old.StencilBackOpFail ||
New.StencilBackOpZFail != _old.StencilBackOpZFail ||
New.StencilBackOpZPass != _old.StencilBackOpZPass)
{
GL.StencilOpSeparate(
StencilFace.Back,
OGLEnumConverter.GetStencilOp(New.StencilBackOpFail),
OGLEnumConverter.GetStencilOp(New.StencilBackOpZFail),
OGLEnumConverter.GetStencilOp(New.StencilBackOpZPass));
}
if (New.StencilBackMask != _old.StencilBackMask) GL.StencilMaskSeparate(StencilFace.Back, New.StencilBackMask);
if (New.StencilBackMask != _old.StencilBackMask)
{
GL.StencilMaskSeparate(StencilFace.Back, New.StencilBackMask);
}
if (New.StencilFrontFuncFunc != _old.StencilFrontFuncFunc ||
New.StencilFrontFuncRef != _old.StencilFrontFuncRef ||
New.StencilFrontFuncMask != _old.StencilFrontFuncMask)
{
GL.StencilFuncSeparate(
StencilFace.Front,
OGLEnumConverter.GetStencilFunc(New.StencilFrontFuncFunc),
New.StencilFrontFuncRef,
New.StencilFrontFuncMask);
}
if (New.StencilFrontOpFail != _old.StencilFrontOpFail ||
New.StencilFrontOpZFail != _old.StencilFrontOpZFail ||
New.StencilFrontOpZPass != _old.StencilFrontOpZPass)
{
GL.StencilOpSeparate(
StencilFace.Front,
OGLEnumConverter.GetStencilOp(New.StencilFrontOpFail),
OGLEnumConverter.GetStencilOp(New.StencilFrontOpZFail),
OGLEnumConverter.GetStencilOp(New.StencilFrontOpZPass));
}
if (New.StencilFrontMask != _old.StencilFrontMask) GL.StencilMaskSeparate(StencilFace.Front, New.StencilFrontMask);
if (New.StencilFrontMask != _old.StencilFrontMask)
{
GL.StencilMaskSeparate(StencilFace.Front, New.StencilFrontMask);
}
}
if (New.BlendEnabled != _old.BlendEnabled) Enable(EnableCap.Blend, New.BlendEnabled);
if (New.BlendEnabled != _old.BlendEnabled)
{
Enable(EnableCap.Blend, New.BlendEnabled);
}
if (New.BlendEnabled)
{
@ -234,57 +279,80 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
if (New.BlendEquationRgb != _old.BlendEquationRgb ||
New.BlendEquationAlpha != _old.BlendEquationAlpha)
{
GL.BlendEquationSeparate(
OGLEnumConverter.GetBlendEquation(New.BlendEquationRgb),
OGLEnumConverter.GetBlendEquation(New.BlendEquationAlpha));
}
if (New.BlendFuncSrcRgb != _old.BlendFuncSrcRgb ||
New.BlendFuncDstRgb != _old.BlendFuncDstRgb ||
New.BlendFuncSrcAlpha != _old.BlendFuncSrcAlpha ||
New.BlendFuncDstAlpha != _old.BlendFuncDstAlpha)
{
GL.BlendFuncSeparate(
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.BlendFuncSrcRgb),
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.BlendFuncDstRgb),
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.BlendFuncSrcAlpha),
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.BlendFuncDstAlpha));
}
}
else
{
if (New.BlendEquationRgb != _old.BlendEquationRgb) GL.BlendEquation(OGLEnumConverter.GetBlendEquation(New.BlendEquationRgb));
if (New.BlendEquationRgb != _old.BlendEquationRgb)
{
GL.BlendEquation(OGLEnumConverter.GetBlendEquation(New.BlendEquationRgb));
}
if (New.BlendFuncSrcRgb != _old.BlendFuncSrcRgb ||
New.BlendFuncDstRgb != _old.BlendFuncDstRgb)
{
GL.BlendFunc(
OGLEnumConverter.GetBlendFactor(New.BlendFuncSrcRgb),
OGLEnumConverter.GetBlendFactor(New.BlendFuncDstRgb));
}
}
}
if (New.ColorMaskCommon)
{
if (New.ColorMaskCommon != _old.ColorMaskCommon || !New.ColorMasks[0].Equals(_old.ColorMasks[0]))
{
GL.ColorMask(
New.ColorMasks[0].Red,
New.ColorMasks[0].Green,
New.ColorMasks[0].Blue,
New.ColorMasks[0].Alpha);
}
}
else
{
for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++)
{
if (!New.ColorMasks[index].Equals(_old.ColorMasks[index]))
{
GL.ColorMask(
index,
New.ColorMasks[index].Red,
New.ColorMasks[index].Green,
New.ColorMasks[index].Blue,
New.ColorMasks[index].Alpha);
}
}
}
if (New.PrimitiveRestartEnabled != _old.PrimitiveRestartEnabled) Enable(EnableCap.PrimitiveRestart, New.PrimitiveRestartEnabled);
if (New.PrimitiveRestartEnabled != _old.PrimitiveRestartEnabled)
{
Enable(EnableCap.PrimitiveRestart, New.PrimitiveRestartEnabled);
}
if (New.PrimitiveRestartEnabled)
if (New.PrimitiveRestartIndex != _old.PrimitiveRestartIndex) GL.PrimitiveRestartIndex(New.PrimitiveRestartIndex);
{
if (New.PrimitiveRestartIndex != _old.PrimitiveRestartIndex)
{
GL.PrimitiveRestartIndex(New.PrimitiveRestartIndex);
}
}
_old = New;
}
@ -296,14 +364,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
void BindIfNotNull(OGLShaderStage stage)
{
if (stage != null)
{
foreach (ShaderDeclInfo declInfo in stage.ConstBufferUsage)
{
long key = New.ConstBufferKeys[(int)stage.Type][declInfo.Cbuf];
if (key != 0 && _buffer.TryGetUbo(key, out int uboHandle)) GL.BindBufferBase(BufferRangeTarget.UniformBuffer, freeBinding, uboHandle);
if (key != 0 && _buffer.TryGetUbo(key, out int uboHandle))
{
GL.BindBufferBase(BufferRangeTarget.UniformBuffer, freeBinding, uboHandle);
}
freeBinding++;
}
}
}
BindIfNotNull(_shader.Current.Vertex);
@ -317,7 +390,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
foreach (GalVertexBinding binding in New.VertexBindings)
{
if (!binding.Enabled || !_rasterizer.TryGetVbo(binding.VboKey, out int vboHandle)) continue;
if (!binding.Enabled || !_rasterizer.TryGetVbo(binding.VboKey, out int vboHandle))
{
continue;
}
if (_vaoHandle == 0)
{
@ -331,7 +407,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
foreach (GalVertexAttrib attrib in binding.Attribs)
{
//Skip uninitialized attributes.
if (attrib.Size == 0) continue;
if (attrib.Size == 0)
{
continue;
}
GL.BindBuffer(BufferTarget.ArrayBuffer, vboHandle);
@ -353,12 +432,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
else
{
if (unsigned)
{
type = GetType(_unsignedAttribTypes, attrib);
}
else
{
type = GetType(_signedAttribTypes, attrib);
}
}
if (!_attribElements.TryGetValue(attrib.Size, out int size)) throw new InvalidOperationException("Invalid attribute size \"" + attrib.Size + "\"!");
if (!_attribElements.TryGetValue(attrib.Size, out int size))
{
throw new InvalidOperationException("Invalid attribute size \"" + attrib.Size + "\"!");
}
int offset = attrib.Offset;
@ -388,16 +474,23 @@ namespace Ryujinx.Graphics.Gal.OpenGL
}
if (binding.Instanced && binding.Divisor != 0)
{
GL.VertexAttribDivisor(attrib.Index, 1);
}
else
{
GL.VertexAttribDivisor(attrib.Index, 0);
}
}
}
}
private static VertexAttribPointerType GetType(Dictionary<GalVertexAttribSize, VertexAttribPointerType> dict, GalVertexAttrib attrib)
{
if (!dict.TryGetValue(attrib.Size, out VertexAttribPointerType type)) ThrowUnsupportedAttrib(attrib);
if (!dict.TryGetValue(attrib.Size, out VertexAttribPointerType type))
{
ThrowUnsupportedAttrib(attrib);
}
return type;
}
@ -406,9 +499,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
if (attrib.Size == GalVertexAttribSize._10_10_10_2 ||
attrib.Size == GalVertexAttribSize._11_11_10)
{
ThrowUnsupportedAttrib(attrib);
}
if (attrib.Type == GalVertexAttribType.Unorm)
{
switch (attrib.Size)
{
case GalVertexAttribSize._8:
@ -432,7 +528,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.VertexAttrib4N((uint)attrib.Index, (uint*)attrib.Pointer);
break;
}
}
else if (attrib.Type == GalVertexAttribType.Snorm)
{
switch (attrib.Size)
{
case GalVertexAttribSize._8:
@ -456,7 +554,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.VertexAttrib4N((uint)attrib.Index, (int*)attrib.Pointer);
break;
}
}
else if (attrib.Type == GalVertexAttribType.Uint)
{
switch (attrib.Size)
{
case GalVertexAttribSize._8:
@ -480,7 +580,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.VertexAttribI4((uint)attrib.Index, (uint*)attrib.Pointer);
break;
}
}
else if (attrib.Type == GalVertexAttribType.Sint)
{
switch (attrib.Size)
{
case GalVertexAttribSize._8:
@ -504,7 +606,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.VertexAttribI4((uint)attrib.Index, (int*)attrib.Pointer);
break;
}
}
else if (attrib.Type == GalVertexAttribType.Float)
{
switch (attrib.Size)
{
case GalVertexAttribSize._32:
@ -516,6 +620,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
default: ThrowUnsupportedAttrib(attrib); break;
}
}
}
private static void ThrowUnsupportedAttrib(GalVertexAttrib attrib)
@ -526,9 +631,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private void Enable(EnableCap cap, bool enabled)
{
if (enabled)
{
GL.Enable(cap);
}
else
{
GL.Disable(cap);
}
}
public void ResetDepthMask()

View file

@ -64,9 +64,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.ColorMask(attachment, true, true, true, true);
GL.DepthMask(true);
if (flags.HasFlag(GalClearBufferFlags.Depth)) GL.ClearBuffer(ClearBuffer.Depth, 0, ref depth);
if (flags.HasFlag(GalClearBufferFlags.Depth))
{
GL.ClearBuffer(ClearBuffer.Depth, 0, ref depth);
}
if (flags.HasFlag(GalClearBufferFlags.Stencil)) GL.ClearBuffer(ClearBuffer.Stencil, 0, ref stencil);
if (flags.HasFlag(GalClearBufferFlags.Stencil))
{
GL.ClearBuffer(ClearBuffer.Stencil, 0, ref stencil);
}
}
public bool IsVboCached(long key, long dataSize)
@ -126,17 +132,26 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void DrawArrays(int first, int count, GalPrimitiveType primType)
{
if (count == 0) return;
if (count == 0)
{
return;
}
if (primType == GalPrimitiveType.Quads)
{
for (int offset = 0; offset < count; offset += 4) GL.DrawArrays(PrimitiveType.TriangleFan, first + offset, 4);
for (int offset = 0; offset < count; offset += 4)
{
GL.DrawArrays(PrimitiveType.TriangleFan, first + offset, 4);
}
}
else if (primType == GalPrimitiveType.QuadStrip)
{
GL.DrawArrays(PrimitiveType.TriangleFan, first, 4);
for (int offset = 2; offset < count; offset += 2) GL.DrawArrays(PrimitiveType.TriangleFan, first + offset, 4);
for (int offset = 2; offset < count; offset += 2)
{
GL.DrawArrays(PrimitiveType.TriangleFan, first + offset, 4);
}
}
else
{
@ -146,7 +161,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void DrawElements(long iboKey, int first, int vertexBase, GalPrimitiveType primType)
{
if (!_iboCache.TryGetValue(iboKey, out int iboHandle)) return;
if (!_iboCache.TryGetValue(iboKey, out int iboHandle))
{
return;
}
PrimitiveType mode = OGLEnumConverter.GetPrimitiveType(primType);

View file

@ -110,14 +110,25 @@ namespace Ryujinx.Graphics.Gal.OpenGL
//Texture was deleted, the handle is no longer valid, so
//reset all uses of this handle on a render target.
for (int attachment = 0; attachment < RenderTargetsCount; attachment++)
if (_colorHandles[attachment] == handle) _colorHandles[attachment] = 0;
{
if (_colorHandles[attachment] == handle)
{
_colorHandles[attachment] = 0;
}
}
if (_zetaHandle == handle) _zetaHandle = 0;
if (_zetaHandle == handle)
{
_zetaHandle = 0;
}
}
public void Bind()
{
if (_dummyFrameBuffer == 0) _dummyFrameBuffer = GL.GenFramebuffer();
if (_dummyFrameBuffer == 0)
{
_dummyFrameBuffer = GL.GenFramebuffer();
}
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, _dummyFrameBuffer);
@ -129,9 +140,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL
int handle = 0;
if (key != 0 && _texture.TryGetImageHandler(key, out cachedImage)) handle = cachedImage.Handle;
if (key != 0 && _texture.TryGetImageHandler(key, out cachedImage))
{
handle = cachedImage.Handle;
}
if (handle == _colorHandles[attachment]) continue;
if (handle == _colorHandles[attachment])
{
continue;
}
GL.FramebufferTexture(
FramebufferTarget.DrawFramebuffer,
@ -188,20 +205,30 @@ namespace Ryujinx.Graphics.Gal.OpenGL
}
if (OGLExtension.ViewportArray)
{
GL.ViewportArray(0, RenderTargetsCount, _viewports);
}
else
{
GL.Viewport(
(int)_viewports[0],
(int)_viewports[1],
(int)_viewports[2],
(int)_viewports[3]);
}
if (_attachments.MapCount > 1)
{
GL.DrawBuffers(_attachments.MapCount, _attachments.Map);
}
else if (_attachments.MapCount == 1)
{
GL.DrawBuffer((DrawBufferMode)_attachments.Map[0]);
}
else
{
GL.DrawBuffer(DrawBufferMode.None);
}
_oldAttachments.Update(_attachments);
}
@ -237,7 +264,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
_attachments.MapCount = map.Length;
for (int attachment = 0; attachment < _attachments.MapCount; attachment++) _attachments.Map[attachment] = DrawBuffersEnum.ColorAttachment0 + map[attachment];
for (int attachment = 0; attachment < _attachments.MapCount; attachment++)
{
_attachments.Map[attachment] = DrawBuffersEnum.ColorAttachment0 + map[attachment];
}
}
else
{
@ -273,7 +303,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void Render()
{
if (_readTex == null) return;
if (_readTex == null)
{
return;
}
int srcX0, srcX1, srcY0, srcY1;
@ -316,7 +349,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.Viewport(0, 0, _window.Width, _window.Height);
if (_srcFb == 0) _srcFb = GL.GenFramebuffer();
if (_srcFb == 0)
{
_srcFb = GL.GenFramebuffer();
}
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, _srcFb);
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0);
@ -352,11 +388,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
if (srcTex.HasColor != dstTex.HasColor ||
srcTex.HasDepth != dstTex.HasDepth ||
srcTex.HasStencil != dstTex.HasStencil)
{
throw new NotImplementedException();
}
if (_srcFb == 0) _srcFb = GL.GenFramebuffer();
if (_srcFb == 0)
{
_srcFb = GL.GenFramebuffer();
}
if (_dstFb == 0) _dstFb = GL.GenFramebuffer();
if (_dstFb == 0)
{
_dstFb = GL.GenFramebuffer();
}
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, _srcFb);
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, _dstFb);
@ -385,17 +429,29 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void Reinterpret(long key, GalImage newImage)
{
if (!_texture.TryGetImage(key, out GalImage oldImage)) return;
if (!_texture.TryGetImage(key, out GalImage oldImage))
{
return;
}
if (newImage.Format == oldImage.Format) return;
if (newImage.Format == oldImage.Format)
{
return;
}
if (_copyPbo == 0) _copyPbo = GL.GenBuffer();
if (_copyPbo == 0)
{
_copyPbo = GL.GenBuffer();
}
GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyPbo);
GL.BufferData(BufferTarget.PixelPackBuffer, Math.Max(ImageUtils.GetSize(oldImage), ImageUtils.GetSize(newImage)), IntPtr.Zero, BufferUsageHint.StreamCopy);
if (!_texture.TryGetImageHandler(key, out ImageHandler cachedImage)) throw new InvalidOperationException();
if (!_texture.TryGetImageHandler(key, out ImageHandler cachedImage))
{
throw new InvalidOperationException();
}
(_, PixelFormat format, PixelType type) = OGLEnumConverter.GetImageFormat(cachedImage.Format);
@ -414,15 +470,25 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private static FramebufferAttachment GetAttachment(ImageHandler cachedImage)
{
if (cachedImage.HasColor)
{
return FramebufferAttachment.ColorAttachment0;
}
else if (cachedImage.HasDepth && cachedImage.HasStencil)
{
return FramebufferAttachment.DepthStencilAttachment;
}
else if (cachedImage.HasDepth)
{
return FramebufferAttachment.DepthAttachment;
}
else if (cachedImage.HasStencil)
{
return FramebufferAttachment.StencilAttachment;
}
else
{
throw new InvalidOperationException();
}
}
private static ClearBufferMask GetClearMask(ImageHandler cachedImage)

View file

@ -45,7 +45,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
int count = _actionsQueue.Count;
while (count-- > 0 && _actionsQueue.TryDequeue(out Action renderAction)) renderAction();
while (count-- > 0 && _actionsQueue.TryDequeue(out Action renderAction))
{
renderAction();
}
}
}
}

View file

@ -73,21 +73,30 @@ namespace Ryujinx.Graphics.Gal.OpenGL
string code = program.Code;
if (ShaderDumper.IsDumpEnabled()) code = "//Shader " + shaderDumpIndex + Environment.NewLine + code;
if (ShaderDumper.IsDumpEnabled())
{
code = "//Shader " + shaderDumpIndex + Environment.NewLine + code;
}
return new OGLShaderStage(type, code, program.Uniforms, program.Textures);
}
public IEnumerable<ShaderDeclInfo> GetConstBufferUsage(long key)
{
if (_stages.TryGetValue(key, out OGLShaderStage stage)) return stage.ConstBufferUsage;
if (_stages.TryGetValue(key, out OGLShaderStage stage))
{
return stage.ConstBufferUsage;
}
return Enumerable.Empty<ShaderDeclInfo>();
}
public IEnumerable<ShaderDeclInfo> GetTextureUsage(long key)
{
if (_stages.TryGetValue(key, out OGLShaderStage stage)) return stage.TextureUsage;
if (_stages.TryGetValue(key, out OGLShaderStage stage))
{
return stage.TextureUsage;
}
return Enumerable.Empty<ShaderDeclInfo>();
}
@ -113,13 +122,21 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void Bind(long key)
{
if (_stages.TryGetValue(key, out OGLShaderStage stage)) Bind(stage);
if (_stages.TryGetValue(key, out OGLShaderStage stage))
{
Bind(stage);
}
}
private void Bind(OGLShaderStage stage)
{
if (stage.Type == GalShaderType.Geometry)
if (!OGLExtension.EnhancedLayouts) return;
{
if (!OGLExtension.EnhancedLayouts)
{
return;
}
}
switch (stage.Type)
{
@ -147,7 +164,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
if (Current.Vertex == null ||
Current.Fragment == null)
{
return;
}
if (!_programs.TryGetValue(Current, out int handle))
{
@ -209,16 +228,21 @@ namespace Ryujinx.Graphics.Gal.OpenGL
void BindUniformBlocksIfNotNull(OGLShaderStage stage)
{
if (stage != null)
{
foreach (ShaderDeclInfo declInfo in stage.ConstBufferUsage)
{
int blockIndex = GL.GetUniformBlockIndex(programHandle, declInfo.Name);
if (blockIndex < 0) throw new InvalidOperationException();
if (blockIndex < 0)
{
throw new InvalidOperationException();
}
GL.UniformBlockBinding(programHandle, blockIndex, freeBinding);
freeBinding++;
}
}
}
BindUniformBlocksIfNotNull(Current.Vertex);
@ -235,6 +259,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
void BindTexturesIfNotNull(OGLShaderStage stage)
{
if (stage != null)
{
foreach (ShaderDeclInfo decl in stage.TextureUsage)
{
int location = GL.GetUniformLocation(programHandle, decl.Name);
@ -243,6 +268,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
index++;
}
}
}
GL.UseProgram(programHandle);
@ -260,7 +286,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.GetProgram(handle, GetProgramParameterName.LinkStatus, out status);
if (status == 0) throw new ShaderException(GL.GetProgramInfoLog(handle));
if (status == 0)
{
throw new ShaderException(GL.GetProgramInfoLog(handle));
}
}
}
}

View file

@ -77,7 +77,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.GetShader(handle, ShaderParameter.CompileStatus, out status);
if (status == 0) throw new ShaderException(GL.GetShaderInfoLog(handle));
if (status == 0)
{
throw new ShaderException(GL.GetShaderInfoLog(handle));
}
}
}
}

View file

@ -43,7 +43,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
_textureCache.AddOrUpdate(key, new ImageHandler(handle, image), (uint)size);
if (ImageUtils.IsCompressed(image.Format)) throw new InvalidOperationException("Surfaces with compressed formats are not supported!");
if (ImageUtils.IsCompressed(image.Format))
{
throw new InvalidOperationException("Surfaces with compressed formats are not supported!");
}
(PixelInternalFormat internalFmt,
PixelFormat format,
@ -144,7 +147,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public bool TryGetImageHandler(long key, out ImageHandler cachedImage)
{
if (_textureCache.TryGetValue(key, out cachedImage)) return true;
if (_textureCache.TryGetValue(key, out cachedImage))
{
return true;
}
cachedImage = null;

View file

@ -108,13 +108,17 @@ namespace Ryujinx.Graphics.Gal.Shader
int index = 0;
for (int attachment = 0; attachment < 8; attachment++)
for (int component = 0; component < 4; component++)
if (header.OmapTargets[attachment].ComponentEnabled(component))
{
for (int component = 0; component < 4; component++)
{
if (header.OmapTargets[attachment].ComponentEnabled(component))
{
_gprs.TryAdd(index, new ShaderDeclInfo(GetGprName(index), index));
index++;
}
}
}
if (header.OmapDepth)
{
@ -128,7 +132,10 @@ namespace Ryujinx.Graphics.Gal.Shader
{
ShaderIrNode[] nodes = block.GetNodes();
foreach (ShaderIrNode node in nodes) Traverse(nodes, null, node);
foreach (ShaderIrNode node in nodes)
{
Traverse(nodes, null, node);
}
}
}
@ -146,15 +153,23 @@ namespace Ryujinx.Graphics.Gal.Shader
Merge(combined._preds, vpA._preds, vpB._preds);
//Merge input attributes.
foreach (KeyValuePair<int, ShaderDeclInfo> kv in vpA._inAttributes) combined._inAttributes.TryAdd(kv.Key, kv.Value);
foreach (KeyValuePair<int, ShaderDeclInfo> kv in vpA._inAttributes)
{
combined._inAttributes.TryAdd(kv.Key, kv.Value);
}
foreach (KeyValuePair<int, ShaderDeclInfo> kv in vpB._inAttributes)
//If Vertex Program A already writes to this attribute,
{
//If Vertex Program A already writes to this attribute,
//then we don't need to add it as an input attribute since
//Vertex Program A will already have written to it anyway,
//and there's no guarantee that there is an input attribute
//for this slot.
if (!vpA._outAttributes.ContainsKey(kv.Key)) combined._inAttributes.TryAdd(kv.Key, kv.Value);
if (!vpA._outAttributes.ContainsKey(kv.Key))
{
combined._inAttributes.TryAdd(kv.Key, kv.Value);
}
}
return combined;
}
@ -169,9 +184,15 @@ namespace Ryujinx.Graphics.Gal.Shader
Dictionary<int, ShaderDeclInfo> a,
Dictionary<int, ShaderDeclInfo> b)
{
foreach (KeyValuePair<int, ShaderDeclInfo> kv in a) c.TryAdd(kv.Key, kv.Value);
foreach (KeyValuePair<int, ShaderDeclInfo> kv in a)
{
c.TryAdd(kv.Key, kv.Value);
}
foreach (KeyValuePair<int, ShaderDeclInfo> kv in b) c.TryAdd(kv.Key, kv.Value);
foreach (KeyValuePair<int, ShaderDeclInfo> kv in b)
{
c.TryAdd(kv.Key, kv.Value);
}
}
private void Traverse(ShaderIrNode[] nodes, ShaderIrNode parent, ShaderIrNode node)
@ -223,13 +244,15 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrNode curr = nodes[index];
if (curr is ShaderIrAsg asg && asg.Dst is ShaderIrOperGpr gpr)
if (gpr.Index == ((ShaderIrOperGpr)op.OperandC).Index)
{
if (gpr.Index == ((ShaderIrOperGpr)op.OperandC).Index)
{
handleSrc = asg.Src;
break;
}
}
}
}
if (handleSrc != null && handleSrc is ShaderIrOperCbuf cbuf)
{
@ -268,16 +291,21 @@ namespace Ryujinx.Graphics.Gal.Shader
abuf.Offs == VertexIdAttr ||
abuf.Offs == InstanceIdAttr ||
abuf.Offs == FaceAttr)
break;
{
break;
}
int index = abuf.Offs >> 4;
int index = abuf.Offs >> 4;
int elem = (abuf.Offs >> 2) & 3;
int glslIndex = index - AttrStartIndex;
if (glslIndex < 0) return;
if (glslIndex < 0)
{
return;
}
ShaderDeclInfo declInfo;
ShaderDeclInfo declInfo;
if (parent is ShaderIrAsg asg && asg.Dst == node)
{
@ -344,7 +372,12 @@ namespace Ryujinx.Graphics.Gal.Shader
int vecIndex = index & ~3;
if (decls.TryGetValue(vecIndex, out ShaderDeclInfo declInfo))
if (declInfo.Size > 1 && index < vecIndex + declInfo.Size) return true;
{
if (declInfo.Size > 1 && index < vecIndex + declInfo.Size)
{
return true;
}
}
return decls.ContainsKey(index);
}

View file

@ -217,7 +217,10 @@ namespace Ryujinx.Graphics.Gal.Shader
private void PrintDeclTextures()
{
foreach (ShaderDeclInfo declInfo in IterateCbTextures()) _sb.AppendLine("uniform sampler2D " + declInfo.Name + ";");
foreach (ShaderDeclInfo declInfo in IterateCbTextures())
{
_sb.AppendLine("uniform sampler2D " + declInfo.Name + ";");
}
PrintDecls(_decl.Textures, "uniform sampler2D");
}
@ -227,7 +230,12 @@ namespace Ryujinx.Graphics.Gal.Shader
HashSet<string> names = new HashSet<string>();
foreach (ShaderDeclInfo declInfo in _decl.CbTextures.Values.OrderBy(DeclKeySelector))
if (names.Add(declInfo.Name)) yield return declInfo;
{
if (names.Add(declInfo.Name))
{
yield return declInfo;
}
}
}
private void PrintDeclUniforms()
@ -256,7 +264,10 @@ namespace Ryujinx.Graphics.Gal.Shader
_sb.AppendLine("};");
}
if (_decl.Uniforms.Count > 0) _sb.AppendLine();
if (_decl.Uniforms.Count > 0)
{
_sb.AppendLine();
}
}
private void PrintDeclAttributes()
@ -268,7 +279,10 @@ namespace Ryujinx.Graphics.Gal.Shader
private void PrintDeclInAttributes()
{
if (_decl.ShaderType == GalShaderType.Fragment) _sb.AppendLine("layout (location = " + GlslDecl.PositionOutAttrLocation + ") in vec4 " + GlslDecl.PositionOutAttrName + ";");
if (_decl.ShaderType == GalShaderType.Fragment)
{
_sb.AppendLine("layout (location = " + GlslDecl.PositionOutAttrLocation + ") in vec4 " + GlslDecl.PositionOutAttrName + ";");
}
if (_decl.ShaderType == GalShaderType.Geometry)
{
@ -277,7 +291,12 @@ namespace Ryujinx.Graphics.Gal.Shader
_sb.AppendLine("in Vertex {");
foreach (ShaderDeclInfo declInfo in _decl.InAttributes.Values.OrderBy(DeclKeySelector))
if (declInfo.Index >= 0) _sb.AppendLine(IdentationStr + "layout (location = " + declInfo.Index + ") vec4 " + declInfo.Name + "; ");
{
if (declInfo.Index >= 0)
{
_sb.AppendLine(IdentationStr + "layout (location = " + declInfo.Index + ") vec4 " + declInfo.Name + "; ");
}
}
_sb.AppendLine("} block_in[];" + Environment.NewLine);
}
@ -295,14 +314,19 @@ namespace Ryujinx.Graphics.Gal.Shader
int count = 0;
for (int attachment = 0; attachment < 8; attachment++)
{
if (_header.OmapTargets[attachment].Enabled)
{
_sb.AppendLine("layout (location = " + attachment + ") out vec4 " + GlslDecl.FragmentOutputName + attachment + ";");
count++;
}
}
if (count > 0) _sb.AppendLine();
if (count > 0)
{
_sb.AppendLine();
}
}
else
{
@ -318,14 +342,19 @@ namespace Ryujinx.Graphics.Gal.Shader
int count = 0;
foreach (ShaderDeclInfo declInfo in decls.OrderBy(DeclKeySelector))
{
if (declInfo.Index >= 0)
{
_sb.AppendLine("layout (location = " + declInfo.Index + ") " + inOut + " vec4 " + declInfo.Name + ";");
count++;
}
}
if (count > 0) _sb.AppendLine();
if (count > 0)
{
_sb.AppendLine();
}
}
private void PrintDeclGprs()
@ -352,16 +381,25 @@ namespace Ryujinx.Graphics.Gal.Shader
string name;
if (customType != null)
{
name = customType + " " + declInfo.Name + suffix + ";";
}
else if (declInfo.Name.Contains(GlslDecl.FragmentOutputName))
{
name = "layout (location = " + declInfo.Index / 4 + ") out vec4 " + declInfo.Name + suffix + ";";
}
else
{
name = GetDecl(declInfo) + suffix + ";";
}
_sb.AppendLine(name);
}
if (dict.Count > 0) _sb.AppendLine();
if (dict.Count > 0)
{
_sb.AppendLine();
}
}
private int DeclKeySelector(ShaderDeclInfo declInfo)
@ -372,9 +410,13 @@ namespace Ryujinx.Graphics.Gal.Shader
private string GetDecl(ShaderDeclInfo declInfo)
{
if (declInfo.Size == 4)
{
return "vec4 " + declInfo.Name;
}
else
{
return "float " + declInfo.Name;
}
}
private void PrintMain()
@ -383,11 +425,15 @@ namespace Ryujinx.Graphics.Gal.Shader
foreach (KeyValuePair<int, ShaderDeclInfo> kv in _decl.InAttributes)
{
if (!_decl.Attributes.TryGetValue(kv.Key, out ShaderDeclInfo attr)) continue;
if (!_decl.Attributes.TryGetValue(kv.Key, out ShaderDeclInfo attr))
{
continue;
}
ShaderDeclInfo declInfo = kv.Value;
if (_decl.ShaderType == GalShaderType.Geometry)
{
for (int vertex = 0; vertex < MaxVertexInput; vertex++)
{
string dst = attr.Name + "[" + vertex + "]";
@ -396,8 +442,11 @@ namespace Ryujinx.Graphics.Gal.Shader
_sb.AppendLine(IdentationStr + dst + " = " + src + ";");
}
}
else
{
_sb.AppendLine(IdentationStr + attr.Name + " = " + declInfo.Name + ";");
}
}
_sb.AppendLine(IdentationStr + "uint pc;");
@ -412,11 +461,17 @@ namespace Ryujinx.Graphics.Gal.Shader
PrintProgram(_blocks, GlslDecl.BasicBlockName);
}
if (_decl.ShaderType != GalShaderType.Geometry) PrintAttrToOutput();
if (_decl.ShaderType != GalShaderType.Geometry)
{
PrintAttrToOutput();
}
if (_decl.ShaderType == GalShaderType.Fragment)
{
if (_header.OmapDepth) _sb.AppendLine(IdentationStr + "gl_FragDepth = " + GlslDecl.GetGprName(_header.DepthRegister) + ";");
if (_header.OmapDepth)
{
_sb.AppendLine(IdentationStr + "gl_FragDepth = " + GlslDecl.GetGprName(_header.DepthRegister) + ";");
}
int gprIndex = 0;
@ -427,12 +482,14 @@ namespace Ryujinx.Graphics.Gal.Shader
OmapTarget target = _header.OmapTargets[attachment];
for (int component = 0; component < 4; component++)
{
if (target.ComponentEnabled(component))
{
_sb.AppendLine(IdentationStr + output + "[" + component + "] = " + GlslDecl.GetGprName(gprIndex) + ";");
gprIndex++;
}
}
}
}
@ -469,18 +526,27 @@ namespace Ryujinx.Graphics.Gal.Shader
{
foreach (KeyValuePair<int, ShaderDeclInfo> kv in _decl.OutAttributes)
{
if (!_decl.Attributes.TryGetValue(kv.Key, out ShaderDeclInfo attr)) continue;
if (!_decl.Attributes.TryGetValue(kv.Key, out ShaderDeclInfo attr))
{
continue;
}
ShaderDeclInfo declInfo = kv.Value;
string name = attr.Name;
if (_decl.ShaderType == GalShaderType.Geometry) name += "[0]";
if (_decl.ShaderType == GalShaderType.Geometry)
{
name += "[0]";
}
_sb.AppendLine(identation + declInfo.Name + " = " + name + ";");
}
if (_decl.ShaderType == GalShaderType.Vertex) _sb.AppendLine(identation + "gl_Position.xy *= " + GlslDecl.FlipUniformName + ";");
if (_decl.ShaderType == GalShaderType.Vertex)
{
_sb.AppendLine(identation + "gl_Position.xy *= " + GlslDecl.FlipUniformName + ";");
}
if (_decl.ShaderType != GalShaderType.Fragment)
{
@ -503,7 +569,10 @@ namespace Ryujinx.Graphics.Gal.Shader
private void PrintNodes(ShaderIrBlock block, ShaderIrNode[] nodes)
{
foreach (ShaderIrNode node in nodes) PrintNode(block, node, IdentationStr);
foreach (ShaderIrNode node in nodes)
{
PrintNode(block, node, IdentationStr);
}
if (nodes.Length == 0)
{
@ -517,6 +586,7 @@ namespace Ryujinx.Graphics.Gal.Shader
bool unconditionalFlowChange = false;
if (last is ShaderIrOp op)
{
switch (op.Inst)
{
case ShaderIrInst.Bra:
@ -525,13 +595,18 @@ namespace Ryujinx.Graphics.Gal.Shader
unconditionalFlowChange = true;
break;
}
}
if (!unconditionalFlowChange)
{
if (block.Next != null)
{
_sb.AppendLine(IdentationStr + "return " + GetBlockPosition(block.Next) + ";");
}
else
{
_sb.AppendLine(IdentationStr + "return 0u;");
}
}
}
@ -541,7 +616,10 @@ namespace Ryujinx.Graphics.Gal.Shader
{
string ifExpr = GetSrcExpr(cond.Pred, true);
if (cond.Not) ifExpr = "!(" + ifExpr + ")";
if (cond.Not)
{
ifExpr = "!(" + ifExpr + ")";
}
_sb.AppendLine(identation + "if (" + ifExpr + ") {");
@ -625,8 +703,13 @@ namespace Ryujinx.Graphics.Gal.Shader
private bool IsValidOutOper(ShaderIrNode node)
{
if (node is ShaderIrOperGpr gpr && gpr.IsConst)
{
return false;
else if (node is ShaderIrOperPred pred && pred.IsConst) return false;
}
else if (node is ShaderIrOperPred pred && pred.IsConst)
{
return false;
}
return true;
}
@ -634,10 +717,17 @@ namespace Ryujinx.Graphics.Gal.Shader
private string GetDstOperName(ShaderIrNode node)
{
if (node is ShaderIrOperAbuf abuf)
{
return GetOutAbufName(abuf);
}
else if (node is ShaderIrOperGpr gpr)
{
return GetName(gpr);
else if (node is ShaderIrOperPred pred) return GetName(pred);
}
else if (node is ShaderIrOperPred pred)
{
return GetName(pred);
}
throw new ArgumentException(nameof(node));
}
@ -657,11 +747,18 @@ namespace Ryujinx.Graphics.Gal.Shader
string expr;
if (_instsExpr.TryGetValue(op.Inst, out GetInstExpr getExpr))
{
expr = getExpr(op);
}
else
{
throw new NotImplementedException(op.Inst.ToString());
}
if (!entry && NeedsParentheses(op)) expr = "(" + expr + ")";
if (!entry && NeedsParentheses(op))
{
expr = "(" + expr + ")";
}
return expr;
@ -685,7 +782,10 @@ namespace Ryujinx.Graphics.Gal.Shader
private string GetName(ShaderIrOperCbuf cbuf)
{
if (!_decl.Uniforms.TryGetValue(cbuf.Index, out ShaderDeclInfo declInfo)) throw new InvalidOperationException();
if (!_decl.Uniforms.TryGetValue(cbuf.Index, out ShaderDeclInfo declInfo))
{
throw new InvalidOperationException();
}
if (cbuf.Offs != null)
{
@ -704,10 +804,12 @@ namespace Ryujinx.Graphics.Gal.Shader
private string GetOutAbufName(ShaderIrOperAbuf abuf)
{
if (_decl.ShaderType == GalShaderType.Geometry)
{
switch (abuf.Offs)
{
case GlslDecl.LayerAttr: return "gl_Layer";
}
}
return GetAttrTempName(abuf);
}
@ -716,19 +818,24 @@ namespace Ryujinx.Graphics.Gal.Shader
{
//Handle special scalar read-only attributes here.
if (_decl.ShaderType == GalShaderType.Vertex)
{
switch (abuf.Offs)
{
case GlslDecl.VertexIdAttr: return "gl_VertexID";
case GlslDecl.InstanceIdAttr: return GlslDecl.InstanceUniformName;
}
}
else if (_decl.ShaderType == GalShaderType.TessEvaluation)
{
switch (abuf.Offs)
{
case GlslDecl.TessCoordAttrX: return "gl_TessCoord.x";
case GlslDecl.TessCoordAttrY: return "gl_TessCoord.y";
case GlslDecl.TessCoordAttrZ: return "gl_TessCoord.z";
}
}
else if (_decl.ShaderType == GalShaderType.Fragment)
{
switch (abuf.Offs)
{
case GlslDecl.PointCoordAttrX: return "gl_PointCoord.x";
@ -737,6 +844,7 @@ namespace Ryujinx.Graphics.Gal.Shader
//Note: It's a guess that Maxwell's face is 1 when gl_FrontFacing == true
case GlslDecl.FaceAttr: return "(gl_FrontFacing ? 1 : 0)";
}
}
return GetAttrTempName(abuf);
}
@ -766,7 +874,10 @@ namespace Ryujinx.Graphics.Gal.Shader
}
}
if (declInfo.Index >= 16) throw new InvalidOperationException($"Shader attribute offset {abuf.Offs} is invalid.");
if (declInfo.Index >= 16)
{
throw new InvalidOperationException($"Shader attribute offset {abuf.Offs} is invalid.");
}
if (_decl.ShaderType == GalShaderType.Geometry)
{
@ -790,9 +901,13 @@ namespace Ryujinx.Graphics.Gal.Shader
//Only use hex is the value is too big and would likely be hard to read as int.
if (imm.Value > 0xfff ||
imm.Value < -0xfff)
{
return "0x" + imm.Value.ToString("x8", CultureInfo.InvariantCulture);
}
else
{
return GetIntConst(imm.Value);
}
}
private string GetValue(ShaderIrOperImmf immf)
@ -810,9 +925,17 @@ namespace Ryujinx.Graphics.Gal.Shader
int vecIndex = index & ~3;
if (dict.TryGetValue(vecIndex, out ShaderDeclInfo declInfo))
if (declInfo.Size > 1 && index < vecIndex + declInfo.Size) return declInfo.Name + "." + GetAttrSwizzle(index & 3);
{
if (declInfo.Size > 1 && index < vecIndex + declInfo.Size)
{
return declInfo.Name + "." + GetAttrSwizzle(index & 3);
}
}
if (!dict.TryGetValue(index, out declInfo)) throw new InvalidOperationException();
if (!dict.TryGetValue(index, out declInfo))
{
throw new InvalidOperationException();
}
return declInfo.Name;
}
@ -1033,6 +1156,7 @@ namespace Ryujinx.Graphics.Gal.Shader
int elem = (abuf.Offs >> 2) & 3;
if (_decl.ShaderType == GalShaderType.Fragment && index == GlslDecl.GlPositionVec4Index)
{
switch (elem)
{
case 0: return "gl_FragCoord.x";
@ -1040,6 +1164,7 @@ namespace Ryujinx.Graphics.Gal.Shader
case 2: return "gl_FragCoord.z";
case 3: return "1";
}
}
}
return GetSrcExpr(op.OperandA);
@ -1105,7 +1230,10 @@ namespace Ryujinx.Graphics.Gal.Shader
{
ShaderIrMetaTex meta = (ShaderIrMetaTex)op.MetaData;
if (!_decl.CbTextures.TryGetValue(op, out ShaderDeclInfo declInfo)) throw new InvalidOperationException();
if (!_decl.CbTextures.TryGetValue(op, out ShaderDeclInfo declInfo))
{
throw new InvalidOperationException();
}
string coords = GetTexSamplerCoords(op);
@ -1229,7 +1357,10 @@ namespace Ryujinx.Graphics.Gal.Shader
int handle = ((ShaderIrOperImm)op.OperandC).Value;
if (!_decl.Textures.TryGetValue(handle, out ShaderDeclInfo declInfo)) throw new InvalidOperationException();
if (!_decl.Textures.TryGetValue(handle, out ShaderDeclInfo declInfo))
{
throw new InvalidOperationException();
}
return declInfo.Name;
}
@ -1266,7 +1397,9 @@ namespace Ryujinx.Graphics.Gal.Shader
//(like bool to int/float and others).
if (srcType != OperType.F32 &&
srcType != OperType.I32)
{
throw new InvalidOperationException();
}
switch (src)
{
@ -1274,8 +1407,12 @@ namespace Ryujinx.Graphics.Gal.Shader
{
//When the Gpr is ZR, just return the 0 value directly,
//since the float encoding for 0 is 0.
if (gpr.IsConst) return "0";
break;
if (gpr.IsConst)
{
return "0";
}
break;
}
case ShaderIrOperImm imm:
@ -1286,8 +1423,11 @@ namespace Ryujinx.Graphics.Gal.Shader
{
float value = BitConverter.Int32BitsToSingle(imm.Value);
if (!float.IsNaN(value) && !float.IsInfinity(value)) return GetFloatConst(value);
}
if (!float.IsNaN(value) && !float.IsInfinity(value))
{
return GetFloatConst(value);
}
}
break;
}
}
@ -1321,6 +1461,7 @@ namespace Ryujinx.Graphics.Gal.Shader
//Special case instructions with the result type different
//from the input types (like integer <-> float conversion) here.
if (node is ShaderIrOp op)
{
switch (op.Inst)
{
case ShaderIrInst.Stof:
@ -1332,6 +1473,7 @@ namespace Ryujinx.Graphics.Gal.Shader
case ShaderIrInst.Ftou:
return OperType.I32;
}
}
return GetSrcNodeType(node);
}
@ -1357,13 +1499,20 @@ namespace Ryujinx.Graphics.Gal.Shader
case ShaderIrOp op:
if (op.Inst > ShaderIrInst.BStart &&
op.Inst < ShaderIrInst.BEnd)
{
return OperType.Bool;
}
else if (op.Inst > ShaderIrInst.FStart &&
op.Inst < ShaderIrInst.FEnd)
{
return OperType.F32;
}
else if (op.Inst > ShaderIrInst.Start &&
op.Inst < ShaderIrInst.End)
{
return OperType.I32;
}
break;
}
@ -1373,9 +1522,13 @@ namespace Ryujinx.Graphics.Gal.Shader
private static string GetBlockPosition(ShaderIrBlock block)
{
if (block != null)
{
return "0x" + block.Position.ToString("x8") + "u";
}
else
{
return "0u";
}
}
}
}

View file

@ -351,9 +351,15 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrNode operA = opCode.Pred12();
ShaderIrNode operB = opCode.Pred29();
if (negA) operA = new ShaderIrOp(ShaderIrInst.Bnot, operA);
if (negA)
{
operA = new ShaderIrOp(ShaderIrInst.Bnot, operA);
}
if (negB) operB = new ShaderIrOp(ShaderIrInst.Bnot, operB);
if (negB)
{
operB = new ShaderIrOp(ShaderIrInst.Bnot, operB);
}
ShaderIrOp op = new ShaderIrOp(lopInst, operA, operB);
@ -365,11 +371,17 @@ namespace Ryujinx.Graphics.Gal.Shader
lopInst = opCode.BLop45();
if (lopInst == ShaderIrInst.Band && p1Node.IsConst && p2Node.IsConst) return;
if (lopInst == ShaderIrInst.Band && p1Node.IsConst && p2Node.IsConst)
{
return;
}
ShaderIrNode p2NNode = p2Node;
if (negP) p2NNode = new ShaderIrOp(ShaderIrInst.Bnot, p2NNode);
if (negP)
{
p2NNode = new ShaderIrOp(ShaderIrInst.Bnot, p2NNode);
}
op = new ShaderIrOp(ShaderIrInst.Bnot, p0Node);
@ -441,9 +453,13 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrNode operB;
if (opCode.Read(50))
{
operB = opCode.Gpr20();
}
else
{
operB = opCode.Imm19_20();
}
ShaderIrOperGpr operC = opCode.Gpr39();
@ -635,9 +651,13 @@ namespace Ryujinx.Graphics.Gal.Shader
operB = GetAluFneg(operB, negB);
if (oper == ShaderOper.Rc)
{
operC = GetAluFneg(opCode.Cbuf34(), negC);
}
else
{
operC = GetAluFneg(opCode.Gpr39(), negC);
}
ShaderIrOp op = new ShaderIrOp(ShaderIrInst.Ffma, operA, operB, operC);
@ -694,7 +714,10 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrNode ApplyHeight(ShaderIrNode src, int height)
{
if (oper != ShaderOper.Rr) return src;
if (oper != ShaderOper.Rr)
{
return src;
}
switch (height)
{
@ -713,11 +736,13 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrOp sum = new ShaderIrOp(ShaderIrInst.Add, src1, src2);
if (oper == ShaderOper.Rr)
{
switch (mode)
{
case 1: sum = new ShaderIrOp(ShaderIrInst.Lsr, sum, new ShaderIrOperImm(16)); break;
case 2: sum = new ShaderIrOp(ShaderIrInst.Lsl, sum, new ShaderIrOperImm(16)); break;
}
}
//Note: Here there should be a "+ 1" when carry flag is set
//but since carry is mostly ignored by other instructions, it's excluded for now
@ -772,9 +797,13 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrNode operA = opCode.Gpr8(), operB;
if (isFloat)
{
operA = GetAluFabsFneg(operA, absA, negA);
}
else
{
operA = GetAluIabsIneg(operA, absA, negA);
}
switch (oper)
{
@ -787,9 +816,13 @@ namespace Ryujinx.Graphics.Gal.Shader
}
if (isFloat)
{
operB = GetAluFabsFneg(operB, absB, negB);
}
else
{
operB = GetAluIabsIneg(operB, absB, negB);
}
ShaderIrOperPred pred = opCode.Pred39();
@ -985,11 +1018,17 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrInst lopInst = opCode.BLop45();
if (lopInst == ShaderIrInst.Band && p1Node.IsConst && p2Node.IsConst) return;
if (lopInst == ShaderIrInst.Band && p1Node.IsConst && p2Node.IsConst)
{
return;
}
ShaderIrNode p2NNode = p2Node;
if (negP) p2NNode = new ShaderIrOp(ShaderIrInst.Bnot, p2NNode);
if (negP)
{
p2NNode = new ShaderIrOp(ShaderIrInst.Bnot, p2NNode);
}
op = new ShaderIrOp(ShaderIrInst.Bnot, p0Node);
@ -1035,9 +1074,13 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrNode op;
if (subOp < 3)
{
op = new ShaderIrOp(inst, operA, operB);
}
else
{
op = operB;
}
ShaderIrNode compare = new ShaderIrOp(ShaderIrInst.Cne, op, new ShaderIrOperImm(0));
@ -1065,7 +1108,10 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrInst shiftAb = signAb ? ShaderIrInst.Asr : ShaderIrInst.Lsr;
ShaderIrInst shiftC = signC ? ShaderIrInst.Asr : ShaderIrInst.Lsr;
if (highA) operA = new ShaderIrOp(shiftAb, operA, imm16);
if (highA)
{
operA = new ShaderIrOp(shiftAb, operA, imm16);
}
switch (oper)
{
@ -1102,11 +1148,17 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrNode operBh = operB;
if (highB) operBh = new ShaderIrOp(shiftAb, operBh, imm16);
if (highB)
{
operBh = new ShaderIrOp(shiftAb, operBh, imm16);
}
ShaderIrOp mulOp = new ShaderIrOp(ShaderIrInst.Mul, operA, operBh);
if (productShiftLeft) mulOp = new ShaderIrOp(ShaderIrInst.Lsl, mulOp, imm16);
if (productShiftLeft)
{
mulOp = new ShaderIrOp(ShaderIrInst.Lsl, mulOp, imm16);
}
ShaderIrOp addOp = new ShaderIrOp(ShaderIrInst.Add, mulOp, operC);

View file

@ -6,7 +6,10 @@ namespace Ryujinx.Graphics.Gal.Shader
{
public static void Bra(ShaderIrBlock block, long opCode, int position)
{
if ((opCode & 0x20) != 0) throw new NotImplementedException();
if ((opCode & 0x20) != 0)
{
throw new NotImplementedException();
}
ShaderIrOperImm imm = new ShaderIrOperImm(position + opCode.Branch());
@ -18,7 +21,10 @@ namespace Ryujinx.Graphics.Gal.Shader
int cCode = (int)opCode & 0x1f;
//TODO: Figure out what the other condition codes mean...
if (cCode == 0xf) block.AddNode(opCode.PredNode(new ShaderIrOp(ShaderIrInst.Exit)));
if (cCode == 0xf)
{
block.AddNode(opCode.PredNode(new ShaderIrOp(ShaderIrInst.Exit)));
}
}
public static void Kil(ShaderIrBlock block, long opCode, int position)
@ -28,7 +34,10 @@ namespace Ryujinx.Graphics.Gal.Shader
public static void Ssy(ShaderIrBlock block, long opCode, int position)
{
if ((opCode & 0x20) != 0) throw new NotImplementedException();
if ((opCode & 0x20) != 0)
{
throw new NotImplementedException();
}
ShaderIrOperImm imm = new ShaderIrOperImm(position + opCode.Branch());

View file

@ -56,7 +56,10 @@ namespace Ryujinx.Graphics.Gal.Shader
int cbufIndex = opCode.Read(36, 0x1f);
int type = opCode.Read(48, 7);
if (type > 5) throw new InvalidOperationException();
if (type > 5)
{
throw new InvalidOperationException();
}
ShaderIrOperGpr temp = ShaderIrOperGpr.MakeTemporary();
@ -73,7 +76,10 @@ namespace Ryujinx.Graphics.Gal.Shader
operA.Pos += index;
operD.Index += index;
if (!operD.IsValidRegister) break;
if (!operD.IsValidRegister)
{
break;
}
ShaderIrNode node = operA;
@ -147,7 +153,10 @@ namespace Ryujinx.Graphics.Gal.Shader
coords[index].Index += index;
if (coords[index].Index > ShaderIrOperGpr.ZrIndex) coords[index].Index = ShaderIrOperGpr.ZrIndex;
if (coords[index].Index > ShaderIrOperGpr.ZrIndex)
{
coords[index].Index = ShaderIrOperGpr.ZrIndex;
}
}
int chMask = opCode.Read(31, 0xf);
@ -173,7 +182,10 @@ namespace Ryujinx.Graphics.Gal.Shader
for (int ch = 0; ch < 4; ch++)
{
if (!IsChannelUsed(chMask, ch)) continue;
if (!IsChannelUsed(chMask, ch))
{
continue;
}
ShaderIrOperGpr src = new ShaderIrOperGpr(TempRegStart + ch);
@ -181,7 +193,10 @@ namespace Ryujinx.Graphics.Gal.Shader
dst.Index += regInc++;
if (dst.Index >= ShaderIrOperGpr.ZrIndex) continue;
if (dst.Index >= ShaderIrOperGpr.ZrIndex)
{
continue;
}
block.AddNode(opCode.PredNode(new ShaderIrAsg(dst, src)));
}
@ -209,7 +224,10 @@ namespace Ryujinx.Graphics.Gal.Shader
lutIndex = opCode.Gpr0 ().Index != ShaderIrOperGpr.ZrIndex ? 1 : 0;
lutIndex |= opCode.Gpr28().Index != ShaderIrOperGpr.ZrIndex ? 2 : 0;
if (lutIndex == 0) return;
if (lutIndex == 0)
{
return;
}
int chMask = _maskLut[lutIndex, opCode.Read(50, 7)];
@ -248,13 +266,19 @@ namespace Ryujinx.Graphics.Gal.Shader
for (int ch = 0; ch < 4; ch++)
{
if (!IsChannelUsed(chMask, ch)) continue;
if (!IsChannelUsed(chMask, ch))
{
continue;
}
ShaderIrOperGpr src = new ShaderIrOperGpr(TempRegStart + ch);
ShaderIrOperGpr dst = GetDst();
if (dst.Index != ShaderIrOperGpr.ZrIndex) block.AddNode(opCode.PredNode(new ShaderIrAsg(dst, src)));
if (dst.Index != ShaderIrOperGpr.ZrIndex)
{
block.AddNode(opCode.PredNode(new ShaderIrAsg(dst, src)));
}
}
}

View file

@ -168,7 +168,10 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrInst roundInst = GetRoundInst(opCode);
if (roundInst != ShaderIrInst.Invalid) operA = new ShaderIrOp(roundInst, operA);
if (roundInst != ShaderIrInst.Invalid)
{
operA = new ShaderIrOp(roundInst, operA);
}
block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), operA)));
}
@ -179,7 +182,9 @@ namespace Ryujinx.Graphics.Gal.Shader
if (type == IntType.U64 ||
type == IntType.S64)
{
throw new NotImplementedException();
}
bool negA = opCode.Read(45);
bool absA = opCode.Read(49);
@ -199,7 +204,10 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrInst roundInst = GetRoundInst(opCode);
if (roundInst != ShaderIrInst.Invalid) operA = new ShaderIrOp(roundInst, operA);
if (roundInst != ShaderIrInst.Invalid)
{
operA = new ShaderIrOp(roundInst, operA);
}
bool signed = type >= IntType.S8;
@ -241,7 +249,9 @@ namespace Ryujinx.Graphics.Gal.Shader
if (type == IntType.U64 ||
type == IntType.S64)
{
throw new NotImplementedException();
}
int sel = opCode.Read(41, 3);
@ -267,9 +277,15 @@ namespace Ryujinx.Graphics.Gal.Shader
int size = 8 << ((int)type & 3);
if (shift != 0) operA = new ShaderIrOp(ShaderIrInst.Asr, operA, new ShaderIrOperImm(shift));
if (shift != 0)
{
operA = new ShaderIrOp(ShaderIrInst.Asr, operA, new ShaderIrOperImm(shift));
}
if (size < 32) operA = ExtendTo32(operA, signed, size);
if (size < 32)
{
operA = ExtendTo32(operA, signed, size);
}
ShaderIrInst inst = signed
? ShaderIrInst.Stof
@ -286,7 +302,9 @@ namespace Ryujinx.Graphics.Gal.Shader
if (type == IntType.U64 ||
type == IntType.S64)
{
throw new NotImplementedException();
}
int sel = opCode.Read(41, 3);
@ -313,7 +331,10 @@ namespace Ryujinx.Graphics.Gal.Shader
int size = 8 << ((int)type & 3);
if (shift != 0) operA = new ShaderIrOp(ShaderIrInst.Asr, operA, new ShaderIrOperImm(shift));
if (shift != 0)
{
operA = new ShaderIrOp(ShaderIrInst.Asr, operA, new ShaderIrOperImm(shift));
}
if (size < 32)
{
@ -376,7 +397,10 @@ namespace Ryujinx.Graphics.Gal.Shader
IntType type = (IntType)opCode.Read(10, 3);
if (signed) type += (int)IntType.S8;
if (signed)
{
type += (int)IntType.S8;
}
return type;
}

View file

@ -28,7 +28,10 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrOperAbuf[] opers = new ShaderIrOperAbuf[size + 1];
for (int index = 0; index <= size; index++) opers[index] = new ShaderIrOperAbuf(abuf + index * 4, vertex);
for (int index = 0; index <= size; index++)
{
opers[index] = new ShaderIrOperAbuf(abuf + index * 4, vertex);
}
return opers;
}
@ -98,7 +101,10 @@ namespace Ryujinx.Graphics.Gal.Shader
bool neg = opCode.Read(56);
if (neg) value = -value;
if (neg)
{
value = -value;
}
return new ShaderIrOperImm(value);
}
@ -111,7 +117,10 @@ namespace Ryujinx.Graphics.Gal.Shader
imm <<= 12;
if (neg) imm |= 0x80000000;
if (neg)
{
imm |= 0x80000000;
}
float value = BitConverter.Int32BitsToSingle((int)imm);
@ -142,7 +151,10 @@ namespace Ryujinx.Graphics.Gal.Shader
{
ShaderIrNode node = opCode.Pred39();
if (opCode.Read(42)) node = new ShaderIrOp(ShaderIrInst.Bnot, node);
if (opCode.Read(42))
{
node = new ShaderIrOp(ShaderIrInst.Bnot, node);
}
return node;
}
@ -237,7 +249,10 @@ namespace Ryujinx.Graphics.Gal.Shader
{
int pred = opCode.Read(16, 0xf);
if (pred != 0xf) pred &= 7;
if (pred != 0xf)
{
pred &= 7;
}
return new ShaderIrOperPred(pred);
}

View file

@ -11,9 +11,15 @@
int type = opCode.Read(39, 3);
if ((type & 1) != 0) block.AddNode(opCode.PredNode(new ShaderIrOp(ShaderIrInst.Emit)));
if ((type & 1) != 0)
{
block.AddNode(opCode.PredNode(new ShaderIrOp(ShaderIrInst.Emit)));
}
if ((type & 2) != 0) block.AddNode(opCode.PredNode(new ShaderIrOp(ShaderIrInst.Cut)));
if ((type & 2) != 0)
{
block.AddNode(opCode.PredNode(new ShaderIrOp(ShaderIrInst.Cut)));
}
}
}
}

View file

@ -28,7 +28,10 @@ namespace Ryujinx.Graphics.Gal.Shader
visited.Add(position, output);
}
if (source != null) output.Sources.Add(source);
if (source != null)
{
output.Sources.Add(source);
}
return output;
}
@ -70,7 +73,10 @@ namespace Ryujinx.Graphics.Gal.Shader
}
}
if (NodeHasNext(lastNode)) current.Next = Enqueue(current.EndPosition);
if (NodeHasNext(lastNode))
{
current.Next = Enqueue(current.EndPosition);
}
}
//If we have on the graph two blocks with the same end position,
@ -109,8 +115,12 @@ namespace Ryujinx.Graphics.Gal.Shader
uint firstPos = uint.MaxValue;
foreach (ShaderIrBlock block in visited.Values)
{
if (firstPos > (uint)block.Position)
{
firstPos = (uint)block.Position;
}
}
ShaderIrBlock current = visited[(int)firstPos];
@ -169,7 +179,10 @@ namespace Ryujinx.Graphics.Gal.Shader
block.AddNode(new ShaderIrCmnt(dbgOpCode));
}
if (decode == null) continue;
if (decode == null)
{
continue;
}
decode(block, opCode, position);
}
@ -185,14 +198,20 @@ namespace Ryujinx.Graphics.Gal.Shader
private static ShaderIrOp GetInnermostOp(ShaderIrNode node)
{
if (node is ShaderIrCond cond) node = cond.Child;
if (node is ShaderIrCond cond)
{
node = cond.Child;
}
return node is ShaderIrOp op ? op : null;
}
private static bool NodeHasNext(ShaderIrNode node)
{
if (!(node is ShaderIrOp op)) return true;
if (!(node is ShaderIrOp op))
{
return true;
}
return op.Inst != ShaderIrInst.Exit &&
op.Inst != ShaderIrInst.Bra;

View file

@ -121,8 +121,15 @@ namespace Ryujinx.Graphics.Gal.Shader
int count = 0;
for (int index = 0; index < OmapTargets.Length; index++)
for (int component = 0; component < 4; component++)
if (OmapTargets[index].ComponentEnabled(component)) count++;
{
for (int component = 0; component < 4; component++)
{
if (OmapTargets[index].ComponentEnabled(component))
{
count++;
}
}
}
// Depth register is always two registers after the last color output
return count + 1;

View file

@ -35,7 +35,10 @@ namespace Ryujinx.Graphics.Gal.Shader
public ShaderIrNode GetLastNode()
{
if (Nodes.Count > 0) return Nodes[Nodes.Count - 1];
if (Nodes.Count > 0)
{
return Nodes[Nodes.Count - 1];
}
return null;
}

View file

@ -130,7 +130,10 @@ namespace Ryujinx.Graphics.Gal.Shader
private static void Set(string encoding, ShaderDecodeFunc func)
{
if (encoding.Length != EncodingBits) throw new ArgumentException(nameof(encoding));
if (encoding.Length != EncodingBits)
{
throw new ArgumentException(nameof(encoding));
}
int bit = encoding.Length - 1;
int value = 0;
@ -163,9 +166,15 @@ namespace Ryujinx.Graphics.Gal.Shader
{
value &= xMask;
for (int x = 0; x < xBits; x++) value |= ((index >> x) & 1) << xPos[x];
for (int x = 0; x < xBits; x++)
{
value |= ((index >> x) & 1) << xPos[x];
}
if (_opCodes[value] == null || _opCodes[value].XBits > xBits) _opCodes[value] = entry;
if (_opCodes[value] == null || _opCodes[value].XBits > xBits)
{
_opCodes[value] = entry;
}
}
}

View file

@ -25,7 +25,10 @@ namespace Ryujinx.Graphics.Gal
internal void Enlarge(int newSize)
{
if (Size < newSize) Size = newSize;
if (Size < newSize)
{
Size = newSize;
}
}
}
}

View file

@ -11,7 +11,10 @@ namespace Ryujinx.Graphics.Gal
public static void Dump(IGalMemory memory, long position, GalShaderType type, string extSuffix = "")
{
if (!IsDumpEnabled()) return;
if (!IsDumpEnabled())
{
return;
}
string fileName = "Shader" + DumpIndex.ToString("d4") + "." + ShaderExtension(type) + extSuffix + ".bin";
@ -26,7 +29,10 @@ namespace Ryujinx.Graphics.Gal
BinaryWriter fullWriter = new BinaryWriter(fullFile);
BinaryWriter codeWriter = new BinaryWriter(codeFile);
for (long i = 0; i < 0x50; i += 4) fullWriter.Write(memory.ReadInt32(position + i));
for (long i = 0; i < 0x50; i += 4)
{
fullWriter.Write(memory.ReadInt32(position + i));
}
long offset = 0;
@ -42,7 +48,10 @@ namespace Ryujinx.Graphics.Gal
//Zero instructions (other kind of NOP) stop immediatly,
//this is to avoid two rows of zeroes
if (instruction == 0) break;
if (instruction == 0)
{
break;
}
fullWriter.Write(instruction);
codeWriter.Write(instruction);
@ -98,7 +107,10 @@ namespace Ryujinx.Graphics.Gal
private static string CreateAndReturn(string dir)
{
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
return dir;
}

View file

@ -27,7 +27,10 @@ namespace Ryujinx.Graphics
_uploadedKeys = new HashSet<long>[(int)NvGpuBufferType.Count];
for (int index = 0; index < _uploadedKeys.Length; index++) _uploadedKeys[index] = new HashSet<long>();
for (int index = 0; index < _uploadedKeys.Length; index++)
{
_uploadedKeys[index] = new HashSet<long>();
}
_imageTypes = new Dictionary<long, ImageType>();
}
@ -38,7 +41,10 @@ namespace Ryujinx.Graphics
_imageTypes[position] = ImageType.ColorBuffer;
if (!TryReuse(vmm, position, newImage)) _gpu.Renderer.Texture.Create(position, (int)size, newImage);
if (!TryReuse(vmm, position, newImage))
{
_gpu.Renderer.Texture.Create(position, (int)size, newImage);
}
_gpu.Renderer.RenderTarget.BindColor(position, attachment);
}
@ -49,7 +55,10 @@ namespace Ryujinx.Graphics
_imageTypes[position] = ImageType.ZetaBuffer;
if (!TryReuse(vmm, position, newImage)) _gpu.Renderer.Texture.Create(position, (int)size, newImage);
if (!TryReuse(vmm, position, newImage))
{
_gpu.Renderer.Texture.Create(position, (int)size, newImage);
}
_gpu.Renderer.RenderTarget.BindZeta(position);
}
@ -58,7 +67,10 @@ namespace Ryujinx.Graphics
{
PrepareSendTexture(vmm, position, newImage);
if (texIndex >= 0) _gpu.Renderer.Texture.Bind(position, texIndex, newImage);
if (texIndex >= 0)
{
_gpu.Renderer.Texture.Bind(position, texIndex, newImage);
}
_imageTypes[position] = ImageType.Texture;
}
@ -70,6 +82,7 @@ namespace Ryujinx.Graphics
bool skipCheck = false;
if (_imageTypes.TryGetValue(position, out ImageType oldType))
{
if (oldType == ImageType.ColorBuffer || oldType == ImageType.ZetaBuffer)
{
//Avoid data destruction
@ -77,9 +90,15 @@ namespace Ryujinx.Graphics
skipCheck = true;
}
}
if (skipCheck || !MemoryRegionModified(vmm, position, size, NvGpuBufferType.Texture))
if (TryReuse(vmm, position, newImage)) return;
{
if (TryReuse(vmm, position, newImage))
{
return;
}
}
byte[] data = ImageUtils.ReadTexture(vmm, newImage, position);
@ -102,14 +121,20 @@ namespace Ryujinx.Graphics
{
HashSet<long> uploaded = _uploadedKeys[(int)type];
if (!uploaded.Add(position)) return false;
if (!uploaded.Add(position))
{
return false;
}
return vmm.IsRegionModified(position, size, type);
}
public void ClearPbCache()
{
for (int index = 0; index < _uploadedKeys.Length; index++) _uploadedKeys[index].Clear();
for (int index = 0; index < _uploadedKeys.Length; index++)
{
_uploadedKeys[index].Clear();
}
}
}
}

View file

@ -79,7 +79,10 @@ namespace Ryujinx.Graphics
FetchOpCode(mme);
while (Step(vmm, mme));
while (Step(vmm, mme))
{
;
}
//Due to the delay slot, we still need to execute
//one more instruction before we actually exit.
@ -88,7 +91,10 @@ namespace Ryujinx.Graphics
private void Reset()
{
for (int index = 0; index < _gprs.Length; index++) _gprs[index] = 0;
for (int index = 0; index < _gprs.Length; index++)
{
_gprs[index] = 0;
}
_methAddr = 0;
_methIncr = 0;
@ -207,7 +213,10 @@ namespace Ryujinx.Graphics
bool noDelays = (_opCode & 0x20) != 0;
if (noDelays) FetchOpCode(mme);
if (noDelays)
{
FetchOpCode(mme);
}
return true;
}
@ -385,7 +394,12 @@ namespace Ryujinx.Graphics
//If we don't have any parameters in the FIFO,
//keep running the PFIFO engine until it writes the parameters.
while (!Fifo.TryDequeue(out value))
if (!_pFifo.Step()) return 0;
{
if (!_pFifo.Step())
{
return 0;
}
}
return value;
}

View file

@ -39,9 +39,12 @@ namespace Ryujinx.Graphics.Memory
{
case SubmissionMode.Incrementing:
{
for (int index = 0; index < args && CanRead(); index++, meth++) pushBuffer.Add(new NvGpuPBEntry(meth, subC, reader.ReadInt32()));
for (int index = 0; index < args && CanRead(); index++, meth++)
{
pushBuffer.Add(new NvGpuPBEntry(meth, subC, reader.ReadInt32()));
}
break;
break;
}
case SubmissionMode.NonIncrementing:
@ -50,9 +53,12 @@ namespace Ryujinx.Graphics.Memory
for (int index = 0; index < arguments.Length; index++)
{
if (!CanRead()) break;
if (!CanRead())
{
break;
}
arguments[index] = reader.ReadInt32();
arguments[index] = reader.ReadInt32();
}
pushBuffer.Add(new NvGpuPBEntry(meth, subC, arguments));
@ -69,15 +75,21 @@ namespace Ryujinx.Graphics.Memory
case SubmissionMode.IncrementOnce:
{
if (CanRead()) pushBuffer.Add(new NvGpuPBEntry(meth, subC, reader.ReadInt32()));
if (CanRead())
{
pushBuffer.Add(new NvGpuPBEntry(meth, subC, reader.ReadInt32()));
}
if (CanRead() && args > 1)
if (CanRead() && args > 1)
{
int[] arguments = new int[args - 1];
for (int index = 0; index < arguments.Length && CanRead(); index++) arguments[index] = reader.ReadInt32();
for (int index = 0; index < arguments.Length && CanRead(); index++)
{
arguments[index] = reader.ReadInt32();
}
pushBuffer.Add(new NvGpuPBEntry(meth + 1, subC, arguments));
pushBuffer.Add(new NvGpuPBEntry(meth + 1, subC, arguments));
}
break;

View file

@ -45,7 +45,10 @@ namespace Ryujinx.Graphics.Memory
{
lock (_pageTable)
{
for (long offset = 0; offset < size; offset += PageSize) SetPte(va + offset, pa + offset);
for (long offset = 0; offset < size; offset += PageSize)
{
SetPte(va + offset, pa + offset);
}
}
return va;
@ -58,7 +61,12 @@ namespace Ryujinx.Graphics.Memory
long va = GetFreePosition(size);
if (va != -1)
for (long offset = 0; offset < size; offset += PageSize) SetPte(va + offset, pa + offset);
{
for (long offset = 0; offset < size; offset += PageSize)
{
SetPte(va + offset, pa + offset);
}
}
return va;
}
@ -69,9 +77,17 @@ namespace Ryujinx.Graphics.Memory
lock (_pageTable)
{
for (long offset = 0; offset < size; offset += PageSize)
if (IsPageInUse(va + offset)) return -1;
{
if (IsPageInUse(va + offset))
{
return -1;
}
}
for (long offset = 0; offset < size; offset += PageSize) SetPte(va + offset, PteReserved);
for (long offset = 0; offset < size; offset += PageSize)
{
SetPte(va + offset, PteReserved);
}
}
return va;
@ -84,7 +100,12 @@ namespace Ryujinx.Graphics.Memory
long position = GetFreePosition(size, align);
if (position != -1)
for (long offset = 0; offset < size; offset += PageSize) SetPte(position + offset, PteReserved);
{
for (long offset = 0; offset < size; offset += PageSize)
{
SetPte(position + offset, PteReserved);
}
}
return position;
}
@ -94,7 +115,10 @@ namespace Ryujinx.Graphics.Memory
{
lock (_pageTable)
{
for (long offset = 0; offset < size; offset += PageSize) SetPte(va + offset, PteUnmapped);
for (long offset = 0; offset < size; offset += PageSize)
{
SetPte(va + offset, PteUnmapped);
}
}
}
@ -105,16 +129,23 @@ namespace Ryujinx.Graphics.Memory
long position = PageSize;
long freeSize = 0;
if (align < 1) align = 1;
if (align < 1)
{
align = 1;
}
align = (align + PageMask) & ~PageMask;
while (position + freeSize < AddrSize)
{
if (!IsPageInUse(position + freeSize))
{
freeSize += PageSize;
if (freeSize >= size) return position;
if (freeSize >= size)
{
return position;
}
}
else
{
@ -123,8 +154,12 @@ namespace Ryujinx.Graphics.Memory
long remainder = position % align;
if (remainder != 0) position = position - remainder + align;
if (remainder != 0)
{
position = position - remainder + align;
}
}
}
return -1;
}
@ -133,7 +168,10 @@ namespace Ryujinx.Graphics.Memory
{
long basePos = GetPte(va);
if (basePos < 0) return -1;
if (basePos < 0)
{
return -1;
}
return basePos + (va & PageMask);
}
@ -141,19 +179,30 @@ namespace Ryujinx.Graphics.Memory
public bool IsRegionFree(long va, long size)
{
for (long offset = 0; offset < size; offset += PageSize)
if (IsPageInUse(va + offset)) return false;
{
if (IsPageInUse(va + offset))
{
return false;
}
}
return true;
}
private bool IsPageInUse(long va)
{
if (va >> (PtLvl0Bits + PtLvl1Bits + PtPageBits) != 0) return false;
if (va >> (PtLvl0Bits + PtLvl1Bits + PtPageBits) != 0)
{
return false;
}
long l0 = (va >> PtLvl0Bit) & PtLvl0Mask;
long l1 = (va >> PtLvl1Bit) & PtLvl1Mask;
if (_pageTable[l0] == null) return false;
if (_pageTable[l0] == null)
{
return false;
}
return _pageTable[l0][l1] != PteUnmapped;
}
@ -163,7 +212,10 @@ namespace Ryujinx.Graphics.Memory
long l0 = (position >> PtLvl0Bit) & PtLvl0Mask;
long l1 = (position >> PtLvl1Bit) & PtLvl1Mask;
if (_pageTable[l0] == null) return -1;
if (_pageTable[l0] == null)
{
return -1;
}
return _pageTable[l0][l1];
}
@ -177,7 +229,10 @@ namespace Ryujinx.Graphics.Memory
{
_pageTable[l0] = new long[PtLvl1Size];
for (int index = 0; index < PtLvl1Size; index++) _pageTable[l0][index] = PteUnmapped;
for (int index = 0; index < PtLvl1Size; index++)
{
_pageTable[l0][index] = PteUnmapped;
}
}
_pageTable[l0][l1] = tgtAddr;

View file

@ -55,16 +55,26 @@ namespace Ryujinx.Graphics.Memory
long rgEnd = Math.Min(current.End, newCached.End);
if ((current.Value & mask) == 0)
{
_cachedRanges.Add(new ValueRange<int>(rgStart, rgEnd, current.Value | mask));
}
else
{
coverage += rgEnd - rgStart;
}
if (rgStart > lastEnd) _cachedRanges.Add(new ValueRange<int>(lastEnd, rgStart, mask));
if (rgStart > lastEnd)
{
_cachedRanges.Add(new ValueRange<int>(lastEnd, rgStart, mask));
}
lastEnd = rgEnd;
}
if (lastEnd < newCached.End) _cachedRanges.Add(new ValueRange<int>(lastEnd, newCached.End, mask));
if (lastEnd < newCached.End)
{
_cachedRanges.Add(new ValueRange<int>(lastEnd, newCached.End, mask));
}
return coverage != size;
}

View file

@ -48,9 +48,13 @@ namespace Ryujinx.Graphics
public void CallMethod(NvGpuVmm vmm, NvGpuPBEntry pbEntry)
{
if (_methods.TryGetValue(pbEntry.Method, out NvGpuMethod method))
{
method(vmm, pbEntry);
}
else
{
WriteRegister(pbEntry);
}
}
private void TextureCopy(NvGpuVmm vmm, NvGpuPBEntry pbEntry)
@ -134,7 +138,10 @@ namespace Ryujinx.Graphics
{
int argsCount = pbEntry.Arguments.Count;
if (argsCount > 0) Registers[pbEntry.Method] = pbEntry.Arguments[argsCount - 1];
if (argsCount > 0)
{
Registers[pbEntry.Method] = pbEntry.Arguments[argsCount - 1];
}
}
private int ReadRegister(NvGpuEngine2dReg reg)

View file

@ -53,11 +53,17 @@ namespace Ryujinx.Graphics
_constBuffers = new ConstBuffer[6][];
for (int index = 0; index < _constBuffers.Length; index++) _constBuffers[index] = new ConstBuffer[18];
for (int index = 0; index < _constBuffers.Length; index++)
{
_constBuffers[index] = new ConstBuffer[18];
}
_uploadedKeys = new List<long>[(int)NvGpuBufferType.Count];
for (int i = 0; i < _uploadedKeys.Length; i++) _uploadedKeys[i] = new List<long>();
for (int i = 0; i < _uploadedKeys.Length; i++)
{
_uploadedKeys[i] = new List<long>();
}
//Ensure that all components are enabled by default.
//FIXME: Is this correct?
@ -67,14 +73,21 @@ namespace Ryujinx.Graphics
public void CallMethod(NvGpuVmm vmm, NvGpuPBEntry pbEntry)
{
if (_methods.TryGetValue(pbEntry.Method, out NvGpuMethod method))
{
method(vmm, pbEntry);
}
else
{
WriteRegister(pbEntry);
}
}
public void ResetCache()
{
foreach (List<long> uploaded in _uploadedKeys) uploaded.Clear();
foreach (List<long> uploaded in _uploadedKeys)
{
uploaded.Clear();
}
}
private void VertexEndGl(NvGpuVmm vmm, NvGpuPBEntry pbEntry)
@ -92,7 +105,10 @@ namespace Ryujinx.Graphics
SetColorMask(state);
SetPrimitiveRestart(state);
for (int fbIndex = 0; fbIndex < 8; fbIndex++) SetFrameBuffer(vmm, fbIndex);
for (int fbIndex = 0; fbIndex < 8; fbIndex++)
{
SetFrameBuffer(vmm, fbIndex);
}
SetZeta(vmm);
@ -328,11 +344,13 @@ namespace Ryujinx.Graphics
//Flipping breaks facing. Flipping front facing too fixes it
if (signX != signY)
{
switch (frontFace)
{
case GalFrontFace.Cw: frontFace = GalFrontFace.Ccw; break;
case GalFrontFace.Ccw: frontFace = GalFrontFace.Cw; break;
}
}
state.FrontFace = frontFace;
}
@ -341,7 +359,10 @@ namespace Ryujinx.Graphics
{
state.CullFaceEnabled = ReadRegisterBool(NvGpuEngine3dReg.CullFaceEnable);
if (state.CullFaceEnabled) state.CullFace = (GalCullFace)ReadRegister(NvGpuEngine3dReg.CullFace);
if (state.CullFaceEnabled)
{
state.CullFace = (GalCullFace)ReadRegister(NvGpuEngine3dReg.CullFace);
}
}
private void SetDepth(GalPipelineState state)
@ -350,7 +371,10 @@ namespace Ryujinx.Graphics
state.DepthWriteEnabled = ReadRegisterBool(NvGpuEngine3dReg.DepthWriteEnable);
if (state.DepthTestEnabled) state.DepthFunc = (GalComparisonOp)ReadRegister(NvGpuEngine3dReg.DepthTestFunction);
if (state.DepthTestEnabled)
{
state.DepthFunc = (GalComparisonOp)ReadRegister(NvGpuEngine3dReg.DepthTestFunction);
}
state.DepthRangeNear = ReadRegisterFloat(NvGpuEngine3dReg.DepthRangeNNear);
state.DepthRangeFar = ReadRegisterFloat(NvGpuEngine3dReg.DepthRangeNFar);
@ -419,7 +443,10 @@ namespace Ryujinx.Graphics
{
state.PrimitiveRestartEnabled = ReadRegisterBool(NvGpuEngine3dReg.PrimRestartEnable);
if (state.PrimitiveRestartEnabled) state.PrimitiveRestartIndex = (uint)ReadRegister(NvGpuEngine3dReg.PrimRestartIndex);
if (state.PrimitiveRestartEnabled)
{
state.PrimitiveRestartIndex = (uint)ReadRegister(NvGpuEngine3dReg.PrimRestartIndex);
}
}
private void SetRenderTargets()
@ -459,14 +486,19 @@ namespace Ryujinx.Graphics
int texIndex = 0;
for (int index = 0; index < keys.Length; index++)
{
foreach (ShaderDeclInfo declInfo in _gpu.Renderer.Shader.GetTextureUsage(keys[index]))
{
long position;
if (declInfo.IsCb)
{
position = _constBuffers[index][declInfo.Cbuf].Position;
}
else
{
position = _constBuffers[index][textureCbIndex].Position;
}
int textureHandle = vmm.ReadInt32(position + declInfo.Index * 4);
@ -474,11 +506,15 @@ namespace Ryujinx.Graphics
texIndex++;
}
}
}
private void UploadTexture(NvGpuVmm vmm, int texIndex, int textureHandle)
{
if (textureHandle == 0) return;
if (textureHandle == 0)
{
return;
}
int ticIndex = (textureHandle >> 0) & 0xfffff;
int tscIndex = (textureHandle >> 20) & 0xfff;
@ -496,12 +532,20 @@ namespace Ryujinx.Graphics
long key = vmm.ReadInt64(ticPosition + 4) & 0xffffffffffff;
if (image.Layout == GalMemoryLayout.BlockLinear)
{
key &= ~0x1ffL;
else if (image.Layout == GalMemoryLayout.Pitch) key &= ~0x1fL;
}
else if (image.Layout == GalMemoryLayout.Pitch)
{
key &= ~0x1fL;
}
key = vmm.GetPhysicalAddress(key);
if (key == -1) return;
if (key == -1)
{
return;
}
_gpu.ResourceManager.SendTexture(vmm, key, image, texIndex);
@ -511,11 +555,15 @@ namespace Ryujinx.Graphics
private void UploadConstBuffers(NvGpuVmm vmm, GalPipelineState state, long[] keys)
{
for (int stage = 0; stage < keys.Length; stage++)
{
foreach (ShaderDeclInfo declInfo in _gpu.Renderer.Shader.GetConstBufferUsage(keys[stage]))
{
ConstBuffer cb = _constBuffers[stage][declInfo.Cbuf];
if (!cb.Enabled) continue;
if (!cb.Enabled)
{
continue;
}
long key = vmm.GetPhysicalAddress(cb.Position);
@ -528,6 +576,7 @@ namespace Ryujinx.Graphics
state.ConstBufferKeys[stage][declInfo.Cbuf] = key;
}
}
}
private void UploadVertexArrays(NvGpuVmm vmm, GalPipelineState state)
@ -546,7 +595,10 @@ namespace Ryujinx.Graphics
int indexEntrySize = 1 << indexEntryFmt;
if (indexEntrySize > 4) throw new InvalidOperationException();
if (indexEntrySize > 4)
{
throw new InvalidOperationException();
}
if (indexCount != 0)
{
@ -571,9 +623,13 @@ namespace Ryujinx.Graphics
byte[] buffer = vmm.ReadBytes(ibPosition, ibSize);
if (primType == GalPrimitiveType.Quads)
{
buffer = QuadHelper.ConvertIbQuadsToTris(buffer, indexEntrySize, indexCount);
}
else /* if (PrimType == GalPrimitiveType.QuadStrip) */
{
buffer = QuadHelper.ConvertIbQuadStripToTris(buffer, indexEntrySize, indexCount);
}
_gpu.Renderer.Rasterizer.CreateIbo(iboKey, ibSize, buffer);
}
@ -586,9 +642,13 @@ namespace Ryujinx.Graphics
else
{
if (primType == GalPrimitiveType.Quads)
{
_gpu.Renderer.Rasterizer.SetIndexArray(QuadHelper.ConvertIbSizeQuadsToTris(ibSize), indexFormat);
}
else /* if (PrimType == GalPrimitiveType.QuadStrip) */
{
_gpu.Renderer.Rasterizer.SetIndexArray(QuadHelper.ConvertIbSizeQuadStripToTris(ibSize), indexFormat);
}
}
}
@ -600,7 +660,10 @@ namespace Ryujinx.Graphics
int arrayIndex = packed & 0x1f;
if (attribs[arrayIndex] == null) attribs[arrayIndex] = new List<GalVertexAttrib>();
if (attribs[arrayIndex] == null)
{
attribs[arrayIndex] = new List<GalVertexAttrib>();
}
long vertexPosition = MakeInt64From2XInt32(NvGpuEngine3dReg.VertexArrayNAddress + arrayIndex * 4);
@ -624,13 +687,19 @@ namespace Ryujinx.Graphics
for (int index = 0; index < 32; index++)
{
if (attribs[index] == null) continue;
if (attribs[index] == null)
{
continue;
}
int control = ReadRegister(NvGpuEngine3dReg.VertexArrayNControl + index * 4);
bool enable = (control & 0x1000) != 0;
if (!enable) continue;
if (!enable)
{
continue;
}
long vertexPosition = MakeInt64From2XInt32(NvGpuEngine3dReg.VertexArrayNAddress + index * 4);
long vertexEndPos = MakeInt64From2XInt32(NvGpuEngine3dReg.VertexArrayNEndAddr + index * 2);
@ -641,9 +710,15 @@ namespace Ryujinx.Graphics
int stride = control & 0xfff;
if (instanced && vertexDivisor != 0) vertexPosition += stride * (_currentInstance / vertexDivisor);
if (instanced && vertexDivisor != 0)
{
vertexPosition += stride * (_currentInstance / vertexDivisor);
}
if (vertexPosition > vertexEndPos) continue;
if (vertexPosition > vertexEndPos)
{
continue;
}
long vboKey = vmm.GetPhysicalAddress(vertexPosition);
@ -677,11 +752,19 @@ namespace Ryujinx.Graphics
bool instanceNext = ((primCtrl >> 26) & 1) != 0;
bool instanceCont = ((primCtrl >> 27) & 1) != 0;
if (instanceNext && instanceCont) throw new InvalidOperationException("GPU tried to increase and reset instance count at the same time");
if (instanceNext && instanceCont)
{
throw new InvalidOperationException("GPU tried to increase and reset instance count at the same time");
}
if (instanceNext)
{
_currentInstance++;
else if (!instanceCont) _currentInstance = 0;
}
else if (!instanceCont)
{
_currentInstance = 0;
}
state.Instance = _currentInstance;
@ -711,9 +794,13 @@ namespace Ryujinx.Graphics
//vertex of a quad, if it points to the middle of a
//quad (First % 4 != 0 for Quads) then it will not work properly.
if (primType == GalPrimitiveType.Quads)
{
indexFirst = QuadHelper.ConvertIbSizeQuadsToTris(indexFirst);
}
else /* if (PrimType == GalPrimitiveType.QuadStrip) */
{
indexFirst = QuadHelper.ConvertIbSizeQuadStripToTris(indexFirst);
}
}
_gpu.Renderer.Rasterizer.DrawElements(iboKey, indexFirst, vertexBase, primType);
@ -804,7 +891,10 @@ namespace Ryujinx.Graphics
int size = ReadRegister(NvGpuEngine3dReg.ConstBufferSize);
if (!_gpu.Renderer.Buffer.IsCached(cbKey, size)) _gpu.Renderer.Buffer.Create(cbKey, size);
if (!_gpu.Renderer.Buffer.IsCached(cbKey, size))
{
_gpu.Renderer.Buffer.Create(cbKey, size);
}
ConstBuffer cb = _constBuffers[stage][index];
@ -832,7 +922,10 @@ namespace Ryujinx.Graphics
{
int argsCount = pbEntry.Arguments.Count;
if (argsCount > 0) Registers[pbEntry.Method] = pbEntry.Arguments[argsCount - 1];
if (argsCount > 0)
{
Registers[pbEntry.Method] = pbEntry.Arguments[argsCount - 1];
}
}
private int ReadRegister(NvGpuEngine3dReg reg)
@ -859,7 +952,10 @@ namespace Ryujinx.Graphics
{
List<long> uploaded = _uploadedKeys[(int)type];
if (uploaded.Contains(key)) return false;
if (uploaded.Contains(key))
{
return false;
}
uploaded.Add(key);

View file

@ -36,9 +36,13 @@ namespace Ryujinx.Graphics
public void CallMethod(NvGpuVmm vmm, NvGpuPBEntry pbEntry)
{
if (_methods.TryGetValue(pbEntry.Method, out NvGpuMethod method))
{
method(vmm, pbEntry);
}
else
{
WriteRegister(pbEntry);
}
}
private void Execute(NvGpuVmm vmm, NvGpuPBEntry pbEntry)
@ -92,9 +96,15 @@ namespace Ryujinx.Graphics
if (copy2D)
{
if (srcLinear) srcPosX = srcPosY = srcPosZ = 0;
if (srcLinear)
{
srcPosX = srcPosY = srcPosZ = 0;
}
if (dstLinear) dstPosX = dstPosY = dstPosZ = 0;
if (dstLinear)
{
dstPosX = dstPosY = dstPosZ = 0;
}
if (srcLinear && dstLinear)
{
@ -114,19 +124,28 @@ namespace Ryujinx.Graphics
ISwizzle srcSwizzle;
if (srcLinear)
{
srcSwizzle = new LinearSwizzle(srcPitch, srcCpp);
}
else
{
srcSwizzle = new BlockLinearSwizzle(srcSizeX, srcCpp, srcBlockHeight);
}
ISwizzle dstSwizzle;
if (dstLinear)
{
dstSwizzle = new LinearSwizzle(dstPitch, dstCpp);
}
else
{
dstSwizzle = new BlockLinearSwizzle(dstSizeX, dstCpp, dstBlockHeight);
}
for (int y = 0; y < yCount; y++)
for (int x = 0; x < xCount; x++)
{
for (int x = 0; x < xCount; x++)
{
int srcOffset = srcSwizzle.GetSwizzleOffset(srcPosX + x, srcPosY + y);
int dstOffset = dstSwizzle.GetSwizzleOffset(dstPosX + x, dstPosY + y);
@ -136,6 +155,7 @@ namespace Ryujinx.Graphics
vmm.Memory.CopyBytes(src, dst, srcCpp);
}
}
}
}
else
@ -155,7 +175,10 @@ namespace Ryujinx.Graphics
{
int argsCount = pbEntry.Arguments.Count;
if (argsCount > 0) Registers[pbEntry.Method] = pbEntry.Arguments[argsCount - 1];
if (argsCount > 0)
{
Registers[pbEntry.Method] = pbEntry.Arguments[argsCount - 1];
}
}
private int ReadRegister(NvGpuEngineM2mfReg reg)

View file

@ -39,9 +39,13 @@ namespace Ryujinx.Graphics
public void CallMethod(NvGpuVmm vmm, NvGpuPBEntry pbEntry)
{
if (_methods.TryGetValue(pbEntry.Method, out NvGpuMethod method))
{
method(vmm, pbEntry);
}
else
{
WriteRegister(pbEntry);
}
}
private void Execute(NvGpuVmm vmm, NvGpuPBEntry pbEntry)
@ -57,7 +61,10 @@ namespace Ryujinx.Graphics
_gpu.Fifo.Step();
for (int offset = 0; offset < lineLengthIn; offset += 4) vmm.WriteInt32(dstAddress + offset, _dataBuffer[offset >> 2]);
for (int offset = 0; offset < lineLengthIn; offset += 4)
{
vmm.WriteInt32(dstAddress + offset, _dataBuffer[offset >> 2]);
}
}
private void PushData(NvGpuVmm vmm, NvGpuPBEntry pbEntry)
@ -76,7 +83,10 @@ namespace Ryujinx.Graphics
{
int argsCount = pbEntry.Arguments.Count;
if (argsCount > 0) Registers[pbEntry.Method] = pbEntry.Arguments[argsCount - 1];
if (argsCount > 0)
{
Registers[pbEntry.Method] = pbEntry.Arguments[argsCount - 1];
}
}
private int ReadRegister(NvGpuEngineP2mfReg reg)

View file

@ -76,7 +76,10 @@ namespace Ryujinx.Graphics
public void DispatchCalls()
{
while (Step());
while (Step())
{
;
}
}
private (NvGpuVmm Vmm, NvGpuPBEntry[] Pb) _curr;
@ -87,7 +90,10 @@ namespace Ryujinx.Graphics
{
while (_curr.Pb == null || _curr.Pb.Length <= _currPbEntryIndex)
{
if (!_bufferQueue.TryDequeue(out _curr)) return false;
if (!_bufferQueue.TryDequeue(out _curr))
{
return false;
}
_gpu.Engine3D.ResetCache();
@ -141,8 +147,12 @@ namespace Ryujinx.Graphics
case NvGpuFifoMeth.SendMacroCodeData:
{
foreach (int arg in pbEntry.Arguments) _mme[_currMacroPosition++] = arg;
break;
foreach (int arg in pbEntry.Arguments)
{
_mme[_currMacroPosition++] = arg;
}
break;
}
case NvGpuFifoMeth.SetMacroBindingIndex:
@ -171,9 +181,16 @@ namespace Ryujinx.Graphics
int macroIndex = (pbEntry.Method >> 1) & MacroIndexMask;
if ((pbEntry.Method & 1) != 0)
foreach (int arg in pbEntry.Arguments) _macros[macroIndex].PushParam(arg);
{
foreach (int arg in pbEntry.Arguments)
{
_macros[macroIndex].PushParam(arg);
}
}
else
{
_macros[macroIndex].Execute(vmm, _mme, pbEntry.Arguments[0]);
}
}
}

View file

@ -29,7 +29,10 @@ namespace Ryujinx.Graphics.Texture
// How many indices do we have?
int indices = Height * Width;
if (DualPlane) indices *= 2;
if (DualPlane)
{
indices *= 2;
}
IntegerEncoded intEncoded = IntegerEncoded.CreateEncoding(MaxWeight);
@ -40,7 +43,10 @@ namespace Ryujinx.Graphics.Texture
{
int ret = Width * Height;
if (DualPlane) ret *= 2;
if (DualPlane)
{
ret *= 2;
}
return ret;
}
@ -59,16 +65,23 @@ namespace Ryujinx.Graphics.Texture
{
BinaryReader binReader = new BinaryReader(inputStream);
if (blockX > 12 || blockY > 12) throw new ASTCDecoderException("Block size unsupported!");
if (blockX > 12 || blockY > 12)
{
throw new ASTCDecoderException("Block size unsupported!");
}
if (blockZ != 1 || z != 1) throw new ASTCDecoderException("3D compressed textures unsupported!");
if (blockZ != 1 || z != 1)
{
throw new ASTCDecoderException("3D compressed textures unsupported!");
}
using (MemoryStream outputStream = new MemoryStream())
{
int blockIndex = 0;
for (int j = 0; j < y; j += blockY)
for (int i = 0; i < x; i += blockX)
{
for (int i = 0; i < x; i += blockX)
{
int[] decompressedData = new int[144];
@ -90,6 +103,7 @@ namespace Ryujinx.Graphics.Texture
blockIndex++;
}
}
return outputStream.ToArray();
}
@ -105,7 +119,10 @@ namespace Ryujinx.Graphics.Texture
BitArrayStream bitStream = new BitArrayStream(new BitArray(inputBuffer));
TexelWeightParams texelParams = DecodeBlockInfo(bitStream);
if (texelParams.Error) throw new ASTCDecoderException("Invalid block mode");
if (texelParams.Error)
{
throw new ASTCDecoderException("Invalid block mode");
}
if (texelParams.VoidExtentLdr)
{
@ -114,17 +131,29 @@ namespace Ryujinx.Graphics.Texture
return true;
}
if (texelParams.VoidExtentHdr) throw new ASTCDecoderException("HDR void extent blocks are unsupported!");
if (texelParams.VoidExtentHdr)
{
throw new ASTCDecoderException("HDR void extent blocks are unsupported!");
}
if (texelParams.Width > blockWidth) throw new ASTCDecoderException("Texel weight grid width should be smaller than block width");
if (texelParams.Width > blockWidth)
{
throw new ASTCDecoderException("Texel weight grid width should be smaller than block width");
}
if (texelParams.Height > blockHeight) throw new ASTCDecoderException("Texel weight grid height should be smaller than block height");
if (texelParams.Height > blockHeight)
{
throw new ASTCDecoderException("Texel weight grid height should be smaller than block height");
}
// Read num partitions
int numberPartitions = bitStream.ReadBits(2) + 1;
Debug.Assert(numberPartitions <= 4);
if (numberPartitions == 4 && texelParams.DualPlane) throw new ASTCDecoderException("Dual plane mode is incompatible with four partition blocks");
if (numberPartitions == 4 && texelParams.DualPlane)
{
throw new ASTCDecoderException("Dual plane mode is incompatible with four partition blocks");
}
// Based on the number of partitions, read the color endpoint mode for
// each partition.
@ -160,6 +189,7 @@ namespace Ryujinx.Graphics.Texture
uint extraColorEndpointModeBits = 0;
if (baseMode != 0)
{
switch (numberPartitions)
{
case 2: extraColorEndpointModeBits += 2; break;
@ -167,13 +197,17 @@ namespace Ryujinx.Graphics.Texture
case 4: extraColorEndpointModeBits += 8; break;
default: Debug.Assert(false); break;
}
}
remainingBits -= (int)extraColorEndpointModeBits;
// Do we have a dual plane situation?
int planeSelectorBits = 0;
if (texelParams.DualPlane) planeSelectorBits = 2;
if (texelParams.DualPlane)
{
planeSelectorBits = 2;
}
remainingBits -= planeSelectorBits;
@ -218,7 +252,11 @@ namespace Ryujinx.Graphics.Texture
for (int i = 0; i < numberPartitions; i++)
{
colorEndpointMode[i] = baseMode;
if (!c[i]) colorEndpointMode[i] -= 1;
if (!c[i])
{
colorEndpointMode[i] -= 1;
}
colorEndpointMode[i] <<= 2;
colorEndpointMode[i] |= m[i];
}
@ -227,11 +265,18 @@ namespace Ryujinx.Graphics.Texture
{
uint tempColorEndpointMode = baseColorEndpointMode >> 2;
for (uint i = 0; i < numberPartitions; i++) colorEndpointMode[i] = tempColorEndpointMode;
for (uint i = 0; i < numberPartitions; i++)
{
colorEndpointMode[i] = tempColorEndpointMode;
}
}
// Make sure everything up till here is sane.
for (int i = 0; i < numberPartitions; i++) Debug.Assert(colorEndpointMode[i] < 16);
for (int i = 0; i < numberPartitions; i++)
{
Debug.Assert(colorEndpointMode[i] < 16);
}
Debug.Assert(bitStream.Position + texelParams.GetPackedBitSize() == 128);
// Decode both color data and texel weight data
@ -246,7 +291,10 @@ namespace Ryujinx.Graphics.Texture
int colorValuesPosition = 0;
for (int i = 0; i < numberPartitions; i++) ComputeEndpoints(endPoints[i], colorValues, colorEndpointMode[i], ref colorValuesPosition);
for (int i = 0; i < numberPartitions; i++)
{
ComputeEndpoints(endPoints[i], colorValues, colorEndpointMode[i], ref colorValuesPosition);
}
// Read the texel weight data.
byte[] texelWeightData = (byte[])inputBuffer.Clone();
@ -266,7 +314,10 @@ namespace Ryujinx.Graphics.Texture
texelWeightData[clearByteStart - 1] &= (byte)((1 << (texelParams.GetPackedBitSize() % 8)) - 1);
int cLen = 16 - clearByteStart;
for (int i = clearByteStart; i < clearByteStart + cLen; i++) texelWeightData[i] = 0;
for (int i = clearByteStart; i < clearByteStart + cLen; i++)
{
texelWeightData[i] = 0;
}
List<IntegerEncoded> texelWeightValues = new List<IntegerEncoded>();
BitArrayStream weightBitStream = new BitArrayStream(new BitArray(texelWeightData));
@ -283,7 +334,8 @@ namespace Ryujinx.Graphics.Texture
// Now that we have endpoints and weights, we can interpolate and generate
// the proper decoding...
for (int j = 0; j < blockHeight; j++)
for (int i = 0; i < blockWidth; i++)
{
for (int i = 0; i < blockWidth; i++)
{
int partition = Select2DPartition(partitionIndex, i, j, numberPartitions, blockHeight * blockWidth < 32);
Debug.Assert(partition < numberPartitions);
@ -298,9 +350,12 @@ namespace Ryujinx.Graphics.Texture
int plane = 0;
if (texelParams.DualPlane && ((planeIndices + 1) & 3) == component) plane = 1;
if (texelParams.DualPlane && ((planeIndices + 1) & 3) == component)
{
plane = 1;
}
int weight = weights[plane][j * blockWidth + i];
int weight = weights[plane][j * blockWidth + i];
int finalComponent = (component0 * (64 - weight) + component1 * weight + 32) / 64;
if (finalComponent == 65535)
@ -316,6 +371,7 @@ namespace Ryujinx.Graphics.Texture
outputBuffer[j * blockWidth + i] = pixel.Pack();
}
}
return true;
}
@ -327,7 +383,10 @@ namespace Ryujinx.Graphics.Texture
private static int SelectPartition(int seed, int x, int y, int z, int partitionCount, bool isSmallBlock)
{
if (partitionCount == 1) return 0;
if (partitionCount == 1)
{
return 0;
}
if (isSmallBlock)
{
@ -385,12 +444,29 @@ namespace Ryujinx.Graphics.Texture
a &= 0x3F; b &= 0x3F; c &= 0x3F; d &= 0x3F;
if (partitionCount < 4) d = 0;
if (partitionCount < 3) c = 0;
if (partitionCount < 4)
{
d = 0;
}
if (partitionCount < 3)
{
c = 0;
}
if (a >= b && a >= c && a >= d)
{
return 0;
}
else if (b >= c && b >= d)
{
return 1;
}
else if (c >= d)
{
return 2;
}
if (a >= b && a >= c && a >= d) return 0;
else if (b >= c && b >= d) return 1;
else if (c >= d) return 2;
return 3;
}
@ -424,10 +500,16 @@ namespace Ryujinx.Graphics.Texture
i++;
unquantized[1][weightIndices] = UnquantizeTexelWeight(weights[i]);
if (i == weights.Count) break;
if (i == weights.Count)
{
break;
}
}
if (++weightIndices >= texelParams.Width * texelParams.Height) break;
if (++weightIndices >= texelParams.Width * texelParams.Height)
{
break;
}
}
// Do infill if necessary (Section C.2.18) ...
@ -437,8 +519,10 @@ namespace Ryujinx.Graphics.Texture
int planeScale = texelParams.DualPlane ? 2 : 1;
for (int plane = 0; plane < planeScale; plane++)
for (int t = 0; t < blockHeight; t++)
for (int s = 0; s < blockWidth; s++)
{
for (int t = 0; t < blockHeight; t++)
{
for (int s = 0; s < blockWidth; s++)
{
int cs = ds * s;
int ct = dt * t;
@ -464,15 +548,29 @@ namespace Ryujinx.Graphics.Texture
int p10 = 0;
int p11 = 0;
if (v0 < texelParams.Width * texelParams.Height) p00 = unquantized[plane][v0];
if (v0 < texelParams.Width * texelParams.Height)
{
p00 = unquantized[plane][v0];
}
if (v0 + 1 < texelParams.Width * texelParams.Height) p01 = unquantized[plane][v0 + 1];
if (v0 + 1 < texelParams.Width * texelParams.Height)
{
p01 = unquantized[plane][v0 + 1];
}
if (v0 + texelParams.Width < texelParams.Width * texelParams.Height) p10 = unquantized[plane][v0 + texelParams.Width];
if (v0 + texelParams.Width < texelParams.Width * texelParams.Height)
{
p10 = unquantized[plane][v0 + texelParams.Width];
}
if (v0 + texelParams.Width + 1 < texelParams.Width * texelParams.Height) p11 = unquantized[plane][v0 + texelParams.Width + 1];
if (v0 + texelParams.Width + 1 < texelParams.Width * texelParams.Height)
{
p11 = unquantized[plane][v0 + texelParams.Width + 1];
}
outputBuffer[plane][t * blockWidth + s] = (p00 * w00 + p01 * w01 + p10 * w10 + p11 * w11 + 8) >> 4;
outputBuffer[plane][t * blockWidth + s] = (p00 * w00 + p01 * w01 + p10 * w10 + p11 * w11 + 8) >> 4;
}
}
}
}
@ -588,7 +686,10 @@ namespace Ryujinx.Graphics.Texture
Debug.Assert(result < 64);
// Change from [0,63] to [0,64]
if (result > 32) result += 1;
if (result > 32)
{
result += 1;
}
return result;
}
@ -603,7 +704,10 @@ namespace Ryujinx.Graphics.Texture
{
uint[] ret = new uint[number];
for (int i = 0; i < number; i++) ret[i] = (uint)colorValues[colorValuesPosition++];
for (int i = 0; i < number; i++)
{
ret[i] = (uint)colorValues[colorValuesPosition++];
}
return ret;
}
@ -612,7 +716,10 @@ namespace Ryujinx.Graphics.Texture
{
int[] ret = new int[number];
for (int i = 0; i < number; i++) ret[i] = colorValues[colorValuesPosition++];
for (int i = 0; i < number; i++)
{
ret[i] = colorValues[colorValuesPosition++];
}
return ret;
}
@ -796,7 +903,10 @@ namespace Ryujinx.Graphics.Texture
// First figure out how many color values we have
int numberValues = 0;
for (int i = 0; i < numberPartitions; i++) numberValues += (int)((modes[i] >> 2) + 1) << 1;
for (int i = 0; i < numberPartitions; i++)
{
numberValues += (int)((modes[i] >> 2) + 1) << 1;
}
// Then based on the number of values and the remaining number of bits,
// figure out the max value for each of them...
@ -813,7 +923,10 @@ namespace Ryujinx.Graphics.Texture
while (--range > 0)
{
IntegerEncoded newIntEncoded = IntegerEncoded.CreateEncoding(range);
if (!newIntEncoded.MatchesEncoding(intEncoded)) break;
if (!newIntEncoded.MatchesEncoding(intEncoded))
{
break;
}
}
// Return to last matching range.
@ -994,13 +1107,19 @@ namespace Ryujinx.Graphics.Texture
}
// Make sure that each of our values is in the proper range...
for (int i = 0; i < numberValues; i++) Debug.Assert(outputValues[i] <= 255);
for (int i = 0; i < numberValues; i++)
{
Debug.Assert(outputValues[i] <= 255);
}
}
private static void FillVoidExtentLdr(BitArrayStream bitStream, int[] outputBuffer, int blockWidth, int blockHeight)
{
// Don't actually care about the void extent, just read the bits...
for (int i = 0; i < 4; ++i) bitStream.ReadBits(13);
for (int i = 0; i < 4; ++i)
{
bitStream.ReadBits(13);
}
// Decode the RGBA components and renormalize them to the range [0, 255]
ushort r = (ushort)bitStream.ReadBits(16);
@ -1011,7 +1130,12 @@ namespace Ryujinx.Graphics.Texture
int rgba = (r >> 8) | (g & 0xFF00) | ((b & 0xFF00) << 8) | ((a & 0xFF00) << 16);
for (int j = 0; j < blockHeight; j++)
for (int i = 0; i < blockWidth; i++) outputBuffer[j * blockWidth + i] = rgba;
{
for (int i = 0; i < blockWidth; i++)
{
outputBuffer[j * blockWidth + i] = rgba;
}
}
}
private static TexelWeightParams DecodeBlockInfo(BitArrayStream bitStream)
@ -1025,12 +1149,19 @@ namespace Ryujinx.Graphics.Texture
if ((modeBits & 0x01FF) == 0x1FC)
{
if ((modeBits & 0x200) != 0)
{
texelParams.VoidExtentHdr = true;
}
else
{
texelParams.VoidExtentLdr = true;
}
// Next two bits must be one.
if ((modeBits & 0x400) == 0 || bitStream.ReadBits(1) == 0) texelParams.Error = true;
if ((modeBits & 0x400) == 0 || bitStream.ReadBits(1) == 0)
{
texelParams.Error = true;
}
return texelParams;
}
@ -1067,9 +1198,13 @@ namespace Ryujinx.Graphics.Texture
{
// layout is in [3-4]
if ((modeBits & 0x100) != 0)
{
layout = 4;
}
else
{
layout = 3;
}
}
else
{
@ -1080,9 +1215,13 @@ namespace Ryujinx.Graphics.Texture
{
// layout is in [0-1]
if ((modeBits & 0x4) != 0)
{
layout = 1;
}
else
{
layout = 0;
}
}
}
else
@ -1097,9 +1236,13 @@ namespace Ryujinx.Graphics.Texture
Debug.Assert((modeBits & 0x40) == 0);
if ((modeBits & 0x20) != 0)
{
layout = 8;
}
else
{
layout = 7;
}
}
else
{
@ -1110,9 +1253,13 @@ namespace Ryujinx.Graphics.Texture
{
// layout is in [5-6]
if ((modeBits & 0x80) != 0)
{
layout = 6;
}
else
{
layout = 5;
}
}
}
@ -1121,9 +1268,13 @@ namespace Ryujinx.Graphics.Texture
// Determine R
int r = (modeBits >> 4) & 1;
if (layout < 5)
{
r |= (modeBits & 0x3) << 1;
}
else
{
r |= (modeBits & 0xC) >> 1;
}
Debug.Assert(2 <= r && r <= 7);

View file

@ -20,7 +20,9 @@ namespace Ryujinx.Graphics.Texture
B = b;
for (int i = 0; i < 4; i++)
{
_bitDepth[i] = 8;
}
}
public void ClampByte()

View file

@ -19,7 +19,12 @@ namespace Ryujinx.Graphics.Texture
{
int retValue = 0;
for (int i = Position; i < Position + length; i++)
if (BitsArray[i]) retValue |= 1 << (i - Position);
{
if (BitsArray[i])
{
retValue |= 1 << (i - Position);
}
}
Position += length;
return (short)retValue;
@ -29,7 +34,12 @@ namespace Ryujinx.Graphics.Texture
{
int retValue = 0;
for (int i = start; i <= end; i++)
if (BitsArray[i]) retValue |= 1 << (i - start);
{
if (BitsArray[i])
{
retValue |= 1 << (i - start);
}
}
return retValue;
}
@ -41,7 +51,10 @@ namespace Ryujinx.Graphics.Texture
public void WriteBits(int value, int length)
{
for (int i = Position; i < Position + length; i++) BitsArray[i] = ((value >> (i - Position)) & 1) != 0;
for (int i = Position; i < Position + length; i++)
{
BitsArray[i] = ((value >> (i - Position)) & 1) != 0;
}
Position += length;
}
@ -55,8 +68,15 @@ namespace Ryujinx.Graphics.Texture
public static int Replicate(int value, int numberBits, int toBit)
{
if (numberBits == 0) return 0;
if (toBit == 0) return 0;
if (numberBits == 0)
{
return 0;
}
if (toBit == 0)
{
return 0;
}
int tempValue = value & ((1 << numberBits) - 1);
int retValue = tempValue;
@ -81,7 +101,11 @@ namespace Ryujinx.Graphics.Texture
public static int PopCnt(int number)
{
int counter;
for (counter = 0; number != 0; counter++) number &= number - 1;
for (counter = 0; number != 0; counter++)
{
number &= number - 1;
}
return counter;
}
@ -99,7 +123,10 @@ namespace Ryujinx.Graphics.Texture
b |= a & 0x80;
a >>= 1;
a &= 0x3F;
if ((a & 0x20) != 0) a -= 0x40;
if ((a & 0x20) != 0)
{
a -= 0x40;
}
}
}
}

View file

@ -29,7 +29,10 @@ namespace Ryujinx.Graphics.Texture
{
int count = 0;
while (((value >> count) & 1) == 0) count++;
while (((value >> count) & 1) == 0)
{
count++;
}
return count;
}

View file

@ -144,15 +144,24 @@ namespace Ryujinx.Graphics.Texture
GalTextureType aType,
bool convSrgb)
{
if (rType != gType || rType != bType || rType != aType) throw new NotImplementedException("Per component types are not implemented!");
if (rType != gType || rType != bType || rType != aType)
{
throw new NotImplementedException("Per component types are not implemented!");
}
if (!_textureTable.TryGetValue(format, out GalImageFormat imageFormat)) throw new NotImplementedException($"Format 0x{(int)format:x} not implemented!");
if (!_textureTable.TryGetValue(format, out GalImageFormat imageFormat))
{
throw new NotImplementedException($"Format 0x{(int)format:x} not implemented!");
}
GalImageFormat formatType = convSrgb ? Srgb : GetFormatType(rType);
GalImageFormat combinedFormat = (imageFormat & GalImageFormat.FormatMask) | formatType;
if (!imageFormat.HasFlag(formatType)) throw new NotImplementedException($"Format \"{combinedFormat}\" not implemented!");
if (!imageFormat.HasFlag(formatType))
{
throw new NotImplementedException($"Format \"{combinedFormat}\" not implemented!");
}
return combinedFormat;
}
@ -212,9 +221,13 @@ namespace Ryujinx.Graphics.Texture
AMemory cpuMemory;
if (memory is NvGpuVmm vmm)
{
cpuMemory = vmm.Memory;
}
else
{
cpuMemory = (AMemory)memory;
}
ISwizzle swizzle = TextureHelper.GetSwizzle(image);
@ -259,7 +272,8 @@ namespace Ryujinx.Graphics.Texture
int inOffs = 0;
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
{
for (int x = 0; x < width; x++)
{
long offset = (uint)swizzle.GetSwizzleOffset(x, y);
@ -267,6 +281,7 @@ namespace Ryujinx.Graphics.Texture
inOffs += bytesPerPixel;
}
}
}
public static int GetSize(GalImage image)
@ -307,9 +322,13 @@ namespace Ryujinx.Graphics.Texture
int alignMask;
if (image.Layout == GalMemoryLayout.BlockLinear)
{
alignMask = image.TileWidth * (64 / desc.BytesPerPixel) - 1;
}
else
{
alignMask = 32 / desc.BytesPerPixel - 1;
}
return (image.Width + alignMask) & ~alignMask;
}
@ -358,7 +377,10 @@ namespace Ryujinx.Graphics.Texture
{
GalImageFormat pixelFormat = format & GalImageFormat.FormatMask;
if (_imageTable.TryGetValue(pixelFormat, out ImageDescriptor descriptor)) return descriptor;
if (_imageTable.TryGetValue(pixelFormat, out ImageDescriptor descriptor))
{
return descriptor;
}
throw new NotImplementedException($"Format \"{pixelFormat}\" not implemented!");
}

View file

@ -41,8 +41,14 @@ namespace Ryujinx.Graphics.Texture
{
int totalBits = NumberBits * numberVals;
if (_encoding == EIntegerEncoding.Trit)
{
totalBits += (numberVals * 8 + 4) / 5;
else if (_encoding == EIntegerEncoding.Quint) totalBits += (numberVals * 7 + 2) / 3;
}
else if (_encoding == EIntegerEncoding.Quint)
{
totalBits += (numberVals * 7 + 2) / 3;
}
return totalBits;
}
@ -53,13 +59,22 @@ namespace Ryujinx.Graphics.Texture
int check = maxVal + 1;
// Is maxVal a power of two?
if ((check & (check - 1)) == 0) return new IntegerEncoded(EIntegerEncoding.JustBits, BitArrayStream.PopCnt(maxVal));
if ((check & (check - 1)) == 0)
{
return new IntegerEncoded(EIntegerEncoding.JustBits, BitArrayStream.PopCnt(maxVal));
}
// Is maxVal of the type 3*2^n - 1?
if (check % 3 == 0 && ((check / 3) & (check / 3 - 1)) == 0) return new IntegerEncoded(EIntegerEncoding.Trit, BitArrayStream.PopCnt(check / 3 - 1));
if (check % 3 == 0 && ((check / 3) & (check / 3 - 1)) == 0)
{
return new IntegerEncoded(EIntegerEncoding.Trit, BitArrayStream.PopCnt(check / 3 - 1));
}
// Is maxVal of the type 5*2^n - 1?
if (check % 5 == 0 && ((check / 5) & (check / 5 - 1)) == 0) return new IntegerEncoded(EIntegerEncoding.Quint, BitArrayStream.PopCnt(check / 5 - 1));
if (check % 5 == 0 && ((check / 5) & (check / 5 - 1)) == 0)
{
return new IntegerEncoded(EIntegerEncoding.Quint, BitArrayStream.PopCnt(check / 5 - 1));
}
// Apparently it can't be represented with a bounded integer sequence...
// just iterate.
@ -221,6 +236,7 @@ namespace Ryujinx.Graphics.Texture
// Start decoding
int numberValuesDecoded = 0;
while (numberValuesDecoded < numberValues)
{
switch (intEncoded.GetEncoding())
{
case EIntegerEncoding.Quint:
@ -248,6 +264,7 @@ namespace Ryujinx.Graphics.Texture
break;
}
}
}
}
}
}

View file

@ -23,9 +23,13 @@ namespace Ryujinx.Graphics.Texture
if (swizzle == TextureSwizzle.BlockLinear ||
swizzle == TextureSwizzle.BlockLinearColorKey)
{
layout = GalMemoryLayout.BlockLinear;
}
else
{
layout = GalMemoryLayout.Pitch;
}
int blockHeightLog2 = (tic[3] >> 3) & 7;
int tileWidthLog2 = (tic[3] >> 10) & 7;
@ -48,7 +52,10 @@ namespace Ryujinx.Graphics.Texture
zSource,
wSource);
if (layout == GalMemoryLayout.Pitch) image.Pitch = (tic[3] & 0xffff) << 5;
if (layout == GalMemoryLayout.Pitch)
{
image.Pitch = (tic[3] & 0xffff) << 5;
}
return image;
}
@ -99,7 +106,10 @@ namespace Ryujinx.Graphics.Texture
{
int[] words = new int[count];
for (int index = 0; index < count; index++, position += 4) words[index] = vmm.ReadInt32(position);
for (int index = 0; index < count; index++, position += 4)
{
words[index] = vmm.ReadInt32(position);
}
return words;
}

View file

@ -31,7 +31,10 @@ namespace Ryujinx.Graphics.Texture
IAMemory memory,
long position)
{
if (memory is NvGpuVmm vmm) return (vmm.Memory, vmm.GetPhysicalAddress(position));
if (memory is NvGpuVmm vmm)
{
return (vmm.Memory, vmm.GetPhysicalAddress(position));
}
return ((AMemory)memory, position);
}

View file

@ -13,7 +13,10 @@ namespace Ryujinx.Graphics
public void Add(ValueRange<T> range)
{
if (range.End <= range.Start) return;
if (range.End <= range.Start)
{
return;
}
int first = BinarySearchFirstIntersection(range);
@ -25,9 +28,13 @@ namespace Ryujinx.Graphics
int gtIndex = BinarySearchGt(range);
if (gtIndex != -1)
{
_ranges.Insert(gtIndex, range);
}
else
{
_ranges.Add(range);
}
return;
}
@ -82,7 +89,10 @@ namespace Ryujinx.Graphics
{
int first = BinarySearchFirstIntersection(range);
if (first == -1) return;
if (first == -1)
{
return;
}
(int start, int end) = GetAllIntersectionRanges(range, first);
@ -98,13 +108,19 @@ namespace Ryujinx.Graphics
private void InsertNextNeighbour(int index, ValueRange<T> range, ValueRange<T> next)
{
//Split last intersection (ordered by Start) if necessary.
if (range.End < next.End) InsertNewRange(index, range.End, next.End, next.Value);
if (range.End < next.End)
{
InsertNewRange(index, range.End, next.End, next.Value);
}
}
private void InsertPrevNeighbour(int index, ValueRange<T> range, ValueRange<T> prev)
{
//Split first intersection (ordered by Start) if necessary.
if (range.Start > prev.Start) InsertNewRange(index, prev.Start, range.Start, prev.Value);
if (range.Start > prev.Start)
{
InsertNewRange(index, prev.Start, range.Start, prev.Value);
}
}
private void InsertNewRange(int index, long start, long end, T value)
@ -116,7 +132,10 @@ namespace Ryujinx.Graphics
{
int first = BinarySearchFirstIntersection(range);
if (first == -1) return new ValueRange<T>[0];
if (first == -1)
{
return new ValueRange<T>[0];
}
(int start, int end) = GetAllIntersectionRanges(range, first);
@ -128,9 +147,15 @@ namespace Ryujinx.Graphics
int start = baseIndex;
int end = baseIndex;
while (start > 0 && Intersects(range, _ranges[start - 1])) start--;
while (start > 0 && Intersects(range, _ranges[start - 1]))
{
start--;
}
while (end < _ranges.Count - 1 && Intersects(range, _ranges[end + 1])) end++;
while (end < _ranges.Count - 1 && Intersects(range, _ranges[end + 1]))
{
end++;
}
return (start, end);
}
@ -148,12 +173,19 @@ namespace Ryujinx.Graphics
ValueRange<T> current = _ranges[middle];
if (Intersects(range, current)) return middle;
if (Intersects(range, current))
{
return middle;
}
if (range.Start < current.Start)
{
right = middle - 1;
}
else
{
left = middle + 1;
}
}
return -1;
@ -178,7 +210,10 @@ namespace Ryujinx.Graphics
{
right = middle - 1;
if (gtIndex == -1 || current.Start < _ranges[gtIndex].Start) gtIndex = middle;
if (gtIndex == -1 || current.Start < _ranges[gtIndex].Start)
{
gtIndex = middle;
}
}
else
{

View file

@ -28,7 +28,12 @@ namespace Ryujinx.HLE.FileSystem
baseSavePath = Path.Combine(baseSavePath, "save");
if (saveMetaData.TitleId == 0 && saveMetaData.SaveDataType == SaveDataType.SaveData)
if (context.Process.MetaData != null) currentTitleId = context.Process.MetaData.Aci0.TitleId;
{
if (context.Process.MetaData != null)
{
currentTitleId = context.Process.MetaData.Aci0.TitleId;
}
}
string saveAccount = saveMetaData.UserId.IsZero() ? "savecommon" : saveMetaData.UserId.ToString();

View file

@ -30,15 +30,24 @@ namespace Ryujinx.HLE.FileSystem
public string GetFullPath(string basePath, string fileName)
{
if (fileName.StartsWith("//"))
{
fileName = fileName.Substring(2);
}
else if (fileName.StartsWith('/'))
{
fileName = fileName.Substring(1);
}
else
{
return null;
}
string fullPath = Path.GetFullPath(Path.Combine(basePath, fileName));
if (!fullPath.StartsWith(GetBasePath())) return null;
if (!fullPath.StartsWith(GetBasePath()))
{
return null;
}
return fullPath;
}
@ -66,7 +75,11 @@ namespace Ryujinx.HLE.FileSystem
public string SwitchPathToSystemPath(string switchPath)
{
string[] parts = switchPath.Split(":");
if (parts.Length != 2) return null;
if (parts.Length != 2)
{
return null;
}
return GetFullPath(MakeDirAndGetFullPath(parts[0]), parts[1]);
}
@ -77,7 +90,10 @@ namespace Ryujinx.HLE.FileSystem
{
string rawPath = systemPath.Replace(baseSystemPath, "");
int firstSeparatorOffset = rawPath.IndexOf(Path.DirectorySeparatorChar);
if (firstSeparatorOffset == -1) return $"{rawPath}:/";
if (firstSeparatorOffset == -1)
{
return $"{rawPath}:/";
}
string basePath = rawPath.Substring(0, firstSeparatorOffset);
string fileName = rawPath.Substring(firstSeparatorOffset + 1);
@ -90,7 +106,10 @@ namespace Ryujinx.HLE.FileSystem
{
string fullPath = Path.Combine(GetBasePath(), dir);
if (!Directory.Exists(fullPath)) Directory.CreateDirectory(fullPath);
if (!Directory.Exists(fullPath))
{
Directory.CreateDirectory(fullPath);
}
return fullPath;
}
@ -114,7 +133,10 @@ namespace Ryujinx.HLE.FileSystem
protected virtual void Dispose(bool disposing)
{
if (disposing) RomFs?.Dispose();
if (disposing)
{
RomFs?.Dispose();
}
}
}
}

View file

@ -43,8 +43,13 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
writer.Write("[");
if (_dimensionString != null)
{
writer.Write(_dimensionString);
else if (_dimensionExpression != null) _dimensionExpression.Print(writer);
}
else if (_dimensionExpression != null)
{
_dimensionExpression.Print(writer);
}
writer.Write("]");

View file

@ -71,7 +71,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
{
PrintLeft(writer);
if (HasRightPart()) PrintRight(writer);
if (HasRightPart())
{
PrintRight(writer);
}
}
public abstract void PrintLeft(TextWriter writer);

View file

@ -17,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
public override void PrintLeft(TextWriter writer)
{
if (_name.Equals(">")) writer.Write("(");
if (_name.Equals(">"))
{
writer.Write("(");
}
writer.Write("(");
_leftPart.Print(writer);
@ -29,7 +32,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
_rightPart.Print(writer);
writer.Write(")");
if (_name.Equals(">")) writer.Write(")");
if (_name.Equals(">"))
{
writer.Write(")");
}
}
}
}

View file

@ -29,7 +29,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
_element.Print(writer);
}
if (!_expression.GetType().Equals(NodeType.BracedExpression) || !_expression.GetType().Equals(NodeType.BracedRangeExpression)) writer.Write(" = ");
if (!_expression.GetType().Equals(NodeType.BracedExpression) || !_expression.GetType().Equals(NodeType.BracedRangeExpression))
{
writer.Write(" = ");
}
_expression.Print(writer);
}

Some files were not shown because too many files have changed in this diff Show more