private static bool IsUnconditional(ref InstOp op) { InstConditional condOp = new InstConditional(op.RawOpCode); if (op.Name == InstName.Exit && condOp.Ccc != Ccc.T) { return(false); } return(condOp.Pred == RegisterConsts.PredicateTrueIndex && !condOp.PredInv); }
private static void EmitOps(EmitterContext context, Block block) { for (int opIndex = 0; opIndex < block.OpCodes.Count; opIndex++) { InstOp op = block.OpCodes[opIndex]; if (context.Config.Options.Flags.HasFlag(TranslationFlags.DebugMode)) { string instName; if (op.Emitter != null) { instName = op.Name.ToString(); } else { instName = "???"; context.Config.GpuAccessor.Log($"Invalid instruction at 0x{op.Address:X6} (0x{op.RawOpCode:X16})."); } string dbgComment = $"0x{op.Address:X6}: 0x{op.RawOpCode:X16} {instName}"; context.Add(new CommentNode(dbgComment)); } InstConditional opConditional = new InstConditional(op.RawOpCode); bool noPred = op.Props.HasFlag(InstProps.NoPred); if (!noPred && opConditional.Pred == RegisterConsts.PredicateTrueIndex && opConditional.PredInv) { continue; } Operand predSkipLbl = null; if (Decoder.IsPopBranch(op.Name)) { // If the instruction is a SYNC or BRK instruction with only one // possible target address, then the instruction is basically // just a simple branch, we can generate code similar to branch // instructions, with the condition check on the branch itself. noPred = block.SyncTargets.Count <= 1; } else if (op.Name == InstName.Bra) { noPred = true; } if (!(opConditional.Pred == RegisterConsts.PredicateTrueIndex || noPred)) { Operand label; if (opIndex == block.OpCodes.Count - 1 && block.HasNext()) { label = context.GetLabel(block.Successors[0].Address); } else { label = Label(); predSkipLbl = label; } Operand pred = Register(opConditional.Pred, RegisterType.Predicate); if (opConditional.PredInv) { context.BranchIfTrue(label, pred); } else { context.BranchIfFalse(label, pred); } } context.CurrOp = op; op.Emitter?.Invoke(context); if (predSkipLbl != null) { context.MarkLabel(predSkipLbl); } } }