Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d29da11d5f | ||
|
ea07328aea | ||
|
a0b3d82ee0 | ||
|
609de33b0b |
@@ -45,7 +45,6 @@
|
|||||||
<PackageVersion Include="SixLabors.ImageSharp" Version="1.0.4" />
|
<PackageVersion Include="SixLabors.ImageSharp" Version="1.0.4" />
|
||||||
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
|
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
|
||||||
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
||||||
<PackageVersion Include="System.Drawing.Common" Version="8.0.1" />
|
|
||||||
<PackageVersion Include="System.IO.Hashing" Version="8.0.0" />
|
<PackageVersion Include="System.IO.Hashing" Version="8.0.0" />
|
||||||
<PackageVersion Include="System.Management" Version="8.0.0" />
|
<PackageVersion Include="System.Management" Version="8.0.0" />
|
||||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
||||||
|
@@ -10,6 +10,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
|||||||
public readonly List<InstInfo> Instructions;
|
public readonly List<InstInfo> Instructions;
|
||||||
public readonly bool EndsWithBranch;
|
public readonly bool EndsWithBranch;
|
||||||
public readonly bool HasHostCall;
|
public readonly bool HasHostCall;
|
||||||
|
public readonly bool HasHostCallSkipContext;
|
||||||
public readonly bool IsTruncated;
|
public readonly bool IsTruncated;
|
||||||
public readonly bool IsLoopEnd;
|
public readonly bool IsLoopEnd;
|
||||||
public readonly bool IsThumb;
|
public readonly bool IsThumb;
|
||||||
@@ -20,6 +21,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
|||||||
List<InstInfo> instructions,
|
List<InstInfo> instructions,
|
||||||
bool endsWithBranch,
|
bool endsWithBranch,
|
||||||
bool hasHostCall,
|
bool hasHostCall,
|
||||||
|
bool hasHostCallSkipContext,
|
||||||
bool isTruncated,
|
bool isTruncated,
|
||||||
bool isLoopEnd,
|
bool isLoopEnd,
|
||||||
bool isThumb)
|
bool isThumb)
|
||||||
@@ -31,6 +33,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
|||||||
Instructions = instructions;
|
Instructions = instructions;
|
||||||
EndsWithBranch = endsWithBranch;
|
EndsWithBranch = endsWithBranch;
|
||||||
HasHostCall = hasHostCall;
|
HasHostCall = hasHostCall;
|
||||||
|
HasHostCallSkipContext = hasHostCallSkipContext;
|
||||||
IsTruncated = isTruncated;
|
IsTruncated = isTruncated;
|
||||||
IsLoopEnd = isLoopEnd;
|
IsLoopEnd = isLoopEnd;
|
||||||
IsThumb = isThumb;
|
IsThumb = isThumb;
|
||||||
@@ -57,6 +60,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
|||||||
Instructions.GetRange(0, splitIndex),
|
Instructions.GetRange(0, splitIndex),
|
||||||
false,
|
false,
|
||||||
HasHostCall,
|
HasHostCall,
|
||||||
|
HasHostCallSkipContext,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
IsThumb);
|
IsThumb);
|
||||||
@@ -67,6 +71,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
|||||||
Instructions.GetRange(splitIndex, splitCount),
|
Instructions.GetRange(splitIndex, splitCount),
|
||||||
EndsWithBranch,
|
EndsWithBranch,
|
||||||
HasHostCall,
|
HasHostCall,
|
||||||
|
HasHostCallSkipContext,
|
||||||
IsTruncated,
|
IsTruncated,
|
||||||
IsLoopEnd,
|
IsLoopEnd,
|
||||||
IsThumb);
|
IsThumb);
|
||||||
|
@@ -208,6 +208,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
|||||||
InstMeta meta;
|
InstMeta meta;
|
||||||
InstFlags extraFlags = InstFlags.None;
|
InstFlags extraFlags = InstFlags.None;
|
||||||
bool hasHostCall = false;
|
bool hasHostCall = false;
|
||||||
|
bool hasHostCallSkipContext = false;
|
||||||
bool isTruncated = false;
|
bool isTruncated = false;
|
||||||
|
|
||||||
do
|
do
|
||||||
@@ -246,9 +247,17 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
|||||||
meta = InstTableA32<T>.GetMeta(encoding, cpuPreset.Version, cpuPreset.Features);
|
meta = InstTableA32<T>.GetMeta(encoding, cpuPreset.Version, cpuPreset.Features);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (meta.Name.IsSystemOrCall() && !hasHostCall)
|
if (meta.Name.IsSystemOrCall())
|
||||||
{
|
{
|
||||||
hasHostCall = meta.Name.IsCall() || InstEmitSystem.NeedsCall(meta.Name);
|
if (!hasHostCall)
|
||||||
|
{
|
||||||
|
hasHostCall = InstEmitSystem.NeedsCall(meta.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasHostCallSkipContext)
|
||||||
|
{
|
||||||
|
hasHostCallSkipContext = meta.Name.IsCall() || InstEmitSystem.NeedsCallSkipContext(meta.Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
insts.Add(new(encoding, meta.Name, meta.EmitFunc, meta.Flags | extraFlags));
|
insts.Add(new(encoding, meta.Name, meta.EmitFunc, meta.Flags | extraFlags));
|
||||||
@@ -259,8 +268,8 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
|||||||
|
|
||||||
if (!isTruncated && IsBackwardsBranch(meta.Name, encoding))
|
if (!isTruncated && IsBackwardsBranch(meta.Name, encoding))
|
||||||
{
|
{
|
||||||
hasHostCall = true;
|
|
||||||
isLoopEnd = true;
|
isLoopEnd = true;
|
||||||
|
hasHostCallSkipContext = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new(
|
return new(
|
||||||
@@ -269,6 +278,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
|||||||
insts,
|
insts,
|
||||||
!isTruncated,
|
!isTruncated,
|
||||||
hasHostCall,
|
hasHostCall,
|
||||||
|
hasHostCallSkipContext,
|
||||||
isTruncated,
|
isTruncated,
|
||||||
isLoopEnd,
|
isLoopEnd,
|
||||||
isThumb);
|
isThumb);
|
||||||
|
@@ -6,6 +6,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
|||||||
{
|
{
|
||||||
public readonly List<Block> Blocks;
|
public readonly List<Block> Blocks;
|
||||||
public readonly bool HasHostCall;
|
public readonly bool HasHostCall;
|
||||||
|
public readonly bool HasHostCallSkipContext;
|
||||||
public readonly bool IsTruncated;
|
public readonly bool IsTruncated;
|
||||||
|
|
||||||
public MultiBlock(List<Block> blocks)
|
public MultiBlock(List<Block> blocks)
|
||||||
@@ -15,12 +16,14 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
|||||||
Block block = blocks[0];
|
Block block = blocks[0];
|
||||||
|
|
||||||
HasHostCall = block.HasHostCall;
|
HasHostCall = block.HasHostCall;
|
||||||
|
HasHostCallSkipContext = block.HasHostCallSkipContext;
|
||||||
|
|
||||||
for (int index = 1; index < blocks.Count; index++)
|
for (int index = 1; index < blocks.Count; index++)
|
||||||
{
|
{
|
||||||
block = blocks[index];
|
block = blocks[index];
|
||||||
|
|
||||||
HasHostCall |= block.HasHostCall;
|
HasHostCall |= block.HasHostCall;
|
||||||
|
HasHostCallSkipContext |= block.HasHostCallSkipContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
block = blocks[^1];
|
block = blocks[^1];
|
||||||
|
@@ -106,6 +106,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
|||||||
if ((regMask & AbiConstants.ReservedRegsMask) == 0)
|
if ((regMask & AbiConstants.ReservedRegsMask) == 0)
|
||||||
{
|
{
|
||||||
_gprMask |= regMask;
|
_gprMask |= regMask;
|
||||||
|
UsedGprsMask |= regMask;
|
||||||
|
|
||||||
return firstCalleeSaved;
|
return firstCalleeSaved;
|
||||||
}
|
}
|
||||||
|
@@ -305,12 +305,23 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
|||||||
ForceConditionalEnd(cgContext, ref lastCondition, lastConditionIp);
|
ForceConditionalEnd(cgContext, ref lastCondition, lastConditionIp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int reservedStackSize = 0;
|
||||||
|
|
||||||
|
if (multiBlock.HasHostCall)
|
||||||
|
{
|
||||||
|
reservedStackSize = CalculateStackSizeForCallSpill(regAlloc.UsedGprsMask, regAlloc.UsedFpSimdMask, UsablePStateMask);
|
||||||
|
}
|
||||||
|
else if (multiBlock.HasHostCallSkipContext)
|
||||||
|
{
|
||||||
|
reservedStackSize = 2 * sizeof(ulong); // Context and page table pointers.
|
||||||
|
}
|
||||||
|
|
||||||
RegisterSaveRestore rsr = new(
|
RegisterSaveRestore rsr = new(
|
||||||
regAlloc.UsedGprsMask & AbiConstants.GprCalleeSavedRegsMask,
|
regAlloc.UsedGprsMask & AbiConstants.GprCalleeSavedRegsMask,
|
||||||
regAlloc.UsedFpSimdMask & AbiConstants.FpSimdCalleeSavedRegsMask,
|
regAlloc.UsedFpSimdMask & AbiConstants.FpSimdCalleeSavedRegsMask,
|
||||||
OperandType.FP64,
|
OperandType.FP64,
|
||||||
multiBlock.HasHostCall,
|
multiBlock.HasHostCall || multiBlock.HasHostCallSkipContext,
|
||||||
multiBlock.HasHostCall ? CalculateStackSizeForCallSpill(regAlloc.UsedGprsMask, regAlloc.UsedFpSimdMask, UsablePStateMask) : 0);
|
reservedStackSize);
|
||||||
|
|
||||||
TailMerger tailMerger = new();
|
TailMerger tailMerger = new();
|
||||||
|
|
||||||
@@ -596,7 +607,8 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
|||||||
name == InstName.Ldm ||
|
name == InstName.Ldm ||
|
||||||
name == InstName.Ldmda ||
|
name == InstName.Ldmda ||
|
||||||
name == InstName.Ldmdb ||
|
name == InstName.Ldmdb ||
|
||||||
name == InstName.Ldmib)
|
name == InstName.Ldmib ||
|
||||||
|
name == InstName.Pop)
|
||||||
{
|
{
|
||||||
// Arm32 does not have a return instruction, instead returns are implemented
|
// Arm32 does not have a return instruction, instead returns are implemented
|
||||||
// either using BX LR (for leaf functions), or POP { ... PC }.
|
// either using BX LR (for leaf functions), or POP { ... PC }.
|
||||||
@@ -711,7 +723,14 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case BranchType.SyncPoint:
|
case BranchType.SyncPoint:
|
||||||
InstEmitSystem.WriteSyncPoint(context.Writer, context.RegisterAllocator, context.TailMerger, context.GetReservedStackOffset());
|
InstEmitSystem.WriteSyncPoint(
|
||||||
|
context.Writer,
|
||||||
|
ref asm,
|
||||||
|
context.RegisterAllocator,
|
||||||
|
context.TailMerger,
|
||||||
|
context.GetReservedStackOffset(),
|
||||||
|
context.StoreToContext,
|
||||||
|
context.LoadFromContext);
|
||||||
break;
|
break;
|
||||||
case BranchType.SoftwareInterrupt:
|
case BranchType.SoftwareInterrupt:
|
||||||
context.StoreToContext();
|
context.StoreToContext();
|
||||||
|
@@ -199,12 +199,12 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WriteSpillSkipContext(ref Assembler asm, RegisterAllocator regAlloc, int spillOffset)
|
public static void WriteSpillSkipContext(ref Assembler asm, RegisterAllocator regAlloc, int spillOffset)
|
||||||
{
|
{
|
||||||
WriteSpillOrFillSkipContext(ref asm, regAlloc, spillOffset, spill: true);
|
WriteSpillOrFillSkipContext(ref asm, regAlloc, spillOffset, spill: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WriteFillSkipContext(ref Assembler asm, RegisterAllocator regAlloc, int spillOffset)
|
public static void WriteFillSkipContext(ref Assembler asm, RegisterAllocator regAlloc, int spillOffset)
|
||||||
{
|
{
|
||||||
WriteSpillOrFillSkipContext(ref asm, regAlloc, spillOffset, spill: false);
|
WriteSpillOrFillSkipContext(ref asm, regAlloc, spillOffset, spill: false);
|
||||||
}
|
}
|
||||||
|
@@ -354,11 +354,18 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
|||||||
// All instructions that might do a host call should be included here.
|
// All instructions that might do a host call should be included here.
|
||||||
// That is required to reserve space on the stack for caller saved registers.
|
// That is required to reserve space on the stack for caller saved registers.
|
||||||
|
|
||||||
|
return name == InstName.Mrrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool NeedsCallSkipContext(InstName name)
|
||||||
|
{
|
||||||
|
// All instructions that might do a host call should be included here.
|
||||||
|
// That is required to reserve space on the stack for caller saved registers.
|
||||||
|
|
||||||
switch (name)
|
switch (name)
|
||||||
{
|
{
|
||||||
case InstName.Mcr:
|
case InstName.Mcr:
|
||||||
case InstName.Mrc:
|
case InstName.Mrc:
|
||||||
case InstName.Mrrc:
|
|
||||||
case InstName.Svc:
|
case InstName.Svc:
|
||||||
case InstName.Udf:
|
case InstName.Udf:
|
||||||
return true;
|
return true;
|
||||||
@@ -372,7 +379,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
|||||||
Assembler asm = new(writer);
|
Assembler asm = new(writer);
|
||||||
|
|
||||||
WriteCall(ref asm, regAlloc, GetBkptHandlerPtr(), skipContext: true, spillBaseOffset, null, pc, imm);
|
WriteCall(ref asm, regAlloc, GetBkptHandlerPtr(), skipContext: true, spillBaseOffset, null, pc, imm);
|
||||||
WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: true, spillBaseOffset);
|
WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, spillBaseOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void WriteSvc(CodeWriter writer, RegisterAllocator regAlloc, TailMerger tailMerger, int spillBaseOffset, uint pc, uint svcId)
|
public static void WriteSvc(CodeWriter writer, RegisterAllocator regAlloc, TailMerger tailMerger, int spillBaseOffset, uint pc, uint svcId)
|
||||||
@@ -380,7 +387,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
|||||||
Assembler asm = new(writer);
|
Assembler asm = new(writer);
|
||||||
|
|
||||||
WriteCall(ref asm, regAlloc, GetSvcHandlerPtr(), skipContext: true, spillBaseOffset, null, pc, svcId);
|
WriteCall(ref asm, regAlloc, GetSvcHandlerPtr(), skipContext: true, spillBaseOffset, null, pc, svcId);
|
||||||
WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: true, spillBaseOffset);
|
WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, spillBaseOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void WriteUdf(CodeWriter writer, RegisterAllocator regAlloc, TailMerger tailMerger, int spillBaseOffset, uint pc, uint imm)
|
public static void WriteUdf(CodeWriter writer, RegisterAllocator regAlloc, TailMerger tailMerger, int spillBaseOffset, uint pc, uint imm)
|
||||||
@@ -388,7 +395,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
|||||||
Assembler asm = new(writer);
|
Assembler asm = new(writer);
|
||||||
|
|
||||||
WriteCall(ref asm, regAlloc, GetUdfHandlerPtr(), skipContext: true, spillBaseOffset, null, pc, imm);
|
WriteCall(ref asm, regAlloc, GetUdfHandlerPtr(), skipContext: true, spillBaseOffset, null, pc, imm);
|
||||||
WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: true, spillBaseOffset);
|
WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, spillBaseOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void WriteReadCntpct(CodeWriter writer, RegisterAllocator regAlloc, int spillBaseOffset, int rt, int rt2)
|
public static void WriteReadCntpct(CodeWriter writer, RegisterAllocator regAlloc, int spillBaseOffset, int rt, int rt2)
|
||||||
@@ -422,14 +429,14 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
|||||||
WriteFill(ref asm, regAlloc, resultMask, skipContext: false, spillBaseOffset, tempRegister);
|
WriteFill(ref asm, regAlloc, resultMask, skipContext: false, spillBaseOffset, tempRegister);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void WriteSyncPoint(CodeWriter writer, RegisterAllocator regAlloc, TailMerger tailMerger, int spillBaseOffset)
|
public static void WriteSyncPoint(
|
||||||
{
|
CodeWriter writer,
|
||||||
Assembler asm = new(writer);
|
ref Assembler asm,
|
||||||
|
RegisterAllocator regAlloc,
|
||||||
WriteSyncPoint(writer, ref asm, regAlloc, tailMerger, skipContext: false, spillBaseOffset);
|
TailMerger tailMerger,
|
||||||
}
|
int spillBaseOffset,
|
||||||
|
Action storeToContext = null,
|
||||||
private static void WriteSyncPoint(CodeWriter writer, ref Assembler asm, RegisterAllocator regAlloc, TailMerger tailMerger, bool skipContext, int spillBaseOffset)
|
Action loadFromContext = null)
|
||||||
{
|
{
|
||||||
int tempRegister = regAlloc.AllocateTempGprRegister();
|
int tempRegister = regAlloc.AllocateTempGprRegister();
|
||||||
|
|
||||||
@@ -440,7 +447,8 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
|||||||
int branchIndex = writer.InstructionPointer;
|
int branchIndex = writer.InstructionPointer;
|
||||||
asm.Cbnz(rt, 0);
|
asm.Cbnz(rt, 0);
|
||||||
|
|
||||||
WriteSpill(ref asm, regAlloc, 1u << tempRegister, skipContext, spillBaseOffset, tempRegister);
|
storeToContext?.Invoke();
|
||||||
|
WriteSpill(ref asm, regAlloc, 1u << tempRegister, skipContext: true, spillBaseOffset, tempRegister);
|
||||||
|
|
||||||
Operand rn = Register(tempRegister == 0 ? 1 : 0);
|
Operand rn = Register(tempRegister == 0 ? 1 : 0);
|
||||||
|
|
||||||
@@ -449,7 +457,8 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
|||||||
|
|
||||||
tailMerger.AddConditionalZeroReturn(writer, asm, Register(0, OperandType.I32));
|
tailMerger.AddConditionalZeroReturn(writer, asm, Register(0, OperandType.I32));
|
||||||
|
|
||||||
WriteFill(ref asm, regAlloc, 1u << tempRegister, skipContext, spillBaseOffset, tempRegister);
|
WriteFill(ref asm, regAlloc, 1u << tempRegister, skipContext: true, spillBaseOffset, tempRegister);
|
||||||
|
loadFromContext?.Invoke();
|
||||||
|
|
||||||
asm.LdrRiUn(rt, Register(regAlloc.FixedContextRegister), NativeContextOffsets.CounterOffset);
|
asm.LdrRiUn(rt, Register(regAlloc.FixedContextRegister), NativeContextOffsets.CounterOffset);
|
||||||
|
|
||||||
@@ -514,18 +523,31 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
|||||||
|
|
||||||
private static void WriteSpill(ref Assembler asm, RegisterAllocator regAlloc, uint exceptMask, bool skipContext, int spillOffset, int tempRegister)
|
private static void WriteSpill(ref Assembler asm, RegisterAllocator regAlloc, uint exceptMask, bool skipContext, int spillOffset, int tempRegister)
|
||||||
{
|
{
|
||||||
WriteSpillOrFill(ref asm, regAlloc, skipContext, exceptMask, spillOffset, tempRegister, spill: true);
|
if (skipContext)
|
||||||
|
{
|
||||||
|
InstEmitFlow.WriteSpillSkipContext(ref asm, regAlloc, spillOffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteSpillOrFill(ref asm, regAlloc, exceptMask, spillOffset, tempRegister, spill: true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WriteFill(ref Assembler asm, RegisterAllocator regAlloc, uint exceptMask, bool skipContext, int spillOffset, int tempRegister)
|
private static void WriteFill(ref Assembler asm, RegisterAllocator regAlloc, uint exceptMask, bool skipContext, int spillOffset, int tempRegister)
|
||||||
{
|
{
|
||||||
WriteSpillOrFill(ref asm, regAlloc, skipContext, exceptMask, spillOffset, tempRegister, spill: false);
|
if (skipContext)
|
||||||
|
{
|
||||||
|
InstEmitFlow.WriteFillSkipContext(ref asm, regAlloc, spillOffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteSpillOrFill(ref asm, regAlloc, exceptMask, spillOffset, tempRegister, spill: false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WriteSpillOrFill(
|
private static void WriteSpillOrFill(
|
||||||
ref Assembler asm,
|
ref Assembler asm,
|
||||||
RegisterAllocator regAlloc,
|
RegisterAllocator regAlloc,
|
||||||
bool skipContext,
|
|
||||||
uint exceptMask,
|
uint exceptMask,
|
||||||
int spillOffset,
|
int spillOffset,
|
||||||
int tempRegister,
|
int tempRegister,
|
||||||
@@ -533,11 +555,6 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
|||||||
{
|
{
|
||||||
uint gprMask = regAlloc.UsedGprsMask & ~(AbiConstants.GprCalleeSavedRegsMask | exceptMask);
|
uint gprMask = regAlloc.UsedGprsMask & ~(AbiConstants.GprCalleeSavedRegsMask | exceptMask);
|
||||||
|
|
||||||
if (skipContext)
|
|
||||||
{
|
|
||||||
gprMask &= ~Compiler.UsableGprsMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!spill)
|
if (!spill)
|
||||||
{
|
{
|
||||||
// We must reload the status register before reloading the GPRs,
|
// We must reload the status register before reloading the GPRs,
|
||||||
@@ -600,11 +617,6 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
|||||||
|
|
||||||
uint fpSimdMask = regAlloc.UsedFpSimdMask;
|
uint fpSimdMask = regAlloc.UsedFpSimdMask;
|
||||||
|
|
||||||
if (skipContext)
|
|
||||||
{
|
|
||||||
fpSimdMask &= ~Compiler.UsableFpSimdMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (fpSimdMask != 0)
|
while (fpSimdMask != 0)
|
||||||
{
|
{
|
||||||
int reg = BitOperations.TrailingZeroCount(fpSimdMask);
|
int reg = BitOperations.TrailingZeroCount(fpSimdMask);
|
||||||
|
@@ -147,6 +147,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
A1B5G5R5Unorm,
|
A1B5G5R5Unorm,
|
||||||
B8G8R8A8Unorm,
|
B8G8R8A8Unorm,
|
||||||
B8G8R8A8Srgb,
|
B8G8R8A8Srgb,
|
||||||
|
B10G10R10A2Unorm,
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FormatExtensions
|
public static class FormatExtensions
|
||||||
@@ -260,6 +261,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
case Format.R10G10B10A2Sint:
|
case Format.R10G10B10A2Sint:
|
||||||
case Format.R10G10B10A2Uscaled:
|
case Format.R10G10B10A2Uscaled:
|
||||||
case Format.R10G10B10A2Sscaled:
|
case Format.R10G10B10A2Sscaled:
|
||||||
|
case Format.B10G10R10A2Unorm:
|
||||||
return 4;
|
return 4;
|
||||||
|
|
||||||
case Format.S8Uint:
|
case Format.S8Uint:
|
||||||
@@ -451,6 +453,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
case Format.R32G32Uint:
|
case Format.R32G32Uint:
|
||||||
case Format.B8G8R8A8Unorm:
|
case Format.B8G8R8A8Unorm:
|
||||||
case Format.B8G8R8A8Srgb:
|
case Format.B8G8R8A8Srgb:
|
||||||
|
case Format.B10G10R10A2Unorm:
|
||||||
case Format.R10G10B10A2Unorm:
|
case Format.R10G10B10A2Unorm:
|
||||||
case Format.R10G10B10A2Uint:
|
case Format.R10G10B10A2Uint:
|
||||||
case Format.R8G8B8A8Unorm:
|
case Format.R8G8B8A8Unorm:
|
||||||
@@ -611,6 +614,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
case Format.B5G5R5A1Unorm:
|
case Format.B5G5R5A1Unorm:
|
||||||
case Format.B8G8R8A8Unorm:
|
case Format.B8G8R8A8Unorm:
|
||||||
case Format.B8G8R8A8Srgb:
|
case Format.B8G8R8A8Srgb:
|
||||||
|
case Format.B10G10R10A2Unorm:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -37,6 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Types
|
|||||||
R16G16Sint = 0xdc,
|
R16G16Sint = 0xdc,
|
||||||
R16G16Uint = 0xdd,
|
R16G16Uint = 0xdd,
|
||||||
R16G16Float = 0xde,
|
R16G16Float = 0xde,
|
||||||
|
B10G10R10A2Unorm = 0xdf,
|
||||||
R11G11B10Float = 0xe0,
|
R11G11B10Float = 0xe0,
|
||||||
R32Sint = 0xe3,
|
R32Sint = 0xe3,
|
||||||
R32Uint = 0xe4,
|
R32Uint = 0xe4,
|
||||||
@@ -104,6 +105,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Types
|
|||||||
ColorFormat.R16G16Sint => new FormatInfo(Format.R16G16Sint, 1, 1, 4, 2),
|
ColorFormat.R16G16Sint => new FormatInfo(Format.R16G16Sint, 1, 1, 4, 2),
|
||||||
ColorFormat.R16G16Uint => new FormatInfo(Format.R16G16Uint, 1, 1, 4, 2),
|
ColorFormat.R16G16Uint => new FormatInfo(Format.R16G16Uint, 1, 1, 4, 2),
|
||||||
ColorFormat.R16G16Float => new FormatInfo(Format.R16G16Float, 1, 1, 4, 2),
|
ColorFormat.R16G16Float => new FormatInfo(Format.R16G16Float, 1, 1, 4, 2),
|
||||||
|
ColorFormat.B10G10R10A2Unorm => new FormatInfo(Format.B10G10R10A2Unorm, 1, 1, 4, 4),
|
||||||
ColorFormat.R11G11B10Float => new FormatInfo(Format.R11G11B10Float, 1, 1, 4, 3),
|
ColorFormat.R11G11B10Float => new FormatInfo(Format.R11G11B10Float, 1, 1, 4, 3),
|
||||||
ColorFormat.R32Sint => new FormatInfo(Format.R32Sint, 1, 1, 4, 1),
|
ColorFormat.R32Sint => new FormatInfo(Format.R32Sint, 1, 1, 4, 1),
|
||||||
ColorFormat.R32Uint => new FormatInfo(Format.R32Uint, 1, 1, 4, 1),
|
ColorFormat.R32Uint => new FormatInfo(Format.R32Uint, 1, 1, 4, 1),
|
||||||
|
@@ -161,6 +161,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
Add(Format.A1B5G5R5Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort5551));
|
Add(Format.A1B5G5R5Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort5551));
|
||||||
Add(Format.B8G8R8A8Unorm, new FormatInfo(4, true, false, All.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
Add(Format.B8G8R8A8Unorm, new FormatInfo(4, true, false, All.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
||||||
Add(Format.B8G8R8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
Add(Format.B8G8R8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
||||||
|
Add(Format.B10G10R10A2Unorm, new FormatInfo(4, false, false, All.Rgb10A2, PixelFormat.Rgba, PixelType.UnsignedInt2101010Reversed));
|
||||||
|
|
||||||
Add(Format.R8Unorm, SizedInternalFormat.R8);
|
Add(Format.R8Unorm, SizedInternalFormat.R8);
|
||||||
Add(Format.R8Uint, SizedInternalFormat.R8ui);
|
Add(Format.R8Uint, SizedInternalFormat.R8ui);
|
||||||
|
@@ -8,7 +8,6 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Host1x\Ryujinx.Graphics.Host1x.csproj" />
|
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@@ -161,6 +161,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Add(Format.A1B5G5R5Unorm, VkFormat.R5G5B5A1UnormPack16);
|
Add(Format.A1B5G5R5Unorm, VkFormat.R5G5B5A1UnormPack16);
|
||||||
Add(Format.B8G8R8A8Unorm, VkFormat.B8G8R8A8Unorm);
|
Add(Format.B8G8R8A8Unorm, VkFormat.B8G8R8A8Unorm);
|
||||||
Add(Format.B8G8R8A8Srgb, VkFormat.B8G8R8A8Srgb);
|
Add(Format.B8G8R8A8Srgb, VkFormat.B8G8R8A8Srgb);
|
||||||
|
Add(Format.B10G10R10A2Unorm, VkFormat.A2R10G10B10UnormPack32);
|
||||||
#pragma warning restore IDE0055
|
#pragma warning restore IDE0055
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,15 +2,13 @@ using Ryujinx.Common;
|
|||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using ShellLink;
|
using ShellLink;
|
||||||
using SixLabors.ImageSharp;
|
using SixLabors.ImageSharp;
|
||||||
|
using SixLabors.ImageSharp.Formats.Png;
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
|
using SixLabors.ImageSharp.Processing;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
|
||||||
using System.Drawing.Drawing2D;
|
|
||||||
using System.Drawing.Imaging;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
using Image = System.Drawing.Image;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ui.Common.Helper
|
namespace Ryujinx.Ui.Common.Helper
|
||||||
{
|
{
|
||||||
@@ -23,12 +21,9 @@ namespace Ryujinx.Ui.Common.Helper
|
|||||||
iconPath += ".ico";
|
iconPath += ".ico";
|
||||||
|
|
||||||
MemoryStream iconDataStream = new(iconData);
|
MemoryStream iconDataStream = new(iconData);
|
||||||
using Image image = Image.FromStream(iconDataStream);
|
var image = Image.Load(iconDataStream);
|
||||||
using Bitmap bitmap = new(128, 128);
|
image.Mutate(x => x.Resize(128, 128));
|
||||||
using System.Drawing.Graphics graphic = System.Drawing.Graphics.FromImage(bitmap);
|
SaveBitmapAsIcon(image, iconPath);
|
||||||
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
|
||||||
graphic.DrawImage(image, 0, 0, 128, 128);
|
|
||||||
SaveBitmapAsIcon(bitmap, iconPath);
|
|
||||||
|
|
||||||
var shortcut = Shortcut.CreateShortcut(basePath, GetArgsString(applicationFilePath), iconPath, 0);
|
var shortcut = Shortcut.CreateShortcut(basePath, GetArgsString(applicationFilePath), iconPath, 0);
|
||||||
shortcut.StringData.NameString = cleanedAppName;
|
shortcut.StringData.NameString = cleanedAppName;
|
||||||
@@ -42,7 +37,7 @@ namespace Ryujinx.Ui.Common.Helper
|
|||||||
var desktopFile = EmbeddedResources.ReadAllText("Ryujinx.Ui.Common/shortcut-template.desktop");
|
var desktopFile = EmbeddedResources.ReadAllText("Ryujinx.Ui.Common/shortcut-template.desktop");
|
||||||
iconPath += ".png";
|
iconPath += ".png";
|
||||||
|
|
||||||
var image = SixLabors.ImageSharp.Image.Load<Rgba32>(iconData);
|
var image = Image.Load<Rgba32>(iconData);
|
||||||
image.SaveAsPng(iconPath);
|
image.SaveAsPng(iconPath);
|
||||||
|
|
||||||
using StreamWriter outputFile = new(Path.Combine(desktopPath, cleanedAppName + ".desktop"));
|
using StreamWriter outputFile = new(Path.Combine(desktopPath, cleanedAppName + ".desktop"));
|
||||||
@@ -83,7 +78,7 @@ namespace Ryujinx.Ui.Common.Helper
|
|||||||
}
|
}
|
||||||
|
|
||||||
const string IconName = "icon.png";
|
const string IconName = "icon.png";
|
||||||
var image = SixLabors.ImageSharp.Image.Load<Rgba32>(iconData);
|
var image = Image.Load<Rgba32>(iconData);
|
||||||
image.SaveAsPng(Path.Combine(resourceFolderPath, IconName));
|
image.SaveAsPng(Path.Combine(resourceFolderPath, IconName));
|
||||||
|
|
||||||
// plist file
|
// plist file
|
||||||
@@ -147,7 +142,7 @@ namespace Ryujinx.Ui.Common.Helper
|
|||||||
/// <param name="source">The source bitmap image that will be saved as an .ico file</param>
|
/// <param name="source">The source bitmap image that will be saved as an .ico file</param>
|
||||||
/// <param name="filePath">The location that the new .ico file will be saved too (Make sure to include '.ico' in the path).</param>
|
/// <param name="filePath">The location that the new .ico file will be saved too (Make sure to include '.ico' in the path).</param>
|
||||||
[SupportedOSPlatform("windows")]
|
[SupportedOSPlatform("windows")]
|
||||||
private static void SaveBitmapAsIcon(Bitmap source, string filePath)
|
private static void SaveBitmapAsIcon(Image source, string filePath)
|
||||||
{
|
{
|
||||||
// Code Modified From https://stackoverflow.com/a/11448060/368354 by Benlitz
|
// Code Modified From https://stackoverflow.com/a/11448060/368354 by Benlitz
|
||||||
byte[] header = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 32, 0, 0, 0, 0, 0, 22, 0, 0, 0 };
|
byte[] header = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 32, 0, 0, 0, 0, 0, 22, 0, 0, 0 };
|
||||||
@@ -155,7 +150,7 @@ namespace Ryujinx.Ui.Common.Helper
|
|||||||
|
|
||||||
fs.Write(header);
|
fs.Write(header);
|
||||||
// Writing actual data
|
// Writing actual data
|
||||||
source.Save(fs, ImageFormat.Png);
|
source.Save(fs, PngFormat.Instance);
|
||||||
// Getting data length (file length minus header)
|
// Getting data length (file length minus header)
|
||||||
long dataLength = fs.Length - header.Length;
|
long dataLength = fs.Length - header.Length;
|
||||||
// Write it in the correct place
|
// Write it in the correct place
|
||||||
|
@@ -57,7 +57,6 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DiscordRichPresence" />
|
<PackageReference Include="DiscordRichPresence" />
|
||||||
<PackageReference Include="securifybv.ShellLink" />
|
<PackageReference Include="securifybv.ShellLink" />
|
||||||
<PackageReference Include="System.Drawing.Common" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
Reference in New Issue
Block a user