Example #1
0
Optional<double>
MCSchedModel::getReciprocalThroughput(const MCSubtargetInfo &STI,
                                      const MCInstrInfo &MCII,
                                      const MCInst &Inst) const {
  Optional<double> Throughput;
  unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass();
  const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass);
  if (!SCDesc->isValid())
    return Throughput;

  unsigned CPUID = getProcessorID();
  while (SCDesc->isVariant()) {
    SchedClass = STI.resolveVariantSchedClass(SchedClass, &Inst, CPUID);
    SCDesc = getSchedClassDesc(SchedClass);
  }

  if (SchedClass)
    return MCSchedModel::getReciprocalThroughput(STI, *SCDesc);

  llvm_unreachable("unsupported variant scheduling class");
}
Example #2
0
/// \brief Gets latency information for \p Inst form the itinerary
/// scheduling model, based on \p DC information.
/// \return The maximum expected latency over all the operands or -1
/// if no information are available.
static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
  const int NoInformationAvailable = -1;

  // Check if we have a CPU to get the itinerary information.
  if (DC->getCPU().empty())
    return NoInformationAvailable;

  // Get itinerary information.
  const MCSubtargetInfo *STI = DC->getSubtargetInfo();
  InstrItineraryData IID = STI->getInstrItineraryForCPU(DC->getCPU());
  // Get the scheduling class of the requested instruction.
  const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
  unsigned SCClass = Desc.getSchedClass();

  int Latency = 0;
  for (unsigned OpIdx = 0, OpIdxEnd = Inst.getNumOperands(); OpIdx != OpIdxEnd;
       ++OpIdx)
    Latency = std::max(Latency, IID.getOperandCycle(SCClass, OpIdx));

  return Latency;
}
void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
  OutMI.setOpcode(MI->getOpcode());

  for (const MachineOperand &MO : MI->operands()) {
    MCOperand MCOp;
    if (lowerOperand(MO, MCOp))
      OutMI.addOperand(MCOp);
  }

  switch (OutMI.getOpcode()) {
  case AArch64::CATCHRET:
    OutMI = MCInst();
    OutMI.setOpcode(AArch64::RET);
    OutMI.addOperand(MCOperand::createReg(AArch64::LR));
    break;
  case AArch64::CLEANUPRET:
    OutMI = MCInst();
    OutMI.setOpcode(AArch64::RET);
    OutMI.addOperand(MCOperand::createReg(AArch64::LR));
    break;
  }
}
void PatmosDisassembler::adjustSignedImm(MCInst &instr) const {

  const MCInstrDesc &MID = MII->get(instr.getOpcode());

  bool ImmSigned = isPatmosImmediateSigned(MID.TSFlags);

  if (hasPatmosImmediate(MID.TSFlags) && ImmSigned) {
    unsigned ImmOpNo = getPatmosImmediateOpNo(MID.TSFlags);
    unsigned ImmSize = getPatmosImmediateSize(MID.TSFlags);

    uint64_t Value = instr.getOperand(ImmOpNo).getImm();

    if (Value & (1 << (ImmSize-1))) {

      // sign bit is set => sign-extend
      Value |= ~0ULL ^ ((1ULL << ImmSize) - 1);

      instr.getOperand(ImmOpNo).setImm(Value);
    }
  }

}
Example #5
0
/// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label
/// target.
uint32_t
AArch64MCCodeEmitter::getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
                                         SmallVectorImpl<MCFixup> &Fixups,
                                         const MCSubtargetInfo &STI) const {
  const MCOperand &MO = MI.getOperand(OpIdx);

  // If the destination is an immediate, we have nothing to do.
  if (MO.isImm())
    return MO.getImm();
  assert(MO.isExpr() && "Unexpected target type!");
  const MCExpr *Expr = MO.getExpr();

  MCFixupKind Kind = MI.getOpcode() == AArch64::ADR
                         ? MCFixupKind(AArch64::fixup_aarch64_pcrel_adr_imm21)
                         : MCFixupKind(AArch64::fixup_aarch64_pcrel_adrp_imm21);
  Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc()));

  MCNumFixups += 1;

  // All of the information is in the fixup.
  return 0;
}
Example #6
0
    bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
                        uint64_t &Target) const override {
        if (Inst.getNumOperands() == 0)
            return false;

        if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType ==
                MCOI::OPERAND_PCREL) {
            int64_t Imm = Inst.getOperand(0).getImm();
            Target = Addr + Size + Imm;
            return true;
        } else {
            int64_t Imm = Inst.getOperand(0).getImm();

            // Skip case where immediate is 0 as that occurs in file that isn't linked
            // and the branch target inferred would be wrong.
            if (Imm == 0)
                return false;

            Target = Imm;
            return true;
        }
    }
Example #7
0
// FIXME: Custom X86 cleanup function to implement a temporary hack to handle
// matching INCL/DECL correctly for x86_64. This needs to be replaced by a
// proper mechanism for supporting (ambiguous) feature dependent instructions.
void X86ATTAsmParser::InstructionCleanup(MCInst &Inst) {
  if (!Is64Bit) return;

  switch (Inst.getOpcode()) {
  case X86::DEC16r: Inst.setOpcode(X86::DEC64_16r); break;
  case X86::DEC16m: Inst.setOpcode(X86::DEC64_16m); break;
  case X86::DEC32r: Inst.setOpcode(X86::DEC64_32r); break;
  case X86::DEC32m: Inst.setOpcode(X86::DEC64_32m); break;
  case X86::INC16r: Inst.setOpcode(X86::INC64_16r); break;
  case X86::INC16m: Inst.setOpcode(X86::INC64_16m); break;
  case X86::INC32r: Inst.setOpcode(X86::INC64_32r); break;
  case X86::INC32m: Inst.setOpcode(X86::INC64_32m); break;
      
  // moffset instructions are x86-32 only.
  case X86::MOV8o8a:   LowerMOffset(Inst, X86::MOV8rm , X86::AL , false); break;
  case X86::MOV16o16a: LowerMOffset(Inst, X86::MOV16rm, X86::AX , false); break;
  case X86::MOV32o32a: LowerMOffset(Inst, X86::MOV32rm, X86::EAX, false); break;
  case X86::MOV8ao8:   LowerMOffset(Inst, X86::MOV8mr , X86::AL , true); break;
  case X86::MOV16ao16: LowerMOffset(Inst, X86::MOV16mr, X86::AX , true); break;
  case X86::MOV32ao32: LowerMOffset(Inst, X86::MOV32mr, X86::EAX, true); break;
  }
}
/// getJumpTargetOpValue - Return binary encoding of the jump
/// target operand
/// If the machine operand requires relocation,
/// record the relocation and return zero.
unsigned DSPMCCodeEmitter::
getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
	unsigned Opcode = MI.getOpcode();
	const MCOperand &MO = MI.getOperand(OpNo);
	// If the destination is an immediate, we have nothing to do.
	if (MO.isImm()) return MO.getImm();
	assert(MO.isExpr() && "getJumpTargetOpValue expects only expressions");

	const MCExpr *Expr = MO.getExpr();
	std::cout << "kind is" << Expr->getKind() << std::endl;
	//std::cout << "kind is" << Expr->getKind() << std::endl;

	if (Opcode == DSP::CALL)
		Fixups.push_back(MCFixup::Create(0, Expr,
		MCFixupKind(DSP::fixup_Mips_PC26_S2)));
	else
		llvm_unreachable("unexpect opcode in getJumpAbsoluteTargetOpValue()");

	return 0;
}
bool HexagonMCInstrInfo::subInstWouldBeExtended(MCInst const &potentialDuplex) {

  unsigned DstReg, SrcReg;

  switch (potentialDuplex.getOpcode()) {
  case Hexagon::A2_addi:
    // testing for case of: Rx = add(Rx,#s7)
    DstReg = potentialDuplex.getOperand(0).getReg();
    SrcReg = potentialDuplex.getOperand(1).getReg();
    if (DstReg == SrcReg && HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
      if (potentialDuplex.getOperand(2).isExpr())
        return true;
      if (potentialDuplex.getOperand(2).isImm() &&
          !(isShiftedInt<7, 0>(potentialDuplex.getOperand(2).getImm())))
        return true;
    }
    break;
  case Hexagon::A2_tfrsi:
    DstReg = potentialDuplex.getOperand(0).getReg();

    if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
      if (potentialDuplex.getOperand(1).isExpr())
        return true;
      // Check for case of Rd = #-1.
      if (potentialDuplex.getOperand(1).isImm() &&
          (potentialDuplex.getOperand(1).getImm() == -1))
        return false;
      // Check for case of Rd = #u6.
      if (potentialDuplex.getOperand(1).isImm() &&
          !isShiftedUInt<6, 0>(potentialDuplex.getOperand(1).getImm()))
        return true;
    }
    break;
  default:
    break;
  }
  return false;
}
void X86::X86MCNaClExpander::doExpandInst(const MCInst &Inst, MCStreamer &Out,
                                          const MCSubtargetInfo &STI) {
  if (isPrefix(Inst)) {
    Prefixes.push_back(Inst);
  } else {
    switch (Inst.getOpcode()) {
    case X86::CALL16r:
    case X86::CALL32r:
    case X86::CALL16m:
    case X86::CALL32m:
    case X86::JMP16r:
    case X86::JMP32r:
    case X86::JMP16m:
    case X86::JMP32m:
      return expandIndirectBranch(Inst, Out, STI);
    case X86::RETL:
    case X86::RETIL:
      return expandReturn(Inst, Out, STI);
    default:
      emitPrefixes(Out, STI);
      Out.EmitInstruction(Inst, STI);
    }
  }
}
void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
                                           SmallVectorImpl<MCFixup> &Fixups,
                                           const MCSubtargetInfo &STI) const {
  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
  // Get byte count of instruction.
  unsigned Size = Desc.getSize();

  switch (Size) {
  default:
    llvm_unreachable("Unhandled encodeInstruction length!");
  case 2: {
    uint16_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
    support::endian::Writer<support::little>(OS).write<uint16_t>(Bits);
    break;
  }
  case 4: {
    uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
    support::endian::Writer<support::little>(OS).write(Bits);
    break;
  }
  }

  ++MCNumEmitted; // Keep track of the # of mi's emitted.
}
Example #12
0
EDInst *EDDisassembler::createInst(EDByteReaderCallback byteReader, 
                                   uint64_t address, 
                                   void *arg) {
  EDMemoryObject memoryObject(byteReader, arg);
  
  MCInst* inst = new MCInst;
  uint64_t byteSize;
  
  if (!Disassembler->getInstruction(*inst,
                                    byteSize,
                                    memoryObject,
                                    address,
                                    ErrorStream)) {
    delete inst;
    return NULL;
  } else {
    const llvm::EDInstInfo *thisInstInfo;

    thisInstInfo = &InstInfos[inst->getOpcode()];
    
    EDInst* sdInst = new EDInst(inst, byteSize, *this, thisInstInfo);
    return sdInst;
  }
}
Example #13
0
MCInst HexagonMCInstrInfo::deriveSubInst(MCInst const &Inst) {
  MCInst Result;
  bool Absolute;
  int64_t Value;
  switch (Inst.getOpcode()) {
  default:
    // dbgs() << "opcode: "<< Inst->getOpcode() << "\n";
    llvm_unreachable("Unimplemented subinstruction \n");
    break;
  case Hexagon::A2_addi:
    Absolute = Inst.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
    assert(Absolute);(void)Absolute;
    if (Value == 1) {
      Result.setOpcode(Hexagon::SA1_inc);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 1);
      break;
    } //  1,2 SUBInst $Rd = add($Rs, #1)
    else if (Value == -1) {
      Result.setOpcode(Hexagon::SA1_dec);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 1);
      break;
    } //  1,2 SUBInst $Rd = add($Rs,#-1)
    else if (Inst.getOperand(1).getReg() == Hexagon::R29) {
      Result.setOpcode(Hexagon::SA1_addsp);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 2);
      break;
    } //  1,3 SUBInst $Rd = add(r29, #$u6_2)
    else {
      Result.setOpcode(Hexagon::SA1_addi);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 1);
      addOps(Result, Inst, 2);
      break;
    } //    1,2,3 SUBInst $Rx = add($Rx, #$s7)
  case Hexagon::A2_add:
    Result.setOpcode(Hexagon::SA1_addrx);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    addOps(Result, Inst, 2);
    break; //    1,2,3 SUBInst $Rx = add($_src_, $Rs)
  case Hexagon::S2_allocframe:
    Result.setOpcode(Hexagon::SS2_allocframe);
    addOps(Result, Inst, 0);
    break; //    1 SUBInst allocframe(#$u5_3)
  case Hexagon::A2_andir:
    if (minConstant(Inst, 2) == 255) {
      Result.setOpcode(Hexagon::SA1_zxtb);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 1);
      break; //    1,2    $Rd = and($Rs, #255)
    } else {
      Result.setOpcode(Hexagon::SA1_and1);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 1);
      break; //    1,2 SUBInst $Rd = and($Rs, #1)
    }
  case Hexagon::C2_cmpeqi:
    Result.setOpcode(Hexagon::SA1_cmpeqi);
    addOps(Result, Inst, 1);
    addOps(Result, Inst, 2);
    break; //    2,3 SUBInst p0 = cmp.eq($Rs, #$u2)
  case Hexagon::A4_combineii:
  case Hexagon::A2_combineii:
    Absolute = Inst.getOperand(1).getExpr()->evaluateAsAbsolute(Value);
    assert(Absolute);(void)Absolute;
    if (Value == 1) {
      Result.setOpcode(Hexagon::SA1_combine1i);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 2);
      break; //  1,3 SUBInst $Rdd = combine(#1, #$u2)
    }
    if (Value == 3) {
      Result.setOpcode(Hexagon::SA1_combine3i);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 2);
      break; //  1,3 SUBInst $Rdd = combine(#3, #$u2)
    }
    if (Value == 0) {
      Result.setOpcode(Hexagon::SA1_combine0i);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 2);
      break; //  1,3 SUBInst $Rdd = combine(#0, #$u2)
    }
    if (Value == 2) {
      Result.setOpcode(Hexagon::SA1_combine2i);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 2);
      break; //  1,3 SUBInst $Rdd = combine(#2, #$u2)
    }
  case Hexagon::A4_combineir:
    Result.setOpcode(Hexagon::SA1_combinezr);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 2);
    break; //    1,3 SUBInst $Rdd = combine(#0, $Rs)

  case Hexagon::A4_combineri:
    Result.setOpcode(Hexagon::SA1_combinerz);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    break; //    1,2 SUBInst $Rdd = combine($Rs, #0)
  case Hexagon::L4_return_tnew_pnt:
  case Hexagon::L4_return_tnew_pt:
    Result.setOpcode(Hexagon::SL2_return_tnew);
    break; //    none  SUBInst if (p0.new) dealloc_return:nt
  case Hexagon::L4_return_fnew_pnt:
  case Hexagon::L4_return_fnew_pt:
    Result.setOpcode(Hexagon::SL2_return_fnew);
    break; //    none  SUBInst if (!p0.new) dealloc_return:nt
  case Hexagon::L4_return_f:
    Result.setOpcode(Hexagon::SL2_return_f);
    break; //    none  SUBInst if (!p0) dealloc_return
  case Hexagon::L4_return_t:
    Result.setOpcode(Hexagon::SL2_return_t);
    break; //    none  SUBInst if (p0) dealloc_return
  case Hexagon::L4_return:
    Result.setOpcode(Hexagon::SL2_return);
    break; //    none  SUBInst dealloc_return
  case Hexagon::L2_deallocframe:
    Result.setOpcode(Hexagon::SL2_deallocframe);
    break; //    none  SUBInst deallocframe
  case Hexagon::EH_RETURN_JMPR:
  case Hexagon::J2_jumpr:
    Result.setOpcode(Hexagon::SL2_jumpr31);
    break; //    none  SUBInst jumpr r31
  case Hexagon::J2_jumprf:
    Result.setOpcode(Hexagon::SL2_jumpr31_f);
    break; //    none  SUBInst if (!p0) jumpr r31
  case Hexagon::J2_jumprfnew:
  case Hexagon::J2_jumprfnewpt:
    Result.setOpcode(Hexagon::SL2_jumpr31_fnew);
    break; //    none  SUBInst if (!p0.new) jumpr:nt r31
  case Hexagon::J2_jumprt:
    Result.setOpcode(Hexagon::SL2_jumpr31_t);
    break; //    none  SUBInst if (p0) jumpr r31
  case Hexagon::J2_jumprtnew:
  case Hexagon::J2_jumprtnewpt:
    Result.setOpcode(Hexagon::SL2_jumpr31_tnew);
    break; //    none  SUBInst if (p0.new) jumpr:nt r31
  case Hexagon::L2_loadrb_io:
    Result.setOpcode(Hexagon::SL2_loadrb_io);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    addOps(Result, Inst, 2);
    break; //    1,2,3 SUBInst $Rd = memb($Rs + #$u3_0)
  case Hexagon::L2_loadrd_io:
    Result.setOpcode(Hexagon::SL2_loadrd_sp);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 2);
    break; //    1,3 SUBInst $Rdd = memd(r29 + #$u5_3)
  case Hexagon::L2_loadrh_io:
    Result.setOpcode(Hexagon::SL2_loadrh_io);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    addOps(Result, Inst, 2);
    break; //    1,2,3 SUBInst $Rd = memh($Rs + #$u3_1)
  case Hexagon::L2_loadrub_io:
    Result.setOpcode(Hexagon::SL1_loadrub_io);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    addOps(Result, Inst, 2);
    break; //    1,2,3 SUBInst $Rd = memub($Rs + #$u4_0)
  case Hexagon::L2_loadruh_io:
    Result.setOpcode(Hexagon::SL2_loadruh_io);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    addOps(Result, Inst, 2);
    break; //    1,2,3 SUBInst $Rd = memuh($Rs + #$u3_1)
  case Hexagon::L2_loadri_io:
    if (Inst.getOperand(1).getReg() == Hexagon::R29) {
      Result.setOpcode(Hexagon::SL2_loadri_sp);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 2);
      break; //  2 1,3 SUBInst $Rd = memw(r29 + #$u5_2)
    } else {
      Result.setOpcode(Hexagon::SL1_loadri_io);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 1);
      addOps(Result, Inst, 2);
      break; //    1,2,3 SUBInst $Rd = memw($Rs + #$u4_2)
    }
  case Hexagon::S4_storeirb_io:
    Absolute = Inst.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
    assert(Absolute);(void)Absolute;
    if (Value == 0) {
      Result.setOpcode(Hexagon::SS2_storebi0);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 1);
      break; //    1,2 SUBInst memb($Rs + #$u4_0)=#0
    } else if (Value == 1) {
      Result.setOpcode(Hexagon::SS2_storebi1);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 1);
      break; //  2 1,2 SUBInst memb($Rs + #$u4_0)=#1
    }
  case Hexagon::S2_storerb_io:
    Result.setOpcode(Hexagon::SS1_storeb_io);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    addOps(Result, Inst, 2);
    break; //    1,2,3 SUBInst memb($Rs + #$u4_0) = $Rt
  case Hexagon::S2_storerd_io:
    Result.setOpcode(Hexagon::SS2_stored_sp);
    addOps(Result, Inst, 1);
    addOps(Result, Inst, 2);
    break; //    2,3 SUBInst memd(r29 + #$s6_3) = $Rtt
  case Hexagon::S2_storerh_io:
    Result.setOpcode(Hexagon::SS2_storeh_io);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    addOps(Result, Inst, 2);
    break; //    1,2,3 SUBInst memb($Rs + #$u4_0) = $Rt
  case Hexagon::S4_storeiri_io:
    Absolute = Inst.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
    assert(Absolute);(void)Absolute;
    if (Value == 0) {
      Result.setOpcode(Hexagon::SS2_storewi0);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 1);
      break; //  3 1,2 SUBInst memw($Rs + #$u4_2)=#0
    } else if (Value == 1) {
      Result.setOpcode(Hexagon::SS2_storewi1);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 1);
      break; //  3 1,2 SUBInst memw($Rs + #$u4_2)=#1
    } else if (Inst.getOperand(0).getReg() == Hexagon::R29) {
      Result.setOpcode(Hexagon::SS2_storew_sp);
      addOps(Result, Inst, 1);
      addOps(Result, Inst, 2);
      break; //  1 2,3 SUBInst memw(r29 + #$u5_2) = $Rt
    }
  case Hexagon::S2_storeri_io:
    if (Inst.getOperand(0).getReg() == Hexagon::R29) {
      Result.setOpcode(Hexagon::SS2_storew_sp);
      addOps(Result, Inst, 1);
      addOps(Result, Inst, 2); //  1,2,3 SUBInst memw(sp + #$u5_2) = $Rt
    } else {
      Result.setOpcode(Hexagon::SS1_storew_io);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 1);
      addOps(Result, Inst, 2); //  1,2,3 SUBInst memw($Rs + #$u4_2) = $Rt
    }
    break;
  case Hexagon::A2_sxtb:
    Result.setOpcode(Hexagon::SA1_sxtb);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    break; //  1,2 SUBInst $Rd = sxtb($Rs)
  case Hexagon::A2_sxth:
    Result.setOpcode(Hexagon::SA1_sxth);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    break; //  1,2 SUBInst $Rd = sxth($Rs)
  case Hexagon::A2_tfr:
    Result.setOpcode(Hexagon::SA1_tfr);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    break; //  1,2 SUBInst $Rd = $Rs
  case Hexagon::C2_cmovenewif:
    Result.setOpcode(Hexagon::SA1_clrfnew);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    break; //  2 SUBInst if (!p0.new) $Rd = #0
  case Hexagon::C2_cmovenewit:
    Result.setOpcode(Hexagon::SA1_clrtnew);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    break; //  2 SUBInst if (p0.new) $Rd = #0
  case Hexagon::C2_cmoveif:
    Result.setOpcode(Hexagon::SA1_clrf);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    break; //  2 SUBInst if (!p0) $Rd = #0
  case Hexagon::C2_cmoveit:
    Result.setOpcode(Hexagon::SA1_clrt);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    break; //  2 SUBInst if (p0) $Rd = #0
  case Hexagon::A2_tfrsi:
    Absolute = Inst.getOperand(1).getExpr()->evaluateAsAbsolute(Value);
    if (Absolute && Value == -1) {
      Result.setOpcode(Hexagon::SA1_setin1);
      addOps(Result, Inst, 0);
      break; //  2 1 SUBInst $Rd = #-1
    } else {
      Result.setOpcode(Hexagon::SA1_seti);
      addOps(Result, Inst, 0);
      addOps(Result, Inst, 1);
      break; //    1,2 SUBInst $Rd = #$u6
    }
  case Hexagon::A2_zxtb:
    Result.setOpcode(Hexagon::SA1_zxtb);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    break; //    1,2    $Rd = and($Rs, #255)

  case Hexagon::A2_zxth:
    Result.setOpcode(Hexagon::SA1_zxth);
    addOps(Result, Inst, 0);
    addOps(Result, Inst, 1);
    break; //    1,2 SUBInst $Rd = zxth($Rs)
  }
  return Result;
}
Example #14
0
/// non-Symmetrical. See if these two instructions are fit for duplex pair.
bool HexagonMCInstrInfo::isOrderedDuplexPair(MCInstrInfo const &MCII,
                                             MCInst const &MIa, bool ExtendedA,
                                             MCInst const &MIb, bool ExtendedB,
                                             bool bisReversable) {
  // Slot 1 cannot be extended in duplexes PRM 10.5
  if (ExtendedA)
    return false;
  // Only A2_addi and A2_tfrsi can be extended in duplex form PRM 10.5
  if (ExtendedB) {
    unsigned Opcode = MIb.getOpcode();
    if ((Opcode != Hexagon::A2_addi) && (Opcode != Hexagon::A2_tfrsi))
      return false;
  }
  unsigned MIaG = HexagonMCInstrInfo::getDuplexCandidateGroup(MIa),
           MIbG = HexagonMCInstrInfo::getDuplexCandidateGroup(MIb);

  static std::map<unsigned, unsigned> subinstOpcodeMap(std::begin(opcodeData),
                                                       std::end(opcodeData));

  // If a duplex contains 2 insns in the same group, the insns must be
  // ordered such that the numerically smaller opcode is in slot 1.
  if ((MIaG != HexagonII::HSIG_None) && (MIaG == MIbG) && bisReversable) {
    MCInst SubInst0 = HexagonMCInstrInfo::deriveSubInst(MIa);
    MCInst SubInst1 = HexagonMCInstrInfo::deriveSubInst(MIb);

    unsigned zeroedSubInstS0 =
        subinstOpcodeMap.find(SubInst0.getOpcode())->second;
    unsigned zeroedSubInstS1 =
        subinstOpcodeMap.find(SubInst1.getOpcode())->second;

    if (zeroedSubInstS0 < zeroedSubInstS1)
      // subinstS0 (maps to slot 0) must be greater than
      // subinstS1 (maps to slot 1)
      return false;
  }

  // allocframe must always be in slot 0
  if (MIb.getOpcode() == Hexagon::S2_allocframe)
    return false;

  if ((MIaG != HexagonII::HSIG_None) && (MIbG != HexagonII::HSIG_None)) {
    // Prevent 2 instructions with extenders from duplexing
    // Note that MIb (slot1) can be extended and MIa (slot0)
    //   can never be extended
    if (subInstWouldBeExtended(MIa))
      return false;

    // If duplexing produces an extender, but the original did not
    //   have an extender, do not duplex.
    if (subInstWouldBeExtended(MIb) && !ExtendedB)
      return false;
  }

  // If jumpr r31 appears, it must be in slot 0, and never slot 1 (MIb).
  if (MIbG == HexagonII::HSIG_L2) {
    if ((MIb.getNumOperands() > 1) && MIb.getOperand(1).isReg() &&
        (MIb.getOperand(1).getReg() == Hexagon::R31))
      return false;
    if ((MIb.getNumOperands() > 0) && MIb.getOperand(0).isReg() &&
        (MIb.getOperand(0).getReg() == Hexagon::R31))
      return false;
  }

  // If a store appears, it must be in slot 0 (MIa) 1st, and then slot 1 (MIb);
  //   therefore, not duplexable if slot 1 is a store, and slot 0 is not.
  if ((MIbG == HexagonII::HSIG_S1) || (MIbG == HexagonII::HSIG_S2)) {
    if ((MIaG != HexagonII::HSIG_S1) && (MIaG != HexagonII::HSIG_S2))
      return false;
  }

  return (isDuplexPairMatch(MIaG, MIbG));
}
Example #15
0
unsigned HexagonMCInstrInfo::getDuplexCandidateGroup(MCInst const &MCI) {
  unsigned DstReg, PredReg, SrcReg, Src1Reg, Src2Reg;

  switch (MCI.getOpcode()) {
  default:
    return HexagonII::HSIG_None;
  //
  // Group L1:
  //
  // Rd = memw(Rs+#u4:2)
  // Rd = memub(Rs+#u4:0)
  case Hexagon::L2_loadri_io:
    DstReg = MCI.getOperand(0).getReg();
    SrcReg = MCI.getOperand(1).getReg();
    // Special case this one from Group L2.
    // Rd = memw(r29+#u5:2)
    if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
      if (HexagonMCInstrInfo::isIntReg(SrcReg) &&
          Hexagon::R29 == SrcReg && inRange<5, 2>(MCI, 2)) {
        return HexagonII::HSIG_L2;
      }
      // Rd = memw(Rs+#u4:2)
      if (HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
          inRange<4, 2>(MCI, 2)) {
        return HexagonII::HSIG_L1;
      }
    }
    break;
  case Hexagon::L2_loadrub_io:
    // Rd = memub(Rs+#u4:0)
    DstReg = MCI.getOperand(0).getReg();
    SrcReg = MCI.getOperand(1).getReg();
    if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
        HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
        inRange<4>(MCI, 2)) {
      return HexagonII::HSIG_L1;
    }
    break;
  //
  // Group L2:
  //
  // Rd = memh/memuh(Rs+#u3:1)
  // Rd = memb(Rs+#u3:0)
  // Rd = memw(r29+#u5:2) - Handled above.
  // Rdd = memd(r29+#u5:3)
  // deallocframe
  // [if ([!]p0[.new])] dealloc_return
  // [if ([!]p0[.new])] jumpr r31
  case Hexagon::L2_loadrh_io:
  case Hexagon::L2_loadruh_io:
    // Rd = memh/memuh(Rs+#u3:1)
    DstReg = MCI.getOperand(0).getReg();
    SrcReg = MCI.getOperand(1).getReg();
    if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
        HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
        inRange<3, 1>(MCI, 2)) {
      return HexagonII::HSIG_L2;
    }
    break;
  case Hexagon::L2_loadrb_io:
    // Rd = memb(Rs+#u3:0)
    DstReg = MCI.getOperand(0).getReg();
    SrcReg = MCI.getOperand(1).getReg();
    if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
        HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
        inRange<3>(MCI, 2)) {
      return HexagonII::HSIG_L2;
    }
    break;
  case Hexagon::L2_loadrd_io:
    // Rdd = memd(r29+#u5:3)
    DstReg = MCI.getOperand(0).getReg();
    SrcReg = MCI.getOperand(1).getReg();
    if (HexagonMCInstrInfo::isDblRegForSubInst(DstReg) &&
        HexagonMCInstrInfo::isIntReg(SrcReg) && Hexagon::R29 == SrcReg &&
        inRange<5, 3>(MCI, 2)) {
      return HexagonII::HSIG_L2;
    }
    break;

  case Hexagon::L4_return:

  case Hexagon::L2_deallocframe:

    return HexagonII::HSIG_L2;
  case Hexagon::EH_RETURN_JMPR:

  case Hexagon::J2_jumpr:
    // jumpr r31
    // Actual form JMPR %PC<imp-def>, %R31<imp-use>, %R0<imp-use,internal>.
    DstReg = MCI.getOperand(0).getReg();
    if (Hexagon::R31 == DstReg)
      return HexagonII::HSIG_L2;
    break;

  case Hexagon::J2_jumprt:
  case Hexagon::J2_jumprf:
  case Hexagon::J2_jumprtnew:
  case Hexagon::J2_jumprfnew:
  case Hexagon::J2_jumprtnewpt:
  case Hexagon::J2_jumprfnewpt:
    DstReg = MCI.getOperand(1).getReg();
    SrcReg = MCI.getOperand(0).getReg();
    // [if ([!]p0[.new])] jumpr r31
    if ((HexagonMCInstrInfo::isPredReg(SrcReg) && (Hexagon::P0 == SrcReg)) &&
        (Hexagon::R31 == DstReg)) {
      return HexagonII::HSIG_L2;
    }
    break;
  case Hexagon::L4_return_t:

  case Hexagon::L4_return_f:

  case Hexagon::L4_return_tnew_pnt:

  case Hexagon::L4_return_fnew_pnt:

  case Hexagon::L4_return_tnew_pt:

  case Hexagon::L4_return_fnew_pt:
    // [if ([!]p0[.new])] dealloc_return
    SrcReg = MCI.getOperand(0).getReg();
    if (Hexagon::P0 == SrcReg) {
      return HexagonII::HSIG_L2;
    }
    break;
  //
  // Group S1:
  //
  // memw(Rs+#u4:2) = Rt
  // memb(Rs+#u4:0) = Rt
  case Hexagon::S2_storeri_io:
    // Special case this one from Group S2.
    // memw(r29+#u5:2) = Rt
    Src1Reg = MCI.getOperand(0).getReg();
    Src2Reg = MCI.getOperand(2).getReg();
    if (HexagonMCInstrInfo::isIntReg(Src1Reg) &&
        HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg) &&
        Hexagon::R29 == Src1Reg && inRange<5, 2>(MCI, 1)) {
      return HexagonII::HSIG_S2;
    }
    // memw(Rs+#u4:2) = Rt
    if (HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
        HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg) &&
        inRange<4, 2>(MCI, 1)) {
      return HexagonII::HSIG_S1;
    }
    break;
  case Hexagon::S2_storerb_io:
    // memb(Rs+#u4:0) = Rt
    Src1Reg = MCI.getOperand(0).getReg();
    Src2Reg = MCI.getOperand(2).getReg();
    if (HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
        HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg) &&
        inRange<4>(MCI, 1)) {
      return HexagonII::HSIG_S1;
    }
    break;
  //
  // Group S2:
  //
  // memh(Rs+#u3:1) = Rt
  // memw(r29+#u5:2) = Rt
  // memd(r29+#s6:3) = Rtt
  // memw(Rs+#u4:2) = #U1
  // memb(Rs+#u4) = #U1
  // allocframe(#u5:3)
  case Hexagon::S2_storerh_io:
    // memh(Rs+#u3:1) = Rt
    Src1Reg = MCI.getOperand(0).getReg();
    Src2Reg = MCI.getOperand(2).getReg();
    if (HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
        HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg) &&
        inRange<3, 1>(MCI, 1)) {
      return HexagonII::HSIG_S2;
    }
    break;
  case Hexagon::S2_storerd_io:
    // memd(r29+#s6:3) = Rtt
    Src1Reg = MCI.getOperand(0).getReg();
    Src2Reg = MCI.getOperand(2).getReg();
    if (HexagonMCInstrInfo::isDblRegForSubInst(Src2Reg) &&
        HexagonMCInstrInfo::isIntReg(Src1Reg) && Hexagon::R29 == Src1Reg &&
        inSRange<6, 3>(MCI, 1)) {
      return HexagonII::HSIG_S2;
    }
    break;
  case Hexagon::S4_storeiri_io:
    // memw(Rs+#u4:2) = #U1
    Src1Reg = MCI.getOperand(0).getReg();
    if (HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
        inRange<4, 2>(MCI, 1) && inRange<1>(MCI, 2)) {
      return HexagonII::HSIG_S2;
    }
    break;
  case Hexagon::S4_storeirb_io:
    // memb(Rs+#u4) = #U1
    Src1Reg = MCI.getOperand(0).getReg();
    if (HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
        inRange<4>(MCI, 1) && inRange<1>(MCI, 2)) {
      return HexagonII::HSIG_S2;
    }
    break;
  case Hexagon::S2_allocframe:
    if (inRange<5, 3>(MCI, 0))
      return HexagonII::HSIG_S2;
    break;
  //
  // Group A:
  //
  // Rx = add(Rx,#s7)
  // Rd = Rs
  // Rd = #u6
  // Rd = #-1
  // if ([!]P0[.new]) Rd = #0
  // Rd = add(r29,#u6:2)
  // Rx = add(Rx,Rs)
  // P0 = cmp.eq(Rs,#u2)
  // Rdd = combine(#0,Rs)
  // Rdd = combine(Rs,#0)
  // Rdd = combine(#u2,#U2)
  // Rd = add(Rs,#1)
  // Rd = add(Rs,#-1)
  // Rd = sxth/sxtb/zxtb/zxth(Rs)
  // Rd = and(Rs,#1)
  case Hexagon::A2_addi:
    DstReg = MCI.getOperand(0).getReg();
    SrcReg = MCI.getOperand(1).getReg();
    if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
      // Rd = add(r29,#u6:2)
      if (HexagonMCInstrInfo::isIntReg(SrcReg) && Hexagon::R29 == SrcReg &&
          inRange<6, 2>(MCI, 2)) {
        return HexagonII::HSIG_A;
      }
      // Rx = add(Rx,#s7)
      if (DstReg == SrcReg) {
        return HexagonII::HSIG_A;
      }
      // Rd = add(Rs,#1)
      // Rd = add(Rs,#-1)
      if (HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
          (minConstant(MCI, 2) == 1 || minConstant(MCI, 2) == -1)) {
        return HexagonII::HSIG_A;
      }
    }
    break;
  case Hexagon::A2_add:
    // Rx = add(Rx,Rs)
    DstReg = MCI.getOperand(0).getReg();
    Src1Reg = MCI.getOperand(1).getReg();
    Src2Reg = MCI.getOperand(2).getReg();
    if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) && (DstReg == Src1Reg) &&
        HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg)) {
      return HexagonII::HSIG_A;
    }
    break;
  case Hexagon::A2_andir:
    DstReg = MCI.getOperand(0).getReg();
    SrcReg = MCI.getOperand(1).getReg();
    if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
        HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
        (minConstant(MCI, 2) == 1 || minConstant(MCI, 2) == 255)) {
      return HexagonII::HSIG_A;
    }
    break;
  case Hexagon::A2_tfr:
    // Rd = Rs
    DstReg = MCI.getOperand(0).getReg();
    SrcReg = MCI.getOperand(1).getReg();
    if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
        HexagonMCInstrInfo::isIntRegForSubInst(SrcReg)) {
      return HexagonII::HSIG_A;
    }
    break;
  case Hexagon::A2_tfrsi:
    DstReg = MCI.getOperand(0).getReg();

    if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
      return HexagonII::HSIG_A;
    }
    break;
  case Hexagon::C2_cmoveit:
  case Hexagon::C2_cmovenewit:
  case Hexagon::C2_cmoveif:
  case Hexagon::C2_cmovenewif:
    // if ([!]P0[.new]) Rd = #0
    // Actual form:
    // %R16<def> = C2_cmovenewit %P0<internal>, 0, %R16<imp-use,undef>;
    DstReg = MCI.getOperand(0).getReg();  // Rd
    PredReg = MCI.getOperand(1).getReg(); // P0
    if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
        Hexagon::P0 == PredReg && minConstant(MCI, 2) == 0) {
      return HexagonII::HSIG_A;
    }
    break;
  case Hexagon::C2_cmpeqi:
    // P0 = cmp.eq(Rs,#u2)
    DstReg = MCI.getOperand(0).getReg();
    SrcReg = MCI.getOperand(1).getReg();
    if (Hexagon::P0 == DstReg &&
        HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
        inRange<2>(MCI, 2)) {
      return HexagonII::HSIG_A;
    }
    break;
  case Hexagon::A2_combineii:
  case Hexagon::A4_combineii:
    // Rdd = combine(#u2,#U2)
    DstReg = MCI.getOperand(0).getReg();
    if (HexagonMCInstrInfo::isDblRegForSubInst(DstReg) &&
        inRange<2>(MCI, 1) && inRange<2>(MCI, 2)) {
      return HexagonII::HSIG_A;
    }
    break;
  case Hexagon::A4_combineri:
    // Rdd = combine(Rs,#0)
    DstReg = MCI.getOperand(0).getReg();
    SrcReg = MCI.getOperand(1).getReg();
    if (HexagonMCInstrInfo::isDblRegForSubInst(DstReg) &&
        HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
        minConstant(MCI, 2) == 0) {
      return HexagonII::HSIG_A;
    }
    break;
  case Hexagon::A4_combineir:
    // Rdd = combine(#0,Rs)
    DstReg = MCI.getOperand(0).getReg();
    SrcReg = MCI.getOperand(2).getReg();
    if (HexagonMCInstrInfo::isDblRegForSubInst(DstReg) &&
        HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
        minConstant(MCI, 1) == 0) {
      return HexagonII::HSIG_A;
    }
    break;
  case Hexagon::A2_sxtb:
  case Hexagon::A2_sxth:
  case Hexagon::A2_zxtb:
  case Hexagon::A2_zxth:
    // Rd = sxth/sxtb/zxtb/zxth(Rs)
    DstReg = MCI.getOperand(0).getReg();
    SrcReg = MCI.getOperand(1).getReg();
    if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
        HexagonMCInstrInfo::isIntRegForSubInst(SrcReg)) {
      return HexagonII::HSIG_A;
    }
    break;
  }

  return HexagonII::HSIG_None;
}
void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
  OutMI.setOpcode(MI->getOpcode());

  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);

    MCOperand MCOp;
    switch (MO.getType()) {
    default:
      MI->dump();
      llvm_unreachable("unknown operand type");
    case MachineOperand::MO_Register:
      // Ignore all implicit register operands.
      if (MO.isImplicit()) continue;
      MCOp = MCOperand::CreateReg(MO.getReg());
      break;
    case MachineOperand::MO_Immediate:
      MCOp = MCOperand::CreateImm(MO.getImm());
      break;
    case MachineOperand::MO_MachineBasicBlock:
    case MachineOperand::MO_GlobalAddress:
    case MachineOperand::MO_ExternalSymbol:
      MCOp = LowerSymbolOperand(MO, GetSymbolFromOperand(MO));
      break;
    case MachineOperand::MO_JumpTableIndex:
      MCOp = LowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex()));
      break;
    case MachineOperand::MO_ConstantPoolIndex:
      MCOp = LowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex()));
      break;
    case MachineOperand::MO_BlockAddress:
      MCOp = LowerSymbolOperand(MO,
                     AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()));
      break;
    case MachineOperand::MO_RegisterMask:
      // Ignore call clobbers.
      continue;
    }

    OutMI.addOperand(MCOp);
  }

  // Handle a few special cases to eliminate operand modifiers.
ReSimplify:
  switch (OutMI.getOpcode()) {
  case X86::LEA64_32r:
  case X86::LEA64r:
  case X86::LEA16r:
  case X86::LEA32r:
    // LEA should have a segment register, but it must be empty.
    assert(OutMI.getNumOperands() == 1+X86::AddrNumOperands &&
           "Unexpected # of LEA operands");
    assert(OutMI.getOperand(1+X86::AddrSegmentReg).getReg() == 0 &&
           "LEA has segment specified!");
    break;

  case X86::MOV32ri64:
    OutMI.setOpcode(X86::MOV32ri);
    break;

  // Commute operands to get a smaller encoding by using VEX.R instead of VEX.B
  // if one of the registers is extended, but other isn't.
  case X86::VMOVAPDrr:
  case X86::VMOVAPDYrr:
  case X86::VMOVAPSrr:
  case X86::VMOVAPSYrr:
  case X86::VMOVDQArr:
  case X86::VMOVDQAYrr:
  case X86::VMOVDQUrr:
  case X86::VMOVDQUYrr:
  case X86::VMOVUPDrr:
  case X86::VMOVUPDYrr:
  case X86::VMOVUPSrr:
  case X86::VMOVUPSYrr: {
    if (!X86II::isX86_64ExtendedReg(OutMI.getOperand(0).getReg()) &&
        X86II::isX86_64ExtendedReg(OutMI.getOperand(1).getReg())) {
      unsigned NewOpc;
      switch (OutMI.getOpcode()) {
      default: llvm_unreachable("Invalid opcode");
      case X86::VMOVAPDrr:  NewOpc = X86::VMOVAPDrr_REV;  break;
      case X86::VMOVAPDYrr: NewOpc = X86::VMOVAPDYrr_REV; break;
      case X86::VMOVAPSrr:  NewOpc = X86::VMOVAPSrr_REV;  break;
      case X86::VMOVAPSYrr: NewOpc = X86::VMOVAPSYrr_REV; break;
      case X86::VMOVDQArr:  NewOpc = X86::VMOVDQArr_REV;  break;
      case X86::VMOVDQAYrr: NewOpc = X86::VMOVDQAYrr_REV; break;
      case X86::VMOVDQUrr:  NewOpc = X86::VMOVDQUrr_REV;  break;
      case X86::VMOVDQUYrr: NewOpc = X86::VMOVDQUYrr_REV; break;
      case X86::VMOVUPDrr:  NewOpc = X86::VMOVUPDrr_REV;  break;
      case X86::VMOVUPDYrr: NewOpc = X86::VMOVUPDYrr_REV; break;
      case X86::VMOVUPSrr:  NewOpc = X86::VMOVUPSrr_REV;  break;
      case X86::VMOVUPSYrr: NewOpc = X86::VMOVUPSYrr_REV; break;
      }
      OutMI.setOpcode(NewOpc);
    }
    break;
  }
  case X86::VMOVSDrr:
  case X86::VMOVSSrr: {
    if (!X86II::isX86_64ExtendedReg(OutMI.getOperand(0).getReg()) &&
        X86II::isX86_64ExtendedReg(OutMI.getOperand(2).getReg())) {
      unsigned NewOpc;
      switch (OutMI.getOpcode()) {
      default: llvm_unreachable("Invalid opcode");
      case X86::VMOVSDrr:   NewOpc = X86::VMOVSDrr_REV;   break;
      case X86::VMOVSSrr:   NewOpc = X86::VMOVSSrr_REV;   break;
      }
      OutMI.setOpcode(NewOpc);
    }
    break;
  }

  // TAILJMPr64, CALL64r, CALL64pcrel32 - These instructions have register
  // inputs modeled as normal uses instead of implicit uses.  As such, truncate
  // off all but the first operand (the callee).  FIXME: Change isel.
  case X86::TAILJMPr64:
  case X86::CALL64r:
  case X86::CALL64pcrel32: {
    unsigned Opcode = OutMI.getOpcode();
    MCOperand Saved = OutMI.getOperand(0);
    OutMI = MCInst();
    OutMI.setOpcode(Opcode);
    OutMI.addOperand(Saved);
    break;
  }

  case X86::EH_RETURN:
  case X86::EH_RETURN64: {
    OutMI = MCInst();
    OutMI.setOpcode(getRetOpcode(AsmPrinter.getSubtarget()));
    break;
  }

  // TAILJMPd, TAILJMPd64 - Lower to the correct jump instructions.
  case X86::TAILJMPr:
  case X86::TAILJMPd:
  case X86::TAILJMPd64: {
    unsigned Opcode;
    switch (OutMI.getOpcode()) {
    default: llvm_unreachable("Invalid opcode");
    case X86::TAILJMPr: Opcode = X86::JMP32r; break;
    case X86::TAILJMPd:
    case X86::TAILJMPd64: Opcode = X86::JMP_1; break;
    }

    MCOperand Saved = OutMI.getOperand(0);
    OutMI = MCInst();
    OutMI.setOpcode(Opcode);
    OutMI.addOperand(Saved);
    break;
  }

  // These are pseudo-ops for OR to help with the OR->ADD transformation.  We do
  // this with an ugly goto in case the resultant OR uses EAX and needs the
  // short form.
  case X86::ADD16rr_DB:   OutMI.setOpcode(X86::OR16rr); goto ReSimplify;
  case X86::ADD32rr_DB:   OutMI.setOpcode(X86::OR32rr); goto ReSimplify;
  case X86::ADD64rr_DB:   OutMI.setOpcode(X86::OR64rr); goto ReSimplify;
  case X86::ADD16ri_DB:   OutMI.setOpcode(X86::OR16ri); goto ReSimplify;
  case X86::ADD32ri_DB:   OutMI.setOpcode(X86::OR32ri); goto ReSimplify;
  case X86::ADD64ri32_DB: OutMI.setOpcode(X86::OR64ri32); goto ReSimplify;
  case X86::ADD16ri8_DB:  OutMI.setOpcode(X86::OR16ri8); goto ReSimplify;
  case X86::ADD32ri8_DB:  OutMI.setOpcode(X86::OR32ri8); goto ReSimplify;
  case X86::ADD64ri8_DB:  OutMI.setOpcode(X86::OR64ri8); goto ReSimplify;

  // The assembler backend wants to see branches in their small form and relax
  // them to their large form.  The JIT can only handle the large form because
  // it does not do relaxation.  For now, translate the large form to the
  // small one here.
  case X86::JMP_4: OutMI.setOpcode(X86::JMP_1); break;
  case X86::JO_4:  OutMI.setOpcode(X86::JO_1); break;
  case X86::JNO_4: OutMI.setOpcode(X86::JNO_1); break;
  case X86::JB_4:  OutMI.setOpcode(X86::JB_1); break;
  case X86::JAE_4: OutMI.setOpcode(X86::JAE_1); break;
  case X86::JE_4:  OutMI.setOpcode(X86::JE_1); break;
  case X86::JNE_4: OutMI.setOpcode(X86::JNE_1); break;
  case X86::JBE_4: OutMI.setOpcode(X86::JBE_1); break;
  case X86::JA_4:  OutMI.setOpcode(X86::JA_1); break;
  case X86::JS_4:  OutMI.setOpcode(X86::JS_1); break;
  case X86::JNS_4: OutMI.setOpcode(X86::JNS_1); break;
  case X86::JP_4:  OutMI.setOpcode(X86::JP_1); break;
  case X86::JNP_4: OutMI.setOpcode(X86::JNP_1); break;
  case X86::JL_4:  OutMI.setOpcode(X86::JL_1); break;
  case X86::JGE_4: OutMI.setOpcode(X86::JGE_1); break;
  case X86::JLE_4: OutMI.setOpcode(X86::JLE_1); break;
  case X86::JG_4:  OutMI.setOpcode(X86::JG_1); break;

  // Atomic load and store require a separate pseudo-inst because Acquire
  // implies mayStore and Release implies mayLoad; fix these to regular MOV
  // instructions here
  case X86::ACQUIRE_MOV8rm:  OutMI.setOpcode(X86::MOV8rm); goto ReSimplify;
  case X86::ACQUIRE_MOV16rm: OutMI.setOpcode(X86::MOV16rm); goto ReSimplify;
  case X86::ACQUIRE_MOV32rm: OutMI.setOpcode(X86::MOV32rm); goto ReSimplify;
  case X86::ACQUIRE_MOV64rm: OutMI.setOpcode(X86::MOV64rm); goto ReSimplify;
  case X86::RELEASE_MOV8mr:  OutMI.setOpcode(X86::MOV8mr); goto ReSimplify;
  case X86::RELEASE_MOV16mr: OutMI.setOpcode(X86::MOV16mr); goto ReSimplify;
  case X86::RELEASE_MOV32mr: OutMI.setOpcode(X86::MOV32mr); goto ReSimplify;
  case X86::RELEASE_MOV64mr: OutMI.setOpcode(X86::MOV64mr); goto ReSimplify;

  // We don't currently select the correct instruction form for instructions
  // which have a short %eax, etc. form. Handle this by custom lowering, for
  // now.
  //
  // Note, we are currently not handling the following instructions:
  // MOV64ao8, MOV64o8a
  // XCHG16ar, XCHG32ar, XCHG64ar
  case X86::MOV8mr_NOREX:
  case X86::MOV8mr:     SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV8ao8); break;
  case X86::MOV8rm_NOREX:
  case X86::MOV8rm:     SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV8o8a); break;
  case X86::MOV16mr:    SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV16ao16); break;
  case X86::MOV16rm:    SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV16o16a); break;
  case X86::MOV32mr:    SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV32ao32); break;
  case X86::MOV32rm:    SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV32o32a); break;

  case X86::ADC8ri:     SimplifyShortImmForm(OutMI, X86::ADC8i8);    break;
  case X86::ADC16ri:    SimplifyShortImmForm(OutMI, X86::ADC16i16);  break;
  case X86::ADC32ri:    SimplifyShortImmForm(OutMI, X86::ADC32i32);  break;
  case X86::ADC64ri32:  SimplifyShortImmForm(OutMI, X86::ADC64i32);  break;
  case X86::ADD8ri:     SimplifyShortImmForm(OutMI, X86::ADD8i8);    break;
  case X86::ADD16ri:    SimplifyShortImmForm(OutMI, X86::ADD16i16);  break;
  case X86::ADD32ri:    SimplifyShortImmForm(OutMI, X86::ADD32i32);  break;
  case X86::ADD64ri32:  SimplifyShortImmForm(OutMI, X86::ADD64i32);  break;
  case X86::AND8ri:     SimplifyShortImmForm(OutMI, X86::AND8i8);    break;
  case X86::AND16ri:    SimplifyShortImmForm(OutMI, X86::AND16i16);  break;
  case X86::AND32ri:    SimplifyShortImmForm(OutMI, X86::AND32i32);  break;
  case X86::AND64ri32:  SimplifyShortImmForm(OutMI, X86::AND64i32);  break;
  case X86::CMP8ri:     SimplifyShortImmForm(OutMI, X86::CMP8i8);    break;
  case X86::CMP16ri:    SimplifyShortImmForm(OutMI, X86::CMP16i16);  break;
  case X86::CMP32ri:    SimplifyShortImmForm(OutMI, X86::CMP32i32);  break;
  case X86::CMP64ri32:  SimplifyShortImmForm(OutMI, X86::CMP64i32);  break;
  case X86::OR8ri:      SimplifyShortImmForm(OutMI, X86::OR8i8);     break;
  case X86::OR16ri:     SimplifyShortImmForm(OutMI, X86::OR16i16);   break;
  case X86::OR32ri:     SimplifyShortImmForm(OutMI, X86::OR32i32);   break;
  case X86::OR64ri32:   SimplifyShortImmForm(OutMI, X86::OR64i32);   break;
  case X86::SBB8ri:     SimplifyShortImmForm(OutMI, X86::SBB8i8);    break;
  case X86::SBB16ri:    SimplifyShortImmForm(OutMI, X86::SBB16i16);  break;
  case X86::SBB32ri:    SimplifyShortImmForm(OutMI, X86::SBB32i32);  break;
  case X86::SBB64ri32:  SimplifyShortImmForm(OutMI, X86::SBB64i32);  break;
  case X86::SUB8ri:     SimplifyShortImmForm(OutMI, X86::SUB8i8);    break;
  case X86::SUB16ri:    SimplifyShortImmForm(OutMI, X86::SUB16i16);  break;
  case X86::SUB32ri:    SimplifyShortImmForm(OutMI, X86::SUB32i32);  break;
  case X86::SUB64ri32:  SimplifyShortImmForm(OutMI, X86::SUB64i32);  break;
  case X86::TEST8ri:    SimplifyShortImmForm(OutMI, X86::TEST8i8);   break;
  case X86::TEST16ri:   SimplifyShortImmForm(OutMI, X86::TEST16i16); break;
  case X86::TEST32ri:   SimplifyShortImmForm(OutMI, X86::TEST32i32); break;
  case X86::TEST64ri32: SimplifyShortImmForm(OutMI, X86::TEST64i32); break;
  case X86::XOR8ri:     SimplifyShortImmForm(OutMI, X86::XOR8i8);    break;
  case X86::XOR16ri:    SimplifyShortImmForm(OutMI, X86::XOR16i16);  break;
  case X86::XOR32ri:    SimplifyShortImmForm(OutMI, X86::XOR32i32);  break;
  case X86::XOR64ri32:  SimplifyShortImmForm(OutMI, X86::XOR64i32);  break;

  // Try to shrink some forms of movsx.
  case X86::MOVSX16rr8:
  case X86::MOVSX32rr16:
  case X86::MOVSX64rr32:
    SimplifyMOVSX(OutMI);
    break;
  }
}
Example #17
0
void HexagonAsmPrinter::HexagonProcessInstruction(MCInst &Inst,
                                                  const MachineInstr &MI) {
  MCInst &MappedInst = static_cast <MCInst &>(Inst);
  const MCRegisterInfo *RI = OutStreamer->getContext().getRegisterInfo();

  switch (Inst.getOpcode()) {
  default: return;

  case Hexagon::A2_iconst: {
    Inst.setOpcode(Hexagon::A2_addi);
    MCOperand Reg = Inst.getOperand(0);
    MCOperand S16 = Inst.getOperand(1);
    HexagonMCInstrInfo::setMustNotExtend(*S16.getExpr());
    HexagonMCInstrInfo::setS23_2_reloc(*S16.getExpr());
    Inst.clear();
    Inst.addOperand(Reg);
    Inst.addOperand(MCOperand::createReg(Hexagon::R0));
    Inst.addOperand(S16);
    break;
  }

  // "$dst = CONST64(#$src1)",
  case Hexagon::CONST64:
    if (!OutStreamer->hasRawTextSupport()) {
      const MCOperand &Imm = MappedInst.getOperand(1);
      MCSectionSubPair Current = OutStreamer->getCurrentSection();

      MCSymbol *Sym = smallData(*this, MI, *OutStreamer, Imm, 8);

      OutStreamer->SwitchSection(Current.first, Current.second);
      MCInst TmpInst;
      MCOperand &Reg = MappedInst.getOperand(0);
      TmpInst.setOpcode(Hexagon::L2_loadrdgp);
      TmpInst.addOperand(Reg);
      TmpInst.addOperand(MCOperand::createExpr(
                         MCSymbolRefExpr::create(Sym, OutContext)));
      MappedInst = TmpInst;

    }
    break;
  case Hexagon::CONST32:
    if (!OutStreamer->hasRawTextSupport()) {
      MCOperand &Imm = MappedInst.getOperand(1);
      MCSectionSubPair Current = OutStreamer->getCurrentSection();
      MCSymbol *Sym = smallData(*this, MI, *OutStreamer, Imm, 4);
      OutStreamer->SwitchSection(Current.first, Current.second);
      MCInst TmpInst;
      MCOperand &Reg = MappedInst.getOperand(0);
      TmpInst.setOpcode(Hexagon::L2_loadrigp);
      TmpInst.addOperand(Reg);
      TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create(
          MCSymbolRefExpr::create(Sym, OutContext), OutContext)));
      MappedInst = TmpInst;
    }
    break;

  // C2_pxfer_map maps to C2_or instruction. Though, it's possible to use
  // C2_or during instruction selection itself but it results
  // into suboptimal code.
  case Hexagon::C2_pxfer_map: {
    MCOperand &Ps = Inst.getOperand(1);
    MappedInst.setOpcode(Hexagon::C2_or);
    MappedInst.addOperand(Ps);
    return;
  }

  // Vector reduce complex multiply by scalar, Rt & 1 map to :hi else :lo
  // The insn is mapped from the 4 operand to the 3 operand raw form taking
  // 3 register pairs.
  case Hexagon::M2_vrcmpys_acc_s1: {
    MCOperand &Rt = Inst.getOperand(3);
    assert (Rt.isReg() && "Expected register and none was found");
    unsigned Reg = RI->getEncodingValue(Rt.getReg());
    if (Reg & 1)
      MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h);
    else
      MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l);
    Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));
    return;
  }
  case Hexagon::M2_vrcmpys_s1: {
    MCOperand &Rt = Inst.getOperand(2);
    assert (Rt.isReg() && "Expected register and none was found");
    unsigned Reg = RI->getEncodingValue(Rt.getReg());
    if (Reg & 1)
      MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_h);
    else
      MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_l);
    Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));
    return;
  }

  case Hexagon::M2_vrcmpys_s1rp: {
    MCOperand &Rt = Inst.getOperand(2);
    assert (Rt.isReg() && "Expected register and none was found");
    unsigned Reg = RI->getEncodingValue(Rt.getReg());
    if (Reg & 1)
      MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_h);
    else
      MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_l);
    Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));
    return;
  }

  case Hexagon::A4_boundscheck: {
    MCOperand &Rs = Inst.getOperand(1);
    assert (Rs.isReg() && "Expected register and none was found");
    unsigned Reg = RI->getEncodingValue(Rs.getReg());
    if (Reg & 1) // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2
      MappedInst.setOpcode(Hexagon::A4_boundscheck_hi);
    else         // raw:lo
      MappedInst.setOpcode(Hexagon::A4_boundscheck_lo);
    Rs.setReg(getHexagonRegisterPair(Rs.getReg(), RI));
    return;
  }
  case Hexagon::S5_asrhub_rnd_sat_goodsyntax: {
    MCOperand &MO = MappedInst.getOperand(2);
    int64_t Imm;
    MCExpr const *Expr = MO.getExpr();
    bool Success = Expr->evaluateAsAbsolute(Imm);
    assert (Success && "Expected immediate and none was found");
    (void)Success;
    MCInst TmpInst;
    if (Imm == 0) {
      TmpInst.setOpcode(Hexagon::S2_vsathub);
      TmpInst.addOperand(MappedInst.getOperand(0));
      TmpInst.addOperand(MappedInst.getOperand(1));
      MappedInst = TmpInst;
      return;
    }
    TmpInst.setOpcode(Hexagon::S5_asrhub_rnd_sat);
    TmpInst.addOperand(MappedInst.getOperand(0));
    TmpInst.addOperand(MappedInst.getOperand(1));
    const MCExpr *One = MCConstantExpr::create(1, OutContext);
    const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext);
    TmpInst.addOperand(
        MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext)));
    MappedInst = TmpInst;
    return;
  }
  case Hexagon::S5_vasrhrnd_goodsyntax:
  case Hexagon::S2_asr_i_p_rnd_goodsyntax: {
    MCOperand &MO2 = MappedInst.getOperand(2);
    MCExpr const *Expr = MO2.getExpr();
    int64_t Imm;
    bool Success = Expr->evaluateAsAbsolute(Imm);
    assert (Success && "Expected immediate and none was found");
    (void)Success;
    MCInst TmpInst;
    if (Imm == 0) {
      TmpInst.setOpcode(Hexagon::A2_combinew);
      TmpInst.addOperand(MappedInst.getOperand(0));
      MCOperand &MO1 = MappedInst.getOperand(1);
      unsigned High = RI->getSubReg(MO1.getReg(), Hexagon::subreg_hireg);
      unsigned Low = RI->getSubReg(MO1.getReg(), Hexagon::subreg_loreg);
      // Add a new operand for the second register in the pair.
      TmpInst.addOperand(MCOperand::createReg(High));
      TmpInst.addOperand(MCOperand::createReg(Low));
      MappedInst = TmpInst;
      return;
    }

    if (Inst.getOpcode() == Hexagon::S2_asr_i_p_rnd_goodsyntax)
      TmpInst.setOpcode(Hexagon::S2_asr_i_p_rnd);
    else
      TmpInst.setOpcode(Hexagon::S5_vasrhrnd);
    TmpInst.addOperand(MappedInst.getOperand(0));
    TmpInst.addOperand(MappedInst.getOperand(1));
    const MCExpr *One = MCConstantExpr::create(1, OutContext);
    const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext);
    TmpInst.addOperand(
        MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext)));
    MappedInst = TmpInst;
    return;
  }
  // if ("#u5==0") Assembler mapped to: "Rd=Rs"; else Rd=asr(Rs,#u5-1):rnd
  case Hexagon::S2_asr_i_r_rnd_goodsyntax: {
    MCOperand &MO = Inst.getOperand(2);
    MCExpr const *Expr = MO.getExpr();
    int64_t Imm;
    bool Success = Expr->evaluateAsAbsolute(Imm);
    assert (Success && "Expected immediate and none was found");
    (void)Success;
    MCInst TmpInst;
    if (Imm == 0) {
      TmpInst.setOpcode(Hexagon::A2_tfr);
      TmpInst.addOperand(MappedInst.getOperand(0));
      TmpInst.addOperand(MappedInst.getOperand(1));
      MappedInst = TmpInst;
      return;
    }
    TmpInst.setOpcode(Hexagon::S2_asr_i_r_rnd);
    TmpInst.addOperand(MappedInst.getOperand(0));
    TmpInst.addOperand(MappedInst.getOperand(1));
    const MCExpr *One = MCConstantExpr::create(1, OutContext);
    const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext);
    TmpInst.addOperand(
        MCOperand::createExpr(HexagonMCExpr::create(Sub, OutContext)));
    MappedInst = TmpInst;
    return;
  }

  // Translate a "$Rdd = #imm" to "$Rdd = combine(#[-1,0], #imm)"
  case Hexagon::A2_tfrpi: {
    MCInst TmpInst;
    MCOperand &Rdd = MappedInst.getOperand(0);
    MCOperand &MO = MappedInst.getOperand(1);

    TmpInst.setOpcode(Hexagon::A2_combineii);
    TmpInst.addOperand(Rdd);
    int64_t Imm;
    bool Success = MO.getExpr()->evaluateAsAbsolute(Imm);
    if (Success && Imm < 0) {
      const MCExpr *MOne = MCConstantExpr::create(-1, OutContext);
      TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create(MOne, OutContext)));
    } else {
      const MCExpr *Zero = MCConstantExpr::create(0, OutContext);
      TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create(Zero, OutContext)));
    }
    TmpInst.addOperand(MO);
    MappedInst = TmpInst;
    return;
  }
  // Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)"
  case Hexagon::A2_tfrp: {
    MCOperand &MO = MappedInst.getOperand(1);
    unsigned High = RI->getSubReg(MO.getReg(), Hexagon::subreg_hireg);
    unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::subreg_loreg);
    MO.setReg(High);
    // Add a new operand for the second register in the pair.
    MappedInst.addOperand(MCOperand::createReg(Low));
    MappedInst.setOpcode(Hexagon::A2_combinew);
    return;
  }

  case Hexagon::A2_tfrpt:
  case Hexagon::A2_tfrpf: {
    MCOperand &MO = MappedInst.getOperand(2);
    unsigned High = RI->getSubReg(MO.getReg(), Hexagon::subreg_hireg);
    unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::subreg_loreg);
    MO.setReg(High);
    // Add a new operand for the second register in the pair.
    MappedInst.addOperand(MCOperand::createReg(Low));
    MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt)
                          ? Hexagon::C2_ccombinewt
                          : Hexagon::C2_ccombinewf);
    return;
  }
  case Hexagon::A2_tfrptnew:
  case Hexagon::A2_tfrpfnew: {
    MCOperand &MO = MappedInst.getOperand(2);
    unsigned High = RI->getSubReg(MO.getReg(), Hexagon::subreg_hireg);
    unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::subreg_loreg);
    MO.setReg(High);
    // Add a new operand for the second register in the pair.
    MappedInst.addOperand(MCOperand::createReg(Low));
    MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrptnew)
                          ? Hexagon::C2_ccombinewnewt
                          : Hexagon::C2_ccombinewnewf);
    return;
  }

  case Hexagon::M2_mpysmi: {
    MCOperand &Imm = MappedInst.getOperand(2);
    MCExpr const *Expr = Imm.getExpr();
    int64_t Value;
    bool Success = Expr->evaluateAsAbsolute(Value);
    assert(Success);
    (void)Success;
    if (Value < 0 && Value > -256) {
      MappedInst.setOpcode(Hexagon::M2_mpysin);
      Imm.setExpr(HexagonMCExpr::create(
          MCUnaryExpr::createMinus(Expr, OutContext), OutContext));
    } else
      MappedInst.setOpcode(Hexagon::M2_mpysip);
    return;
  }

  case Hexagon::A2_addsp: {
    MCOperand &Rt = Inst.getOperand(1);
    assert (Rt.isReg() && "Expected register and none was found");
    unsigned Reg = RI->getEncodingValue(Rt.getReg());
    if (Reg & 1)
      MappedInst.setOpcode(Hexagon::A2_addsph);
    else
      MappedInst.setOpcode(Hexagon::A2_addspl);
    Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));
    return;
  }
  case Hexagon::HEXAGON_V6_vd0_pseudo:
  case Hexagon::HEXAGON_V6_vd0_pseudo_128B: {
    MCInst TmpInst;
    assert (Inst.getOperand(0).isReg() &&
            "Expected register and none was found");

    TmpInst.setOpcode(Hexagon::V6_vxor);
    TmpInst.addOperand(Inst.getOperand(0));
    TmpInst.addOperand(Inst.getOperand(0));
    TmpInst.addOperand(Inst.getOperand(0));
    MappedInst = TmpInst;
    return;
  }

  }
}
void WebAssemblyMCCodeEmitter::encodeInstruction(
    const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups,
    const MCSubtargetInfo &STI) const {
  uint64_t Start = OS.tell();

  uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI);
  assert(Binary < UINT8_MAX && "Multi-byte opcodes not supported yet");
  OS << uint8_t(Binary);

  // For br_table instructions, encode the size of the table. In the MCInst,
  // there's an index operand, one operand for each table entry, and the
  // default operand.
  if (MI.getOpcode() == WebAssembly::BR_TABLE_I32 ||
      MI.getOpcode() == WebAssembly::BR_TABLE_I64)
    encodeULEB128(MI.getNumOperands() - 2, OS);

  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
  for (unsigned i = 0, e = MI.getNumOperands(); i < e; ++i) {
    const MCOperand &MO = MI.getOperand(i);
    if (MO.isReg()) {
      /* nothing to encode */
    } else if (MO.isImm()) {
      if (i < Desc.getNumOperands()) {
        assert(Desc.TSFlags == 0 &&
               "WebAssembly non-variable_ops don't use TSFlags");
        const MCOperandInfo &Info = Desc.OpInfo[i];
        if (Info.OperandType == WebAssembly::OPERAND_I32IMM) {
          encodeSLEB128(int32_t(MO.getImm()), OS);
        } else if (Info.OperandType == WebAssembly::OPERAND_I64IMM) {
          encodeSLEB128(int64_t(MO.getImm()), OS);
        } else if (Info.OperandType == WebAssembly::OPERAND_GLOBAL) {
          llvm_unreachable("wasm globals should only be accessed symbolicly");
        } else if (Info.OperandType == WebAssembly::OPERAND_SIGNATURE) {
          encodeSLEB128(int64_t(MO.getImm()), OS);
        } else {
          encodeULEB128(uint64_t(MO.getImm()), OS);
        }
      } else {
        assert(Desc.TSFlags == (WebAssemblyII::VariableOpIsImmediate |
                                WebAssemblyII::VariableOpImmediateIsLabel));
        encodeULEB128(uint64_t(MO.getImm()), OS);
      }
    } else if (MO.isFPImm()) {
      assert(i < Desc.getNumOperands() &&
             "Unexpected floating-point immediate as a non-fixed operand");
      assert(Desc.TSFlags == 0 &&
             "WebAssembly variable_ops floating point ops don't use TSFlags");
      const MCOperandInfo &Info = Desc.OpInfo[i];
      if (Info.OperandType == WebAssembly::OPERAND_F32IMM) {
        // TODO: MC converts all floating point immediate operands to double.
        // This is fine for numeric values, but may cause NaNs to change bits.
        float f = float(MO.getFPImm());
        support::endian::Writer<support::little>(OS).write<float>(f);
      } else {
        assert(Info.OperandType == WebAssembly::OPERAND_F64IMM);
        double d = MO.getFPImm();
        support::endian::Writer<support::little>(OS).write<double>(d);
      }
    } else if (MO.isExpr()) {
      const MCOperandInfo &Info = Desc.OpInfo[i];
      llvm::MCFixupKind FixupKind;
      size_t PaddedSize;
      if (Info.OperandType == WebAssembly::OPERAND_I32IMM) {
        FixupKind = MCFixupKind(WebAssembly::fixup_code_sleb128_i32);
        PaddedSize = 5;
      } else if (Info.OperandType == WebAssembly::OPERAND_I64IMM) {
        FixupKind = MCFixupKind(WebAssembly::fixup_code_sleb128_i64);
        PaddedSize = 10;
      } else if (Info.OperandType == WebAssembly::OPERAND_FUNCTION32 ||
                 Info.OperandType == WebAssembly::OPERAND_OFFSET32 ||
                 Info.OperandType == WebAssembly::OPERAND_TYPEINDEX) {
        FixupKind = MCFixupKind(WebAssembly::fixup_code_uleb128_i32);
        PaddedSize = 5;
      } else if (Info.OperandType == WebAssembly::OPERAND_GLOBAL) {
        FixupKind = MCFixupKind(WebAssembly::fixup_code_global_index);
        PaddedSize = 5;
      } else {
        llvm_unreachable("unexpected symbolic operand kind");
      }
      Fixups.push_back(MCFixup::create(
          OS.tell() - Start, MO.getExpr(),
          FixupKind, MI.getLoc()));
      ++MCNumFixups;
      encodeULEB128(0, OS, PaddedSize - 1);
    } else {
      llvm_unreachable("unexpected operand kind");
    }
  }

  ++MCNumEmitted; // Keep track of the # of mi's emitted.
}
Example #19
0
static void jl_dump_asm_internal(
        uintptr_t Fptr, size_t Fsize, int64_t slide,
        const object::ObjectFile *object,
        DIContext *di_ctx,
        raw_ostream &rstream,
        const char* asm_variant)
{
    // GC safe
    // Get the host information
    std::string TripleName = sys::getDefaultTargetTriple();
    Triple TheTriple(Triple::normalize(TripleName));

    const auto &target = jl_get_llvm_disasm_target();
    const auto &cpu = target.first;
    const auto &features = target.second;

    std::string err;
    const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, err);

    // Set up required helpers and streamer
    std::unique_ptr<MCStreamer> Streamer;
    SourceMgr SrcMgr;

    std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*TheTarget->createMCRegInfo(TripleName),TripleName));
    assert(MAI && "Unable to create target asm info!");

    std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
    assert(MRI && "Unable to create target register info!");

    std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
    MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr);
    MOFI->InitMCObjectFileInfo(TheTriple, /* PIC */ false, Ctx);

    // Set up Subtarget and Disassembler
    std::unique_ptr<MCSubtargetInfo>
        STI(TheTarget->createMCSubtargetInfo(TripleName, cpu, features));
    std::unique_ptr<MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI, Ctx));
    if (!DisAsm) {
        jl_printf(JL_STDERR, "ERROR: no disassembler for target %s\n",
                  TripleName.c_str());
        return;
    }
    unsigned OutputAsmVariant = 0; // ATT or Intel-style assembly

    if (strcmp(asm_variant, "intel")==0) {
        OutputAsmVariant = 1;
    }
    bool ShowEncoding = false;

    std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
    std::unique_ptr<MCInstrAnalysis>
        MCIA(TheTarget->createMCInstrAnalysis(MCII.get()));
    MCInstPrinter *IP =
        TheTarget->createMCInstPrinter(TheTriple, OutputAsmVariant, *MAI, *MCII, *MRI);
    //IP->setPrintImmHex(true); // prefer hex or decimal immediates
    MCCodeEmitter *CE = 0;
    MCAsmBackend *MAB = 0;
    if (ShowEncoding) {
        CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
        MCTargetOptions Options;
        MAB = TheTarget->createMCAsmBackend(*STI, *MRI, Options);
    }

    // createAsmStreamer expects a unique_ptr to a formatted stream, which means
    // it will destruct the stream when it is done. We cannot have this, so we
    // start out with a raw stream, and create formatted stream from it here.
    // LLVM will desctruct the formatted stream, and we keep the raw stream.
    auto ustream = llvm::make_unique<formatted_raw_ostream>(rstream);
    Streamer.reset(TheTarget->createAsmStreamer(Ctx, std::move(ustream), /*asmverbose*/true,
                                                /*useDwarfDirectory*/ true,
                                                IP, CE, MAB, /*ShowInst*/ false));
    Streamer->InitSections(true);

    // Make the MemoryObject wrapper
    ArrayRef<uint8_t> memoryObject(const_cast<uint8_t*>((const uint8_t*)Fptr),Fsize);
    SymbolTable DisInfo(Ctx, object, slide, memoryObject);

    DILineInfoTable di_lineinfo;
    if (di_ctx)
        di_lineinfo = di_ctx->getLineInfoForAddressRange(Fptr+slide, Fsize);
    if (!di_lineinfo.empty()) {
        auto cur_addr = di_lineinfo[0].first;
        auto nlineinfo = di_lineinfo.size();
        // filter out line infos that doesn't contain any instructions
        unsigned j = 0;
        for (unsigned i = 1; i < nlineinfo; i++) {
            auto &info = di_lineinfo[i];
            if (info.first != cur_addr)
                j++;
            cur_addr = info.first;
            if (i != j) {
                di_lineinfo[j] = std::move(info);
            }
        }
        if (j + 1 < nlineinfo) {
            di_lineinfo.resize(j + 1);
        }
    }

    // Take two passes: In the first pass we record all branch labels,
    // in the second we actually perform the output
    for (int pass = 0; pass < 2; ++ pass) {
        DisInfo.setPass(pass);
        if (pass != 0) {
            // Switch to symbolic disassembly. We cannot do this
            // before the first pass, because this changes branch
            // targets from immediate values (constants) to
            // expressions, which are not handled correctly by
            // MCIA->evaluateBranch. (It should be possible to rewrite
            // this routine to handle this case correctly as well.)
            // Could add OpInfoLookup here
            DisAsm->setSymbolizer(std::unique_ptr<MCSymbolizer>(new MCExternalSymbolizer(
                        Ctx,
                        std::unique_ptr<MCRelocationInfo>(new MCRelocationInfo(Ctx)),
                        OpInfoLookup,
                        SymbolLookup,
                        &DisInfo)));
        }

        uint64_t nextLineAddr = -1;
        DILineInfoTable::iterator di_lineIter = di_lineinfo.begin();
        DILineInfoTable::iterator di_lineEnd = di_lineinfo.end();
        DILineInfoPrinter dbgctx{';', true};
        if (pass != 0) {
            if (di_ctx && di_lineIter != di_lineEnd) {
                // Set up the line info
                nextLineAddr = di_lineIter->first;
                if (nextLineAddr != (uint64_t)(Fptr + slide)) {
                    std::string buf;
                    dbgctx.emit_lineinfo(buf, di_lineIter->second);
                    if (!buf.empty()) {
                        Streamer->EmitRawText(buf);
                    }
                }
            }
        }

        uint64_t Index = 0;
        uint64_t insSize = 0;

        // Do the disassembly
        for (Index = 0; Index < Fsize; Index += insSize) {

            if (pass != 0 && nextLineAddr != (uint64_t)-1 && Index + Fptr + slide == nextLineAddr) {
                if (di_ctx) {
                    std::string buf;
                    DILineInfoSpecifier infoSpec(DILineInfoSpecifier::FileLineInfoKind::Default,
                                                 DILineInfoSpecifier::FunctionNameKind::ShortName);
                    DIInliningInfo dbg = di_ctx->getInliningInfoForAddress(Index + Fptr + slide, infoSpec);
                    if (dbg.getNumberOfFrames()) {
                        dbgctx.emit_lineinfo(buf, dbg);
                    }
                    else {
                        dbgctx.emit_lineinfo(buf, di_lineIter->second);
                    }
                    if (!buf.empty())
                        Streamer->EmitRawText(buf);
                    nextLineAddr = (++di_lineIter)->first;
                }
            }

            DisInfo.setIP(Fptr+Index);
            if (pass != 0) {
                // Uncomment this to output addresses for all instructions
                // stream << Index << ": ";
                MCSymbol *symbol = DisInfo.lookupSymbol(Fptr+Index);
                if (symbol)
                    Streamer->EmitLabel(symbol);
            }

            MCInst Inst;
            MCDisassembler::DecodeStatus S;
            FuncMCView view = memoryObject.slice(Index);
            S = DisAsm->getInstruction(Inst, insSize, view, 0,
                                      /*VStream*/ nulls(),
                                      /*CStream*/ pass != 0 ? Streamer->GetCommentOS() : nulls());
            if (pass != 0 && Streamer->GetCommentOS().tell() > 0)
                Streamer->GetCommentOS() << '\n';
            switch (S) {
            case MCDisassembler::Fail:
                if (insSize == 0) // skip illegible bytes
#if defined(_CPU_PPC_) || defined(_CPU_PPC64_) || defined(_CPU_ARM_) || defined(_CPU_AARCH64_)
                    insSize = 4; // instructions are always 4 bytes
#else
                    insSize = 1; // attempt to slide 1 byte forward
#endif
                if (pass != 0) {
                    std::ostringstream buf;
                    if (insSize == 4)
                        buf << "\t.long\t0x" << std::hex
                            << std::setfill('0') << std::setw(8)
                            << *(uint32_t*)(Fptr+Index);
                    else
                        for (uint64_t i=0; i<insSize; ++i)
                            buf << "\t.byte\t0x" << std::hex
                                << std::setfill('0') << std::setw(2)
                                << (int)*(uint8_t*)(Fptr+Index+i);
                    Streamer->EmitRawText(StringRef(buf.str()));
                }
                break;

            case MCDisassembler::SoftFail:
                if (pass != 0)
                    Streamer->EmitRawText(StringRef("potentially undefined instruction encoding:"));
                // Fall through

            case MCDisassembler::Success:
                if (pass == 0) {
                    // Pass 0: Record all branch target references
                    if (MCIA) {
                        const MCInstrDesc &opcode = MCII->get(Inst.getOpcode());
                        if (opcode.isBranch() || opcode.isCall()) {
                            uint64_t addr;
                            if (MCIA->evaluateBranch(Inst, Fptr + Index, insSize, addr))
                                DisInfo.insertAddress(addr);
                        }
                    }
                }
                else {
                    // Pass 1: Output instruction
                    if (pass != 0) {
                        // attempt to symbolicate any immediate operands
                        const MCInstrDesc &opinfo = MCII->get(Inst.getOpcode());
                        for (unsigned Op = 0; Op < opinfo.NumOperands; Op++) {
                            const MCOperand &OpI = Inst.getOperand(Op);
                            if (OpI.isImm()) {
                                int64_t imm = OpI.getImm();
                                if (opinfo.OpInfo[Op].OperandType == MCOI::OPERAND_PCREL)
                                    imm += Fptr + Index;
                                const char *name = DisInfo.lookupSymbolName(imm);
                                if (name)
                                    Streamer->AddComment(name);
                            }
                        }
                    }
                    Streamer->EmitInstruction(Inst, *STI);
                }
                break;
            }
        }

        DisInfo.setIP(Fptr);
        if (pass == 0)
            DisInfo.createSymbols();

        if (pass != 0 && di_ctx) {
            std::string buf;
            dbgctx.emit_finish(buf);
            if (!buf.empty()) {
                Streamer->EmitRawText(buf);
            }
        }
    }
}
bool RISCVMCAsmBackend::mayNeedRelaxation(const MCInst &Inst) const {
  return getRelaxedOpcode(Inst.getOpcode()) != 0;
}
Example #21
0
// Note that MIMG format provides no information about VADDR size.
// Consequently, decoded instructions always show address
// as if it has 1 dword, which could be not really so.
DecodeStatus AMDGPUDisassembler::convertMIMGInst(MCInst &MI) const {
  int VDstIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
                                           AMDGPU::OpName::vdst);

  int VDataIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
                                            AMDGPU::OpName::vdata);

  int DMaskIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
                                            AMDGPU::OpName::dmask);

  int TFEIdx   = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
                                            AMDGPU::OpName::tfe);

  assert(VDataIdx != -1);
  assert(DMaskIdx != -1);
  assert(TFEIdx != -1);

  bool isAtomic = (VDstIdx != -1);

  unsigned DMask = MI.getOperand(DMaskIdx).getImm() & 0xf;
  if (DMask == 0)
    return MCDisassembler::Success;

  unsigned DstSize = countPopulation(DMask);
  if (DstSize == 1)
    return MCDisassembler::Success;

  bool D16 = MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::D16;
  if (D16 && AMDGPU::hasPackedD16(STI)) {
    DstSize = (DstSize + 1) / 2;
  }

  // FIXME: Add tfe support
  if (MI.getOperand(TFEIdx).getImm())
    return MCDisassembler::Success;

  int NewOpcode = -1;

  if (isAtomic) {
    if (DMask == 0x1 || DMask == 0x3 || DMask == 0xF) {
      NewOpcode = AMDGPU::getMaskedMIMGAtomicOp(*MCII, MI.getOpcode(), DstSize);
    }
    if (NewOpcode == -1) return MCDisassembler::Success;
  } else {
    NewOpcode = AMDGPU::getMaskedMIMGOp(*MCII, MI.getOpcode(), DstSize);
    assert(NewOpcode != -1 && "could not find matching mimg channel instruction");
  }

  auto RCID = MCII->get(NewOpcode).OpInfo[VDataIdx].RegClass;

  // Get first subregister of VData
  unsigned Vdata0 = MI.getOperand(VDataIdx).getReg();
  unsigned VdataSub0 = MRI.getSubReg(Vdata0, AMDGPU::sub0);
  Vdata0 = (VdataSub0 != 0)? VdataSub0 : Vdata0;

  // Widen the register to the correct number of enabled channels.
  auto NewVdata = MRI.getMatchingSuperReg(Vdata0, AMDGPU::sub0,
                                          &MRI.getRegClass(RCID));
  if (NewVdata == AMDGPU::NoRegister) {
    // It's possible to encode this such that the low register + enabled
    // components exceeds the register count.
    return MCDisassembler::Success;
  }

  MI.setOpcode(NewOpcode);
  // vaddr will be always appear as a single VGPR. This will look different than
  // how it is usually emitted because the number of register components is not
  // in the instruction encoding.
  MI.getOperand(VDataIdx) = MCOperand::createReg(NewVdata);

  if (isAtomic) {
    // Atomic operations have an additional operand (a copy of data)
    MI.getOperand(VDstIdx) = MCOperand::createReg(NewVdata);
  }

  return MCDisassembler::Success;
}
Example #22
0
DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
                                                ArrayRef<uint8_t> Bytes_,
                                                uint64_t Address,
                                                raw_ostream &WS,
                                                raw_ostream &CS) const {
  CommentStream = &CS;
  bool IsSDWA = false;

  // ToDo: AMDGPUDisassembler supports only VI ISA.
  if (!STI.getFeatureBits()[AMDGPU::FeatureGCN3Encoding])
    report_fatal_error("Disassembly not yet supported for subtarget");

  const unsigned MaxInstBytesNum = (std::min)((size_t)8, Bytes_.size());
  Bytes = Bytes_.slice(0, MaxInstBytesNum);

  DecodeStatus Res = MCDisassembler::Fail;
  do {
    // ToDo: better to switch encoding length using some bit predicate
    // but it is unknown yet, so try all we can

    // Try to decode DPP and SDWA first to solve conflict with VOP1 and VOP2
    // encodings
    if (Bytes.size() >= 8) {
      const uint64_t QW = eatBytes<uint64_t>(Bytes);
      Res = tryDecodeInst(DecoderTableDPP64, MI, QW, Address);
      if (Res) break;

      Res = tryDecodeInst(DecoderTableSDWA64, MI, QW, Address);
      if (Res) { IsSDWA = true;  break; }

      Res = tryDecodeInst(DecoderTableSDWA964, MI, QW, Address);
      if (Res) { IsSDWA = true;  break; }

      if (STI.getFeatureBits()[AMDGPU::FeatureUnpackedD16VMem]) {
        Res = tryDecodeInst(DecoderTableGFX80_UNPACKED64, MI, QW, Address);
        if (Res) break;
      }
    }

    // Reinitialize Bytes as DPP64 could have eaten too much
    Bytes = Bytes_.slice(0, MaxInstBytesNum);

    // Try decode 32-bit instruction
    if (Bytes.size() < 4) break;
    const uint32_t DW = eatBytes<uint32_t>(Bytes);
    Res = tryDecodeInst(DecoderTableVI32, MI, DW, Address);
    if (Res) break;

    Res = tryDecodeInst(DecoderTableAMDGPU32, MI, DW, Address);
    if (Res) break;

    Res = tryDecodeInst(DecoderTableGFX932, MI, DW, Address);
    if (Res) break;

    if (Bytes.size() < 4) break;
    const uint64_t QW = ((uint64_t)eatBytes<uint32_t>(Bytes) << 32) | DW;
    Res = tryDecodeInst(DecoderTableVI64, MI, QW, Address);
    if (Res) break;

    Res = tryDecodeInst(DecoderTableAMDGPU64, MI, QW, Address);
    if (Res) break;

    Res = tryDecodeInst(DecoderTableGFX964, MI, QW, Address);
  } while (false);

  if (Res && (MI.getOpcode() == AMDGPU::V_MAC_F32_e64_vi ||
              MI.getOpcode() == AMDGPU::V_MAC_F32_e64_si ||
              MI.getOpcode() == AMDGPU::V_MAC_F16_e64_vi)) {
    // Insert dummy unused src2_modifiers.
    insertNamedMCOperand(MI, MCOperand::createImm(0),
                         AMDGPU::OpName::src2_modifiers);
  }

  if (Res && (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::MIMG)) {
    Res = convertMIMGInst(MI);
  }

  if (Res && IsSDWA)
    Res = convertSDWAInst(MI);

  Size = Res ? (MaxInstBytesNum - Bytes.size()) : 0;
  return Res;
}
Example #23
0
bool ARMAsmBackend::mayNeedRelaxation(const MCInst &Inst,
                                      const MCSubtargetInfo &STI) const {
  if (getRelaxedOpcode(Inst.getOpcode(), STI) != Inst.getOpcode())
    return true;
  return false;
}
Example #24
0
/*
 * Disassemble a function, using the LLVM MC disassembler.
 *
 * See also:
 * - http://blog.llvm.org/2010/01/x86-disassembler.html
 * - http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html
 */
static size_t
disassemble(const void* func, llvm::raw_ostream & Out)
{
   using namespace llvm;

   const uint8_t *bytes = (const uint8_t *)func;

   /*
    * Limit disassembly to this extent
    */
   const uint64_t extent = 96 * 1024;

   uint64_t max_pc = 0;

   /*
    * Initialize all used objects.
    */

   std::string Triple = sys::getDefaultTargetTriple();

   std::string Error;
   const Target *T = TargetRegistry::lookupTarget(Triple, Error);

#if HAVE_LLVM >= 0x0304
   OwningPtr<const MCAsmInfo> AsmInfo(T->createMCAsmInfo(*T->createMCRegInfo(Triple), Triple));
#else
   OwningPtr<const MCAsmInfo> AsmInfo(T->createMCAsmInfo(Triple));
#endif

   if (!AsmInfo) {
      Out << "error: no assembly info for target " << Triple << "\n";
      Out.flush();
      return 0;
   }

   unsigned int AsmPrinterVariant = AsmInfo->getAssemblerDialect();

   OwningPtr<const MCRegisterInfo> MRI(T->createMCRegInfo(Triple));
   if (!MRI) {
      Out << "error: no register info for target " << Triple.c_str() << "\n";
      Out.flush();
      return 0;
   }

   OwningPtr<const MCInstrInfo> MII(T->createMCInstrInfo());
   if (!MII) {
      Out << "error: no instruction info for target " << Triple.c_str() << "\n";
      Out.flush();
      return 0;
   }

#if HAVE_LLVM >= 0x0305
   OwningPtr<const MCSubtargetInfo> STI(T->createMCSubtargetInfo(Triple, sys::getHostCPUName(), ""));
   OwningPtr<MCContext> MCCtx(new MCContext(AsmInfo.get(), MRI.get(), 0));
   OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler(*STI, *MCCtx));
#else
   OwningPtr<const MCSubtargetInfo> STI(T->createMCSubtargetInfo(Triple, sys::getHostCPUName(), ""));
   OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler(*STI));
#endif
   if (!DisAsm) {
      Out << "error: no disassembler for target " << Triple << "\n";
      Out.flush();
      return 0;
   }


   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI));
   if (!Printer) {
      Out << "error: no instruction printer for target " << Triple.c_str() << "\n";
      Out.flush();
      return 0;
   }

   TargetOptions options;
#if defined(DEBUG)
   options.JITEmitDebugInfo = true;
#endif
#if defined(PIPE_ARCH_X86)
   options.StackAlignmentOverride = 4;
#endif
#if defined(DEBUG) || defined(PROFILE)
   options.NoFramePointerElim = true;
#endif
   OwningPtr<TargetMachine> TM(T->createTargetMachine(Triple, sys::getHostCPUName(), "", options));

#if HAVE_LLVM >= 0x0306
   const TargetInstrInfo *TII = TM->getSubtargetImpl()->getInstrInfo();
#else
   const TargetInstrInfo *TII = TM->getInstrInfo();
#endif

   /*
    * Wrap the data in a MemoryObject
    */
   BufferMemoryObject memoryObject((const uint8_t *)bytes, extent);

   uint64_t pc;
   pc = 0;
   while (true) {
      MCInst Inst;
      uint64_t Size;

      /*
       * Print address.  We use addresses relative to the start of the function,
       * so that between runs.
       */

      Out << llvm::format("%6lu:\t", (unsigned long)pc);

      if (!DisAsm->getInstruction(Inst, Size, memoryObject,
                                 pc,
				  nulls(), nulls())) {
         Out << "invalid";
         pc += 1;
      }

      /*
       * Output the bytes in hexidecimal format.
       */

      if (0) {
         unsigned i;
         for (i = 0; i < Size; ++i) {
            Out << llvm::format("%02x ", ((const uint8_t*)bytes)[pc + i]);
         }
         for (; i < 16; ++i) {
            Out << "   ";
         }
      }

      /*
       * Print the instruction.
       */
      Printer->printInst(&Inst, Out, "");

      /*
       * Advance.
       */

      pc += Size;

      const MCInstrDesc &TID = TII->get(Inst.getOpcode());

      /*
       * Keep track of forward jumps to a nearby address.
       */

      if (TID.isBranch()) {
         for (unsigned i = 0; i < Inst.getNumOperands(); ++i) {
            const MCOperand &operand = Inst.getOperand(i);
            if (operand.isImm()) {
               uint64_t jump;

               /*
                * FIXME: Handle both relative and absolute addresses correctly.
                * EDInstInfo actually has this info, but operandTypes and
                * operandFlags enums are not exposed in the public interface.
                */

               if (1) {
                  /*
                   * PC relative addr.
                   */

                  jump = pc + operand.getImm();
               } else {
                  /*
                   * Absolute addr.
                   */

                  jump = (uint64_t)operand.getImm();
               }

               /*
                * Output the address relative to the function start, given
                * that MC will print the addresses relative the current pc.
                */
               Out << "\t\t; " << jump;

               /*
                * Ignore far jumps given it could be actually a tail return to
                * a random address.
                */

               if (jump > max_pc &&
                   jump < extent) {
                  max_pc = jump;
               }
            }
         }
      }

      Out << "\n";

      /*
       * Stop disassembling on return statements, if there is no record of a
       * jump to a successive address.
       */

      if (TID.isReturn()) {
         if (pc > max_pc) {
            break;
         }
      }
   }

   /*
    * Print GDB command, useful to verify output.
    */

   if (0) {
      _debug_printf("disassemble %p %p\n", bytes, bytes + pc);
   }

   Out << "\n";
   Out.flush();

   return pc;
}
void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
  OutMI.setOpcode(MI->getOpcode());

  for (const MachineOperand &MO : MI->operands())
    if (auto MaybeMCOp = LowerMachineOperand(MI, MO))
      OutMI.addOperand(MaybeMCOp.getValue());

  // Handle a few special cases to eliminate operand modifiers.
ReSimplify:
  switch (OutMI.getOpcode()) {
  case X86::LEA64_32r:
  case X86::LEA64r:
  case X86::LEA16r:
  case X86::LEA32r:
    // LEA should have a segment register, but it must be empty.
    assert(OutMI.getNumOperands() == 1+X86::AddrNumOperands &&
           "Unexpected # of LEA operands");
    assert(OutMI.getOperand(1+X86::AddrSegmentReg).getReg() == 0 &&
           "LEA has segment specified!");
    break;

  case X86::MOV32ri64:
    OutMI.setOpcode(X86::MOV32ri);
    break;

  // Commute operands to get a smaller encoding by using VEX.R instead of VEX.B
  // if one of the registers is extended, but other isn't.
  case X86::VMOVAPDrr:
  case X86::VMOVAPDYrr:
  case X86::VMOVAPSrr:
  case X86::VMOVAPSYrr:
  case X86::VMOVDQArr:
  case X86::VMOVDQAYrr:
  case X86::VMOVDQUrr:
  case X86::VMOVDQUYrr:
  case X86::VMOVUPDrr:
  case X86::VMOVUPDYrr:
  case X86::VMOVUPSrr:
  case X86::VMOVUPSYrr: {
    if (!X86II::isX86_64ExtendedReg(OutMI.getOperand(0).getReg()) &&
        X86II::isX86_64ExtendedReg(OutMI.getOperand(1).getReg())) {
      unsigned NewOpc;
      switch (OutMI.getOpcode()) {
      default: llvm_unreachable("Invalid opcode");
      case X86::VMOVAPDrr:  NewOpc = X86::VMOVAPDrr_REV;  break;
      case X86::VMOVAPDYrr: NewOpc = X86::VMOVAPDYrr_REV; break;
      case X86::VMOVAPSrr:  NewOpc = X86::VMOVAPSrr_REV;  break;
      case X86::VMOVAPSYrr: NewOpc = X86::VMOVAPSYrr_REV; break;
      case X86::VMOVDQArr:  NewOpc = X86::VMOVDQArr_REV;  break;
      case X86::VMOVDQAYrr: NewOpc = X86::VMOVDQAYrr_REV; break;
      case X86::VMOVDQUrr:  NewOpc = X86::VMOVDQUrr_REV;  break;
      case X86::VMOVDQUYrr: NewOpc = X86::VMOVDQUYrr_REV; break;
      case X86::VMOVUPDrr:  NewOpc = X86::VMOVUPDrr_REV;  break;
      case X86::VMOVUPDYrr: NewOpc = X86::VMOVUPDYrr_REV; break;
      case X86::VMOVUPSrr:  NewOpc = X86::VMOVUPSrr_REV;  break;
      case X86::VMOVUPSYrr: NewOpc = X86::VMOVUPSYrr_REV; break;
      }
      OutMI.setOpcode(NewOpc);
    }
    break;
  }
  case X86::VMOVSDrr:
  case X86::VMOVSSrr: {
    if (!X86II::isX86_64ExtendedReg(OutMI.getOperand(0).getReg()) &&
        X86II::isX86_64ExtendedReg(OutMI.getOperand(2).getReg())) {
      unsigned NewOpc;
      switch (OutMI.getOpcode()) {
      default: llvm_unreachable("Invalid opcode");
      case X86::VMOVSDrr:   NewOpc = X86::VMOVSDrr_REV;   break;
      case X86::VMOVSSrr:   NewOpc = X86::VMOVSSrr_REV;   break;
      }
      OutMI.setOpcode(NewOpc);
    }
    break;
  }

  // TAILJMPr64, CALL64r, CALL64pcrel32 - These instructions have register
  // inputs modeled as normal uses instead of implicit uses.  As such, truncate
  // off all but the first operand (the callee).  FIXME: Change isel.
  case X86::TAILJMPr64:
  case X86::TAILJMPr64_REX:
  case X86::CALL64r:
  case X86::CALL64pcrel32: {
    unsigned Opcode = OutMI.getOpcode();
    MCOperand Saved = OutMI.getOperand(0);
    OutMI = MCInst();
    OutMI.setOpcode(Opcode);
    OutMI.addOperand(Saved);
    break;
  }

  case X86::EH_RETURN:
  case X86::EH_RETURN64: {
    OutMI = MCInst();
    OutMI.setOpcode(getRetOpcode(AsmPrinter.getSubtarget()));
    break;
  }

  // TAILJMPd, TAILJMPd64 - Lower to the correct jump instructions.
  case X86::TAILJMPr:
  case X86::TAILJMPd:
  case X86::TAILJMPd64: {
    unsigned Opcode;
    switch (OutMI.getOpcode()) {
    default: llvm_unreachable("Invalid opcode");
    case X86::TAILJMPr: Opcode = X86::JMP32r; break;
    case X86::TAILJMPd:
    case X86::TAILJMPd64: Opcode = X86::JMP_1; break;
    }

    MCOperand Saved = OutMI.getOperand(0);
    OutMI = MCInst();
    OutMI.setOpcode(Opcode);
    OutMI.addOperand(Saved);
    break;
  }

  case X86::DEC16r:
  case X86::DEC32r:
  case X86::INC16r:
  case X86::INC32r:
    // If we aren't in 64-bit mode we can use the 1-byte inc/dec instructions.
    if (!AsmPrinter.getSubtarget().is64Bit()) {
      unsigned Opcode;
      switch (OutMI.getOpcode()) {
      default: llvm_unreachable("Invalid opcode");
      case X86::DEC16r: Opcode = X86::DEC16r_alt; break;
      case X86::DEC32r: Opcode = X86::DEC32r_alt; break;
      case X86::INC16r: Opcode = X86::INC16r_alt; break;
      case X86::INC32r: Opcode = X86::INC32r_alt; break;
      }
      OutMI.setOpcode(Opcode);
    }
    break;

  // These are pseudo-ops for OR to help with the OR->ADD transformation.  We do
  // this with an ugly goto in case the resultant OR uses EAX and needs the
  // short form.
  case X86::ADD16rr_DB:   OutMI.setOpcode(X86::OR16rr); goto ReSimplify;
  case X86::ADD32rr_DB:   OutMI.setOpcode(X86::OR32rr); goto ReSimplify;
  case X86::ADD64rr_DB:   OutMI.setOpcode(X86::OR64rr); goto ReSimplify;
  case X86::ADD16ri_DB:   OutMI.setOpcode(X86::OR16ri); goto ReSimplify;
  case X86::ADD32ri_DB:   OutMI.setOpcode(X86::OR32ri); goto ReSimplify;
  case X86::ADD64ri32_DB: OutMI.setOpcode(X86::OR64ri32); goto ReSimplify;
  case X86::ADD16ri8_DB:  OutMI.setOpcode(X86::OR16ri8); goto ReSimplify;
  case X86::ADD32ri8_DB:  OutMI.setOpcode(X86::OR32ri8); goto ReSimplify;
  case X86::ADD64ri8_DB:  OutMI.setOpcode(X86::OR64ri8); goto ReSimplify;

  // Atomic load and store require a separate pseudo-inst because Acquire
  // implies mayStore and Release implies mayLoad; fix these to regular MOV
  // instructions here
  case X86::ACQUIRE_MOV8rm:    OutMI.setOpcode(X86::MOV8rm); goto ReSimplify;
  case X86::ACQUIRE_MOV16rm:   OutMI.setOpcode(X86::MOV16rm); goto ReSimplify;
  case X86::ACQUIRE_MOV32rm:   OutMI.setOpcode(X86::MOV32rm); goto ReSimplify;
  case X86::ACQUIRE_MOV64rm:   OutMI.setOpcode(X86::MOV64rm); goto ReSimplify;
  case X86::RELEASE_MOV8mr:    OutMI.setOpcode(X86::MOV8mr); goto ReSimplify;
  case X86::RELEASE_MOV16mr:   OutMI.setOpcode(X86::MOV16mr); goto ReSimplify;
  case X86::RELEASE_MOV32mr:   OutMI.setOpcode(X86::MOV32mr); goto ReSimplify;
  case X86::RELEASE_MOV64mr:   OutMI.setOpcode(X86::MOV64mr); goto ReSimplify;
  case X86::RELEASE_MOV8mi:    OutMI.setOpcode(X86::MOV8mi); goto ReSimplify;
  case X86::RELEASE_MOV16mi:   OutMI.setOpcode(X86::MOV16mi); goto ReSimplify;
  case X86::RELEASE_MOV32mi:   OutMI.setOpcode(X86::MOV32mi); goto ReSimplify;
  case X86::RELEASE_MOV64mi32: OutMI.setOpcode(X86::MOV64mi32); goto ReSimplify;
  case X86::RELEASE_ADD8mi:    OutMI.setOpcode(X86::ADD8mi); goto ReSimplify;
  case X86::RELEASE_ADD32mi:   OutMI.setOpcode(X86::ADD32mi); goto ReSimplify;
  case X86::RELEASE_ADD64mi32: OutMI.setOpcode(X86::ADD64mi32); goto ReSimplify;
  case X86::RELEASE_AND8mi:    OutMI.setOpcode(X86::AND8mi); goto ReSimplify;
  case X86::RELEASE_AND32mi:   OutMI.setOpcode(X86::AND32mi); goto ReSimplify;
  case X86::RELEASE_AND64mi32: OutMI.setOpcode(X86::AND64mi32); goto ReSimplify;
  case X86::RELEASE_OR8mi:     OutMI.setOpcode(X86::OR8mi); goto ReSimplify;
  case X86::RELEASE_OR32mi:    OutMI.setOpcode(X86::OR32mi); goto ReSimplify;
  case X86::RELEASE_OR64mi32:  OutMI.setOpcode(X86::OR64mi32); goto ReSimplify;
  case X86::RELEASE_XOR8mi:    OutMI.setOpcode(X86::XOR8mi); goto ReSimplify;
  case X86::RELEASE_XOR32mi:   OutMI.setOpcode(X86::XOR32mi); goto ReSimplify;
  case X86::RELEASE_XOR64mi32: OutMI.setOpcode(X86::XOR64mi32); goto ReSimplify;
  case X86::RELEASE_INC8m:     OutMI.setOpcode(X86::INC8m); goto ReSimplify;
  case X86::RELEASE_INC16m:    OutMI.setOpcode(X86::INC16m); goto ReSimplify;
  case X86::RELEASE_INC32m:    OutMI.setOpcode(X86::INC32m); goto ReSimplify;
  case X86::RELEASE_INC64m:    OutMI.setOpcode(X86::INC64m); goto ReSimplify;
  case X86::RELEASE_DEC8m:     OutMI.setOpcode(X86::DEC8m); goto ReSimplify;
  case X86::RELEASE_DEC16m:    OutMI.setOpcode(X86::DEC16m); goto ReSimplify;
  case X86::RELEASE_DEC32m:    OutMI.setOpcode(X86::DEC32m); goto ReSimplify;
  case X86::RELEASE_DEC64m:    OutMI.setOpcode(X86::DEC64m); goto ReSimplify;

  // We don't currently select the correct instruction form for instructions
  // which have a short %eax, etc. form. Handle this by custom lowering, for
  // now.
  //
  // Note, we are currently not handling the following instructions:
  // MOV64ao8, MOV64o8a
  // XCHG16ar, XCHG32ar, XCHG64ar
  case X86::MOV8mr_NOREX:
  case X86::MOV8mr:     SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV8o32a); break;
  case X86::MOV8rm_NOREX:
  case X86::MOV8rm:     SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV8ao32); break;
  case X86::MOV16mr:    SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV16o32a); break;
  case X86::MOV16rm:    SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV16ao32); break;
  case X86::MOV32mr:    SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV32o32a); break;
  case X86::MOV32rm:    SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV32ao32); break;

  case X86::ADC8ri:     SimplifyShortImmForm(OutMI, X86::ADC8i8);    break;
  case X86::ADC16ri:    SimplifyShortImmForm(OutMI, X86::ADC16i16);  break;
  case X86::ADC32ri:    SimplifyShortImmForm(OutMI, X86::ADC32i32);  break;
  case X86::ADC64ri32:  SimplifyShortImmForm(OutMI, X86::ADC64i32);  break;
  case X86::ADD8ri:     SimplifyShortImmForm(OutMI, X86::ADD8i8);    break;
  case X86::ADD16ri:    SimplifyShortImmForm(OutMI, X86::ADD16i16);  break;
  case X86::ADD32ri:    SimplifyShortImmForm(OutMI, X86::ADD32i32);  break;
  case X86::ADD64ri32:  SimplifyShortImmForm(OutMI, X86::ADD64i32);  break;
  case X86::AND8ri:     SimplifyShortImmForm(OutMI, X86::AND8i8);    break;
  case X86::AND16ri:    SimplifyShortImmForm(OutMI, X86::AND16i16);  break;
  case X86::AND32ri:    SimplifyShortImmForm(OutMI, X86::AND32i32);  break;
  case X86::AND64ri32:  SimplifyShortImmForm(OutMI, X86::AND64i32);  break;
  case X86::CMP8ri:     SimplifyShortImmForm(OutMI, X86::CMP8i8);    break;
  case X86::CMP16ri:    SimplifyShortImmForm(OutMI, X86::CMP16i16);  break;
  case X86::CMP32ri:    SimplifyShortImmForm(OutMI, X86::CMP32i32);  break;
  case X86::CMP64ri32:  SimplifyShortImmForm(OutMI, X86::CMP64i32);  break;
  case X86::OR8ri:      SimplifyShortImmForm(OutMI, X86::OR8i8);     break;
  case X86::OR16ri:     SimplifyShortImmForm(OutMI, X86::OR16i16);   break;
  case X86::OR32ri:     SimplifyShortImmForm(OutMI, X86::OR32i32);   break;
  case X86::OR64ri32:   SimplifyShortImmForm(OutMI, X86::OR64i32);   break;
  case X86::SBB8ri:     SimplifyShortImmForm(OutMI, X86::SBB8i8);    break;
  case X86::SBB16ri:    SimplifyShortImmForm(OutMI, X86::SBB16i16);  break;
  case X86::SBB32ri:    SimplifyShortImmForm(OutMI, X86::SBB32i32);  break;
  case X86::SBB64ri32:  SimplifyShortImmForm(OutMI, X86::SBB64i32);  break;
  case X86::SUB8ri:     SimplifyShortImmForm(OutMI, X86::SUB8i8);    break;
  case X86::SUB16ri:    SimplifyShortImmForm(OutMI, X86::SUB16i16);  break;
  case X86::SUB32ri:    SimplifyShortImmForm(OutMI, X86::SUB32i32);  break;
  case X86::SUB64ri32:  SimplifyShortImmForm(OutMI, X86::SUB64i32);  break;
  case X86::TEST8ri:    SimplifyShortImmForm(OutMI, X86::TEST8i8);   break;
  case X86::TEST16ri:   SimplifyShortImmForm(OutMI, X86::TEST16i16); break;
  case X86::TEST32ri:   SimplifyShortImmForm(OutMI, X86::TEST32i32); break;
  case X86::TEST64ri32: SimplifyShortImmForm(OutMI, X86::TEST64i32); break;
  case X86::XOR8ri:     SimplifyShortImmForm(OutMI, X86::XOR8i8);    break;
  case X86::XOR16ri:    SimplifyShortImmForm(OutMI, X86::XOR16i16);  break;
  case X86::XOR32ri:    SimplifyShortImmForm(OutMI, X86::XOR32i32);  break;
  case X86::XOR64ri32:  SimplifyShortImmForm(OutMI, X86::XOR64i32);  break;

  // Try to shrink some forms of movsx.
  case X86::MOVSX16rr8:
  case X86::MOVSX32rr16:
  case X86::MOVSX64rr32:
    SimplifyMOVSX(OutMI);
    break;
  }
}
Example #26
0
bool X86MCInstrAnalysis::isDependencyBreaking(const MCSubtargetInfo &STI,
                                              const MCInst &Inst) const {
  if (STI.getCPU() == "btver2") {
    // Reference: Agner Fog's microarchitecture.pdf - Section 20 "AMD Bobcat and
    // Jaguar pipeline", subsection 8 "Dependency-breaking instructions".
    switch (Inst.getOpcode()) {
    default:
      return false;
    case X86::SUB32rr:
    case X86::SUB64rr:
    case X86::SBB32rr:
    case X86::SBB64rr:
    case X86::XOR32rr:
    case X86::XOR64rr:
    case X86::XORPSrr:
    case X86::XORPDrr:
    case X86::VXORPSrr:
    case X86::VXORPDrr:
    case X86::ANDNPSrr:
    case X86::VANDNPSrr:
    case X86::ANDNPDrr:
    case X86::VANDNPDrr:
    case X86::PXORrr:
    case X86::VPXORrr:
    case X86::PANDNrr:
    case X86::VPANDNrr:
    case X86::PSUBBrr:
    case X86::PSUBWrr:
    case X86::PSUBDrr:
    case X86::PSUBQrr:
    case X86::VPSUBBrr:
    case X86::VPSUBWrr:
    case X86::VPSUBDrr:
    case X86::VPSUBQrr:
    case X86::PCMPEQBrr:
    case X86::PCMPEQWrr:
    case X86::PCMPEQDrr:
    case X86::PCMPEQQrr:
    case X86::VPCMPEQBrr:
    case X86::VPCMPEQWrr:
    case X86::VPCMPEQDrr:
    case X86::VPCMPEQQrr:
    case X86::PCMPGTBrr:
    case X86::PCMPGTWrr:
    case X86::PCMPGTDrr:
    case X86::PCMPGTQrr:
    case X86::VPCMPGTBrr:
    case X86::VPCMPGTWrr:
    case X86::VPCMPGTDrr:
    case X86::VPCMPGTQrr:
    case X86::MMX_PXORirr:
    case X86::MMX_PANDNirr:
    case X86::MMX_PSUBBirr:
    case X86::MMX_PSUBDirr:
    case X86::MMX_PSUBQirr:
    case X86::MMX_PSUBWirr:
    case X86::MMX_PCMPGTBirr:
    case X86::MMX_PCMPGTDirr:
    case X86::MMX_PCMPGTWirr:
    case X86::MMX_PCMPEQBirr:
    case X86::MMX_PCMPEQDirr:
    case X86::MMX_PCMPEQWirr:
      return Inst.getOperand(1).getReg() == Inst.getOperand(2).getReg();
    case X86::CMP32rr:
    case X86::CMP64rr:
      return Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg();
    }
  }

  return false;
}
Example #27
0
/*
 * Disassemble a function, using the LLVM MC disassembler.
 *
 * See also:
 * - http://blog.llvm.org/2010/01/x86-disassembler.html
 * - http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html
 */
extern "C" void
lp_disassemble(const void* func)
{
#if HAVE_LLVM >= 0x0207
   using namespace llvm;

   const uint8_t *bytes = (const uint8_t *)func;

   /*
    * Limit disassembly to this extent
    */
   const uint64_t extent = 0x10000;

   uint64_t max_pc = 0;

   /*
    * Initialize all used objects.
    */

#if HAVE_LLVM >= 0x0301
   std::string Triple = sys::getDefaultTargetTriple();
#else
   std::string Triple = sys::getHostTriple();
#endif

   std::string Error;
   const Target *T = TargetRegistry::lookupTarget(Triple, Error);

#if HAVE_LLVM >= 0x0208
   InitializeNativeTargetAsmPrinter();
#elif defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
   LLVMInitializeX86AsmPrinter();
#elif defined(PIPE_ARCH_ARM)
   LLVMInitializeARMAsmPrinter();
#elif defined(PIPE_ARCH_PPC)
   LLVMInitializePowerPCAsmPrinter();
#endif

#if HAVE_LLVM >= 0x0301
   InitializeNativeTargetDisassembler();
#elif defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
   LLVMInitializeX86Disassembler();
#elif defined(PIPE_ARCH_ARM)
   LLVMInitializeARMDisassembler();
#endif

#if HAVE_LLVM >= 0x0300
   OwningPtr<const MCAsmInfo> AsmInfo(T->createMCAsmInfo(Triple));
#else
   OwningPtr<const MCAsmInfo> AsmInfo(T->createAsmInfo(Triple));
#endif

   if (!AsmInfo) {
      debug_printf("error: no assembly info for target %s\n", Triple.c_str());
      return;
   }

#if HAVE_LLVM >= 0x0300
   const MCSubtargetInfo *STI = T->createMCSubtargetInfo(Triple, sys::getHostCPUName(), "");
   OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler(*STI));
#else 
   OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler());
#endif 
   if (!DisAsm) {
      debug_printf("error: no disassembler for target %s\n", Triple.c_str());
      return;
   }

   raw_debug_ostream Out;

#if HAVE_LLVM >= 0x0300
   unsigned int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
#else
   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
#endif

#if HAVE_LLVM >= 0x0301
   OwningPtr<const MCRegisterInfo> MRI(T->createMCRegInfo(Triple));
   if (!MRI) {
      debug_printf("error: no register info for target %s\n", Triple.c_str());
      return;
   }

   OwningPtr<const MCInstrInfo> MII(T->createMCInstrInfo());
   if (!MII) {
      debug_printf("error: no instruction info for target %s\n", Triple.c_str());
      return;
   }
#endif

#if HAVE_LLVM >= 0x0301
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI));
#elif HAVE_LLVM == 0x0300
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *STI));
#elif HAVE_LLVM >= 0x0208
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo));
#else
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, Out));
#endif
   if (!Printer) {
      debug_printf("error: no instruction printer for target %s\n", Triple.c_str());
      return;
   }

#if HAVE_LLVM >= 0x0301
   TargetOptions options;
#if defined(DEBUG)
   options.JITEmitDebugInfo = true;
#endif
#if defined(PIPE_ARCH_X86)
   options.StackAlignmentOverride = 4;
#endif
#if defined(DEBUG) || defined(PROFILE)
   options.NoFramePointerElim = true;
#endif
   TargetMachine *TM = T->createTargetMachine(Triple, sys::getHostCPUName(), "", options);
#elif HAVE_LLVM == 0x0300
   TargetMachine *TM = T->createTargetMachine(Triple, sys::getHostCPUName(), "");
#else
   TargetMachine *TM = T->createTargetMachine(Triple, "");
#endif

   const TargetInstrInfo *TII = TM->getInstrInfo();

   /*
    * Wrap the data in a MemoryObject
    */
   BufferMemoryObject memoryObject((const uint8_t *)bytes, extent);

   uint64_t pc;
   pc = 0;
   while (true) {
      MCInst Inst;
      uint64_t Size;

      /*
       * Print address.  We use addresses relative to the start of the function,
       * so that between runs.
       */

      debug_printf("%6lu:\t", (unsigned long)pc);

      if (!DisAsm->getInstruction(Inst, Size, memoryObject,
                                 pc,
#if HAVE_LLVM >= 0x0300
				  nulls(), nulls())) {
#else
				  nulls())) {
#endif
         debug_printf("invalid\n");
         pc += 1;
      }

      /*
       * Output the bytes in hexidecimal format.
       */

      if (0) {
         unsigned i;
         for (i = 0; i < Size; ++i) {
            debug_printf("%02x ", ((const uint8_t*)bytes)[pc + i]);
         }
         for (; i < 16; ++i) {
            debug_printf("   ");
         }
      }

      /*
       * Print the instruction.
       */

#if HAVE_LLVM >= 0x0300
      Printer->printInst(&Inst, Out, "");
#elif HAVE_LLVM >= 0x208
      Printer->printInst(&Inst, Out);
#else
      Printer->printInst(&Inst);
#endif
      Out.flush();

      /*
       * Advance.
       */

      pc += Size;

#if HAVE_LLVM >= 0x0300
      const MCInstrDesc &TID = TII->get(Inst.getOpcode());
#else
      const TargetInstrDesc &TID = TII->get(Inst.getOpcode());
#endif

      /*
       * Keep track of forward jumps to a nearby address.
       */

      if (TID.isBranch()) {
         for (unsigned i = 0; i < Inst.getNumOperands(); ++i) {
            const MCOperand &operand = Inst.getOperand(i);
            if (operand.isImm()) {
               uint64_t jump;

               /*
                * FIXME: Handle both relative and absolute addresses correctly.
                * EDInstInfo actually has this info, but operandTypes and
                * operandFlags enums are not exposed in the public interface.
                */

               if (1) {
                  /*
                   * PC relative addr.
                   */

                  jump = pc + operand.getImm();
               } else {
                  /*
                   * Absolute addr.
                   */

                  jump = (uint64_t)operand.getImm();
               }

               /*
                * Output the address relative to the function start, given
                * that MC will print the addresses relative the current pc.
                */
               debug_printf("\t\t; %lu", (unsigned long)jump);

               /*
                * Ignore far jumps given it could be actually a tail return to
                * a random address.
                */

               if (jump > max_pc &&
                   jump < extent) {
                  max_pc = jump;
               }
            }
         }
      }

      debug_printf("\n");

      /*
       * Stop disassembling on return statements, if there is no record of a
       * jump to a successive address.
       */

      if (TID.isReturn()) {
         if (pc > max_pc) {
            break;
         }
      }
   }

   /*
    * Print GDB command, useful to verify output.
    */

   if (0) {
      debug_printf("disassemble %p %p\n", bytes, bytes + pc);
   }

   debug_printf("\n");
#else /* HAVE_LLVM < 0x0207 */
   (void)func;
#endif /* HAVE_LLVM < 0x0207 */
}
Example #28
0
/// translateImmediate  - Appends an immediate operand to an MCInst.
///
/// @param mcInst       - The MCInst to append to.
/// @param immediate    - The immediate value to append.
/// @param operand      - The operand, as stored in the descriptor table.
/// @param insn         - The internal instruction.
static void translateImmediate(MCInst &mcInst, uint64_t immediate,
                               const OperandSpecifier &operand,
                               InternalInstruction &insn) {
  // Sign-extend the immediate if necessary.

  OperandType type = operand.type;

  if (type == TYPE_RELv) {
    switch (insn.displacementSize) {
    default:
      break;
    case 1:
      type = TYPE_MOFFS8;
      break;
    case 2:
      type = TYPE_MOFFS16;
      break;
    case 4:
      type = TYPE_MOFFS32;
      break;
    case 8:
      type = TYPE_MOFFS64;
      break;
    }
  }
  // By default sign-extend all X86 immediates based on their encoding.
  else if (type == TYPE_IMM8 || type == TYPE_IMM16 || type == TYPE_IMM32 ||
           type == TYPE_IMM64) {
    uint32_t Opcode = mcInst.getOpcode();
    switch (operand.encoding) {
    default:
      break;
    case ENCODING_IB:
      // Special case those X86 instructions that use the imm8 as a set of
      // bits, bit count, etc. and are not sign-extend.
      if (Opcode != X86::BLENDPSrri && Opcode != X86::BLENDPDrri &&
	  Opcode != X86::PBLENDWrri && Opcode != X86::MPSADBWrri &&
	  Opcode != X86::DPPSrri && Opcode != X86::DPPDrri &&
	  Opcode != X86::INSERTPSrr && Opcode != X86::VBLENDPSYrri &&
	  Opcode != X86::VBLENDPSYrmi && Opcode != X86::VBLENDPDYrri &&
	  Opcode != X86::VBLENDPDYrmi && Opcode != X86::VPBLENDWrri &&
	  Opcode != X86::VMPSADBWrri && Opcode != X86::VDPPSYrri &&
	  Opcode != X86::VDPPSYrmi && Opcode != X86::VDPPDrri &&
	  Opcode != X86::VINSERTPSrr)
	type = TYPE_MOFFS8;
      break;
    case ENCODING_IW:
      type = TYPE_MOFFS16;
      break;
    case ENCODING_ID:
      type = TYPE_MOFFS32;
      break;
    case ENCODING_IO:
      type = TYPE_MOFFS64;
      break;
    }
  }

  switch (type) {
  case TYPE_MOFFS8:
  case TYPE_REL8:
    if(immediate & 0x80)
      immediate |= ~(0xffull);
    break;
  case TYPE_MOFFS16:
    if(immediate & 0x8000)
      immediate |= ~(0xffffull);
    break;
  case TYPE_MOFFS32:
  case TYPE_REL32:
  case TYPE_REL64:
    if(immediate & 0x80000000)
      immediate |= ~(0xffffffffull);
    break;
  case TYPE_MOFFS64:
  default:
    // operand is 64 bits wide.  Do nothing.
    break;
  }
    
  mcInst.addOperand(MCOperand::CreateImm(immediate));
}
bool ARMAsmBackend::mayNeedRelaxation(const MCInst &Inst) const {
  if (getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode())
    return true;
  return false;
}
Example #30
0
void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
  OutMI.setOpcode(MI->getOpcode());

  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);

    MCOperand MCOp;
    switch (MO.getType()) {
    default:
      MI->dump();
      llvm_unreachable("unknown operand type");
    case MachineOperand::MO_Register:
      // Ignore all implicit register operands.
      if (MO.isImplicit()) continue;
      MCOp = MCOperand::CreateReg(MO.getReg());
      break;
    case MachineOperand::MO_Immediate:
      MCOp = MCOperand::CreateImm(MO.getImm());
      break;
    case MachineOperand::MO_MachineBasicBlock:
      MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
                       MO.getMBB()->getSymbol(), Ctx));
      break;
    case MachineOperand::MO_GlobalAddress:
    case MachineOperand::MO_ExternalSymbol:
      MCOp = LowerSymbolOperand(MO, GetSymbolFromOperand(MO));
      break;
    case MachineOperand::MO_JumpTableIndex:
      MCOp = LowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex()));
      break;
    case MachineOperand::MO_ConstantPoolIndex:
      MCOp = LowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex()));
      break;
    case MachineOperand::MO_BlockAddress:
      MCOp = LowerSymbolOperand(MO,
                     AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()));
      break;
    case MachineOperand::MO_RegisterMask:
      // Ignore call clobbers.
      continue;
    }

    OutMI.addOperand(MCOp);
  }

  // Handle a few special cases to eliminate operand modifiers.
ReSimplify:
  switch (OutMI.getOpcode()) {
  case X86::LEA64_32r: // Handle 'subreg rewriting' for the lea64_32mem operand.
    lower_lea64_32mem(&OutMI, 1);
    // FALL THROUGH.
  case X86::LEA64r:
  case X86::LEA16r:
  case X86::LEA32r:
    // LEA should have a segment register, but it must be empty.
    assert(OutMI.getNumOperands() == 1+X86::AddrNumOperands &&
           "Unexpected # of LEA operands");
    assert(OutMI.getOperand(1+X86::AddrSegmentReg).getReg() == 0 &&
           "LEA has segment specified!");
    break;
  case X86::MOVZX64rr32:  LowerSubReg32_Op0(OutMI, X86::MOV32rr); break;
  case X86::MOVZX64rm32:  LowerSubReg32_Op0(OutMI, X86::MOV32rm); break;
  case X86::MOV64ri64i32: LowerSubReg32_Op0(OutMI, X86::MOV32ri); break;
  case X86::MOVZX64rr8:   LowerSubReg32_Op0(OutMI, X86::MOVZX32rr8); break;
  case X86::MOVZX64rm8:   LowerSubReg32_Op0(OutMI, X86::MOVZX32rm8); break;
  case X86::MOVZX64rr16:  LowerSubReg32_Op0(OutMI, X86::MOVZX32rr16); break;
  case X86::MOVZX64rm16:  LowerSubReg32_Op0(OutMI, X86::MOVZX32rm16); break;
  case X86::SETB_C8r:     LowerUnaryToTwoAddr(OutMI, X86::SBB8rr); break;
  case X86::SETB_C16r:    LowerUnaryToTwoAddr(OutMI, X86::SBB16rr); break;
  case X86::SETB_C32r:    LowerUnaryToTwoAddr(OutMI, X86::SBB32rr); break;
  case X86::SETB_C64r:    LowerUnaryToTwoAddr(OutMI, X86::SBB64rr); break;
  case X86::MOV8r0:       LowerUnaryToTwoAddr(OutMI, X86::XOR8rr); break;
  case X86::MOV32r0:      LowerUnaryToTwoAddr(OutMI, X86::XOR32rr); break;

  case X86::MOV16r0:
    LowerSubReg32_Op0(OutMI, X86::MOV32r0);   // MOV16r0 -> MOV32r0
    LowerUnaryToTwoAddr(OutMI, X86::XOR32rr); // MOV32r0 -> XOR32rr
    break;
  case X86::MOV64r0:
    LowerSubReg32_Op0(OutMI, X86::MOV32r0);   // MOV64r0 -> MOV32r0
    LowerUnaryToTwoAddr(OutMI, X86::XOR32rr); // MOV32r0 -> XOR32rr
    break;

  // TAILJMPr64, CALL64r, CALL64pcrel32 - These instructions have register
  // inputs modeled as normal uses instead of implicit uses.  As such, truncate
  // off all but the first operand (the callee).  FIXME: Change isel.
  case X86::TAILJMPr64:
  case X86::CALL64r:
  case X86::CALL64pcrel32: {
    unsigned Opcode = OutMI.getOpcode();
    MCOperand Saved = OutMI.getOperand(0);
    OutMI = MCInst();
    OutMI.setOpcode(Opcode);
    OutMI.addOperand(Saved);
    break;
  }

  case X86::EH_RETURN:
  case X86::EH_RETURN64: {
    OutMI = MCInst();
    OutMI.setOpcode(X86::RET);
    break;
  }

  // TAILJMPd, TAILJMPd64 - Lower to the correct jump instructions.
  case X86::TAILJMPr:
  case X86::TAILJMPd:
  case X86::TAILJMPd64: {
    unsigned Opcode;
    switch (OutMI.getOpcode()) {
    default: llvm_unreachable("Invalid opcode");
    case X86::TAILJMPr: Opcode = X86::JMP32r; break;
    case X86::TAILJMPd:
    case X86::TAILJMPd64: Opcode = X86::JMP_1; break;
    }

    MCOperand Saved = OutMI.getOperand(0);
    OutMI = MCInst();
    OutMI.setOpcode(Opcode);
    OutMI.addOperand(Saved);
    break;
  }

  // These are pseudo-ops for OR to help with the OR->ADD transformation.  We do
  // this with an ugly goto in case the resultant OR uses EAX and needs the
  // short form.
  case X86::ADD16rr_DB:   OutMI.setOpcode(X86::OR16rr); goto ReSimplify;
  case X86::ADD32rr_DB:   OutMI.setOpcode(X86::OR32rr); goto ReSimplify;
  case X86::ADD64rr_DB:   OutMI.setOpcode(X86::OR64rr); goto ReSimplify;
  case X86::ADD16ri_DB:   OutMI.setOpcode(X86::OR16ri); goto ReSimplify;
  case X86::ADD32ri_DB:   OutMI.setOpcode(X86::OR32ri); goto ReSimplify;
  case X86::ADD64ri32_DB: OutMI.setOpcode(X86::OR64ri32); goto ReSimplify;
  case X86::ADD16ri8_DB:  OutMI.setOpcode(X86::OR16ri8); goto ReSimplify;
  case X86::ADD32ri8_DB:  OutMI.setOpcode(X86::OR32ri8); goto ReSimplify;
  case X86::ADD64ri8_DB:  OutMI.setOpcode(X86::OR64ri8); goto ReSimplify;

  // The assembler backend wants to see branches in their small form and relax
  // them to their large form.  The JIT can only handle the large form because
  // it does not do relaxation.  For now, translate the large form to the
  // small one here.
  case X86::JMP_4: OutMI.setOpcode(X86::JMP_1); break;
  case X86::JO_4:  OutMI.setOpcode(X86::JO_1); break;
  case X86::JNO_4: OutMI.setOpcode(X86::JNO_1); break;
  case X86::JB_4:  OutMI.setOpcode(X86::JB_1); break;
  case X86::JAE_4: OutMI.setOpcode(X86::JAE_1); break;
  case X86::JE_4:  OutMI.setOpcode(X86::JE_1); break;
  case X86::JNE_4: OutMI.setOpcode(X86::JNE_1); break;
  case X86::JBE_4: OutMI.setOpcode(X86::JBE_1); break;
  case X86::JA_4:  OutMI.setOpcode(X86::JA_1); break;
  case X86::JS_4:  OutMI.setOpcode(X86::JS_1); break;
  case X86::JNS_4: OutMI.setOpcode(X86::JNS_1); break;
  case X86::JP_4:  OutMI.setOpcode(X86::JP_1); break;
  case X86::JNP_4: OutMI.setOpcode(X86::JNP_1); break;
  case X86::JL_4:  OutMI.setOpcode(X86::JL_1); break;
  case X86::JGE_4: OutMI.setOpcode(X86::JGE_1); break;
  case X86::JLE_4: OutMI.setOpcode(X86::JLE_1); break;
  case X86::JG_4:  OutMI.setOpcode(X86::JG_1); break;

  // Atomic load and store require a separate pseudo-inst because Acquire
  // implies mayStore and Release implies mayLoad; fix these to regular MOV
  // instructions here
  case X86::ACQUIRE_MOV8rm:  OutMI.setOpcode(X86::MOV8rm); goto ReSimplify;
  case X86::ACQUIRE_MOV16rm: OutMI.setOpcode(X86::MOV16rm); goto ReSimplify;
  case X86::ACQUIRE_MOV32rm: OutMI.setOpcode(X86::MOV32rm); goto ReSimplify;
  case X86::ACQUIRE_MOV64rm: OutMI.setOpcode(X86::MOV64rm); goto ReSimplify;
  case X86::RELEASE_MOV8mr:  OutMI.setOpcode(X86::MOV8mr); goto ReSimplify;
  case X86::RELEASE_MOV16mr: OutMI.setOpcode(X86::MOV16mr); goto ReSimplify;
  case X86::RELEASE_MOV32mr: OutMI.setOpcode(X86::MOV32mr); goto ReSimplify;
  case X86::RELEASE_MOV64mr: OutMI.setOpcode(X86::MOV64mr); goto ReSimplify;

  // We don't currently select the correct instruction form for instructions
  // which have a short %eax, etc. form. Handle this by custom lowering, for
  // now.
  //
  // Note, we are currently not handling the following instructions:
  // MOV64ao8, MOV64o8a
  // XCHG16ar, XCHG32ar, XCHG64ar
  case X86::MOV8mr_NOREX:
  case X86::MOV8mr:     SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV8ao8); break;
  case X86::MOV8rm_NOREX:
  case X86::MOV8rm:     SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV8o8a); break;
  case X86::MOV16mr:    SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV16ao16); break;
  case X86::MOV16rm:    SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV16o16a); break;
  case X86::MOV32mr:    SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV32ao32); break;
  case X86::MOV32rm:    SimplifyShortMoveForm(AsmPrinter, OutMI, X86::MOV32o32a); break;

  case X86::ADC8ri:     SimplifyShortImmForm(OutMI, X86::ADC8i8);    break;
  case X86::ADC16ri:    SimplifyShortImmForm(OutMI, X86::ADC16i16);  break;
  case X86::ADC32ri:    SimplifyShortImmForm(OutMI, X86::ADC32i32);  break;
  case X86::ADC64ri32:  SimplifyShortImmForm(OutMI, X86::ADC64i32);  break;
  case X86::ADD8ri:     SimplifyShortImmForm(OutMI, X86::ADD8i8);    break;
  case X86::ADD16ri:    SimplifyShortImmForm(OutMI, X86::ADD16i16);  break;
  case X86::ADD32ri:    SimplifyShortImmForm(OutMI, X86::ADD32i32);  break;
  case X86::ADD64ri32:  SimplifyShortImmForm(OutMI, X86::ADD64i32);  break;
  case X86::AND8ri:     SimplifyShortImmForm(OutMI, X86::AND8i8);    break;
  case X86::AND16ri:    SimplifyShortImmForm(OutMI, X86::AND16i16);  break;
  case X86::AND32ri:    SimplifyShortImmForm(OutMI, X86::AND32i32);  break;
  case X86::AND64ri32:  SimplifyShortImmForm(OutMI, X86::AND64i32);  break;
  case X86::CMP8ri:     SimplifyShortImmForm(OutMI, X86::CMP8i8);    break;
  case X86::CMP16ri:    SimplifyShortImmForm(OutMI, X86::CMP16i16);  break;
  case X86::CMP32ri:    SimplifyShortImmForm(OutMI, X86::CMP32i32);  break;
  case X86::CMP64ri32:  SimplifyShortImmForm(OutMI, X86::CMP64i32);  break;
  case X86::OR8ri:      SimplifyShortImmForm(OutMI, X86::OR8i8);     break;
  case X86::OR16ri:     SimplifyShortImmForm(OutMI, X86::OR16i16);   break;
  case X86::OR32ri:     SimplifyShortImmForm(OutMI, X86::OR32i32);   break;
  case X86::OR64ri32:   SimplifyShortImmForm(OutMI, X86::OR64i32);   break;
  case X86::SBB8ri:     SimplifyShortImmForm(OutMI, X86::SBB8i8);    break;
  case X86::SBB16ri:    SimplifyShortImmForm(OutMI, X86::SBB16i16);  break;
  case X86::SBB32ri:    SimplifyShortImmForm(OutMI, X86::SBB32i32);  break;
  case X86::SBB64ri32:  SimplifyShortImmForm(OutMI, X86::SBB64i32);  break;
  case X86::SUB8ri:     SimplifyShortImmForm(OutMI, X86::SUB8i8);    break;
  case X86::SUB16ri:    SimplifyShortImmForm(OutMI, X86::SUB16i16);  break;
  case X86::SUB32ri:    SimplifyShortImmForm(OutMI, X86::SUB32i32);  break;
  case X86::SUB64ri32:  SimplifyShortImmForm(OutMI, X86::SUB64i32);  break;
  case X86::TEST8ri:    SimplifyShortImmForm(OutMI, X86::TEST8i8);   break;
  case X86::TEST16ri:   SimplifyShortImmForm(OutMI, X86::TEST16i16); break;
  case X86::TEST32ri:   SimplifyShortImmForm(OutMI, X86::TEST32i32); break;
  case X86::TEST64ri32: SimplifyShortImmForm(OutMI, X86::TEST64i32); break;
  case X86::XOR8ri:     SimplifyShortImmForm(OutMI, X86::XOR8i8);    break;
  case X86::XOR16ri:    SimplifyShortImmForm(OutMI, X86::XOR16i16);  break;
  case X86::XOR32ri:    SimplifyShortImmForm(OutMI, X86::XOR32i32);  break;
  case X86::XOR64ri32:  SimplifyShortImmForm(OutMI, X86::XOR64i32);  break;

  case X86::MORESTACK_RET:
    OutMI.setOpcode(X86::RET);
    break;

  case X86::MORESTACK_RET_RESTORE_R10: {
    MCInst retInst;

    OutMI.setOpcode(X86::MOV64rr);
    OutMI.addOperand(MCOperand::CreateReg(X86::R10));
    OutMI.addOperand(MCOperand::CreateReg(X86::RAX));

    retInst.setOpcode(X86::RET);
    AsmPrinter.OutStreamer.EmitInstruction(retInst);
    break;
  }
  }
}