1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
2 | /* |
3 | NetWinder Floating Point Emulator |
4 | (c) Rebel.com, 1998-1999 |
5 | |
6 | Direct questions, comments to Scott Bambrough <scottb@netwinder.org> |
7 | |
8 | */ |
9 | |
10 | #ifndef __FPA11_H__ |
11 | #define __FPA11_H__ |
12 | |
13 | #define GET_FPA11() ((FPA11 *)(¤t_thread_info()->fpstate)) |
14 | |
15 | /* |
16 | * The processes registers are always at the very top of the 8K |
17 | * stack+task struct. Use the same method as 'current' uses to |
18 | * reach them. |
19 | */ |
20 | #define GET_USERREG() ((struct pt_regs *)(THREAD_START_SP + (unsigned long)current_thread_info()) - 1) |
21 | |
22 | #include <linux/thread_info.h> |
23 | |
24 | /* includes */ |
25 | #include "fpsr.h" /* FP control and status register definitions */ |
26 | #include "milieu.h" |
27 | |
28 | struct roundingData { |
29 | int8 mode; |
30 | int8 precision; |
31 | signed char exception; |
32 | }; |
33 | |
34 | #include "softfloat.h" |
35 | |
36 | #define typeNone 0x00 |
37 | #define typeSingle 0x01 |
38 | #define typeDouble 0x02 |
39 | #define typeExtended 0x03 |
40 | |
41 | /* |
42 | * This must be no more and no less than 12 bytes. |
43 | */ |
44 | typedef union tagFPREG { |
45 | float32 fSingle; |
46 | float64 fDouble; |
47 | #ifdef CONFIG_FPE_NWFPE_XP |
48 | floatx80 fExtended; |
49 | #else |
50 | u32 padding[3]; |
51 | #endif |
52 | } __attribute__ ((packed,aligned(4))) FPREG; |
53 | |
54 | /* |
55 | * FPA11 device model. |
56 | * |
57 | * This structure is exported to user space. Do not re-order. |
58 | * Only add new stuff to the end, and do not change the size of |
59 | * any element. Elements of this structure are used by user |
60 | * space, and must match struct user_fp in <asm/user.h>. |
61 | * We include the byte offsets below for documentation purposes. |
62 | * |
63 | * The size of this structure and FPREG are checked by fpmodule.c |
64 | * on initialisation. If the rules have been broken, NWFPE will |
65 | * not initialise. |
66 | */ |
67 | typedef struct tagFPA11 { |
68 | /* 0 */ FPREG fpreg[8]; /* 8 floating point registers */ |
69 | /* 96 */ FPSR fpsr; /* floating point status register */ |
70 | /* 100 */ FPCR fpcr; /* floating point control register */ |
71 | /* 104 */ unsigned char fType[8]; /* type of floating point value held in |
72 | floating point registers. One of |
73 | none, single, double or extended. */ |
74 | /* 112 */ int initflag; /* this is special. The kernel guarantees |
75 | to set it to 0 when a thread is launched, |
76 | so we can use it to detect whether this |
77 | instance of the emulator needs to be |
78 | initialised. */ |
79 | } __attribute__ ((packed,aligned(4))) FPA11; |
80 | |
81 | extern int8 SetRoundingMode(const unsigned int); |
82 | extern int8 SetRoundingPrecision(const unsigned int); |
83 | extern void nwfpe_init_fpa(union fp_state *fp); |
84 | |
85 | extern unsigned int EmulateAll(unsigned int opcode); |
86 | |
87 | extern unsigned int EmulateCPDT(const unsigned int opcode); |
88 | extern unsigned int EmulateCPDO(const unsigned int opcode); |
89 | extern unsigned int EmulateCPRT(const unsigned int opcode); |
90 | |
91 | /* fpa11_cpdt.c */ |
92 | extern unsigned int PerformLDF(const unsigned int opcode); |
93 | extern unsigned int PerformSTF(const unsigned int opcode); |
94 | extern unsigned int PerformLFM(const unsigned int opcode); |
95 | extern unsigned int PerformSFM(const unsigned int opcode); |
96 | |
97 | /* single_cpdo.c */ |
98 | |
99 | extern unsigned int SingleCPDO(struct roundingData *roundData, |
100 | const unsigned int opcode, FPREG * rFd); |
101 | /* double_cpdo.c */ |
102 | extern unsigned int DoubleCPDO(struct roundingData *roundData, |
103 | const unsigned int opcode, FPREG * rFd); |
104 | |
105 | /* extneded_cpdo.c */ |
106 | extern unsigned int ExtendedCPDO(struct roundingData *roundData, |
107 | const unsigned int opcode, FPREG * rFd); |
108 | |
109 | #endif |
110 | |