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 namespace { | |
106 | |
105 // Checks that Offset can fit in imm16 constant of branch instruction. | 107 // Checks that Offset can fit in imm16 constant of branch instruction. |
106 void assertCanEncodeBranchOffset(IOffsetT Offset) { | 108 void assertCanEncodeBranchOffset(IOffsetT Offset) { |
107 (void)Offset; | 109 (void)Offset; |
108 (void)kBranchOffsetBits; | 110 (void)kBranchOffsetBits; |
109 assert(Utils::IsAligned(Offset, 4)); | 111 assert(Utils::IsAligned(Offset, 4)); |
110 assert(Utils::IsInt(kBranchOffsetBits, Offset >> 2)); | 112 assert(Utils::IsInt(kBranchOffsetBits, Offset >> 2)); |
111 } | 113 } |
112 | 114 |
113 IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) { | 115 IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) { |
114 Offset -= kPCReadOffset; | 116 Offset -= kPCReadOffset; |
115 assertCanEncodeBranchOffset(Offset); | 117 assertCanEncodeBranchOffset(Offset); |
116 Offset >>= 2; | 118 Offset >>= 2; |
117 Offset &= kBranchOffsetMask; | 119 Offset &= kBranchOffsetMask; |
118 return (Inst & ~kBranchOffsetMask) | Offset; | 120 return (Inst & ~kBranchOffsetMask) | Offset; |
119 } | 121 } |
120 | 122 |
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 }; | 123 enum RegSetWanted { WantGPRegs, WantFPRegs }; |
142 | 124 |
143 IValueT getEncodedGPRegNum(const Variable *Var) { | 125 IValueT getEncodedGPRegNum(const Variable *Var) { |
144 assert(Var->hasReg()); | 126 assert(Var->hasReg() && isScalarIntegerType(Var->getType())); |
145 const auto Reg = Var->getRegNum(); | 127 const auto Reg = Var->getRegNum(); |
146 return RegMIPS32::getEncodedGPR(Reg); | 128 return RegMIPS32::getEncodedGPR(Reg); |
147 } | 129 } |
148 | 130 |
131 IValueT getEncodedFPRegNum(const Variable *Var) { | |
132 assert(Var->hasReg() && isScalarFloatingType(Var->getType())); | |
133 const auto Reg = Var->getRegNum(); | |
134 IValueT RegEncoding; | |
135 if (RegMIPS32::isFPRReg(Reg)) { | |
136 RegEncoding = RegMIPS32::getEncodedFPR(Reg); | |
137 } else { | |
138 RegEncoding = RegMIPS32::getEncodedFPR64(Reg); | |
139 } | |
140 return RegEncoding; | |
141 } | |
142 | |
149 bool encodeOperand(const Operand *Opnd, IValueT &Value, | 143 bool encodeOperand(const Operand *Opnd, IValueT &Value, |
150 RegSetWanted WantedRegSet) { | 144 RegSetWanted WantedRegSet) { |
151 Value = 0; | 145 Value = 0; |
152 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 146 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
153 if (Var->hasReg()) { | 147 if (Var->hasReg()) { |
154 switch (WantedRegSet) { | 148 switch (WantedRegSet) { |
155 case WantGPRegs: | 149 case WantGPRegs: |
156 Value = getEncodedGPRegNum(Var); | 150 Value = getEncodedGPRegNum(Var); |
157 break; | 151 break; |
158 default: | 152 case WantFPRegs: |
153 Value = getEncodedFPRegNum(Var); | |
159 break; | 154 break; |
160 } | 155 } |
161 return true; | 156 return true; |
162 } | 157 } |
163 return false; | 158 return false; |
164 } | 159 } |
165 return false; | 160 return false; |
166 } | 161 } |
167 | 162 |
168 IValueT encodeRegister(const Operand *OpReg, RegSetWanted WantedRegSet, | 163 IValueT encodeRegister(const Operand *OpReg, RegSetWanted WantedRegSet, |
169 const char *RegName, const char *InstName) { | 164 const char *RegName, const char *InstName) { |
170 IValueT Reg = 0; | 165 IValueT Reg = 0; |
171 if (encodeOperand(OpReg, Reg, WantedRegSet) != true) | 166 if (encodeOperand(OpReg, Reg, WantedRegSet) != true) |
172 llvm::report_fatal_error(std::string(InstName) + ": Can't find register " + | 167 llvm::report_fatal_error(std::string(InstName) + ": Can't find register " + |
173 RegName); | 168 RegName); |
174 return Reg; | 169 return Reg; |
175 } | 170 } |
176 | 171 |
177 IValueT encodeGPRegister(const Operand *OpReg, const char *RegName, | 172 IValueT encodeGPRegister(const Operand *OpReg, const char *RegName, |
178 const char *InstName) { | 173 const char *InstName) { |
179 return encodeRegister(OpReg, WantGPRegs, RegName, InstName); | 174 return encodeRegister(OpReg, WantGPRegs, RegName, InstName); |
180 } | 175 } |
181 | 176 |
177 IValueT encodeFPRegister(const Operand *OpReg, const char *RegName, | |
178 const char *InstName) { | |
179 return encodeRegister(OpReg, WantFPRegs, RegName, InstName); | |
180 } | |
181 } | |
Jim Stichnoth
2016/09/16 03:25:00
// end of anonymous namespace
| |
182 | |
183 IOffsetT AssemblerMIPS32::decodeBranchOffset(IValueT Inst) { | |
184 int16_t imm = (Inst & kBranchOffsetMask); | |
185 IOffsetT Offset = imm; | |
186 Offset = Offset << 2; | |
187 return (Offset + kPCReadOffset); | |
188 } | |
189 | |
190 void AssemblerMIPS32::bind(Label *L) { | |
191 IOffsetT BoundPc = Buffer.size(); | |
192 assert(!L->isBound()); // Labels can only be bound once. | |
193 while (L->isLinked()) { | |
194 IOffsetT Position = L->getLinkPosition(); | |
195 IOffsetT Dest = BoundPc - Position; | |
196 IValueT Inst = Buffer.load<IValueT>(Position); | |
197 Buffer.store<IValueT>(Position, encodeBranchOffset(Dest, Inst)); | |
198 L->setPosition(decodeBranchOffset(Inst)); | |
199 } | |
200 L->bindTo(BoundPc); | |
201 } | |
202 | |
182 void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt, | 203 void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt, |
183 const Operand *OpRs, const uint32_t Imm, | 204 const Operand *OpRs, const uint32_t Imm, |
184 const char *InsnName) { | 205 const char *InsnName) { |
185 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); | 206 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); |
186 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); | 207 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); |
187 | 208 |
188 Opcode |= Rs << 21; | 209 Opcode |= Rs << 21; |
189 Opcode |= Rt << 16; | 210 Opcode |= Rt << 16; |
190 Opcode |= Imm & 0xffff; | 211 Opcode |= Imm & 0xffff; |
191 | 212 |
192 emitInst(Opcode); | 213 emitInst(Opcode); |
193 } | 214 } |
194 | 215 |
216 void AssemblerMIPS32::emitFtRsImm16(IValueT Opcode, const Operand *OpFt, | |
217 const Operand *OpRs, const uint32_t Imm, | |
218 const char *InsnName) { | |
219 const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName); | |
220 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); | |
221 | |
222 Opcode |= Rs << 21; | |
223 Opcode |= Ft << 16; | |
224 Opcode |= Imm & 0xffff; | |
225 | |
226 emitInst(Opcode); | |
227 } | |
228 | |
195 void AssemblerMIPS32::emitRdRtSa(IValueT Opcode, const Operand *OpRd, | 229 void AssemblerMIPS32::emitRdRtSa(IValueT Opcode, const Operand *OpRd, |
196 const Operand *OpRt, const uint32_t Sa, | 230 const Operand *OpRt, const uint32_t Sa, |
197 const char *InsnName) { | 231 const char *InsnName) { |
198 const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName); | 232 const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName); |
199 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); | 233 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); |
200 | 234 |
201 Opcode |= Rt << 16; | 235 Opcode |= Rt << 16; |
202 Opcode |= Rd << 11; | 236 Opcode |= Rd << 11; |
203 Opcode |= (Sa & 0x1f) << 6; | 237 Opcode |= (Sa & 0x1f) << 6; |
204 | 238 |
205 emitInst(Opcode); | 239 emitInst(Opcode); |
206 } | 240 } |
207 | 241 |
208 void AssemblerMIPS32::emitRdRsRt(IValueT Opcode, const Operand *OpRd, | 242 void AssemblerMIPS32::emitRdRsRt(IValueT Opcode, const Operand *OpRd, |
209 const Operand *OpRs, const Operand *OpRt, | 243 const Operand *OpRs, const Operand *OpRt, |
210 const char *InsnName) { | 244 const char *InsnName) { |
211 const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName); | 245 const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName); |
212 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); | 246 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); |
213 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); | 247 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); |
214 | 248 |
215 Opcode |= Rs << 21; | 249 Opcode |= Rs << 21; |
216 Opcode |= Rt << 16; | 250 Opcode |= Rt << 16; |
217 Opcode |= Rd << 11; | 251 Opcode |= Rd << 11; |
218 | 252 |
219 emitInst(Opcode); | 253 emitInst(Opcode); |
220 } | 254 } |
221 | 255 |
256 void AssemblerMIPS32::emitCOP1FmtFsFd(IValueT Opcode, FPInstDataFormat Format, | |
257 const Operand *OpFd, const Operand *OpFs, | |
258 const char *InsnName) { | |
259 const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName); | |
260 const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName); | |
261 | |
262 Opcode |= Fd << 6; | |
263 Opcode |= Fs << 11; | |
264 Opcode |= Format << 21; | |
265 | |
266 emitInst(Opcode); | |
267 } | |
268 | |
269 void AssemblerMIPS32::emitCOP1FmtFtFsFd(IValueT Opcode, FPInstDataFormat Format, | |
270 const Operand *OpFd, | |
271 const Operand *OpFs, | |
272 const Operand *OpFt, | |
273 const char *InsnName) { | |
274 const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName); | |
275 const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName); | |
276 const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName); | |
277 | |
278 Opcode |= Fd << 6; | |
279 Opcode |= Fs << 11; | |
280 Opcode |= Ft << 16; | |
281 Opcode |= Format << 21; | |
282 | |
283 emitInst(Opcode); | |
284 } | |
285 | |
286 void AssemblerMIPS32::emitCOP1FmtRtFsFd(IValueT Opcode, FPInstDataFormat Format, | |
287 const Operand *OpFd, | |
288 const Operand *OpFs, | |
289 const Operand *OpRt, | |
290 const char *InsnName) { | |
291 const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName); | |
292 const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName); | |
293 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); | |
294 | |
295 Opcode |= Fd << 6; | |
296 Opcode |= Fs << 11; | |
297 Opcode |= Rt << 16; | |
298 Opcode |= Format << 21; | |
299 | |
300 emitInst(Opcode); | |
301 } | |
302 | |
303 void AssemblerMIPS32::emitCOP1MovRtFs(IValueT Opcode, const Operand *OpRt, | |
304 const Operand *OpFs, | |
305 const char *InsnName) { | |
306 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); | |
307 const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName); | |
308 Opcode |= Fs << 11; | |
309 Opcode |= Rt << 16; | |
310 | |
311 emitInst(Opcode); | |
312 } | |
313 | |
314 void AssemblerMIPS32::abs_d(const Operand *OpFd, const Operand *OpFs) { | |
315 static constexpr IValueT Opcode = 0x44000005; | |
316 emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "abs.d"); | |
317 } | |
318 | |
319 void AssemblerMIPS32::abs_s(const Operand *OpFd, const Operand *OpFs) { | |
320 static constexpr IValueT Opcode = 0x44000005; | |
321 emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "abs.s"); | |
322 } | |
323 | |
324 void AssemblerMIPS32::add_d(const Operand *OpFd, const Operand *OpFs, | |
325 const Operand *OpFt) { | |
326 static constexpr IValueT Opcode = 0x44000000; | |
327 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "add.d"); | |
328 } | |
329 | |
330 void AssemblerMIPS32::add_s(const Operand *OpFd, const Operand *OpFs, | |
331 const Operand *OpFt) { | |
332 static constexpr IValueT Opcode = 0x44000000; | |
333 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "add.s"); | |
334 } | |
335 | |
336 void AssemblerMIPS32::div_d(const Operand *OpFd, const Operand *OpFs, | |
337 const Operand *OpFt) { | |
338 static constexpr IValueT Opcode = 0x44000003; | |
339 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "div.d"); | |
340 } | |
341 | |
342 void AssemblerMIPS32::div_s(const Operand *OpFd, const Operand *OpFs, | |
343 const Operand *OpFt) { | |
344 static constexpr IValueT Opcode = 0x44000003; | |
345 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "div.s"); | |
346 } | |
347 | |
348 void AssemblerMIPS32::mfc1(const Operand *OpRt, const Operand *OpFs) { | |
349 static constexpr IValueT Opcode = 0x44000000; | |
350 emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mfc1"); | |
351 } | |
352 | |
353 void AssemblerMIPS32::mov_d(const Operand *OpFd, const Operand *OpFs) { | |
354 static constexpr IValueT Opcode = 0x44000006; | |
355 emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "mov.d"); | |
356 } | |
357 | |
358 void AssemblerMIPS32::mov_s(const Operand *OpFd, const Operand *OpFs) { | |
359 static constexpr IValueT Opcode = 0x44000006; | |
360 emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "mov.s"); | |
361 } | |
362 | |
363 void AssemblerMIPS32::movn_d(const Operand *OpFd, const Operand *OpFs, | |
364 const Operand *OpFt) { | |
365 static constexpr IValueT Opcode = 0x44000013; | |
366 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movn.d"); | |
367 } | |
368 | |
369 void AssemblerMIPS32::movn_s(const Operand *OpFd, const Operand *OpFs, | |
370 const Operand *OpFt) { | |
371 static constexpr IValueT Opcode = 0x44000013; | |
372 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movn.s"); | |
373 } | |
374 | |
375 void AssemblerMIPS32::movz_d(const Operand *OpFd, const Operand *OpFs, | |
376 const Operand *OpFt) { | |
377 static constexpr IValueT Opcode = 0x44000012; | |
378 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movz.d"); | |
379 } | |
380 | |
381 void AssemblerMIPS32::movz_s(const Operand *OpFd, const Operand *OpFs, | |
382 const Operand *OpFt) { | |
383 static constexpr IValueT Opcode = 0x44000012; | |
384 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movz.s"); | |
385 } | |
386 | |
387 void AssemblerMIPS32::mtc1(const Operand *OpRt, const Operand *OpFs) { | |
388 static constexpr IValueT Opcode = 0x44800000; | |
389 emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mtc1"); | |
390 } | |
391 | |
392 void AssemblerMIPS32::mul_d(const Operand *OpFd, const Operand *OpFs, | |
393 const Operand *OpFt) { | |
394 static constexpr IValueT Opcode = 0x44000002; | |
395 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "mul.d"); | |
396 } | |
397 | |
398 void AssemblerMIPS32::mul_s(const Operand *OpFd, const Operand *OpFs, | |
399 const Operand *OpFt) { | |
400 static constexpr IValueT Opcode = 0x44000002; | |
401 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "mul.s"); | |
402 } | |
403 | |
404 void AssemblerMIPS32::sqrt_d(const Operand *OpFd, const Operand *OpFs) { | |
405 static constexpr IValueT Opcode = 0x44000004; | |
406 emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "sqrt.d"); | |
407 } | |
408 | |
409 void AssemblerMIPS32::sqrt_s(const Operand *OpFd, const Operand *OpFs) { | |
410 static constexpr IValueT Opcode = 0x44000004; | |
411 emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "sqrt.s"); | |
412 } | |
413 | |
414 void AssemblerMIPS32::sub_d(const Operand *OpFd, const Operand *OpFs, | |
415 const Operand *OpFt) { | |
416 static constexpr IValueT Opcode = 0x44000001; | |
417 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "sub.d"); | |
418 } | |
419 | |
420 void AssemblerMIPS32::sub_s(const Operand *OpFd, const Operand *OpFs, | |
421 const Operand *OpFt) { | |
422 static constexpr IValueT Opcode = 0x44000001; | |
423 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "sub.s"); | |
424 } | |
425 | |
222 void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs, | 426 void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs, |
223 const uint32_t Imm) { | 427 const uint32_t Imm) { |
224 static constexpr IValueT Opcode = 0x24000000; | 428 static constexpr IValueT Opcode = 0x24000000; |
225 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu"); | 429 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu"); |
226 } | 430 } |
227 | 431 |
228 void AssemblerMIPS32::slti(const Operand *OpRt, const Operand *OpRs, | 432 void AssemblerMIPS32::slti(const Operand *OpRt, const Operand *OpRs, |
229 const uint32_t Imm) { | 433 const uint32_t Imm) { |
230 static constexpr IValueT Opcode = 0x28000000; | 434 static constexpr IValueT Opcode = 0x28000000; |
231 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "slti"); | 435 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "slti"); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
285 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "srl"); | 489 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "srl"); |
286 } | 490 } |
287 | 491 |
288 void AssemblerMIPS32::sra(const Operand *OpRd, const Operand *OpRt, | 492 void AssemblerMIPS32::sra(const Operand *OpRd, const Operand *OpRt, |
289 const uint32_t Sa) { | 493 const uint32_t Sa) { |
290 static constexpr IValueT Opcode = 0x00000003; | 494 static constexpr IValueT Opcode = 0x00000003; |
291 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sra"); | 495 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sra"); |
292 } | 496 } |
293 | 497 |
294 void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) { | 498 void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) { |
295 IValueT Opcode = 0x00000021; | 499 |
296 const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move"); | 500 const Type DstType = OpRd->getType(); |
297 const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move"); | 501 const Type SrcType = OpRs->getType(); |
298 const IValueT Rt = 0; // $0 | 502 |
299 Opcode |= Rs << 21; | 503 if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) || |
300 Opcode |= Rt << 16; | 504 (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) { |
301 Opcode |= Rd << 11; | 505 if (isScalarFloatingType(DstType)) { |
302 emitInst(Opcode); | 506 mtc1(OpRd, OpRs); |
507 } else { | |
508 mfc1(OpRd, OpRs); | |
509 } | |
510 } else { | |
511 switch (DstType) { | |
512 case IceType_f32: | |
513 mov_s(OpRd, OpRs); | |
514 break; | |
515 case IceType_f64: | |
516 mov_d(OpRd, OpRs); | |
517 break; | |
518 case IceType_i1: | |
519 case IceType_i8: | |
520 case IceType_i16: | |
521 case IceType_i32: { | |
522 IValueT Opcode = 0x00000021; | |
523 const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move"); | |
524 const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move"); | |
525 const IValueT Rt = 0; // $0 | |
526 Opcode |= Rs << 21; | |
527 Opcode |= Rt << 16; | |
528 Opcode |= Rd << 11; | |
529 emitInst(Opcode); | |
530 break; | |
531 } | |
532 default: { UnimplementedError(getFlags()); } | |
533 } | |
534 } | |
303 } | 535 } |
304 | 536 |
305 void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs, | 537 void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs, |
306 const Operand *OpRt) { | 538 const Operand *OpRt) { |
307 static constexpr IValueT Opcode = 0x00000021; | 539 static constexpr IValueT Opcode = 0x00000021; |
308 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "addu"); | 540 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "addu"); |
309 } | 541 } |
310 | 542 |
311 void AssemblerMIPS32::sltu(const Operand *OpRd, const Operand *OpRs, | 543 void AssemblerMIPS32::sltu(const Operand *OpRd, const Operand *OpRs, |
312 const Operand *OpRt) { | 544 const Operand *OpRt) { |
313 static constexpr IValueT Opcode = 0x0000002B; | 545 static constexpr IValueT Opcode = 0x0000002B; |
314 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sltu"); | 546 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sltu"); |
315 } | 547 } |
316 | 548 |
317 void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs, | 549 void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs, |
318 const Operand *OpRt) { | 550 const Operand *OpRt) { |
319 static constexpr IValueT Opcode = 0x0000002A; | 551 static constexpr IValueT Opcode = 0x0000002A; |
320 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "slt"); | 552 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "slt"); |
321 } | 553 } |
322 | 554 |
323 void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase, | 555 void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase, |
324 const uint32_t Offset) { | 556 const uint32_t Offset) { |
325 static constexpr IValueT Opcode = 0xAC000000; | 557 switch (OpRt->getType()) { |
326 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw"); | 558 case IceType_i1: |
559 case IceType_i8: { | |
560 static constexpr IValueT Opcode = 0xA0000000; | |
561 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sb"); | |
562 break; | |
563 } | |
564 case IceType_i16: { | |
565 static constexpr IValueT Opcode = 0xA4000000; | |
566 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sh"); | |
567 break; | |
568 } | |
569 case IceType_i32: { | |
570 static constexpr IValueT Opcode = 0xAC000000; | |
571 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw"); | |
572 break; | |
573 } | |
574 case IceType_f32: { | |
575 static constexpr IValueT Opcode = 0xE4000000; | |
576 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "swc1"); | |
577 break; | |
578 } | |
579 case IceType_f64: { | |
580 static constexpr IValueT Opcode = 0xF4000000; | |
581 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "sdc1"); | |
582 break; | |
583 } | |
584 default: { UnimplementedError(getFlags()); } | |
585 } | |
327 } | 586 } |
328 | 587 |
329 void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase, | 588 void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase, |
330 const uint32_t Offset) { | 589 const uint32_t Offset) { |
331 static constexpr IValueT Opcode = 0x8C000000; | 590 switch (OpRt->getType()) { |
332 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw"); | 591 case IceType_i1: |
592 case IceType_i8: { | |
593 static constexpr IValueT Opcode = 0x80000000; | |
594 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lb"); | |
595 } | |
596 case IceType_i16: { | |
597 static constexpr IValueT Opcode = 0x84000000; | |
598 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lh"); | |
599 } | |
600 case IceType_i32: { | |
601 static constexpr IValueT Opcode = 0x8C000000; | |
602 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw"); | |
603 break; | |
604 } | |
605 case IceType_f32: { | |
606 static constexpr IValueT Opcode = 0xC4000000; | |
607 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "lwc1"); | |
608 } | |
609 case IceType_f64: { | |
610 static constexpr IValueT Opcode = 0xD4000000; | |
611 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "ldc1"); | |
612 break; | |
613 } | |
614 default: { UnimplementedError(getFlags()); } | |
615 } | |
333 } | 616 } |
334 | 617 |
335 void AssemblerMIPS32::ret(void) { | 618 void AssemblerMIPS32::ret(void) { |
336 static constexpr IValueT Opcode = 0x03E00008; // JR $31 | 619 static constexpr IValueT Opcode = 0x03E00008; // JR $31 |
337 emitInst(Opcode); | 620 emitInst(Opcode); |
338 nop(); // delay slot | 621 nop(); // delay slot |
339 } | 622 } |
340 | 623 |
341 void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs, | 624 void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs, |
342 const Operand *OpRt, IOffsetT Offset) { | 625 const Operand *OpRt, IOffsetT Offset) { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
420 emitBr(Cond, OpRs, OpRtNone, Dest); | 703 emitBr(Cond, OpRs, OpRtNone, Dest); |
421 return; | 704 return; |
422 } | 705 } |
423 const IOffsetT Position = Buffer.size(); | 706 const IOffsetT Position = Buffer.size(); |
424 emitBr(Cond, OpRs, OpRtNone, TargetLabel->getEncodedPosition()); | 707 emitBr(Cond, OpRs, OpRtNone, TargetLabel->getEncodedPosition()); |
425 TargetLabel->linkTo(*this, Position); | 708 TargetLabel->linkTo(*this, Position); |
426 } | 709 } |
427 | 710 |
428 } // end of namespace MIPS32 | 711 } // end of namespace MIPS32 |
429 } // end of namespace Ice | 712 } // end of namespace Ice |
OLD | NEW |