Linux Audio

Check our new training course

Loading...
v6.13.7
  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}
v5.14.15
  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}