From 4eeb386cec1c73733773d5b9c0c6132e5c23c81c Mon Sep 17 00:00:00 2001 From: "fur%netscape.com" Date: Sun, 28 Feb 1999 00:18:23 +0000 Subject: [PATCH] A bunch of grunge work to reduce the amount of OS-dependent code in ElectricalFire sources. The end result eliminated nearly all of the differences between FreeBSD and Linux in the source code. It also increased the amount of sharing between Win32 and unix code. + Renamed files and classes that were inappropriately named, i.e. the names started with 'x86Win32', but the code was for generic x86, not specific to Win32. + Eliminated several gratuitous duplicated files, e.g. x86Linux.s and x86FreeBSD.s were essentially identical. + Shared code that had been duplicated in x86Win32_Support.cpp, x86Linux_Support.cpp and x86FreeBSD_Support.cpp. Created x86GenStub.cpp, which contains only XP code, to replace them all. --- ef/Compiler/CodeGenerator/md/x86/Makefile | 17 +- .../CodeGenerator/md/x86/x86Emitter.cpp | 28 +- ef/Compiler/CodeGenerator/md/x86/x86FreeBSD.s | 0 .../md/x86/x86FreeBSD_Support.cpp | 0 .../CodeGenerator/md/x86/x86FreeBSD_Support.h | 0 .../CodeGenerator/md/x86/x86Linux_Support.cpp | 0 .../CodeGenerator/md/x86/x86Linux_Support.h | 0 .../CodeGenerator/md/x86/x86Stub_gas.s | 593 ++++++++++++++++++ 8 files changed, 598 insertions(+), 40 deletions(-) delete mode 100644 ef/Compiler/CodeGenerator/md/x86/x86FreeBSD.s delete mode 100644 ef/Compiler/CodeGenerator/md/x86/x86FreeBSD_Support.cpp delete mode 100644 ef/Compiler/CodeGenerator/md/x86/x86FreeBSD_Support.h delete mode 100644 ef/Compiler/CodeGenerator/md/x86/x86Linux_Support.cpp delete mode 100644 ef/Compiler/CodeGenerator/md/x86/x86Linux_Support.h create mode 100644 ef/Compiler/CodeGenerator/md/x86/x86Stub_gas.s diff --git a/ef/Compiler/CodeGenerator/md/x86/Makefile b/ef/Compiler/CodeGenerator/md/x86/Makefile index f3dc079aed0..526b70b0e66 100644 --- a/ef/Compiler/CodeGenerator/md/x86/Makefile +++ b/ef/Compiler/CodeGenerator/md/x86/Makefile @@ -28,6 +28,7 @@ CPPSRCS = x86.nad.burg.cpp \ x86Emitter.cpp \ x86Float.cpp \ x86Formatter.cpp \ + x86GenStub.cpp \ x86Instruction.cpp \ x86StdCall.cpp \ $(OS_SUPPORT) \ @@ -36,8 +37,6 @@ CPPSRCS = x86.nad.burg.cpp \ LOCAL_MD_EXPORTS_x86 = x86ArgumentList.h \ x86Float.h \ x86Formatter.h \ - x86Linux_Support.h \ - x86FreeBSD_Support.h \ x86Opcode.h \ x86StdCall.h \ x86Cpu.h \ @@ -61,17 +60,9 @@ include $(DEPTH)/config/config.mk # Generation of OS-specific support files # ifeq ($(OS_ARCH),WINNT) -OS_SUPPORT = x86Win32_Support.cpp -endif - -ifeq ($(OS_ARCH),Linux) -ASFILES = x86Linux.s -OS_SUPPORT = x86Linux_Support.cpp -endif - -ifeq ($(OS_ARCH),FreeBSD) -ASFILES = x86FreeBSD.s -OS_SUPPORT = x86FreeBSD_Support.cpp +OS_SUPPORT = x86Stub.cpp +else +ASFILES = x86Stub_gas.s endif ####################################################################### diff --git a/ef/Compiler/CodeGenerator/md/x86/x86Emitter.cpp b/ef/Compiler/CodeGenerator/md/x86/x86Emitter.cpp index d35c0197c60..ff7149f9e90 100644 --- a/ef/Compiler/CodeGenerator/md/x86/x86Emitter.cpp +++ b/ef/Compiler/CodeGenerator/md/x86/x86Emitter.cpp @@ -694,33 +694,7 @@ emit_Logic_L(Primitive& inPrimitive, x86DoubleOpDirCode insnType) redefineTemporary(insnHi, vrHi, 0); } -#if defined(WIN32) -# include "x86Arith64.h" -#elif defined(LINUX) || defined(FREEBSD) -extern "C" { -extern void x86Mul64Bit(void); -extern void x86Div64Bit(void); -extern void x86Mod64Bit(void); -extern void x86Shl64Bit(void); -extern void x86Shr64Bit(void); -extern void x86Sar64Bit(void); -extern void x86ThreeWayCMP_L(void); -extern void x86ThreeWayCMPC_L(void) {trespass("Not implemented");} -extern void x86Extract64Bit(void); -}; -#endif - -#if !defined(WIN32) && !defined(LINUX) && !defined(FREEBSD) -static void x86Mul64Bit() {trespass("Not implemented");} -static void x86Div64Bit() {trespass("Not implemented");} -static void x86Mod64Bit() {trespass("Not implemented");} -static void x86Shl64Bit() {trespass("Not implemented");} -static void x86Shr64Bit() {trespass("Not implemented");} -static void x86Sar64Bit() {trespass("Not implemented");} -static void x86ThreeWayCMP_L() {trespass("Not implemented");} -static void x86ThreeWayCMPC_L() {trespass("Not implemented");} -static void x86Extract64Bit() {trespass("Not implemented");} -#endif +#include "x86Arith64.h" void x86Emitter:: emit_Mul_L(Primitive& inPrimitive) diff --git a/ef/Compiler/CodeGenerator/md/x86/x86FreeBSD.s b/ef/Compiler/CodeGenerator/md/x86/x86FreeBSD.s deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/ef/Compiler/CodeGenerator/md/x86/x86FreeBSD_Support.cpp b/ef/Compiler/CodeGenerator/md/x86/x86FreeBSD_Support.cpp deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/ef/Compiler/CodeGenerator/md/x86/x86FreeBSD_Support.h b/ef/Compiler/CodeGenerator/md/x86/x86FreeBSD_Support.h deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/ef/Compiler/CodeGenerator/md/x86/x86Linux_Support.cpp b/ef/Compiler/CodeGenerator/md/x86/x86Linux_Support.cpp deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/ef/Compiler/CodeGenerator/md/x86/x86Linux_Support.h b/ef/Compiler/CodeGenerator/md/x86/x86Linux_Support.h deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/ef/Compiler/CodeGenerator/md/x86/x86Stub_gas.s b/ef/Compiler/CodeGenerator/md/x86/x86Stub_gas.s new file mode 100644 index 00000000000..7d47f2aa428 --- /dev/null +++ b/ef/Compiler/CodeGenerator/md/x86/x86Stub_gas.s @@ -0,0 +1,593 @@ +/* -*- Mode: asm; tab-width:4; truncate-lines:t -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + + .file "x86Linux.S" + +#define ALIGN .align 16 +#define SYMBOL_NAME(name) name +#define SYMBOL_NAME_LABEL(name) name##: + +#define GLOBAL_ENTRY_START(name) \ + ALIGN; \ + .globl SYMBOL_NAME(name); \ + .type SYMBOL_NAME(name),@function; \ + SYMBOL_NAME_LABEL(name) + +#define GLOBAL_ENTRY_END(name) \ + SYMBOL_NAME_LABEL(.L##name); \ + .size SYMBOL_NAME(name),SYMBOL_NAME(.L##name)-SYMBOL_NAME(name) + + +GLOBAL_ENTRY_START(staticCompileStub) + + push %ebp /* Make stack frame */ + mov %esp,%ebp + + /* Even though ESI and EDI are non-volatile (callee-saved) registers, we need to + preserve them here in case an exception is thrown. The exception-handling + code expects to encounter this specially-prepared stack "guard" frame when + unwinding the stack. See x86ExceptionHandler.cpp. */ + push %edi + push %esi + push %ebx /* XXX - Why push EBX ? It's caller-saved */ + + /* Call compileAndBackPatchMethod() with 2 args */ + push 16(%esp) /* Push the second argument to compileAndBackPatchMethod (return address) */ + push %eax /* Push the first argument to compileAndBackPatchMethod (cacheEntry) */ + call compileAndBackPatchMethod + + mov %ebp,%esp /* Pop stack frame */ + pop %ebp + + jmp *%eax /* Jump to function leaving the return address at the top of the stack */ + +GLOBAL_ENTRY_END(staticCompileStub) + +/* + * 64bit Arithmetic Support Functions + * + * x86Extract64Bit + * + * Origin: Simon + * Purpose: signed right-aligned field extraction + * In: 64 bit source (on stack) + * 32 bit extraction size (on stack) + * Out: 64 bit result + * Note: Only works in range 1 <= b <= 63, b is extraction amount + */ +GLOBAL_ENTRY_START(x86Extract64Bit) + + mov 4(%esp),%eax /* load low byte of a */ + + mov 12(%esp),%ecx /*load shift amount */ + cmp $0x20,%ecx + jg greater32 + + /* extract <= than 32 bits + * shift amount = 32 - extract + */ + neg %ecx + add $0x20,%ecx /* ecx = 32 - extract */ + shl %cl,%eax + sar %cl,%eax + cdq /* sign extend into EDX:EAX */ + ret $12 + +greater32: + /* ext > 32 bits + * shift amount = 64 - extract + */ + mov 8(%esp),%edx /* load high byte of a */ + neg %ecx + add $0x40,%ecx /* ecx = 64 - extract */ + shl %cl,%edx + sar %cl,%edx + ret $12 + +GLOBAL_ENTRY_END(x86Extract64Bit) + +/* + * 3WayCompare + * + * Origin: Symantec JIT + * Purpose: compare two longs + * In: two longs on the stack + * Out: depends on condition flags: + * less = -1 + * equal = 0 + * greater = 1 + */ +GLOBAL_ENTRY_START(x86ThreeWayCMP_L) + + /* edx:eax is tos, ecx:ebx is nos */ + mov 8(%esp),%ecx + mov 16(%esp),%edx + + cmp %edx,%ecx + jl lcmp_m1 + + jg lcmp_1 + + mov 4(%esp),%ecx + mov 12(%esp),%edx + + cmp %edx,%ecx + ja lcmp_1 + + mov $0,%eax + jb lcmp_m1 + + ret $16 + + .align 4 +lcmp_m1: + mov $-1,%eax + ret $16 + + .align 4 +lcmp_1: + mov $1,%eax + ret $16 + +GLOBAL_ENTRY_END(x86ThreeWayCMP_L) + +/* + * llmul + * + * Origin: Intel Code (via MSDev) + * Purpose: long multiply (same for signed/unsigned) + * In: args are passed on the stack: + * 1st pushed: multiplier (QWORD) + * 2nd pushed: multiplicand (QWORD) + * Out: EDX:EAX - product of multiplier and multiplicand + * Note: parameters are removed from the stack + * Uses: ECX + */ +GLOBAL_ENTRY_START(x86Mul64Bit) + + /* A*B = (A.lo * B.lo) + (A.lo * B.hi) + (B.lo * A.hi) ??? */ + mov 8(%esp),%eax /* A.hi */ + mov 16(%esp),%ecx /* B.hi */ + or %eax,%ecx /* test for both hiwords zero */ + mov 12(%esp),%ecx /* B.lo */ + jnz hard + + /* easy case + * both are zero, just mult ALO and BLO + */ + mov 4(%esp),%eax /* A.lo */ + mul %ecx /* A.lo * B.lo */ + ret $16 /* callee restores the stack */ + + /* hard case */ +hard: + push %ebx + + mul %ecx /* A.hi * B.lo */ + mov %eax,%ebx /* save result */ + + mov 8(%esp),%eax /* A.lo */ + mull 14(%esp) /* A.lo * B.hi */ + add %eax,%ebx /* ebx = ((A.lo * B.hi) + (A.hi * B.lo)) */ + + mov 8(%esp),%eax /* A.lo */ + mul %ecx /* edx:eax = A.lo * B.lo */ + add %ebx,%edx /* now edx has all the LO*HI stuff */ + + pop %ebx + + ret $16 /* callee restores the stack */ + +GLOBAL_ENTRY_END(x86Mul64Bit) + +/* + * lldiv + * + * Origin: Intel Code (via MSDev) + * Purpose: signed long divide + * In: args are passed on the stack: + * 1st pushed: divisor (QWORD) + * 2nd pushed: dividend (QWORD) + * Out: EDX:EAX contains the quotient (dividend/divisor) + * Note: parameters are removed from the stack + * Uses: ECX + */ +GLOBAL_ENTRY_START(x86Div64Bit) + + push %edi + push %esi + push %ebx + + /* Determine sign of the result (%edi = 0 if result is positive, non-zero + * otherwise) and make operands positive. + */ + xor %edi,%edi /* result sign assumed positive */ + + mov 20(%esp),%eax /* hi word of a */ + or %eax,%eax /* test to see if signed */ + jge L1 /* skip rest if a is already positive */ + inc %edi /* complement result sign flag */ + mov 16(%esp),%edx /* lo word of a */ + neg %eax /* make a positive */ + neg %edx + sbb $0,%eax + mov %eax,20(%esp) /* save positive value */ + mov %edx,16(%esp) +L1: + mov 28(%esp),%eax /* hi word of b */ + or %eax,%eax /* test to see if signed */ + jge L2 /* skip rest if b is already positive */ + inc %edi /* complement the result sign flag */ + mov 24(%esp),%edx /* lo word of a */ + neg %eax /* make b positive */ + neg %edx + sbb $0,%eax + mov %eax,28(%esp) /* save positive value */ + mov %edx,24(%esp) +L2: + + /* Now do the divide. First look to see if the divisor is less than 4194304K. + * If so, then we can use a simple algorithm with word divides, otherwise + * things get a little more complex. + * NOTE - %eax currently contains the high order word of DVSR + */ + or %eax,%eax /* check to see if divisor < 4194304K */ + jnz L3 /* nope, gotta do this the hard way */ + mov 24(%esp),%ecx /* load divisor */ + mov 20(%esp),%eax /* load high word of dividend */ + xor %edx,%edx + div %ecx /* %eax <- high order bits of quotient */ + mov %eax,%ebx /* save high bits of quotient */ + mov 16(%esp),%eax /* %edx:%eax <- remainder:lo word of dividend */ + div %ecx /* %eax <- low order bits of quotient */ + mov %ebx,%edx /* %edx:%eax <- quotient */ + jmp L4 /* set sign, restore stack and return */ + + /* Here we do it the hard way. Remember, %eax contains the high word of DVSR */ +L3: + mov %eax,%ebx /* %ebx:ecx <- divisor */ + mov 24(%esp),%ecx + mov 20(%esp),%edx /* %edx:%eax <- dividend */ + mov 16(%esp),%eax +L5: + shr $1,%ebx /* shift divisor right one bit */ + rcr $1,%ecx + shr $1,%edx /* shift dividend right one bit */ + rcr $1,%eax + or %ebx,%ebx + jnz L5 /* loop until divisor < 4194304K */ + div %ecx /* now divide, ignore remainder */ + mov %eax,%esi /* save quotient */ + + /* 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. + */ + mull 28(%esp) /* QUOT * HIWORD(DVSR) */ + mov %eax,%ecx + mov 24(%esp),%eax + mul %esi /* QUOT * LOWORD(DVSR) */ + add %ecx,%edx /* %EDX:%EAX = QUOT * DVSR */ + jc L6 /* 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 20(%esp),%edx /* compare hi words of result and original */ + ja L6 /* if result > original, do subtract */ + jb L7 /* if result < original, we are ok */ + cmp 16(%esp),%eax /* hi words are equal, compare lo words */ + jbe L7 /* if less or equal we are ok, else subtract */ +L6: + dec %esi /* subtract 1 from quotient */ +L7: + xor %edx,%edx /* %edx:%eax <- quotient */ + mov %esi,%eax + + /* Just the cleanup left to do. %edx:%eax contains the quotient. Set the sign + * according to the save value, cleanup the stack, and return. + */ +L4: + dec %edi /* check to see if result is negative */ + jnz L8 /* if %EDI == 0, result should be negative */ + neg %edx /* otherwise, negate the result */ + neg %eax + sbb $0,%edx + + /* Restore the saved registers and return. */ +L8: + pop %ebx + pop %esi + pop %edi + + ret $16 + +GLOBAL_ENTRY_END(x86Div64Bit) + +/* + * llrem + * + * Origin: MSDev + * Purpose: signed long remainder + * In: args are passed on the stack: + * 1st pushed: divisor (QWORD) + * 2nd pushed: dividend (QWORD) + * Out: %EDX:%EAX contains the quotient (dividend/divisor) + * Note: parameters are removed from the stack + * Uses: %ECX + */ +GLOBAL_ENTRY_START(x86Mod64Bit) + + push %ebx + push %edi + + /* Determine sign of the result (%edi = 0 if result is positive, non-zero + * otherwise) and make operands positive. + */ + xor %edi,%edi /* result sign assumed positive */ + + mov 16(%esp),%eax /* hi word of a */ + or %eax,%eax /* test to see if signed */ + jge LL1 /* skip rest if a is already positive */ + inc %edi /* complement result sign flag bit */ + mov 12(%esp),%edx /* lo word of a */ + neg %eax /* make a positive */ + neg %edx + sbb $0,%eax + mov %eax,16(%esp) /* save positive value */ + mov %edx,12(%esp) +LL1: + mov 24(%esp),%eax /* hi word of b */ + or %eax,%eax /* test to see if signed */ + jge LL2 /* skip rest if b is already positive */ + mov 20(%esp),%edx /* lo word of b */ + neg %eax /* make b positive */ + neg %edx + sbb $0,%eax + mov %eax,24(%esp) /* save positive value */ + mov %edx,20(%esp) +LL2: + /* Now do the divide. First look to see if the divisor is less than 4194304K. + * If so, then we can use a simple algorithm with word divides, otherwise + * things get a little more complex. + * NOTE - %eax currently contains the high order word of DVSR + */ + or %eax,%eax /* check to see if divisor < 4194304K */ + jnz LL3 /* nope, gotta do this the hard way */ + mov 20(%esp),%ecx /* load divisor */ + mov 16(%esp),%eax /* load high word of dividend */ + xor %edx,%edx + div %ecx /* %edx <- remainder */ + mov 12(%esp),%eax /* %edx:%eax <- remainder:lo word of dividend */ + div %ecx /* %edx <- final remainder */ + mov %edx,%eax /* %edx:%eax <- remainder */ + xor %edx,%edx + dec %edi /* check result sign flag */ + jns LL4 /* negate result, restore stack and return */ + jmp LL8 /* result sign ok, restore stack and return */ + + /* Here we do it the hard way. Remember, %eax contains the high word of DVSR */ +LL3: + mov %eax,%ebx /* %ebx:%ecx <- divisor */ + mov 20(%esp),%ecx + mov 16(%esp),%edx /* %edx:%eax <- dividend */ + mov 12(%esp),%eax +LL5: + shr $1,%ebx /* shift divisor right one bit */ + rcr $1,%ecx + shr $1,%edx /* shift dividend right one bit */ + rcr $1,%eax + or %ebx,%ebx + jnz LL5 /* 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 %eax,%ecx /* save a copy of quotient in %ECX */ + mull 24(%esp) + xchg %eax,%ecx /* save product, get quotient in %EAX */ + mull 20(%esp) + add %ecx,%edx /* %EDX:%EAX = QUOT * DVSR */ + jc LL6 /* 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 the original divisor from the result. + */ + cmp 16(%esp),%edx /* compare hi words of result and original */ + ja LL6 /* if result > original, do subtract */ + jb LL7 /* if result < original, we are ok */ + cmp 12(%esp),%eax /* hi words are equal, compare lo words */ + jbe LL7 /* if less or equal we are ok, else subtract */ +LL6: + sub 20(%esp),%eax /* subtract divisor from result */ + sbb 24(%esp),%edx +LL7: + + /* Calculate remainder by subtracting the result from the original dividend. + * Since the result is already in a register, we will do the subtract in the + * opposite direction and negate the result if necessary. + */ + sub 12(%esp),%eax /* subtract dividend from result */ + sbb 16(%esp),%edx + + /* Now check the result sign flag to see if the result is supposed to be positive + * or negative. It is currently negated (because we subtracted in the 'wrong' + * direction), so if the sign flag is set we are done, otherwise we must negate + * the result to make it positive again. + */ + dec %edi /* check result sign flag */ + jns LL8 /* result is ok, restore stack and return */ +LL4: + neg %edx /* otherwise, negate the result */ + neg %eax + sbb $0,%edx + + /* Just the cleanup left to do. %edx:%eax contains the quotient. + * Restore the saved registers and return. + */ +LL8: + pop %edi + pop %ebx + + ret $16 + +GLOBAL_ENTRY_END(x86Mod64Bit) + +/* + * llshl + * + * Origin: MSDev. modified + * Purpose: long shift left + * In: args are passed on the stack: (FIX make fastcall) + * 1st pushed: amount (int) + * 2nd pushed: source (long) + * Out: %EDX:%EAX contains the result + * Note: parameters are removed from the stack + * Uses: %ECX, destroyed + */ +GLOBAL_ENTRY_START(x86Shl64Bit) + + /* prepare from stack */ + mov 4(%esp),%eax + mov 8(%esp),%edx + mov 12(%esp),%ecx + + cmp $64,%cl + jae RETZERO + + /* Handle shifts of between 0 and 31 bits */ + cmp $32,%cl + jae MORE32 + shld %eax,%edx + shl %cl,%eax + ret $12 + + /* Handle shifts of between 32 and 63 bits */ +MORE32: + mov %eax,%edx + xor %eax,%eax + and $31,%cl + shl %cl,%edx + ret $12 + + /* return 0 in %edx:%eax */ +RETZERO: + xor %eax,%eax + xor %edx,%edx + ret $12 + +GLOBAL_ENTRY_END(x86Shl64Bit) + + +/* + * llshr + * + * Origin: MSDev. modified + * Purpose: long shift right + * In: args are passed on the stack: (FIX make fastcall) + * 1st pushed: amount (int) + * 2nd pushed: source (long) + * Out: %EDX:%EAX contains the result + * Note: parameters are removed from the stack + * Uses: %ECX, destroyed + */ +GLOBAL_ENTRY_START(x86Shr64Bit) + + /* prepare from stack */ + mov 4(%esp),%eax + mov 8(%esp),%edx + mov 12(%esp),%ecx + + cmp $64,%cl + jae RRETZERO + + /* Handle shifts of between 0 and 31 bits */ + cmp $32,%cl + jae MMORE32 + shrd %edx,%eax + shr %cl,%edx + ret $12 + + /* Handle shifts of between 32 and 63 bits */ +MMORE32: + mov %edx,%eax + xor %edx,%edx + and $31,%cl + shr %cl,%eax + ret $12 + + /* return 0 in %edx:%eax */ +RRETZERO: + xor %eax,%eax + xor %edx,%edx + ret $12 + +GLOBAL_ENTRY_END(x86Shr64Bit) + +/* + * llsar + * + * Origin: MSDev. modified + * Purpose: long shift right signed + * In: args are passed on the stack: (FIX make fastcall) + * 1st pushed: amount (int) + * 2nd pushed: source (long) + * Out: %EDX:%EAX contains the result + * Note: parameters are removed from the stack + * Uses: %ECX, destroyed + */ +GLOBAL_ENTRY_START(x86Sar64Bit) + + /* prepare from stack */ + mov 4(%esp),%eax + mov 8(%esp),%edx + mov 12(%esp),%ecx + + /* Handle shifts of 64 bits or more (if shifting 64 bits or more, the result */ + /* depends only on the high order bit of %edx). */ + cmp $64,%cl + jae RETSIGN + + /* Handle shifts of between 0 and 31 bits */ + cmp $32,%cl + jae MMMORE32 + shrd %edx,%eax + sar %cl,%edx + ret $12 + + /* Handle shifts of between 32 and 63 bits */ +MMMORE32: + mov %edx,%eax + sar $31,%edx + and $31,%cl + sar %cl,%eax + ret $12 + + /* Return double precision 0 or -1, depending on the sign of %edx */ +RETSIGN: + sar $31,%edx + mov %edx,%eax + ret $12 + +GLOBAL_ENTRY_END(x86Sar64Bit)