aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
commitd8e91e46262bc44006913e6796843909f1ac7bcd (patch)
tree7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp
parentb7eb8e35e481a74962664b63dfb09483b200209a (diff)
Notes
Diffstat (limited to 'lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp')
-rw-r--r--lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp211
1 files changed, 211 insertions, 0 deletions
diff --git a/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp b/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp
new file mode 100644
index 000000000000..06f9f307cb1a
--- /dev/null
+++ b/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp
@@ -0,0 +1,211 @@
+//===-- MSP430MCCodeEmitter.cpp - Convert MSP430 code to machine code -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the MSP430MCCodeEmitter class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MSP430.h"
+#include "MCTargetDesc/MSP430MCTargetDesc.h"
+#include "MCTargetDesc/MSP430FixupKinds.h"
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/raw_ostream.h"
+
+#define DEBUG_TYPE "mccodeemitter"
+
+namespace llvm {
+
+class MSP430MCCodeEmitter : public MCCodeEmitter {
+ MCContext &Ctx;
+ MCInstrInfo const &MCII;
+
+ // Offset keeps track of current word number being emitted
+ // inside a particular instruction.
+ mutable unsigned Offset;
+
+ /// TableGen'erated function for getting the binary encoding for an
+ /// instruction.
+ uint64_t getBinaryCodeForInstr(const MCInst &MI,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ /// Returns the binary encoding of operands.
+ ///
+ /// If an operand requires relocation, the relocation is recorded
+ /// and zero is returned.
+ unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ unsigned getMemOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ unsigned getPCRelImmOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ unsigned getCGImmOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ unsigned getCCOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+public:
+ MSP430MCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
+ : Ctx(ctx), MCII(MCII) {}
+
+ void encodeInstruction(const MCInst &MI, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const override;
+};
+
+void MSP430MCCodeEmitter::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();
+
+ // Initialize fixup offset
+ Offset = 2;
+
+ uint64_t BinaryOpCode = getBinaryCodeForInstr(MI, Fixups, STI);
+ size_t WordCount = Size / 2;
+
+ while (WordCount--) {
+ support::endian::write(OS, (uint16_t)BinaryOpCode, support::little);
+ BinaryOpCode >>= 16;
+ }
+}
+
+unsigned MSP430MCCodeEmitter::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()) {
+ Offset += 2;
+ return MO.getImm();
+ }
+
+ assert(MO.isExpr() && "Expected expr operand");
+ Fixups.push_back(MCFixup::create(Offset, MO.getExpr(),
+ static_cast<MCFixupKind>(MSP430::fixup_16_byte), MI.getLoc()));
+ Offset += 2;
+ return 0;
+}
+
+unsigned MSP430MCCodeEmitter::getMemOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO1 = MI.getOperand(Op);
+ assert(MO1.isReg() && "Register operand expected");
+ unsigned Reg = Ctx.getRegisterInfo()->getEncodingValue(MO1.getReg());
+
+ const MCOperand &MO2 = MI.getOperand(Op + 1);
+ if (MO2.isImm()) {
+ Offset += 2;
+ return ((unsigned)MO2.getImm() << 4) | Reg;
+ }
+
+ assert(MO2.isExpr() && "Expr operand expected");
+ MSP430::Fixups FixupKind;
+ switch (Reg) {
+ case 0:
+ FixupKind = MSP430::fixup_16_pcrel_byte;
+ break;
+ case 2:
+ FixupKind = MSP430::fixup_16_byte;
+ break;
+ default:
+ FixupKind = MSP430::fixup_16_byte;
+ break;
+ }
+ Fixups.push_back(MCFixup::create(Offset, MO2.getExpr(),
+ static_cast<MCFixupKind>(FixupKind), MI.getLoc()));
+ Offset += 2;
+ return Reg;
+}
+
+unsigned MSP430MCCodeEmitter::getPCRelImmOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO = MI.getOperand(Op);
+ if (MO.isImm())
+ return MO.getImm();
+
+ assert(MO.isExpr() && "Expr operand expected");
+ Fixups.push_back(MCFixup::create(0, MO.getExpr(),
+ static_cast<MCFixupKind>(MSP430::fixup_10_pcrel), MI.getLoc()));
+ return 0;
+}
+
+unsigned MSP430MCCodeEmitter::getCGImmOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO = MI.getOperand(Op);
+ assert(MO.isImm() && "Expr operand expected");
+
+ int64_t Imm = MO.getImm();
+ switch (Imm) {
+ default:
+ llvm_unreachable("Invalid immediate value");
+ case 4: return 0x22;
+ case 8: return 0x32;
+ case 0: return 0x03;
+ case 1: return 0x13;
+ case 2: return 0x23;
+ case -1: return 0x33;
+ }
+}
+
+unsigned MSP430MCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned Op,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO = MI.getOperand(Op);
+ assert(MO.isImm() && "Immediate operand expected");
+ switch (MO.getImm()) {
+ case MSP430CC::COND_NE: return 0;
+ case MSP430CC::COND_E: return 1;
+ case MSP430CC::COND_LO: return 2;
+ case MSP430CC::COND_HS: return 3;
+ case MSP430CC::COND_N: return 4;
+ case MSP430CC::COND_GE: return 5;
+ case MSP430CC::COND_L: return 6;
+ default:
+ llvm_unreachable("Unknown condition code");
+ }
+}
+
+MCCodeEmitter *createMSP430MCCodeEmitter(const MCInstrInfo &MCII,
+ const MCRegisterInfo &MRI,
+ MCContext &Ctx) {
+ return new MSP430MCCodeEmitter(Ctx, MCII);
+}
+
+#include "MSP430GenMCCodeEmitter.inc"
+
+} // end of namespace llvm