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 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 |
| 73 } // end of anonymous namespace | 76 const char *getWidthString(Type Ty) { |
| 74 | |
| 75 const char *InstARM32::getWidthString(Type Ty) { | |
| 76 return TypeARM32Attributes[Ty].WidthString; | 77 return TypeARM32Attributes[Ty].WidthString; |
| 77 } | 78 } |
| 78 | 79 |
| 79 const char *InstARM32::getVecWidthString(Type Ty) { | 80 const char *getFpWidthString(Type Ty) { |
| 80 return TypeARM32Attributes[Ty].VecWidthString; | 81 return TypeARM32Attributes[Ty].FpWidthString; |
| 81 } | 82 } |
| 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 } // end of anonymous namespace | |
| 92 | |
| 83 const char *InstARM32Pred::predString(CondARM32::Cond Pred) { | 93 const char *InstARM32Pred::predString(CondARM32::Cond Pred) { |
| 84 return InstARM32CondAttributes[Pred].EmitString; | 94 return InstARM32CondAttributes[Pred].EmitString; |
| 85 } | 95 } |
| 86 | 96 |
| 87 void InstARM32Pred::dumpOpcodePred(Ostream &Str, const char *Opcode, | 97 void InstARM32Pred::dumpOpcodePred(Ostream &Str, const char *Opcode, |
| 88 Type Ty) const { | 98 Type Ty) const { |
| 89 Str << Opcode << getPredicate() << "." << Ty; | 99 Str << Opcode << getPredicate() << "." << Ty; |
| 90 } | 100 } |
| 91 | 101 |
| 92 CondARM32::Cond InstARM32::getOppositeCondition(CondARM32::Cond Cond) { | 102 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(); | 153 Type SrcTy = Instr->getSrc(0)->getType(); |
| 144 Str << "\t" << Opcode; | 154 Str << "\t" << Opcode; |
| 145 if (NeedsWidthSuffix) | 155 if (NeedsWidthSuffix) |
| 146 Str << getWidthString(SrcTy); | 156 Str << getWidthString(SrcTy); |
| 147 Str << Instr->getPredicate() << "\t"; | 157 Str << Instr->getPredicate() << "\t"; |
| 148 Instr->getDest()->emit(Func); | 158 Instr->getDest()->emit(Func); |
| 149 Str << ", "; | 159 Str << ", "; |
| 150 Instr->getSrc(0)->emit(Func); | 160 Instr->getSrc(0)->emit(Func); |
| 151 } | 161 } |
| 152 | 162 |
| 153 void InstARM32Pred::emitUnaryopFP(const char *Opcode, | 163 void InstARM32Pred::emitUnaryopFP(const char *Opcode, FPSign Sign, |
| 154 const InstARM32Pred *Instr, const Cfg *Func) { | 164 const InstARM32Pred *Instr, const Cfg *Func) { |
| 155 Ostream &Str = Func->getContext()->getStrEmit(); | 165 Ostream &Str = Func->getContext()->getStrEmit(); |
| 156 assert(Instr->getSrcSize() == 1); | 166 assert(Instr->getSrcSize() == 1); |
| 157 Type SrcTy = Instr->getSrc(0)->getType(); | 167 Type SrcTy = Instr->getSrc(0)->getType(); |
| 158 Str << "\t" << Opcode << Instr->getPredicate() << getVecWidthString(SrcTy) | 168 Str << "\t" << Opcode << Instr->getPredicate(); |
| 159 << "\t"; | 169 switch (Sign) { |
| 170 case FS_None: | |
| 171 Str << getFpWidthString(SrcTy); | |
| 172 break; | |
| 173 case FS_Signed: | |
| 174 Str << getSVecWidthString(SrcTy); | |
| 175 break; | |
| 176 case FS_Unsigned: | |
| 177 Str << getUVecWidthString(SrcTy); | |
| 178 break; | |
| 179 } | |
| 180 Str << "\t"; | |
| 160 Instr->getDest()->emit(Func); | 181 Instr->getDest()->emit(Func); |
| 161 Str << ", "; | 182 Str << ", "; |
| 162 Instr->getSrc(0)->emit(Func); | 183 Instr->getSrc(0)->emit(Func); |
| 163 } | 184 } |
| 164 | 185 |
| 165 void InstARM32Pred::emitTwoAddr(const char *Opcode, const InstARM32Pred *Instr, | 186 void InstARM32Pred::emitTwoAddr(const char *Opcode, const InstARM32Pred *Instr, |
| 166 const Cfg *Func) { | 187 const Cfg *Func) { |
| 167 if (!BuildDefs::dump()) | 188 if (!BuildDefs::dump()) |
| 168 return; | 189 return; |
| 169 Ostream &Str = Func->getContext()->getStrEmit(); | 190 Ostream &Str = Func->getContext()->getStrEmit(); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 185 assert(Instr->getSrcSize() == 2); | 206 assert(Instr->getSrcSize() == 2); |
| 186 Str << "\t" << Opcode << (SetFlags ? "s" : "") << Instr->getPredicate() | 207 Str << "\t" << Opcode << (SetFlags ? "s" : "") << Instr->getPredicate() |
| 187 << "\t"; | 208 << "\t"; |
| 188 Instr->getDest()->emit(Func); | 209 Instr->getDest()->emit(Func); |
| 189 Str << ", "; | 210 Str << ", "; |
| 190 Instr->getSrc(0)->emit(Func); | 211 Instr->getSrc(0)->emit(Func); |
| 191 Str << ", "; | 212 Str << ", "; |
| 192 Instr->getSrc(1)->emit(Func); | 213 Instr->getSrc(1)->emit(Func); |
| 193 } | 214 } |
| 194 | 215 |
| 195 void InstARM32::emitThreeAddrFP(const char *Opcode, const InstARM32 *Instr, | 216 void InstARM32::emitThreeAddrFP(const char *Opcode, FPSign SignType, |
| 196 const Cfg *Func) { | 217 const InstARM32 *Instr, const Cfg *Func) { |
| 197 if (!BuildDefs::dump()) | 218 if (!BuildDefs::dump()) |
| 198 return; | 219 return; |
| 199 Ostream &Str = Func->getContext()->getStrEmit(); | 220 Ostream &Str = Func->getContext()->getStrEmit(); |
| 200 assert(Instr->getSrcSize() == 2); | 221 assert(Instr->getSrcSize() == 2); |
| 201 Str << "\t" << Opcode << getVecWidthString(Instr->getDest()->getType()) | 222 Str << "\t" << Opcode; |
| 202 << "\t"; | 223 switch (SignType) { |
|
Karl
2016/04/13 16:17:36
This switch appears in multiple places. Consider f
John
2016/04/15 13:20:56
Done.
| |
| 224 case FS_None: | |
| 225 Str << getFpWidthString(Instr->getDest()->getType()); | |
| 226 break; | |
| 227 case FS_Signed: | |
| 228 Str << getSVecWidthString(Instr->getDest()->getType()); | |
| 229 break; | |
| 230 case FS_Unsigned: | |
| 231 Str << getUVecWidthString(Instr->getDest()->getType()); | |
| 232 break; | |
| 233 } | |
| 234 Str << "\t"; | |
| 203 Instr->getDest()->emit(Func); | 235 Instr->getDest()->emit(Func); |
| 204 Str << ", "; | 236 Str << ", "; |
| 205 Instr->getSrc(0)->emit(Func); | 237 Instr->getSrc(0)->emit(Func); |
| 206 Str << ", "; | 238 Str << ", "; |
| 207 Instr->getSrc(1)->emit(Func); | 239 Instr->getSrc(1)->emit(Func); |
| 208 } | 240 } |
| 209 | 241 |
| 210 void InstARM32::emitFourAddrFP(const char *Opcode, const InstARM32 *Instr, | 242 void InstARM32::emitFourAddrFP(const char *Opcode, FPSign SignType, |
| 211 const Cfg *Func) { | 243 const InstARM32 *Instr, const Cfg *Func) { |
| 212 if (!BuildDefs::dump()) | 244 if (!BuildDefs::dump()) |
| 213 return; | 245 return; |
| 214 Ostream &Str = Func->getContext()->getStrEmit(); | 246 Ostream &Str = Func->getContext()->getStrEmit(); |
| 215 assert(Instr->getSrcSize() == 3); | 247 assert(Instr->getSrcSize() == 3); |
| 216 assert(Instr->getSrc(0) == Instr->getDest()); | 248 assert(Instr->getSrc(0) == Instr->getDest()); |
| 217 Str << "\t" << Opcode << getVecWidthString(Instr->getDest()->getType()) | 249 Str << "\t" << Opcode; |
| 218 << "\t"; | 250 switch (SignType) { |
| 251 case FS_None: | |
| 252 Str << getFpWidthString(Instr->getDest()->getType()); | |
| 253 break; | |
| 254 case FS_Signed: | |
| 255 Str << getSVecWidthString(Instr->getDest()->getType()); | |
| 256 break; | |
| 257 case FS_Unsigned: | |
| 258 Str << getUVecWidthString(Instr->getDest()->getType()); | |
| 259 break; | |
| 260 } | |
| 261 Str << "\t"; | |
| 219 Instr->getDest()->emit(Func); | 262 Instr->getDest()->emit(Func); |
| 220 Str << ", "; | 263 Str << ", "; |
| 221 Instr->getSrc(1)->emit(Func); | 264 Instr->getSrc(1)->emit(Func); |
| 222 Str << ", "; | 265 Str << ", "; |
| 223 Instr->getSrc(2)->emit(Func); | 266 Instr->getSrc(2)->emit(Func); |
| 224 } | 267 } |
| 225 | 268 |
| 226 void InstARM32Pred::emitFourAddr(const char *Opcode, const InstARM32Pred *Instr, | 269 void InstARM32Pred::emitFourAddr(const char *Opcode, const InstARM32Pred *Instr, |
| 227 const Cfg *Func) { | 270 const Cfg *Func) { |
| 228 if (!BuildDefs::dump()) | 271 if (!BuildDefs::dump()) |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 247 template <InstARM32::InstKindARM32 K> | 290 template <InstARM32::InstKindARM32 K> |
| 248 void InstARM32FourAddrFP<K>::emitIAS(const Cfg *Func) const { | 291 void InstARM32FourAddrFP<K>::emitIAS(const Cfg *Func) const { |
| 249 emitUsingTextFixup(Func); | 292 emitUsingTextFixup(Func); |
| 250 } | 293 } |
| 251 | 294 |
| 252 template <InstARM32::InstKindARM32 K> | 295 template <InstARM32::InstKindARM32 K> |
| 253 void InstARM32ThreeAddrFP<K>::emitIAS(const Cfg *Func) const { | 296 void InstARM32ThreeAddrFP<K>::emitIAS(const Cfg *Func) const { |
| 254 emitUsingTextFixup(Func); | 297 emitUsingTextFixup(Func); |
| 255 } | 298 } |
| 256 | 299 |
| 300 template <InstARM32::InstKindARM32 K> | |
| 301 void InstARM32ThreeAddrSignAwareFP<K>::emitIAS(const Cfg *Func) const { | |
| 302 InstARM32::emitUsingTextFixup(Func); | |
| 303 } | |
| 304 | |
| 257 template <> void InstARM32Mla::emitIAS(const Cfg *Func) const { | 305 template <> void InstARM32Mla::emitIAS(const Cfg *Func) const { |
| 258 assert(getSrcSize() == 3); | 306 assert(getSrcSize() == 3); |
| 259 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 307 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 260 Asm->mla(getDest(), getSrc(0), getSrc(1), getSrc(2), getPredicate()); | 308 Asm->mla(getDest(), getSrc(0), getSrc(1), getSrc(2), getPredicate()); |
| 261 if (Asm->needsTextFixup()) | 309 if (Asm->needsTextFixup()) |
| 262 emitUsingTextFixup(Func); | 310 emitUsingTextFixup(Func); |
| 263 } | 311 } |
| 264 | 312 |
| 265 template <> void InstARM32Mls::emitIAS(const Cfg *Func) const { | 313 template <> void InstARM32Mls::emitIAS(const Cfg *Func) const { |
| 266 assert(getSrcSize() == 3); | 314 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); | 778 Asm->vmlss(getDest(), getSrc(1), getSrc(2), CondARM32::AL); |
| 731 assert(!Asm->needsTextFixup()); | 779 assert(!Asm->needsTextFixup()); |
| 732 return; | 780 return; |
| 733 case IceType_f64: | 781 case IceType_f64: |
| 734 Asm->vmlsd(getDest(), getSrc(1), getSrc(2), CondARM32::AL); | 782 Asm->vmlsd(getDest(), getSrc(1), getSrc(2), CondARM32::AL); |
| 735 assert(!Asm->needsTextFixup()); | 783 assert(!Asm->needsTextFixup()); |
| 736 return; | 784 return; |
| 737 } | 785 } |
| 738 } | 786 } |
| 739 | 787 |
| 788 template <> void InstARM32Vneg::emitIAS(const Cfg *Func) const { | |
| 789 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | |
| 790 const Variable *Dest = getDest(); | |
| 791 const Type DestTy = Dest->getType(); | |
| 792 switch (Dest->getType()) { | |
| 793 default: | |
| 794 llvm::report_fatal_error("Vneg not defined on type " + | |
| 795 typeStdString(Dest->getType())); | |
| 796 case IceType_v4i1: | |
| 797 case IceType_v8i1: | |
| 798 case IceType_v16i1: | |
| 799 case IceType_v16i8: | |
| 800 case IceType_v8i16: | |
| 801 case IceType_v4i32: | |
| 802 case IceType_v4f32: { | |
| 803 const Type ElmtTy = typeElementType(DestTy); | |
| 804 Asm->vnegqs(ElmtTy, Dest, getSrc(0)); | |
|
Karl
2016/04/13 16:17:36
Is it necessary to factor out ElmtTy here and pass
John
2016/04/15 13:20:56
No, it is not, but there is precedent in this file
| |
| 805 } break; | |
| 806 } | |
| 807 } | |
| 808 | |
| 740 template <> void InstARM32Vorr::emitIAS(const Cfg *Func) const { | 809 template <> void InstARM32Vorr::emitIAS(const Cfg *Func) const { |
| 741 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 810 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 742 const Variable *Dest = getDest(); | 811 const Variable *Dest = getDest(); |
| 743 switch (Dest->getType()) { | 812 switch (Dest->getType()) { |
| 744 default: | 813 default: |
| 745 llvm::report_fatal_error("Vorr not defined on type " + | 814 llvm::report_fatal_error("Vorr not defined on type " + |
| 746 typeStdString(Dest->getType())); | 815 typeStdString(Dest->getType())); |
| 747 case IceType_v4i1: | 816 case IceType_v4i1: |
| 748 case IceType_v8i1: | 817 case IceType_v8i1: |
| 749 case IceType_v16i1: | 818 case IceType_v16i1: |
| 750 case IceType_v16i8: | 819 case IceType_v16i8: |
| 751 case IceType_v8i16: | 820 case IceType_v8i16: |
| 752 case IceType_v4i32: | 821 case IceType_v4i32: |
| 753 Asm->vorrq(Dest, getSrc(0), getSrc(1)); | 822 Asm->vorrq(Dest, getSrc(0), getSrc(1)); |
| 754 } | 823 } |
| 755 assert(!Asm->needsTextFixup()); | 824 assert(!Asm->needsTextFixup()); |
| 756 } | 825 } |
| 757 | 826 |
| 827 template <> void InstARM32Vshl::emitIAS(const Cfg *Func) const { | |
| 828 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | |
| 829 const Variable *Dest = getDest(); | |
| 830 const Type DestTy = Dest->getType(); | |
| 831 switch (DestTy) { | |
| 832 default: | |
| 833 llvm::report_fatal_error("Vshl not defined on type " + | |
| 834 typeStdString(Dest->getType())); | |
| 835 case IceType_v4i1: | |
| 836 case IceType_v8i1: | |
| 837 case IceType_v16i1: | |
| 838 case IceType_v16i8: | |
| 839 case IceType_v8i16: | |
| 840 case IceType_v4i32: { | |
| 841 const Type ElmtTy = typeElementType(DestTy); | |
| 842 assert(Sign != InstARM32::FS_None); | |
| 843 switch (Sign) { | |
| 844 case InstARM32::FS_None: // defaults to unsigned. | |
| 845 case InstARM32::FS_Unsigned: | |
| 846 Asm->vshlqu(ElmtTy, Dest, getSrc(0), getSrc(1)); | |
|
Karl
2016/04/13 16:17:36
Similar question here. Should we be forcing the pa
John
2016/04/15 13:20:56
Acknowledged.
| |
| 847 break; | |
| 848 case InstARM32::FS_Signed: | |
| 849 Asm->vshlqi(ElmtTy, Dest, getSrc(0), getSrc(1)); | |
| 850 break; | |
| 851 } | |
| 852 } break; | |
| 853 } | |
| 854 } | |
| 855 | |
| 758 template <> void InstARM32Vsub::emitIAS(const Cfg *Func) const { | 856 template <> void InstARM32Vsub::emitIAS(const Cfg *Func) const { |
| 759 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 857 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 760 const Variable *Dest = getDest(); | 858 const Variable *Dest = getDest(); |
| 761 Type DestTy = Dest->getType(); | 859 Type DestTy = Dest->getType(); |
| 762 switch (DestTy) { | 860 switch (DestTy) { |
| 763 default: | 861 default: |
| 764 llvm::report_fatal_error("Vsub not defined on type " + | 862 llvm::report_fatal_error("Vsub not defined on type " + |
| 765 typeStdString(DestTy)); | 863 typeStdString(DestTy)); |
| 766 case IceType_v16i8: | 864 case IceType_v16i8: |
| 767 case IceType_v8i16: | 865 case IceType_v8i16: |
| (...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1367 template <> const char *InstARM32Udiv::Opcode = "udiv"; | 1465 template <> const char *InstARM32Udiv::Opcode = "udiv"; |
| 1368 // FP | 1466 // FP |
| 1369 template <> const char *InstARM32Vadd::Opcode = "vadd"; | 1467 template <> const char *InstARM32Vadd::Opcode = "vadd"; |
| 1370 template <> const char *InstARM32Vand::Opcode = "vand"; | 1468 template <> const char *InstARM32Vand::Opcode = "vand"; |
| 1371 template <> const char *InstARM32Vdiv::Opcode = "vdiv"; | 1469 template <> const char *InstARM32Vdiv::Opcode = "vdiv"; |
| 1372 template <> const char *InstARM32Veor::Opcode = "veor"; | 1470 template <> const char *InstARM32Veor::Opcode = "veor"; |
| 1373 template <> const char *InstARM32Vmla::Opcode = "vmla"; | 1471 template <> const char *InstARM32Vmla::Opcode = "vmla"; |
| 1374 template <> const char *InstARM32Vmls::Opcode = "vmls"; | 1472 template <> const char *InstARM32Vmls::Opcode = "vmls"; |
| 1375 template <> const char *InstARM32Vmul::Opcode = "vmul"; | 1473 template <> const char *InstARM32Vmul::Opcode = "vmul"; |
| 1376 template <> const char *InstARM32Vorr::Opcode = "vorr"; | 1474 template <> const char *InstARM32Vorr::Opcode = "vorr"; |
| 1475 template <> const char *InstARM32UnaryopFP<InstARM32::Vneg>::Opcode = "vneg"; | |
| 1476 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vshl>::Opcode = "vshl"; | |
| 1377 template <> const char *InstARM32Vsub::Opcode = "vsub"; | 1477 template <> const char *InstARM32Vsub::Opcode = "vsub"; |
| 1378 // Four-addr ops | 1478 // Four-addr ops |
| 1379 template <> const char *InstARM32Mla::Opcode = "mla"; | 1479 template <> const char *InstARM32Mla::Opcode = "mla"; |
| 1380 template <> const char *InstARM32Mls::Opcode = "mls"; | 1480 template <> const char *InstARM32Mls::Opcode = "mls"; |
| 1381 // Cmp-like ops | 1481 // Cmp-like ops |
| 1382 template <> const char *InstARM32Cmn::Opcode = "cmn"; | 1482 template <> const char *InstARM32Cmn::Opcode = "cmn"; |
| 1383 template <> const char *InstARM32Cmp::Opcode = "cmp"; | 1483 template <> const char *InstARM32Cmp::Opcode = "cmp"; |
| 1384 template <> const char *InstARM32Tst::Opcode = "tst"; | 1484 template <> const char *InstARM32Tst::Opcode = "tst"; |
| 1385 | 1485 |
| 1386 void InstARM32::dump(const Cfg *Func) const { | 1486 void InstARM32::dump(const Cfg *Func) const { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1472 | 1572 |
| 1473 Type Ty = Dest->getType(); | 1573 Type Ty = Dest->getType(); |
| 1474 const bool IsVector = isVectorType(Ty); | 1574 const bool IsVector = isVectorType(Ty); |
| 1475 const bool IsScalarFP = isScalarFloatingType(Ty); | 1575 const bool IsScalarFP = isScalarFloatingType(Ty); |
| 1476 const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0); | 1576 const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0); |
| 1477 const bool IsVMove = (IsVector || IsScalarFP || CoreVFPMove); | 1577 const bool IsVMove = (IsVector || IsScalarFP || CoreVFPMove); |
| 1478 const char *Opcode = IsVMove ? "vmov" : "mov"; | 1578 const char *Opcode = IsVMove ? "vmov" : "mov"; |
| 1479 // when vmov{c}'ing, we need to emit a width string. Otherwise, the | 1579 // 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 | 1580 // assembler might be tempted to assume we want a vector vmov{c}, and that |
| 1481 // is disallowed because ARM. | 1581 // is disallowed because ARM. |
| 1482 const char *WidthString = !CoreVFPMove ? getVecWidthString(Ty) : ""; | 1582 const char *WidthString = !CoreVFPMove ? getFpWidthString(Ty) : ""; |
| 1483 CondARM32::Cond Cond = getPredicate(); | 1583 CondARM32::Cond Cond = getPredicate(); |
| 1484 if (IsVector) | 1584 if (IsVector) |
| 1485 assert(CondARM32::isUnconditional(Cond) && | 1585 assert(CondARM32::isUnconditional(Cond) && |
| 1486 "Moves on vectors must be unconditional!"); | 1586 "Moves on vectors must be unconditional!"); |
| 1487 Str << "\t" << Opcode; | 1587 Str << "\t" << Opcode; |
| 1488 if (IsVMove) { | 1588 if (IsVMove) { |
| 1489 Str << Cond << WidthString; | 1589 Str << Cond << WidthString; |
| 1490 } else { | 1590 } else { |
| 1491 Str << WidthString << Cond; | 1591 Str << WidthString << Cond; |
| 1492 } | 1592 } |
| (...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2002 Asm->uxt(getDest(), getSrc(0), getPredicate()); | 2102 Asm->uxt(getDest(), getSrc(0), getPredicate()); |
| 2003 if (Asm->needsTextFixup()) | 2103 if (Asm->needsTextFixup()) |
| 2004 emitUsingTextFixup(Func); | 2104 emitUsingTextFixup(Func); |
| 2005 } | 2105 } |
| 2006 | 2106 |
| 2007 template <InstARM32::InstKindARM32 K> | 2107 template <InstARM32::InstKindARM32 K> |
| 2008 void InstARM32UnaryopFP<K>::emitIAS(const Cfg *Func) const { | 2108 void InstARM32UnaryopFP<K>::emitIAS(const Cfg *Func) const { |
| 2009 emitUsingTextFixup(Func); | 2109 emitUsingTextFixup(Func); |
| 2010 } | 2110 } |
| 2011 | 2111 |
| 2112 template <InstARM32::InstKindARM32 K> | |
| 2113 void InstARM32UnaryopSignAwareFP<K>::emitIAS(const Cfg *Func) const { | |
| 2114 InstARM32::emitUsingTextFixup(Func); | |
| 2115 } | |
| 2116 | |
| 2012 template <> void InstARM32Vsqrt::emitIAS(const Cfg *Func) const { | 2117 template <> void InstARM32Vsqrt::emitIAS(const Cfg *Func) const { |
| 2013 assert(getSrcSize() == 1); | 2118 assert(getSrcSize() == 1); |
| 2014 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 2119 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 2015 const Operand *Dest = getDest(); | 2120 const Operand *Dest = getDest(); |
| 2016 switch (Dest->getType()) { | 2121 switch (Dest->getType()) { |
| 2017 case IceType_f32: | 2122 case IceType_f32: |
| 2018 Asm->vsqrts(Dest, getSrc(0), getPredicate()); | 2123 Asm->vsqrts(Dest, getSrc(0), getPredicate()); |
| 2019 break; | 2124 break; |
| 2020 case IceType_f64: | 2125 case IceType_f64: |
| 2021 Asm->vsqrtd(Dest, getSrc(0), getPredicate()); | 2126 Asm->vsqrtd(Dest, getSrc(0), getPredicate()); |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2413 << "vcvt" << getPredicate() << vcvtVariantSuffix(Variant) << " "; | 2518 << "vcvt" << getPredicate() << vcvtVariantSuffix(Variant) << " "; |
| 2414 dumpSources(Func); | 2519 dumpSources(Func); |
| 2415 } | 2520 } |
| 2416 | 2521 |
| 2417 void InstARM32Vcmp::emit(const Cfg *Func) const { | 2522 void InstARM32Vcmp::emit(const Cfg *Func) const { |
| 2418 if (!BuildDefs::dump()) | 2523 if (!BuildDefs::dump()) |
| 2419 return; | 2524 return; |
| 2420 Ostream &Str = Func->getContext()->getStrEmit(); | 2525 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2421 assert(getSrcSize() == 2); | 2526 assert(getSrcSize() == 2); |
| 2422 Str << "\t" | 2527 Str << "\t" |
| 2423 "vcmp" << getPredicate() << getVecWidthString(getSrc(0)->getType()) | 2528 "vcmp" << getPredicate() << getFpWidthString(getSrc(0)->getType()) |
| 2424 << "\t"; | 2529 << "\t"; |
| 2425 getSrc(0)->emit(Func); | 2530 getSrc(0)->emit(Func); |
| 2426 Str << ", "; | 2531 Str << ", "; |
| 2427 getSrc(1)->emit(Func); | 2532 getSrc(1)->emit(Func); |
| 2428 } | 2533 } |
| 2429 | 2534 |
| 2430 void InstARM32Vcmp::emitIAS(const Cfg *Func) const { | 2535 void InstARM32Vcmp::emitIAS(const Cfg *Func) const { |
| 2431 assert(getSrcSize() == 2); | 2536 assert(getSrcSize() == 2); |
| 2432 const Operand *Src0 = getSrc(0); | 2537 const Operand *Src0 = getSrc(0); |
| 2433 const Type Ty = Src0->getType(); | 2538 const Type Ty = Src0->getType(); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 2457 llvm::report_fatal_error("Vcvt on non floating value"); | 2562 llvm::report_fatal_error("Vcvt on non floating value"); |
| 2458 } | 2563 } |
| 2459 } | 2564 } |
| 2460 assert(!Asm->needsTextFixup()); | 2565 assert(!Asm->needsTextFixup()); |
| 2461 } | 2566 } |
| 2462 | 2567 |
| 2463 void InstARM32Vcmp::dump(const Cfg *Func) const { | 2568 void InstARM32Vcmp::dump(const Cfg *Func) const { |
| 2464 if (!BuildDefs::dump()) | 2569 if (!BuildDefs::dump()) |
| 2465 return; | 2570 return; |
| 2466 Ostream &Str = Func->getContext()->getStrDump(); | 2571 Ostream &Str = Func->getContext()->getStrDump(); |
| 2467 Str << "vcmp" << getPredicate() << getVecWidthString(getSrc(0)->getType()); | 2572 Str << "vcmp" << getPredicate() << getFpWidthString(getSrc(0)->getType()); |
| 2468 dumpSources(Func); | 2573 dumpSources(Func); |
| 2469 } | 2574 } |
| 2470 | 2575 |
| 2471 void InstARM32Vmrs::emit(const Cfg *Func) const { | 2576 void InstARM32Vmrs::emit(const Cfg *Func) const { |
| 2472 if (!BuildDefs::dump()) | 2577 if (!BuildDefs::dump()) |
| 2473 return; | 2578 return; |
| 2474 Ostream &Str = Func->getContext()->getStrEmit(); | 2579 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2475 assert(getSrcSize() == 0); | 2580 assert(getSrcSize() == 0); |
| 2476 Str << "\t" | 2581 Str << "\t" |
| 2477 "vmrs" << getPredicate() << "\t" | 2582 "vmrs" << getPredicate() << "\t" |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 2493 Str << "APSR{n,z,v,c} = vmrs" << getPredicate() << "\t" | 2598 Str << "APSR{n,z,v,c} = vmrs" << getPredicate() << "\t" |
| 2494 "FPSCR{n,z,c,v}"; | 2599 "FPSCR{n,z,c,v}"; |
| 2495 } | 2600 } |
| 2496 | 2601 |
| 2497 void InstARM32Vabs::emit(const Cfg *Func) const { | 2602 void InstARM32Vabs::emit(const Cfg *Func) const { |
| 2498 if (!BuildDefs::dump()) | 2603 if (!BuildDefs::dump()) |
| 2499 return; | 2604 return; |
| 2500 Ostream &Str = Func->getContext()->getStrEmit(); | 2605 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2501 assert(getSrcSize() == 1); | 2606 assert(getSrcSize() == 1); |
| 2502 Str << "\t" | 2607 Str << "\t" |
| 2503 "vabs" << getPredicate() << getVecWidthString(getSrc(0)->getType()) | 2608 "vabs" << getPredicate() << getFpWidthString(getSrc(0)->getType()) |
| 2504 << "\t"; | 2609 << "\t"; |
| 2505 getDest()->emit(Func); | 2610 getDest()->emit(Func); |
| 2506 Str << ", "; | 2611 Str << ", "; |
| 2507 getSrc(0)->emit(Func); | 2612 getSrc(0)->emit(Func); |
| 2508 } | 2613 } |
| 2509 | 2614 |
| 2510 void InstARM32Vabs::emitIAS(const Cfg *Func) const { | 2615 void InstARM32Vabs::emitIAS(const Cfg *Func) const { |
| 2511 assert(getSrcSize() == 1); | 2616 assert(getSrcSize() == 1); |
| 2512 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 2617 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 2513 const Variable *Dest = getDest(); | 2618 const Variable *Dest = getDest(); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 2527 Asm->vabsq(Dest, getSrc(0)); | 2632 Asm->vabsq(Dest, getSrc(0)); |
| 2528 } | 2633 } |
| 2529 assert(!Asm->needsTextFixup()); | 2634 assert(!Asm->needsTextFixup()); |
| 2530 } | 2635 } |
| 2531 | 2636 |
| 2532 void InstARM32Vabs::dump(const Cfg *Func) const { | 2637 void InstARM32Vabs::dump(const Cfg *Func) const { |
| 2533 if (!BuildDefs::dump()) | 2638 if (!BuildDefs::dump()) |
| 2534 return; | 2639 return; |
| 2535 Ostream &Str = Func->getContext()->getStrDump(); | 2640 Ostream &Str = Func->getContext()->getStrDump(); |
| 2536 dumpDest(Func); | 2641 dumpDest(Func); |
| 2537 Str << " = vabs" << getPredicate() << getVecWidthString(getSrc(0)->getType()); | 2642 Str << " = vabs" << getPredicate() << getFpWidthString(getSrc(0)->getType()); |
| 2538 } | 2643 } |
| 2539 | 2644 |
| 2540 void InstARM32Dmb::emit(const Cfg *Func) const { | 2645 void InstARM32Dmb::emit(const Cfg *Func) const { |
| 2541 if (!BuildDefs::dump()) | 2646 if (!BuildDefs::dump()) |
| 2542 return; | 2647 return; |
| 2543 Ostream &Str = Func->getContext()->getStrEmit(); | 2648 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2544 assert(getSrcSize() == 0); | 2649 assert(getSrcSize() == 0); |
| 2545 Str << "\t" | 2650 Str << "\t" |
| 2546 "dmb" | 2651 "dmb" |
| 2547 "\t" | 2652 "\t" |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2727 case IceType_f32: | 2832 case IceType_f32: |
| 2728 Str << "#" << materializeFloatImmediate(ModifiedImm) | 2833 Str << "#" << materializeFloatImmediate(ModifiedImm) |
| 2729 << " @ Modified: " << ModifiedImm; | 2834 << " @ Modified: " << ModifiedImm; |
| 2730 break; | 2835 break; |
| 2731 } | 2836 } |
| 2732 } | 2837 } |
| 2733 | 2838 |
| 2734 void OperandARM32FlexFpImm::dump(const Cfg * /*Func*/, Ostream &Str) const { | 2839 void OperandARM32FlexFpImm::dump(const Cfg * /*Func*/, Ostream &Str) const { |
| 2735 if (!BuildDefs::dump()) | 2840 if (!BuildDefs::dump()) |
| 2736 return; | 2841 return; |
| 2737 Str << "#" << materializeFloatImmediate(ModifiedImm) | 2842 Str << "#" << materializeFloatImmediate(ModifiedImm) << getFpWidthString(Ty); |
| 2738 << InstARM32::getVecWidthString(Ty); | |
| 2739 } | 2843 } |
| 2740 | 2844 |
| 2741 void OperandARM32FlexFpZero::emit(const Cfg *Func) const { | 2845 void OperandARM32FlexFpZero::emit(const Cfg *Func) const { |
| 2742 if (!BuildDefs::dump()) | 2846 if (!BuildDefs::dump()) |
| 2743 return; | 2847 return; |
| 2744 Ostream &Str = Func->getContext()->getStrEmit(); | 2848 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2745 switch (Ty) { | 2849 switch (Ty) { |
| 2746 default: | 2850 default: |
| 2747 llvm::report_fatal_error("Invalid flex fp imm type."); | 2851 llvm::report_fatal_error("Invalid flex fp imm type."); |
| 2748 case IceType_f64: | 2852 case IceType_f64: |
| 2749 case IceType_f32: | 2853 case IceType_f32: |
| 2750 Str << "#0.0"; | 2854 Str << "#0.0"; |
| 2751 } | 2855 } |
| 2752 } | 2856 } |
| 2753 | 2857 |
| 2754 void OperandARM32FlexFpZero::dump(const Cfg * /*Func*/, Ostream &Str) const { | 2858 void OperandARM32FlexFpZero::dump(const Cfg * /*Func*/, Ostream &Str) const { |
| 2755 if (!BuildDefs::dump()) | 2859 if (!BuildDefs::dump()) |
| 2756 return; | 2860 return; |
| 2757 Str << "#0.0" << InstARM32::getVecWidthString(Ty); | 2861 Str << "#0.0" << getFpWidthString(Ty); |
| 2758 } | 2862 } |
| 2759 | 2863 |
| 2760 void OperandARM32FlexReg::emit(const Cfg *Func) const { | 2864 void OperandARM32FlexReg::emit(const Cfg *Func) const { |
| 2761 if (!BuildDefs::dump()) | 2865 if (!BuildDefs::dump()) |
| 2762 return; | 2866 return; |
| 2763 Ostream &Str = Func->getContext()->getStrEmit(); | 2867 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2764 getReg()->emit(Func); | 2868 getReg()->emit(Func); |
| 2765 if (getShiftOp() != kNoShift) { | 2869 if (getShiftOp() != kNoShift) { |
| 2766 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " "; | 2870 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " "; |
| 2767 getShiftAmt()->emit(Func); | 2871 getShiftAmt()->emit(Func); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2802 template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>; | 2906 template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>; |
| 2803 template class InstARM32ThreeAddrGPR<InstARM32::Sub>; | 2907 template class InstARM32ThreeAddrGPR<InstARM32::Sub>; |
| 2804 template class InstARM32ThreeAddrGPR<InstARM32::Udiv>; | 2908 template class InstARM32ThreeAddrGPR<InstARM32::Udiv>; |
| 2805 | 2909 |
| 2806 template class InstARM32ThreeAddrFP<InstARM32::Vadd>; | 2910 template class InstARM32ThreeAddrFP<InstARM32::Vadd>; |
| 2807 template class InstARM32ThreeAddrFP<InstARM32::Vdiv>; | 2911 template class InstARM32ThreeAddrFP<InstARM32::Vdiv>; |
| 2808 template class InstARM32ThreeAddrFP<InstARM32::Veor>; | 2912 template class InstARM32ThreeAddrFP<InstARM32::Veor>; |
| 2809 template class InstARM32FourAddrFP<InstARM32::Vmla>; | 2913 template class InstARM32FourAddrFP<InstARM32::Vmla>; |
| 2810 template class InstARM32FourAddrFP<InstARM32::Vmls>; | 2914 template class InstARM32FourAddrFP<InstARM32::Vmls>; |
| 2811 template class InstARM32ThreeAddrFP<InstARM32::Vmul>; | 2915 template class InstARM32ThreeAddrFP<InstARM32::Vmul>; |
| 2916 template class InstARM32UnaryopSignAwareFP<InstARM32::Vneg>; | |
| 2917 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vshl>; | |
| 2812 template class InstARM32ThreeAddrFP<InstARM32::Vsub>; | 2918 template class InstARM32ThreeAddrFP<InstARM32::Vsub>; |
| 2813 | 2919 |
| 2814 template class InstARM32LoadBase<InstARM32::Ldr>; | 2920 template class InstARM32LoadBase<InstARM32::Ldr>; |
| 2815 template class InstARM32LoadBase<InstARM32::Ldrex>; | 2921 template class InstARM32LoadBase<InstARM32::Ldrex>; |
| 2816 | 2922 |
| 2817 template class InstARM32TwoAddrGPR<InstARM32::Movt>; | 2923 template class InstARM32TwoAddrGPR<InstARM32::Movt>; |
| 2818 | 2924 |
| 2819 template class InstARM32UnaryopGPR<InstARM32::Movw, false>; | 2925 template class InstARM32UnaryopGPR<InstARM32::Movw, false>; |
| 2820 template class InstARM32UnaryopGPR<InstARM32::Clz, false>; | 2926 template class InstARM32UnaryopGPR<InstARM32::Clz, false>; |
| 2821 template class InstARM32UnaryopGPR<InstARM32::Mvn, false>; | 2927 template class InstARM32UnaryopGPR<InstARM32::Mvn, false>; |
| 2822 template class InstARM32UnaryopGPR<InstARM32::Rbit, false>; | 2928 template class InstARM32UnaryopGPR<InstARM32::Rbit, false>; |
| 2823 template class InstARM32UnaryopGPR<InstARM32::Rev, false>; | 2929 template class InstARM32UnaryopGPR<InstARM32::Rev, false>; |
| 2824 template class InstARM32UnaryopGPR<InstARM32::Sxt, true>; | 2930 template class InstARM32UnaryopGPR<InstARM32::Sxt, true>; |
| 2825 template class InstARM32UnaryopGPR<InstARM32::Uxt, true>; | 2931 template class InstARM32UnaryopGPR<InstARM32::Uxt, true>; |
| 2826 template class InstARM32UnaryopFP<InstARM32::Vsqrt>; | 2932 template class InstARM32UnaryopFP<InstARM32::Vsqrt>; |
| 2827 | 2933 |
| 2828 template class InstARM32FourAddrGPR<InstARM32::Mla>; | 2934 template class InstARM32FourAddrGPR<InstARM32::Mla>; |
| 2829 template class InstARM32FourAddrGPR<InstARM32::Mls>; | 2935 template class InstARM32FourAddrGPR<InstARM32::Mls>; |
| 2830 | 2936 |
| 2831 template class InstARM32CmpLike<InstARM32::Cmn>; | 2937 template class InstARM32CmpLike<InstARM32::Cmn>; |
| 2832 template class InstARM32CmpLike<InstARM32::Cmp>; | 2938 template class InstARM32CmpLike<InstARM32::Cmp>; |
| 2833 template class InstARM32CmpLike<InstARM32::Tst>; | 2939 template class InstARM32CmpLike<InstARM32::Tst>; |
| 2834 | 2940 |
| 2835 } // end of namespace ARM32 | 2941 } // end of namespace ARM32 |
| 2836 } // end of namespace Ice | 2942 } // end of namespace Ice |
| OLD | NEW |