Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(323)

Side by Side Diff: src/IceAssemblerMIPS32.cpp

Issue 2259983004: [SubZero] Generate ELF output for MIPS (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Removed Dart comment Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 //===- subzero/src/IceAssemblerMIPS32.cpp - MIPS32 Assembler --------------===//
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 Implements the Assembler class for MIPS32.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #include "IceAssemblerMIPS32.h"
16 #include "IceCfgNode.h"
17 #include "IceRegistersMIPS32.h"
18 #include "IceUtils.h"
19
20 namespace {
21
22 using namespace Ice;
23 using namespace Ice::MIPS32;
24
25 // Offset modifier to current PC for next instruction.
26 static constexpr IOffsetT kPCReadOffset = 4;
27
28 // Mask to pull out PC offset from branch instruction.
29 static constexpr int kBranchOffsetBits = 16;
30 static constexpr IOffsetT kBranchOffsetMask = 0x0000ffff;
31
32 } // end of anonymous namespace
33
34 namespace Ice {
35 namespace MIPS32 {
36
37 void AssemblerMIPS32::emitTextInst(const std::string &Text, SizeT InstSize) {
38 AssemblerFixup *F = createTextFixup(Text, InstSize);
39 emitFixup(F);
40 for (SizeT I = 0; I < InstSize; ++I) {
41 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
42 Buffer.emit<char>(0);
43 }
44 }
45
46 namespace {
47
48 // TEQ $0, $0 - Trap if equal
49 static constexpr uint8_t TrapBytesRaw[] = {0x00, 0x00, 0x00, 0x34};
50
51 const auto TrapBytes =
52 llvm::ArrayRef<uint8_t>(TrapBytesRaw, llvm::array_lengthof(TrapBytesRaw));
53
54 } // end of anonymous namespace
55
56 llvm::ArrayRef<uint8_t> AssemblerMIPS32::getNonExecBundlePadding() const {
57 return TrapBytes;
58 }
59
60 void AssemblerMIPS32::trap() {
61 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
62 for (const uint8_t &Byte : reverse_range(TrapBytes))
63 Buffer.emit<uint8_t>(Byte);
64 }
65
66 void AssemblerMIPS32::nop() { emitInst(0); }
67
68 void AssemblerMIPS32::padWithNop(intptr_t Padding) {
69 constexpr intptr_t InstWidth = sizeof(IValueT);
70 assert(Padding % InstWidth == 0 &&
71 "Padding not multiple of instruction size");
72 for (intptr_t i = 0; i < Padding; i += InstWidth)
73 nop();
74 }
75
76 Label *AssemblerMIPS32::getOrCreateLabel(SizeT Number, LabelVector &Labels) {
77 Label *L = nullptr;
78 if (Number == Labels.size()) {
79 L = new (this->allocate<Label>()) Label();
80 Labels.push_back(L);
81 return L;
82 }
83 if (Number > Labels.size()) {
84 Labels.resize(Number + 1);
85 }
86 L = Labels[Number];
87 if (L == nullptr) {
88 L = new (this->allocate<Label>()) Label();
89 Labels[Number] = L;
90 }
91 return L;
92 }
93
94 void AssemblerMIPS32::bindCfgNodeLabel(const CfgNode *Node) {
95 if (BuildDefs::dump() && !getFlags().getDisableHybridAssembly()) {
96 constexpr SizeT InstSize = 0;
97 emitTextInst(Node->getAsmName() + ":", InstSize);
98 }
99 SizeT NodeNumber = Node->getIndex();
100 assert(!getPreliminary());
101 Label *L = getOrCreateCfgNodeLabel(NodeNumber);
102 this->bind(L);
103 }
104
105 // Checks that Offset can fit in imm16 constant of branch instruction.
106 void assertCanEncodeBranchOffset(IOffsetT Offset) {
107 (void)Offset;
108 (void)kBranchOffsetBits;
109 assert(Utils::IsAligned(Offset, 4));
110 assert(Utils::IsInt(kBranchOffsetBits, Offset >> 2));
111 }
112
113 IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) {
114 Offset -= kPCReadOffset;
115 assertCanEncodeBranchOffset(Offset);
116 Offset >>= 2;
117 Offset &= kBranchOffsetMask;
118 return (Inst & ~kBranchOffsetMask) | Offset;
119 }
120
121 IOffsetT AssemblerMIPS32::decodeBranchOffset(IValueT Inst) {
122 int16_t imm = (Inst & kBranchOffsetMask);
123 IOffsetT Offset = imm;
124 Offset = Offset << 2;
125 return (Offset + kPCReadOffset);
126 }
127
128 void AssemblerMIPS32::bind(Label *L) {
129 IOffsetT BoundPc = Buffer.size();
130 assert(!L->isBound()); // Labels can only be bound once.
131 while (L->isLinked()) {
132 IOffsetT Position = L->getLinkPosition();
133 IOffsetT Dest = BoundPc - Position;
134 IValueT Inst = Buffer.load<IValueT>(Position);
135 Buffer.store<IValueT>(Position, encodeBranchOffset(Dest, Inst));
136 L->setPosition(decodeBranchOffset(Inst));
137 }
138 L->bindTo(BoundPc);
139 }
140
141 enum RegSetWanted { WantGPRegs, WantFPRegs };
142
143 IValueT getEncodedGPRegNum(const Variable *Var) {
144 assert(Var->hasReg());
145 const auto Reg = Var->getRegNum();
146 return RegMIPS32::getEncodedGPR(Reg);
147 }
148
149 bool encodeOperand(const Operand *Opnd, IValueT &Value,
150 RegSetWanted WantedRegSet) {
151 Value = 0;
152 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
153 if (Var->hasReg()) {
154 switch (WantedRegSet) {
155 case WantGPRegs:
156 Value = getEncodedGPRegNum(Var);
157 break;
158 default:
159 break;
160 }
161 return true;
162 }
163 return false;
164 }
165 return false;
166 }
167
168 IValueT encodeRegister(const Operand *OpReg, RegSetWanted WantedRegSet,
169 const char *RegName, const char *InstName) {
170 IValueT Reg = 0;
171 if (encodeOperand(OpReg, Reg, WantedRegSet) != true)
172 llvm::report_fatal_error(std::string(InstName) + ": Can't find register " +
173 RegName);
174 return Reg;
175 }
176
177 IValueT encodeGPRegister(const Operand *OpReg, const char *RegName,
178 const char *InstName) {
179 return encodeRegister(OpReg, WantGPRegs, RegName, InstName);
180 }
181
182 void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt,
183 const Operand *OpRs, const uint32_t Imm,
184 const char *InsnName) {
185 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
186 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
187
188 Opcode |= Rs << 21;
189 Opcode |= Rt << 16;
190 Opcode |= Imm & 0xffff;
191
192 emitInst(Opcode);
193 }
194
195 void AssemblerMIPS32::emitRdRtSa(IValueT Opcode, const Operand *OpRd,
196 const Operand *OpRt, const uint32_t Sa,
197 const char *InsnName) {
198 const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName);
199 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
200
201 Opcode |= Rt << 16;
202 Opcode |= Rd << 11;
203 Opcode |= (Sa & 0x1f) << 6;
204
205 emitInst(Opcode);
206 }
207
208 void AssemblerMIPS32::emitRdRsRt(IValueT Opcode, const Operand *OpRd,
209 const Operand *OpRs, const Operand *OpRt,
210 const char *InsnName) {
211 const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName);
212 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
213 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
214
215 Opcode |= Rs << 21;
216 Opcode |= Rt << 16;
217 Opcode |= Rd << 11;
218
219 emitInst(Opcode);
220 }
221
222 void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs,
223 const uint32_t Imm) {
224 static constexpr IValueT Opcode = 0x24000000;
225 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu");
226 }
227
228 void AssemblerMIPS32::slti(const Operand *OpRt, const Operand *OpRs,
229 const uint32_t Imm) {
230 static constexpr IValueT Opcode = 0x28000000;
231 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "slti");
232 }
233
234 void AssemblerMIPS32::sltiu(const Operand *OpRt, const Operand *OpRs,
235 const uint32_t Imm) {
236 static constexpr IValueT Opcode = 0x2c000000;
237 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "sltiu");
238 }
239
240 void AssemblerMIPS32::and_(const Operand *OpRd, const Operand *OpRs,
241 const Operand *OpRt) {
242 static constexpr IValueT Opcode = 0x00000024;
243 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "and");
244 }
245
246 void AssemblerMIPS32::andi(const Operand *OpRt, const Operand *OpRs,
247 const uint32_t Imm) {
248 static constexpr IValueT Opcode = 0x30000000;
249 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "andi");
250 }
251
252 void AssemblerMIPS32::or_(const Operand *OpRd, const Operand *OpRs,
253 const Operand *OpRt) {
254 static constexpr IValueT Opcode = 0x00000025;
255 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "or");
256 }
257
258 void AssemblerMIPS32::ori(const Operand *OpRt, const Operand *OpRs,
259 const uint32_t Imm) {
260 static constexpr IValueT Opcode = 0x34000000;
261 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "ori");
262 }
263
264 void AssemblerMIPS32::xor_(const Operand *OpRd, const Operand *OpRs,
265 const Operand *OpRt) {
266 static constexpr IValueT Opcode = 0x00000026;
267 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "xor");
268 }
269
270 void AssemblerMIPS32::xori(const Operand *OpRt, const Operand *OpRs,
271 const uint32_t Imm) {
272 static constexpr IValueT Opcode = 0x38000000;
273 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "xori");
274 }
275
276 void AssemblerMIPS32::sll(const Operand *OpRd, const Operand *OpRt,
277 const uint32_t Sa) {
278 static constexpr IValueT Opcode = 0x00000000;
279 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sll");
280 }
281
282 void AssemblerMIPS32::srl(const Operand *OpRd, const Operand *OpRt,
283 const uint32_t Sa) {
284 static constexpr IValueT Opcode = 0x00000002;
285 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "srl");
286 }
287
288 void AssemblerMIPS32::sra(const Operand *OpRd, const Operand *OpRt,
289 const uint32_t Sa) {
290 static constexpr IValueT Opcode = 0x00000003;
291 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sra");
292 }
293
294 void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) {
295 IValueT Opcode = 0x00000021;
296 const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move");
297 const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move");
298 const IValueT Rt = 0; // $0
299 Opcode |= Rs << 21;
300 Opcode |= Rt << 16;
301 Opcode |= Rd << 11;
302 emitInst(Opcode);
303 }
304
305 void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs,
306 const Operand *OpRt) {
307 static constexpr IValueT Opcode = 0x00000021;
308 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "addu");
309 }
310
311 void AssemblerMIPS32::sltu(const Operand *OpRd, const Operand *OpRs,
312 const Operand *OpRt) {
313 static constexpr IValueT Opcode = 0x0000002B;
314 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sltu");
315 }
316
317 void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs,
318 const Operand *OpRt) {
319 static constexpr IValueT Opcode = 0x0000002A;
320 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "slt");
321 }
322
323 void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase,
324 const uint32_t Offset) {
325 static constexpr IValueT Opcode = 0xAC000000;
326 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw");
327 }
328
329 void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase,
330 const uint32_t Offset) {
331 static constexpr IValueT Opcode = 0x8C000000;
332 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw");
333 }
334
335 void AssemblerMIPS32::ret(void) {
336 static constexpr IValueT Opcode = 0x03E00008; // JR $31
337 emitInst(Opcode);
338 nop(); // delay slot
339 }
340
341 void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs,
342 const Operand *OpRt, IOffsetT Offset) {
343 IValueT Opcode = 0;
344
345 switch (Cond) {
346 default:
347 break;
348 case CondMIPS32::AL:
349 case CondMIPS32::EQ:
350 case CondMIPS32::EQZ:
351 Opcode = 0x10000000;
352 break;
353 case CondMIPS32::NE:
354 case CondMIPS32::NEZ:
355 Opcode = 0x14000000;
356 break;
357 case CondMIPS32::LEZ:
358 Opcode = 0x18000000;
359 break;
360 case CondMIPS32::LTZ:
361 Opcode = 0x04000000;
362 break;
363 case CondMIPS32::GEZ:
364 Opcode = 0x04010000;
365 break;
366 case CondMIPS32::GTZ:
367 Opcode = 0x1C000000;
368 break;
369 }
370
371 if (Opcode == 0) {
372 llvm::report_fatal_error("Branch: Invalid condition");
373 }
374
375 if (OpRs != nullptr) {
376 IValueT Rs = encodeGPRegister(OpRs, "Rs", "branch");
377 Opcode |= Rs << 21;
378 }
379
380 if (OpRt != nullptr) {
381 IValueT Rt = encodeGPRegister(OpRt, "Rt", "branch");
382 Opcode |= Rt << 16;
383 }
384
385 Opcode = encodeBranchOffset(Offset, Opcode);
386 emitInst(Opcode);
387 nop(); // delay slot
388 }
389
390 void AssemblerMIPS32::b(Label *TargetLabel) {
391 static constexpr Operand *OpRsNone = nullptr;
392 static constexpr Operand *OpRtNone = nullptr;
393 if (TargetLabel->isBound()) {
394 const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
395 emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, Dest);
396 return;
397 }
398 const IOffsetT Position = Buffer.size();
399 emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, TargetLabel->getEncodedPosition());
400 TargetLabel->linkTo(*this, Position);
401 }
402
403 void AssemblerMIPS32::bcc(const CondMIPS32::Cond Cond, const Operand *OpRs,
404 const Operand *OpRt, Label *TargetLabel) {
405 if (TargetLabel->isBound()) {
406 const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
407 emitBr(Cond, OpRs, OpRt, Dest);
408 return;
409 }
410 const IOffsetT Position = Buffer.size();
411 emitBr(Cond, OpRs, OpRt, TargetLabel->getEncodedPosition());
412 TargetLabel->linkTo(*this, Position);
413 }
414
415 void AssemblerMIPS32::bzc(const CondMIPS32::Cond Cond, const Operand *OpRs,
416 Label *TargetLabel) {
417 static constexpr Operand *OpRtNone = nullptr;
418 if (TargetLabel->isBound()) {
419 const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
420 emitBr(Cond, OpRs, OpRtNone, Dest);
421 return;
422 }
423 const IOffsetT Position = Buffer.size();
424 emitBr(Cond, OpRs, OpRtNone, TargetLabel->getEncodedPosition());
425 TargetLabel->linkTo(*this, Position);
426 }
427
428 } // end of namespace MIPS32
429 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceAssemblerMIPS32.h ('k') | src/IceInstMIPS32.h » ('j') | src/IceInstMIPS32.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698