home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
kaffe-0.5p4-src.tgz
/
tar.out
/
contrib
/
kaffe
/
config
/
i386
/
win32
/
md-soft.c
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
8KB
|
481 lines
/*
* i386/win32/md-soft.c
* Windows'95 i386 extra soft functions.
*
* Copyright (c) 1996 Systems Architecture Research Centre,
* City University, London, UK.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* Written by Tim Wilkinson <tim@sarc.city.ac.uk>, June 1996.
* Original assembly routines by Des Barry <desb@desb.demon.co.uk>.
*/
#define DBG(s)
#include "config.h"
#include "gtypes.h"
#if !defined(HAVE_NATIVE_INT64)
#define plong(s) printf("%s = 0x%08x%08x\n", #s, s.jh, s.jl);
#define pint(s) printf("%s = 0x%08x\n", #s, s);
jlong
soft_moveconst(jint s1)
{
jlong d;
d.jl = s1;
if (s1 >= 0) {
d.jh = 0;
}
else {
d.jh = -1;
}
DBG( printf("soft_moveconst\n");
plong(d); )
return (d);
}
jlong
soft_ladd(jlong s1, jlong s2)
{
DBG( printf("soft_ladd\n");
plong(s1);
plong(s2); )
asm {
mov esi, DWORD PTR s2.jl
mov edi, DWORD PTR s2.jh
add DWORD PTR s1.jl,esi
adc DWORD PTR s1.jh,edi
}
DBG( plong(s1); )
return (s1);
}
jlong
soft_lsub(jlong s1, jlong s2)
{
DBG( printf("soft_lsub\n");
plong(s1);
plong(s2); )
asm {
mov esi,DWORD PTR s2.jl
mov edi,DWORD PTR s2.jh
sub DWORD PTR s1.jl,esi
sbb DWORD PTR s1.jh,edi
}
DBG( plong(s1); )
return (s1);
}
jlong
soft_lneg(jlong s1)
{
DBG( printf("soft_lneg\n");
plong(s1); )
asm {
neg DWORD PTR s1.jl
adc DWORD PTR s1.jh,0
neg DWORD PTR s1.jh
}
DBG( plong(s1); )
return (s1);
}
jlong
soft_lmul(jlong s1, jlong s2)
{
DBG( printf("soft_lmul\n");
plong(s1);
plong(s2); )
asm {
push eax
push ecx
push ebx
push edx
mov eax,DWORD PTR s1.jh /* high word of s2 */
mov ecx,DWORD PTR s2.jh /* high word of s1 */
or ecx,eax /* test for both hiwords zero. */
mov ecx,DWORD PTR s1.jl /* low word of s1 */
jnz l4 /* both are zero, just mult low s2 and low s1 */
mov eax,DWORD PTR s2.jl /* low word of s2 */
mul ecx
jmp l5
l4:
mul ecx /* eax has high s2, ecx has low s1 */
/* so high s2 * low s1 */
mov ebx,eax /* save result */
mov eax,DWORD PTR s2.jl /* low word of s2 */
mul DWORD PTR s1.jh
/* low s2 * high s1 */
add ebx,eax
mov eax,DWORD PTR s2.jl /* low s2 - ecx already low s1 */
mul ecx
add edx,ebx
l5:
mov DWORD PTR s1.jl,eax
mov DWORD PTR s1.jh,edx
pop edx
pop ebx
pop ecx
pop eax
}
DBG( plong(s1); )
return (s1);
}
static
void
soft_ldivrem(jlong* v1, jlong* v2)
{
jlong s1 = *v1;
jlong s2 = *v2;
asm {
push eax
push ecx
push ebx
push edx
mov eax,DWORD PTR s2.jh
or eax,eax /* check to see if divisor < 4194304K */
jnz short dhard /* nope, gotta do this the hard way */
mov ecx,DWORD PTR s2.jl /* load divisor */
xor edx,edx
mov eax,DWORD PTR s1.jh /* load high word of dividend */
div ecx /* eax <- high order bits of quotient */
mov DWORD PTR s1.jh,eax /* save high bits of quotient */
mov eax,DWORD PTR s1.jl /* edx:eax <- remainder:lo word of dividend */
div ecx /* eax <- low order bits of quotient */
mov DWORD PTR s1.jl,eax /* save low bits of quotient */
mov DWORD PTR s2.jl,edx /* save low bits of remainder - high bits = 0 */
jmp short d4
/*
* Here we do it the hard way.
*/
dhard:
mov ebx,DWORD PTR s2.jh /* ebx:ecx <- divisor */
mov ecx,DWORD PTR s2.jl
mov edx,DWORD PTR s1.jh /* edx:eax <- dividend */
mov eax,DWORD PTR s1.jl
d5:
shr ebx,1 /* shift divisor right one bit */
rcr ecx,1
shr edx,1 /* shift dividend right one bit */
rcr eax,1
or ebx,ebx
jnz short d5 /* loop until divisor < 4194304K */
div ecx /* now divide, ignore remainder */
/*
* We may be off by one, so to check, we will multiply the quotient
* by the divisor and check the result against the orignal dividend
* Note that we must also check for overflow, which can occur if the
* dividend is close to 2**64 and the quotient is off by 1.
*/
mov esi,eax /* save quotient */
mul DWORD PTR s2.jh /* QUOT * s2.jh */
mov ecx,eax
mov eax,esi
mul DWORD PTR s2.jl /* QUOT * s2.jl */
add edx,ecx /* EDX:EAX = QUOT * DVSR */
jc short d6 /* carry means Quotient is off by 1 */
/*
* do long compare here between original dividend and the result of the
* multiply in edx:eax. If original is larger or equal, we are ok, otherwise
* subtract one (1) from the quotient.
*/
cmp edx,DWORD PTR s1.jh /* compare hi words of result and original */
ja short d6 /* if result > original, do subtract */
jb short d7 /* if result < original, we are ok */
cmp eax,DWORD PTR s1.jl /* hi words are equal, compare lo words */
jbe short d7 /* if less or equal we are ok, else subtract */
d6:
dec esi
sub eax,DWORD PTR s2.jl /* Substract divisor from result */
sbb edx,DWORD PTR s2.jh
d7:
sub eax,DWORD PTR s1.jl
sbb edx,DWORD PTR s1.jh
neg edx
neg eax
sbb edx,0
mov DWORD PTR s2.jl,eax /* s2 = s1 % s2 */
mov DWORD PTR s2.jh,edx
mov DWORD PTR s1.jl,esi /* s1 = s1 / s2 */
mov DWORD PTR s1.jh,0
d4:
pop edx
pop ebx
pop ecx
pop eax
}
*v1 = s1;
*v2 = s2;
}
jlong
soft_ldiv(jlong s1, jlong s2)
{
int sign = 1;
DBG( printf("soft_ldiv\n");
plong(s1);
plong(s2); )
if (s1.jh < 0) {
s1 = soft_lneg(s1);
sign = -sign;
}
if (s2.jh < 0) {
s2 = soft_lneg(s2);
sign = -sign;
}
soft_ldivrem(&s1, &s2);
if (sign == -1) {
s1 = soft_lneg(s1);
}
DBG( plong(s1); )
return (s1);
}
jlong
soft_lrem(jlong s1, jlong s2)
{
int sign = 1;
DBG( printf("soft_lrem\n");
plong(s1);
plong(s2); )
if (s1.jh < 0) {
s1 = soft_lneg(s1);
sign = -sign;
}
if (s2.jh < 0) {
s2 = soft_lneg(s2);
sign = -sign;
}
soft_ldivrem(&s1, &s2);
if (sign == -1) {
s2 = soft_lneg(s2);
}
DBG( plong(s2); )
return (s2);
}
jlong
soft_land(jlong s1, jlong s2)
{
jlong d;
d.jl = s1.jl & s2.jl;
d.jh = s1.jh & s2.jh;
return (d);
}
jlong
soft_lor(jlong s1, jlong s2)
{
jlong d;
d.jl = s1.jl | s2.jl;
d.jh = s1.jh | s2.jh;
return (d);
}
jlong
soft_lxor(jlong s1, jlong s2)
{
jlong d;
d.jl = s1.jl ^ s2.jl;
d.jh = s1.jh ^ s2.jh;
return (d);
}
jlong
soft_llshl(jlong s1, jint s2)
{
DBG( printf("soft_llshl\n");
plong(s1);
pint(s2); )
if (s2 > 0) {
asm {
push ecx
mov ecx,s2.jl
l1:
shl DWORD PTR s1.jl,1
rcl DWORD PTR s1.jh,1
loop l1
pop ecx
}
}
DBG( plong(s1); )
return (s1);
}
jlong
soft_lashr(jlong s1, jint s2)
{
DBG( printf("soft_lashr\n");
plong(s1);
pint(s2); )
if (s2 > 0) {
asm {
push ecx
mov ecx,s2.jl
l2:
sar DWORD PTR s1.jh,1
rcr DWORD PTR s1.jl,1
loop l2
pop ecx
}
}
DBG( plong(s1); )
return (s1);
}
jlong
soft_llshr(jlong s1, jint s2)
{
DBG( printf("soft_llshr\n");
plong(s1);
pint(s2); )
if (s2 > 0) {
asm {
push ecx
mov ecx,s2.jl
l3:
shr DWORD PTR s1.jh,1
rcr DWORD PTR s1.jl,1
loop l3
pop ecx
}
}
DBG( plong(s1); )
return (s1);
}
jint
soft_lcmp(jlong s1, jlong s2)
{
if (s1.jh < s2.jh) {
return (-1);
}
else if (s1.jh > s2.jh) {
return (1);
}
else if (s1.jl < s2.jl) {
return (-1);
}
else if (s1.jl > s2.jl) {
return (1);
}
else {
return (0);
}
}
jlong
soft_cvtil(jint s1)
{
return (soft_moveconst(s1));
}
jint
soft_cvtli(jlong s1)
{
return (s1.jl);
}
jfloat
soft_cvtlf(jlong s1)
{
jfloat d;
asm {
fild QWORD PTR s1
fstp DWORD PTR d
}
return (d);
}
jdouble
soft_cvtld(jlong s1)
{
jdouble d;
asm {
fild QWORD PTR s1
fstp QWORD PTR d
}
return (d);
}
jlong
soft_cvtfl(jfloat s1)
{
jlong d;
asm {
fld DWORD PTR s1
fistp QWORD PTR d
}
return (d);
}
jlong
soft_cvtdl(jdouble s1)
{
jlong d;
asm {
fld QWORD PTR s1
fistp QWORD PTR d
}
return (d);
}
#endif