OLD | NEW |
---|---|
1 //===- subzero/src/IceAssemblerMIPS32.cpp - MIPS32 Assembler --------------===// | 1 //===- subzero/src/IceAssemblerMIPS32.cpp - MIPS32 Assembler --------------===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
95 if (BuildDefs::dump() && !getFlags().getDisableHybridAssembly()) { | 95 if (BuildDefs::dump() && !getFlags().getDisableHybridAssembly()) { |
96 constexpr SizeT InstSize = 0; | 96 constexpr SizeT InstSize = 0; |
97 emitTextInst(Node->getAsmName() + ":", InstSize); | 97 emitTextInst(Node->getAsmName() + ":", InstSize); |
98 } | 98 } |
99 SizeT NodeNumber = Node->getIndex(); | 99 SizeT NodeNumber = Node->getIndex(); |
100 assert(!getPreliminary()); | 100 assert(!getPreliminary()); |
101 Label *L = getOrCreateCfgNodeLabel(NodeNumber); | 101 Label *L = getOrCreateCfgNodeLabel(NodeNumber); |
102 this->bind(L); | 102 this->bind(L); |
103 } | 103 } |
104 | 104 |
105 // Checks that Offset can fit in imm16 constant of branch instruction. | 105 // Checks that Offset can fit in imm16 constant of branch instruction. |
Jim Stichnoth
2016/09/15 04:53:45
Can all the code from here down to the note below,
obucinac
2016/09/15 13:35:06
Done.
| |
106 void assertCanEncodeBranchOffset(IOffsetT Offset) { | 106 void assertCanEncodeBranchOffset(IOffsetT Offset) { |
107 (void)Offset; | 107 (void)Offset; |
108 (void)kBranchOffsetBits; | 108 (void)kBranchOffsetBits; |
109 assert(Utils::IsAligned(Offset, 4)); | 109 assert(Utils::IsAligned(Offset, 4)); |
110 assert(Utils::IsInt(kBranchOffsetBits, Offset >> 2)); | 110 assert(Utils::IsInt(kBranchOffsetBits, Offset >> 2)); |
111 } | 111 } |
112 | 112 |
113 IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) { | 113 IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) { |
114 Offset -= kPCReadOffset; | 114 Offset -= kPCReadOffset; |
115 assertCanEncodeBranchOffset(Offset); | 115 assertCanEncodeBranchOffset(Offset); |
(...skipping 23 matching lines...) Expand all Loading... | |
139 } | 139 } |
140 | 140 |
141 enum RegSetWanted { WantGPRegs, WantFPRegs }; | 141 enum RegSetWanted { WantGPRegs, WantFPRegs }; |
142 | 142 |
143 IValueT getEncodedGPRegNum(const Variable *Var) { | 143 IValueT getEncodedGPRegNum(const Variable *Var) { |
144 assert(Var->hasReg()); | 144 assert(Var->hasReg()); |
145 const auto Reg = Var->getRegNum(); | 145 const auto Reg = Var->getRegNum(); |
146 return RegMIPS32::getEncodedGPR(Reg); | 146 return RegMIPS32::getEncodedGPR(Reg); |
147 } | 147 } |
148 | 148 |
149 IValueT getEncodedFPRegNum(const Variable *Var) { | |
150 assert(Var->hasReg()); | |
151 const auto Reg = Var->getRegNum(); | |
152 if (RegMIPS32::isFPRReg(Reg)) { | |
153 return RegMIPS32::getEncodedFPR(Reg); | |
154 } else { | |
Jim Stichnoth
2016/09/15 04:53:45
http://llvm.org/docs/CodingStandards.html#don-t-us
obucinac
2016/09/15 13:35:06
Done.
| |
155 return RegMIPS32::getEncodedFPR64(Reg); | |
156 } | |
157 } | |
158 | |
149 bool encodeOperand(const Operand *Opnd, IValueT &Value, | 159 bool encodeOperand(const Operand *Opnd, IValueT &Value, |
150 RegSetWanted WantedRegSet) { | 160 RegSetWanted WantedRegSet) { |
151 Value = 0; | 161 Value = 0; |
152 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 162 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
153 if (Var->hasReg()) { | 163 if (Var->hasReg()) { |
154 switch (WantedRegSet) { | 164 switch (WantedRegSet) { |
155 case WantGPRegs: | 165 case WantGPRegs: |
156 Value = getEncodedGPRegNum(Var); | 166 Value = getEncodedGPRegNum(Var); |
157 break; | 167 break; |
158 default: | 168 case WantFPRegs: |
169 Value = getEncodedFPRegNum(Var); | |
159 break; | 170 break; |
160 } | 171 } |
161 return true; | 172 return true; |
162 } | 173 } |
163 return false; | 174 return false; |
164 } | 175 } |
165 return false; | 176 return false; |
166 } | 177 } |
167 | 178 |
168 IValueT encodeRegister(const Operand *OpReg, RegSetWanted WantedRegSet, | 179 IValueT encodeRegister(const Operand *OpReg, RegSetWanted WantedRegSet, |
169 const char *RegName, const char *InstName) { | 180 const char *RegName, const char *InstName) { |
170 IValueT Reg = 0; | 181 IValueT Reg = 0; |
171 if (encodeOperand(OpReg, Reg, WantedRegSet) != true) | 182 if (encodeOperand(OpReg, Reg, WantedRegSet) != true) |
172 llvm::report_fatal_error(std::string(InstName) + ": Can't find register " + | 183 llvm::report_fatal_error(std::string(InstName) + ": Can't find register " + |
173 RegName); | 184 RegName); |
174 return Reg; | 185 return Reg; |
175 } | 186 } |
176 | 187 |
177 IValueT encodeGPRegister(const Operand *OpReg, const char *RegName, | 188 IValueT encodeGPRegister(const Operand *OpReg, const char *RegName, |
178 const char *InstName) { | 189 const char *InstName) { |
179 return encodeRegister(OpReg, WantGPRegs, RegName, InstName); | 190 return encodeRegister(OpReg, WantGPRegs, RegName, InstName); |
180 } | 191 } |
181 | 192 |
193 IValueT encodeFPRegister(const Operand *OpReg, const char *RegName, | |
194 const char *InstName) { | |
195 return encodeRegister(OpReg, WantFPRegs, RegName, InstName); | |
196 } | |
197 | |
Jim Stichnoth
2016/09/15 04:53:45
Here's where my proposed anonymous namespace would
obucinac
2016/09/15 13:35:06
Done.
| |
182 void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt, | 198 void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt, |
183 const Operand *OpRs, const uint32_t Imm, | 199 const Operand *OpRs, const uint32_t Imm, |
184 const char *InsnName) { | 200 const char *InsnName) { |
185 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); | 201 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); |
186 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); | 202 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); |
187 | 203 |
188 Opcode |= Rs << 21; | 204 Opcode |= Rs << 21; |
189 Opcode |= Rt << 16; | 205 Opcode |= Rt << 16; |
190 Opcode |= Imm & 0xffff; | 206 Opcode |= Imm & 0xffff; |
191 | 207 |
192 emitInst(Opcode); | 208 emitInst(Opcode); |
193 } | 209 } |
194 | 210 |
211 void AssemblerMIPS32::emitFtRsImm16(IValueT Opcode, const Operand *OpFt, | |
212 const Operand *OpRs, const uint32_t Imm, | |
213 const char *InsnName) { | |
214 const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName); | |
215 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); | |
216 | |
217 Opcode |= Rs << 21; | |
218 Opcode |= Ft << 16; | |
219 Opcode |= Imm & 0xffff; | |
220 | |
221 emitInst(Opcode); | |
222 } | |
223 | |
195 void AssemblerMIPS32::emitRdRtSa(IValueT Opcode, const Operand *OpRd, | 224 void AssemblerMIPS32::emitRdRtSa(IValueT Opcode, const Operand *OpRd, |
196 const Operand *OpRt, const uint32_t Sa, | 225 const Operand *OpRt, const uint32_t Sa, |
197 const char *InsnName) { | 226 const char *InsnName) { |
198 const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName); | 227 const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName); |
199 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); | 228 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); |
200 | 229 |
201 Opcode |= Rt << 16; | 230 Opcode |= Rt << 16; |
202 Opcode |= Rd << 11; | 231 Opcode |= Rd << 11; |
203 Opcode |= (Sa & 0x1f) << 6; | 232 Opcode |= (Sa & 0x1f) << 6; |
204 | 233 |
205 emitInst(Opcode); | 234 emitInst(Opcode); |
206 } | 235 } |
207 | 236 |
208 void AssemblerMIPS32::emitRdRsRt(IValueT Opcode, const Operand *OpRd, | 237 void AssemblerMIPS32::emitRdRsRt(IValueT Opcode, const Operand *OpRd, |
209 const Operand *OpRs, const Operand *OpRt, | 238 const Operand *OpRs, const Operand *OpRt, |
210 const char *InsnName) { | 239 const char *InsnName) { |
211 const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName); | 240 const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName); |
212 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); | 241 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); |
213 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); | 242 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); |
214 | 243 |
215 Opcode |= Rs << 21; | 244 Opcode |= Rs << 21; |
216 Opcode |= Rt << 16; | 245 Opcode |= Rt << 16; |
217 Opcode |= Rd << 11; | 246 Opcode |= Rd << 11; |
218 | 247 |
219 emitInst(Opcode); | 248 emitInst(Opcode); |
220 } | 249 } |
221 | 250 |
251 void AssemblerMIPS32::emitFPFormatFtFsFd( | |
252 IValueT Opcode, FPInstDataFormat Format, const Operand *OpFd, | |
253 const Operand *OpFs, const Operand *OpFt, const char *InsnName) { | |
254 const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName); | |
255 const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName); | |
256 const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName); | |
257 | |
258 Opcode |= Fd << 6; | |
259 Opcode |= Fs << 11; | |
260 Opcode |= Ft << 16; | |
261 Opcode |= Format << 21; | |
262 | |
263 emitInst(Opcode); | |
264 } | |
265 | |
266 void AssemblerMIPS32::add_d(const Operand *OpFd, const Operand *OpFs, | |
267 const Operand *OpFt) { | |
268 static constexpr IValueT Opcode = 0x44000000; | |
269 emitFPFormatFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "add.d"); | |
270 } | |
271 | |
272 void AssemblerMIPS32::add_s(const Operand *OpFd, const Operand *OpFs, | |
273 const Operand *OpFt) { | |
274 static constexpr IValueT Opcode = 0x44000000; | |
275 emitFPFormatFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "add.s"); | |
276 } | |
277 | |
278 void AssemblerMIPS32::div_d(const Operand *OpFd, const Operand *OpFs, | |
279 const Operand *OpFt) { | |
280 static constexpr IValueT Opcode = 0x44000003; | |
281 emitFPFormatFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "div.d"); | |
282 } | |
283 | |
284 void AssemblerMIPS32::div_s(const Operand *OpFd, const Operand *OpFs, | |
285 const Operand *OpFt) { | |
286 static constexpr IValueT Opcode = 0x44000003; | |
287 emitFPFormatFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "div.s"); | |
288 } | |
289 | |
290 void AssemblerMIPS32::mul_d(const Operand *OpFd, const Operand *OpFs, | |
291 const Operand *OpFt) { | |
292 static constexpr IValueT Opcode = 0x44000002; | |
293 emitFPFormatFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "mul.d"); | |
294 } | |
295 | |
296 void AssemblerMIPS32::mul_s(const Operand *OpFd, const Operand *OpFs, | |
297 const Operand *OpFt) { | |
298 static constexpr IValueT Opcode = 0x44000002; | |
299 emitFPFormatFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "mul.s"); | |
300 } | |
301 | |
302 void AssemblerMIPS32::sub_d(const Operand *OpFd, const Operand *OpFs, | |
303 const Operand *OpFt) { | |
304 static constexpr IValueT Opcode = 0x44000001; | |
305 emitFPFormatFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "sub.d"); | |
306 } | |
307 | |
308 void AssemblerMIPS32::sub_s(const Operand *OpFd, const Operand *OpFs, | |
309 const Operand *OpFt) { | |
310 static constexpr IValueT Opcode = 0x44000001; | |
311 emitFPFormatFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "sub.s"); | |
312 } | |
313 | |
222 void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs, | 314 void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs, |
223 const uint32_t Imm) { | 315 const uint32_t Imm) { |
224 static constexpr IValueT Opcode = 0x24000000; | 316 static constexpr IValueT Opcode = 0x24000000; |
225 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu"); | 317 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu"); |
226 } | 318 } |
227 | 319 |
228 void AssemblerMIPS32::slti(const Operand *OpRt, const Operand *OpRs, | 320 void AssemblerMIPS32::slti(const Operand *OpRt, const Operand *OpRs, |
229 const uint32_t Imm) { | 321 const uint32_t Imm) { |
230 static constexpr IValueT Opcode = 0x28000000; | 322 static constexpr IValueT Opcode = 0x28000000; |
231 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "slti"); | 323 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "slti"); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
315 } | 407 } |
316 | 408 |
317 void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs, | 409 void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs, |
318 const Operand *OpRt) { | 410 const Operand *OpRt) { |
319 static constexpr IValueT Opcode = 0x0000002A; | 411 static constexpr IValueT Opcode = 0x0000002A; |
320 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "slt"); | 412 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "slt"); |
321 } | 413 } |
322 | 414 |
323 void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase, | 415 void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase, |
324 const uint32_t Offset) { | 416 const uint32_t Offset) { |
325 static constexpr IValueT Opcode = 0xAC000000; | 417 switch (OpRt->getType()) { |
326 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw"); | 418 case IceType_i1: |
419 case IceType_i8: { | |
420 static constexpr IValueT Opcode = 0xA0000000; | |
421 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sb"); | |
422 break; | |
423 } | |
424 case IceType_i16: { | |
425 static constexpr IValueT Opcode = 0xA4000000; | |
426 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sh"); | |
427 break; | |
428 } | |
429 case IceType_i32: { | |
430 static constexpr IValueT Opcode = 0xAC000000; | |
431 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw"); | |
432 break; | |
433 } | |
434 case IceType_f32: { | |
435 static constexpr IValueT Opcode = 0xE4000000; | |
436 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "swc1"); | |
437 break; | |
438 } | |
439 case IceType_f64: { | |
440 static constexpr IValueT Opcode = 0xF4000000; | |
441 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "sdc1"); | |
442 break; | |
443 } | |
444 default: { UnimplementedError(getFlags()); } | |
445 } | |
327 } | 446 } |
328 | 447 |
329 void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase, | 448 void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase, |
330 const uint32_t Offset) { | 449 const uint32_t Offset) { |
331 static constexpr IValueT Opcode = 0x8C000000; | 450 switch (OpRt->getType()) { |
332 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw"); | 451 case IceType_i1: |
452 case IceType_i8: { | |
453 static constexpr IValueT Opcode = 0x80000000; | |
454 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lb"); | |
455 } | |
456 case IceType_i16: { | |
457 static constexpr IValueT Opcode = 0x84000000; | |
458 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lh"); | |
459 } | |
460 case IceType_i32: { | |
461 static constexpr IValueT Opcode = 0x8C000000; | |
462 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw"); | |
463 break; | |
464 } | |
465 case IceType_f32: { | |
466 static constexpr IValueT Opcode = 0xC4000000; | |
467 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "lwc1"); | |
468 } | |
469 case IceType_f64: { | |
470 static constexpr IValueT Opcode = 0xD4000000; | |
471 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "ldc1"); | |
472 break; | |
473 } | |
474 default: { UnimplementedError(getFlags()); } | |
475 } | |
333 } | 476 } |
334 | 477 |
335 void AssemblerMIPS32::ret(void) { | 478 void AssemblerMIPS32::ret(void) { |
336 static constexpr IValueT Opcode = 0x03E00008; // JR $31 | 479 static constexpr IValueT Opcode = 0x03E00008; // JR $31 |
337 emitInst(Opcode); | 480 emitInst(Opcode); |
338 nop(); // delay slot | 481 nop(); // delay slot |
339 } | 482 } |
340 | 483 |
341 void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs, | 484 void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs, |
342 const Operand *OpRt, IOffsetT Offset) { | 485 const Operand *OpRt, IOffsetT Offset) { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
420 emitBr(Cond, OpRs, OpRtNone, Dest); | 563 emitBr(Cond, OpRs, OpRtNone, Dest); |
421 return; | 564 return; |
422 } | 565 } |
423 const IOffsetT Position = Buffer.size(); | 566 const IOffsetT Position = Buffer.size(); |
424 emitBr(Cond, OpRs, OpRtNone, TargetLabel->getEncodedPosition()); | 567 emitBr(Cond, OpRs, OpRtNone, TargetLabel->getEncodedPosition()); |
425 TargetLabel->linkTo(*this, Position); | 568 TargetLabel->linkTo(*this, Position); |
426 } | 569 } |
427 | 570 |
428 } // end of namespace MIPS32 | 571 } // end of namespace MIPS32 |
429 } // end of namespace Ice | 572 } // end of namespace Ice |
OLD | NEW |