| OLD | NEW |
| 1 //===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===// | 1 //===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===// |
| 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 declares the InstARM32 and OperandARM32 classes and | 10 // This file declares the InstARM32 and OperandARM32 classes and |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 }; | 238 }; |
| 239 | 239 |
| 240 class InstARM32 : public InstTarget { | 240 class InstARM32 : public InstTarget { |
| 241 InstARM32() = delete; | 241 InstARM32() = delete; |
| 242 InstARM32(const InstARM32 &) = delete; | 242 InstARM32(const InstARM32 &) = delete; |
| 243 InstARM32 &operator=(const InstARM32 &) = delete; | 243 InstARM32 &operator=(const InstARM32 &) = delete; |
| 244 | 244 |
| 245 public: | 245 public: |
| 246 enum InstKindARM32 { | 246 enum InstKindARM32 { |
| 247 k__Start = Inst::Target, | 247 k__Start = Inst::Target, |
| 248 Adc, |
| 249 Add, |
| 250 And, |
| 251 Eor, |
| 252 Ldr, |
| 253 Mla, |
| 248 Mov, | 254 Mov, |
| 249 Movt, | 255 Movt, |
| 250 Movw, | 256 Movw, |
| 257 Mul, |
| 251 Mvn, | 258 Mvn, |
| 259 Orr, |
| 252 Ret, | 260 Ret, |
| 253 Ldr | 261 Sbc, |
| 262 Sub, |
| 263 Umull |
| 254 }; | 264 }; |
| 255 | 265 |
| 256 static const char *getWidthString(Type Ty); | 266 static const char *getWidthString(Type Ty); |
| 257 | 267 |
| 258 void dump(const Cfg *Func) const override; | 268 void dump(const Cfg *Func) const override; |
| 259 | 269 |
| 260 protected: | 270 protected: |
| 261 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest) | 271 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest) |
| 262 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} | 272 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} |
| 263 ~InstARM32() override {} | 273 ~InstARM32() override {} |
| 264 static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) { | 274 static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) { |
| 265 return Inst->getKind() == static_cast<InstKind>(MyKind); | 275 return Inst->getKind() == static_cast<InstKind>(MyKind); |
| 266 } | 276 } |
| 267 }; | 277 }; |
| 268 | 278 |
| 269 void emitTwoAddr(const char *Opcode, const Inst *Inst, const Cfg *Func); | 279 void emitTwoAddr(const char *Opcode, const Inst *Inst, const Cfg *Func); |
| 280 void emitThreeAddr(const char *Opcode, const Inst *Inst, const Cfg *Func, |
| 281 bool SetFlags); |
| 270 | 282 |
| 271 // TODO(jvoung): add condition codes if instruction can be predicated. | 283 // TODO(jvoung): add condition codes if instruction can be predicated. |
| 272 | 284 |
| 273 // Instructions of the form x := op(y). | 285 // Instructions of the form x := op(y). |
| 274 template <InstARM32::InstKindARM32 K> | 286 template <InstARM32::InstKindARM32 K> |
| 275 class InstARM32UnaryopGPR : public InstARM32 { | 287 class InstARM32UnaryopGPR : public InstARM32 { |
| 276 InstARM32UnaryopGPR() = delete; | 288 InstARM32UnaryopGPR() = delete; |
| 277 InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete; | 289 InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete; |
| 278 InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete; | 290 InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete; |
| 279 | 291 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 private: | 402 private: |
| 391 InstARM32Movlike(Cfg *Func, Variable *Dest, Operand *Source) | 403 InstARM32Movlike(Cfg *Func, Variable *Dest, Operand *Source) |
| 392 : InstARM32(Func, K, 1, Dest) { | 404 : InstARM32(Func, K, 1, Dest) { |
| 393 addSource(Source); | 405 addSource(Source); |
| 394 } | 406 } |
| 395 ~InstARM32Movlike() override {} | 407 ~InstARM32Movlike() override {} |
| 396 | 408 |
| 397 static const char *Opcode; | 409 static const char *Opcode; |
| 398 }; | 410 }; |
| 399 | 411 |
| 412 // Instructions of the form x := y op z. May have the side-effect of setting |
| 413 // status flags. |
| 414 template <InstARM32::InstKindARM32 K> |
| 415 class InstARM32ThreeAddrGPR : public InstARM32 { |
| 416 InstARM32ThreeAddrGPR() = delete; |
| 417 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete; |
| 418 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete; |
| 419 |
| 420 public: |
| 421 // Create an ordinary binary-op instruction like add, and sub. |
| 422 // Dest and Src1 must be registers. |
| 423 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest, |
| 424 Variable *Src1, Operand *Src2, |
| 425 bool SetFlags = false) { |
| 426 return new (Func->allocate<InstARM32ThreeAddrGPR>()) |
| 427 InstARM32ThreeAddrGPR(Func, Dest, Src1, Src2, SetFlags); |
| 428 } |
| 429 void emit(const Cfg *Func) const override { |
| 430 if (!ALLOW_DUMP) |
| 431 return; |
| 432 emitThreeAddr(Opcode, this, Func, SetFlags); |
| 433 } |
| 434 void emitIAS(const Cfg *Func) const override { |
| 435 (void)Func; |
| 436 llvm::report_fatal_error("Not yet implemented"); |
| 437 } |
| 438 void dump(const Cfg *Func) const override { |
| 439 if (!ALLOW_DUMP) |
| 440 return; |
| 441 Ostream &Str = Func->getContext()->getStrDump(); |
| 442 dumpDest(Func); |
| 443 Str << " = " << Opcode << (SetFlags ? "s" : "") << "." |
| 444 << getDest()->getType() << " "; |
| 445 dumpSources(Func); |
| 446 } |
| 447 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 448 |
| 449 private: |
| 450 InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src1, |
| 451 Operand *Src2, bool SetFlags) |
| 452 : InstARM32(Func, K, 2, Dest), SetFlags(SetFlags) { |
| 453 addSource(Src1); |
| 454 addSource(Src2); |
| 455 } |
| 456 ~InstARM32ThreeAddrGPR() override {} |
| 457 static const char *Opcode; |
| 458 bool SetFlags; |
| 459 }; |
| 460 |
| 461 typedef InstARM32ThreeAddrGPR<InstARM32::Adc> InstARM32Adc; |
| 462 typedef InstARM32ThreeAddrGPR<InstARM32::Add> InstARM32Add; |
| 463 typedef InstARM32ThreeAddrGPR<InstARM32::And> InstARM32And; |
| 464 typedef InstARM32ThreeAddrGPR<InstARM32::Eor> InstARM32Eor; |
| 465 typedef InstARM32ThreeAddrGPR<InstARM32::Mul> InstARM32Mul; |
| 466 typedef InstARM32ThreeAddrGPR<InstARM32::Orr> InstARM32Orr; |
| 467 typedef InstARM32ThreeAddrGPR<InstARM32::Sbc> InstARM32Sbc; |
| 468 typedef InstARM32ThreeAddrGPR<InstARM32::Sub> InstARM32Sub; |
| 400 // Move instruction (variable <- flex). This is more of a pseudo-inst. | 469 // Move instruction (variable <- flex). This is more of a pseudo-inst. |
| 401 // If var is a register, then we use "mov". If var is stack, then we use | 470 // If var is a register, then we use "mov". If var is stack, then we use |
| 402 // "str" to store to the stack. | 471 // "str" to store to the stack. |
| 403 typedef InstARM32Movlike<InstARM32::Mov> InstARM32Mov; | 472 typedef InstARM32Movlike<InstARM32::Mov> InstARM32Mov; |
| 404 // MovT leaves the bottom bits alone so dest is also a source. | 473 // MovT leaves the bottom bits alone so dest is also a source. |
| 405 // This helps indicate that a previous MovW setting dest is not dead code. | 474 // This helps indicate that a previous MovW setting dest is not dead code. |
| 406 typedef InstARM32TwoAddrGPR<InstARM32::Movt> InstARM32Movt; | 475 typedef InstARM32TwoAddrGPR<InstARM32::Movt> InstARM32Movt; |
| 407 typedef InstARM32UnaryopGPR<InstARM32::Movw> InstARM32Movw; | 476 typedef InstARM32UnaryopGPR<InstARM32::Movw> InstARM32Movw; |
| 408 typedef InstARM32UnaryopGPR<InstARM32::Mvn> InstARM32Mvn; | 477 typedef InstARM32UnaryopGPR<InstARM32::Mvn> InstARM32Mvn; |
| 409 | 478 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 421 void emit(const Cfg *Func) const override; | 490 void emit(const Cfg *Func) const override; |
| 422 void emitIAS(const Cfg *Func) const override; | 491 void emitIAS(const Cfg *Func) const override; |
| 423 void dump(const Cfg *Func) const override; | 492 void dump(const Cfg *Func) const override; |
| 424 static bool classof(const Inst *Inst) { return isClassof(Inst, Ldr); } | 493 static bool classof(const Inst *Inst) { return isClassof(Inst, Ldr); } |
| 425 | 494 |
| 426 private: | 495 private: |
| 427 InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem); | 496 InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem); |
| 428 ~InstARM32Ldr() override {} | 497 ~InstARM32Ldr() override {} |
| 429 }; | 498 }; |
| 430 | 499 |
| 500 // Multiply Accumulate: d := x * y + a |
| 501 class InstARM32Mla : public InstARM32 { |
| 502 InstARM32Mla() = delete; |
| 503 InstARM32Mla(const InstARM32Mla &) = delete; |
| 504 InstARM32Mla &operator=(const InstARM32Mla &) = delete; |
| 505 |
| 506 public: |
| 507 // Everything must be a register. |
| 508 static InstARM32Mla *create(Cfg *Func, Variable *Dest, Variable *Src0, |
| 509 Variable *Src1, Variable *Acc) { |
| 510 return new (Func->allocate<InstARM32Mla>()) |
| 511 InstARM32Mla(Func, Dest, Src0, Src1, Acc); |
| 512 } |
| 513 void emit(const Cfg *Func) const override; |
| 514 void emitIAS(const Cfg *Func) const override; |
| 515 void dump(const Cfg *Func) const override; |
| 516 static bool classof(const Inst *Inst) { return isClassof(Inst, Mla); } |
| 517 |
| 518 private: |
| 519 InstARM32Mla(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1, |
| 520 Variable *Acc); |
| 521 ~InstARM32Mla() override {} |
| 522 }; |
| 523 |
| 431 // Ret pseudo-instruction. This is actually a "bx" instruction with | 524 // Ret pseudo-instruction. This is actually a "bx" instruction with |
| 432 // an "lr" register operand, but epilogue lowering will search for a Ret | 525 // an "lr" register operand, but epilogue lowering will search for a Ret |
| 433 // instead of a generic "bx". This instruction also takes a Source | 526 // instead of a generic "bx". This instruction also takes a Source |
| 434 // operand (for non-void returning functions) for liveness analysis, though | 527 // operand (for non-void returning functions) for liveness analysis, though |
| 435 // a FakeUse before the ret would do just as well. | 528 // a FakeUse before the ret would do just as well. |
| 436 class InstARM32Ret : public InstARM32 { | 529 class InstARM32Ret : public InstARM32 { |
| 437 InstARM32Ret() = delete; | 530 InstARM32Ret() = delete; |
| 438 InstARM32Ret(const InstARM32Ret &) = delete; | 531 InstARM32Ret(const InstARM32Ret &) = delete; |
| 439 InstARM32Ret &operator=(const InstARM32Ret &) = delete; | 532 InstARM32Ret &operator=(const InstARM32Ret &) = delete; |
| 440 | 533 |
| 441 public: | 534 public: |
| 442 static InstARM32Ret *create(Cfg *Func, Variable *LR, | 535 static InstARM32Ret *create(Cfg *Func, Variable *LR, |
| 443 Variable *Source = nullptr) { | 536 Variable *Source = nullptr) { |
| 444 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source); | 537 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source); |
| 445 } | 538 } |
| 446 void emit(const Cfg *Func) const override; | 539 void emit(const Cfg *Func) const override; |
| 447 void emitIAS(const Cfg *Func) const override; | 540 void emitIAS(const Cfg *Func) const override; |
| 448 void dump(const Cfg *Func) const override; | 541 void dump(const Cfg *Func) const override; |
| 449 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } | 542 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } |
| 450 | 543 |
| 451 private: | 544 private: |
| 452 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source); | 545 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source); |
| 453 ~InstARM32Ret() override {} | 546 ~InstARM32Ret() override {} |
| 454 }; | 547 }; |
| 455 | 548 |
| 549 // Unsigned Multiply Long: d.lo, d.hi := x * y |
| 550 class InstARM32Umull : public InstARM32 { |
| 551 InstARM32Umull() = delete; |
| 552 InstARM32Umull(const InstARM32Umull &) = delete; |
| 553 InstARM32Umull &operator=(const InstARM32Umull &) = delete; |
| 554 |
| 555 public: |
| 556 // Everything must be a register. |
| 557 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi, |
| 558 Variable *Src0, Variable *Src1) { |
| 559 return new (Func->allocate<InstARM32Umull>()) |
| 560 InstARM32Umull(Func, DestLo, DestHi, Src0, Src1); |
| 561 } |
| 562 void emit(const Cfg *Func) const override; |
| 563 void emitIAS(const Cfg *Func) const override; |
| 564 void dump(const Cfg *Func) const override; |
| 565 static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); } |
| 566 |
| 567 private: |
| 568 InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0, |
| 569 Variable *Src1); |
| 570 ~InstARM32Umull() override {} |
| 571 Variable *DestHi; |
| 572 }; |
| 573 |
| 456 // Declare partial template specializations of emit() methods that | 574 // Declare partial template specializations of emit() methods that |
| 457 // already have default implementations. Without this, there is the | 575 // already have default implementations. Without this, there is the |
| 458 // possibility of ODR violations and link errors. | 576 // possibility of ODR violations and link errors. |
| 459 | 577 |
| 460 template <> void InstARM32Movw::emit(const Cfg *Func) const; | 578 template <> void InstARM32Movw::emit(const Cfg *Func) const; |
| 461 template <> void InstARM32Movt::emit(const Cfg *Func) const; | 579 template <> void InstARM32Movt::emit(const Cfg *Func) const; |
| 462 | 580 |
| 463 } // end of namespace Ice | 581 } // end of namespace Ice |
| 464 | 582 |
| 465 #endif // SUBZERO_SRC_ICEINSTARM32_H | 583 #endif // SUBZERO_SRC_ICEINSTARM32_H |
| OLD | NEW |