aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2020-10-12 21:46:04 -0300
committerGitHub <noreply@github.com>2020-10-12 21:46:04 -0300
commite4777717cdf70c61365494cdb91568172fa5bfe8 (patch)
tree40951b868041e7fbab2047ec56ef4ebc3edd2cd6
parentb066cfc1a3e31bf7197ddbd0f4d774b886cd9d65 (diff)
Implement LEA.HI shader instruction (#1609)
-rw-r--r--Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs2
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs45
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs10
3 files changed, 57 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs
index eef36a95..edbd8bb2 100644
--- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs
@@ -179,6 +179,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
Set("010010111101xx", InstEmit.Lea, typeof(OpCodeAluCbuf));
Set("0011011x11010x", InstEmit.Lea, typeof(OpCodeAluImm));
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("0011100001000x", InstEmit.Lop, typeof(OpCodeLopImm));
Set("000001xxxxxxxx", InstEmit.Lop, typeof(OpCodeLopImm32));
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs
index b883edc1..5d00adb5 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs
@@ -405,6 +405,51 @@ namespace Ryujinx.Graphics.Shader.Instructions
// 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)
{
IOpCodeLop op = (IOpCodeLop)context.CurrOp;
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs
index 588ec216..7fe969a0 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs
@@ -100,5 +100,15 @@ namespace Ryujinx.Graphics.Shader.Instructions
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;
+ }
}
} \ No newline at end of file