@@ -72,15 +72,20 @@ type Optab struct {
7272 flag uint8
7373}
7474
75+ const (
76+ // Optab.flag
77+ NOTUSETMP = 1 << iota // p expands to multiple instructions, but does NOT use REGTMP
78+ )
79+
7580var optab = []Optab {
7681 {obj .ATEXT , C_LEXT , C_NONE , C_TEXTSIZE , 0 , 0 , 0 , sys .MIPS64 , 0 },
7782 {obj .ATEXT , C_ADDR , C_NONE , C_TEXTSIZE , 0 , 0 , 0 , 0 , 0 },
7883
7984 {AMOVW , C_REG , C_NONE , C_REG , 1 , 4 , 0 , 0 , 0 },
8085 {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 },
8287 {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 },
8489
8590 {ASUB , C_REG , C_REG , C_REG , 2 , 4 , 0 , 0 , 0 },
8691 {ASUBV , C_REG , C_REG , C_REG , 2 , 4 , 0 , sys .MIPS64 , 0 },
@@ -182,11 +187,11 @@ var optab = []Optab{
182187 {AMOVB , C_REG , C_NONE , C_ADDR , 50 , 12 , 0 , sys .MIPS64 , 0 },
183188 {AMOVBU , C_REG , C_NONE , C_ADDR , 50 , 8 , 0 , sys .MIPS , 0 },
184189 {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 },
190195
191196 {AMOVW , C_LEXT , C_NONE , C_REG , 36 , 12 , REGSB , sys .MIPS64 , 0 },
192197 {AMOVWU , C_LEXT , C_NONE , C_REG , 36 , 12 , REGSB , sys .MIPS64 , 0 },
@@ -211,33 +216,33 @@ var optab = []Optab{
211216 {AMOVB , C_ADDR , C_NONE , C_REG , 51 , 12 , 0 , sys .MIPS64 , 0 },
212217 {AMOVBU , C_ADDR , C_NONE , C_REG , 51 , 8 , 0 , sys .MIPS , 0 },
213218 {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 },
219224
220225 {AMOVW , C_SECON , C_NONE , C_REG , 3 , 4 , REGSB , sys .MIPS64 , 0 },
221226 {AMOVV , C_SECON , C_NONE , C_REG , 3 , 4 , REGSB , sys .MIPS64 , 0 },
222227 {AMOVW , C_SACON , C_NONE , C_REG , 3 , 4 , REGSP , 0 , 0 },
223228 {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 },
227232
228233 {AMOVW , C_LACON , C_NONE , C_REG , 26 , 12 , REGSP , 0 , 0 },
229234 {AMOVV , C_LACON , C_NONE , C_REG , 26 , 12 , REGSP , sys .MIPS64 , 0 },
230235 {AMOVW , C_ADDCON , C_NONE , C_REG , 3 , 4 , REGZERO , 0 , 0 },
231236 {AMOVV , C_ADDCON , C_NONE , C_REG , 3 , 4 , REGZERO , sys .MIPS64 , 0 },
232237 {AMOVW , C_ANDCON , C_NONE , C_REG , 3 , 4 , REGZERO , 0 , 0 },
233238 {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 },
236241
237242 {AMOVW , C_UCON , C_NONE , C_REG , 24 , 4 , 0 , 0 , 0 },
238243 {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 },
241246
242247 {AMOVW , C_HI , C_NONE , C_REG , 20 , 4 , 0 , 0 , 0 },
243248 {AMOVV , C_HI , C_NONE , C_REG , 20 , 4 , 0 , sys .MIPS64 , 0 },
@@ -292,7 +297,7 @@ var optab = []Optab{
292297 {ABEQ , C_REG , C_REG , C_SBRA , 6 , 4 , 0 , 0 , 0 },
293298 {ABEQ , C_REG , C_NONE , C_SBRA , 6 , 4 , 0 , 0 , 0 },
294299 {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 },
296301
297302 {AJMP , C_NONE , C_NONE , C_LBRA , 11 , 4 , 0 , 0 , 0 },
298303 {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) {
506511 bp = bp [4 :]
507512 }
508513 }
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
509531}
510532
511533func isint32 (v int64 ) bool {
@@ -1253,6 +1275,8 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
12531275 }
12541276
12551277 case 12 : /* movbs r,r */
1278+ // NOTE: this case does not use REGTMP. If it ever does,
1279+ // remove the NOTUSETMP flag in optab.
12561280 v := 16
12571281 if p .As == AMOVB {
12581282 v = 24
@@ -1268,6 +1292,8 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
12681292 }
12691293
12701294 case 14 : /* movwu r,r */
1295+ // NOTE: this case does not use REGTMP. If it ever does,
1296+ // remove the NOTUSETMP flag in optab.
12711297 o1 = OP_SRR (c .opirr (- ASLLV ), uint32 (0 ), uint32 (p .From .Reg ), uint32 (p .To .Reg ))
12721298 o2 = OP_SRR (c .opirr (- ASRLV ), uint32 (0 ), uint32 (p .To .Reg ), uint32 (p .To .Reg ))
12731299
@@ -1309,6 +1335,8 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
13091335 rel .Type = objabi .R_CALLIND
13101336
13111337 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.
13121340 v := c .regoff (& p .From )
13131341 o1 = OP_IRR (c .opirr (ALUI ), uint32 (v >> 16 ), uint32 (REGZERO ), uint32 (p .To .Reg ))
13141342 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) {
15391567 }
15401568
15411569 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.
15421572 o1 = OP_IRR (c .opirr (ALUI ), uint32 (0 ), uint32 (REGZERO ), uint32 (p .To .Reg ))
15431573 rel := obj .Addrel (c .cursym )
15441574 rel .Off = int32 (c .pc )
@@ -1563,6 +1593,8 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
15631593 case 53 : /* mov r, tlsvar ==> rdhwr + sw o(r3) */
15641594 // clobbers R3 !
15651595 // 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.
15661598 o1 = (037 << 26 + 073 ) | (29 << 11 ) | (3 << 16 ) // rdhwr $29, r3
15671599 o2 = OP_IRR (c .opirr (p .As ), uint32 (0 ), uint32 (REG_R3 ), uint32 (p .From .Reg ))
15681600 rel := obj .Addrel (c .cursym )
@@ -1574,6 +1606,8 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
15741606
15751607 case 54 : /* mov tlsvar, r ==> rdhwr + lw o(r3) */
15761608 // clobbers R3 !
1609+ // NOTE: this case does not use REGTMP. If it ever does,
1610+ // remove the NOTUSETMP flag in optab.
15771611 o1 = (037 << 26 + 073 ) | (29 << 11 ) | (3 << 16 ) // rdhwr $29, r3
15781612 o2 = OP_IRR (c .opirr (- p .As ), uint32 (0 ), uint32 (REG_R3 ), uint32 (p .To .Reg ))
15791613 rel := obj .Addrel (c .cursym )
@@ -1585,6 +1619,8 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
15851619
15861620 case 55 : /* mov $tlsvar, r ==> rdhwr + add */
15871621 // clobbers R3 !
1622+ // NOTE: this case does not use REGTMP. If it ever does,
1623+ // remove the NOTUSETMP flag in optab.
15881624 o1 = (037 << 26 + 073 ) | (29 << 11 ) | (3 << 16 ) // rdhwr $29, r3
15891625 o2 = OP_IRR (c .opirr (add ), uint32 (0 ), uint32 (REG_R3 ), uint32 (p .To .Reg ))
15901626 rel := obj .Addrel (c .cursym )
0 commit comments