@@ -710,7 +710,8 @@ var optab = []Optab{
710
710
{AFLDPQ , C_PQAUTO_16 , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , REGSP , 0 , 0 },
711
711
{AFLDPQ , C_UAUTO4K , C_NONE , C_NONE , C_PAIR , C_NONE , 74 , 8 , REGSP , 0 , 0 },
712
712
{AFLDPQ , C_NAUTO4K , C_NONE , C_NONE , C_PAIR , C_NONE , 74 , 8 , REGSP , 0 , 0 },
713
- {AFLDPQ , C_LAUTO , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , REGSP , LFROM , 0 },
713
+ {AFLDPQ , C_LAUTO , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , REGSP , 0 , 0 },
714
+ {AFLDPQ , C_LAUTOPOOL , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , REGSP , LFROM , 0 },
714
715
{AFLDPQ , C_NQOREG_16 , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , 0 , 0 , 0 },
715
716
{AFLDPQ , C_NQOREG_16 , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , 0 , 0 , C_XPRE },
716
717
{AFLDPQ , C_NQOREG_16 , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , 0 , 0 , C_XPOST },
@@ -719,14 +720,16 @@ var optab = []Optab{
719
720
{AFLDPQ , C_PQOREG_16 , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , 0 , 0 , C_XPOST },
720
721
{AFLDPQ , C_UOREG4K , C_NONE , C_NONE , C_PAIR , C_NONE , 74 , 8 , 0 , 0 , 0 },
721
722
{AFLDPQ , C_NOREG4K , C_NONE , C_NONE , C_PAIR , C_NONE , 74 , 8 , 0 , 0 , 0 },
722
- {AFLDPQ , C_LOREG , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , 0 , LFROM , 0 },
723
+ {AFLDPQ , C_LOREG , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , 0 , 0 , 0 },
724
+ {AFLDPQ , C_LOREGPOOL , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , 0 , LFROM , 0 },
723
725
{AFLDPQ , C_ADDR , C_NONE , C_NONE , C_PAIR , C_NONE , 88 , 12 , 0 , 0 , 0 },
724
726
725
727
{AFSTPQ , C_PAIR , C_NONE , C_NONE , C_NQAUTO_16 , C_NONE , 67 , 4 , REGSP , 0 , 0 },
726
728
{AFSTPQ , C_PAIR , C_NONE , C_NONE , C_PQAUTO_16 , C_NONE , 67 , 4 , REGSP , 0 , 0 },
727
729
{AFSTPQ , C_PAIR , C_NONE , C_NONE , C_UAUTO4K , C_NONE , 76 , 8 , REGSP , 0 , 0 },
728
730
{AFSTPQ , C_PAIR , C_NONE , C_NONE , C_NAUTO4K , C_NONE , 76 , 8 , REGSP , 0 , 0 },
729
- {AFSTPQ , C_PAIR , C_NONE , C_NONE , C_LAUTO , C_NONE , 77 , 12 , REGSP , LTO , 0 },
731
+ {AFSTPQ , C_PAIR , C_NONE , C_NONE , C_LAUTO , C_NONE , 77 , 12 , REGSP , 0 , 0 },
732
+ {AFSTPQ , C_PAIR , C_NONE , C_NONE , C_LAUTOPOOL , C_NONE , 77 , 12 , REGSP , LTO , 0 },
730
733
{AFSTPQ , C_PAIR , C_NONE , C_NONE , C_NQOREG_16 , C_NONE , 67 , 4 , 0 , 0 , 0 },
731
734
{AFSTPQ , C_PAIR , C_NONE , C_NONE , C_NQOREG_16 , C_NONE , 67 , 4 , 0 , 0 , C_XPRE },
732
735
{AFSTPQ , C_PAIR , C_NONE , C_NONE , C_NQOREG_16 , C_NONE , 67 , 4 , 0 , 0 , C_XPOST },
@@ -735,14 +738,16 @@ var optab = []Optab{
735
738
{AFSTPQ , C_PAIR , C_NONE , C_NONE , C_PQOREG_16 , C_NONE , 67 , 4 , 0 , 0 , C_XPOST },
736
739
{AFSTPQ , C_PAIR , C_NONE , C_NONE , C_UOREG4K , C_NONE , 76 , 8 , 0 , 0 , 0 },
737
740
{AFSTPQ , C_PAIR , C_NONE , C_NONE , C_NOREG4K , C_NONE , 76 , 8 , 0 , 0 , 0 },
738
- {AFSTPQ , C_PAIR , C_NONE , C_NONE , C_LOREG , C_NONE , 77 , 12 , 0 , LTO , 0 },
741
+ {AFSTPQ , C_PAIR , C_NONE , C_NONE , C_LOREG , C_NONE , 77 , 12 , 0 , 0 , 0 },
742
+ {AFSTPQ , C_PAIR , C_NONE , C_NONE , C_LOREGPOOL , C_NONE , 77 , 12 , 0 , LTO , 0 },
739
743
{AFSTPQ , C_PAIR , C_NONE , C_NONE , C_ADDR , C_NONE , 87 , 12 , 0 , 0 , 0 },
740
744
741
745
{ALDP , C_NPAUTO , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , REGSP , 0 , 0 },
742
746
{ALDP , C_PPAUTO , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , REGSP , 0 , 0 },
743
747
{ALDP , C_UAUTO4K , C_NONE , C_NONE , C_PAIR , C_NONE , 74 , 8 , REGSP , 0 , 0 },
744
748
{ALDP , C_NAUTO4K , C_NONE , C_NONE , C_PAIR , C_NONE , 74 , 8 , REGSP , 0 , 0 },
745
- {ALDP , C_LAUTO , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , REGSP , LFROM , 0 },
749
+ {ALDP , C_LAUTO , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , REGSP , 0 , 0 },
750
+ {ALDP , C_LAUTOPOOL , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , REGSP , LFROM , 0 },
746
751
{ALDP , C_NPOREG , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , 0 , 0 , 0 },
747
752
{ALDP , C_NPOREG , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , 0 , 0 , C_XPRE },
748
753
{ALDP , C_NPOREG , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , 0 , 0 , C_XPOST },
@@ -751,14 +756,16 @@ var optab = []Optab{
751
756
{ALDP , C_PPOREG , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , 0 , 0 , C_XPOST },
752
757
{ALDP , C_UOREG4K , C_NONE , C_NONE , C_PAIR , C_NONE , 74 , 8 , 0 , 0 , 0 },
753
758
{ALDP , C_NOREG4K , C_NONE , C_NONE , C_PAIR , C_NONE , 74 , 8 , 0 , 0 , 0 },
754
- {ALDP , C_LOREG , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , 0 , LFROM , 0 },
759
+ {ALDP , C_LOREG , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , 0 , 0 , 0 },
760
+ {ALDP , C_LOREGPOOL , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , 0 , LFROM , 0 },
755
761
{ALDP , C_ADDR , C_NONE , C_NONE , C_PAIR , C_NONE , 88 , 12 , 0 , 0 , 0 },
756
762
757
763
{ASTP , C_PAIR , C_NONE , C_NONE , C_NPAUTO , C_NONE , 67 , 4 , REGSP , 0 , 0 },
758
764
{ASTP , C_PAIR , C_NONE , C_NONE , C_PPAUTO , C_NONE , 67 , 4 , REGSP , 0 , 0 },
759
765
{ASTP , C_PAIR , C_NONE , C_NONE , C_UAUTO4K , C_NONE , 76 , 8 , REGSP , 0 , 0 },
760
766
{ASTP , C_PAIR , C_NONE , C_NONE , C_NAUTO4K , C_NONE , 76 , 8 , REGSP , 0 , 0 },
761
- {ASTP , C_PAIR , C_NONE , C_NONE , C_LAUTO , C_NONE , 77 , 12 , REGSP , LTO , 0 },
767
+ {ASTP , C_PAIR , C_NONE , C_NONE , C_LAUTO , C_NONE , 77 , 12 , REGSP , 0 , 0 },
768
+ {ASTP , C_PAIR , C_NONE , C_NONE , C_LAUTOPOOL , C_NONE , 77 , 12 , REGSP , LTO , 0 },
762
769
{ASTP , C_PAIR , C_NONE , C_NONE , C_NPOREG , C_NONE , 67 , 4 , 0 , 0 , 0 },
763
770
{ASTP , C_PAIR , C_NONE , C_NONE , C_NPOREG , C_NONE , 67 , 4 , 0 , 0 , C_XPRE },
764
771
{ASTP , C_PAIR , C_NONE , C_NONE , C_NPOREG , C_NONE , 67 , 4 , 0 , 0 , C_XPOST },
@@ -767,15 +774,17 @@ var optab = []Optab{
767
774
{ASTP , C_PAIR , C_NONE , C_NONE , C_PPOREG , C_NONE , 67 , 4 , 0 , 0 , C_XPOST },
768
775
{ASTP , C_PAIR , C_NONE , C_NONE , C_UOREG4K , C_NONE , 76 , 8 , 0 , 0 , 0 },
769
776
{ASTP , C_PAIR , C_NONE , C_NONE , C_NOREG4K , C_NONE , 76 , 8 , 0 , 0 , 0 },
770
- {ASTP , C_PAIR , C_NONE , C_NONE , C_LOREG , C_NONE , 77 , 12 , 0 , LTO , 0 },
777
+ {ASTP , C_PAIR , C_NONE , C_NONE , C_LOREG , C_NONE , 77 , 12 , 0 , 0 , 0 },
778
+ {ASTP , C_PAIR , C_NONE , C_NONE , C_LOREGPOOL , C_NONE , 77 , 12 , 0 , LTO , 0 },
771
779
{ASTP , C_PAIR , C_NONE , C_NONE , C_ADDR , C_NONE , 87 , 12 , 0 , 0 , 0 },
772
780
773
781
// differ from LDP/STP for C_NSAUTO_4/C_PSAUTO_4/C_NSOREG_4/C_PSOREG_4
774
782
{ALDPW , C_NSAUTO_4 , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , REGSP , 0 , 0 },
775
783
{ALDPW , C_PSAUTO_4 , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , REGSP , 0 , 0 },
776
784
{ALDPW , C_UAUTO4K , C_NONE , C_NONE , C_PAIR , C_NONE , 74 , 8 , REGSP , 0 , 0 },
777
785
{ALDPW , C_NAUTO4K , C_NONE , C_NONE , C_PAIR , C_NONE , 74 , 8 , REGSP , 0 , 0 },
778
- {ALDPW , C_LAUTO , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , REGSP , LFROM , 0 },
786
+ {ALDPW , C_LAUTO , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , REGSP , 0 , 0 },
787
+ {ALDPW , C_LAUTOPOOL , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , REGSP , LFROM , 0 },
779
788
{ALDPW , C_NSOREG_4 , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , 0 , 0 , 0 },
780
789
{ALDPW , C_NSOREG_4 , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , 0 , 0 , C_XPRE },
781
790
{ALDPW , C_NSOREG_4 , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , 0 , 0 , C_XPOST },
@@ -784,14 +793,16 @@ var optab = []Optab{
784
793
{ALDPW , C_PSOREG_4 , C_NONE , C_NONE , C_PAIR , C_NONE , 66 , 4 , 0 , 0 , C_XPOST },
785
794
{ALDPW , C_UOREG4K , C_NONE , C_NONE , C_PAIR , C_NONE , 74 , 8 , 0 , 0 , 0 },
786
795
{ALDPW , C_NOREG4K , C_NONE , C_NONE , C_PAIR , C_NONE , 74 , 8 , 0 , 0 , 0 },
787
- {ALDPW , C_LOREG , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , 0 , LFROM , 0 },
796
+ {ALDPW , C_LOREG , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , 0 , 0 , 0 },
797
+ {ALDPW , C_LOREGPOOL , C_NONE , C_NONE , C_PAIR , C_NONE , 75 , 12 , 0 , LFROM , 0 },
788
798
{ALDPW , C_ADDR , C_NONE , C_NONE , C_PAIR , C_NONE , 88 , 12 , 0 , 0 , 0 },
789
799
790
800
{ASTPW , C_PAIR , C_NONE , C_NONE , C_NSAUTO_4 , C_NONE , 67 , 4 , REGSP , 0 , 0 },
791
801
{ASTPW , C_PAIR , C_NONE , C_NONE , C_PSAUTO_4 , C_NONE , 67 , 4 , REGSP , 0 , 0 },
792
802
{ASTPW , C_PAIR , C_NONE , C_NONE , C_UAUTO4K , C_NONE , 76 , 8 , REGSP , 0 , 0 },
793
803
{ASTPW , C_PAIR , C_NONE , C_NONE , C_NAUTO4K , C_NONE , 76 , 8 , REGSP , 0 , 0 },
794
- {ASTPW , C_PAIR , C_NONE , C_NONE , C_LAUTO , C_NONE , 77 , 12 , REGSP , LTO , 0 },
804
+ {ASTPW , C_PAIR , C_NONE , C_NONE , C_LAUTO , C_NONE , 77 , 12 , REGSP , 0 , 0 },
805
+ {ASTPW , C_PAIR , C_NONE , C_NONE , C_LAUTOPOOL , C_NONE , 77 , 12 , REGSP , LTO , 0 },
795
806
{ASTPW , C_PAIR , C_NONE , C_NONE , C_NSOREG_4 , C_NONE , 67 , 4 , 0 , 0 , 0 },
796
807
{ASTPW , C_PAIR , C_NONE , C_NONE , C_NSOREG_4 , C_NONE , 67 , 4 , 0 , 0 , C_XPRE },
797
808
{ASTPW , C_PAIR , C_NONE , C_NONE , C_NSOREG_4 , C_NONE , 67 , 4 , 0 , 0 , C_XPOST },
@@ -800,7 +811,8 @@ var optab = []Optab{
800
811
{ASTPW , C_PAIR , C_NONE , C_NONE , C_PSOREG_4 , C_NONE , 67 , 4 , 0 , 0 , C_XPOST },
801
812
{ASTPW , C_PAIR , C_NONE , C_NONE , C_UOREG4K , C_NONE , 76 , 8 , 0 , 0 , 0 },
802
813
{ASTPW , C_PAIR , C_NONE , C_NONE , C_NOREG4K , C_NONE , 76 , 8 , 0 , 0 , 0 },
803
- {ASTPW , C_PAIR , C_NONE , C_NONE , C_LOREG , C_NONE , 77 , 12 , 0 , LTO , 0 },
814
+ {ASTPW , C_PAIR , C_NONE , C_NONE , C_LOREG , C_NONE , 77 , 12 , 0 , 0 , 0 },
815
+ {ASTPW , C_PAIR , C_NONE , C_NONE , C_LOREGPOOL , C_NONE , 77 , 12 , 0 , LTO , 0 },
804
816
{ASTPW , C_PAIR , C_NONE , C_NONE , C_ADDR , C_NONE , 87 , 12 , 0 , 0 , 0 },
805
817
806
818
{ASWPD , C_ZREG , C_NONE , C_NONE , C_ZOREG , C_ZREG , 47 , 4 , 0 , 0 , 0 },
@@ -1479,6 +1491,14 @@ func isNEGop(op obj.As) bool {
1479
1491
return false
1480
1492
}
1481
1493
1494
+ func isLoadStorePairOp (op obj.As ) bool {
1495
+ switch op {
1496
+ case AFLDPQ , AFSTPQ , ALDP , ASTP , ALDPW , ASTPW :
1497
+ return true
1498
+ }
1499
+ return false
1500
+ }
1501
+
1482
1502
func isMOVop (op obj.As ) bool {
1483
1503
switch op {
1484
1504
case AMOVB , AMOVBU , AMOVH , AMOVHU , AMOVW , AMOVWU , AMOVD , AFMOVS , AFMOVD , AFMOVQ :
@@ -1984,6 +2004,33 @@ func (c *ctxt7) loadStoreClass(p *obj.Prog, lsc int, v int64) int {
1984
2004
return lsc
1985
2005
}
1986
2006
2007
+ // loadStorePairClass reclassifies a load or store pair operation based on its offset.
2008
+ func (c * ctxt7 ) loadStorePairClass (p * obj.Prog , lsc int , v int64 ) int {
2009
+ // Avoid reclassification of pre/post-indexed loads and stores.
2010
+ if p .Scond == C_XPRE || p .Scond == C_XPOST {
2011
+ return lsc
2012
+ }
2013
+
2014
+ if cmp (C_NAUTO4K , lsc ) || cmp (C_NOREG4K , lsc ) {
2015
+ return lsc
2016
+ }
2017
+ if cmp (C_UAUTO4K , lsc ) || cmp (C_UOREG4K , lsc ) {
2018
+ return lsc
2019
+ }
2020
+
2021
+ needsPool := true
2022
+ if v >= 0 && v <= 0xffffff {
2023
+ needsPool = false
2024
+ }
2025
+ if needsPool && cmp (C_LAUTO , lsc ) {
2026
+ return C_LAUTOPOOL
2027
+ }
2028
+ if needsPool && cmp (C_LOREG , lsc ) {
2029
+ return C_LOREGPOOL
2030
+ }
2031
+ return lsc
2032
+ }
2033
+
1987
2034
func (c * ctxt7 ) aclass (a * obj.Addr ) int {
1988
2035
switch a .Type {
1989
2036
case obj .TYPE_NONE :
@@ -2212,6 +2259,10 @@ func (c *ctxt7) oplook(p *obj.Prog) *Optab {
2212
2259
// More specific classification of large offset loads and stores.
2213
2260
a1 = c .loadStoreClass (p , a1 , c .instoffset )
2214
2261
}
2262
+ if isLoadStorePairOp (p .As ) && (cmp (C_LAUTO , a1 ) || cmp (C_LOREG , a1 )) {
2263
+ // More specific classification of large offset loads and stores.
2264
+ a1 = c .loadStorePairClass (p , a1 , c .instoffset )
2265
+ }
2215
2266
}
2216
2267
p .From .Class = int8 (a1 )
2217
2268
}
@@ -2238,6 +2289,10 @@ func (c *ctxt7) oplook(p *obj.Prog) *Optab {
2238
2289
// More specific classification of large offset loads and stores.
2239
2290
a4 = c .loadStoreClass (p , a4 , c .instoffset )
2240
2291
}
2292
+ if isLoadStorePairOp (p .As ) && (cmp (C_LAUTO , a4 ) || cmp (C_LOREG , a4 )) {
2293
+ // More specific classification of large offset loads and stores.
2294
+ a4 = c .loadStorePairClass (p , a4 , c .instoffset )
2295
+ }
2241
2296
}
2242
2297
p .To .Class = int8 (a4 )
2243
2298
}
@@ -4035,12 +4090,12 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
4035
4090
break
4036
4091
4037
4092
storeusepool:
4038
- if r == REGTMP || p .From .Reg == REGTMP {
4039
- c .ctxt .Diag ("REGTMP used in large offset store: %v" , p )
4040
- }
4041
4093
if p .Pool == nil {
4042
4094
c .ctxt .Diag ("%v: constant is not in pool" , p )
4043
4095
}
4096
+ if r == REGTMP || p .From .Reg == REGTMP {
4097
+ c .ctxt .Diag ("REGTMP used in large offset store: %v" , p )
4098
+ }
4044
4099
o1 = c .omovlit (AMOVD , p , & p .To , REGTMP )
4045
4100
o2 = c .olsxrr (p , int32 (c .opstrr (p , p .As , false )), int (p .From .Reg ), int (r ), REGTMP )
4046
4101
@@ -4831,6 +4886,11 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
4831
4886
o2 = c .opldpstp (p , o , 0 , REGTMP , rt1 , rt2 , 1 )
4832
4887
4833
4888
case 75 :
4889
+ // If offset L fits in a 24 bit unsigned immediate:
4890
+ // add $lo, R, Rtmp
4891
+ // add $hi, Rtmp, Rtmp
4892
+ // ldr (Rtmp), R
4893
+ // Otherwise, use constant pool:
4834
4894
// mov $L, Rtmp (from constant pool)
4835
4895
// add Rtmp, R, Rtmp
4836
4896
// ldp (Rtmp), (R1, R2)
@@ -4844,6 +4904,31 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
4844
4904
if rf == obj .REG_NONE {
4845
4905
c .ctxt .Diag ("invalid ldp source: %v" , p )
4846
4906
}
4907
+
4908
+ v := c .regoff (& p .From )
4909
+ if v >= - 4095 && v <= 4095 {
4910
+ c .ctxt .Diag ("%v: bad type for offset %d (should be add/sub+ldp)" , p , v )
4911
+ }
4912
+
4913
+ hi , lo , err := splitImm24uScaled (v , 0 )
4914
+ if err != nil {
4915
+ goto loadpairusepool
4916
+ }
4917
+ if p .Pool != nil {
4918
+ c .ctxt .Diag ("%v: unused constant in pool (%v)\n " , p , v )
4919
+ }
4920
+ o1 = c .oaddi (p , AADD , lo , REGTMP , int16 (rf ))
4921
+ o2 = c .oaddi (p , AADD , hi , REGTMP , REGTMP )
4922
+ o3 = c .opldpstp (p , o , 0 , REGTMP , rt1 , rt2 , 1 )
4923
+ break
4924
+
4925
+ loadpairusepool:
4926
+ if p .Pool == nil {
4927
+ c .ctxt .Diag ("%v: constant is not in pool" , p )
4928
+ }
4929
+ if rf == REGTMP || p .From .Reg == REGTMP {
4930
+ c .ctxt .Diag ("REGTMP used in large offset load: %v" , p )
4931
+ }
4847
4932
o1 = c .omovlit (AMOVD , p , & p .From , REGTMP )
4848
4933
o2 = c .opxrrr (p , AADD , REGTMP , rf , REGTMP , false )
4849
4934
o3 = c .opldpstp (p , o , 0 , REGTMP , rt1 , rt2 , 1 )
@@ -4866,6 +4951,11 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
4866
4951
o2 = c .opldpstp (p , o , 0 , REGTMP , rf1 , rf2 , 0 )
4867
4952
4868
4953
case 77 :
4954
+ // If offset L fits in a 24 bit unsigned immediate:
4955
+ // add $lo, R, Rtmp
4956
+ // add $hi, Rtmp, Rtmp
4957
+ // stp (R1, R2), (Rtmp)
4958
+ // Otherwise, use constant pool:
4869
4959
// mov $L, Rtmp (from constant pool)
4870
4960
// add Rtmp, R, Rtmp
4871
4961
// stp (R1, R2), (Rtmp)
@@ -4879,6 +4969,31 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
4879
4969
if rt == obj .REG_NONE {
4880
4970
c .ctxt .Diag ("invalid stp destination: %v" , p )
4881
4971
}
4972
+
4973
+ v := c .regoff (& p .To )
4974
+ if v >= - 4095 && v <= 4095 {
4975
+ c .ctxt .Diag ("%v: bad type for offset %d (should be add/sub+stp)" , p , v )
4976
+ }
4977
+
4978
+ hi , lo , err := splitImm24uScaled (v , 0 )
4979
+ if err != nil {
4980
+ goto storepairusepool
4981
+ }
4982
+ if p .Pool != nil {
4983
+ c .ctxt .Diag ("%v: unused constant in pool (%v)\n " , p , v )
4984
+ }
4985
+ o1 = c .oaddi (p , AADD , lo , REGTMP , int16 (rt ))
4986
+ o2 = c .oaddi (p , AADD , hi , REGTMP , REGTMP )
4987
+ o3 = c .opldpstp (p , o , 0 , REGTMP , rf1 , rf2 , 0 )
4988
+ break
4989
+
4990
+ storepairusepool:
4991
+ if p .Pool == nil {
4992
+ c .ctxt .Diag ("%v: constant is not in pool" , p )
4993
+ }
4994
+ if rt == REGTMP || p .From .Reg == REGTMP {
4995
+ c .ctxt .Diag ("REGTMP used in large offset store: %v" , p )
4996
+ }
4882
4997
o1 = c .omovlit (AMOVD , p , & p .To , REGTMP )
4883
4998
o2 = c .opxrrr (p , AADD , REGTMP , rt , REGTMP , false )
4884
4999
o3 = c .opldpstp (p , o , 0 , REGTMP , rf1 , rf2 , 0 )
0 commit comments