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

Side by Side Diff: src/IceAssemblerMIPS32.cpp

Issue 2341713003: Subzero, MIPS32: Floating point support in ELF output (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Encodings for more existing instructions, alphabetized 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
« no previous file with comments | « src/IceAssemblerMIPS32.h ('k') | src/IceInstMIPS32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 }
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
222 void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs, 336 void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs,
223 const uint32_t Imm) { 337 const uint32_t Imm) {
224 static constexpr IValueT Opcode = 0x24000000; 338 static constexpr IValueT Opcode = 0x24000000;
225 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu"); 339 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu");
226 } 340 }
227 341
228 void AssemblerMIPS32::slti(const Operand *OpRt, const Operand *OpRs, 342 void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs,
229 const uint32_t Imm) { 343 const Operand *OpRt) {
230 static constexpr IValueT Opcode = 0x28000000; 344 static constexpr IValueT Opcode = 0x00000021;
231 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "slti"); 345 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "addu");
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 } 346 }
239 347
240 void AssemblerMIPS32::and_(const Operand *OpRd, const Operand *OpRs, 348 void AssemblerMIPS32::and_(const Operand *OpRd, const Operand *OpRs,
241 const Operand *OpRt) { 349 const Operand *OpRt) {
242 static constexpr IValueT Opcode = 0x00000024; 350 static constexpr IValueT Opcode = 0x00000024;
243 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "and"); 351 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "and");
244 } 352 }
245 353
246 void AssemblerMIPS32::andi(const Operand *OpRt, const Operand *OpRs, 354 void AssemblerMIPS32::andi(const Operand *OpRt, const Operand *OpRs,
247 const uint32_t Imm) { 355 const uint32_t Imm) {
248 static constexpr IValueT Opcode = 0x30000000; 356 static constexpr IValueT Opcode = 0x30000000;
249 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "andi"); 357 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "andi");
250 } 358 }
251 359
360 void AssemblerMIPS32::b(Label *TargetLabel) {
361 static constexpr Operand *OpRsNone = nullptr;
362 static constexpr Operand *OpRtNone = nullptr;
363 if (TargetLabel->isBound()) {
364 const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
365 emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, Dest);
366 return;
367 }
368 const IOffsetT Position = Buffer.size();
369 emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, TargetLabel->getEncodedPosition());
370 TargetLabel->linkTo(*this, Position);
371 }
372
373 void AssemblerMIPS32::cvt_d_l(const Operand *OpFd, const Operand *OpFs) {
374 static constexpr IValueT Opcode = 0x44000021;
375 emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "cvt.d.l");
376 }
377
378 void AssemblerMIPS32::cvt_d_s(const Operand *OpFd, const Operand *OpFs) {
379 static constexpr IValueT Opcode = 0x44000021;
380 emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "cvt.d.s");
381 }
382
383 void AssemblerMIPS32::cvt_d_w(const Operand *OpFd, const Operand *OpFs) {
384 static constexpr IValueT Opcode = 0x44000021;
385 emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "cvt.d.w");
386 }
387
388 void AssemblerMIPS32::cvt_s_d(const Operand *OpFd, const Operand *OpFs) {
389 static constexpr IValueT Opcode = 0x44000020;
390 emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "cvt.s.d");
391 }
392
393 void AssemblerMIPS32::cvt_s_l(const Operand *OpFd, const Operand *OpFs) {
394 static constexpr IValueT Opcode = 0x44000020;
395 emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "cvt.s.l");
396 }
397
398 void AssemblerMIPS32::cvt_s_w(const Operand *OpFd, const Operand *OpFs) {
399 static constexpr IValueT Opcode = 0x44000020;
400 emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "cvt.s.w");
401 }
402
403 void AssemblerMIPS32::div_d(const Operand *OpFd, const Operand *OpFs,
404 const Operand *OpFt) {
405 static constexpr IValueT Opcode = 0x44000003;
406 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "div.d");
407 }
408
409 void AssemblerMIPS32::div_s(const Operand *OpFd, const Operand *OpFs,
410 const Operand *OpFt) {
411 static constexpr IValueT Opcode = 0x44000003;
412 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "div.s");
413 }
414
415 void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase,
416 const uint32_t Offset) {
417 switch (OpRt->getType()) {
418 case IceType_i1:
419 case IceType_i8: {
420 static constexpr IValueT Opcode = 0x80000000;
421 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lb");
422 }
423 case IceType_i16: {
424 static constexpr IValueT Opcode = 0x84000000;
425 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lh");
426 }
427 case IceType_i32: {
428 static constexpr IValueT Opcode = 0x8C000000;
429 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw");
430 break;
431 }
432 case IceType_f32: {
433 static constexpr IValueT Opcode = 0xC4000000;
434 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "lwc1");
435 }
436 case IceType_f64: {
437 static constexpr IValueT Opcode = 0xD4000000;
438 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "ldc1");
439 break;
440 }
441 default: { UnimplementedError(getFlags()); }
442 }
443 }
444
445 void AssemblerMIPS32::mfc1(const Operand *OpRt, const Operand *OpFs) {
446 static constexpr IValueT Opcode = 0x44000000;
447 emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mfc1");
448 }
449
450 void AssemblerMIPS32::mov_d(const Operand *OpFd, const Operand *OpFs) {
451 static constexpr IValueT Opcode = 0x44000006;
452 emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "mov.d");
453 }
454
455 void AssemblerMIPS32::mov_s(const Operand *OpFd, const Operand *OpFs) {
456 static constexpr IValueT Opcode = 0x44000006;
457 emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "mov.s");
458 }
459
460 void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) {
461
462 const Type DstType = OpRd->getType();
463 const Type SrcType = OpRs->getType();
464
465 if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) ||
466 (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) {
467 if (isScalarFloatingType(DstType)) {
468 mtc1(OpRd, OpRs);
469 } else {
470 mfc1(OpRd, OpRs);
471 }
472 } else {
473 switch (DstType) {
474 case IceType_f32:
475 mov_s(OpRd, OpRs);
476 break;
477 case IceType_f64:
478 mov_d(OpRd, OpRs);
479 break;
480 case IceType_i1:
481 case IceType_i8:
482 case IceType_i16:
483 case IceType_i32: {
484 IValueT Opcode = 0x00000021;
485 const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move");
486 const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move");
487 const IValueT Rt = 0; // $0
488 Opcode |= Rs << 21;
489 Opcode |= Rt << 16;
490 Opcode |= Rd << 11;
491 emitInst(Opcode);
492 break;
493 }
494 default: { UnimplementedError(getFlags()); }
495 }
496 }
497 }
498
499 void AssemblerMIPS32::movn_d(const Operand *OpFd, const Operand *OpFs,
500 const Operand *OpFt) {
501 static constexpr IValueT Opcode = 0x44000013;
502 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movn.d");
503 }
504
505 void AssemblerMIPS32::movn_s(const Operand *OpFd, const Operand *OpFs,
506 const Operand *OpFt) {
507 static constexpr IValueT Opcode = 0x44000013;
508 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movn.s");
509 }
510
511 void AssemblerMIPS32::movz_d(const Operand *OpFd, const Operand *OpFs,
512 const Operand *OpFt) {
513 static constexpr IValueT Opcode = 0x44000012;
514 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movz.d");
515 }
516
517 void AssemblerMIPS32::movz_s(const Operand *OpFd, const Operand *OpFs,
518 const Operand *OpFt) {
519 static constexpr IValueT Opcode = 0x44000012;
520 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movz.s");
521 }
522
523 void AssemblerMIPS32::mtc1(const Operand *OpRt, const Operand *OpFs) {
524 static constexpr IValueT Opcode = 0x44800000;
525 emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mtc1");
526 }
527
528 void AssemblerMIPS32::mul_d(const Operand *OpFd, const Operand *OpFs,
529 const Operand *OpFt) {
530 static constexpr IValueT Opcode = 0x44000002;
531 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "mul.d");
532 }
533
534 void AssemblerMIPS32::mul_s(const Operand *OpFd, const Operand *OpFs,
535 const Operand *OpFt) {
536 static constexpr IValueT Opcode = 0x44000002;
537 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "mul.s");
538 }
539
252 void AssemblerMIPS32::or_(const Operand *OpRd, const Operand *OpRs, 540 void AssemblerMIPS32::or_(const Operand *OpRd, const Operand *OpRs,
253 const Operand *OpRt) { 541 const Operand *OpRt) {
254 static constexpr IValueT Opcode = 0x00000025; 542 static constexpr IValueT Opcode = 0x00000025;
255 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "or"); 543 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "or");
256 } 544 }
257 545
258 void AssemblerMIPS32::ori(const Operand *OpRt, const Operand *OpRs, 546 void AssemblerMIPS32::ori(const Operand *OpRt, const Operand *OpRs,
259 const uint32_t Imm) { 547 const uint32_t Imm) {
260 static constexpr IValueT Opcode = 0x34000000; 548 static constexpr IValueT Opcode = 0x34000000;
261 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "ori"); 549 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "ori");
262 } 550 }
263 551
264 void AssemblerMIPS32::xor_(const Operand *OpRd, const Operand *OpRs, 552 void AssemblerMIPS32::ret(void) {
265 const Operand *OpRt) { 553 static constexpr IValueT Opcode = 0x03E00008; // JR $31
266 static constexpr IValueT Opcode = 0x00000026; 554 emitInst(Opcode);
267 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "xor"); 555 nop(); // delay slot
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 } 556 }
275 557
276 void AssemblerMIPS32::sll(const Operand *OpRd, const Operand *OpRt, 558 void AssemblerMIPS32::sll(const Operand *OpRd, const Operand *OpRt,
277 const uint32_t Sa) { 559 const uint32_t Sa) {
278 static constexpr IValueT Opcode = 0x00000000; 560 static constexpr IValueT Opcode = 0x00000000;
279 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sll"); 561 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sll");
280 } 562 }
281 563
282 void AssemblerMIPS32::srl(const Operand *OpRd, const Operand *OpRt, 564 void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs,
283 const uint32_t Sa) { 565 const Operand *OpRt) {
284 static constexpr IValueT Opcode = 0x00000002; 566 static constexpr IValueT Opcode = 0x0000002A;
285 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "srl"); 567 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "slt");
568 }
569
570 void AssemblerMIPS32::slti(const Operand *OpRt, const Operand *OpRs,
571 const uint32_t Imm) {
572 static constexpr IValueT Opcode = 0x28000000;
573 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "slti");
574 }
575
576 void AssemblerMIPS32::sltu(const Operand *OpRd, const Operand *OpRs,
577 const Operand *OpRt) {
578 static constexpr IValueT Opcode = 0x0000002B;
579 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sltu");
580 }
581
582 void AssemblerMIPS32::sltiu(const Operand *OpRt, const Operand *OpRs,
583 const uint32_t Imm) {
584 static constexpr IValueT Opcode = 0x2c000000;
585 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "sltiu");
586 }
587
588 void AssemblerMIPS32::sqrt_d(const Operand *OpFd, const Operand *OpFs) {
589 static constexpr IValueT Opcode = 0x44000004;
590 emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "sqrt.d");
591 }
592
593 void AssemblerMIPS32::sqrt_s(const Operand *OpFd, const Operand *OpFs) {
594 static constexpr IValueT Opcode = 0x44000004;
595 emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "sqrt.s");
286 } 596 }
287 597
288 void AssemblerMIPS32::sra(const Operand *OpRd, const Operand *OpRt, 598 void AssemblerMIPS32::sra(const Operand *OpRd, const Operand *OpRt,
289 const uint32_t Sa) { 599 const uint32_t Sa) {
290 static constexpr IValueT Opcode = 0x00000003; 600 static constexpr IValueT Opcode = 0x00000003;
291 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sra"); 601 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sra");
292 } 602 }
293 603
294 void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) { 604 void AssemblerMIPS32::srl(const Operand *OpRd, const Operand *OpRt,
295 IValueT Opcode = 0x00000021; 605 const uint32_t Sa) {
296 const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move"); 606 static constexpr IValueT Opcode = 0x00000002;
297 const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move"); 607 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "srl");
298 const IValueT Rt = 0; // $0
299 Opcode |= Rs << 21;
300 Opcode |= Rt << 16;
301 Opcode |= Rd << 11;
302 emitInst(Opcode);
303 } 608 }
304 609
305 void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs, 610 void AssemblerMIPS32::sub_d(const Operand *OpFd, const Operand *OpFs,
306 const Operand *OpRt) { 611 const Operand *OpFt) {
307 static constexpr IValueT Opcode = 0x00000021; 612 static constexpr IValueT Opcode = 0x44000001;
308 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "addu"); 613 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "sub.d");
309 } 614 }
310 615
311 void AssemblerMIPS32::sltu(const Operand *OpRd, const Operand *OpRs, 616 void AssemblerMIPS32::sub_s(const Operand *OpFd, const Operand *OpFs,
312 const Operand *OpRt) { 617 const Operand *OpFt) {
313 static constexpr IValueT Opcode = 0x0000002B; 618 static constexpr IValueT Opcode = 0x44000001;
314 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sltu"); 619 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "sub.s");
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 } 620 }
322 621
323 void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase, 622 void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase,
324 const uint32_t Offset) { 623 const uint32_t Offset) {
325 static constexpr IValueT Opcode = 0xAC000000; 624 switch (OpRt->getType()) {
326 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw"); 625 case IceType_i1:
626 case IceType_i8: {
627 static constexpr IValueT Opcode = 0xA0000000;
628 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sb");
629 break;
630 }
631 case IceType_i16: {
632 static constexpr IValueT Opcode = 0xA4000000;
633 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sh");
634 break;
635 }
636 case IceType_i32: {
637 static constexpr IValueT Opcode = 0xAC000000;
638 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw");
639 break;
640 }
641 case IceType_f32: {
642 static constexpr IValueT Opcode = 0xE4000000;
643 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "swc1");
644 break;
645 }
646 case IceType_f64: {
647 static constexpr IValueT Opcode = 0xF4000000;
648 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "sdc1");
649 break;
650 }
651 default: { UnimplementedError(getFlags()); }
652 }
327 } 653 }
328 654
329 void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase, 655 void AssemblerMIPS32::trunc_l_d(const Operand *OpFd, const Operand *OpFs) {
330 const uint32_t Offset) { 656 static constexpr IValueT Opcode = 0x4400000D;
331 static constexpr IValueT Opcode = 0x8C000000; 657 emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.d");
332 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw");
333 } 658 }
334 659
335 void AssemblerMIPS32::ret(void) { 660 void AssemblerMIPS32::trunc_l_s(const Operand *OpFd, const Operand *OpFs) {
336 static constexpr IValueT Opcode = 0x03E00008; // JR $31 661 static constexpr IValueT Opcode = 0x4400000D;
337 emitInst(Opcode); 662 emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.s");
338 nop(); // delay slot 663 }
664
665 void AssemblerMIPS32::trunc_w_d(const Operand *OpFd, const Operand *OpFs) {
666 static constexpr IValueT Opcode = 0x4400000D;
667 emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "trunc.w.d");
668 }
669
670 void AssemblerMIPS32::trunc_w_s(const Operand *OpFd, const Operand *OpFs) {
671 static constexpr IValueT Opcode = 0x4400000D;
672 emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "trunc.w.s");
673 }
674
675 void AssemblerMIPS32::xor_(const Operand *OpRd, const Operand *OpRs,
676 const Operand *OpRt) {
677 static constexpr IValueT Opcode = 0x00000026;
678 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "xor");
679 }
680
681 void AssemblerMIPS32::xori(const Operand *OpRt, const Operand *OpRs,
682 const uint32_t Imm) {
683 static constexpr IValueT Opcode = 0x38000000;
684 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "xori");
339 } 685 }
340 686
341 void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs, 687 void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs,
342 const Operand *OpRt, IOffsetT Offset) { 688 const Operand *OpRt, IOffsetT Offset) {
343 IValueT Opcode = 0; 689 IValueT Opcode = 0;
344 690
345 switch (Cond) { 691 switch (Cond) {
346 default: 692 default:
347 break; 693 break;
348 case CondMIPS32::AL: 694 case CondMIPS32::AL:
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 if (OpRt != nullptr) { 726 if (OpRt != nullptr) {
381 IValueT Rt = encodeGPRegister(OpRt, "Rt", "branch"); 727 IValueT Rt = encodeGPRegister(OpRt, "Rt", "branch");
382 Opcode |= Rt << 16; 728 Opcode |= Rt << 16;
383 } 729 }
384 730
385 Opcode = encodeBranchOffset(Offset, Opcode); 731 Opcode = encodeBranchOffset(Offset, Opcode);
386 emitInst(Opcode); 732 emitInst(Opcode);
387 nop(); // delay slot 733 nop(); // delay slot
388 } 734 }
389 735
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, 736 void AssemblerMIPS32::bcc(const CondMIPS32::Cond Cond, const Operand *OpRs,
404 const Operand *OpRt, Label *TargetLabel) { 737 const Operand *OpRt, Label *TargetLabel) {
405 if (TargetLabel->isBound()) { 738 if (TargetLabel->isBound()) {
406 const int32_t Dest = TargetLabel->getPosition() - Buffer.size(); 739 const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
407 emitBr(Cond, OpRs, OpRt, Dest); 740 emitBr(Cond, OpRs, OpRt, Dest);
408 return; 741 return;
409 } 742 }
410 const IOffsetT Position = Buffer.size(); 743 const IOffsetT Position = Buffer.size();
411 emitBr(Cond, OpRs, OpRt, TargetLabel->getEncodedPosition()); 744 emitBr(Cond, OpRs, OpRt, TargetLabel->getEncodedPosition());
412 TargetLabel->linkTo(*this, Position); 745 TargetLabel->linkTo(*this, Position);
413 } 746 }
414 747
415 void AssemblerMIPS32::bzc(const CondMIPS32::Cond Cond, const Operand *OpRs, 748 void AssemblerMIPS32::bzc(const CondMIPS32::Cond Cond, const Operand *OpRs,
416 Label *TargetLabel) { 749 Label *TargetLabel) {
417 static constexpr Operand *OpRtNone = nullptr; 750 static constexpr Operand *OpRtNone = nullptr;
418 if (TargetLabel->isBound()) { 751 if (TargetLabel->isBound()) {
419 const int32_t Dest = TargetLabel->getPosition() - Buffer.size(); 752 const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
420 emitBr(Cond, OpRs, OpRtNone, Dest); 753 emitBr(Cond, OpRs, OpRtNone, Dest);
421 return; 754 return;
422 } 755 }
423 const IOffsetT Position = Buffer.size(); 756 const IOffsetT Position = Buffer.size();
424 emitBr(Cond, OpRs, OpRtNone, TargetLabel->getEncodedPosition()); 757 emitBr(Cond, OpRs, OpRtNone, TargetLabel->getEncodedPosition());
425 TargetLabel->linkTo(*this, Position); 758 TargetLabel->linkTo(*this, Position);
426 } 759 }
427 760
428 } // end of namespace MIPS32 761 } // end of namespace MIPS32
429 } // end of namespace Ice 762 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceAssemblerMIPS32.h ('k') | src/IceInstMIPS32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698