Chromium Code Reviews| 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 |