mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
2.4 KiB
116 lines
2.4 KiB
// SPDX-License-Identifier: GPL-2.0-or-later |
|
/* |
|
NetWinder Floating Point Emulator |
|
(c) Rebel.COM, 1998,1999 |
|
(c) Philip Blundell, 2001 |
|
|
|
Direct questions, comments to Scott Bambrough <[email protected]> |
|
|
|
*/ |
|
|
|
#include "fpa11.h" |
|
#include "fpopcode.h" |
|
|
|
#include "fpmodule.h" |
|
#include "fpmodule.inl" |
|
|
|
#include <linux/compiler.h> |
|
#include <linux/string.h> |
|
|
|
/* Reset the FPA11 chip. Called to initialize and reset the emulator. */ |
|
static void resetFPA11(void) |
|
{ |
|
int i; |
|
FPA11 *fpa11 = GET_FPA11(); |
|
|
|
/* initialize the register type array */ |
|
for (i = 0; i <= 7; i++) { |
|
fpa11->fType[i] = typeNone; |
|
} |
|
|
|
/* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */ |
|
fpa11->fpsr = FP_EMULATOR | BIT_AC; |
|
} |
|
|
|
int8 SetRoundingMode(const unsigned int opcode) |
|
{ |
|
switch (opcode & MASK_ROUNDING_MODE) { |
|
default: |
|
case ROUND_TO_NEAREST: |
|
return float_round_nearest_even; |
|
|
|
case ROUND_TO_PLUS_INFINITY: |
|
return float_round_up; |
|
|
|
case ROUND_TO_MINUS_INFINITY: |
|
return float_round_down; |
|
|
|
case ROUND_TO_ZERO: |
|
return float_round_to_zero; |
|
} |
|
} |
|
|
|
int8 SetRoundingPrecision(const unsigned int opcode) |
|
{ |
|
#ifdef CONFIG_FPE_NWFPE_XP |
|
switch (opcode & MASK_ROUNDING_PRECISION) { |
|
case ROUND_SINGLE: |
|
return 32; |
|
|
|
case ROUND_DOUBLE: |
|
return 64; |
|
|
|
case ROUND_EXTENDED: |
|
return 80; |
|
|
|
default: |
|
return 80; |
|
} |
|
#endif |
|
return 80; |
|
} |
|
|
|
void nwfpe_init_fpa(union fp_state *fp) |
|
{ |
|
FPA11 *fpa11 = (FPA11 *)fp; |
|
#ifdef NWFPE_DEBUG |
|
printk("NWFPE: setting up state.\n"); |
|
#endif |
|
memset(fpa11, 0, sizeof(FPA11)); |
|
resetFPA11(); |
|
fpa11->initflag = 1; |
|
} |
|
|
|
/* Emulate the instruction in the opcode. */ |
|
unsigned int EmulateAll(unsigned int opcode) |
|
{ |
|
unsigned int code; |
|
|
|
#ifdef NWFPE_DEBUG |
|
printk("NWFPE: emulating opcode %08x\n", opcode); |
|
#endif |
|
code = opcode & 0x00000f00; |
|
if (code == 0x00000100 || code == 0x00000200) { |
|
/* For coprocessor 1 or 2 (FPA11) */ |
|
code = opcode & 0x0e000000; |
|
if (code == 0x0e000000) { |
|
if (opcode & 0x00000010) { |
|
/* Emulate conversion opcodes. */ |
|
/* Emulate register transfer opcodes. */ |
|
/* Emulate comparison opcodes. */ |
|
return EmulateCPRT(opcode); |
|
} else { |
|
/* Emulate monadic arithmetic opcodes. */ |
|
/* Emulate dyadic arithmetic opcodes. */ |
|
return EmulateCPDO(opcode); |
|
} |
|
} else if (code == 0x0c000000) { |
|
/* Emulate load/store opcodes. */ |
|
/* Emulate load/store multiple opcodes. */ |
|
return EmulateCPDT(opcode); |
|
} |
|
} |
|
|
|
/* Invalid instruction detected. Return FALSE. */ |
|
return 0; |
|
}
|
|
|