1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
//=- LoongArchMCCodeEmitter.cpp - Convert LoongArch code to machine code --===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the LoongArchMCCodeEmitter class.
//
//===----------------------------------------------------------------------===//
#include "MCTargetDesc/LoongArchBaseInfo.h"
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/EndianStream.h"
using namespace llvm;
#define DEBUG_TYPE "mccodeemitter"
namespace {
class LoongArchMCCodeEmitter : public MCCodeEmitter {
LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete;
void operator=(const LoongArchMCCodeEmitter &) = delete;
MCContext &Ctx;
MCInstrInfo const &MCII;
public:
LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
: Ctx(ctx), MCII(MCII) {}
~LoongArchMCCodeEmitter() override {}
void encodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const override;
/// TableGen'erated function for getting the binary encoding for an
/// instruction.
uint64_t getBinaryCodeForInstr(const MCInst &MI,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
/// Return binary encoding of operand. If the machine operand requires
/// relocation, record the relocation and return zero.
unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
/// Return binary encoding of an immediate operand specified by OpNo.
/// The value returned is the value of the immediate minus 1.
/// Note that this function is dedicated to specific immediate types,
/// e.g. uimm2_plus1.
unsigned getImmOpValueSub1(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
/// Return binary encoding of an immediate operand specified by OpNo.
/// The value returned is the value of the immediate shifted right
// arithmetically by 2.
/// Note that this function is dedicated to specific immediate types,
/// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2.
unsigned getImmOpValueAsr2(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
};
} // end namespace
unsigned
LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
if (MO.isReg())
return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
if (MO.isImm())
return static_cast<unsigned>(MO.getImm());
llvm_unreachable("Unhandled expression!");
}
unsigned
LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
return MI.getOperand(OpNo).getImm() - 1;
}
unsigned
LoongArchMCCodeEmitter::getImmOpValueAsr2(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
unsigned Res = MI.getOperand(OpNo).getImm();
assert((Res & 3) == 0 && "lowest 2 bits are non-zero");
return Res >> 2;
}
void LoongArchMCCodeEmitter::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 4: {
uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
support::endian::write(OS, Bits, support::little);
break;
}
}
}
MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII,
MCContext &Ctx) {
return new LoongArchMCCodeEmitter(Ctx, MCII);
}
#include "LoongArchGenMCCodeEmitter.inc"
|