Chromium Code Reviews| Index: src/IceInstX8632.cpp |
| diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp |
| index 5b77a37d2f4ef9a9f52eb644ea19b7452ae0c827..e68b8c5248b4846cb382723be6351040eefcff2c 100644 |
| --- a/src/IceInstX8632.cpp |
| +++ b/src/IceInstX8632.cpp |
| @@ -52,10 +52,11 @@ const struct TypeX8632Attributes_ { |
| const char *CvtString; // i (integer), s (single FP), d (double FP) |
| const char *SdSsString; // ss, sd, or <blank> |
| const char *PackString; // b, w, d, or <blank> |
| - const char *WidthString; // {byte,word,dword,qword} ptr |
| + const char *WidthString; // b, w, l, q, or <blank> |
| + const char *FldString; // s, l, or <blank> |
| } TypeX8632Attributes[] = { |
| -#define X(tag, elementty, cvt, sdss, pack, width) \ |
| - { cvt, "" sdss, pack, width } \ |
| +#define X(tag, elementty, cvt, sdss, pack, width, fld) \ |
| + { cvt, sdss, pack, width, fld } \ |
| , |
| ICETYPEX8632_TABLE |
| #undef X |
| @@ -79,6 +80,10 @@ const char *InstX8632::getWidthString(Type Ty) { |
| return TypeX8632Attributes[Ty].WidthString; |
| } |
| +const char *InstX8632::getFldString(Type Ty) { |
| + return TypeX8632Attributes[Ty].FldString; |
| +} |
| + |
| OperandX8632Mem::OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base, |
| Constant *Offset, Variable *Index, |
| uint16_t Shift, SegmentRegisters SegmentReg) |
| @@ -528,7 +533,14 @@ void InstX8632Call::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| assert(getSrcSize() == 1); |
| Str << "\tcall\t"; |
| - getCallTarget()->emit(Func); |
| + if (auto CallTarget = llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) { |
| + // TODO(stichnot): All constant targets should suppress the '$', |
| + // not just relocatables. |
| + CallTarget->emitWithoutDollar(Func->getContext()); |
| + } else { |
| + Str << "*"; |
| + getCallTarget()->emit(Func); |
| + } |
| Func->getTarget()->resetStackAdjustment(); |
| } |
| @@ -597,20 +609,17 @@ void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func, |
| bool ShiftHack) { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| assert(Inst->getSrcSize() == 2); |
| - assert(Inst->getDest() == Inst->getSrc(0)); |
| - Str << "\t" << Opcode << "\t"; |
| - Inst->getDest()->emit(Func); |
| + Variable *Dest = Inst->getDest(); |
| + assert(Dest == Inst->getSrc(0)); |
| + Operand *Src1 = Inst->getSrc(1); |
| + Str << "\t" << Opcode << InstX8632::getWidthString(Dest->getType()) << "\t"; |
| + Variable *ShiftReg = llvm::dyn_cast<Variable>(Src1); |
| + if (ShiftHack && ShiftReg && ShiftReg->getRegNum() == RegX8632::Reg_ecx) |
| + Str << "%cl"; |
| + else |
| + Src1->emit(Func); |
| Str << ", "; |
| - bool EmittedSrc1 = false; |
| - if (ShiftHack) { |
| - Variable *ShiftReg = llvm::dyn_cast<Variable>(Inst->getSrc(1)); |
| - if (ShiftReg && ShiftReg->getRegNum() == RegX8632::Reg_ecx) { |
| - Str << "cl"; |
| - EmittedSrc1 = true; |
| - } |
| - } |
| - if (!EmittedSrc1) |
| - Inst->getSrc(1)->emit(Func); |
| + Dest->emit(Func); |
| } |
| void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op, |
| @@ -942,8 +951,8 @@ template <> const char *InstX8632Bsf::Opcode = "bsf"; |
| template <> const char *InstX8632Bsr::Opcode = "bsr"; |
| template <> const char *InstX8632Lea::Opcode = "lea"; |
| template <> const char *InstX8632Movd::Opcode = "movd"; |
| -template <> const char *InstX8632Movsx::Opcode = "movsx"; |
| -template <> const char *InstX8632Movzx::Opcode = "movzx"; |
| +template <> const char *InstX8632Movsx::Opcode = "movs"; |
| +template <> const char *InstX8632Movzx::Opcode = "movz"; |
| template <> const char *InstX8632Sqrtss::Opcode = "sqrtss"; |
| template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq"; |
| // Mov-like ops |
| @@ -1154,9 +1163,9 @@ template <> void InstX8632Sqrtss::emit(const Cfg *Func) const { |
| Type Ty = getSrc(0)->getType(); |
| assert(isScalarFloatingType(Ty)); |
| Str << "\tsqrt" << TypeX8632Attributes[Ty].SdSsString << "\t"; |
| - getDest()->emit(Func); |
| - Str << ", "; |
| getSrc(0)->emit(Func); |
| + Str << ", "; |
| + getDest()->emit(Func); |
| } |
| template <> void InstX8632Addss::emit(const Cfg *Func) const { |
| @@ -1243,8 +1252,9 @@ template <> void InstX8632Divss::emit(const Cfg *Func) const { |
| template <> void InstX8632Div::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| assert(getSrcSize() == 3); |
| - Str << "\t" << Opcode << "\t"; |
| - getSrc(1)->emit(Func); |
| + Operand *Src1 = getSrc(1); |
| + Str << "\t" << Opcode << getWidthString(Src1->getType()) << "\t"; |
| + Src1->emit(Func); |
| } |
| template <> void InstX8632Div::emitIAS(const Cfg *Func) const { |
| @@ -1259,8 +1269,9 @@ template <> void InstX8632Div::emitIAS(const Cfg *Func) const { |
| template <> void InstX8632Idiv::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| assert(getSrcSize() == 3); |
| - Str << "\t" << Opcode << "\t"; |
| - getSrc(1)->emit(Func); |
| + Operand *Src1 = getSrc(1); |
| + Str << "\t" << Opcode << getWidthString(Src1->getType()) << "\t"; |
| + Src1->emit(Func); |
| } |
| template <> void InstX8632Idiv::emitIAS(const Cfg *Func) const { |
| @@ -1282,9 +1293,9 @@ void emitVariableBlendInst(const char *Opcode, const Inst *Inst, |
| assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == |
| RegX8632::Reg_xmm0); |
| Str << "\t" << Opcode << "\t"; |
| - Inst->getDest()->emit(Func); |
| - Str << ", "; |
| Inst->getSrc(1)->emit(Func); |
| + Str << ", "; |
| + Inst->getDest()->emit(Func); |
| } |
| void |
| @@ -1331,20 +1342,21 @@ template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const { |
| template <> void InstX8632Imul::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| assert(getSrcSize() == 2); |
| - if (isByteSizedArithType(getDest()->getType())) { |
| + Variable *Dest = getDest(); |
| + if (isByteSizedArithType(Dest->getType())) { |
| // The 8-bit version of imul only allows the form "imul r/m8". |
| Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0)); |
| (void)Src0; |
| assert(Src0 && Src0->getRegNum() == RegX8632::Reg_eax); |
| - Str << "\timul\t"; |
| + Str << "\timulb\t"; |
| getSrc(1)->emit(Func); |
| } else if (llvm::isa<Constant>(getSrc(1))) { |
| - Str << "\timul\t"; |
| - getDest()->emit(Func); |
| + Str << "\timul" << getWidthString(Dest->getType()) << "\t"; |
| + getSrc(1)->emit(Func); |
| Str << ", "; |
| getSrc(0)->emit(Func); |
| Str << ", "; |
| - getSrc(1)->emit(Func); |
| + Dest->emit(Func); |
| } else { |
| emitTwoAddress("imul", this, Func); |
| } |
| @@ -1401,15 +1413,15 @@ template <> void InstX8632Cbwdq::emit(const Cfg *Func) const { |
| break; |
| case IceType_i8: |
| assert(getDest()->getRegNum() == RegX8632::Reg_eax); |
| - Str << "\tcbw"; |
| + Str << "\tcbtw"; |
| break; |
| case IceType_i16: |
| assert(getDest()->getRegNum() == RegX8632::Reg_edx); |
| - Str << "\tcwd"; |
| + Str << "\tcwtd"; |
| break; |
| case IceType_i32: |
| assert(getDest()->getRegNum() == RegX8632::Reg_edx); |
| - Str << "\tcdq"; |
| + Str << "\tcltd"; |
| break; |
| } |
| } |
| @@ -1447,7 +1459,7 @@ void InstX8632Mul::emit(const Cfg *Func) const { |
| assert(llvm::isa<Variable>(getSrc(0))); |
| assert(llvm::dyn_cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); |
| assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? |
| - Str << "\tmul\t"; |
| + Str << "\tmul" << getWidthString(getDest()->getType()) << "\t"; |
| getSrc(1)->emit(Func); |
| } |
| @@ -1472,20 +1484,21 @@ void InstX8632Mul::dump(const Cfg *Func) const { |
| void InstX8632Shld::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| + Variable *Dest = getDest(); |
| assert(getSrcSize() == 3); |
| - assert(getDest() == getSrc(0)); |
| - Str << "\tshld\t"; |
| - getDest()->emit(Func); |
| - Str << ", "; |
| - getSrc(1)->emit(Func); |
| - Str << ", "; |
| + assert(Dest == getSrc(0)); |
| + Str << "\tshld" << getWidthString(Dest->getType()) << "\t"; |
| if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { |
| (void)ShiftReg; |
| assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); |
| - Str << "cl"; |
| + Str << "%cl"; |
| } else { |
| getSrc(2)->emit(Func); |
| } |
| + Str << ", "; |
| + getSrc(1)->emit(Func); |
| + Str << ", "; |
| + Dest->emit(Func); |
| } |
| void InstX8632Shld::emitIAS(const Cfg *Func) const { |
| @@ -1508,20 +1521,21 @@ void InstX8632Shld::dump(const Cfg *Func) const { |
| void InstX8632Shrd::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| + Variable *Dest = getDest(); |
| assert(getSrcSize() == 3); |
| - assert(getDest() == getSrc(0)); |
| - Str << "\tshrd\t"; |
| - getDest()->emit(Func); |
| - Str << ", "; |
| - getSrc(1)->emit(Func); |
| - Str << ", "; |
| + assert(Dest == getSrc(0)); |
| + Str << "\tshrd" << getWidthString(Dest->getType()) << "\t"; |
| if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { |
| (void)ShiftReg; |
| assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); |
| - Str << "cl"; |
| + Str << "%cl"; |
| } else { |
| getSrc(2)->emit(Func); |
| } |
| + Str << ", "; |
| + getSrc(1)->emit(Func); |
| + Str << ", "; |
| + Dest->emit(Func); |
| } |
| void InstX8632Shrd::emitIAS(const Cfg *Func) const { |
| @@ -1544,13 +1558,15 @@ void InstX8632Shrd::dump(const Cfg *Func) const { |
| void InstX8632Cmov::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| + Variable *Dest = getDest(); |
| Str << "\t"; |
| assert(Condition != CondX86::Br_None); |
| assert(getDest()->hasReg()); |
| - Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "\t"; |
| - getDest()->emit(Func); |
| - Str << ", "; |
| + Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString |
| + << getWidthString(Dest->getType()) << "\t"; |
| getSrc(1)->emit(Func); |
| + Str << ", "; |
| + Dest->emit(Func); |
| } |
| void InstX8632Cmov::emitIAS(const Cfg *Func) const { |
| @@ -1584,9 +1600,9 @@ void InstX8632Cmpps::emit(const Cfg *Func) const { |
| Str << "\t"; |
| Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" |
| << "\t"; |
| - getDest()->emit(Func); |
| - Str << ", "; |
| getSrc(1)->emit(Func); |
| + Str << ", "; |
| + getDest()->emit(Func); |
| } |
| void InstX8632Cmpps::emitIAS(const Cfg *Func) const { |
| @@ -1625,10 +1641,10 @@ void InstX8632Cmpxchg::emit(const Cfg *Func) const { |
| if (Locked) { |
| Str << "\tlock"; |
| } |
| - Str << "\tcmpxchg\t"; |
| - getSrc(0)->emit(Func); |
| - Str << ", "; |
| + Str << "\tcmpxchg" << getWidthString(getSrc(0)->getType()) << "\t"; |
| getSrc(2)->emit(Func); |
| + Str << ", "; |
| + getSrc(0)->emit(Func); |
| } |
| void InstX8632Cmpxchg::emitIAS(const Cfg *Func) const { |
| @@ -1701,9 +1717,9 @@ void InstX8632Cvt::emit(const Cfg *Func) const { |
| Str << "t"; |
| Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2" |
| << TypeX8632Attributes[getDest()->getType()].CvtString << "\t"; |
| - getDest()->emit(Func); |
| - Str << ", "; |
| getSrc(0)->emit(Func); |
| + Str << ", "; |
| + getDest()->emit(Func); |
| } |
| void InstX8632Cvt::emitIAS(const Cfg *Func) const { |
| @@ -1779,10 +1795,10 @@ void InstX8632Cvt::dump(const Cfg *Func) const { |
| void InstX8632Icmp::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| assert(getSrcSize() == 2); |
| - Str << "\tcmp\t"; |
| - getSrc(0)->emit(Func); |
| - Str << ", "; |
| + Str << "\tcmp" << getWidthString(getSrc(0)->getType()) << "\t"; |
| getSrc(1)->emit(Func); |
| + Str << ", "; |
| + getSrc(0)->emit(Func); |
| } |
| void InstX8632Icmp::emitIAS(const Cfg *Func) const { |
| @@ -1816,9 +1832,9 @@ void InstX8632Ucomiss::emit(const Cfg *Func) const { |
| assert(getSrcSize() == 2); |
| Str << "\tucomi" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString |
| << "\t"; |
| - getSrc(0)->emit(Func); |
| - Str << ", "; |
| getSrc(1)->emit(Func); |
| + Str << ", "; |
| + getSrc(0)->emit(Func); |
| } |
| void InstX8632Ucomiss::emitIAS(const Cfg *Func) const { |
| @@ -1861,10 +1877,10 @@ void InstX8632UD2::dump(const Cfg *Func) const { |
| void InstX8632Test::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| assert(getSrcSize() == 2); |
| - Str << "\ttest\t"; |
| - getSrc(0)->emit(Func); |
| - Str << ", "; |
| + Str << "\ttest" << getWidthString(getSrc(0)->getType()) << "\t"; |
| getSrc(1)->emit(Func); |
| + Str << ", "; |
| + getSrc(0)->emit(Func); |
| } |
| void InstX8632Test::emitIAS(const Cfg *Func) const { |
| @@ -1916,11 +1932,12 @@ void InstX8632Mfence::dump(const Cfg *Func) const { |
| void InstX8632Store::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| assert(getSrcSize() == 2); |
| - Str << "\tmov" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString |
| + Type Ty = getSrc(0)->getType(); |
| + Str << "\tmov" << getWidthString(Ty) << TypeX8632Attributes[Ty].SdSsString |
| << "\t"; |
| - getSrc(1)->emit(Func); |
| - Str << ", "; |
| getSrc(0)->emit(Func); |
| + Str << ", "; |
| + getSrc(1)->emit(Func); |
| } |
| void InstX8632Store::emitIAS(const Cfg *Func) const { |
| @@ -1967,9 +1984,9 @@ void InstX8632StoreP::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| assert(getSrcSize() == 2); |
| Str << "\tmovups\t"; |
| - getSrc(1)->emit(Func); |
| - Str << ", "; |
| getSrc(0)->emit(Func); |
| + Str << ", "; |
| + getSrc(1)->emit(Func); |
| } |
| void InstX8632StoreP::emitIAS(const Cfg *Func) const { |
| @@ -1999,9 +2016,9 @@ void InstX8632StoreQ::emit(const Cfg *Func) const { |
| assert(getSrc(1)->getType() == IceType_i64 || |
| getSrc(1)->getType() == IceType_f64); |
| Str << "\tmovq\t"; |
| - getSrc(1)->emit(Func); |
| - Str << ", "; |
| getSrc(0)->emit(Func); |
| + Str << ", "; |
| + getSrc(1)->emit(Func); |
| } |
| void InstX8632StoreQ::emitIAS(const Cfg *Func) const { |
| @@ -2029,9 +2046,7 @@ template <> void InstX8632Lea::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| assert(getSrcSize() == 1); |
| assert(getDest()->hasReg()); |
| - Str << "\tlea\t"; |
| - getDest()->emit(Func); |
| - Str << ", "; |
| + Str << "\tleal\t"; |
| Operand *Src0 = getSrc(0); |
| if (Variable *VSrc0 = llvm::dyn_cast<Variable>(Src0)) { |
| Type Ty = VSrc0->getType(); |
| @@ -2041,32 +2056,19 @@ template <> void InstX8632Lea::emit(const Cfg *Func) const { |
| } else { |
| Src0->emit(Func); |
| } |
| + Str << ", "; |
| + getDest()->emit(Func); |
| } |
| template <> void InstX8632Mov::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| assert(getSrcSize() == 1); |
| Operand *Src = getSrc(0); |
| - // The llvm-mc assembler using Intel syntax has a bug in which "mov |
| - // reg, RelocatableConstant" does not generate the right instruction |
| - // with a relocation. To work around, we emit "lea reg, |
| - // RelocatableConstant". Also, the lowering and legalization is |
| - // changed to allow relocatable constants only in Assign and Call |
| - // instructions or in Mem operands. TODO(stichnot): remove LEAHACK |
| - // once a proper emitter is used. |
| - // |
| - // In addition, llvm-mc doesn't like "lea eax, bp" or "lea eax, Sp" |
| - // or "lea eax, flags" etc., when the relocatable constant name is a |
| - // reserved word. The hack-on-top-of-hack is to temporarily drop |
| - // into AT&T syntax for this lea instruction. |
| - bool UseLeaHack = llvm::isa<ConstantRelocatable>(Src); |
| - if (UseLeaHack) { |
| - Str << ".att_syntax\n"; |
| - Str << "\tleal"; |
| - } else { |
| - Str << "\tmov" << TypeX8632Attributes[getDest()->getType()].SdSsString; |
| - } |
| - Str << "\t"; |
| + Type SrcTy = Src->getType(); |
| + Type DestTy = getDest()->getType(); |
| + Str << "\tmov" << (!isScalarFloatingType(DestTy) |
| + ? getWidthString(SrcTy) |
| + : TypeX8632Attributes[DestTy].SdSsString) << "\t"; |
| // For an integer truncation operation, src is wider than dest. |
| // Ideally, we use a mov instruction whose data width matches the |
| // narrower dest. This is a problem if e.g. src is a register like |
| @@ -2077,19 +2079,11 @@ template <> void InstX8632Mov::emit(const Cfg *Func) const { |
| // TODO: This assert disallows usages such as copying a floating point |
| // value between a vector and a scalar (which movss is used for). |
| // Clean this up. |
| - assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) == |
| - Func->getTarget()->typeWidthInBytesOnStack(Src->getType())); |
| - if (UseLeaHack) { |
| - Src->emit(Func); |
| - Str << ", %"; |
| - getDest()->emit(Func); |
| - Str << "\n"; |
| - Str << ".intel_syntax"; |
| - } else { |
| - getDest()->asType(Src->getType()).emit(Func); |
| - Str << ", "; |
| - Src->emit(Func); |
| - } |
| + assert(Func->getTarget()->typeWidthInBytesOnStack(DestTy) == |
| + Func->getTarget()->typeWidthInBytesOnStack(SrcTy)); |
| + Src->emit(Func); |
| + Str << ", "; |
| + getDest()->asType(SrcTy).emit(Func); |
| } |
| template <> void InstX8632Mov::emitIAS(const Cfg *Func) const { |
| @@ -2206,9 +2200,9 @@ template <> void InstX8632Movp::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| assert(getSrcSize() == 1); |
| Str << "\tmovups\t"; |
| - getDest()->emit(Func); |
| - Str << ", "; |
| getSrc(0)->emit(Func); |
| + Str << ", "; |
| + getDest()->emit(Func); |
| } |
| template <> void InstX8632Movp::emitIAS(const Cfg *Func) const { |
| @@ -2229,9 +2223,9 @@ template <> void InstX8632Movq::emit(const Cfg *Func) const { |
| assert(getDest()->getType() == IceType_i64 || |
| getDest()->getType() == IceType_f64); |
| Str << "\tmovq\t"; |
| - getDest()->emit(Func); |
| - Str << ", "; |
| getSrc(0)->emit(Func); |
| + Str << ", "; |
| + getDest()->emit(Func); |
| } |
| template <> void InstX8632Movq::emitIAS(const Cfg *Func) const { |
| @@ -2307,21 +2301,22 @@ void InstX8632Fld::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| assert(getSrcSize() == 1); |
| Type Ty = getSrc(0)->getType(); |
| + SizeT Width = typeWidthInBytes(Ty); |
| Variable *Var = llvm::dyn_cast<Variable>(getSrc(0)); |
| if (Var && Var->hasReg()) { |
| // This is a physical xmm register, so we need to spill it to a |
| // temporary stack slot. |
| - SizeT Width = typeWidthInBytes(Ty); |
| - Str << "\tsub\tesp, " << Width << "\n"; |
| - Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" |
| - << TypeX8632Attributes[Ty].WidthString << " [esp], "; |
| + Str << "\tsubl\t$" << Width << ", %esp" |
| + << "\n"; |
|
jvoung (off chromium)
2014/10/31 22:12:18
\n could fit on the previous line next to %esp
Jim Stichnoth
2014/11/01 13:44:17
Done.
|
| + Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"; |
| Var->emit(Func); |
| - Str << "\n"; |
| - Str << "\tfld\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n"; |
| - Str << "\tadd\tesp, " << Width; |
| + Str << ", (%esp)\n"; |
| + Str << "\tfld" << getFldString(Ty) << "\t" |
| + << "(%esp)\n"; |
| + Str << "\taddl\t$" << Width << ", %esp"; |
| return; |
| } |
| - Str << "\tfld\t"; |
| + Str << "\tfld" << getFldString(Ty) << "\t"; |
| getSrc(0)->emit(Func); |
| } |
| @@ -2374,8 +2369,10 @@ void InstX8632Fstp::emit(const Cfg *Func) const { |
| Str << "\tfstp\tst(0)"; |
| return; |
| } |
| + Type Ty = getDest()->getType(); |
| + size_t Width = typeWidthInBytes(Ty); |
| if (!getDest()->hasReg()) { |
| - Str << "\tfstp\t"; |
| + Str << "\tfstp" << getFldString(Ty) << "\t"; |
| getDest()->emit(Func); |
| return; |
| } |
| @@ -2383,14 +2380,14 @@ void InstX8632Fstp::emit(const Cfg *Func) const { |
| // memory. Hack this by creating a temporary stack slot, spilling |
| // st(0) there, loading it into the xmm register, and deallocating |
| // the stack slot. |
| - Type Ty = getDest()->getType(); |
| - size_t Width = typeWidthInBytes(Ty); |
| - Str << "\tsub\tesp, " << Width << "\n"; |
| - Str << "\tfstp\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n"; |
| - Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"; |
| + Str << "\tsubl\t$" << Width << ", %esp\n"; |
| + Str << "\tfstp" << getFldString(Ty) << "\t" |
| + << "(%esp)\n"; |
|
jvoung (off chromium)
2014/10/31 22:12:18
nit: Could do the full fstp on one line like befor
Jim Stichnoth
2014/11/01 13:44:17
Done.
|
| + Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" |
| + << "(%esp), "; |
| getDest()->emit(Func); |
| - Str << ", " << TypeX8632Attributes[Ty].WidthString << " [esp]\n"; |
| - Str << "\tadd\tesp, " << Width; |
| + Str << "\n"; |
| + Str << "\taddl\t$" << Width << ", %esp"; |
| } |
| void InstX8632Fstp::emitIAS(const Cfg *Func) const { |
| @@ -2458,16 +2455,16 @@ template <> void InstX8632Pextr::emit(const Cfg *Func) const { |
| >= TargetX8632::SSE4_1); |
| Str << "\t" << Opcode |
| << TypeX8632Attributes[getSrc(0)->getType()].PackString << "\t"; |
| + getSrc(1)->emit(Func); |
| + Str << ", "; |
| + getSrc(0)->emit(Func); |
| + Str << ", "; |
| Variable *Dest = getDest(); |
| // pextrw must take a register dest. There is an SSE4.1 version that takes |
| // a memory dest, but we aren't using it. For uniformity, just restrict |
| // them all to have a register dest for now. |
| assert(Dest->hasReg()); |
| Dest->asType(IceType_i32).emit(Func); |
| - Str << ", "; |
| - getSrc(0)->emit(Func); |
| - Str << ", "; |
| - getSrc(1)->emit(Func); |
| } |
| template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const { |
| @@ -2502,7 +2499,7 @@ template <> void InstX8632Pinsr::emit(const Cfg *Func) const { |
| >= TargetX8632::SSE4_1); |
| Str << "\t" << Opcode |
| << TypeX8632Attributes[getDest()->getType()].PackString << "\t"; |
| - getDest()->emit(Func); |
| + getSrc(2)->emit(Func); |
| Str << ", "; |
| Operand *Src1 = getSrc(1); |
| if (Variable *VSrc1 = llvm::dyn_cast<Variable>(Src1)) { |
| @@ -2516,7 +2513,7 @@ template <> void InstX8632Pinsr::emit(const Cfg *Func) const { |
| Src1->emit(Func); |
| } |
| Str << ", "; |
| - getSrc(2)->emit(Func); |
| + getDest()->emit(Func); |
| } |
| template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const { |
| @@ -2593,7 +2590,7 @@ void InstX8632Pop::dump(const Cfg *Func) const { |
| void InstX8632AdjustStack::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| - Str << "\tsub\tesp, " << Amount; |
| + Str << "\tsubl\t$" << Amount << ", %esp"; |
| Func->getTarget()->updateStackAdjustment(Amount); |
| } |
| @@ -2683,10 +2680,10 @@ void InstX8632Xadd::emit(const Cfg *Func) const { |
| if (Locked) { |
| Str << "\tlock"; |
| } |
| - Str << "\txadd\t"; |
| - getSrc(0)->emit(Func); |
| - Str << ", "; |
| + Str << "\txadd" << getWidthString(getSrc(0)->getType()) << "\t"; |
| getSrc(1)->emit(Func); |
| + Str << ", "; |
| + getSrc(0)->emit(Func); |
| } |
| void InstX8632Xadd::emitIAS(const Cfg *Func) const { |
| @@ -2721,9 +2718,9 @@ void InstX8632Xadd::dump(const Cfg *Func) const { |
| void InstX8632Xchg::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| Str << "\txchg\t"; |
|
jvoung (off chromium)
2014/10/31 22:12:18
I'm surprised this doesn't have the getWidthString
Jim Stichnoth
2014/11/01 13:44:16
Good point. It turns out that for both llvm-mc an
|
| - getSrc(0)->emit(Func); |
| - Str << ", "; |
| getSrc(1)->emit(Func); |
| + Str << ", "; |
| + getSrc(0)->emit(Func); |
| } |
| void InstX8632Xchg::emitIAS(const Cfg *Func) const { |
| @@ -2751,49 +2748,36 @@ void InstX8632Xchg::dump(const Cfg *Func) const { |
| void OperandX8632Mem::emit(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| - Str << TypeX8632Attributes[getType()].WidthString << " "; |
| if (SegmentReg != DefaultSegment) { |
| assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
| Str << InstX8632SegmentRegNames[SegmentReg] << ":"; |
| } |
| - // TODO: The following is an almost verbatim paste of dump(). |
| - bool Dumped = false; |
| - Str << "["; |
| - if (Base) { |
| - Base->emit(Func); |
| - Dumped = true; |
| - } |
| - if (Index) { |
| - assert(Base); |
| - Str << "+"; |
| - if (Shift > 0) |
| - Str << (1u << Shift) << "*"; |
| - Index->emit(Func); |
| - Dumped = true; |
| - } |
| - // Pretty-print the Offset. |
| - bool OffsetIsZero = false; |
| - bool OffsetIsNegative = false; |
| + // Emit as Offset(Base,Index,1<<Shift). |
| + // Offset is emitted without the leading '$'. |
| + // Omit the (Base,Index,1<<Shift) part if Base==NULL. |
| if (Offset == NULL) { |
| - OffsetIsZero = true; |
| - } else if (ConstantInteger32 *CI = |
| - llvm::dyn_cast<ConstantInteger32>(Offset)) { |
| - OffsetIsZero = (CI->getValue() == 0); |
| - OffsetIsNegative = (static_cast<int32_t>(CI->getValue()) < 0); |
| + // No offset, emit nothing. |
| + } else if (auto CI = llvm::dyn_cast<ConstantInteger32>(Offset)) { |
| + if (CI->getValue()) |
| + // Emit a non-zero offset without a leading '$'. |
| + Str << CI->getValue(); |
| + } else if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) { |
| + CR->emitWithoutDollar(Func->getContext()); |
| } else { |
| - assert(llvm::isa<ConstantRelocatable>(Offset)); |
| + assert(0); |
|
jvoung (off chromium)
2014/10/31 22:12:18
could do llvm_unreachable("...")
Jim Stichnoth
2014/11/01 13:44:17
Done.
|
| } |
| - if (Dumped) { |
| - if (!OffsetIsZero) { // Suppress if Offset is known to be 0 |
| - if (!OffsetIsNegative) // Suppress if Offset is known to be negative |
| - Str << "+"; |
| - Offset->emit(Func); |
| + |
| + if (Base) { |
| + Str << "("; |
| + Base->emit(Func); |
| + if (Index) { |
| + Str << ","; |
| + Index->emit(Func); |
| + if (Shift) |
| + Str << "," << (1u << Shift); |
| } |
| - } else { |
| - // There is only the offset. |
| - Offset->emit(Func); |
| + Str << ")"; |
| } |
| - Str << "]"; |
| } |
| void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const { |
| @@ -2903,16 +2887,11 @@ void VariableSplit::emit(const Cfg *Func) const { |
| // The following is copied/adapted from TargetX8632::emitVariable(). |
| const TargetLowering *Target = Func->getTarget(); |
| const Type Ty = IceType_i32; |
| - Str << TypeX8632Attributes[Ty].WidthString << " [" |
| - << Target->getRegName(Target->getFrameOrStackReg(), Ty); |
| int32_t Offset = |
| Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); |
| - if (Offset) { |
| - if (Offset > 0) |
| - Str << "+"; |
| + if (Offset) |
| Str << Offset; |
| - } |
| - Str << "]"; |
| + Str << "(%" << Target->getRegName(Target->getFrameOrStackReg(), Ty) << ")"; |
| } |
| void VariableSplit::dump(const Cfg *Func, Ostream &Str) const { |