Exemple #1
0
static void printInst(const llvm::MCInst& inst) {
	const llvm::MCInstrDesc& id = MII->get(inst.getOpcode());
	llvm::outs() << MII->getName(inst.getOpcode()) << " (" << inst.getNumOperands() << ") ";

	for (int iop = 0; iop < inst.getNumOperands(); ++iop) {
		const llvm::MCOperand& op = inst.getOperand(iop);

		if (op.isReg()) {
			unsigned reg = op.getReg();
			const char* rcName;
			char clsn[128];

			if (id.OpInfo[iop].RegClass < MRI->getNumRegClasses()) {
				const llvm::MCRegisterClass& rc = MRI->getRegClass(id.OpInfo[iop].RegClass);
				rcName = rc.getName();
			} else {
				snprintf(clsn, sizeof(clsn), "CLS%d", id.OpInfo[iop].RegClass);
				rcName = clsn;
			}
			llvm::outs() << MRI->getName(reg) << "(" << rcName << ", " << (uint64_t)id.OpInfo[iop].OperandType << ")";
		} else if (op.isImm()) {
			llvm::outs() << op.getImm() << "(" << (uint64_t)id.OpInfo[iop].OperandType << ")";
		} else {
			llvm::outs() << "<UNK>";
		}

		llvm::outs() << ", ";
	}

	llvm::outs() << "\n";
}
bool
EmulateInstructionMIPS::Emulate_ADDiu (llvm::MCInst& insn)
{
    bool success = false;
    const uint32_t imm16 = insn.getOperand(2).getImm();
    uint32_t imm = SignedBits(imm16, 15, 0);
    uint64_t result;
    uint32_t src, dst;

    dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
    src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());

    /* Check if this is addiu sp,<src>,imm16 */
    if (dst == gcc_dwarf_sp_mips64)
    {
        /* read <src> register */
        uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, 0, &success);
        if (!success)
            return false;

        result = src_opd_val + imm;

        Context context;
        RegisterInfo reg_info_sp;
        if (GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_sp_mips64, reg_info_sp))
            context.SetRegisterPlusOffset (reg_info_sp, imm);

        /* We are allocating bytes on stack */
        context.type = eContextAdjustStackPointer;

        WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_sp_mips64, result);
    }
    
    return true;
}
bool
EmulateInstructionMIPS::Emulate_LW (llvm::MCInst& insn)
{
    uint32_t src, base;

    src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
    base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());

    if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src))
    {
        RegisterValue data_src;
        RegisterInfo reg_info_src;

        if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src))
            return false;

        Context context;
        context.type = eContextRegisterLoad;

        if (!WriteRegister (context, &reg_info_src, data_src))
            return false;

        return true;
    }

    return false;
}
Exemple #4
0
static std::string getLocalName(const llvm::MCInst& inst, unsigned iop) {
	const llvm::MCOperand& op = inst.getOperand(iop);

	if (op.isReg() && strcmp(MRI->getName(op.getReg()), "RBP") == 0) {
		char buf[128];

		snprintf(buf, 128, "local_%x", -inst.getOperand(iop + 3).getImm());
		return std::string(buf);
	} else {
		return std::string("UNK");
	}
}
bool
EmulateInstructionMIPS::Emulate_SW (llvm::MCInst& insn)
{
    bool success = false;
    uint32_t imm16 = insn.getOperand(2).getImm();
    uint32_t imm = SignedBits(imm16, 15, 0);
    uint32_t src, base;

    src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
    base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());

    /* We look for sp based non-volatile register stores */
    if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src))
    {
        uint32_t address;
        RegisterInfo reg_info_base;
        RegisterInfo reg_info_src;

        if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base)
            || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src))
            return false;

        /* read SP */
        address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success);
        if (!success)
            return false;

        /* destination address */
        address = address + imm;

        Context context;
        RegisterValue data_src;
        context.type = eContextPushRegisterOnStack;
        context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0);

        uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
        Error error;

        if (!ReadRegister (&reg_info_base, data_src))
            return false;

        if (data_src.GetAsMemoryData (&reg_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0)
            return false;

        if (!WriteMemory (context, address, buffer, reg_info_src.byte_size))
            return false;

        return true;
    }

    return false;
}
static DecodeStatus DecodeSingleIndexedInstruction(llvm::MCInst &Inst,
                                                   unsigned Insn,
                                                   uint64_t Address,
                                                   const void *Decoder) {
  unsigned Rt = fieldFromInstruction(Insn, 0, 5);
  unsigned Rn = fieldFromInstruction(Insn, 5, 5);
  unsigned Imm9 = fieldFromInstruction(Insn, 12, 9);

  unsigned Opc = fieldFromInstruction(Insn, 22, 2);
  unsigned V = fieldFromInstruction(Insn, 26, 1);
  unsigned Size = fieldFromInstruction(Insn, 30, 2);

  if (Opc == 0 || (V == 1 && Opc == 2)) {
    // It's a store, the MCInst gets: Rn_wb, Rt, Rn, Imm
    DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
  }

  if (V == 0 && (Opc == 2 || Size == 3)) {
    DecodeGPR64RegisterClass(Inst, Rt, Address, Decoder);
  } else if (V == 0) {
    DecodeGPR32RegisterClass(Inst, Rt, Address, Decoder);
  } else if (V == 1 && (Opc & 2)) {
    DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder);
  } else {
    switch (Size) {
    case 0:
      DecodeFPR8RegisterClass(Inst, Rt, Address, Decoder);
      break;
    case 1:
      DecodeFPR16RegisterClass(Inst, Rt, Address, Decoder);
      break;
    case 2:
      DecodeFPR32RegisterClass(Inst, Rt, Address, Decoder);
      break;
    case 3:
      DecodeFPR64RegisterClass(Inst, Rt, Address, Decoder);
      break;
    }
  }

  if (Opc != 0 && (V != 1 || Opc != 2)) {
    // It's a load, the MCInst gets: Rt, Rn_wb, Rn, Imm
    DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
  }

  DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);

  Inst.addOperand(MCOperand::CreateImm(Imm9));

  // N.b. The official documentation says undpredictable if Rt == Rn, but this
  // takes place at the architectural rather than encoding level:
  //
  // "STR xzr, [sp], #4" is perfectly valid.
  if (V == 0 && Rt == Rn && Rn != 31)
    return MCDisassembler::SoftFail;
  else
    return MCDisassembler::Success;
}
static DecodeStatus DecodeGPR64RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
                                        uint64_t Address, const void *Decoder) {
  if (RegNo > 31)
    return MCDisassembler::Fail;

  uint16_t Register = getReg(Decoder, AArch64::GPR64RegClassID, RegNo);
  Inst.addOperand(MCOperand::CreateReg(Register));
  return MCDisassembler::Success;
}
static DecodeStatus DecodeFPZeroOperand(llvm::MCInst &Inst,
                                        unsigned RmBits,
                                        uint64_t Address,
                                        const void *Decoder) {
  // Any bits are valid in the instruction (they're architecturally ignored),
  // but a code generator should insert 0.
  Inst.addOperand(MCOperand::CreateImm(0));
  return MCDisassembler::Success;
}
Exemple #9
0
DecodeStatus AMDGPUDisassembler::DecodeVGPR_32RegisterClass(llvm::MCInst &Inst, 
                                                            unsigned Imm, 
                                                            uint64_t Addr) const {
  unsigned RegID;
  if (DecodeVgprRegister(Imm, RegID) == MCDisassembler::Success) {
    Inst.addOperand(MCOperand::createReg(RegID));
    return MCDisassembler::Success;
  }
  return MCDisassembler::Fail;
}
Exemple #10
0
static DecodeStatus DecodeRegisterClassByID(llvm::MCInst &Inst, unsigned RegNo,
                                            unsigned RegID,
                                            const void *Decoder) {
  if (RegNo > 31)
    return MCDisassembler::Fail;

  uint16_t Register = getReg(Decoder, RegID, RegNo);
  Inst.addOperand(MCOperand::CreateReg(Register));
  return MCDisassembler::Success;
}
static DecodeStatus DecodeRegExtendOperand(llvm::MCInst &Inst,
                                           unsigned ShiftAmount,
                                           uint64_t Address,
                                           const void *Decoder) {
  // Only values 0-4 are valid for this 3-bit field
  if (ShiftAmount > 4)
    return MCDisassembler::Fail;

  Inst.addOperand(MCOperand::CreateImm(ShiftAmount));
  return MCDisassembler::Success;
}
static DecodeStatus DecodeLogicalImmOperand(llvm::MCInst &Inst,
                                            unsigned Bits,
                                            uint64_t Address,
                                            const void *Decoder) {
  uint64_t Imm;
  if (!A64Imms::isLogicalImmBits(RegWidth, Bits, Imm))
    return MCDisassembler::Fail;

  Inst.addOperand(MCOperand::CreateImm(Bits));
  return MCDisassembler::Success;
}
static DecodeStatus DecodeCVT32FixedPosOperand(llvm::MCInst &Inst,
                                               unsigned Imm6Bits,
                                               uint64_t Address,
                                               const void *Decoder) {
  // 1 <= Imm <= 32. Encoded as 64 - Imm so: 63 >= Encoded >= 32.
  if (Imm6Bits < 32)
    return MCDisassembler::Fail;

  Inst.addOperand(MCOperand::CreateImm(Imm6Bits));
  return MCDisassembler::Success;
}
static DecodeStatus Decode32BitShiftOperand(llvm::MCInst &Inst,
                                            unsigned ShiftAmount,
                                            uint64_t Address,
                                            const void *Decoder) {
  // Only values below 32 are valid for a 32-bit register
  if (ShiftAmount > 31)
    return MCDisassembler::Fail;

  Inst.addOperand(MCOperand::CreateImm(ShiftAmount));
  return MCDisassembler::Success;
}
static DecodeStatus DecodeSysRegOperand(const A64SysReg::SysRegMapper &Mapper,
                                        llvm::MCInst &Inst,
                                        unsigned Val,
                                        uint64_t Address,
                                        const void *Decoder) {
  bool ValidNamed;
  Mapper.toString(Val, ValidNamed);

  Inst.addOperand(MCOperand::CreateImm(Val));

  return ValidNamed ? MCDisassembler::Success : MCDisassembler::Fail;
}
static DecodeStatus DecodeBitfield32ImmOperand(llvm::MCInst &Inst,
                                               unsigned Imm6Bits,
                                               uint64_t Address,
                                               const void *Decoder) {
  // In the 32-bit variant, bit 6 must be zero. I.e. the immediate must be
  // between 0 and 31.
  if (Imm6Bits > 31)
    return MCDisassembler::Fail;

  Inst.addOperand(MCOperand::CreateImm(Imm6Bits));
  return MCDisassembler::Success;
}
static DecodeStatus DecodeAddrRegExtendOperand(llvm::MCInst &Inst,
                                               unsigned OptionHiS,
                                               uint64_t Address,
                                               const void *Decoder) {
  // Option{1} must be 1. OptionHiS is made up of {Option{2}, Option{1},
  // S}. Hence we want to check bit 1.
  if (!(OptionHiS & 2))
    return MCDisassembler::Fail;

  Inst.addOperand(MCOperand::CreateImm(OptionHiS));
  return MCDisassembler::Success;
}
static DecodeStatus DecodeMoveWideImmOperand(llvm::MCInst &Inst,
                                             unsigned FullImm,
                                             uint64_t Address,
                                             const void *Decoder) {
  unsigned Imm16 = FullImm & 0xffff;
  unsigned Shift = FullImm >> 16;

  if (RegWidth == 32 && Shift > 1) return MCDisassembler::Fail;

  Inst.addOperand(MCOperand::CreateImm(Imm16));
  Inst.addOperand(MCOperand::CreateImm(Shift));
  return MCDisassembler::Success;
}
static DecodeStatus DecodeNamedImmOperand(llvm::MCInst &Inst,
                                          unsigned Val,
                                          uint64_t Address,
                                          const void *Decoder) {
  SomeNamedImmMapper Mapper;
  bool ValidNamed;
  Mapper.toString(Val, ValidNamed);
  if (ValidNamed || Mapper.validImm(Val)) {
    Inst.addOperand(MCOperand::CreateImm(Val));
    return MCDisassembler::Success;
  }

  return MCDisassembler::Fail;
}
Exemple #20
0
// Decodes the instruction, and returns the number of bytes decoded.
size_t ArchDecodeInstruction(const uint8_t *bytes, const uint8_t *bytes_end,
                             uintptr_t va, llvm::MCInst &inst) {


  size_t total_size = 0;
  size_t max_size = static_cast<size_t>(bytes_end - bytes);

  std::unordered_set<unsigned> prefixes;

  for (; total_size < max_size; ) {
    llvm::ArrayRef<uint8_t> bytes_to_decode(
        &(bytes[total_size]), max_size - total_size);

    uint64_t size = 0;
    auto decode_status = gDisassembler->getInstruction(
        inst, size, bytes_to_decode, va, llvm::nulls(), llvm::nulls());

    if (llvm::MCDisassembler::Success != decode_status) {
      return 0;
    }

    total_size += size;

    switch (auto op_code = inst.getOpcode()) {
      case llvm::X86::CS_PREFIX:
      case llvm::X86::DATA16_PREFIX:
      case llvm::X86::DS_PREFIX:
      case llvm::X86::ES_PREFIX:
      case llvm::X86::FS_PREFIX:
      case llvm::X86::GS_PREFIX:
      case llvm::X86::LOCK_PREFIX:
      case llvm::X86::REPNE_PREFIX:
      case llvm::X86::REP_PREFIX:
      case llvm::X86::REX64_PREFIX:
      case llvm::X86::SS_PREFIX:
      case llvm::X86::XACQUIRE_PREFIX:
      case llvm::X86::XRELEASE_PREFIX:
        prefixes.insert(op_code);
        break;
      default:
        max_size = 0;  // Stop decoding.
        break;
    }
  }

  FixupInstruction(inst, prefixes);

  return total_size;
}
Exemple #21
0
static DecodeStatus
DecodeNeonMovImmShiftOperand(llvm::MCInst &Inst, unsigned ShiftAmount,
                             uint64_t Address, const void *Decoder) {
  bool IsLSL = false;
  if (Ext == A64SE::LSL)
    IsLSL = true;
  else if (Ext != A64SE::MSL)
    return MCDisassembler::Fail;

  // MSL and LSLH accepts encoded shift amount 0 or 1.
  if ((!IsLSL || (IsLSL && IsHalf)) && ShiftAmount != 0 && ShiftAmount != 1)
    return MCDisassembler::Fail;

  // LSL  accepts encoded shift amount 0, 1, 2 or 3.
  if (IsLSL && ShiftAmount > 3)
    return MCDisassembler::Fail;

  Inst.addOperand(MCOperand::CreateImm(ShiftAmount));
  return MCDisassembler::Success;
}
static DecodeStatus DecodeFMOVLaneInstruction(llvm::MCInst &Inst, unsigned Insn,
                                              uint64_t Address,
                                              const void *Decoder) {
  // This decoder exists to add the dummy Lane operand to the MCInst, which must
  // be 1 in assembly but has no other real manifestation.
  unsigned Rd = fieldFromInstruction(Insn, 0, 5);
  unsigned Rn = fieldFromInstruction(Insn, 5, 5);
  unsigned IsToVec = fieldFromInstruction(Insn, 16, 1);

  if (IsToVec) {
    DecodeVPR128RegisterClass(Inst, Rd, Address, Decoder);
    DecodeGPR64RegisterClass(Inst, Rn, Address, Decoder);
  } else {
    DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder);
    DecodeVPR128RegisterClass(Inst, Rn, Address, Decoder);
  }

  // Add the lane
  Inst.addOperand(MCOperand::CreateImm(1));

  return MCDisassembler::Success;
}
static DecodeStatus DecodeBitfieldInstruction(llvm::MCInst &Inst, unsigned Insn,
                                              uint64_t Address,
                                              const void *Decoder) {
  unsigned Rd = fieldFromInstruction(Insn, 0, 5);
  unsigned Rn = fieldFromInstruction(Insn, 5, 5);
  unsigned ImmS = fieldFromInstruction(Insn, 10, 6);
  unsigned ImmR = fieldFromInstruction(Insn, 16, 6);
  unsigned SF = fieldFromInstruction(Insn, 31, 1);

  // Undef for 0b11 just in case it occurs. Don't want the compiler to optimise
  // out assertions that it thinks should never be hit.
  enum OpcTypes { SBFM = 0, BFM, UBFM, Undef } Opc;
  Opc = (OpcTypes)fieldFromInstruction(Insn, 29, 2);

  if (!SF) {
    // ImmR and ImmS must be between 0 and 31 for 32-bit instructions.
    if (ImmR > 31 || ImmS > 31)
      return MCDisassembler::Fail;
  }

  if (SF) {
    DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder);
    // BFM MCInsts use Rd as a source too.
    if (Opc == BFM) DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder);
    DecodeGPR64RegisterClass(Inst, Rn, Address, Decoder);
  } else {
    DecodeGPR32RegisterClass(Inst, Rd, Address, Decoder);
    // BFM MCInsts use Rd as a source too.
    if (Opc == BFM) DecodeGPR32RegisterClass(Inst, Rd, Address, Decoder);
    DecodeGPR32RegisterClass(Inst, Rn, Address, Decoder);
  }

  // ASR and LSR have more specific patterns so they won't get here:
  assert(!(ImmS == 31 && !SF && Opc != BFM)
         && "shift should have used auto decode");
  assert(!(ImmS == 63 && SF && Opc != BFM)
         && "shift should have used auto decode");

  // Extension instructions similarly:
  if (Opc == SBFM && ImmR == 0) {
    assert((ImmS != 7 && ImmS != 15) && "extension got here");
    assert((ImmS != 31 || SF == 0) && "extension got here");
  } else if (Opc == UBFM && ImmR == 0) {
    assert((SF != 0 || (ImmS != 7 && ImmS != 15)) && "extension got here");
  }

  if (Opc == UBFM) {
    // It might be a LSL instruction, which actually takes the shift amount
    // itself as an MCInst operand.
    if (SF && (ImmS + 1) % 64 == ImmR) {
      Inst.setOpcode(AArch64::LSLxxi);
      Inst.addOperand(MCOperand::CreateImm(63 - ImmS));
      return MCDisassembler::Success;
    } else if (!SF && (ImmS + 1) % 32 == ImmR) {
      Inst.setOpcode(AArch64::LSLwwi);
      Inst.addOperand(MCOperand::CreateImm(31 - ImmS));
      return MCDisassembler::Success;
    }
  }

  // Otherwise it's definitely either an extract or an insert depending on which
  // of ImmR or ImmS is larger.
  unsigned ExtractOp, InsertOp;
  switch (Opc) {
  default: llvm_unreachable("unexpected instruction trying to decode bitfield");
  case SBFM:
    ExtractOp = SF ? AArch64::SBFXxxii : AArch64::SBFXwwii;
    InsertOp = SF ? AArch64::SBFIZxxii : AArch64::SBFIZwwii;
    break;
  case BFM:
    ExtractOp = SF ? AArch64::BFXILxxii : AArch64::BFXILwwii;
    InsertOp = SF ? AArch64::BFIxxii : AArch64::BFIwwii;
    break;
  case UBFM:
    ExtractOp = SF ? AArch64::UBFXxxii : AArch64::UBFXwwii;
    InsertOp = SF ? AArch64::UBFIZxxii : AArch64::UBFIZwwii;
    break;
  }

  // Otherwise it's a boring insert or extract
  Inst.addOperand(MCOperand::CreateImm(ImmR));
  Inst.addOperand(MCOperand::CreateImm(ImmS));


  if (ImmS < ImmR)
    Inst.setOpcode(InsertOp);
  else
    Inst.setOpcode(ExtractOp);

  return MCDisassembler::Success;
}
bool
DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst)
{
    return m_instr_info_ap->get(mc_inst.getOpcode()).mayAffectControlFlow(mc_inst, *m_reg_info_ap.get());
}
static DecodeStatus DecodeLDSTPairInstruction(llvm::MCInst &Inst,
                                              unsigned Insn,
                                              uint64_t Address,
                                              const void *Decoder) {
  DecodeStatus Result = MCDisassembler::Success;
  unsigned Rt = fieldFromInstruction(Insn, 0, 5);
  unsigned Rn = fieldFromInstruction(Insn, 5, 5);
  unsigned Rt2 = fieldFromInstruction(Insn, 10, 5);
  unsigned SImm7 = fieldFromInstruction(Insn, 15, 7);
  unsigned L = fieldFromInstruction(Insn, 22, 1);
  unsigned V = fieldFromInstruction(Insn, 26, 1);
  unsigned Opc = fieldFromInstruction(Insn, 30, 2);

  // Not an official name, but it turns out that bit 23 distinguishes indexed
  // from non-indexed operations.
  unsigned Indexed = fieldFromInstruction(Insn, 23, 1);

  if (Indexed && L == 0) {
    // The MCInst for an indexed store has an out operand and 4 ins:
    //    Rn_wb, Rt, Rt2, Rn, Imm
    DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
  }

  // You shouldn't load to the same register twice in an instruction...
  if (L && Rt == Rt2)
    Result = MCDisassembler::SoftFail;

  // ... or do any operation that writes-back to a transfer register. But note
  // that "stp xzr, xzr, [sp], #4" is fine because xzr and sp are different.
  if (Indexed && V == 0 && Rn != 31 && (Rt == Rn || Rt2 == Rn))
    Result = MCDisassembler::SoftFail;

  // Exactly how we decode the MCInst's registers depends on the Opc and V
  // fields of the instruction. These also obviously determine the size of the
  // operation so we can fill in that information while we're at it.
  if (V) {
    // The instruction operates on the FP/SIMD registers
    switch (Opc) {
    default: return MCDisassembler::Fail;
    case 0:
      DecodeFPR32RegisterClass(Inst, Rt, Address, Decoder);
      DecodeFPR32RegisterClass(Inst, Rt2, Address, Decoder);
      break;
    case 1:
      DecodeFPR64RegisterClass(Inst, Rt, Address, Decoder);
      DecodeFPR64RegisterClass(Inst, Rt2, Address, Decoder);
      break;
    case 2:
      DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder);
      DecodeFPR128RegisterClass(Inst, Rt2, Address, Decoder);
      break;
    }
  } else {
    switch (Opc) {
    default: return MCDisassembler::Fail;
    case 0:
      DecodeGPR32RegisterClass(Inst, Rt, Address, Decoder);
      DecodeGPR32RegisterClass(Inst, Rt2, Address, Decoder);
      break;
    case 1:
      assert(L && "unexpected \"store signed\" attempt");
      DecodeGPR64RegisterClass(Inst, Rt, Address, Decoder);
      DecodeGPR64RegisterClass(Inst, Rt2, Address, Decoder);
      break;
    case 2:
      DecodeGPR64RegisterClass(Inst, Rt, Address, Decoder);
      DecodeGPR64RegisterClass(Inst, Rt2, Address, Decoder);
      break;
    }
  }

  if (Indexed && L == 1) {
    // The MCInst for an indexed load has 3 out operands and an 3 ins:
    //    Rt, Rt2, Rn_wb, Rt2, Rn, Imm
    DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
  }


  DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder);
  Inst.addOperand(MCOperand::CreateImm(SImm7));

  return Result;
}
Exemple #26
0
// Convert the given assembly instruction into an inline ASM operation in lieu
// of decompiling it. The output instruction will look something like this
// (although note that i128 doesn't work properly with LLVM codegen for the
// inline ASM instructions, necessitating a vector instead).
// %151 = load i128, i128* %XMM0_read
// %152 = bitcast i128 %151 to <16 x i8>
// %153 = load i128, i128* %XMM1_read
// %154 = bitcast i128 %153 to <16 x i8>
// %AESDECrr = call <16 x i8> asm "\09aesdec\09%xmm1, %xmm0", "={XMM0},{XMM0},{XMM1}"(<16 x i8> %152, <16 x i8> %154)
// %155 = bitcast <16 x i8> %AESDECrr to i128
// store volatile i128 %155, i128* %XMM0_write
void ArchBuildInlineAsm(llvm::MCInst &inst, llvm::BasicBlock *block) {
  auto opcode = inst.getOpcode();

  // Use the printer to build the ASM string. We'll need to escape the $ in
  // register names with $$.
  std::stringstream asmString;
  {
    std::string outS;
    llvm::raw_string_ostream strOut(outS);
    gIP->printInst(&inst, strOut, "", *gSTI);
    for (char c : strOut.str()) {
      if (c == '$')
        asmString << "$$";
      else
        asmString << c;
    }
  }

  // Next, find all the registers being used as definitions or uses in the
  // inline ASM. This will write up the constraints for us, as well as
  // provide us with a list of types (for the inline ASM output) and a list of
  // values to pass into the string.
  llvm::SmallVector<llvm::Value *, 3> operands;
  llvm::SmallVector<llvm::Type *, 3> resultTypes;
  std::stringstream constraints;
  for (unsigned i = 0; i < inst.getNumOperands(); i++) {
    llvm::MCOperand &op = inst.getOperand(i);
    if (op.isReg()) {
      unsigned regSize = ArchRegisterSize(op.getReg());
      if (constraints.tellp() > 0) constraints << ",";
      if (i < gMII->get(opcode).getNumDefs()) {
        constraints << "=";

        if (regSize > 64) {
          // LLVM can't handle register constraints of i128, so we
          // need to map this to <16 x i8>.
          resultTypes.push_back(llvm::VectorType::get(
            llvm::Type::getInt8Ty(block->getContext()), regSize / 8));
        } else {
          resultTypes.push_back(llvm::IntegerType::get(block->getContext(),
            regSize));
        }
      } else {
        auto readReg = GENERIC_MC_READREG(block, op.getReg(), regSize);
        if (regSize > 64) {
          // LLVM can't handle register constraints of i128, so we
          // need to map this to <16 x i8>.
          readReg = llvm::CastInst::Create(llvm::Instruction::BitCast, readReg,
            llvm::VectorType::get(llvm::Type::getInt8Ty(block->getContext()), regSize / 8),
            "", block);
        }
        operands.push_back(readReg);
      }
      constraints << "{" << gMRI->getName(op.getReg()) << "}";
    }
  }

  // With all of these pieces, piece together the actual call to the inline ASM
  // string.
  llvm::SmallVector<llvm::Type *, 3> argTypes;
  for (auto val : operands)
    argTypes.push_back(val->getType());

  llvm::Type *returnTy;
  if (resultTypes.empty())
    returnTy = llvm::Type::getVoidTy(block->getContext());
  else if (resultTypes.size() == 1)
    returnTy = resultTypes[0];
  else
    returnTy = llvm::StructType::get(block->getContext(), resultTypes);

  auto asmTy = llvm::FunctionType::get(returnTy, argTypes, false);
  auto callee = llvm::InlineAsm::get(asmTy, asmString.str(), constraints.str(),
      false);
  llvm::Value *resultPack =
    llvm::CallInst::Create(callee, operands, "", block);

  // Unpack the called registers into the LLVM values.
  for (unsigned i = 0; i < resultTypes.size(); i++) {
    llvm::Value *result = resultTypes.size() == 1 ? resultPack :
      llvm::ExtractValueInst::Create(resultPack, i, "", block);
    llvm::Type *ty = resultTypes[i];
    // Cast vector outputs to iXYZ for R_WRITE.
    if (ty->isVectorTy()) {
      ty = llvm::Type::getIntNTy(block->getContext(),
        ty->getVectorNumElements() * 8);
      result = llvm::CastInst::Create(llvm::Instruction::BitCast, result,
        ty, "", block);
    }
    unsigned regNo = inst.getOperand(i).getReg();
    GENERIC_MC_WRITEREG(block, regNo, result);
  }
}