| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869 |
- using Ryujinx.Graphics.Shader.Decoders;
- using Ryujinx.Graphics.Shader.IntermediateRepresentation;
- using Ryujinx.Graphics.Shader.Translation;
- using System;
- using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
- using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
- using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
- namespace Ryujinx.Graphics.Shader.Instructions
- {
- static partial class InstEmit
- {
- public static void Bfe(EmitterContext context)
- {
- OpCodeAlu op = (OpCodeAlu)context.CurrOp;
- bool isReverse = op.RawOpCode.Extract(40);
- bool isSigned = op.RawOpCode.Extract(48);
- Operand srcA = GetSrcA(context);
- Operand srcB = GetSrcB(context);
- if (isReverse)
- {
- srcA = context.BitfieldReverse(srcA);
- }
- Operand position = context.BitwiseAnd(srcB, Const(0xff));
- Operand size = context.BitfieldExtractU32(srcB, Const(8), Const(8));
- Operand res = isSigned
- ? context.BitfieldExtractS32(srcA, position, size)
- : context.BitfieldExtractU32(srcA, position, size);
- context.Copy(GetDest(context), res);
- // TODO: CC, X, corner cases
- }
- public static void Bfi(EmitterContext context)
- {
- OpCodeAlu op = (OpCodeAlu)context.CurrOp;
- Operand srcA = GetSrcA(context);
- Operand srcB = GetSrcB(context);
- Operand srcC = GetSrcC(context);
- Operand position = context.BitwiseAnd(srcB, Const(0xff));
- Operand size = context.BitfieldExtractU32(srcB, Const(8), Const(8));
- Operand res = context.BitfieldInsert(srcC, srcA, position, size);
- context.Copy(GetDest(context), res);
- }
- public static void Csetp(EmitterContext context)
- {
- OpCodePset op = (OpCodePset)context.CurrOp;
- // TODO: Implement that properly
- Operand p0Res = Const(IrConsts.True);
- Operand p1Res = context.BitwiseNot(p0Res);
- Operand pred = GetPredicate39(context);
- p0Res = GetPredLogicalOp(context, op.LogicalOp, p0Res, pred);
- p1Res = GetPredLogicalOp(context, op.LogicalOp, p1Res, pred);
- context.Copy(Register(op.Predicate3), p0Res);
- context.Copy(Register(op.Predicate0), p1Res);
- }
- public static void Flo(EmitterContext context)
- {
- OpCodeAlu op = (OpCodeAlu)context.CurrOp;
- bool invert = op.RawOpCode.Extract(40);
- bool countZeros = op.RawOpCode.Extract(41);
- bool isSigned = op.RawOpCode.Extract(48);
- Operand srcB = context.BitwiseNot(GetSrcB(context), invert);
- Operand res = isSigned
- ? context.FindFirstSetS32(srcB)
- : context.FindFirstSetU32(srcB);
- if (countZeros)
- {
- res = context.BitwiseExclusiveOr(res, Const(31));
- }
- context.Copy(GetDest(context), res);
- }
- public static void Iadd(EmitterContext context)
- {
- OpCodeAlu op = (OpCodeAlu)context.CurrOp;
- bool negateA = false, negateB = false;
- if (!(op is OpCodeAluImm32))
- {
- negateB = op.RawOpCode.Extract(48);
- negateA = op.RawOpCode.Extract(49);
- }
- else
- {
- // TODO: Other IADD32I variant without the negate.
- negateA = op.RawOpCode.Extract(56);
- }
- Operand srcA = context.INegate(GetSrcA(context), negateA);
- Operand srcB = context.INegate(GetSrcB(context), negateB);
- Operand res = context.IAdd(srcA, srcB);
- bool isSubtraction = negateA || negateB;
- if (op.Extended)
- {
- // Add carry, or subtract borrow.
- res = context.IAdd(res, isSubtraction
- ? context.BitwiseNot(GetCF())
- : context.BitwiseAnd(GetCF(), Const(1)));
- }
- SetIaddFlags(context, res, srcA, srcB, op.SetCondCode, op.Extended, isSubtraction);
- context.Copy(GetDest(context), res);
- }
- public static void Iadd3(EmitterContext context)
- {
- OpCodeAlu op = (OpCodeAlu)context.CurrOp;
- IntegerHalfPart partC = (IntegerHalfPart)op.RawOpCode.Extract(31, 2);
- IntegerHalfPart partB = (IntegerHalfPart)op.RawOpCode.Extract(33, 2);
- IntegerHalfPart partA = (IntegerHalfPart)op.RawOpCode.Extract(35, 2);
- IntegerShift mode = (IntegerShift)op.RawOpCode.Extract(37, 2);
- bool negateC = op.RawOpCode.Extract(49);
- bool negateB = op.RawOpCode.Extract(50);
- bool negateA = op.RawOpCode.Extract(51);
- Operand Extend(Operand src, IntegerHalfPart part)
- {
- if (!(op is OpCodeAluReg) || part == IntegerHalfPart.B32)
- {
- return src;
- }
- if (part == IntegerHalfPart.H0)
- {
- return context.BitwiseAnd(src, Const(0xffff));
- }
- else if (part == IntegerHalfPart.H1)
- {
- return context.ShiftRightU32(src, Const(16));
- }
- else
- {
- // TODO: Warning.
- }
- return src;
- }
- Operand srcA = context.INegate(Extend(GetSrcA(context), partA), negateA);
- Operand srcB = context.INegate(Extend(GetSrcB(context), partB), negateB);
- Operand srcC = context.INegate(Extend(GetSrcC(context), partC), negateC);
- Operand res = context.IAdd(srcA, srcB);
- if (op is OpCodeAluReg && mode != IntegerShift.NoShift)
- {
- if (mode == IntegerShift.ShiftLeft)
- {
- res = context.ShiftLeft(res, Const(16));
- }
- else if (mode == IntegerShift.ShiftRight)
- {
- res = context.ShiftRightU32(res, Const(16));
- }
- else
- {
- // TODO: Warning.
- }
- }
- res = context.IAdd(res, srcC);
- context.Copy(GetDest(context), res);
- // TODO: CC, X, corner cases
- }
- public static void Icmp(EmitterContext context)
- {
- OpCode op = context.CurrOp;
- bool isSigned = op.RawOpCode.Extract(48);
- IntegerCondition cmpOp = (IntegerCondition)op.RawOpCode.Extract(49, 3);
- Operand srcA = GetSrcA(context);
- Operand srcB = GetSrcB(context);
- Operand srcC = GetSrcC(context);
- Operand cmpRes = GetIntComparison(context, cmpOp, srcC, Const(0), isSigned);
- Operand res = context.ConditionalSelect(cmpRes, srcA, srcB);
- context.Copy(GetDest(context), res);
- }
- public static void Imad(EmitterContext context)
- {
- bool signedA = context.CurrOp.RawOpCode.Extract(48);
- bool signedB = context.CurrOp.RawOpCode.Extract(53);
- bool high = context.CurrOp.RawOpCode.Extract(54);
- Operand srcA = GetSrcA(context);
- Operand srcB = GetSrcB(context);
- Operand srcC = GetSrcC(context);
- Operand res;
- if (high)
- {
- if (signedA && signedB)
- {
- res = context.MultiplyHighS32(srcA, srcB);
- }
- else
- {
- res = context.MultiplyHighU32(srcA, srcB);
- if (signedA)
- {
- res = context.IAdd(res, context.IMultiply(srcB, context.ShiftRightS32(srcA, Const(31))));
- }
- else if (signedB)
- {
- res = context.IAdd(res, context.IMultiply(srcA, context.ShiftRightS32(srcB, Const(31))));
- }
- }
- }
- else
- {
- res = context.IMultiply(srcA, srcB);
- }
- res = context.IAdd(res, srcC);
- // TODO: CC, X, SAT, and more?
- context.Copy(GetDest(context), res);
- }
- public static void Imnmx(EmitterContext context)
- {
- OpCodeAlu op = (OpCodeAlu)context.CurrOp;
- bool isSignedInt = op.RawOpCode.Extract(48);
- Operand srcA = GetSrcA(context);
- Operand srcB = GetSrcB(context);
- Operand resMin = isSignedInt
- ? context.IMinimumS32(srcA, srcB)
- : context.IMinimumU32(srcA, srcB);
- Operand resMax = isSignedInt
- ? context.IMaximumS32(srcA, srcB)
- : context.IMaximumU32(srcA, srcB);
- Operand pred = GetPredicate39(context);
- Operand dest = GetDest(context);
- context.Copy(dest, context.ConditionalSelect(pred, resMin, resMax));
- SetZnFlags(context, dest, op.SetCondCode);
- // TODO: X flags.
- }
- public static void Iscadd(EmitterContext context)
- {
- OpCodeAlu op = (OpCodeAlu)context.CurrOp;
- bool negateA = false, negateB = false;
- if (!(op is OpCodeAluImm32))
- {
- negateB = op.RawOpCode.Extract(48);
- negateA = op.RawOpCode.Extract(49);
- }
- int shift = op is OpCodeAluImm32
- ? op.RawOpCode.Extract(53, 5)
- : op.RawOpCode.Extract(39, 5);
- Operand srcA = GetSrcA(context);
- Operand srcB = GetSrcB(context);
- srcA = context.ShiftLeft(srcA, Const(shift));
- srcA = context.INegate(srcA, negateA);
- srcB = context.INegate(srcB, negateB);
- Operand res = context.IAdd(srcA, srcB);
- context.Copy(GetDest(context), res);
- // TODO: CC, X
- }
- public static void Iset(EmitterContext context)
- {
- OpCodeSet op = (OpCodeSet)context.CurrOp;
- bool boolFloat = op.RawOpCode.Extract(44);
- bool isSigned = op.RawOpCode.Extract(48);
- IntegerCondition cmpOp = (IntegerCondition)op.RawOpCode.Extract(49, 3);
- Operand srcA = GetSrcA(context);
- Operand srcB = GetSrcB(context);
- Operand res = GetIntComparison(context, cmpOp, srcA, srcB, isSigned);
- Operand pred = GetPredicate39(context);
- res = GetPredLogicalOp(context, op.LogicalOp, res, pred);
- Operand dest = GetDest(context);
- if (boolFloat)
- {
- res = context.ConditionalSelect(res, ConstF(1), Const(0));
- context.Copy(dest, res);
- SetFPZnFlags(context, res, op.SetCondCode);
- }
- else
- {
- context.Copy(dest, res);
- SetZnFlags(context, res, op.SetCondCode, op.Extended);
- }
- // TODO: X
- }
- public static void Isetp(EmitterContext context)
- {
- OpCodeSet op = (OpCodeSet)context.CurrOp;
- bool isSigned = op.RawOpCode.Extract(48);
- IntegerCondition cmpOp = (IntegerCondition)op.RawOpCode.Extract(49, 3);
- Operand srcA = GetSrcA(context);
- Operand srcB = GetSrcB(context);
- Operand p0Res = GetIntComparison(context, cmpOp, srcA, srcB, isSigned);
- Operand p1Res = context.BitwiseNot(p0Res);
- Operand pred = GetPredicate39(context);
- p0Res = GetPredLogicalOp(context, op.LogicalOp, p0Res, pred);
- p1Res = GetPredLogicalOp(context, op.LogicalOp, p1Res, pred);
- context.Copy(Register(op.Predicate3), p0Res);
- context.Copy(Register(op.Predicate0), p1Res);
- }
- public static void Lea(EmitterContext context)
- {
- OpCodeAlu op = (OpCodeAlu)context.CurrOp;
- bool negateA = op.RawOpCode.Extract(45);
- int shift = op.RawOpCode.Extract(39, 5);
- Operand srcA = GetSrcA(context);
- Operand srcB = GetSrcB(context);
- srcA = context.ShiftLeft(srcA, Const(shift));
- srcA = context.INegate(srcA, negateA);
- Operand res = context.IAdd(srcA, srcB);
- context.Copy(GetDest(context), res);
- // TODO: CC, X
- }
- public static void Lop(EmitterContext context)
- {
- IOpCodeLop op = (IOpCodeLop)context.CurrOp;
- Operand srcA = context.BitwiseNot(GetSrcA(context), op.InvertA);
- Operand srcB = context.BitwiseNot(GetSrcB(context), op.InvertB);
- Operand res = srcB;
- switch (op.LogicalOp)
- {
- case LogicalOperation.And: res = context.BitwiseAnd (srcA, srcB); break;
- case LogicalOperation.Or: res = context.BitwiseOr (srcA, srcB); break;
- case LogicalOperation.ExclusiveOr: res = context.BitwiseExclusiveOr(srcA, srcB); break;
- }
- EmitLopPredWrite(context, op, res);
- Operand dest = GetDest(context);
- context.Copy(dest, res);
- SetZnFlags(context, dest, op.SetCondCode, op.Extended);
- }
- public static void Lop3(EmitterContext context)
- {
- IOpCodeLop op = (IOpCodeLop)context.CurrOp;
- Operand srcA = GetSrcA(context);
- Operand srcB = GetSrcB(context);
- Operand srcC = GetSrcC(context);
- bool regVariant = op is OpCodeLopReg;
- int truthTable = regVariant
- ? op.RawOpCode.Extract(28, 8)
- : op.RawOpCode.Extract(48, 8);
- Operand res = Lop3Expression.GetFromTruthTable(context, srcA, srcB, srcC, truthTable);
- if (regVariant)
- {
- EmitLopPredWrite(context, op, res);
- }
- Operand dest = GetDest(context);
- context.Copy(dest, res);
- SetZnFlags(context, dest, op.SetCondCode, op.Extended);
- }
- public static void Popc(EmitterContext context)
- {
- OpCodeAlu op = (OpCodeAlu)context.CurrOp;
- bool invert = op.RawOpCode.Extract(40);
- Operand srcB = context.BitwiseNot(GetSrcB(context), invert);
- Operand res = context.BitCount(srcB);
- context.Copy(GetDest(context), res);
- }
- public static void Pset(EmitterContext context)
- {
- OpCodePset op = (OpCodePset)context.CurrOp;
- bool boolFloat = op.RawOpCode.Extract(44);
- Operand srcA = context.BitwiseNot(Register(op.Predicate12), op.InvertA);
- Operand srcB = context.BitwiseNot(Register(op.Predicate29), op.InvertB);
- Operand srcC = context.BitwiseNot(Register(op.Predicate39), op.InvertP);
- Operand res = GetPredLogicalOp(context, op.LogicalOpAB, srcA, srcB);
- res = GetPredLogicalOp(context, op.LogicalOp, res, srcC);
- Operand dest = GetDest(context);
- if (boolFloat)
- {
- context.Copy(dest, context.ConditionalSelect(res, ConstF(1), Const(0)));
- }
- else
- {
- context.Copy(dest, res);
- }
- }
- public static void Psetp(EmitterContext context)
- {
- OpCodePset op = (OpCodePset)context.CurrOp;
- Operand srcA = context.BitwiseNot(Register(op.Predicate12), op.InvertA);
- Operand srcB = context.BitwiseNot(Register(op.Predicate29), op.InvertB);
- Operand p0Res = GetPredLogicalOp(context, op.LogicalOpAB, srcA, srcB);
- Operand p1Res = context.BitwiseNot(p0Res);
- Operand pred = GetPredicate39(context);
- p0Res = GetPredLogicalOp(context, op.LogicalOp, p0Res, pred);
- p1Res = GetPredLogicalOp(context, op.LogicalOp, p1Res, pred);
- context.Copy(Register(op.Predicate3), p0Res);
- context.Copy(Register(op.Predicate0), p1Res);
- }
- public static void Rro(EmitterContext context)
- {
- // This is the range reduction operator,
- // we translate it as a simple move, as it
- // should be always followed by a matching
- // MUFU instruction.
- OpCodeAlu op = (OpCodeAlu)context.CurrOp;
- bool negateB = op.RawOpCode.Extract(45);
- bool absoluteB = op.RawOpCode.Extract(49);
- Operand srcB = GetSrcB(context);
- srcB = context.FPAbsNeg(srcB, absoluteB, negateB);
- context.Copy(GetDest(context), srcB);
- }
- public static void Shl(EmitterContext context)
- {
- OpCodeAlu op = (OpCodeAlu)context.CurrOp;
- bool isMasked = op.RawOpCode.Extract(39);
- Operand srcB = GetSrcB(context);
- if (isMasked)
- {
- srcB = context.BitwiseAnd(srcB, Const(0x1f));
- }
- Operand res = context.ShiftLeft(GetSrcA(context), srcB);
- if (!isMasked)
- {
- // Clamped shift value.
- Operand isLessThan32 = context.ICompareLessUnsigned(srcB, Const(32));
- res = context.ConditionalSelect(isLessThan32, res, Const(0));
- }
- // TODO: X, CC
- context.Copy(GetDest(context), res);
- }
- public static void Shr(EmitterContext context)
- {
- OpCodeAlu op = (OpCodeAlu)context.CurrOp;
- bool isMasked = op.RawOpCode.Extract(39);
- bool isReverse = op.RawOpCode.Extract(40);
- bool isSigned = op.RawOpCode.Extract(48);
- Operand srcA = GetSrcA(context);
- Operand srcB = GetSrcB(context);
- if (isReverse)
- {
- srcA = context.BitfieldReverse(srcA);
- }
- if (isMasked)
- {
- srcB = context.BitwiseAnd(srcB, Const(0x1f));
- }
- Operand res = isSigned
- ? context.ShiftRightS32(srcA, srcB)
- : context.ShiftRightU32(srcA, srcB);
- if (!isMasked)
- {
- // Clamped shift value.
- Operand resShiftBy32;
- if (isSigned)
- {
- resShiftBy32 = context.ShiftRightS32(srcA, Const(31));
- }
- else
- {
- resShiftBy32 = Const(0);
- }
- Operand isLessThan32 = context.ICompareLessUnsigned(srcB, Const(32));
- res = context.ConditionalSelect(isLessThan32, res, resShiftBy32);
- }
- // TODO: X, CC
- context.Copy(GetDest(context), res);
- }
- public static void Xmad(EmitterContext context)
- {
- OpCodeAlu op = (OpCodeAlu)context.CurrOp;
- bool signedA = context.CurrOp.RawOpCode.Extract(48);
- bool signedB = context.CurrOp.RawOpCode.Extract(49);
- bool highA = context.CurrOp.RawOpCode.Extract(53);
- bool isReg = (op is OpCodeAluReg) && !(op is OpCodeAluRegCbuf);
- bool isImm = (op is OpCodeAluImm);
- XmadCMode mode = isReg || isImm
- ? (XmadCMode)context.CurrOp.RawOpCode.Extract(50, 3)
- : (XmadCMode)context.CurrOp.RawOpCode.Extract(50, 2);
- bool highB = false;
- if (isReg)
- {
- highB = context.CurrOp.RawOpCode.Extract(35);
- }
- else if (!isImm)
- {
- highB = context.CurrOp.RawOpCode.Extract(52);
- }
- Operand srcA = GetSrcA(context);
- Operand srcB = GetSrcB(context);
- Operand srcC = GetSrcC(context);
- // XMAD immediates are 16-bits unsigned integers.
- if (srcB.Type == OperandType.Constant)
- {
- srcB = Const(srcB.Value & 0xffff);
- }
- Operand Extend16To32(Operand src, bool high, bool signed)
- {
- if (signed && high)
- {
- return context.ShiftRightS32(src, Const(16));
- }
- else if (signed)
- {
- return context.BitfieldExtractS32(src, Const(0), Const(16));
- }
- else if (high)
- {
- return context.ShiftRightU32(src, Const(16));
- }
- else
- {
- return context.BitwiseAnd(src, Const(0xffff));
- }
- }
- srcA = Extend16To32(srcA, highA, signedA);
- srcB = Extend16To32(srcB, highB, signedB);
- bool productShiftLeft = false;
- bool merge = false;
- if (!(op is OpCodeAluRegCbuf))
- {
- productShiftLeft = context.CurrOp.RawOpCode.Extract(36);
- merge = context.CurrOp.RawOpCode.Extract(37);
- }
- bool extended;
- if ((op is OpCodeAluReg) || (op is OpCodeAluImm))
- {
- extended = context.CurrOp.RawOpCode.Extract(38);
- }
- else
- {
- extended = context.CurrOp.RawOpCode.Extract(54);
- }
- Operand res = context.IMultiply(srcA, srcB);
- if (productShiftLeft)
- {
- res = context.ShiftLeft(res, Const(16));
- }
- switch (mode)
- {
- case XmadCMode.Cfull: break;
- case XmadCMode.Clo: srcC = Extend16To32(srcC, high: false, signed: false); break;
- case XmadCMode.Chi: srcC = Extend16To32(srcC, high: true, signed: false); break;
- case XmadCMode.Cbcc:
- {
- srcC = context.IAdd(srcC, context.ShiftLeft(GetSrcB(context), Const(16)));
- break;
- }
- case XmadCMode.Csfu:
- {
- Operand signAdjustA = context.ShiftLeft(context.ShiftRightU32(srcA, Const(31)), Const(16));
- Operand signAdjustB = context.ShiftLeft(context.ShiftRightU32(srcB, Const(31)), Const(16));
- srcC = context.ISubtract(srcC, context.IAdd(signAdjustA, signAdjustB));
- break;
- }
- default: /* TODO: Warning */ break;
- }
- Operand product = res;
- if (extended)
- {
- // Add with carry.
- res = context.IAdd(res, context.BitwiseAnd(GetCF(), Const(1)));
- }
- else
- {
- // Add (no carry in).
- res = context.IAdd(res, srcC);
- }
- SetIaddFlags(context, res, product, srcC, op.SetCondCode, extended);
- if (merge)
- {
- res = context.BitwiseAnd(res, Const(0xffff));
- res = context.BitwiseOr(res, context.ShiftLeft(GetSrcB(context), Const(16)));
- }
- context.Copy(GetDest(context), res);
- }
- private static Operand GetIntComparison(
- EmitterContext context,
- IntegerCondition cond,
- Operand srcA,
- Operand srcB,
- bool isSigned)
- {
- Operand res;
- if (cond == IntegerCondition.Always)
- {
- res = Const(IrConsts.True);
- }
- else if (cond == IntegerCondition.Never)
- {
- res = Const(IrConsts.False);
- }
- else
- {
- var inst = cond switch
- {
- IntegerCondition.Less => Instruction.CompareLessU32,
- IntegerCondition.Equal => Instruction.CompareEqual,
- IntegerCondition.LessOrEqual => Instruction.CompareLessOrEqualU32,
- IntegerCondition.Greater => Instruction.CompareGreaterU32,
- IntegerCondition.NotEqual => Instruction.CompareNotEqual,
- IntegerCondition.GreaterOrEqual => Instruction.CompareGreaterOrEqualU32,
- _ => throw new InvalidOperationException($"Unexpected condition \"{cond}\".")
- };
- if (isSigned)
- {
- switch (cond)
- {
- case IntegerCondition.Less: inst = Instruction.CompareLess; break;
- case IntegerCondition.LessOrEqual: inst = Instruction.CompareLessOrEqual; break;
- case IntegerCondition.Greater: inst = Instruction.CompareGreater; break;
- case IntegerCondition.GreaterOrEqual: inst = Instruction.CompareGreaterOrEqual; break;
- }
- }
- res = context.Add(inst, Local(), srcA, srcB);
- }
- return res;
- }
- private static void EmitLopPredWrite(EmitterContext context, IOpCodeLop op, Operand result)
- {
- if (op is OpCodeLop opLop && !opLop.Predicate48.IsPT)
- {
- Operand pRes;
- if (opLop.CondOp == ConditionalOperation.False)
- {
- pRes = Const(IrConsts.False);
- }
- else if (opLop.CondOp == ConditionalOperation.True)
- {
- pRes = Const(IrConsts.True);
- }
- else if (opLop.CondOp == ConditionalOperation.Zero)
- {
- pRes = context.ICompareEqual(result, Const(0));
- }
- else /* if (opLop.CondOp == ConditionalOperation.NotZero) */
- {
- pRes = context.ICompareNotEqual(result, Const(0));
- }
- context.Copy(Register(opLop.Predicate48), pRes);
- }
- }
- private static void SetIaddFlags(
- EmitterContext context,
- Operand res,
- Operand srcA,
- Operand srcB,
- bool setCC,
- bool extended,
- bool isSubtraction = false)
- {
- if (!setCC)
- {
- return;
- }
- if (!extended || isSubtraction)
- {
- // C = d < a
- context.Copy(GetCF(), context.ICompareLessUnsigned(res, srcA));
- }
- else
- {
- // C = (d == a && CIn) || d < a
- Operand tempC0 = context.ICompareEqual (res, srcA);
- Operand tempC1 = context.ICompareLessUnsigned(res, srcA);
- tempC0 = context.BitwiseAnd(tempC0, GetCF());
- context.Copy(GetCF(), context.BitwiseOr(tempC0, tempC1));
- }
- // V = (d ^ a) & ~(a ^ b) < 0
- Operand tempV0 = context.BitwiseExclusiveOr(res, srcA);
- Operand tempV1 = context.BitwiseExclusiveOr(srcA, srcB);
- tempV1 = context.BitwiseNot(tempV1);
- Operand tempV = context.BitwiseAnd(tempV0, tempV1);
- context.Copy(GetVF(), context.ICompareLess(tempV, Const(0)));
- SetZnFlags(context, res, setCC: true, extended: extended);
- }
- }
- }
|