diff options
author | 2008-01-21 21:41:33 +0000 | |
---|---|---|
committer | 2008-01-21 21:41:33 +0000 | |
commit | b0e569464a7acbbe52c3ae503fc33436bfc1a1a2 (patch) | |
tree | d502521566f81987f3515e081fb0aff08f82b91b /src | |
parent | 3924c0bc9c6fac49e844f9652ce15e397af858b3 (diff) |
fixed VRCP instruction to match the real hardware results
Diffstat (limited to 'src')
-rw-r--r-- | src/emu/cpu/rsp/rsp.c | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/src/emu/cpu/rsp/rsp.c b/src/emu/cpu/rsp/rsp.c index 7fa25bd272b..394a09a4f09 100644 --- a/src/emu/cpu/rsp/rsp.c +++ b/src/emu/cpu/rsp/rsp.c @@ -2301,32 +2301,59 @@ static void handle_vector_ops(UINT32 op) } else { - int negative = 0; + int sign = 0; + int exp = 0; + int mantissa = 0; + if (rec < 0) { - rec = ~rec+1; - negative = 1; + rec = -rec; // rec = MINUS rec + sign = 1; } - for (i = 15; i > 0; i--) + + // restrict to 10-bit mantissa + for (i = 15; i >= 0; i--) { if (rec & (1 << i)) { - rec &= ((0xffc0) >> (15 - i)); - i = 0; + exp = i; + mantissa = (rec << (15 - i)) >> 6; + break; } } - rec = (INT32)(0x7fffffff / (double)rec); - for (i = 31; i > 0; i--) + + if (mantissa == 0x200) { - if (rec & (1 << i)) - { - rec &= ((0xffff8000) >> (31 - i)); - i = 0; - } + rec = 0x7fffffff; } - if (negative) + else { - rec = ~rec; + rec = 0xffffffffU / mantissa; + + // + // simulate rounding error + // + // This has been verified on the real hardware. + // + // I was able to replicate this exact behaviour by using a five-round + // Newton reciprocal method using floorf() on intermediate results + // to force the use of IEEE 754 32bit floats. + // However, for the sake of portability, we'll use integer arithmetic. + // + if (rec & 0x800) + rec += 1; + + rec <<= 8; + } + + // restrict result to 17 significant bits + rec &= 0x7fffc000; + + rec >>= exp; + + if (sign) + { + rec = ~rec; // rec = BITWISE NOT rec } } |