Chromium Code Reviews| 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 /// \file | 10 /// \file |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 277 uint32_t Imm8 = Utils::rotateLeft32(Immediate, 2 * Rot); | 277 uint32_t Imm8 = Utils::rotateLeft32(Immediate, 2 * Rot); |
| 278 if (Imm8 <= 0xFF) { | 278 if (Imm8 <= 0xFF) { |
| 279 *RotateAmt = Rot; | 279 *RotateAmt = Rot; |
| 280 *Immed_8 = Imm8; | 280 *Immed_8 = Imm8; |
| 281 return true; | 281 return true; |
| 282 } | 282 } |
| 283 } | 283 } |
| 284 return false; | 284 return false; |
| 285 } | 285 } |
| 286 | 286 |
| 287 OperandARM32FlexFpImm::OperandARM32FlexFpImm(Cfg * /*Func*/, Type Ty, | |
| 288 uint32_t ModifiedImm) | |
| 289 : OperandARM32Flex(kFlexFpImm, Ty), ModifiedImm(ModifiedImm) {} | |
| 290 | |
| 291 bool OperandARM32FlexFpImm::canHoldImm(Operand *C, uint32_t *ModifiedImm) { | |
| 292 switch (C->getType()) { | |
| 293 default: | |
| 294 llvm::report_fatal_error("Unhandled fp constant type."); | |
| 295 case IceType_f32: { | |
| 296 // We violate llvm naming conventions a bit here so that the constants are | |
| 297 // named after the bit fields they represent. See "A7.5.1 Operation of | |
| 298 // modified immediate constants, Floating-point" in the ARM ARM. | |
| 299 static constexpr uint32_t a = 0x80000000; | |
|
sehr
2015/11/13 21:56:29
0x80000000u?
John
2015/11/14 00:00:38
Done.
| |
| 300 static constexpr uint32_t B = 0x40000000; | |
| 301 static constexpr uint32_t bbbbb = 0x3E000000; | |
| 302 static constexpr uint32_t cdefgh = 0x01F80000; | |
| 303 static constexpr uint32_t AllowedBits = a | B | bbbbb | cdefgh; | |
| 304 static_assert(AllowedBits == 0xFFF80000, | |
|
sehr
2015/11/13 21:56:29
Ditto regarding u suffix, here and below wherever
John
2015/11/14 00:00:38
Done.
| |
| 305 "Invalid mask for f32 modified immediates."); | |
| 306 const float F32 = llvm::cast<ConstantFloat>(C)->getValue(); | |
| 307 const uint32_t I32 = *reinterpret_cast<const uint32_t *>(&F32); | |
| 308 if (I32 & ~AllowedBits) { | |
| 309 // constant has disallowed bits. | |
| 310 return false; | |
| 311 } | |
| 312 | |
| 313 if ((I32 & bbbbb) != bbbbb && (I32 & bbbbb)) { | |
| 314 // not all bbbbb bits are 0 or 1. | |
| 315 return false; | |
| 316 } | |
| 317 | |
| 318 if (((I32 & B) != 0) == ((I32 & bbbbb) != 0)) { | |
| 319 // B ^ b = 0; | |
| 320 return false; | |
| 321 } | |
| 322 | |
| 323 *ModifiedImm = ((I32 & a) ? 0x80 : 0x00) | ((I32 & bbbbb) ? 0x40 : 0x00) | | |
| 324 ((I32 & cdefgh) >> 19); | |
| 325 return true; | |
| 326 } | |
| 327 case IceType_f64: { | |
| 328 static constexpr uint32_t a = 0x80000000; | |
| 329 static constexpr uint32_t B = 0x40000000; | |
| 330 static constexpr uint32_t bbbbbbbb = 0x3FC00000; | |
| 331 static constexpr uint32_t cdefgh = 0x003F0000; | |
| 332 static constexpr uint32_t AllowedBits = a | B | bbbbbbbb | cdefgh; | |
| 333 static_assert(AllowedBits == 0xFFFF0000, | |
| 334 "Invalid mask for f64 modified immediates."); | |
| 335 const double F64 = llvm::cast<ConstantDouble>(C)->getValue(); | |
| 336 const uint64_t I64 = *reinterpret_cast<const uint64_t *>(&F64); | |
| 337 if (I64 & 0xFFFFFFFF) { | |
| 338 // constant has disallowed bits. | |
| 339 return false; | |
| 340 } | |
| 341 const uint32_t I32 = I64 >> 32; | |
| 342 | |
| 343 if (I32 & ~AllowedBits) { | |
| 344 // constant has disallowed bits. | |
| 345 return false; | |
| 346 } | |
| 347 | |
| 348 if ((I32 & bbbbbbbb) != bbbbbbbb && (I32 & bbbbbbbb)) { | |
| 349 // not all bbbbb bits are 0 or 1. | |
| 350 return false; | |
| 351 } | |
| 352 | |
| 353 if (((I32 & B) != 0) == ((I32 & bbbbbbbb) != 0)) { | |
| 354 // B ^ b = 0; | |
| 355 return false; | |
| 356 } | |
| 357 | |
| 358 *ModifiedImm = ((I32 & a) ? 0x80 : 0x00) | | |
| 359 ((I32 & bbbbbbbb) ? 0x40 : 0x00) | ((I32 & cdefgh) >> 16); | |
| 360 return true; | |
| 361 } | |
| 362 } | |
| 363 } | |
| 364 | |
| 365 OperandARM32FlexFpZero::OperandARM32FlexFpZero(Cfg * /*Func*/, Type Ty) | |
| 366 : OperandARM32Flex(kFlexFpZero, Ty) {} | |
| 367 | |
| 287 OperandARM32FlexReg::OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, | 368 OperandARM32FlexReg::OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, |
| 288 ShiftKind ShiftOp, Operand *ShiftAmt) | 369 ShiftKind ShiftOp, Operand *ShiftAmt) |
| 289 : OperandARM32Flex(kFlexReg, Ty), Reg(Reg), ShiftOp(ShiftOp), | 370 : OperandARM32Flex(kFlexReg, Ty), Reg(Reg), ShiftOp(ShiftOp), |
| 290 ShiftAmt(ShiftAmt) { | 371 ShiftAmt(ShiftAmt) { |
| 291 NumVars = 1; | 372 NumVars = 1; |
| 292 Variable *ShiftVar = llvm::dyn_cast_or_null<Variable>(ShiftAmt); | 373 Variable *ShiftVar = llvm::dyn_cast_or_null<Variable>(ShiftAmt); |
| 293 if (ShiftVar) | 374 if (ShiftVar) |
| 294 ++NumVars; | 375 ++NumVars; |
| 295 Vars = Func->allocateArrayOf<Variable *>(NumVars); | 376 Vars = Func->allocateArrayOf<Variable *>(NumVars); |
| 296 Vars[0] = Reg; | 377 Vars[0] = Reg; |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 550 } | 631 } |
| 551 | 632 |
| 552 template <> void InstARM32Tst::emitIAS(const Cfg *Func) const { | 633 template <> void InstARM32Tst::emitIAS(const Cfg *Func) const { |
| 553 assert(getSrcSize() == 2); | 634 assert(getSrcSize() == 2); |
| 554 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 635 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 555 Asm->tst(getSrc(0), getSrc(1), getPredicate()); | 636 Asm->tst(getSrc(0), getSrc(1), getPredicate()); |
| 556 if (Asm->needsTextFixup()) | 637 if (Asm->needsTextFixup()) |
| 557 emitUsingTextFixup(Func); | 638 emitUsingTextFixup(Func); |
| 558 } | 639 } |
| 559 | 640 |
| 560 InstARM32Vcmp::InstARM32Vcmp(Cfg *Func, Variable *Src0, Variable *Src1, | 641 InstARM32Vcmp::InstARM32Vcmp(Cfg *Func, Variable *Src0, Operand *Src1, |
| 561 CondARM32::Cond Predicate) | 642 CondARM32::Cond Predicate) |
| 562 : InstARM32Pred(Func, InstARM32::Vcmp, 2, nullptr, Predicate) { | 643 : InstARM32Pred(Func, InstARM32::Vcmp, 2, nullptr, Predicate) { |
| 644 HasSideEffects = true; | |
| 563 addSource(Src0); | 645 addSource(Src0); |
| 564 addSource(Src1); | 646 addSource(Src1); |
| 565 } | 647 } |
| 566 | 648 |
| 567 InstARM32Vmrs::InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate) | 649 InstARM32Vmrs::InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate) |
| 568 : InstARM32Pred(Func, InstARM32::Vmrs, 0, nullptr, Predicate) {} | 650 : InstARM32Pred(Func, InstARM32::Vmrs, 0, nullptr, Predicate) { |
| 651 HasSideEffects = true; | |
| 652 } | |
| 569 | 653 |
| 570 InstARM32Vabs::InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src, | 654 InstARM32Vabs::InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src, |
| 571 CondARM32::Cond Predicate) | 655 CondARM32::Cond Predicate) |
| 572 : InstARM32Pred(Func, InstARM32::Vabs, 1, Dest, Predicate) { | 656 : InstARM32Pred(Func, InstARM32::Vabs, 1, Dest, Predicate) { |
| 573 addSource(Src); | 657 addSource(Src); |
| 574 } | 658 } |
| 575 | 659 |
| 576 InstARM32Dmb::InstARM32Dmb(Cfg *Func) | 660 InstARM32Dmb::InstARM32Dmb(Cfg *Func) |
| 577 : InstARM32Pred(Func, InstARM32::Dmb, 0, nullptr, CondARM32::AL) {} | 661 : InstARM32Pred(Func, InstARM32::Dmb, 0, nullptr, CondARM32::AL) {} |
| 578 | 662 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 598 template <> const char *InstARM32Add::Opcode = "add"; | 682 template <> const char *InstARM32Add::Opcode = "add"; |
| 599 template <> const char *InstARM32And::Opcode = "and"; | 683 template <> const char *InstARM32And::Opcode = "and"; |
| 600 template <> const char *InstARM32Asr::Opcode = "asr"; | 684 template <> const char *InstARM32Asr::Opcode = "asr"; |
| 601 template <> const char *InstARM32Bic::Opcode = "bic"; | 685 template <> const char *InstARM32Bic::Opcode = "bic"; |
| 602 template <> const char *InstARM32Eor::Opcode = "eor"; | 686 template <> const char *InstARM32Eor::Opcode = "eor"; |
| 603 template <> const char *InstARM32Lsl::Opcode = "lsl"; | 687 template <> const char *InstARM32Lsl::Opcode = "lsl"; |
| 604 template <> const char *InstARM32Lsr::Opcode = "lsr"; | 688 template <> const char *InstARM32Lsr::Opcode = "lsr"; |
| 605 template <> const char *InstARM32Mul::Opcode = "mul"; | 689 template <> const char *InstARM32Mul::Opcode = "mul"; |
| 606 template <> const char *InstARM32Orr::Opcode = "orr"; | 690 template <> const char *InstARM32Orr::Opcode = "orr"; |
| 607 template <> const char *InstARM32Rsb::Opcode = "rsb"; | 691 template <> const char *InstARM32Rsb::Opcode = "rsb"; |
| 692 template <> const char *InstARM32Rsc::Opcode = "rsc"; | |
| 608 template <> const char *InstARM32Sbc::Opcode = "sbc"; | 693 template <> const char *InstARM32Sbc::Opcode = "sbc"; |
| 609 template <> const char *InstARM32Sdiv::Opcode = "sdiv"; | 694 template <> const char *InstARM32Sdiv::Opcode = "sdiv"; |
| 610 template <> const char *InstARM32Sub::Opcode = "sub"; | 695 template <> const char *InstARM32Sub::Opcode = "sub"; |
| 611 template <> const char *InstARM32Udiv::Opcode = "udiv"; | 696 template <> const char *InstARM32Udiv::Opcode = "udiv"; |
| 612 // FP | 697 // FP |
| 613 template <> const char *InstARM32Vadd::Opcode = "vadd"; | 698 template <> const char *InstARM32Vadd::Opcode = "vadd"; |
| 614 template <> const char *InstARM32Vdiv::Opcode = "vdiv"; | 699 template <> const char *InstARM32Vdiv::Opcode = "vdiv"; |
| 615 template <> const char *InstARM32Vmul::Opcode = "vmul"; | 700 template <> const char *InstARM32Vmul::Opcode = "vmul"; |
| 616 template <> const char *InstARM32Vsub::Opcode = "vsub"; | 701 template <> const char *InstARM32Vsub::Opcode = "vsub"; |
| 617 // Four-addr ops | 702 // Four-addr ops |
| (...skipping 1078 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1696 } | 1781 } |
| 1697 | 1782 |
| 1698 void OperandARM32FlexImm::dump(const Cfg * /* Func */, Ostream &Str) const { | 1783 void OperandARM32FlexImm::dump(const Cfg * /* Func */, Ostream &Str) const { |
| 1699 if (!BuildDefs::dump()) | 1784 if (!BuildDefs::dump()) |
| 1700 return; | 1785 return; |
| 1701 uint32_t Imm = getImm(); | 1786 uint32_t Imm = getImm(); |
| 1702 uint32_t RotateAmt = getRotateAmt(); | 1787 uint32_t RotateAmt = getRotateAmt(); |
| 1703 Str << "#(" << Imm << " ror 2*" << RotateAmt << ")"; | 1788 Str << "#(" << Imm << " ror 2*" << RotateAmt << ")"; |
| 1704 } | 1789 } |
| 1705 | 1790 |
| 1791 namespace { | |
| 1792 static constexpr uint32_t a = 0x80; | |
| 1793 static constexpr uint32_t b = 0x40; | |
| 1794 static constexpr uint32_t cdefgh = 0x3F; | |
| 1795 static constexpr uint32_t AllowedBits = a | b | cdefgh; | |
| 1796 static_assert(AllowedBits == 0xFF, | |
| 1797 "Invalid mask for f32/f64 constant rematerialization."); | |
| 1798 | |
| 1799 // There's no loss in always returning the modified immediate as float. | |
| 1800 // TODO(jpp): returning a double causes problems when outputting the constants | |
| 1801 // for filetype=asm. Why? | |
|
sehr
2015/11/13 21:56:29
How did you do the double version?
John
2015/11/14 00:00:38
almost the same things, except that the constant i
| |
| 1802 float materializeFloatImmediate(uint32_t ModifiedImm) { | |
| 1803 const uint32_t Ret = ((ModifiedImm & a) ? 0x80000000 : 0) | | |
| 1804 ((ModifiedImm & b) ? 0x3E000000 : 0x40000000) | | |
| 1805 ((ModifiedImm & cdefgh) << 19); | |
| 1806 return *reinterpret_cast<const float *>(&Ret); | |
| 1807 } | |
| 1808 | |
| 1809 } // end of anonymous namespace | |
| 1810 | |
| 1811 void OperandARM32FlexFpImm::emit(const Cfg *Func) const { | |
| 1812 if (!BuildDefs::dump()) | |
| 1813 return; | |
| 1814 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1815 switch (Ty) { | |
| 1816 default: | |
| 1817 llvm::report_fatal_error("Invalid flex fp imm type."); | |
| 1818 case IceType_f64: | |
| 1819 case IceType_f32: | |
| 1820 Str << "#" << materializeFloatImmediate(ModifiedImm) | |
| 1821 << " @ Modified: " << ModifiedImm; | |
| 1822 break; | |
| 1823 } | |
| 1824 } | |
| 1825 | |
| 1826 void OperandARM32FlexFpImm::dump(const Cfg * /*Func*/, Ostream &Str) const { | |
| 1827 if (!BuildDefs::dump()) | |
| 1828 return; | |
| 1829 Str << "#" << materializeFloatImmediate(ModifiedImm) | |
| 1830 << InstARM32::getVecWidthString(Ty); | |
| 1831 } | |
| 1832 | |
| 1833 void OperandARM32FlexFpZero::emit(const Cfg *Func) const { | |
| 1834 if (!BuildDefs::dump()) | |
| 1835 return; | |
| 1836 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1837 switch (Ty) { | |
| 1838 default: | |
| 1839 llvm::report_fatal_error("Invalid flex fp imm type."); | |
| 1840 case IceType_f64: | |
| 1841 case IceType_f32: | |
| 1842 Str << "#0.0"; | |
| 1843 } | |
| 1844 } | |
| 1845 | |
| 1846 void OperandARM32FlexFpZero::dump(const Cfg * /*Func*/, Ostream &Str) const { | |
| 1847 if (!BuildDefs::dump()) | |
| 1848 return; | |
| 1849 Str << "#0.0" << InstARM32::getVecWidthString(Ty); | |
| 1850 } | |
| 1851 | |
| 1706 void OperandARM32FlexReg::emit(const Cfg *Func) const { | 1852 void OperandARM32FlexReg::emit(const Cfg *Func) const { |
| 1707 if (!BuildDefs::dump()) | 1853 if (!BuildDefs::dump()) |
| 1708 return; | 1854 return; |
| 1709 Ostream &Str = Func->getContext()->getStrEmit(); | 1855 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1710 getReg()->emit(Func); | 1856 getReg()->emit(Func); |
| 1711 if (getShiftOp() != kNoShift) { | 1857 if (getShiftOp() != kNoShift) { |
| 1712 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " "; | 1858 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " "; |
| 1713 getShiftAmt()->emit(Func); | 1859 getShiftAmt()->emit(Func); |
| 1714 } | 1860 } |
| 1715 } | 1861 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1736 template class InstARM32ThreeAddrGPR<InstARM32::Add>; | 1882 template class InstARM32ThreeAddrGPR<InstARM32::Add>; |
| 1737 template class InstARM32ThreeAddrGPR<InstARM32::And>; | 1883 template class InstARM32ThreeAddrGPR<InstARM32::And>; |
| 1738 template class InstARM32ThreeAddrGPR<InstARM32::Asr>; | 1884 template class InstARM32ThreeAddrGPR<InstARM32::Asr>; |
| 1739 template class InstARM32ThreeAddrGPR<InstARM32::Bic>; | 1885 template class InstARM32ThreeAddrGPR<InstARM32::Bic>; |
| 1740 template class InstARM32ThreeAddrGPR<InstARM32::Eor>; | 1886 template class InstARM32ThreeAddrGPR<InstARM32::Eor>; |
| 1741 template class InstARM32ThreeAddrGPR<InstARM32::Lsl>; | 1887 template class InstARM32ThreeAddrGPR<InstARM32::Lsl>; |
| 1742 template class InstARM32ThreeAddrGPR<InstARM32::Lsr>; | 1888 template class InstARM32ThreeAddrGPR<InstARM32::Lsr>; |
| 1743 template class InstARM32ThreeAddrGPR<InstARM32::Mul>; | 1889 template class InstARM32ThreeAddrGPR<InstARM32::Mul>; |
| 1744 template class InstARM32ThreeAddrGPR<InstARM32::Orr>; | 1890 template class InstARM32ThreeAddrGPR<InstARM32::Orr>; |
| 1745 template class InstARM32ThreeAddrGPR<InstARM32::Rsb>; | 1891 template class InstARM32ThreeAddrGPR<InstARM32::Rsb>; |
| 1892 template class InstARM32ThreeAddrGPR<InstARM32::Rsc>; | |
| 1746 template class InstARM32ThreeAddrGPR<InstARM32::Sbc>; | 1893 template class InstARM32ThreeAddrGPR<InstARM32::Sbc>; |
| 1747 template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>; | 1894 template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>; |
| 1748 template class InstARM32ThreeAddrGPR<InstARM32::Sub>; | 1895 template class InstARM32ThreeAddrGPR<InstARM32::Sub>; |
| 1749 template class InstARM32ThreeAddrGPR<InstARM32::Udiv>; | 1896 template class InstARM32ThreeAddrGPR<InstARM32::Udiv>; |
| 1750 | 1897 |
| 1751 template class InstARM32ThreeAddrFP<InstARM32::Vadd>; | 1898 template class InstARM32ThreeAddrFP<InstARM32::Vadd>; |
| 1752 template class InstARM32ThreeAddrFP<InstARM32::Vdiv>; | 1899 template class InstARM32ThreeAddrFP<InstARM32::Vdiv>; |
| 1753 template class InstARM32ThreeAddrFP<InstARM32::Vmul>; | 1900 template class InstARM32ThreeAddrFP<InstARM32::Vmul>; |
| 1754 template class InstARM32ThreeAddrFP<InstARM32::Vsub>; | 1901 template class InstARM32ThreeAddrFP<InstARM32::Vsub>; |
| 1755 | 1902 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1767 template class InstARM32UnaryopGPR<InstARM32::Uxt, true>; | 1914 template class InstARM32UnaryopGPR<InstARM32::Uxt, true>; |
| 1768 template class InstARM32UnaryopFP<InstARM32::Vsqrt>; | 1915 template class InstARM32UnaryopFP<InstARM32::Vsqrt>; |
| 1769 | 1916 |
| 1770 template class InstARM32FourAddrGPR<InstARM32::Mla>; | 1917 template class InstARM32FourAddrGPR<InstARM32::Mla>; |
| 1771 template class InstARM32FourAddrGPR<InstARM32::Mls>; | 1918 template class InstARM32FourAddrGPR<InstARM32::Mls>; |
| 1772 | 1919 |
| 1773 template class InstARM32CmpLike<InstARM32::Cmp>; | 1920 template class InstARM32CmpLike<InstARM32::Cmp>; |
| 1774 template class InstARM32CmpLike<InstARM32::Tst>; | 1921 template class InstARM32CmpLike<InstARM32::Tst>; |
| 1775 | 1922 |
| 1776 } // end of namespace Ice | 1923 } // end of namespace Ice |
| OLD | NEW |