mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2024-12-23 16:45:35 +00:00
Implement LEA.HI shader instruction (#1609)
This commit is contained in:
parent
b066cfc1a3
commit
e4777717cd
|
@ -179,6 +179,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
Set("010010111101xx", InstEmit.Lea, typeof(OpCodeAluCbuf));
|
Set("010010111101xx", InstEmit.Lea, typeof(OpCodeAluCbuf));
|
||||||
Set("0011011x11010x", InstEmit.Lea, typeof(OpCodeAluImm));
|
Set("0011011x11010x", InstEmit.Lea, typeof(OpCodeAluImm));
|
||||||
Set("0101101111010x", InstEmit.Lea, typeof(OpCodeAluReg));
|
Set("0101101111010x", InstEmit.Lea, typeof(OpCodeAluReg));
|
||||||
|
Set("000110xxxxxxxx", InstEmit.Lea_Hi, typeof(OpCodeAluCbuf));
|
||||||
|
Set("0101101111011x", InstEmit.Lea_Hi, typeof(OpCodeAluReg));
|
||||||
Set("0100110001000x", InstEmit.Lop, typeof(OpCodeLopCbuf));
|
Set("0100110001000x", InstEmit.Lop, typeof(OpCodeLopCbuf));
|
||||||
Set("0011100001000x", InstEmit.Lop, typeof(OpCodeLopImm));
|
Set("0011100001000x", InstEmit.Lop, typeof(OpCodeLopImm));
|
||||||
Set("000001xxxxxxxx", InstEmit.Lop, typeof(OpCodeLopImm32));
|
Set("000001xxxxxxxx", InstEmit.Lop, typeof(OpCodeLopImm32));
|
||||||
|
|
|
@ -405,6 +405,51 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
// TODO: CC, X
|
// TODO: CC, X
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Lea_Hi(EmitterContext context)
|
||||||
|
{
|
||||||
|
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
|
||||||
|
|
||||||
|
bool isReg = op is OpCodeAluReg;
|
||||||
|
bool negateA;
|
||||||
|
int shift;
|
||||||
|
|
||||||
|
if (isReg)
|
||||||
|
{
|
||||||
|
negateA = op.RawOpCode.Extract(37);
|
||||||
|
shift = op.RawOpCode.Extract(28, 5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
negateA = op.RawOpCode.Extract(56);
|
||||||
|
shift = op.RawOpCode.Extract(51, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand srcA = GetSrcA(context);
|
||||||
|
Operand srcB = GetSrcB(context);
|
||||||
|
Operand srcC = GetSrcC(context);
|
||||||
|
|
||||||
|
Operand aLow = context.ShiftLeft(srcA, Const(shift));
|
||||||
|
Operand aHigh = shift == 0 ? Const(0) : context.ShiftRightU32(srcA, Const(32 - shift));
|
||||||
|
aHigh = context.BitwiseOr(aHigh, context.ShiftLeft(srcC, Const(shift)));
|
||||||
|
|
||||||
|
if (negateA)
|
||||||
|
{
|
||||||
|
// Perform 64-bit negation by doing bitwise not of the value,
|
||||||
|
// then adding 1 and carrying over from low to high.
|
||||||
|
aLow = context.BitwiseNot(aLow);
|
||||||
|
aHigh = context.BitwiseNot(aHigh);
|
||||||
|
|
||||||
|
aLow = AddWithCarry(context, aLow, Const(1), out Operand aLowCOut);
|
||||||
|
aHigh = context.IAdd(aHigh, aLowCOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand res = context.IAdd(aHigh, srcB);
|
||||||
|
|
||||||
|
context.Copy(GetDest(context), res);
|
||||||
|
|
||||||
|
// TODO: CC, X
|
||||||
|
}
|
||||||
|
|
||||||
public static void Lop(EmitterContext context)
|
public static void Lop(EmitterContext context)
|
||||||
{
|
{
|
||||||
IOpCodeLop op = (IOpCodeLop)context.CurrOp;
|
IOpCodeLop op = (IOpCodeLop)context.CurrOp;
|
||||||
|
|
|
@ -100,5 +100,15 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
context.Copy(GetNF(), context.FPCompareLess (dest, zero, fpType));
|
context.Copy(GetNF(), context.FPCompareLess (dest, zero, fpType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Operand AddWithCarry(EmitterContext context, Operand lhs, Operand rhs, out Operand carryOut)
|
||||||
|
{
|
||||||
|
Operand result = context.IAdd(lhs, rhs);
|
||||||
|
|
||||||
|
// C = Rd < Rn
|
||||||
|
carryOut = context.INegate(context.ICompareLessUnsigned(result, lhs));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue