mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-03-26 13:00:17 +00:00
78 lines
3.1 KiB
C#
78 lines
3.1 KiB
C#
|
using Ryujinx.Cpu.LightningJit.CodeGen;
|
||
|
|
||
|
namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
||
|
{
|
||
|
static class InstEmitNeonSystem
|
||
|
{
|
||
|
public static void Vmrs(CodeGenContext context, uint rt, uint reg)
|
||
|
{
|
||
|
if (context.ConsumeSkipNextInstruction())
|
||
|
{
|
||
|
// This case means that we managed to combine a VCMP and VMRS instruction,
|
||
|
// so we have nothing to do here as FCMP/FCMPE already set PSTATE.NZCV.
|
||
|
context.SetNzcvModified();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (reg == 1)
|
||
|
{
|
||
|
// FPSCR
|
||
|
|
||
|
Operand ctx = InstEmitSystem.Register(context.RegisterAllocator.FixedContextRegister);
|
||
|
|
||
|
if (rt == RegisterUtils.PcRegister)
|
||
|
{
|
||
|
using ScopedRegister fpsrRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped();
|
||
|
|
||
|
context.Arm64Assembler.LdrRiUn(fpsrRegister.Operand, ctx, NativeContextOffsets.FpFlagsBaseOffset);
|
||
|
context.Arm64Assembler.Lsr(fpsrRegister.Operand, fpsrRegister.Operand, InstEmitCommon.Const(28));
|
||
|
|
||
|
InstEmitCommon.RestoreNzcvFlags(context, fpsrRegister.Operand);
|
||
|
|
||
|
context.SetNzcvModified();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// FPSCR is a combination of the FPCR and FPSR registers.
|
||
|
// We also need to set the FPSR NZCV bits that no longer exist on AArch64.
|
||
|
|
||
|
using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped();
|
||
|
|
||
|
Operand rtOperand = InstEmitCommon.GetOutputGpr(context, rt);
|
||
|
|
||
|
context.Arm64Assembler.MrsFpsr(rtOperand);
|
||
|
context.Arm64Assembler.MrsFpcr(tempRegister.Operand);
|
||
|
context.Arm64Assembler.Orr(rtOperand, rtOperand, tempRegister.Operand);
|
||
|
context.Arm64Assembler.LdrRiUn(tempRegister.Operand, ctx, NativeContextOffsets.FpFlagsBaseOffset);
|
||
|
context.Arm64Assembler.Bfc(tempRegister.Operand, 0, 28);
|
||
|
context.Arm64Assembler.Orr(rtOperand, rtOperand, tempRegister.Operand);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Operand rtOperand = InstEmitCommon.GetOutputGpr(context, rt);
|
||
|
|
||
|
context.Arm64Assembler.Mov(rtOperand, 0u);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void Vmsr(CodeGenContext context, uint rt, uint reg)
|
||
|
{
|
||
|
if (reg == 1)
|
||
|
{
|
||
|
// FPSCR
|
||
|
|
||
|
// TODO: Do not set bits related to features that are not supported (like FP16)?
|
||
|
|
||
|
Operand ctx = InstEmitSystem.Register(context.RegisterAllocator.FixedContextRegister);
|
||
|
Operand rtOperand = InstEmitCommon.GetInputGpr(context, rt);
|
||
|
|
||
|
context.Arm64Assembler.MsrFpcr(rtOperand);
|
||
|
context.Arm64Assembler.MsrFpsr(rtOperand);
|
||
|
context.Arm64Assembler.StrRiUn(rtOperand, ctx, NativeContextOffsets.FpFlagsBaseOffset);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|