encoding |= vop3->neg[i] << (29+i);
out.push_back(encoding);
+ } else if (instr->format == Format::VOP3P) {
+ VOP3P_instruction* vop3 = static_cast<VOP3P_instruction*>(instr);
+
+ uint32_t encoding;
+ if (ctx.chip_class == GFX9) {
+ encoding = (0b110100111 << 23);
+ } else if (ctx.chip_class == GFX10) {
+ encoding = (0b110011 << 26);
+ } else {
+ unreachable("Unknown chip_class.");
+ }
+
+ encoding |= opcode << 16;
+ encoding |= (vop3->clamp ? 1 : 0) << 15;
+ encoding |= vop3->opsel_lo << 11;
+ encoding |= (vop3->opsel_hi & 0x4) ? 1 : 0 << 14;
+ for (unsigned i = 0; i < 3; i++)
+ encoding |= vop3->neg_hi[i] << (8+i);
+ encoding |= (0xFF & instr->definitions[0].physReg());
+ out.push_back(encoding);
+ encoding = 0;
+ for (unsigned i = 0; i < instr->operands.size(); i++)
+ encoding |= instr->operands[i].physReg() << (i * 9);
+ encoding |= vop3->opsel_hi & 0x3 << 27;
+ for (unsigned i = 0; i < 3; i++)
+ encoding |= vop3->neg_lo[i] << (29+i);
+ out.push_back(encoding);
+
} else if (instr->isDPP()){
assert(ctx.chip_class >= GFX8);
/* first emit the instruction without the DPP operand */
PSEUDO_REDUCTION = 18,
/* Vector ALU Formats */
+ VOP3P = 19,
VOP1 = 1 << 8,
VOP2 = 1 << 9,
VOPC = 1 << 10,
VOP3 = 1 << 11,
VOP3A = 1 << 11,
VOP3B = 1 << 11,
- VOP3P = 1 << 12,
/* Vector Parameter Interpolation Format */
- VINTRP = 1 << 13,
- DPP = 1 << 14,
- SDWA = 1 << 15,
+ VINTRP = 1 << 12,
+ DPP = 1 << 13,
+ SDWA = 1 << 14,
};
enum barrier_interaction : uint8_t {
|| ((uint16_t) format & (uint16_t) Format::VOPC) == (uint16_t) Format::VOPC
|| ((uint16_t) format & (uint16_t) Format::VOP3A) == (uint16_t) Format::VOP3A
|| ((uint16_t) format & (uint16_t) Format::VOP3B) == (uint16_t) Format::VOP3B
- || ((uint16_t) format & (uint16_t) Format::VOP3P) == (uint16_t) Format::VOP3P;
+ || format == Format::VOP3P;
}
constexpr bool isSALU() const noexcept
constexpr bool isVOP3() const noexcept
{
return ((uint16_t) format & (uint16_t) Format::VOP3A) ||
- ((uint16_t) format & (uint16_t) Format::VOP3B) ||
- format == Format::VOP3P;
+ ((uint16_t) format & (uint16_t) Format::VOP3B);
}
constexpr bool isSDWA() const noexcept
};
static_assert(sizeof(VOP3A_instruction) == sizeof(Instruction) + 8);
+struct VOP3P_instruction : public Instruction {
+ bool neg_lo[3];
+ bool neg_hi[3];
+ uint8_t opsel_lo : 3;
+ uint8_t opsel_hi : 3;
+ bool clamp : 1;
+ uint32_t padding : 9;
+};
+static_assert(sizeof(VOP3P_instruction) == sizeof(Instruction) + 8);
+
/**
* Data Parallel Primitives Format:
* This format can be used for VOP1, VOP2 or VOPC instructions.
{
if (isDPP() || isSDWA())
return true;
- if (!isVOP3())
- return false;
- const VOP3A_instruction *vop3 = static_cast<const VOP3A_instruction*>(this);
- for (unsigned i = 0; i < operands.size(); i++) {
- if (vop3->abs[i] || vop3->neg[i])
- return true;
+
+ if (format == Format::VOP3P) {
+ const VOP3P_instruction *vop3p = static_cast<const VOP3P_instruction*>(this);
+ for (unsigned i = 0; i < operands.size(); i++) {
+ if (vop3p->neg_lo[i] || vop3p->neg_hi[i])
+ return true;
+ }
+ return vop3p->opsel_lo || vop3p->opsel_hi || vop3p->clamp;
+ } else if (isVOP3()) {
+ const VOP3A_instruction *vop3 = static_cast<const VOP3A_instruction*>(this);
+ for (unsigned i = 0; i < operands.size(); i++) {
+ if (vop3->abs[i] || vop3->neg[i])
+ return true;
+ }
+ return vop3->opsel || vop3->clamp || vop3->omod;
}
- return vop3->opsel || vop3->clamp || vop3->omod;
+ return false;
}
constexpr bool is_phi(Instruction* instr)
PSEUDO_BRANCH = 16
PSEUDO_BARRIER = 17
PSEUDO_REDUCTION = 18
+ VOP3P = 19
VOP1 = 1 << 8
VOP2 = 1 << 9
VOPC = 1 << 10
VOP3A = 1 << 11
VOP3B = 1 << 11
- VOP3P = 1 << 12
- VINTRP = 1 << 13
- DPP = 1 << 14
- SDWA = 1 << 15
+ VINTRP = 1 << 12
+ DPP = 1 << 13
+ SDWA = 1 << 14
def get_builder_fields(self):
if self == Format.SOPK:
print_barrier_reorder(mtbuf->can_reorder, mtbuf->barrier, output);
break;
}
+ case Format::VOP3P: {
+ if (static_cast<VOP3P_instruction*>(instr)->clamp)
+ fprintf(output, " clamp");
+ break;
+ }
default: {
break;
}
}
if (abs[i])
fprintf(output, "|");
- }
+
+ if (instr->format == Format::VOP3P) {
+ VOP3P_instruction* vop3 = static_cast<VOP3P_instruction*>(instr);
+ if ((vop3->opsel_lo & (1 << i)) || !(vop3->opsel_hi & (1 << i))) {
+ fprintf(output, ".%c%c",
+ vop3->opsel_lo & (1 << i) ? 'y' : 'x',
+ vop3->opsel_hi & (1 << i) ? 'y' : 'x');
+ }
+ if (vop3->neg_lo[i] && vop3->neg_hi[i])
+ fprintf(output, "*[-1,-1]");
+ else if (vop3->neg_lo[i])
+ fprintf(output, "*[-1,1]");
+ else if (vop3->neg_hi[i])
+ fprintf(output, "*[1,-1]");
+ }
+ }
}
print_instr_format_specific(instr, output);
}