mirror of
https://github.com/pruten/shoebill.git
synced 2025-01-04 20:30:03 +00:00
More minor tweaks to newfpu
This commit is contained in:
parent
adc2e16ffd
commit
c9adc49a82
214
core/newfpu.c
214
core/newfpu.c
@ -279,7 +279,7 @@ static float128 _extended_to_intermediate(uint8_t *e)
|
||||
*/
|
||||
static void _set_rounding_mode(enum rounding_mode_t mode)
|
||||
{
|
||||
const int8 rounding_map[4] = {
|
||||
const int8_t rounding_map[4] = {
|
||||
float_round_nearest_even, float_round_to_zero,
|
||||
float_round_up, float_round_down
|
||||
};
|
||||
@ -411,7 +411,7 @@ got_address:
|
||||
*result = _extended_to_intermediate(buf);
|
||||
break;
|
||||
case format_Ps:
|
||||
case format_Pd:
|
||||
// case format_Pd: // not possible as a src specifier
|
||||
// FIXME: implement packed formats
|
||||
assert(!"Somebody tried to use a packed format!\n");
|
||||
// throw_illegal_instruction();
|
||||
@ -428,6 +428,79 @@ got_data:
|
||||
|
||||
#pragma mark Second-hop instructions
|
||||
|
||||
|
||||
static float128 _get_fmovecr_constant(const uint8_t offset)
|
||||
{
|
||||
float128 foo;
|
||||
|
||||
/*
|
||||
* FYI: these constants are stored in the "intermediate" 85-bit
|
||||
* format in the 6888x rom. This has the side effect that
|
||||
* they are rounded according to fpcr.mc_rnd.
|
||||
* We emulate the 85-bit format with float128.
|
||||
*/
|
||||
|
||||
switch (offset) {
|
||||
case 0x00: // pi
|
||||
break;
|
||||
case 0x0b: // log_10(2)
|
||||
break;
|
||||
case 0x0c: // e
|
||||
break;
|
||||
case 0x0d: // log_2(e)
|
||||
break;
|
||||
case 0x0e: // log_10(e)
|
||||
break;
|
||||
case 0x0f: // 0.0
|
||||
break;
|
||||
case 0x30: // ln(2)
|
||||
break;
|
||||
case 0x31: // ln(10)
|
||||
break;
|
||||
case 0x32: // 1 (68kprm has typesetting issues everywhere. This one says 100, but means 10^0.)
|
||||
break;
|
||||
case 0x33: // 10
|
||||
break;
|
||||
case 0x34: // 10^2
|
||||
break;
|
||||
case 0x35: // 10^4
|
||||
break;
|
||||
case 0x36: // 10^8
|
||||
break;
|
||||
case 0x37: // 10^16
|
||||
break;
|
||||
case 0x38: // 10^32
|
||||
break;
|
||||
case 0x39: // 10^64
|
||||
break;
|
||||
case 0x3a: // 10^128
|
||||
break;
|
||||
case 0x3b: // 10^256
|
||||
break;
|
||||
case 0x3c: // 10^512
|
||||
break;
|
||||
case 0x3d: // 10^1024
|
||||
break;
|
||||
case 0x3e: // 10^2048
|
||||
break;
|
||||
case 0x3f: // 10^4096
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* I wanted to include the actual values for the other ROM offsets,
|
||||
* but they might be proprietary. Most of them are 0 anyways, and some
|
||||
* cause FPU exceptions, even with all exceptions disabled... (?)
|
||||
* (Also, looking at the micro/nanocode on a high res 68881/2 die pic,
|
||||
* I can't figure out where these constants are stored.)
|
||||
*/
|
||||
// result = 0.0;
|
||||
break;
|
||||
}
|
||||
|
||||
return foo;
|
||||
}
|
||||
|
||||
|
||||
static void inst_fmath (const uint16_t ext)
|
||||
{
|
||||
fpu_get_state_ptr();
|
||||
@ -494,14 +567,30 @@ static void inst_fmath (const uint16_t ext)
|
||||
es_snan = 0; // Set if one of the inputs was a signaling NaN
|
||||
es_bsun = 0; // never set here
|
||||
|
||||
/*
|
||||
* All instructions with bit #6 set are illegal on
|
||||
* 6888x. No other opcodes seem to be illegal.
|
||||
*/
|
||||
if (extension & ~b(1000000)) {
|
||||
throw_illegal_instruction();
|
||||
return ;
|
||||
}
|
||||
|
||||
/* Handle fmovecr */
|
||||
if (src_in_ea && (source_specifier == 7)) { // fmovecr
|
||||
/*
|
||||
* 68kprm says M should be ~b(000000), but apparently
|
||||
* any value will work for fmovecr
|
||||
*/
|
||||
result = _get_fmovecr_constant(extension);
|
||||
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
switch (e) {
|
||||
case ~b(1000000): // fsmove
|
||||
case ~b(1000100): // fdmove
|
||||
/* These are only legal on 68040 */
|
||||
throw_illegal_instruction();
|
||||
return ;
|
||||
|
||||
if (e == ~b(1000000)) rounding_prec = prec_single;
|
||||
else if (e == ~b(1000100)) rounding_prec = prec_double;
|
||||
else assert(0);
|
||||
@ -522,9 +611,6 @@ static void inst_fmath (const uint16_t ext)
|
||||
case ~b(1000001): // fssqrt
|
||||
case ~b(1000101): // fdsqrt
|
||||
/* These are only legal on 68040 */
|
||||
throw_illegal_instruction();
|
||||
return ;
|
||||
|
||||
if (e == ~b(1000001)) rounding_prec = prec_single;
|
||||
else if (e == ~b(1000101)) rounding_prec = prec_double;
|
||||
else assert(0);
|
||||
@ -532,6 +618,8 @@ static void inst_fmath (const uint16_t ext)
|
||||
|
||||
break;
|
||||
|
||||
/* case ~b(0000101): // not documented, seems to be fsqrt again */
|
||||
|
||||
case ~b(0000110): // flognp1
|
||||
break;
|
||||
|
||||
@ -544,6 +632,8 @@ static void inst_fmath (const uint16_t ext)
|
||||
case ~b(0001010): // fatan
|
||||
break;
|
||||
|
||||
/* case ~b(0001011): // not documented, seems to be fatan again */
|
||||
|
||||
case ~b(0001100): // fasin
|
||||
break;
|
||||
|
||||
@ -565,6 +655,8 @@ static void inst_fmath (const uint16_t ext)
|
||||
case ~b(0010010): // ftentox
|
||||
break;
|
||||
|
||||
/* case ~b(0010011): // not documented, seems to be ftentox again */
|
||||
|
||||
case ~b(0010100): // flogn
|
||||
break;
|
||||
|
||||
@ -573,13 +665,12 @@ static void inst_fmath (const uint16_t ext)
|
||||
|
||||
case ~b(0010110): // flog2
|
||||
break;
|
||||
|
||||
/* case ~b(0010111): // not documented, seems to be flog2 again */
|
||||
|
||||
case ~b(1011000): // fsabs
|
||||
case ~b(1011100): // fdabs
|
||||
/* These are only legal on 68040 */
|
||||
throw_illegal_instruction();
|
||||
return ;
|
||||
|
||||
if (e == ~b(1011000)) rounding_prec = prec_single;
|
||||
else if (e == ~b(1011100)) rounding_prec = prec_double;
|
||||
else assert(0);
|
||||
@ -593,16 +684,14 @@ static void inst_fmath (const uint16_t ext)
|
||||
case ~b(1011010): // fsneg
|
||||
case ~b(1011110): // fdneg
|
||||
/* These are only legal on 68040 */
|
||||
throw_illegal_instruction();
|
||||
return ;
|
||||
|
||||
if (e == ~b(1011010)) rounding_prec = prec_single;
|
||||
else if (e == ~b(1011110)) rounding_prec = prec_double;
|
||||
else assert(0);
|
||||
case ~b(0011010): // fneg
|
||||
|
||||
break;
|
||||
|
||||
/* case ~b(0011010): // not documented, seems to be fneg again */
|
||||
|
||||
case ~b(0011100): // facos
|
||||
break;
|
||||
|
||||
@ -615,84 +704,93 @@ static void inst_fmath (const uint16_t ext)
|
||||
case ~b(0011111): // fgetman
|
||||
break;
|
||||
|
||||
case ~b(1100000): // fsdiv
|
||||
case ~b(1100100): // fddiv
|
||||
/* These are only legal on 68040 */
|
||||
if (e == ~b(1100000)) rounding_prec = prec_single;
|
||||
else if (e == ~b(1100100)) rounding_prec = prec_double;
|
||||
else assert(0);
|
||||
case ~b(0100000): // fdiv
|
||||
break;
|
||||
|
||||
case ~b(0100001): // fmod
|
||||
break;
|
||||
|
||||
/* case ~b(0100000): // not documented, seems to be fmod again */
|
||||
|
||||
case ~b(1100010): // fsadd
|
||||
case ~b(1100110): // fdadd
|
||||
/* These are only legal on 68040 */
|
||||
throw_illegal_instruction();
|
||||
return ;
|
||||
|
||||
if (e == ~b(1100010)) rounding_prec = prec_single;
|
||||
else if (e == ~b(1100110)) rounding_prec = prec_double;
|
||||
else assert(0);
|
||||
case ~b(0100010): // fadd
|
||||
break;
|
||||
|
||||
case ~b(1100011): // fsmul
|
||||
case ~b(1100111): // fdmul
|
||||
/* These are only legal on 68040 */
|
||||
if (e == ~b(1100011)) rounding_prec = prec_single;
|
||||
else if (e == ~b(1100111)) rounding_prec = prec_double;
|
||||
else assert(0);
|
||||
case ~b(0100011): // fmul
|
||||
break;
|
||||
|
||||
case ~b(0100100): // fsgldiv
|
||||
break;
|
||||
|
||||
case ~b(0100111): // fsglmul
|
||||
break;
|
||||
|
||||
case ~b(0100101): // frem
|
||||
break;
|
||||
|
||||
case ~b(0100110): // fscale
|
||||
break;
|
||||
|
||||
case ~b(0111000): // fcmp
|
||||
break;
|
||||
|
||||
case ~b(0111010): // ftst
|
||||
break;
|
||||
|
||||
case ~b(1100000): // fsdiv
|
||||
case ~b(1100100): // fddiv
|
||||
/* These are only legal on 68040 */
|
||||
throw_illegal_instruction();
|
||||
return ;
|
||||
|
||||
if (e == ~b(1100000)) rounding_prec = prec_single;
|
||||
else if (e == ~b(1100100)) rounding_prec = prec_double;
|
||||
else assert(0);
|
||||
case ~b(0100000): // fdiv
|
||||
|
||||
break;
|
||||
|
||||
case ~b(1100011): // fsmul
|
||||
case ~b(1100111): // fdmul
|
||||
/* These are only legal on 68040 */
|
||||
throw_illegal_instruction();
|
||||
return ;
|
||||
|
||||
if (e == ~b(1100011)) rounding_prec = prec_single;
|
||||
else if (e == ~b(1100111)) rounding_prec = prec_double;
|
||||
else assert(0);
|
||||
case ~b(0100011): // fmul
|
||||
|
||||
case ~b(0100111): // fsglmul
|
||||
break;
|
||||
|
||||
case ~b(1101000): // fssub
|
||||
case ~b(1101100): // fdsub
|
||||
/* These are only legal on 68040 */
|
||||
throw_illegal_instruction();
|
||||
return ;
|
||||
|
||||
if (e == ~b(1101000)) rounding_prec = prec_single;
|
||||
else if (e == ~b(1101100)) rounding_prec = prec_double;
|
||||
else assert(0);
|
||||
case ~b(0101000): // fsub
|
||||
|
||||
break;
|
||||
|
||||
/* case ~b(0101000) through ~b(0101111): // not documented, seems to be fsub again */
|
||||
|
||||
case ~b(0110000):
|
||||
case ~b(0110001):
|
||||
case ~b(0110010):
|
||||
case ~b(0110011):
|
||||
case ~b(0110100):
|
||||
case ~b(0110101):
|
||||
case ~b(0110110):
|
||||
case ~b(0110111): // fsincos
|
||||
break;
|
||||
|
||||
case ~b(0111000): // fcmp
|
||||
break;
|
||||
|
||||
case ~b(0111010): // ftst
|
||||
break;
|
||||
|
||||
/*
|
||||
* All the rest of these 0xxxxxx opcodes seem to be either fcmp or ftst.
|
||||
* That's why the new 68040 opcodes have to use that high bit (1xxxxxx),
|
||||
* none of the other ones throw illegal-instruction on 6888x.
|
||||
*/
|
||||
default:
|
||||
/* Nonetheless, I'm just going to throw an f-trap. */
|
||||
throw_illegal_instruction();
|
||||
return;
|
||||
}
|
||||
|
||||
finalize:
|
||||
|
||||
/*
|
||||
* Now update all the exception flags,
|
||||
* and determine whether we want to
|
||||
* actually throw an exception.
|
||||
* Now update all the exception flags, and determine
|
||||
* whether we want to actually throw an exception.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user