case SEL_OP_RNDU: p->RNDU(dst, src); break;
case SEL_OP_RNDE: p->RNDE(dst, src); break;
case SEL_OP_RNDZ: p->RNDZ(dst, src); break;
+ case SEL_OP_LOAD_INT64_IMM: p->LOAD_INT64_IMM(dst, src.value.i64); break;
default: NOT_IMPLEMENTED;
}
}
MOV(dest, src0);
}
+ void GenEncoder::LOAD_INT64_IMM(GenRegister dest, int64_t value) {
+ GenRegister u0 = GenRegister::immd((int)value), u1 = GenRegister::immd(value >> 32);
+ int execWidth = curr.execWidth;
+ push();
+ curr.execWidth = 8;
+ for(int nib = 0; nib < execWidth/4; nib ++) {
+ curr.chooseNib(nib);
+ MOV(dest.top_half(), u1);
+ MOV(dest.bottom_half(), u0);
+ dest = GenRegister::suboffset(dest, 4);
+ }
+ pop();
+ }
+
void GenEncoder::MOV_DF(GenRegister dest, GenRegister src0, GenRegister r) {
int w = curr.execWidth;
if (src0.isdf()) {
#undef ALU3
void MOV_DF(GenRegister dest, GenRegister src0, GenRegister tmp = GenRegister::null());
void LOAD_DF_IMM(GenRegister dest, GenRegister tmp, double value);
+ void LOAD_INT64_IMM(GenRegister dest, int64_t value);
/*! Barrier message (to synchronize threads of a workgroup) */
void BARRIER(GenRegister src);
/*! Memory fence message (to order loads and stores between threads) */
ALU1(MOV)
ALU2(MOV_DF)
ALU2(LOAD_DF_IMM)
+ ALU1(LOAD_INT64_IMM)
ALU1(RNDZ)
ALU1(RNDE)
ALU2(SEL)
case TYPE_U8: sel.MOV(dst, GenRegister::immuw(imm.data.u8)); break;
case TYPE_S8: sel.MOV(dst, GenRegister::immw(imm.data.s8)); break;
case TYPE_DOUBLE: sel.LOAD_DF_IMM(dst, GenRegister::immdf(imm.data.f64), sel.selReg(sel.reg(FAMILY_QWORD))); break;
+ case TYPE_S64: sel.LOAD_INT64_IMM(dst, GenRegister::immint64(imm.data.s64)); break;
+ case TYPE_U64: sel.LOAD_INT64_IMM(dst, GenRegister::immint64(imm.data.u64)); break;
default: NOT_SUPPORTED;
}
sel.pop();
DECL_SELECTION_IR(MOV, UnaryInstruction)
DECL_SELECTION_IR(MOV_DF, BinaryInstruction)
DECL_SELECTION_IR(LOAD_DF_IMM, BinaryInstruction)
+DECL_SELECTION_IR(LOAD_INT64_IMM, UnaryInstruction)
DECL_SELECTION_IR(NOT, UnaryInstruction)
DECL_SELECTION_IR(LZD, UnaryInstruction)
DECL_SELECTION_IR(RNDZ, UnaryInstruction)
uint32_t predicate:4;
uint32_t inversePredicate:1;
uint32_t saturate:1;
+ void chooseNib(int nib) {
+ switch (nib) {
+ case 0:
+ quarterControl = 0;
+ nibControl = 0;
+ break;
+ case 1:
+ quarterControl = 0;
+ nibControl = 1;
+ break;
+ case 2:
+ quarterControl = 1;
+ nibControl = 0;
+ break;
+ case 3:
+ quarterControl = 1;
+ nibControl = 1;
+ break;
+ default:
+ NOT_IMPLEMENTED;
+ }
+ }
};
/*! This is a book-keeping structure used to encode both virtual and physical
int32_t d;
uint32_t ud;
uint16_t reg;
+ int64_t i64;
} value;
uint32_t nr:8; //!< Just for some physical registers (acc, null)
GEN_HORIZONTAL_STRIDE_0);
}
+ static INLINE GenRegister immint64(int64_t i) {
+ GenRegister immediate = imm(GEN_TYPE_L);
+ immediate.value.i64 = i;
+ return immediate;
+ }
+
static INLINE GenRegister immdf(double df) {
GenRegister immediate = imm(GEN_TYPE_DF);
immediate.value.df = df;