}
void GenContext::emitConvertInstruction(const ir::ConvertInstruction &insn) {
- const ir::Type dstType = insn.getDstType();
- const ir::Type srcType = insn.getSrcType();
+ using namespace ir;
+ const Type dstType = insn.getDstType();
+ const Type srcType = insn.getSrcType();
+ const RegisterFamily dstFamily = getFamily(dstType);
+ const RegisterFamily srcFamily = getFamily(srcType);
const GenReg dst = this->genReg(insn.getDst(0), dstType);
const GenReg src = this->genReg(insn.getSrc(0), srcType);
- p->MOV(dst, src);
+
+ GBE_ASSERT(dstFamily != FAMILY_QWORD && srcFamily != FAMILY_QWORD);
+
+ // We need two steps here to make the conversion
+ if (dstFamily != FAMILY_DWORD && srcFamily == FAMILY_DWORD) {
+ GenReg unpacked;
+ const uint32_t vstride = simdWidth == 8 ? GEN_VERTICAL_STRIDE_8 : GEN_VERTICAL_STRIDE_16;
+ if (dstFamily == FAMILY_WORD) {
+ unpacked = GenReg(GEN_GENERAL_REGISTER_FILE,
+ 112,
+ 0,
+ dstType == TYPE_U16 ? GEN_TYPE_UW : GEN_TYPE_W,
+ vstride,
+ GEN_WIDTH_8,
+ GEN_HORIZONTAL_STRIDE_2);
+ } else {
+ GBE_ASSERT(dstFamily == FAMILY_BYTE);
+ unpacked = GenReg(GEN_GENERAL_REGISTER_FILE,
+ 112,
+ 0,
+ dstType == TYPE_U8 ? GEN_TYPE_UB : GEN_TYPE_B,
+ vstride,
+ GEN_WIDTH_8,
+ GEN_HORIZONTAL_STRIDE_4);
+ }
+ p->MOV(unpacked, src);
+ p->MOV(dst, unpacked);
+ } else {
+ p->MOV(dst, src);
+ }
}
void GenContext::emitBranchInstruction(const ir::BranchInstruction &insn) {
if (isScalarReg(insn.getAddress()) == true) {
if (this->simdWidth == 8) {
p->MOV(GenReg::f8grf(112, 0), GenReg::retype(address, GEN_TYPE_F));
- p->BYTE_GATHER(dst, GenReg::f8grf(112, 0), 0, 1);
+ p->BYTE_GATHER(dst, GenReg::f8grf(112, 0), 0, elemSize);
} else if (this->simdWidth == 16) {
p->MOV(GenReg::f16grf(112, 0), GenReg::retype(address, GEN_TYPE_F));
- p->BYTE_GATHER(dst, GenReg::f16grf(112, 0), 0, 1);
+ p->BYTE_GATHER(dst, GenReg::f16grf(112, 0), 0, elemSize);
}
} else
- p->BYTE_GATHER(dst, address, 0, 1);
+ p->BYTE_GATHER(dst, address, 0, elemSize);
} else
NOT_IMPLEMENTED;
- // Repack bytes or words
- if (elemSize == GEN_BYTE_SCATTER_WORD) {
- if (simdWidth == 8) {
-
- } else if (simdWidth == 16) {
-
- }
- } else if (elemSize == GEN_BYTE_SCATTER_BYTE) {
-
- }
+ // Repack bytes or words using a converting mov instruction
+ if (elemSize == GEN_BYTE_SCATTER_WORD)
+ p->MOV(GenReg::retype(value, GEN_TYPE_UW), GenReg::retype(dst, GEN_TYPE_UD));
+ else if (elemSize == GEN_BYTE_SCATTER_BYTE)
+ p->MOV(GenReg::retype(value, GEN_TYPE_UB), GenReg::retype(dst, GEN_TYPE_UD));
}
-
void GenContext::emitLoadInstruction(const ir::LoadInstruction &insn) {
using namespace ir;
const GenReg address = this->genReg(insn.getAddress());
this->emitByteGather(insn, address, value);
}
- void GenContext::emitStoreInstruction(const ir::StoreInstruction &insn) {
+ void GenContext::emitUntypedWrite(const ir::StoreInstruction &insn,
+ GenReg address,
+ GenReg value)
+ {
using namespace ir;
- GBE_ASSERT(insn.getAddressSpace() == MEM_GLOBAL);
- GBE_ASSERT(insn.getValueNum() == 1);
- GBE_ASSERT(insn.isAligned() == true);
- GBE_ASSERT(this->simdWidth <= 16);
- const GenReg address = this->genReg(insn.getAddress());
- const GenReg value = this->genReg(insn.getValue(0));
- // XXX remove that later. Now we just copy everything to GRFs to make it
- // contiguous
if (this->simdWidth == 8) {
p->MOV(GenReg::f8grf(112, 0), GenReg::retype(address, GEN_TYPE_F));
p->MOV(GenReg::f8grf(113, 0), GenReg::retype(value, GEN_TYPE_F));
} else
NOT_IMPLEMENTED;
}
+
+ void GenContext::emitByteScatter(const ir::StoreInstruction &insn,
+ GenReg address,
+ GenReg value)
+ {
+ using namespace ir;
+ const Type type = insn.getValueType();
+ const uint32_t elemSize = getByteScatterGatherSize(type);
+
+ if (this->simdWidth == 8) {
+ p->MOV(GenReg::f8grf(112, 0), GenReg::retype(address, GEN_TYPE_F));
+ if (elemSize == GEN_BYTE_SCATTER_DWORD)
+ p->MOV(GenReg::f8grf(113, 0), GenReg::retype(value, GEN_TYPE_F));
+ else if (elemSize == GEN_BYTE_SCATTER_WORD)
+ p->MOV(GenReg::ud8grf(113, 0), GenReg::retype(value, GEN_TYPE_UW));
+ else if (elemSize == GEN_BYTE_SCATTER_BYTE)
+ p->MOV(GenReg::ud8grf(113, 0), GenReg::retype(value, GEN_TYPE_UB));
+ p->BYTE_SCATTER(GenReg::f8grf(112, 0), 0, elemSize);
+ } else if (this->simdWidth == 16) {
+ p->MOV(GenReg::f16grf(112, 0), GenReg::retype(address, GEN_TYPE_F));
+ if (elemSize == GEN_BYTE_SCATTER_DWORD)
+ p->MOV(GenReg::f16grf(114, 0), GenReg::retype(value, GEN_TYPE_F));
+ else if (elemSize == GEN_BYTE_SCATTER_WORD)
+ p->MOV(GenReg::ud16grf(114, 0), GenReg::retype(value, GEN_TYPE_UW));
+ else if (elemSize == GEN_BYTE_SCATTER_BYTE)
+ p->MOV(GenReg::ud16grf(114, 0), GenReg::retype(value, GEN_TYPE_UB));
+ p->BYTE_SCATTER(GenReg::f16grf(112, 0), 0, elemSize);
+ } else
+ NOT_IMPLEMENTED;
+ }
+
+ void GenContext::emitStoreInstruction(const ir::StoreInstruction &insn) {
+ using namespace ir;
+ GBE_ASSERT(insn.getAddressSpace() == MEM_GLOBAL);
+ GBE_ASSERT(insn.getValueNum() == 1);
+ const GenReg address = this->genReg(insn.getAddress());
+ const GenReg value = this->genReg(insn.getValue(0));
+ if (insn.isAligned() == true)
+ this->emitUntypedWrite(insn, address, value);
+ else
+ this->emitByteScatter(insn, address, value);
+ }
+
void GenContext::emitFenceInstruction(const ir::FenceInstruction &insn) {}
void GenContext::emitLabelInstruction(const ir::LabelInstruction &insn) {
const ir::LabelIndex label = insn.getLabelIndex();
return 2;
case GEN_TYPE_UB:
case GEN_TYPE_B:
- return 1;
+ return 2;
default:
return 0;
}
static INLINE GenReg uw1(uint32_t file, uint32_t nr, uint32_t subnr) {
return suboffset(retype(vec1(file, nr, 0), GEN_TYPE_UW), subnr);
}
-
+#if 0
static INLINE GenReg ub16(uint32_t file, uint32_t nr, uint32_t subnr) {
return GenReg(file,
nr,
static INLINE GenReg ub1(uint32_t file, uint32_t nr, uint32_t subnr) {
return suboffset(retype(vec1(file, nr, 0), GEN_TYPE_UB), subnr);
}
+#else
+ static INLINE GenReg ub16(uint32_t file, uint32_t nr, uint32_t subnr) {
+ return suboffset(retype(vec16(file, nr, 0), GEN_TYPE_UW), subnr);
+ }
+
+ static INLINE GenReg ub8(uint32_t file, uint32_t nr, uint32_t subnr) {
+ return suboffset(retype(vec8(file, nr, 0), GEN_TYPE_UW), subnr);
+ }
+
+ static INLINE GenReg ub1(uint32_t file, uint32_t nr, uint32_t subnr) {
+ return suboffset(retype(vec1(file, nr, 0), GEN_TYPE_UW), subnr);
+ }
+#endif
static INLINE GenReg imm(uint32_t type) {
return GenReg(GEN_IMMEDIATE_VALUE,
return vec16(GEN_GENERAL_REGISTER_FILE, nr, subnr);
}
+ static INLINE GenReg ud16grf(uint32_t nr, uint32_t subnr) {
+ return ud16(GEN_GENERAL_REGISTER_FILE, nr, subnr);
+ }
+
static INLINE GenReg ud8grf(uint32_t nr, uint32_t subnr) {
return ud8(GEN_GENERAL_REGISTER_FILE, nr, subnr);
}
/*! Untyped write (upto 4 channels) */
void UNTYPED_WRITE(GenReg src, uint32_t bti, uint32_t elemNum);
/*! Byte gather (for unaligned bytes, shorts and ints) */
- void BYTE_GATHER(GenReg dst, GenReg src, uint32_t bti, uint32_t type);
+ void BYTE_GATHER(GenReg dst, GenReg src, uint32_t bti, uint32_t elemSize);
/*! Byte scatter (for unaligned bytes, shorts and ints) */
- void BYTE_SCATTER(GenReg src, uint32_t bti, uint32_t type);
+ void BYTE_SCATTER(GenReg src, uint32_t bti, uint32_t elemSize);
/*! Send instruction for the sampler */
void SAMPLE(GenReg dest,
uint32_t msg_reg_nr,