aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/x86/387.go
diff options
context:
space:
mode:
authorJeremy Faller <jeremy@golang.org>2020-09-30 17:57:14 -0400
committerJeremy Faller <jeremy@golang.org>2020-09-30 18:00:58 -0400
commit91e4d2d57bc341dd82c98247117114c851380aef (patch)
tree15a2d023cdc63543cf8a6e99f8a561c0a0459000 /src/cmd/compile/internal/x86/387.go
parentc863e14a6c15e174ac0979ddd7f9530d6a4ec9cc (diff)
parent846dce9d05f19a1f53465e62a304dea21b99f910 (diff)
downloadgo-91e4d2d57bc341dd82c98247117114c851380aef.tar.gz
go-91e4d2d57bc341dd82c98247117114c851380aef.zip
[dev.link] Merge branch 'master' into dev.link
2 conflicts, that make sense. src/cmd/internal/obj/objfile.go src/cmd/link/internal/loader/loader.go Change-Id: Ib224e2d248cb568fa1e888af79dd908b2f5e05ff
Diffstat (limited to 'src/cmd/compile/internal/x86/387.go')
-rw-r--r--src/cmd/compile/internal/x86/387.go68
1 files changed, 48 insertions, 20 deletions
diff --git a/src/cmd/compile/internal/x86/387.go b/src/cmd/compile/internal/x86/387.go
index 796aa82f19..594adb2cd5 100644
--- a/src/cmd/compile/internal/x86/387.go
+++ b/src/cmd/compile/internal/x86/387.go
@@ -139,12 +139,18 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) {
// Set precision if needed. 64 bits is the default.
switch v.Op {
case ssa.Op386ADDSS, ssa.Op386SUBSS, ssa.Op386MULSS, ssa.Op386DIVSS:
- p := s.Prog(x86.AFSTCW)
+ // Save AX so we can use it as scratch space.
+ p := s.Prog(x86.AMOVL)
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = x86.REG_AX
s.AddrScratch(&p.To)
- p = s.Prog(x86.AFLDCW)
- p.From.Type = obj.TYPE_MEM
- p.From.Name = obj.NAME_EXTERN
- p.From.Sym = gc.ControlWord32
+ // Install a 32-bit version of the control word.
+ installControlWord(s, gc.ControlWord32, x86.REG_AX)
+ // Restore AX.
+ p = s.Prog(x86.AMOVL)
+ s.AddrScratch(&p.From)
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = x86.REG_AX
}
var op obj.As
@@ -167,8 +173,7 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) {
// Restore precision if needed.
switch v.Op {
case ssa.Op386ADDSS, ssa.Op386SUBSS, ssa.Op386MULSS, ssa.Op386DIVSS:
- p := s.Prog(x86.AFLDCW)
- s.AddrScratch(&p.From)
+ restoreControlWord(s)
}
case ssa.Op386UCOMISS, ssa.Op386UCOMISD:
@@ -225,19 +230,11 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) {
case ssa.Op386CVTTSD2SL, ssa.Op386CVTTSS2SL:
push(s, v.Args[0])
- // Save control word.
- p := s.Prog(x86.AFSTCW)
- s.AddrScratch(&p.To)
- p.To.Offset += 4
-
// Load control word which truncates (rounds towards zero).
- p = s.Prog(x86.AFLDCW)
- p.From.Type = obj.TYPE_MEM
- p.From.Name = obj.NAME_EXTERN
- p.From.Sym = gc.ControlWord64trunc
+ installControlWord(s, gc.ControlWord64trunc, v.Reg())
// Now do the conversion.
- p = s.Prog(x86.AFMOVLP)
+ p := s.Prog(x86.AFMOVLP)
p.From.Type = obj.TYPE_REG
p.From.Reg = x86.REG_F0
s.AddrScratch(&p.To)
@@ -247,9 +244,7 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) {
p.To.Reg = v.Reg()
// Restore control word.
- p = s.Prog(x86.AFLDCW)
- s.AddrScratch(&p.From)
- p.From.Offset += 4
+ restoreControlWord(s)
case ssa.Op386CVTSS2SD:
// float32 -> float64 is a nop
@@ -373,3 +368,36 @@ func ssaGenBlock387(s *gc.SSAGenState, b, next *ssa.Block) {
ssaGenBlock(s, b, next)
}
+
+// installControlWord saves the current floating-point control
+// word and installs a new one loaded from cw.
+// scratchReg must be an unused register.
+// This call must be paired with restoreControlWord.
+// Bytes 4-5 of the scratch space (s.AddrScratch) are used between
+// this call and restoreControlWord.
+func installControlWord(s *gc.SSAGenState, cw *obj.LSym, scratchReg int16) {
+ // Save current control word.
+ p := s.Prog(x86.AFSTCW)
+ s.AddrScratch(&p.To)
+ p.To.Offset += 4
+
+ // Materialize address of new control word.
+ // Note: this must be a seperate instruction to handle PIE correctly.
+ // See issue 41503.
+ p = s.Prog(x86.ALEAL)
+ p.From.Type = obj.TYPE_MEM
+ p.From.Name = obj.NAME_EXTERN
+ p.From.Sym = cw
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = scratchReg
+
+ // Load replacement control word.
+ p = s.Prog(x86.AFLDCW)
+ p.From.Type = obj.TYPE_MEM
+ p.From.Reg = scratchReg
+}
+func restoreControlWord(s *gc.SSAGenState) {
+ p := s.Prog(x86.AFLDCW)
+ s.AddrScratch(&p.From)
+ p.From.Offset += 4
+}