зеркало из https://github.com/mozilla/pjs.git
Check-in rth's support for 64-bit arithmetic, with a few mods to make it build
on Win32.
This commit is contained in:
Родитель
b5297e5cdd
Коммит
e898c10772
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -32,37 +32,64 @@ void* JNIenv = 0;
|
|||
|
||||
extern ClassWorld world;
|
||||
|
||||
#define Naked __declspec( naked )
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
/*
|
||||
+-------------------------------+
|
||||
| return address |
|
||||
========+===============================+========
|
||||
| EBP link |
|
||||
+-------------------------------+
|
||||
| Saved Non-volatiles |
|
||||
| eg. EDI |
|
||||
| ESI |
|
||||
| EBX |
|
||||
+-------------------------------+
|
||||
Following code written by rth@cygnus.org. Comment from fur@netscape.com.
|
||||
|
||||
I suspect that your code will work OK if there are no exceptions while a method is being
|
||||
compiled, but you'll probably crash if the compilation terminates with an exception. That's
|
||||
because the Java exception code relies on the presence of a "guard frame" when calling from
|
||||
JIT'ed to native code so as to restore the callee-saved registers when unwinding the stack.
|
||||
See x86ExceptionHandler.cpp for some details. This code is "temporary". What we
|
||||
eventually hoped to do was to use a different calling convention (in terms of which registers
|
||||
are volatile) for calls that make an exceptional return versus a normal return, so that the stack
|
||||
unwinding code did not have to restore any registers. Until we can educate the register
|
||||
allocator about these constraints, we'll need to retain this hacky guard frame and the various
|
||||
bits of code that are used to create it. (See also x86Win32InvokeNative.cpp).
|
||||
|
||||
Some of the exception debugging code makes assumptions about the location of the call
|
||||
instruction inside the static compile stub - assumptions that are broken by the new code. (And
|
||||
the exception debugging code should probably be changed to get rid of that dependency.)
|
||||
*/
|
||||
|
||||
// Fucntion: staticCompileStub
|
||||
//
|
||||
// WARNING: if you change this method, you must change compileStubReEntryPoint below.
|
||||
// It must point to the instruction after the invokation of compileAndBackPatchMethod
|
||||
static Naked void staticCompileStub()
|
||||
/* Go through one level of extra indirection to isolate ourselves from name
|
||||
mangling and cdecl vs stdcall changes. */
|
||||
|
||||
static void* compileStub_1(const CacheEntry&, void *) __attribute__((regparm(2), unused));
|
||||
static void* compileStub_1(const CacheEntry&, void *) __asm__("compileStub_1");
|
||||
|
||||
static void*
|
||||
compileStub_1(const CacheEntry& inCacheEntry, void *retAddr)
|
||||
{
|
||||
return compileAndBackPatchMethod(inCacheEntry, retAddr);
|
||||
}
|
||||
|
||||
extern void compileStub() __asm__("compileStub");
|
||||
|
||||
asm("\n\
|
||||
compileStub:\n\
|
||||
movl 0(%esp), %edx\n\
|
||||
call compileStub_1\n\
|
||||
jmpl *%eax");
|
||||
|
||||
#else /* !__GNUC__ */
|
||||
|
||||
static void __declspec( naked )
|
||||
compileStub()
|
||||
{
|
||||
_asm
|
||||
{
|
||||
// remove cache entry from the stack
|
||||
pop eax
|
||||
// eax contains the cache entry.
|
||||
|
||||
// make frame
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
|
||||
// save all volatiles (especially for exception handler)
|
||||
// ??? Um, these are _non_ volatile, ie callee saved.
|
||||
// We shouldn't have to do anything with them.
|
||||
push edi
|
||||
push esi
|
||||
push ebx
|
||||
|
@ -86,10 +113,10 @@ static Naked void staticCompileStub()
|
|||
pop ebp
|
||||
|
||||
// jump to the compiled method
|
||||
push eax // ret will jump to this address
|
||||
ret // Jump to function leaving the return address at the top of the stack
|
||||
jmp eax
|
||||
}
|
||||
}
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#ifdef DEBUG
|
||||
// Pointer to the instruction after the call (used by exception handler to check
|
||||
|
@ -97,18 +124,11 @@ static Naked void staticCompileStub()
|
|||
// void* compileStubReEntryPoint = (void*) ((Uint8*)staticCompileStub + 17);
|
||||
// but MSDev appears to have a bug, in that compileStubReEntryPoint will be set == (void*)staticCompileStub
|
||||
// which is clearly wrong.
|
||||
void* compileStubAddress = (void*)staticCompileStub;
|
||||
void* compileStubReEntryPoint = (Uint8*)compileStubAddress + 17;
|
||||
void* compileStubAddress = (void*)compileStub;
|
||||
// void* compileStubReEntryPoint = (Uint8*)compileStubAddress + 15; // Correct address ?
|
||||
void* compileStubReEntryPoint = NULL;
|
||||
#endif // DEBUG
|
||||
|
||||
static Naked void compileStub()
|
||||
{
|
||||
_asm {
|
||||
push 0xEFBEADDE // This is a dummy immediate that will be filled in by
|
||||
jmp staticCompileStub // generateCompileStub with the cacheEntry.
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
generateNativeStub(NativeCodeCache& inCache, const CacheEntry& inCacheEntry, void *nativeFunction)
|
||||
{
|
||||
|
@ -140,31 +160,24 @@ void*
|
|||
generateCompileStub(NativeCodeCache& inCache, const CacheEntry& inCacheEntry)
|
||||
{
|
||||
void* stub;
|
||||
uint8 stubSize;
|
||||
uint8 argumentOffset;
|
||||
uint32 locationOfCompileStub;
|
||||
|
||||
stubSize = 10;
|
||||
uint8 *where;
|
||||
|
||||
// Write out the dynamic compile stub
|
||||
stub = inCache.acquireMemory(stubSize);
|
||||
argumentOffset = 1;
|
||||
locationOfCompileStub = (uint32)compileStub ;
|
||||
|
||||
// Copy the stub into the allocated memory
|
||||
memcpy(stub, (void*)locationOfCompileStub, stubSize);
|
||||
stub = inCache.acquireMemory(10);
|
||||
where = (uint8 *)stub;
|
||||
|
||||
// Write your cacheEntry into the proper spot in the stub
|
||||
uint8* loadCacheEntryInstruction = (uint8*)stub + argumentOffset;
|
||||
writeLittleWordUnaligned((void*)loadCacheEntryInstruction, (uint32)(&inCacheEntry));
|
||||
// movl $inCacheEntry, %eax
|
||||
*where++ = 0xb8;
|
||||
writeLittleWordUnaligned(where, (uint32)&inCacheEntry);
|
||||
where += 4;
|
||||
|
||||
// Fix the new dynamic stub to jump to the static stub
|
||||
uint32* relativeCallLocation = (uint32*)(loadCacheEntryInstruction + 5);
|
||||
uint32 newRelativeDisplacement = locationOfCompileStub - (uint32)stub + *(uint32*)relativeCallLocation;
|
||||
writeLittleWordUnaligned((void*)relativeCallLocation, newRelativeDisplacement);
|
||||
// jmp compileStub
|
||||
*where++ = 0xe9;
|
||||
writeLittleWordUnaligned(where, (Uint8 *) compileStub - (where + 4));
|
||||
|
||||
// Return the address of the dynamic stub.
|
||||
return ((void*)stub);
|
||||
return stub;
|
||||
}
|
||||
|
||||
void*
|
||||
|
@ -199,34 +212,19 @@ backPatchMethod(void* inMethodAddress, void* inLastPC, void* /*inUserDefined*/)
|
|||
// 32 bit extraction size (on stack)
|
||||
// Out: 64 bit result
|
||||
// Note: Only works in range 1 <= b <= 63, b is extraction amount
|
||||
Naked void x86Extract64Bit()
|
||||
|
||||
int64 __stdcall
|
||||
x86Extract64Bit(int64 src, int b)
|
||||
{
|
||||
__asm
|
||||
if (b <= 32)
|
||||
{
|
||||
mov eax, [esp+4] // load low byte of a
|
||||
|
||||
mov ecx, [esp+12] // load shift amount
|
||||
cmp ecx, 0x20
|
||||
jg greater32
|
||||
|
||||
// extract <= than 32 bits
|
||||
// shift amount = 32 - extract
|
||||
neg ecx
|
||||
add ecx, 0x20 // ecx = 32 - extract
|
||||
shl eax, cl
|
||||
sar eax, cl
|
||||
cdq // sign extend into EDX:EAX
|
||||
ret 12
|
||||
|
||||
greater32:
|
||||
// ext > 32 bits
|
||||
// shift amount = 64 - extract
|
||||
mov edx, [esp+8] // load high byte of a
|
||||
neg ecx
|
||||
add ecx, 0x40 // ecx = 64 - extract
|
||||
shl edx, cl
|
||||
sar edx, cl
|
||||
ret 12
|
||||
b = 32 - b;
|
||||
return (int)src << b >> b;
|
||||
}
|
||||
else
|
||||
{
|
||||
b = 64 - b;
|
||||
return (int)(src >> 32) << b >> b;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,42 +236,11 @@ greater32:
|
|||
// less = -1
|
||||
// equal = 0
|
||||
// greater = 1
|
||||
Naked void x86ThreeWayCMP_L()
|
||||
|
||||
int64 __stdcall
|
||||
x86ThreeWayCMP_L(int64 a, int64 b)
|
||||
{
|
||||
// edx:eax is tos, ecx:ebx is nos
|
||||
__asm
|
||||
{
|
||||
mov ecx,[esp+8]
|
||||
mov edx,[esp+16]
|
||||
|
||||
cmp ecx,edx
|
||||
jl lcmp_m1
|
||||
|
||||
jg lcmp_1
|
||||
|
||||
mov ecx,[esp+4]
|
||||
mov edx,[esp+12]
|
||||
|
||||
cmp ecx,edx
|
||||
ja lcmp_1
|
||||
|
||||
mov eax,0
|
||||
jb lcmp_m1
|
||||
|
||||
ret 16
|
||||
|
||||
align 4
|
||||
lcmp_m1:
|
||||
mov eax,-1
|
||||
|
||||
ret 16
|
||||
|
||||
align 4
|
||||
lcmp_1:
|
||||
mov eax,1
|
||||
|
||||
ret 16
|
||||
}
|
||||
return (a > b) - (a < b);
|
||||
}
|
||||
|
||||
// 3WayCompare
|
||||
|
@ -284,42 +251,11 @@ Naked void x86ThreeWayCMP_L()
|
|||
// less = 1
|
||||
// equal = 0
|
||||
// greater = -1
|
||||
Naked void x86ThreeWayCMPC_L()
|
||||
|
||||
int64 __stdcall
|
||||
x86ThreeWayCMPC_L(int64 a, int64 b)
|
||||
{
|
||||
// edx:eax is tos, ecx:ebx is nos
|
||||
__asm
|
||||
{
|
||||
mov ecx,[esp+8]
|
||||
mov edx,[esp+16]
|
||||
|
||||
cmp ecx,edx
|
||||
jl lcmp_m1
|
||||
|
||||
jg lcmp_1
|
||||
|
||||
mov ecx,[esp+4]
|
||||
mov edx,[esp+12]
|
||||
|
||||
cmp ecx,edx
|
||||
ja lcmp_1
|
||||
|
||||
mov eax,0
|
||||
jb lcmp_m1
|
||||
|
||||
ret 16
|
||||
|
||||
align 4
|
||||
lcmp_m1:
|
||||
mov eax,1
|
||||
|
||||
ret 16
|
||||
|
||||
align 4
|
||||
lcmp_1:
|
||||
mov eax,-1
|
||||
|
||||
ret 16
|
||||
}
|
||||
return (a < b) - (a > b);
|
||||
}
|
||||
|
||||
// llmul
|
||||
|
@ -331,13 +267,11 @@ Naked void x86ThreeWayCMPC_L()
|
|||
// Out: EDX:EAX - product of multiplier and multiplicand
|
||||
// Note: parameters are removed from the stack
|
||||
// Uses: ECX
|
||||
Naked void x86Mul64Bit()
|
||||
|
||||
int64 __stdcall
|
||||
x86Mul64Bit(int64 a, int64 b)
|
||||
{
|
||||
// IMPLEMENT: Needs to be written
|
||||
_asm
|
||||
{
|
||||
int 3
|
||||
}
|
||||
return a * b;
|
||||
}
|
||||
|
||||
// lldiv
|
||||
|
@ -349,13 +283,11 @@ Naked void x86Mul64Bit()
|
|||
// Out: EDX:EAX contains the quotient (dividend/divisor)
|
||||
// Note: parameters are removed from the stack
|
||||
// Uses: ECX
|
||||
Naked void x86Div64Bit()
|
||||
|
||||
int64 __stdcall
|
||||
x86Div64Bit(int64 dividend, int64 divisor)
|
||||
{
|
||||
// IMPLEMENT: Needs to be written
|
||||
_asm
|
||||
{
|
||||
int 3
|
||||
}
|
||||
return dividend / divisor;
|
||||
}
|
||||
|
||||
// llrem
|
||||
|
@ -364,16 +296,14 @@ Naked void x86Div64Bit()
|
|||
// In: args are passed on the stack:
|
||||
// 1st pushed: divisor (QWORD)
|
||||
// 2nd pushed: dividend (QWORD)
|
||||
// Out: EDX:EAX contains the quotient (dividend/divisor)
|
||||
// Out: EDX:EAX contains the remainder (dividend/divisor)
|
||||
// Note: parameters are removed from the stack
|
||||
// Uses: ECX
|
||||
Naked void x86Mod64Bit()
|
||||
|
||||
int64 __stdcall
|
||||
x86Mod64Bit(int64 dividend, int64 divisor)
|
||||
{
|
||||
// IMPLEMENT: Needs to be written
|
||||
_asm
|
||||
{
|
||||
int 3
|
||||
}
|
||||
return dividend % divisor;
|
||||
}
|
||||
|
||||
// llshl
|
||||
|
@ -385,18 +315,15 @@ Naked void x86Mod64Bit()
|
|||
// Out: EDX:EAX contains the result
|
||||
// Note: parameters are removed from the stack
|
||||
// Uses: ECX, destroyed
|
||||
Naked void x86Shl64Bit()
|
||||
|
||||
int64 __stdcall
|
||||
x86Shl64Bit(int64 src, int amount)
|
||||
{
|
||||
// IMPLEMENT: Needs to be written
|
||||
_asm
|
||||
{
|
||||
int 3
|
||||
}
|
||||
return src << amount;
|
||||
}
|
||||
|
||||
// llshr
|
||||
//
|
||||
// Origin: MSDev. modified
|
||||
// Purpose: long shift right
|
||||
// In: args are passed on the stack: (FIX make fastcall)
|
||||
// 1st pushed: amount (int)
|
||||
|
@ -404,18 +331,15 @@ Naked void x86Shl64Bit()
|
|||
// Out: EDX:EAX contains the result
|
||||
// Note: parameters are removed from the stack
|
||||
// Uses: ECX, destroyed
|
||||
Naked void x86Shr64Bit()
|
||||
|
||||
uint64 __stdcall
|
||||
x86Shr64Bit(uint64 src, int amount)
|
||||
{
|
||||
// IMPLEMENT: Needs to be written
|
||||
_asm
|
||||
{
|
||||
int 3
|
||||
}
|
||||
return src >> amount;
|
||||
}
|
||||
|
||||
// llsar
|
||||
//
|
||||
// Origin: MSDev. modified
|
||||
// Purpose: long shift right signed
|
||||
// In: args are passed on the stack: (FIX make fastcall)
|
||||
// 1st pushed: amount (int)
|
||||
|
@ -423,13 +347,11 @@ Naked void x86Shr64Bit()
|
|||
// Out: EDX:EAX contains the result
|
||||
// Note: parameters are removed from the stack
|
||||
// Uses: ECX, destroyed
|
||||
Naked void x86Sar64Bit()
|
||||
|
||||
int64 __stdcall
|
||||
x86Sar64Bit(int64 src, int amount)
|
||||
{
|
||||
// IMPLEMENT: Needs to be written
|
||||
_asm
|
||||
{
|
||||
int 3
|
||||
}
|
||||
return src >> amount;
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
|
|
Загрузка…
Ссылка в новой задаче