| Index: src/IceInstX8632.cpp
|
| diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp
|
| index a1a4d68790d22d39fa6eafd5bf9d326d9b6d8e3b..a55c8fee76193163dcebda44d7f047aac9731670 100644
|
| --- a/src/IceInstX8632.cpp
|
| +++ b/src/IceInstX8632.cpp
|
| @@ -12,6 +12,7 @@
|
| //
|
| //===----------------------------------------------------------------------===//
|
|
|
| +#include "assembler_ia32.h"
|
| #include "IceCfg.h"
|
| #include "IceCfgNode.h"
|
| #include "IceInst.h"
|
| @@ -63,6 +64,44 @@ const char *InstX8632SegmentRegNames[] = {
|
| #undef X
|
| };
|
|
|
| +x86::Condition convertToAsmCondition(InstX8632::BrCond Cond) {
|
| + return x86::Condition(Cond);
|
| +}
|
| +
|
| +x86::Register convertToAsmGPR(int32_t RegNum) {
|
| + assert(TargetX8632::Reg_eax <= RegNum && RegNum <= TargetX8632::Reg_edi);
|
| + // TODO(jvoung): do some sort of cross-check that the numbers are the same.
|
| + return x86::Register(RegNum);
|
| +}
|
| +
|
| +x86::ByteRegister convertToAsmByteRegister(int32_t RegNum) {
|
| + if (RegNum == TargetX8632::Reg_ah) {
|
| + return x86::AH;
|
| + }
|
| + // TODO(jvoung): do some sort of cross-check that the numbers are the same.
|
| + assert(TargetX8632::Reg_eax <= RegNum && RegNum <= TargetX8632::Reg_ebx);
|
| + return x86::ByteRegister(RegNum);
|
| +}
|
| +
|
| +x86::XmmRegister convertToAsmXMMReg(int32_t RegNum) {
|
| + assert(TargetX8632::Reg_xmm0 <= RegNum && RegNum <= TargetX8632::Reg_xmm7);
|
| + // TODO(jvoung): do some sort of cross-check that the numbers are the same.
|
| + return x86::XmmRegister(RegNum - TargetX8632::Reg_xmm0);
|
| +}
|
| +
|
| +// Convert a float or double immediate to an Address Operand.
|
| +// Modifies SymbolicOffset to contain the symbol.
|
| +x86::Address convertImmToAsmAddress(const Constant *Imm,
|
| + IceString &SymbolicOffset) {
|
| + std::string Buffer;
|
| + llvm::raw_string_ostream StrBuf(Buffer);
|
| + Type Ty = Imm->getType();
|
| + assert(llvm::isa<ConstantFloat>(Imm) || llvm::isa<ConstantDouble>(Imm));
|
| + StrBuf << "L$" << Ty << "$" << Imm->getPoolEntryID();
|
| + SymbolicOffset = StrBuf.str();
|
| + return x86::Address::Absolute(0);
|
| +}
|
| +
|
| } // end of anonymous namespace
|
|
|
| const char *InstX8632::getWidthString(Type Ty) {
|
| @@ -284,12 +323,76 @@ InstX8632Xchg::InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source)
|
|
|
| // ======================== Dump routines ======================== //
|
|
|
| +namespace {
|
| +
|
| +void emitIASBytes(Ostream &Str, const x86::AssemblerX86 *Asm,
|
| + intptr_t StartPosition) {
|
| + intptr_t EndPosition = Asm->GetPosition();
|
| + for (intptr_t i = 0; i < EndPosition - StartPosition; ++i) {
|
| + Str << "\t.byte "
|
| + << static_cast<uint32_t>(Asm->LoadBuffer(StartPosition + i)) << "\n";
|
| + }
|
| +}
|
| +
|
| +void emitIASBytesRelocatable(Ostream &Str, const x86::AssemblerX86 *Asm,
|
| + intptr_t StartPosition,
|
| + const IceString &SymbolicOffset) {
|
| + const intptr_t OffsetSize = 4;
|
| + intptr_t EndPosition = Asm->GetPosition() - OffsetSize;
|
| + for (intptr_t i = 0; i < EndPosition - StartPosition; ++i) {
|
| + Str << "\t.byte "
|
| + << static_cast<uint32_t>(Asm->LoadBuffer(StartPosition + i)) << "\n";
|
| + }
|
| + Str << "\t.long " << SymbolicOffset << "\n";
|
| +}
|
| +
|
| +void emitIASDestSrcXMM(const Cfg *Func, const Variable *Dest,
|
| + const Operand *Src,
|
| + x86::AssemblerX86::EmitXmmXmm EmitXmmXmm,
|
| + x86::AssemblerX86::EmitXmmAddr EmitXmmAddr) {
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + intptr_t StartPosition = Asm->GetPosition();
|
| + assert(Dest->hasReg());
|
| + x86::XmmRegister DestReg = convertToAsmXMMReg(Dest->getRegNum());
|
| + IceString SymbolicOffset = "";
|
| + if (const Variable *SrcVar = llvm::dyn_cast<Variable>(Src)) {
|
| + if (SrcVar->hasReg()) {
|
| + x86::XmmRegister SrcReg = convertToAsmXMMReg(SrcVar->getRegNum());
|
| + (Asm->*EmitXmmXmm)(DestReg, SrcReg);
|
| + } else {
|
| + x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget())
|
| + ->stackVarToAsmOperand(SrcVar);
|
| + (Asm->*EmitXmmAddr)(DestReg, SrcStackAddr);
|
| + }
|
| + } else if (const OperandX8632Mem *Mem =
|
| + llvm::dyn_cast<OperandX8632Mem>(Src)) {
|
| + x86::Address SrcAddr = Mem->convertToAsmAddress(SymbolicOffset);
|
| + (Asm->*EmitXmmAddr)(DestReg, SrcAddr);
|
| + } else if (const Constant *Imm = llvm::dyn_cast<Constant>(Src)) {
|
| + (Asm->*EmitXmmAddr)(DestReg, convertImmToAsmAddress(Imm, SymbolicOffset));
|
| + } else {
|
| + llvm_unreachable("Unexpected operand type");
|
| + }
|
| + // TODO(jvoung): Record the buffer position containing the relocation,
|
| + // instead of just assuming it's the last 4 bytes.
|
| + if (!SymbolicOffset.empty()) {
|
| + emitIASBytesRelocatable(Str, Asm, StartPosition, SymbolicOffset);
|
| + } else {
|
| + emitIASBytes(Str, Asm, StartPosition);
|
| + }
|
| +}
|
| +
|
| +} // end of anonymous namespace
|
| +
|
| void InstX8632::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| Str << "[X8632] ";
|
| Inst::dump(Func);
|
| }
|
|
|
| +void InstX8632::emitIAS(const Cfg *Func) const { emit(Func); }
|
| +
|
| void InstX8632Label::emit(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrEmit();
|
| Str << getName(Func) << ":\n";
|
| @@ -354,6 +457,43 @@ void InstX8632Call::emit(const Cfg *Func) const {
|
| Func->getTarget()->resetStackAdjustment();
|
| }
|
|
|
| +void InstX8632Call::emitIAS(const Cfg *Func) const {
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + intptr_t StartPosition = Asm->GetPosition();
|
| + Operand *Target = getCallTarget();
|
| + IceString SymbolicOffset = "";
|
| + if (Variable *Var = llvm::dyn_cast<Variable>(Target)) {
|
| + if (Var->hasReg()) {
|
| + Asm->call(convertToAsmGPR(Var->getRegNum()));
|
| + } else {
|
| + Asm->call(static_cast<TargetX8632 *>(Func->getTarget())
|
| + ->stackVarToAsmOperand(Var));
|
| + }
|
| + } else if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) {
|
| + Asm->call(Mem->convertToAsmAddress(SymbolicOffset));
|
| + } else if (ConstantRelocatable *CR =
|
| + llvm::dyn_cast<ConstantRelocatable>(Target)) {
|
| + assert(CR->getOffset() == 0 && "We only support calling a function");
|
| + SymbolicOffset = CR->getName();
|
| + Asm->call(CR);
|
| + }
|
| + if (!SymbolicOffset.empty()) {
|
| + // TODO(jvoung): This .byte and .long hack doesn't work, since we need
|
| + // a pc-rel relocation, and we also need the section contents to be
|
| + // -4 instead of 0.
|
| + //
|
| + // Still, we have at least filled the assembler buffer so that the
|
| + // instruction sizes/positions are correct for jumps.
|
| + //
|
| + // For now, fall back to the regular .s emission.
|
| + emit(Func);
|
| + } else {
|
| + emitIASBytes(Str, Asm, StartPosition);
|
| + }
|
| + Func->getTarget()->resetStackAdjustment();
|
| +}
|
| +
|
| void InstX8632Call::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| if (getDest()) {
|
| @@ -477,6 +617,27 @@ template <> void InstX8632Sqrtss::emit(const Cfg *Func) const {
|
| Str << "\n";
|
| }
|
|
|
| +template <> void InstX8632Sqrtss::emitIAS(const Cfg *Func) const {
|
| + assert(getDest()->hasReg());
|
| + assert(getSrcSize() == 1);
|
| + const Operand *Src = getSrc(0);
|
| + Type Ty = getSrc(0)->getType();
|
| + assert(Ty == IceType_f32 || Ty == IceType_f64);
|
| + if (Ty == IceType_f64) {
|
| + emitIASDestSrcXMM(Func, getDest(), Src, &x86::AssemblerX86::sqrtsd,
|
| + &x86::AssemblerX86::sqrtsd);
|
| + } else {
|
| + emitIASDestSrcXMM(Func, getDest(), Src, &x86::AssemblerX86::sqrtss,
|
| + &x86::AssemblerX86::sqrtss);
|
| + }
|
| +}
|
| +
|
| +template <> void InstX8632Addps::emitIAS(const Cfg *Func) const {
|
| + assert(getSrcSize() == 2);
|
| + emitIASDestSrcXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::addps,
|
| + &x86::AssemblerX86::addps);
|
| +}
|
| +
|
| template <> void InstX8632Addss::emit(const Cfg *Func) const {
|
| char buf[30];
|
| snprintf(buf, llvm::array_lengthof(buf), "add%s",
|
| @@ -484,6 +645,18 @@ template <> void InstX8632Addss::emit(const Cfg *Func) const {
|
| emitTwoAddress(buf, this, Func);
|
| }
|
|
|
| +template <> void InstX8632Addss::emitIAS(const Cfg *Func) const {
|
| + Type Ty = getDest()->getType();
|
| + assert(getSrcSize() == 2);
|
| + if (Ty == IceType_f64) {
|
| + emitIASDestSrcXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::addsd,
|
| + &x86::AssemblerX86::addsd);
|
| + } else {
|
| + emitIASDestSrcXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::addss,
|
| + &x86::AssemblerX86::addss);
|
| + }
|
| +}
|
| +
|
| template <> void InstX8632Padd::emit(const Cfg *Func) const {
|
| char buf[30];
|
| snprintf(buf, llvm::array_lengthof(buf), "padd%s",
|
| @@ -508,6 +681,12 @@ template <> void InstX8632Pmull::emit(const Cfg *Func) const {
|
| emitTwoAddress(buf, this, Func);
|
| }
|
|
|
| +template <> void InstX8632Subps::emitIAS(const Cfg *Func) const {
|
| + assert(getSrcSize() == 2);
|
| + emitIASDestSrcXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::subps,
|
| + &x86::AssemblerX86::subps);
|
| +}
|
| +
|
| template <> void InstX8632Subss::emit(const Cfg *Func) const {
|
| char buf[30];
|
| snprintf(buf, llvm::array_lengthof(buf), "sub%s",
|
| @@ -515,6 +694,18 @@ template <> void InstX8632Subss::emit(const Cfg *Func) const {
|
| emitTwoAddress(buf, this, Func);
|
| }
|
|
|
| +template <> void InstX8632Subss::emitIAS(const Cfg *Func) const {
|
| + Type Ty = getDest()->getType();
|
| + assert(getSrcSize() == 2);
|
| + if (Ty == IceType_f64) {
|
| + emitIASDestSrcXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::subsd,
|
| + &x86::AssemblerX86::subsd);
|
| + } else {
|
| + emitIASDestSrcXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::subss,
|
| + &x86::AssemblerX86::subss);
|
| + }
|
| +}
|
| +
|
| template <> void InstX8632Psub::emit(const Cfg *Func) const {
|
| char buf[30];
|
| snprintf(buf, llvm::array_lengthof(buf), "psub%s",
|
| @@ -522,6 +713,12 @@ template <> void InstX8632Psub::emit(const Cfg *Func) const {
|
| emitTwoAddress(buf, this, Func);
|
| }
|
|
|
| +template <> void InstX8632Mulps::emitIAS(const Cfg *Func) const {
|
| + assert(getSrcSize() == 2);
|
| + emitIASDestSrcXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::mulps,
|
| + &x86::AssemblerX86::mulps);
|
| +}
|
| +
|
| template <> void InstX8632Mulss::emit(const Cfg *Func) const {
|
| char buf[30];
|
| snprintf(buf, llvm::array_lengthof(buf), "mul%s",
|
| @@ -529,12 +726,30 @@ template <> void InstX8632Mulss::emit(const Cfg *Func) const {
|
| emitTwoAddress(buf, this, Func);
|
| }
|
|
|
| +template <> void InstX8632Mulss::emitIAS(const Cfg *Func) const {
|
| + Type Ty = getDest()->getType();
|
| + assert(getSrcSize() == 2);
|
| + if (Ty == IceType_f64) {
|
| + emitIASDestSrcXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::mulsd,
|
| + &x86::AssemblerX86::mulsd);
|
| + } else {
|
| + emitIASDestSrcXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::mulss,
|
| + &x86::AssemblerX86::mulss);
|
| + }
|
| +}
|
| +
|
| template <> void InstX8632Pmuludq::emit(const Cfg *Func) const {
|
| assert(getSrc(0)->getType() == IceType_v4i32 &&
|
| getSrc(1)->getType() == IceType_v4i32);
|
| emitTwoAddress(Opcode, this, Func);
|
| }
|
|
|
| +template <> void InstX8632Divps::emitIAS(const Cfg *Func) const {
|
| + assert(getSrcSize() == 2);
|
| + emitIASDestSrcXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::divps,
|
| + &x86::AssemblerX86::divps);
|
| +}
|
| +
|
| template <> void InstX8632Divss::emit(const Cfg *Func) const {
|
| char buf[30];
|
| snprintf(buf, llvm::array_lengthof(buf), "div%s",
|
| @@ -542,6 +757,18 @@ template <> void InstX8632Divss::emit(const Cfg *Func) const {
|
| emitTwoAddress(buf, this, Func);
|
| }
|
|
|
| +template <> void InstX8632Divss::emitIAS(const Cfg *Func) const {
|
| + Type Ty = getDest()->getType();
|
| + assert(getSrcSize() == 2);
|
| + if (Ty == IceType_f64) {
|
| + emitIASDestSrcXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::divsd,
|
| + &x86::AssemblerX86::divsd);
|
| + } else {
|
| + emitIASDestSrcXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::divss,
|
| + &x86::AssemblerX86::divss);
|
| + }
|
| +}
|
| +
|
| template <> void InstX8632Div::emit(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrEmit();
|
| assert(getSrcSize() == 3);
|
| @@ -639,6 +866,34 @@ template <> void InstX8632Cbwdq::emit(const Cfg *Func) const {
|
| }
|
| }
|
|
|
| +template <> void InstX8632Cbwdq::emitIAS(const Cfg *Func) const {
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + intptr_t StartPosition = Asm->GetPosition();
|
| + assert(getSrcSize() == 1);
|
| + Operand *Src0 = getSrc(0);
|
| + assert(llvm::isa<Variable>(Src0));
|
| + assert(llvm::cast<Variable>(Src0)->getRegNum() == TargetX8632::Reg_eax);
|
| + switch (Src0->getType()) {
|
| + default:
|
| + llvm_unreachable("unexpected source type!");
|
| + break;
|
| + case IceType_i8:
|
| + assert(getDest()->getRegNum() == TargetX8632::Reg_eax);
|
| + Asm->cbw();
|
| + break;
|
| + case IceType_i16:
|
| + assert(getDest()->getRegNum() == TargetX8632::Reg_edx);
|
| + Asm->cwd();
|
| + break;
|
| + case IceType_i32:
|
| + assert(getDest()->getRegNum() == TargetX8632::Reg_edx);
|
| + Asm->cdq();
|
| + break;
|
| + }
|
| + emitIASBytes(Str, Asm, StartPosition);
|
| +}
|
| +
|
| void InstX8632Mul::emit(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrEmit();
|
| assert(getSrcSize() == 2);
|
| @@ -722,6 +977,23 @@ void InstX8632Cmov::emit(const Cfg *Func) const {
|
| Str << "\n";
|
| }
|
|
|
| +void InstX8632Cmov::emitIAS(const Cfg *Func) const {
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + assert(Condition != Br_None);
|
| + assert(getDest()->hasReg());
|
| + assert(getSrcSize() == 2);
|
| + const Variable *Src = llvm::cast<Variable>(getSrc(1));
|
| + // Only need the 32-bit register form right now.
|
| + assert(Src->hasReg());
|
| + assert(Src->getType() == IceType_i32);
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + intptr_t StartPosition = Asm->GetPosition();
|
| + Asm->cmov(convertToAsmCondition(Condition),
|
| + convertToAsmGPR(getDest()->getRegNum()),
|
| + convertToAsmGPR(Src->getRegNum()));
|
| + emitIASBytes(Str, Asm, StartPosition);
|
| +}
|
| +
|
| void InstX8632Cmov::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << ".";
|
| @@ -744,6 +1016,28 @@ void InstX8632Cmpps::emit(const Cfg *Func) const {
|
| Str << "\n";
|
| }
|
|
|
| +void InstX8632Cmpps::emitIAS(const Cfg *Func) const {
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + intptr_t StartPosition = Asm->GetPosition();
|
| + assert(getSrcSize() == 2);
|
| + assert(Condition < Cmpps_Invalid);
|
| + // Assuming there isn't any load folding for cmpps, and vector constants
|
| + // are not allowed in PNaCl.
|
| + assert(llvm::isa<Variable>(getSrc(1)));
|
| + const Variable *SrcVar = llvm::cast<Variable>(getSrc(1));
|
| + if (SrcVar->hasReg()) {
|
| + Asm->cmpps(convertToAsmXMMReg(getDest()->getRegNum()),
|
| + convertToAsmXMMReg(SrcVar->getRegNum()), Condition);
|
| + } else {
|
| + x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget())
|
| + ->stackVarToAsmOperand(SrcVar);
|
| + Asm->cmpps(convertToAsmXMMReg(getDest()->getRegNum()), SrcStackAddr,
|
| + Condition);
|
| + }
|
| + emitIASBytes(Str, Asm, StartPosition);
|
| +}
|
| +
|
| void InstX8632Cmpps::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| assert(Condition < Cmpps_Invalid);
|
| @@ -997,6 +1291,11 @@ template <> void InstX8632Mov::emit(const Cfg *Func) const {
|
| Str << "\n";
|
| }
|
|
|
| +template <> void InstX8632Mov::emitIAS(const Cfg *Func) const {
|
| + // Could be movss/sd, or movb/movw/movl.
|
| + emit(Func);
|
| +}
|
| +
|
| template <> void InstX8632Movp::emit(const Cfg *Func) const {
|
| // TODO(wala,stichnot): movups works with all vector operands, but
|
| // there exist other instructions (movaps, movdqa, movdqu) that may
|
| @@ -1023,6 +1322,49 @@ template <> void InstX8632Movq::emit(const Cfg *Func) const {
|
| Str << "\n";
|
| }
|
|
|
| +static void emitIASSignZeroExt(const Cfg *Func, const Variable *Dest,
|
| + const Operand *Src0,
|
| + x86::AssemblerX86::EmitRegByteR EmitByte,
|
| + x86::AssemblerX86::EmitRegReg EmitWord,
|
| + x86::AssemblerX86::EmitRegAddr EmitAddress) {
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + assert(Dest->hasReg());
|
| + x86::Register DestReg = convertToAsmGPR(Dest->getRegNum());
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + intptr_t StartPosition = Asm->GetPosition();
|
| + IceString SymbolicOffset = "";
|
| + Type SrcType = Src0->getType();
|
| + // Source is ByteReg, WordReg, or stack slot, or other memory operand.
|
| + if (const Variable *SrcVar = llvm::dyn_cast<Variable>(Src0)) {
|
| + if (SrcVar->hasReg()) {
|
| + if (SrcType == IceType_i8 || SrcType == IceType_i1) {
|
| + (Asm->*EmitByte)(DestReg,
|
| + convertToAsmByteRegister(SrcVar->getRegNum()));
|
| + } else {
|
| + assert(SrcType == IceType_i16);
|
| + (Asm->*EmitWord)(DestReg, convertToAsmGPR(SrcVar->getRegNum()));
|
| + }
|
| + } else {
|
| + x86::Address StackAddr = static_cast<TargetX8632 *>(Func->getTarget())
|
| + ->stackVarToAsmOperand(SrcVar);
|
| + (Asm->*EmitAddress)(DestReg, StackAddr);
|
| + }
|
| + } else if (const OperandX8632Mem *Mem =
|
| + llvm::dyn_cast<OperandX8632Mem>(Src0)) {
|
| + x86::Address SrcAddr = Mem->convertToAsmAddress(SymbolicOffset);
|
| + (Asm->*EmitAddress)(DestReg, SrcAddr);
|
| + } else {
|
| + llvm_unreachable("Unexpected operand type for Movzx");
|
| + }
|
| +
|
| + if (!SymbolicOffset.empty()) {
|
| + emitIASBytesRelocatable(Str, Func->getAssembler<x86::AssemblerX86>(),
|
| + StartPosition, SymbolicOffset);
|
| + } else {
|
| + emitIASBytes(Str, Func->getAssembler<x86::AssemblerX86>(), StartPosition);
|
| + }
|
| +}
|
| +
|
| void InstX8632Movsx::emit(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrEmit();
|
| assert(getSrcSize() == 1);
|
| @@ -1033,6 +1375,20 @@ void InstX8632Movsx::emit(const Cfg *Func) const {
|
| Str << "\n";
|
| }
|
|
|
| +void InstX8632Movsx::emitIAS(const Cfg *Func) const {
|
| + assert(getSrcSize() == 1);
|
| + const Operand *Src0 = getSrc(0);
|
| + Type SrcType = Src0->getType();
|
| + if (SrcType == IceType_i8 || SrcType == IceType_i1) {
|
| + emitIASSignZeroExt(Func, getDest(), Src0, &x86::AssemblerX86::movsxb,
|
| + &x86::AssemblerX86::movsxw, &x86::AssemblerX86::movsxb);
|
| + } else {
|
| + assert(SrcType == IceType_i16);
|
| + emitIASSignZeroExt(Func, getDest(), Src0, &x86::AssemblerX86::movsxb,
|
| + &x86::AssemblerX86::movsxw, &x86::AssemblerX86::movsxw);
|
| + }
|
| +}
|
| +
|
| void InstX8632Movsx::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| Str << "movsx." << getDest()->getType() << "." << getSrc(0)->getType();
|
| @@ -1052,6 +1408,20 @@ void InstX8632Movzx::emit(const Cfg *Func) const {
|
| Str << "\n";
|
| }
|
|
|
| +void InstX8632Movzx::emitIAS(const Cfg *Func) const {
|
| + assert(getSrcSize() == 1);
|
| + const Operand *Src0 = getSrc(0);
|
| + Type SrcType = Src0->getType();
|
| + if (SrcType == IceType_i8 || SrcType == IceType_i1) {
|
| + emitIASSignZeroExt(Func, getDest(), Src0, &x86::AssemblerX86::movzxb,
|
| + &x86::AssemblerX86::movzxw, &x86::AssemblerX86::movzxb);
|
| + } else {
|
| + assert(SrcType == IceType_i16);
|
| + emitIASSignZeroExt(Func, getDest(), Src0, &x86::AssemblerX86::movzxb,
|
| + &x86::AssemblerX86::movzxw, &x86::AssemblerX86::movzxw);
|
| + }
|
| +}
|
| +
|
| void InstX8632Movzx::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| Str << "movzx." << getDest()->getType() << "." << getSrc(0)->getType();
|
| @@ -1067,6 +1437,15 @@ void InstX8632Nop::emit(const Cfg *Func) const {
|
| Str << "\tnop\t# variant = " << Variant << "\n";
|
| }
|
|
|
| +void InstX8632Nop::emitIAS(const Cfg *Func) const {
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + intptr_t StartPosition = Asm->GetPosition();
|
| + // TODO: Emit the right code for the variant.
|
| + Asm->nop();
|
| + emitIASBytes(Str, Asm, StartPosition);
|
| +}
|
| +
|
| void InstX8632Nop::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| Str << "nop (variant = " << Variant << ")";
|
| @@ -1201,11 +1580,27 @@ template <> void InstX8632Pinsr::emit(const Cfg *Func) const {
|
| void InstX8632Pop::emit(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrEmit();
|
| assert(getSrcSize() == 0);
|
| + assert(getDest()->getType() == IceType_i32);
|
| Str << "\tpop\t";
|
| getDest()->emit(Func);
|
| Str << "\n";
|
| }
|
|
|
| +void InstX8632Pop::emitIAS(const Cfg *Func) const {
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + assert(getSrcSize() == 0);
|
| + assert(getDest()->getType() == IceType_i32);
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + intptr_t StartPosition = Asm->GetPosition();
|
| + if (getDest()->hasReg()) {
|
| + Asm->popl(convertToAsmGPR(getDest()->getRegNum()));
|
| + } else {
|
| + Asm->popl(static_cast<TargetX8632 *>(Func->getTarget())
|
| + ->stackVarToAsmOperand(getDest()));
|
| + }
|
| + emitIASBytes(Str, Asm, StartPosition);
|
| +}
|
| +
|
| void InstX8632Pop::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| dumpDest(Func);
|
| @@ -1290,6 +1685,14 @@ void InstX8632Ret::emit(const Cfg *Func) const {
|
| Str << "\tret\n";
|
| }
|
|
|
| +void InstX8632Ret::emitIAS(const Cfg *Func) const {
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + intptr_t StartPosition = Asm->GetPosition();
|
| + Asm->ret();
|
| + emitIASBytes(Str, Asm, StartPosition);
|
| +}
|
| +
|
| void InstX8632Ret::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType());
|
| @@ -1426,6 +1829,37 @@ void OperandX8632Mem::dump(const Cfg *Func) const {
|
| Str << "]";
|
| }
|
|
|
| +x86::Address
|
| +OperandX8632Mem::convertToAsmAddress(IceString &SymbolicOffset) const {
|
| + int32_t Disp = 0;
|
| + // Determine the offset (is it relocatable?)
|
| + if (ConstantInteger *CI = llvm::dyn_cast<ConstantInteger>(getOffset())) {
|
| + // Should there be a subclass of ConstantInteger that is just int32_t?
|
| + assert(Utils::IsInt<int64_t>(32, CI->getValue()));
|
| + Disp = static_cast<int32_t>(CI->getValue());
|
| + } else if (ConstantRelocatable *CR =
|
| + llvm::dyn_cast<ConstantRelocatable>(getOffset())) {
|
| + SymbolicOffset = CR->getName();
|
| + assert(CR->getOffset() == 0 && "Not yet handling Reloc + offset");
|
| + }
|
| +
|
| + // Now convert to the various possible forms.
|
| + if (getBase() && getIndex()) {
|
| + return x86::Address(convertToAsmGPR(getBase()->getRegNum()),
|
| + convertToAsmGPR(getIndex()->getRegNum()),
|
| + x86::ScaleFactor(getShift()), Disp);
|
| + } else if (getBase()) {
|
| + return x86::Address(convertToAsmGPR(getBase()->getRegNum()), Disp);
|
| + } else if (getIndex()) {
|
| + return x86::Address(convertToAsmGPR(getIndex()->getRegNum()),
|
| + x86::ScaleFactor(getShift()), Disp);
|
| + } else {
|
| + assert(!SymbolicOffset.empty() && Disp == 0 &&
|
| + "Remaining case is symbolic offset...");
|
| + return x86::Address::Absolute(Disp);
|
| + }
|
| +}
|
| +
|
| void VariableSplit::emit(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrEmit();
|
| assert(Var->getLocalUseNode() == NULL ||
|
|
|