(Cvt32to32F ...) => (CVTSL2SS ...)
(Cvt32to64F ...) => (CVTSL2SD ...)
-(Cvt32Fto32 <t> x) && base.ConvertHash.MatchPos(v.Pos, nil) => (XORL <t> y (SARLconst <t> [31] (ANDL <t> y:(CVTTSS2SL <t> x) (NOTL <typ.Int32> (MOVLf2i x)))))
-(Cvt64Fto32 <t> x) && base.ConvertHash.MatchPos(v.Pos, nil) => (XORL <t> y (SARLconst <t> [31] (ANDL <t> y:(CVTTSD2SL <t> x) (NOTL <typ.Int32> (MOVLf2i (CVTSD2SS <typ.Float32> x))))))
-(Cvt32Fto32 <t> x) && !base.ConvertHash.MatchPos(v.Pos, nil) => (CVTTSS2SL <t> x)
-(Cvt64Fto32 <t> x) && !base.ConvertHash.MatchPos(v.Pos, nil) => (CVTTSD2SL <t> x)
+(Cvt32Fto32 ...) => (CVTTSS2SL ...)
+(Cvt64Fto32 ...) => (CVTTSD2SL ...)
(Cvt32Fto64F ...) => (CVTSS2SD ...)
(Cvt64Fto32F ...) => (CVTSD2SS ...)
{name: "MOVWLSX", argLength: 1, reg: gp11, asm: "MOVWLSX"}, // sign extend arg0 from int16 to int32
{name: "MOVWLZX", argLength: 1, reg: gp11, asm: "MOVWLZX"}, // zero extend arg0 from int16 to int32
- {name: "MOVLf2i", argLength: 1, reg: fpgp, typ: "UInt32"}, // move 32 bits from float to int reg, zero extend
-
{name: "MOVLconst", reg: gp01, asm: "MOVL", typ: "UInt32", aux: "Int32", rematerializeable: true}, // 32 low bits of auxint
{name: "CVTTSD2SL", argLength: 1, reg: fpgp, asm: "CVTTSD2SL"}, // convert float64 to int32
Op386MOVBLZX
Op386MOVWLSX
Op386MOVWLZX
- Op386MOVLf2i
Op386MOVLconst
Op386CVTTSD2SL
Op386CVTTSS2SL
},
},
},
- {
- name: "MOVLf2i",
- argLen: 1,
- reg: regInfo{
- inputs: []inputInfo{
- {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
- },
- outputs: []outputInfo{
- {0, 239}, // AX CX DX BX BP SI DI
- },
- },
- },
{
name: "MOVLconst",
auxType: auxInt32,
package ssa
import "math"
-import "cmd/compile/internal/base"
import "cmd/compile/internal/types"
func rewriteValue386(v *Value) bool {
v.Op = Op386BSFL
return true
case OpCvt32Fto32:
- return rewriteValue386_OpCvt32Fto32(v)
+ v.Op = Op386CVTTSS2SL
+ return true
case OpCvt32Fto64F:
v.Op = Op386CVTSS2SD
return true
v.Op = Op386CVTSL2SD
return true
case OpCvt64Fto32:
- return rewriteValue386_OpCvt64Fto32(v)
+ v.Op = Op386CVTTSD2SL
+ return true
case OpCvt64Fto32F:
v.Op = Op386CVTSD2SS
return true
return true
}
}
-func rewriteValue386_OpCvt32Fto32(v *Value) bool {
- v_0 := v.Args[0]
- b := v.Block
- typ := &b.Func.Config.Types
- // match: (Cvt32Fto32 <t> x)
- // cond: base.ConvertHash.MatchPos(v.Pos, nil)
- // result: (XORL <t> y (SARLconst <t> [31] (ANDL <t> y:(CVTTSS2SL <t> x) (NOTL <typ.Int32> (MOVLf2i x)))))
- for {
- t := v.Type
- x := v_0
- if !(base.ConvertHash.MatchPos(v.Pos, nil)) {
- break
- }
- v.reset(Op386XORL)
- v.Type = t
- v0 := b.NewValue0(v.Pos, Op386SARLconst, t)
- v0.AuxInt = int32ToAuxInt(31)
- v1 := b.NewValue0(v.Pos, Op386ANDL, t)
- y := b.NewValue0(v.Pos, Op386CVTTSS2SL, t)
- y.AddArg(x)
- v3 := b.NewValue0(v.Pos, Op386NOTL, typ.Int32)
- v4 := b.NewValue0(v.Pos, Op386MOVLf2i, typ.UInt32)
- v4.AddArg(x)
- v3.AddArg(v4)
- v1.AddArg2(y, v3)
- v0.AddArg(v1)
- v.AddArg2(y, v0)
- return true
- }
- // match: (Cvt32Fto32 <t> x)
- // cond: !base.ConvertHash.MatchPos(v.Pos, nil)
- // result: (CVTTSS2SL <t> x)
- for {
- t := v.Type
- x := v_0
- if !(!base.ConvertHash.MatchPos(v.Pos, nil)) {
- break
- }
- v.reset(Op386CVTTSS2SL)
- v.Type = t
- v.AddArg(x)
- return true
- }
- return false
-}
-func rewriteValue386_OpCvt64Fto32(v *Value) bool {
- v_0 := v.Args[0]
- b := v.Block
- typ := &b.Func.Config.Types
- // match: (Cvt64Fto32 <t> x)
- // cond: base.ConvertHash.MatchPos(v.Pos, nil)
- // result: (XORL <t> y (SARLconst <t> [31] (ANDL <t> y:(CVTTSD2SL <t> x) (NOTL <typ.Int32> (MOVLf2i (CVTSD2SS <typ.Float32> x))))))
- for {
- t := v.Type
- x := v_0
- if !(base.ConvertHash.MatchPos(v.Pos, nil)) {
- break
- }
- v.reset(Op386XORL)
- v.Type = t
- v0 := b.NewValue0(v.Pos, Op386SARLconst, t)
- v0.AuxInt = int32ToAuxInt(31)
- v1 := b.NewValue0(v.Pos, Op386ANDL, t)
- y := b.NewValue0(v.Pos, Op386CVTTSD2SL, t)
- y.AddArg(x)
- v3 := b.NewValue0(v.Pos, Op386NOTL, typ.Int32)
- v4 := b.NewValue0(v.Pos, Op386MOVLf2i, typ.UInt32)
- v5 := b.NewValue0(v.Pos, Op386CVTSD2SS, typ.Float32)
- v5.AddArg(x)
- v4.AddArg(v5)
- v3.AddArg(v4)
- v1.AddArg2(y, v3)
- v0.AddArg(v1)
- v.AddArg2(y, v0)
- return true
- }
- // match: (Cvt64Fto32 <t> x)
- // cond: !base.ConvertHash.MatchPos(v.Pos, nil)
- // result: (CVTTSD2SL <t> x)
- for {
- t := v.Type
- x := v_0
- if !(!base.ConvertHash.MatchPos(v.Pos, nil)) {
- break
- }
- v.reset(Op386CVTTSD2SL)
- v.Type = t
- v.AddArg(x)
- return true
- }
- return false
-}
func rewriteValue386_OpDiv8(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
p.To.Type = obj.TYPE_MEM
p.To.Reg = v.Args[0].Reg()
ssagen.AddAux(&p.To, v)
- case ssa.Op386MOVLf2i:
- var p *obj.Prog
- p = s.Prog(x86.AMOVL)
- p.From.Type = obj.TYPE_REG
- p.From.Reg = v.Args[0].Reg()
- p.To.Type = obj.TYPE_REG
- p.To.Reg = v.Reg()
case ssa.Op386ADDLconstmodify:
sc := v.AuxValAndOff()
val := sc.Val()
FMOVDP F0, ret+4(FP)
RET
+TEXT runtime·float64touint32(SB),NOSPLIT,$12-12
+ FMOVD a+0(FP), F0
+ FSTCW 0(SP)
+ FLDCW runtime·controlWord64trunc(SB)
+ FMOVVP F0, 4(SP)
+ FLDCW 0(SP)
+ MOVL 4(SP), AX
+ MOVL AX, ret+8(FP)
+ RET
+
// gcWriteBarrier informs the GC about heap pointer writes.
//
// gcWriteBarrier returns space in a write barrier buffer which
import "unsafe"
+func float64touint32(a float64) uint32
func uint32tofloat64(a uint32) float64
// stackcheck checks that SP is in range [g->stack.lo, g->stack.hi).
}
func float64touint64(d float64) (y uint64) {
- _d2vu(&y, d)
+ _d2v(&y, d)
return
}
-func float64touint32(a float64) uint32 {
- if a >= 0xffffffff {
- return 0xffffffff
- }
- return uint32(float64touint64(a))
-}
-
func int64tofloat64(y int64) float64 {
if y < 0 {
return -uint64tofloat64(-uint64(y))
} else {
/* v = (hi||lo) << -sh */
sh := uint32(-sh)
- if sh <= 10 {
+ if sh <= 11 {
ylo = xlo << sh
yhi = xhi<<sh | xlo>>(32-sh)
} else {
- if x&sign64 != 0 {
- *y = 0x8000000000000000
- } else {
- *y = 0x7fffffffffffffff
- }
- return
+ /* overflow */
+ yhi = uint32(d) /* causes something awful */
}
}
if x&sign64 != 0 {
*y = uint64(yhi)<<32 | uint64(ylo)
}
-func _d2vu(y *uint64, d float64) {
- x := *(*uint64)(unsafe.Pointer(&d))
- if x&sign64 != 0 {
- *y = 0
- return
- }
-
- xhi := uint32(x>>32)&0xfffff | 0x100000
- xlo := uint32(x)
- sh := 1075 - int32(uint32(x>>52)&0x7ff)
-
- var ylo, yhi uint32
- if sh >= 0 {
- sh := uint32(sh)
- /* v = (hi||lo) >> sh */
- if sh < 32 {
- if sh == 0 {
- ylo = xlo
- yhi = xhi
- } else {
- ylo = xlo>>sh | xhi<<(32-sh)
- yhi = xhi >> sh
- }
- } else {
- if sh == 32 {
- ylo = xhi
- } else if sh < 64 {
- ylo = xhi >> (sh - 32)
- }
- }
- } else {
- /* v = (hi||lo) << -sh */
- sh := uint32(-sh)
- if sh <= 11 {
- ylo = xlo << sh
- yhi = xhi<<sh | xlo>>(32-sh)
- } else {
- /* overflow */
- *y = 0xffffffffffffffff
- return
- }
- }
- *y = uint64(yhi)<<32 | uint64(ylo)
-}
func uint64div(n, d uint64) uint64 {
// Check for 32 bit operands
if uint32(n>>32) == 0 && uint32(d>>32) == 0 {
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build !wasm
+//go:build !wasm && !386 && !arm && !mips
-// TODO fix this to work for wasm
+// TODO fix this to work for wasm and 32-bit architectures.
// Doing more than this, however, expands the change.
package main