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 |