diff options
Diffstat (limited to 'private/fp32/tran/alpha/floors.s')
-rw-r--r-- | private/fp32/tran/alpha/floors.s | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/private/fp32/tran/alpha/floors.s b/private/fp32/tran/alpha/floors.s new file mode 100644 index 000000000..8406e6b17 --- /dev/null +++ b/private/fp32/tran/alpha/floors.s @@ -0,0 +1,161 @@ +// TITLE("Alpha AXP floor") +//++ +// +// Copyright (c) 1993, 1994 Digital Equipment Corporation +// +// Module Name: +// +// floor.s +// +// Abstract: +// +// This module implements a high-performance Alpha AXP specific routine +// for IEEE double format floor. +// +// Author: +// +// Bill Gray +// +// Environment: +// +// User mode. +// +// Revision History: +// +// Thomas Van Baak (tvb) 15-Apr-1994 +// +// Adapted for NT. +// +//-- + +#include "ksalpha.h" + + +// +// Define stack frame. +// + + .struct 0 +Temp: .space 8 // save argument + .space 8 // for 16-byte stack alignment +FrameLength: + +// +// Define lower and upper 32-bit parts of 64-bit double. +// + +#define LowPart 0x0 +#define HighPart 0x4 + + SBTTL("floor") + +//++ +// +// double +// floor ( +// IN double x +// ) +// +// Routine Description: +// +// This function returns the floor of the given double argument. +// +// Arguments: +// +// x (f16) - Supplies the argument value. +// +// Return Value: +// +// The double floor result is returned as the function value in f0. +// +//-- + + NESTED_ENTRY(floor, FrameLength, ra) + + lda sp, -FrameLength(sp) // allocate stack frame + + PROLOGUE_END + + ldah t0, 0x7ff0(zero) // exp mask + ldt f0, two_to_52 // get big + ldah t1, 0x10(zero) // one in exp field + stt f16, Temp(sp) + ldl v0, Temp + HighPart(sp) + cpys f16, f0, f1 // fix sign of big + cpys f16, f16, f0 + and v0, t0, t0 + subl t0, t1, t0 + ldt f10, neg_one + ldah t1, 0x4320(zero) // cutoff value + cmpult t0, t1, t0 + beq t0, quick_out + +// Add big, sub big to round to int. + + addt f16, f1, f11 + subt f11, f1, f1 + cmptlt f0, f1, f0 + fbeq f0, it_rounded_down + +// It rounded up so subtract one. + + ldt f10, one + subt f1, f10, f1 + +it_rounded_down: + cpys f1, f1, f0 + br zero, done + + +// Value is abnormal (or too big). +// If it is zero or denorm, figure out +// whether to return 0.0 or -1.0 -- if +// value is too big, just return it. + +quick_out: + ldah t1, 0x7ff0(zero) + ldah t2, -0x8000(zero) + and v0, t1, t0 + and v0, t2, v0 + bne t0, ret_arg + ldah t0, 0x10(zero) + beq v0, ret_zero + stt f16, Temp(sp) + ldl v0, Temp(sp) + lda t0, -1(t0) + ldl t2, Temp + HighPart(sp) + cpys f10, f10, f16 + and t2, t0, t0 + bis t0, v0, v0 + and t2, t1, t1 + cmpult zero, v0, v0 + cmpeq t1, zero, t1 + beq t1, ret_zero + and t1, v0, t1 + beq t1, ret_zero + br zero, ret_arg + +ret_zero: + cpys f31, f31, f16 + +ret_arg: + cpys f16, f16, f0 + +done: + lda sp, FrameLength(sp) // deallocate stack frame + + ret zero, (ra) + + .end floor + + .align 3 + .rdata + +one: + .quad 0x3ff0000000000000 // 1.0 + +neg_one: + .quad 0xbff0000000000000 // -(1.0) + +two_to_52: + .quad 0x4330000000000000 // 2^52 (4503599627370496.0) |