@@ -72,15 +72,20 @@ type Optab struct {
72
72
flag uint8
73
73
}
74
74
75
+ const (
76
+ // Optab.flag
77
+ NOTUSETMP = 1 << iota // p expands to multiple instructions, but does NOT use REGTMP
78
+ )
79
+
75
80
var optab = []Optab {
76
81
{obj .ATEXT , C_LEXT , C_NONE , C_TEXTSIZE , 0 , 0 , 0 , sys .MIPS64 , 0 },
77
82
{obj .ATEXT , C_ADDR , C_NONE , C_TEXTSIZE , 0 , 0 , 0 , 0 , 0 },
78
83
79
84
{AMOVW , C_REG , C_NONE , C_REG , 1 , 4 , 0 , 0 , 0 },
80
85
{AMOVV , C_REG , C_NONE , C_REG , 1 , 4 , 0 , sys .MIPS64 , 0 },
81
- {AMOVB , C_REG , C_NONE , C_REG , 12 , 8 , 0 , 0 , 0 },
86
+ {AMOVB , C_REG , C_NONE , C_REG , 12 , 8 , 0 , 0 , NOTUSETMP },
82
87
{AMOVBU , C_REG , C_NONE , C_REG , 13 , 4 , 0 , 0 , 0 },
83
- {AMOVWU , C_REG , C_NONE , C_REG , 14 , 8 , 0 , sys .MIPS64 , 0 },
88
+ {AMOVWU , C_REG , C_NONE , C_REG , 14 , 8 , 0 , sys .MIPS64 , NOTUSETMP },
84
89
85
90
{ASUB , C_REG , C_REG , C_REG , 2 , 4 , 0 , 0 , 0 },
86
91
{ASUBV , C_REG , C_REG , C_REG , 2 , 4 , 0 , sys .MIPS64 , 0 },
@@ -182,11 +187,11 @@ var optab = []Optab{
182
187
{AMOVB , C_REG , C_NONE , C_ADDR , 50 , 12 , 0 , sys .MIPS64 , 0 },
183
188
{AMOVBU , C_REG , C_NONE , C_ADDR , 50 , 8 , 0 , sys .MIPS , 0 },
184
189
{AMOVBU , C_REG , C_NONE , C_ADDR , 50 , 12 , 0 , sys .MIPS64 , 0 },
185
- {AMOVW , C_REG , C_NONE , C_TLS , 53 , 8 , 0 , 0 , 0 },
186
- {AMOVWU , C_REG , C_NONE , C_TLS , 53 , 8 , 0 , sys .MIPS64 , 0 },
187
- {AMOVV , C_REG , C_NONE , C_TLS , 53 , 8 , 0 , sys .MIPS64 , 0 },
188
- {AMOVB , C_REG , C_NONE , C_TLS , 53 , 8 , 0 , 0 , 0 },
189
- {AMOVBU , C_REG , C_NONE , C_TLS , 53 , 8 , 0 , 0 , 0 },
190
+ {AMOVW , C_REG , C_NONE , C_TLS , 53 , 8 , 0 , 0 , NOTUSETMP },
191
+ {AMOVWU , C_REG , C_NONE , C_TLS , 53 , 8 , 0 , sys .MIPS64 , NOTUSETMP },
192
+ {AMOVV , C_REG , C_NONE , C_TLS , 53 , 8 , 0 , sys .MIPS64 , NOTUSETMP },
193
+ {AMOVB , C_REG , C_NONE , C_TLS , 53 , 8 , 0 , 0 , NOTUSETMP },
194
+ {AMOVBU , C_REG , C_NONE , C_TLS , 53 , 8 , 0 , 0 , NOTUSETMP },
190
195
191
196
{AMOVW , C_LEXT , C_NONE , C_REG , 36 , 12 , REGSB , sys .MIPS64 , 0 },
192
197
{AMOVWU , C_LEXT , C_NONE , C_REG , 36 , 12 , REGSB , sys .MIPS64 , 0 },
@@ -211,33 +216,33 @@ var optab = []Optab{
211
216
{AMOVB , C_ADDR , C_NONE , C_REG , 51 , 12 , 0 , sys .MIPS64 , 0 },
212
217
{AMOVBU , C_ADDR , C_NONE , C_REG , 51 , 8 , 0 , sys .MIPS , 0 },
213
218
{AMOVBU , C_ADDR , C_NONE , C_REG , 51 , 12 , 0 , sys .MIPS64 , 0 },
214
- {AMOVW , C_TLS , C_NONE , C_REG , 54 , 8 , 0 , 0 , 0 },
215
- {AMOVWU , C_TLS , C_NONE , C_REG , 54 , 8 , 0 , sys .MIPS64 , 0 },
216
- {AMOVV , C_TLS , C_NONE , C_REG , 54 , 8 , 0 , sys .MIPS64 , 0 },
217
- {AMOVB , C_TLS , C_NONE , C_REG , 54 , 8 , 0 , 0 , 0 },
218
- {AMOVBU , C_TLS , C_NONE , C_REG , 54 , 8 , 0 , 0 , 0 },
219
+ {AMOVW , C_TLS , C_NONE , C_REG , 54 , 8 , 0 , 0 , NOTUSETMP },
220
+ {AMOVWU , C_TLS , C_NONE , C_REG , 54 , 8 , 0 , sys .MIPS64 , NOTUSETMP },
221
+ {AMOVV , C_TLS , C_NONE , C_REG , 54 , 8 , 0 , sys .MIPS64 , NOTUSETMP },
222
+ {AMOVB , C_TLS , C_NONE , C_REG , 54 , 8 , 0 , 0 , NOTUSETMP },
223
+ {AMOVBU , C_TLS , C_NONE , C_REG , 54 , 8 , 0 , 0 , NOTUSETMP },
219
224
220
225
{AMOVW , C_SECON , C_NONE , C_REG , 3 , 4 , REGSB , sys .MIPS64 , 0 },
221
226
{AMOVV , C_SECON , C_NONE , C_REG , 3 , 4 , REGSB , sys .MIPS64 , 0 },
222
227
{AMOVW , C_SACON , C_NONE , C_REG , 3 , 4 , REGSP , 0 , 0 },
223
228
{AMOVV , C_SACON , C_NONE , C_REG , 3 , 4 , REGSP , sys .MIPS64 , 0 },
224
- {AMOVW , C_LECON , C_NONE , C_REG , 52 , 8 , REGSB , sys .MIPS , 0 },
225
- {AMOVW , C_LECON , C_NONE , C_REG , 52 , 12 , REGSB , sys .MIPS64 , 0 },
226
- {AMOVV , C_LECON , C_NONE , C_REG , 52 , 12 , REGSB , sys .MIPS64 , 0 },
229
+ {AMOVW , C_LECON , C_NONE , C_REG , 52 , 8 , REGSB , sys .MIPS , NOTUSETMP },
230
+ {AMOVW , C_LECON , C_NONE , C_REG , 52 , 12 , REGSB , sys .MIPS64 , NOTUSETMP },
231
+ {AMOVV , C_LECON , C_NONE , C_REG , 52 , 12 , REGSB , sys .MIPS64 , NOTUSETMP },
227
232
228
233
{AMOVW , C_LACON , C_NONE , C_REG , 26 , 12 , REGSP , 0 , 0 },
229
234
{AMOVV , C_LACON , C_NONE , C_REG , 26 , 12 , REGSP , sys .MIPS64 , 0 },
230
235
{AMOVW , C_ADDCON , C_NONE , C_REG , 3 , 4 , REGZERO , 0 , 0 },
231
236
{AMOVV , C_ADDCON , C_NONE , C_REG , 3 , 4 , REGZERO , sys .MIPS64 , 0 },
232
237
{AMOVW , C_ANDCON , C_NONE , C_REG , 3 , 4 , REGZERO , 0 , 0 },
233
238
{AMOVV , C_ANDCON , C_NONE , C_REG , 3 , 4 , REGZERO , sys .MIPS64 , 0 },
234
- {AMOVW , C_STCON , C_NONE , C_REG , 55 , 8 , 0 , 0 , 0 },
235
- {AMOVV , C_STCON , C_NONE , C_REG , 55 , 8 , 0 , sys .MIPS64 , 0 },
239
+ {AMOVW , C_STCON , C_NONE , C_REG , 55 , 8 , 0 , 0 , NOTUSETMP },
240
+ {AMOVV , C_STCON , C_NONE , C_REG , 55 , 8 , 0 , sys .MIPS64 , NOTUSETMP },
236
241
237
242
{AMOVW , C_UCON , C_NONE , C_REG , 24 , 4 , 0 , 0 , 0 },
238
243
{AMOVV , C_UCON , C_NONE , C_REG , 24 , 4 , 0 , sys .MIPS64 , 0 },
239
- {AMOVW , C_LCON , C_NONE , C_REG , 19 , 8 , 0 , 0 , 0 },
240
- {AMOVV , C_LCON , C_NONE , C_REG , 19 , 8 , 0 , sys .MIPS64 , 0 },
244
+ {AMOVW , C_LCON , C_NONE , C_REG , 19 , 8 , 0 , 0 , NOTUSETMP },
245
+ {AMOVV , C_LCON , C_NONE , C_REG , 19 , 8 , 0 , sys .MIPS64 , NOTUSETMP },
241
246
242
247
{AMOVW , C_HI , C_NONE , C_REG , 20 , 4 , 0 , 0 , 0 },
243
248
{AMOVV , C_HI , C_NONE , C_REG , 20 , 4 , 0 , sys .MIPS64 , 0 },
@@ -292,7 +297,7 @@ var optab = []Optab{
292
297
{ABEQ , C_REG , C_REG , C_SBRA , 6 , 4 , 0 , 0 , 0 },
293
298
{ABEQ , C_REG , C_NONE , C_SBRA , 6 , 4 , 0 , 0 , 0 },
294
299
{ABLEZ , C_REG , C_NONE , C_SBRA , 6 , 4 , 0 , 0 , 0 },
295
- {ABFPT , C_NONE , C_NONE , C_SBRA , 6 , 8 , 0 , 0 , 0 },
300
+ {ABFPT , C_NONE , C_NONE , C_SBRA , 6 , 8 , 0 , 0 , NOTUSETMP },
296
301
297
302
{AJMP , C_NONE , C_NONE , C_LBRA , 11 , 4 , 0 , 0 , 0 },
298
303
{AJAL , C_NONE , C_NONE , C_LBRA , 11 , 4 , 0 , 0 , 0 },
@@ -506,6 +511,23 @@ func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
506
511
bp = bp [4 :]
507
512
}
508
513
}
514
+
515
+ // Mark nonpreemptible instruction sequences.
516
+ // We use REGTMP as a scratch register during call injection,
517
+ // so instruction sequences that use REGTMP are unsafe to
518
+ // preempt asynchronously.
519
+ obj .MarkUnsafePoints (c .ctxt , c .cursym .Func .Text , c .newprog , c .isUnsafePoint )
520
+ }
521
+
522
+ // Return whether p is an unsafe point.
523
+ func (c * ctxt0 ) isUnsafePoint (p * obj.Prog ) bool {
524
+ if p .From .Reg == REGTMP || p .To .Reg == REGTMP || p .Reg == REGTMP {
525
+ return true
526
+ }
527
+ // Most of the multi-instruction sequence uses REGTMP, except
528
+ // ones marked safe.
529
+ o := c .oplook (p )
530
+ return o .size > 4 && o .flag & NOTUSETMP == 0
509
531
}
510
532
511
533
func isint32 (v int64 ) bool {
@@ -1253,6 +1275,8 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
1253
1275
}
1254
1276
1255
1277
case 12 : /* movbs r,r */
1278
+ // NOTE: this case does not use REGTMP. If it ever does,
1279
+ // remove the NOTUSETMP flag in optab.
1256
1280
v := 16
1257
1281
if p .As == AMOVB {
1258
1282
v = 24
@@ -1268,6 +1292,8 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
1268
1292
}
1269
1293
1270
1294
case 14 : /* movwu r,r */
1295
+ // NOTE: this case does not use REGTMP. If it ever does,
1296
+ // remove the NOTUSETMP flag in optab.
1271
1297
o1 = OP_SRR (c .opirr (- ASLLV ), uint32 (0 ), uint32 (p .From .Reg ), uint32 (p .To .Reg ))
1272
1298
o2 = OP_SRR (c .opirr (- ASRLV ), uint32 (0 ), uint32 (p .To .Reg ), uint32 (p .To .Reg ))
1273
1299
@@ -1309,6 +1335,8 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
1309
1335
rel .Type = objabi .R_CALLIND
1310
1336
1311
1337
case 19 : /* mov $lcon,r ==> lu+or */
1338
+ // NOTE: this case does not use REGTMP. If it ever does,
1339
+ // remove the NOTUSETMP flag in optab.
1312
1340
v := c .regoff (& p .From )
1313
1341
o1 = OP_IRR (c .opirr (ALUI ), uint32 (v >> 16 ), uint32 (REGZERO ), uint32 (p .To .Reg ))
1314
1342
o2 = OP_IRR (c .opirr (AOR ), uint32 (v ), uint32 (p .To .Reg ), uint32 (p .To .Reg ))
@@ -1539,6 +1567,8 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
1539
1567
}
1540
1568
1541
1569
case 52 : /* mov $lext, r ==> lu + add REGSB, r + add */
1570
+ // NOTE: this case does not use REGTMP. If it ever does,
1571
+ // remove the NOTUSETMP flag in optab.
1542
1572
o1 = OP_IRR (c .opirr (ALUI ), uint32 (0 ), uint32 (REGZERO ), uint32 (p .To .Reg ))
1543
1573
rel := obj .Addrel (c .cursym )
1544
1574
rel .Off = int32 (c .pc )
@@ -1563,6 +1593,8 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
1563
1593
case 53 : /* mov r, tlsvar ==> rdhwr + sw o(r3) */
1564
1594
// clobbers R3 !
1565
1595
// load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux
1596
+ // NOTE: this case does not use REGTMP. If it ever does,
1597
+ // remove the NOTUSETMP flag in optab.
1566
1598
o1 = (037 << 26 + 073 ) | (29 << 11 ) | (3 << 16 ) // rdhwr $29, r3
1567
1599
o2 = OP_IRR (c .opirr (p .As ), uint32 (0 ), uint32 (REG_R3 ), uint32 (p .From .Reg ))
1568
1600
rel := obj .Addrel (c .cursym )
@@ -1574,6 +1606,8 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
1574
1606
1575
1607
case 54 : /* mov tlsvar, r ==> rdhwr + lw o(r3) */
1576
1608
// clobbers R3 !
1609
+ // NOTE: this case does not use REGTMP. If it ever does,
1610
+ // remove the NOTUSETMP flag in optab.
1577
1611
o1 = (037 << 26 + 073 ) | (29 << 11 ) | (3 << 16 ) // rdhwr $29, r3
1578
1612
o2 = OP_IRR (c .opirr (- p .As ), uint32 (0 ), uint32 (REG_R3 ), uint32 (p .To .Reg ))
1579
1613
rel := obj .Addrel (c .cursym )
@@ -1585,6 +1619,8 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
1585
1619
1586
1620
case 55 : /* mov $tlsvar, r ==> rdhwr + add */
1587
1621
// clobbers R3 !
1622
+ // NOTE: this case does not use REGTMP. If it ever does,
1623
+ // remove the NOTUSETMP flag in optab.
1588
1624
o1 = (037 << 26 + 073 ) | (29 << 11 ) | (3 << 16 ) // rdhwr $29, r3
1589
1625
o2 = OP_IRR (c .opirr (add ), uint32 (0 ), uint32 (REG_R3 ), uint32 (p .To .Reg ))
1590
1626
rel := obj .Addrel (c .cursym )
0 commit comments