1 //===- subzero/src/IceAssemblerMIPS32.h - Assembler for MIPS ----*- C++ -*-===//
2 //
3 //                        The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Declares the Assembler class for MIPS32.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef SUBZERO_SRC_ICEASSEMBLERMIPS32_H
16 #define SUBZERO_SRC_ICEASSEMBLERMIPS32_H
17 
18 #include "IceAssembler.h"
19 #include "IceDefs.h"
20 #include "IceFixups.h"
21 #include "IceInstMIPS32.h"
22 #include "IceTargetLowering.h"
23 
24 namespace Ice {
25 namespace MIPS32 {
26 
27 using IValueT = uint32_t;
28 using IOffsetT = int32_t;
29 
30 enum FPInstDataFormat {
31   SinglePrecision = 16,
32   DoublePrecision = 17,
33   Word = 20,
34   Long = 21
35 };
36 
37 class MIPS32Fixup final : public AssemblerFixup {
38   MIPS32Fixup &operator=(const MIPS32Fixup &) = delete;
39   MIPS32Fixup(const MIPS32Fixup &) = default;
40 
41 public:
42   MIPS32Fixup() = default;
43   size_t emit(GlobalContext *Ctx, const Assembler &Asm) const final;
44   void emitOffset(Assembler *Asm) const;
45 };
46 
47 class AssemblerMIPS32 : public Assembler {
48   AssemblerMIPS32(const AssemblerMIPS32 &) = delete;
49   AssemblerMIPS32 &operator=(const AssemblerMIPS32 &) = delete;
50 
51 public:
52   explicit AssemblerMIPS32(bool use_far_branches = false)
Assembler(Asm_MIPS32)53       : Assembler(Asm_MIPS32) {
54     // This mode is only needed and implemented for MIPS32 and ARM.
55     assert(!use_far_branches);
56     (void)use_far_branches;
57   }
~AssemblerMIPS32()58   ~AssemblerMIPS32() override {
59     if (BuildDefs::asserts()) {
60       for (const Label *Label : CfgNodeLabels) {
61         Label->finalCheck();
62       }
63       for (const Label *Label : LocalLabels) {
64         Label->finalCheck();
65       }
66     }
67   }
68 
69   MIPS32Fixup *createMIPS32Fixup(const RelocOp Reloc, const Constant *RelOp);
70 
71   void trap();
72 
73   void nop();
74 
75   void emitRsRt(IValueT Opcode, const Operand *OpRs, const Operand *OpRt,
76                 const char *InsnName);
77 
78   void emitRtRsImm16(IValueT Opcode, const Operand *OpRt, const Operand *OpRs,
79                      uint32_t Imm, const char *InsnName);
80 
81   void emitRtRsImm16Rel(IValueT Opcode, const Operand *OpRt,
82                         const Operand *OpRs, const Operand *OpImm,
83                         const RelocOp Reloc, const char *InsnName);
84 
85   void emitFtRsImm16(IValueT Opcode, const Operand *OpFt, const Operand *OpRs,
86                      uint32_t Imm, const char *InsnName);
87 
88   void emitRdRtSa(IValueT Opcode, const Operand *OpRd, const Operand *OpRt,
89                   uint32_t Sa, const char *InsnName);
90 
91   void emitRdRsRt(IValueT Opcode, const Operand *OpRd, const Operand *OpRs,
92                   const Operand *OpRt, const char *InsnName);
93 
94   void emitCOP1Fcmp(IValueT Opcode, FPInstDataFormat Format,
95                     const Operand *OpFs, const Operand *OpFt, IValueT CC,
96                     const char *InsnName);
97 
98   void emitCOP1FmtFsFd(IValueT Opcode, FPInstDataFormat Format,
99                        const Operand *OpFd, const Operand *OpFs,
100                        const char *InsnName);
101 
102   void emitCOP1FmtFtFsFd(IValueT Opcode, FPInstDataFormat Format,
103                          const Operand *OpFd, const Operand *OpFs,
104                          const Operand *OpFt, const char *InsnName);
105 
106   void emitCOP1FmtRtFsFd(IValueT Opcode, FPInstDataFormat Format,
107                          const Operand *OpFd, const Operand *OpFs,
108                          const Operand *OpRt, const char *InsnName);
109 
110   void emitCOP1MovRtFs(IValueT Opcode, const Operand *OpRt, const Operand *OpFs,
111                        const char *InsnName);
112 
113   void emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs,
114               const Operand *OpRt, IOffsetT Offset);
115 
116   void abs_d(const Operand *OpFd, const Operand *OpFs);
117 
118   void abs_s(const Operand *OpFd, const Operand *OpFs);
119 
120   void addi(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
121 
122   void add_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
123 
124   void add_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
125 
126   void addu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
127 
128   void addiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
129 
130   void addiu(const Operand *OpRt, const Operand *OpRs, const Operand *OpImm,
131              const RelocOp Reloc);
132 
133   void and_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
134 
135   void andi(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
136 
137   void b(Label *TargetLabel);
138 
139   void c_eq_d(const Operand *OpFd, const Operand *OpFs);
140 
141   void c_eq_s(const Operand *OpFd, const Operand *OpFs);
142 
143   void c_ole_d(const Operand *OpFd, const Operand *OpFs);
144 
145   void c_ole_s(const Operand *OpFd, const Operand *OpFs);
146 
147   void c_olt_d(const Operand *OpFd, const Operand *OpFs);
148 
149   void c_olt_s(const Operand *OpFd, const Operand *OpFs);
150 
151   void c_ueq_d(const Operand *OpFd, const Operand *OpFs);
152 
153   void c_ueq_s(const Operand *OpFd, const Operand *OpFs);
154 
155   void c_ule_d(const Operand *OpFd, const Operand *OpFs);
156 
157   void c_ule_s(const Operand *OpFd, const Operand *OpFs);
158 
159   void c_ult_d(const Operand *OpFd, const Operand *OpFs);
160 
161   void c_ult_s(const Operand *OpFd, const Operand *OpFs);
162 
163   void c_un_d(const Operand *OpFd, const Operand *OpFs);
164 
165   void c_un_s(const Operand *OpFd, const Operand *OpFs);
166 
167   void clz(const Operand *OpRd, const Operand *OpRs);
168 
169   void cvt_d_l(const Operand *OpFd, const Operand *OpFs);
170 
171   void cvt_d_s(const Operand *OpFd, const Operand *OpFs);
172 
173   void cvt_d_w(const Operand *OpFd, const Operand *OpFs);
174 
175   void cvt_s_d(const Operand *OpFd, const Operand *OpFs);
176 
177   void cvt_s_l(const Operand *OpFd, const Operand *OpFs);
178 
179   void cvt_s_w(const Operand *OpFd, const Operand *OpFs);
180 
181   void div(const Operand *OpRs, const Operand *OpRt);
182 
183   void div_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
184 
185   void div_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
186 
187   void divu(const Operand *OpRs, const Operand *OpRt);
188 
189   void jal(const ConstantRelocatable *Target);
190 
191   void jalr(const Operand *OpRs, const Operand *OpRd);
192 
193   void lui(const Operand *OpRt, const Operand *OpImm, const RelocOp Reloc);
194 
195   void ldc1(const Operand *OpRt, const Operand *OpBase, const Operand *OpOff,
196             const RelocOp Reloc);
197 
198   void ll(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
199 
200   void lw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
201 
202   void lwc1(const Operand *OpRt, const Operand *OpBase, const Operand *OpOff,
203             const RelocOp Reloc);
204 
205   void mfc1(const Operand *OpRt, const Operand *OpFs);
206 
207   void mfhi(const Operand *OpRd);
208 
209   void mflo(const Operand *OpRd);
210 
211   void mov_d(const Operand *OpFd, const Operand *OpFs);
212 
213   void mov_s(const Operand *OpFd, const Operand *OpFs);
214 
215   void move(const Operand *OpRd, const Operand *OpRs);
216 
217   void movf(const Operand *OpRd, const Operand *OpRs, const Operand *OpCc);
218 
219   void movn(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
220 
221   void movn_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
222 
223   void movn_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
224 
225   void movt(const Operand *OpRd, const Operand *OpRs, const Operand *OpCc);
226 
227   void movz(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
228 
229   void movz_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
230 
231   void movz_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
232 
233   void mtc1(const Operand *OpRt, const Operand *OpFs);
234 
235   void mthi(const Operand *OpRs);
236 
237   void mtlo(const Operand *OpRs);
238 
239   void mul(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
240 
241   void mul_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
242 
243   void mul_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
244 
245   void mult(const Operand *OpRs, const Operand *OpRt);
246 
247   void multu(const Operand *OpRs, const Operand *OpRt);
248 
249   void nor(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
250 
251   void or_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
252 
253   void ori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
254 
255   void ret(void);
256 
257   void sc(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
258 
259   void sll(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
260 
261   void sllv(const Operand *OpRd, const Operand *OpRt, const Operand *OpRs);
262 
263   void slt(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
264 
265   void slti(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
266 
267   void sltiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
268 
269   void sltu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
270 
271   void sqrt_d(const Operand *OpFd, const Operand *OpFs);
272 
273   void sqrt_s(const Operand *OpFd, const Operand *OpFs);
274 
275   void sra(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
276 
277   void srav(const Operand *OpRd, const Operand *OpRt, const Operand *OpRs);
278 
279   void srl(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
280 
281   void srlv(const Operand *OpRd, const Operand *OpRt, const Operand *OpRs);
282 
283   void sub_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
284 
285   void sub_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
286 
287   void subu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
288 
289   void sdc1(const Operand *OpRt, const Operand *OpBase, const Operand *OpOff,
290             const RelocOp Reloc);
291 
292   void sw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
293 
294   void swc1(const Operand *OpRt, const Operand *OpBase, const Operand *OpOff,
295             const RelocOp Reloc);
296 
297   void sync();
298 
299   void teq(const Operand *OpRs, const Operand *OpRt, const uint32_t TrapCode);
300 
301   void trunc_l_d(const Operand *OpFd, const Operand *OpFs);
302 
303   void trunc_l_s(const Operand *OpFd, const Operand *OpFs);
304 
305   void trunc_w_d(const Operand *OpFd, const Operand *OpFs);
306 
307   void trunc_w_s(const Operand *OpFd, const Operand *OpFs);
308 
309   void xor_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
310 
311   void xori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
312 
313   void bcc(const CondMIPS32::Cond Cond, const Operand *OpRs,
314            const Operand *OpRt, Label *TargetLabel);
315 
316   void bzc(const CondMIPS32::Cond Cond, const Operand *OpRs,
317            Label *TargetLabel);
318 
alignFunction()319   void alignFunction() override {
320     const SizeT Align = 1 << getBundleAlignLog2Bytes();
321     SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align);
322     constexpr SizeT InstSize = sizeof(IValueT);
323     assert(BytesNeeded % InstMIPS32::InstSize == 0);
324     while (BytesNeeded > 0) {
325       trap();
326       BytesNeeded -= InstSize;
327     }
328   }
329 
getBundleAlignLog2Bytes()330   SizeT getBundleAlignLog2Bytes() const override { return 4; }
331 
getAlignDirective()332   const char *getAlignDirective() const override { return ".p2alignl"; }
333 
334   llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override;
335 
336   void padWithNop(intptr_t Padding) override;
337 
338   void bind(Label *label);
339 
340   void emitTextInst(const std::string &Text, SizeT InstSize);
341 
getCfgNodeLabel(SizeT NodeNumber)342   Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override {
343     assert(NodeNumber < CfgNodeLabels.size());
344     return CfgNodeLabels[NodeNumber];
345   }
346 
getOrCreateCfgNodeLabel(SizeT NodeNumber)347   Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) {
348     return getOrCreateLabel(NodeNumber, CfgNodeLabels);
349   }
350 
getOrCreateLocalLabel(SizeT Number)351   Label *getOrCreateLocalLabel(SizeT Number) {
352     return getOrCreateLabel(Number, LocalLabels);
353   }
354 
bindLocalLabel(const InstMIPS32Label * InstL,SizeT Number)355   void bindLocalLabel(const InstMIPS32Label *InstL, SizeT Number) {
356     if (BuildDefs::dump() && !getFlags().getDisableHybridAssembly()) {
357       constexpr SizeT InstSize = 0;
358       emitTextInst(InstL->getLabelName() + ":", InstSize);
359     }
360     Label *L = getOrCreateLocalLabel(Number);
361     if (!getPreliminary())
362       this->bind(L);
363   }
364 
fixupIsPCRel(FixupKind Kind)365   bool fixupIsPCRel(FixupKind Kind) const override {
366     (void)Kind;
367     return false;
368   }
369 
classof(const Assembler * Asm)370   static bool classof(const Assembler *Asm) {
371     return Asm->getKind() == Asm_MIPS32;
372   }
373 
374 private:
375   ENABLE_MAKE_UNIQUE;
376 
377   using LabelVector = std::vector<Label *>;
378   LabelVector CfgNodeLabels;
379   LabelVector LocalLabels;
380 
381   // Returns the offset encoded in the branch instruction Inst.
382   static IOffsetT decodeBranchOffset(IValueT Inst);
383 
384   Label *getOrCreateLabel(SizeT Number, LabelVector &Labels);
385 
386   void bindCfgNodeLabel(const CfgNode *) override;
387 
emitInst(IValueT Value)388   void emitInst(IValueT Value) {
389     AssemblerBuffer::EnsureCapacity _(&Buffer);
390     Buffer.emit<IValueT>(Value);
391   }
392 };
393 
394 } // end of namespace MIPS32
395 } // end of namespace Ice
396 
397 #endif // SUBZERO_SRC_ICEASSEMBLERMIPS32_H
398