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