}
}
+ 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();
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);
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);
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)
#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 */
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;
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;
}
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)