| Index: src/IceInstX8632.cpp
 | 
| diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp
 | 
| index 373ab59e47503c4b3535edaaf87bc17a4aa015f5..25db6c73cdf967fbb7a33deac071b80c019d3e1c 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,50 @@ 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);
 | 
| +  return x86::Register(RegNum);
 | 
| +}
 | 
| +
 | 
| +x86::ByteRegister convertToAsmByteRegister(int32_t RegNum) {
 | 
| +  if (RegNum == TargetX8632::Reg_ah) {
 | 
| +    return x86::AH;
 | 
| +  }
 | 
| +  assert(TargetX8632::Reg_eax <= RegNum && RegNum <= TargetX8632::Reg_ebx);
 | 
| +  return x86::ByteRegister(RegNum);
 | 
| +}
 | 
| +
 | 
| +x86::Immediate convertIntImmToAsmImm(const ConstantInteger32 *CI) {
 | 
| +  int32_t V = static_cast<int32_t>(CI->getValue());
 | 
| +  return x86::Immediate(V);
 | 
| +}
 | 
| +
 | 
| +x86::XmmRegister convertToAsmXMMReg(int32_t RegNum) {
 | 
| +  assert(TargetX8632::Reg_xmm0 <= RegNum && RegNum <= TargetX8632::Reg_xmm7);
 | 
| +  return x86::XmmRegister(RegNum - TargetX8632::Reg_xmm0);
 | 
| +}
 | 
| +
 | 
| +// Convert a float or double immediate to an Address Operand.
 | 
| +x86::Address convertFloatImmToAsmAddr(GlobalContext *Ctx, Assembler *Asm,
 | 
| +                                      const Constant *Imm) {
 | 
| +  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();
 | 
| +  const int64_t Offset = 0;
 | 
| +  const bool SuppressMangling = true;
 | 
| +  Constant *Sym =
 | 
| +      Ctx->getConstantSym(Ty, Offset, StrBuf.str(), SuppressMangling);
 | 
| +  AssemblerFixup *Fixup = x86::DisplacementRelocation::create(
 | 
| +      Asm, FK_Abs_4, llvm::cast<ConstantRelocatable>(Sym));
 | 
| +  return x86::Address::Absolute(Offset, Fixup);
 | 
| +}
 | 
| +
 | 
|  } // end of anonymous namespace
 | 
|  
 | 
|  const char *InstX8632::getWidthString(Type Ty) {
 | 
| @@ -285,12 +330,216 @@ 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();
 | 
| +  intptr_t LastFixupLoc = -1;
 | 
| +  AssemblerFixup *LastFixup = NULL;
 | 
| +  if (Asm->GetLatestFixup()) {
 | 
| +    LastFixup = Asm->GetLatestFixup();
 | 
| +    LastFixupLoc = LastFixup->position();
 | 
| +  }
 | 
| +  if (LastFixupLoc < StartPosition) {
 | 
| +    // The fixup doesn't apply to this current block.
 | 
| +    for (intptr_t i = 0; i < EndPosition - StartPosition; ++i) {
 | 
| +      Str << "\t.byte "
 | 
| +          << static_cast<uint32_t>(Asm->LoadBuffer<uint8_t>(StartPosition + i))
 | 
| +          << "\n";
 | 
| +    }
 | 
| +    return;
 | 
| +  }
 | 
| +  const intptr_t FixupSize = 4;
 | 
| +  assert(LastFixupLoc + FixupSize <= EndPosition);
 | 
| +  // The fixup does apply to this current block.
 | 
| +  for (intptr_t i = 0; i < LastFixupLoc - StartPosition; ++i) {
 | 
| +    Str << "\t.byte "
 | 
| +        << static_cast<uint32_t>(Asm->LoadBuffer<uint8_t>(StartPosition + i))
 | 
| +        << "\n";
 | 
| +  }
 | 
| +  Str << "\t.long " << LastFixup->value()->getName();
 | 
| +  if (LastFixup->value()->getOffset()) {
 | 
| +    Str << " + " << LastFixup->value()->getOffset();
 | 
| +  }
 | 
| +  Str << "\n";
 | 
| +  for (intptr_t i = LastFixupLoc + FixupSize; i < EndPosition; ++i) {
 | 
| +    Str << "\t.byte " << static_cast<uint32_t>(Asm->LoadBuffer<uint8_t>(i))
 | 
| +        << "\n";
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void emitIASTwoOperandGPR(const Cfg *Func, const Operand *Src0,
 | 
| +                          const Operand *Src1,
 | 
| +                          x86::AssemblerX86::EmitTyRegReg EmitRegReg,
 | 
| +                          x86::AssemblerX86::EmitTyRegAddr EmitRegAddr,
 | 
| +                          x86::AssemblerX86::EmitTyRegImm EmitRegImm,
 | 
| +                          x86::AssemblerX86::EmitTyAddrReg EmitAddrReg = NULL,
 | 
| +                          x86::AssemblerX86::EmitTyAddrImm EmitAddrImm = NULL) {
 | 
| +  x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
 | 
| +  intptr_t StartPosition = Asm->GetPosition();
 | 
| +  Type Ty = Src0->getType();
 | 
| +
 | 
| +  // Classify Src0 (Reg or Mem).
 | 
| +  bool Src0IsReg = false;
 | 
| +  x86::Register Src0Reg = x86::kNoRegister;
 | 
| +  x86::Address Src0Addr = x86::Address::Absolute(0, NULL);
 | 
| +  if (const Variable *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
 | 
| +    if (Src0Var->hasReg()) {
 | 
| +      Src0IsReg = true;
 | 
| +      if (typeWidthInBytes(Ty) == 1) {
 | 
| +        Src0Reg =
 | 
| +            convertToAsmGPR(convertToAsmByteRegister(Src0Var->getRegNum()));
 | 
| +      } else {
 | 
| +        Src0Reg = convertToAsmGPR(Src0Var->getRegNum());
 | 
| +      }
 | 
| +    } else {
 | 
| +      Src0Addr = static_cast<TargetX8632 *>(Func->getTarget())
 | 
| +                     ->stackVarToAsmOperand(Src0Var);
 | 
| +    }
 | 
| +  } else if (const OperandX8632Mem *Mem =
 | 
| +                 llvm::dyn_cast<OperandX8632Mem>(Src0)) {
 | 
| +    assert(EmitAddrReg != NULL && EmitAddrImm != NULL);
 | 
| +    Src0Addr = Mem->convertToAsmAddress(Asm);
 | 
| +  }
 | 
| +
 | 
| +  // Classify Src1 (Reg, Mem, or Imm).
 | 
| +  if (const Variable *Src1Var = llvm::dyn_cast<Variable>(Src1)) {
 | 
| +    if (Src1Var->hasReg()) {
 | 
| +      x86::Register Src1Reg;
 | 
| +      if (typeWidthInBytes(Ty) == 1) {
 | 
| +        Src1Reg =
 | 
| +            convertToAsmGPR(convertToAsmByteRegister(Src1Var->getRegNum()));
 | 
| +      } else {
 | 
| +        Src1Reg = convertToAsmGPR(Src1Var->getRegNum());
 | 
| +      }
 | 
| +      if (Src0IsReg)
 | 
| +        (Asm->*EmitRegReg)(Ty, Src0Reg, Src1Reg);
 | 
| +      else
 | 
| +        (Asm->*EmitAddrReg)(Ty, Src0Addr, Src1Reg);
 | 
| +    } else {
 | 
| +      x86::Address Src1Addr = static_cast<TargetX8632 *>(Func->getTarget())
 | 
| +                                  ->stackVarToAsmOperand(Src1Var);
 | 
| +      assert(Src0IsReg);
 | 
| +      (Asm->*EmitRegAddr)(Ty, Src0Reg, Src1Addr);
 | 
| +    }
 | 
| +  } else if (const OperandX8632Mem *Mem =
 | 
| +                 llvm::dyn_cast<OperandX8632Mem>(Src1)) {
 | 
| +    x86::Address Src1Addr = Mem->convertToAsmAddress(Asm);
 | 
| +    assert(Src0IsReg);
 | 
| +    (Asm->*EmitRegAddr)(Ty, Src0Reg, Src1Addr);
 | 
| +  } else if (const ConstantInteger32 *CI =
 | 
| +                 llvm::dyn_cast<ConstantInteger32>(Src1)) {
 | 
| +    x86::Immediate Imm = convertIntImmToAsmImm(CI);
 | 
| +    if (Src0IsReg)
 | 
| +      (Asm->*EmitRegImm)(Ty, Src0Reg, Imm);
 | 
| +    else
 | 
| +      (Asm->*EmitAddrImm)(Ty, Src0Addr, Imm);
 | 
| +  } else {
 | 
| +    llvm_unreachable("Unexpected operand type");
 | 
| +  }
 | 
| +  Ostream &Str = Func->getContext()->getStrEmit();
 | 
| +  emitIASBytes(Str, Asm, StartPosition);
 | 
| +}
 | 
| +
 | 
| +void emitIASVarOperandXMM(const Cfg *Func, const Variable *Var,
 | 
| +                          const Operand *Src,
 | 
| +                          x86::AssemblerX86::EmitXmmXmm EmitXmmXmm,
 | 
| +                          x86::AssemblerX86::EmitXmmAddr EmitXmmAddr) {
 | 
| +  x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
 | 
| +  intptr_t StartPosition = Asm->GetPosition();
 | 
| +  assert(Var->hasReg());
 | 
| +  x86::XmmRegister VarReg = convertToAsmXMMReg(Var->getRegNum());
 | 
| +  if (const Variable *SrcVar = llvm::dyn_cast<Variable>(Src)) {
 | 
| +    if (SrcVar->hasReg()) {
 | 
| +      x86::XmmRegister SrcReg = convertToAsmXMMReg(SrcVar->getRegNum());
 | 
| +      (Asm->*EmitXmmXmm)(VarReg, SrcReg);
 | 
| +    } else {
 | 
| +      x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget())
 | 
| +                                      ->stackVarToAsmOperand(SrcVar);
 | 
| +      (Asm->*EmitXmmAddr)(VarReg, SrcStackAddr);
 | 
| +    }
 | 
| +  } else if (const OperandX8632Mem *Mem =
 | 
| +                 llvm::dyn_cast<OperandX8632Mem>(Src)) {
 | 
| +    x86::Address SrcAddr = Mem->convertToAsmAddress(Asm);
 | 
| +    (Asm->*EmitXmmAddr)(VarReg, SrcAddr);
 | 
| +  } else if (const Constant *Imm = llvm::dyn_cast<Constant>(Src)) {
 | 
| +    (Asm->*EmitXmmAddr)(VarReg,
 | 
| +                        convertFloatImmToAsmAddr(Func->getContext(), Asm, Imm));
 | 
| +  } else {
 | 
| +    llvm_unreachable("Unexpected operand type");
 | 
| +  }
 | 
| +  Ostream &Str = Func->getContext()->getStrEmit();
 | 
| +  emitIASBytes(Str, Asm, StartPosition);
 | 
| +}
 | 
| +
 | 
| +void
 | 
| +emitIASTwoOperandTyXMM(const Cfg *Func, Type Ty, const Operand *Src0,
 | 
| +                       const Operand *Src1,
 | 
| +                       x86::AssemblerX86::EmitTyXmmXmm EmitXmmXmm,
 | 
| +                       x86::AssemblerX86::EmitTyXmmAddr EmitXmmAddr,
 | 
| +                       x86::AssemblerX86::EmitTyAddrXmm EmitAddrXmm = NULL) {
 | 
| +  x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
 | 
| +  intptr_t StartPosition = Asm->GetPosition();
 | 
| +
 | 
| +  // Classify Src0 (Reg or Mem).
 | 
| +  bool Src0IsReg = false;
 | 
| +  x86::XmmRegister Src0Reg = x86::kNoXmmRegister;
 | 
| +  x86::Address Src0Addr = x86::Address::Absolute(0, NULL);
 | 
| +  if (const Variable *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
 | 
| +    if (Src0Var->hasReg()) {
 | 
| +      Src0IsReg = true;
 | 
| +      Src0Reg = convertToAsmXMMReg(Src0Var->getRegNum());
 | 
| +    } else {
 | 
| +      Src0Addr = static_cast<TargetX8632 *>(Func->getTarget())
 | 
| +                     ->stackVarToAsmOperand(Src0Var);
 | 
| +    }
 | 
| +  } else if (const OperandX8632Mem *Mem =
 | 
| +                 llvm::dyn_cast<OperandX8632Mem>(Src0)) {
 | 
| +    assert(EmitAddrXmm != NULL);
 | 
| +    Src0Addr = Mem->convertToAsmAddress(Asm);
 | 
| +  }
 | 
| +
 | 
| +  if (const Variable *Src1Var = llvm::dyn_cast<Variable>(Src1)) {
 | 
| +    if (Src1Var->hasReg()) {
 | 
| +      x86::XmmRegister Src1Reg = convertToAsmXMMReg(Src1Var->getRegNum());
 | 
| +      if (Src0IsReg) {
 | 
| +        (Asm->*EmitXmmXmm)(Ty, Src0Reg, Src1Reg);
 | 
| +      } else {
 | 
| +        (Asm->*EmitAddrXmm)(Ty, Src0Addr, Src1Reg);
 | 
| +      }
 | 
| +    } else {
 | 
| +      x86::Address Src1StackAddr = static_cast<TargetX8632 *>(Func->getTarget())
 | 
| +                                       ->stackVarToAsmOperand(Src1Var);
 | 
| +      assert(Src0IsReg);
 | 
| +      (Asm->*EmitXmmAddr)(Ty, Src0Reg, Src1StackAddr);
 | 
| +    }
 | 
| +  } else if (const OperandX8632Mem *Mem =
 | 
| +                 llvm::dyn_cast<OperandX8632Mem>(Src1)) {
 | 
| +    x86::Address Src1Addr = Mem->convertToAsmAddress(Asm);
 | 
| +    assert(Src0IsReg);
 | 
| +    (Asm->*EmitXmmAddr)(Ty, Src0Reg, Src1Addr);
 | 
| +  } else if (const Constant *Imm = llvm::dyn_cast<Constant>(Src1)) {
 | 
| +    assert(Src0IsReg);
 | 
| +    (Asm->*EmitXmmAddr)(Ty, Src0Reg,
 | 
| +                        convertFloatImmToAsmAddr(Func->getContext(), Asm, Imm));
 | 
| +  } else {
 | 
| +    llvm_unreachable("Unexpected operand type");
 | 
| +  }
 | 
| +  Ostream &Str = Func->getContext()->getStrEmit();
 | 
| +  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";
 | 
| @@ -355,6 +604,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();
 | 
| +  bool NeedsFallback = false;
 | 
| +  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(Asm));
 | 
| +  } else if (ConstantRelocatable *CR =
 | 
| +                 llvm::dyn_cast<ConstantRelocatable>(Target)) {
 | 
| +    assert(CR->getOffset() == 0 && "We only support calling a function");
 | 
| +    Asm->call(CR);
 | 
| +    NeedsFallback = true;
 | 
| +  }
 | 
| +  if (NeedsFallback) {
 | 
| +    // 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()) {
 | 
| @@ -478,6 +764,37 @@ template <> void InstX8632Sqrtss::emit(const Cfg *Func) const {
 | 
|    Str << "\n";
 | 
|  }
 | 
|  
 | 
| +template <> void InstX8632Sqrtss::emitIAS(const Cfg *Func) const {
 | 
| +  Type Ty = getDest()->getType();
 | 
| +  assert(getSrcSize() == 1);
 | 
| +  assert(Ty == IceType_f32 || Ty == IceType_f64);
 | 
| +  if (Ty == IceType_f64) {
 | 
| +    emitIASVarOperandXMM(Func, getDest(), getSrc(0), &x86::AssemblerX86::sqrtsd,
 | 
| +                         &x86::AssemblerX86::sqrtsd);
 | 
| +  } else {
 | 
| +    emitIASVarOperandXMM(Func, getDest(), getSrc(0), &x86::AssemblerX86::sqrtss,
 | 
| +                         &x86::AssemblerX86::sqrtss);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +template <> void InstX8632Adc::emitIAS(const Cfg *Func) const {
 | 
| +  assert(getSrcSize() == 2);
 | 
| +  emitIASTwoOperandGPR(Func, getDest(), getSrc(1), &x86::AssemblerX86::adc,
 | 
| +                       &x86::AssemblerX86::adc, &x86::AssemblerX86::adc);
 | 
| +}
 | 
| +
 | 
| +template <> void InstX8632Add::emitIAS(const Cfg *Func) const {
 | 
| +  assert(getSrcSize() == 2);
 | 
| +  emitIASTwoOperandGPR(Func, getDest(), getSrc(1), &x86::AssemblerX86::add,
 | 
| +                       &x86::AssemblerX86::add, &x86::AssemblerX86::add);
 | 
| +}
 | 
| +
 | 
| +template <> void InstX8632Addps::emitIAS(const Cfg *Func) const {
 | 
| +  assert(getSrcSize() == 2);
 | 
| +  emitIASVarOperandXMM(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",
 | 
| @@ -485,6 +802,24 @@ 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) {
 | 
| +    emitIASVarOperandXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::addsd,
 | 
| +                         &x86::AssemblerX86::addsd);
 | 
| +  } else {
 | 
| +    emitIASVarOperandXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::addss,
 | 
| +                         &x86::AssemblerX86::addss);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +template <> void InstX8632And::emitIAS(const Cfg *Func) const {
 | 
| +  assert(getSrcSize() == 2);
 | 
| +  emitIASTwoOperandGPR(Func, getDest(), getSrc(1), &x86::AssemblerX86::_and,
 | 
| +                       &x86::AssemblerX86::_and, &x86::AssemblerX86::_and);
 | 
| +}
 | 
| +
 | 
|  template <> void InstX8632Padd::emit(const Cfg *Func) const {
 | 
|    char buf[30];
 | 
|    snprintf(buf, llvm::array_lengthof(buf), "padd%s",
 | 
| @@ -492,6 +827,15 @@ template <> void InstX8632Padd::emit(const Cfg *Func) const {
 | 
|    emitTwoAddress(buf, this, Func);
 | 
|  }
 | 
|  
 | 
| +template <> void InstX8632Padd::emitIAS(const Cfg *Func) const {
 | 
| +  Type Ty = getDest()->getType();
 | 
| +  assert(isVectorType(Ty));
 | 
| +  Type ElTy = typeElementType(Ty);
 | 
| +  assert(getSrcSize() == 2);
 | 
| +  emitIASTwoOperandTyXMM(Func, ElTy, getDest(), getSrc(1),
 | 
| +                         &x86::AssemblerX86::padd, &x86::AssemblerX86::padd);
 | 
| +}
 | 
| +
 | 
|  template <> void InstX8632Pmull::emit(const Cfg *Func) const {
 | 
|    char buf[30];
 | 
|    bool TypesAreValid = getDest()->getType() == IceType_v4i32 ||
 | 
| @@ -509,6 +853,24 @@ template <> void InstX8632Pmull::emit(const Cfg *Func) const {
 | 
|    emitTwoAddress(buf, this, Func);
 | 
|  }
 | 
|  
 | 
| +template <> void InstX8632Sbb::emitIAS(const Cfg *Func) const {
 | 
| +  assert(getSrcSize() == 2);
 | 
| +  emitIASTwoOperandGPR(Func, getDest(), getSrc(1), &x86::AssemblerX86::sbb,
 | 
| +                       &x86::AssemblerX86::sbb, &x86::AssemblerX86::sbb);
 | 
| +}
 | 
| +
 | 
| +template <> void InstX8632Sub::emitIAS(const Cfg *Func) const {
 | 
| +  assert(getSrcSize() == 2);
 | 
| +  emitIASTwoOperandGPR(Func, getDest(), getSrc(1), &x86::AssemblerX86::sub,
 | 
| +                       &x86::AssemblerX86::sub, &x86::AssemblerX86::sub);
 | 
| +}
 | 
| +
 | 
| +template <> void InstX8632Subps::emitIAS(const Cfg *Func) const {
 | 
| +  assert(getSrcSize() == 2);
 | 
| +  emitIASVarOperandXMM(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",
 | 
| @@ -516,6 +878,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) {
 | 
| +    emitIASVarOperandXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::subsd,
 | 
| +                         &x86::AssemblerX86::subsd);
 | 
| +  } else {
 | 
| +    emitIASVarOperandXMM(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",
 | 
| @@ -523,6 +897,21 @@ template <> void InstX8632Psub::emit(const Cfg *Func) const {
 | 
|    emitTwoAddress(buf, this, Func);
 | 
|  }
 | 
|  
 | 
| +template <> void InstX8632Psub::emitIAS(const Cfg *Func) const {
 | 
| +  Type Ty = getDest()->getType();
 | 
| +  assert(isVectorType(Ty));
 | 
| +  Type ElTy = typeElementType(Ty);
 | 
| +  assert(getSrcSize() == 2);
 | 
| +  emitIASTwoOperandTyXMM(Func, ElTy, getDest(), getSrc(1),
 | 
| +                         &x86::AssemblerX86::psub, &x86::AssemblerX86::psub);
 | 
| +}
 | 
| +
 | 
| +template <> void InstX8632Mulps::emitIAS(const Cfg *Func) const {
 | 
| +  assert(getSrcSize() == 2);
 | 
| +  emitIASVarOperandXMM(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",
 | 
| @@ -530,12 +919,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) {
 | 
| +    emitIASVarOperandXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::mulsd,
 | 
| +                         &x86::AssemblerX86::mulsd);
 | 
| +  } else {
 | 
| +    emitIASVarOperandXMM(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);
 | 
| +  emitIASVarOperandXMM(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",
 | 
| @@ -543,6 +950,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) {
 | 
| +    emitIASVarOperandXMM(Func, getDest(), getSrc(1), &x86::AssemblerX86::divsd,
 | 
| +                         &x86::AssemblerX86::divsd);
 | 
| +  } else {
 | 
| +    emitIASVarOperandXMM(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);
 | 
| @@ -640,6 +1059,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);
 | 
| @@ -723,6 +1170,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 << ".";
 | 
| @@ -745,6 +1209,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);
 | 
| @@ -831,6 +1317,13 @@ void InstX8632Icmp::emit(const Cfg *Func) const {
 | 
|    Str << "\n";
 | 
|  }
 | 
|  
 | 
| +void InstX8632Icmp::emitIAS(const Cfg *Func) const {
 | 
| +  assert(getSrcSize() == 2);
 | 
| +  emitIASTwoOperandGPR(Func, getSrc(0), getSrc(1), &x86::AssemblerX86::cmp,
 | 
| +                       &x86::AssemblerX86::cmp, &x86::AssemblerX86::cmp,
 | 
| +                       &x86::AssemblerX86::cmp, &x86::AssemblerX86::cmp);
 | 
| +}
 | 
| +
 | 
|  void InstX8632Icmp::dump(const Cfg *Func) const {
 | 
|    Ostream &Str = Func->getContext()->getStrDump();
 | 
|    Str << "cmp." << getSrc(0)->getType() << " ";
 | 
| @@ -848,6 +1341,22 @@ void InstX8632Ucomiss::emit(const Cfg *Func) const {
 | 
|    Str << "\n";
 | 
|  }
 | 
|  
 | 
| +void InstX8632Ucomiss::emitIAS(const Cfg *Func) const {
 | 
| +  assert(getSrcSize() == 2);
 | 
| +  // Currently src0 is always a variable by convention, to avoid having
 | 
| +  // two memory operands.
 | 
| +  assert(llvm::isa<Variable>(getSrc(0)));
 | 
| +  const Variable *Src0 = llvm::cast<Variable>(getSrc(0));
 | 
| +  Type Ty = Src0->getType();
 | 
| +  if (Ty == IceType_f64) {
 | 
| +    emitIASVarOperandXMM(Func, Src0, getSrc(1), &x86::AssemblerX86::ucomisd,
 | 
| +                         &x86::AssemblerX86::ucomisd);
 | 
| +  } else {
 | 
| +    emitIASVarOperandXMM(Func, Src0, getSrc(1), &x86::AssemblerX86::ucomiss,
 | 
| +                         &x86::AssemblerX86::ucomiss);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
|  void InstX8632Ucomiss::dump(const Cfg *Func) const {
 | 
|    Ostream &Str = Func->getContext()->getStrDump();
 | 
|    Str << "ucomiss." << getSrc(0)->getType() << " ";
 | 
| @@ -1018,6 +1527,11 @@ template <> void InstX8632Mov::emit(const Cfg *Func) const {
 | 
|    }
 | 
|  }
 | 
|  
 | 
| +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
 | 
| @@ -1044,6 +1558,42 @@ 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();
 | 
| +  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(Asm);
 | 
| +    (Asm->*EmitAddress)(DestReg, SrcAddr);
 | 
| +  } else {
 | 
| +    llvm_unreachable("Unexpected operand type for Movzx");
 | 
| +  }
 | 
| +  emitIASBytes(Str, Asm, StartPosition);
 | 
| +}
 | 
| +
 | 
|  void InstX8632Movsx::emit(const Cfg *Func) const {
 | 
|    Ostream &Str = Func->getContext()->getStrEmit();
 | 
|    assert(getSrcSize() == 1);
 | 
| @@ -1054,6 +1604,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();
 | 
| @@ -1073,6 +1637,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();
 | 
| @@ -1088,11 +1666,26 @@ 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 << ")";
 | 
|  }
 | 
|  
 | 
| +template <> void InstX8632Or::emitIAS(const Cfg *Func) const {
 | 
| +  assert(getSrcSize() == 2);
 | 
| +  emitIASTwoOperandGPR(Func, getDest(), getSrc(1), &x86::AssemblerX86::_or,
 | 
| +                       &x86::AssemblerX86::_or, &x86::AssemblerX86::_or);
 | 
| +}
 | 
| +
 | 
|  void InstX8632Fld::emit(const Cfg *Func) const {
 | 
|    Ostream &Str = Func->getContext()->getStrEmit();
 | 
|    assert(getSrcSize() == 1);
 | 
| @@ -1222,11 +1815,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);
 | 
| @@ -1239,6 +1848,16 @@ void InstX8632AdjustStack::emit(const Cfg *Func) const {
 | 
|    Func->getTarget()->updateStackAdjustment(Amount);
 | 
|  }
 | 
|  
 | 
| +void InstX8632AdjustStack::emitIAS(const Cfg *Func) const {
 | 
| +  Ostream &Str = Func->getContext()->getStrEmit();
 | 
| +  x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
 | 
| +  intptr_t StartPosition = Asm->GetPosition();
 | 
| +  Asm->sub(IceType_i32, convertToAsmGPR(TargetX8632::Reg_esp),
 | 
| +           x86::Immediate(Amount));
 | 
| +  emitIASBytes(Str, Asm, StartPosition);
 | 
| +  Func->getTarget()->updateStackAdjustment(Amount);
 | 
| +}
 | 
| +
 | 
|  void InstX8632AdjustStack::dump(const Cfg *Func) const {
 | 
|    Ostream &Str = Func->getContext()->getStrDump();
 | 
|    Str << "esp = sub.i32 esp, " << Amount;
 | 
| @@ -1311,6 +1930,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());
 | 
| @@ -1356,6 +1983,12 @@ void InstX8632Xchg::dump(const Cfg *Func) const {
 | 
|    dumpSources(Func);
 | 
|  }
 | 
|  
 | 
| +template <> void InstX8632Xor::emitIAS(const Cfg *Func) const {
 | 
| +  assert(getSrcSize() == 2);
 | 
| +  emitIASTwoOperandGPR(Func, getDest(), getSrc(1), &x86::AssemblerX86::_xor,
 | 
| +                       &x86::AssemblerX86::_xor, &x86::AssemblerX86::_xor);
 | 
| +}
 | 
| +
 | 
|  void OperandX8632::dump(const Cfg *Func) const {
 | 
|    Ostream &Str = Func->getContext()->getStrDump();
 | 
|    Str << "<OperandX8632>";
 | 
| @@ -1388,9 +2021,12 @@ void OperandX8632Mem::emit(const Cfg *Func) const {
 | 
|    bool OffsetIsNegative = false;
 | 
|    if (Offset == NULL) {
 | 
|      OffsetIsZero = true;
 | 
| -  } else if (ConstantInteger *CI = llvm::dyn_cast<ConstantInteger>(Offset)) {
 | 
| +  } else if (ConstantInteger32 *CI =
 | 
| +                 llvm::dyn_cast<ConstantInteger32>(Offset)) {
 | 
|      OffsetIsZero = (CI->getValue() == 0);
 | 
| -    OffsetIsNegative = (static_cast<int64_t>(CI->getValue()) < 0);
 | 
| +    OffsetIsNegative = (static_cast<int32_t>(CI->getValue()) < 0);
 | 
| +  } else if (llvm::isa<ConstantInteger64>(Offset)) {
 | 
| +    llvm_unreachable("Unexpected offset type (64-bit)");
 | 
|    }
 | 
|    if (Dumped) {
 | 
|      if (!OffsetIsZero) {     // Suppress if Offset is known to be 0
 | 
| @@ -1430,9 +2066,12 @@ void OperandX8632Mem::dump(const Cfg *Func) const {
 | 
|    bool OffsetIsNegative = false;
 | 
|    if (Offset == NULL) {
 | 
|      OffsetIsZero = true;
 | 
| -  } else if (ConstantInteger *CI = llvm::dyn_cast<ConstantInteger>(Offset)) {
 | 
| +  } else if (ConstantInteger32 *CI =
 | 
| +                 llvm::dyn_cast<ConstantInteger32>(Offset)) {
 | 
|      OffsetIsZero = (CI->getValue() == 0);
 | 
| -    OffsetIsNegative = (static_cast<int64_t>(CI->getValue()) < 0);
 | 
| +    OffsetIsNegative = (static_cast<int32_t>(CI->getValue()) < 0);
 | 
| +  } else if (llvm::isa<ConstantInteger64>(Offset)) {
 | 
| +    llvm_unreachable("Unexpected offset type (64-bit)");
 | 
|    }
 | 
|    if (Dumped) {
 | 
|      if (!OffsetIsZero) {     // Suppress if Offset is known to be 0
 | 
| @@ -1447,6 +2086,41 @@ void OperandX8632Mem::dump(const Cfg *Func) const {
 | 
|    Str << "]";
 | 
|  }
 | 
|  
 | 
| +x86::Address OperandX8632Mem::convertToAsmAddress(Assembler *Asm) const {
 | 
| +  int32_t Disp = 0;
 | 
| +  AssemblerFixup *Fixup = NULL;
 | 
| +  // Determine the offset (is it relocatable?)
 | 
| +  if (getOffset()) {
 | 
| +    if (ConstantInteger32 *CI =
 | 
| +            llvm::dyn_cast<ConstantInteger32>(getOffset())) {
 | 
| +      Disp = static_cast<int32_t>(CI->getValue());
 | 
| +    } else if (ConstantRelocatable *CR =
 | 
| +                   llvm::dyn_cast<ConstantRelocatable>(getOffset())) {
 | 
| +      // TODO(jvoung): CR + non-zero-offset isn't really tested yet,
 | 
| +      // since the addressing mode optimization doesn't try to combine
 | 
| +      // ConstantRelocatable with something else.
 | 
| +      assert(CR->getOffset() == 0);
 | 
| +      Fixup = x86::DisplacementRelocation::create(Asm, FK_Abs_4, CR);
 | 
| +    } else {
 | 
| +      llvm_unreachable("Unexpected offset type");
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  // 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 {
 | 
| +    return x86::Address::Absolute(Disp, Fixup);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
|  void VariableSplit::emit(const Cfg *Func) const {
 | 
|    Ostream &Str = Func->getContext()->getStrEmit();
 | 
|    assert(Var->getLocalUseNode() == NULL ||
 | 
| 
 |