linux/arch/arm/nwfpe/fpa11.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3    NetWinder Floating Point Emulator
   4    (c) Rebel.COM, 1998,1999
   5    (c) Philip Blundell, 2001
   6
   7    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
   8
   9*/
  10
  11#include "fpa11.h"
  12#include "fpopcode.h"
  13
  14#include "fpmodule.h"
  15#include "fpmodule.inl"
  16
  17#include <linux/compiler.h>
  18#include <linux/string.h>
  19
  20/* Reset the FPA11 chip.  Called to initialize and reset the emulator. */
  21static void resetFPA11(void)
  22{
  23        int i;
  24        FPA11 *fpa11 = GET_FPA11();
  25
  26        /* initialize the register type array */
  27        for (i = 0; i <= 7; i++) {
  28                fpa11->fType[i] = typeNone;
  29        }
  30
  31        /* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */
  32        fpa11->fpsr = FP_EMULATOR | BIT_AC;
  33}
  34
  35int8 SetRoundingMode(const unsigned int opcode)
  36{
  37        switch (opcode & MASK_ROUNDING_MODE) {
  38        default:
  39        case ROUND_TO_NEAREST:
  40                return float_round_nearest_even;
  41
  42        case ROUND_TO_PLUS_INFINITY:
  43                return float_round_up;
  44
  45        case ROUND_TO_MINUS_INFINITY:
  46                return float_round_down;
  47
  48        case ROUND_TO_ZERO:
  49                return float_round_to_zero;
  50        }
  51}
  52
  53int8 SetRoundingPrecision(const unsigned int opcode)
  54{
  55#ifdef CONFIG_FPE_NWFPE_XP
  56        switch (opcode & MASK_ROUNDING_PRECISION) {
  57        case ROUND_SINGLE:
  58                return 32;
  59
  60        case ROUND_DOUBLE:
  61                return 64;
  62
  63        case ROUND_EXTENDED:
  64                return 80;
  65
  66        default:
  67                return 80;
  68        }
  69#endif
  70        return 80;
  71}
  72
  73void nwfpe_init_fpa(union fp_state *fp)
  74{
  75        FPA11 *fpa11 = (FPA11 *)fp;
  76#ifdef NWFPE_DEBUG
  77        printk("NWFPE: setting up state.\n");
  78#endif
  79        memset(fpa11, 0, sizeof(FPA11));
  80        resetFPA11();
  81        fpa11->initflag = 1;
  82}
  83
  84/* Emulate the instruction in the opcode. */
  85unsigned int EmulateAll(unsigned int opcode)
  86{
  87        unsigned int code;
  88
  89#ifdef NWFPE_DEBUG
  90        printk("NWFPE: emulating opcode %08x\n", opcode);
  91#endif
  92        code = opcode & 0x00000f00;
  93        if (code == 0x00000100 || code == 0x00000200) {
  94                /* For coprocessor 1 or 2 (FPA11) */
  95                code = opcode & 0x0e000000;
  96                if (code == 0x0e000000) {
  97                        if (opcode & 0x00000010) {
  98                                /* Emulate conversion opcodes. */
  99                                /* Emulate register transfer opcodes. */
 100                                /* Emulate comparison opcodes. */
 101                                return EmulateCPRT(opcode);
 102                        } else {
 103                                /* Emulate monadic arithmetic opcodes. */
 104                                /* Emulate dyadic arithmetic opcodes. */
 105                                return EmulateCPDO(opcode);
 106                        }
 107                } else if (code == 0x0c000000) {
 108                        /* Emulate load/store opcodes. */
 109                        /* Emulate load/store multiple opcodes. */
 110                        return EmulateCPDT(opcode);
 111                }
 112        }
 113
 114        /* Invalid instruction detected.  Return FALSE. */
 115        return 0;
 116}
 117