Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003     NetWinder Floating Point Emulator
0004     (c) Rebel.COM, 1998,1999
0005     (c) Philip Blundell, 2001
0006 
0007     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
0008 
0009 */
0010 
0011 #include "fpa11.h"
0012 #include "fpopcode.h"
0013 
0014 #include "fpmodule.h"
0015 #include "fpmodule.inl"
0016 
0017 #include <linux/compiler.h>
0018 #include <linux/string.h>
0019 
0020 /* Reset the FPA11 chip.  Called to initialize and reset the emulator. */
0021 static void resetFPA11(void)
0022 {
0023     int i;
0024     FPA11 *fpa11 = GET_FPA11();
0025 
0026     /* initialize the register type array */
0027     for (i = 0; i <= 7; i++) {
0028         fpa11->fType[i] = typeNone;
0029     }
0030 
0031     /* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */
0032     fpa11->fpsr = FP_EMULATOR | BIT_AC;
0033 }
0034 
0035 int8 SetRoundingMode(const unsigned int opcode)
0036 {
0037     switch (opcode & MASK_ROUNDING_MODE) {
0038     default:
0039     case ROUND_TO_NEAREST:
0040         return float_round_nearest_even;
0041 
0042     case ROUND_TO_PLUS_INFINITY:
0043         return float_round_up;
0044 
0045     case ROUND_TO_MINUS_INFINITY:
0046         return float_round_down;
0047 
0048     case ROUND_TO_ZERO:
0049         return float_round_to_zero;
0050     }
0051 }
0052 
0053 int8 SetRoundingPrecision(const unsigned int opcode)
0054 {
0055 #ifdef CONFIG_FPE_NWFPE_XP
0056     switch (opcode & MASK_ROUNDING_PRECISION) {
0057     case ROUND_SINGLE:
0058         return 32;
0059 
0060     case ROUND_DOUBLE:
0061         return 64;
0062 
0063     case ROUND_EXTENDED:
0064         return 80;
0065 
0066     default:
0067         return 80;
0068     }
0069 #endif
0070     return 80;
0071 }
0072 
0073 void nwfpe_init_fpa(union fp_state *fp)
0074 {
0075     FPA11 *fpa11 = (FPA11 *)fp;
0076 #ifdef NWFPE_DEBUG
0077     printk("NWFPE: setting up state.\n");
0078 #endif
0079     memset(fpa11, 0, sizeof(FPA11));
0080     resetFPA11();
0081     fpa11->initflag = 1;
0082 }
0083 
0084 /* Emulate the instruction in the opcode. */
0085 unsigned int EmulateAll(unsigned int opcode)
0086 {
0087     unsigned int code;
0088 
0089 #ifdef NWFPE_DEBUG
0090     printk("NWFPE: emulating opcode %08x\n", opcode);
0091 #endif
0092     code = opcode & 0x00000f00;
0093     if (code == 0x00000100 || code == 0x00000200) {
0094         /* For coprocessor 1 or 2 (FPA11) */
0095         code = opcode & 0x0e000000;
0096         if (code == 0x0e000000) {
0097             if (opcode & 0x00000010) {
0098                 /* Emulate conversion opcodes. */
0099                 /* Emulate register transfer opcodes. */
0100                 /* Emulate comparison opcodes. */
0101                 return EmulateCPRT(opcode);
0102             } else {
0103                 /* Emulate monadic arithmetic opcodes. */
0104                 /* Emulate dyadic arithmetic opcodes. */
0105                 return EmulateCPDO(opcode);
0106             }
0107         } else if (code == 0x0c000000) {
0108             /* Emulate load/store opcodes. */
0109             /* Emulate load/store multiple opcodes. */
0110             return EmulateCPDT(opcode);
0111         }
0112     }
0113 
0114     /* Invalid instruction detected.  Return FALSE. */
0115     return 0;
0116 }