nvc0/ir: add a "high" subop for shifts, emit shf.l/shf.r for 64-bit

Note that this is not available for SM20/SM30.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
This commit is contained in:
Ilia Mirkin
2017-02-04 22:29:17 -05:00
parent 2e986fa806
commit 22c705ea8c
3 changed files with 74 additions and 3 deletions
@@ -175,6 +175,7 @@ enum operation
#define NV50_IR_SUBOP_LDC_IS 2
#define NV50_IR_SUBOP_LDC_ISL 3
#define NV50_IR_SUBOP_SHIFT_WRAP 1
#define NV50_IR_SUBOP_SHIFT_HIGH 2
#define NV50_IR_SUBOP_EMU_PRERET 1
#define NV50_IR_SUBOP_TEXBAR(n) n
#define NV50_IR_SUBOP_MOV_FINAL 1
@@ -109,6 +109,7 @@ private:
void emitBFIND(const Instruction *);
void emitPERMT(const Instruction *);
void emitShift(const Instruction *);
void emitShift64(const Instruction *);
void emitSFnOp(const Instruction *, uint8_t subOp);
@@ -935,6 +936,24 @@ CodeEmitterGK110::emitShift(const Instruction *i)
code[1] |= 1 << 10;
}
void
CodeEmitterGK110::emitShift64(const Instruction *i)
{
if (i->op == OP_SHR) {
emitForm_21(i, 0x27c, 0xc7c);
if (isSignedType(i->sType))
code[1] |= 0x100;
if (i->subOp & NV50_IR_SUBOP_SHIFT_HIGH)
code[1] |= 1 << 19;
} else {
emitForm_21(i, 0xdfc, 0xf7c);
}
code[1] |= 0x200;
if (i->subOp & NV50_IR_SUBOP_SHIFT_WRAP)
code[1] |= 1 << 21;
}
void
CodeEmitterGK110::emitPreOp(const Instruction *i)
{
@@ -2475,7 +2494,10 @@ CodeEmitterGK110::emitInstruction(Instruction *insn)
break;
case OP_SHL:
case OP_SHR:
emitShift(insn);
if (typeSizeof(insn->sType) == 8)
emitShift64(insn);
else
emitShift(insn);
break;
case OP_SET:
case OP_SET_AND:
@@ -161,6 +161,7 @@ private:
void emitISETP();
void emitSHL();
void emitSHR();
void emitSHF();
void emitPOPC();
void emitBFI();
void emitBFE();
@@ -2071,6 +2072,47 @@ CodeEmitterGM107::emitSHR()
emitGPR (0x00, insn->def(0));
}
void
CodeEmitterGM107::emitSHF()
{
unsigned type;
switch (insn->src(1).getFile()) {
case FILE_GPR:
emitInsn(insn->op == OP_SHL ? 0x5bf80000 : 0x5cf80000);
emitGPR(0x14, insn->src(1));
break;
case FILE_IMMEDIATE:
emitInsn(insn->op == OP_SHL ? 0x36f80000 : 0x38f80000);
emitIMMD(0x14, 19, insn->src(1));
break;
default:
assert(!"bad src1 file");
break;
}
switch (insn->sType) {
case TYPE_U64:
type = 2;
break;
case TYPE_S64:
type = 3;
break;
default:
type = 0;
break;
}
emitField(0x32, 1, !!(insn->subOp & NV50_IR_SUBOP_SHIFT_WRAP));
emitX (0x31);
emitField(0x30, 1, !!(insn->subOp & NV50_IR_SUBOP_SHIFT_HIGH));
emitCC (0x2f);
emitGPR (0x27, insn->src(2));
emitField(0x25, 2, type);
emitGPR (0x08, insn->src(0));
emitGPR (0x00, insn->def(0));
}
void
CodeEmitterGM107::emitPOPC()
{
@@ -3169,10 +3211,16 @@ CodeEmitterGM107::emitInstruction(Instruction *i)
}
break;
case OP_SHL:
emitSHL();
if (typeSizeof(insn->sType) == 8)
emitSHF();
else
emitSHL();
break;
case OP_SHR:
emitSHR();
if (typeSizeof(insn->sType) == 8)
emitSHF();
else
emitSHR();
break;
case OP_POPCNT:
emitPOPC();