1 //===-- SystemZMCCodeEmitter.cpp - Convert SystemZ code to machine code ---===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the SystemZMCCodeEmitter class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #define DEBUG_TYPE "mccodeemitter"
15 #include "MCTargetDesc/SystemZMCTargetDesc.h"
16 #include "MCTargetDesc/SystemZMCFixups.h"
17 #include "llvm/MC/MCCodeEmitter.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCExpr.h"
20 #include "llvm/MC/MCInstrInfo.h"
21 
22 using namespace llvm;
23 
24 namespace {
25 class SystemZMCCodeEmitter : public MCCodeEmitter {
26   const MCInstrInfo &MCII;
27   MCContext &Ctx;
28 
29 public:
30   SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
31     : MCII(mcii), Ctx(ctx) {
32   }
33 
34   ~SystemZMCCodeEmitter() {}
35 
36   // OVerride MCCodeEmitter.
37   virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
38                                  SmallVectorImpl<MCFixup> &Fixups) const
39     LLVM_OVERRIDE;
40 
41 private:
42   // Automatically generated by TableGen.
43   uint64_t getBinaryCodeForInstr(const MCInst &MI,
44                                  SmallVectorImpl<MCFixup> &Fixups) const;
45 
46   // Called by the TableGen code to get the binary encoding of operand
47   // MO in MI.  Fixups is the list of fixups against MI.
48   uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
49                              SmallVectorImpl<MCFixup> &Fixups) const;
50 
51   // Called by the TableGen code to get the binary encoding of an address.
52   // The index, if any, is encoded first, followed by the base,
53   // followed by the displacement.  In a 20-bit displacement,
54   // the low 12 bits are encoded before the high 8 bits.
55   uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
56                                SmallVectorImpl<MCFixup> &Fixups) const;
57   uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
58                                SmallVectorImpl<MCFixup> &Fixups) const;
59   uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
60                                 SmallVectorImpl<MCFixup> &Fixups) const;
61   uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
62                                 SmallVectorImpl<MCFixup> &Fixups) const;
63 
64   // Operand OpNum of MI needs a PC-relative fixup of kind Kind at
65   // Offset bytes from the start of MI.  Add the fixup to Fixups
66   // and return the in-place addend, which since we're a RELA target
67   // is always 0.
68   uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,
69                             SmallVectorImpl<MCFixup> &Fixups,
70                             unsigned Kind, int64_t Offset) const;
71 
72   uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,
73                               SmallVectorImpl<MCFixup> &Fixups) const {
74     return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC16DBL, 2);
75   }
76   uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,
77                               SmallVectorImpl<MCFixup> &Fixups) const {
78     return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC32DBL, 2);
79   }
80   uint64_t getPLT16DBLEncoding(const MCInst &MI, unsigned OpNum,
81                                SmallVectorImpl<MCFixup> &Fixups) const {
82     return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PLT16DBL, 2);
83   }
84   uint64_t getPLT32DBLEncoding(const MCInst &MI, unsigned OpNum,
85                                SmallVectorImpl<MCFixup> &Fixups) const {
86     return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PLT32DBL, 2);
87   }
88 };
89 }
90 
91 MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,
92                                                 const MCRegisterInfo &MRI,
93                                                 const MCSubtargetInfo &MCSTI,
94                                                 MCContext &Ctx) {
95   return new SystemZMCCodeEmitter(MCII, Ctx);
96 }
97 
98 void SystemZMCCodeEmitter::
99 EncodeInstruction(const MCInst &MI, raw_ostream &OS,
100                   SmallVectorImpl<MCFixup> &Fixups) const {
101   uint64_t Bits = getBinaryCodeForInstr(MI, Fixups);
102   unsigned Size = MCII.get(MI.getOpcode()).getSize();
103   // Big-endian insertion of Size bytes.
104   unsigned ShiftValue = (Size * 8) - 8;
105   for (unsigned I = 0; I != Size; ++I) {
106     OS << uint8_t(Bits >> ShiftValue);
107     ShiftValue -= 8;
108   }
109 }
110 
111 uint64_t SystemZMCCodeEmitter::
112 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
113                   SmallVectorImpl<MCFixup> &Fixups) const {
114   if (MO.isReg())
115     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
116   if (MO.isImm())
117     return static_cast<uint64_t>(MO.getImm());
118   llvm_unreachable("Unexpected operand type!");
119 }
120 
121 uint64_t SystemZMCCodeEmitter::
122 getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
123                     SmallVectorImpl<MCFixup> &Fixups) const {
124   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups);
125   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups);
126   assert(isUInt<4>(Base) && isUInt<12>(Disp));
127   return (Base << 12) | Disp;
128 }
129 
130 uint64_t SystemZMCCodeEmitter::
131 getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
132                     SmallVectorImpl<MCFixup> &Fixups) const {
133   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups);
134   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups);
135   assert(isUInt<4>(Base) && isInt<20>(Disp));
136   return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12);
137 }
138 
139 uint64_t SystemZMCCodeEmitter::
140 getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
141                      SmallVectorImpl<MCFixup> &Fixups) const {
142   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups);
143   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups);
144   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups);
145   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index));
146   return (Index << 16) | (Base << 12) | Disp;
147 }
148 
149 uint64_t SystemZMCCodeEmitter::
150 getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
151                      SmallVectorImpl<MCFixup> &Fixups) const {
152   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups);
153   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups);
154   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups);
155   assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index));
156   return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8)
157     | ((Disp & 0xff000) >> 12);
158 }
159 
160 uint64_t
161 SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
162                                        SmallVectorImpl<MCFixup> &Fixups,
163                                        unsigned Kind, int64_t Offset) const {
164   const MCOperand &MO = MI.getOperand(OpNum);
165   const MCExpr *Expr;
166   if (MO.isImm())
167     Expr = MCConstantExpr::Create(MO.getImm() + Offset, Ctx);
168   else {
169     Expr = MO.getExpr();
170     if (Offset) {
171       // The operand value is relative to the start of MI, but the fixup
172       // is relative to the operand field itself, which is Offset bytes
173       // into MI.  Add Offset to the relocation value to cancel out
174       // this difference.
175       const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx);
176       Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx);
177     }
178   }
179   Fixups.push_back(MCFixup::Create(Offset, Expr, (MCFixupKind)Kind));
180   return 0;
181 }
182 
183 #include "SystemZGenMCCodeEmitter.inc"
184