Home | History | Annotate | Download | only in math
      1 // Copyright 2012 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 #include "textflag.h"
      6 
      7 #define Big		0x4330000000000000 // 2**52
      8 
      9 // func hasSSE4() bool
     10 // returns whether SSE4.1 is supported
     11 TEXT hasSSE4(SB),NOSPLIT,$0
     12 	XORQ AX, AX
     13 	INCL AX
     14 	CPUID
     15 	SHRQ $19, CX
     16 	ANDQ $1, CX
     17 	MOVB CX, ret+0(FP)
     18 	RET
     19 
     20 // func Floor(x float64) float64
     21 TEXT Floor(SB),NOSPLIT,$0
     22 	CMPB    mathuseSSE4(SB), $1
     23 	JNE     nosse4
     24 	ROUNDSD $1, x+0(FP), X0
     25 	MOVQ X0, ret+8(FP)
     26 	RET
     27 nosse4:
     28 	MOVQ	x+0(FP), AX
     29 	MOVQ	$~(1<<63), DX // sign bit mask
     30 	ANDQ	AX,DX // DX = |x|
     31 	SUBQ	$1,DX
     32 	MOVQ    $(Big - 1), CX // if |x| >= 2**52-1 or IsNaN(x) or |x| == 0, return x
     33 	CMPQ	DX,CX
     34 	JAE     isBig_floor
     35 	MOVQ	AX, X0 // X0 = x
     36 	CVTTSD2SQ	X0, AX
     37 	CVTSQ2SD	AX, X1 // X1 = float(int(x))
     38 	CMPSD	X1, X0, 1 // compare LT; X0 = 0xffffffffffffffff or 0
     39 	MOVSD	$(-1.0), X2
     40 	ANDPD	X2, X0 // if x < float(int(x)) {X0 = -1} else {X0 = 0}
     41 	ADDSD	X1, X0
     42 	MOVSD	X0, ret+8(FP)
     43 	RET
     44 isBig_floor:
     45 	MOVQ    AX, ret+8(FP) // return x
     46 	RET
     47 
     48 // func Ceil(x float64) float64
     49 TEXT Ceil(SB),NOSPLIT,$0
     50 	CMPB    mathuseSSE4(SB), $1
     51 	JNE     nosse4
     52 	ROUNDSD $2, x+0(FP), X0
     53 	MOVQ X0, ret+8(FP)
     54 	RET
     55 nosse4:
     56 	MOVQ	x+0(FP), AX
     57 	MOVQ	$~(1<<63), DX // sign bit mask
     58 	MOVQ	AX, BX // BX = copy of x
     59 	ANDQ    DX, BX // BX = |x|
     60 	MOVQ    $Big, CX // if |x| >= 2**52 or IsNaN(x), return x
     61 	CMPQ    BX, CX
     62 	JAE     isBig_ceil
     63 	MOVQ	AX, X0 // X0 = x
     64 	MOVQ	DX, X2 // X2 = sign bit mask
     65 	CVTTSD2SQ	X0, AX
     66 	ANDNPD	X0, X2 // X2 = sign
     67 	CVTSQ2SD	AX, X1	// X1 = float(int(x))
     68 	CMPSD	X1, X0, 2 // compare LE; X0 = 0xffffffffffffffff or 0
     69 	ORPD	X2, X1 // if X1 = 0.0, incorporate sign
     70 	MOVSD	$1.0, X3
     71 	ANDNPD	X3, X0
     72 	ORPD	X2, X0 // if float(int(x)) <= x {X0 = 1} else {X0 = -0}
     73 	ADDSD	X1, X0
     74 	MOVSD	X0, ret+8(FP)
     75 	RET
     76 isBig_ceil:
     77 	MOVQ	AX, ret+8(FP)
     78 	RET
     79 
     80 // func Trunc(x float64) float64
     81 TEXT Trunc(SB),NOSPLIT,$0
     82 	MOVQ	x+0(FP), AX
     83 	MOVQ	$~(1<<63), DX // sign bit mask
     84 	MOVQ	AX, BX // BX = copy of x
     85 	ANDQ    DX, BX // BX = |x|
     86 	MOVQ    $Big, CX // if |x| >= 2**52 or IsNaN(x), return x
     87 	CMPQ    BX, CX
     88 	JAE     isBig_trunc
     89 	MOVQ	AX, X0
     90 	MOVQ	DX, X2 // X2 = sign bit mask
     91 	CVTTSD2SQ	X0, AX
     92 	ANDNPD	X0, X2 // X2 = sign
     93 	CVTSQ2SD	AX, X0 // X0 = float(int(x))
     94 	ORPD	X2, X0 // if X0 = 0.0, incorporate sign
     95 	MOVSD	X0, ret+8(FP)
     96 	RET
     97 isBig_trunc:
     98 	MOVQ    AX, ret+8(FP) // return x
     99 	RET
    100