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 archFloor(x float64) float64
10TEXT ·archFloor(SB),NOSPLIT,$0
11	MOVQ	x+0(FP), AX
12	MOVQ	$~(1<<63), DX // sign bit mask
13	ANDQ	AX,DX // DX = |x|
14	SUBQ	$1,DX
15	MOVQ    $(Big - 1), CX // if |x| >= 2**52-1 or IsNaN(x) or |x| == 0, return x
16	CMPQ	DX,CX
17	JAE     isBig_floor
18	MOVQ	AX, X0 // X0 = x
19	CVTTSD2SQ	X0, AX
20	CVTSQ2SD	AX, X1 // X1 = float(int(x))
21	CMPSD	X1, X0, 1 // compare LT; X0 = 0xffffffffffffffff or 0
22	MOVSD	$(-1.0), X2
23	ANDPD	X2, X0 // if x < float(int(x)) {X0 = -1} else {X0 = 0}
24	ADDSD	X1, X0
25	MOVSD	X0, ret+8(FP)
26	RET
27isBig_floor:
28	MOVQ    AX, ret+8(FP) // return x
29	RET
30
31// func archCeil(x float64) float64
32TEXT ·archCeil(SB),NOSPLIT,$0
33	MOVQ	x+0(FP), AX
34	MOVQ	$~(1<<63), DX // sign bit mask
35	MOVQ	AX, BX // BX = copy of x
36	ANDQ    DX, BX // BX = |x|
37	MOVQ    $Big, CX // if |x| >= 2**52 or IsNaN(x), return x
38	CMPQ    BX, CX
39	JAE     isBig_ceil
40	MOVQ	AX, X0 // X0 = x
41	MOVQ	DX, X2 // X2 = sign bit mask
42	CVTTSD2SQ	X0, AX
43	ANDNPD	X0, X2 // X2 = sign
44	CVTSQ2SD	AX, X1	// X1 = float(int(x))
45	CMPSD	X1, X0, 2 // compare LE; X0 = 0xffffffffffffffff or 0
46	ORPD	X2, X1 // if X1 = 0.0, incorporate sign
47	MOVSD	$1.0, X3
48	ANDNPD	X3, X0
49	ORPD	X2, X0 // if float(int(x)) <= x {X0 = 1} else {X0 = -0}
50	ADDSD	X1, X0
51	MOVSD	X0, ret+8(FP)
52	RET
53isBig_ceil:
54	MOVQ	AX, ret+8(FP)
55	RET
56
57// func archTrunc(x float64) float64
58TEXT ·archTrunc(SB),NOSPLIT,$0
59	MOVQ	x+0(FP), AX
60	MOVQ	$~(1<<63), DX // sign bit mask
61	MOVQ	AX, BX // BX = copy of x
62	ANDQ    DX, BX // BX = |x|
63	MOVQ    $Big, CX // if |x| >= 2**52 or IsNaN(x), return x
64	CMPQ    BX, CX
65	JAE     isBig_trunc
66	MOVQ	AX, X0
67	MOVQ	DX, X2 // X2 = sign bit mask
68	CVTTSD2SQ	X0, AX
69	ANDNPD	X0, X2 // X2 = sign
70	CVTSQ2SD	AX, X0 // X0 = float(int(x))
71	ORPD	X2, X0 // if X0 = 0.0, incorporate sign
72	MOVSD	X0, ret+8(FP)
73	RET
74isBig_trunc:
75	MOVQ    AX, ret+8(FP) // return x
76	RET
77