Пример #1
0
static void
binaryCompareSet(State &state,
                 const ControlFlowInst &cf,
                 const AluInst &alu,
                 const char *op)
{
   // dst = (src0 op src1) ? 1 : 0
   auto flags = getInstructionFlags(alu.op2.ALU_INST());

   insertLineStart(state);
   insertDestBegin(state, cf, alu, state.unit);

   state.out << "(";
   insertSource0(state, state.out, cf, alu);
   state.out << op;
   insertSource1(state, state.out, cf, alu);
   state.out << ") ? ";

   if ((flags & SQ_ALU_FLAG_INT_OUT) || (flags & SQ_ALU_FLAG_UINT_OUT)) {
      state.out << "1 : 0";
   } else {
      state.out << "1.0f : 0.0f";
   }

   insertDestEnd(state, cf, alu);
   state.out << ';';
   insertLineEnd(state);
}
Пример #2
0
static void
binaryCompareKill(State &state,
                  const ControlFlowInst &cf,
                  const AluInst &alu,
                  const char *op)
{
   // if (src0 op src1) { discard; } else { dst = 0.0f; }
   auto flags = getInstructionFlags(alu.op2.ALU_INST());

   insertLineStart(state);
   state.out << "if (";
   insertSource0(state, state.out, cf, alu);
   state.out << op;
   insertSource1(state, state.out, cf, alu);
   state.out << ") {";
   insertLineEnd(state);

   increaseIndent(state);
   insertLineStart(state);
   state.out << "discard;";
   insertLineEnd(state);
   decreaseIndent(state);

   insertLineStart(state);
   state.out << "} else {";
   insertLineEnd(state);

   increaseIndent(state);
   insertLineStart(state);
   insertDestBegin(state, cf, alu, state.unit);

   if ((flags & SQ_ALU_FLAG_INT_OUT) || (flags & SQ_ALU_FLAG_UINT_OUT)) {
      state.out << "0";
   } else {
      state.out << "0.0f";
   }

   insertDestEnd(state, cf, alu);
   state.out << ';';
   insertLineEnd(state);
   decreaseIndent(state);

   insertLineStart(state);
   state.out << '}';
   insertLineEnd(state);
}
void
disassembleAluInstruction(fmt::MemoryWriter &out,
                          const ControlFlowInst &parent,
                          const AluInst &inst,
                          size_t groupPC,
                          SQ_CHAN unit,
                          const gsl::span<const uint32_t> &literals,
                          int namePad)
{
   const char *name = nullptr;
   SQ_ALU_FLAGS flags;
   auto srcCount = 0u;

   if (inst.word1.ENCODING() == SQ_ALU_ENCODING::OP2) {
      name = getInstructionName(inst.op2.ALU_INST());
      flags = getInstructionFlags(inst.op2.ALU_INST());
      srcCount = getInstructionNumSrcs(inst.op2.ALU_INST());
   } else {
      name = getInstructionName(inst.op3.ALU_INST());
      flags = getInstructionFlags(inst.op3.ALU_INST());
      srcCount = getInstructionNumSrcs(inst.op3.ALU_INST());
   }

   out << fmt::pad(name, namePad, ' ') << ' ';

   auto writeMask = true;

   if (inst.word1.ENCODING() == SQ_ALU_ENCODING::OP2) {
      writeMask = inst.op2.WRITE_MASK();
   }

   if (!writeMask) {
      out << "____";
   } else {
      disassembleAluSource(out,
                           parent,
                           groupPC,
                           inst.word0.INDEX_MODE(),
                           inst.word1.DST_GPR(),
                           inst.word1.DST_REL(),
                           inst.word1.DST_CHAN(),
                           0,
                           false,
                           false);
   }

   if (srcCount > 0) {
      auto literal = 0u;
      auto abs = false;

      if (inst.word0.SRC0_SEL() == SQ_ALU_SRC::LITERAL) {
         literal = literals[inst.word0.SRC0_CHAN()];
      }

      if (inst.word1.ENCODING() == SQ_ALU_ENCODING::OP2) {
         abs = !!inst.op2.SRC0_ABS();
      }

      out << ", ";
      disassembleAluSource(out,
                           parent,
                           groupPC,
                           inst.word0.INDEX_MODE(),
                           inst.word0.SRC0_SEL(),
                           inst.word0.SRC0_REL(),
                           inst.word0.SRC0_CHAN(),
                           literal,
                           inst.word0.SRC0_NEG(),
                           abs);
   }

   if (srcCount > 1) {
      auto literal = 0u;
      auto abs = false;

      if (inst.word0.SRC1_SEL() == SQ_ALU_SRC::LITERAL) {
         literal = literals[inst.word0.SRC1_CHAN()];
      }

      if (inst.word1.ENCODING() == SQ_ALU_ENCODING::OP2) {
         abs = !!inst.op2.SRC1_ABS();
      }

      out << ", ";
      disassembleAluSource(out,
                           parent,
                           groupPC,
                           inst.word0.INDEX_MODE(),
                           inst.word0.SRC1_SEL(),
                           inst.word0.SRC1_REL(),
                           inst.word0.SRC1_CHAN(),
                           literal,
                           inst.word0.SRC1_NEG(),
                           abs);
   }

   if (srcCount > 2) {
      auto literal = 0u;

      if (inst.op3.SRC2_SEL() == SQ_ALU_SRC::LITERAL) {
         literal = literals[inst.op3.SRC2_CHAN()];
      }

      out << ", ";
      disassembleAluSource(out,
                           parent,
                           groupPC,
                           inst.word0.INDEX_MODE(),
                           inst.op3.SRC2_SEL(),
                           inst.op3.SRC2_REL(),
                           inst.op3.SRC2_CHAN(),
                           literal,
                           inst.op3.SRC2_NEG(),
                           false);
   }

   if (inst.word1.CLAMP()) {
      out << " CLAMP";
   }

   if (isTranscendentalOnly(flags)) {
      switch (static_cast<SQ_ALU_SCL_BANK_SWIZZLE>(inst.word1.BANK_SWIZZLE())) {
      case SQ_ALU_SCL_BANK_SWIZZLE::SCL_210:
         out << " SCL_210";
         break;
      case SQ_ALU_SCL_BANK_SWIZZLE::SCL_122:
         out << " SCL_122";
         break;
      case SQ_ALU_SCL_BANK_SWIZZLE::SCL_212:
         out << " SCL_212";
         break;
      case SQ_ALU_SCL_BANK_SWIZZLE::SCL_221:
         out << " SCL_221";
         break;
      default:
         decaf_abort(fmt::format("Unexpected BANK_SWIZZLE {}", inst.word1.BANK_SWIZZLE()));
      }
   } else {
      switch (inst.word1.BANK_SWIZZLE()) {
      case SQ_ALU_VEC_BANK_SWIZZLE::VEC_012:
         // This is default, no need to print
         break;
      case SQ_ALU_VEC_BANK_SWIZZLE::VEC_021:
         out << " VEC_021";
         break;
      case SQ_ALU_VEC_BANK_SWIZZLE::VEC_120:
         out << " VEC_120";
         break;
      case SQ_ALU_VEC_BANK_SWIZZLE::VEC_102:
         out << " VEC_102";
         break;
      case SQ_ALU_VEC_BANK_SWIZZLE::VEC_201:
         out << " VEC_201";
         break;
      case SQ_ALU_VEC_BANK_SWIZZLE::VEC_210:
         out << " VEC_210";
         break;
      default:
         decaf_abort(fmt::format("Unexpected BANK_SWIZZLE {}", inst.word1.BANK_SWIZZLE()));
      }
   }

   switch (inst.word0.PRED_SEL()) {
   case SQ_PRED_SEL::OFF:
      break;
   case SQ_PRED_SEL::ZERO:
      out << " PRED_SEL_ZERO";
      break;
   case SQ_PRED_SEL::ONE:
      out << " PRED_SEL_ONE";
      break;
   default:
      decaf_abort(fmt::format("Unexpected PRED_SEL {}", inst.word0.PRED_SEL()));
   }

   if (inst.word1.ENCODING() == SQ_ALU_ENCODING::OP2) {
      if (inst.op2.UPDATE_EXECUTE_MASK()) {
         out << " UPDATE_EXECUTE_MASK";

         switch (inst.op2.EXECUTE_MASK_OP()) {
         case SQ_ALU_EXECUTE_MASK_OP::DEACTIVATE:
            out << " DEACTIVATE";
            break;
         case SQ_ALU_EXECUTE_MASK_OP::BREAK:
            out << " BREAK";
            break;
         case SQ_ALU_EXECUTE_MASK_OP::CONTINUE:
            out << " CONTINUE";
            break;
         case SQ_ALU_EXECUTE_MASK_OP::KILL:
            out << " KILL";
            break;
         default:
            decaf_abort(fmt::format("Unexpected EXECUTE_MASK_OP {}", inst.op2.EXECUTE_MASK_OP()));
         }
      } else {
         switch (inst.op2.OMOD()) {
         case SQ_ALU_OMOD::OFF:
            break;
         case SQ_ALU_OMOD::D2:
            out << " OMOD_D2";
            break;
         case SQ_ALU_OMOD::M2:
            out << " OMOD_M2";
            break;
         case SQ_ALU_OMOD::M4:
            out << " OMOD_M4";
            break;
         default:
            decaf_abort(fmt::format("Unexpected OMOD {}", inst.op2.OMOD()));
         }
      }

      if (inst.op2.UPDATE_PRED()) {
         out << " UPDATE_PRED";
      }
   }
}