o IEEE 754 floating-point completion code.
o Implement the architected FP_C "Floating Point Control Quadword"
This commit is contained in:
parent
8032753ad3
commit
2df695b1e4
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: db_instruction.h,v 1.6 2000/03/20 02:54:45 thorpej Exp $ */
|
||||
/* $NetBSD: db_instruction.h,v 1.7 2001/04/26 03:10:44 ross Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
|
||||
@ -184,6 +184,16 @@ typedef union {
|
||||
opcode : 6;
|
||||
} float_format;
|
||||
|
||||
struct {
|
||||
unsigned fc : 5,
|
||||
opclass : 4,
|
||||
src : 2,
|
||||
rnd : 2,
|
||||
trp : 3,
|
||||
fb : 5,
|
||||
fa : 5,
|
||||
opcode : 6;
|
||||
} float_detail;
|
||||
|
||||
/*
|
||||
* PAL instructions just define the major opcode
|
||||
@ -221,7 +231,7 @@ typedef union {
|
||||
#define op_logical 0x11 /* see LOGICAL sub-table */
|
||||
#define op_bit 0x12 /* see BIT sub-table */
|
||||
#define op_mul 0x13 /* see MUL sub-table */
|
||||
/* reserved */
|
||||
#define op_fix_float 0x14 /* if ALPHA_AMASK_FIX */
|
||||
#define op_vax_float 0x15 /* see FLOAT sub-table */
|
||||
#define op_ieee_float 0x16 /* see FLOAT sub-table */
|
||||
#define op_any_float 0x17 /* see FLOAT sub-table */
|
||||
@ -411,6 +421,12 @@ typedef union {
|
||||
* Load and store operations use opcodes op_ldf..op_stt
|
||||
*/
|
||||
|
||||
/* src encoding from function, 9..10 */
|
||||
#define op_src_sf 0
|
||||
#define op_src_xd 1
|
||||
#define op_src_tg 2
|
||||
#define op_src_qq 3
|
||||
|
||||
/* any FLOAT, "function" opcodes (bits 5..11) */
|
||||
|
||||
#define op_cvtlq 0x010
|
||||
@ -427,7 +443,7 @@ typedef union {
|
||||
#define op_fcmovgt 0x02f
|
||||
#define op_cvtql 0x030
|
||||
#define op_cvtql_v 0x130
|
||||
#define op_cvtql_sv 0x330
|
||||
#define op_cvtql_sv 0x530
|
||||
|
||||
|
||||
/* ieee FLOAT, "function" opcodes (bits 5..11) */
|
||||
@ -520,6 +536,7 @@ typedef union {
|
||||
#define op_mult_ud 0x1e2
|
||||
#define op_divt_ud 0x1e3
|
||||
#define op_cvtts_ud 0x1ec
|
||||
#define op_cvtst 0x2ac
|
||||
#define op_adds_suc 0x500
|
||||
#define op_subs_suc 0x501
|
||||
#define op_muls_suc 0x502
|
||||
@ -562,6 +579,7 @@ typedef union {
|
||||
#define op_mult_sud 0x5e2
|
||||
#define op_divt_sud 0x5e3
|
||||
#define op_cvtts_sud 0x5ec
|
||||
#define op_cvtst_u 0x6ac
|
||||
#define op_adds_suic 0x700
|
||||
#define op_subs_suic 0x701
|
||||
#define op_muls_suic 0x702
|
||||
|
@ -1 +1,714 @@
|
||||
/* $NetBSD: fp_complete.c,v 1.1 2001/04/22 20:47:22 ross Exp $ */
|
||||
/* $NetBSD: fp_complete.c,v 1.2 2001/04/26 03:10:44 ross Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 Ross Harvey
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: fp_complete.c,v 1.2 2001/04/26 03:10:44 ross Exp $");
|
||||
|
||||
#include "opt_compat_osf1.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#ifdef COMPAT_OSF1
|
||||
#include <compat/osf1/osf1_exec.h>
|
||||
#endif
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/fpu.h>
|
||||
#include <machine/reg.h>
|
||||
#include <machine/alpha.h>
|
||||
#include <alpha/alpha/db_instruction.h>
|
||||
|
||||
#include <lib/libkern/softfloat.h>
|
||||
|
||||
#define TSWINSIZE 4 /* size of trap shadow window in u_int32_t units */
|
||||
|
||||
/* Set Name Opcodes AARM C.* Symbols */
|
||||
|
||||
#define CPUREG_CLASS (0xfUL << 0x10) /* INT[ALSM] */
|
||||
#define FPUREG_CLASS (0xfUL << 0x14) /* ITFP, FLT[ILV] */
|
||||
#define CHECKFUNCTIONCODE (1UL << 0x18) /* MISC */
|
||||
#define TRAPSHADOWBOUNDARY (1UL << 0x00 | /* PAL */\
|
||||
1UL << 0x19 | /* \PAL\ */\
|
||||
1UL << 0x1a | /* JSR */\
|
||||
1UL << 0x1b | /* \PAL\ */\
|
||||
1UL << 0x1d | /* \PAL\ */\
|
||||
1UL << 0x1e | /* \PAL\ */\
|
||||
1UL << 0x1f | /* \PAL\ */\
|
||||
0xffffUL << 0x30 | /* branch ops */\
|
||||
CHECKFUNCTIONCODE)
|
||||
|
||||
#define MAKE_FLOATXX(width, expwidth, sign, exp, msb, rest_of_frac) \
|
||||
(u_int ## width ## _t)(sign) << ((width) - 1) |\
|
||||
(u_int ## width ## _t)(exp) << ((width) - 1 - (expwidth)) |\
|
||||
(u_int ## width ## _t)(msb) << ((width) - 1 - (expwidth) - 1) |\
|
||||
(u_int ## width ## _t)(rest_of_frac)
|
||||
|
||||
#define FLOAT32QNAN MAKE_FLOATXX(32, 8, 0, 0xff, 1, 0)
|
||||
#define FLOAT64QNAN MAKE_FLOATXX(64, 11, 0, 0x7ff, 1, 0)
|
||||
|
||||
#define IS_SUBNORMAL(v) ((v)->exp == 0 && (v)->frac != 0)
|
||||
|
||||
#define PREFILTER_SUBNORMAL(p,v) if ((p)->p_md.md_flags & IEEE_MAP_DMZ \
|
||||
&& IS_SUBNORMAL(v)) \
|
||||
(v)->frac = 0; else
|
||||
|
||||
#define POSTFILTER_SUBNORMAL(p,v) if ((p)->p_md.md_flags & IEEE_MAP_UMZ \
|
||||
&& IS_SUBNORMAL(v)) \
|
||||
(v)->frac = 0; else
|
||||
|
||||
/* Alpha returns 2.0 for true, all zeroes for false. */
|
||||
|
||||
#define CMP_RESULT(flag) ((flag) ? 4UL << 60 : 0L)
|
||||
|
||||
/* Move bits from sw fp_c to hw fpcr. */
|
||||
|
||||
#define CRBLIT(sw, hw, m, offs) (((sw) & ~(m)) | ((hw) >> (offs) & (m)))
|
||||
|
||||
/*
|
||||
* Temporary trap shadow instrumentation. The [un]resolved counters
|
||||
* could be kept permanently, as they provide information on whether
|
||||
* user code has met AARM trap shadow generation requirements.
|
||||
*/
|
||||
|
||||
struct alpha_shadow {
|
||||
u_int64_t resolved; /* cases trigger pc found */
|
||||
u_int64_t unresolved; /* cases it wasn't, code problems? */
|
||||
u_int64_t scans; /* trap shadow scans */
|
||||
u_int64_t len; /* number of instructions examined */
|
||||
u_int64_t uop; /* bit mask of unexpected opcodes */
|
||||
u_int64_t sqrts; /* ev6+ square root single count */
|
||||
u_int64_t sqrtt; /* ev6+ square root double count */
|
||||
u_int32_t ufunc; /* bit mask of unexpected functions */
|
||||
u_int32_t max; /* max trap shadow scan */
|
||||
u_int32_t nilswop; /* unexpected op codes */
|
||||
u_int32_t nilswfunc; /* unexpected function codes */
|
||||
u_int32_t nilanyop; /* this "cannot happen" */
|
||||
u_int32_t vax; /* sigs from vax fp opcodes */
|
||||
} alpha_shadow, alpha_shadow_zero;
|
||||
|
||||
static float64 float64_unk(float64, float64);
|
||||
static float64 compare_un(float64, float64);
|
||||
static float64 compare_eq(float64, float64);
|
||||
static float64 compare_lt(float64, float64);
|
||||
static float64 compare_le(float64, float64);
|
||||
static void cvt_qs_ts_st_gf_qf(u_int32_t, struct proc *);
|
||||
static void cvt_gd(u_int32_t, struct proc *);
|
||||
static void cvt_qt_dg_qg(u_int32_t, struct proc *);
|
||||
static void cvt_tq_gq(u_int32_t, struct proc *);
|
||||
|
||||
static float32 (*swfp_s[])(float32, float32) = {
|
||||
float32_add, float32_sub, float32_mul, float32_div,
|
||||
};
|
||||
|
||||
static float64 (*swfp_t[])(float64, float64) = {
|
||||
float64_add, float64_sub, float64_mul, float64_div,
|
||||
compare_un, compare_eq, compare_lt, compare_le,
|
||||
float64_unk, float64_unk, float64_unk, float64_unk
|
||||
};
|
||||
|
||||
static void (*swfp_cvt[])(u_int32_t, struct proc *) = {
|
||||
cvt_qs_ts_st_gf_qf, cvt_gd, cvt_qt_dg_qg, cvt_tq_gq
|
||||
};
|
||||
|
||||
static void
|
||||
this_cannot_happen(int what_cannot_happen, int64_t bits)
|
||||
{
|
||||
static int total;
|
||||
alpha_instruction inst;
|
||||
static u_int64_t reported;
|
||||
|
||||
inst.bits = bits;
|
||||
++alpha_shadow.nilswfunc;
|
||||
if (bits != -1)
|
||||
alpha_shadow.uop |= 1UL << inst.generic_format.opcode;
|
||||
if (1UL << what_cannot_happen & reported)
|
||||
return;
|
||||
reported |= 1UL << what_cannot_happen;
|
||||
if (total >= 1000)
|
||||
return; /* right now, this return "cannot happen" */
|
||||
++total;
|
||||
if (bits)
|
||||
printf("FP instruction %x\n", (unsigned int)bits);
|
||||
printf("FP event %d/%lx/%lx\n", what_cannot_happen, reported,
|
||||
alpha_shadow.uop);
|
||||
printf("Please report this to port-alpha-maintainer@netbsd.org\n");
|
||||
}
|
||||
|
||||
static __inline void
|
||||
sts(unsigned int rn, s_float *v, struct proc *p)
|
||||
{
|
||||
alpha_sts(rn, v);
|
||||
PREFILTER_SUBNORMAL(p, v);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
stt(unsigned int rn, t_float *v, struct proc *p)
|
||||
{
|
||||
alpha_stt(rn, v);
|
||||
PREFILTER_SUBNORMAL(p, v);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
lds(unsigned int rn, s_float *v, struct proc *p)
|
||||
{
|
||||
POSTFILTER_SUBNORMAL(p, v);
|
||||
alpha_lds(rn, v);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
ldt(unsigned int rn, t_float *v, struct proc *p)
|
||||
{
|
||||
POSTFILTER_SUBNORMAL(p, v);
|
||||
alpha_ldt(rn, v);
|
||||
}
|
||||
|
||||
static float64
|
||||
compare_lt(float64 a, float64 b)
|
||||
{
|
||||
return CMP_RESULT(float64_lt(a, b));
|
||||
}
|
||||
|
||||
static float64
|
||||
compare_le(float64 a, float64 b)
|
||||
{
|
||||
return CMP_RESULT(float64_le(a, b));
|
||||
}
|
||||
|
||||
static float64
|
||||
compare_un(float64 a, float64 b)
|
||||
{
|
||||
if (float64_is_nan(a) | float64_is_nan(b)) {
|
||||
if (float64_is_signaling_nan(a) | float64_is_signaling_nan(b))
|
||||
float_set_invalid();
|
||||
return CMP_RESULT(1);
|
||||
}
|
||||
return CMP_RESULT(0);
|
||||
}
|
||||
|
||||
static float64
|
||||
compare_eq(float64 a, float64 b)
|
||||
{
|
||||
return CMP_RESULT(float64_eq(a, b));
|
||||
}
|
||||
/*
|
||||
* A note regarding the VAX FP ops.
|
||||
*
|
||||
* The AARM gives us completely leeway to set or not set status flags on VAX
|
||||
* ops, but we do any subnorm, NaN and dirty zero fixups anyway, and we set
|
||||
* flags by IEEE rules. Many ops are common to d/f/g and s/t source types.
|
||||
* For the purely vax ones, it's hard to imagine ever running them.
|
||||
* (Generated VAX fp ops with completion flags? Hmm.) We are careful never
|
||||
* to panic, assert, or print unlimited output based on a path through the
|
||||
* decoder, so wierd cases don't become security issues.
|
||||
*/
|
||||
static void
|
||||
cvt_qs_ts_st_gf_qf(u_int32_t inst_bits, struct proc *p)
|
||||
{
|
||||
t_float tfb, tfc;
|
||||
s_float sfb, sfc;
|
||||
alpha_instruction inst;
|
||||
|
||||
inst.bits = inst_bits;
|
||||
/*
|
||||
* cvtst and cvtts have the same opcode, function, and source. The
|
||||
* distinction for cvtst is hidden in the illegal modifier combinations.
|
||||
* We decode even the non-/s modifier, so that the fix-up-always mode
|
||||
* works on ev6 and later. The rounding bits are unused and fixed for
|
||||
* cvtst, so we check those too.
|
||||
*/
|
||||
switch(inst.float_format.function) {
|
||||
case op_cvtst:
|
||||
case op_cvtst_u:
|
||||
sts(inst.float_detail.fb, &sfb, p);
|
||||
tfc.i = float32_to_float64(sfb.i);
|
||||
ldt(inst.float_detail.fc, &tfc, p);
|
||||
return;
|
||||
}
|
||||
if(inst.float_detail.src == 2) {
|
||||
stt(inst.float_detail.fb, &tfb, p);
|
||||
sfc.i = float64_to_float32(tfb.i);
|
||||
lds(inst.float_detail.fc, &sfc, p);
|
||||
return;
|
||||
}
|
||||
/* 0: S/F */
|
||||
/* 1: /D */
|
||||
/* 3: Q/Q */
|
||||
this_cannot_happen(5, inst.generic_format.opcode);
|
||||
tfc.i = FLOAT64QNAN;
|
||||
ldt(inst.float_detail.fc, &tfc, p);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
cvt_gd(u_int32_t inst_bits, struct proc *p)
|
||||
{
|
||||
t_float tfb, tfc;
|
||||
alpha_instruction inst;
|
||||
|
||||
inst.bits = inst_bits;
|
||||
stt(inst.float_detail.fb, &tfb, p);
|
||||
(void) float64_to_float32(tfb.i);
|
||||
p->p_md.md_flags &= ~NETBSD_FLAG_TO_FP_C(FP_X_IMP);
|
||||
tfc.i = float64_add(tfb.i, (float64)0);
|
||||
ldt(inst.float_detail.fc, &tfc, p);
|
||||
}
|
||||
|
||||
static void
|
||||
cvt_qt_dg_qg(u_int32_t inst_bits, struct proc *p)
|
||||
{
|
||||
t_float tfb, tfc;
|
||||
alpha_instruction inst;
|
||||
|
||||
inst.bits = inst_bits;
|
||||
switch(inst.float_detail.src) {
|
||||
case 0: /* S/F */
|
||||
this_cannot_happen(3, inst.bits);
|
||||
/* fall thru */
|
||||
case 1: /* D */
|
||||
/* VAX dirty 0's and reserved ops => UNPREDICTABLE */
|
||||
/* We've done what's important by just not trapping */
|
||||
tfc.i = 0;
|
||||
break;
|
||||
case 2: /* T/G */
|
||||
this_cannot_happen(4, inst.bits);
|
||||
tfc.i = 0;
|
||||
break;
|
||||
case 3: /* Q/Q */
|
||||
stt(inst.float_detail.fb, &tfb, p);
|
||||
tfc.i = int64_to_float64(tfb.i);
|
||||
break;
|
||||
}
|
||||
alpha_ldt(inst.float_detail.fc, &tfc);
|
||||
}
|
||||
/*
|
||||
* XXX: AARM and 754 seem to disagree here, also, beware of softfloat's
|
||||
* unfortunate habit of always returning the nontrapping result.
|
||||
* XXX: there are several apparent AARM/AAH disagreements, as well as
|
||||
* the issue of trap handler pc and trapping results.
|
||||
*/
|
||||
static void
|
||||
cvt_tq_gq(u_int32_t inst_bits, struct proc *p)
|
||||
{
|
||||
t_float tfb, tfc;
|
||||
alpha_instruction inst;
|
||||
|
||||
inst.bits = inst_bits;
|
||||
stt(inst.float_detail.fb, &tfb, p);
|
||||
tfc.i = float64_to_int64(tfb.i);
|
||||
alpha_ldt(inst.float_detail.fc, &tfc); /* yes, ldt */
|
||||
}
|
||||
|
||||
static u_int64_t
|
||||
fp_c_to_fpcr_1(u_int64_t fpcr, u_int64_t fp_c)
|
||||
{
|
||||
u_int64_t disables;
|
||||
|
||||
/*
|
||||
* It's hard to arrange for conforming bit fields, because the FP_C
|
||||
* and the FPCR are both architected, with specified (and relatively
|
||||
* scrambled) bit numbers. Defining an internal unscrambled FP_C
|
||||
* wouldn't help much, because every user exception requires the
|
||||
* architected bit order in the sigcontext.
|
||||
*
|
||||
* Programs that fiddle with the fpcr exception bits (instead of fp_c)
|
||||
* will lose, because those bits can be and usually are subsetted;
|
||||
* the official home is in the fp_c. Furthermore, the kernel puts
|
||||
* phony enables (it lies :-) in the fpcr in order to get control when
|
||||
* it is necessary to initially set a sticky bit.
|
||||
*/
|
||||
|
||||
fpcr &= FPCR_DYN(3);
|
||||
|
||||
/*
|
||||
* enable traps = case where flag bit is clear OR program wants a trap
|
||||
* enables = ~flags | mask
|
||||
* disables = ~(~flags | mask)
|
||||
* disables = flags & ~mask. Thank you, Augustus De Morgan (1806-1871)
|
||||
*/
|
||||
disables = FP_C_TO_NETBSD_FLAG(fp_c) & ~FP_C_TO_NETBSD_MASK(fp_c);
|
||||
|
||||
fpcr |= (disables & (FP_X_IMP | FP_X_UFL)) << (61 - 3);
|
||||
fpcr |= (disables & (FP_X_OFL | FP_X_DZ | FP_X_INV)) << (49 - 0);
|
||||
|
||||
# if !(FP_X_INV == 1 && FP_X_DZ == 2 && FP_X_OFL == 4 && \
|
||||
FP_X_UFL == 8 && FP_X_IMP == 16 && FP_X_IOV == 32 && \
|
||||
FP_X_UFL << (61 - 3) == FPCR_UNFD && \
|
||||
FP_X_IMP << (61 - 3) == FPCR_INED && \
|
||||
FP_X_OFL << (49 - 0) == FPCR_OVFD)
|
||||
# error "Assertion failed"
|
||||
/*
|
||||
* We don't care about the other built-in bit numbers because they
|
||||
* have been architecturally specified.
|
||||
*/
|
||||
# endif
|
||||
|
||||
fpcr |= fp_c & FP_C_MIRRORED << (FPCR_MIR_START - FP_C_MIR_START);
|
||||
fpcr |= (fp_c & IEEE_MAP_DMZ) << 36;
|
||||
if (fp_c & FP_C_MIRRORED)
|
||||
fpcr |= FPCR_SUM;
|
||||
if (fp_c & IEEE_MAP_UMZ)
|
||||
fpcr |= FPCR_UNDZ | FPCR_UNFD;
|
||||
fpcr |= (~fp_c & IEEE_TRAP_ENABLE_DNO) << 41;
|
||||
return fpcr;
|
||||
}
|
||||
|
||||
static void
|
||||
fp_c_to_fpcr(struct proc *p)
|
||||
{
|
||||
alpha_write_fpcr(fp_c_to_fpcr_1(alpha_read_fpcr(), p->p_md.md_flags));
|
||||
}
|
||||
|
||||
void
|
||||
alpha_write_fp_c(struct proc *p, u_int64_t fp_c)
|
||||
{
|
||||
u_int64_t md_flags;
|
||||
|
||||
fp_c &= MDP_FP_C;
|
||||
md_flags = p->p_md.md_flags;
|
||||
if ((md_flags & MDP_FP_C) == fp_c)
|
||||
return;
|
||||
p->p_md.md_flags = (md_flags & ~MDP_FP_C) | fp_c;
|
||||
alpha_enable_fp(p, 1);
|
||||
fp_c_to_fpcr(p);
|
||||
alpha_pal_wrfen(0);
|
||||
}
|
||||
|
||||
u_int64_t
|
||||
alpha_read_fp_c(struct proc *p)
|
||||
{
|
||||
/*
|
||||
* A possibly-desireable EV6-specific optimization would deviate from
|
||||
* the Alpha Architecture spec and keep some FP_C bits in the FPCR,
|
||||
* but in a transparent way. Some of the code for that would need to
|
||||
* go right here.
|
||||
*/
|
||||
return p->p_md.md_flags & MDP_FP_C;
|
||||
}
|
||||
|
||||
static float64
|
||||
float64_unk(float64 a, float64 b)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The real function field encodings for IEEE and VAX FP instructions.
|
||||
*
|
||||
* Since there is only one operand type field, the cvtXX instructions
|
||||
* require a variety of special cases, and these have to be analyzed as
|
||||
* they don't always fit into the field descriptions in AARM section I.
|
||||
*
|
||||
* Lots of staring at bits in the appendix shows what's really going on.
|
||||
*
|
||||
* | |
|
||||
* 15 14 13|12 11 10 09|08 07 06 05
|
||||
* --------======------============
|
||||
* TRAP : RND : SRC : FUNCTION :
|
||||
* 0 0 0:. . .:. . . . . . . . . . . . Imprecise
|
||||
* 0 0 1|. . .:. . . . . . . . . . . ./U underflow enable (if FP output)
|
||||
* | /V overfloat enable (if int output)
|
||||
* 0 1 0:. . .:. . . . . . . . . . . ."Unsupported", but used for CVTST
|
||||
* 0 1 1|. . .:. . . . . . . . . . . . Unsupported
|
||||
* 1 0 0:. . .:. . . . . . . . . . . ./S software completion (VAX only)
|
||||
* 1 0 1|. . .:. . . . . . . . . . . ./SU
|
||||
* | /SV
|
||||
* 1 1 0:. . .:. . . . . . . . . . . ."Unsupported", but used for CVTST/S
|
||||
* 1 1 1|. . .:. . . . . . . . . . . ./SUI (if FP output) (IEEE only)
|
||||
* | /SVI (if int output) (IEEE only)
|
||||
* S I UV: In other words: bits 15:13 are S:I:UV, except that _usually_
|
||||
* | not all combinations are valid.
|
||||
* | |
|
||||
* 15 14 13|12 11 10 09|08 07 06 05
|
||||
* --------======------============
|
||||
* TRAP : RND : SRC : FUNCTION :
|
||||
* | 0 0 . . . . . . . . . . . ./C Chopped
|
||||
* : 0 1 . . . . . . . . . . . ./M Minus Infinity
|
||||
* | 1 0 . . . . . . . . . . . . Normal
|
||||
* : 1 1 . . . . . . . . . . . ./D Dynamic (in FPCR: Plus Infinity)
|
||||
* | |
|
||||
* 15 14 13|12 11 10 09|08 07 06 05
|
||||
* --------======------============
|
||||
* TRAP : RND : SRC : FUNCTION :
|
||||
* 0 0. . . . . . . . . . S/F
|
||||
* 0 1. . . . . . . . . . -/D
|
||||
* 1 0. . . . . . . . . . T/G
|
||||
* 1 1. . . . . . . . . . Q/Q
|
||||
* | |
|
||||
* 15 14 13|12 11 10 09|08 07 06 05
|
||||
* --------======------============
|
||||
* TRAP : RND : SRC : FUNCTION :
|
||||
* 0 0 0 0 . . . addX
|
||||
* 0 0 0 1 . . . subX
|
||||
* 0 0 1 0 . . . mulX
|
||||
* 0 0 1 1 . . . divX
|
||||
* 0 1 0 0 . . . cmpXun
|
||||
* 0 1 0 1 . . . cmpXeq
|
||||
* 0 1 1 0 . . . cmpXlt
|
||||
* 0 1 1 1 . . . cmpXle
|
||||
* 1 0 0 0 . . . reserved
|
||||
* 1 0 0 1 . . . reserved
|
||||
* 1 0 1 0 . . . sqrt[fg] (op_fix, not exactly "vax")
|
||||
* 1 0 1 1 . . . sqrt[st] (op_fix, not exactly "ieee")
|
||||
* 1 1 0 0 . . . cvtXs/f (cvt[qt]s, cvtst(!), cvt[gq]f)
|
||||
* 1 1 0 1 . . . cvtXd (vax only)
|
||||
* 1 1 1 0 . . . cvtXt/g (cvtqt, cvt[dq]g only)
|
||||
* 1 1 1 1 . . . cvtXq/q (cvttq, cvtgq)
|
||||
* | |
|
||||
* 15 14 13|12 11 10 09|08 07 06 05 the twilight zone
|
||||
* --------======------============
|
||||
* TRAP : RND : SRC : FUNCTION :
|
||||
* /s /i /u x x 1 0 1 1 0 0 . . . cvtts, /siu only 0, 1, 5, 7
|
||||
* 0 1 0 1 0 1 0 1 1 0 0 . . . cvtst (src == T (!)) 2ac NOT /S
|
||||
* 1 1 0 1 0 1 0 1 1 0 0 . . . cvtst/s (src == T (!)) 6ac
|
||||
* x 0 x x x x 0 1 1 1 1 . . . cvttq/_ (src == T)
|
||||
*/
|
||||
|
||||
static void
|
||||
alpha_fp_interpret(alpha_instruction *pc, struct proc *p, u_int64_t bits)
|
||||
{
|
||||
s_float sfa, sfb, sfc;
|
||||
t_float tfa, tfb, tfc;
|
||||
alpha_instruction inst;
|
||||
|
||||
inst.bits = bits;
|
||||
switch(inst.generic_format.opcode) {
|
||||
default:
|
||||
/* this "cannot happen" */
|
||||
this_cannot_happen(2, inst.bits);
|
||||
return;
|
||||
case op_any_float:
|
||||
/* HW supplies result, we supply sticky bit and maybe trap */
|
||||
if (inst.float_format.function == op_cvtql_sv ||
|
||||
inst.float_format.function == op_cvtql_v) {
|
||||
alpha_stt(inst.float_detail.fb, &tfb);
|
||||
sfc.i = (int64_t)tfb.i >= 0L ? INT_MAX : INT_MIN;
|
||||
alpha_lds(inst.float_detail.fc, &sfc);
|
||||
float_raise(FP_X_INV);
|
||||
} else {
|
||||
++alpha_shadow.nilanyop;
|
||||
this_cannot_happen(3, inst.bits);
|
||||
}
|
||||
break;
|
||||
case op_vax_float:
|
||||
++alpha_shadow.vax; /* fall thru */
|
||||
case op_ieee_float:
|
||||
case op_fix_float:
|
||||
switch(inst.float_detail.src) {
|
||||
case op_src_sf:
|
||||
sts(inst.float_detail.fb, &sfb, p);
|
||||
if (inst.float_detail.opclass == 10)
|
||||
sfc.i = float32_sqrt(sfb.i);
|
||||
else if (inst.float_detail.opclass & ~3) {
|
||||
this_cannot_happen(1, inst.bits);
|
||||
sfc.i = FLOAT32QNAN;
|
||||
} else {
|
||||
sts(inst.float_detail.fa, &sfa, p);
|
||||
sfc.i = (*swfp_s[inst.float_detail.opclass])(
|
||||
sfa.i, sfb.i);
|
||||
}
|
||||
lds(inst.float_detail.fc, &sfc, p);
|
||||
break;
|
||||
case op_src_xd:
|
||||
case op_src_tg:
|
||||
if (inst.float_detail.opclass >= 12)
|
||||
(*swfp_cvt[inst.float_detail.opclass - 12])(
|
||||
inst.bits, p);
|
||||
else {
|
||||
stt(inst.float_detail.fb, &tfb, p);
|
||||
if (inst.float_detail.opclass == 10)
|
||||
tfc.i = float64_sqrt(tfb.i);
|
||||
else {
|
||||
stt(inst.float_detail.fa, &tfa, p);
|
||||
tfc.i = (*swfp_t[inst.float_detail
|
||||
.opclass])(tfa.i, tfb.i);
|
||||
}
|
||||
ldt(inst.float_detail.fc, &tfc, p);
|
||||
}
|
||||
break;
|
||||
case op_src_qq:
|
||||
float_raise(FP_X_IMP);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
alpha_fp_complete_at(alpha_instruction *trigger_pc, struct proc *p,
|
||||
u_int64_t *ucode)
|
||||
{
|
||||
int needsig;
|
||||
alpha_instruction inst;
|
||||
u_int64_t rm, fpcr, orig_fpcr;
|
||||
u_int64_t orig_flags, new_flags, changed_flags, md_flags;
|
||||
|
||||
if (__predict_false(copyin(trigger_pc, &inst, sizeof inst))) {
|
||||
this_cannot_happen(6, -1);
|
||||
return SIGSEGV;
|
||||
}
|
||||
alpha_enable_fp(p, 1);
|
||||
/*
|
||||
* If necessary, lie about the dynamic rounding mode so emulation
|
||||
* software need go to only one place for it, and so we don't have to
|
||||
* lock any memory locations or pass a third parameter to every
|
||||
* SoftFloat entry point.
|
||||
*/
|
||||
orig_fpcr = fpcr = alpha_read_fpcr();
|
||||
rm = inst.float_detail.rnd;
|
||||
if (__predict_false(rm != 3 /* dynamic */ && rm != (fpcr >> 58 & 3))) {
|
||||
fpcr = (fpcr & ~FPCR_DYN(3)) | FPCR_DYN(rm);
|
||||
alpha_write_fpcr(fpcr);
|
||||
}
|
||||
orig_flags = FP_C_TO_NETBSD_FLAG(p->p_md.md_flags);
|
||||
|
||||
alpha_fp_interpret(trigger_pc, p, inst.bits);
|
||||
|
||||
md_flags = p->p_md.md_flags;
|
||||
|
||||
new_flags = FP_C_TO_NETBSD_FLAG(md_flags);
|
||||
changed_flags = orig_flags ^ new_flags;
|
||||
KASSERT((orig_flags | changed_flags) == new_flags); /* panic on 1->0 */
|
||||
alpha_write_fpcr(fp_c_to_fpcr_1(orig_fpcr, md_flags));
|
||||
needsig = changed_flags & FP_C_TO_NETBSD_MASK(md_flags);
|
||||
alpha_pal_wrfen(0);
|
||||
if (__predict_false(needsig)) {
|
||||
*ucode = needsig;
|
||||
return SIGFPE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
alpha_fp_complete(u_long a0, u_long a1, struct proc *p, u_int64_t *ucode)
|
||||
{
|
||||
int t;
|
||||
int sig;
|
||||
u_int64_t op_class;
|
||||
alpha_instruction inst;
|
||||
/* "trigger_pc" is Compaq's term for the earliest faulting op */
|
||||
alpha_instruction *trigger_pc, *usertrap_pc;
|
||||
alpha_instruction *pc, *win_begin, tsw[TSWINSIZE];
|
||||
|
||||
sig = SIGFPE;
|
||||
pc = (alpha_instruction *)p->p_md.md_tf->tf_regs[FRAME_PC];
|
||||
trigger_pc = pc - 1; /* for ALPHA_AMASK_PAT case */
|
||||
if (cpu_amask & ALPHA_AMASK_PAT) {
|
||||
if (a0 & 1 || alpha_fp_sync_complete) {
|
||||
sig = alpha_fp_complete_at(trigger_pc, p, ucode);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
*ucode = a0;
|
||||
if (!(a0 & 1))
|
||||
return sig;
|
||||
/*
|
||||
* At this point we are somwhere in the trap shadow of one or more instruc-
|
||||
* tions that have trapped with software completion specified. We have a mask
|
||||
* of the registers written by trapping instructions.
|
||||
*
|
||||
* Now step backwards through the trap shadow, clearing bits in the
|
||||
* destination write mask until the trigger instruction is found, and
|
||||
* interpret this one instruction in SW. If a SIGFPE is not required, back up
|
||||
* the PC until just after this instruction and restart. This will execute all
|
||||
* trap shadow instructions between the trigger pc and the trap pc twice.
|
||||
*
|
||||
* If a SIGFPE is generated from the OSF1 emulation, back up one more
|
||||
* instruction to the trigger pc itself. Native binaries don't because it
|
||||
* completely defeats the intended purpose of IEEE traps -- for example,
|
||||
* to count the number of exponent wraps for a later correction -- and it's
|
||||
* terribly non-portable, you would have to determine for every platform the
|
||||
* instruction length in bytes in order to continue. Fortunately, trapping
|
||||
* SIGFPE is rare, or there might be a difficult compatibility issue for
|
||||
* programs incrementing trap PC's conditionally for alphas. (Now, we could
|
||||
* detect that...) The NetBSD native behavior matches all other alpha freenix
|
||||
* kernels.
|
||||
*/
|
||||
trigger_pc = 0;
|
||||
win_begin = pc;
|
||||
++alpha_shadow.scans;
|
||||
t = alpha_shadow.len;
|
||||
for (--pc; a1; --pc) {
|
||||
++alpha_shadow.len;
|
||||
if (pc < win_begin) {
|
||||
win_begin = pc - TSWINSIZE + 1;
|
||||
if (copyin(win_begin, tsw, sizeof tsw)) {
|
||||
/* sigh, try to get just one */
|
||||
win_begin = pc;
|
||||
if (copyin(win_begin, tsw, 4))
|
||||
return SIGSEGV;
|
||||
}
|
||||
}
|
||||
assert(win_begin <= pc && !((long)pc & 3));
|
||||
inst = tsw[pc - win_begin];
|
||||
op_class = 1UL << inst.generic_format.opcode;
|
||||
if (op_class & FPUREG_CLASS) {
|
||||
a1 &= ~(1UL << (inst.operate_generic_format.rc + 32));
|
||||
trigger_pc = pc;
|
||||
} else if (op_class & CPUREG_CLASS) {
|
||||
a1 &= ~(1UL << inst.operate_generic_format.rc);
|
||||
trigger_pc = pc;
|
||||
} else if (op_class & TRAPSHADOWBOUNDARY) {
|
||||
if (op_class & CHECKFUNCTIONCODE) {
|
||||
if (inst.mem_format.displacement == op_trapb ||
|
||||
inst.mem_format.displacement == op_excb)
|
||||
break; /* code breaks AARM rules */
|
||||
} else
|
||||
break; /* code breaks AARM rules */
|
||||
}
|
||||
/* Some shadow-safe op, probably load, store, or FPTI class */
|
||||
}
|
||||
t = alpha_shadow.len - t;
|
||||
if (t > alpha_shadow.max)
|
||||
alpha_shadow.max = t;
|
||||
if (__predict_true(trigger_pc != 0 && a1 == 0)) {
|
||||
++alpha_shadow.resolved;
|
||||
sig = alpha_fp_complete_at(trigger_pc, p, ucode);
|
||||
} else {
|
||||
++alpha_shadow.unresolved;
|
||||
return sig;
|
||||
}
|
||||
done:
|
||||
if (sig) {
|
||||
usertrap_pc = trigger_pc + 1;
|
||||
#ifdef COMPAT_OSF1
|
||||
if (p->p_emul == &emul_osf1)
|
||||
usertrap_pc = trigger_pc;
|
||||
#endif
|
||||
p->p_md.md_tf->tf_regs[FRAME_PC] = (unsigned long)usertrap_pc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: locore.s,v 1.93 2001/04/21 22:03:21 ross Exp $ */
|
||||
/* $NetBSD: locore.s,v 1.94 2001/04/26 03:10:44 ross Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -72,7 +72,7 @@
|
||||
|
||||
#include <machine/asm.h>
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: locore.s,v 1.93 2001/04/21 22:03:21 ross Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: locore.s,v 1.94 2001/04/26 03:10:44 ross Exp $");
|
||||
|
||||
#include "assym.h"
|
||||
|
||||
@ -1851,4 +1851,57 @@ longjmp_botchmsg:
|
||||
.text
|
||||
END(longjmp)
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
* void sts(int rn, u_int32_t *rval);
|
||||
* void stt(int rn, u_int64_t *rval);
|
||||
* void lds(int rn, u_int32_t *rval);
|
||||
* void ldt(int rn, u_int64_t *rval);
|
||||
*/
|
||||
|
||||
.macro make_freg_util name, op
|
||||
LEAF(alpha_\name, 2)
|
||||
and a0, 0x1f, a0
|
||||
s8addq a0, pv, pv
|
||||
addq pv, 1f - alpha_\name, pv
|
||||
jmp (pv)
|
||||
1:
|
||||
rn = 0
|
||||
.rept 32
|
||||
\op $f0 + rn, 0(a1)
|
||||
RET
|
||||
rn = rn + 1
|
||||
.endr
|
||||
END(alpha_\name)
|
||||
.endm
|
||||
/*
|
||||
LEAF(alpha_sts, 2)
|
||||
LEAF(alpha_stt, 2)
|
||||
LEAF(alpha_lds, 2)
|
||||
LEAF(alpha_ldt, 2)
|
||||
*/
|
||||
make_freg_util sts, sts
|
||||
make_freg_util stt, stt
|
||||
make_freg_util lds, lds
|
||||
make_freg_util ldt, ldt
|
||||
|
||||
LEAF(alpha_read_fpcr, 0); f30save = 0; rettmp = 8; framesz = 16
|
||||
lda sp, -framesz(sp)
|
||||
stt $f30, f30save(sp)
|
||||
mf_fpcr $f30
|
||||
stt $f30, rettmp(sp)
|
||||
ldt $f30, f30save(sp)
|
||||
ldq v0, rettmp(sp)
|
||||
lda sp, framesz(sp)
|
||||
RET
|
||||
END(alpha_read_fpcr)
|
||||
|
||||
LEAF(alpha_write_fpcr, 1); f30save = 0; fpcrtmp = 8; framesz = 16
|
||||
lda sp, -framesz(sp)
|
||||
stq a0, fpcrtmp(sp)
|
||||
stt $f30, f30save(sp)
|
||||
ldt $f30, fpcrtmp(sp)
|
||||
mt_fpcr $f30
|
||||
ldt $f30, f30save(sp)
|
||||
lda sp, framesz(sp)
|
||||
RET
|
||||
END(alpha_write_fpcr)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: machdep.c,v 1.240 2001/04/24 04:30:50 thorpej Exp $ */
|
||||
/* $NetBSD: machdep.c,v 1.241 2001/04/26 03:10:44 ross Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -73,7 +73,7 @@
|
||||
|
||||
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.240 2001/04/24 04:30:50 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.241 2001/04/26 03:10:44 ross Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -98,6 +98,7 @@ __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.240 2001/04/24 04:30:50 thorpej Exp $"
|
||||
#include <sys/core.h>
|
||||
#include <sys/kcore.h>
|
||||
#include <machine/kcore.h>
|
||||
#include <machine/fpu.h>
|
||||
|
||||
#include <sys/mount.h>
|
||||
#include <sys/syscallargs.h>
|
||||
@ -188,6 +189,7 @@ void *ksym_start, *ksym_end;
|
||||
int alpha_unaligned_print = 1; /* warn about unaligned accesses */
|
||||
int alpha_unaligned_fix = 1; /* fix up unaligned accesses */
|
||||
int alpha_unaligned_sigbus = 0; /* don't SIGBUS on fixed-up accesses */
|
||||
int alpha_fp_sync_complete = 0; /* fp fixup if sync even without /s */
|
||||
|
||||
/*
|
||||
* XXX This should be dynamically sized, but we have the chicken-egg problem!
|
||||
@ -1540,7 +1542,7 @@ sendsig(catcher, sig, mask, code)
|
||||
ksc.sc_ownedfp = p->p_md.md_flags & MDP_FPUSED;
|
||||
bcopy(&p->p_addr->u_pcb.pcb_fp, (struct fpreg *)ksc.sc_fpregs,
|
||||
sizeof(struct fpreg));
|
||||
ksc.sc_fp_control = 0; /* XXX ? */
|
||||
ksc.sc_fp_control = alpha_read_fp_c(p);
|
||||
bzero(ksc.sc_reserved, sizeof ksc.sc_reserved); /* XXX */
|
||||
bzero(ksc.sc_xxx, sizeof ksc.sc_xxx); /* XXX */
|
||||
|
||||
@ -1667,7 +1669,8 @@ sys___sigreturn14(p, v, retval)
|
||||
fpusave_proc(p, 0);
|
||||
bcopy((struct fpreg *)ksc.sc_fpregs, &p->p_addr->u_pcb.pcb_fp,
|
||||
sizeof(struct fpreg));
|
||||
/* XXX ksc.sc_fp_control ? */
|
||||
p->p_addr->u_pcb.pcb_fp.fpr_cr = ksc.sc_fpcr;
|
||||
p->p_md.md_flags = ksc.sc_fp_control & MDP_FP_C;
|
||||
|
||||
/* Restore signal stack. */
|
||||
if (ksc.sc_onstack & SS_ONSTACK)
|
||||
@ -1733,6 +1736,10 @@ cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
|
||||
return (sysctl_rdstring(oldp, oldlenp, newp,
|
||||
bootinfo.booted_kernel));
|
||||
|
||||
case CPU_FP_SYNC_COMPLETE:
|
||||
return (sysctl_int(oldp, oldlenp, newp, newlen,
|
||||
&alpha_fp_sync_complete));
|
||||
|
||||
default:
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
@ -1768,14 +1775,6 @@ setregs(p, pack, stack)
|
||||
bzero(tfp->tf_regs, FRAME_SIZE * sizeof tfp->tf_regs[0]);
|
||||
#endif
|
||||
bzero(&p->p_addr->u_pcb.pcb_fp, sizeof p->p_addr->u_pcb.pcb_fp);
|
||||
p->p_addr->u_pcb.pcb_fp.fpr_cr = FPCR_INED
|
||||
| FPCR_UNFD
|
||||
| FPCR_UNDZ
|
||||
| FPCR_DYN(FP_RN)
|
||||
| FPCR_OVFD
|
||||
| FPCR_DZED
|
||||
| FPCR_INVD
|
||||
| FPCR_DNZ;
|
||||
alpha_pal_wrusp(stack);
|
||||
tfp->tf_regs[FRAME_PS] = ALPHA_PSL_USERSET;
|
||||
tfp->tf_regs[FRAME_PC] = pack->ep_entry & ~3;
|
||||
@ -1787,6 +1786,10 @@ setregs(p, pack, stack)
|
||||
tfp->tf_regs[FRAME_T12] = tfp->tf_regs[FRAME_PC]; /* a.k.a. PV */
|
||||
|
||||
p->p_md.md_flags &= ~MDP_FPUSED;
|
||||
if (__predict_true((p->p_md.md_flags & IEEE_INHERIT) == 0)) {
|
||||
p->p_md.md_flags &= ~MDP_FP_C;
|
||||
p->p_addr->u_pcb.pcb_fp.fpr_cr = FPCR_DYN(FP_RN);
|
||||
}
|
||||
if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
|
||||
fpusave_proc(p, 0);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: sys_machdep.c,v 1.12 2001/01/03 22:15:38 thorpej Exp $ */
|
||||
/* $NetBSD: sys_machdep.c,v 1.13 2001/04/26 03:10:45 ross Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
@ -65,15 +65,17 @@
|
||||
|
||||
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: sys_machdep.c,v 1.12 2001/01/03 22:15:38 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sys_machdep.c,v 1.13 2001/04/26 03:10:45 ross Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#include <sys/mount.h>
|
||||
#include <sys/syscallargs.h>
|
||||
|
||||
#include <machine/fpu.h>
|
||||
#include <machine/sysarch.h>
|
||||
|
||||
#include <dev/pci/pcivar.h>
|
||||
@ -96,11 +98,33 @@ sys_sysarch(struct proc *p, void *v, register_t *retval)
|
||||
|
||||
switch(SCARG(uap, op)) {
|
||||
case ALPHA_FPGETMASK:
|
||||
*retval = FP_C_TO_NETBSD_MASK(p->p_md.md_flags);
|
||||
break;
|
||||
case ALPHA_FPGETSTICKY:
|
||||
*retval = FP_C_TO_NETBSD_FLAG(p->p_md.md_flags);
|
||||
break;
|
||||
case ALPHA_FPSETMASK:
|
||||
case ALPHA_FPSETSTICKY:
|
||||
/* XXX kernel Magick required here */
|
||||
break;
|
||||
{
|
||||
fp_except m;
|
||||
u_int64_t md_flags;
|
||||
struct alpha_fp_except_args args;
|
||||
|
||||
error = copyin(SCARG(uap, parms), &args, sizeof args);
|
||||
if (error)
|
||||
return error;
|
||||
m = args.mask;
|
||||
md_flags = p->p_md.md_flags;
|
||||
if (SCARG(uap, op) == ALPHA_FPSETMASK) {
|
||||
*retval = FP_C_TO_NETBSD_MASK(md_flags);
|
||||
md_flags = SET_FP_C_MASK(md_flags, m);
|
||||
} else {
|
||||
*retval = FP_C_TO_NETBSD_FLAG(md_flags);
|
||||
md_flags = SET_FP_C_FLAG(md_flags, m);
|
||||
}
|
||||
alpha_write_fp_c(p, md_flags);
|
||||
break;
|
||||
}
|
||||
case ALPHA_BUS_GET_WINDOW_COUNT:
|
||||
{
|
||||
struct alpha_bus_get_window_count_args args;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: trap.c,v 1.69 2001/04/20 18:00:50 thorpej Exp $ */
|
||||
/* $NetBSD: trap.c,v 1.70 2001/04/26 03:10:45 ross Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
@ -6,7 +6,7 @@
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center, and by Charles M. Hannum.
|
||||
* NASA Ames Research Center, by Charles M. Hannum, and by Ross Harvey.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -95,12 +95,11 @@
|
||||
*/
|
||||
|
||||
#include "opt_fix_unaligned_vax_fp.h"
|
||||
#include "opt_compat_osf1.h"
|
||||
#include "opt_ddb.h"
|
||||
|
||||
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.69 2001/04/20 18:00:50 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.70 2001/04/26 03:10:45 ross Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -118,12 +117,11 @@ __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.69 2001/04/20 18:00:50 thorpej Exp $");
|
||||
#ifdef DDB
|
||||
#include <machine/db_machdep.h>
|
||||
#endif
|
||||
#include <alpha/alpha/db_instruction.h> /* for handle_opdec() */
|
||||
#include <alpha/alpha/db_instruction.h>
|
||||
#include <machine/userret.h>
|
||||
|
||||
int unaligned_fixup(unsigned long, unsigned long,
|
||||
unsigned long, struct proc *);
|
||||
int handle_opdec(struct proc *p, u_int64_t *ucodep);
|
||||
static int unaligned_fixup(u_long, u_long, u_long, struct proc *);
|
||||
static int handle_opdec(struct proc *p, u_int64_t *ucodep);
|
||||
|
||||
/*
|
||||
* Initialize the trap vectors for the current processor.
|
||||
@ -262,21 +260,16 @@ trap(const u_long a0, const u_long a1, const u_long a2, const u_long entry,
|
||||
goto dopanic;
|
||||
|
||||
case ALPHA_KENTRY_ARITH:
|
||||
/*
|
||||
* If user-land, just give a SIGFPE. Should do
|
||||
* software completion and IEEE handling, if the
|
||||
* user has requested that.
|
||||
/*
|
||||
* Resolve trap shadows, interpret FP ops requiring infinities,
|
||||
* NaNs, or denorms, and maintain FPCR corrections.
|
||||
*/
|
||||
if (user) {
|
||||
#ifdef COMPAT_OSF1
|
||||
extern struct emul emul_osf1;
|
||||
|
||||
/* just punt on OSF/1. XXX THIS IS EVIL */
|
||||
if (p->p_emul == &emul_osf1)
|
||||
KERNEL_PROC_LOCK(p);
|
||||
i = alpha_fp_complete(a0, a1, p, &ucode);
|
||||
KERNEL_PROC_UNLOCK(p);
|
||||
if (i == 0)
|
||||
goto out;
|
||||
#endif
|
||||
i = SIGFPE;
|
||||
ucode = a0; /* exception summary */
|
||||
break;
|
||||
}
|
||||
|
||||
@ -329,48 +322,9 @@ trap(const u_long a0, const u_long a1, const u_long a2, const u_long entry,
|
||||
break;
|
||||
|
||||
case ALPHA_IF_CODE_FEN:
|
||||
{
|
||||
struct cpu_info *ci = curcpu();
|
||||
#if defined(MULTIPROCESSOR)
|
||||
int s;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* on exit from the kernel, if proc == fpcurproc,
|
||||
* FP is enabled.
|
||||
*/
|
||||
if (ci->ci_fpcurproc == p) {
|
||||
printf("trap: fp disabled for fpcurproc == %p",
|
||||
p);
|
||||
goto dopanic;
|
||||
}
|
||||
|
||||
if (ci->ci_fpcurproc != NULL)
|
||||
fpusave_cpu(ci, 1);
|
||||
|
||||
KDASSERT(ci->ci_fpcurproc == NULL);
|
||||
|
||||
#if defined(MULTIPROCESSOR)
|
||||
if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
|
||||
fpusave_proc(p, 1);
|
||||
#else
|
||||
KDASSERT(p->p_addr->u_pcb.pcb_fpcpu == NULL);
|
||||
#endif
|
||||
|
||||
FPCPU_LOCK(&p->p_addr->u_pcb, s);
|
||||
|
||||
p->p_addr->u_pcb.pcb_fpcpu = ci;
|
||||
ci->ci_fpcurproc = p;
|
||||
|
||||
FPCPU_UNLOCK(&p->p_addr->u_pcb, s);
|
||||
|
||||
alpha_pal_wrfen(1);
|
||||
restorefpstate(&p->p_addr->u_pcb.pcb_fp);
|
||||
alpha_enable_fp(p, 0);
|
||||
alpha_pal_wrfen(0);
|
||||
|
||||
p->p_md.md_flags |= MDP_FPUSED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
default:
|
||||
printf("trap: unknown IF type 0x%lx\n", a0);
|
||||
@ -568,6 +522,50 @@ dopanic:
|
||||
panic("trap");
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the float-point enable for the current process, and return
|
||||
* the FPU context to the named process. If check == 0, it is an
|
||||
* error for the named process to already be fpcurproc.
|
||||
*/
|
||||
void
|
||||
alpha_enable_fp(struct proc *p, int check)
|
||||
{
|
||||
#if defined(MULTIPROCESSOR)
|
||||
int s;
|
||||
#endif
|
||||
struct cpu_info *ci = curcpu();
|
||||
|
||||
if (check && ci->ci_fpcurproc == p) {
|
||||
alpha_pal_wrfen(1);
|
||||
return;
|
||||
}
|
||||
if (ci->ci_fpcurproc == p)
|
||||
panic("trap: fp disabled for fpcurproc == %p", p);
|
||||
|
||||
if (ci->ci_fpcurproc != NULL)
|
||||
fpusave_cpu(ci, 1);
|
||||
|
||||
KDASSERT(ci->ci_fpcurproc == NULL);
|
||||
|
||||
#if defined(MULTIPROCESSOR)
|
||||
if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
|
||||
fpusave_proc(p, 1);
|
||||
#else
|
||||
KDASSERT(p->p_addr->u_pcb.pcb_fpcpu == NULL);
|
||||
#endif
|
||||
|
||||
FPCPU_LOCK(&p->p_addr->u_pcb, s);
|
||||
|
||||
p->p_addr->u_pcb.pcb_fpcpu = ci;
|
||||
ci->ci_fpcurproc = p;
|
||||
|
||||
FPCPU_UNLOCK(&p->p_addr->u_pcb, s);
|
||||
|
||||
p->p_md.md_flags |= MDP_FPUSED;
|
||||
alpha_pal_wrfen(1);
|
||||
restorefpstate(&p->p_addr->u_pcb.pcb_fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process an asynchronous software trap.
|
||||
* This is relatively easy.
|
||||
@ -775,9 +773,6 @@ Gfloat_reg_cvt(u_long input)
|
||||
}
|
||||
#endif /* FIX_UNALIGNED_VAX_FP */
|
||||
|
||||
extern int alpha_unaligned_print, alpha_unaligned_fix;
|
||||
extern int alpha_unaligned_sigbus;
|
||||
|
||||
struct unaligned_fixup_data {
|
||||
const char *type; /* opcode name */
|
||||
int fixable; /* fixable, 0 if fixup not supported */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vm_machdep.c,v 1.67 2001/04/24 04:30:50 thorpej Exp $ */
|
||||
/* $NetBSD: vm_machdep.c,v 1.68 2001/04/26 03:10:45 ross Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.67 2001/04/24 04:30:50 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.68 2001/04/26 03:10:45 ross Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -143,7 +143,8 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
|
||||
struct user *up = p2->p_addr;
|
||||
|
||||
p2->p_md.md_tf = p1->p_md.md_tf;
|
||||
p2->p_md.md_flags = p1->p_md.md_flags & MDP_FPUSED;
|
||||
|
||||
p2->p_md.md_flags = p1->p_md.md_flags & (MDP_FPUSED | MDP_FP_C);
|
||||
|
||||
/*
|
||||
* Cache the physical address of the pcb, so we can
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: files.alpha,v 1.135 2001/04/19 17:48:46 thorpej Exp $
|
||||
# $NetBSD: files.alpha,v 1.136 2001/04/26 03:10:45 ross Exp $
|
||||
#
|
||||
# alpha-specific configuration info
|
||||
|
||||
@ -495,6 +495,7 @@ file arch/alpha/alpha/support.c
|
||||
file arch/alpha/alpha/sys_machdep.c
|
||||
file arch/alpha/alpha/syscall.c
|
||||
file arch/alpha/alpha/trap.c
|
||||
file arch/alpha/alpha/fp_complete.c
|
||||
file arch/alpha/alpha/vm_machdep.c
|
||||
file arch/alpha/alpha/disksubr.c
|
||||
file arch/alpha/common/bus_dma.c
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: alpha.h,v 1.14 2000/12/13 03:16:38 mycroft Exp $ */
|
||||
/* $NetBSD: alpha.h,v 1.15 2001/04/26 03:10:46 ross Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988 University of Utah.
|
||||
@ -44,6 +44,21 @@
|
||||
|
||||
#ifndef _ALPHA_H_
|
||||
#define _ALPHA_H_
|
||||
|
||||
typedef union alpha_s_float {
|
||||
u_int32_t i;
|
||||
u_int32_t frac: 23,
|
||||
exp: 8,
|
||||
sign: 1;
|
||||
} s_float;
|
||||
|
||||
typedef union alpha_t_float {
|
||||
u_int64_t i;
|
||||
u_int64_t frac: 52,
|
||||
exp: 11,
|
||||
sign: 1;
|
||||
} t_float;
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#include <machine/bus.h>
|
||||
@ -54,7 +69,11 @@ struct reg;
|
||||
struct rpb;
|
||||
struct trapframe;
|
||||
|
||||
extern u_long cpu_implver; /* from IMPLVER instruction */
|
||||
extern u_long cpu_amask; /* from AMASK instruction */
|
||||
extern int bootdev_debug;
|
||||
extern int alpha_fp_sync_complete;
|
||||
extern int alpha_unaligned_print, alpha_unaligned_fix, alpha_unaligned_sigbus;
|
||||
|
||||
void XentArith(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
|
||||
void XentIF(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
|
||||
@ -110,5 +129,21 @@ void cpu_resume(unsigned long);
|
||||
void cpu_debug_dump(void);
|
||||
#endif
|
||||
|
||||
/* IEEE and VAX FP completion */
|
||||
|
||||
void alpha_sts(int, s_float *); /* MAGIC */
|
||||
void alpha_stt(int, t_float *); /* MAGIC */
|
||||
void alpha_lds(int, s_float *); /* MAGIC */
|
||||
void alpha_ldt(int, t_float *); /* MAGIC */
|
||||
|
||||
uint64_t alpha_read_fpcr(void); /* MAGIC */
|
||||
void alpha_write_fpcr(u_int64_t); /* MAGIC */
|
||||
|
||||
u_int64_t alpha_read_fp_c(struct proc *);
|
||||
void alpha_write_fp_c(struct proc *, u_int64_t);
|
||||
|
||||
void alpha_enable_fp(struct proc *, int);
|
||||
int alpha_fp_complete(u_long, u_long, struct proc *, u_int64_t *);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
#endif /* _ALPHA_H_ */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cpu.h,v 1.54 2001/04/21 16:27:11 thorpej Exp $ */
|
||||
/* $NetBSD: cpu.h,v 1.55 2001/04/26 03:10:46 ross Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
|
||||
@ -169,9 +169,6 @@ void cpu_pause_resume_all(int);
|
||||
#define fpcurproc curcpu()->ci_fpcurproc
|
||||
#define curpcb curcpu()->ci_curpcb
|
||||
|
||||
extern u_long cpu_implver; /* from IMPLVER instruction */
|
||||
extern u_long cpu_amask; /* from AMASK instruction */
|
||||
|
||||
/*
|
||||
* definitions of cpu-dependent requirements
|
||||
* referenced in generic code
|
||||
@ -252,7 +249,8 @@ do { \
|
||||
#define CPU_UNALIGNED_FIX 4 /* int: fix unaligned accesses */
|
||||
#define CPU_UNALIGNED_SIGBUS 5 /* int: SIGBUS unaligned accesses */
|
||||
#define CPU_BOOTED_KERNEL 6 /* string: booted kernel name */
|
||||
#define CPU_MAXID 7 /* 6 valid machdep IDs */
|
||||
#define CPU_FP_SYNC_COMPLETE 7 /* int: always fixup sync fp traps */
|
||||
#define CPU_MAXID 8 /* 7 valid machdep IDs */
|
||||
|
||||
#define CTL_MACHDEP_NAMES { \
|
||||
{ 0, 0 }, \
|
||||
@ -262,6 +260,7 @@ do { \
|
||||
{ "unaligned_fix", CTLTYPE_INT }, \
|
||||
{ "unaligned_sigbus", CTLTYPE_INT }, \
|
||||
{ "booted_kernel", CTLTYPE_STRING }, \
|
||||
{ "fp_sync_complete", CTLTYPE_INT }, \
|
||||
}
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
120
sys/arch/alpha/include/fpu.h
Normal file
120
sys/arch/alpha/include/fpu.h
Normal file
@ -0,0 +1,120 @@
|
||||
/* $NetBSD: fpu.h,v 1.4 2001/04/26 03:10:46 ross Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 Ross Harvey
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was written for NetBSD.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _ALPHA_FPU_H_
|
||||
#define _ALPHA_FPU_H_
|
||||
|
||||
#define _FP_C_DEF(n) (1UL << (n))
|
||||
|
||||
/*
|
||||
* Most of these next definitions were moved from <ieeefp.h>. Apparently the
|
||||
* names happen to match those exported by Compaq and Linux from their fpu.h
|
||||
* files.
|
||||
*/
|
||||
|
||||
#define FPCR_SUM _FP_C_DEF(63)
|
||||
#define FPCR_INED _FP_C_DEF(62)
|
||||
#define FPCR_UNFD _FP_C_DEF(61)
|
||||
#define FPCR_UNDZ _FP_C_DEF(60)
|
||||
#define FPCR_DYN(rm) ((unsigned long)(rm) << 58)
|
||||
#define FPCR_IOV _FP_C_DEF(57)
|
||||
#define FPCR_INE _FP_C_DEF(56)
|
||||
#define FPCR_UNF _FP_C_DEF(55)
|
||||
#define FPCR_OVF _FP_C_DEF(54)
|
||||
#define FPCR_DZE _FP_C_DEF(53)
|
||||
#define FPCR_INV _FP_C_DEF(52)
|
||||
#define FPCR_OVFD _FP_C_DEF(51)
|
||||
#define FPCR_DZED _FP_C_DEF(50)
|
||||
#define FPCR_INVD _FP_C_DEF(49)
|
||||
#define FPCR_DNZ _FP_C_DEF(48)
|
||||
#define FPCR_DNOD _FP_C_DEF(47)
|
||||
|
||||
#define FPCR_MIRRORED (FPCR_INE | FPCR_UNF | FPCR_OVF | FPCR_DZE | FPCR_INV)
|
||||
#define FPCR_MIR_START 52
|
||||
|
||||
/*
|
||||
* The AARM specifies the bit positions of the software word used for
|
||||
* user mode interface to the control and status of the kernel completion
|
||||
* routines. Although it largely just redefines the FPCR, it shuffles
|
||||
* the bit order. The names of the bits are defined in the AARM, and
|
||||
* the definition prefix can easily be determined from public domain
|
||||
* programs written to either the Compaq or Linux interfaces, which
|
||||
* appear to be identical.
|
||||
*/
|
||||
|
||||
#define IEEE_STATUS_DNO _FP_C_DEF(22)
|
||||
#define IEEE_STATUS_INE _FP_C_DEF(21)
|
||||
#define IEEE_STATUS_UNF _FP_C_DEF(20)
|
||||
#define IEEE_STATUS_OVF _FP_C_DEF(19)
|
||||
#define IEEE_STATUS_DZE _FP_C_DEF(18)
|
||||
#define IEEE_STATUS_INV _FP_C_DEF(17)
|
||||
|
||||
#define IEEE_TRAP_ENABLE_DNO _FP_C_DEF(6)
|
||||
#define IEEE_TRAP_ENABLE_INE _FP_C_DEF(5)
|
||||
#define IEEE_TRAP_ENABLE_UNF _FP_C_DEF(4)
|
||||
#define IEEE_TRAP_ENABLE_OVF _FP_C_DEF(3)
|
||||
#define IEEE_TRAP_ENABLE_DZE _FP_C_DEF(2)
|
||||
#define IEEE_TRAP_ENABLE_INV _FP_C_DEF(1)
|
||||
|
||||
#define IEEE_INHERIT _FP_C_DEF(14)
|
||||
#define IEEE_MAP_UMZ _FP_C_DEF(13)
|
||||
#define IEEE_MAP_DMZ _FP_C_DEF(12)
|
||||
|
||||
#define FP_C_MIRRORED (IEEE_STATUS_INE | IEEE_STATUS_UNF | IEEE_STATUS_OVF\
|
||||
| IEEE_STATUS_DZE | IEEE_STATUS_INV)
|
||||
#define FP_C_MIR_START 17
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#define FLD_MASK(len) ((1UL << (len)) - 1)
|
||||
#define FLD_CLEAR(obj, origin, len) \
|
||||
((obj) & ~(FLD_MASK(len) << (origin)))
|
||||
#define FLD_INSERT(obj, origin, len, value) \
|
||||
(FLD_CLEAR(obj, origin, len) | (value) << origin)
|
||||
|
||||
#define FP_C_TO_NETBSD_MASK(fp_c) ((fp_c) >> 1 & 0x3f)
|
||||
#define FP_C_TO_NETBSD_FLAG(fp_c) ((fp_c) >> 17 & 0x3f)
|
||||
#define NETBSD_MASK_TO_FP_C(m) (((m) & 0x3f) << 1)
|
||||
#define NETBSD_FLAG_TO_FP_C(s) (((s) & 0x3f) << 17)
|
||||
#define CLEAR_FP_C_MASK(fp_c) ((fp_c) & ~(0x3f << 1))
|
||||
#define CLEAR_FP_C_FLAG(fp_c) ((fp_c) & ~(0x3f << 17))
|
||||
#define SET_FP_C_MASK(fp_c, m) (CLEAR_FP_C_MASK(fp_c) | NETBSD_MASK_TO_FP_C(m))
|
||||
#define SET_FP_C_FLAG(fp_c, m) (CLEAR_FP_C_FLAG(fp_c) | NETBSD_FLAG_TO_FP_C(m))
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ieeefp.h,v 1.3 1999/04/29 02:55:50 ross Exp $ */
|
||||
/* $NetBSD: ieeefp.h,v 1.4 2001/04/26 03:10:46 ross Exp $ */
|
||||
|
||||
/*
|
||||
* Written by J.T. Conklin, Apr 28, 1995
|
||||
@ -9,37 +9,45 @@
|
||||
#define _ALPHA_IEEEFP_H_
|
||||
|
||||
typedef int fp_except;
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/proc.h>
|
||||
#include <machine/fpu.h>
|
||||
#include <machine/alpha.h>
|
||||
|
||||
/* FP_X_IOV is intentionally omitted from the architecture flags mask */
|
||||
|
||||
#define FP_AA_FLAGS (FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_UFL | FP_X_IMP)
|
||||
|
||||
#define float_raise(f) \
|
||||
do curproc->p_md.md_flags |= NETBSD_FLAG_TO_FP_C(f); \
|
||||
while(0)
|
||||
|
||||
#define float_set_inexact() float_raise(FP_X_IMP)
|
||||
#define float_set_invalid() float_raise(FP_X_INV)
|
||||
#define fpgetround() (alpha_read_fpcr() >> 58 & 3)
|
||||
|
||||
#endif
|
||||
|
||||
#define FP_X_INV 0x01 /* invalid operation exception */
|
||||
#define FP_X_DZ 0x02 /* divide-by-zero exception */
|
||||
#define FP_X_OFL 0x04 /* overflow exception */
|
||||
#define FP_X_UFL 0x08 /* underflow exception */
|
||||
#define FP_X_IMP 0x10 /* imprecise (loss of precision; "inexact") */
|
||||
#define FP_X_IOV 0x20 /* integer overflow XXX? */
|
||||
#define FP_X_IOV 0x20 /* integer overflow */
|
||||
|
||||
/*
|
||||
* fp_rnd bits match the fpcr, below, as well as bits 12:11
|
||||
* in fp operate instructions
|
||||
*/
|
||||
typedef enum {
|
||||
FP_RZ=0, /* round to zero (truncate) */
|
||||
FP_RM=1, /* round toward negative infinity */
|
||||
FP_RN=2, /* round to nearest representable number */
|
||||
FP_RP=3 /* round toward positive infinity */
|
||||
FP_RZ = 0, /* round to zero (truncate) */
|
||||
FP_RM = 1, /* round toward negative infinity */
|
||||
FP_RN = 2, /* round to nearest representable number */
|
||||
FP_RP = 3, /* round toward positive infinity */
|
||||
_FP_DYNAMIC=FP_RP
|
||||
} fp_rnd;
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define FPCR_SUM (1UL << 63)
|
||||
#define FPCR_INED (1UL << 62)
|
||||
#define FPCR_UNFD (1UL << 61)
|
||||
#define FPCR_UNDZ (1UL << 60)
|
||||
#define FPCR_DYN(rm) ((unsigned long)(rm) << 58)
|
||||
#define FPCR_IOV (1UL << 57)
|
||||
#define FPCR_INE (1UL << 56)
|
||||
#define FPCR_UNF (1UL << 55)
|
||||
#define FPCR_OVF (1UL << 54)
|
||||
#define FPCR_DZE (1UL << 53)
|
||||
#define FPCR_INV (1UL << 52)
|
||||
#define FPCR_OVFD (1UL << 51)
|
||||
#define FPCR_DZED (1UL << 50)
|
||||
#define FPCR_INVD (1UL << 49)
|
||||
#define FPCR_DNZ (1UL << 48)
|
||||
#define FPCR_DNOD (1UL << 47)
|
||||
#endif
|
||||
|
||||
#endif /* _ALPHA_IEEEFP_H_ */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: proc.h,v 1.9 2001/01/19 18:51:18 thorpej Exp $ */
|
||||
/* $NetBSD: proc.h,v 1.10 2001/04/26 03:10:46 ross Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1995 Carnegie-Mellon University.
|
||||
@ -41,5 +41,23 @@ struct mdproc {
|
||||
void (*md_syscall)(struct proc *, u_int64_t, struct trapframe *);
|
||||
__volatile int md_astpending; /* AST pending for this process */
|
||||
};
|
||||
|
||||
/*
|
||||
* md_flags usage
|
||||
* --------------
|
||||
* MDP_FPUSED
|
||||
* A largely unused bit indicating the presence of FPU history.
|
||||
* Cleared on exec. Set but not used by the fpu context switcher
|
||||
* itself.
|
||||
*
|
||||
* MDP_FP_C
|
||||
* The architected FP Control word. It should forever begin at bit 1,
|
||||
* as the bits are AARM specified and this way it doesn't need to be
|
||||
* shifted.
|
||||
*
|
||||
* Until C99 there was never an IEEE 754 API, making most of the
|
||||
* standard useless. Because of overlapping AARM, OSF/1, NetBSD, and
|
||||
* C99 API's, the use of the MDP_FP_C bits is defined variously in
|
||||
* ieeefp.h and fpu.h.
|
||||
*/
|
||||
#define MDP_FPUSED 0x0001 /* Process used the FPU */
|
||||
#define MDP_FP_C 0x7ffffe /* Extended FP_C Quadword bits */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: sysarch.h,v 1.7 2001/04/20 23:52:23 ross Exp $ */
|
||||
/* $NetBSD: sysarch.h,v 1.8 2001/04/26 03:10:46 ross Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
@ -52,6 +52,7 @@
|
||||
#define ALPHA_BUS_GET_WINDOW_COUNT 3
|
||||
#define ALPHA_BUS_GET_WINDOW 4
|
||||
#define ALPHA_PCI_CONF_READWRITE 5
|
||||
#define ALPHA_FPGETSTICKY 6
|
||||
|
||||
struct alpha_fp_except_args {
|
||||
fp_except mask;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cia.c,v 1.56 2000/06/29 08:58:45 mrg Exp $ */
|
||||
/* $NetBSD: cia.c,v 1.57 2001/04/26 03:10:46 ross Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
|
||||
@ -72,7 +72,7 @@
|
||||
|
||||
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: cia.c,v 1.56 2000/06/29 08:58:45 mrg Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: cia.c,v 1.57 2001/04/26 03:10:46 ross Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -85,6 +85,7 @@ __KERNEL_RCSID(0, "$NetBSD: cia.c,v 1.56 2000/06/29 08:58:45 mrg Exp $");
|
||||
#include <machine/autoconf.h>
|
||||
#include <machine/rpb.h>
|
||||
#include <machine/sysarch.h>
|
||||
#include <machine/alpha.h>
|
||||
|
||||
#include <dev/isa/isareg.h>
|
||||
#include <dev/isa/isavar.h>
|
||||
@ -219,8 +220,7 @@ cia_init(ccp, mallocsafe)
|
||||
* - It hasn't been disbled by the user,
|
||||
* - it's enabled in CNFG,
|
||||
* - we're implementation version ev5,
|
||||
* - BWX is enabled in the CPU's capabilities mask (yes,
|
||||
* the bit is really cleared if the capability exists...)
|
||||
* - BWX is enabled in the CPU's capabilities mask
|
||||
*/
|
||||
if ((pci_use_bwx || bus_use_bwx) &&
|
||||
(ccp->cc_cnfg & CNFG_BWEN) != 0 &&
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: linux_machdep.c,v 1.15 2001/01/26 19:45:58 manu Exp $ */
|
||||
/* $NetBSD: linux_machdep.c,v 1.16 2001/04/26 03:10:47 ross Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -154,14 +154,10 @@ void setup_linux_rt_sigframe(tf, sig, mask)
|
||||
frametoreg(tf, (struct reg *)sigframe.uc.uc_mcontext.sc_regs);
|
||||
sigframe.uc.uc_mcontext.sc_regs[R_SP] = alpha_pal_rdusp();
|
||||
|
||||
if (p == fpcurproc) {
|
||||
alpha_pal_wrfen(1);
|
||||
savefpstate(&p->p_addr->u_pcb.pcb_fp);
|
||||
alpha_pal_wrfen(0);
|
||||
sigframe.uc.uc_mcontext.sc_fpcr = p->p_addr->u_pcb.pcb_fp.fpr_cr;
|
||||
fpcurproc = NULL;
|
||||
}
|
||||
/* XXX ownedfp ? etc...? */
|
||||
alpha_enable_fp(p, 1);
|
||||
sigframe.uc.uc_mcontext.sc_fpcr = alpha_read_fpcr();
|
||||
sigframe.uc.uc_mcontext.sc_fp_control = alpha_read_fp_c(p);
|
||||
alpha_pal_wrfen(0);
|
||||
|
||||
sigframe.uc.uc_mcontext.sc_traparg_a0 = tf->tf_regs[FRAME_A0];
|
||||
sigframe.uc.uc_mcontext.sc_traparg_a1 = tf->tf_regs[FRAME_A1];
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: osf1_misc.c,v 1.62 2000/12/01 19:20:56 jdolecek Exp $ */
|
||||
/* $NetBSD: osf1_misc.c,v 1.63 2001/04/26 03:10:47 ross Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
|
||||
@ -87,6 +87,7 @@
|
||||
#include <machine/alpha.h>
|
||||
#include <machine/cpuconf.h>
|
||||
#include <machine/rpb.h>
|
||||
#include <machine/fpu.h>
|
||||
|
||||
#include <compat/osf1/osf1.h>
|
||||
#include <compat/osf1/osf1_syscallargs.h>
|
||||
@ -163,6 +164,7 @@ osf1_sys_getsysinfo(struct proc *p, void *v, register_t *retval)
|
||||
int unit;
|
||||
long percpu;
|
||||
long proctype;
|
||||
u_int64_t fpflags;
|
||||
struct osf1_cpu_info cpuinfo;
|
||||
|
||||
error = 0;
|
||||
@ -184,14 +186,11 @@ osf1_sys_getsysinfo(struct proc *p, void *v, register_t *retval)
|
||||
retval[0] = 1;
|
||||
break;
|
||||
case OSF_GET_IEEE_FP_CONTROL:
|
||||
/*
|
||||
* XXX This is not correct, but we don't keep track
|
||||
* XXX of the fp_control. Return the fpcr just for fun.
|
||||
*/
|
||||
fpusave_proc(p, 1);
|
||||
error = copyout(&p->p_addr->u_pcb.pcb_fp.fpr_cr,
|
||||
SCARG(uap, buffer),
|
||||
sizeof(p->p_addr->u_pcb.pcb_fp.fpr_cr));
|
||||
if (((fpflags = alpha_read_fp_c(p)) & IEEE_INHERIT) != 0) {
|
||||
fpflags |= 1UL << 63;
|
||||
fpflags &= ~IEEE_INHERIT;
|
||||
}
|
||||
error = copyout(&fpflags, SCARG(uap, buffer), sizeof fpflags);
|
||||
retval[0] = 1;
|
||||
break;
|
||||
case OSF_GET_CPU_INFO:
|
||||
@ -262,30 +261,20 @@ osf1_sys_setsysinfo(p, v, retval)
|
||||
register_t *retval;
|
||||
{
|
||||
struct osf1_sys_setsysinfo_args *uap = v;
|
||||
u_int64_t temp;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
|
||||
switch(SCARG(uap, op))
|
||||
{
|
||||
case OSF_SET_IEEE_FP_CONTROL: {
|
||||
u_int64_t temp;
|
||||
/*
|
||||
* XXX This is definitely not correct. This should instead
|
||||
* XXX set the fp_control, but we don't keep track of it.
|
||||
* XXX The fp_control is then used to reload the fpcr.
|
||||
*/
|
||||
#define FPCR_SETTABLE (FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_UFL | FP_X_IMP)
|
||||
switch(SCARG(uap, op)) {
|
||||
case OSF_SET_IEEE_FP_CONTROL:
|
||||
|
||||
if ((error = copyin(SCARG(uap, buffer), &temp, sizeof(temp))))
|
||||
break;
|
||||
|
||||
#if 0
|
||||
synchronize_fpstate(p, 1);
|
||||
p->p_addr->u_pcb.pcb_fp.fp_control = (temp & FPCR_SETTABLE);
|
||||
/* Translate from fp_control => fpr_cr. */
|
||||
#endif
|
||||
if (temp >> 63 != 0)
|
||||
temp |= IEEE_INHERIT;
|
||||
alpha_write_fp_c(p, temp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
uprintf("osf1_setsysinfo called with op=%ld\n", SCARG(uap, op));
|
||||
//error = EINVAL;
|
||||
|
@ -1,10 +1,11 @@
|
||||
# $NetBSD: Makefile.inc,v 1.20 2000/11/01 19:37:18 thorpej Exp $
|
||||
# $NetBSD: Makefile.inc,v 1.21 2001/04/26 03:10:48 ross Exp $
|
||||
|
||||
SRCS+= __main.c __assert.c _mcount.S \
|
||||
imax.c imin.c lmax.c lmin.c max.c min.c ulmax.c ulmin.c \
|
||||
byte_swap_2.S byte_swap_4.S bswap64.c \
|
||||
bcmp.c bzero.S ffs.S \
|
||||
memchr.c memcmp.c memcpy.S memmove.S memset.c \
|
||||
softfloat.c \
|
||||
strcat.c strcmp.c strcpy.c strlen.c strcasecmp.c \
|
||||
strncasecmp.c strncmp.c strncpy.c \
|
||||
scanc.c skpc.c \
|
||||
|
160
sys/lib/libkern/milieu.h
Normal file
160
sys/lib/libkern/milieu.h
Normal file
@ -0,0 +1,160 @@
|
||||
/* $NetBSD: milieu.h,v 1.1 2001/04/26 03:10:47 ross Exp $ */
|
||||
|
||||
/* This is a derivative work. */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Ross Harvey.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
This C header file is part of TestFloat, Release 2a, a package of programs
|
||||
for testing the correctness of floating-point arithmetic complying to the
|
||||
IEC/IEEE Standard for Floating-Point.
|
||||
|
||||
Written by John R. Hauser. More information is available through the Web
|
||||
page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'.
|
||||
|
||||
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
|
||||
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
|
||||
TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
|
||||
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
|
||||
AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
|
||||
|
||||
Derivative works are acceptable, even for commercial purposes, so long as
|
||||
(1) they include prominent notice that the work is derivative, and (2) they
|
||||
include prominent notice akin to these four paragraphs for those parts of
|
||||
this code that are retained.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
#ifndef MILIEU_H
|
||||
#define MILIEU_H
|
||||
|
||||
#if !defined(_KERNEL) && !defined(_STANDALONE)
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
#include <sys/inttypes.h>
|
||||
#endif
|
||||
|
||||
#include <sys/endian.h>
|
||||
|
||||
enum {
|
||||
FALSE = 0,
|
||||
TRUE = 1
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#if _BYTE_ORDER == _LITTLE_ENDIAN
|
||||
#define LITTLEENDIAN
|
||||
#else
|
||||
#define BIGENDIAN
|
||||
#endif
|
||||
|
||||
#define BITS64
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Each of the following `typedef's defines the most convenient type that holds
|
||||
integers of at least as many bits as specified. For example, `uint8' should
|
||||
be the most convenient type that can hold unsigned integers of as many as
|
||||
8 bits. The `flag' type must be able to hold either a 0 or 1. For most
|
||||
implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
|
||||
to the same as `int'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
typedef int flag;
|
||||
typedef unsigned int uint8;
|
||||
typedef signed int int8;
|
||||
typedef unsigned int uint16;
|
||||
typedef int int16;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed int int32;
|
||||
#ifdef BITS64
|
||||
typedef uint64_t uint64;
|
||||
typedef int64_t int64;
|
||||
#endif
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Each of the following `typedef's defines a type that holds integers
|
||||
of _exactly_ the number of bits specified. For instance, for most
|
||||
implementation of C, `bits16' and `sbits16' should be `typedef'ed to
|
||||
`unsigned short int' and `signed short int' (or `short int'), respectively.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
typedef uint8_t bits8;
|
||||
typedef int8_t sbits8;
|
||||
typedef uint16_t bits16;
|
||||
typedef int16_t sbits16;
|
||||
typedef uint32_t bits32;
|
||||
typedef int32_t sbits32;
|
||||
#ifdef BITS64
|
||||
typedef uint64_t bits64;
|
||||
typedef int64_t sbits64;
|
||||
#endif
|
||||
|
||||
#ifdef BITS64
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
The `LIT64' macro takes as its argument a textual integer literal and
|
||||
if necessary ``marks'' the literal as having a 64-bit integer type.
|
||||
For example, the GNU C Compiler (`gcc') requires that 64-bit literals be
|
||||
appended with the letters `LL' standing for `long long', which is `gcc's
|
||||
name for the 64-bit integer type. Some compilers may allow `LIT64' to be
|
||||
defined as the identity macro: `#define LIT64( a ) a'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
#define LIT64( a ) a##LL
|
||||
#endif
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
The macro `INLINE' can be used before functions that should be inlined. If
|
||||
a compiler does not support explicit inlining, this macro should be defined
|
||||
to be `static'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
#define INLINE static inline
|
||||
|
||||
#endif
|
745
sys/lib/libkern/softfloat-macros.h
Normal file
745
sys/lib/libkern/softfloat-macros.h
Normal file
@ -0,0 +1,745 @@
|
||||
/* $NetBSD: softfloat-macros.h,v 1.1 2001/04/26 03:10:47 ross Exp $ */
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
|
||||
Arithmetic Package, Release 2a.
|
||||
|
||||
Written by John R. Hauser. This work was made possible in part by the
|
||||
International Computer Science Institute, located at Suite 600, 1947 Center
|
||||
Street, Berkeley, California 94704. Funding was partially provided by the
|
||||
National Science Foundation under grant MIP-9311980. The original version
|
||||
of this code was written as part of a project to build a fixed-point vector
|
||||
processor in collaboration with the University of California at Berkeley,
|
||||
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
|
||||
is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
|
||||
arithmetic/SoftFloat.html'.
|
||||
|
||||
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
|
||||
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
|
||||
TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
|
||||
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
|
||||
AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
|
||||
|
||||
Derivative works are acceptable, even for commercial purposes, so long as
|
||||
(1) they include prominent notice that the work is derivative, and (2) they
|
||||
include prominent notice akin to these four paragraphs for those parts of
|
||||
this code that are retained.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Shifts `a' right by the number of bits given in `count'. If any nonzero
|
||||
bits are shifted off, they are ``jammed'' into the least significant bit of
|
||||
the result by setting the least significant bit to 1. The value of `count'
|
||||
can be arbitrarily large; in particular, if `count' is greater than 32, the
|
||||
result will be either 0 or 1, depending on whether `a' is zero or nonzero.
|
||||
The result is stored in the location pointed to by `zPtr'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr )
|
||||
{
|
||||
bits32 z;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z = a;
|
||||
}
|
||||
else if ( count < 32 ) {
|
||||
z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 );
|
||||
}
|
||||
else {
|
||||
z = ( a != 0 );
|
||||
}
|
||||
*zPtr = z;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Shifts `a' right by the number of bits given in `count'. If any nonzero
|
||||
bits are shifted off, they are ``jammed'' into the least significant bit of
|
||||
the result by setting the least significant bit to 1. The value of `count'
|
||||
can be arbitrarily large; in particular, if `count' is greater than 64, the
|
||||
result will be either 0 or 1, depending on whether `a' is zero or nonzero.
|
||||
The result is stored in the location pointed to by `zPtr'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr )
|
||||
{
|
||||
bits64 z;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z = a;
|
||||
}
|
||||
else if ( count < 64 ) {
|
||||
z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 );
|
||||
}
|
||||
else {
|
||||
z = ( a != 0 );
|
||||
}
|
||||
*zPtr = z;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64
|
||||
_plus_ the number of bits given in `count'. The shifted result is at most
|
||||
64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The
|
||||
bits shifted off form a second 64-bit result as follows: The _last_ bit
|
||||
shifted off is the most-significant bit of the extra result, and the other
|
||||
63 bits of the extra result are all zero if and only if _all_but_the_last_
|
||||
bits shifted off were all zero. This extra result is stored in the location
|
||||
pointed to by `z1Ptr'. The value of `count' can be arbitrarily large.
|
||||
(This routine makes more sense if `a0' and `a1' are considered to form a
|
||||
fixed-point value with binary point between `a0' and `a1'. This fixed-point
|
||||
value is shifted right by the number of bits given in `count', and the
|
||||
integer part of the result is returned at the location pointed to by
|
||||
`z0Ptr'. The fractional part of the result may be slightly corrupted as
|
||||
described above, and is returned at the location pointed to by `z1Ptr'.)
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE void
|
||||
shift64ExtraRightJamming(
|
||||
bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
|
||||
{
|
||||
bits64 z0, z1;
|
||||
int8 negCount = ( - count ) & 63;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z1 = a1;
|
||||
z0 = a0;
|
||||
}
|
||||
else if ( count < 64 ) {
|
||||
z1 = ( a0<<negCount ) | ( a1 != 0 );
|
||||
z0 = a0>>count;
|
||||
}
|
||||
else {
|
||||
if ( count == 64 ) {
|
||||
z1 = a0 | ( a1 != 0 );
|
||||
}
|
||||
else {
|
||||
z1 = ( ( a0 | a1 ) != 0 );
|
||||
}
|
||||
z0 = 0;
|
||||
}
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
|
||||
number of bits given in `count'. Any bits shifted off are lost. The value
|
||||
of `count' can be arbitrarily large; in particular, if `count' is greater
|
||||
than 128, the result will be 0. The result is broken into two 64-bit pieces
|
||||
which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE void
|
||||
shift128Right(
|
||||
bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
|
||||
{
|
||||
bits64 z0, z1;
|
||||
int8 negCount = ( - count ) & 63;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z1 = a1;
|
||||
z0 = a0;
|
||||
}
|
||||
else if ( count < 64 ) {
|
||||
z1 = ( a0<<negCount ) | ( a1>>count );
|
||||
z0 = a0>>count;
|
||||
}
|
||||
else {
|
||||
z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0;
|
||||
z0 = 0;
|
||||
}
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
|
||||
number of bits given in `count'. If any nonzero bits are shifted off, they
|
||||
are ``jammed'' into the least significant bit of the result by setting the
|
||||
least significant bit to 1. The value of `count' can be arbitrarily large;
|
||||
in particular, if `count' is greater than 128, the result will be either
|
||||
0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or
|
||||
nonzero. The result is broken into two 64-bit pieces which are stored at
|
||||
the locations pointed to by `z0Ptr' and `z1Ptr'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE void
|
||||
shift128RightJamming(
|
||||
bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
|
||||
{
|
||||
bits64 z0, z1;
|
||||
int8 negCount = ( - count ) & 63;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z1 = a1;
|
||||
z0 = a0;
|
||||
}
|
||||
else if ( count < 64 ) {
|
||||
z1 = ( a0<<negCount ) | ( a1>>count ) | ( ( a1<<negCount ) != 0 );
|
||||
z0 = a0>>count;
|
||||
}
|
||||
else {
|
||||
if ( count == 64 ) {
|
||||
z1 = a0 | ( a1 != 0 );
|
||||
}
|
||||
else if ( count < 128 ) {
|
||||
z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<<negCount ) | a1 ) != 0 );
|
||||
}
|
||||
else {
|
||||
z1 = ( ( a0 | a1 ) != 0 );
|
||||
}
|
||||
z0 = 0;
|
||||
}
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right
|
||||
by 64 _plus_ the number of bits given in `count'. The shifted result is
|
||||
at most 128 nonzero bits; these are broken into two 64-bit pieces which are
|
||||
stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
|
||||
off form a third 64-bit result as follows: The _last_ bit shifted off is
|
||||
the most-significant bit of the extra result, and the other 63 bits of the
|
||||
extra result are all zero if and only if _all_but_the_last_ bits shifted off
|
||||
were all zero. This extra result is stored in the location pointed to by
|
||||
`z2Ptr'. The value of `count' can be arbitrarily large.
|
||||
(This routine makes more sense if `a0', `a1', and `a2' are considered
|
||||
to form a fixed-point value with binary point between `a1' and `a2'. This
|
||||
fixed-point value is shifted right by the number of bits given in `count',
|
||||
and the integer part of the result is returned at the locations pointed to
|
||||
by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
|
||||
corrupted as described above, and is returned at the location pointed to by
|
||||
`z2Ptr'.)
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE void
|
||||
shift128ExtraRightJamming(
|
||||
bits64 a0,
|
||||
bits64 a1,
|
||||
bits64 a2,
|
||||
int16 count,
|
||||
bits64 *z0Ptr,
|
||||
bits64 *z1Ptr,
|
||||
bits64 *z2Ptr
|
||||
)
|
||||
{
|
||||
bits64 z0, z1, z2;
|
||||
int8 negCount = ( - count ) & 63;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z2 = a2;
|
||||
z1 = a1;
|
||||
z0 = a0;
|
||||
}
|
||||
else {
|
||||
if ( count < 64 ) {
|
||||
z2 = a1<<negCount;
|
||||
z1 = ( a0<<negCount ) | ( a1>>count );
|
||||
z0 = a0>>count;
|
||||
}
|
||||
else {
|
||||
if ( count == 64 ) {
|
||||
z2 = a1;
|
||||
z1 = a0;
|
||||
}
|
||||
else {
|
||||
a2 |= a1;
|
||||
if ( count < 128 ) {
|
||||
z2 = a0<<negCount;
|
||||
z1 = a0>>( count & 63 );
|
||||
}
|
||||
else {
|
||||
z2 = ( count == 128 ) ? a0 : ( a0 != 0 );
|
||||
z1 = 0;
|
||||
}
|
||||
}
|
||||
z0 = 0;
|
||||
}
|
||||
z2 |= ( a2 != 0 );
|
||||
}
|
||||
*z2Ptr = z2;
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
|
||||
number of bits given in `count'. Any bits shifted off are lost. The value
|
||||
of `count' must be less than 64. The result is broken into two 64-bit
|
||||
pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE void
|
||||
shortShift128Left(
|
||||
bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
|
||||
{
|
||||
|
||||
*z1Ptr = a1<<count;
|
||||
*z0Ptr =
|
||||
( count == 0 ) ? a0 : ( a0<<count ) | ( a1>>( ( - count ) & 63 ) );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left
|
||||
by the number of bits given in `count'. Any bits shifted off are lost.
|
||||
The value of `count' must be less than 64. The result is broken into three
|
||||
64-bit pieces which are stored at the locations pointed to by `z0Ptr',
|
||||
`z1Ptr', and `z2Ptr'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE void
|
||||
shortShift192Left(
|
||||
bits64 a0,
|
||||
bits64 a1,
|
||||
bits64 a2,
|
||||
int16 count,
|
||||
bits64 *z0Ptr,
|
||||
bits64 *z1Ptr,
|
||||
bits64 *z2Ptr
|
||||
)
|
||||
{
|
||||
bits64 z0, z1, z2;
|
||||
int8 negCount;
|
||||
|
||||
z2 = a2<<count;
|
||||
z1 = a1<<count;
|
||||
z0 = a0<<count;
|
||||
if ( 0 < count ) {
|
||||
negCount = ( ( - count ) & 63 );
|
||||
z1 |= a2>>negCount;
|
||||
z0 |= a1>>negCount;
|
||||
}
|
||||
*z2Ptr = z2;
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit
|
||||
value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so
|
||||
any carry out is lost. The result is broken into two 64-bit pieces which
|
||||
are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE void
|
||||
add128(
|
||||
bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
|
||||
{
|
||||
bits64 z1;
|
||||
|
||||
z1 = a1 + b1;
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = a0 + b0 + ( z1 < a1 );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the
|
||||
192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
|
||||
modulo 2^192, so any carry out is lost. The result is broken into three
|
||||
64-bit pieces which are stored at the locations pointed to by `z0Ptr',
|
||||
`z1Ptr', and `z2Ptr'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE void
|
||||
add192(
|
||||
bits64 a0,
|
||||
bits64 a1,
|
||||
bits64 a2,
|
||||
bits64 b0,
|
||||
bits64 b1,
|
||||
bits64 b2,
|
||||
bits64 *z0Ptr,
|
||||
bits64 *z1Ptr,
|
||||
bits64 *z2Ptr
|
||||
)
|
||||
{
|
||||
bits64 z0, z1, z2;
|
||||
int8 carry0, carry1;
|
||||
|
||||
z2 = a2 + b2;
|
||||
carry1 = ( z2 < a2 );
|
||||
z1 = a1 + b1;
|
||||
carry0 = ( z1 < a1 );
|
||||
z0 = a0 + b0;
|
||||
z1 += carry1;
|
||||
z0 += ( z1 < carry1 );
|
||||
z0 += carry0;
|
||||
*z2Ptr = z2;
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the
|
||||
128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
|
||||
2^128, so any borrow out (carry out) is lost. The result is broken into two
|
||||
64-bit pieces which are stored at the locations pointed to by `z0Ptr' and
|
||||
`z1Ptr'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE void
|
||||
sub128(
|
||||
bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
|
||||
{
|
||||
|
||||
*z1Ptr = a1 - b1;
|
||||
*z0Ptr = a0 - b0 - ( a1 < b1 );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2'
|
||||
from the 192-bit value formed by concatenating `a0', `a1', and `a2'.
|
||||
Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The
|
||||
result is broken into three 64-bit pieces which are stored at the locations
|
||||
pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE void
|
||||
sub192(
|
||||
bits64 a0,
|
||||
bits64 a1,
|
||||
bits64 a2,
|
||||
bits64 b0,
|
||||
bits64 b1,
|
||||
bits64 b2,
|
||||
bits64 *z0Ptr,
|
||||
bits64 *z1Ptr,
|
||||
bits64 *z2Ptr
|
||||
)
|
||||
{
|
||||
bits64 z0, z1, z2;
|
||||
int8 borrow0, borrow1;
|
||||
|
||||
z2 = a2 - b2;
|
||||
borrow1 = ( a2 < b2 );
|
||||
z1 = a1 - b1;
|
||||
borrow0 = ( a1 < b1 );
|
||||
z0 = a0 - b0;
|
||||
z0 -= ( z1 < borrow1 );
|
||||
z1 -= borrow1;
|
||||
z0 -= borrow0;
|
||||
*z2Ptr = z2;
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Multiplies `a' by `b' to obtain a 128-bit product. The product is broken
|
||||
into two 64-bit pieces which are stored at the locations pointed to by
|
||||
`z0Ptr' and `z1Ptr'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr )
|
||||
{
|
||||
bits32 aHigh, aLow, bHigh, bLow;
|
||||
bits64 z0, zMiddleA, zMiddleB, z1;
|
||||
|
||||
aLow = a;
|
||||
aHigh = a>>32;
|
||||
bLow = b;
|
||||
bHigh = b>>32;
|
||||
z1 = ( (bits64) aLow ) * bLow;
|
||||
zMiddleA = ( (bits64) aLow ) * bHigh;
|
||||
zMiddleB = ( (bits64) aHigh ) * bLow;
|
||||
z0 = ( (bits64) aHigh ) * bHigh;
|
||||
zMiddleA += zMiddleB;
|
||||
z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 );
|
||||
zMiddleA <<= 32;
|
||||
z1 += zMiddleA;
|
||||
z0 += ( z1 < zMiddleA );
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Multiplies the 128-bit value formed by concatenating `a0' and `a1' by
|
||||
`b' to obtain a 192-bit product. The product is broken into three 64-bit
|
||||
pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
|
||||
`z2Ptr'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE void
|
||||
mul128By64To192(
|
||||
bits64 a0,
|
||||
bits64 a1,
|
||||
bits64 b,
|
||||
bits64 *z0Ptr,
|
||||
bits64 *z1Ptr,
|
||||
bits64 *z2Ptr
|
||||
)
|
||||
{
|
||||
bits64 z0, z1, z2, more1;
|
||||
|
||||
mul64To128( a1, b, &z1, &z2 );
|
||||
mul64To128( a0, b, &z0, &more1 );
|
||||
add128( z0, more1, 0, z1, &z0, &z1 );
|
||||
*z2Ptr = z2;
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the
|
||||
128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit
|
||||
product. The product is broken into four 64-bit pieces which are stored at
|
||||
the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE void
|
||||
mul128To256(
|
||||
bits64 a0,
|
||||
bits64 a1,
|
||||
bits64 b0,
|
||||
bits64 b1,
|
||||
bits64 *z0Ptr,
|
||||
bits64 *z1Ptr,
|
||||
bits64 *z2Ptr,
|
||||
bits64 *z3Ptr
|
||||
)
|
||||
{
|
||||
bits64 z0, z1, z2, z3;
|
||||
bits64 more1, more2;
|
||||
|
||||
mul64To128( a1, b1, &z2, &z3 );
|
||||
mul64To128( a1, b0, &z1, &more2 );
|
||||
add128( z1, more2, 0, z2, &z1, &z2 );
|
||||
mul64To128( a0, b0, &z0, &more1 );
|
||||
add128( z0, more1, 0, z1, &z0, &z1 );
|
||||
mul64To128( a0, b1, &more1, &more2 );
|
||||
add128( more1, more2, 0, z2, &more1, &z2 );
|
||||
add128( z0, z1, 0, more1, &z0, &z1 );
|
||||
*z3Ptr = z3;
|
||||
*z2Ptr = z2;
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns an approximation to the 64-bit integer quotient obtained by dividing
|
||||
`b' into the 128-bit value formed by concatenating `a0' and `a1'. The
|
||||
divisor `b' must be at least 2^63. If q is the exact quotient truncated
|
||||
toward zero, the approximation returned lies between q and q + 2 inclusive.
|
||||
If the exact quotient q is larger than 64 bits, the maximum positive 64-bit
|
||||
unsigned integer is returned.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b )
|
||||
{
|
||||
bits64 b0, b1;
|
||||
bits64 rem0, rem1, term0, term1;
|
||||
bits64 z;
|
||||
|
||||
if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF );
|
||||
b0 = b>>32;
|
||||
z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32;
|
||||
mul64To128( b, z, &term0, &term1 );
|
||||
sub128( a0, a1, term0, term1, &rem0, &rem1 );
|
||||
while ( ( (sbits64) rem0 ) < 0 ) {
|
||||
z -= LIT64( 0x100000000 );
|
||||
b1 = b<<32;
|
||||
add128( rem0, rem1, b0, b1, &rem0, &rem1 );
|
||||
}
|
||||
rem0 = ( rem0<<32 ) | ( rem1>>32 );
|
||||
z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0;
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
#ifndef SOFTFLOAT_FOR_GCC /* Not used */
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns an approximation to the square root of the 32-bit significand given
|
||||
by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
|
||||
`aExp' (the least significant bit) is 1, the integer returned approximates
|
||||
2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
|
||||
is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
|
||||
case, the approximation returned lies strictly within +/-2 of the exact
|
||||
value.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static bits32 estimateSqrt32( int16 aExp, bits32 a )
|
||||
{
|
||||
static const bits16 sqrtOddAdjustments[] = {
|
||||
0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
|
||||
0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
|
||||
};
|
||||
static const bits16 sqrtEvenAdjustments[] = {
|
||||
0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
|
||||
0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
|
||||
};
|
||||
int8 index;
|
||||
bits32 z;
|
||||
|
||||
index = ( a>>27 ) & 15;
|
||||
if ( aExp & 1 ) {
|
||||
z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ];
|
||||
z = ( ( a / z )<<14 ) + ( z<<15 );
|
||||
a >>= 1;
|
||||
}
|
||||
else {
|
||||
z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ];
|
||||
z = a / z + z;
|
||||
z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
|
||||
if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 );
|
||||
}
|
||||
return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 );
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns the number of leading 0 bits before the most-significant 1 bit of
|
||||
`a'. If `a' is zero, 32 is returned.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static int8 countLeadingZeros32( bits32 a )
|
||||
{
|
||||
static const int8 countLeadingZerosHigh[] = {
|
||||
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
int8 shiftCount;
|
||||
|
||||
shiftCount = 0;
|
||||
if ( a < 0x10000 ) {
|
||||
shiftCount += 16;
|
||||
a <<= 16;
|
||||
}
|
||||
if ( a < 0x1000000 ) {
|
||||
shiftCount += 8;
|
||||
a <<= 8;
|
||||
}
|
||||
shiftCount += countLeadingZerosHigh[ a>>24 ];
|
||||
return shiftCount;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns the number of leading 0 bits before the most-significant 1 bit of
|
||||
`a'. If `a' is zero, 64 is returned.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static int8 countLeadingZeros64( bits64 a )
|
||||
{
|
||||
int8 shiftCount;
|
||||
|
||||
shiftCount = 0;
|
||||
if ( a < ( (bits64) 1 )<<32 ) {
|
||||
shiftCount += 32;
|
||||
}
|
||||
else {
|
||||
a >>= 32;
|
||||
}
|
||||
shiftCount += countLeadingZeros32( a );
|
||||
return shiftCount;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'
|
||||
is equal to the 128-bit value formed by concatenating `b0' and `b1'.
|
||||
Otherwise, returns 0.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
|
||||
{
|
||||
|
||||
return ( a0 == b0 ) && ( a1 == b1 );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
|
||||
than or equal to the 128-bit value formed by concatenating `b0' and `b1'.
|
||||
Otherwise, returns 0.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
|
||||
{
|
||||
|
||||
return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
|
||||
than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise,
|
||||
returns 0.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
|
||||
{
|
||||
|
||||
return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is
|
||||
not equal to the 128-bit value formed by concatenating `b0' and `b1'.
|
||||
Otherwise, returns 0.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
INLINE flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
|
||||
{
|
||||
|
||||
return ( a0 != b0 ) || ( a1 != b1 );
|
||||
|
||||
}
|
||||
|
487
sys/lib/libkern/softfloat-specialize.h
Normal file
487
sys/lib/libkern/softfloat-specialize.h
Normal file
@ -0,0 +1,487 @@
|
||||
/* $NetBSD: softfloat-specialize.h,v 1.1 2001/04/26 03:10:47 ross Exp $ */
|
||||
|
||||
/* This is a derivative work. */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Ross Harvey.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
|
||||
Arithmetic Package, Release 2a.
|
||||
|
||||
Written by John R. Hauser. This work was made possible in part by the
|
||||
International Computer Science Institute, located at Suite 600, 1947 Center
|
||||
Street, Berkeley, California 94704. Funding was partially provided by the
|
||||
National Science Foundation under grant MIP-9311980. The original version
|
||||
of this code was written as part of a project to build a fixed-point vector
|
||||
processor in collaboration with the University of California at Berkeley,
|
||||
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
|
||||
is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
|
||||
arithmetic/SoftFloat.html'.
|
||||
|
||||
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
|
||||
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
|
||||
TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
|
||||
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
|
||||
AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
|
||||
|
||||
Derivative works are acceptable, even for commercial purposes, so long as
|
||||
(1) they include prominent notice that the work is derivative, and (2) they
|
||||
include prominent notice akin to these four paragraphs for those parts of
|
||||
this code that are retained.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Underflow tininess-detection mode, statically initialized to default value.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* [ MP safe, does not change dynamically ] */
|
||||
int float_detect_tininess = float_tininess_after_rounding;
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Internal canonical NaN format.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
typedef struct {
|
||||
flag sign;
|
||||
bits64 high, low;
|
||||
} commonNaNT;
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
The pattern for a default generated single-precision NaN.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
#define float32_default_nan 0xFFC00000
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns 1 if the single-precision floating-point value `a' is a NaN;
|
||||
otherwise returns 0.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static flag float32_is_nan( float32 a )
|
||||
{
|
||||
|
||||
return ( 0xFF000000 < (bits32) ( a<<1 ) );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns 1 if the single-precision floating-point value `a' is a signaling
|
||||
NaN; otherwise returns 0.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
flag float32_is_signaling_nan( float32 a )
|
||||
{
|
||||
|
||||
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns the result of converting the single-precision floating-point NaN
|
||||
`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
|
||||
exception is raised.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static commonNaNT float32ToCommonNaN( float32 a )
|
||||
{
|
||||
commonNaNT z;
|
||||
|
||||
if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
|
||||
z.sign = a>>31;
|
||||
z.low = 0;
|
||||
z.high = ( (bits64) a )<<41;
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns the result of converting the canonical NaN `a' to the single-
|
||||
precision floating-point format.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static float32 commonNaNToFloat32( commonNaNT a )
|
||||
{
|
||||
|
||||
return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Takes two single-precision floating-point values `a' and `b', one of which
|
||||
is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
|
||||
signaling NaN, the invalid exception is raised.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static float32 propagateFloat32NaN( float32 a, float32 b )
|
||||
{
|
||||
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
||||
|
||||
aIsNaN = float32_is_nan( a );
|
||||
aIsSignalingNaN = float32_is_signaling_nan( a );
|
||||
bIsNaN = float32_is_nan( b );
|
||||
bIsSignalingNaN = float32_is_signaling_nan( b );
|
||||
a |= 0x00400000;
|
||||
b |= 0x00400000;
|
||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
|
||||
if ( aIsSignalingNaN ) {
|
||||
if ( bIsSignalingNaN ) goto returnLargerSignificand;
|
||||
return bIsNaN ? b : a;
|
||||
}
|
||||
else if ( aIsNaN ) {
|
||||
if ( bIsSignalingNaN | ! bIsNaN ) return a;
|
||||
returnLargerSignificand:
|
||||
if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
|
||||
if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
|
||||
return ( a < b ) ? a : b;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns the result of converting the double-precision floating-point NaN
|
||||
`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
|
||||
exception is raised.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static commonNaNT float64ToCommonNaN( float64 a )
|
||||
{
|
||||
commonNaNT z;
|
||||
|
||||
if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
|
||||
z.sign = a>>63;
|
||||
z.low = 0;
|
||||
z.high = a<<12;
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns the result of converting the canonical NaN `a' to the double-
|
||||
precision floating-point format.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static float64 commonNaNToFloat64( commonNaNT a )
|
||||
{
|
||||
|
||||
return
|
||||
( ( (bits64) a.sign )<<63 )
|
||||
| LIT64( 0x7FF8000000000000 )
|
||||
| ( a.high>>12 );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Takes two double-precision floating-point values `a' and `b', one of which
|
||||
is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
|
||||
signaling NaN, the invalid exception is raised.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static float64 propagateFloat64NaN( float64 a, float64 b )
|
||||
{
|
||||
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
||||
|
||||
aIsNaN = float64_is_nan( a );
|
||||
aIsSignalingNaN = float64_is_signaling_nan( a );
|
||||
bIsNaN = float64_is_nan( b );
|
||||
bIsSignalingNaN = float64_is_signaling_nan( b );
|
||||
a |= LIT64( 0x0008000000000000 );
|
||||
b |= LIT64( 0x0008000000000000 );
|
||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
|
||||
if ( aIsSignalingNaN ) {
|
||||
if ( bIsSignalingNaN ) goto returnLargerSignificand;
|
||||
return bIsNaN ? b : a;
|
||||
}
|
||||
else if ( aIsNaN ) {
|
||||
if ( bIsSignalingNaN | ! bIsNaN ) return a;
|
||||
returnLargerSignificand:
|
||||
if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
|
||||
if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
|
||||
return ( a < b ) ? a : b;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef FLOATX80
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
The pattern for a default generated extended double-precision NaN. The
|
||||
`high' and `low' values hold the most- and least-significant bits,
|
||||
respectively.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
#define floatx80_default_nan_high 0xFFFF
|
||||
#define floatx80_default_nan_low LIT64( 0xC000000000000000 )
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns 1 if the extended double-precision floating-point value `a' is a
|
||||
NaN; otherwise returns 0.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static flag floatx80_is_nan( floatx80 a )
|
||||
{
|
||||
|
||||
return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns 1 if the extended double-precision floating-point value `a' is a
|
||||
signaling NaN; otherwise returns 0.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
flag floatx80_is_signaling_nan( floatx80 a )
|
||||
{
|
||||
bits64 aLow;
|
||||
|
||||
aLow = a.low & ~ LIT64( 0x4000000000000000 );
|
||||
return
|
||||
( ( a.high & 0x7FFF ) == 0x7FFF )
|
||||
&& (bits64) ( aLow<<1 )
|
||||
&& ( a.low == aLow );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns the result of converting the extended double-precision floating-
|
||||
point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
|
||||
invalid exception is raised.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static commonNaNT floatx80ToCommonNaN( floatx80 a )
|
||||
{
|
||||
commonNaNT z;
|
||||
|
||||
if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
|
||||
z.sign = a.high>>15;
|
||||
z.low = 0;
|
||||
z.high = a.low<<1;
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns the result of converting the canonical NaN `a' to the extended
|
||||
double-precision floating-point format.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static floatx80 commonNaNToFloatx80( commonNaNT a )
|
||||
{
|
||||
floatx80 z;
|
||||
|
||||
z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
|
||||
z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Takes two extended double-precision floating-point values `a' and `b', one
|
||||
of which is a NaN, and returns the appropriate NaN result. If either `a' or
|
||||
`b' is a signaling NaN, the invalid exception is raised.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
|
||||
{
|
||||
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
||||
|
||||
aIsNaN = floatx80_is_nan( a );
|
||||
aIsSignalingNaN = floatx80_is_signaling_nan( a );
|
||||
bIsNaN = floatx80_is_nan( b );
|
||||
bIsSignalingNaN = floatx80_is_signaling_nan( b );
|
||||
a.low |= LIT64( 0xC000000000000000 );
|
||||
b.low |= LIT64( 0xC000000000000000 );
|
||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
|
||||
if ( aIsSignalingNaN ) {
|
||||
if ( bIsSignalingNaN ) goto returnLargerSignificand;
|
||||
return bIsNaN ? b : a;
|
||||
}
|
||||
else if ( aIsNaN ) {
|
||||
if ( bIsSignalingNaN | ! bIsNaN ) return a;
|
||||
returnLargerSignificand:
|
||||
if ( a.low < b.low ) return b;
|
||||
if ( b.low < a.low ) return a;
|
||||
return ( a.high < b.high ) ? a : b;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FLOAT128
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
The pattern for a default generated quadruple-precision NaN. The `high' and
|
||||
`low' values hold the most- and least-significant bits, respectively.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
|
||||
#define float128_default_nan_low LIT64( 0x0000000000000000 )
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
|
||||
otherwise returns 0.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
flag float128_is_nan( float128 a )
|
||||
{
|
||||
|
||||
return
|
||||
( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
|
||||
&& ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns 1 if the quadruple-precision floating-point value `a' is a
|
||||
signaling NaN; otherwise returns 0.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
flag float128_is_signaling_nan( float128 a )
|
||||
{
|
||||
|
||||
return
|
||||
( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
|
||||
&& ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns the result of converting the quadruple-precision floating-point NaN
|
||||
`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
|
||||
exception is raised.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static commonNaNT float128ToCommonNaN( float128 a )
|
||||
{
|
||||
commonNaNT z;
|
||||
|
||||
if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
|
||||
z.sign = a.high>>63;
|
||||
shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Returns the result of converting the canonical NaN `a' to the quadruple-
|
||||
precision floating-point format.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static float128 commonNaNToFloat128( commonNaNT a )
|
||||
{
|
||||
float128 z;
|
||||
|
||||
shift128Right( a.high, a.low, 16, &z.high, &z.low );
|
||||
z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Takes two quadruple-precision floating-point values `a' and `b', one of
|
||||
which is a NaN, and returns the appropriate NaN result. If either `a' or
|
||||
`b' is a signaling NaN, the invalid exception is raised.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
static float128 propagateFloat128NaN( float128 a, float128 b )
|
||||
{
|
||||
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
||||
|
||||
aIsNaN = float128_is_nan( a );
|
||||
aIsSignalingNaN = float128_is_signaling_nan( a );
|
||||
bIsNaN = float128_is_nan( b );
|
||||
bIsSignalingNaN = float128_is_signaling_nan( b );
|
||||
a.high |= LIT64( 0x0000800000000000 );
|
||||
b.high |= LIT64( 0x0000800000000000 );
|
||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
|
||||
if ( aIsSignalingNaN ) {
|
||||
if ( bIsSignalingNaN ) goto returnLargerSignificand;
|
||||
return bIsNaN ? b : a;
|
||||
}
|
||||
else if ( aIsNaN ) {
|
||||
if ( bIsSignalingNaN | ! bIsNaN ) return a;
|
||||
returnLargerSignificand:
|
||||
if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
|
||||
if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
|
||||
return ( a.high < b.high ) ? a : b;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
5497
sys/lib/libkern/softfloat.c
Normal file
5497
sys/lib/libkern/softfloat.c
Normal file
File diff suppressed because it is too large
Load Diff
370
sys/lib/libkern/softfloat.h
Normal file
370
sys/lib/libkern/softfloat.h
Normal file
@ -0,0 +1,370 @@
|
||||
/* $NetBSD: softfloat.h,v 1.1 2001/04/26 03:10:48 ross Exp $ */
|
||||
|
||||
/* This is a derivative work. */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Ross Harvey.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
This C header file is part of the SoftFloat IEC/IEEE Floating-point
|
||||
Arithmetic Package, Release 2a.
|
||||
|
||||
Written by John R. Hauser. This work was made possible in part by the
|
||||
International Computer Science Institute, located at Suite 600, 1947 Center
|
||||
Street, Berkeley, California 94704. Funding was partially provided by the
|
||||
National Science Foundation under grant MIP-9311980. The original version
|
||||
of this code was written as part of a project to build a fixed-point vector
|
||||
processor in collaboration with the University of California at Berkeley,
|
||||
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
|
||||
is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
|
||||
arithmetic/SoftFloat.html'.
|
||||
|
||||
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
|
||||
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
|
||||
TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
|
||||
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
|
||||
AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
|
||||
|
||||
Derivative works are acceptable, even for commercial purposes, so long as
|
||||
(1) they include prominent notice that the work is derivative, and (2) they
|
||||
include prominent notice akin to these four paragraphs for those parts of
|
||||
this code that are retained.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if !defined(_KERNEL) && !defined(_STANDALONE)
|
||||
#include <inttypes.h>
|
||||
#include <ieeefp.h>
|
||||
#else
|
||||
#include "sys/inttypes.h"
|
||||
#include "machine/ieeefp.h"
|
||||
#endif
|
||||
#include <sys/endian.h>
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
The macro `FLOATX80' must be defined to enable the extended double-precision
|
||||
floating-point format `floatx80'. If this macro is not defined, the
|
||||
`floatx80' type will not be defined, and none of the functions that either
|
||||
input or output the `floatx80' type will be defined. The same applies to
|
||||
the `FLOAT128' macro and the quadruple-precision format `float128'.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
/* #define FLOATX80 */
|
||||
/* #define FLOAT128 */
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE floating-point types.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
typedef u_int32_t float32;
|
||||
typedef u_int64_t float64;
|
||||
#ifdef FLOATX80
|
||||
typedef struct {
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
u_int16_t high;
|
||||
u_int64_t low;
|
||||
#else
|
||||
u_int64_t low;
|
||||
u_int16_t high;
|
||||
#endif
|
||||
} floatx80;
|
||||
#endif
|
||||
#ifdef FLOAT128
|
||||
typedef struct {
|
||||
u_int64_t high, low;
|
||||
} float128;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some of the global variables that used to be here have been removed for
|
||||
* fairly obvious (defopt-MULTIPROCESSOR) reasons. The rest (which don't
|
||||
* change dynamically) will be removed later. [ross]
|
||||
*/
|
||||
|
||||
#define float_rounding_mode() fpgetround()
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE floating-point underflow tininess-detection mode.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
extern int float_detect_tininess;
|
||||
enum {
|
||||
float_tininess_after_rounding = 1,
|
||||
float_tininess_before_rounding = 0
|
||||
};
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE floating-point rounding mode.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
enum {
|
||||
float_round_nearest_even = FP_RN,
|
||||
float_round_to_zero = FP_RZ,
|
||||
float_round_down = FP_RM,
|
||||
float_round_up = FP_RP
|
||||
};
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE floating-point exception flags.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
enum {
|
||||
float_flag_inexact = FP_X_IMP,
|
||||
float_flag_underflow = FP_X_UFL,
|
||||
float_flag_overflow = FP_X_OFL,
|
||||
float_flag_divbyzero = FP_X_DZ,
|
||||
float_flag_invalid = FP_X_INV
|
||||
};
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE integer-to-floating-point conversion routines.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
float32 int32_to_float32( int );
|
||||
float64 int32_to_float64( int );
|
||||
#ifdef FLOATX80
|
||||
floatx80 int32_to_floatx80( int );
|
||||
#endif
|
||||
#ifdef FLOAT128
|
||||
float128 int32_to_float128( int );
|
||||
#endif
|
||||
#ifndef SOFTFLOAT_FOR_GCC /* __floatdi?f is in libgcc2.c */
|
||||
float32 int64_to_float32( int64_t );
|
||||
float64 int64_to_float64( int64_t );
|
||||
#ifdef FLOATX80
|
||||
floatx80 int64_to_floatx80( int64_t );
|
||||
#endif
|
||||
#ifdef FLOAT128
|
||||
float128 int64_to_float128( int64_t );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE single-precision conversion routines.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
int float32_to_int32( float32 );
|
||||
int float32_to_int32_round_to_zero( float32 );
|
||||
#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */
|
||||
int64_t float32_to_int64( float32 );
|
||||
int64_t float32_to_int64_round_to_zero( float32 );
|
||||
#endif
|
||||
float64 float32_to_float64( float32 );
|
||||
#ifdef FLOATX80
|
||||
floatx80 float32_to_floatx80( float32 );
|
||||
#endif
|
||||
#ifdef FLOAT128
|
||||
float128 float32_to_float128( float32 );
|
||||
#endif
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE single-precision operations.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
float32 float32_round_to_int( float32 );
|
||||
float32 float32_add( float32, float32 );
|
||||
float32 float32_sub( float32, float32 );
|
||||
float32 float32_mul( float32, float32 );
|
||||
float32 float32_div( float32, float32 );
|
||||
float32 float32_rem( float32, float32 );
|
||||
float32 float32_sqrt( float32 );
|
||||
int float32_eq( float32, float32 );
|
||||
int float32_le( float32, float32 );
|
||||
int float32_lt( float32, float32 );
|
||||
int float32_eq_signaling( float32, float32 );
|
||||
int float32_le_quiet( float32, float32 );
|
||||
int float32_lt_quiet( float32, float32 );
|
||||
#ifndef SOFTFLOAT_FOR_GCC
|
||||
int float32_is_signaling_nan( float32 );
|
||||
#endif
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE double-precision conversion routines.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
int float64_to_int32( float64 );
|
||||
int float64_to_int32_round_to_zero( float64 );
|
||||
#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */
|
||||
int64_t float64_to_int64( float64 );
|
||||
int64_t float64_to_int64_round_to_zero( float64 );
|
||||
#endif
|
||||
float32 float64_to_float32( float64 );
|
||||
#ifdef FLOATX80
|
||||
floatx80 float64_to_floatx80( float64 );
|
||||
#endif
|
||||
#ifdef FLOAT128
|
||||
float128 float64_to_float128( float64 );
|
||||
#endif
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE double-precision operations.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
#define float64_default_nan 0xFFF8000000000000LL
|
||||
|
||||
static __inline int
|
||||
float64_is_nan(float64 a)
|
||||
{
|
||||
return 0xFFE0000000000000LL < a << 1;
|
||||
}
|
||||
|
||||
static __inline int
|
||||
float64_is_signaling_nan(float64 a)
|
||||
{
|
||||
return (a >> 51 & 0xFFF) == 0xFFE && (a & 0x0007FFFFFFFFFFFFLL);
|
||||
}
|
||||
|
||||
float64 float64_round_to_int( float64 );
|
||||
float64 float64_add( float64, float64 );
|
||||
float64 float64_sub( float64, float64 );
|
||||
float64 float64_mul( float64, float64 );
|
||||
float64 float64_div( float64, float64 );
|
||||
float64 float64_rem( float64, float64 );
|
||||
float64 float64_sqrt( float64 );
|
||||
int float64_eq( float64, float64 );
|
||||
int float64_le( float64, float64 );
|
||||
int float64_lt( float64, float64 );
|
||||
int float64_eq_signaling( float64, float64 );
|
||||
int float64_le_quiet( float64, float64 );
|
||||
int float64_lt_quiet( float64, float64 );
|
||||
#ifndef SOFTFLOAT_FOR_GCC
|
||||
int float64_is_signaling_nan( float64 );
|
||||
#endif
|
||||
|
||||
#ifdef FLOATX80
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE extended double-precision conversion routines.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
int floatx80_to_int32( floatx80 );
|
||||
int floatx80_to_int32_round_to_zero( floatx80 );
|
||||
int64_t floatx80_to_int64( floatx80 );
|
||||
int64_t floatx80_to_int64_round_to_zero( floatx80 );
|
||||
float32 floatx80_to_float32( floatx80 );
|
||||
float64 floatx80_to_float64( floatx80 );
|
||||
#ifdef FLOAT128
|
||||
float128 floatx80_to_float128( floatx80 );
|
||||
#endif
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE extended double-precision rounding precision. Valid
|
||||
values are 32, 64, and 80.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
extern int floatx80_rounding_precision;
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE extended double-precision operations.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
floatx80 floatx80_round_to_int( floatx80 );
|
||||
floatx80 floatx80_add( floatx80, floatx80 );
|
||||
floatx80 floatx80_sub( floatx80, floatx80 );
|
||||
floatx80 floatx80_mul( floatx80, floatx80 );
|
||||
floatx80 floatx80_div( floatx80, floatx80 );
|
||||
floatx80 floatx80_rem( floatx80, floatx80 );
|
||||
floatx80 floatx80_sqrt( floatx80 );
|
||||
int floatx80_eq( floatx80, floatx80 );
|
||||
int floatx80_le( floatx80, floatx80 );
|
||||
int floatx80_lt( floatx80, floatx80 );
|
||||
int floatx80_eq_signaling( floatx80, floatx80 );
|
||||
int floatx80_le_quiet( floatx80, floatx80 );
|
||||
int floatx80_lt_quiet( floatx80, floatx80 );
|
||||
int floatx80_is_signaling_nan( floatx80 );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FLOAT128
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE quadruple-precision conversion routines.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
int float128_to_int32( float128 );
|
||||
int float128_to_int32_round_to_zero( float128 );
|
||||
int64_t float128_to_int64( float128 );
|
||||
int64_t float128_to_int64_round_to_zero( float128 );
|
||||
float32 float128_to_float32( float128 );
|
||||
float64 float128_to_float64( float128 );
|
||||
#ifdef FLOATX80
|
||||
floatx80 float128_to_floatx80( float128 );
|
||||
#endif
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Software IEC/IEEE quadruple-precision operations.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
float128 float128_round_to_int( float128 );
|
||||
float128 float128_add( float128, float128 );
|
||||
float128 float128_sub( float128, float128 );
|
||||
float128 float128_mul( float128, float128 );
|
||||
float128 float128_div( float128, float128 );
|
||||
float128 float128_rem( float128, float128 );
|
||||
float128 float128_sqrt( float128 );
|
||||
int float128_eq( float128, float128 );
|
||||
int float128_le( float128, float128 );
|
||||
int float128_lt( float128, float128 );
|
||||
int float128_eq_signaling( float128, float128 );
|
||||
int float128_le_quiet( float128, float128 );
|
||||
int float128_lt_quiet( float128, float128 );
|
||||
int float128_is_signaling_nan( float128 );
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user