| OLD | NEW |
| 1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// | 1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This file implements the InstX8632 and OperandX8632 classes, | 10 // This file implements the InstX8632 and OperandX8632 classes, |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 // ======================== Dump routines ======================== // | 343 // ======================== Dump routines ======================== // |
| 344 | 344 |
| 345 namespace { | 345 namespace { |
| 346 | 346 |
| 347 void emitIASBytes(const Cfg *Func, const x86::AssemblerX86 *Asm, | 347 void emitIASBytes(const Cfg *Func, const x86::AssemblerX86 *Asm, |
| 348 intptr_t StartPosition) { | 348 intptr_t StartPosition) { |
| 349 GlobalContext *Ctx = Func->getContext(); | 349 GlobalContext *Ctx = Func->getContext(); |
| 350 Ostream &Str = Ctx->getStrEmit(); | 350 Ostream &Str = Ctx->getStrEmit(); |
| 351 intptr_t EndPosition = Asm->GetPosition(); | 351 intptr_t EndPosition = Asm->GetPosition(); |
| 352 AssemblerFixup *LastFixup = Asm->GetLatestFixup(StartPosition); | 352 AssemblerFixup *LastFixup = Asm->GetLatestFixup(StartPosition); |
| 353 if (LastFixup == NULL) { | 353 if (!LastFixup) { |
| 354 // The fixup doesn't apply to this current block. | 354 // The fixup doesn't apply to this current block. |
| 355 for (intptr_t i = StartPosition; i < EndPosition; ++i) { | 355 for (intptr_t i = StartPosition; i < EndPosition; ++i) { |
| 356 Str << "\t.byte 0x"; | 356 Str << "\t.byte 0x"; |
| 357 Str.write_hex(Asm->LoadBuffer<uint8_t>(i)); | 357 Str.write_hex(Asm->LoadBuffer<uint8_t>(i)); |
| 358 Str << "\n"; | 358 Str << "\n"; |
| 359 } | 359 } |
| 360 return; | 360 return; |
| 361 } | 361 } |
| 362 intptr_t LastFixupLoc = LastFixup->position(); | 362 intptr_t LastFixupLoc = LastFixup->position(); |
| 363 const intptr_t FixupSize = 4; | 363 const intptr_t FixupSize = 4; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 375 else | 375 else |
| 376 Str << Ctx->mangleName(Reloc->getName()); | 376 Str << Ctx->mangleName(Reloc->getName()); |
| 377 if (LastFixup->value()->getOffset()) { | 377 if (LastFixup->value()->getOffset()) { |
| 378 Str << " + " << LastFixup->value()->getOffset(); | 378 Str << " + " << LastFixup->value()->getOffset(); |
| 379 } | 379 } |
| 380 Str << "\n"; | 380 Str << "\n"; |
| 381 LastFixupLoc += FixupSize; | 381 LastFixupLoc += FixupSize; |
| 382 assert(LastFixupLoc <= EndPosition); | 382 assert(LastFixupLoc <= EndPosition); |
| 383 LastFixup = Asm->GetLatestFixup(LastFixupLoc); | 383 LastFixup = Asm->GetLatestFixup(LastFixupLoc); |
| 384 // Assume multi-fixups are adjacent in the instruction encoding. | 384 // Assume multi-fixups are adjacent in the instruction encoding. |
| 385 assert(LastFixup == NULL || LastFixup->position() == LastFixupLoc); | 385 assert(!LastFixup || LastFixup->position() == LastFixupLoc); |
| 386 } | 386 } |
| 387 for (intptr_t i = LastFixupLoc; i < EndPosition; ++i) { | 387 for (intptr_t i = LastFixupLoc; i < EndPosition; ++i) { |
| 388 Str << "\t.byte 0x"; | 388 Str << "\t.byte 0x"; |
| 389 Str.write_hex(Asm->LoadBuffer<uint8_t>(i)); | 389 Str.write_hex(Asm->LoadBuffer<uint8_t>(i)); |
| 390 Str << "\n"; | 390 Str << "\n"; |
| 391 } | 391 } |
| 392 } | 392 } |
| 393 | 393 |
| 394 void emitIASBytesBranch(const Cfg *Func, const x86::AssemblerX86 *Asm, | 394 void emitIASBytesBranch(const Cfg *Func, const x86::AssemblerX86 *Asm, |
| 395 intptr_t StartPosition, const x86::Label *Label, | 395 intptr_t StartPosition, const x86::Label *Label, |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 if (getTargetFalse()) { | 528 if (getTargetFalse()) { |
| 529 Str << ", label %" << getTargetFalse()->getName(); | 529 Str << ", label %" << getTargetFalse()->getName(); |
| 530 } | 530 } |
| 531 } | 531 } |
| 532 } | 532 } |
| 533 | 533 |
| 534 void InstX8632Call::emit(const Cfg *Func) const { | 534 void InstX8632Call::emit(const Cfg *Func) const { |
| 535 Ostream &Str = Func->getContext()->getStrEmit(); | 535 Ostream &Str = Func->getContext()->getStrEmit(); |
| 536 assert(getSrcSize() == 1); | 536 assert(getSrcSize() == 1); |
| 537 Str << "\tcall\t"; | 537 Str << "\tcall\t"; |
| 538 if (auto CallTarget = llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) { | 538 if (const auto CallTarget = |
| 539 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) { |
| 539 // TODO(stichnot): All constant targets should suppress the '$', | 540 // TODO(stichnot): All constant targets should suppress the '$', |
| 540 // not just relocatables. | 541 // not just relocatables. |
| 541 CallTarget->emitWithoutDollar(Func->getContext()); | 542 CallTarget->emitWithoutDollar(Func->getContext()); |
| 542 } else { | 543 } else { |
| 543 Str << "*"; | 544 Str << "*"; |
| 544 getCallTarget()->emit(Func); | 545 getCallTarget()->emit(Func); |
| 545 } | 546 } |
| 546 Func->getTarget()->resetStackAdjustment(); | 547 Func->getTarget()->resetStackAdjustment(); |
| 547 } | 548 } |
| 548 | 549 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 // Opcode parameter needs to be char* and not IceString because of | 609 // Opcode parameter needs to be char* and not IceString because of |
| 609 // template issues. | 610 // template issues. |
| 610 void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func, | 611 void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func, |
| 611 bool ShiftHack) { | 612 bool ShiftHack) { |
| 612 Ostream &Str = Func->getContext()->getStrEmit(); | 613 Ostream &Str = Func->getContext()->getStrEmit(); |
| 613 assert(Inst->getSrcSize() == 2); | 614 assert(Inst->getSrcSize() == 2); |
| 614 Variable *Dest = Inst->getDest(); | 615 Variable *Dest = Inst->getDest(); |
| 615 assert(Dest == Inst->getSrc(0)); | 616 assert(Dest == Inst->getSrc(0)); |
| 616 Operand *Src1 = Inst->getSrc(1); | 617 Operand *Src1 = Inst->getSrc(1); |
| 617 Str << "\t" << Opcode << InstX8632::getWidthString(Dest->getType()) << "\t"; | 618 Str << "\t" << Opcode << InstX8632::getWidthString(Dest->getType()) << "\t"; |
| 618 Variable *ShiftReg = llvm::dyn_cast<Variable>(Src1); | 619 const auto ShiftReg = llvm::dyn_cast<Variable>(Src1); |
| 619 if (ShiftHack && ShiftReg && ShiftReg->getRegNum() == RegX8632::Reg_ecx) | 620 if (ShiftHack && ShiftReg && ShiftReg->getRegNum() == RegX8632::Reg_ecx) |
| 620 Str << "%cl"; | 621 Str << "%cl"; |
| 621 else | 622 else |
| 622 Src1->emit(Func); | 623 Src1->emit(Func); |
| 623 Str << ", "; | 624 Str << ", "; |
| 624 Dest->emit(Func); | 625 Dest->emit(Func); |
| 625 } | 626 } |
| 626 | 627 |
| 627 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op, | 628 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op, |
| 628 const x86::AssemblerX86::GPREmitterOneOp &Emitter) { | 629 const x86::AssemblerX86::GPREmitterOneOp &Emitter) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 } | 758 } |
| 758 | 759 |
| 759 void emitIASGPRShiftDouble(const Cfg *Func, const Variable *Dest, | 760 void emitIASGPRShiftDouble(const Cfg *Func, const Variable *Dest, |
| 760 const Operand *Src1Op, const Operand *Src2Op, | 761 const Operand *Src1Op, const Operand *Src2Op, |
| 761 const x86::AssemblerX86::GPREmitterShiftD &Emitter) { | 762 const x86::AssemblerX86::GPREmitterShiftD &Emitter) { |
| 762 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 763 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 763 intptr_t StartPosition = Asm->GetPosition(); | 764 intptr_t StartPosition = Asm->GetPosition(); |
| 764 // Dest can be reg or mem, but we only use the reg variant. | 765 // Dest can be reg or mem, but we only use the reg variant. |
| 765 assert(Dest->hasReg()); | 766 assert(Dest->hasReg()); |
| 766 RegX8632::GPRRegister DestReg = RegX8632::getEncodedGPR(Dest->getRegNum()); | 767 RegX8632::GPRRegister DestReg = RegX8632::getEncodedGPR(Dest->getRegNum()); |
| 767 // Src1 must be reg. | 768 // SrcVar1 must be reg. |
| 768 const auto Src1 = llvm::cast<Variable>(Src1Op); | 769 const auto SrcVar1 = llvm::cast<Variable>(Src1Op); |
| 769 assert(Src1->hasReg()); | 770 assert(SrcVar1->hasReg()); |
| 770 RegX8632::GPRRegister SrcReg = RegX8632::getEncodedGPR(Src1->getRegNum()); | 771 RegX8632::GPRRegister SrcReg = RegX8632::getEncodedGPR(SrcVar1->getRegNum()); |
| 771 Type Ty = Src1->getType(); | 772 Type Ty = SrcVar1->getType(); |
| 772 // Src2 can be the implicit CL register or an immediate. | 773 // Src2 can be the implicit CL register or an immediate. |
| 773 if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) { | 774 if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) { |
| 774 (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg, | 775 (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg, |
| 775 x86::Immediate(Imm->getValue())); | 776 x86::Immediate(Imm->getValue())); |
| 776 } else { | 777 } else { |
| 777 assert(llvm::cast<Variable>(Src2Op)->getRegNum() == RegX8632::Reg_ecx); | 778 assert(llvm::cast<Variable>(Src2Op)->getRegNum() == RegX8632::Reg_ecx); |
| 778 (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg); | 779 (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg); |
| 779 } | 780 } |
| 780 emitIASBytes(Func, Asm, StartPosition); | 781 emitIASBytes(Func, Asm, StartPosition); |
| 781 } | 782 } |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 914 } else if (const auto SrcMem = llvm::dyn_cast<OperandX8632Mem>(Src)) { | 915 } else if (const auto SrcMem = llvm::dyn_cast<OperandX8632Mem>(Src)) { |
| 915 assert(SrcMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 916 assert(SrcMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 916 (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm)); | 917 (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm)); |
| 917 } else { | 918 } else { |
| 918 llvm_unreachable("Unexpected operand type"); | 919 llvm_unreachable("Unexpected operand type"); |
| 919 } | 920 } |
| 920 } else { | 921 } else { |
| 921 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 922 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 922 ->stackVarToAsmOperand(Dest)); | 923 ->stackVarToAsmOperand(Dest)); |
| 923 // Src must be a register in this case. | 924 // Src must be a register in this case. |
| 924 const Variable *SrcVar = llvm::cast<Variable>(Src); | 925 const auto SrcVar = llvm::cast<Variable>(Src); |
| 925 assert(SrcVar->hasReg()); | 926 assert(SrcVar->hasReg()); |
| 926 (Asm->*(Emitter.AddrXmm))(StackAddr, | 927 (Asm->*(Emitter.AddrXmm))(StackAddr, |
| 927 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | 928 RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
| 928 } | 929 } |
| 929 emitIASBytes(Func, Asm, StartPosition); | 930 emitIASBytes(Func, Asm, StartPosition); |
| 930 } | 931 } |
| 931 | 932 |
| 932 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) { | 933 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) { |
| 933 const Variable *Src = llvm::dyn_cast<const Variable>(Source); | 934 const auto SrcVar = llvm::dyn_cast<const Variable>(Source); |
| 934 if (Src == NULL) | 935 if (!SrcVar) |
| 935 return false; | 936 return false; |
| 936 if (Dest->hasReg() && Dest->getRegNum() == Src->getRegNum()) { | 937 if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) { |
| 937 // TODO: On x86-64, instructions like "mov eax, eax" are used to | 938 // TODO: On x86-64, instructions like "mov eax, eax" are used to |
| 938 // clear the upper 32 bits of rax. We need to recognize and | 939 // clear the upper 32 bits of rax. We need to recognize and |
| 939 // preserve these. | 940 // preserve these. |
| 940 return true; | 941 return true; |
| 941 } | 942 } |
| 942 if (!Dest->hasReg() && !Src->hasReg() && | 943 if (!Dest->hasReg() && !SrcVar->hasReg() && |
| 943 Dest->getStackOffset() == Src->getStackOffset()) | 944 Dest->getStackOffset() == SrcVar->getStackOffset()) |
| 944 return true; | 945 return true; |
| 945 return false; | 946 return false; |
| 946 } | 947 } |
| 947 | 948 |
| 948 // In-place ops | 949 // In-place ops |
| 949 template <> const char *InstX8632Bswap::Opcode = "bswap"; | 950 template <> const char *InstX8632Bswap::Opcode = "bswap"; |
| 950 template <> const char *InstX8632Neg::Opcode = "neg"; | 951 template <> const char *InstX8632Neg::Opcode = "neg"; |
| 951 // Unary ops | 952 // Unary ops |
| 952 template <> const char *InstX8632Bsf::Opcode = "bsf"; | 953 template <> const char *InstX8632Bsf::Opcode = "bsf"; |
| 953 template <> const char *InstX8632Bsr::Opcode = "bsr"; | 954 template <> const char *InstX8632Bsr::Opcode = "bsr"; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1003 template <> const char *InstX8632Pinsr::Opcode = "pinsr"; | 1004 template <> const char *InstX8632Pinsr::Opcode = "pinsr"; |
| 1004 template <> const char *InstX8632Blendvps::Opcode = "blendvps"; | 1005 template <> const char *InstX8632Blendvps::Opcode = "blendvps"; |
| 1005 template <> const char *InstX8632Pblendvb::Opcode = "pblendvb"; | 1006 template <> const char *InstX8632Pblendvb::Opcode = "pblendvb"; |
| 1006 // Three address ops | 1007 // Three address ops |
| 1007 template <> const char *InstX8632Pextr::Opcode = "pextr"; | 1008 template <> const char *InstX8632Pextr::Opcode = "pextr"; |
| 1008 template <> const char *InstX8632Pshufd::Opcode = "pshufd"; | 1009 template <> const char *InstX8632Pshufd::Opcode = "pshufd"; |
| 1009 | 1010 |
| 1010 // Inplace GPR ops | 1011 // Inplace GPR ops |
| 1011 template <> | 1012 template <> |
| 1012 const x86::AssemblerX86::GPREmitterOneOp InstX8632Bswap::Emitter = { | 1013 const x86::AssemblerX86::GPREmitterOneOp InstX8632Bswap::Emitter = { |
| 1013 &x86::AssemblerX86::bswap, NULL /* only a reg form exists */}; | 1014 &x86::AssemblerX86::bswap, nullptr /* only a reg form exists */}; |
| 1014 template <> | 1015 template <> |
| 1015 const x86::AssemblerX86::GPREmitterOneOp InstX8632Neg::Emitter = { | 1016 const x86::AssemblerX86::GPREmitterOneOp InstX8632Neg::Emitter = { |
| 1016 &x86::AssemblerX86::neg, &x86::AssemblerX86::neg}; | 1017 &x86::AssemblerX86::neg, &x86::AssemblerX86::neg}; |
| 1017 | 1018 |
| 1018 // Unary GPR ops | 1019 // Unary GPR ops |
| 1019 template <> | 1020 template <> |
| 1020 const x86::AssemblerX86::GPREmitterRegOp InstX8632Bsf::Emitter = { | 1021 const x86::AssemblerX86::GPREmitterRegOp InstX8632Bsf::Emitter = { |
| 1021 &x86::AssemblerX86::bsf, &x86::AssemblerX86::bsf, NULL}; | 1022 &x86::AssemblerX86::bsf, &x86::AssemblerX86::bsf, nullptr}; |
| 1022 template <> | 1023 template <> |
| 1023 const x86::AssemblerX86::GPREmitterRegOp InstX8632Bsr::Emitter = { | 1024 const x86::AssemblerX86::GPREmitterRegOp InstX8632Bsr::Emitter = { |
| 1024 &x86::AssemblerX86::bsr, &x86::AssemblerX86::bsr, NULL}; | 1025 &x86::AssemblerX86::bsr, &x86::AssemblerX86::bsr, nullptr}; |
| 1025 template <> | 1026 template <> |
| 1026 const x86::AssemblerX86::GPREmitterRegOp InstX8632Lea::Emitter = { | 1027 const x86::AssemblerX86::GPREmitterRegOp InstX8632Lea::Emitter = { |
| 1027 /* reg/reg and reg/imm are illegal */ NULL, &x86::AssemblerX86::lea, NULL}; | 1028 /* reg/reg and reg/imm are illegal */ nullptr, &x86::AssemblerX86::lea, |
| 1029 nullptr}; |
| 1028 template <> | 1030 template <> |
| 1029 const x86::AssemblerX86::GPREmitterRegOp InstX8632Movsx::Emitter = { | 1031 const x86::AssemblerX86::GPREmitterRegOp InstX8632Movsx::Emitter = { |
| 1030 &x86::AssemblerX86::movsx, &x86::AssemblerX86::movsx, NULL}; | 1032 &x86::AssemblerX86::movsx, &x86::AssemblerX86::movsx, nullptr}; |
| 1031 template <> | 1033 template <> |
| 1032 const x86::AssemblerX86::GPREmitterRegOp InstX8632Movzx::Emitter = { | 1034 const x86::AssemblerX86::GPREmitterRegOp InstX8632Movzx::Emitter = { |
| 1033 &x86::AssemblerX86::movzx, &x86::AssemblerX86::movzx, NULL}; | 1035 &x86::AssemblerX86::movzx, &x86::AssemblerX86::movzx, nullptr}; |
| 1034 | 1036 |
| 1035 // Unary XMM ops | 1037 // Unary XMM ops |
| 1036 template <> | 1038 template <> |
| 1037 const x86::AssemblerX86::XmmEmitterRegOp InstX8632Sqrtss::Emitter = { | 1039 const x86::AssemblerX86::XmmEmitterRegOp InstX8632Sqrtss::Emitter = { |
| 1038 &x86::AssemblerX86::sqrtss, &x86::AssemblerX86::sqrtss | 1040 &x86::AssemblerX86::sqrtss, &x86::AssemblerX86::sqrtss |
| 1039 }; | 1041 }; |
| 1040 | 1042 |
| 1041 // Binary GPR ops | 1043 // Binary GPR ops |
| 1042 template <> | 1044 template <> |
| 1043 const x86::AssemblerX86::GPREmitterRegOp InstX8632Add::Emitter = { | 1045 const x86::AssemblerX86::GPREmitterRegOp InstX8632Add::Emitter = { |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1340 &x86::AssemblerX86::pblendvb, &x86::AssemblerX86::pblendvb}; | 1342 &x86::AssemblerX86::pblendvb, &x86::AssemblerX86::pblendvb}; |
| 1341 emitIASVariableBlendInst(this, Func, Emitter); | 1343 emitIASVariableBlendInst(this, Func, Emitter); |
| 1342 } | 1344 } |
| 1343 | 1345 |
| 1344 template <> void InstX8632Imul::emit(const Cfg *Func) const { | 1346 template <> void InstX8632Imul::emit(const Cfg *Func) const { |
| 1345 Ostream &Str = Func->getContext()->getStrEmit(); | 1347 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1346 assert(getSrcSize() == 2); | 1348 assert(getSrcSize() == 2); |
| 1347 Variable *Dest = getDest(); | 1349 Variable *Dest = getDest(); |
| 1348 if (isByteSizedArithType(Dest->getType())) { | 1350 if (isByteSizedArithType(Dest->getType())) { |
| 1349 // The 8-bit version of imul only allows the form "imul r/m8". | 1351 // The 8-bit version of imul only allows the form "imul r/m8". |
| 1350 Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0)); | 1352 const auto Src0Var = llvm::dyn_cast<Variable>(getSrc(0)); |
| 1351 (void)Src0; | 1353 (void)Src0Var; |
| 1352 assert(Src0 && Src0->getRegNum() == RegX8632::Reg_eax); | 1354 assert(Src0Var && Src0Var->getRegNum() == RegX8632::Reg_eax); |
| 1353 Str << "\timulb\t"; | 1355 Str << "\timulb\t"; |
| 1354 getSrc(1)->emit(Func); | 1356 getSrc(1)->emit(Func); |
| 1355 } else if (llvm::isa<Constant>(getSrc(1))) { | 1357 } else if (llvm::isa<Constant>(getSrc(1))) { |
| 1356 Str << "\timul" << getWidthString(Dest->getType()) << "\t"; | 1358 Str << "\timul" << getWidthString(Dest->getType()) << "\t"; |
| 1357 getSrc(1)->emit(Func); | 1359 getSrc(1)->emit(Func); |
| 1358 Str << ", "; | 1360 Str << ", "; |
| 1359 getSrc(0)->emit(Func); | 1361 getSrc(0)->emit(Func); |
| 1360 Str << ", "; | 1362 Str << ", "; |
| 1361 Dest->emit(Func); | 1363 Dest->emit(Func); |
| 1362 } else { | 1364 } else { |
| 1363 emitTwoAddress("imul", this, Func); | 1365 emitTwoAddress("imul", this, Func); |
| 1364 } | 1366 } |
| 1365 } | 1367 } |
| 1366 | 1368 |
| 1367 template <> void InstX8632Imul::emitIAS(const Cfg *Func) const { | 1369 template <> void InstX8632Imul::emitIAS(const Cfg *Func) const { |
| 1368 assert(getSrcSize() == 2); | 1370 assert(getSrcSize() == 2); |
| 1369 const Variable *Var = getDest(); | 1371 const Variable *Var = getDest(); |
| 1370 Type Ty = Var->getType(); | 1372 Type Ty = Var->getType(); |
| 1371 const Operand *Src = getSrc(1); | 1373 const Operand *Src = getSrc(1); |
| 1372 if (isByteSizedArithType(Ty)) { | 1374 if (isByteSizedArithType(Ty)) { |
| 1373 // The 8-bit version of imul only allows the form "imul r/m8". | 1375 // The 8-bit version of imul only allows the form "imul r/m8". |
| 1374 Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0)); | 1376 const auto Src0Var = llvm::dyn_cast<Variable>(getSrc(0)); |
| 1375 (void)Src0; | 1377 (void)Src0Var; |
| 1376 assert(Src0 && Src0->getRegNum() == RegX8632::Reg_eax); | 1378 assert(Src0Var && Src0Var->getRegNum() == RegX8632::Reg_eax); |
| 1377 const x86::AssemblerX86::GPREmitterOneOp Emitter = { | 1379 const x86::AssemblerX86::GPREmitterOneOp Emitter = { |
| 1378 &x86::AssemblerX86::imul, &x86::AssemblerX86::imul}; | 1380 &x86::AssemblerX86::imul, &x86::AssemblerX86::imul}; |
| 1379 emitIASOpTyGPR(Func, Ty, getSrc(1), Emitter); | 1381 emitIASOpTyGPR(Func, Ty, getSrc(1), Emitter); |
| 1380 } else { | 1382 } else { |
| 1381 // We only use imul as a two-address instruction even though | 1383 // We only use imul as a two-address instruction even though |
| 1382 // there is a 3 operand version when one of the operands is a constant. | 1384 // there is a 3 operand version when one of the operands is a constant. |
| 1383 assert(Var == getSrc(0)); | 1385 assert(Var == getSrc(0)); |
| 1384 const x86::AssemblerX86::GPREmitterRegOp Emitter = { | 1386 const x86::AssemblerX86::GPREmitterRegOp Emitter = { |
| 1385 &x86::AssemblerX86::imul, &x86::AssemblerX86::imul, | 1387 &x86::AssemblerX86::imul, &x86::AssemblerX86::imul, |
| 1386 &x86::AssemblerX86::imul}; | 1388 &x86::AssemblerX86::imul}; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1452 Asm->cdq(); | 1454 Asm->cdq(); |
| 1453 break; | 1455 break; |
| 1454 } | 1456 } |
| 1455 emitIASBytes(Func, Asm, StartPosition); | 1457 emitIASBytes(Func, Asm, StartPosition); |
| 1456 } | 1458 } |
| 1457 | 1459 |
| 1458 void InstX8632Mul::emit(const Cfg *Func) const { | 1460 void InstX8632Mul::emit(const Cfg *Func) const { |
| 1459 Ostream &Str = Func->getContext()->getStrEmit(); | 1461 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1460 assert(getSrcSize() == 2); | 1462 assert(getSrcSize() == 2); |
| 1461 assert(llvm::isa<Variable>(getSrc(0))); | 1463 assert(llvm::isa<Variable>(getSrc(0))); |
| 1462 assert(llvm::dyn_cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); | 1464 assert(llvm::cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); |
| 1463 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? | 1465 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? |
| 1464 Str << "\tmul" << getWidthString(getDest()->getType()) << "\t"; | 1466 Str << "\tmul" << getWidthString(getDest()->getType()) << "\t"; |
| 1465 getSrc(1)->emit(Func); | 1467 getSrc(1)->emit(Func); |
| 1466 } | 1468 } |
| 1467 | 1469 |
| 1468 void InstX8632Mul::emitIAS(const Cfg *Func) const { | 1470 void InstX8632Mul::emitIAS(const Cfg *Func) const { |
| 1469 assert(getSrcSize() == 2); | 1471 assert(getSrcSize() == 2); |
| 1470 assert(llvm::isa<Variable>(getSrc(0))); | 1472 assert(llvm::isa<Variable>(getSrc(0))); |
| 1471 assert(llvm::dyn_cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); | 1473 assert(llvm::cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); |
| 1472 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? | 1474 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? |
| 1473 const Operand *Src = getSrc(1); | 1475 const Operand *Src = getSrc(1); |
| 1474 Type Ty = Src->getType(); | 1476 Type Ty = Src->getType(); |
| 1475 const static x86::AssemblerX86::GPREmitterOneOp Emitter = { | 1477 const static x86::AssemblerX86::GPREmitterOneOp Emitter = { |
| 1476 &x86::AssemblerX86::mul, &x86::AssemblerX86::mul}; | 1478 &x86::AssemblerX86::mul, &x86::AssemblerX86::mul}; |
| 1477 emitIASOpTyGPR(Func, Ty, Src, Emitter); | 1479 emitIASOpTyGPR(Func, Ty, Src, Emitter); |
| 1478 } | 1480 } |
| 1479 | 1481 |
| 1480 void InstX8632Mul::dump(const Cfg *Func) const { | 1482 void InstX8632Mul::dump(const Cfg *Func) const { |
| 1481 Ostream &Str = Func->getContext()->getStrDump(); | 1483 Ostream &Str = Func->getContext()->getStrDump(); |
| 1482 dumpDest(Func); | 1484 dumpDest(Func); |
| 1483 Str << " = mul." << getDest()->getType() << " "; | 1485 Str << " = mul." << getDest()->getType() << " "; |
| 1484 dumpSources(Func); | 1486 dumpSources(Func); |
| 1485 } | 1487 } |
| 1486 | 1488 |
| 1487 void InstX8632Shld::emit(const Cfg *Func) const { | 1489 void InstX8632Shld::emit(const Cfg *Func) const { |
| 1488 Ostream &Str = Func->getContext()->getStrEmit(); | 1490 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1489 Variable *Dest = getDest(); | 1491 Variable *Dest = getDest(); |
| 1490 assert(getSrcSize() == 3); | 1492 assert(getSrcSize() == 3); |
| 1491 assert(Dest == getSrc(0)); | 1493 assert(Dest == getSrc(0)); |
| 1492 Str << "\tshld" << getWidthString(Dest->getType()) << "\t"; | 1494 Str << "\tshld" << getWidthString(Dest->getType()) << "\t"; |
| 1493 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { | 1495 if (const auto ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { |
| 1494 (void)ShiftReg; | 1496 (void)ShiftReg; |
| 1495 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); | 1497 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); |
| 1496 Str << "%cl"; | 1498 Str << "%cl"; |
| 1497 } else { | 1499 } else { |
| 1498 getSrc(2)->emit(Func); | 1500 getSrc(2)->emit(Func); |
| 1499 } | 1501 } |
| 1500 Str << ", "; | 1502 Str << ", "; |
| 1501 getSrc(1)->emit(Func); | 1503 getSrc(1)->emit(Func); |
| 1502 Str << ", "; | 1504 Str << ", "; |
| 1503 Dest->emit(Func); | 1505 Dest->emit(Func); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1520 Str << " = shld." << getDest()->getType() << " "; | 1522 Str << " = shld." << getDest()->getType() << " "; |
| 1521 dumpSources(Func); | 1523 dumpSources(Func); |
| 1522 } | 1524 } |
| 1523 | 1525 |
| 1524 void InstX8632Shrd::emit(const Cfg *Func) const { | 1526 void InstX8632Shrd::emit(const Cfg *Func) const { |
| 1525 Ostream &Str = Func->getContext()->getStrEmit(); | 1527 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1526 Variable *Dest = getDest(); | 1528 Variable *Dest = getDest(); |
| 1527 assert(getSrcSize() == 3); | 1529 assert(getSrcSize() == 3); |
| 1528 assert(Dest == getSrc(0)); | 1530 assert(Dest == getSrc(0)); |
| 1529 Str << "\tshrd" << getWidthString(Dest->getType()) << "\t"; | 1531 Str << "\tshrd" << getWidthString(Dest->getType()) << "\t"; |
| 1530 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { | 1532 if (const auto ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { |
| 1531 (void)ShiftReg; | 1533 (void)ShiftReg; |
| 1532 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); | 1534 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); |
| 1533 Str << "%cl"; | 1535 Str << "%cl"; |
| 1534 } else { | 1536 } else { |
| 1535 getSrc(2)->emit(Func); | 1537 getSrc(2)->emit(Func); |
| 1536 } | 1538 } |
| 1537 Str << ", "; | 1539 Str << ", "; |
| 1538 getSrc(1)->emit(Func); | 1540 getSrc(1)->emit(Func); |
| 1539 Str << ", "; | 1541 Str << ", "; |
| 1540 Dest->emit(Func); | 1542 Dest->emit(Func); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1569 getSrc(1)->emit(Func); | 1571 getSrc(1)->emit(Func); |
| 1570 Str << ", "; | 1572 Str << ", "; |
| 1571 Dest->emit(Func); | 1573 Dest->emit(Func); |
| 1572 } | 1574 } |
| 1573 | 1575 |
| 1574 void InstX8632Cmov::emitIAS(const Cfg *Func) const { | 1576 void InstX8632Cmov::emitIAS(const Cfg *Func) const { |
| 1575 assert(Condition != CondX86::Br_None); | 1577 assert(Condition != CondX86::Br_None); |
| 1576 assert(getDest()->hasReg()); | 1578 assert(getDest()->hasReg()); |
| 1577 assert(getSrcSize() == 2); | 1579 assert(getSrcSize() == 2); |
| 1578 // Only need the reg/reg form now. | 1580 // Only need the reg/reg form now. |
| 1579 const Variable *Src = llvm::cast<Variable>(getSrc(1)); | 1581 const auto SrcVar = llvm::cast<Variable>(getSrc(1)); |
| 1580 assert(Src->hasReg()); | 1582 assert(SrcVar->hasReg()); |
| 1581 assert(Src->getType() == IceType_i32); | 1583 assert(SrcVar->getType() == IceType_i32); |
| 1582 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1584 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1583 intptr_t StartPosition = Asm->GetPosition(); | 1585 intptr_t StartPosition = Asm->GetPosition(); |
| 1584 Asm->cmov(Condition, RegX8632::getEncodedGPR(getDest()->getRegNum()), | 1586 Asm->cmov(Condition, RegX8632::getEncodedGPR(getDest()->getRegNum()), |
| 1585 RegX8632::getEncodedGPR(Src->getRegNum())); | 1587 RegX8632::getEncodedGPR(SrcVar->getRegNum())); |
| 1586 emitIASBytes(Func, Asm, StartPosition); | 1588 emitIASBytes(Func, Asm, StartPosition); |
| 1587 } | 1589 } |
| 1588 | 1590 |
| 1589 void InstX8632Cmov::dump(const Cfg *Func) const { | 1591 void InstX8632Cmov::dump(const Cfg *Func) const { |
| 1590 Ostream &Str = Func->getContext()->getStrDump(); | 1592 Ostream &Str = Func->getContext()->getStrDump(); |
| 1591 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "."; | 1593 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "."; |
| 1592 Str << getDest()->getType() << " "; | 1594 Str << getDest()->getType() << " "; |
| 1593 dumpDest(Func); | 1595 dumpDest(Func); |
| 1594 Str << ", "; | 1596 Str << ", "; |
| 1595 dumpSources(Func); | 1597 dumpSources(Func); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1608 } | 1610 } |
| 1609 | 1611 |
| 1610 void InstX8632Cmpps::emitIAS(const Cfg *Func) const { | 1612 void InstX8632Cmpps::emitIAS(const Cfg *Func) const { |
| 1611 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1613 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1612 intptr_t StartPosition = Asm->GetPosition(); | 1614 intptr_t StartPosition = Asm->GetPosition(); |
| 1613 assert(getSrcSize() == 2); | 1615 assert(getSrcSize() == 2); |
| 1614 assert(Condition < CondX86::Cmpps_Invalid); | 1616 assert(Condition < CondX86::Cmpps_Invalid); |
| 1615 // Assuming there isn't any load folding for cmpps, and vector constants | 1617 // Assuming there isn't any load folding for cmpps, and vector constants |
| 1616 // are not allowed in PNaCl. | 1618 // are not allowed in PNaCl. |
| 1617 assert(llvm::isa<Variable>(getSrc(1))); | 1619 assert(llvm::isa<Variable>(getSrc(1))); |
| 1618 const Variable *SrcVar = llvm::cast<Variable>(getSrc(1)); | 1620 const auto SrcVar = llvm::cast<Variable>(getSrc(1)); |
| 1619 if (SrcVar->hasReg()) { | 1621 if (SrcVar->hasReg()) { |
| 1620 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), | 1622 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), |
| 1621 RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition); | 1623 RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition); |
| 1622 } else { | 1624 } else { |
| 1623 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) | 1625 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) |
| 1624 ->stackVarToAsmOperand(SrcVar); | 1626 ->stackVarToAsmOperand(SrcVar); |
| 1625 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), SrcStackAddr, | 1627 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), SrcStackAddr, |
| 1626 Condition); | 1628 Condition); |
| 1627 } | 1629 } |
| 1628 emitIASBytes(Func, Asm, StartPosition); | 1630 emitIASBytes(Func, Asm, StartPosition); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1647 getSrc(2)->emit(Func); | 1649 getSrc(2)->emit(Func); |
| 1648 Str << ", "; | 1650 Str << ", "; |
| 1649 getSrc(0)->emit(Func); | 1651 getSrc(0)->emit(Func); |
| 1650 } | 1652 } |
| 1651 | 1653 |
| 1652 void InstX8632Cmpxchg::emitIAS(const Cfg *Func) const { | 1654 void InstX8632Cmpxchg::emitIAS(const Cfg *Func) const { |
| 1653 assert(getSrcSize() == 3); | 1655 assert(getSrcSize() == 3); |
| 1654 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1656 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1655 intptr_t StartPosition = Asm->GetPosition(); | 1657 intptr_t StartPosition = Asm->GetPosition(); |
| 1656 Type Ty = getSrc(0)->getType(); | 1658 Type Ty = getSrc(0)->getType(); |
| 1657 const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | 1659 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
| 1658 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 1660 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 1659 const x86::Address Addr = Mem->toAsmAddress(Asm); | 1661 const x86::Address Addr = Mem->toAsmAddress(Asm); |
| 1660 const Variable *VarReg = llvm::cast<Variable>(getSrc(2)); | 1662 const auto VarReg = llvm::cast<Variable>(getSrc(2)); |
| 1661 assert(VarReg->hasReg()); | 1663 assert(VarReg->hasReg()); |
| 1662 const RegX8632::GPRRegister Reg = | 1664 const RegX8632::GPRRegister Reg = |
| 1663 RegX8632::getEncodedGPR(VarReg->getRegNum()); | 1665 RegX8632::getEncodedGPR(VarReg->getRegNum()); |
| 1664 if (Locked) { | 1666 if (Locked) { |
| 1665 Asm->LockCmpxchg(Ty, Addr, Reg); | 1667 Asm->LockCmpxchg(Ty, Addr, Reg); |
| 1666 } else { | 1668 } else { |
| 1667 Asm->cmpxchg(Ty, Addr, Reg); | 1669 Asm->cmpxchg(Ty, Addr, Reg); |
| 1668 } | 1670 } |
| 1669 emitIASBytes(Func, Asm, StartPosition); | 1671 emitIASBytes(Func, Asm, StartPosition); |
| 1670 } | 1672 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1685 Str << "\tlock"; | 1687 Str << "\tlock"; |
| 1686 } | 1688 } |
| 1687 Str << "\tcmpxchg8b\t"; | 1689 Str << "\tcmpxchg8b\t"; |
| 1688 getSrc(0)->emit(Func); | 1690 getSrc(0)->emit(Func); |
| 1689 } | 1691 } |
| 1690 | 1692 |
| 1691 void InstX8632Cmpxchg8b::emitIAS(const Cfg *Func) const { | 1693 void InstX8632Cmpxchg8b::emitIAS(const Cfg *Func) const { |
| 1692 assert(getSrcSize() == 5); | 1694 assert(getSrcSize() == 5); |
| 1693 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1695 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1694 intptr_t StartPosition = Asm->GetPosition(); | 1696 intptr_t StartPosition = Asm->GetPosition(); |
| 1695 const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | 1697 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
| 1696 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 1698 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 1697 const x86::Address Addr = Mem->toAsmAddress(Asm); | 1699 const x86::Address Addr = Mem->toAsmAddress(Asm); |
| 1698 if (Locked) { | 1700 if (Locked) { |
| 1699 Asm->lock(); | 1701 Asm->lock(); |
| 1700 } | 1702 } |
| 1701 Asm->cmpxchg8b(Addr); | 1703 Asm->cmpxchg8b(Addr); |
| 1702 emitIASBytes(Func, Asm, StartPosition); | 1704 emitIASBytes(Func, Asm, StartPosition); |
| 1703 } | 1705 } |
| 1704 | 1706 |
| 1705 void InstX8632Cmpxchg8b::dump(const Cfg *Func) const { | 1707 void InstX8632Cmpxchg8b::dump(const Cfg *Func) const { |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1837 getSrc(1)->emit(Func); | 1839 getSrc(1)->emit(Func); |
| 1838 Str << ", "; | 1840 Str << ", "; |
| 1839 getSrc(0)->emit(Func); | 1841 getSrc(0)->emit(Func); |
| 1840 } | 1842 } |
| 1841 | 1843 |
| 1842 void InstX8632Ucomiss::emitIAS(const Cfg *Func) const { | 1844 void InstX8632Ucomiss::emitIAS(const Cfg *Func) const { |
| 1843 assert(getSrcSize() == 2); | 1845 assert(getSrcSize() == 2); |
| 1844 // Currently src0 is always a variable by convention, to avoid having | 1846 // Currently src0 is always a variable by convention, to avoid having |
| 1845 // two memory operands. | 1847 // two memory operands. |
| 1846 assert(llvm::isa<Variable>(getSrc(0))); | 1848 assert(llvm::isa<Variable>(getSrc(0))); |
| 1847 const Variable *Src0 = llvm::cast<Variable>(getSrc(0)); | 1849 const auto Src0Var = llvm::cast<Variable>(getSrc(0)); |
| 1848 Type Ty = Src0->getType(); | 1850 Type Ty = Src0Var->getType(); |
| 1849 const static x86::AssemblerX86::XmmEmitterRegOp Emitter = { | 1851 const static x86::AssemblerX86::XmmEmitterRegOp Emitter = { |
| 1850 &x86::AssemblerX86::ucomiss, &x86::AssemblerX86::ucomiss | 1852 &x86::AssemblerX86::ucomiss, &x86::AssemblerX86::ucomiss |
| 1851 }; | 1853 }; |
| 1852 emitIASRegOpTyXMM(Func, Ty, Src0, getSrc(1), Emitter); | 1854 emitIASRegOpTyXMM(Func, Ty, Src0Var, getSrc(1), Emitter); |
| 1853 } | 1855 } |
| 1854 | 1856 |
| 1855 void InstX8632Ucomiss::dump(const Cfg *Func) const { | 1857 void InstX8632Ucomiss::dump(const Cfg *Func) const { |
| 1856 Ostream &Str = Func->getContext()->getStrDump(); | 1858 Ostream &Str = Func->getContext()->getStrDump(); |
| 1857 Str << "ucomiss." << getSrc(0)->getType() << " "; | 1859 Str << "ucomiss." << getSrc(0)->getType() << " "; |
| 1858 dumpSources(Func); | 1860 dumpSources(Func); |
| 1859 } | 1861 } |
| 1860 | 1862 |
| 1861 void InstX8632UD2::emit(const Cfg *Func) const { | 1863 void InstX8632UD2::emit(const Cfg *Func) const { |
| 1862 Ostream &Str = Func->getContext()->getStrEmit(); | 1864 Ostream &Str = Func->getContext()->getStrEmit(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1885 getSrc(0)->emit(Func); | 1887 getSrc(0)->emit(Func); |
| 1886 } | 1888 } |
| 1887 | 1889 |
| 1888 void InstX8632Test::emitIAS(const Cfg *Func) const { | 1890 void InstX8632Test::emitIAS(const Cfg *Func) const { |
| 1889 assert(getSrcSize() == 2); | 1891 assert(getSrcSize() == 2); |
| 1890 const Operand *Src0 = getSrc(0); | 1892 const Operand *Src0 = getSrc(0); |
| 1891 const Operand *Src1 = getSrc(1); | 1893 const Operand *Src1 = getSrc(1); |
| 1892 Type Ty = Src0->getType(); | 1894 Type Ty = Src0->getType(); |
| 1893 // The Reg/Addr form of test is not encodeable. | 1895 // The Reg/Addr form of test is not encodeable. |
| 1894 static const x86::AssemblerX86::GPREmitterRegOp RegEmitter = { | 1896 static const x86::AssemblerX86::GPREmitterRegOp RegEmitter = { |
| 1895 &x86::AssemblerX86::test, NULL, &x86::AssemblerX86::test | 1897 &x86::AssemblerX86::test, nullptr, &x86::AssemblerX86::test}; |
| 1896 }; | |
| 1897 static const x86::AssemblerX86::GPREmitterAddrOp AddrEmitter = { | 1898 static const x86::AssemblerX86::GPREmitterAddrOp AddrEmitter = { |
| 1898 &x86::AssemblerX86::test, &x86::AssemblerX86::test | 1899 &x86::AssemblerX86::test, &x86::AssemblerX86::test |
| 1899 }; | 1900 }; |
| 1900 if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { | 1901 if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { |
| 1901 if (SrcVar0->hasReg()) { | 1902 if (SrcVar0->hasReg()) { |
| 1902 emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); | 1903 emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); |
| 1903 return; | 1904 return; |
| 1904 } | 1905 } |
| 1905 } | 1906 } |
| 1906 llvm_unreachable("Nothing actually generates this so it's untested"); | 1907 llvm_unreachable("Nothing actually generates this so it's untested"); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1942 getSrc(1)->emit(Func); | 1943 getSrc(1)->emit(Func); |
| 1943 } | 1944 } |
| 1944 | 1945 |
| 1945 void InstX8632Store::emitIAS(const Cfg *Func) const { | 1946 void InstX8632Store::emitIAS(const Cfg *Func) const { |
| 1946 assert(getSrcSize() == 2); | 1947 assert(getSrcSize() == 2); |
| 1947 const Operand *Dest = getSrc(1); | 1948 const Operand *Dest = getSrc(1); |
| 1948 const Operand *Src = getSrc(0); | 1949 const Operand *Src = getSrc(0); |
| 1949 Type DestTy = Dest->getType(); | 1950 Type DestTy = Dest->getType(); |
| 1950 if (isScalarFloatingType(DestTy)) { | 1951 if (isScalarFloatingType(DestTy)) { |
| 1951 // Src must be a register, since Dest is a Mem operand of some kind. | 1952 // Src must be a register, since Dest is a Mem operand of some kind. |
| 1952 const Variable *SrcVar = llvm::cast<Variable>(Src); | 1953 const auto SrcVar = llvm::cast<Variable>(Src); |
| 1953 assert(SrcVar->hasReg()); | 1954 assert(SrcVar->hasReg()); |
| 1954 RegX8632::XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum()); | 1955 RegX8632::XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum()); |
| 1955 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1956 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1956 intptr_t StartPosition = Asm->GetPosition(); | 1957 intptr_t StartPosition = Asm->GetPosition(); |
| 1957 if (const auto DestVar = llvm::dyn_cast<Variable>(Dest)) { | 1958 if (const auto DestVar = llvm::dyn_cast<Variable>(Dest)) { |
| 1958 assert(!DestVar->hasReg()); | 1959 assert(!DestVar->hasReg()); |
| 1959 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 1960 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 1960 ->stackVarToAsmOperand(DestVar)); | 1961 ->stackVarToAsmOperand(DestVar)); |
| 1961 Asm->movss(DestTy, StackAddr, SrcReg); | 1962 Asm->movss(DestTy, StackAddr, SrcReg); |
| 1962 } else { | 1963 } else { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1988 Str << "\tmovups\t"; | 1989 Str << "\tmovups\t"; |
| 1989 getSrc(0)->emit(Func); | 1990 getSrc(0)->emit(Func); |
| 1990 Str << ", "; | 1991 Str << ", "; |
| 1991 getSrc(1)->emit(Func); | 1992 getSrc(1)->emit(Func); |
| 1992 } | 1993 } |
| 1993 | 1994 |
| 1994 void InstX8632StoreP::emitIAS(const Cfg *Func) const { | 1995 void InstX8632StoreP::emitIAS(const Cfg *Func) const { |
| 1995 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1996 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1996 intptr_t StartPosition = Asm->GetPosition(); | 1997 intptr_t StartPosition = Asm->GetPosition(); |
| 1997 assert(getSrcSize() == 2); | 1998 assert(getSrcSize() == 2); |
| 1998 const Variable *Src = llvm::cast<Variable>(getSrc(0)); | 1999 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); |
| 1999 const OperandX8632Mem *DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); | 2000 const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); |
| 2000 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 2001 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2001 assert(Src->hasReg()); | 2002 assert(SrcVar->hasReg()); |
| 2002 Asm->movups(DestMem->toAsmAddress(Asm), | 2003 Asm->movups(DestMem->toAsmAddress(Asm), |
| 2003 RegX8632::getEncodedXmm(Src->getRegNum())); | 2004 RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
| 2004 emitIASBytes(Func, Asm, StartPosition); | 2005 emitIASBytes(Func, Asm, StartPosition); |
| 2005 } | 2006 } |
| 2006 | 2007 |
| 2007 void InstX8632StoreP::dump(const Cfg *Func) const { | 2008 void InstX8632StoreP::dump(const Cfg *Func) const { |
| 2008 Ostream &Str = Func->getContext()->getStrDump(); | 2009 Ostream &Str = Func->getContext()->getStrDump(); |
| 2009 Str << "storep." << getSrc(0)->getType() << " "; | 2010 Str << "storep." << getSrc(0)->getType() << " "; |
| 2010 getSrc(1)->dump(Func); | 2011 getSrc(1)->dump(Func); |
| 2011 Str << ", "; | 2012 Str << ", "; |
| 2012 getSrc(0)->dump(Func); | 2013 getSrc(0)->dump(Func); |
| 2013 } | 2014 } |
| 2014 | 2015 |
| 2015 void InstX8632StoreQ::emit(const Cfg *Func) const { | 2016 void InstX8632StoreQ::emit(const Cfg *Func) const { |
| 2016 Ostream &Str = Func->getContext()->getStrEmit(); | 2017 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2017 assert(getSrcSize() == 2); | 2018 assert(getSrcSize() == 2); |
| 2018 assert(getSrc(1)->getType() == IceType_i64 || | 2019 assert(getSrc(1)->getType() == IceType_i64 || |
| 2019 getSrc(1)->getType() == IceType_f64); | 2020 getSrc(1)->getType() == IceType_f64); |
| 2020 Str << "\tmovq\t"; | 2021 Str << "\tmovq\t"; |
| 2021 getSrc(0)->emit(Func); | 2022 getSrc(0)->emit(Func); |
| 2022 Str << ", "; | 2023 Str << ", "; |
| 2023 getSrc(1)->emit(Func); | 2024 getSrc(1)->emit(Func); |
| 2024 } | 2025 } |
| 2025 | 2026 |
| 2026 void InstX8632StoreQ::emitIAS(const Cfg *Func) const { | 2027 void InstX8632StoreQ::emitIAS(const Cfg *Func) const { |
| 2027 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2028 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2028 intptr_t StartPosition = Asm->GetPosition(); | 2029 intptr_t StartPosition = Asm->GetPosition(); |
| 2029 assert(getSrcSize() == 2); | 2030 assert(getSrcSize() == 2); |
| 2030 const Variable *Src = llvm::cast<Variable>(getSrc(0)); | 2031 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); |
| 2031 const OperandX8632Mem *DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); | 2032 const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); |
| 2032 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 2033 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2033 assert(Src->hasReg()); | 2034 assert(SrcVar->hasReg()); |
| 2034 Asm->movq(DestMem->toAsmAddress(Asm), | 2035 Asm->movq(DestMem->toAsmAddress(Asm), |
| 2035 RegX8632::getEncodedXmm(Src->getRegNum())); | 2036 RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
| 2036 emitIASBytes(Func, Asm, StartPosition); | 2037 emitIASBytes(Func, Asm, StartPosition); |
| 2037 } | 2038 } |
| 2038 | 2039 |
| 2039 void InstX8632StoreQ::dump(const Cfg *Func) const { | 2040 void InstX8632StoreQ::dump(const Cfg *Func) const { |
| 2040 Ostream &Str = Func->getContext()->getStrDump(); | 2041 Ostream &Str = Func->getContext()->getStrDump(); |
| 2041 Str << "storeq." << getSrc(0)->getType() << " "; | 2042 Str << "storeq." << getSrc(0)->getType() << " "; |
| 2042 getSrc(1)->dump(Func); | 2043 getSrc(1)->dump(Func); |
| 2043 Str << ", "; | 2044 Str << ", "; |
| 2044 getSrc(0)->dump(Func); | 2045 getSrc(0)->dump(Func); |
| 2045 } | 2046 } |
| 2046 | 2047 |
| 2047 template <> void InstX8632Lea::emit(const Cfg *Func) const { | 2048 template <> void InstX8632Lea::emit(const Cfg *Func) const { |
| 2048 Ostream &Str = Func->getContext()->getStrEmit(); | 2049 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2049 assert(getSrcSize() == 1); | 2050 assert(getSrcSize() == 1); |
| 2050 assert(getDest()->hasReg()); | 2051 assert(getDest()->hasReg()); |
| 2051 Str << "\tleal\t"; | 2052 Str << "\tleal\t"; |
| 2052 Operand *Src0 = getSrc(0); | 2053 Operand *Src0 = getSrc(0); |
| 2053 if (Variable *VSrc0 = llvm::dyn_cast<Variable>(Src0)) { | 2054 if (const auto Src0Var = llvm::dyn_cast<Variable>(Src0)) { |
| 2054 Type Ty = VSrc0->getType(); | 2055 Type Ty = Src0Var->getType(); |
| 2055 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an | 2056 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an |
| 2056 // acceptable type. | 2057 // acceptable type. |
| 2057 VSrc0->asType(isVectorType(Ty) ? IceType_i32 : Ty).emit(Func); | 2058 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty).emit(Func); |
| 2058 } else { | 2059 } else { |
| 2059 Src0->emit(Func); | 2060 Src0->emit(Func); |
| 2060 } | 2061 } |
| 2061 Str << ", "; | 2062 Str << ", "; |
| 2062 getDest()->emit(Func); | 2063 getDest()->emit(Func); |
| 2063 } | 2064 } |
| 2064 | 2065 |
| 2065 template <> void InstX8632Mov::emit(const Cfg *Func) const { | 2066 template <> void InstX8632Mov::emit(const Cfg *Func) const { |
| 2066 Ostream &Str = Func->getContext()->getStrEmit(); | 2067 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2067 assert(getSrcSize() == 1); | 2068 assert(getSrcSize() == 1); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2134 emitIASRegOpTyGPR(Func, DestTy, Dest, Src, GPRRegEmitter); | 2135 emitIASRegOpTyGPR(Func, DestTy, Dest, Src, GPRRegEmitter); |
| 2135 return; | 2136 return; |
| 2136 } | 2137 } |
| 2137 } else { | 2138 } else { |
| 2138 // Dest must be Stack and Src *could* be a register. Use Src's type | 2139 // Dest must be Stack and Src *could* be a register. Use Src's type |
| 2139 // to decide on the emitters. | 2140 // to decide on the emitters. |
| 2140 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 2141 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 2141 ->stackVarToAsmOperand(Dest)); | 2142 ->stackVarToAsmOperand(Dest)); |
| 2142 if (isScalarFloatingType(SrcTy)) { | 2143 if (isScalarFloatingType(SrcTy)) { |
| 2143 // Src must be a register. | 2144 // Src must be a register. |
| 2144 const Variable *SrcVar = llvm::cast<Variable>(Src); | 2145 const auto SrcVar = llvm::cast<Variable>(Src); |
| 2145 assert(SrcVar->hasReg()); | 2146 assert(SrcVar->hasReg()); |
| 2146 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2147 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2147 intptr_t StartPosition = Asm->GetPosition(); | 2148 intptr_t StartPosition = Asm->GetPosition(); |
| 2148 Asm->movss(SrcTy, StackAddr, | 2149 Asm->movss(SrcTy, StackAddr, |
| 2149 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | 2150 RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
| 2150 emitIASBytes(Func, Asm, StartPosition); | 2151 emitIASBytes(Func, Asm, StartPosition); |
| 2151 return; | 2152 return; |
| 2152 } else { | 2153 } else { |
| 2153 // Src can be a register or immediate. | 2154 // Src can be a register or immediate. |
| 2154 assert(isScalarIntegerType(SrcTy)); | 2155 assert(isScalarIntegerType(SrcTy)); |
| 2155 emitIASAddrOpTyGPR(Func, SrcTy, StackAddr, Src, GPRAddrEmitter); | 2156 emitIASAddrOpTyGPR(Func, SrcTy, StackAddr, Src, GPRAddrEmitter); |
| 2156 return; | 2157 return; |
| 2157 } | 2158 } |
| 2158 return; | 2159 return; |
| 2159 } | 2160 } |
| 2160 } | 2161 } |
| 2161 | 2162 |
| 2162 template <> void InstX8632Movd::emitIAS(const Cfg *Func) const { | 2163 template <> void InstX8632Movd::emitIAS(const Cfg *Func) const { |
| 2163 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2164 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2164 intptr_t StartPosition = Asm->GetPosition(); | 2165 intptr_t StartPosition = Asm->GetPosition(); |
| 2165 assert(getSrcSize() == 1); | 2166 assert(getSrcSize() == 1); |
| 2166 const Variable *Dest = getDest(); | 2167 const Variable *Dest = getDest(); |
| 2167 const Variable *Src = llvm::cast<Variable>(getSrc(0)); | 2168 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); |
| 2168 // For insert/extract element (one of Src/Dest is an Xmm vector and | 2169 // For insert/extract element (one of Src/Dest is an Xmm vector and |
| 2169 // the other is an int type). | 2170 // the other is an int type). |
| 2170 if (Src->getType() == IceType_i32) { | 2171 if (SrcVar->getType() == IceType_i32) { |
| 2171 assert(isVectorType(Dest->getType())); | 2172 assert(isVectorType(Dest->getType())); |
| 2172 assert(Dest->hasReg()); | 2173 assert(Dest->hasReg()); |
| 2173 RegX8632::XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum()); | 2174 RegX8632::XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum()); |
| 2174 if (Src->hasReg()) { | 2175 if (SrcVar->hasReg()) { |
| 2175 Asm->movd(DestReg, RegX8632::getEncodedGPR(Src->getRegNum())); | 2176 Asm->movd(DestReg, RegX8632::getEncodedGPR(SrcVar->getRegNum())); |
| 2176 } else { | 2177 } else { |
| 2177 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 2178 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 2178 ->stackVarToAsmOperand(Src)); | 2179 ->stackVarToAsmOperand(SrcVar)); |
| 2179 Asm->movd(DestReg, StackAddr); | 2180 Asm->movd(DestReg, StackAddr); |
| 2180 } | 2181 } |
| 2181 } else { | 2182 } else { |
| 2182 assert(isVectorType(Src->getType())); | 2183 assert(isVectorType(SrcVar->getType())); |
| 2183 assert(Src->hasReg()); | 2184 assert(SrcVar->hasReg()); |
| 2184 assert(Dest->getType() == IceType_i32); | 2185 assert(Dest->getType() == IceType_i32); |
| 2185 RegX8632::XmmRegister SrcReg = RegX8632::getEncodedXmm(Src->getRegNum()); | 2186 RegX8632::XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum()); |
| 2186 if (Dest->hasReg()) { | 2187 if (Dest->hasReg()) { |
| 2187 Asm->movd(RegX8632::getEncodedGPR(Dest->getRegNum()), SrcReg); | 2188 Asm->movd(RegX8632::getEncodedGPR(Dest->getRegNum()), SrcReg); |
| 2188 } else { | 2189 } else { |
| 2189 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 2190 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 2190 ->stackVarToAsmOperand(Dest)); | 2191 ->stackVarToAsmOperand(Dest)); |
| 2191 Asm->movd(StackAddr, SrcReg); | 2192 Asm->movd(StackAddr, SrcReg); |
| 2192 } | 2193 } |
| 2193 } | 2194 } |
| 2194 emitIASBytes(Func, Asm, StartPosition); | 2195 emitIASBytes(Func, Asm, StartPosition); |
| 2195 } | 2196 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2241 }; | 2242 }; |
| 2242 emitIASMovlikeXMM(Func, Dest, Src, Emitter); | 2243 emitIASMovlikeXMM(Func, Dest, Src, Emitter); |
| 2243 } | 2244 } |
| 2244 | 2245 |
| 2245 template <> void InstX8632MovssRegs::emitIAS(const Cfg *Func) const { | 2246 template <> void InstX8632MovssRegs::emitIAS(const Cfg *Func) const { |
| 2246 // This is Binop variant is only intended to be used for reg-reg moves | 2247 // This is Binop variant is only intended to be used for reg-reg moves |
| 2247 // where part of the Dest register is untouched. | 2248 // where part of the Dest register is untouched. |
| 2248 assert(getSrcSize() == 2); | 2249 assert(getSrcSize() == 2); |
| 2249 const Variable *Dest = getDest(); | 2250 const Variable *Dest = getDest(); |
| 2250 assert(Dest == getSrc(0)); | 2251 assert(Dest == getSrc(0)); |
| 2251 const Variable *Src = llvm::cast<Variable>(getSrc(1)); | 2252 const auto SrcVar = llvm::cast<Variable>(getSrc(1)); |
| 2252 assert(Dest->hasReg() && Src->hasReg()); | 2253 assert(Dest->hasReg() && SrcVar->hasReg()); |
| 2253 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2254 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2254 intptr_t StartPosition = Asm->GetPosition(); | 2255 intptr_t StartPosition = Asm->GetPosition(); |
| 2255 Asm->movss(IceType_f32, RegX8632::getEncodedXmm(Dest->getRegNum()), | 2256 Asm->movss(IceType_f32, RegX8632::getEncodedXmm(Dest->getRegNum()), |
| 2256 RegX8632::getEncodedXmm(Src->getRegNum())); | 2257 RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
| 2257 emitIASBytes(Func, Asm, StartPosition); | 2258 emitIASBytes(Func, Asm, StartPosition); |
| 2258 } | 2259 } |
| 2259 | 2260 |
| 2260 template <> void InstX8632Movsx::emitIAS(const Cfg *Func) const { | 2261 template <> void InstX8632Movsx::emitIAS(const Cfg *Func) const { |
| 2261 assert(getSrcSize() == 1); | 2262 assert(getSrcSize() == 1); |
| 2262 const Variable *Dest = getDest(); | 2263 const Variable *Dest = getDest(); |
| 2263 const Operand *Src = getSrc(0); | 2264 const Operand *Src = getSrc(0); |
| 2264 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice | 2265 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice |
| 2265 // we just use the full register for Dest to avoid having an | 2266 // we just use the full register for Dest to avoid having an |
| 2266 // OperandSizeOverride prefix. It also allows us to only dispatch on SrcTy. | 2267 // OperandSizeOverride prefix. It also allows us to only dispatch on SrcTy. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2297 void InstX8632Nop::dump(const Cfg *Func) const { | 2298 void InstX8632Nop::dump(const Cfg *Func) const { |
| 2298 Ostream &Str = Func->getContext()->getStrDump(); | 2299 Ostream &Str = Func->getContext()->getStrDump(); |
| 2299 Str << "nop (variant = " << Variant << ")"; | 2300 Str << "nop (variant = " << Variant << ")"; |
| 2300 } | 2301 } |
| 2301 | 2302 |
| 2302 void InstX8632Fld::emit(const Cfg *Func) const { | 2303 void InstX8632Fld::emit(const Cfg *Func) const { |
| 2303 Ostream &Str = Func->getContext()->getStrEmit(); | 2304 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2304 assert(getSrcSize() == 1); | 2305 assert(getSrcSize() == 1); |
| 2305 Type Ty = getSrc(0)->getType(); | 2306 Type Ty = getSrc(0)->getType(); |
| 2306 SizeT Width = typeWidthInBytes(Ty); | 2307 SizeT Width = typeWidthInBytes(Ty); |
| 2307 Variable *Var = llvm::dyn_cast<Variable>(getSrc(0)); | 2308 const auto Var = llvm::dyn_cast<Variable>(getSrc(0)); |
| 2308 if (Var && Var->hasReg()) { | 2309 if (Var && Var->hasReg()) { |
| 2309 // This is a physical xmm register, so we need to spill it to a | 2310 // This is a physical xmm register, so we need to spill it to a |
| 2310 // temporary stack slot. | 2311 // temporary stack slot. |
| 2311 Str << "\tsubl\t$" << Width << ", %esp" | 2312 Str << "\tsubl\t$" << Width << ", %esp" |
| 2312 << "\n"; | 2313 << "\n"; |
| 2313 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"; | 2314 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"; |
| 2314 Var->emit(Func); | 2315 Var->emit(Func); |
| 2315 Str << ", (%esp)\n"; | 2316 Str << ", (%esp)\n"; |
| 2316 Str << "\tfld" << getFldString(Ty) << "\t" | 2317 Str << "\tfld" << getFldString(Ty) << "\t" |
| 2317 << "(%esp)\n"; | 2318 << "(%esp)\n"; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2356 | 2357 |
| 2357 void InstX8632Fld::dump(const Cfg *Func) const { | 2358 void InstX8632Fld::dump(const Cfg *Func) const { |
| 2358 Ostream &Str = Func->getContext()->getStrDump(); | 2359 Ostream &Str = Func->getContext()->getStrDump(); |
| 2359 Str << "fld." << getSrc(0)->getType() << " "; | 2360 Str << "fld." << getSrc(0)->getType() << " "; |
| 2360 dumpSources(Func); | 2361 dumpSources(Func); |
| 2361 } | 2362 } |
| 2362 | 2363 |
| 2363 void InstX8632Fstp::emit(const Cfg *Func) const { | 2364 void InstX8632Fstp::emit(const Cfg *Func) const { |
| 2364 Ostream &Str = Func->getContext()->getStrEmit(); | 2365 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2365 assert(getSrcSize() == 0); | 2366 assert(getSrcSize() == 0); |
| 2366 // TODO(jvoung,stichnot): Utilize this by setting Dest to NULL to | 2367 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to |
| 2367 // "partially" delete the fstp if the Dest is unused. | 2368 // "partially" delete the fstp if the Dest is unused. |
| 2368 // Even if Dest is unused, the fstp should be kept for the SideEffects | 2369 // Even if Dest is unused, the fstp should be kept for the SideEffects |
| 2369 // of popping the stack. | 2370 // of popping the stack. |
| 2370 if (getDest() == NULL) { | 2371 if (!getDest()) { |
| 2371 Str << "\tfstp\tst(0)"; | 2372 Str << "\tfstp\tst(0)"; |
| 2372 return; | 2373 return; |
| 2373 } | 2374 } |
| 2374 Type Ty = getDest()->getType(); | 2375 Type Ty = getDest()->getType(); |
| 2375 size_t Width = typeWidthInBytes(Ty); | 2376 size_t Width = typeWidthInBytes(Ty); |
| 2376 if (!getDest()->hasReg()) { | 2377 if (!getDest()->hasReg()) { |
| 2377 Str << "\tfstp" << getFldString(Ty) << "\t"; | 2378 Str << "\tfstp" << getFldString(Ty) << "\t"; |
| 2378 getDest()->emit(Func); | 2379 getDest()->emit(Func); |
| 2379 return; | 2380 return; |
| 2380 } | 2381 } |
| 2381 // Dest is a physical (xmm) register, so st(0) needs to go through | 2382 // Dest is a physical (xmm) register, so st(0) needs to go through |
| 2382 // memory. Hack this by creating a temporary stack slot, spilling | 2383 // memory. Hack this by creating a temporary stack slot, spilling |
| 2383 // st(0) there, loading it into the xmm register, and deallocating | 2384 // st(0) there, loading it into the xmm register, and deallocating |
| 2384 // the stack slot. | 2385 // the stack slot. |
| 2385 Str << "\tsubl\t$" << Width << ", %esp\n"; | 2386 Str << "\tsubl\t$" << Width << ", %esp\n"; |
| 2386 Str << "\tfstp" << getFldString(Ty) << "\t" | 2387 Str << "\tfstp" << getFldString(Ty) << "\t" |
| 2387 << "(%esp)\n"; | 2388 << "(%esp)\n"; |
| 2388 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" | 2389 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" |
| 2389 << "(%esp), "; | 2390 << "(%esp), "; |
| 2390 getDest()->emit(Func); | 2391 getDest()->emit(Func); |
| 2391 Str << "\n"; | 2392 Str << "\n"; |
| 2392 Str << "\taddl\t$" << Width << ", %esp"; | 2393 Str << "\taddl\t$" << Width << ", %esp"; |
| 2393 } | 2394 } |
| 2394 | 2395 |
| 2395 void InstX8632Fstp::emitIAS(const Cfg *Func) const { | 2396 void InstX8632Fstp::emitIAS(const Cfg *Func) const { |
| 2396 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2397 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2397 intptr_t StartPosition = Asm->GetPosition(); | 2398 intptr_t StartPosition = Asm->GetPosition(); |
| 2398 assert(getSrcSize() == 0); | 2399 assert(getSrcSize() == 0); |
| 2399 const Variable *Dest = getDest(); | 2400 const Variable *Dest = getDest(); |
| 2400 // TODO(jvoung,stichnot): Utilize this by setting Dest to NULL to | 2401 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to |
| 2401 // "partially" delete the fstp if the Dest is unused. | 2402 // "partially" delete the fstp if the Dest is unused. |
| 2402 // Even if Dest is unused, the fstp should be kept for the SideEffects | 2403 // Even if Dest is unused, the fstp should be kept for the SideEffects |
| 2403 // of popping the stack. | 2404 // of popping the stack. |
| 2404 if (Dest == NULL) { | 2405 if (!Dest) { |
| 2405 Asm->fstp(RegX8632::getEncodedSTReg(0)); | 2406 Asm->fstp(RegX8632::getEncodedSTReg(0)); |
| 2406 emitIASBytes(Func, Asm, StartPosition); | 2407 emitIASBytes(Func, Asm, StartPosition); |
| 2407 return; | 2408 return; |
| 2408 } | 2409 } |
| 2409 Type Ty = Dest->getType(); | 2410 Type Ty = Dest->getType(); |
| 2410 if (!Dest->hasReg()) { | 2411 if (!Dest->hasReg()) { |
| 2411 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 2412 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 2412 ->stackVarToAsmOperand(Dest)); | 2413 ->stackVarToAsmOperand(Dest)); |
| 2413 Asm->fstp(Ty, StackAddr); | 2414 Asm->fstp(Ty, StackAddr); |
| 2414 } else { | 2415 } else { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2478 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | 2479 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
| 2479 TargetX8632::SSE4_1); | 2480 TargetX8632::SSE4_1); |
| 2480 // pextrw must take a register dest. There is an SSE4.1 version that takes | 2481 // pextrw must take a register dest. There is an SSE4.1 version that takes |
| 2481 // a memory dest, but we aren't using it. For uniformity, just restrict | 2482 // a memory dest, but we aren't using it. For uniformity, just restrict |
| 2482 // them all to have a register dest for now. | 2483 // them all to have a register dest for now. |
| 2483 assert(Dest->hasReg()); | 2484 assert(Dest->hasReg()); |
| 2484 // pextrw's Src(0) must be a register (both SSE4.1 and SSE2). | 2485 // pextrw's Src(0) must be a register (both SSE4.1 and SSE2). |
| 2485 assert(llvm::cast<Variable>(getSrc(0))->hasReg()); | 2486 assert(llvm::cast<Variable>(getSrc(0))->hasReg()); |
| 2486 static const x86::AssemblerX86::ThreeOpImmEmitter< | 2487 static const x86::AssemblerX86::ThreeOpImmEmitter< |
| 2487 RegX8632::GPRRegister, RegX8632::XmmRegister> Emitter = { | 2488 RegX8632::GPRRegister, RegX8632::XmmRegister> Emitter = { |
| 2488 &x86::AssemblerX86::pextr, NULL}; | 2489 &x86::AssemblerX86::pextr, nullptr}; |
| 2489 emitIASThreeOpImmOps<RegX8632::GPRRegister, RegX8632::XmmRegister, | 2490 emitIASThreeOpImmOps<RegX8632::GPRRegister, RegX8632::XmmRegister, |
| 2490 RegX8632::getEncodedGPR, RegX8632::getEncodedXmm>( | 2491 RegX8632::getEncodedGPR, RegX8632::getEncodedXmm>( |
| 2491 Func, DispatchTy, Dest, getSrc(0), getSrc(1), Emitter); | 2492 Func, DispatchTy, Dest, getSrc(0), getSrc(1), Emitter); |
| 2492 } | 2493 } |
| 2493 | 2494 |
| 2494 template <> void InstX8632Pinsr::emit(const Cfg *Func) const { | 2495 template <> void InstX8632Pinsr::emit(const Cfg *Func) const { |
| 2495 Ostream &Str = Func->getContext()->getStrEmit(); | 2496 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2496 assert(getSrcSize() == 3); | 2497 assert(getSrcSize() == 3); |
| 2497 // pinsrb and pinsrd are SSE4.1 instructions. | 2498 // pinsrb and pinsrd are SSE4.1 instructions. |
| 2498 assert(getDest()->getType() == IceType_v8i16 || | 2499 assert(getDest()->getType() == IceType_v8i16 || |
| 2499 getDest()->getType() == IceType_v8i1 || | 2500 getDest()->getType() == IceType_v8i1 || |
| 2500 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() | 2501 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() |
| 2501 >= TargetX8632::SSE4_1); | 2502 >= TargetX8632::SSE4_1); |
| 2502 Str << "\t" << Opcode | 2503 Str << "\t" << Opcode |
| 2503 << TypeX8632Attributes[getDest()->getType()].PackString << "\t"; | 2504 << TypeX8632Attributes[getDest()->getType()].PackString << "\t"; |
| 2504 getSrc(2)->emit(Func); | 2505 getSrc(2)->emit(Func); |
| 2505 Str << ", "; | 2506 Str << ", "; |
| 2506 Operand *Src1 = getSrc(1); | 2507 Operand *Src1 = getSrc(1); |
| 2507 if (Variable *VSrc1 = llvm::dyn_cast<Variable>(Src1)) { | 2508 if (const auto Src1Var = llvm::dyn_cast<Variable>(Src1)) { |
| 2508 // If src1 is a register, it should always be r32. | 2509 // If src1 is a register, it should always be r32. |
| 2509 if (VSrc1->hasReg()) { | 2510 if (Src1Var->hasReg()) { |
| 2510 VSrc1->asType(IceType_i32).emit(Func); | 2511 Src1Var->asType(IceType_i32).emit(Func); |
| 2511 } else { | 2512 } else { |
| 2512 VSrc1->emit(Func); | 2513 Src1Var->emit(Func); |
| 2513 } | 2514 } |
| 2514 } else { | 2515 } else { |
| 2515 Src1->emit(Func); | 2516 Src1->emit(Func); |
| 2516 } | 2517 } |
| 2517 Str << ", "; | 2518 Str << ", "; |
| 2518 getDest()->emit(Func); | 2519 getDest()->emit(Func); |
| 2519 } | 2520 } |
| 2520 | 2521 |
| 2521 template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const { | 2522 template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const { |
| 2522 assert(getSrcSize() == 3); | 2523 assert(getSrcSize() == 3); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2606 | 2607 |
| 2607 void InstX8632AdjustStack::dump(const Cfg *Func) const { | 2608 void InstX8632AdjustStack::dump(const Cfg *Func) const { |
| 2608 Ostream &Str = Func->getContext()->getStrDump(); | 2609 Ostream &Str = Func->getContext()->getStrDump(); |
| 2609 Str << "esp = sub.i32 esp, " << Amount; | 2610 Str << "esp = sub.i32 esp, " << Amount; |
| 2610 } | 2611 } |
| 2611 | 2612 |
| 2612 void InstX8632Push::emit(const Cfg *Func) const { | 2613 void InstX8632Push::emit(const Cfg *Func) const { |
| 2613 Ostream &Str = Func->getContext()->getStrEmit(); | 2614 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2614 assert(getSrcSize() == 1); | 2615 assert(getSrcSize() == 1); |
| 2615 // Push is currently only used for saving GPRs. | 2616 // Push is currently only used for saving GPRs. |
| 2616 Variable *Var = llvm::cast<Variable>(getSrc(0)); | 2617 const auto Var = llvm::cast<Variable>(getSrc(0)); |
| 2617 assert(Var->hasReg()); | 2618 assert(Var->hasReg()); |
| 2618 Str << "\tpush\t"; | 2619 Str << "\tpush\t"; |
| 2619 Var->emit(Func); | 2620 Var->emit(Func); |
| 2620 } | 2621 } |
| 2621 | 2622 |
| 2622 void InstX8632Push::emitIAS(const Cfg *Func) const { | 2623 void InstX8632Push::emitIAS(const Cfg *Func) const { |
| 2623 assert(getSrcSize() == 1); | 2624 assert(getSrcSize() == 1); |
| 2624 // Push is currently only used for saving GPRs. | 2625 // Push is currently only used for saving GPRs. |
| 2625 Variable *Var = llvm::cast<Variable>(getSrc(0)); | 2626 const auto Var = llvm::cast<Variable>(getSrc(0)); |
| 2626 assert(Var->hasReg()); | 2627 assert(Var->hasReg()); |
| 2627 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2628 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2628 intptr_t StartPosition = Asm->GetPosition(); | 2629 intptr_t StartPosition = Asm->GetPosition(); |
| 2629 Asm->pushl(RegX8632::getEncodedGPR(Var->getRegNum())); | 2630 Asm->pushl(RegX8632::getEncodedGPR(Var->getRegNum())); |
| 2630 emitIASBytes(Func, Asm, StartPosition); | 2631 emitIASBytes(Func, Asm, StartPosition); |
| 2631 } | 2632 } |
| 2632 | 2633 |
| 2633 void InstX8632Push::dump(const Cfg *Func) const { | 2634 void InstX8632Push::dump(const Cfg *Func) const { |
| 2634 Ostream &Str = Func->getContext()->getStrDump(); | 2635 Ostream &Str = Func->getContext()->getStrDump(); |
| 2635 Str << "push." << getSrc(0)->getType() << " "; | 2636 Str << "push." << getSrc(0)->getType() << " "; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2686 getSrc(1)->emit(Func); | 2687 getSrc(1)->emit(Func); |
| 2687 Str << ", "; | 2688 Str << ", "; |
| 2688 getSrc(0)->emit(Func); | 2689 getSrc(0)->emit(Func); |
| 2689 } | 2690 } |
| 2690 | 2691 |
| 2691 void InstX8632Xadd::emitIAS(const Cfg *Func) const { | 2692 void InstX8632Xadd::emitIAS(const Cfg *Func) const { |
| 2692 assert(getSrcSize() == 2); | 2693 assert(getSrcSize() == 2); |
| 2693 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2694 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2694 intptr_t StartPosition = Asm->GetPosition(); | 2695 intptr_t StartPosition = Asm->GetPosition(); |
| 2695 Type Ty = getSrc(0)->getType(); | 2696 Type Ty = getSrc(0)->getType(); |
| 2696 const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | 2697 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
| 2697 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 2698 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2698 const x86::Address Addr = Mem->toAsmAddress(Asm); | 2699 const x86::Address Addr = Mem->toAsmAddress(Asm); |
| 2699 const Variable *VarReg = llvm::cast<Variable>(getSrc(1)); | 2700 const auto VarReg = llvm::cast<Variable>(getSrc(1)); |
| 2700 assert(VarReg->hasReg()); | 2701 assert(VarReg->hasReg()); |
| 2701 const RegX8632::GPRRegister Reg = | 2702 const RegX8632::GPRRegister Reg = |
| 2702 RegX8632::getEncodedGPR(VarReg->getRegNum()); | 2703 RegX8632::getEncodedGPR(VarReg->getRegNum()); |
| 2703 if (Locked) { | 2704 if (Locked) { |
| 2704 Asm->lock(); | 2705 Asm->lock(); |
| 2705 } | 2706 } |
| 2706 Asm->xadd(Ty, Addr, Reg); | 2707 Asm->xadd(Ty, Addr, Reg); |
| 2707 emitIASBytes(Func, Asm, StartPosition); | 2708 emitIASBytes(Func, Asm, StartPosition); |
| 2708 } | 2709 } |
| 2709 | 2710 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2723 getSrc(1)->emit(Func); | 2724 getSrc(1)->emit(Func); |
| 2724 Str << ", "; | 2725 Str << ", "; |
| 2725 getSrc(0)->emit(Func); | 2726 getSrc(0)->emit(Func); |
| 2726 } | 2727 } |
| 2727 | 2728 |
| 2728 void InstX8632Xchg::emitIAS(const Cfg *Func) const { | 2729 void InstX8632Xchg::emitIAS(const Cfg *Func) const { |
| 2729 assert(getSrcSize() == 2); | 2730 assert(getSrcSize() == 2); |
| 2730 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2731 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2731 intptr_t StartPosition = Asm->GetPosition(); | 2732 intptr_t StartPosition = Asm->GetPosition(); |
| 2732 Type Ty = getSrc(0)->getType(); | 2733 Type Ty = getSrc(0)->getType(); |
| 2733 const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | 2734 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
| 2734 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 2735 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2735 const x86::Address Addr = Mem->toAsmAddress(Asm); | 2736 const x86::Address Addr = Mem->toAsmAddress(Asm); |
| 2736 const Variable *VarReg = llvm::cast<Variable>(getSrc(1)); | 2737 const auto VarReg = llvm::cast<Variable>(getSrc(1)); |
| 2737 assert(VarReg->hasReg()); | 2738 assert(VarReg->hasReg()); |
| 2738 const RegX8632::GPRRegister Reg = | 2739 const RegX8632::GPRRegister Reg = |
| 2739 RegX8632::getEncodedGPR(VarReg->getRegNum()); | 2740 RegX8632::getEncodedGPR(VarReg->getRegNum()); |
| 2740 Asm->xchg(Ty, Addr, Reg); | 2741 Asm->xchg(Ty, Addr, Reg); |
| 2741 emitIASBytes(Func, Asm, StartPosition); | 2742 emitIASBytes(Func, Asm, StartPosition); |
| 2742 } | 2743 } |
| 2743 | 2744 |
| 2744 void InstX8632Xchg::dump(const Cfg *Func) const { | 2745 void InstX8632Xchg::dump(const Cfg *Func) const { |
| 2745 Ostream &Str = Func->getContext()->getStrDump(); | 2746 Ostream &Str = Func->getContext()->getStrDump(); |
| 2746 Type Ty = getSrc(0)->getType(); | 2747 Type Ty = getSrc(0)->getType(); |
| 2747 Str << "xchg." << Ty << " "; | 2748 Str << "xchg." << Ty << " "; |
| 2748 dumpSources(Func); | 2749 dumpSources(Func); |
| 2749 } | 2750 } |
| 2750 | 2751 |
| 2751 void OperandX8632Mem::emit(const Cfg *Func) const { | 2752 void OperandX8632Mem::emit(const Cfg *Func) const { |
| 2752 Ostream &Str = Func->getContext()->getStrEmit(); | 2753 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2753 if (SegmentReg != DefaultSegment) { | 2754 if (SegmentReg != DefaultSegment) { |
| 2754 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); | 2755 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
| 2755 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; | 2756 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; |
| 2756 } | 2757 } |
| 2757 // Emit as Offset(Base,Index,1<<Shift). | 2758 // Emit as Offset(Base,Index,1<<Shift). |
| 2758 // Offset is emitted without the leading '$'. | 2759 // Offset is emitted without the leading '$'. |
| 2759 // Omit the (Base,Index,1<<Shift) part if Base==NULL. | 2760 // Omit the (Base,Index,1<<Shift) part if Base==nullptr. |
| 2760 if (Offset == NULL) { | 2761 if (!Offset) { |
| 2761 // No offset, emit nothing. | 2762 // No offset, emit nothing. |
| 2762 } else if (auto CI = llvm::dyn_cast<ConstantInteger32>(Offset)) { | 2763 } else if (const auto CI = llvm::dyn_cast<ConstantInteger32>(Offset)) { |
| 2763 if (CI->getValue()) | 2764 if (CI->getValue()) |
| 2764 // Emit a non-zero offset without a leading '$'. | 2765 // Emit a non-zero offset without a leading '$'. |
| 2765 Str << CI->getValue(); | 2766 Str << CI->getValue(); |
| 2766 } else if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) { | 2767 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) { |
| 2767 CR->emitWithoutDollar(Func->getContext()); | 2768 CR->emitWithoutDollar(Func->getContext()); |
| 2768 } else { | 2769 } else { |
| 2769 llvm_unreachable("Invalid offset type for x86 mem operand"); | 2770 llvm_unreachable("Invalid offset type for x86 mem operand"); |
| 2770 } | 2771 } |
| 2771 | 2772 |
| 2772 if (Base) { | 2773 if (Base) { |
| 2773 Str << "("; | 2774 Str << "("; |
| 2774 Base->emit(Func); | 2775 Base->emit(Func); |
| 2775 if (Index) { | 2776 if (Index) { |
| 2776 Str << ","; | 2777 Str << ","; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2803 Str << (1u << Shift) << "*"; | 2804 Str << (1u << Shift) << "*"; |
| 2804 if (Func) | 2805 if (Func) |
| 2805 Index->dump(Func); | 2806 Index->dump(Func); |
| 2806 else | 2807 else |
| 2807 Index->dump(Str); | 2808 Index->dump(Str); |
| 2808 Dumped = true; | 2809 Dumped = true; |
| 2809 } | 2810 } |
| 2810 // Pretty-print the Offset. | 2811 // Pretty-print the Offset. |
| 2811 bool OffsetIsZero = false; | 2812 bool OffsetIsZero = false; |
| 2812 bool OffsetIsNegative = false; | 2813 bool OffsetIsNegative = false; |
| 2813 if (Offset == NULL) { | 2814 if (!Offset) { |
| 2814 OffsetIsZero = true; | 2815 OffsetIsZero = true; |
| 2815 } else if (ConstantInteger32 *CI = | 2816 } else if (const auto CI = llvm::dyn_cast<ConstantInteger32>(Offset)) { |
| 2816 llvm::dyn_cast<ConstantInteger32>(Offset)) { | |
| 2817 OffsetIsZero = (CI->getValue() == 0); | 2817 OffsetIsZero = (CI->getValue() == 0); |
| 2818 OffsetIsNegative = (static_cast<int32_t>(CI->getValue()) < 0); | 2818 OffsetIsNegative = (static_cast<int32_t>(CI->getValue()) < 0); |
| 2819 } else { | 2819 } else { |
| 2820 assert(llvm::isa<ConstantRelocatable>(Offset)); | 2820 assert(llvm::isa<ConstantRelocatable>(Offset)); |
| 2821 } | 2821 } |
| 2822 if (Dumped) { | 2822 if (Dumped) { |
| 2823 if (!OffsetIsZero) { // Suppress if Offset is known to be 0 | 2823 if (!OffsetIsZero) { // Suppress if Offset is known to be 0 |
| 2824 if (!OffsetIsNegative) // Suppress if Offset is known to be negative | 2824 if (!OffsetIsNegative) // Suppress if Offset is known to be negative |
| 2825 Str << "+"; | 2825 Str << "+"; |
| 2826 Offset->dump(Func, Str); | 2826 Offset->dump(Func, Str); |
| 2827 } | 2827 } |
| 2828 } else { | 2828 } else { |
| 2829 // There is only the offset. | 2829 // There is only the offset. |
| 2830 Offset->dump(Func, Str); | 2830 Offset->dump(Func, Str); |
| 2831 } | 2831 } |
| 2832 Str << "]"; | 2832 Str << "]"; |
| 2833 } | 2833 } |
| 2834 | 2834 |
| 2835 void OperandX8632Mem::emitSegmentOverride(x86::AssemblerX86 *Asm) const { | 2835 void OperandX8632Mem::emitSegmentOverride(x86::AssemblerX86 *Asm) const { |
| 2836 if (SegmentReg != DefaultSegment) { | 2836 if (SegmentReg != DefaultSegment) { |
| 2837 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); | 2837 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
| 2838 Asm->EmitSegmentOverride(InstX8632SegmentPrefixes[SegmentReg]); | 2838 Asm->EmitSegmentOverride(InstX8632SegmentPrefixes[SegmentReg]); |
| 2839 } | 2839 } |
| 2840 } | 2840 } |
| 2841 | 2841 |
| 2842 x86::Address OperandX8632Mem::toAsmAddress(Assembler *Asm) const { | 2842 x86::Address OperandX8632Mem::toAsmAddress(Assembler *Asm) const { |
| 2843 int32_t Disp = 0; | 2843 int32_t Disp = 0; |
| 2844 AssemblerFixup *Fixup = NULL; | 2844 AssemblerFixup *Fixup = nullptr; |
| 2845 // Determine the offset (is it relocatable?) | 2845 // Determine the offset (is it relocatable?) |
| 2846 if (getOffset()) { | 2846 if (getOffset()) { |
| 2847 if (ConstantInteger32 *CI = | 2847 if (const auto CI = llvm::dyn_cast<ConstantInteger32>(getOffset())) { |
| 2848 llvm::dyn_cast<ConstantInteger32>(getOffset())) { | |
| 2849 Disp = static_cast<int32_t>(CI->getValue()); | 2848 Disp = static_cast<int32_t>(CI->getValue()); |
| 2850 } else if (ConstantRelocatable *CR = | 2849 } else if (const auto CR = |
| 2851 llvm::dyn_cast<ConstantRelocatable>(getOffset())) { | 2850 llvm::dyn_cast<ConstantRelocatable>(getOffset())) { |
| 2852 Fixup = x86::DisplacementRelocation::create(Asm, FK_Abs_4, CR); | 2851 Fixup = x86::DisplacementRelocation::create(Asm, FK_Abs_4, CR); |
| 2853 } else { | 2852 } else { |
| 2854 llvm_unreachable("Unexpected offset type"); | 2853 llvm_unreachable("Unexpected offset type"); |
| 2855 } | 2854 } |
| 2856 } | 2855 } |
| 2857 | 2856 |
| 2858 // Now convert to the various possible forms. | 2857 // Now convert to the various possible forms. |
| 2859 if (getBase() && getIndex()) { | 2858 if (getBase() && getIndex()) { |
| 2860 return x86::Address(RegX8632::getEncodedGPR(getBase()->getRegNum()), | 2859 return x86::Address(RegX8632::getEncodedGPR(getBase()->getRegNum()), |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2910 } | 2909 } |
| 2911 Str << "("; | 2910 Str << "("; |
| 2912 if (Func) | 2911 if (Func) |
| 2913 Var->dump(Func); | 2912 Var->dump(Func); |
| 2914 else | 2913 else |
| 2915 Var->dump(Str); | 2914 Var->dump(Str); |
| 2916 Str << ")"; | 2915 Str << ")"; |
| 2917 } | 2916 } |
| 2918 | 2917 |
| 2919 } // end of namespace Ice | 2918 } // end of namespace Ice |
| OLD | NEW |