void emitDMUL(const Instruction *);
void emitIMAD(const Instruction *);
void emitISAD(const Instruction *);
+ void emitSHLADD(const Instruction *a);
void emitFMAD(const Instruction *);
void emitDMAD(const Instruction *);
void emitMADSP(const Instruction *);
if (i->saturate)
code[0] |= 1 << 5;
+
+ if (i->dnz)
+ code[0] |= 1 << 7;
+ else
if (i->ftz)
code[0] |= 1 << 6;
} else {
uint32_t addOp = 0;
assert(!i->src(0).mod.abs() && !i->src(1).mod.abs());
- assert(!i->src(0).mod.neg() || !i->src(1).mod.neg());
if (i->src(0).mod.neg())
addOp |= 0x200;
if (i->src(1).mod.neg())
addOp |= 0x100;
- if (i->op == OP_SUB) {
+ if (i->op == OP_SUB)
addOp ^= 0x100;
- assert(addOp != 0x300); // would be add-plus-one
- }
+
+ assert(addOp != 0x300); // would be add-plus-one
if (i->encSize == 8) {
if (isLIMM(i->src(1), TYPE_U32)) {
}
}
-// TODO: shl-add
void
CodeEmitterNVC0::emitIMAD(const Instruction *i)
{
+ uint8_t addOp =
+ i->src(2).mod.neg() | ((i->src(0).mod.neg() ^ i->src(1).mod.neg()) << 1);
+
assert(i->encSize == 8);
emitForm_A(i, HEX64(20000000, 00000003));
+ assert(addOp != 3);
+ code[0] |= addOp << 8;
+
if (isSignedType(i->dType))
code[0] |= 1 << 7;
if (isSignedType(i->sType))
if (i->flagsDef >= 0) code[1] |= 1 << 16;
if (i->flagsSrc >= 0) code[1] |= 1 << 23;
- if (i->src(2).mod.neg()) code[0] |= 0x10;
- if (i->src(1).mod.neg() ^
- i->src(0).mod.neg()) code[0] |= 0x20;
-
if (i->subOp == NV50_IR_SUBOP_MUL_HIGH)
code[0] |= 1 << 6;
}
+void
+CodeEmitterNVC0::emitSHLADD(const Instruction *i)
+{
+ uint8_t addOp = (i->src(0).mod.neg() << 1) | i->src(2).mod.neg();
+ const ImmediateValue *imm = i->src(1).get()->asImm();
+ assert(imm);
+
+ code[0] = 0x00000003;
+ code[1] = 0x40000000 | addOp << 23;
+
+ emitPredicate(i);
+
+ defId(i->def(0), 14);
+ srcId(i->src(0), 20);
+
+ if (i->flagsDef >= 0)
+ code[1] |= 1 << 16;
+
+ assert(!(imm->reg.data.u32 & 0xffffffe0));
+ code[0] |= imm->reg.data.u32 << 5;
+
+ switch (i->src(2).getFile()) {
+ case FILE_GPR:
+ srcId(i->src(2), 26);
+ break;
+ case FILE_MEMORY_CONST:
+ code[1] |= 0x4000;
+ code[1] |= i->getSrc(2)->reg.fileIndex << 10;
+ setAddress16(i->src(2));
+ break;
+ case FILE_IMMEDIATE:
+ setImmediate(i, 2);
+ break;
+ default:
+ assert(!"bad src2 file");
+ break;
+ }
+}
+
void
CodeEmitterNVC0::emitMADSP(const Instruction *i)
{
if (i->ftz)
op |= 1 << 5;
else
- if (!isFloatType(i->dType))
+ if (!isFloatType(i->dType)) {
op |= isSignedType(i->dType) ? 0x23 : 0x03;
+ op |= i->subOp << 6;
+ }
if (i->dType == TYPE_F64)
op |= 0x01;
emitForm_A(i, op);
emitNegAbs12(i);
+
+ if (i->flagsDef >= 0)
+ code[1] |= 1 << 16;
}
void
void
CodeEmitterNVC0::emitQUADOP(const Instruction *i, uint8_t qOp, uint8_t laneMask)
{
- code[0] = 0x00000000 | (laneMask << 6);
+ code[0] = 0x00000200 | (laneMask << 6); // dall
code[1] = 0x48000000 | qOp;
defId(i->def(0), 14);
srcId(i->src(0), 20);
srcId((i->srcExists(1) && i->predSrc != 1) ? i->src(1) : i->src(0), 26);
- if (i->op == OP_QUADOP && progType != Program::TYPE_FRAGMENT)
- code[0] |= 1 << 9; // dall
-
emitPredicate(i);
}
opc |= i->lanes << 5;
emitForm_B(i, opc);
+
+ // Explicitly emit the predicate source as emitForm_B skips it.
+ if (i->src(0).getFile() == FILE_PREDICATE)
+ srcId(i->src(0), 20);
} else {
uint32_t imm;
void
CodeEmitterNVC0::emitVOTE(const Instruction *i)
{
- assert(i->src(0).getFile() == FILE_PREDICATE &&
- i->def(1).getFile() == FILE_PREDICATE);
+ assert(i->src(0).getFile() == FILE_PREDICATE);
code[0] = 0x00000004 | (i->subOp << 5);
code[1] = 0x48000000;
emitPredicate(i);
- defId(i->def(0), 14);
- defId(i->def(1), 32 + 22);
+ unsigned rp = 0;
+ for (int d = 0; i->defExists(d); d++) {
+ if (i->def(d).getFile() == FILE_PREDICATE) {
+ assert(!(rp & 2));
+ rp |= 2;
+ defId(i->def(d), 32 + 22);
+ } else if (i->def(d).getFile() == FILE_GPR) {
+ assert(!(rp & 1));
+ rp |= 1;
+ defId(i->def(d), 14);
+ } else {
+ assert(!"Unhandled def");
+ }
+ }
+ if (!(rp & 1))
+ code[0] |= 63 << 14;
+ if (!(rp & 2))
+ code[1] |= 7 << 22;
if (i->src(0).mod == Modifier(NV50_IR_MOD_NOT))
code[0] |= 1 << 23;
srcId(i->src(0), 20);
case OP_SAD:
emitISAD(insn);
break;
+ case OP_SHLADD:
+ emitSHLADD(insn);
+ break;
case OP_NOT:
emitNOT(insn);
break;