| // Copyright 2017 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package ssa |
| |
| import ( |
| "cmd/compile/internal/types" |
| "math" |
| ) |
| |
| func softfloat(f *Func) { |
| if !f.Config.SoftFloat { |
| return |
| } |
| newInt64 := false |
| |
| for _, b := range f.Blocks { |
| for _, v := range b.Values { |
| if v.Type.IsFloat() { |
| switch v.Op { |
| case OpPhi, OpLoad, OpArg: |
| if v.Type.Size() == 4 { |
| v.Type = f.Config.Types.UInt32 |
| } else { |
| v.Type = f.Config.Types.UInt64 |
| } |
| case OpConst32F: |
| v.Op = OpConst32 |
| v.Type = f.Config.Types.UInt32 |
| v.AuxInt = int64(int32(math.Float32bits(auxTo32F(v.AuxInt)))) |
| case OpConst64F: |
| v.Op = OpConst64 |
| v.Type = f.Config.Types.UInt64 |
| case OpNeg32F: |
| arg0 := v.Args[0] |
| v.reset(OpXor32) |
| v.Type = f.Config.Types.UInt32 |
| v.AddArg(arg0) |
| mask := v.Block.NewValue0(v.Pos, OpConst32, v.Type) |
| mask.AuxInt = -0x80000000 |
| v.AddArg(mask) |
| case OpNeg64F: |
| arg0 := v.Args[0] |
| v.reset(OpXor64) |
| v.Type = f.Config.Types.UInt64 |
| v.AddArg(arg0) |
| mask := v.Block.NewValue0(v.Pos, OpConst64, v.Type) |
| mask.AuxInt = -0x8000000000000000 |
| v.AddArg(mask) |
| case OpRound32F: |
| v.Op = OpCopy |
| v.Type = f.Config.Types.UInt32 |
| case OpRound64F: |
| v.Op = OpCopy |
| v.Type = f.Config.Types.UInt64 |
| } |
| newInt64 = newInt64 || v.Type.Size() == 8 |
| } else if (v.Op == OpStore || v.Op == OpZero || v.Op == OpMove) && v.Aux.(*types.Type).IsFloat() { |
| switch size := v.Aux.(*types.Type).Size(); size { |
| case 4: |
| v.Aux = f.Config.Types.UInt32 |
| case 8: |
| v.Aux = f.Config.Types.UInt64 |
| default: |
| v.Fatalf("bad float type with size %d", size) |
| } |
| } |
| } |
| } |
| |
| if newInt64 && f.Config.RegSize == 4 { |
| // On 32bit arch, decompose Uint64 introduced in the switch above. |
| decomposeBuiltIn(f) |
| applyRewrite(f, rewriteBlockdec64, rewriteValuedec64) |
| } |
| |
| } |