summaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
authorJunyan He <junyan.he@linux.intel.com>2015-09-18 17:58:20 +0800
committerYang Rong <rong.r.yang@intel.com>2015-10-27 15:52:50 +0800
commita89ee97da992c3eb38b2ba1ed73ff824b02de304 (patch)
tree93e2663fba300d14218120cb7d8124420ef53e40 /backend
parent2da100f0739ee0035ceda2eba2143a076a6dc789 (diff)
Backend: Implement FDIV64 on BDW.
According to the document, we use a set of instructions to implement double type division. Here, we specially take care of uniform register. The madm and invm instructions both work in align16 mode and uniform register can not be used directly. So we need to allocate a tmp register and mov the uniform src to it. Align16 mode's channel mask is different from the align1, So we can not directly write the result to the dst, and need a tmp register to hold the result and MOV it to dst later. Signed-off-by: Junyan He <junyan.he@linux.intel.com> Reviewed-by: Yang Rong <rong.r.yang@intel.com>
Diffstat (limited to 'backend')
-rw-r--r--backend/src/backend/gen8_context.cpp145
-rw-r--r--backend/src/backend/gen8_context.hpp2
2 files changed, 147 insertions, 0 deletions
diff --git a/backend/src/backend/gen8_context.cpp b/backend/src/backend/gen8_context.cpp
index 83235c02..5b1529d6 100644
--- a/backend/src/backend/gen8_context.cpp
+++ b/backend/src/backend/gen8_context.cpp
@@ -987,6 +987,151 @@ namespace gbe
this->unpackLongVec(src, dst, p->curr.execWidth);
}
+ void Gen8Context::emitF64DIVInstruction(const SelectionInstruction &insn) {
+ /* Macro for Double Precision IEEE Compliant fdiv
+
+ Set Rounding Mode in CR to RNE
+ GRF are initialized: r0 = 0, r6 = a, r7 = b, r1 = 1
+ The default data type for the macro is :df
+
+ math.eo.f0.0 (4) r8.acc2 r6.noacc r7.noacc 0xE
+ (-f0.0) if
+ madm (4) r9.acc3 r0.noacc r6.noacc r8.acc2 // Step(1), q0=a*y0
+ madm (4) r10.acc4 r1.noacc -r7.noacc r8.acc2 // Step(2), e0=(1-b*y0)
+ madm (4) r11.acc5 r6.noacc -r7.noacc r9.acc3 // Step(3), r0=a-b*q0
+ madm (4) r12.acc6 r8.acc2 r10.acc4 r8.acc2 // Step(4), y1=y0+e0*y0
+ madm (4) r13.acc7 r1.noacc -r7.noacc r12.acc6 // Step(5), e1=(1-b*y1)
+ madm (4) r8.acc8 r8.acc2 r10.acc4 r12.acc6 // Step(6), y2=y0+e0*y1
+ madm (4) r9.acc9 r9.acc3 r11.acc5 r12.acc6 // Step(7), q1=q0+r0*y1
+ madm (4) r12.acc2 r12.acc6 r8.acc8 r13.acc7 // Step(8), y3=y1+e1*y2
+ madm (4) r11.acc3 r6.noacc -r7.noacc r9.acc9 // Step(9), r1=a-b*q1
+
+ Change Rounding Mode in CR if required
+ Implicit Accumulator for destination is NULL
+
+ madm (4) r8.noacc r9.acc9 r11.acc3 r12.acc2 // Step(10), q=q1+r1*y3
+ endif */
+ GenRegister src0 = GenRegister::retype(ra->genReg(insn.src(0)), GEN_TYPE_DF);
+ GenRegister src1 = GenRegister::retype(ra->genReg(insn.src(1)), GEN_TYPE_DF);
+ GenRegister dst = GenRegister::retype(ra->genReg(insn.dst(0)), GEN_TYPE_DF);
+ GenRegister r6 , r7, r8;
+ int src0Stride = 1;
+ int src1Stride = 1;
+ int tmpNum = 7;
+ int loopNum = 0;
+
+ if (dst.hstride == GEN_HORIZONTAL_STRIDE_0) {// dst is uniform
+ loopNum = 1;
+ } else if (p->curr.execWidth == 4) {
+ loopNum = 1;
+ } else if (p->curr.execWidth == 8) {
+ loopNum = 2;
+ } else if (p->curr.execWidth == 16) {
+ loopNum = 4;
+ } else
+ GBE_ASSERT(0);
+
+ r8 = GenRegister::retype(ra->genReg(insn.dst(tmpNum + 1)), GEN_TYPE_DF);
+ tmpNum++;
+
+ if (src0.vstride == GEN_HORIZONTAL_STRIDE_0) {
+ r6 = GenRegister::retype(ra->genReg(insn.dst(tmpNum + 1)), GEN_TYPE_DF);
+ tmpNum++;
+ src0Stride = 0;
+ p->push(); {
+ p->curr.execWidth = 4;
+ p->curr.predicate = GEN_PREDICATE_NONE;
+ p->curr.noMask= 1;
+ p->MOV(r6, src0);
+ } p->pop();
+ } else {
+ r6 = src0;
+ }
+
+ if (src1.vstride == GEN_HORIZONTAL_STRIDE_0) {
+ r7 = GenRegister::retype(ra->genReg(insn.dst(tmpNum + 1)), GEN_TYPE_DF);
+ tmpNum++;
+ src1Stride = 0;
+ p->push(); {
+ p->curr.execWidth = 4;
+ p->curr.predicate = GEN_PREDICATE_NONE;
+ p->curr.noMask = 1;
+ p->MOV(r7, src1);
+ } p->pop();
+ } else {
+ r7 = src1;
+ }
+
+ const GenRegister r0 = GenRegister::retype(ra->genReg(insn.dst(1)), GEN_TYPE_DF);
+ const GenRegister r1 = GenRegister::retype(ra->genReg(insn.dst(2)), GEN_TYPE_DF);
+ const GenRegister r9 = GenRegister::retype(ra->genReg(insn.dst(3)), GEN_TYPE_DF);
+ const GenRegister r10 = GenRegister::retype(ra->genReg(insn.dst(4)), GEN_TYPE_DF);
+ const GenRegister r11 = GenRegister::retype(ra->genReg(insn.dst(5)), GEN_TYPE_DF);
+ const GenRegister r12 = GenRegister::retype(ra->genReg(insn.dst(6)), GEN_TYPE_DF);
+ const GenRegister r13 = GenRegister::retype(ra->genReg(insn.dst(7)), GEN_TYPE_DF);
+ Gen8Encoder *p8 = reinterpret_cast<Gen8Encoder *>(p);
+ p->push(); {
+ p->curr.execWidth = 4;
+ p->curr.predicate = GEN_PREDICATE_NONE;
+ p->curr.noMask= 1;
+ p->MOV(r1, GenRegister::immdf(1.0d));
+ p->MOV(r0, GenRegister::immdf(0.0d));
+ } p->pop();
+
+ for (int i = 0; i < loopNum; i++) {
+ p->push(); {
+ p->curr.noMask= 1;
+ p->curr.execWidth = 4;
+ p->curr.predicate = GEN_PREDICATE_NONE;
+ p8->MATH_WITH_ACC(r8, GEN8_MATH_FUNCTION_INVM, r6, r7, GEN8_INSN_ACC2, GEN8_INSN_NOACC, GEN8_INSN_NOACC);
+ p->curr.useFlag(insn.state.flag, insn.state.subFlag);
+ p->curr.predicate = GEN_PREDICATE_NORMAL;
+ p->curr.inversePredicate = 1;
+ p8->MADM(r9, r0, r6, r8, GEN8_INSN_ACC3, GEN8_INSN_NOACC, GEN8_INSN_NOACC, GEN8_INSN_ACC2);
+ p8->MADM(r10, r1, GenRegister::negate(r7), r8, GEN8_INSN_ACC4, GEN8_INSN_NOACC, GEN8_INSN_NOACC, GEN8_INSN_ACC2);
+ p8->MADM(r11, r6, GenRegister::negate(r7), r9, GEN8_INSN_ACC5, GEN8_INSN_NOACC, GEN8_INSN_NOACC, GEN8_INSN_ACC3);
+ p8->MADM(r12, r8, r10, r8, GEN8_INSN_ACC6, GEN8_INSN_ACC2, GEN8_INSN_ACC4, GEN8_INSN_ACC2);
+ p8->MADM(r13, r1, GenRegister::negate(r7), r12, GEN8_INSN_ACC7, GEN8_INSN_NOACC, GEN8_INSN_NOACC, GEN8_INSN_ACC6);
+ p8->MADM(r8, r8, r10, r12, GEN8_INSN_ACC8, GEN8_INSN_ACC2, GEN8_INSN_ACC4, GEN8_INSN_ACC6);
+ p8->MADM(r9, r9, r11, r12, GEN8_INSN_ACC9, GEN8_INSN_ACC3, GEN8_INSN_ACC5, GEN8_INSN_ACC6);
+ p8->MADM(r12, r12, r8, r13, GEN8_INSN_ACC2, GEN8_INSN_ACC6, GEN8_INSN_ACC8, GEN8_INSN_ACC7);
+ p8->MADM(r11, r6, GenRegister::negate(r7), r9, GEN8_INSN_ACC3, GEN8_INSN_NOACC, GEN8_INSN_NOACC, GEN8_INSN_ACC9);
+
+ p8->MADM(r8, r9, r11, r12, GEN8_INSN_NOACC, GEN8_INSN_ACC9, GEN8_INSN_ACC3, GEN8_INSN_ACC2);
+ } p->pop();
+
+ r6 = GenRegister::offset(r6, src0Stride);
+ r7 = GenRegister::offset(r7, src1Stride);
+
+ /* Move back the result. */
+ if (dst.hstride == GEN_HORIZONTAL_STRIDE_0) {// dst is uniform
+ p->push(); {
+ p->curr.execWidth = 1;
+ r8.hstride = GEN_HORIZONTAL_STRIDE_0;
+ r8.vstride = GEN_VERTICAL_STRIDE_0;
+ r8.width = GEN_WIDTH_1;
+ p->MOV(dst, r8);
+ } p->pop();
+ break;
+ } else {
+ p->push(); {
+ p->curr.execWidth = 4;
+ if (i % 2 == 0)
+ p->curr.nibControl = 0;
+ else
+ p->curr.nibControl = 1;
+
+ if (i < 2)
+ p->curr.quarterControl = GEN_COMPRESSION_Q1;
+ else
+ p->curr.quarterControl = GEN_COMPRESSION_Q2;
+
+ p->MOV(GenRegister::offset(dst, i), r8);
+ } p->pop();
+ }
+ }
+ }
+
void Gen8Context::setA0Content(uint16_t new_a0[16], uint16_t max_offset, int sz) {
if (sz == 0)
sz = 16;
diff --git a/backend/src/backend/gen8_context.hpp b/backend/src/backend/gen8_context.hpp
index 84508e95..386f7f30 100644
--- a/backend/src/backend/gen8_context.hpp
+++ b/backend/src/backend/gen8_context.hpp
@@ -74,6 +74,8 @@ namespace gbe
virtual void emitPackLongInstruction(const SelectionInstruction &insn);
virtual void emitUnpackLongInstruction(const SelectionInstruction &insn);
+ virtual void emitF64DIVInstruction(const SelectionInstruction &insn);
+
protected:
virtual void setA0Content(uint16_t new_a0[16], uint16_t max_offset = 0, int sz = 0);
virtual GenEncoder* generateEncoder(void) {