From 088c01c11b798f96008e682531d6f758083f6018 Mon Sep 17 00:00:00 2001 From: Homer Hsing Date: Wed, 14 Aug 2013 09:40:33 +0800 Subject: [PATCH] support 64bit-integer comparing support 64bit-integer comparing, including EQ(==), NEQ(!=), G(>), GE(>=), L(<), LE(<=) Signed-off-by: Homer Hsing Reviwed-by: Zhigang Gong --- backend/src/backend/gen_context.cpp | 77 ++++++++++++++++++++++ backend/src/backend/gen_context.hpp | 2 + .../src/backend/gen_insn_gen7_schedule_info.hxx | 1 + backend/src/backend/gen_insn_selection.cpp | 19 +++++- backend/src/backend/gen_insn_selection.hxx | 1 + 5 files changed, 99 insertions(+), 1 deletion(-) diff --git a/backend/src/backend/gen_context.cpp b/backend/src/backend/gen_context.cpp index 4246423..364ed1d 100644 --- a/backend/src/backend/gen_context.cpp +++ b/backend/src/backend/gen_context.cpp @@ -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(); diff --git a/backend/src/backend/gen_context.hpp b/backend/src/backend/gen_context.hpp index 9e7b384..8b481d0 100644 --- a/backend/src/backend/gen_context.hpp +++ b/backend/src/backend/gen_context.hpp @@ -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); diff --git a/backend/src/backend/gen_insn_gen7_schedule_info.hxx b/backend/src/backend/gen_insn_gen7_schedule_info.hxx index 7f214ac..2204837 100644 --- a/backend/src/backend/gen_insn_gen7_schedule_info.hxx +++ b/backend/src/backend/gen_insn_gen7_schedule_info.hxx @@ -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) diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp index b0dada0..7d579f8 100644 --- a/backend/src/backend/gen_insn_selection.cpp +++ b/backend/src/backend/gen_insn_selection.cpp @@ -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; } diff --git a/backend/src/backend/gen_insn_selection.hxx b/backend/src/backend/gen_insn_selection.hxx index 6ef50b8..cf974af 100644 --- a/backend/src/backend/gen_insn_selection.hxx +++ b/backend/src/backend/gen_insn_selection.hxx @@ -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) -- 2.7.4