support 64bit-integer comparing
authorHomer Hsing <homer.xing@intel.com>
Wed, 14 Aug 2013 01:40:33 +0000 (09:40 +0800)
committerZhigang Gong <zhigang.gong@linux.intel.com>
Wed, 14 Aug 2013 08:08:49 +0000 (16:08 +0800)
support 64bit-integer comparing,
including EQ(==), NEQ(!=), G(>), GE(>=), L(<), LE(<=)

Signed-off-by: Homer Hsing <homer.xing@intel.com>
Reviwed-by: Zhigang Gong <zhigang.gong@linux.intel.com>
backend/src/backend/gen_context.cpp
backend/src/backend/gen_context.hpp
backend/src/backend/gen_insn_gen7_schedule_info.hxx
backend/src/backend/gen_insn_selection.cpp
backend/src/backend/gen_insn_selection.hxx

index 4246423..364ed1d 100644 (file)
@@ -498,6 +498,83 @@ namespace gbe
     }
   }
 
+  void GenContext::saveFlag(GenRegister dest, int flag, int subFlag) {
+    p->push();
+    p->curr.execWidth = 1;
+    p->MOV(dest, GenRegister::flag(flag, subFlag));
+    p->pop();
+  }
+
+  void GenContext::emitI64CompareInstruction(const SelectionInstruction &insn) {
+    GenRegister src0 = ra->genReg(insn.src(0));
+    GenRegister src1 = ra->genReg(insn.src(1));
+    GenRegister tmp0 = ra->genReg(insn.dst(0));
+    GenRegister tmp1 = ra->genReg(insn.dst(1));
+    GenRegister tmp2 = ra->genReg(insn.dst(2));
+    tmp0.type = (src0.type == GEN_TYPE_L) ? GEN_TYPE_D : GEN_TYPE_UD;
+    tmp1.type = (src1.type == GEN_TYPE_L) ? GEN_TYPE_D : GEN_TYPE_UD;
+    int flag = p->curr.flag, subFlag = p->curr.subFlag;
+    GenRegister f1 = GenRegister::retype(tmp2, GEN_TYPE_UW),
+                f2 = GenRegister::suboffset(f1, 1),
+                f3 = GenRegister::suboffset(f1, 2);
+    p->push();
+    p->curr.predicate = GEN_PREDICATE_NONE;
+    p->curr.flag = 0, p->curr.subFlag = 1;
+    loadTopHalf(tmp0, src0);
+    loadTopHalf(tmp1, src1);
+    switch(insn.extra.function) {
+      case GEN_CONDITIONAL_L:
+      case GEN_CONDITIONAL_LE:
+      case GEN_CONDITIONAL_G:
+      case GEN_CONDITIONAL_GE:
+        {
+          int cmpTopHalf = insn.extra.function;
+          if(insn.extra.function == GEN_CONDITIONAL_LE)
+            cmpTopHalf = GEN_CONDITIONAL_L;
+          if(insn.extra.function == GEN_CONDITIONAL_GE)
+            cmpTopHalf = GEN_CONDITIONAL_G;
+          p->CMP(cmpTopHalf, tmp0, tmp1);
+        }
+        saveFlag(f1, 0, 1);
+        p->CMP(GEN_CONDITIONAL_EQ, tmp0, tmp1);
+        saveFlag(f2, 0, 1);
+        tmp0.type = tmp1.type = GEN_TYPE_UD;
+        loadBottomHalf(tmp0, src0);
+        loadBottomHalf(tmp1, src1);
+        p->CMP(insn.extra.function, tmp0, tmp1);
+        saveFlag(f3, 0, 1);
+        p->AND(f2, f2, f3);
+        p->OR(f1, f1, f2);
+        break;
+      case GEN_CONDITIONAL_EQ:
+        p->CMP(GEN_CONDITIONAL_EQ, tmp0, tmp1);
+        saveFlag(f1, 0, 1);
+        tmp0.type = tmp1.type = GEN_TYPE_UD;
+        loadBottomHalf(tmp0, src0);
+        loadBottomHalf(tmp1, src1);
+        p->CMP(GEN_CONDITIONAL_EQ, tmp0, tmp1);
+        saveFlag(f2, 0, 1);
+        p->AND(f1, f1, f2);
+        break;
+      case GEN_CONDITIONAL_NEQ:
+        p->CMP(GEN_CONDITIONAL_NEQ, tmp0, tmp1);
+        saveFlag(f1, 0, 1);
+        tmp0.type = tmp1.type = GEN_TYPE_UD;
+        loadBottomHalf(tmp0, src0);
+        loadBottomHalf(tmp1, src1);
+        p->CMP(GEN_CONDITIONAL_NEQ, tmp0, tmp1);
+        saveFlag(f2, 0, 1);
+        p->OR(f1, f1, f2);
+        break;
+      default:
+        NOT_IMPLEMENTED;
+    }
+    saveFlag(f2, flag, subFlag);
+    p->AND(f1, f1, f2);
+    p->MOV(GenRegister::flag(flag, subFlag), f1);
+    p->pop();
+  }
+
   void GenContext::loadTopHalf(GenRegister dest, GenRegister src) {
     int execWidth = p->curr.execWidth;
     src = src.top_half();
index 9e7b384..8b481d0 100644 (file)
@@ -86,6 +86,7 @@ namespace gbe
     void addWithCarry(GenRegister dest, GenRegister src0, GenRegister src1);
     void subWithBorrow(GenRegister dest, GenRegister src0, GenRegister src1);
     void I32FullMult(GenRegister high, GenRegister low, GenRegister src0, GenRegister src1);
+    void saveFlag(GenRegister dest, int flag, int subFlag);
 
     /*! Final Gen ISA emission helper functions */
     void emitLabelInstruction(const SelectionInstruction &insn);
@@ -95,6 +96,7 @@ namespace gbe
     void emitBinaryWithTempInstruction(const SelectionInstruction &insn);
     void emitTernaryInstruction(const SelectionInstruction &insn);
     void emitI64ShiftInstruction(const SelectionInstruction &insn);
+    void emitI64CompareInstruction(const SelectionInstruction &insn);
     void emitCompareInstruction(const SelectionInstruction &insn);
     void emitJumpInstruction(const SelectionInstruction &insn);
     void emitIndirectMoveInstruction(const SelectionInstruction &insn);
index 7f214ac..2204837 100644 (file)
@@ -7,6 +7,7 @@ DECL_GEN7_SCHEDULE(BinaryWithTemp,  20,        4,        2)
 DECL_GEN7_SCHEDULE(Ternary,         20,        4,        2)
 DECL_GEN7_SCHEDULE(I64Shift,        20,        4,        2)
 DECL_GEN7_SCHEDULE(Compare,         20,        4,        2)
+DECL_GEN7_SCHEDULE(I64Compare,      20,        4,        2)
 DECL_GEN7_SCHEDULE(Jump,            14,        1,        1)
 DECL_GEN7_SCHEDULE(IndirectMove,    20,        2,        2)
 DECL_GEN7_SCHEDULE(Eot,             20,        1,        1)
index b0dada0..7d579f8 100644 (file)
@@ -469,6 +469,8 @@ namespace gbe
 #undef I64Shift
     /*! Shift a 64-bit integer */
     void I64Shift(SelectionOpcode opcode, Reg dst, Reg src0, Reg src1, GenRegister tmp[6]);
+    /*! Compare 64-bit integer */
+    void I64CMP(uint32_t conditional, Reg src0, Reg src1, GenRegister tmp[3]);
     /*! Encode a barrier instruction */
     void BARRIER(GenRegister src);
     /*! Encode a barrier instruction */
@@ -1050,6 +1052,15 @@ namespace gbe
     insn->src(2) = src2;
   }
 
+  void Selection::Opaque::I64CMP(uint32_t conditional, Reg src0, Reg src1, GenRegister tmp[3]) {
+    SelectionInstruction *insn = this->appendInsn(SEL_OP_I64CMP, 3, 2);
+    insn->src(0) = src0;
+    insn->src(1) = src1;
+    for(int i=0; i<3; i++)
+      insn->dst(i) = tmp[i];
+    insn->extra.function = conditional;
+  }
+
   void Selection::Opaque::I64Shift(SelectionOpcode opcode, Reg dst, Reg src0, Reg src1, GenRegister tmp[6]) {
     SelectionInstruction *insn = this->appendInsn(opcode, 7, 2);
     insn->dst(0) = dst;
@@ -2293,7 +2304,13 @@ namespace gbe
       sel.push();
         sel.curr.physicalFlag = 0;
         sel.curr.flagIndex = uint16_t(dst);
-        sel.CMP(genCmp, src0, src1);
+        if (type == TYPE_S64 || type == TYPE_U64) {
+          GenRegister tmp[3];
+          for(int i=0; i<3; i++)
+            tmp[i] = sel.selReg(sel.reg(FAMILY_DWORD));
+          sel.I64CMP(genCmp, src0, src1, tmp);
+        } else
+          sel.CMP(genCmp, src0, src1);
       sel.pop();
       return true;
     }
index 6ef50b8..cf974af 100644 (file)
@@ -34,6 +34,7 @@ DECL_SELECTION_IR(I64MUL, I64MULInstruction)
 DECL_SELECTION_IR(ATOMIC, AtomicInstruction)
 DECL_SELECTION_IR(MACH, BinaryInstruction)
 DECL_SELECTION_IR(CMP, CompareInstruction)
+DECL_SELECTION_IR(I64CMP, I64CompareInstruction)
 DECL_SELECTION_IR(SEL_CMP, CompareInstruction)
 DECL_SELECTION_IR(MAD, TernaryInstruction)
 DECL_SELECTION_IR(JMPI, JumpInstruction)