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 } |
| 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 Loading... |
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 |
OLD | NEW |