18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci    NetWinder Floating Point Emulator
48c2ecf20Sopenharmony_ci    (c) Rebel.com, 1998-1999
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci*/
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#ifndef __FPA11_H__
118c2ecf20Sopenharmony_ci#define __FPA11_H__
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#define GET_FPA11() ((FPA11 *)(&current_thread_info()->fpstate))
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/*
168c2ecf20Sopenharmony_ci * The processes registers are always at the very top of the 8K
178c2ecf20Sopenharmony_ci * stack+task struct.  Use the same method as 'current' uses to
188c2ecf20Sopenharmony_ci * reach them.
198c2ecf20Sopenharmony_ci */
208c2ecf20Sopenharmony_ci#define GET_USERREG() ((struct pt_regs *)(THREAD_START_SP + (unsigned long)current_thread_info()) - 1)
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include <linux/thread_info.h>
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci/* includes */
258c2ecf20Sopenharmony_ci#include "fpsr.h"		/* FP control and status register definitions */
268c2ecf20Sopenharmony_ci#include "milieu.h"
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistruct roundingData {
298c2ecf20Sopenharmony_ci    int8 mode;
308c2ecf20Sopenharmony_ci    int8 precision;
318c2ecf20Sopenharmony_ci    signed char exception;
328c2ecf20Sopenharmony_ci};
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#include "softfloat.h"
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#define		typeNone		0x00
378c2ecf20Sopenharmony_ci#define		typeSingle		0x01
388c2ecf20Sopenharmony_ci#define		typeDouble		0x02
398c2ecf20Sopenharmony_ci#define		typeExtended		0x03
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci/*
428c2ecf20Sopenharmony_ci * This must be no more and no less than 12 bytes.
438c2ecf20Sopenharmony_ci */
448c2ecf20Sopenharmony_citypedef union tagFPREG {
458c2ecf20Sopenharmony_ci	float32 fSingle;
468c2ecf20Sopenharmony_ci	float64 fDouble;
478c2ecf20Sopenharmony_ci#ifdef CONFIG_FPE_NWFPE_XP
488c2ecf20Sopenharmony_ci	floatx80 fExtended;
498c2ecf20Sopenharmony_ci#else
508c2ecf20Sopenharmony_ci	u32 padding[3];
518c2ecf20Sopenharmony_ci#endif
528c2ecf20Sopenharmony_ci} __attribute__ ((packed,aligned(4))) FPREG;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci/*
558c2ecf20Sopenharmony_ci * FPA11 device model.
568c2ecf20Sopenharmony_ci *
578c2ecf20Sopenharmony_ci * This structure is exported to user space.  Do not re-order.
588c2ecf20Sopenharmony_ci * Only add new stuff to the end, and do not change the size of
598c2ecf20Sopenharmony_ci * any element.  Elements of this structure are used by user
608c2ecf20Sopenharmony_ci * space, and must match struct user_fp in <asm/user.h>.
618c2ecf20Sopenharmony_ci * We include the byte offsets below for documentation purposes.
628c2ecf20Sopenharmony_ci *
638c2ecf20Sopenharmony_ci * The size of this structure and FPREG are checked by fpmodule.c
648c2ecf20Sopenharmony_ci * on initialisation.  If the rules have been broken, NWFPE will
658c2ecf20Sopenharmony_ci * not initialise.
668c2ecf20Sopenharmony_ci */
678c2ecf20Sopenharmony_citypedef struct tagFPA11 {
688c2ecf20Sopenharmony_ci/*   0 */ FPREG fpreg[8];	/* 8 floating point registers */
698c2ecf20Sopenharmony_ci/*  96 */ FPSR fpsr;		/* floating point status register */
708c2ecf20Sopenharmony_ci/* 100 */ FPCR fpcr;		/* floating point control register */
718c2ecf20Sopenharmony_ci/* 104 */ unsigned char fType[8];	/* type of floating point value held in
728c2ecf20Sopenharmony_ci					   floating point registers.  One of
738c2ecf20Sopenharmony_ci					   none, single, double or extended. */
748c2ecf20Sopenharmony_ci/* 112 */ int initflag;		/* this is special.  The kernel guarantees
758c2ecf20Sopenharmony_ci				   to set it to 0 when a thread is launched,
768c2ecf20Sopenharmony_ci				   so we can use it to detect whether this
778c2ecf20Sopenharmony_ci				   instance of the emulator needs to be
788c2ecf20Sopenharmony_ci				   initialised. */
798c2ecf20Sopenharmony_ci} __attribute__ ((packed,aligned(4))) FPA11;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ciextern int8 SetRoundingMode(const unsigned int);
828c2ecf20Sopenharmony_ciextern int8 SetRoundingPrecision(const unsigned int);
838c2ecf20Sopenharmony_ciextern void nwfpe_init_fpa(union fp_state *fp);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ciextern unsigned int EmulateAll(unsigned int opcode);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ciextern unsigned int EmulateCPDT(const unsigned int opcode);
888c2ecf20Sopenharmony_ciextern unsigned int EmulateCPDO(const unsigned int opcode);
898c2ecf20Sopenharmony_ciextern unsigned int EmulateCPRT(const unsigned int opcode);
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci/* fpa11_cpdt.c */
928c2ecf20Sopenharmony_ciextern unsigned int PerformLDF(const unsigned int opcode);
938c2ecf20Sopenharmony_ciextern unsigned int PerformSTF(const unsigned int opcode);
948c2ecf20Sopenharmony_ciextern unsigned int PerformLFM(const unsigned int opcode);
958c2ecf20Sopenharmony_ciextern unsigned int PerformSFM(const unsigned int opcode);
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci/* single_cpdo.c */
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ciextern unsigned int SingleCPDO(struct roundingData *roundData,
1008c2ecf20Sopenharmony_ci			       const unsigned int opcode, FPREG * rFd);
1018c2ecf20Sopenharmony_ci/* double_cpdo.c */
1028c2ecf20Sopenharmony_ciextern unsigned int DoubleCPDO(struct roundingData *roundData,
1038c2ecf20Sopenharmony_ci			       const unsigned int opcode, FPREG * rFd);
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci/* extneded_cpdo.c */
1068c2ecf20Sopenharmony_ciextern unsigned int ExtendedCPDO(struct roundingData *roundData,
1078c2ecf20Sopenharmony_ci				 const unsigned int opcode, FPREG * rFd);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci#endif
110