@@ -164,6 +164,10 @@ func OPBIT(x uint32) uint32 {
164
164
return 1 << 30 | 0 << 29 | 0xD6 << 21 | 0 << 16 | x << 10
165
165
}
166
166
167
+ func MOVCONST (d int64 , s int , rt int ) uint32 {
168
+ return uint32 (((d >> uint (s * 16 ))& 0xFFFF )<< 5 ) | uint32 (s )& 3 << 21 | uint32 (rt & 31 )
169
+ }
170
+
167
171
const (
168
172
LFROM = 1 << 0
169
173
LTO = 1 << 1
@@ -272,12 +276,10 @@ var optab = []Optab{
272
276
/* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */
273
277
{AMOVW , C_MOVCON , C_NONE , C_NONE , C_REG , 32 , 4 , 0 , 0 , 0 },
274
278
{AMOVD , C_MOVCON , C_NONE , C_NONE , C_REG , 32 , 4 , 0 , 0 , 0 },
275
-
276
- // TODO: these don't work properly.
277
- // { AMOVW, C_ADDCON, C_NONE, C_REG, 2, 4, 0 , 0},
278
- // { AMOVD, C_ADDCON, C_NONE, C_REG, 2, 4, 0 , 0},
279
279
{AMOVW , C_BITCON , C_NONE , C_NONE , C_REG , 32 , 4 , 0 , 0 , 0 },
280
280
{AMOVD , C_BITCON , C_NONE , C_NONE , C_REG , 32 , 4 , 0 , 0 , 0 },
281
+ {AMOVW , C_LCON , C_NONE , C_NONE , C_REG , 12 , 4 , 0 , LFROM , 0 },
282
+ {AMOVD , C_VCON , C_NONE , C_NONE , C_REG , 12 , 4 , 0 , LFROM , 0 },
281
283
282
284
{AMOVK , C_VCON , C_NONE , C_NONE , C_REG , 33 , 4 , 0 , 0 , 0 },
283
285
{AMOVD , C_AACON , C_NONE , C_NONE , C_REG , 4 , 4 , REGFROM , 0 , 0 },
@@ -318,9 +320,7 @@ var optab = []Optab{
318
320
{AWORD , C_NONE , C_NONE , C_NONE , C_LCON , 14 , 4 , 0 , 0 , 0 },
319
321
{AWORD , C_NONE , C_NONE , C_NONE , C_LEXT , 14 , 4 , 0 , 0 , 0 },
320
322
{AWORD , C_NONE , C_NONE , C_NONE , C_ADDR , 14 , 4 , 0 , 0 , 0 },
321
- {AMOVW , C_VCON , C_NONE , C_NONE , C_REG , 12 , 4 , 0 , LFROM , 0 },
322
323
{AMOVW , C_VCONADDR , C_NONE , C_NONE , C_REG , 68 , 8 , 0 , 0 , 0 },
323
- {AMOVD , C_VCON , C_NONE , C_NONE , C_REG , 12 , 4 , 0 , LFROM , 0 },
324
324
{AMOVD , C_VCONADDR , C_NONE , C_NONE , C_REG , 68 , 8 , 0 , 0 , 0 },
325
325
{AMOVB , C_REG , C_NONE , C_NONE , C_ADDR , 64 , 12 , 0 , 0 , 0 },
326
326
{AMOVBU , C_REG , C_NONE , C_NONE , C_ADDR , 64 , 12 , 0 , 0 , 0 },
@@ -1105,6 +1105,23 @@ func isSTXPop(op obj.As) bool {
1105
1105
return false
1106
1106
}
1107
1107
1108
+ func isANDWop (op obj.As ) bool {
1109
+ switch op {
1110
+ case AANDW , AORRW , AEORW , AANDSW , ATSTW ,
1111
+ ABICW , AEONW , AORNW , ABICSW :
1112
+ return true
1113
+ }
1114
+ return false
1115
+ }
1116
+
1117
+ func isADDWop (op obj.As ) bool {
1118
+ switch op {
1119
+ case AADDW , AADDSW , ASUBW , ASUBSW , ACMNW , ACMPW :
1120
+ return true
1121
+ }
1122
+ return false
1123
+ }
1124
+
1108
1125
func isRegShiftOrExt (a * obj.Addr ) bool {
1109
1126
return (a .Index - obj .RBaseARM64 )& REG_EXT != 0 || (a .Index - obj .RBaseARM64 )& REG_LSL != 0
1110
1127
}
@@ -1411,6 +1428,52 @@ func rclass(r int16) int {
1411
1428
return C_GOK
1412
1429
}
1413
1430
1431
+ // con32class reclassifies the constant of 32-bit instruction. Becuase the constant type is 32-bit,
1432
+ // but saved in Offset which type is int64, con32class treats it as uint32 type and reclassifies it.
1433
+ func (c * ctxt7 ) con32class (a * obj.Addr ) int {
1434
+ v := uint32 (a .Offset )
1435
+ if v == 0 {
1436
+ return C_ZCON
1437
+ }
1438
+ if isaddcon (int64 (v )) {
1439
+ if v <= 0xFFF {
1440
+ if isbitcon (uint64 (v )) {
1441
+ return C_ABCON0
1442
+ }
1443
+ return C_ADDCON0
1444
+ }
1445
+ if isbitcon (uint64 (v )) {
1446
+ return C_ABCON
1447
+ }
1448
+ return C_ADDCON
1449
+ }
1450
+
1451
+ t := movcon (int64 (v ))
1452
+ if t >= 0 {
1453
+ if isbitcon (uint64 (v )) {
1454
+ return C_MBCON
1455
+ }
1456
+ return C_MOVCON
1457
+ }
1458
+
1459
+ t = movcon (int64 (^ v ))
1460
+ if t >= 0 {
1461
+ if isbitcon (uint64 (v )) {
1462
+ return C_MBCON
1463
+ }
1464
+ return C_MOVCON
1465
+ }
1466
+
1467
+ if isbitcon (uint64 (v )) {
1468
+ return C_BITCON
1469
+ }
1470
+
1471
+ if 0 <= v && v <= 0xffffff {
1472
+ return C_ADDCON2
1473
+ }
1474
+ return C_LCON
1475
+ }
1476
+
1414
1477
func (c * ctxt7 ) aclass (a * obj.Addr ) int {
1415
1478
switch a .Type {
1416
1479
case obj .TYPE_NONE :
@@ -1517,6 +1580,12 @@ func (c *ctxt7) aclass(a *obj.Addr) int {
1517
1580
if isbitcon (uint64 (v )) {
1518
1581
return C_ABCON
1519
1582
}
1583
+ if movcon (v ) >= 0 {
1584
+ return C_AMCON
1585
+ }
1586
+ if movcon (^ v ) >= 0 {
1587
+ return C_AMCON
1588
+ }
1520
1589
return C_ADDCON
1521
1590
}
1522
1591
@@ -1609,6 +1678,34 @@ func (c *ctxt7) oplook(p *obj.Prog) *Optab {
1609
1678
}
1610
1679
a1 = a0 + 1
1611
1680
p .From .Class = int8 (a1 )
1681
+ // more specific classification of 32-bit integers
1682
+ if p .From .Type == obj .TYPE_CONST && p .From .Name == obj .NAME_NONE {
1683
+ if p .As == AMOVW || isADDWop (p .As ) {
1684
+ ra0 := c .con32class (& p .From )
1685
+ // do not break C_ADDCON2 when S bit is set
1686
+ if (p .As == AADDSW || p .As == ASUBSW ) && ra0 == C_ADDCON2 {
1687
+ ra0 = C_LCON
1688
+ }
1689
+ a1 = ra0 + 1
1690
+ p .From .Class = int8 (a1 )
1691
+ }
1692
+ if isANDWop (p .As ) {
1693
+ switch p .As {
1694
+ case AANDW , AORRW , AEORW , AANDSW , ATSTW :
1695
+ // For 32-bit logical instruction with constant,
1696
+ // rewrite the high 32-bit to be a copy of the low
1697
+ // 32-bit, so that the BITCON test can be shared
1698
+ // for both 32-bit and 64-bit.
1699
+ if a0 == C_BITCON {
1700
+ break
1701
+ }
1702
+ fallthrough
1703
+ default :
1704
+ a1 = c .con32class (& p .From ) + 1
1705
+ p .From .Class = int8 (a1 )
1706
+ }
1707
+ }
1708
+ }
1612
1709
}
1613
1710
1614
1711
a1 --
@@ -1679,7 +1776,7 @@ func cmp(a int, b int) bool {
1679
1776
}
1680
1777
1681
1778
case C_ADDCON :
1682
- if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON {
1779
+ if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON || b == C_AMCON {
1683
1780
return true
1684
1781
}
1685
1782
@@ -1689,7 +1786,7 @@ func cmp(a int, b int) bool {
1689
1786
}
1690
1787
1691
1788
case C_MOVCON :
1692
- if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 {
1789
+ if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_AMCON {
1693
1790
return true
1694
1791
}
1695
1792
@@ -1699,7 +1796,7 @@ func cmp(a int, b int) bool {
1699
1796
}
1700
1797
1701
1798
case C_LCON :
1702
- if b == C_ZCON || b == C_BITCON || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_ABCON0 || b == C_MBCON || b == C_MOVCON || b == C_ADDCON2 {
1799
+ if b == C_ZCON || b == C_BITCON || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_ABCON0 || b == C_MBCON || b == C_MOVCON || b == C_ADDCON2 || b == C_AMCON {
1703
1800
return true
1704
1801
}
1705
1802
@@ -3501,8 +3598,8 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
3501
3598
if r == 0 {
3502
3599
r = rt
3503
3600
}
3504
- o1 = c .oaddi (p , int32 (op ), int32 (c .regoff (& p .From )) & 0x000fff , r , rt )
3505
- o2 = c .oaddi (p , int32 (op ), int32 (c .regoff (& p .From )) & 0xfff000 , rt , rt )
3601
+ o1 = c .oaddi (p , int32 (op ), int32 (c .regoff (& p .From ))& 0x000fff , r , rt )
3602
+ o2 = c .oaddi (p , int32 (op ), int32 (c .regoff (& p .From ))& 0xfff000 , rt , rt )
3506
3603
3507
3604
case 50 : /* sys/sysl */
3508
3605
o1 = c .opirr (p , p .As )
@@ -3670,7 +3767,11 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
3670
3767
if p .Reg == REGTMP {
3671
3768
c .ctxt .Diag ("cannot use REGTMP as source: %v\n " , p )
3672
3769
}
3673
- o1 = c .omovconst (AMOVD , p , & p .From , REGTMP )
3770
+ if isADDWop (p .As ) || isANDWop (p .As ) {
3771
+ o1 = c .omovconst (AMOVW , p , & p .From , REGTMP )
3772
+ } else {
3773
+ o1 = c .omovconst (AMOVD , p , & p .From , REGTMP )
3774
+ }
3674
3775
3675
3776
rt := int (p .To .Reg )
3676
3777
if p .To .Type == obj .TYPE_NONE {
@@ -6195,31 +6296,37 @@ func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint3
6195
6296
return o1
6196
6297
}
6197
6298
6198
- r := 32
6199
- if as == AMOVD {
6200
- r = 64
6299
+ if as == AMOVW {
6300
+ d := uint32 (a .Offset )
6301
+ s := movcon (int64 (d ))
6302
+ if s < 0 || 16 * s >= 32 {
6303
+ d = ^ d
6304
+ s = movcon (int64 (d ))
6305
+ if s < 0 || 16 * s >= 32 {
6306
+ c .ctxt .Diag ("impossible 32-bit move wide: %#x\n %v" , uint32 (a .Offset ), p )
6307
+ }
6308
+ o1 = c .opirr (p , AMOVNW )
6309
+ } else {
6310
+ o1 = c .opirr (p , AMOVZW )
6311
+ }
6312
+ o1 |= MOVCONST (int64 (d ), s , rt )
6201
6313
}
6202
- d := a . Offset
6203
- s := movcon ( d )
6204
- if s < 0 || s >= r {
6205
- d = ^ d
6206
- s = movcon ( d )
6207
- if s < 0 || s >= r {
6208
- c . ctxt . Diag ( "impossible move wide: %#x \n %v" , uint64 ( a . Offset ), p )
6209
- }
6210
- if as == AMOVD {
6314
+ if as == AMOVD {
6315
+ d := a . Offset
6316
+ s := movcon ( d )
6317
+ if s < 0 || 16 * s >= 64 {
6318
+ d = ^ d
6319
+ s = movcon ( d )
6320
+ if s < 0 || 16 * s >= 64 {
6321
+ c . ctxt . Diag ( "impossible 64-bit move wide: %#x \n %v" , uint64 ( a . Offset ), p )
6322
+ }
6211
6323
o1 = c .opirr (p , AMOVN )
6212
6324
} else {
6213
- o1 = c .opirr (p , AMOVNW )
6214
- }
6215
- } else {
6216
- if as == AMOVD {
6217
6325
o1 = c .opirr (p , AMOVZ )
6218
- } else {
6219
- o1 = c .opirr (p , AMOVZW )
6220
6326
}
6327
+ o1 |= MOVCONST (d , s , rt )
6221
6328
}
6222
- o1 |= uint32 (((( d >> uint ( s * 16 )) & 0xFFFF ) << 5 ) | int64 (( uint32 ( s ) & 3 ) << 21 ) | int64 ( rt & 31 ))
6329
+
6223
6330
return o1
6224
6331
}
6225
6332
0 commit comments