mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Renamed to x86Stub_gas.s
This commit is contained in:
parent
c833c56242
commit
224fa283d3
@ -1,593 +0,0 @@
|
||||
/* -*- 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)
|
Loading…
Reference in New Issue
Block a user