blob: 898a0746766a1fe6e9ca388afe1293c901ef5e29 [file] [log] [blame]
John Porto2da710c2015-06-29 07:57:02 -07001//===- subzero/src/IceAssemblerMIPS32.h - Assembler for MIPS ----*- C++ -*-===//
Jim Stichnoth6da4cef2015-06-11 13:26:33 -07002//
Jim Stichnoth6da4cef2015-06-11 13:26:33 -07003// 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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Declares the Assembler class for MIPS32.
Andrew Scull9612d322015-07-06 14:53:25 -070012///
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070013//===----------------------------------------------------------------------===//
14
John Porto2da710c2015-06-29 07:57:02 -070015#ifndef SUBZERO_SRC_ICEASSEMBLERMIPS32_H
16#define SUBZERO_SRC_ICEASSEMBLERMIPS32_H
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070017
18#include "IceAssembler.h"
19#include "IceDefs.h"
20#include "IceFixups.h"
Jaydeep Patil135f5db2016-08-29 05:14:05 -070021#include "IceInstMIPS32.h"
22#include "IceTargetLowering.h"
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070023
24namespace Ice {
25namespace MIPS32 {
26
Jaydeep Patil135f5db2016-08-29 05:14:05 -070027using IValueT = uint32_t;
28using IOffsetT = int32_t;
29
Srdjan Obucina132ea7a2016-09-18 07:30:19 -070030enum FPInstDataFormat {
31 SinglePrecision = 16,
32 DoublePrecision = 17,
33 Word = 20,
34 Long = 21
35};
36
Jaydeep Patil130aca72016-10-28 05:30:54 -070037class MIPS32Fixup final : public AssemblerFixup {
38 MIPS32Fixup &operator=(const MIPS32Fixup &) = delete;
39 MIPS32Fixup(const MIPS32Fixup &) = default;
40
41public:
42 MIPS32Fixup() = default;
43 size_t emit(GlobalContext *Ctx, const Assembler &Asm) const final;
44 void emitOffset(Assembler *Asm) const;
45};
46
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070047class AssemblerMIPS32 : public Assembler {
48 AssemblerMIPS32(const AssemblerMIPS32 &) = delete;
49 AssemblerMIPS32 &operator=(const AssemblerMIPS32 &) = delete;
50
51public:
Jim Stichnoth5bff61c2015-10-28 09:26:00 -070052 explicit AssemblerMIPS32(bool use_far_branches = false)
53 : Assembler(Asm_MIPS32) {
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070054 // This mode is only needed and implemented for MIPS32 and ARM.
55 assert(!use_far_branches);
56 (void)use_far_branches;
57 }
Jaydeep Patil135f5db2016-08-29 05:14:05 -070058 ~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
Jaydeep Patil130aca72016-10-28 05:30:54 -070069 MIPS32Fixup *createMIPS32Fixup(const RelocOp Reloc, const Constant *RelOp);
70
Jaydeep Patil135f5db2016-08-29 05:14:05 -070071 void trap();
72
73 void nop();
74
Srdjan Obucina623f8ce2016-09-26 20:03:20 -070075 void emitRsRt(IValueT Opcode, const Operand *OpRs, const Operand *OpRt,
76 const char *InsnName);
77
Jaydeep Patil135f5db2016-08-29 05:14:05 -070078 void emitRtRsImm16(IValueT Opcode, const Operand *OpRt, const Operand *OpRs,
Srdjan Obucina132ea7a2016-09-18 07:30:19 -070079 uint32_t Imm, const char *InsnName);
80
Jaydeep Patil130aca72016-10-28 05:30:54 -070081 void emitRtRsImm16Rel(IValueT Opcode, const Operand *OpRt,
82 const Operand *OpRs, const Operand *OpImm,
83 const RelocOp Reloc, const char *InsnName);
84
Srdjan Obucina132ea7a2016-09-18 07:30:19 -070085 void emitFtRsImm16(IValueT Opcode, const Operand *OpFt, const Operand *OpRs,
86 uint32_t Imm, const char *InsnName);
Jaydeep Patil135f5db2016-08-29 05:14:05 -070087
88 void emitRdRtSa(IValueT Opcode, const Operand *OpRd, const Operand *OpRt,
Srdjan Obucina132ea7a2016-09-18 07:30:19 -070089 uint32_t Sa, const char *InsnName);
Jaydeep Patil135f5db2016-08-29 05:14:05 -070090
91 void emitRdRsRt(IValueT Opcode, const Operand *OpRd, const Operand *OpRs,
92 const Operand *OpRt, const char *InsnName);
93
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -070094 void emitCOP1Fcmp(IValueT Opcode, FPInstDataFormat Format,
95 const Operand *OpFs, const Operand *OpFt, IValueT CC,
96 const char *InsnName);
97
Srdjan Obucina132ea7a2016-09-18 07:30:19 -070098 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
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700113 void emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs,
114 const Operand *OpRt, IOffsetT Offset);
115
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700116 void abs_d(const Operand *OpFd, const Operand *OpFs);
117
118 void abs_s(const Operand *OpFd, const Operand *OpFs);
119
Jaydeep Patil130aca72016-10-28 05:30:54 -0700120 void addi(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
121
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700122 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
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700128 void addiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
129
Jaydeep Patil130aca72016-10-28 05:30:54 -0700130 void addiu(const Operand *OpRt, const Operand *OpRs, const Operand *OpImm,
131 const RelocOp Reloc);
132
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700133 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
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700137 void b(Label *TargetLabel);
138
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -0700139 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
Srdjan Obucinad27ce3d2016-09-22 12:56:12 -0700167 void clz(const Operand *OpRd, const Operand *OpRs);
168
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700169 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
Srdjan Obucina623f8ce2016-09-26 20:03:20 -0700181 void div(const Operand *OpRs, const Operand *OpRt);
182
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700183 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
Srdjan Obucina6163c622016-09-27 20:38:30 -0700187 void divu(const Operand *OpRs, const Operand *OpRt);
188
Jaydeep Patil130aca72016-10-28 05:30:54 -0700189 void jal(const ConstantRelocatable *Target);
190
Jaydeep Patil0c4c07d2016-11-01 23:53:52 -0700191 void jalr(const Operand *OpRs, const Operand *OpRd);
192
Jaydeep Patil130aca72016-10-28 05:30:54 -0700193 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);
Srdjan Obucina623f8ce2016-09-26 20:03:20 -0700197
Sagar Thakurbecb85f2016-11-18 12:15:46 -0800198 void ll(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
199
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700200 void lw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
201
Jaydeep Patil130aca72016-10-28 05:30:54 -0700202 void lwc1(const Operand *OpRt, const Operand *OpBase, const Operand *OpOff,
203 const RelocOp Reloc);
204
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700205 void mfc1(const Operand *OpRt, const Operand *OpFs);
206
Srdjan Obucina623f8ce2016-09-26 20:03:20 -0700207 void mfhi(const Operand *OpRd);
208
209 void mflo(const Operand *OpRd);
210
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700211 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
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -0700217 void movf(const Operand *OpRd, const Operand *OpRs, const Operand *OpCc);
218
Srdjan Obucinad27ce3d2016-09-22 12:56:12 -0700219 void movn(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
220
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700221 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
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -0700225 void movt(const Operand *OpRd, const Operand *OpRs, const Operand *OpCc);
226
Srdjan Obucinab0f09fc2016-09-27 20:43:11 -0700227 void movz(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
228
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700229 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
Srdjan Obucina623f8ce2016-09-26 20:03:20 -0700235 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
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700241 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
Jaydeep Patil130aca72016-10-28 05:30:54 -0700245 void mult(const Operand *OpRs, const Operand *OpRt);
246
Srdjan Obucina623f8ce2016-09-26 20:03:20 -0700247 void multu(const Operand *OpRs, const Operand *OpRt);
248
Srdjan Obucinacadda792016-09-22 11:24:44 -0700249 void nor(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
250
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700251 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
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700255 void ret(void);
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700256
Sagar Thakurbecb85f2016-11-18 12:15:46 -0800257 void sc(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
258
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700259 void sll(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
260
Srdjan Obucina623f8ce2016-09-26 20:03:20 -0700261 void sllv(const Operand *OpRd, const Operand *OpRt, const Operand *OpRs);
262
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700263 void slt(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
264
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700265 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
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700269 void sltu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
270
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700271 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
Srdjan Obucinafe93fdd2016-09-28 06:38:44 -0700277 void srav(const Operand *OpRd, const Operand *OpRt, const Operand *OpRs);
278
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700279 void srl(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
280
Srdjan Obucina623f8ce2016-09-26 20:03:20 -0700281 void srlv(const Operand *OpRd, const Operand *OpRt, const Operand *OpRs);
282
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700283 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
Srdjan Obucina0a7f99d2016-09-23 06:59:50 -0700287 void subu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
288
Jaydeep Patil130aca72016-10-28 05:30:54 -0700289 void sdc1(const Operand *OpRt, const Operand *OpBase, const Operand *OpOff,
290 const RelocOp Reloc);
291
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700292 void sw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
293
Jaydeep Patil130aca72016-10-28 05:30:54 -0700294 void swc1(const Operand *OpRt, const Operand *OpBase, const Operand *OpOff,
295 const RelocOp Reloc);
296
Sagar Thakurbecb85f2016-11-18 12:15:46 -0800297 void sync();
298
Srdjan Obucina3b61d702016-09-20 06:49:52 -0700299 void teq(const Operand *OpRs, const Operand *OpRt, const uint32_t TrapCode);
300
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700301 void trunc_l_d(const Operand *OpFd, const Operand *OpFs);
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700302
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700303 void trunc_l_s(const Operand *OpFd, const Operand *OpFs);
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700304
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700305 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);
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700312
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);
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700318
319 void alignFunction() override {
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700320 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 }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700328 }
329
330 SizeT getBundleAlignLog2Bytes() const override { return 4; }
331
Andrew Scull86df4e92015-07-30 13:54:44 -0700332 const char *getAlignDirective() const override { return ".p2alignl"; }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700333
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700334 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700335
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700336 void padWithNop(intptr_t Padding) override;
337
338 void bind(Label *label);
339
340 void emitTextInst(const std::string &Text, SizeT InstSize);
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700341
Jan Voungc2ec5812015-08-05 09:35:18 -0700342 Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override {
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700343 assert(NodeNumber < CfgNodeLabels.size());
344 return CfgNodeLabels[NodeNumber];
Andrew Scull86df4e92015-07-30 13:54:44 -0700345 }
346
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700347 Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) {
348 return getOrCreateLabel(NodeNumber, CfgNodeLabels);
349 }
350
351 Label *getOrCreateLocalLabel(SizeT Number) {
352 return getOrCreateLabel(Number, LocalLabels);
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700353 }
354
Jaydeep Patil58eeedf2016-09-26 20:48:18 -0700355 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
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700365 bool fixupIsPCRel(FixupKind Kind) const override {
366 (void)Kind;
Jaydeep Patil130aca72016-10-28 05:30:54 -0700367 return false;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700368 }
John Porto2da710c2015-06-29 07:57:02 -0700369
370 static bool classof(const Assembler *Asm) {
371 return Asm->getKind() == Asm_MIPS32;
372 }
John Porto53611e22015-12-30 07:30:10 -0800373
374private:
375 ENABLE_MAKE_UNIQUE;
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700376
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
388 void emitInst(IValueT Value) {
389 AssemblerBuffer::EnsureCapacity _(&Buffer);
390 Buffer.emit<IValueT>(Value);
391 }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700392};
393
394} // end of namespace MIPS32
395} // end of namespace Ice
396
John Porto2da710c2015-06-29 07:57:02 -0700397#endif // SUBZERO_SRC_ICEASSEMBLERMIPS32_H