| OLD | NEW |
| 1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===// | 1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===// |
| 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 // This file implements the InstARM32 and OperandARM32 classes, | 10 // This file implements the InstARM32 and OperandARM32 classes, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 return TypeARM32Attributes[Ty].WidthString; | 53 return TypeARM32Attributes[Ty].WidthString; |
| 54 } | 54 } |
| 55 | 55 |
| 56 void emitTwoAddr(const char *Opcode, const Inst *Inst, const Cfg *Func) { | 56 void emitTwoAddr(const char *Opcode, const Inst *Inst, const Cfg *Func) { |
| 57 if (!ALLOW_DUMP) | 57 if (!ALLOW_DUMP) |
| 58 return; | 58 return; |
| 59 Ostream &Str = Func->getContext()->getStrEmit(); | 59 Ostream &Str = Func->getContext()->getStrEmit(); |
| 60 assert(Inst->getSrcSize() == 2); | 60 assert(Inst->getSrcSize() == 2); |
| 61 Variable *Dest = Inst->getDest(); | 61 Variable *Dest = Inst->getDest(); |
| 62 assert(Dest == Inst->getSrc(0)); | 62 assert(Dest == Inst->getSrc(0)); |
| 63 Operand *Src1 = Inst->getSrc(1); | |
| 64 Str << "\t" << Opcode << "\t"; | 63 Str << "\t" << Opcode << "\t"; |
| 65 Dest->emit(Func); | 64 Dest->emit(Func); |
| 66 Str << ", "; | 65 Str << ", "; |
| 67 Src1->emit(Func); | 66 Inst->getSrc(1)->emit(Func); |
| 67 } |
| 68 |
| 69 void emitThreeAddr(const char *Opcode, const Inst *Inst, const Cfg *Func, |
| 70 bool SetFlags) { |
| 71 if (!ALLOW_DUMP) |
| 72 return; |
| 73 Ostream &Str = Func->getContext()->getStrEmit(); |
| 74 assert(Inst->getSrcSize() == 2); |
| 75 Str << "\t" << Opcode << (SetFlags ? "s" : "") << "\t"; |
| 76 Inst->getDest()->emit(Func); |
| 77 Str << ", "; |
| 78 Inst->getSrc(0)->emit(Func); |
| 79 Str << ", "; |
| 80 Inst->getSrc(1)->emit(Func); |
| 68 } | 81 } |
| 69 | 82 |
| 70 OperandARM32Mem::OperandARM32Mem(Cfg * /* Func */, Type Ty, Variable *Base, | 83 OperandARM32Mem::OperandARM32Mem(Cfg * /* Func */, Type Ty, Variable *Base, |
| 71 ConstantInteger32 *ImmOffset, AddrMode Mode) | 84 ConstantInteger32 *ImmOffset, AddrMode Mode) |
| 72 : OperandARM32(kMem, Ty), Base(Base), ImmOffset(ImmOffset), Index(nullptr), | 85 : OperandARM32(kMem, Ty), Base(Base), ImmOffset(ImmOffset), Index(nullptr), |
| 73 ShiftOp(kNoShift), ShiftAmt(0), Mode(Mode) { | 86 ShiftOp(kNoShift), ShiftAmt(0), Mode(Mode) { |
| 74 // The Neg modes are only needed for Reg +/- Reg. | 87 // The Neg modes are only needed for Reg +/- Reg. |
| 75 assert(!isNegAddrMode()); | 88 assert(!isNegAddrMode()); |
| 76 NumVars = 1; | 89 NumVars = 1; |
| 77 Vars = &this->Base; | 90 Vars = &this->Base; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 Vars[0] = Reg; | 152 Vars[0] = Reg; |
| 140 if (ShiftVar) | 153 if (ShiftVar) |
| 141 Vars[1] = ShiftVar; | 154 Vars[1] = ShiftVar; |
| 142 } | 155 } |
| 143 | 156 |
| 144 InstARM32Ldr::InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem) | 157 InstARM32Ldr::InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem) |
| 145 : InstARM32(Func, InstARM32::Ldr, 1, Dest) { | 158 : InstARM32(Func, InstARM32::Ldr, 1, Dest) { |
| 146 addSource(Mem); | 159 addSource(Mem); |
| 147 } | 160 } |
| 148 | 161 |
| 162 InstARM32Mla::InstARM32Mla(Cfg *Func, Variable *Dest, Variable *Src0, |
| 163 Variable *Src1, Variable *Acc) |
| 164 : InstARM32(Func, InstARM32::Mla, 3, Dest) { |
| 165 addSource(Src0); |
| 166 addSource(Src1); |
| 167 addSource(Acc); |
| 168 } |
| 169 |
| 149 InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source) | 170 InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source) |
| 150 : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) { | 171 : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) { |
| 151 addSource(LR); | 172 addSource(LR); |
| 152 if (Source) | 173 if (Source) |
| 153 addSource(Source); | 174 addSource(Source); |
| 154 } | 175 } |
| 155 | 176 |
| 177 InstARM32Umull::InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, |
| 178 Variable *Src0, Variable *Src1) |
| 179 : InstARM32(Func, InstARM32::Umull, 2, DestLo), |
| 180 // DestHi is expected to have a FakeDef inserted by the lowering code. |
| 181 DestHi(DestHi) { |
| 182 addSource(Src0); |
| 183 addSource(Src1); |
| 184 } |
| 185 |
| 156 // ======================== Dump routines ======================== // | 186 // ======================== Dump routines ======================== // |
| 157 | 187 |
| 158 // Two-addr ops | 188 // Two-addr ops |
| 159 template <> const char *InstARM32Movt::Opcode = "movt"; | 189 template <> const char *InstARM32Movt::Opcode = "movt"; |
| 160 // Unary ops | 190 // Unary ops |
| 161 template <> const char *InstARM32Movw::Opcode = "movw"; | 191 template <> const char *InstARM32Movw::Opcode = "movw"; |
| 162 template <> const char *InstARM32Mvn::Opcode = "mvn"; | 192 template <> const char *InstARM32Mvn::Opcode = "mvn"; |
| 163 // Mov-like ops | 193 // Mov-like ops |
| 164 template <> const char *InstARM32Mov::Opcode = "mov"; | 194 template <> const char *InstARM32Mov::Opcode = "mov"; |
| 195 // Three-addr ops |
| 196 template <> const char *InstARM32Adc::Opcode = "adc"; |
| 197 template <> const char *InstARM32Add::Opcode = "add"; |
| 198 template <> const char *InstARM32And::Opcode = "and"; |
| 199 template <> const char *InstARM32Eor::Opcode = "eor"; |
| 200 template <> const char *InstARM32Mul::Opcode = "mul"; |
| 201 template <> const char *InstARM32Orr::Opcode = "orr"; |
| 202 template <> const char *InstARM32Sbc::Opcode = "sbc"; |
| 203 template <> const char *InstARM32Sub::Opcode = "sub"; |
| 165 | 204 |
| 166 void InstARM32::dump(const Cfg *Func) const { | 205 void InstARM32::dump(const Cfg *Func) const { |
| 167 if (!ALLOW_DUMP) | 206 if (!ALLOW_DUMP) |
| 168 return; | 207 return; |
| 169 Ostream &Str = Func->getContext()->getStrDump(); | 208 Ostream &Str = Func->getContext()->getStrDump(); |
| 170 Str << "[ARM32] "; | 209 Str << "[ARM32] "; |
| 171 Inst::dump(Func); | 210 Inst::dump(Func); |
| 172 } | 211 } |
| 173 | 212 |
| 174 template <> void InstARM32Mov::emit(const Cfg *Func) const { | 213 template <> void InstARM32Mov::emit(const Cfg *Func) const { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 assert(getDest()->hasReg()); | 249 assert(getDest()->hasReg()); |
| 211 Type Ty = getSrc(0)->getType(); | 250 Type Ty = getSrc(0)->getType(); |
| 212 Str << "\t" | 251 Str << "\t" |
| 213 << "ldr" << getWidthString(Ty) << "\t"; | 252 << "ldr" << getWidthString(Ty) << "\t"; |
| 214 getDest()->emit(Func); | 253 getDest()->emit(Func); |
| 215 Str << ", "; | 254 Str << ", "; |
| 216 getSrc(0)->emit(Func); | 255 getSrc(0)->emit(Func); |
| 217 } | 256 } |
| 218 | 257 |
| 219 void InstARM32Ldr::emitIAS(const Cfg *Func) const { | 258 void InstARM32Ldr::emitIAS(const Cfg *Func) const { |
| 220 assert(getSrcSize() == 2); | 259 assert(getSrcSize() == 1); |
| 221 (void)Func; | 260 (void)Func; |
| 222 llvm_unreachable("Not yet implemented"); | 261 llvm_unreachable("Not yet implemented"); |
| 223 } | 262 } |
| 224 | 263 |
| 225 void InstARM32Ldr::dump(const Cfg *Func) const { | 264 void InstARM32Ldr::dump(const Cfg *Func) const { |
| 226 if (!ALLOW_DUMP) | 265 if (!ALLOW_DUMP) |
| 227 return; | 266 return; |
| 228 Ostream &Str = Func->getContext()->getStrDump(); | 267 Ostream &Str = Func->getContext()->getStrDump(); |
| 229 dumpDest(Func); | 268 dumpDest(Func); |
| 230 Str << "ldr." << getSrc(0)->getType() << " "; | 269 Str << " = ldr." << getSrc(0)->getType() << " "; |
| 231 dumpSources(Func); | 270 dumpSources(Func); |
| 232 } | 271 } |
| 233 | 272 |
| 273 void InstARM32Mla::emit(const Cfg *Func) const { |
| 274 if (!ALLOW_DUMP) |
| 275 return; |
| 276 Ostream &Str = Func->getContext()->getStrEmit(); |
| 277 assert(getSrcSize() == 3); |
| 278 assert(getDest()->hasReg()); |
| 279 Str << "\t" |
| 280 << "mla" |
| 281 << "\t"; |
| 282 getDest()->emit(Func); |
| 283 Str << ", "; |
| 284 getSrc(0)->emit(Func); |
| 285 Str << ", "; |
| 286 getSrc(1)->emit(Func); |
| 287 Str << ", "; |
| 288 getSrc(2)->emit(Func); |
| 289 } |
| 290 |
| 291 void InstARM32Mla::emitIAS(const Cfg *Func) const { |
| 292 assert(getSrcSize() == 3); |
| 293 (void)Func; |
| 294 llvm_unreachable("Not yet implemented"); |
| 295 } |
| 296 |
| 297 void InstARM32Mla::dump(const Cfg *Func) const { |
| 298 if (!ALLOW_DUMP) |
| 299 return; |
| 300 Ostream &Str = Func->getContext()->getStrDump(); |
| 301 dumpDest(Func); |
| 302 Str << " = mla." << getSrc(0)->getType() << " "; |
| 303 dumpSources(Func); |
| 304 } |
| 305 |
| 234 template <> void InstARM32Movw::emit(const Cfg *Func) const { | 306 template <> void InstARM32Movw::emit(const Cfg *Func) const { |
| 235 if (!ALLOW_DUMP) | 307 if (!ALLOW_DUMP) |
| 236 return; | 308 return; |
| 237 Ostream &Str = Func->getContext()->getStrEmit(); | 309 Ostream &Str = Func->getContext()->getStrEmit(); |
| 238 assert(getSrcSize() == 1); | 310 assert(getSrcSize() == 1); |
| 239 Str << "\t" << Opcode << "\t"; | 311 Str << "\t" << Opcode << "\t"; |
| 240 getDest()->emit(Func); | 312 getDest()->emit(Func); |
| 241 Str << ", "; | 313 Str << ", "; |
| 242 Constant *Src0 = llvm::cast<Constant>(getSrc(0)); | 314 Constant *Src0 = llvm::cast<Constant>(getSrc(0)); |
| 243 if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) { | 315 if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 267 } | 339 } |
| 268 | 340 |
| 269 void InstARM32Ret::emit(const Cfg *Func) const { | 341 void InstARM32Ret::emit(const Cfg *Func) const { |
| 270 if (!ALLOW_DUMP) | 342 if (!ALLOW_DUMP) |
| 271 return; | 343 return; |
| 272 assert(getSrcSize() > 0); | 344 assert(getSrcSize() > 0); |
| 273 Variable *LR = llvm::cast<Variable>(getSrc(0)); | 345 Variable *LR = llvm::cast<Variable>(getSrc(0)); |
| 274 assert(LR->hasReg()); | 346 assert(LR->hasReg()); |
| 275 assert(LR->getRegNum() == RegARM32::Reg_lr); | 347 assert(LR->getRegNum() == RegARM32::Reg_lr); |
| 276 Ostream &Str = Func->getContext()->getStrEmit(); | 348 Ostream &Str = Func->getContext()->getStrEmit(); |
| 277 Str << "\tbx\t"; | 349 Str << "\t" |
| 350 << "bx" |
| 351 << "\t"; |
| 278 LR->emit(Func); | 352 LR->emit(Func); |
| 279 } | 353 } |
| 280 | 354 |
| 281 void InstARM32Ret::emitIAS(const Cfg *Func) const { | 355 void InstARM32Ret::emitIAS(const Cfg *Func) const { |
| 282 (void)Func; | 356 (void)Func; |
| 283 llvm_unreachable("Not yet implemented"); | 357 llvm_unreachable("Not yet implemented"); |
| 284 } | 358 } |
| 285 | 359 |
| 286 void InstARM32Ret::dump(const Cfg *Func) const { | 360 void InstARM32Ret::dump(const Cfg *Func) const { |
| 287 if (!ALLOW_DUMP) | 361 if (!ALLOW_DUMP) |
| 288 return; | 362 return; |
| 289 Ostream &Str = Func->getContext()->getStrDump(); | 363 Ostream &Str = Func->getContext()->getStrDump(); |
| 290 Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType()); | 364 Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType()); |
| 291 Str << "ret." << Ty << " "; | 365 Str << "ret." << Ty << " "; |
| 292 dumpSources(Func); | 366 dumpSources(Func); |
| 293 } | 367 } |
| 294 | 368 |
| 369 void InstARM32Umull::emit(const Cfg *Func) const { |
| 370 if (!ALLOW_DUMP) |
| 371 return; |
| 372 Ostream &Str = Func->getContext()->getStrEmit(); |
| 373 assert(getSrcSize() == 2); |
| 374 assert(getDest()->hasReg()); |
| 375 Str << "\t" |
| 376 << "umull" |
| 377 << "\t"; |
| 378 getDest()->emit(Func); |
| 379 Str << ", "; |
| 380 DestHi->emit(Func); |
| 381 Str << ", "; |
| 382 getSrc(0)->emit(Func); |
| 383 Str << ", "; |
| 384 getSrc(1)->emit(Func); |
| 385 } |
| 386 |
| 387 void InstARM32Umull::emitIAS(const Cfg *Func) const { |
| 388 assert(getSrcSize() == 2); |
| 389 (void)Func; |
| 390 llvm_unreachable("Not yet implemented"); |
| 391 } |
| 392 |
| 393 void InstARM32Umull::dump(const Cfg *Func) const { |
| 394 if (!ALLOW_DUMP) |
| 395 return; |
| 396 Ostream &Str = Func->getContext()->getStrDump(); |
| 397 dumpDest(Func); |
| 398 Str << " = umull." << getSrc(0)->getType() << " "; |
| 399 dumpSources(Func); |
| 400 } |
| 401 |
| 295 void OperandARM32Mem::emit(const Cfg *Func) const { | 402 void OperandARM32Mem::emit(const Cfg *Func) const { |
| 296 if (!ALLOW_DUMP) | 403 if (!ALLOW_DUMP) |
| 297 return; | 404 return; |
| 298 Ostream &Str = Func->getContext()->getStrEmit(); | 405 Ostream &Str = Func->getContext()->getStrEmit(); |
| 299 Str << "["; | 406 Str << "["; |
| 300 getBase()->emit(Func); | 407 getBase()->emit(Func); |
| 301 switch (getAddrMode()) { | 408 switch (getAddrMode()) { |
| 302 case PostIndex: | 409 case PostIndex: |
| 303 case NegPostIndex: | 410 case NegPostIndex: |
| 304 Str << "], "; | 411 Str << "], "; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 if (getShiftOp() != kNoShift) { | 508 if (getShiftOp() != kNoShift) { |
| 402 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " "; | 509 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " "; |
| 403 if (Func) | 510 if (Func) |
| 404 getShiftAmt()->dump(Func); | 511 getShiftAmt()->dump(Func); |
| 405 else | 512 else |
| 406 getShiftAmt()->dump(Str); | 513 getShiftAmt()->dump(Str); |
| 407 } | 514 } |
| 408 } | 515 } |
| 409 | 516 |
| 410 } // end of namespace Ice | 517 } // end of namespace Ice |
| OLD | NEW |