OLD | NEW |
1 //===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===// | 1 //===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
(...skipping 22 matching lines...) Expand all Loading... |
33 OperandARM32() = delete; | 33 OperandARM32() = delete; |
34 OperandARM32(const OperandARM32 &) = delete; | 34 OperandARM32(const OperandARM32 &) = delete; |
35 OperandARM32 &operator=(const OperandARM32 &) = delete; | 35 OperandARM32 &operator=(const OperandARM32 &) = delete; |
36 | 36 |
37 public: | 37 public: |
38 enum OperandKindARM32 { | 38 enum OperandKindARM32 { |
39 k__Start = Operand::kTarget, | 39 k__Start = Operand::kTarget, |
40 kMem, | 40 kMem, |
41 kFlexStart, | 41 kFlexStart, |
42 kFlexImm = kFlexStart, | 42 kFlexImm = kFlexStart, |
| 43 kFlexFpImm, |
| 44 kFlexFpZero, |
43 kFlexReg, | 45 kFlexReg, |
44 kFlexEnd = kFlexReg | 46 kFlexEnd = kFlexReg |
45 }; | 47 }; |
46 | 48 |
47 enum ShiftKind { | 49 enum ShiftKind { |
48 kNoShift = -1, | 50 kNoShift = -1, |
49 #define X(enum, emit) enum, | 51 #define X(enum, emit) enum, |
50 ICEINSTARM32SHIFT_TABLE | 52 ICEINSTARM32SHIFT_TABLE |
51 #undef X | 53 #undef X |
52 }; | 54 }; |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 uint32_t getImm() const { return Imm; } | 200 uint32_t getImm() const { return Imm; } |
199 uint32_t getRotateAmt() const { return RotateAmt; } | 201 uint32_t getRotateAmt() const { return RotateAmt; } |
200 | 202 |
201 private: | 203 private: |
202 OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt); | 204 OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt); |
203 | 205 |
204 uint32_t Imm; | 206 uint32_t Imm; |
205 uint32_t RotateAmt; | 207 uint32_t RotateAmt; |
206 }; | 208 }; |
207 | 209 |
| 210 /// Modified Floating-point constant. |
| 211 class OperandARM32FlexFpImm : public OperandARM32Flex { |
| 212 OperandARM32FlexFpImm() = delete; |
| 213 OperandARM32FlexFpImm(const OperandARM32FlexFpImm &) = delete; |
| 214 OperandARM32FlexFpImm &operator=(const OperandARM32FlexFpImm &) = delete; |
| 215 |
| 216 public: |
| 217 static OperandARM32FlexFpImm *create(Cfg *Func, Type Ty, |
| 218 uint32_t ModifiedImm) { |
| 219 return new (Func->allocate<OperandARM32FlexFpImm>()) |
| 220 OperandARM32FlexFpImm(Func, Ty, ModifiedImm); |
| 221 } |
| 222 |
| 223 void emit(const Cfg *Func) const override; |
| 224 using OperandARM32::dump; |
| 225 void dump(const Cfg *Func, Ostream &Str) const override; |
| 226 |
| 227 static bool classof(const Operand *Operand) { |
| 228 return Operand->getKind() == static_cast<OperandKind>(kFlexFpImm); |
| 229 } |
| 230 |
| 231 static bool canHoldImm(Operand *C, uint32_t *ModifiedImm); |
| 232 |
| 233 private: |
| 234 OperandARM32FlexFpImm(Cfg *Func, Type Ty, uint32_t ModifiedImm); |
| 235 |
| 236 uint32_t ModifiedImm; |
| 237 }; |
| 238 |
| 239 /// An operand for representing the 0.0 immediate in vcmp. |
| 240 class OperandARM32FlexFpZero : public OperandARM32Flex { |
| 241 OperandARM32FlexFpZero() = delete; |
| 242 OperandARM32FlexFpZero(const OperandARM32FlexFpZero &) = delete; |
| 243 OperandARM32FlexFpZero &operator=(const OperandARM32FlexFpZero &) = delete; |
| 244 |
| 245 public: |
| 246 static OperandARM32FlexFpZero *create(Cfg *Func, Type Ty) { |
| 247 return new (Func->allocate<OperandARM32FlexFpZero>()) |
| 248 OperandARM32FlexFpZero(Func, Ty); |
| 249 } |
| 250 |
| 251 void emit(const Cfg *Func) const override; |
| 252 using OperandARM32::dump; |
| 253 void dump(const Cfg *Func, Ostream &Str) const override; |
| 254 |
| 255 static bool classof(const Operand *Operand) { |
| 256 return Operand->getKind() == static_cast<OperandKind>(kFlexFpZero); |
| 257 } |
| 258 |
| 259 private: |
| 260 OperandARM32FlexFpZero(Cfg *Func, Type Ty); |
| 261 }; |
| 262 |
208 /// Shifted register variant. | 263 /// Shifted register variant. |
209 class OperandARM32FlexReg : public OperandARM32Flex { | 264 class OperandARM32FlexReg : public OperandARM32Flex { |
210 OperandARM32FlexReg() = delete; | 265 OperandARM32FlexReg() = delete; |
211 OperandARM32FlexReg(const OperandARM32FlexReg &) = delete; | 266 OperandARM32FlexReg(const OperandARM32FlexReg &) = delete; |
212 OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete; | 267 OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete; |
213 | 268 |
214 public: | 269 public: |
215 /// Register with immediate/reg shift amount and shift operation. | 270 /// Register with immediate/reg shift amount and shift operation. |
216 static OperandARM32FlexReg *create(Cfg *Func, Type Ty, Variable *Reg, | 271 static OperandARM32FlexReg *create(Cfg *Func, Type Ty, Variable *Reg, |
217 ShiftKind ShiftOp, Operand *ShiftAmt) { | 272 ShiftKind ShiftOp, Operand *ShiftAmt) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 enum InstKindARM32 { | 337 enum InstKindARM32 { |
283 k__Start = Inst::Target, | 338 k__Start = Inst::Target, |
284 Adc, | 339 Adc, |
285 Add, | 340 Add, |
286 Adjuststack, | 341 Adjuststack, |
287 And, | 342 And, |
288 Asr, | 343 Asr, |
289 Bic, | 344 Bic, |
290 Br, | 345 Br, |
291 Call, | 346 Call, |
| 347 Cmn, |
292 Cmp, | 348 Cmp, |
293 Clz, | 349 Clz, |
294 Dmb, | 350 Dmb, |
295 Eor, | 351 Eor, |
296 Label, | 352 Label, |
297 Ldr, | 353 Ldr, |
298 Ldrex, | 354 Ldrex, |
299 Lsl, | 355 Lsl, |
300 Lsr, | 356 Lsr, |
301 Mla, | 357 Mla, |
302 Mls, | 358 Mls, |
303 Mov, | 359 Mov, |
304 Movt, | 360 Movt, |
305 Movw, | 361 Movw, |
306 Mul, | 362 Mul, |
307 Mvn, | 363 Mvn, |
308 Orr, | 364 Orr, |
309 Pop, | 365 Pop, |
310 Push, | 366 Push, |
311 Rbit, | 367 Rbit, |
312 Ret, | 368 Ret, |
313 Rev, | 369 Rev, |
314 Rsb, | 370 Rsb, |
| 371 Rsc, |
315 Sbc, | 372 Sbc, |
316 Sdiv, | 373 Sdiv, |
317 Str, | 374 Str, |
318 Strex, | 375 Strex, |
319 Sub, | 376 Sub, |
320 Sxt, | 377 Sxt, |
321 Trap, | 378 Trap, |
322 Tst, | 379 Tst, |
323 Udiv, | 380 Udiv, |
324 Umull, | 381 Umull, |
325 Uxt, | 382 Uxt, |
326 Vabs, | 383 Vabs, |
327 Vadd, | 384 Vadd, |
328 Vcmp, | 385 Vcmp, |
329 Vcvt, | 386 Vcvt, |
330 Vdiv, | 387 Vdiv, |
| 388 Veor, |
331 Vmrs, | 389 Vmrs, |
332 Vmul, | 390 Vmul, |
333 Vsqrt, | 391 Vsqrt, |
334 Vsub | 392 Vsub |
335 }; | 393 }; |
336 | 394 |
337 static constexpr size_t InstSize = sizeof(uint32_t); | 395 static constexpr size_t InstSize = sizeof(uint32_t); |
338 | 396 |
339 static const char *getWidthString(Type Ty); | 397 static const char *getWidthString(Type Ty); |
340 static const char *getVecWidthString(Type Ty); | 398 static const char *getVecWidthString(Type Ty); |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 dumpOpcodePred(Str, Opcode, getDest()->getType()); | 660 dumpOpcodePred(Str, Opcode, getDest()->getType()); |
603 Str << (SetFlags ? ".s " : " "); | 661 Str << (SetFlags ? ".s " : " "); |
604 dumpSources(Func); | 662 dumpSources(Func); |
605 } | 663 } |
606 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 664 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
607 | 665 |
608 private: | 666 private: |
609 InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0, | 667 InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0, |
610 Operand *Src1, CondARM32::Cond Predicate, bool SetFlags) | 668 Operand *Src1, CondARM32::Cond Predicate, bool SetFlags) |
611 : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) { | 669 : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) { |
| 670 HasSideEffects = SetFlags; |
612 addSource(Src0); | 671 addSource(Src0); |
613 addSource(Src1); | 672 addSource(Src1); |
614 } | 673 } |
615 | 674 |
616 static const char *Opcode; | 675 static const char *Opcode; |
617 bool SetFlags; | 676 bool SetFlags; |
618 }; | 677 }; |
619 | 678 |
620 /// Instructions of the form x := y op z, for vector/FP. We leave these as | 679 /// Instructions of the form x := y op z, for vector/FP. We leave these as |
621 /// unconditional: "ARM deprecates the conditional execution of any instruction | 680 /// unconditional: "ARM deprecates the conditional execution of any instruction |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
734 dumpOpcodePred(Str, Opcode, getSrc(0)->getType()); | 793 dumpOpcodePred(Str, Opcode, getSrc(0)->getType()); |
735 Str << " "; | 794 Str << " "; |
736 dumpSources(Func); | 795 dumpSources(Func); |
737 } | 796 } |
738 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 797 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
739 | 798 |
740 private: | 799 private: |
741 InstARM32CmpLike(Cfg *Func, Variable *Src0, Operand *Src1, | 800 InstARM32CmpLike(Cfg *Func, Variable *Src0, Operand *Src1, |
742 CondARM32::Cond Predicate) | 801 CondARM32::Cond Predicate) |
743 : InstARM32Pred(Func, K, 2, nullptr, Predicate) { | 802 : InstARM32Pred(Func, K, 2, nullptr, Predicate) { |
| 803 HasSideEffects = true; |
744 addSource(Src0); | 804 addSource(Src0); |
745 addSource(Src1); | 805 addSource(Src1); |
746 } | 806 } |
747 | 807 |
748 static const char *Opcode; | 808 static const char *Opcode; |
749 }; | 809 }; |
750 | 810 |
751 using InstARM32Adc = InstARM32ThreeAddrGPR<InstARM32::Adc>; | 811 using InstARM32Adc = InstARM32ThreeAddrGPR<InstARM32::Adc>; |
752 using InstARM32Add = InstARM32ThreeAddrGPR<InstARM32::Add>; | 812 using InstARM32Add = InstARM32ThreeAddrGPR<InstARM32::Add>; |
753 using InstARM32And = InstARM32ThreeAddrGPR<InstARM32::And>; | 813 using InstARM32And = InstARM32ThreeAddrGPR<InstARM32::And>; |
754 using InstARM32Asr = InstARM32ThreeAddrGPR<InstARM32::Asr>; | 814 using InstARM32Asr = InstARM32ThreeAddrGPR<InstARM32::Asr>; |
755 using InstARM32Bic = InstARM32ThreeAddrGPR<InstARM32::Bic>; | 815 using InstARM32Bic = InstARM32ThreeAddrGPR<InstARM32::Bic>; |
756 using InstARM32Eor = InstARM32ThreeAddrGPR<InstARM32::Eor>; | 816 using InstARM32Eor = InstARM32ThreeAddrGPR<InstARM32::Eor>; |
757 using InstARM32Lsl = InstARM32ThreeAddrGPR<InstARM32::Lsl>; | 817 using InstARM32Lsl = InstARM32ThreeAddrGPR<InstARM32::Lsl>; |
758 using InstARM32Lsr = InstARM32ThreeAddrGPR<InstARM32::Lsr>; | 818 using InstARM32Lsr = InstARM32ThreeAddrGPR<InstARM32::Lsr>; |
759 using InstARM32Mul = InstARM32ThreeAddrGPR<InstARM32::Mul>; | 819 using InstARM32Mul = InstARM32ThreeAddrGPR<InstARM32::Mul>; |
760 using InstARM32Orr = InstARM32ThreeAddrGPR<InstARM32::Orr>; | 820 using InstARM32Orr = InstARM32ThreeAddrGPR<InstARM32::Orr>; |
761 using InstARM32Rsb = InstARM32ThreeAddrGPR<InstARM32::Rsb>; | 821 using InstARM32Rsb = InstARM32ThreeAddrGPR<InstARM32::Rsb>; |
| 822 using InstARM32Rsc = InstARM32ThreeAddrGPR<InstARM32::Rsc>; |
762 using InstARM32Sbc = InstARM32ThreeAddrGPR<InstARM32::Sbc>; | 823 using InstARM32Sbc = InstARM32ThreeAddrGPR<InstARM32::Sbc>; |
763 using InstARM32Sdiv = InstARM32ThreeAddrGPR<InstARM32::Sdiv>; | 824 using InstARM32Sdiv = InstARM32ThreeAddrGPR<InstARM32::Sdiv>; |
764 using InstARM32Sub = InstARM32ThreeAddrGPR<InstARM32::Sub>; | 825 using InstARM32Sub = InstARM32ThreeAddrGPR<InstARM32::Sub>; |
765 using InstARM32Udiv = InstARM32ThreeAddrGPR<InstARM32::Udiv>; | 826 using InstARM32Udiv = InstARM32ThreeAddrGPR<InstARM32::Udiv>; |
766 using InstARM32Vadd = InstARM32ThreeAddrFP<InstARM32::Vadd>; | 827 using InstARM32Vadd = InstARM32ThreeAddrFP<InstARM32::Vadd>; |
767 using InstARM32Vdiv = InstARM32ThreeAddrFP<InstARM32::Vdiv>; | 828 using InstARM32Vdiv = InstARM32ThreeAddrFP<InstARM32::Vdiv>; |
768 using InstARM32Vmul = InstARM32ThreeAddrFP<InstARM32::Vmul>; | 829 using InstARM32Vmul = InstARM32ThreeAddrFP<InstARM32::Vmul>; |
| 830 using InstARM32Veor = InstARM32ThreeAddrFP<InstARM32::Veor>; |
769 using InstARM32Vsub = InstARM32ThreeAddrFP<InstARM32::Vsub>; | 831 using InstARM32Vsub = InstARM32ThreeAddrFP<InstARM32::Vsub>; |
770 using InstARM32Ldr = InstARM32LoadBase<InstARM32::Ldr>; | 832 using InstARM32Ldr = InstARM32LoadBase<InstARM32::Ldr>; |
771 using InstARM32Ldrex = InstARM32LoadBase<InstARM32::Ldrex>; | 833 using InstARM32Ldrex = InstARM32LoadBase<InstARM32::Ldrex>; |
772 /// MovT leaves the bottom bits alone so dest is also a source. This helps | 834 /// MovT leaves the bottom bits alone so dest is also a source. This helps |
773 /// indicate that a previous MovW setting dest is not dead code. | 835 /// indicate that a previous MovW setting dest is not dead code. |
774 using InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>; | 836 using InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>; |
775 using InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>; | 837 using InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>; |
776 using InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>; | 838 using InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>; |
777 using InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>; | 839 using InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>; |
778 using InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>; | 840 using InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>; |
779 using InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>; | 841 using InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>; |
780 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation operand | 842 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation operand |
781 // as well (rotate source by 8, 16, 24 bits prior to extending), but we aren't | 843 // as well (rotate source by 8, 16, 24 bits prior to extending), but we aren't |
782 // using that for now, so just model as a Unaryop. | 844 // using that for now, so just model as a Unaryop. |
783 using InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>; | 845 using InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>; |
784 using InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>; | 846 using InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>; |
785 using InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>; | 847 using InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>; |
786 using InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>; | 848 using InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>; |
787 using InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>; | 849 using InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>; |
| 850 using InstARM32Cmn = InstARM32CmpLike<InstARM32::Cmn>; |
788 using InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>; | 851 using InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>; |
789 using InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>; | 852 using InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>; |
790 | 853 |
791 // InstARM32Label represents an intra-block label that is the target of an | 854 // InstARM32Label represents an intra-block label that is the target of an |
792 // intra-block branch. The offset between the label and the branch must be fit | 855 // intra-block branch. The offset between the label and the branch must be fit |
793 // in the instruction immediate (considered "near"). | 856 // in the instruction immediate (considered "near"). |
794 class InstARM32Label : public InstARM32 { | 857 class InstARM32Label : public InstARM32 { |
795 InstARM32Label() = delete; | 858 InstARM32Label() = delete; |
796 InstARM32Label(const InstARM32Label &) = delete; | 859 InstARM32Label(const InstARM32Label &) = delete; |
797 InstARM32Label &operator=(const InstARM32Label &) = delete; | 860 InstARM32Label &operator=(const InstARM32Label &) = delete; |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1171 InstARM32Vcmp() = delete; | 1234 InstARM32Vcmp() = delete; |
1172 InstARM32Vcmp(const InstARM32Vcmp &) = delete; | 1235 InstARM32Vcmp(const InstARM32Vcmp &) = delete; |
1173 InstARM32Vcmp &operator=(const InstARM32Vcmp &) = delete; | 1236 InstARM32Vcmp &operator=(const InstARM32Vcmp &) = delete; |
1174 | 1237 |
1175 public: | 1238 public: |
1176 static InstARM32Vcmp *create(Cfg *Func, Variable *Src0, Variable *Src1, | 1239 static InstARM32Vcmp *create(Cfg *Func, Variable *Src0, Variable *Src1, |
1177 CondARM32::Cond Predicate) { | 1240 CondARM32::Cond Predicate) { |
1178 return new (Func->allocate<InstARM32Vcmp>()) | 1241 return new (Func->allocate<InstARM32Vcmp>()) |
1179 InstARM32Vcmp(Func, Src0, Src1, Predicate); | 1242 InstARM32Vcmp(Func, Src0, Src1, Predicate); |
1180 } | 1243 } |
| 1244 static InstARM32Vcmp *create(Cfg *Func, Variable *Src0, |
| 1245 OperandARM32FlexFpZero *Src1, |
| 1246 CondARM32::Cond Predicate) { |
| 1247 return new (Func->allocate<InstARM32Vcmp>()) |
| 1248 InstARM32Vcmp(Func, Src0, Src1, Predicate); |
| 1249 } |
1181 void emit(const Cfg *Func) const override; | 1250 void emit(const Cfg *Func) const override; |
1182 void dump(const Cfg *Func) const override; | 1251 void dump(const Cfg *Func) const override; |
1183 static bool classof(const Inst *Inst) { return isClassof(Inst, Vcmp); } | 1252 static bool classof(const Inst *Inst) { return isClassof(Inst, Vcmp); } |
1184 | 1253 |
1185 private: | 1254 private: |
1186 InstARM32Vcmp(Cfg *Func, Variable *Src0, Variable *Src1, | 1255 InstARM32Vcmp(Cfg *Func, Variable *Src0, Operand *Src1, |
1187 CondARM32::Cond Predicate); | 1256 CondARM32::Cond Predicate); |
1188 }; | 1257 }; |
1189 | 1258 |
1190 /// Copies the FP Status and Control Register the core flags. | 1259 /// Copies the FP Status and Control Register the core flags. |
1191 class InstARM32Vmrs final : public InstARM32Pred { | 1260 class InstARM32Vmrs final : public InstARM32Pred { |
1192 InstARM32Vmrs() = delete; | 1261 InstARM32Vmrs() = delete; |
1193 InstARM32Vmrs(const InstARM32Vmrs &) = delete; | 1262 InstARM32Vmrs(const InstARM32Vmrs &) = delete; |
1194 InstARM32Vmrs &operator=(const InstARM32Vmrs &) = delete; | 1263 InstARM32Vmrs &operator=(const InstARM32Vmrs &) = delete; |
1195 | 1264 |
1196 public: | 1265 public: |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1246 // default implementations. Without this, there is the possibility of ODR | 1315 // default implementations. Without this, there is the possibility of ODR |
1247 // violations and link errors. | 1316 // violations and link errors. |
1248 | 1317 |
1249 template <> void InstARM32Ldr::emit(const Cfg *Func) const; | 1318 template <> void InstARM32Ldr::emit(const Cfg *Func) const; |
1250 template <> void InstARM32Movw::emit(const Cfg *Func) const; | 1319 template <> void InstARM32Movw::emit(const Cfg *Func) const; |
1251 template <> void InstARM32Movt::emit(const Cfg *Func) const; | 1320 template <> void InstARM32Movt::emit(const Cfg *Func) const; |
1252 | 1321 |
1253 } // end of namespace Ice | 1322 } // end of namespace Ice |
1254 | 1323 |
1255 #endif // SUBZERO_SRC_ICEINSTARM32_H | 1324 #endif // SUBZERO_SRC_ICEINSTARM32_H |
OLD | NEW |