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