1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 23 */ 24 /* 25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 .file "rndintl.s" 30 31 #include "libm.h" 32 LIBM_ANSI_PRAGMA_WEAK(aintl,function) 33 LIBM_ANSI_PRAGMA_WEAK(irintl,function) 34 LIBM_ANSI_PRAGMA_WEAK(anintl,function) 35 LIBM_ANSI_PRAGMA_WEAK(nintl,function) 36 #include "libm_synonyms.h" 37 38 #undef fabs 39 40 ENTRY(aintl) 41 movq %rsp,%rax 42 subq $16,%rsp 43 fstcw -8(%rax) 44 fldt 8(%rax) 45 movw -8(%rax),%cx 46 orw $0x0c00,%cx 47 movw %cx,-4(%rax) 48 fldcw -4(%rax) / set RD = to_zero 49 frndint 50 fstcw -4(%rax) 51 movw -4(%rax),%dx 52 andw $0xf3ff,%dx 53 movw -8(%rax),%cx 54 andw $0x0c00,%cx 55 orw %dx,%cx 56 movw %cx,-8(%rax) 57 fldcw -8(%rax) / restore RD 58 addq $16,%rsp 59 ret 60 .align 16 61 SET_SIZE(aintl) 62 63 ENTRY(irintl) 64 movq %rsp,%rcx 65 subq $16,%rsp 66 fldt 8(%rcx) / load x 67 fistpl -8(%rcx) / [x] 68 fwait 69 movslq -8(%rcx),%rax 70 addq $16,%rsp 71 ret 72 .align 16 73 SET_SIZE(irintl) 74 75 .data 76 .align 16 77 half: .float 0.5 78 79 ENTRY(anintl) 80 .Lanintl: 81 movq %rsp,%rcx 82 subq $16,%rsp 83 fstcw -8(%rcx) 84 fldt 8(%rcx) 85 movw -8(%rcx),%dx 86 andw $0xf3ff,%dx 87 movw %dx,-4(%rcx) 88 fldcw -4(%rcx) / set RD = to_nearest 89 fld %st(0) 90 frndint / [x],x 91 fstcw -4(%rcx) 92 movw -4(%rcx),%dx 93 andw $0xf3ff,%dx 94 movw -8(%rcx),%ax 95 andw $0x0c00,%ax 96 orw %dx,%ax 97 movw %ax,-8(%rcx) 98 fldcw -8(%rcx) / restore RD 99 fucomi %st(1),%st / check if x is already an integer 100 jp .L0 101 je .L0 102 fxch / x,[x] 103 fsub %st(1),%st / x-[x],[x] 104 fabs / |x-[x]|,[x] 105 PIC_SETUP(1) 106 flds PIC_L(half) 107 fcomip %st(1),%st / compare 0.5 with |x-[x]| 108 PIC_WRAPUP 109 je .halfway / if 0.5 = |x-[x]| goto halfway, 110 / most cases will not take branch. 111 .L0: 112 addq $16,%rsp 113 fstp %st(0) 114 ret 115 .halfway: 116 / x = n+0.5, recompute anint(x) as x+sign(x)*0.5 117 fldt 8(%rcx) / x, 0.5, [x] 118 movw 16(%rcx),%ax / sign+exp part of x 119 andw $0x8000,%ax / look at sign bit 120 jnz .x_neg 121 faddp 122 addq $16,%rsp 123 fstp %st(1) 124 ret 125 .x_neg: 126 / here, x is negative, so return x-0.5 127 fsubp %st,%st(1) / x-0.5,[x] 128 addq $16,%rsp 129 fstp %st(1) 130 ret 131 .align 16 132 SET_SIZE(anintl) 133 134 ENTRY(nintl) 135 pushq %rbp 136 movq %rsp,%rbp 137 subq $16,%rsp 138 pushq 24(%rbp) 139 pushq 16(%rbp) 140 call .Lanintl /// LOCAL 141 fistpl -8(%rbp) 142 fwait 143 movslq -8(%rbp),%rax 144 leave 145 ret 146 .align 16 147 SET_SIZE(nintl)