@@ -88,20 +88,26 @@ var optab = []Optab{
88
88
{AADD , C_REG , C_NONE , C_REG , 1 , 4 , 0 , 0 , 0 },
89
89
{AAND , C_REG , C_REG , C_REG , 1 , 4 , 0 , 0 , 0 },
90
90
{AAND , C_REG , C_NONE , C_REG , 1 , 4 , 0 , 0 , 0 },
91
+ {AORR , C_REG , C_REG , C_REG , 1 , 4 , 0 , 0 , 0 },
92
+ {AORR , C_REG , C_NONE , C_REG , 1 , 4 , 0 , 0 , 0 },
91
93
{AMOVW , C_REG , C_NONE , C_REG , 1 , 4 , 0 , 0 , 0 },
92
94
{AMVN , C_REG , C_NONE , C_REG , 1 , 4 , 0 , 0 , 0 },
93
95
{ACMP , C_REG , C_REG , C_NONE , 1 , 4 , 0 , 0 , 0 },
94
96
{AADD , C_RCON , C_REG , C_REG , 2 , 4 , 0 , 0 , 0 },
95
97
{AADD , C_RCON , C_NONE , C_REG , 2 , 4 , 0 , 0 , 0 },
96
98
{AAND , C_RCON , C_REG , C_REG , 2 , 4 , 0 , 0 , 0 },
97
99
{AAND , C_RCON , C_NONE , C_REG , 2 , 4 , 0 , 0 , 0 },
100
+ {AORR , C_RCON , C_REG , C_REG , 2 , 4 , 0 , 0 , 0 },
101
+ {AORR , C_RCON , C_NONE , C_REG , 2 , 4 , 0 , 0 , 0 },
98
102
{AMOVW , C_RCON , C_NONE , C_REG , 2 , 4 , 0 , 0 , 0 },
99
103
{AMVN , C_RCON , C_NONE , C_REG , 2 , 4 , 0 , 0 , 0 },
100
104
{ACMP , C_RCON , C_REG , C_NONE , 2 , 4 , 0 , 0 , 0 },
101
105
{AADD , C_SHIFT , C_REG , C_REG , 3 , 4 , 0 , 0 , 0 },
102
106
{AADD , C_SHIFT , C_NONE , C_REG , 3 , 4 , 0 , 0 , 0 },
103
107
{AAND , C_SHIFT , C_REG , C_REG , 3 , 4 , 0 , 0 , 0 },
104
108
{AAND , C_SHIFT , C_NONE , C_REG , 3 , 4 , 0 , 0 , 0 },
109
+ {AORR , C_SHIFT , C_REG , C_REG , 3 , 4 , 0 , 0 , 0 },
110
+ {AORR , C_SHIFT , C_NONE , C_REG , 3 , 4 , 0 , 0 , 0 },
105
111
{AMVN , C_SHIFT , C_NONE , C_REG , 3 , 4 , 0 , 0 , 0 },
106
112
{ACMP , C_SHIFT , C_REG , C_NONE , 3 , 4 , 0 , 0 , 0 },
107
113
{AMOVW , C_RACON , C_NONE , C_REG , 4 , 4 , REGSP , 0 , 0 },
@@ -136,20 +142,27 @@ var optab = []Optab{
136
142
{AADD , C_NCON , C_NONE , C_REG , 13 , 8 , 0 , 0 , 0 },
137
143
{AAND , C_NCON , C_REG , C_REG , 13 , 8 , 0 , 0 , 0 },
138
144
{AAND , C_NCON , C_NONE , C_REG , 13 , 8 , 0 , 0 , 0 },
145
+ {AORR , C_NCON , C_REG , C_REG , 13 , 8 , 0 , 0 , 0 },
146
+ {AORR , C_NCON , C_NONE , C_REG , 13 , 8 , 0 , 0 , 0 },
139
147
{AMVN , C_NCON , C_NONE , C_REG , 13 , 8 , 0 , 0 , 0 },
140
148
{ACMP , C_NCON , C_REG , C_NONE , 13 , 8 , 0 , 0 , 0 },
141
149
{AADD , C_SCON , C_REG , C_REG , 13 , 8 , 0 , 0 , 0 },
142
150
{AADD , C_SCON , C_NONE , C_REG , 13 , 8 , 0 , 0 , 0 },
143
151
{AAND , C_SCON , C_REG , C_REG , 13 , 8 , 0 , 0 , 0 },
144
152
{AAND , C_SCON , C_NONE , C_REG , 13 , 8 , 0 , 0 , 0 },
153
+ {AORR , C_SCON , C_REG , C_REG , 13 , 8 , 0 , 0 , 0 },
154
+ {AORR , C_SCON , C_NONE , C_REG , 13 , 8 , 0 , 0 , 0 },
145
155
{AMVN , C_SCON , C_NONE , C_REG , 13 , 8 , 0 , 0 , 0 },
146
156
{ACMP , C_SCON , C_REG , C_NONE , 13 , 8 , 0 , 0 , 0 },
147
- {AADD , C_RCON2 , C_REG , C_REG , 106 , 8 , 0 , 0 , 0 },
148
- // TODO: RCON2: how to do AND and BIC?
157
+ {AADD , C_RCON2A , C_REG , C_REG , 106 , 8 , 0 , 0 , 0 },
158
+ {AORR , C_RCON2A , C_REG , C_REG , 106 , 8 , 0 , 0 , 0 },
159
+ {AADD , C_RCON2S , C_REG , C_REG , 107 , 8 , 0 , 0 , 0 },
149
160
{AADD , C_LCON , C_REG , C_REG , 13 , 8 , 0 , LFROM , 0 },
150
161
{AADD , C_LCON , C_NONE , C_REG , 13 , 8 , 0 , LFROM , 0 },
151
162
{AAND , C_LCON , C_REG , C_REG , 13 , 8 , 0 , LFROM , 0 },
152
163
{AAND , C_LCON , C_NONE , C_REG , 13 , 8 , 0 , LFROM , 0 },
164
+ {AORR , C_LCON , C_REG , C_REG , 13 , 8 , 0 , LFROM , 0 },
165
+ {AORR , C_LCON , C_NONE , C_REG , 13 , 8 , 0 , LFROM , 0 },
153
166
{AMVN , C_LCON , C_NONE , C_REG , 13 , 8 , 0 , LFROM , 0 },
154
167
{ACMP , C_LCON , C_REG , C_NONE , 13 , 8 , 0 , LFROM , 0 },
155
168
{AMOVB , C_REG , C_NONE , C_REG , 1 , 4 , 0 , 0 , 0 },
@@ -970,10 +983,10 @@ func immrot(v uint32) int32 {
970
983
return 0
971
984
}
972
985
973
- // immrot2 returns bits encoding the immediate constant fields of two instructions,
986
+ // immrot2a returns bits encoding the immediate constant fields of two instructions,
974
987
// such that the encoded constants x, y satisfy x|y==v, x&y==0.
975
988
// Returns 0,0 if no such decomposition of v exists.
976
- func immrot2 (v uint32 ) (uint32 , uint32 ) {
989
+ func immrot2a (v uint32 ) (uint32 , uint32 ) {
977
990
for i := uint (1 ); i < 32 ; i ++ {
978
991
m := uint32 (1 << i - 1 )
979
992
if x , y := immrot (v & m ), immrot (v &^m ); x != 0 && y != 0 {
@@ -985,6 +998,32 @@ func immrot2(v uint32) (uint32, uint32) {
985
998
return 0 , 0
986
999
}
987
1000
1001
+ // immrot2s returns bits encoding the immediate constant fields of two instructions,
1002
+ // such that the encoded constants y, x satisfy y-x==v, y&x==0.
1003
+ // Returns 0,0 if no such decomposition of v exists.
1004
+ func immrot2s (v uint32 ) (uint32 , uint32 ) {
1005
+ if immrot (v ) == 0 {
1006
+ return v , 0
1007
+ }
1008
+ // suppose v in the form of {leading 00, upper effective bits, lower 8 effective bits, trailing 00}
1009
+ // omit trailing 00
1010
+ var i uint32
1011
+ for i = 2 ; i < 32 ; i += 2 {
1012
+ if v & (1 << i - 1 ) != 0 {
1013
+ break
1014
+ }
1015
+ }
1016
+ // i must be <= 24, then adjust i just above lower 8 effective bits of v
1017
+ i += 6
1018
+ // let x = {the complement of lower 8 effective bits, trailing 00}, y = x + v
1019
+ x := 1 << i - v & (1 << i - 1 )
1020
+ y := v + x
1021
+ if y , x = uint32 (immrot (y )), uint32 (immrot (x )); y != 0 && x != 0 {
1022
+ return y , x
1023
+ }
1024
+ return 0 , 0
1025
+ }
1026
+
988
1027
func immaddr (v int32 ) int32 {
989
1028
if v >= 0 && v <= 0xfff {
990
1029
return v & 0xfff | 1 << 24 | 1 << 23 /* pre indexing */ /* pre indexing, up */
@@ -1159,8 +1198,11 @@ func (c *ctxt5) aclass(a *obj.Addr) int {
1159
1198
if uint32 (c .instoffset ) <= 0xffff && objabi .GOARM == 7 {
1160
1199
return C_SCON
1161
1200
}
1162
- if x , y := immrot2 (uint32 (c .instoffset )); x != 0 && y != 0 {
1163
- return C_RCON2
1201
+ if x , y := immrot2a (uint32 (c .instoffset )); x != 0 && y != 0 {
1202
+ return C_RCON2A
1203
+ }
1204
+ if y , x := immrot2s (uint32 (c .instoffset )); x != 0 && y != 0 {
1205
+ return C_RCON2S
1164
1206
}
1165
1207
return C_LCON
1166
1208
@@ -1226,13 +1268,12 @@ func (c *ctxt5) oplook(p *obj.Prog) *Optab {
1226
1268
a2 = C_REG
1227
1269
}
1228
1270
1229
- // If Scond != 0, we must use the constant pool instead of
1230
- // splitting the instruction in two. The most common reason is
1231
- // .S (flag updating) instructions. There may be others.
1232
- if a1 == C_RCON2 && p .Scond != 0 {
1271
+ // If current instruction has a .S suffix (flags update),
1272
+ // we must use the constant pool instead of splitting it.
1273
+ if (a1 == C_RCON2A || a1 == C_RCON2S ) && p .Scond & C_SBIT != 0 {
1233
1274
a1 = C_LCON
1234
1275
}
1235
- if a3 == C_RCON2 && p .Scond != 0 {
1276
+ if ( a3 == C_RCON2A || a3 == C_RCON2S ) && p .Scond & C_SBIT != 0 {
1236
1277
a3 = C_LCON
1237
1278
}
1238
1279
@@ -1266,7 +1307,7 @@ func cmp(a int, b int) bool {
1266
1307
}
1267
1308
switch a {
1268
1309
case C_LCON :
1269
- if b == C_RCON || b == C_NCON || b == C_SCON || b == C_RCON2 {
1310
+ if b == C_RCON || b == C_NCON || b == C_SCON || b == C_RCON2A || b == C_RCON2S {
1270
1311
return true
1271
1312
}
1272
1313
@@ -1406,16 +1447,14 @@ func buildop(ctxt *obj.Link) {
1406
1447
log .Fatalf ("bad code" )
1407
1448
1408
1449
case AADD :
1409
- opset (AEOR , r0 )
1410
1450
opset (ASUB , r0 )
1411
1451
opset (ARSB , r0 )
1412
1452
opset (AADC , r0 )
1413
1453
opset (ASBC , r0 )
1414
1454
opset (ARSC , r0 )
1415
- opset (AORR , r0 )
1416
1455
1417
- case AAND :
1418
- opset (AAND , r0 )
1456
+ case AORR :
1457
+ opset (AEOR , r0 )
1419
1458
opset (ABIC , r0 )
1420
1459
1421
1460
case ACMP :
@@ -1541,6 +1580,7 @@ func buildop(ctxt *obj.Link) {
1541
1580
ALDREXD ,
1542
1581
ASTREXD ,
1543
1582
APLD ,
1583
+ AAND ,
1544
1584
obj .AUNDEF ,
1545
1585
obj .AFUNCDATA ,
1546
1586
obj .APCDATA ,
@@ -1609,11 +1649,11 @@ func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
1609
1649
c .aclass (& p .From )
1610
1650
r := int (p .Reg )
1611
1651
rt := int (p .To .Reg )
1612
- x , y := immrot2 (uint32 (c .instoffset ))
1652
+ x , y := immrot2a (uint32 (c .instoffset ))
1613
1653
var as2 obj.As
1614
1654
switch p .As {
1615
- case AADD , ASUB , AORR , AEOR :
1616
- as2 = p .As // ADD, SUB, ORR, EOR
1655
+ case AADD , ASUB , AORR , AEOR , ABIC :
1656
+ as2 = p .As // ADD, SUB, ORR, EOR, BIC
1617
1657
case ARSB :
1618
1658
as2 = AADD // RSB -> RSB/ADD pair
1619
1659
case AADC :
@@ -1632,6 +1672,35 @@ func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
1632
1672
o1 |= x
1633
1673
o2 |= y
1634
1674
1675
+ case 107 : /* op $I,R,R where I can be decomposed into 2 immediates */
1676
+ c .aclass (& p .From )
1677
+ r := int (p .Reg )
1678
+ rt := int (p .To .Reg )
1679
+ y , x := immrot2s (uint32 (c .instoffset ))
1680
+ var as2 obj.As
1681
+ switch p .As {
1682
+ case AADD :
1683
+ as2 = ASUB // ADD -> ADD/SUB pair
1684
+ case ASUB :
1685
+ as2 = AADD // SUB -> SUB/ADD pair
1686
+ case ARSB :
1687
+ as2 = ASUB // RSB -> RSB/SUB pair
1688
+ case AADC :
1689
+ as2 = ASUB // ADC -> ADC/SUB pair
1690
+ case ASBC :
1691
+ as2 = AADD // SBC -> SBC/ADD pair
1692
+ case ARSC :
1693
+ as2 = ASUB // RSC -> RSC/SUB pair
1694
+ default :
1695
+ c .ctxt .Diag ("unknown second op for %v" , p )
1696
+ }
1697
+ o1 = c .oprrr (p , p .As , int (p .Scond ))
1698
+ o2 = c .oprrr (p , as2 , int (p .Scond ))
1699
+ o1 |= (uint32 (r )& 15 )<< 16 | (uint32 (rt )& 15 )<< 12
1700
+ o2 |= (uint32 (rt )& 15 )<< 16 | (uint32 (rt )& 15 )<< 12
1701
+ o1 |= y
1702
+ o2 |= x
1703
+
1635
1704
case 3 : /* add R<<[IR],[R],R */
1636
1705
o1 = c .mov (p )
1637
1706
0 commit comments