| 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 15 matching lines...) Expand all Loading... |
| 26 namespace ARM32 { | 26 namespace ARM32 { |
| 27 | 27 |
| 28 namespace { | 28 namespace { |
| 29 | 29 |
| 30 using Register = RegARM32::AllRegisters; | 30 using Register = RegARM32::AllRegisters; |
| 31 | 31 |
| 32 // maximum number of registers allowed in vpush/vpop. | 32 // maximum number of registers allowed in vpush/vpop. |
| 33 static constexpr SizeT VpushVpopMaxConsecRegs = 16; | 33 static constexpr SizeT VpushVpopMaxConsecRegs = 16; |
| 34 | 34 |
| 35 const struct TypeARM32Attributes_ { | 35 const struct TypeARM32Attributes_ { |
| 36 const char *WidthString; // b, h, <blank>, or d | 36 const char *WidthString; // b, h, <blank>, or d |
| 37 const char *VecWidthString; // i8, i16, i32, f32, f64 | 37 const char *FpWidthString; // i8, i16, i32, f32, f64 |
| 38 const char *SVecWidthString; // s8, s16, s32, f32 |
| 39 const char *UVecWidthString; // u8, u16, u32, f32 |
| 38 int8_t SExtAddrOffsetBits; | 40 int8_t SExtAddrOffsetBits; |
| 39 int8_t ZExtAddrOffsetBits; | 41 int8_t ZExtAddrOffsetBits; |
| 40 } TypeARM32Attributes[] = { | 42 } TypeARM32Attributes[] = { |
| 41 #define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr, shaddr) \ | 43 #define X(tag, elementty, int_width, fp_width, uvec_width, svec_width, sbits, \ |
| 42 { int_width, vec_width, sbits, ubits } \ | 44 ubits, rraddr, shaddr) \ |
| 45 { int_width, fp_width, svec_width, uvec_width, sbits, ubits } \ |
| 43 , | 46 , |
| 44 ICETYPEARM32_TABLE | 47 ICETYPEARM32_TABLE |
| 45 #undef X | 48 #undef X |
| 46 }; | 49 }; |
| 47 | 50 |
| 48 const struct InstARM32ShiftAttributes_ { | 51 const struct InstARM32ShiftAttributes_ { |
| 49 const char *EmitString; | 52 const char *EmitString; |
| 50 } InstARM32ShiftAttributes[] = { | 53 } InstARM32ShiftAttributes[] = { |
| 51 #define X(tag, emit) \ | 54 #define X(tag, emit) \ |
| 52 { emit } \ | 55 { emit } \ |
| (...skipping 10 matching lines...) Expand all Loading... |
| 63 { CondARM32::opp, emit } \ | 66 { CondARM32::opp, emit } \ |
| 64 , | 67 , |
| 65 ICEINSTARM32COND_TABLE | 68 ICEINSTARM32COND_TABLE |
| 66 #undef X | 69 #undef X |
| 67 }; | 70 }; |
| 68 | 71 |
| 69 size_t getVecElmtBitsize(Type Ty) { | 72 size_t getVecElmtBitsize(Type Ty) { |
| 70 return typeWidthInBytes(typeElementType(Ty)) * CHAR_BIT; | 73 return typeWidthInBytes(typeElementType(Ty)) * CHAR_BIT; |
| 71 } | 74 } |
| 72 | 75 |
| 76 const char *getWidthString(Type Ty) { |
| 77 return TypeARM32Attributes[Ty].WidthString; |
| 78 } |
| 79 |
| 80 const char *getFpWidthString(Type Ty) { |
| 81 return TypeARM32Attributes[Ty].FpWidthString; |
| 82 } |
| 83 |
| 84 const char *getSVecWidthString(Type Ty) { |
| 85 return TypeARM32Attributes[Ty].SVecWidthString; |
| 86 } |
| 87 |
| 88 const char *getUVecWidthString(Type Ty) { |
| 89 return TypeARM32Attributes[Ty].UVecWidthString; |
| 90 } |
| 91 |
| 92 const char *getVWidthString(Type Ty, InstARM32::FPSign SignType) { |
| 93 switch (SignType) { |
| 94 case InstARM32::FS_None: |
| 95 return getFpWidthString(Ty); |
| 96 case InstARM32::FS_Signed: |
| 97 return getSVecWidthString(Ty); |
| 98 case InstARM32::FS_Unsigned: |
| 99 return getUVecWidthString(Ty); |
| 100 } |
| 101 llvm_unreachable("Invalid Sign Type."); |
| 102 return getFpWidthString(Ty); |
| 103 } |
| 104 |
| 73 } // end of anonymous namespace | 105 } // end of anonymous namespace |
| 74 | 106 |
| 75 const char *InstARM32::getWidthString(Type Ty) { | |
| 76 return TypeARM32Attributes[Ty].WidthString; | |
| 77 } | |
| 78 | |
| 79 const char *InstARM32::getVecWidthString(Type Ty) { | |
| 80 return TypeARM32Attributes[Ty].VecWidthString; | |
| 81 } | |
| 82 | |
| 83 const char *InstARM32Pred::predString(CondARM32::Cond Pred) { | 107 const char *InstARM32Pred::predString(CondARM32::Cond Pred) { |
| 84 return InstARM32CondAttributes[Pred].EmitString; | 108 return InstARM32CondAttributes[Pred].EmitString; |
| 85 } | 109 } |
| 86 | 110 |
| 87 void InstARM32Pred::dumpOpcodePred(Ostream &Str, const char *Opcode, | 111 void InstARM32Pred::dumpOpcodePred(Ostream &Str, const char *Opcode, |
| 88 Type Ty) const { | 112 Type Ty) const { |
| 89 Str << Opcode << getPredicate() << "." << Ty; | 113 Str << Opcode << getPredicate() << "." << Ty; |
| 90 } | 114 } |
| 91 | 115 |
| 92 CondARM32::Cond InstARM32::getOppositeCondition(CondARM32::Cond Cond) { | 116 CondARM32::Cond InstARM32::getOppositeCondition(CondARM32::Cond Cond) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 Type SrcTy = Instr->getSrc(0)->getType(); | 167 Type SrcTy = Instr->getSrc(0)->getType(); |
| 144 Str << "\t" << Opcode; | 168 Str << "\t" << Opcode; |
| 145 if (NeedsWidthSuffix) | 169 if (NeedsWidthSuffix) |
| 146 Str << getWidthString(SrcTy); | 170 Str << getWidthString(SrcTy); |
| 147 Str << Instr->getPredicate() << "\t"; | 171 Str << Instr->getPredicate() << "\t"; |
| 148 Instr->getDest()->emit(Func); | 172 Instr->getDest()->emit(Func); |
| 149 Str << ", "; | 173 Str << ", "; |
| 150 Instr->getSrc(0)->emit(Func); | 174 Instr->getSrc(0)->emit(Func); |
| 151 } | 175 } |
| 152 | 176 |
| 153 void InstARM32Pred::emitUnaryopFP(const char *Opcode, | 177 void InstARM32Pred::emitUnaryopFP(const char *Opcode, FPSign Sign, |
| 154 const InstARM32Pred *Instr, const Cfg *Func) { | 178 const InstARM32Pred *Instr, const Cfg *Func) { |
| 155 Ostream &Str = Func->getContext()->getStrEmit(); | 179 Ostream &Str = Func->getContext()->getStrEmit(); |
| 156 assert(Instr->getSrcSize() == 1); | 180 assert(Instr->getSrcSize() == 1); |
| 157 Type SrcTy = Instr->getSrc(0)->getType(); | 181 Type SrcTy = Instr->getSrc(0)->getType(); |
| 158 Str << "\t" << Opcode << Instr->getPredicate() << getVecWidthString(SrcTy) | 182 Str << "\t" << Opcode << Instr->getPredicate(); |
| 159 << "\t"; | 183 switch (Sign) { |
| 184 case FS_None: |
| 185 Str << getFpWidthString(SrcTy); |
| 186 break; |
| 187 case FS_Signed: |
| 188 Str << getSVecWidthString(SrcTy); |
| 189 break; |
| 190 case FS_Unsigned: |
| 191 Str << getUVecWidthString(SrcTy); |
| 192 break; |
| 193 } |
| 194 Str << "\t"; |
| 160 Instr->getDest()->emit(Func); | 195 Instr->getDest()->emit(Func); |
| 161 Str << ", "; | 196 Str << ", "; |
| 162 Instr->getSrc(0)->emit(Func); | 197 Instr->getSrc(0)->emit(Func); |
| 163 } | 198 } |
| 164 | 199 |
| 165 void InstARM32Pred::emitTwoAddr(const char *Opcode, const InstARM32Pred *Instr, | 200 void InstARM32Pred::emitTwoAddr(const char *Opcode, const InstARM32Pred *Instr, |
| 166 const Cfg *Func) { | 201 const Cfg *Func) { |
| 167 if (!BuildDefs::dump()) | 202 if (!BuildDefs::dump()) |
| 168 return; | 203 return; |
| 169 Ostream &Str = Func->getContext()->getStrEmit(); | 204 Ostream &Str = Func->getContext()->getStrEmit(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 185 assert(Instr->getSrcSize() == 2); | 220 assert(Instr->getSrcSize() == 2); |
| 186 Str << "\t" << Opcode << (SetFlags ? "s" : "") << Instr->getPredicate() | 221 Str << "\t" << Opcode << (SetFlags ? "s" : "") << Instr->getPredicate() |
| 187 << "\t"; | 222 << "\t"; |
| 188 Instr->getDest()->emit(Func); | 223 Instr->getDest()->emit(Func); |
| 189 Str << ", "; | 224 Str << ", "; |
| 190 Instr->getSrc(0)->emit(Func); | 225 Instr->getSrc(0)->emit(Func); |
| 191 Str << ", "; | 226 Str << ", "; |
| 192 Instr->getSrc(1)->emit(Func); | 227 Instr->getSrc(1)->emit(Func); |
| 193 } | 228 } |
| 194 | 229 |
| 195 void InstARM32::emitThreeAddrFP(const char *Opcode, const InstARM32 *Instr, | 230 void InstARM32::emitThreeAddrFP(const char *Opcode, FPSign SignType, |
| 196 const Cfg *Func) { | 231 const InstARM32 *Instr, const Cfg *Func) { |
| 197 if (!BuildDefs::dump()) | 232 if (!BuildDefs::dump()) |
| 198 return; | 233 return; |
| 199 Ostream &Str = Func->getContext()->getStrEmit(); | 234 Ostream &Str = Func->getContext()->getStrEmit(); |
| 200 assert(Instr->getSrcSize() == 2); | 235 assert(Instr->getSrcSize() == 2); |
| 201 Str << "\t" << Opcode << getVecWidthString(Instr->getDest()->getType()) | 236 Str << "\t" << Opcode |
| 202 << "\t"; | 237 << getVWidthString(Instr->getDest()->getType(), SignType) << "\t"; |
| 203 Instr->getDest()->emit(Func); | 238 Instr->getDest()->emit(Func); |
| 204 Str << ", "; | 239 Str << ", "; |
| 205 Instr->getSrc(0)->emit(Func); | 240 Instr->getSrc(0)->emit(Func); |
| 206 Str << ", "; | 241 Str << ", "; |
| 207 Instr->getSrc(1)->emit(Func); | 242 Instr->getSrc(1)->emit(Func); |
| 208 } | 243 } |
| 209 | 244 |
| 210 void InstARM32::emitFourAddrFP(const char *Opcode, const InstARM32 *Instr, | 245 void InstARM32::emitFourAddrFP(const char *Opcode, FPSign SignType, |
| 211 const Cfg *Func) { | 246 const InstARM32 *Instr, const Cfg *Func) { |
| 212 if (!BuildDefs::dump()) | 247 if (!BuildDefs::dump()) |
| 213 return; | 248 return; |
| 214 Ostream &Str = Func->getContext()->getStrEmit(); | 249 Ostream &Str = Func->getContext()->getStrEmit(); |
| 215 assert(Instr->getSrcSize() == 3); | 250 assert(Instr->getSrcSize() == 3); |
| 216 assert(Instr->getSrc(0) == Instr->getDest()); | 251 assert(Instr->getSrc(0) == Instr->getDest()); |
| 217 Str << "\t" << Opcode << getVecWidthString(Instr->getDest()->getType()) | 252 Str << "\t" << Opcode |
| 218 << "\t"; | 253 << getVWidthString(Instr->getDest()->getType(), SignType) << "\t"; |
| 219 Instr->getDest()->emit(Func); | 254 Instr->getDest()->emit(Func); |
| 220 Str << ", "; | 255 Str << ", "; |
| 221 Instr->getSrc(1)->emit(Func); | 256 Instr->getSrc(1)->emit(Func); |
| 222 Str << ", "; | 257 Str << ", "; |
| 223 Instr->getSrc(2)->emit(Func); | 258 Instr->getSrc(2)->emit(Func); |
| 224 } | 259 } |
| 225 | 260 |
| 226 void InstARM32Pred::emitFourAddr(const char *Opcode, const InstARM32Pred *Instr, | 261 void InstARM32Pred::emitFourAddr(const char *Opcode, const InstARM32Pred *Instr, |
| 227 const Cfg *Func) { | 262 const Cfg *Func) { |
| 228 if (!BuildDefs::dump()) | 263 if (!BuildDefs::dump()) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 247 template <InstARM32::InstKindARM32 K> | 282 template <InstARM32::InstKindARM32 K> |
| 248 void InstARM32FourAddrFP<K>::emitIAS(const Cfg *Func) const { | 283 void InstARM32FourAddrFP<K>::emitIAS(const Cfg *Func) const { |
| 249 emitUsingTextFixup(Func); | 284 emitUsingTextFixup(Func); |
| 250 } | 285 } |
| 251 | 286 |
| 252 template <InstARM32::InstKindARM32 K> | 287 template <InstARM32::InstKindARM32 K> |
| 253 void InstARM32ThreeAddrFP<K>::emitIAS(const Cfg *Func) const { | 288 void InstARM32ThreeAddrFP<K>::emitIAS(const Cfg *Func) const { |
| 254 emitUsingTextFixup(Func); | 289 emitUsingTextFixup(Func); |
| 255 } | 290 } |
| 256 | 291 |
| 292 template <InstARM32::InstKindARM32 K> |
| 293 void InstARM32ThreeAddrSignAwareFP<K>::emitIAS(const Cfg *Func) const { |
| 294 InstARM32::emitUsingTextFixup(Func); |
| 295 } |
| 296 |
| 257 template <> void InstARM32Mla::emitIAS(const Cfg *Func) const { | 297 template <> void InstARM32Mla::emitIAS(const Cfg *Func) const { |
| 258 assert(getSrcSize() == 3); | 298 assert(getSrcSize() == 3); |
| 259 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 299 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 260 Asm->mla(getDest(), getSrc(0), getSrc(1), getSrc(2), getPredicate()); | 300 Asm->mla(getDest(), getSrc(0), getSrc(1), getSrc(2), getPredicate()); |
| 261 if (Asm->needsTextFixup()) | 301 if (Asm->needsTextFixup()) |
| 262 emitUsingTextFixup(Func); | 302 emitUsingTextFixup(Func); |
| 263 } | 303 } |
| 264 | 304 |
| 265 template <> void InstARM32Mls::emitIAS(const Cfg *Func) const { | 305 template <> void InstARM32Mls::emitIAS(const Cfg *Func) const { |
| 266 assert(getSrcSize() == 3); | 306 assert(getSrcSize() == 3); |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 730 Asm->vmlss(getDest(), getSrc(1), getSrc(2), CondARM32::AL); | 770 Asm->vmlss(getDest(), getSrc(1), getSrc(2), CondARM32::AL); |
| 731 assert(!Asm->needsTextFixup()); | 771 assert(!Asm->needsTextFixup()); |
| 732 return; | 772 return; |
| 733 case IceType_f64: | 773 case IceType_f64: |
| 734 Asm->vmlsd(getDest(), getSrc(1), getSrc(2), CondARM32::AL); | 774 Asm->vmlsd(getDest(), getSrc(1), getSrc(2), CondARM32::AL); |
| 735 assert(!Asm->needsTextFixup()); | 775 assert(!Asm->needsTextFixup()); |
| 736 return; | 776 return; |
| 737 } | 777 } |
| 738 } | 778 } |
| 739 | 779 |
| 780 template <> void InstARM32Vneg::emitIAS(const Cfg *Func) const { |
| 781 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 782 const Variable *Dest = getDest(); |
| 783 const Type DestTy = Dest->getType(); |
| 784 switch (Dest->getType()) { |
| 785 default: |
| 786 llvm::report_fatal_error("Vneg not defined on type " + |
| 787 typeStdString(Dest->getType())); |
| 788 case IceType_v4i1: |
| 789 case IceType_v8i1: |
| 790 case IceType_v16i1: |
| 791 case IceType_v16i8: |
| 792 case IceType_v8i16: |
| 793 case IceType_v4i32: |
| 794 case IceType_v4f32: { |
| 795 const Type ElmtTy = typeElementType(DestTy); |
| 796 Asm->vnegqs(ElmtTy, Dest, getSrc(0)); |
| 797 } break; |
| 798 } |
| 799 } |
| 800 |
| 740 template <> void InstARM32Vorr::emitIAS(const Cfg *Func) const { | 801 template <> void InstARM32Vorr::emitIAS(const Cfg *Func) const { |
| 741 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 802 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 742 const Variable *Dest = getDest(); | 803 const Variable *Dest = getDest(); |
| 743 switch (Dest->getType()) { | 804 switch (Dest->getType()) { |
| 744 default: | 805 default: |
| 745 llvm::report_fatal_error("Vorr not defined on type " + | 806 llvm::report_fatal_error("Vorr not defined on type " + |
| 746 typeStdString(Dest->getType())); | 807 typeStdString(Dest->getType())); |
| 747 case IceType_v4i1: | 808 case IceType_v4i1: |
| 748 case IceType_v8i1: | 809 case IceType_v8i1: |
| 749 case IceType_v16i1: | 810 case IceType_v16i1: |
| 750 case IceType_v16i8: | 811 case IceType_v16i8: |
| 751 case IceType_v8i16: | 812 case IceType_v8i16: |
| 752 case IceType_v4i32: | 813 case IceType_v4i32: |
| 753 Asm->vorrq(Dest, getSrc(0), getSrc(1)); | 814 Asm->vorrq(Dest, getSrc(0), getSrc(1)); |
| 754 } | 815 } |
| 755 assert(!Asm->needsTextFixup()); | 816 assert(!Asm->needsTextFixup()); |
| 756 } | 817 } |
| 757 | 818 |
| 819 template <> void InstARM32Vshl::emitIAS(const Cfg *Func) const { |
| 820 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 821 const Variable *Dest = getDest(); |
| 822 const Type DestTy = Dest->getType(); |
| 823 switch (DestTy) { |
| 824 default: |
| 825 llvm::report_fatal_error("Vshl not defined on type " + |
| 826 typeStdString(Dest->getType())); |
| 827 case IceType_v4i1: |
| 828 case IceType_v8i1: |
| 829 case IceType_v16i1: |
| 830 case IceType_v16i8: |
| 831 case IceType_v8i16: |
| 832 case IceType_v4i32: { |
| 833 const Type ElmtTy = typeElementType(DestTy); |
| 834 assert(Sign != InstARM32::FS_None); |
| 835 switch (Sign) { |
| 836 case InstARM32::FS_None: // defaults to unsigned. |
| 837 case InstARM32::FS_Unsigned: |
| 838 Asm->vshlqu(ElmtTy, Dest, getSrc(0), getSrc(1)); |
| 839 break; |
| 840 case InstARM32::FS_Signed: |
| 841 Asm->vshlqi(ElmtTy, Dest, getSrc(0), getSrc(1)); |
| 842 break; |
| 843 } |
| 844 } break; |
| 845 } |
| 846 } |
| 847 |
| 758 template <> void InstARM32Vsub::emitIAS(const Cfg *Func) const { | 848 template <> void InstARM32Vsub::emitIAS(const Cfg *Func) const { |
| 759 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 849 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 760 const Variable *Dest = getDest(); | 850 const Variable *Dest = getDest(); |
| 761 Type DestTy = Dest->getType(); | 851 Type DestTy = Dest->getType(); |
| 762 switch (DestTy) { | 852 switch (DestTy) { |
| 763 default: | 853 default: |
| 764 llvm::report_fatal_error("Vsub not defined on type " + | 854 llvm::report_fatal_error("Vsub not defined on type " + |
| 765 typeStdString(DestTy)); | 855 typeStdString(DestTy)); |
| 766 case IceType_v16i8: | 856 case IceType_v16i8: |
| 767 case IceType_v8i16: | 857 case IceType_v8i16: |
| (...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1367 template <> const char *InstARM32Udiv::Opcode = "udiv"; | 1457 template <> const char *InstARM32Udiv::Opcode = "udiv"; |
| 1368 // FP | 1458 // FP |
| 1369 template <> const char *InstARM32Vadd::Opcode = "vadd"; | 1459 template <> const char *InstARM32Vadd::Opcode = "vadd"; |
| 1370 template <> const char *InstARM32Vand::Opcode = "vand"; | 1460 template <> const char *InstARM32Vand::Opcode = "vand"; |
| 1371 template <> const char *InstARM32Vdiv::Opcode = "vdiv"; | 1461 template <> const char *InstARM32Vdiv::Opcode = "vdiv"; |
| 1372 template <> const char *InstARM32Veor::Opcode = "veor"; | 1462 template <> const char *InstARM32Veor::Opcode = "veor"; |
| 1373 template <> const char *InstARM32Vmla::Opcode = "vmla"; | 1463 template <> const char *InstARM32Vmla::Opcode = "vmla"; |
| 1374 template <> const char *InstARM32Vmls::Opcode = "vmls"; | 1464 template <> const char *InstARM32Vmls::Opcode = "vmls"; |
| 1375 template <> const char *InstARM32Vmul::Opcode = "vmul"; | 1465 template <> const char *InstARM32Vmul::Opcode = "vmul"; |
| 1376 template <> const char *InstARM32Vorr::Opcode = "vorr"; | 1466 template <> const char *InstARM32Vorr::Opcode = "vorr"; |
| 1467 template <> const char *InstARM32UnaryopFP<InstARM32::Vneg>::Opcode = "vneg"; |
| 1468 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vshl>::Opcode = "vshl"; |
| 1377 template <> const char *InstARM32Vsub::Opcode = "vsub"; | 1469 template <> const char *InstARM32Vsub::Opcode = "vsub"; |
| 1378 // Four-addr ops | 1470 // Four-addr ops |
| 1379 template <> const char *InstARM32Mla::Opcode = "mla"; | 1471 template <> const char *InstARM32Mla::Opcode = "mla"; |
| 1380 template <> const char *InstARM32Mls::Opcode = "mls"; | 1472 template <> const char *InstARM32Mls::Opcode = "mls"; |
| 1381 // Cmp-like ops | 1473 // Cmp-like ops |
| 1382 template <> const char *InstARM32Cmn::Opcode = "cmn"; | 1474 template <> const char *InstARM32Cmn::Opcode = "cmn"; |
| 1383 template <> const char *InstARM32Cmp::Opcode = "cmp"; | 1475 template <> const char *InstARM32Cmp::Opcode = "cmp"; |
| 1384 template <> const char *InstARM32Tst::Opcode = "tst"; | 1476 template <> const char *InstARM32Tst::Opcode = "tst"; |
| 1385 | 1477 |
| 1386 void InstARM32::dump(const Cfg *Func) const { | 1478 void InstARM32::dump(const Cfg *Func) const { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1472 | 1564 |
| 1473 Type Ty = Dest->getType(); | 1565 Type Ty = Dest->getType(); |
| 1474 const bool IsVector = isVectorType(Ty); | 1566 const bool IsVector = isVectorType(Ty); |
| 1475 const bool IsScalarFP = isScalarFloatingType(Ty); | 1567 const bool IsScalarFP = isScalarFloatingType(Ty); |
| 1476 const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0); | 1568 const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0); |
| 1477 const bool IsVMove = (IsVector || IsScalarFP || CoreVFPMove); | 1569 const bool IsVMove = (IsVector || IsScalarFP || CoreVFPMove); |
| 1478 const char *Opcode = IsVMove ? "vmov" : "mov"; | 1570 const char *Opcode = IsVMove ? "vmov" : "mov"; |
| 1479 // when vmov{c}'ing, we need to emit a width string. Otherwise, the | 1571 // when vmov{c}'ing, we need to emit a width string. Otherwise, the |
| 1480 // assembler might be tempted to assume we want a vector vmov{c}, and that | 1572 // assembler might be tempted to assume we want a vector vmov{c}, and that |
| 1481 // is disallowed because ARM. | 1573 // is disallowed because ARM. |
| 1482 const char *WidthString = !CoreVFPMove ? getVecWidthString(Ty) : ""; | 1574 const char *WidthString = !CoreVFPMove ? getFpWidthString(Ty) : ""; |
| 1483 CondARM32::Cond Cond = getPredicate(); | 1575 CondARM32::Cond Cond = getPredicate(); |
| 1484 if (IsVector) | 1576 if (IsVector) |
| 1485 assert(CondARM32::isUnconditional(Cond) && | 1577 assert(CondARM32::isUnconditional(Cond) && |
| 1486 "Moves on vectors must be unconditional!"); | 1578 "Moves on vectors must be unconditional!"); |
| 1487 Str << "\t" << Opcode; | 1579 Str << "\t" << Opcode; |
| 1488 if (IsVMove) { | 1580 if (IsVMove) { |
| 1489 Str << Cond << WidthString; | 1581 Str << Cond << WidthString; |
| 1490 } else { | 1582 } else { |
| 1491 Str << WidthString << Cond; | 1583 Str << WidthString << Cond; |
| 1492 } | 1584 } |
| (...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2002 Asm->uxt(getDest(), getSrc(0), getPredicate()); | 2094 Asm->uxt(getDest(), getSrc(0), getPredicate()); |
| 2003 if (Asm->needsTextFixup()) | 2095 if (Asm->needsTextFixup()) |
| 2004 emitUsingTextFixup(Func); | 2096 emitUsingTextFixup(Func); |
| 2005 } | 2097 } |
| 2006 | 2098 |
| 2007 template <InstARM32::InstKindARM32 K> | 2099 template <InstARM32::InstKindARM32 K> |
| 2008 void InstARM32UnaryopFP<K>::emitIAS(const Cfg *Func) const { | 2100 void InstARM32UnaryopFP<K>::emitIAS(const Cfg *Func) const { |
| 2009 emitUsingTextFixup(Func); | 2101 emitUsingTextFixup(Func); |
| 2010 } | 2102 } |
| 2011 | 2103 |
| 2104 template <InstARM32::InstKindARM32 K> |
| 2105 void InstARM32UnaryopSignAwareFP<K>::emitIAS(const Cfg *Func) const { |
| 2106 InstARM32::emitUsingTextFixup(Func); |
| 2107 } |
| 2108 |
| 2012 template <> void InstARM32Vsqrt::emitIAS(const Cfg *Func) const { | 2109 template <> void InstARM32Vsqrt::emitIAS(const Cfg *Func) const { |
| 2013 assert(getSrcSize() == 1); | 2110 assert(getSrcSize() == 1); |
| 2014 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 2111 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 2015 const Operand *Dest = getDest(); | 2112 const Operand *Dest = getDest(); |
| 2016 switch (Dest->getType()) { | 2113 switch (Dest->getType()) { |
| 2017 case IceType_f32: | 2114 case IceType_f32: |
| 2018 Asm->vsqrts(Dest, getSrc(0), getPredicate()); | 2115 Asm->vsqrts(Dest, getSrc(0), getPredicate()); |
| 2019 break; | 2116 break; |
| 2020 case IceType_f64: | 2117 case IceType_f64: |
| 2021 Asm->vsqrtd(Dest, getSrc(0), getPredicate()); | 2118 Asm->vsqrtd(Dest, getSrc(0), getPredicate()); |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2413 << "vcvt" << getPredicate() << vcvtVariantSuffix(Variant) << " "; | 2510 << "vcvt" << getPredicate() << vcvtVariantSuffix(Variant) << " "; |
| 2414 dumpSources(Func); | 2511 dumpSources(Func); |
| 2415 } | 2512 } |
| 2416 | 2513 |
| 2417 void InstARM32Vcmp::emit(const Cfg *Func) const { | 2514 void InstARM32Vcmp::emit(const Cfg *Func) const { |
| 2418 if (!BuildDefs::dump()) | 2515 if (!BuildDefs::dump()) |
| 2419 return; | 2516 return; |
| 2420 Ostream &Str = Func->getContext()->getStrEmit(); | 2517 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2421 assert(getSrcSize() == 2); | 2518 assert(getSrcSize() == 2); |
| 2422 Str << "\t" | 2519 Str << "\t" |
| 2423 "vcmp" << getPredicate() << getVecWidthString(getSrc(0)->getType()) | 2520 "vcmp" << getPredicate() << getFpWidthString(getSrc(0)->getType()) |
| 2424 << "\t"; | 2521 << "\t"; |
| 2425 getSrc(0)->emit(Func); | 2522 getSrc(0)->emit(Func); |
| 2426 Str << ", "; | 2523 Str << ", "; |
| 2427 getSrc(1)->emit(Func); | 2524 getSrc(1)->emit(Func); |
| 2428 } | 2525 } |
| 2429 | 2526 |
| 2430 void InstARM32Vcmp::emitIAS(const Cfg *Func) const { | 2527 void InstARM32Vcmp::emitIAS(const Cfg *Func) const { |
| 2431 assert(getSrcSize() == 2); | 2528 assert(getSrcSize() == 2); |
| 2432 const Operand *Src0 = getSrc(0); | 2529 const Operand *Src0 = getSrc(0); |
| 2433 const Type Ty = Src0->getType(); | 2530 const Type Ty = Src0->getType(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2457 llvm::report_fatal_error("Vcvt on non floating value"); | 2554 llvm::report_fatal_error("Vcvt on non floating value"); |
| 2458 } | 2555 } |
| 2459 } | 2556 } |
| 2460 assert(!Asm->needsTextFixup()); | 2557 assert(!Asm->needsTextFixup()); |
| 2461 } | 2558 } |
| 2462 | 2559 |
| 2463 void InstARM32Vcmp::dump(const Cfg *Func) const { | 2560 void InstARM32Vcmp::dump(const Cfg *Func) const { |
| 2464 if (!BuildDefs::dump()) | 2561 if (!BuildDefs::dump()) |
| 2465 return; | 2562 return; |
| 2466 Ostream &Str = Func->getContext()->getStrDump(); | 2563 Ostream &Str = Func->getContext()->getStrDump(); |
| 2467 Str << "vcmp" << getPredicate() << getVecWidthString(getSrc(0)->getType()); | 2564 Str << "vcmp" << getPredicate() << getFpWidthString(getSrc(0)->getType()); |
| 2468 dumpSources(Func); | 2565 dumpSources(Func); |
| 2469 } | 2566 } |
| 2470 | 2567 |
| 2471 void InstARM32Vmrs::emit(const Cfg *Func) const { | 2568 void InstARM32Vmrs::emit(const Cfg *Func) const { |
| 2472 if (!BuildDefs::dump()) | 2569 if (!BuildDefs::dump()) |
| 2473 return; | 2570 return; |
| 2474 Ostream &Str = Func->getContext()->getStrEmit(); | 2571 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2475 assert(getSrcSize() == 0); | 2572 assert(getSrcSize() == 0); |
| 2476 Str << "\t" | 2573 Str << "\t" |
| 2477 "vmrs" << getPredicate() << "\t" | 2574 "vmrs" << getPredicate() << "\t" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2493 Str << "APSR{n,z,v,c} = vmrs" << getPredicate() << "\t" | 2590 Str << "APSR{n,z,v,c} = vmrs" << getPredicate() << "\t" |
| 2494 "FPSCR{n,z,c,v}"; | 2591 "FPSCR{n,z,c,v}"; |
| 2495 } | 2592 } |
| 2496 | 2593 |
| 2497 void InstARM32Vabs::emit(const Cfg *Func) const { | 2594 void InstARM32Vabs::emit(const Cfg *Func) const { |
| 2498 if (!BuildDefs::dump()) | 2595 if (!BuildDefs::dump()) |
| 2499 return; | 2596 return; |
| 2500 Ostream &Str = Func->getContext()->getStrEmit(); | 2597 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2501 assert(getSrcSize() == 1); | 2598 assert(getSrcSize() == 1); |
| 2502 Str << "\t" | 2599 Str << "\t" |
| 2503 "vabs" << getPredicate() << getVecWidthString(getSrc(0)->getType()) | 2600 "vabs" << getPredicate() << getFpWidthString(getSrc(0)->getType()) |
| 2504 << "\t"; | 2601 << "\t"; |
| 2505 getDest()->emit(Func); | 2602 getDest()->emit(Func); |
| 2506 Str << ", "; | 2603 Str << ", "; |
| 2507 getSrc(0)->emit(Func); | 2604 getSrc(0)->emit(Func); |
| 2508 } | 2605 } |
| 2509 | 2606 |
| 2510 void InstARM32Vabs::emitIAS(const Cfg *Func) const { | 2607 void InstARM32Vabs::emitIAS(const Cfg *Func) const { |
| 2511 assert(getSrcSize() == 1); | 2608 assert(getSrcSize() == 1); |
| 2512 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 2609 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 2513 const Variable *Dest = getDest(); | 2610 const Variable *Dest = getDest(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2527 Asm->vabsq(Dest, getSrc(0)); | 2624 Asm->vabsq(Dest, getSrc(0)); |
| 2528 } | 2625 } |
| 2529 assert(!Asm->needsTextFixup()); | 2626 assert(!Asm->needsTextFixup()); |
| 2530 } | 2627 } |
| 2531 | 2628 |
| 2532 void InstARM32Vabs::dump(const Cfg *Func) const { | 2629 void InstARM32Vabs::dump(const Cfg *Func) const { |
| 2533 if (!BuildDefs::dump()) | 2630 if (!BuildDefs::dump()) |
| 2534 return; | 2631 return; |
| 2535 Ostream &Str = Func->getContext()->getStrDump(); | 2632 Ostream &Str = Func->getContext()->getStrDump(); |
| 2536 dumpDest(Func); | 2633 dumpDest(Func); |
| 2537 Str << " = vabs" << getPredicate() << getVecWidthString(getSrc(0)->getType()); | 2634 Str << " = vabs" << getPredicate() << getFpWidthString(getSrc(0)->getType()); |
| 2538 } | 2635 } |
| 2539 | 2636 |
| 2540 void InstARM32Dmb::emit(const Cfg *Func) const { | 2637 void InstARM32Dmb::emit(const Cfg *Func) const { |
| 2541 if (!BuildDefs::dump()) | 2638 if (!BuildDefs::dump()) |
| 2542 return; | 2639 return; |
| 2543 Ostream &Str = Func->getContext()->getStrEmit(); | 2640 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2544 assert(getSrcSize() == 0); | 2641 assert(getSrcSize() == 0); |
| 2545 Str << "\t" | 2642 Str << "\t" |
| 2546 "dmb" | 2643 "dmb" |
| 2547 "\t" | 2644 "\t" |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2727 case IceType_f32: | 2824 case IceType_f32: |
| 2728 Str << "#" << materializeFloatImmediate(ModifiedImm) | 2825 Str << "#" << materializeFloatImmediate(ModifiedImm) |
| 2729 << " @ Modified: " << ModifiedImm; | 2826 << " @ Modified: " << ModifiedImm; |
| 2730 break; | 2827 break; |
| 2731 } | 2828 } |
| 2732 } | 2829 } |
| 2733 | 2830 |
| 2734 void OperandARM32FlexFpImm::dump(const Cfg * /*Func*/, Ostream &Str) const { | 2831 void OperandARM32FlexFpImm::dump(const Cfg * /*Func*/, Ostream &Str) const { |
| 2735 if (!BuildDefs::dump()) | 2832 if (!BuildDefs::dump()) |
| 2736 return; | 2833 return; |
| 2737 Str << "#" << materializeFloatImmediate(ModifiedImm) | 2834 Str << "#" << materializeFloatImmediate(ModifiedImm) << getFpWidthString(Ty); |
| 2738 << InstARM32::getVecWidthString(Ty); | |
| 2739 } | 2835 } |
| 2740 | 2836 |
| 2741 void OperandARM32FlexFpZero::emit(const Cfg *Func) const { | 2837 void OperandARM32FlexFpZero::emit(const Cfg *Func) const { |
| 2742 if (!BuildDefs::dump()) | 2838 if (!BuildDefs::dump()) |
| 2743 return; | 2839 return; |
| 2744 Ostream &Str = Func->getContext()->getStrEmit(); | 2840 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2745 switch (Ty) { | 2841 switch (Ty) { |
| 2746 default: | 2842 default: |
| 2747 llvm::report_fatal_error("Invalid flex fp imm type."); | 2843 llvm::report_fatal_error("Invalid flex fp imm type."); |
| 2748 case IceType_f64: | 2844 case IceType_f64: |
| 2749 case IceType_f32: | 2845 case IceType_f32: |
| 2750 Str << "#0.0"; | 2846 Str << "#0.0"; |
| 2751 } | 2847 } |
| 2752 } | 2848 } |
| 2753 | 2849 |
| 2754 void OperandARM32FlexFpZero::dump(const Cfg * /*Func*/, Ostream &Str) const { | 2850 void OperandARM32FlexFpZero::dump(const Cfg * /*Func*/, Ostream &Str) const { |
| 2755 if (!BuildDefs::dump()) | 2851 if (!BuildDefs::dump()) |
| 2756 return; | 2852 return; |
| 2757 Str << "#0.0" << InstARM32::getVecWidthString(Ty); | 2853 Str << "#0.0" << getFpWidthString(Ty); |
| 2758 } | 2854 } |
| 2759 | 2855 |
| 2760 void OperandARM32FlexReg::emit(const Cfg *Func) const { | 2856 void OperandARM32FlexReg::emit(const Cfg *Func) const { |
| 2761 if (!BuildDefs::dump()) | 2857 if (!BuildDefs::dump()) |
| 2762 return; | 2858 return; |
| 2763 Ostream &Str = Func->getContext()->getStrEmit(); | 2859 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2764 getReg()->emit(Func); | 2860 getReg()->emit(Func); |
| 2765 if (getShiftOp() != kNoShift) { | 2861 if (getShiftOp() != kNoShift) { |
| 2766 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " "; | 2862 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " "; |
| 2767 getShiftAmt()->emit(Func); | 2863 getShiftAmt()->emit(Func); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2802 template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>; | 2898 template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>; |
| 2803 template class InstARM32ThreeAddrGPR<InstARM32::Sub>; | 2899 template class InstARM32ThreeAddrGPR<InstARM32::Sub>; |
| 2804 template class InstARM32ThreeAddrGPR<InstARM32::Udiv>; | 2900 template class InstARM32ThreeAddrGPR<InstARM32::Udiv>; |
| 2805 | 2901 |
| 2806 template class InstARM32ThreeAddrFP<InstARM32::Vadd>; | 2902 template class InstARM32ThreeAddrFP<InstARM32::Vadd>; |
| 2807 template class InstARM32ThreeAddrFP<InstARM32::Vdiv>; | 2903 template class InstARM32ThreeAddrFP<InstARM32::Vdiv>; |
| 2808 template class InstARM32ThreeAddrFP<InstARM32::Veor>; | 2904 template class InstARM32ThreeAddrFP<InstARM32::Veor>; |
| 2809 template class InstARM32FourAddrFP<InstARM32::Vmla>; | 2905 template class InstARM32FourAddrFP<InstARM32::Vmla>; |
| 2810 template class InstARM32FourAddrFP<InstARM32::Vmls>; | 2906 template class InstARM32FourAddrFP<InstARM32::Vmls>; |
| 2811 template class InstARM32ThreeAddrFP<InstARM32::Vmul>; | 2907 template class InstARM32ThreeAddrFP<InstARM32::Vmul>; |
| 2908 template class InstARM32UnaryopSignAwareFP<InstARM32::Vneg>; |
| 2909 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vshl>; |
| 2812 template class InstARM32ThreeAddrFP<InstARM32::Vsub>; | 2910 template class InstARM32ThreeAddrFP<InstARM32::Vsub>; |
| 2813 | 2911 |
| 2814 template class InstARM32LoadBase<InstARM32::Ldr>; | 2912 template class InstARM32LoadBase<InstARM32::Ldr>; |
| 2815 template class InstARM32LoadBase<InstARM32::Ldrex>; | 2913 template class InstARM32LoadBase<InstARM32::Ldrex>; |
| 2816 | 2914 |
| 2817 template class InstARM32TwoAddrGPR<InstARM32::Movt>; | 2915 template class InstARM32TwoAddrGPR<InstARM32::Movt>; |
| 2818 | 2916 |
| 2819 template class InstARM32UnaryopGPR<InstARM32::Movw, false>; | 2917 template class InstARM32UnaryopGPR<InstARM32::Movw, false>; |
| 2820 template class InstARM32UnaryopGPR<InstARM32::Clz, false>; | 2918 template class InstARM32UnaryopGPR<InstARM32::Clz, false>; |
| 2821 template class InstARM32UnaryopGPR<InstARM32::Mvn, false>; | 2919 template class InstARM32UnaryopGPR<InstARM32::Mvn, false>; |
| 2822 template class InstARM32UnaryopGPR<InstARM32::Rbit, false>; | 2920 template class InstARM32UnaryopGPR<InstARM32::Rbit, false>; |
| 2823 template class InstARM32UnaryopGPR<InstARM32::Rev, false>; | 2921 template class InstARM32UnaryopGPR<InstARM32::Rev, false>; |
| 2824 template class InstARM32UnaryopGPR<InstARM32::Sxt, true>; | 2922 template class InstARM32UnaryopGPR<InstARM32::Sxt, true>; |
| 2825 template class InstARM32UnaryopGPR<InstARM32::Uxt, true>; | 2923 template class InstARM32UnaryopGPR<InstARM32::Uxt, true>; |
| 2826 template class InstARM32UnaryopFP<InstARM32::Vsqrt>; | 2924 template class InstARM32UnaryopFP<InstARM32::Vsqrt>; |
| 2827 | 2925 |
| 2828 template class InstARM32FourAddrGPR<InstARM32::Mla>; | 2926 template class InstARM32FourAddrGPR<InstARM32::Mla>; |
| 2829 template class InstARM32FourAddrGPR<InstARM32::Mls>; | 2927 template class InstARM32FourAddrGPR<InstARM32::Mls>; |
| 2830 | 2928 |
| 2831 template class InstARM32CmpLike<InstARM32::Cmn>; | 2929 template class InstARM32CmpLike<InstARM32::Cmn>; |
| 2832 template class InstARM32CmpLike<InstARM32::Cmp>; | 2930 template class InstARM32CmpLike<InstARM32::Cmp>; |
| 2833 template class InstARM32CmpLike<InstARM32::Tst>; | 2931 template class InstARM32CmpLike<InstARM32::Tst>; |
| 2834 | 2932 |
| 2835 } // end of namespace ARM32 | 2933 } // end of namespace ARM32 |
| 2836 } // end of namespace Ice | 2934 } // end of namespace Ice |
| OLD | NEW |