"math"
)
-func canuse1insntls(ctxt *obj.Link) bool {
+func CanUse1InsnTLS(ctxt *obj.Link) bool {
if isAndroid {
// For android, we use a disgusting hack that assumes
// the thread-local storage slot for g is allocated
// rewriting the instructions more comprehensively, and it only does because
// we only support a single TLS variable (g).
- if canuse1insntls(ctxt) {
+ if CanUse1InsnTLS(ctxt) {
// Reduce 2-instruction sequence to 1-instruction sequence.
// Sequences like
// MOVQ TLS, BX
// Convert AMOVSS $(0), Xx to AXORPS Xx, Xx
case AMOVSS:
if p.From.Type == obj.TYPE_FCONST {
- if p.From.Val.(float64) == 0 {
+ // f == 0 can't be used here due to -0, so use Float64bits
+ if f := p.From.Val.(float64); math.Float64bits(f) == 0 {
if p.To.Type == obj.TYPE_REG && REG_X0 <= p.To.Reg && p.To.Reg <= REG_X15 {
p.As = AXORPS
p.From = p.To
case AMOVSD:
// Convert AMOVSD $(0), Xx to AXORPS Xx, Xx
if p.From.Type == obj.TYPE_FCONST {
- if p.From.Val.(float64) == 0 {
+ // f == 0 can't be used here due to -0, so use Float64bits
+ if f := p.From.Val.(float64); math.Float64bits(f) == 0 {
if p.To.Type == obj.TYPE_REG && REG_X0 <= p.To.Reg && p.To.Reg <= REG_X15 {
p.As = AXORPS
p.From = p.To
}
if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
// $MOV $sym, Rx becomes $MOV sym@GOT, Rx
- // $MOV $sym+<off>, Rx becomes $MOV sym@GOT, Rx; $ADD <off>, Rx
+ // $MOV $sym+<off>, Rx becomes $MOV sym@GOT, Rx; $LEA <off>(Rx), Rx
// On 386 only, more complicated things like PUSHL $sym become $MOV sym@GOT, CX; PUSHL CX
cmplxdest := false
pAs := p.As
q := p
if p.From.Offset != 0 {
q = obj.Appendp(ctxt, p)
- q.As = add
- q.From.Type = obj.TYPE_CONST
+ q.As = lea
+ q.From.Type = obj.TYPE_MEM
+ q.From.Reg = p.To.Reg
q.From.Offset = p.From.Offset
q.To = p.To
p.From.Offset = 0
q = p.Pcond
if q != nil && q.As != obj.ATEXT {
/* mark instruction as done and continue layout at target of jump */
- p.Mark = 1
+ p.Mark |= DONE
p = q
- if p.Mark == 0 {
+ if p.Mark&DONE == 0 {
goto loop
}
}
}
- if p.Mark != 0 {
+ if p.Mark&DONE != 0 {
/*
* p goes here, but already used it elsewhere.
* copy up to 4 instructions or else branch to other copy.
if nofollow(a) || pushpop(a) {
break // NOTE(rsc): arm does goto copy
}
- if q.Pcond == nil || q.Pcond.Mark != 0 {
+ if q.Pcond == nil || q.Pcond.Mark&DONE != 0 {
continue
}
if a == obj.ACALL || a == ALOOP {
q = obj.Copyp(ctxt, p)
p = p.Link
- q.Mark = 1
+ q.Mark |= DONE
(*last).Link = q
*last = q
- if int(q.As) != a || q.Pcond == nil || q.Pcond.Mark != 0 {
+ if int(q.As) != a || q.Pcond == nil || q.Pcond.Mark&DONE != 0 {
continue
}
q.Link = p
xfol(ctxt, q.Link, last)
p = q.Link
- if p.Mark != 0 {
+ if p.Mark&DONE != 0 {
return
}
goto loop
}
/* emit p */
- p.Mark = 1
+ p.Mark |= DONE
(*last).Link = p
*last = p
}
} else {
q = p.Link
- if q.Mark != 0 {
+ if q.Mark&DONE != 0 {
if a != ALOOP {
p.As = relinv(int16(a))
p.Link = p.Pcond
}
xfol(ctxt, p.Link, last)
- if p.Pcond.Mark != 0 {
+ if p.Pcond.Mark&DONE != 0 {
return
}
p = p.Pcond