Bochs/bochs/fpu/wm_shrx.c

153 lines
4.6 KiB
C
Raw Normal View History

/*---------------------------------------------------------------------------+
| wm_shrx.c |
2001-10-06 07:53:46 +04:00
| $Id: wm_shrx.c,v 1.2 2001-10-06 03:53:46 bdenney Exp $
| |
| 64 bit right shift functions |
| |
| Copyright (C) 1992,1995,1999 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@melbpc.org.au |
| |
| |
+---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------+
| unsigned FPU_shrx(void *arg1, unsigned arg2) |
| |
| Extended shift right function. |
| Fastest for small shifts. |
| Shifts the 64 bit quantity pointed to by the first arg (arg1) |
| right by the number of bits specified by the second arg (arg2). |
| Forms a 96 bit quantity from the 64 bit arg and eax: |
| [ 64 bit arg ][ eax ] |
| shift right ---------> |
| The eax register is initialized to 0 before the shifting. |
| Results returned in the 64 bit arg and eax. |
+---------------------------------------------------------------------------*/
#include "fpu_emu.h"
unsigned FPU_shrx(void *arg1, u32 arg2)
{
u32 x;
if ( arg2 >= 64 )
{
if ( arg2 >= 96 )
{
*(u64 *)arg1 = 0;
return 0;
}
arg2 -= 64;
x = (*(u64 *)arg1) >> 32;
*(u64 *)arg1 = 0;
if ( arg2 )
return x >> arg2;
else
return x;
}
if ( arg2 < 32 )
{
if ( arg2 == 0 )
return 0;
x = (*(u64 *)arg1) << (32 - arg2);
}
else if ( arg2 > 32 )
{
x = (*(u64 *)arg1) >> (arg2 - 32);
}
else
{
/* arg2 == 32 */
x = *(u64 *)arg1;
}
(*(u64 *)arg1) >>= arg2;
return x;
}
/*---------------------------------------------------------------------------+
| unsigned FPU_shrxs(void *arg1, unsigned arg2) |
| |
| Extended shift right function (optimized for small floating point |
| integers). |
| Shifts the 64 bit quantity pointed to by the first arg (arg1) |
| right by the number of bits specified by the second arg (arg2). |
| Forms a 96 bit quantity from the 64 bit arg and eax: |
| [ 64 bit arg ][ eax ] |
| shift right ---------> |
| The eax register is initialized to 0 before the shifting. |
| The lower 8 bits of eax are lost and replaced by a flag which is |
| set (to 0x01) if any bit, apart from the first one, is set in the |
| part which has been shifted out of the arg. |
| Results returned in the 64 bit arg and eax. |
+---------------------------------------------------------------------------*/
unsigned FPU_shrxs(void *arg1, u32 arg2)
{
u32 x, bits;
u64 lost;
if ( arg2 >= 64 )
{
if ( arg2 >= 96 )
{
bits = *(u64 *)arg1 != 0;
*(u64 *)arg1 = 0;
return bits ? 1 : 0;
}
arg2 -= 64;
lost = (*(u64 *)arg1) << (32 - arg2);
x = (*(u64 *)arg1) >> 32;
*(u64 *)arg1 = 0;
if ( arg2 )
x >>= arg2;
if ( lost )
x |= 1;
return x;
}
if ( arg2 < 32 )
{
if ( arg2 == 0 )
/* No bits are lost */
return 0;
/* No bits are lost */
x = (*(u64 *)arg1) << (32 - arg2);
}
else if ( arg2 > 32 )
{
bits = (*(u64 *)arg1);
bits <<= (64 - arg2);
x = (*(u64 *)arg1) >> (arg2 - 32);
if ( bits )
x |= 1;
}
else
{
/* arg2 == 32 */
/* No bits are lost */
x = *(u64 *)arg1;
}
(*(u64 *)arg1) >>= arg2;
if ( x & 0x7fffffff )
x |= 1;
return x;
}