summaryrefslogtreecommitdiffstats
path: root/private/fp32/tran/alpha/floors.s
diff options
context:
space:
mode:
Diffstat (limited to 'private/fp32/tran/alpha/floors.s')
-rw-r--r--private/fp32/tran/alpha/floors.s161
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)