diff options
author | Jeremy Faller <jeremy@golang.org> | 2020-09-30 17:57:14 -0400 |
---|---|---|
committer | Jeremy Faller <jeremy@golang.org> | 2020-09-30 18:00:58 -0400 |
commit | 91e4d2d57bc341dd82c98247117114c851380aef (patch) | |
tree | 15a2d023cdc63543cf8a6e99f8a561c0a0459000 /src/cmd/compile/internal/x86/387.go | |
parent | c863e14a6c15e174ac0979ddd7f9530d6a4ec9cc (diff) | |
parent | 846dce9d05f19a1f53465e62a304dea21b99f910 (diff) | |
download | go-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.go | 68 |
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 +} |