Skip to content
X86InstrInfo.cpp 118 KiB
Newer Older
      break;
    case TargetInstrInfo::IMPLICIT_DEF:
    case X86::DWARF_LOC:
    case X86::FP_REG_KILL:
      break;
    case X86::MOVPC32r: {
      // This emits the "call" portion of this pseudo instruction.
      ++FinalSize;
      FinalSize += sizeConstant(X86InstrInfo::sizeOfImm(Desc));
      break;
    }
    }
    CurOp = NumOps;
    break;
  case X86II::RawFrm:
    ++FinalSize;

    if (CurOp != NumOps) {
      const MachineOperand &MO = MI.getOperand(CurOp++);
        FinalSize += sizePCRelativeBlockAddress();
        FinalSize += sizeGlobalAddress(false);
        FinalSize += sizeExternalSymbolAddress(false);
        FinalSize += sizeConstant(X86InstrInfo::sizeOfImm(Desc));
      } else {
        llvm_unreachable("Unknown RawFrm operand!");
    
    if (CurOp != NumOps) {
      const MachineOperand &MO1 = MI.getOperand(CurOp++);
      unsigned Size = X86InstrInfo::sizeOfImm(Desc);
        FinalSize += sizeConstant(Size);
      else {
        bool dword = false;
        if (Opcode == X86::MOV64ri)
          dword = true; 
          FinalSize += sizeGlobalAddress(dword);
          FinalSize += sizeExternalSymbolAddress(dword);
          FinalSize += sizeConstPoolAddress(dword);
          FinalSize += sizeJumpTableAddress(dword);
      }
    }
    break;

  case X86II::MRMDestReg: {
    ++FinalSize; 
    FinalSize += sizeRegModRMByte();
    CurOp += 2;
      FinalSize += sizeConstant(X86InstrInfo::sizeOfImm(Desc));
    break;
  }
  case X86II::MRMDestMem: {
    ++FinalSize;
    FinalSize += getMemModRMByteSize(MI, CurOp, IsPIC, Is64BitMode);
    CurOp +=  X86AddrNumOperands + 1;
      FinalSize += sizeConstant(X86InstrInfo::sizeOfImm(Desc));
    break;
  }

  case X86II::MRMSrcReg:
    ++FinalSize;
    FinalSize += sizeRegModRMByte();
    CurOp += 2;
      FinalSize += sizeConstant(X86InstrInfo::sizeOfImm(Desc));
    int AddrOperands;
    if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r ||
        Opcode == X86::LEA16r || Opcode == X86::LEA32r)
      AddrOperands = X86AddrNumOperands - 1; // No segment register
    else
      AddrOperands = X86AddrNumOperands;

    ++FinalSize;
    FinalSize += getMemModRMByteSize(MI, CurOp+1, IsPIC, Is64BitMode);
      FinalSize += sizeConstant(X86InstrInfo::sizeOfImm(Desc));
    break;
  }

  case X86II::MRM0r: case X86II::MRM1r:
  case X86II::MRM2r: case X86II::MRM3r:
  case X86II::MRM4r: case X86II::MRM5r:
  case X86II::MRM6r: case X86II::MRM7r:
    ++FinalSize;
    if (Desc->getOpcode() == X86::LFENCE ||
        Desc->getOpcode() == X86::MFENCE) {
      // Special handling of lfence and mfence;
      FinalSize += sizeRegModRMByte();
    } else if (Desc->getOpcode() == X86::MONITOR ||
               Desc->getOpcode() == X86::MWAIT) {
      // Special handling of monitor and mwait.
      FinalSize += sizeRegModRMByte() + 1; // +1 for the opcode.
    } else {
      ++CurOp;
      FinalSize += sizeRegModRMByte();
    }

    if (CurOp != NumOps) {
      const MachineOperand &MO1 = MI.getOperand(CurOp++);
      unsigned Size = X86InstrInfo::sizeOfImm(Desc);
        FinalSize += sizeConstant(Size);
      else {
        bool dword = false;
        if (Opcode == X86::MOV64ri32)
          dword = true;
          FinalSize += sizeGlobalAddress(dword);
          FinalSize += sizeExternalSymbolAddress(dword);
          FinalSize += sizeConstPoolAddress(dword);
          FinalSize += sizeJumpTableAddress(dword);
      }
    }
    break;

  case X86II::MRM0m: case X86II::MRM1m:
  case X86II::MRM2m: case X86II::MRM3m:
  case X86II::MRM4m: case X86II::MRM5m:
  case X86II::MRM6m: case X86II::MRM7m: {
    
    ++FinalSize;
    FinalSize += getMemModRMByteSize(MI, CurOp, IsPIC, Is64BitMode);
    CurOp += X86AddrNumOperands;

    if (CurOp != NumOps) {
      const MachineOperand &MO = MI.getOperand(CurOp++);
      unsigned Size = X86InstrInfo::sizeOfImm(Desc);
        FinalSize += sizeConstant(Size);
      else {
        bool dword = false;
        if (Opcode == X86::MOV64mi32)
          dword = true;
          FinalSize += sizeGlobalAddress(dword);
          FinalSize += sizeExternalSymbolAddress(dword);
          FinalSize += sizeConstPoolAddress(dword);
          FinalSize += sizeJumpTableAddress(dword);
      }
    }
    break;
  }

  case X86II::MRMInitReg:
    ++FinalSize;
    // Duplicate register, used by things like MOV8r0 (aka xor reg,reg).
    FinalSize += sizeRegModRMByte();
    ++CurOp;
    break;
  }

  if (!Desc->isVariadic() && CurOp != NumOps) {
    std::string msg;
    raw_string_ostream Msg(msg);
    Msg << "Cannot determine size: " << MI;
    llvm_report_error(Msg.str());
  }
  

  return FinalSize;
}


unsigned X86InstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
  const TargetInstrDesc &Desc = MI->getDesc();
  bool IsPIC = TM.getRelocationModel() == Reloc::PIC_;
  bool Is64BitMode = TM.getSubtargetImpl()->is64Bit();
  unsigned Size = GetInstSizeWithDesc(*MI, &Desc, IsPIC, Is64BitMode);
  if (Desc.getOpcode() == X86::MOVPC32r)
    Size += GetInstSizeWithDesc(*MI, &get(X86::POP32r), IsPIC, Is64BitMode);
  return Size;
}
/// getGlobalBaseReg - Return a virtual register initialized with the
/// the global base register value. Output instructions required to
/// initialize the register in the function entry block, if necessary.
unsigned X86InstrInfo::getGlobalBaseReg(MachineFunction *MF) const {
  assert(!TM.getSubtarget<X86Subtarget>().is64Bit() &&
         "X86-64 PIC uses RIP relative addressing");

  X86MachineFunctionInfo *X86FI = MF->getInfo<X86MachineFunctionInfo>();
  unsigned GlobalBaseReg = X86FI->getGlobalBaseReg();
  if (GlobalBaseReg != 0)
    return GlobalBaseReg;

  // Insert the set of GlobalBaseReg into the first MBB of the function
  MachineBasicBlock &FirstMBB = MF->front();
  MachineBasicBlock::iterator MBBI = FirstMBB.begin();
  DebugLoc DL = DebugLoc::getUnknownLoc();
  if (MBBI != FirstMBB.end()) DL = MBBI->getDebugLoc();
  MachineRegisterInfo &RegInfo = MF->getRegInfo();
  unsigned PC = RegInfo.createVirtualRegister(X86::GR32RegisterClass);
  
  const TargetInstrInfo *TII = TM.getInstrInfo();
  // Operand of MovePCtoStack is completely ignored by asm printer. It's
  // only used in JIT code emission as displacement to pc.
  BuildMI(FirstMBB, MBBI, DL, TII->get(X86::MOVPC32r), PC).addImm(0);
  
  // If we're using vanilla 'GOT' PIC style, we should use relative addressing
  // not to pc, but to _GLOBAL_OFFSET_TABLE_ external.
  if (TM.getSubtarget<X86Subtarget>().isPICStyleGOT()) {
    GlobalBaseReg = RegInfo.createVirtualRegister(X86::GR32RegisterClass);
    // Generate addl $__GLOBAL_OFFSET_TABLE_ + [.-piclabel], %some_register
    BuildMI(FirstMBB, MBBI, DL, TII->get(X86::ADD32ri), GlobalBaseReg)
      .addReg(PC).addExternalSymbol("_GLOBAL_OFFSET_TABLE_",
                                    X86II::MO_GOT_ABSOLUTE_ADDRESS);
  } else {
    GlobalBaseReg = PC;
  X86FI->setGlobalBaseReg(GlobalBaseReg);
  return GlobalBaseReg;