1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /*---------------------------------------------------------------------------+ |
3 | | reg_constant.c | |
4 | | | |
5 | | All of the constant FPU_REGs | |
6 | | | |
7 | | Copyright (C) 1992,1993,1994,1997 | |
8 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | |
9 | | Australia. E-mail billm@suburbia.net | |
10 | | | |
11 | | | |
12 | +---------------------------------------------------------------------------*/ |
13 | |
14 | #include "fpu_system.h" |
15 | #include "fpu_emu.h" |
16 | #include "status_w.h" |
17 | #include "reg_constant.h" |
18 | #include "control_w.h" |
19 | |
20 | #define MAKE_REG(s, e, l, h) { l, h, \ |
21 | (u16)((EXTENDED_Ebias+(e)) | ((SIGN_##s != 0)*0x8000)) } |
22 | |
23 | FPU_REG const CONST_1 = MAKE_REG(POS, 0, 0x00000000, 0x80000000); |
24 | #if 0 |
25 | FPU_REG const CONST_2 = MAKE_REG(POS, 1, 0x00000000, 0x80000000); |
26 | FPU_REG const CONST_HALF = MAKE_REG(POS, -1, 0x00000000, 0x80000000); |
27 | #endif /* 0 */ |
28 | static FPU_REG const CONST_L2T = MAKE_REG(POS, 1, 0xcd1b8afe, 0xd49a784b); |
29 | static FPU_REG const CONST_L2E = MAKE_REG(POS, 0, 0x5c17f0bc, 0xb8aa3b29); |
30 | FPU_REG const CONST_PI = MAKE_REG(POS, 1, 0x2168c235, 0xc90fdaa2); |
31 | FPU_REG const CONST_PI2 = MAKE_REG(POS, 0, 0x2168c235, 0xc90fdaa2); |
32 | FPU_REG const CONST_PI4 = MAKE_REG(POS, -1, 0x2168c235, 0xc90fdaa2); |
33 | static FPU_REG const CONST_LG2 = MAKE_REG(POS, -2, 0xfbcff799, 0x9a209a84); |
34 | static FPU_REG const CONST_LN2 = MAKE_REG(POS, -1, 0xd1cf79ac, 0xb17217f7); |
35 | |
36 | /* Extra bits to take pi/2 to more than 128 bits precision. */ |
37 | FPU_REG const = MAKE_REG(NEG, -66, |
38 | 0xfc8f8cbb, 0xece675d1); |
39 | |
40 | /* Only the sign (and tag) is used in internal zeroes */ |
41 | FPU_REG const CONST_Z = MAKE_REG(POS, EXP_UNDER, 0x0, 0x0); |
42 | |
43 | /* Only the sign and significand (and tag) are used in internal NaNs */ |
44 | /* The 80486 never generates one of these |
45 | FPU_REG const CONST_SNAN = MAKE_REG(POS, EXP_OVER, 0x00000001, 0x80000000); |
46 | */ |
47 | /* This is the real indefinite QNaN */ |
48 | FPU_REG const CONST_QNaN = MAKE_REG(NEG, EXP_OVER, 0x00000000, 0xC0000000); |
49 | |
50 | /* Only the sign (and tag) is used in internal infinities */ |
51 | FPU_REG const CONST_INF = MAKE_REG(POS, EXP_OVER, 0x00000000, 0x80000000); |
52 | |
53 | static void fld_const(FPU_REG const * c, int adj, u_char tag) |
54 | { |
55 | FPU_REG *st_new_ptr; |
56 | |
57 | if (STACK_OVERFLOW) { |
58 | FPU_stack_overflow(); |
59 | return; |
60 | } |
61 | push(); |
62 | reg_copy(x: c, y: st_new_ptr); |
63 | st_new_ptr->sigl += adj; /* For all our fldxxx constants, we don't need to |
64 | borrow or carry. */ |
65 | FPU_settag0(tag); |
66 | clear_C1(); |
67 | } |
68 | |
69 | /* A fast way to find out whether x is one of RC_DOWN or RC_CHOP |
70 | (and not one of RC_RND or RC_UP). |
71 | */ |
72 | #define DOWN_OR_CHOP(x) (x & RC_DOWN) |
73 | |
74 | static void fld1(int rc) |
75 | { |
76 | fld_const(c: &CONST_1, adj: 0, TAG_Valid); |
77 | } |
78 | |
79 | static void fldl2t(int rc) |
80 | { |
81 | fld_const(c: &CONST_L2T, adj: (rc == RC_UP) ? 1 : 0, TAG_Valid); |
82 | } |
83 | |
84 | static void fldl2e(int rc) |
85 | { |
86 | fld_const(c: &CONST_L2E, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid); |
87 | } |
88 | |
89 | static void fldpi(int rc) |
90 | { |
91 | fld_const(c: &CONST_PI, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid); |
92 | } |
93 | |
94 | static void fldlg2(int rc) |
95 | { |
96 | fld_const(c: &CONST_LG2, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid); |
97 | } |
98 | |
99 | static void fldln2(int rc) |
100 | { |
101 | fld_const(c: &CONST_LN2, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid); |
102 | } |
103 | |
104 | static void fldz(int rc) |
105 | { |
106 | fld_const(c: &CONST_Z, adj: 0, TAG_Zero); |
107 | } |
108 | |
109 | typedef void (*FUNC_RC) (int); |
110 | |
111 | static FUNC_RC constants_table[] = { |
112 | fld1, fldl2t, fldl2e, fldpi, fldlg2, fldln2, fldz, (FUNC_RC) FPU_illegal |
113 | }; |
114 | |
115 | void fconst(void) |
116 | { |
117 | (constants_table[FPU_rm]) (control_word & CW_RC); |
118 | } |
119 | |