Misc cleanup (#708)

* Fix typos

* Remove unneeded using statements

* Enforce var style more

* Remove redundant qualifiers

* Fix some indentation

* Disable naming warnings on files with external enum names

* Fix build

* Mass find & replace for comments with no spacing

* Standardize todo capitalization and for/if spacing
This commit is contained in:
Alex Barney 2019-07-01 21:39:22 -05:00 committed by Ac_K
parent 10c74182ba
commit b2b736abc2
205 changed files with 1020 additions and 1041 deletions

View File

@ -24,8 +24,8 @@ namespace ChocolArm64.Decoders
{ {
public static Condition Invert(this Condition cond) public static Condition Invert(this Condition cond)
{ {
//Bit 0 of all conditions is basically a negation bit, so // Bit 0 of all conditions is basically a negation bit, so
//inverting this bit has the effect of inverting the condition. // inverting this bit has the effect of inverting the condition.
return (Condition)((int)cond ^ 1); return (Condition)((int)cond ^ 1);
} }
} }

View File

@ -29,12 +29,12 @@ namespace ChocolArm64.Decoders
if (IsBranch(lastOp) && !IsCall(lastOp) && lastOp is IOpCodeBImm op) if (IsBranch(lastOp) && !IsCall(lastOp) && lastOp is IOpCodeBImm op)
{ {
//It's possible that the branch on this block lands on the middle of the block. // It's possible that the branch on this block lands on the middle of the block.
//This is more common on tight loops. In this case, we can improve the codegen // This is more common on tight loops. In this case, we can improve the codegen
//a bit by changing the CFG and either making the branch point to the same block // a bit by changing the CFG and either making the branch point to the same block
//(which indicates that the block is a loop that jumps back to the start), and the // (which indicates that the block is a loop that jumps back to the start), and the
//other possible case is a jump somewhere on the middle of the block, which is // other possible case is a jump somewhere on the middle of the block, which is
//also a loop, but in this case we need to split the block in half. // also a loop, but in this case we need to split the block in half.
if ((ulong)op.Imm == address) if ((ulong)op.Imm == address)
{ {
block.Branch = block; block.Branch = block;
@ -79,7 +79,7 @@ namespace ChocolArm64.Decoders
while (workQueue.TryDequeue(out Block currBlock)) while (workQueue.TryDequeue(out Block currBlock))
{ {
//Check if the current block is inside another block. // Check if the current block is inside another block.
if (BinarySearch(blocks, currBlock.Address, out int nBlkIndex)) if (BinarySearch(blocks, currBlock.Address, out int nBlkIndex))
{ {
Block nBlock = blocks[nBlkIndex]; Block nBlock = blocks[nBlkIndex];
@ -96,7 +96,7 @@ namespace ChocolArm64.Decoders
continue; continue;
} }
//If we have a block after the current one, set the limit address. // If we have a block after the current one, set the limit address.
ulong limitAddress = ulong.MaxValue; ulong limitAddress = ulong.MaxValue;
if (nBlkIndex != blocks.Count) if (nBlkIndex != blocks.Count)
@ -119,10 +119,10 @@ namespace ChocolArm64.Decoders
if (currBlock.OpCodes.Count != 0) if (currBlock.OpCodes.Count != 0)
{ {
//Set child blocks. "Branch" is the block the branch instruction // Set child blocks. "Branch" is the block the branch instruction
//points to (when taken), "Next" is the block at the next address, // points to (when taken), "Next" is the block at the next address,
//executed when the branch is not taken. For Unconditional Branches // executed when the branch is not taken. For Unconditional Branches
//(except BL/BLR that are sub calls) or end of executable, Next is null. // (except BL/BLR that are sub calls) or end of executable, Next is null.
OpCode64 lastOp = currBlock.GetLastOp(); OpCode64 lastOp = currBlock.GetLastOp();
bool isCall = IsCall(lastOp); bool isCall = IsCall(lastOp);
@ -138,7 +138,7 @@ namespace ChocolArm64.Decoders
} }
} }
//Insert the new block on the list (sorted by address). // Insert the new block on the list (sorted by address).
if (blocks.Count != 0) if (blocks.Count != 0)
{ {
Block nBlock = blocks[nBlkIndex]; Block nBlock = blocks[nBlkIndex];
@ -236,25 +236,25 @@ namespace ChocolArm64.Decoders
return false; return false;
} }
//Note: On ARM32, most instructions have conditional execution, // Note: On ARM32, most instructions have conditional execution,
//so there's no "Always" (unconditional) branch like on ARM64. // so there's no "Always" (unconditional) branch like on ARM64.
//We need to check if the condition is "Always" instead. // We need to check if the condition is "Always" instead.
return IsAarch32Branch(op) && op.Cond >= Condition.Al; return IsAarch32Branch(op) && op.Cond >= Condition.Al;
} }
private static bool IsAarch32Branch(OpCode64 opCode) private static bool IsAarch32Branch(OpCode64 opCode)
{ {
//Note: On ARM32, most ALU operations can write to R15 (PC), // Note: On ARM32, most ALU operations can write to R15 (PC),
//so we must consider such operations as a branch in potential aswell. // so we must consider such operations as a branch in potential as well.
if (opCode is IOpCode32Alu opAlu && opAlu.Rd == RegisterAlias.Aarch32Pc) if (opCode is IOpCode32Alu opAlu && opAlu.Rd == RegisterAlias.Aarch32Pc)
{ {
return true; return true;
} }
//Same thing for memory operations. We have the cases where PC is a target // Same thing for memory operations. We have the cases where PC is a target
//register (Rt == 15 or (mask & (1 << 15)) != 0), and cases where there is // register (Rt == 15 or (mask & (1 << 15)) != 0), and cases where there is
//a write back to PC (wback == true && Rn == 15), however the later may // a write back to PC (wback == true && Rn == 15), however the later may
//be "undefined" depending on the CPU, so compilers should not produce that. // be "undefined" depending on the CPU, so compilers should not produce that.
if (opCode is IOpCode32Mem || opCode is IOpCode32MemMult) if (opCode is IOpCode32Mem || opCode is IOpCode32MemMult)
{ {
int rt, rn; int rt, rn;
@ -268,8 +268,8 @@ namespace ChocolArm64.Decoders
wBack = opMem.WBack; wBack = opMem.WBack;
isLoad = opMem.IsLoad; isLoad = opMem.IsLoad;
//For the dual load, we also need to take into account the // For the dual load, we also need to take into account the
//case were Rt2 == 15 (PC). // case were Rt2 == 15 (PC).
if (rt == 14 && opMem.Emitter == InstEmit32.Ldrd) if (rt == 14 && opMem.Emitter == InstEmit32.Ldrd)
{ {
rt = RegisterAlias.Aarch32Pc; rt = RegisterAlias.Aarch32Pc;
@ -296,14 +296,14 @@ namespace ChocolArm64.Decoders
} }
} }
//Explicit branch instructions. // Explicit branch instructions.
return opCode is IOpCode32BImm || return opCode is IOpCode32BImm ||
opCode is IOpCode32BReg; opCode is IOpCode32BReg;
} }
private static bool IsCall(OpCode64 opCode) private static bool IsCall(OpCode64 opCode)
{ {
//TODO (CQ): ARM32 support. // TODO (CQ): ARM32 support.
return opCode.Emitter == InstEmit.Bl || return opCode.Emitter == InstEmit.Bl ||
opCode.Emitter == InstEmit.Blr; opCode.Emitter == InstEmit.Blr;
} }

View File

@ -16,8 +16,8 @@ namespace ChocolArm64.Decoders
public uint GetPc() public uint GetPc()
{ {
//Due to backwards compatibility and legacy behavior of ARMv4 CPUs pipeline, // Due to backwards compatibility and legacy behavior of ARMv4 CPUs pipeline,
//the PC actually points 2 instructions ahead. // the PC actually points 2 instructions ahead.
return (uint)Position + (uint)OpCodeSizeInBytes * 2; return (uint)Position + (uint)OpCodeSizeInBytes * 2;
} }
} }

View File

@ -10,7 +10,7 @@ namespace ChocolArm64.Decoders
{ {
uint pc = GetPc(); uint pc = GetPc();
//When the codition is never, the instruction is BLX to Thumb mode. // When the condition is never, the instruction is BLX to Thumb mode.
if (Cond != Condition.Nv) if (Cond != Condition.Nv)
{ {
pc &= ~3u; pc &= ~3u;

View File

@ -23,16 +23,16 @@ namespace ChocolArm64.Decoders
Extend64 = ((opCode >> 22) & 3) == 2; Extend64 = ((opCode >> 22) & 3) == 2;
WBack = ((opCode >> 24) & 1) == 0; WBack = ((opCode >> 24) & 1) == 0;
//The type is not valid for the Unsigned Immediate 12-bits encoding, // The type is not valid for the Unsigned Immediate 12-bits encoding,
//because the bits 11:10 are used for the larger Immediate offset. // because the bits 11:10 are used for the larger Immediate offset.
MemOp type = WBack ? (MemOp)((opCode >> 10) & 3) : MemOp.Unsigned; MemOp type = WBack ? (MemOp)((opCode >> 10) & 3) : MemOp.Unsigned;
PostIdx = type == MemOp.PostIndexed; PostIdx = type == MemOp.PostIndexed;
Unscaled = type == MemOp.Unscaled || Unscaled = type == MemOp.Unscaled ||
type == MemOp.Unprivileged; type == MemOp.Unprivileged;
//Unscaled and Unprivileged doesn't write back, // Unscaled and Unprivileged doesn't write back,
//but they do use the 9-bits Signed Immediate. // but they do use the 9-bits Signed Immediate.
if (Unscaled) if (Unscaled)
{ {
WBack = false; WBack = false;
@ -40,12 +40,12 @@ namespace ChocolArm64.Decoders
if (WBack || Unscaled) if (WBack || Unscaled)
{ {
//9-bits Signed Immediate. // 9-bits Signed Immediate.
Imm = (opCode << 11) >> 23; Imm = (opCode << 11) >> 23;
} }
else else
{ {
//12-bits Unsigned Immediate. // 12-bits Unsigned Immediate.
Imm = ((opCode >> 10) & 0xfff) << Size; Imm = ((opCode >> 10) & 0xfff) << Size;
} }
} }

View File

@ -30,14 +30,14 @@ namespace ChocolArm64.Decoders
switch (op | (modeLow << 1)) switch (op | (modeLow << 1))
{ {
case 0: case 0:
//64-bits Immediate. // 64-bits Immediate.
//Transform abcd efgh into abcd efgh abcd efgh ... // Transform abcd efgh into abcd efgh abcd efgh ...
imm = (long)((ulong)imm * 0x0101010101010101); imm = (long)((ulong)imm * 0x0101010101010101);
break; break;
case 1: case 1:
//64-bits Immediate. // 64-bits Immediate.
//Transform abcd efgh into aaaa aaaa bbbb bbbb ... // Transform abcd efgh into aaaa aaaa bbbb bbbb ...
imm = (imm & 0xf0) >> 4 | (imm & 0x0f) << 4; imm = (imm & 0xf0) >> 4 | (imm & 0x0f) << 4;
imm = (imm & 0xcc) >> 2 | (imm & 0x33) << 2; imm = (imm & 0xcc) >> 2 | (imm & 0x33) << 2;
imm = (imm & 0xaa) >> 1 | (imm & 0x55) << 1; imm = (imm & 0xaa) >> 1 | (imm & 0x55) << 1;
@ -52,29 +52,29 @@ namespace ChocolArm64.Decoders
case 2: case 2:
case 3: case 3:
//Floating point Immediate. // Floating point Immediate.
imm = DecoderHelper.DecodeImm8Float(imm, Size); imm = DecoderHelper.DecodeImm8Float(imm, Size);
break; break;
} }
} }
else if ((modeHigh & 0b110) == 0b100) else if ((modeHigh & 0b110) == 0b100)
{ {
//16-bits shifted Immediate. // 16-bits shifted Immediate.
Size = 1; imm <<= (modeHigh & 1) << 3; Size = 1; imm <<= (modeHigh & 1) << 3;
} }
else if ((modeHigh & 0b100) == 0b000) else if ((modeHigh & 0b100) == 0b000)
{ {
//32-bits shifted Immediate. // 32-bits shifted Immediate.
Size = 2; imm <<= modeHigh << 3; Size = 2; imm <<= modeHigh << 3;
} }
else if ((modeHigh & 0b111) == 0b110) else if ((modeHigh & 0b111) == 0b110)
{ {
//32-bits shifted Immediate (fill with ones). // 32-bits shifted Immediate (fill with ones).
Size = 2; imm = ShlOnes(imm, 8 << modeLow); Size = 2; imm = ShlOnes(imm, 8 << modeLow);
} }
else else
{ {
//8 bits without shift. // 8 bits without shift.
Size = 0; Size = 0;
} }

View File

@ -24,7 +24,7 @@ namespace ChocolArm64.Instructions
} }
else else
{ {
context.EmitLdint(InstEmit32Helper.GetRegisterAlias(context.Mode, register)); context.EmitLdint(GetRegisterAlias(context.Mode, register));
} }
} }

View File

@ -151,7 +151,7 @@ namespace ChocolArm64.Instructions
public static void Extr(ILEmitterCtx context) public static void Extr(ILEmitterCtx context)
{ {
//TODO: Ensure that the Shift is valid for the Is64Bits. // TODO: Ensure that the Shift is valid for the Is64Bits.
OpCodeAluRs64 op = (OpCodeAluRs64)context.CurrOp; OpCodeAluRs64 op = (OpCodeAluRs64)context.CurrOp;
context.EmitLdintzr(op.Rm); context.EmitLdintzr(op.Rm);
@ -309,7 +309,7 @@ namespace ChocolArm64.Instructions
private static void EmitDiv(ILEmitterCtx context, OpCode ilOp) private static void EmitDiv(ILEmitterCtx context, OpCode ilOp)
{ {
//If Rm == 0, Rd = 0 (division by zero). // If Rm == 0, Rd = 0 (division by zero).
context.EmitLdc_I(0); context.EmitLdc_I(0);
EmitAluLoadRm(context); EmitAluLoadRm(context);
@ -323,7 +323,7 @@ namespace ChocolArm64.Instructions
if (ilOp == OpCodes.Div) if (ilOp == OpCodes.Div)
{ {
//If Rn == INT_MIN && Rm == -1, Rd = INT_MIN (overflow). // If Rn == INT_MIN && Rm == -1, Rd = INT_MIN (overflow).
long intMin = 1L << (context.CurrOp.GetBitsCount() - 1); long intMin = 1L << (context.CurrOp.GetBitsCount() - 1);
context.EmitLdc_I(intMin); context.EmitLdc_I(intMin);
@ -381,10 +381,10 @@ namespace ChocolArm64.Instructions
context.Emit(OpCodes.And); context.Emit(OpCodes.And);
//Note: Only 32-bits shift values are valid, so when the value is 64-bits // Note: Only 32-bits shift values are valid, so when the value is 64-bits
//we need to cast it to a 32-bits integer. This is fine because we // 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 // AND the value and only keep the lower 5 or 6 bits anyway -- it
//could very well fit on a byte. // could very well fit on a byte.
if (context.CurrOp.RegisterSize != RegisterSize.Int32) if (context.CurrOp.RegisterSize != RegisterSize.Int32)
{ {
context.Emit(OpCodes.Conv_I4); context.Emit(OpCodes.Conv_I4);

View File

@ -87,7 +87,7 @@ namespace ChocolArm64.Instructions
{ {
if (op.SetFlags) if (op.SetFlags)
{ {
//TODO: Load SPSR etc. // TODO: Load SPSR etc.
context.EmitLdflg((int)PState.TBit); context.EmitLdflg((int)PState.TBit);

View File

@ -10,7 +10,7 @@ namespace ChocolArm64.Instructions
{ {
public static void EmitAdcsCCheck(ILEmitterCtx context) public static void EmitAdcsCCheck(ILEmitterCtx context)
{ {
//C = (Rd == Rn && CIn) || Rd < Rn // C = (Rd == Rn && CIn) || Rd < Rn
context.EmitSttmp(); context.EmitSttmp();
context.EmitLdtmp(); context.EmitLdtmp();
context.EmitLdtmp(); context.EmitLdtmp();
@ -35,7 +35,7 @@ namespace ChocolArm64.Instructions
public static void EmitAddsCCheck(ILEmitterCtx context) public static void EmitAddsCCheck(ILEmitterCtx context)
{ {
//C = Rd < Rn // C = Rd < Rn
context.Emit(OpCodes.Dup); context.Emit(OpCodes.Dup);
EmitAluLoadRn(context); EmitAluLoadRn(context);
@ -47,7 +47,7 @@ namespace ChocolArm64.Instructions
public static void EmitAddsVCheck(ILEmitterCtx context) public static void EmitAddsVCheck(ILEmitterCtx context)
{ {
//V = (Rd ^ Rn) & ~(Rn ^ Rm) < 0 // V = (Rd ^ Rn) & ~(Rn ^ Rm) < 0
context.Emit(OpCodes.Dup); context.Emit(OpCodes.Dup);
EmitAluLoadRn(context); EmitAluLoadRn(context);
@ -69,7 +69,7 @@ namespace ChocolArm64.Instructions
public static void EmitSbcsCCheck(ILEmitterCtx context) public static void EmitSbcsCCheck(ILEmitterCtx context)
{ {
//C = (Rn == Rm && CIn) || Rn > Rm // C = (Rn == Rm && CIn) || Rn > Rm
EmitAluLoadOpers(context); EmitAluLoadOpers(context);
context.Emit(OpCodes.Ceq); context.Emit(OpCodes.Ceq);
@ -88,7 +88,7 @@ namespace ChocolArm64.Instructions
public static void EmitSubsCCheck(ILEmitterCtx context) public static void EmitSubsCCheck(ILEmitterCtx context)
{ {
//C = Rn == Rm || Rn > Rm = !(Rn < Rm) // C = Rn == Rm || Rn > Rm = !(Rn < Rm)
EmitAluLoadOpers(context); EmitAluLoadOpers(context);
context.Emit(OpCodes.Clt_Un); context.Emit(OpCodes.Clt_Un);
@ -102,7 +102,7 @@ namespace ChocolArm64.Instructions
public static void EmitSubsVCheck(ILEmitterCtx context) public static void EmitSubsVCheck(ILEmitterCtx context)
{ {
//V = (Rd ^ Rn) & (Rn ^ Rm) < 0 // V = (Rd ^ Rn) & (Rn ^ Rm) < 0
context.Emit(OpCodes.Dup); context.Emit(OpCodes.Dup);
EmitAluLoadRn(context); EmitAluLoadRn(context);
@ -170,7 +170,7 @@ namespace ChocolArm64.Instructions
{ {
switch (context.CurrOp) switch (context.CurrOp)
{ {
//ARM32. // ARM32.
case OpCode32AluImm op: case OpCode32AluImm op:
context.EmitLdc_I4(op.Imm); context.EmitLdc_I4(op.Imm);
@ -190,7 +190,7 @@ namespace ChocolArm64.Instructions
context.EmitLdc_I4(op.Imm); context.EmitLdc_I4(op.Imm);
break; break;
//ARM64. // ARM64.
case IOpCodeAluImm64 op: case IOpCodeAluImm64 op:
context.EmitLdc_I(op.Imm); context.EmitLdc_I(op.Imm);
break; break;
@ -245,7 +245,7 @@ namespace ChocolArm64.Instructions
context.EmitStflg((int)PState.NBit); context.EmitStflg((int)PState.NBit);
} }
//ARM32 helpers. // ARM32 helpers.
private static void EmitLoadRmShiftedByImmediate(ILEmitterCtx context, OpCode32AluRsImm op, bool setCarry) private static void EmitLoadRmShiftedByImmediate(ILEmitterCtx context, OpCode32AluRsImm op, bool setCarry)
{ {
int shift = op.Imm; int shift = op.Imm;
@ -432,7 +432,7 @@ namespace ChocolArm64.Instructions
private static void EmitRrxC(ILEmitterCtx context, bool setCarry) private static void EmitRrxC(ILEmitterCtx context, bool setCarry)
{ {
//Rotate right by 1 with carry. // Rotate right by 1 with carry.
if (setCarry) if (setCarry)
{ {
context.Emit(OpCodes.Dup); context.Emit(OpCodes.Dup);

View File

@ -13,7 +13,7 @@ namespace ChocolArm64.Instructions
if (op.Pos < op.Shift) if (op.Pos < op.Shift)
{ {
//BFI. // BFI.
context.EmitLdintzr(op.Rn); context.EmitLdintzr(op.Rn);
int shift = op.GetBitsCount() - op.Shift; int shift = op.GetBitsCount() - op.Shift;
@ -39,7 +39,7 @@ namespace ChocolArm64.Instructions
} }
else else
{ {
//BFXIL. // BFXIL.
context.EmitLdintzr(op.Rn); context.EmitLdintzr(op.Rn);
context.EmitLsr(op.Shift); context.EmitLsr(op.Shift);

View File

@ -31,8 +31,8 @@ namespace ChocolArm64.Instructions
context.EmitPrivateCall(typeof(CpuThreadState), mthdName); context.EmitPrivateCall(typeof(CpuThreadState), mthdName);
//Check if the thread should still be running, if it isn't then we return 0 // Check if the thread should still be running, if it isn't then we return 0
//to force a return to the dispatcher and then exit the thread. // to force a return to the dispatcher and then exit the thread.
context.EmitLdarg(TranslatedSub.StateArgIdx); context.EmitLdarg(TranslatedSub.StateArgIdx);
context.EmitCallPropGet(typeof(CpuThreadState), nameof(CpuThreadState.Running)); context.EmitCallPropGet(typeof(CpuThreadState), nameof(CpuThreadState.Running));

View File

@ -66,8 +66,8 @@ namespace ChocolArm64.Instructions
context.EmitStint(GetBankedRegisterAlias(context.Mode, RegisterAlias.Aarch32Lr)); context.EmitStint(GetBankedRegisterAlias(context.Mode, RegisterAlias.Aarch32Lr));
//If x is true, then this is a branch with link and exchange. // If x is true, then this is a branch with link and exchange.
//In this case we need to swap the mode between Arm <-> Thumb. // In this case we need to swap the mode between Arm <-> Thumb.
if (x) if (x)
{ {
context.EmitLdc_I4(isThumb ? 0 : 1); context.EmitLdc_I4(isThumb ? 0 : 1);

View File

@ -90,10 +90,10 @@ namespace ChocolArm64.Instructions
if (isJump) if (isJump)
{ {
//The tail prefix allows the JIT to jump to the next function, // The tail prefix allows the JIT to jump to the next function,
//while releasing the stack space used by the current one. // while releasing the stack space used by the current one.
//This is ideal for BR ARM instructions, which are // This is ideal for BR ARM instructions, which are
//basically indirect tail calls. // basically indirect tail calls.
context.Emit(OpCodes.Tailcall); context.Emit(OpCodes.Tailcall);
} }
@ -114,10 +114,10 @@ namespace ChocolArm64.Instructions
private static void EmitContinueOrReturnCheck(ILEmitterCtx context) private static void EmitContinueOrReturnCheck(ILEmitterCtx context)
{ {
//Note: The return value of the called method will be placed // Note: The return value of the called method will be placed
//at the Stack, the return value is always a Int64 with the // at the Stack, the return value is always a Int64 with the
//return address of the function. We check if the address is // return address of the function. We check if the address is
//correct, if it isn't we keep returning until we reach the dispatcher. // correct, if it isn't we keep returning until we reach the dispatcher.
if (context.CurrBlock.Next != null) if (context.CurrBlock.Next != null)
{ {
context.Emit(OpCodes.Dup); context.Emit(OpCodes.Dup);

View File

@ -192,7 +192,7 @@ namespace ChocolArm64.Instructions
if (!op.PostIdx) if (!op.PostIdx)
{ {
//Pre-indexing. // Pre-indexing.
context.EmitLdc_I(op.Imm); context.EmitLdc_I(op.Imm);
context.Emit(OpCodes.Add); context.Emit(OpCodes.Add);
@ -213,7 +213,7 @@ namespace ChocolArm64.Instructions
break; break;
} }
//Save address to Scratch var since the register value may change. // Save address to Scratch var since the register value may change.
context.Emit(OpCodes.Dup); context.Emit(OpCodes.Dup);
context.EmitSttmp(); context.EmitSttmp();
@ -221,8 +221,8 @@ namespace ChocolArm64.Instructions
private static void EmitWBackIfNeeded(ILEmitterCtx context) private static void EmitWBackIfNeeded(ILEmitterCtx context)
{ {
//Check whenever the current OpCode has post-indexed write back, if so write it. // Check whenever the current OpCode has post-indexed write back, if so write it.
//Note: AOpCodeMemPair inherits from AOpCodeMemImm, so this works for both. // Note: AOpCodeMemPair inherits from AOpCodeMemImm, so this works for both.
if (context.CurrOp is OpCodeMemImm64 op && op.WBack) if (context.CurrOp is OpCodeMemImm64 op && op.WBack)
{ {
context.EmitLdtmp(); context.EmitLdtmp();

View File

@ -137,15 +137,15 @@ namespace ChocolArm64.Instructions
EmitWriteCall(context, WordSizeLog2); EmitWriteCall(context, WordSizeLog2);
//Note: If Rn is also specified on the register list, // Note: If Rn is also specified on the register list,
//and Rn is the first register on this list, then the // and Rn is the first register on this list, then the
//value that is written to memory is the unmodified value, // value that is written to memory is the unmodified value,
//before the write back. If it is on the list, but it's // before the write back. If it is on the list, but it's
//not the first one, then the value written to memory // not the first one, then the value written to memory
//varies between CPUs. // varies between CPUs.
if (offset == 0 && op.PostOffset != 0) if (offset == 0 && op.PostOffset != 0)
{ {
//Emit write back after the first write. // Emit write back after the first write.
EmitLoadFromRegister(context, op.Rn); EmitLoadFromRegister(context, op.Rn);
context.EmitLdc_I4(op.PostOffset); context.EmitLdc_I4(op.PostOffset);
@ -233,7 +233,7 @@ namespace ChocolArm64.Instructions
context.Emit(OpCodes.Brtrue_S, lblBigEndian); context.Emit(OpCodes.Brtrue_S, lblBigEndian);
//Little endian mode. // Little endian mode.
context.Emit(OpCodes.Conv_U4); context.Emit(OpCodes.Conv_U4);
EmitStoreToRegister(context, op.Rt); EmitStoreToRegister(context, op.Rt);
@ -246,7 +246,7 @@ namespace ChocolArm64.Instructions
context.Emit(OpCodes.Br_S, lblEnd); context.Emit(OpCodes.Br_S, lblEnd);
//Big endian mode. // Big endian mode.
context.MarkLabel(lblBigEndian); context.MarkLabel(lblBigEndian);
context.EmitLsr(32); context.EmitLsr(32);
@ -288,7 +288,7 @@ namespace ChocolArm64.Instructions
context.Emit(OpCodes.Brtrue_S, lblBigEndian); context.Emit(OpCodes.Brtrue_S, lblBigEndian);
//Little endian mode. // Little endian mode.
EmitLoadFromRegister(context, op.Rt | 1); EmitLoadFromRegister(context, op.Rt | 1);
context.Emit(OpCodes.Conv_U8); context.Emit(OpCodes.Conv_U8);
@ -299,7 +299,7 @@ namespace ChocolArm64.Instructions
context.Emit(OpCodes.Br_S, lblEnd); context.Emit(OpCodes.Br_S, lblEnd);
//Big endian mode. // Big endian mode.
context.MarkLabel(lblBigEndian); context.MarkLabel(lblBigEndian);
context.EmitLsl(32); context.EmitLsl(32);

View File

@ -89,10 +89,10 @@ namespace ChocolArm64.Instructions
if (pair) if (pair)
{ {
//Exclusive loads should be atomic. For pairwise loads, we need to // Exclusive loads should be atomic. For pairwise loads, we need to
//read all the data at once. For a 32-bits pairwise load, we do a // read all the data at once. For a 32-bits pairwise load, we do a
//simple 64-bits load, for a 128-bits load, we need to call a special // simple 64-bits load, for a 128-bits load, we need to call a special
//method to read 128-bits atomically. // method to read 128-bits atomically.
if (op.Size == 2) if (op.Size == 2)
{ {
context.EmitLdtmp(); context.EmitLdtmp();
@ -101,7 +101,7 @@ namespace ChocolArm64.Instructions
context.Emit(OpCodes.Dup); context.Emit(OpCodes.Dup);
//Mask low half. // Mask low half.
context.Emit(OpCodes.Conv_U4); context.Emit(OpCodes.Conv_U4);
if (exclusive) if (exclusive)
@ -111,7 +111,7 @@ namespace ChocolArm64.Instructions
context.EmitStintzr(op.Rt); context.EmitStintzr(op.Rt);
//Shift high half. // Shift high half.
context.EmitLsr(32); context.EmitLsr(32);
context.Emit(OpCodes.Conv_U4); context.Emit(OpCodes.Conv_U4);
@ -131,7 +131,7 @@ namespace ChocolArm64.Instructions
context.Emit(OpCodes.Dup); context.Emit(OpCodes.Dup);
//Load low part of the vector. // Load low part of the vector.
context.EmitLdc_I4(0); context.EmitLdc_I4(0);
context.EmitLdc_I4(3); context.EmitLdc_I4(3);
@ -144,7 +144,7 @@ namespace ChocolArm64.Instructions
context.EmitStintzr(op.Rt); context.EmitStintzr(op.Rt);
//Load high part of the vector. // Load high part of the vector.
context.EmitLdc_I4(1); context.EmitLdc_I4(1);
context.EmitLdc_I4(3); context.EmitLdc_I4(3);
@ -164,7 +164,7 @@ namespace ChocolArm64.Instructions
} }
else else
{ {
//8, 16, 32 or 64-bits (non-pairwise) load. // 8, 16, 32 or 64-bits (non-pairwise) load.
context.EmitLdtmp(); context.EmitLdtmp();
EmitReadZxCall(context, op.Size); EmitReadZxCall(context, op.Size);
@ -180,7 +180,7 @@ namespace ChocolArm64.Instructions
public static void Pfrm(ILEmitterCtx context) public static void Pfrm(ILEmitterCtx context)
{ {
//Memory Prefetch, execute as no-op. // Memory Prefetch, execute as no-op.
} }
public static void Stlr(ILEmitterCtx context) => EmitStr(context, AccessType.Ordered); public static void Stlr(ILEmitterCtx context) => EmitStr(context, AccessType.Ordered);
@ -223,13 +223,13 @@ namespace ChocolArm64.Instructions
context.Emit(OpCodes.Brtrue_S, lblEx); context.Emit(OpCodes.Brtrue_S, lblEx);
//Address check failed, set error right away and do not store anything. // Address check failed, set error right away and do not store anything.
context.EmitLdc_I4(1); context.EmitLdc_I4(1);
context.EmitStintzr(op.Rs); context.EmitStintzr(op.Rs);
context.Emit(OpCodes.Br, lblEnd); context.Emit(OpCodes.Br, lblEnd);
//Address check passsed. // Address check passed.
context.MarkLabel(lblEx); context.MarkLabel(lblEx);
context.EmitLdarg(TranslatedSub.MemoryArgIdx); context.EmitLdarg(TranslatedSub.MemoryArgIdx);
@ -241,7 +241,7 @@ namespace ChocolArm64.Instructions
void EmitCast() void EmitCast()
{ {
//The input should be always int64. // The input should be always int64.
switch (op.Size) switch (op.Size)
{ {
case 0: context.Emit(OpCodes.Conv_U1); break; case 0: context.Emit(OpCodes.Conv_U1); break;
@ -293,10 +293,10 @@ namespace ChocolArm64.Instructions
} }
} }
//The value returned is a bool, true if the values compared // The value returned is a bool, true if the values compared
//were equal and the new value was written, false otherwise. // were equal and the new value was written, false otherwise.
//We need to invert this result, as on ARM 1 indicates failure, // We need to invert this result, as on ARM 1 indicates failure,
//and 0 success on those instructions. // and 0 success on those instructions.
context.EmitLdc_I4(1); context.EmitLdc_I4(1);
context.Emit(OpCodes.Xor); context.Emit(OpCodes.Xor);
@ -305,7 +305,7 @@ namespace ChocolArm64.Instructions
context.EmitStintzr(op.Rs); context.EmitStintzr(op.Rs);
//Only clear the exclusive monitor if the store was successful (Rs = false). // Only clear the exclusive monitor if the store was successful (Rs = false).
context.Emit(OpCodes.Brtrue_S, lblEnd); context.Emit(OpCodes.Brtrue_S, lblEnd);
Clrex(context); Clrex(context);
@ -341,9 +341,9 @@ namespace ChocolArm64.Instructions
private static void EmitBarrier(ILEmitterCtx context) private static void EmitBarrier(ILEmitterCtx context)
{ {
//Note: This barrier is most likely not necessary, and probably // Note: This barrier is most likely not necessary, and probably
//doesn't make any difference since we need to do a ton of stuff // doesn't make any difference since we need to do a ton of stuff
//(software MMU emulation) to read or write anything anyway. // (software MMU emulation) to read or write anything anyway.
context.EmitCall(typeof(Thread), nameof(Thread.MemoryBarrier)); context.EmitCall(typeof(Thread), nameof(Thread.MemoryBarrier));
} }
} }

View File

@ -40,7 +40,7 @@ namespace ChocolArm64.Instructions
private static void EmitReadCall(ILEmitterCtx context, Extension ext, int size) private static void EmitReadCall(ILEmitterCtx context, Extension ext, int size)
{ {
//Save the address into a temp. // Save the address into a temp.
context.EmitStint(_tempIntAddress); context.EmitStint(_tempIntAddress);
bool isSimd = IsSimd(context); bool isSimd = IsSimd(context);
@ -99,7 +99,7 @@ namespace ChocolArm64.Instructions
{ {
bool isSimd = IsSimd(context); bool isSimd = IsSimd(context);
//Save the value into a temp. // Save the value into a temp.
if (isSimd) if (isSimd)
{ {
context.EmitStvec(_tempVecValue); context.EmitStvec(_tempVecValue);
@ -109,7 +109,7 @@ namespace ChocolArm64.Instructions
context.EmitStint(_tempIntValue); context.EmitStint(_tempIntValue);
} }
//Save the address into a temp. // Save the address into a temp.
context.EmitStint(_tempIntAddress); context.EmitStint(_tempIntAddress);
if (size < 0 || size > (isSimd ? 4 : 3)) if (size < 0 || size > (isSimd ? 4 : 3))

View File

@ -1298,8 +1298,8 @@ namespace ChocolArm64.Instructions
{ {
if (Optimizations.UseSse41 && size == 0) if (Optimizations.UseSse41 && size == 0)
{ {
//If the type is float, we can perform insertion and // If the type is float, we can perform insertion and
//zero the upper bits with a single instruction (INSERTPS); // zero the upper bits with a single instruction (INSERTPS);
context.EmitLdvec(reg); context.EmitLdvec(reg);
VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41VectorInsertScalarSingle)); VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41VectorInsertScalarSingle));

View File

@ -96,7 +96,7 @@ namespace ChocolArm64.Instructions
if (op.Replicate) if (op.Replicate)
{ {
//Only loads uses the replicate mode. // Only loads uses the replicate mode.
if (!isLoad) if (!isLoad)
{ {
throw new InvalidOperationException(); throw new InvalidOperationException();

View File

@ -11,12 +11,12 @@ namespace ChocolArm64.Instructions
{ {
public static void Hint(ILEmitterCtx context) public static void Hint(ILEmitterCtx context)
{ {
//Execute as no-op. // Execute as no-op.
} }
public static void Isb(ILEmitterCtx context) public static void Isb(ILEmitterCtx context)
{ {
//Execute as no-op. // Execute as no-op.
} }
public static void Mrs(ILEmitterCtx context) public static void Mrs(ILEmitterCtx context)
@ -85,21 +85,21 @@ namespace ChocolArm64.Instructions
public static void Nop(ILEmitterCtx context) public static void Nop(ILEmitterCtx context)
{ {
//Do nothing. // Do nothing.
} }
public static void Sys(ILEmitterCtx context) public static void Sys(ILEmitterCtx context)
{ {
//This instruction is used to do some operations on the CPU like cache invalidation, // This instruction is used to do some operations on the CPU like cache invalidation,
//address translation and the like. // address translation and the like.
//We treat it as no-op here since we don't have any cache being emulated anyway. // We treat it as no-op here since we don't have any cache being emulated anyway.
OpCodeSystem64 op = (OpCodeSystem64)context.CurrOp; OpCodeSystem64 op = (OpCodeSystem64)context.CurrOp;
switch (GetPackedId(op)) switch (GetPackedId(op))
{ {
case 0b11_011_0111_0100_001: case 0b11_011_0111_0100_001:
{ {
//DC ZVA // DC ZVA
for (int offs = 0; offs < (4 << CpuThreadState.DczSizeLog2); offs += 8) for (int offs = 0; offs < (4 << CpuThreadState.DczSizeLog2); offs += 8)
{ {
context.EmitLdintzr(op.Rt); context.EmitLdintzr(op.Rt);
@ -115,7 +115,7 @@ namespace ChocolArm64.Instructions
break; break;
} }
//No-op // No-op
case 0b11_011_0111_1110_001: //DC CIVAC case 0b11_011_0111_1110_001: //DC CIVAC
break; break;
} }

View File

@ -583,9 +583,9 @@ namespace ChocolArm64.Instructions
{ {
if (Sse41.IsSupported) if (Sse41.IsSupported)
{ {
//Note: The if/else if is necessary to enable the JIT to // Note: The if/else if is necessary to enable the JIT to
//produce a single INSERTPS instruction instead of the // produce a single INSERTPS instruction instead of the
//jump table fallback. // jump table fallback.
if (index == 0) if (index == 0)
{ {
return Sse41.Insert(vector, value, 0x00); return Sse41.Insert(vector, value, 0x00);
@ -628,7 +628,7 @@ namespace ChocolArm64.Instructions
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> Sse41VectorInsertScalarSingle(float value, Vector128<float> vector) public static Vector128<float> Sse41VectorInsertScalarSingle(float value, Vector128<float> vector)
{ {
//Note: 0b1110 is the mask to zero the upper bits. // Note: 0b1110 is the mask to zero the upper bits.
return Sse41.Insert(vector, value, 0b1110); return Sse41.Insert(vector, value, 0b1110);
} }

View File

@ -96,9 +96,9 @@ namespace ChocolArm64.Memory
IntPtr[] addresses, IntPtr[] addresses,
out ulong count) out ulong count)
{ {
//This is only supported on windows, but returning // This is only supported on windows, but returning
//false (failed) is also valid for platforms without // false (failed) is also valid for platforms without
//write tracking support on the OS. // write tracking support on the OS.
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {
return MemoryManagementWindows.GetModifiedPages(address, size, addresses, out count); return MemoryManagementWindows.GetModifiedPages(address, size, addresses, out count);

View File

@ -30,22 +30,22 @@ namespace ChocolArm64.Memory
return ptr; return ptr;
} }
public static bool Reprotect(IntPtr address, ulong size, Memory.MemoryProtection protection) public static bool Reprotect(IntPtr address, ulong size, MemoryProtection protection)
{ {
MmapProts prot = GetProtection(protection); MmapProts prot = GetProtection(protection);
return Syscall.mprotect(address, size, prot) == 0; return Syscall.mprotect(address, size, prot) == 0;
} }
private static MmapProts GetProtection(Memory.MemoryProtection protection) private static MmapProts GetProtection(MemoryProtection protection)
{ {
switch (protection) switch (protection)
{ {
case Memory.MemoryProtection.None: return MmapProts.PROT_NONE; case MemoryProtection.None: return MmapProts.PROT_NONE;
case Memory.MemoryProtection.Read: return MmapProts.PROT_READ; case MemoryProtection.Read: return MmapProts.PROT_READ;
case Memory.MemoryProtection.ReadAndWrite: return MmapProts.PROT_READ | MmapProts.PROT_WRITE; case MemoryProtection.ReadAndWrite: return MmapProts.PROT_READ | MmapProts.PROT_WRITE;
case Memory.MemoryProtection.ReadAndExecute: return MmapProts.PROT_READ | MmapProts.PROT_EXEC; case MemoryProtection.ReadAndExecute: return MmapProts.PROT_READ | MmapProts.PROT_EXEC;
case Memory.MemoryProtection.Execute: return MmapProts.PROT_EXEC; case MemoryProtection.Execute: return MmapProts.PROT_EXEC;
default: throw new ArgumentException($"Invalid permission \"{protection}\"."); default: throw new ArgumentException($"Invalid permission \"{protection}\".");
} }

View File

@ -50,12 +50,12 @@ namespace ChocolArm64.Memory
AddressSpaceBits = addressSpaceBits; AddressSpaceBits = addressSpaceBits;
AddressSpaceSize = 1L << addressSpaceBits; AddressSpaceSize = 1L << addressSpaceBits;
//When flat page table is requested, we use a single // When flat page table is requested, we use a single
//array for the mappings of the entire address space. // array for the mappings of the entire address space.
//This has better performance, but also high memory usage. // This has better performance, but also high memory usage.
//The multi level page table uses 9 bits per level, so // The multi level page table uses 9 bits per level, so
//the memory usage is lower, but the performance is also // the memory usage is lower, but the performance is also
//lower, since each address translation requires multiple reads. // lower, since each address translation requires multiple reads.
if (useFlatPageTable) if (useFlatPageTable)
{ {
PtLevelBits = addressSpaceBits - PageBits; PtLevelBits = addressSpaceBits - PageBits;
@ -237,13 +237,13 @@ namespace ChocolArm64.Memory
if (nextPtr == IntPtr.Zero) if (nextPtr == IntPtr.Zero)
{ {
//Entry does not yet exist, allocate a new one. // Entry does not yet exist, allocate a new one.
IntPtr newPtr = Allocate((ulong)(PtLevelSize * IntPtr.Size)); IntPtr newPtr = Allocate((ulong)(PtLevelSize * IntPtr.Size));
//Try to swap the current pointer (should be zero), with the allocated one. // Try to swap the current pointer (should be zero), with the allocated one.
nextPtr = Interlocked.Exchange(ref *ptePtr, newPtr); nextPtr = Interlocked.Exchange(ref *ptePtr, newPtr);
//If the old pointer is not null, then another thread already has set it. // If the old pointer is not null, then another thread already has set it.
if (nextPtr != IntPtr.Zero) if (nextPtr != IntPtr.Zero)
{ {
Free(newPtr); Free(newPtr);
@ -533,7 +533,7 @@ namespace ChocolArm64.Memory
private void AbortWithAlignmentFault(long position) private void AbortWithAlignmentFault(long position)
{ {
//TODO: Abort mode and exception support on the CPU. // TODO: Abort mode and exception support on the CPU.
throw new InvalidOperationException($"Tried to compare exchange a misaligned address 0x{position:X16}."); throw new InvalidOperationException($"Tried to compare exchange a misaligned address 0x{position:X16}.");
} }
@ -726,7 +726,7 @@ namespace ChocolArm64.Memory
public void ReadBytes(long position, byte[] data, int startIndex, int size) public void ReadBytes(long position, byte[] data, int startIndex, int size)
{ {
//Note: This will be moved later. // Note: This will be moved later.
long endAddr = position + size; long endAddr = position + size;
if ((ulong)size > int.MaxValue) if ((ulong)size > int.MaxValue)
@ -924,7 +924,7 @@ namespace ChocolArm64.Memory
public void WriteBytes(long position, byte[] data, int startIndex, int size) public void WriteBytes(long position, byte[] data, int startIndex, int size)
{ {
//Note: This will be moved later. // Note: This will be moved later.
long endAddr = position + size; long endAddr = position + size;
if ((ulong)endAddr < (ulong)position) if ((ulong)endAddr < (ulong)position)
@ -954,7 +954,7 @@ namespace ChocolArm64.Memory
public void CopyBytes(long src, long dst, long size) public void CopyBytes(long src, long dst, long size)
{ {
//Note: This will be moved later. // Note: This will be moved later.
if (IsContiguous(src, size) && if (IsContiguous(src, size) &&
IsContiguous(dst, size)) IsContiguous(dst, size))
{ {

View File

@ -36,7 +36,7 @@ namespace ChocolArm64
static OpCodeTable() static OpCodeTable()
{ {
#region "OpCode Table (AArch32)" #region "OpCode Table (AArch32)"
//Integer // Integer
SetA32("<<<<0010100xxxxxxxxxxxxxxxxxxxxx", InstEmit32.Add, typeof(OpCode32AluImm)); SetA32("<<<<0010100xxxxxxxxxxxxxxxxxxxxx", InstEmit32.Add, typeof(OpCode32AluImm));
SetA32("<<<<0000100xxxxxxxxxxxxxxxx0xxxx", InstEmit32.Add, typeof(OpCode32AluRsImm)); SetA32("<<<<0000100xxxxxxxxxxxxxxxx0xxxx", InstEmit32.Add, typeof(OpCode32AluRsImm));
SetA32("<<<<1010xxxxxxxxxxxxxxxxxxxxxxxx", InstEmit32.B, typeof(OpCode32BImm)); SetA32("<<<<1010xxxxxxxxxxxxxxxxxxxxxxxx", InstEmit32.B, typeof(OpCode32BImm));
@ -66,7 +66,7 @@ namespace ChocolArm64
#endregion #endregion
#region "OpCode Table (AArch64)" #region "OpCode Table (AArch64)"
//Integer // Integer
SetA64("x0011010000xxxxx000000xxxxxxxxxx", InstEmit.Adc, typeof(OpCodeAluRs64)); SetA64("x0011010000xxxxx000000xxxxxxxxxx", InstEmit.Adc, typeof(OpCodeAluRs64));
SetA64("x0111010000xxxxx000000xxxxxxxxxx", InstEmit.Adcs, typeof(OpCodeAluRs64)); SetA64("x0111010000xxxxx000000xxxxxxxxxx", InstEmit.Adcs, typeof(OpCodeAluRs64));
SetA64("x00100010xxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Add, typeof(OpCodeAluImm64)); SetA64("x00100010xxxxxxxxxxxxxxxxxxxxxxx", InstEmit.Add, typeof(OpCodeAluImm64));
@ -217,7 +217,7 @@ namespace ChocolArm64
SetA64("10011011101xxxxx1xxxxxxxxxxxxxxx", InstEmit.Umsubl, typeof(OpCodeMul64)); SetA64("10011011101xxxxx1xxxxxxxxxxxxxxx", InstEmit.Umsubl, typeof(OpCodeMul64));
SetA64("10011011110xxxxx0xxxxxxxxxxxxxxx", InstEmit.Umulh, typeof(OpCodeMul64)); SetA64("10011011110xxxxx0xxxxxxxxxxxxxxx", InstEmit.Umulh, typeof(OpCodeMul64));
//Vector // Vector
SetA64("0101111011100000101110xxxxxxxxxx", InstEmit.Abs_S, typeof(OpCodeSimd64)); SetA64("0101111011100000101110xxxxxxxxxx", InstEmit.Abs_S, typeof(OpCodeSimd64));
SetA64("0>001110<<100000101110xxxxxxxxxx", InstEmit.Abs_V, typeof(OpCodeSimd64)); SetA64("0>001110<<100000101110xxxxxxxxxx", InstEmit.Abs_V, typeof(OpCodeSimd64));
SetA64("01011110111xxxxx100001xxxxxxxxxx", InstEmit.Add_S, typeof(OpCodeSimdReg64)); SetA64("01011110111xxxxx100001xxxxxxxxxx", InstEmit.Add_S, typeof(OpCodeSimdReg64));
@ -656,12 +656,12 @@ namespace ChocolArm64
for (int index = 0; index < encoding.Length; index++, bit--) for (int index = 0; index < encoding.Length; index++, bit--)
{ {
//Note: < and > are used on special encodings. // Note: < and > are used on special encodings.
//The < means that we should never have ALL bits with the '<' set. // The < means that we should never have ALL bits with the '<' set.
//So, when the encoding has <<, it means that 00, 01, and 10 are valid, // So, when the encoding has <<, it means that 00, 01, and 10 are valid,
//but not 11. <<< is 000, 001, ..., 110 but NOT 111, and so on... // but not 11. <<< is 000, 001, ..., 110 but NOT 111, and so on...
//For >, the invalid value is zero. So, for >> 01, 10 and 11 are valid, // For >, the invalid value is zero. So, for >> 01, 10 and 11 are valid,
//but 00 isn't. // but 00 isn't.
char chr = encoding[index]; char chr = encoding[index];
if (chr == '1') if (chr == '1')

View File

@ -126,8 +126,8 @@ namespace ChocolArm64.State
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal bool Synchronize() internal bool Synchronize()
{ {
//Firing a interrupt frequently is expensive, so we only // Firing a interrupt frequently is expensive, so we only
//do it after a given number of instructions has executed. // do it after a given number of instructions has executed.
_syncCount++; _syncCount++;
if (_syncCount >= MinCountForCheck) if (_syncCount >= MinCountForCheck)

View File

@ -56,10 +56,10 @@ namespace ChocolArm64.Translation
private OpCode64 _optOpLastCompare; private OpCode64 _optOpLastCompare;
private OpCode64 _optOpLastFlagSet; private OpCode64 _optOpLastFlagSet;
//This is the index of the temporary register, used to store temporary // This is the index of the temporary register, used to store temporary
//values needed by some functions, since IL doesn't have a swap instruction. // values needed by some functions, since IL doesn't have a swap instruction.
//You can use any value here as long it doesn't conflict with the indices // You can use any value here as long it doesn't conflict with the indices
//for the other registers. Any value >= 64 or < 0 will do. // for the other registers. Any value >= 64 or < 0 will do.
private const int ReservedLocalsCount = 64; private const int ReservedLocalsCount = 64;
private const int RorTmpIndex = ReservedLocalsCount + 0; private const int RorTmpIndex = ReservedLocalsCount + 0;
@ -69,7 +69,7 @@ namespace ChocolArm64.Translation
private const int IntGpTmp2Index = ReservedLocalsCount + 4; private const int IntGpTmp2Index = ReservedLocalsCount + 4;
private const int UserIntTempStart = ReservedLocalsCount + 5; private const int UserIntTempStart = ReservedLocalsCount + 5;
//Vectors are part of another "set" of locals. // Vectors are part of another "set" of locals.
private const int VecGpTmp1Index = ReservedLocalsCount + 0; private const int VecGpTmp1Index = ReservedLocalsCount + 0;
private const int VecGpTmp2Index = ReservedLocalsCount + 1; private const int VecGpTmp2Index = ReservedLocalsCount + 1;
private const int VecGpTmp3Index = ReservedLocalsCount + 2; private const int VecGpTmp3Index = ReservedLocalsCount + 2;
@ -139,10 +139,10 @@ namespace ChocolArm64.Translation
public void ResetBlockStateForPredicatedOp() public void ResetBlockStateForPredicatedOp()
{ {
//Check if this is a predicated instruction that modifies flags, // Check if this is a predicated instruction that modifies flags,
//in this case the value of the flags is unknown as we don't know // in this case the value of the flags is unknown as we don't know
//in advance if the instruction is going to be executed or not. // in advance if the instruction is going to be executed or not.
//So, we reset the block state to prevent an invalid optimization. // So, we reset the block state to prevent an invalid optimization.
if (CurrOp == _optOpLastFlagSet) if (CurrOp == _optOpLastFlagSet)
{ {
ResetBlockState(); ResetBlockState();
@ -167,8 +167,8 @@ namespace ChocolArm64.Translation
public bool TryOptEmitSubroutineCall() public bool TryOptEmitSubroutineCall()
{ {
//Calls should always have a next block, unless // Calls should always have a next block, unless
//we're translating a single basic block. // we're translating a single basic block.
if (_currBlock.Next == null) if (_currBlock.Next == null)
{ {
return false; return false;
@ -239,15 +239,15 @@ namespace ChocolArm64.Translation
&& cond != Condition.GtUn && cond != Condition.GtUn
&& cond != Condition.LeUn) && cond != Condition.LeUn)
{ {
//There are several limitations that needs to be taken into account for CMN comparisons: // There are several limitations that needs to be taken into account for CMN comparisons:
//- The unsigned comparisons are not valid, as they depend on the // - The unsigned comparisons are not valid, as they depend on the
//carry flag value, and they will have different values for addition and // carry flag value, and they will have different values for addition and
//subtraction. For addition, it's carry, and for subtraction, it's borrow. // subtraction. For addition, it's carry, and for subtraction, it's borrow.
//So, we need to make sure we're not doing a unsigned compare for the CMN case. // So, we need to make sure we're not doing a unsigned compare for the CMN case.
//- We can only do the optimization for the immediate variants, // - We can only do the optimization for the immediate variants,
//because when the second operand value is exactly INT_MIN, we can't // because when the second operand value is exactly INT_MIN, we can't
//negate the value as theres no positive counterpart. // negate the value as theres no positive counterpart.
//Such invalid values can't be encoded on the immediate encodings. // Such invalid values can't be encoded on the immediate encodings.
if (_optOpLastCompare is IOpCodeAluImm64 op) if (_optOpLastCompare is IOpCodeAluImm64 op)
{ {
Ldloc(CmpOptTmp1Index, RegisterType.Int, _optOpLastCompare.RegisterSize); Ldloc(CmpOptTmp1Index, RegisterType.Int, _optOpLastCompare.RegisterSize);
@ -513,11 +513,11 @@ namespace ChocolArm64.Translation
public void EmitLdflg(int index) => Ldloc(index, RegisterType.Flag); public void EmitLdflg(int index) => Ldloc(index, RegisterType.Flag);
public void EmitStflg(int index) public void EmitStflg(int index)
{ {
//Set this only if any of the NZCV flag bits were modified. // Set this only if any of the NZCV flag bits were modified.
//This is used to ensure that when emiting a direct IL branch // This is used to ensure that when emiting a direct IL branch
//instruction for compare + branch sequences, we're not expecting // instruction for compare + branch sequences, we're not expecting
//to use comparison values from an old instruction, when in fact // to use comparison values from an old instruction, when in fact
//the flags were already overwritten by another instruction further along. // the flags were already overwritten by another instruction further along.
if (index >= (int)PState.VBit) if (index >= (int)PState.VBit)
{ {
_optOpLastFlagSet = CurrOp; _optOpLastFlagSet = CurrOp;

View File

@ -153,7 +153,7 @@ namespace ChocolArm64.Translation
public static long ClearCallerSavedIntRegs(long mask, ExecutionMode mode) public static long ClearCallerSavedIntRegs(long mask, ExecutionMode mode)
{ {
//TODO: ARM32 support. // TODO: ARM32 support.
if (mode == ExecutionMode.Aarch64) if (mode == ExecutionMode.Aarch64)
{ {
mask &= ~(CallerSavedIntRegistersMask | PStateNzcvFlagsMask); mask &= ~(CallerSavedIntRegistersMask | PStateNzcvFlagsMask);
@ -164,7 +164,7 @@ namespace ChocolArm64.Translation
public static long ClearCallerSavedVecRegs(long mask, ExecutionMode mode) public static long ClearCallerSavedVecRegs(long mask, ExecutionMode mode)
{ {
//TODO: ARM32 support. // TODO: ARM32 support.
if (mode == ExecutionMode.Aarch64) if (mode == ExecutionMode.Aarch64)
{ {
mask &= ~CallerSavedVecRegistersMask; mask &= ~CallerSavedVecRegistersMask;

View File

@ -10,9 +10,9 @@ namespace ChocolArm64.Translation
class TranslatedSub class TranslatedSub
{ {
//This is the minimum amount of calls needed for the method // This is the minimum amount of calls needed for the method
//to be retranslated with higher quality code. It's only worth // to be retranslated with higher quality code. It's only worth
//doing that for hot code. // doing that for hot code.
private const int MinCallCountForOpt = 30; private const int MinCallCountForOpt = 30;
public ArmSubroutine Delegate { get; private set; } public ArmSubroutine Delegate { get; private set; }
@ -32,7 +32,7 @@ namespace ChocolArm64.Translation
public TranslatedSub(DynamicMethod method, TranslationTier tier, bool rejit) public TranslatedSub(DynamicMethod method, TranslationTier tier, bool rejit)
{ {
Method = method ?? throw new ArgumentNullException(nameof(method));; Method = method ?? throw new ArgumentNullException(nameof(method));
Tier = tier; Tier = tier;
_rejit = rejit; _rejit = rejit;
} }
@ -74,7 +74,7 @@ namespace ChocolArm64.Translation
public bool Rejit() public bool Rejit()
{ {
if (!_rejit) if (!_rejit)
{ {
return false; return false;
} }
@ -84,7 +84,7 @@ namespace ChocolArm64.Translation
return false; return false;
} }
//Only return true once, so that it is added to the queue only once. // Only return true once, so that it is added to the queue only once.
_rejit = false; _rejit = false;
return true; return true;

View File

@ -209,11 +209,11 @@ namespace ChocolArm64.Translation
context.ResetBlockStateForPredicatedOp(); context.ResetBlockStateForPredicatedOp();
//If this is the last op on the block, and there's no "next" block // If this is the last op on the block, and there's no "next" block
//after this one, then we have to return right now, with the address // after this one, then we have to return right now, with the address
//of the next instruction to be executed (in the case that the condition // of the next instruction to be executed (in the case that the condition
//is false, and the branch was not taken, as all basic blocks should end // is false, and the branch was not taken, as all basic blocks should end
//with some kind of branch). // with some kind of branch).
if (isLastOp && block.Next == null) if (isLastOp && block.Next == null)
{ {
context.EmitStoreContext(); context.EmitStoreContext();

View File

@ -8,13 +8,13 @@ namespace ChocolArm64.Translation
{ {
class TranslatorCache class TranslatorCache
{ {
//Maximum size of the cache, the unit used is completely arbitrary. // Maximum size of the cache, the unit used is completely arbitrary.
private const int MaxTotalSize = 0x800000; private const int MaxTotalSize = 0x800000;
//Minimum time required in milliseconds for a method to be eligible for deletion. // Minimum time required in milliseconds for a method to be eligible for deletion.
private const int MinTimeDelta = 2 * 60000; private const int MinTimeDelta = 2 * 60000;
//Minimum number of calls required to update the timestamp. // Minimum number of calls required to update the timestamp.
private const int MinCallCountForUpdate = 250; private const int MinCallCountForUpdate = 250;
private class CacheBucket private class CacheBucket
@ -122,10 +122,10 @@ namespace ChocolArm64.Translation
{ {
try try
{ {
//The bucket value on the dictionary may have changed between the // The bucket value on the dictionary may have changed between the
//time we get the value from the dictionary, and we acquire the // time we get the value from the dictionary, and we acquire the
//lock. So we need to ensure we are working with the latest value, // lock. So we need to ensure we are working with the latest value,
//we can do that by getting the value again, inside the lock. // we can do that by getting the value again, inside the lock.
if (_cache.TryGetValue(position, out CacheBucket latestBucket)) if (_cache.TryGetValue(position, out CacheBucket latestBucket))
{ {
latestBucket.CallCount = 0; latestBucket.CallCount = 0;

View File

@ -32,7 +32,7 @@ namespace Ryujinx.Audio
{ {
int trackId; int trackId;
if(!m_TrackIds.TryDequeue(out trackId)) if (!m_TrackIds.TryDequeue(out trackId))
{ {
trackId = ++lastTrackId; trackId = ++lastTrackId;
} }
@ -57,7 +57,7 @@ namespace Ryujinx.Audio
{ {
m_Buffers.Enqueue(bufferTag); m_Buffers.Enqueue(bufferTag);
if(m_ReleaseCallbacks.TryGetValue(trackID, out var callback)) if (m_ReleaseCallbacks.TryGetValue(trackID, out var callback))
{ {
callback?.Invoke(); callback?.Invoke();
} }

View File

@ -124,10 +124,10 @@ namespace Ryujinx.Audio
if (ReleasedCount > 0) if (ReleasedCount > 0)
{ {
//If we signal, then we also need to have released buffers available // If we signal, then we also need to have released buffers available
//to return when GetReleasedBuffers is called. // to return when GetReleasedBuffers is called.
//If playback needs to be re-started due to all buffers being processed, // If playback needs to be re-started due to all buffers being processed,
//then OpenAL zeros the counts (ReleasedCount), so we keep it on the queue. // then OpenAL zeros the counts (ReleasedCount), so we keep it on the queue.
while (ReleasedCount-- > 0 && QueuedTagsQueue.TryDequeue(out long Tag)) while (ReleasedCount-- > 0 && QueuedTagsQueue.TryDequeue(out long Tag))
{ {
AL.SourceUnqueueBuffers(SourceId, 1); AL.SourceUnqueueBuffers(SourceId, 1);
@ -209,7 +209,7 @@ namespace Ryujinx.Audio
} }
} }
//If it's not slept it will waste cycles. // If it's not slept it will waste cycles.
Thread.Sleep(10); Thread.Sleep(10);
} }
while (KeepPolling); while (KeepPolling);

View File

@ -138,7 +138,7 @@ namespace Ryujinx.Audio
public void AppendBuffer<T>(int trackId, long bufferTag, T[] buffer) public void AppendBuffer<T>(int trackId, long bufferTag, T[] buffer)
where T : struct where T : struct
{ {
if(m_TrackPool.TryGet(trackId, out SoundIoAudioTrack track)) if (m_TrackPool.TryGet(trackId, out SoundIoAudioTrack track))
{ {
track.AppendBuffer(bufferTag, buffer); track.AppendBuffer(bufferTag, buffer);
} }
@ -201,12 +201,12 @@ namespace Ryujinx.Audio
{ {
SoundIODevice defaultAudioDevice = audioContext.GetOutputDevice(audioContext.DefaultOutputDeviceIndex); SoundIODevice defaultAudioDevice = audioContext.GetOutputDevice(audioContext.DefaultOutputDeviceIndex);
if(!defaultAudioDevice.IsRaw) if (!defaultAudioDevice.IsRaw)
{ {
return defaultAudioDevice; return defaultAudioDevice;
} }
for(var i = 0; i < audioContext.BackendCount; i++) for (int i = 0; i < audioContext.BackendCount; i++)
{ {
SoundIODevice audioDevice = audioContext.GetOutputDevice(i); SoundIODevice audioDevice = audioContext.GetOutputDevice(i);
@ -242,26 +242,26 @@ namespace Ryujinx.Audio
context.Connect(); context.Connect();
context.FlushEvents(); context.FlushEvents();
if(backendDisconnected) if (backendDisconnected)
{ {
return false; return false;
} }
if(context.OutputDeviceCount == 0) if (context.OutputDeviceCount == 0)
{ {
return false; return false;
} }
device = FindNonRawDefaultAudioDevice(context); device = FindNonRawDefaultAudioDevice(context);
if(device == null || backendDisconnected) if (device == null || backendDisconnected)
{ {
return false; return false;
} }
stream = device.CreateOutStream(); stream = device.CreateOutStream();
if(stream == null || backendDisconnected) if (stream == null || backendDisconnected)
{ {
return false; return false;
} }
@ -274,12 +274,12 @@ namespace Ryujinx.Audio
} }
finally finally
{ {
if(stream != null) if (stream != null)
{ {
stream.Dispose(); stream.Dispose();
} }
if(context != null) if (context != null)
{ {
context.Dispose(); context.Dispose();
} }

View File

@ -140,7 +140,7 @@ namespace Ryujinx.Audio.SoundIo
} }
/// <summary> /// <summary>
/// Attempers to get a <see cref="SoundIoAudioTrack"/> from the pool /// Attempts to get a <see cref="SoundIoAudioTrack"/> from the pool
/// </summary> /// </summary>
/// <param name="track">The track retrieved from the pool</param> /// <param name="track">The track retrieved from the pool</param>
/// <returns>True if retrieve was successful</returns> /// <returns>True if retrieve was successful</returns>

View File

@ -13,19 +13,19 @@ namespace Ryujinx.Common.Logging
public LogEventArgs(LogLevel level, TimeSpan time, int threadId, string message) public LogEventArgs(LogLevel level, TimeSpan time, int threadId, string message)
{ {
this.Level = level; Level = level;
this.Time = time; Time = time;
this.ThreadId = threadId; ThreadId = threadId;
this.Message = message; Message = message;
} }
public LogEventArgs(LogLevel level, TimeSpan time, int threadId, string message, object data) public LogEventArgs(LogLevel level, TimeSpan time, int threadId, string message, object data)
{ {
this.Level = level; Level = level;
this.Time = time; Time = time;
this.ThreadId = threadId; ThreadId = threadId;
this.Message = message; Message = message;
this.Data = data; Data = data;
} }
} }
} }

View File

@ -19,7 +19,7 @@ namespace Ryujinx.Common
public T Allocate() public T Allocate()
{ {
var instance = _firstItem; T instance = _firstItem;
if (instance == null || instance != Interlocked.CompareExchange(ref _firstItem, null, instance)) if (instance == null || instance != Interlocked.CompareExchange(ref _firstItem, null, instance))
{ {
@ -31,11 +31,11 @@ namespace Ryujinx.Common
private T AllocateInternal() private T AllocateInternal()
{ {
var items = _items; T[] items = _items;
for (int i = 0; i < items.Length; i++) for (int i = 0; i < items.Length; i++)
{ {
var instance = items[i]; T instance = items[i];
if (instance != null && instance == Interlocked.CompareExchange(ref items[i], null, instance)) if (instance != null && instance == Interlocked.CompareExchange(ref items[i], null, instance))
{ {
@ -60,7 +60,7 @@ namespace Ryujinx.Common
private void ReleaseInternal(T obj) private void ReleaseInternal(T obj)
{ {
var items = _items; T[] items = _items;
for (int i = 0; i < items.Length; i++) for (int i = 0; i < items.Length; i++)
{ {

View File

@ -104,12 +104,12 @@ namespace Ryujinx.Graphics
} }
else else
{ {
int sumissionMode = (word >> 29) & 7; int submissionMode = (word >> 29) & 7;
switch (sumissionMode) switch (submissionMode)
{ {
case 1: case 1:
//Incrementing. // Incrementing.
SetNonImmediateState(word); SetNonImmediateState(word);
_state.NonIncrementing = false; _state.NonIncrementing = false;
@ -118,7 +118,7 @@ namespace Ryujinx.Graphics
break; break;
case 3: case 3:
//Non-incrementing. // Non-incrementing.
SetNonImmediateState(word); SetNonImmediateState(word);
_state.NonIncrementing = true; _state.NonIncrementing = true;
@ -127,7 +127,7 @@ namespace Ryujinx.Graphics
break; break;
case 4: case 4:
//Immediate. // Immediate.
_state.Method = (word >> 0) & 0x1fff; _state.Method = (word >> 0) & 0x1fff;
_state.SubChannel = (word >> 13) & 7; _state.SubChannel = (word >> 13) & 7;
_state.NonIncrementing = true; _state.NonIncrementing = true;
@ -138,7 +138,7 @@ namespace Ryujinx.Graphics
break; break;
case 5: case 5:
//Increment-once. // Increment-once.
SetNonImmediateState(word); SetNonImmediateState(word);
_state.NonIncrementing = false; _state.NonIncrementing = false;

View File

@ -1,4 +1,5 @@
using System; // ReSharper disable InconsistentNaming
using System;
namespace Ryujinx.Graphics.Gal namespace Ryujinx.Graphics.Gal
{ {

View File

@ -2,7 +2,7 @@ namespace Ryujinx.Graphics.Gal
{ {
public struct GalVertexBinding public struct GalVertexBinding
{ {
//VboKey shouldn't be here, but ARB_vertex_attrib_binding is core since 4.3 // VboKey shouldn't be here, but ARB_vertex_attrib_binding is core since 4.3
public bool Enabled; public bool Enabled;
public int Stride; public int Stride;

View File

@ -275,7 +275,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
} }
else else
{ {
//Fallback to non-mirrored clamps // Fallback to non-mirrored clamps
switch (wrap) switch (wrap)
{ {
case GalTextureWrap.MirrorClampToEdge: return TextureWrapMode.ClampToEdge; case GalTextureWrap.MirrorClampToEdge: return TextureWrapMode.ClampToEdge;
@ -291,7 +291,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GalTextureFilter minFilter, GalTextureFilter minFilter,
GalTextureMipFilter mipFilter) GalTextureMipFilter mipFilter)
{ {
//TODO: Mip (needs mipmap support first). // TODO: Mip (needs mipmap support first).
switch (minFilter) switch (minFilter)
{ {
case GalTextureFilter.Nearest: return TextureMinFilter.Nearest; case GalTextureFilter.Nearest: return TextureMinFilter.Nearest;

View File

@ -96,7 +96,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
_rasterizer = rasterizer; _rasterizer = rasterizer;
_shader = shader; _shader = shader;
//These values match OpenGL's defaults // These values match OpenGL's defaults
_old = new GalPipelineState _old = new GalPipelineState
{ {
FrontFace = GalFrontFace.Ccw, FrontFace = GalFrontFace.Ccw,
@ -564,14 +564,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ {
_vaoHandle = GL.GenVertexArray(); _vaoHandle = GL.GenVertexArray();
//Vertex arrays shouldn't be used anywhere else in OpenGL's backend // Vertex arrays shouldn't be used anywhere else in OpenGL's backend
//if you want to use it, move this line out of the if // if you want to use it, move this line out of the if
GL.BindVertexArray(_vaoHandle); GL.BindVertexArray(_vaoHandle);
} }
foreach (GalVertexAttrib attrib in binding.Attribs) foreach (GalVertexAttrib attrib in binding.Attribs)
{ {
//Skip uninitialized attributes. // Skip uninitialized attributes.
if (attrib.Size == 0) if (attrib.Size == 0)
{ {
continue; continue;

View File

@ -77,11 +77,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private int _cropRight; private int _cropRight;
private int _cropBottom; private int _cropBottom;
//This framebuffer is used to attach guest rendertargets, // This framebuffer is used to attach guest rendertargets,
//think of it as a dummy OpenGL VAO // think of it as a dummy OpenGL VAO
private int _dummyFrameBuffer; private int _dummyFrameBuffer;
//These framebuffers are used to blit images // These framebuffers are used to blit images
private int _srcFb; private int _srcFb;
private int _dstFb; private int _dstFb;
@ -109,8 +109,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private void TextureDeletionHandler(object sender, int handle) private void TextureDeletionHandler(object sender, int handle)
{ {
//Texture was deleted, the handle is no longer valid, so // Texture was deleted, the handle is no longer valid, so
//reset all uses of this handle on a render target. // reset all uses of this handle on a render target.
for (int attachment = 0; attachment < RenderTargetsCount; attachment++) for (int attachment = 0; attachment < RenderTargetsCount; attachment++)
{ {
if (_colorHandles[attachment] == handle) if (_colorHandles[attachment] == handle)
@ -484,7 +484,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyPbo); GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyPbo);
//The buffer should be large enough to hold the largest texture. // The buffer should be large enough to hold the largest texture.
int bufferSize = Math.Max(ImageUtils.GetSize(oldImage), int bufferSize = Math.Max(ImageUtils.GetSize(oldImage),
ImageUtils.GetSize(newImage)); ImageUtils.GetSize(newImage));

View File

@ -115,7 +115,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
data[1] = flipY; data[1] = flipY;
data[2] = BitConverter.Int32BitsToSingle(instance); data[2] = BitConverter.Int32BitsToSingle(instance);
//Invalidate buffer // Invalidate buffer
GL.BufferData(BufferTarget.UniformBuffer, ExtraDataSize * sizeof(float), IntPtr.Zero, BufferUsageHint.StreamDraw); GL.BufferData(BufferTarget.UniformBuffer, ExtraDataSize * sizeof(float), IntPtr.Zero, BufferUsageHint.StreamDraw);
GL.BufferSubData(BufferTarget.UniformBuffer, IntPtr.Zero, ExtraDataSize * sizeof(float), (IntPtr)data); GL.BufferSubData(BufferTarget.UniformBuffer, IntPtr.Zero, ExtraDataSize * sizeof(float), (IntPtr)data);
@ -228,9 +228,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
if (blockIndex < 0) if (blockIndex < 0)
{ {
//This may be fine, the compiler may optimize away unused uniform buffers, // This may be fine, the compiler may optimize away unused uniform buffers,
//and in this case the above call would return -1 as the buffer has been // and in this case the above call would return -1 as the buffer has been
//optimized away. // optimized away.
continue; continue;
} }

View File

@ -207,7 +207,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
} }
else else
{ {
//TODO: Use KHR_texture_compression_astc_hdr when available // TODO: Use KHR_texture_compression_astc_hdr when available
if (IsAstc(image.Format)) if (IsAstc(image.Format))
{ {
int textureBlockWidth = ImageUtils.GetBlockWidth(image.Format); int textureBlockWidth = ImageUtils.GetBlockWidth(image.Format);

View File

@ -38,7 +38,7 @@ namespace Ryujinx.Graphics.Gal
ulong instruction = 0; ulong instruction = 0;
//Dump until a NOP instruction is found // Dump until a NOP instruction is found
while ((instruction >> 48 & 0xfff8) != 0x50b0) while ((instruction >> 48 & 0xfff8) != 0x50b0)
{ {
uint word0 = (uint)memory.ReadInt32(position + 0x50 + offset + 0); uint word0 = (uint)memory.ReadInt32(position + 0x50 + offset + 0);
@ -46,8 +46,8 @@ namespace Ryujinx.Graphics.Gal
instruction = word0 | (ulong)word1 << 32; instruction = word0 | (ulong)word1 << 32;
//Zero instructions (other kind of NOP) stop immediatly, // Zero instructions (other kind of NOP) stop immediately,
//this is to avoid two rows of zeroes // this is to avoid two rows of zeroes
if (instruction == 0) if (instruction == 0)
{ {
break; break;
@ -59,7 +59,7 @@ namespace Ryujinx.Graphics.Gal
offset += 8; offset += 8;
} }
//Align to meet nvdisasm requeriments // Align to meet nvdisasm requirements
while (offset % 0x20 != 0) while (offset % 0x20 != 0)
{ {
fullWriter.Write(0); fullWriter.Write(0);

View File

@ -109,7 +109,7 @@ namespace Ryujinx.Graphics
{ {
if (oldType == ImageType.ColorBuffer || oldType == ImageType.ZetaBuffer) if (oldType == ImageType.ColorBuffer || oldType == ImageType.ZetaBuffer)
{ {
//Avoid data destruction // Avoid data destruction
MemoryRegionModified(vmm, position, size, NvGpuBufferType.Texture); MemoryRegionModified(vmm, position, size, NvGpuBufferType.Texture);
skipCheck = true; skipCheck = true;

View File

@ -82,8 +82,8 @@ namespace Ryujinx.Graphics.Graphics3d
while (Step(vmm, mme)); while (Step(vmm, mme));
//Due to the delay slot, we still need to execute // Due to the delay slot, we still need to execute
//one more instruction before we actually exit. // one more instruction before we actually exit.
Step(vmm, mme); Step(vmm, mme);
} }
@ -108,14 +108,14 @@ namespace Ryujinx.Graphics.Graphics3d
if ((_opCode & 7) < 7) if ((_opCode & 7) < 7)
{ {
//Operation produces a value. // Operation produces a value.
AssignmentOperation asgOp = (AssignmentOperation)((_opCode >> 4) & 7); AssignmentOperation asgOp = (AssignmentOperation)((_opCode >> 4) & 7);
int result = GetAluResult(); int result = GetAluResult();
switch (asgOp) switch (asgOp)
{ {
//Fetch parameter and ignore result. // Fetch parameter and ignore result.
case AssignmentOperation.IgnoreAndFetch: case AssignmentOperation.IgnoreAndFetch:
{ {
SetDstGpr(FetchParam()); SetDstGpr(FetchParam());
@ -123,7 +123,7 @@ namespace Ryujinx.Graphics.Graphics3d
break; break;
} }
//Move result. // Move result.
case AssignmentOperation.Move: case AssignmentOperation.Move:
{ {
SetDstGpr(result); SetDstGpr(result);
@ -131,7 +131,7 @@ namespace Ryujinx.Graphics.Graphics3d
break; break;
} }
//Move result and use as Method Address. // Move result and use as Method Address.
case AssignmentOperation.MoveAndSetMaddr: case AssignmentOperation.MoveAndSetMaddr:
{ {
SetDstGpr(result); SetDstGpr(result);
@ -141,7 +141,7 @@ namespace Ryujinx.Graphics.Graphics3d
break; break;
} }
//Fetch parameter and send result. // Fetch parameter and send result.
case AssignmentOperation.FetchAndSend: case AssignmentOperation.FetchAndSend:
{ {
SetDstGpr(FetchParam()); SetDstGpr(FetchParam());
@ -151,7 +151,7 @@ namespace Ryujinx.Graphics.Graphics3d
break; break;
} }
//Move and send result. // Move and send result.
case AssignmentOperation.MoveAndSend: case AssignmentOperation.MoveAndSend:
{ {
SetDstGpr(result); SetDstGpr(result);
@ -161,7 +161,7 @@ namespace Ryujinx.Graphics.Graphics3d
break; break;
} }
//Fetch parameter and use result as Method Address. // Fetch parameter and use result as Method Address.
case AssignmentOperation.FetchAndSetMaddr: case AssignmentOperation.FetchAndSetMaddr:
{ {
SetDstGpr(FetchParam()); SetDstGpr(FetchParam());
@ -171,7 +171,7 @@ namespace Ryujinx.Graphics.Graphics3d
break; break;
} }
//Move result and use as Method Address, then fetch and send paramter. // Move result and use as Method Address, then fetch and send parameter.
case AssignmentOperation.MoveAndSetMaddrThenFetchAndSend: case AssignmentOperation.MoveAndSetMaddrThenFetchAndSend:
{ {
SetDstGpr(result); SetDstGpr(result);
@ -183,7 +183,7 @@ namespace Ryujinx.Graphics.Graphics3d
break; break;
} }
//Move result and use as Method Address, then send bits 17:12 of result. // Move result and use as Method Address, then send bits 17:12 of result.
case AssignmentOperation.MoveAndSetMaddrThenSendHigh: case AssignmentOperation.MoveAndSetMaddrThenSendHigh:
{ {
SetDstGpr(result); SetDstGpr(result);
@ -198,7 +198,7 @@ namespace Ryujinx.Graphics.Graphics3d
} }
else else
{ {
//Branch. // Branch.
bool onNotZero = ((_opCode >> 4) & 1) != 0; bool onNotZero = ((_opCode >> 4) & 1) != 0;
bool taken = onNotZero bool taken = onNotZero
@ -355,7 +355,7 @@ namespace Ryujinx.Graphics.Graphics3d
private int GetImm() private int GetImm()
{ {
//Note: The immediate is signed, the sign-extension is intended here. // Note: The immediate is signed, the sign-extension is intended here.
return _opCode >> 14; return _opCode >> 14;
} }

View File

@ -204,10 +204,10 @@ namespace Ryujinx.Graphics.Graphics3d
dstBlitX + dstBlitW, dstBlitX + dstBlitW,
dstBlitY + dstBlitH); dstBlitY + dstBlitH);
//Do a guest side copy aswell. This is necessary when // Do a guest side copy as well. This is necessary when
//the texture is modified by the guest, however it doesn't // the texture is modified by the guest, however it doesn't
//work when resources that the gpu can write to are copied, // work when resources that the gpu can write to are copied,
//like framebuffers. // like framebuffers.
// FIXME: SUPPORT MULTILAYER CORRECTLY HERE (this will cause weird stuffs on the first layer) // FIXME: SUPPORT MULTILAYER CORRECTLY HERE (this will cause weird stuffs on the first layer)
ImageUtils.CopyTexture( ImageUtils.CopyTexture(

View File

@ -67,8 +67,8 @@ namespace Ryujinx.Graphics.Graphics3d
_constBuffers[index] = new ConstBuffer[18]; _constBuffers[index] = new ConstBuffer[18];
} }
//Ensure that all components are enabled by default. // Ensure that all components are enabled by default.
//FIXME: Is this correct? // FIXME: Is this correct?
WriteRegister(NvGpuEngine3dReg.ColorMaskN, 0x1111); WriteRegister(NvGpuEngine3dReg.ColorMaskN, 0x1111);
WriteRegister(NvGpuEngine3dReg.FrameBufferSrgb, 1); WriteRegister(NvGpuEngine3dReg.FrameBufferSrgb, 1);
@ -333,12 +333,12 @@ namespace Ryujinx.Graphics.Graphics3d
if (vpAEnable) if (vpAEnable)
{ {
//Note: The maxwell supports 2 vertex programs, usually // Note: The maxwell supports 2 vertex programs, usually
//only VP B is used, but in some cases VP A is also used. // only VP B is used, but in some cases VP A is also used.
//In this case, it seems to function as an extra vertex // In this case, it seems to function as an extra vertex
//shader stage. // shader stage.
//The graphics abstraction layer has a special overload for this // The graphics abstraction layer has a special overload for this
//case, which should merge the two shaders into one vertex shader. // case, which should merge the two shaders into one vertex shader.
int vpAOffset = ReadRegister(NvGpuEngine3dReg.ShaderNOffset); int vpAOffset = ReadRegister(NvGpuEngine3dReg.ShaderNOffset);
int vpBOffset = ReadRegister(NvGpuEngine3dReg.ShaderNOffset + 0x10); int vpBOffset = ReadRegister(NvGpuEngine3dReg.ShaderNOffset + 0x10);
@ -360,7 +360,7 @@ namespace Ryujinx.Graphics.Graphics3d
int control = ReadRegister(NvGpuEngine3dReg.ShaderNControl + index * 0x10); int control = ReadRegister(NvGpuEngine3dReg.ShaderNControl + index * 0x10);
int offset = ReadRegister(NvGpuEngine3dReg.ShaderNOffset + index * 0x10); int offset = ReadRegister(NvGpuEngine3dReg.ShaderNOffset + index * 0x10);
//Note: Vertex Program (B) is always enabled. // Note: Vertex Program (B) is always enabled.
bool enable = (control & 1) != 0 || index == 1; bool enable = (control & 1) != 0 || index == 1;
if (!enable) if (!enable)
@ -405,7 +405,7 @@ namespace Ryujinx.Graphics.Graphics3d
GalFrontFace frontFace = (GalFrontFace)ReadRegister(NvGpuEngine3dReg.FrontFace); GalFrontFace frontFace = (GalFrontFace)ReadRegister(NvGpuEngine3dReg.FrontFace);
//Flipping breaks facing. Flipping front facing too fixes it // Flipping breaks facing. Flipping front facing too fixes it
if (signX != signY) if (signX != signY)
{ {
switch (frontFace) switch (frontFace)
@ -574,8 +574,8 @@ namespace Ryujinx.Graphics.Graphics3d
} }
else else
{ {
//It seems that even when independent blend is disabled, the first IBlend enable // It seems that even when independent blend is disabled, the first IBlend enable
//register is still set to indicate whenever blend is enabled or not (?). // register is still set to indicate whenever blend is enabled or not (?).
state.Blends[index].Enabled = ReadRegisterBool(NvGpuEngine3dReg.IBlendNEnable); state.Blends[index].Enabled = ReadRegisterBool(NvGpuEngine3dReg.IBlendNEnable);
if (state.Blends[index].Enabled) if (state.Blends[index].Enabled)
@ -632,8 +632,8 @@ namespace Ryujinx.Graphics.Graphics3d
private void SetRenderTargets() private void SetRenderTargets()
{ {
//Commercial games do not seem to // Commercial games do not seem to
//bool SeparateFragData = ReadRegisterBool(NvGpuEngine3dReg.RTSeparateFragData); // bool SeparateFragData = ReadRegisterBool(NvGpuEngine3dReg.RTSeparateFragData);
uint control = (uint)(ReadRegister(NvGpuEngine3dReg.RtControl)); uint control = (uint)(ReadRegister(NvGpuEngine3dReg.RtControl));
@ -711,8 +711,8 @@ namespace Ryujinx.Graphics.Graphics3d
{ {
if (textureHandle == 0) if (textureHandle == 0)
{ {
//FIXME: Some games like puyo puyo will use handles with the value 0. // FIXME: Some games like puyo puyo will use handles with the value 0.
//This is a bug, most likely caused by sync issues. // This is a bug, most likely caused by sync issues.
return (0, default(GalImage), default(GalTextureSampler)); return (0, default(GalImage), default(GalTextureSampler));
} }
@ -751,7 +751,7 @@ namespace Ryujinx.Graphics.Graphics3d
{ {
Profile.End(Profiles.GPU.Engine3d.UploadTexture); Profile.End(Profiles.GPU.Engine3d.UploadTexture);
//FIXME: Shouldn't ignore invalid addresses. // FIXME: Shouldn't ignore invalid addresses.
return (0, default(GalImage), default(GalTextureSampler)); return (0, default(GalImage), default(GalTextureSampler));
} }
@ -910,8 +910,8 @@ namespace Ryujinx.Graphics.Graphics3d
// Check vertex array is enabled to avoid out of bounds exception when reading bytes // Check vertex array is enabled to avoid out of bounds exception when reading bytes
bool enable = (ReadRegister(NvGpuEngine3dReg.VertexArrayNControl + arrayIndex * 4) & 0x1000) != 0; bool enable = (ReadRegister(NvGpuEngine3dReg.VertexArrayNControl + arrayIndex * 4) & 0x1000) != 0;
//Note: 16 is the maximum size of an attribute, // Note: 16 is the maximum size of an attribute,
//having a component size of 32-bits with 4 elements (a vec4). // having a component size of 32-bits with 4 elements (a vec4).
if (enable) if (enable)
{ {
byte[] data = vmm.ReadBytes(vbPosition + offset, 16); byte[] data = vmm.ReadBytes(vbPosition + offset, 16);
@ -954,7 +954,7 @@ namespace Ryujinx.Graphics.Graphics3d
if (vbPosition > vbEndPos) if (vbPosition > vbEndPos)
{ {
//Instance is invalid, ignore the draw call // Instance is invalid, ignore the draw call
continue; continue;
} }
@ -1057,14 +1057,14 @@ namespace Ryujinx.Graphics.Graphics3d
long iboKey = vmm.GetPhysicalAddress(indexPosition); long iboKey = vmm.GetPhysicalAddress(indexPosition);
//Quad primitive types were deprecated on OpenGL 3.x, // Quad primitive types were deprecated on OpenGL 3.x,
//they are converted to a triangles index buffer on IB creation, // they are converted to a triangles index buffer on IB creation,
//so we should use the triangles type here too. // so we should use the triangles type here too.
if (primType == GalPrimitiveType.Quads || primType == GalPrimitiveType.QuadStrip) if (primType == GalPrimitiveType.Quads || primType == GalPrimitiveType.QuadStrip)
{ {
//Note: We assume that index first points to the first // Note: We assume that index first points to the first
//vertex of a quad, if it points to the middle of a // vertex of a quad, if it points to the middle of a
//quad (First % 4 != 0 for Quads) then it will not work properly. // quad (First % 4 != 0 for Quads) then it will not work properly.
if (primType == GalPrimitiveType.Quads) if (primType == GalPrimitiveType.Quads)
{ {
indexFirst = QuadHelper.ConvertSizeQuadsToTris(indexFirst); indexFirst = QuadHelper.ConvertSizeQuadsToTris(indexFirst);
@ -1084,14 +1084,14 @@ namespace Ryujinx.Graphics.Graphics3d
int vertexFirst = ReadRegister(NvGpuEngine3dReg.VertexArrayFirst); int vertexFirst = ReadRegister(NvGpuEngine3dReg.VertexArrayFirst);
int vertexCount = ReadRegister(NvGpuEngine3dReg.VertexArrayCount); int vertexCount = ReadRegister(NvGpuEngine3dReg.VertexArrayCount);
//Quad primitive types were deprecated on OpenGL 3.x, // Quad primitive types were deprecated on OpenGL 3.x,
//they are converted to a triangles index buffer on IB creation, // they are converted to a triangles index buffer on IB creation,
//so we should use the triangles type here too. // so we should use the triangles type here too.
if (primType == GalPrimitiveType.Quads || primType == GalPrimitiveType.QuadStrip) if (primType == GalPrimitiveType.Quads || primType == GalPrimitiveType.QuadStrip)
{ {
//Note: We assume that index first points to the first // Note: We assume that index first points to the first
//vertex of a quad, if it points to the middle of a // vertex of a quad, if it points to the middle of a
//quad (First % 4 != 0 for Quads) then it will not work properly. // quad (First % 4 != 0 for Quads) then it will not work properly.
if (primType == GalPrimitiveType.Quads) if (primType == GalPrimitiveType.Quads)
{ {
vertexFirst = QuadHelper.ConvertSizeQuadsToTris(vertexFirst); vertexFirst = QuadHelper.ConvertSizeQuadsToTris(vertexFirst);
@ -1111,7 +1111,7 @@ namespace Ryujinx.Graphics.Graphics3d
// Reset pipeline for host OpenGL calls // Reset pipeline for host OpenGL calls
_gpu.Renderer.Pipeline.Unbind(state); _gpu.Renderer.Pipeline.Unbind(state);
//Is the GPU really clearing those registers after draw? // Is the GPU really clearing those registers after draw?
WriteRegister(NvGpuEngine3dReg.IndexBatchFirst, 0); WriteRegister(NvGpuEngine3dReg.IndexBatchFirst, 0);
WriteRegister(NvGpuEngine3dReg.IndexBatchCount, 0); WriteRegister(NvGpuEngine3dReg.IndexBatchCount, 0);
} }
@ -1140,7 +1140,7 @@ namespace Ryujinx.Graphics.Graphics3d
case QueryMode.WriteCounterAndTimestamp: case QueryMode.WriteCounterAndTimestamp:
{ {
//TODO: Implement counters. // TODO: Implement counters.
long counter = 1; long counter = 1;
long timestamp = PerformanceCounter.ElapsedMilliseconds; long timestamp = PerformanceCounter.ElapsedMilliseconds;

View File

@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.Graphics3d
{ {
Profile.Begin(Profiles.GPU.EngineM2mf.Execute); Profile.Begin(Profiles.GPU.EngineM2mf.Execute);
//TODO: Some registers and copy modes are still not implemented. // TODO: Some registers and copy modes are still not implemented.
int control = methCall.Argument; int control = methCall.Argument;
bool srcLinear = ((control >> 7) & 1) != 0; bool srcLinear = ((control >> 7) & 1) != 0;

View File

@ -73,7 +73,7 @@ namespace Ryujinx.Graphics.Graphics3d
{ {
Profile.Begin(Profiles.GPU.EngineP2mf.Execute); Profile.Begin(Profiles.GPU.EngineP2mf.Execute);
//TODO: Some registers and copy modes are still not implemented. // TODO: Some registers and copy modes are still not implemented.
int control = methCall.Argument; int control = methCall.Argument;
long dstAddress = MakeInt64From2xInt32(NvGpuEngineP2mfReg.DstAddress); long dstAddress = MakeInt64From2xInt32(NvGpuEngineP2mfReg.DstAddress);

View File

@ -7,8 +7,8 @@ namespace Ryujinx.Graphics.Graphics3d
private const int MacrosCount = 0x80; private const int MacrosCount = 0x80;
private const int MacroIndexMask = MacrosCount - 1; private const int MacroIndexMask = MacrosCount - 1;
//Note: The size of the macro memory is unknown, we just make // Note: The size of the macro memory is unknown, we just make
//a guess here and use 256kb as the size. Increase if needed. // a guess here and use 256kb as the size. Increase if needed.
private const int MmeWords = 256 * 256; private const int MmeWords = 256 * 256;
private NvGpu _gpu; private NvGpu _gpu;

View File

@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.Texture
public AstcDecoderException(string exMsg) : base(exMsg) { } public AstcDecoderException(string exMsg) : base(exMsg) { }
} }
//https://github.com/GammaUNC/FasTC/blob/master/ASTCEncoder/src/Decompressor.cpp // https://github.com/GammaUNC/FasTC/blob/master/ASTCEncoder/src/Decompressor.cpp
public static class AstcDecoder public static class AstcDecoder
{ {
struct TexelWeightParams struct TexelWeightParams
@ -1356,7 +1356,7 @@ namespace Ryujinx.Graphics.Texture
} }
default: default:
//Don't know this layout... // Don't know this layout...
texelParams.Error = true; texelParams.Error = true;
break; break;
} }

View File

@ -65,7 +65,7 @@ namespace Ryujinx.Graphics.Texture
public void ChangeBitDepth(byte[] depth) public void ChangeBitDepth(byte[] depth)
{ {
for(int i = 0; i< 4; i++) for (int i = 0; i< 4; i++)
{ {
int value = ChangeBitDepth(GetComponent(i), _bitDepth[i], depth[i]); int value = ChangeBitDepth(GetComponent(i), _bitDepth[i], depth[i]);

View File

@ -67,7 +67,7 @@ namespace Ryujinx.Graphics.Texture
{ GalTextureFormat.D32Fx24S8, GalImageFormat.D32S8 | Float }, { GalTextureFormat.D32Fx24S8, GalImageFormat.D32S8 | Float },
{ GalTextureFormat.D16, GalImageFormat.D16 | Unorm }, { GalTextureFormat.D16, GalImageFormat.D16 | Unorm },
//Compressed formats // Compressed formats
{ GalTextureFormat.BptcSfloat, GalImageFormat.BptcSfloat | Float }, { GalTextureFormat.BptcSfloat, GalImageFormat.BptcSfloat | Float },
{ GalTextureFormat.BptcUfloat, GalImageFormat.BptcUfloat | Float }, { GalTextureFormat.BptcUfloat, GalImageFormat.BptcUfloat | Float },
{ GalTextureFormat.BptcUnorm, GalImageFormat.BptcUnorm | Unorm | Srgb }, { GalTextureFormat.BptcUnorm, GalImageFormat.BptcUnorm | Unorm | Srgb },
@ -248,7 +248,7 @@ namespace Ryujinx.Graphics.Texture
int bytesPerPixel = desc.BytesPerPixel; int bytesPerPixel = desc.BytesPerPixel;
//Note: Each row of the texture needs to be aligned to 4 bytes. // Note: Each row of the texture needs to be aligned to 4 bytes.
int pitch = (width * bytesPerPixel + 3) & ~3; int pitch = (width * bytesPerPixel + 3) & ~3;

View File

@ -146,8 +146,8 @@ namespace Ryujinx.Graphics.Memory
private long GetFreePosition(long size, long align = 1, long start = 1L << 32) private long GetFreePosition(long size, long align = 1, long start = 1L << 32)
{ {
//Note: Address 0 is not considered valid by the driver, // Note: Address 0 is not considered valid by the driver,
//when 0 is returned it's considered a mapping error. // when 0 is returned it's considered a mapping error.
long position = start; long position = start;
long freeSize = 0; long freeSize = 0;

View File

@ -33,13 +33,13 @@ namespace Ryujinx.Graphics
Buffer.BlockCopy(data, src, output, dst, copyCount * entrySize); Buffer.BlockCopy(data, src, output, dst, copyCount * entrySize);
} }
//0 1 2 -> 0 1 2. // 0 1 2 -> 0 1 2.
AssignIndex(0, 0, 3); AssignIndex(0, 0, 3);
//2 3 -> 3 4. // 2 3 -> 3 4.
AssignIndex(2, 3, 2); AssignIndex(2, 3, 2);
//0 -> 5. // 0 -> 5.
AssignIndex(0, 5); AssignIndex(0, 5);
} }
@ -65,13 +65,13 @@ namespace Ryujinx.Graphics
Buffer.BlockCopy(data, src, output, dst, copyCount * entrySize); Buffer.BlockCopy(data, src, output, dst, copyCount * entrySize);
} }
//-2 -1 0 -> 0 1 2. // -2 -1 0 -> 0 1 2.
AssignIndex(-2, 0, 3); AssignIndex(-2, 0, 3);
//0 1 -> 3 4. // 0 1 -> 3 4.
AssignIndex(0, 3, 2); AssignIndex(0, 3, 2);
//-2 -> 5. // -2 -> 5.
AssignIndex(-2, 5); AssignIndex(-2, 5);
} }

View File

@ -18,7 +18,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
private int _level; private int _level;
private string _identation; private string _indentation;
public CodeGenContext(ShaderConfig config) public CodeGenContext(ShaderConfig config)
{ {
@ -39,7 +39,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
public void AppendLine(string str) public void AppendLine(string str)
{ {
_sb.AppendLine(_identation + str); _sb.AppendLine(_indentation + str);
} }
public string GetCode() public string GetCode()
@ -53,7 +53,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
_level++; _level++;
UpdateIdentation(); UpdateIndentation();
} }
public void LeaveScope(string suffix = "") public void LeaveScope(string suffix = "")
@ -65,26 +65,26 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
_level--; _level--;
UpdateIdentation(); UpdateIndentation();
AppendLine("}" + suffix); AppendLine("}" + suffix);
} }
private void UpdateIdentation() private void UpdateIndentation()
{ {
_identation = GetIdentation(_level); _indentation = GetIndentation(_level);
} }
private static string GetIdentation(int level) private static string GetIndentation(int level)
{ {
string identation = string.Empty; string indentation = string.Empty;
for (int index = 0; index < level; index++) for (int index = 0; index < level; index++)
{ {
identation += Tab; indentation += Tab;
} }
return identation; return indentation;
} }
} }
} }

View File

@ -112,13 +112,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
public static bool NeedsParenthesis(IAstNode node, Instruction pInst, InstInfo pInfo, bool isLhs) public static bool NeedsParenthesis(IAstNode node, Instruction pInst, InstInfo pInfo, bool isLhs)
{ {
//If the node isn't a operation, then it can only be a operand, // If the node isn't a operation, then it can only be a operand,
//and those never needs to be surrounded in parenthesis. // and those never needs to be surrounded in parenthesis.
if (!(node is AstOperation operation)) if (!(node is AstOperation operation))
{ {
//This is sort of a special case, if this is a negative constant, // This is sort of a special case, if this is a negative constant,
//and it is consumed by a unary operation, we need to put on the parenthesis, // and it is consumed by a unary operation, we need to put on the parenthesis,
//as in GLSL a sequence like --2 or ~-1 is not valid. // as in GLSL a sequence like --2 or ~-1 is not valid.
if (IsNegativeConst(node) && pInfo.Type == InstType.OpUnary) if (IsNegativeConst(node) && pInfo.Type == InstType.OpUnary)
{ {
return true; return true;

View File

@ -69,8 +69,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
arrayIndexElem = pCount++; arrayIndexElem = pCount++;
} }
//The sampler 1D shadow overload expects a // The sampler 1D shadow overload expects a
//dummy value on the middle of the vector, who knows why... // dummy value on the middle of the vector, who knows why...
bool hasDummy1DShadowElem = texOp.Type == (TextureType.Texture1D | TextureType.Shadow); bool hasDummy1DShadowElem = texOp.Type == (TextureType.Texture1D | TextureType.Shadow);
if (hasDummy1DShadowElem) if (hasDummy1DShadowElem)
@ -83,8 +83,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
pCount++; pCount++;
} }
//On textureGather*, the comparison value is // On textureGather*, the comparison value is
//always specified as an extra argument. // always specified as an extra argument.
bool hasExtraCompareArg = isShadow && isGather; bool hasExtraCompareArg = isShadow && isGather;
if (pCount == 5) if (pCount == 5)
@ -199,8 +199,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
Append(Src(VariableType.F32)); Append(Src(VariableType.F32));
} }
//textureGather* optional extra component index, // textureGather* optional extra component index,
//not needed for shadow samplers. // not needed for shadow samplers.
if (isGather && !isShadow) if (isGather && !isShadow)
{ {
Append(Src(VariableType.S32)); Append(Src(VariableType.S32));

View File

@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
OpUnary = Op | 1, OpUnary = Op | 1,
OpBinary = Op | 2, OpBinary = Op | 2,
OpTernary = Op | 3, OpTernary = Op | 3,
OpBinaryCom = OpBinary | Comutative, OpBinaryCom = OpBinary | Commutative,
CallNullary = Call | 0, CallNullary = Call | 0,
CallUnary = Call | 1, CallUnary = Call | 1,
@ -17,10 +17,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
CallTernary = Call | 3, CallTernary = Call | 3,
CallQuaternary = Call | 4, CallQuaternary = Call | 4,
Comutative = 1 << 8, Commutative = 1 << 8,
Op = 1 << 9, Op = 1 << 9,
Call = 1 << 10, Call = 1 << 10,
Special = 1 << 11, Special = 1 << 11,
ArityMask = 0xff ArityMask = 0xff
} }

View File

@ -102,9 +102,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
public static string GetConstantBufferName(IAstNode slot, string offsetExpr, GalShaderType shaderType) public static string GetConstantBufferName(IAstNode slot, string offsetExpr, GalShaderType shaderType)
{ {
//Non-constant slots are not supported. // Non-constant slots are not supported.
//It is expected that upstream stages are never going to generate non-constant // It is expected that upstream stages are never going to generate non-constant
//slot access. // slot access.
AstOperand operand = (AstOperand)slot; AstOperand operand = (AstOperand)slot;
string ubName = GetUbName(shaderType, operand.Value); string ubName = GetUbName(shaderType, operand.Value);
@ -157,7 +157,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
} }
else if (_builtInAttributes.TryGetValue(value & ~3, out BuiltInAttribute builtInAttr)) else if (_builtInAttributes.TryGetValue(value & ~3, out BuiltInAttribute builtInAttr))
{ {
//TODO: There must be a better way to handle this... // TODO: There must be a better way to handle this...
if (shaderType == GalShaderType.Fragment) if (shaderType == GalShaderType.Fragment)
{ {
switch (value & ~3) switch (value & ~3)
@ -180,14 +180,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
} }
} }
//TODO: Warn about unknown built-in attribute. // TODO: Warn about unknown built-in attribute.
return isOutAttr ? "// bad_attr0x" + value.ToString("X") : "0.0"; return isOutAttr ? "// bad_attr0x" + value.ToString("X") : "0.0";
} }
public static string GetUbName(GalShaderType shaderType, int slot) public static string GetUbName(GalShaderType shaderType, int slot)
{ {
string ubName = OperandManager.GetShaderStagePrefix(shaderType); string ubName = GetShaderStagePrefix(shaderType);
ubName += "_" + DefaultNames.UniformNamePrefix + slot; ubName += "_" + DefaultNames.UniformNamePrefix + slot;

View File

@ -51,7 +51,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
while (workQueue.TryDequeue(out Block currBlock)) while (workQueue.TryDequeue(out Block currBlock))
{ {
//Check if the current block is inside another block. // Check if the current block is inside another block.
if (BinarySearch(blocks, currBlock.Address, out int nBlkIndex)) if (BinarySearch(blocks, currBlock.Address, out int nBlkIndex))
{ {
Block nBlock = blocks[nBlkIndex]; Block nBlock = blocks[nBlkIndex];
@ -68,7 +68,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
continue; continue;
} }
//If we have a block after the current one, set the limit address. // If we have a block after the current one, set the limit address.
ulong limitAddress = ulong.MaxValue; ulong limitAddress = ulong.MaxValue;
if (nBlkIndex != blocks.Count) if (nBlkIndex != blocks.Count)
@ -96,10 +96,10 @@ namespace Ryujinx.Graphics.Shader.Decoders
GetBlock(ssyOp.GetAbsoluteAddress()); GetBlock(ssyOp.GetAbsoluteAddress());
} }
//Set child blocks. "Branch" is the block the branch instruction // Set child blocks. "Branch" is the block the branch instruction
//points to (when taken), "Next" is the block at the next address, // points to (when taken), "Next" is the block at the next address,
//executed when the branch is not taken. For Unconditional Branches // executed when the branch is not taken. For Unconditional Branches
//or end of program, Next is null. // or end of program, Next is null.
OpCode lastOp = currBlock.GetLastOp(); OpCode lastOp = currBlock.GetLastOp();
if (lastOp is OpCodeBranch op) if (lastOp is OpCodeBranch op)
@ -113,7 +113,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
} }
} }
//Insert the new block on the list (sorted by address). // Insert the new block on the list (sorted by address).
if (blocks.Count != 0) if (blocks.Count != 0)
{ {
Block nBlock = blocks[nBlkIndex]; Block nBlock = blocks[nBlkIndex];
@ -187,7 +187,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
break; break;
} }
//Ignore scheduling instructions, which are written every 32 bytes. // Ignore scheduling instructions, which are written every 32 bytes.
if (((address - startAddress) & 0x1f) == 0) if (((address - startAddress) & 0x1f) == 0)
{ {
address += 8; address += 8;
@ -208,7 +208,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
if (emitter == null) if (emitter == null)
{ {
//TODO: Warning, illegal encoding. // TODO: Warning, illegal encoding.
continue; continue;
} }

View File

@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
public bool InvertPredicate { get; protected set; } public bool InvertPredicate { get; protected set; }
//When inverted, the always true predicate == always false. // When inverted, the always true predicate == always false.
public bool NeverExecute => Predicate.Index == RegisterConsts.PredicateTrueIndex && InvertPredicate; public bool NeverExecute => Predicate.Index == RegisterConsts.PredicateTrueIndex && InvertPredicate;
public OpCode(InstEmitter emitter, ulong address, long opCode) public OpCode(InstEmitter emitter, ulong address, long opCode)

View File

@ -1,3 +1,4 @@
// ReSharper disable InconsistentNaming
using Ryujinx.Graphics.Shader.Instructions; using Ryujinx.Graphics.Shader.Instructions;
namespace Ryujinx.Graphics.Shader.Decoders namespace Ryujinx.Graphics.Shader.Decoders

View File

@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
context.Copy(GetDest(context), res); context.Copy(GetDest(context), res);
//TODO: CC, X, corner cases // TODO: CC, X, corner cases
} }
public static void Iadd(EmitterContext context) public static void Iadd(EmitterContext context)
@ -60,7 +60,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (op.Extended) if (op.Extended)
{ {
//Add carry, or subtract borrow. // Add carry, or subtract borrow.
res = context.IAdd(res, isSubtraction res = context.IAdd(res, isSubtraction
? context.BitwiseNot(GetCF(context)) ? context.BitwiseNot(GetCF(context))
: context.BitwiseAnd(GetCF(context), Const(1))); : context.BitwiseAnd(GetCF(context), Const(1)));
@ -102,7 +102,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
} }
else else
{ {
//TODO: Warning. // TODO: Warning.
} }
return src; return src;
@ -126,7 +126,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
} }
else else
{ {
//TODO: Warning. // TODO: Warning.
} }
} }
@ -134,7 +134,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
context.Copy(GetDest(context), res); context.Copy(GetDest(context), res);
//TODO: CC, X, corner cases // TODO: CC, X, corner cases
} }
public static void Imnmx(EmitterContext context) public static void Imnmx(EmitterContext context)
@ -162,7 +162,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
SetZnFlags(context, dest, op.SetCondCode); SetZnFlags(context, dest, op.SetCondCode);
//TODO: X flags. // TODO: X flags.
} }
public static void Iscadd(EmitterContext context) public static void Iscadd(EmitterContext context)
@ -193,7 +193,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
context.Copy(GetDest(context), res); context.Copy(GetDest(context), res);
//TODO: CC, X // TODO: CC, X
} }
public static void Iset(EmitterContext context) public static void Iset(EmitterContext context)
@ -225,7 +225,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
context.Copy(dest, res); context.Copy(dest, res);
} }
//TODO: CC, X // TODO: CC, X
} }
public static void Isetp(EmitterContext context) public static void Isetp(EmitterContext context)
@ -330,10 +330,10 @@ namespace Ryujinx.Graphics.Shader.Instructions
public static void Rro(EmitterContext context) public static void Rro(EmitterContext context)
{ {
//This is the range reduction operator, // This is the range reduction operator,
//we translate it as a simple move, as it // we translate it as a simple move, as it
//should be always followed by a matching // should be always followed by a matching
//MUFU instruction. // MUFU instruction.
OpCodeAlu op = (OpCodeAlu)context.CurrOp; OpCodeAlu op = (OpCodeAlu)context.CurrOp;
bool negateB = op.RawOpCode.Extract(45); bool negateB = op.RawOpCode.Extract(45);
@ -363,13 +363,13 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (!isMasked) if (!isMasked)
{ {
//Clamped shift value. // Clamped shift value.
Operand isLessThan32 = context.ICompareLessUnsigned(srcB, Const(32)); Operand isLessThan32 = context.ICompareLessUnsigned(srcB, Const(32));
res = context.ConditionalSelect(isLessThan32, res, Const(0)); res = context.ConditionalSelect(isLessThan32, res, Const(0));
} }
//TODO: X, CC // TODO: X, CC
context.Copy(GetDest(context), res); context.Copy(GetDest(context), res);
} }
@ -401,7 +401,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (!isMasked) if (!isMasked)
{ {
//Clamped shift value. // Clamped shift value.
Operand resShiftBy32; Operand resShiftBy32;
if (isSigned) if (isSigned)
@ -418,7 +418,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
res = context.ConditionalSelect(isLessThan32, res, resShiftBy32); res = context.ConditionalSelect(isLessThan32, res, resShiftBy32);
} }
//TODO: X, CC // TODO: X, CC
context.Copy(GetDest(context), res); context.Copy(GetDest(context), res);
} }
@ -454,7 +454,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
Operand srcB = GetSrcB(context); Operand srcB = GetSrcB(context);
Operand srcC = GetSrcC(context); Operand srcC = GetSrcC(context);
//XMAD immediates are 16-bits unsigned integers. // XMAD immediates are 16-bits unsigned integers.
if (srcB.Type == OperandType.Constant) if (srcB.Type == OperandType.Constant)
{ {
srcB = Const(srcB.Value & 0xffff); srcB = Const(srcB.Value & 0xffff);
@ -541,12 +541,12 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (extended) if (extended)
{ {
//Add with carry. // Add with carry.
res = context.IAdd(res, context.BitwiseAnd(GetCF(context), Const(1))); res = context.IAdd(res, context.BitwiseAnd(GetCF(context), Const(1)));
} }
else else
{ {
//Add (no carry in). // Add (no carry in).
res = context.IAdd(res, srcC); res = context.IAdd(res, srcC);
} }
@ -654,12 +654,12 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (!extended || isSubtraction) if (!extended || isSubtraction)
{ {
//C = d < a // C = d < a
context.Copy(GetCF(context), context.ICompareLessUnsigned(res, srcA)); context.Copy(GetCF(context), context.ICompareLessUnsigned(res, srcA));
} }
else else
{ {
//C = (d == a && CIn) || d < a // C = (d == a && CIn) || d < a
Operand tempC0 = context.ICompareEqual (res, srcA); Operand tempC0 = context.ICompareEqual (res, srcA);
Operand tempC1 = context.ICompareLessUnsigned(res, srcA); Operand tempC1 = context.ICompareLessUnsigned(res, srcA);
@ -668,7 +668,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
context.Copy(GetCF(context), context.BitwiseOr(tempC0, tempC1)); context.Copy(GetCF(context), context.BitwiseOr(tempC0, tempC1));
} }
//V = (d ^ a) & ~(a ^ b) < 0 // V = (d ^ a) & ~(a ^ b) < 0
Operand tempV0 = context.BitwiseExclusiveOr(res, srcA); Operand tempV0 = context.BitwiseExclusiveOr(res, srcA);
Operand tempV1 = context.BitwiseExclusiveOr(srcA, srcB); Operand tempV1 = context.BitwiseExclusiveOr(srcA, srcB);

View File

@ -65,12 +65,12 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (extended) if (extended)
{ {
//When the operation is extended, it means we are doing // When the operation is extended, it means we are doing
//the operation on a long word with any number of bits, // the operation on a long word with any number of bits,
//so we need to AND the zero flag from result with the // so we need to AND the zero flag from result with the
//previous result when extended is specified, to ensure // previous result when extended is specified, to ensure
//we have ZF set only if all words are zero, and not just // we have ZF set only if all words are zero, and not just
//the last one. // the last one.
Operand oldZF = GetZF(context); Operand oldZF = GetZF(context);
Operand res = context.BitwiseAnd(context.ICompareEqual(dest, Const(0)), oldZF); Operand res = context.BitwiseAnd(context.ICompareEqual(dest, Const(0)), oldZF);

View File

@ -47,7 +47,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
WriteFP(context, dstType, srcB); WriteFP(context, dstType, srcB);
//TODO: CC. // TODO: CC.
} }
public static void F2I(EmitterContext context) public static void F2I(EmitterContext context)
@ -88,7 +88,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
srcB = context.FPConvertToS32(srcB); srcB = context.FPConvertToS32(srcB);
//TODO: S/U64, conversion overflow handling. // TODO: S/U64, conversion overflow handling.
if (intType != IntegerType.S32) if (intType != IntegerType.S32)
{ {
int min = GetIntMin(intType); int min = GetIntMin(intType);
@ -103,7 +103,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
context.Copy(dest, srcB); context.Copy(dest, srcB);
//TODO: CC. // TODO: CC.
} }
public static void I2F(EmitterContext context) public static void I2F(EmitterContext context)
@ -137,7 +137,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
WriteFP(context, dstType, srcB); WriteFP(context, dstType, srcB);
//TODO: CC. // TODO: CC.
} }
public static void I2I(EmitterContext context) public static void I2I(EmitterContext context)
@ -149,7 +149,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (srcType == IntegerType.U64 || dstType == IntegerType.U64) if (srcType == IntegerType.U64 || dstType == IntegerType.U64)
{ {
//TODO: Warning. This instruction doesn't support 64-bits integers // TODO: Warning. This instruction doesn't support 64-bits integers
} }
bool srcIsSmallInt = srcType <= IntegerType.U16; bool srcIsSmallInt = srcType <= IntegerType.U16;
@ -189,7 +189,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
context.Copy(GetDest(context), srcB); context.Copy(GetDest(context), srcB);
//TODO: CC. // TODO: CC.
} }
private static void WriteFP(EmitterContext context, FPType type, Operand srcB) private static void WriteFP(EmitterContext context, FPType type, Operand srcB)
@ -206,7 +206,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
} }
else else
{ {
//TODO. // TODO.
} }
} }
} }

View File

@ -146,7 +146,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
context.Copy(dest, res); context.Copy(dest, res);
} }
//TODO: CC, X // TODO: CC, X
} }
public static void Fsetp(EmitterContext context) public static void Fsetp(EmitterContext context)

View File

@ -19,8 +19,8 @@ namespace Ryujinx.Graphics.Shader.Instructions
{ {
OpCodeExit op = (OpCodeExit)context.CurrOp; OpCodeExit op = (OpCodeExit)context.CurrOp;
//TODO: Figure out how this is supposed to work in the // TODO: Figure out how this is supposed to work in the
//presence of other condition codes. // presence of other condition codes.
if (op.Condition == Condition.Always) if (op.Condition == Condition.Always)
{ {
context.Return(); context.Return();
@ -54,8 +54,8 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (op.Targets.Count == 1) if (op.Targets.Count == 1)
{ {
//If we have only one target, then the SSY is basically // If we have only one target, then the SSY is basically
//a branch, we can produce better codegen for this case. // a branch, we can produce better codegen for this case.
OpCodeSsy opSsy = op.Targets.Keys.First(); OpCodeSsy opSsy = op.Targets.Keys.First();
EmitBranch(context, opSsy.GetAbsoluteAddress()); EmitBranch(context, opSsy.GetAbsoluteAddress());
@ -79,8 +79,8 @@ namespace Ryujinx.Graphics.Shader.Instructions
private static void EmitBranch(EmitterContext context, ulong address) private static void EmitBranch(EmitterContext context, ulong address)
{ {
//If we're branching to the next instruction, then the branch // If we're branching to the next instruction, then the branch
//is useless and we can ignore it. // is useless and we can ignore it.
if (address == context.CurrOp.Address + 8) if (address == context.CurrOp.Address + 8)
{ {
return; return;

View File

@ -53,7 +53,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
} }
else if (floatType == FPType.FP64) else if (floatType == FPType.FP64)
{ {
//TODO. // TODO.
} }
throw new ArgumentException($"Invalid floating point type \"{floatType}\"."); throw new ArgumentException($"Invalid floating point type \"{floatType}\".");

View File

@ -71,7 +71,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (op.Size > IntegerSize.B64) if (op.Size > IntegerSize.B64)
{ {
//TODO: Warning. // TODO: Warning.
} }
bool isSmallInt = op.Size < IntegerSize.B32; bool isSmallInt = op.Size < IntegerSize.B32;
@ -121,7 +121,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (!(emit || cut)) if (!(emit || cut))
{ {
//TODO: Warning. // TODO: Warning.
} }
if (emit) if (emit)

View File

@ -443,7 +443,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
TextureProperty property = (TextureProperty)op.RawOpCode.Extract(22, 6); TextureProperty property = (TextureProperty)op.RawOpCode.Extract(22, 6);
//TODO: Validate and use property. // TODO: Validate and use property.
Instruction inst = Instruction.TextureSize; Instruction inst = Instruction.TextureSize;
TextureType type = TextureType.Texture2D; TextureType type = TextureType.Texture2D;

View File

@ -16,11 +16,11 @@ namespace Ryujinx.Graphics.Shader.Instructions
{ {
Operand expr = null; Operand expr = null;
//Handle some simple cases, or cases where // Handle some simple cases, or cases where
//the KMap would yield poor results (like XORs). // the KMap would yield poor results (like XORs).
if (imm == 0x96 || imm == 0x69) if (imm == 0x96 || imm == 0x69)
{ {
//XOR (0x96) and XNOR (0x69). // XOR (0x96) and XNOR (0x69).
if (imm == 0x69) if (imm == 0x69)
{ {
srcA = context.BitwiseNot(srcA); srcA = context.BitwiseNot(srcA);
@ -33,18 +33,18 @@ namespace Ryujinx.Graphics.Shader.Instructions
} }
else if (imm == 0) else if (imm == 0)
{ {
//Always false. // Always false.
return Const(IrConsts.False); return Const(IrConsts.False);
} }
else if (imm == 0xff) else if (imm == 0xff)
{ {
//Always true. // Always true.
return Const(IrConsts.True); return Const(IrConsts.True);
} }
int map; int map;
//Encode into gray code. // Encode into gray code.
map = ((imm >> 0) & 1) << 0; map = ((imm >> 0) & 1) << 0;
map |= ((imm >> 1) & 1) << 4; map |= ((imm >> 1) & 1) << 4;
map |= ((imm >> 2) & 1) << 1; map |= ((imm >> 2) & 1) << 1;
@ -54,7 +54,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
map |= ((imm >> 6) & 1) << 2; map |= ((imm >> 6) & 1) << 2;
map |= ((imm >> 7) & 1) << 6; map |= ((imm >> 7) & 1) << 6;
//Solve KMap, get sum of products. // Solve KMap, get sum of products.
int visited = 0; int visited = 0;
for (int index = 0; index < 8 && visited != 0xff; index++) for (int index = 0; index < 8 && visited != 0xff; index++)
@ -76,7 +76,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
} }
} }
//The mask should wrap, if we are on the high row, shift to low etc. // The mask should wrap, if we are on the high row, shift to low etc.
int mask2 = (index & 4) != 0 ? mask >> 4 : mask << 4; int mask2 = (index & 4) != 0 ? mask >> 4 : mask << 4;
if ((map & mask2) == mask2) if ((map & mask2) == mask2)

View File

@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
Inst = inst; Inst = inst;
Dest = dest; Dest = dest;
//The array may be modified externally, so we store a copy. // The array may be modified externally, so we store a copy.
_sources = (Operand[])sources.Clone(); _sources = (Operand[])sources.Clone();
for (int index = 0; index < _sources.Length; index++) for (int index = 0; index < _sources.Length; index++)

View File

@ -158,7 +158,7 @@ namespace Ryujinx.Graphics.Shader
} }
} }
//Depth register is always two registers after the last color output. // Depth register is always two registers after the last color output.
return count + 1; return count + 1;
} }
} }

View File

@ -33,7 +33,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
while (node != null) while (node != null)
{ {
//We reached a child block, visit the nodes inside. // We reached a child block, visit the nodes inside.
while (node is AstBlock childBlock) while (node is AstBlock childBlock)
{ {
Block = childBlock; Block = childBlock;
@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
BlockEntered?.Invoke(this, new BlockVisitationEventArgs(Block)); BlockEntered?.Invoke(this, new BlockVisitationEventArgs(Block));
} }
//Node may be null, if the block is empty. // Node may be null, if the block is empty.
if (node != null) if (node != null)
{ {
IAstNode next = Next(node); IAstNode next = Next(node);
@ -53,7 +53,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
node = next; node = next;
} }
//We reached the end of the list, go up on tree to the parent blocks. // We reached the end of the list, go up on tree to the parent blocks.
while (node == null && Block.Type != AstBlockType.Main) while (node == null && Block.Type != AstBlockType.Main)
{ {
BlockLeft?.Invoke(this, new BlockVisitationEventArgs(Block)); BlockLeft?.Invoke(this, new BlockVisitationEventArgs(Block));

View File

@ -8,8 +8,8 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
{ {
static class GotoElimination static class GotoElimination
{ {
//This is a modified version of the algorithm presented on the paper // This is a modified version of the algorithm presented on the paper
//"Taming Control Flow: A Structured Approach to Eliminating Goto Statements". // "Taming Control Flow: A Structured Approach to Eliminating Goto Statements".
public static void Eliminate(GotoStatement[] gotos) public static void Eliminate(GotoStatement[] gotos)
{ {
for (int index = gotos.Length - 1; index >= 0; index--) for (int index = gotos.Length - 1; index >= 0; index--)
@ -43,10 +43,10 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
if (Previous(stmt.Goto) is AstBlock elseBlock && elseBlock.Type == AstBlockType.Else) if (Previous(stmt.Goto) is AstBlock elseBlock && elseBlock.Type == AstBlockType.Else)
{ {
//It's possible that the label was enclosed inside an else block, // It's possible that the label was enclosed inside an else block,
//in this case we need to update the block and level. // in this case we need to update the block and level.
//We also need to set the IsLoop for the case when the label is // We also need to set the IsLoop for the case when the label is
//now before the goto, due to the newly introduced else block. // now before the goto, due to the newly introduced else block.
lBlock = ParentBlock(stmt.Label); lBlock = ParentBlock(stmt.Label);
lLevel = Level(lBlock); lLevel = Level(lBlock);
@ -97,7 +97,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
private static bool DirectlyRelated(AstBlock lBlock, AstBlock rBlock, int lLevel, int rLevel) private static bool DirectlyRelated(AstBlock lBlock, AstBlock rBlock, int lLevel, int rLevel)
{ {
//If the levels are equal, they can be either siblings or indirectly related. // If the levels are equal, they can be either siblings or indirectly related.
if (lLevel == rLevel) if (lLevel == rLevel)
{ {
return false; return false;
@ -171,9 +171,9 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
AstBlock block = origin; AstBlock block = origin;
//Check if a loop is enclosing the goto, and the block that is // Check if a loop is enclosing the goto, and the block that is
//directly related to the label is above the loop block. // directly related to the label is above the loop block.
//In that case, we need to introduce a break to get out of the loop. // In that case, we need to introduce a break to get out of the loop.
AstBlock loopBlock = origin; AstBlock loopBlock = origin;
int loopLevel = gLevel; int loopLevel = gLevel;
@ -199,7 +199,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
} }
} }
//Insert ifs to skip the parts that shouldn't be executed due to the goto. // Insert ifs to skip the parts that shouldn't be executed due to the goto.
bool tryInsertElse = stmt.IsUnconditional && origin.Type == AstBlockType.If; bool tryInsertElse = stmt.IsUnconditional && origin.Type == AstBlockType.If;
while (gLevel > lLevel) while (gLevel > lLevel)
@ -210,10 +210,10 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
AstBlock child = block; AstBlock child = block;
//We can't move the goto in the middle of a if and a else block, in // We can't move the goto in the middle of a if and a else block, in
//this case we need to move it after the else. // this case we need to move it after the else.
//IsLoop may need to be updated if the label is inside the else, as // IsLoop may need to be updated if the label is inside the else, as
//introducing a loop is the only way to ensure the else will be executed. // introducing a loop is the only way to ensure the else will be executed.
if (Next(child) is AstBlock elseBlock && elseBlock.Type == AstBlockType.Else) if (Next(child) is AstBlock elseBlock && elseBlock.Type == AstBlockType.Else)
{ {
child = elseBlock; child = elseBlock;
@ -256,7 +256,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
if (child.Type == AstBlockType.If) if (child.Type == AstBlockType.If)
{ {
//Modify the if condition to allow it to be entered by the goto. // Modify the if condition to allow it to be entered by the goto.
if (!ContainsCondComb(child.Condition, Instruction.LogicalOr, stmt.Condition)) if (!ContainsCondComb(child.Condition, Instruction.LogicalOr, stmt.Condition))
{ {
child.OrCondition(stmt.Condition); child.OrCondition(stmt.Condition);
@ -264,7 +264,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
} }
else if (child.Type == AstBlockType.Else) else if (child.Type == AstBlockType.Else)
{ {
//Modify the matching if condition to force the else to be entered by the goto. // Modify the matching if condition to force the else to be entered by the goto.
if (!(Previous(child) is AstBlock ifBlock) || ifBlock.Type != AstBlockType.If) if (!(Previous(child) is AstBlock ifBlock) || ifBlock.Type != AstBlockType.If)
{ {
throw new InvalidOperationException("Found an else without a matching if."); throw new InvalidOperationException("Found an else without a matching if.");
@ -309,14 +309,14 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
{ {
if (block.Type == AstBlockType.DoWhile && first == block.First) if (block.Type == AstBlockType.DoWhile && first == block.First)
{ {
//We only need to insert the continue if we're not at the end of the loop, // We only need to insert the continue if we're not at the end of the loop,
//or if our condition is different from the loop condition. // or if our condition is different from the loop condition.
if (Next(stmt.Goto) != null || block.Condition != stmt.Condition) if (Next(stmt.Goto) != null || block.Condition != stmt.Condition)
{ {
EncloseSingleInst(stmt, Instruction.LoopContinue); EncloseSingleInst(stmt, Instruction.LoopContinue);
} }
//Modify the do-while condition to allow it to continue. // Modify the do-while condition to allow it to continue.
if (!ContainsCondComb(block.Condition, Instruction.LogicalOr, stmt.Condition)) if (!ContainsCondComb(block.Condition, Instruction.LogicalOr, stmt.Condition))
{ {
block.OrCondition(stmt.Condition); block.OrCondition(stmt.Condition);
@ -356,10 +356,10 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
cond = InverseCond(cond); cond = InverseCond(cond);
} }
//Do a quick check, if we are enclosing a single block, // Do a quick check, if we are enclosing a single block,
//and the block type/condition matches the one we're going // and the block type/condition matches the one we're going
//to create, then we don't need a new block, we can just // to create, then we don't need a new block, we can just
//return the old one. // return the old one.
bool hasSingleNode = Next(first) == last; bool hasSingleNode = Next(first) == last;
if (hasSingleNode && BlockMatches(first, type, cond)) if (hasSingleNode && BlockMatches(first, type, cond))

View File

@ -69,10 +69,10 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
AstAssignment assignment; AstAssignment assignment;
//If all the sources are bool, it's better to use short-circuiting // If all the sources are bool, it's better to use short-circuiting
//logical operations, rather than forcing a cast to int and doing // logical operations, rather than forcing a cast to int and doing
//a bitwise operation with the value, as it is likely to be used as // a bitwise operation with the value, as it is likely to be used as
//a bool in the end. // a bool in the end.
if (IsBitwiseInst(inst) && AreAllSourceTypesEqual(sources, VariableType.Bool)) if (IsBitwiseInst(inst) && AreAllSourceTypesEqual(sources, VariableType.Bool))
{ {
inst = GetLogicalFromBitwiseInst(inst); inst = GetLogicalFromBitwiseInst(inst);

View File

@ -65,8 +65,8 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
private void LookForDoWhileStatements(BasicBlock block) private void LookForDoWhileStatements(BasicBlock block)
{ {
//Check if we have any predecessor whose index is greater than the // Check if we have any predecessor whose index is greater than the
//current block, this indicates a loop. // current block, this indicates a loop.
bool done = false; bool done = false;
foreach (BasicBlock predecessor in block.Predecessors.OrderByDescending(x => x.Index)) foreach (BasicBlock predecessor in block.Predecessors.OrderByDescending(x => x.Index))
@ -146,9 +146,9 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
{ {
AddNode(gotoTempAsg); AddNode(gotoTempAsg);
//For block 0, we don't need to add the extra "reset" at the beggining, // For block 0, we don't need to add the extra "reset" at the beginning,
//because it is already the first node to be executed on the shader, // because it is already the first node to be executed on the shader,
//so it is reset to false by the "local" assignment anyway. // so it is reset to false by the "local" assignment anyway.
if (block.Index != 0) if (block.Index != 0)
{ {
Info.MainBlock.AddFirst(Assign(gotoTempAsg.Destination, Const(IrConsts.False))); Info.MainBlock.AddFirst(Assign(gotoTempAsg.Destination, Const(IrConsts.False)));

View File

@ -29,8 +29,8 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
public const int UserAttributeEnd = UserAttributeBase + UserAttributesCount * 16; public const int UserAttributeEnd = UserAttributeBase + UserAttributesCount * 16;
//Note: Those attributes are used internally by the translator // Note: Those attributes are used internally by the translator
//only, they don't exist on Maxwell. // only, they don't exist on Maxwell.
public const int FragmentOutputDepth = 0x1000000; public const int FragmentOutputDepth = 0x1000000;
public const int FragmentOutputColorBase = 0x1000010; public const int FragmentOutputColorBase = 0x1000010;
public const int FragmentOutputColorEnd = FragmentOutputColorBase + 8 * 16; public const int FragmentOutputColorEnd = FragmentOutputColorBase + 8 * 16;

View File

@ -5,8 +5,8 @@ namespace Ryujinx.Graphics.Shader.Translation
{ {
static class Dominance static class Dominance
{ {
//Those methods are an implementation of the algorithms on "A Simple, Fast Dominance Algorithm". // Those methods are an implementation of the algorithms on "A Simple, Fast Dominance Algorithm".
//https://www.cs.rice.edu/~keith/EMBED/dom.pdf // https://www.cs.rice.edu/~keith/EMBED/dom.pdf
public static void FindDominators(BasicBlock entry, int blocksCount) public static void FindDominators(BasicBlock entry, int blocksCount)
{ {
HashSet<BasicBlock> visited = new HashSet<BasicBlock>(); HashSet<BasicBlock> visited = new HashSet<BasicBlock>();

View File

@ -19,13 +19,13 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
private static bool IsRedundantBranch(Operation current, BasicBlock nextBlock) private static bool IsRedundantBranch(Operation current, BasicBlock nextBlock)
{ {
//Here we check that: // Here we check that:
//- The current block ends with a branch. // - The current block ends with a branch.
//- The next block only contains a branch. // - The next block only contains a branch.
//- The branch on the next block is unconditional. // - The branch on the next block is unconditional.
//- Both branches are jumping to the same location. // - Both branches are jumping to the same location.
//In this case, the branch on the current block can be removed, // In this case, the branch on the current block can be removed,
//as the next block is going to jump to the same place anyway. // as the next block is going to jump to the same place anyway.
if (nextBlock == null) if (nextBlock == null)
{ {
return false; return false;

View File

@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
if (exponent == 0x1f) if (exponent == 0x1f)
{ {
//NaN or Infinity. // NaN or Infinity.
mantissa <<= 13; mantissa <<= 13;
exponent = 0xff; exponent = 0xff;
} }
@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
{ {
if (exponent == 0) if (exponent == 0)
{ {
//Denormal. // Denormal.
int e = -1; int e = -1;
int m = mantissa; int m = mantissa;

View File

@ -81,8 +81,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
private static void PropagateCopy(Operation copyOp) private static void PropagateCopy(Operation copyOp)
{ {
//Propagate copy source operand to all uses of // Propagate copy source operand to all uses of
//the destination operand. // the destination operand.
Operand dest = copyOp.Dest; Operand dest = copyOp.Dest;
Operand src = copyOp.GetSource(0); Operand src = copyOp.GetSource(0);
@ -102,8 +102,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
private static bool PropagatePack(Operation packOp) private static bool PropagatePack(Operation packOp)
{ {
//Propagate pack source operands to uses by unpack // Propagate pack source operands to uses by unpack
//instruction. The source depends on the unpack instruction. // instruction. The source depends on the unpack instruction.
bool modified = false; bool modified = false;
Operand dest = packOp.Dest; Operand dest = packOp.Dest;
@ -132,8 +132,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
private static void RemoveNode(BasicBlock block, LinkedListNode<INode> llNode) private static void RemoveNode(BasicBlock block, LinkedListNode<INode> llNode)
{ {
//Remove a node from the nodes list, and also remove itself // Remove a node from the nodes list, and also remove itself
//from all the use lists on the operands that this node uses. // from all the use lists on the operands that this node uses.
block.Operations.Remove(llNode); block.Operations.Remove(llNode);
Queue<INode> nodes = new Queue<INode>(); Queue<INode> nodes = new Queue<INode>();

View File

@ -14,7 +14,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
{ {
case Instruction.Add: case Instruction.Add:
case Instruction.BitwiseExclusiveOr: case Instruction.BitwiseExclusiveOr:
TryEliminateBinaryOpComutative(operation, 0); TryEliminateBinaryOpCommutative(operation, 0);
break; break;
case Instruction.BitwiseAnd: case Instruction.BitwiseAnd:
@ -34,7 +34,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
break; break;
case Instruction.Multiply: case Instruction.Multiply:
TryEliminateBinaryOpComutative(operation, 1); TryEliminateBinaryOpCommutative(operation, 1);
break; break;
case Instruction.ShiftLeft: case Instruction.ShiftLeft:
@ -48,9 +48,9 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
private static void TryEliminateBitwiseAnd(Operation operation) private static void TryEliminateBitwiseAnd(Operation operation)
{ {
//Try to recognize and optimize those 3 patterns (in order): // Try to recognize and optimize those 3 patterns (in order):
//x & 0xFFFFFFFF == x, 0xFFFFFFFF & y == y, // x & 0xFFFFFFFF == x, 0xFFFFFFFF & y == y,
//x & 0x00000000 == 0x00000000, 0x00000000 & y == 0x00000000 // x & 0x00000000 == 0x00000000, 0x00000000 & y == 0x00000000
Operand x = operation.GetSource(0); Operand x = operation.GetSource(0);
Operand y = operation.GetSource(1); Operand y = operation.GetSource(1);
@ -70,9 +70,9 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
private static void TryEliminateBitwiseOr(Operation operation) private static void TryEliminateBitwiseOr(Operation operation)
{ {
//Try to recognize and optimize those 3 patterns (in order): // Try to recognize and optimize those 3 patterns (in order):
//x | 0x00000000 == x, 0x00000000 | y == y, // x | 0x00000000 == x, 0x00000000 | y == y,
//x | 0xFFFFFFFF == 0xFFFFFFFF, 0xFFFFFFFF | y == 0xFFFFFFFF // x | 0xFFFFFFFF == 0xFFFFFFFF, 0xFFFFFFFF | y == 0xFFFFFFFF
Operand x = operation.GetSource(0); Operand x = operation.GetSource(0);
Operand y = operation.GetSource(1); Operand y = operation.GetSource(1);
@ -101,7 +101,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
} }
} }
private static void TryEliminateBinaryOpComutative(Operation operation, int comparand) private static void TryEliminateBinaryOpCommutative(Operation operation, int comparand)
{ {
Operand x = operation.GetSource(0); Operand x = operation.GetSource(0);
Operand y = operation.GetSource(1); Operand y = operation.GetSource(1);
@ -125,8 +125,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
return; return;
} }
//The condition is constant, we can turn it into a copy, and select // The condition is constant, we can turn it into a copy, and select
//the source based on the condition value. // the source based on the condition value.
int srcIndex = cond.Value != 0 ? 1 : 2; int srcIndex = cond.Value != 0 ? 1 : 2;
Operand source = operation.GetSource(srcIndex); Operand source = operation.GetSource(srcIndex);

View File

@ -86,7 +86,7 @@ namespace Ryujinx.Graphics.Shader.Translation
Queue<BasicBlock> dfPhiBlocks = new Queue<BasicBlock>(); Queue<BasicBlock> dfPhiBlocks = new Queue<BasicBlock>();
//First pass, get all defs and locals uses. // First pass, get all defs and locals uses.
for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++) for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
{ {
Operand[] localDefs = new Operand[RegisterConsts.TotalCount]; Operand[] localDefs = new Operand[RegisterConsts.TotalCount];
@ -157,7 +157,7 @@ namespace Ryujinx.Graphics.Shader.Translation
} }
} }
//Second pass, rename variables with definitions on different blocks. // Second pass, rename variables with definitions on different blocks.
for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++) for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
{ {
Operand[] localDefs = new Operand[RegisterConsts.TotalCount]; Operand[] localDefs = new Operand[RegisterConsts.TotalCount];
@ -251,10 +251,10 @@ namespace Ryujinx.Graphics.Shader.Translation
private static Operand InsertPhi(DefMap[] globalDefs, BasicBlock block, Register reg) private static Operand InsertPhi(DefMap[] globalDefs, BasicBlock block, Register reg)
{ {
//This block has a Phi that has not been materialized yet, but that // This block has a Phi that has not been materialized yet, but that
//would define a new version of the variable we're looking for. We need // would define a new version of the variable we're looking for. We need
//to materialize the Phi, add all the block/operand pairs into the Phi, and // to materialize the Phi, add all the block/operand pairs into the Phi, and
//then use the definition from that Phi. // then use the definition from that Phi.
Operand local = Local(); Operand local = Local();
PhiNode phi = new PhiNode(local); PhiNode phi = new PhiNode(local);

View File

@ -28,7 +28,7 @@ namespace Ryujinx.Graphics.Shader.Translation
if (addressB != 0) if (addressB != 0)
{ {
//Dual vertex shader. // Dual vertex shader.
Operation[] shaderOpsB = DecodeShader(memory, addressB, config.Type); Operation[] shaderOpsB = DecodeShader(memory, addressB, config.Type);
shaderOps = Combine(shaderOps, shaderOpsB); shaderOps = Combine(shaderOps, shaderOpsB);
@ -86,10 +86,10 @@ namespace Ryujinx.Graphics.Shader.Translation
if (op is OpCodeSync opSync) if (op is OpCodeSync opSync)
{ {
//If the instruction is a SYNC instruction with only one // If the instruction is a SYNC instruction with only one
//possible target address, then the instruction is basically // possible target address, then the instruction is basically
//just a simple branch, we can generate code similar to branch // just a simple branch, we can generate code similar to branch
//instructions, with the condition check on the branch itself. // instructions, with the condition check on the branch itself.
skipPredicateCheck |= opSync.Targets.Count < 2; skipPredicateCheck |= opSync.Targets.Count < 2;
} }
@ -136,15 +136,15 @@ namespace Ryujinx.Graphics.Shader.Translation
private static Operation[] Combine(Operation[] a, Operation[] b) private static Operation[] Combine(Operation[] a, Operation[] b)
{ {
//Here we combine two shaders. // Here we combine two shaders.
//For shader A: // For shader A:
//- All user attribute stores on shader A are turned into copies to a // - All user attribute stores on shader A are turned into copies to a
//temporary variable. It's assumed that shader B will consume them. // temporary variable. It's assumed that shader B will consume them.
//- All return instructions are turned into branch instructions, the // - All return instructions are turned into branch instructions, the
//branch target being the start of the shader B code. // branch target being the start of the shader B code.
//For shader B: // For shader B:
//- All user attribute loads on shader B are turned into copies from a // - All user attribute loads on shader B are turned into copies from a
//temporary variable, as long that attribute is written by shader A. // temporary variable, as long that attribute is written by shader A.
List<Operation> output = new List<Operation>(a.Length + b.Length); List<Operation> output = new List<Operation>(a.Length + b.Length);
Operand[] temps = new Operand[AttributeConsts.UserAttributesCount * 4]; Operand[] temps = new Operand[AttributeConsts.UserAttributesCount * 4];

View File

@ -89,7 +89,7 @@ namespace Ryujinx.Graphics.VDec
{ {
H264BitStreamWriter writer = new H264BitStreamWriter(data); H264BitStreamWriter writer = new H264BitStreamWriter(data);
//Sequence Parameter Set. // Sequence Parameter Set.
writer.WriteU(1, 24); writer.WriteU(1, 24);
writer.WriteU(0, 1); writer.WriteU(0, 1);
writer.WriteU(3, 2); writer.WriteU(3, 2);
@ -145,7 +145,7 @@ namespace Ryujinx.Graphics.VDec
writer.End(); writer.End();
//Picture Parameter Set. // Picture Parameter Set.
writer.WriteU(1, 24); writer.WriteU(1, 24);
writer.WriteU(0, 1); writer.WriteU(0, 1);
writer.WriteU(3, 2); writer.WriteU(3, 2);
@ -196,7 +196,7 @@ namespace Ryujinx.Graphics.VDec
} }
} }
//ZigZag LUTs from libavcodec. // ZigZag LUTs from libavcodec.
private static readonly byte[] ZigZagDirect = new byte[] private static readonly byte[] ZigZagDirect = new byte[]
{ {
0, 1, 8, 16, 9, 2, 3, 10, 0, 1, 8, 16, 9, 2, 3, 10,

View File

@ -254,7 +254,7 @@ namespace Ryujinx.Graphics.VDec
} }
} }
//Copy chroma data from both channels with interleaving. // Copy chroma data from both channels with interleaving.
for (int y = 0; y < halfHeight; y++) for (int y = 0; y < halfHeight; y++)
{ {
int src = y * halfSrcWidth; int src = y * halfSrcWidth;

View File

@ -287,7 +287,7 @@ namespace Ryujinx.Graphics.VDec
bool showFrame = !isFrameIntra; bool showFrame = !isFrameIntra;
//Write compressed header. // Write compressed header.
byte[] compressedHeaderData; byte[] compressedHeaderData;
using (MemoryStream compressedHeader = new MemoryStream()) using (MemoryStream compressedHeader = new MemoryStream())
@ -437,7 +437,7 @@ namespace Ryujinx.Graphics.VDec
compressedHeaderData = compressedHeader.ToArray(); compressedHeaderData = compressedHeader.ToArray();
} }
//Write uncompressed header. // Write uncompressed header.
using (MemoryStream encodedHeader = new MemoryStream()) using (MemoryStream encodedHeader = new MemoryStream())
{ {
VpxBitStreamWriter writer = new VpxBitStreamWriter(encodedHeader); VpxBitStreamWriter writer = new VpxBitStreamWriter(encodedHeader);
@ -460,8 +460,8 @@ namespace Ryujinx.Graphics.VDec
_cachedRefFrames.Clear(); _cachedRefFrames.Clear();
//On key frames, all frame slots are set to the current frame, // On key frames, all frame slots are set to the current frame,
//so the value of the selected slot doesn't really matter. // so the value of the selected slot doesn't really matter.
GetNewFrameSlot(keys.CurrKey); GetNewFrameSlot(keys.CurrKey);
} }
else else
@ -593,8 +593,8 @@ namespace Ryujinx.Graphics.VDec
int tileColsLog2IncMask = (1 << tileColsLog2Diff) - 1; int tileColsLog2IncMask = (1 << tileColsLog2Diff) - 1;
//If it's less than the maximum, we need to add an extra 0 on the bitstream // If it's less than the maximum, we need to add an extra 0 on the bitstream
//to indicate that it should stop reading. // to indicate that it should stop reading.
if (header.TileColsLog2 < maxTileColsLog2) if (header.TileColsLog2 < maxTileColsLog2)
{ {
writer.WriteU(tileColsLog2IncMask << 1, tileColsLog2Diff + 1); writer.WriteU(tileColsLog2IncMask << 1, tileColsLog2Diff + 1);
@ -653,8 +653,8 @@ namespace Ryujinx.Graphics.VDec
return node.Value; return node.Value;
} }
//Reference frame was lost. // Reference frame was lost.
//What we should do in this case? // What we should do in this case?
return 0; return 0;
} }
@ -668,8 +668,8 @@ namespace Ryujinx.Graphics.VDec
private void WriteCoefProbabilityUpdate(VpxRangeEncoder writer, int txMode, byte[] New, byte[] old) private void WriteCoefProbabilityUpdate(VpxRangeEncoder writer, int txMode, byte[] New, byte[] old)
{ {
//Note: There's 1 byte added on each packet for alignment, // Note: There's 1 byte added on each packet for alignment,
//this byte is ignored when doing updates. // this byte is ignored when doing updates.
const int blockBytes = 2 * 2 * 6 * 6 * 4; const int blockBytes = 2 * 2 * 6 * 6 * 4;
bool NeedsUpdate(int baseIndex) bool NeedsUpdate(int baseIndex)

View File

@ -1,10 +1,8 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel.Ipc;
using Ryujinx.HLE.HOS.Services; using Ryujinx.HLE.HOS.Services;
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;

View File

@ -131,7 +131,7 @@ namespace Ryujinx.HLE.FileSystem.Content
} }
} }
if(_locationEntries.ContainsKey(storageId) && _locationEntries[storageId]?.Count == 0) if (_locationEntries.ContainsKey(storageId) && _locationEntries[storageId]?.Count == 0)
{ {
_locationEntries.Remove(storageId); _locationEntries.Remove(storageId);
} }

View File

@ -546,7 +546,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
_position += 2; _position += 2;
// FIXME: GNU c++flit returns this but that is not what is supposed to be returned. // FIXME: GNU c++flit returns this but that is not what is supposed to be returned.
return new NameType("half"); return new NameType("half");
//return new NameType("decimal16"); // return new NameType("decimal16");
case 'i': case 'i':
_position += 2; _position += 2;
return new NameType("char32_t"); return new NameType("char32_t");
@ -560,7 +560,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
_position += 2; _position += 2;
// FIXME: GNU c++flit returns this but that is not what is supposed to be returned. // FIXME: GNU c++flit returns this but that is not what is supposed to be returned.
return new NameType("decltype(nullptr)"); return new NameType("decltype(nullptr)");
//return new NameType("std::nullptr_t"); // return new NameType("std::nullptr_t");
case 't': case 't':
case 'T': case 'T':
_position += 2; _position += 2;
@ -1314,7 +1314,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
if (result != null) if (result != null)
{ {
// TODO: ABI Tags // TODO: ABI Tags
//throw new Exception("ABI Tags not implemented"); // throw new Exception("ABI Tags not implemented");
} }
return result; return result;
} }
@ -2909,7 +2909,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
} }
} while (!ConsumeIf("E")); } while (!ConsumeIf("E"));
} }
// ::= sr <unresolved-type> [tempate-args] <base-unresolved-name> # T::x / decltype(p)::x // ::= sr <unresolved-type> [template-args] <base-unresolved-name> # T::x / decltype(p)::x
else else
{ {
result = ParseUnresolvedType(); result = ParseUnresolvedType();

View File

@ -7,26 +7,26 @@ namespace Ryujinx.HLE.HOS
{ {
public const string TemporaryNroSuffix = ".ryu_tmp.nro"; public const string TemporaryNroSuffix = ".ryu_tmp.nro";
//http://switchbrew.org/index.php?title=Homebrew_ABI // http://switchbrew.org/index.php?title=Homebrew_ABI
public static void WriteHbAbiData(MemoryManager memory, long position, int mainThreadHandle, string switchPath) public static void WriteHbAbiData(MemoryManager memory, long position, int mainThreadHandle, string switchPath)
{ {
//MainThreadHandle. // MainThreadHandle.
WriteConfigEntry(memory, ref position, 1, 0, mainThreadHandle); WriteConfigEntry(memory, ref position, 1, 0, mainThreadHandle);
//NextLoadPath. // NextLoadPath.
WriteConfigEntry(memory, ref position, 2, 0, position + 0x200, position + 0x400); WriteConfigEntry(memory, ref position, 2, 0, position + 0x200, position + 0x400);
//Argv. // Argv.
long argvPosition = position + 0xC00; long argvPosition = position + 0xC00;
memory.WriteBytes(argvPosition, Encoding.ASCII.GetBytes(switchPath + "\0")); memory.WriteBytes(argvPosition, Encoding.ASCII.GetBytes(switchPath + "\0"));
WriteConfigEntry(memory, ref position, 5, 0, 0, argvPosition); WriteConfigEntry(memory, ref position, 5, 0, 0, argvPosition);
//AppletType. // AppletType.
WriteConfigEntry(memory, ref position, 7); WriteConfigEntry(memory, ref position, 7);
//EndOfList. // EndOfList.
WriteConfigEntry(memory, ref position, 0); WriteConfigEntry(memory, ref position, 0);
} }

View File

@ -53,7 +53,7 @@ namespace Ryujinx.HLE.HOS
offset += _positionOffset; offset += _positionOffset;
} }
return _baseStream.Seek(offset, origin); return _baseStream.Seek(offset, origin);
} }
public override void SetLength(long value) public override void SetLength(long value)

View File

@ -156,8 +156,8 @@ namespace Ryujinx.HLE.HOS
AutoObjectNames = new ConcurrentDictionary<string, KAutoObject>(); AutoObjectNames = new ConcurrentDictionary<string, KAutoObject>();
//Note: This is not really correct, but with HLE of services, the only memory // Note: This is not really correct, but with HLE of services, the only memory
//region used that is used is Application, so we can use the other ones for anything. // region used that is used is Application, so we can use the other ones for anything.
KMemoryRegionManager region = MemoryRegions[(int)MemoryRegion.NvServices]; KMemoryRegionManager region = MemoryRegions[(int)MemoryRegion.NvServices];
ulong hidPa = region.Address; ulong hidPa = region.Address;
@ -660,7 +660,7 @@ namespace Ryujinx.HLE.HOS
{ {
if (disposing) if (disposing)
{ {
//Force all threads to exit. // Force all threads to exit.
lock (Processes) lock (Processes)
{ {
foreach (KProcess process in Processes.Values) foreach (KProcess process in Processes.Values)
@ -669,8 +669,8 @@ namespace Ryujinx.HLE.HOS
} }
} }
//It's only safe to release resources once all threads // It's only safe to release resources once all threads
//have exited. // have exited.
ThreadCounter.Signal(); ThreadCounter.Signal();
ThreadCounter.Wait(); ThreadCounter.Wait();

View File

@ -72,7 +72,7 @@ namespace Ryujinx.HLE.HOS.Ipc
break; break;
} }
//TODO: Whats the difference between IpcDuplicateSession/Ex? // TODO: Whats the difference between IpcDuplicateSession/Ex?
case 2: case 2:
case 4: case 4:
{ {
@ -95,7 +95,7 @@ namespace Ryujinx.HLE.HOS.Ipc
} }
else if (request.Type == IpcMessageType.CloseSession) else if (request.Type == IpcMessageType.CloseSession)
{ {
//TODO // TODO
} }
else else
{ {

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