1764 lines
40 KiB
NASM
Executable File
1764 lines
40 KiB
NASM
Executable File
; AMXEXECN.ASM Abstract Machine for the "Pawn" language
|
|
;
|
|
|
|
;Some notes:
|
|
; * This file was adapted from AMXEXEC.ASM (for MASM/TASM/WASM). This
|
|
; version is for NASM (Netwide Assembler). NASM uses Intel syntax for
|
|
; the mnemonics, but it is not compatible with MASM.
|
|
; * The "calling convention" is __cdecl for the amx_exec_asm() itself and
|
|
; __cdecl or __stdcall for the native routines (the default is __cdecl,
|
|
; define the macro STDECL to set __stdcall).
|
|
; * The borland compiler uses different segment definitions as Microsoft
|
|
; Visual C/C++ and GNU GCC. To assemble the abstract machine with "Borland"
|
|
; segments, add the definition "BORLAND" on the command line.
|
|
; * You will need to compile the standard AMX.C file with the macro ASM32
|
|
; defined. On the command line, use:
|
|
; nasmw -f obj -d BORLAND amxexecn.asm
|
|
; bcc32 -DASM32 srun.c amx.c amxcore.c amxcons.c amxexecn.obj
|
|
; or
|
|
; nasmw -f win32 amxexecn.asm
|
|
; or
|
|
; nasm -f elf amxexecn.asm
|
|
; gcc -o srun -DLINUX -DASM32 -I../linux srun.c amx.c amxcore.c amxcons.c amxexecn.o
|
|
; * See the notes in AMXEXEC.ASM for more information and a change log).
|
|
;
|
|
;
|
|
;Copyright and license of use, please read
|
|
;-----------------------------------------
|
|
;The assembler implementation of the abstract machine for the Pawn language,
|
|
;specifically the file AMXEXEC.ASM, is copyright (c) 1998-2000 by Marc Peter.
|
|
;
|
|
;Permission is hereby granted, without written agreement and without paid
|
|
;license or royalty fees, to use, copy, modify, and distribute this software
|
|
;and its documentation for any purpose, subject to the following conditions:
|
|
;
|
|
;1. The above copyright notice and this permission notice shall appear in all
|
|
; copies or substantial portions of this software.
|
|
;
|
|
;2. Modifications of this software that do not originate from me (Marc Peter)
|
|
; must be explicitly mentioned in a README file or another appropriate
|
|
; place.
|
|
;
|
|
;The use of this software as a subsystem of a larger software product is
|
|
;explicitly allowed, regardless of whether that larger product is proprietary,
|
|
;gratis or commercially available.
|
|
;
|
|
;I (Marc Peter) specifically disclaim any warranties, including, but not
|
|
;limited to, the implied warranties of merchantability and fitness for a
|
|
;particular purpose. The software is provided on an "as is" basis,
|
|
;and I have no obligation to provide maintenance, support, updates,
|
|
;enhancements or modifications.
|
|
;
|
|
;I cannot be held liable for any damage or loss of profits that results
|
|
;from the use of the software (or part thereof), or from the inability to
|
|
;use it.
|
|
;
|
|
;
|
|
;History (list of changes)
|
|
;-------------------------
|
|
; 10 february 2006 by David Anderson
|
|
; Addition of float opcodes
|
|
; 17 february 2005 by Thiadmer Riemersms
|
|
; Addition of the BREAK opcode, removal of the older debugging opcode table.
|
|
; 6 march 2004 by Thiadmer Riemersma
|
|
; Corrected a bug in OP_FILL, where a cell preceding the array would
|
|
; be overwritten (zero'ed out). This bug was brought to my attention
|
|
; by Robert Daniels.
|
|
; 2 february 2004 by Thiadmer Riemersma (TR)
|
|
; Added checking of the return address in the RET and RETN opcodes.
|
|
; Changed handling of LINE opcode, so that the debugger can force a
|
|
; sleep.
|
|
; 22 december 2003 by Thiadmer Riemersma (TR)
|
|
; Added support for the SYMTAG and SYSCALL.D opcodes
|
|
; 3 october 2003 by Thiadmer Riemersma (TR)
|
|
; Added "non-debug" versions of various opcodes, to avoid repetitive
|
|
; checking of the "debug" flag.
|
|
; 15 September 2003 by Thiadmer Riemersma (TR)
|
|
; Minor corrections, mostly to support older versions of NASM
|
|
; 26 January 2003 by Thiadmer Riemersma (TR)
|
|
; Port to NASM
|
|
;-----
|
|
|
|
;CPU 386 -- some older versions of NASM do not support this keyword
|
|
|
|
; Macro to begin a code segment
|
|
%macro Start_CODE 0
|
|
%ifdef BORLAND
|
|
segment _TEXT public align=1 class=CODE use32
|
|
%else
|
|
segment .text
|
|
%endif
|
|
%endmacro
|
|
|
|
; Macro to begin a data segment
|
|
%macro Start_DATA 0
|
|
%ifdef BORLAND
|
|
segment _DATA public align=4 class=DATA use32
|
|
%else
|
|
segment .data
|
|
%endif
|
|
%endmacro
|
|
|
|
%include "amxdefn.asm"
|
|
|
|
;#define PUSH(v) ( stk-=sizeof(cell), *(cell *)(data+(int)stk)=v )
|
|
%macro _PUSH 1
|
|
mov [edi+ecx-4],%1
|
|
sub ecx,4
|
|
%endmacro
|
|
|
|
|
|
;#define POP(v) ( v=*(cell *)(data+(int)stk), stk+=sizeof(cell) )
|
|
%macro _POP 1
|
|
mov %1,[edi+ecx]
|
|
add ecx,4
|
|
%endmacro
|
|
|
|
%macro GO_ON 0
|
|
jmp DWORD [esi]
|
|
; ALIGN 4
|
|
%endmacro
|
|
|
|
|
|
%macro _CHKSTACK 0
|
|
cmp ecx,stp
|
|
jg near err_stacklow
|
|
%endmacro
|
|
|
|
%macro _CHKMARGIN 0
|
|
lea ebp,[ecx-16*4] ;savety margin = 16 cells
|
|
cmp hea,ebp
|
|
jg near err_stack
|
|
%endmacro
|
|
|
|
;Normal abort, saves pri/alt
|
|
%macro _ABORT 1
|
|
mov ebp,amx
|
|
mov [ebp+_pri], dword eax ; store values in AMX structure (PRI, ALT)
|
|
mov [ebp+_alt], dword edx ; store values in AMX structure (PRI, ALT)
|
|
mov [ebp+_error], dword %1
|
|
jmp _return
|
|
%endmacro
|
|
|
|
;Checked abort, saves nothing and uses a conditional
|
|
%macro _CHKABORT 1
|
|
mov ebp,amx
|
|
mov [ebp+_error], %1
|
|
cmp %1, AMX_ERR_NONE
|
|
jne _return
|
|
%endmacro
|
|
|
|
;Fast abort, only aborts, nothing else
|
|
%macro _FASTABORT 0
|
|
jmp _return
|
|
%endmacro
|
|
|
|
%macro _CHKHEAP 0
|
|
mov ebp,amx
|
|
mov ebp,[ebp+_hlw]
|
|
cmp DWORD hea,ebp
|
|
jl near err_heaplow
|
|
%endmacro
|
|
|
|
%macro _CHKDIVIDEZERO 0
|
|
or ebp,ebp ; check for divide by zero
|
|
jz near err_divide
|
|
%endmacro
|
|
|
|
%macro _VERIFYADDRESS 1 ; used in load.i, store.i & lidx
|
|
cmp %1,stp ; error if address >= stp
|
|
jae near err_memaccess
|
|
cmp %1,hea ; so address<stp, ok if address<hea
|
|
jb short %%address_ok
|
|
cmp %1,ecx ; so address<stp and address>=hea, ok if address>=stk
|
|
jb near err_memaccess
|
|
%%address_ok:
|
|
%endmacro
|
|
|
|
%macro _SAVEREGS 0 ; save the registers (that may not be
|
|
PUSHAD ; __stdcall calling conventions)
|
|
%endmacro
|
|
|
|
%macro _RESTOREREGS 0
|
|
POPAD
|
|
%endmacro
|
|
|
|
%macro _DROPARGS 1 ; remove function arguments from the stack
|
|
%ifndef STDECL ; (only for __cdecl calling convention)
|
|
add esp,%1
|
|
%endif
|
|
%endmacro
|
|
|
|
|
|
Start_CODE
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; ;
|
|
;cell asm_exec( cell *regs, cell *retval, cell stp, cell hea );
|
|
; ;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
GLOBAL _amx_exec_asm
|
|
GLOBAL amx_exec_asm
|
|
amx_exec_asm:
|
|
_amx_exec_asm: ;PROC
|
|
|
|
push ebx
|
|
mov eax,[esp+08h]
|
|
mov edx,[esp+0ch]
|
|
mov ebx,[esp+10h]
|
|
mov ecx,[esp+14h]
|
|
|
|
push edi
|
|
push esi
|
|
push ebp
|
|
|
|
sub esp,4*3 ; place for PRI, ALT & STK at SYSREQs
|
|
|
|
push DWORD [eax+20h] ; store code size
|
|
push DWORD [eax+1ch] ; store pointer to code segment
|
|
push DWORD [eax+18h] ; store pointer to AMX
|
|
push edx ; store address of retval
|
|
push ebx ; store STP
|
|
push ecx ; store HEA
|
|
push DWORD [eax+14h] ; store FRM
|
|
|
|
%define stk [esp+36] ; define some aliases to registers
|
|
%define alt [esp+32] ; that are stored on the stack
|
|
%define pri [esp+28]
|
|
%define codesiz [esp+24]
|
|
%define code [esp+20]
|
|
%define amx [esp+16]
|
|
%define retval [esp+12]
|
|
%define stp [esp+8]
|
|
%define hea [esp+4]
|
|
%define frm [esp] ; FRM is NOT stored in ebp, rather FRM+DAT
|
|
; is being held in ebx.
|
|
|
|
mov edx,code ; change the code size to an...
|
|
add codesiz,edx ; ..."end of code" address
|
|
|
|
mov edx,[eax+04h] ; get ALT
|
|
mov esi,[eax+08h] ; get CIP
|
|
mov edi,[eax+0ch] ; get pointer to data segment
|
|
mov ecx,[eax+10h] ; get STK
|
|
mov ebx,[eax+14h] ; get FRM
|
|
mov eax,[eax] ; get PRI
|
|
add ebx,edi ; relocate frame
|
|
|
|
GO_ON ; start interpreting
|
|
|
|
|
|
OP_LOAD_PRI:
|
|
mov eax,[esi+4]
|
|
add esi,8
|
|
mov eax,[edi+eax]
|
|
GO_ON
|
|
|
|
OP_LOAD_ALT:
|
|
mov edx,[esi+4]
|
|
add esi,8
|
|
mov edx,[edi+edx]
|
|
GO_ON
|
|
|
|
;good
|
|
OP_LOAD_S_PRI:
|
|
mov eax,[esi+4]
|
|
add esi,8
|
|
mov eax,[ebx+eax]
|
|
GO_ON
|
|
|
|
;good
|
|
OP_LOAD_S_ALT:
|
|
mov edx,[esi+4]
|
|
add esi,8
|
|
mov edx,[ebx+edx]
|
|
GO_ON
|
|
|
|
OP_LOAD_I:
|
|
add esi,4
|
|
_VERIFYADDRESS eax
|
|
mov eax,[edi+eax]
|
|
GO_ON
|
|
|
|
OP_LODB_I:
|
|
_VERIFYADDRESS eax
|
|
mov ebp,[esi+4]
|
|
mov eax,[edi+eax] ;subject to misalignment stalls
|
|
add esi,8
|
|
and eax,DWORD [(lodb_and-4)+ebp*4]
|
|
GO_ON
|
|
|
|
OP_LREF_PRI:
|
|
mov eax,[esi+4]
|
|
add esi,8
|
|
mov eax,[edi+eax]
|
|
mov eax,[edi+eax]
|
|
GO_ON
|
|
|
|
OP_LREF_ALT:
|
|
mov edx,[esi+4]
|
|
add esi,8
|
|
mov edx,[edi+edx]
|
|
mov edx,[edi+edx]
|
|
GO_ON
|
|
|
|
OP_LREF_S_PRI:
|
|
mov eax,[esi+4]
|
|
add esi,8
|
|
mov eax,[ebx+eax]
|
|
mov eax,[edi+eax]
|
|
GO_ON
|
|
|
|
OP_LREF_S_ALT:
|
|
mov edx,[esi+4]
|
|
add esi,8
|
|
mov edx,[ebx+edx]
|
|
mov edx,[edi+edx]
|
|
GO_ON
|
|
|
|
;good
|
|
OP_CONST_PRI:
|
|
mov eax,[esi+4]
|
|
add esi,8
|
|
GO_ON
|
|
|
|
;good
|
|
OP_CONST_ALT:
|
|
mov edx,[esi+4]
|
|
add esi,8
|
|
GO_ON
|
|
|
|
;good
|
|
OP_ADDR_PRI:
|
|
mov eax,[esi+4]
|
|
add esi,8
|
|
add eax,frm
|
|
GO_ON
|
|
|
|
;good
|
|
OP_ADDR_ALT:
|
|
mov edx,[esi+4]
|
|
add esi,8
|
|
add edx,frm
|
|
GO_ON
|
|
|
|
OP_STOR_PRI:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
mov [ebp+edi],eax
|
|
GO_ON
|
|
|
|
OP_STOR_ALT:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
mov [ebp+edi],edx
|
|
GO_ON
|
|
|
|
;good
|
|
OP_STOR_S_PRI:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
mov [ebp+ebx],eax
|
|
GO_ON
|
|
|
|
;good
|
|
OP_STOR_S_ALT:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
mov [ebp+ebx],edx
|
|
GO_ON
|
|
|
|
;good
|
|
OP_STOR_I:
|
|
add esi,4
|
|
_VERIFYADDRESS edx
|
|
mov [edi+edx],eax
|
|
GO_ON
|
|
|
|
OP_STRB_I:
|
|
_VERIFYADDRESS edx
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
cmp ebp,1
|
|
jne short strb_not1byte
|
|
mov [edi+edx],al
|
|
GO_ON
|
|
strb_not1byte:
|
|
cmp ebp,4
|
|
je short strb_4byte
|
|
mov [edi+edx],ax
|
|
GO_ON
|
|
strb_4byte:
|
|
mov [edi+edx],eax
|
|
GO_ON
|
|
|
|
OP_SREF_PRI:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
mov ebp,[edi+ebp]
|
|
mov [edi+ebp],eax
|
|
GO_ON
|
|
|
|
OP_SREF_ALT:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
mov ebp,[edi+ebp]
|
|
mov [edi+ebp],edx
|
|
GO_ON
|
|
|
|
OP_SREF_S_PRI:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
mov ebp,[ebx+ebp]
|
|
mov [edi+ebp],eax
|
|
GO_ON
|
|
|
|
OP_SREF_S_ALT:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
mov ebp,[ebx+ebp]
|
|
mov [edi+ebp],edx
|
|
GO_ON
|
|
|
|
;good
|
|
OP_LIDX:
|
|
lea eax,[edx+4*eax]
|
|
add esi,4
|
|
_VERIFYADDRESS eax
|
|
mov eax,[edi+eax]
|
|
GO_ON
|
|
|
|
OP_LIDX_B:
|
|
push ecx
|
|
mov ecx,[esi+4]
|
|
shl eax,cl
|
|
add esi,8
|
|
add eax,edx
|
|
pop ecx
|
|
_VERIFYADDRESS eax
|
|
mov eax,[edi+eax]
|
|
GO_ON
|
|
|
|
;good
|
|
OP_IDXADDR:
|
|
add esi,4
|
|
lea eax,[edx+4*eax]
|
|
GO_ON
|
|
|
|
OP_IDXADDR_B:
|
|
push ecx
|
|
mov ecx,[esi+4]
|
|
add esi,8
|
|
shl eax,cl
|
|
pop ecx
|
|
add eax,edx
|
|
GO_ON
|
|
|
|
OP_ALIGN_PRI:
|
|
mov ebp,4 ; ??? one operation too many?
|
|
sub ebp,[esi+4]
|
|
add esi,8
|
|
xor eax,ebp
|
|
GO_ON
|
|
|
|
OP_ALIGN_ALT:
|
|
mov ebp,4
|
|
sub ebp,[esi+4]
|
|
add esi,8
|
|
xor edx,ebp
|
|
GO_ON
|
|
|
|
OP_LCTRL:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
cmp ebp,0
|
|
jne short lctrl_1
|
|
mov eax,code ; COD
|
|
GO_ON
|
|
lctrl_1:
|
|
cmp ebp,1
|
|
jne short lctrl_2
|
|
mov eax,edi ; DAT
|
|
GO_ON
|
|
lctrl_2:
|
|
cmp ebp,2
|
|
jne short lctrl_3
|
|
mov eax,hea ; 2=HEA
|
|
GO_ON
|
|
lctrl_3:
|
|
cmp ebp,3
|
|
jne short lctrl_4
|
|
mov ebp,amx
|
|
mov eax,stp
|
|
GO_ON
|
|
lctrl_4:
|
|
cmp ebp,4
|
|
jne short lctrl_5
|
|
mov eax,ecx ; 4=STK
|
|
GO_ON
|
|
lctrl_5:
|
|
cmp ebp,5
|
|
jne short lctrl_6
|
|
mov eax,frm ; 5=FRM
|
|
GO_ON
|
|
lctrl_6:
|
|
mov eax,esi ; 6=CIP
|
|
sub eax,code
|
|
GO_ON
|
|
|
|
OP_SCTRL:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
cmp ebp,2
|
|
jne short sctrl_4
|
|
mov hea,eax ; 2=HEA
|
|
GO_ON
|
|
sctrl_4:
|
|
cmp ebp,4
|
|
jne short sctrl_5
|
|
mov ecx,eax ; 4=STK
|
|
GO_ON
|
|
sctrl_5:
|
|
cmp ebp,5
|
|
jne short sctrl_6
|
|
mov ebx,eax ; 5=FRM
|
|
mov frm,eax
|
|
add ebx,edi ; relocate FRM
|
|
sctrl_6:
|
|
GO_ON
|
|
|
|
OP_MOVE_PRI:
|
|
add esi,4
|
|
mov eax,edx
|
|
GO_ON
|
|
|
|
;good
|
|
OP_MOVE_ALT:
|
|
add esi,4
|
|
mov edx,eax
|
|
GO_ON
|
|
|
|
OP_XCHG:
|
|
add esi,4
|
|
xchg eax,edx
|
|
GO_ON
|
|
|
|
;good
|
|
OP_PUSH_PRI:
|
|
add esi,4
|
|
_PUSH eax
|
|
GO_ON
|
|
|
|
;good
|
|
OP_PUSH_ALT:
|
|
add esi,4
|
|
_PUSH edx
|
|
GO_ON
|
|
|
|
OP_PUSH_R_PRI:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
push_loop:
|
|
_PUSH eax
|
|
dec ebp
|
|
jnz short push_loop
|
|
GO_ON
|
|
|
|
;good
|
|
OP_PUSH_C:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
_PUSH ebp
|
|
GO_ON
|
|
|
|
OP_PUSH:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
mov ebp,[ebp+edi]
|
|
_PUSH ebp
|
|
GO_ON
|
|
|
|
;good
|
|
OP_PUSH_S:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
mov ebp,[ebp+ebx]
|
|
_PUSH ebp
|
|
GO_ON
|
|
|
|
OP_POP_PRI:
|
|
add esi,4
|
|
_POP eax
|
|
GO_ON
|
|
|
|
;good
|
|
OP_POP_ALT:
|
|
add esi,4
|
|
_POP edx
|
|
GO_ON
|
|
|
|
;good
|
|
OP_STACK:
|
|
mov edx,ecx
|
|
add ecx,[esi+4]
|
|
_CHKMARGIN
|
|
_CHKSTACK
|
|
add esi,8
|
|
GO_ON
|
|
|
|
;good
|
|
OP_HEAP:
|
|
mov ebp,[esi+4]
|
|
mov edx,hea
|
|
add esi,8
|
|
add hea,ebp
|
|
_CHKMARGIN
|
|
_CHKHEAP
|
|
GO_ON
|
|
|
|
;good
|
|
OP_PROC:
|
|
mov ebx,frm
|
|
add esi,4
|
|
_PUSH ebx
|
|
mov ebx,edi
|
|
mov frm,ecx
|
|
add ebx,ecx
|
|
_CHKMARGIN
|
|
GO_ON
|
|
|
|
OP_RET:
|
|
_POP ebx
|
|
_POP esi
|
|
cmp esi,code ; verify ESI>=code
|
|
jb err_memaccess
|
|
cmp esi,codesiz ; verify ESI<codesiz ("end-of-code" pointer)
|
|
jae err_memaccess
|
|
mov frm,ebx
|
|
add ebx,edi
|
|
GO_ON
|
|
|
|
;good
|
|
OP_RETN:
|
|
_POP ebx
|
|
_POP esi
|
|
cmp esi,code ; verify ESI>=code
|
|
jb err_memaccess
|
|
cmp esi,codesiz ; verify ESI<codesiz ("end-of-code" pointer)
|
|
jae err_memaccess
|
|
mov frm,ebx
|
|
add ebx,edi
|
|
mov ebp,[edi+ecx]
|
|
lea ecx,[ecx+ebp+4]
|
|
GO_ON
|
|
|
|
OP_CALL:
|
|
lea ebp,[esi+8]
|
|
mov esi,[esi+4]
|
|
_PUSH ebp
|
|
GO_ON
|
|
|
|
OP_CALL_PRI:
|
|
lea ebp,[esi+4]
|
|
mov esi,eax
|
|
add esi,code ; cip = PRI + code
|
|
_PUSH ebp
|
|
GO_ON
|
|
|
|
;good
|
|
OP_JUMP:
|
|
mov esi,[esi+4]
|
|
GO_ON
|
|
|
|
OP_JREL:
|
|
add esi,[esi+4]
|
|
add esi,8
|
|
GO_ON
|
|
|
|
;good
|
|
OP_JZER:
|
|
or eax,eax
|
|
jz short jump_taken
|
|
add esi,8
|
|
GO_ON
|
|
|
|
jump_taken:
|
|
mov esi,[esi+4]
|
|
GO_ON
|
|
|
|
;good
|
|
OP_JNZ:
|
|
or eax,eax
|
|
jnz short jump_taken
|
|
add esi,8
|
|
GO_ON
|
|
|
|
;good
|
|
OP_JEQ:
|
|
cmp eax,edx
|
|
je short jump_taken
|
|
add esi,8
|
|
GO_ON
|
|
|
|
OP_JNEQ:
|
|
cmp eax,edx
|
|
jne short jump_taken
|
|
add esi,8
|
|
GO_ON
|
|
|
|
OP_JLESS:
|
|
cmp eax,edx
|
|
jb short jump_taken
|
|
add esi,8
|
|
GO_ON
|
|
|
|
OP_JLEQ:
|
|
cmp eax,edx
|
|
jbe short jump_taken
|
|
add esi,8
|
|
GO_ON
|
|
|
|
OP_JGRTR:
|
|
cmp eax,edx
|
|
ja short jump_taken
|
|
add esi,8
|
|
GO_ON
|
|
|
|
OP_JGEQ:
|
|
cmp eax,edx
|
|
jae short jump_taken ; unsigned comparison
|
|
add esi,8
|
|
GO_ON
|
|
|
|
OP_JSLESS:
|
|
cmp eax,edx
|
|
jl short jump_taken
|
|
add esi,8
|
|
GO_ON
|
|
|
|
;good
|
|
OP_JSLEQ:
|
|
cmp eax,edx
|
|
jle near jump_taken
|
|
add esi,8
|
|
GO_ON
|
|
|
|
OP_JSGRTR:
|
|
cmp eax,edx
|
|
jg near jump_taken
|
|
add esi,8
|
|
GO_ON
|
|
|
|
OP_JSGEQ:
|
|
cmp eax,edx
|
|
jge near jump_taken ; signed comparison
|
|
add esi,8
|
|
GO_ON
|
|
|
|
OP_SHL:
|
|
push ecx
|
|
mov ecx,edx
|
|
add esi,4
|
|
shl eax,cl
|
|
pop ecx
|
|
GO_ON
|
|
|
|
OP_SHR:
|
|
push ecx
|
|
mov ecx,edx
|
|
add esi,4
|
|
shr eax,cl
|
|
pop ecx
|
|
GO_ON
|
|
|
|
OP_SSHR:
|
|
push ecx
|
|
mov ecx,edx
|
|
add esi,4
|
|
sar eax,cl
|
|
pop ecx
|
|
GO_ON
|
|
|
|
OP_SHL_C_PRI:
|
|
push ecx
|
|
mov ecx,[esi+4]
|
|
add esi,8
|
|
shl eax,cl
|
|
pop ecx
|
|
GO_ON
|
|
|
|
OP_SHL_C_ALT:
|
|
push ecx
|
|
mov ecx,[esi+4]
|
|
add esi,8
|
|
shl edx,cl
|
|
pop ecx
|
|
GO_ON
|
|
|
|
OP_SHR_C_PRI:
|
|
push ecx
|
|
mov ecx,[esi+4]
|
|
add esi,8
|
|
shr eax,cl
|
|
pop ecx
|
|
GO_ON
|
|
|
|
OP_SHR_C_ALT:
|
|
push ecx
|
|
mov ecx,[esi+4]
|
|
add esi,8
|
|
shr edx,cl
|
|
pop ecx
|
|
GO_ON
|
|
|
|
OP_SMUL:
|
|
add esi,4
|
|
push edx
|
|
imul edx
|
|
pop edx
|
|
GO_ON
|
|
|
|
;good
|
|
OP_SDIV_ALT:
|
|
xchg eax,edx
|
|
ALIGN 4
|
|
|
|
OP_SDIV:
|
|
mov ebp,edx
|
|
xor edx,eax ; Check signs of the operands.
|
|
cdq
|
|
js short sdiv_fiddle ; If the signs of the operands are different
|
|
; we'll have to fiddle around to achieve
|
|
; proper rounding towards minus infinity.
|
|
_CHKDIVIDEZERO
|
|
add esi,4 ; default behavior is right in the other cases
|
|
idiv ebp
|
|
GO_ON
|
|
|
|
sdiv_fiddle:
|
|
_CHKDIVIDEZERO
|
|
idiv ebp
|
|
add esi,4
|
|
or edx,edx
|
|
jz short sdiv_goon ; If there's no remainder the result is correct
|
|
add edx,ebp ; else fix the result values.
|
|
dec eax ; Amazing, how simple this is...
|
|
sdiv_goon:
|
|
GO_ON
|
|
|
|
OP_UMUL:
|
|
add esi,4
|
|
push edx
|
|
mul edx
|
|
pop edx
|
|
GO_ON
|
|
|
|
OP_UDIV:
|
|
mov ebp,edx
|
|
sub edx,edx
|
|
_CHKDIVIDEZERO
|
|
add esi,4
|
|
div ebp
|
|
GO_ON
|
|
|
|
OP_UDIV_ALT:
|
|
mov ebp,eax
|
|
mov eax,edx
|
|
sub edx,edx
|
|
_CHKDIVIDEZERO
|
|
add esi,4
|
|
div ebp
|
|
GO_ON
|
|
|
|
;good
|
|
OP_ADD:
|
|
add esi,4
|
|
add eax,edx
|
|
GO_ON
|
|
|
|
;good
|
|
OP_SUB:
|
|
add esi,4
|
|
sub eax,edx
|
|
GO_ON
|
|
|
|
;good
|
|
OP_SUB_ALT:
|
|
neg eax
|
|
add esi,4
|
|
add eax,edx
|
|
GO_ON
|
|
|
|
OP_AND:
|
|
add esi,4
|
|
and eax,edx
|
|
GO_ON
|
|
|
|
OP_OR:
|
|
add esi,4
|
|
or eax,edx
|
|
GO_ON
|
|
|
|
OP_XOR:
|
|
add esi,4
|
|
xor eax,edx
|
|
GO_ON
|
|
|
|
OP_NOT:
|
|
add esi,4
|
|
neg eax ; sets CF iff EAX != 0
|
|
sbb eax,eax ; EAX == -1 iff CF set (zero otherwise)
|
|
inc eax ; -1 => 0 and 0 => 1
|
|
GO_ON
|
|
|
|
OP_NEG:
|
|
add esi,4
|
|
neg eax
|
|
GO_ON
|
|
|
|
OP_INVERT:
|
|
add esi,4
|
|
not eax
|
|
GO_ON
|
|
|
|
;good
|
|
OP_ADD_C:
|
|
add eax,[esi+4]
|
|
add esi,8
|
|
GO_ON
|
|
|
|
;good
|
|
OP_SMUL_C:
|
|
mov ebp,[esi+4]
|
|
push edx
|
|
imul ebp
|
|
pop edx
|
|
add esi,8
|
|
GO_ON
|
|
|
|
;good
|
|
OP_ZERO_PRI:
|
|
add esi,4
|
|
sub eax,eax
|
|
GO_ON
|
|
|
|
;good
|
|
OP_ZERO_ALT:
|
|
add esi,4
|
|
sub edx,edx
|
|
GO_ON
|
|
|
|
OP_ZERO:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
mov DWORD [edi+ebp],0
|
|
GO_ON
|
|
|
|
OP_ZERO_S:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
mov DWORD [ebx+ebp],0
|
|
GO_ON
|
|
|
|
OP_SIGN_PRI:
|
|
shl eax,24
|
|
add esi,4
|
|
sar eax,24
|
|
GO_ON
|
|
|
|
OP_SIGN_ALT:
|
|
shl edx,24
|
|
add esi,4
|
|
sar edx,24
|
|
GO_ON
|
|
|
|
OP_EQ:
|
|
add esi,4
|
|
cmp eax,edx ; PRI == ALT ?
|
|
mov eax,0
|
|
sete al
|
|
GO_ON
|
|
|
|
OP_NEQ:
|
|
add esi,4
|
|
cmp eax,edx ; PRI != ALT ?
|
|
mov eax,0
|
|
setne al
|
|
GO_ON
|
|
|
|
OP_LESS:
|
|
add esi,4
|
|
cmp eax,edx ; PRI < ALT ? (unsigned)
|
|
mov eax,0
|
|
setb al
|
|
GO_ON
|
|
|
|
OP_LEQ:
|
|
add esi,4
|
|
cmp eax,edx ; PRI <= ALT ? (unsigned)
|
|
mov eax,0
|
|
setbe al
|
|
GO_ON
|
|
|
|
OP_GRTR:
|
|
add esi,4
|
|
cmp eax,edx ; PRI > ALT ? (unsigned)
|
|
mov eax,0
|
|
seta al
|
|
GO_ON
|
|
|
|
OP_GEQ:
|
|
add esi,4
|
|
cmp eax,edx ; PRI >= ALT ? (unsigned)
|
|
mov eax,0
|
|
setae al
|
|
GO_ON
|
|
|
|
;good
|
|
OP_SLESS:
|
|
add esi,4
|
|
cmp eax,edx ; PRI < ALT ? (signed)
|
|
mov eax,0
|
|
setl al
|
|
GO_ON
|
|
|
|
OP_SLEQ:
|
|
add esi,4
|
|
cmp eax,edx ; PRI <= ALT ? (signed)
|
|
mov eax,0
|
|
setle al
|
|
GO_ON
|
|
|
|
OP_SGRTR:
|
|
add esi,4
|
|
cmp eax,edx ; PRI > ALT ? (signed)
|
|
mov eax,0
|
|
setg al
|
|
GO_ON
|
|
|
|
OP_SGEQ:
|
|
add esi,4
|
|
cmp eax,edx ; PRI >= ALT ? (signed)
|
|
mov eax,0
|
|
setge al
|
|
GO_ON
|
|
|
|
OP_EQ_C_PRI:
|
|
cmp eax,[esi+4] ; PRI == value ?
|
|
lea esi,[esi+8]
|
|
mov eax,0
|
|
sete al
|
|
GO_ON
|
|
|
|
OP_EQ_C_ALT:
|
|
xor eax,eax
|
|
cmp edx,[esi+4] ; ALT == value ?
|
|
lea esi,[esi+8]
|
|
sete al
|
|
GO_ON
|
|
|
|
OP_INC_PRI:
|
|
add esi,4
|
|
inc eax
|
|
GO_ON
|
|
|
|
OP_INC_ALT:
|
|
add esi,4
|
|
inc edx
|
|
GO_ON
|
|
|
|
OP_INC:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
inc DWORD [edi+ebp]
|
|
GO_ON
|
|
|
|
;good
|
|
OP_INC_S:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
inc DWORD [ebx+ebp]
|
|
GO_ON
|
|
|
|
OP_INC_I:
|
|
add esi,4
|
|
inc DWORD [edi+eax]
|
|
GO_ON
|
|
|
|
OP_DEC_PRI:
|
|
add esi,4
|
|
dec eax
|
|
GO_ON
|
|
|
|
OP_DEC_ALT:
|
|
add esi,4
|
|
dec edx
|
|
GO_ON
|
|
|
|
OP_DEC:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
dec DWORD [edi+ebp]
|
|
GO_ON
|
|
|
|
OP_DEC_S:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
dec DWORD [ebx+ebp]
|
|
GO_ON
|
|
|
|
OP_DEC_I:
|
|
add esi,4
|
|
sub DWORD [edi+eax],1
|
|
GO_ON
|
|
|
|
OP_MOVS:
|
|
_VERIFYADDRESS eax ; PRI
|
|
_VERIFYADDRESS edx ; ALT
|
|
mov ebp,eax
|
|
add ebp,[esi+4]
|
|
dec ebp
|
|
_VERIFYADDRESS ebp ; PRI + size - 1
|
|
mov ebp,edx
|
|
add ebp,[esi+4]
|
|
dec ebp
|
|
_VERIFYADDRESS ebp ; ALT + size - 1
|
|
|
|
push ecx
|
|
mov ecx,[esi+4]
|
|
add esi,8
|
|
push edi
|
|
push esi
|
|
lea esi,[edi+eax]
|
|
lea edi,[edi+edx]
|
|
|
|
push ecx
|
|
shr ecx,2
|
|
rep movsd
|
|
pop ecx
|
|
and ecx,3
|
|
rep movsb
|
|
|
|
pop esi
|
|
pop edi
|
|
pop ecx
|
|
GO_ON
|
|
|
|
OP_CMPS:
|
|
_VERIFYADDRESS eax ; PRI
|
|
_VERIFYADDRESS edx ; ALT
|
|
mov ebp,eax
|
|
add ebp,[esi+4] ; size in bytes
|
|
dec ebp ; EBP = PRI + size - 1
|
|
_VERIFYADDRESS ebp ; PRI + size - 1
|
|
sub ebp,eax ; EBP = size - 1
|
|
add ebp,edx ; EBP = ALT + size - 1
|
|
_VERIFYADDRESS ebp ; ALT + size - 1
|
|
|
|
push ecx
|
|
mov ecx,[esi+4]
|
|
add esi,8
|
|
push edi
|
|
push esi
|
|
lea esi,[edi+edx]
|
|
lea edi,[edi+eax]
|
|
|
|
xor eax,eax
|
|
repe cmpsb
|
|
je short cmps1
|
|
sbb eax,eax
|
|
sbb eax,0ffffffffh
|
|
cmps1:
|
|
pop esi
|
|
pop edi
|
|
pop ecx
|
|
GO_ON
|
|
|
|
|
|
OP_FILL:
|
|
mov ebp,[esi+4] ; get byte count
|
|
add esi,8
|
|
and ebp,0fffffffch ; align to words
|
|
jz short fill_ready
|
|
_VERIFYADDRESS edx ; ALT
|
|
dec ebp ; EBP = size - 1
|
|
add ebp,edx ; EBP = ALT + size - 1
|
|
_VERIFYADDRESS ebp ; ALT + size - 1
|
|
sub ebp,edx ; restore EBP
|
|
inc ebp
|
|
|
|
push ecx
|
|
push edi
|
|
mov ecx,ebp ; ECX = count (in bytes)
|
|
lea edi,[edi+edx] ; EDI = physical starting address
|
|
shr ecx,2 ; ECX = count (in DWORDS)
|
|
rep stosd
|
|
pop edi
|
|
pop ecx
|
|
fill_ready:
|
|
GO_ON
|
|
|
|
|
|
OP_HALT:
|
|
cmp DWORD retval,0
|
|
je short halt_no_retval
|
|
mov ebp,retval
|
|
mov [ebp],eax
|
|
halt_no_retval:
|
|
; store the complete status in the AMX
|
|
mov ebp,amx ; get amx into ebp
|
|
mov [ebp+_pri],eax ; store values in AMX structure (PRI, ALT, STK, HEA, FRM, ...)
|
|
mov [ebp+_alt],edx
|
|
mov [ebp+_stk],ecx
|
|
mov ecx,hea
|
|
mov ebx,frm
|
|
mov [ebp+_hea],ecx
|
|
mov [ebp+_frm],ebx ; EBX & ECX are invalid by now
|
|
mov ebx,[esi+4] ; EBX=parameter of the HALT opcode
|
|
add esi,8 ; skip this instruction
|
|
mov eax,esi ; EAX=CIP
|
|
sub eax,code
|
|
mov [ebp+_cip],eax
|
|
_ABORT ebx
|
|
|
|
|
|
OP_BOUNDS:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
cmp eax,ebp
|
|
ja near err_bounds ; use unsigned comparison, so <0 is >bounds
|
|
GO_ON
|
|
|
|
|
|
OP_SYSREQ_C:
|
|
mov eax,[esi+4] ; get function number
|
|
add esi,4
|
|
|
|
|
|
OP_SYSREQ_PRI:
|
|
mov ebp,amx ; get amx into ebp
|
|
add esi,4
|
|
|
|
mov stk,ecx ; save STK
|
|
mov alt,edx ; save ALT
|
|
|
|
mov [ebp+_stk],ecx ; store values in AMX structure (STK, HEA, FRM)
|
|
;we don't save regs since they're useless after this
|
|
mov ecx,hea
|
|
mov ebx,frm
|
|
mov [ebp+_hea],ecx
|
|
mov [ebp+_frm],ebx ; ebx & ecx are invalid by now
|
|
|
|
mov ebx,esi ; also store CIP
|
|
sub ebx,code
|
|
mov [ebp+_cip],ebx
|
|
|
|
mov edx,eax ; 2nd param: function number
|
|
mov eax,ebp ; 1st param: amx
|
|
mov ecx,stk
|
|
lea ebx,pri ; 3rd param: addr. of retval
|
|
add ecx,edi ; 4th param: addr. of function parameters
|
|
; save a few registers (it is not necessary to save them all
|
|
; and EAX should *not* be saved because it will hold the return
|
|
; value)
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
; push the parameters
|
|
push ecx
|
|
push ebx
|
|
push edx
|
|
push eax
|
|
call [ebp+_callback]
|
|
_DROPARGS 10h ; remove arguments from stack
|
|
pop edi ; restore saved registers
|
|
pop esi
|
|
pop ebp
|
|
_CHKABORT eax ; if result was invalid, leave
|
|
|
|
mov eax,pri ; get retval into eax (PRI)
|
|
mov edx,alt ; restore ALT
|
|
mov ebx,frm
|
|
mov ecx,stk ; restore STK
|
|
add ebx,edi ; restore FRM
|
|
GO_ON
|
|
|
|
|
|
OP_SYSREQ_D: ; (TR)
|
|
mov ebx,[esi+4] ; get function address
|
|
mov ebp,amx ; get amx into ebp
|
|
add esi,8
|
|
|
|
mov stk,ecx ; save STK
|
|
mov alt,edx ; save ALT
|
|
|
|
mov [ebp+_stk],ecx ; store values in AMX structure (STK, HEA, FRM)
|
|
mov ecx,hea
|
|
mov eax,frm
|
|
mov [ebp+_hea],ecx
|
|
mov [ebp+_frm],eax ; eax & ecx are invalid by now
|
|
|
|
mov eax,ebp ; 1st param: amx
|
|
mov edx,stk
|
|
add edx,edi ; 2nd param: addr. of function parameters
|
|
; save a few registers (it is not necessary to save them all
|
|
; and EAX should *not* be saved because it will hold the return
|
|
; value)
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
; push the parameters
|
|
push edx
|
|
push eax
|
|
call ebx ; direct call
|
|
_DROPARGS 8 ; remove arguments from stack
|
|
pop edi ; restore saved registers
|
|
pop esi
|
|
pop ebp
|
|
mov eax,[ebp+_error]
|
|
_CHKABORT eax
|
|
|
|
; function result is in eax (PRI)
|
|
mov edx,alt ; restore ALT
|
|
mov ebx,frm
|
|
mov ecx,stk ; restore STK
|
|
add ebx,edi ; restore FRM
|
|
GO_ON
|
|
|
|
|
|
OP_FILE:
|
|
jmp OP_INVALID
|
|
|
|
|
|
OP_LINE:
|
|
add esi,12
|
|
GO_ON
|
|
|
|
|
|
OP_SYMBOL:
|
|
add esi,[esi+4]
|
|
add esi,8 ; skip "fixed" part
|
|
GO_ON
|
|
|
|
|
|
OP_SRANGE:
|
|
add esi,12
|
|
GO_ON
|
|
|
|
|
|
OP_SYMTAG:
|
|
add esi,8
|
|
GO_ON
|
|
|
|
|
|
OP_JUMP_PRI:
|
|
mov esi,eax
|
|
GO_ON
|
|
|
|
|
|
OP_SWITCH:
|
|
push ecx
|
|
mov ebp,[esi+4] ; get offset of the switch table
|
|
add ebp,4 ; skip the "OP_CASETBL" opcode
|
|
mov ecx,[ebp] ; ECX = number of records
|
|
mov esi,[ebp+4] ; preset ESI to "none-matched" case
|
|
op_switch_loop:
|
|
or ecx, ecx ; number of records == 0?
|
|
jz short op_switch_end ; yes, no more records, exit loop
|
|
add ebp,8 ; skip previous record
|
|
dec ecx ; already decrement cases to do
|
|
cmp eax,[ebp] ; PRI == case label?
|
|
jne short op_switch_loop ; no, continue loop
|
|
mov esi,[ebp+4] ; yes, get jump address and exit loop
|
|
op_switch_end:
|
|
pop ecx
|
|
GO_ON
|
|
|
|
|
|
OP_CASETBL:
|
|
jmp OP_INVALID
|
|
|
|
|
|
OP_SWAP_PRI:
|
|
mov ebp,[edi+ecx]
|
|
add esi,4
|
|
mov [edi+ecx],eax
|
|
mov eax,ebp
|
|
GO_ON
|
|
|
|
|
|
OP_SWAP_ALT:
|
|
mov ebp,[edi+ecx]
|
|
add esi,4
|
|
mov [edi+ecx],edx
|
|
mov edx,ebp
|
|
GO_ON
|
|
|
|
|
|
OP_PUSHADDR:
|
|
mov ebp,[esi+4]
|
|
add esi,8
|
|
add ebp,frm
|
|
_PUSH ebp
|
|
GO_ON
|
|
|
|
|
|
OP_NOP:
|
|
add esi,4
|
|
GO_ON
|
|
|
|
OP_FLOAT_MUL:
|
|
add esi,4
|
|
fld dword [edi+ecx+4]
|
|
fmul dword [edi+ecx+8]
|
|
sub esp,4
|
|
fstp dword [esp]
|
|
pop eax
|
|
GO_ON
|
|
|
|
OP_FLOAT_DIV:
|
|
add esi,4
|
|
fld dword [edi+ecx+4]
|
|
fdiv dword [edi+ecx+8]
|
|
sub esp,4
|
|
fstp dword [esp]
|
|
pop eax
|
|
GO_ON
|
|
|
|
OP_FLOAT_ADD:
|
|
add esi,4
|
|
fld dword [edi+ecx+4]
|
|
fadd dword [edi+ecx+8]
|
|
sub esp,4
|
|
fstp dword [esp]
|
|
pop eax
|
|
GO_ON
|
|
|
|
OP_FLOAT_SUB:
|
|
add esi,4
|
|
fld dword [edi+ecx+4]
|
|
fsub dword [edi+ecx+8]
|
|
sub esp, 4
|
|
fstp dword [esp]
|
|
pop eax
|
|
GO_ON
|
|
|
|
OP_FLOAT_TO:
|
|
add esi,4
|
|
fild dword [edi+ecx+4]
|
|
sub esp,4
|
|
fstp dword [esp]
|
|
pop eax
|
|
GO_ON
|
|
|
|
OP_FLOAT_ROUND:
|
|
add esi,4
|
|
;get the float control word
|
|
push 0
|
|
mov ebp,esp
|
|
fstcw [ebp]
|
|
mov eax,[ebp]
|
|
push eax
|
|
;clear the top bits
|
|
xor ah,ah
|
|
;get the control method
|
|
push edx
|
|
mov edx,[edi+ecx+8]
|
|
and edx,3 ;sanity check
|
|
shl edx,2 ;shift it to right position
|
|
;set the bits
|
|
or ah,dl ;set bits 15,14 of FCW to rounding method
|
|
or ah,3 ;set precision to 64bit
|
|
mov [ebp], eax
|
|
fldcw [ebp]
|
|
;calculate
|
|
sub esp,4
|
|
fld dword [edi+ecx+4]
|
|
test edx,edx
|
|
jz .correct
|
|
jmp .skip_correct
|
|
.correct:
|
|
fadd st0
|
|
fadd dword [g_round_nearest]
|
|
fistp dword [esp]
|
|
pop eax
|
|
sar eax,1
|
|
jmp .done
|
|
.skip_correct:
|
|
frndint
|
|
fistp dword [esp]
|
|
pop eax
|
|
.done:
|
|
pop edx
|
|
;restore bits
|
|
pop ebp
|
|
mov [esp], ebp
|
|
fldcw [esp]
|
|
pop ebp
|
|
GO_ON
|
|
|
|
OP_FLOAT_CMP:
|
|
add esi, 4
|
|
fld dword [edi+ecx+8]
|
|
fld dword [edi+ecx+4]
|
|
fucompp
|
|
fnstsw ax
|
|
fwait
|
|
sahf
|
|
cmovz eax, [g_flags+4]
|
|
cmova eax, [g_flags+8]
|
|
cmovb eax, [g_flags+0]
|
|
GO_ON
|
|
|
|
OP_BREAK:
|
|
mov ebp,amx ; get amx into ebp
|
|
add esi,4
|
|
cmp DWORD [ebp+_debug], 0
|
|
jnz break_calldebug
|
|
GO_ON ; debug hook not active, ignore
|
|
|
|
break_calldebug:
|
|
; store the status in the AMX (FRM, STK, HEA, CIP, and PRI + ALT)
|
|
mov [ebp+_pri],eax
|
|
mov [ebp+_alt],edx ; EAX and EDX are now free to use
|
|
mov eax,frm
|
|
mov edx,hea
|
|
mov [ebp+_frm],eax ; store values in AMX structure (STK, FRM & HEA)
|
|
mov [ebp+_hea],edx
|
|
mov [ebp+_stk],ecx
|
|
mov eax,esi
|
|
sub eax,code ; EAX = CIP (relative to start of code segment)
|
|
mov [ebp+_cip],eax
|
|
; call the debug hook
|
|
mov eax,ebp ; 1st parm: amx
|
|
_SAVEREGS
|
|
push eax
|
|
call [ebp+_debug] ; call debug function
|
|
_DROPARGS 4 ; remove arguments from stack
|
|
cmp eax,AMX_ERR_NONE
|
|
je short break_noabort; continue running
|
|
mov [ebp+_error],eax ; save EAX (error code) before restoring all regs
|
|
_RESTOREREGS ; abort run, but restore stack first
|
|
mov eax,[ebp+_error] ; get error code in EAX back again
|
|
_FASTABORT
|
|
break_noabort:
|
|
_RESTOREREGS
|
|
mov eax,[ebp+_pri] ; restore PRI and ALT
|
|
mov edx,[ebp+_alt]
|
|
GO_ON
|
|
|
|
|
|
OP_INVALID:
|
|
_ABORT AMX_ERR_INVINSTR
|
|
|
|
err_call:
|
|
_ABORT AMX_ERR_CALLBACK
|
|
|
|
err_stack:
|
|
_ABORT AMX_ERR_STACKERR
|
|
|
|
err_stacklow:
|
|
_ABORT AMX_ERR_STACKLOW
|
|
|
|
err_memaccess:
|
|
_ABORT AMX_ERR_MEMACCESS
|
|
|
|
err_bounds:
|
|
_ABORT AMX_ERR_BOUNDS
|
|
|
|
err_heaplow:
|
|
_ABORT AMX_ERR_HEAPLOW
|
|
|
|
err_divide:
|
|
_ABORT AMX_ERR_DIVIDE
|
|
|
|
_return:
|
|
; save a few parameters, mostly for the "sleep"function
|
|
mov ebp,amx ; get amx into ebp
|
|
mov [ebp+_cip],esi ; get corrected cip for amxmodx
|
|
mov eax,[ebp+_error]; get error code
|
|
|
|
pop esi ; remove FRM from stack
|
|
|
|
pop ecx
|
|
pop ebx
|
|
pop edx
|
|
|
|
pop esi ; remove pointer to amx from stack
|
|
pop esi ; remove code segment pointer
|
|
pop esi ; remove code size
|
|
|
|
add esp,4*3 ; place for PRI, ALT & STK at SYSREQs
|
|
|
|
pop ebp
|
|
pop esi
|
|
pop edi
|
|
pop ebx
|
|
ret
|
|
|
|
; _amx_exec_asm ENDP
|
|
|
|
|
|
Start_DATA
|
|
ALIGN 4 ; This is essential to avoid misalignment stalls.
|
|
|
|
lodb_and DD 0ffh, 0ffffh, 0, 0ffffffffh
|
|
|
|
g_round_nearest DD 0.5
|
|
|
|
GLOBAL g_flags
|
|
g_flags:
|
|
DD -1
|
|
DD 0
|
|
DD 1
|
|
|
|
GLOBAL amx_opcodelist
|
|
GLOBAL _amx_opcodelist
|
|
amx_opcodelist:
|
|
_amx_opcodelist DD OP_INVALID
|
|
DD OP_LOAD_PRI
|
|
DD OP_LOAD_ALT
|
|
DD OP_LOAD_S_PRI
|
|
DD OP_LOAD_S_ALT
|
|
DD OP_LREF_PRI
|
|
DD OP_LREF_ALT
|
|
DD OP_LREF_S_PRI
|
|
DD OP_LREF_S_ALT
|
|
DD OP_LOAD_I
|
|
DD OP_LODB_I
|
|
DD OP_CONST_PRI
|
|
DD OP_CONST_ALT
|
|
DD OP_ADDR_PRI
|
|
DD OP_ADDR_ALT
|
|
DD OP_STOR_PRI
|
|
DD OP_STOR_ALT
|
|
DD OP_STOR_S_PRI
|
|
DD OP_STOR_S_ALT
|
|
DD OP_SREF_PRI
|
|
DD OP_SREF_ALT
|
|
DD OP_SREF_S_PRI
|
|
DD OP_SREF_S_ALT
|
|
DD OP_STOR_I
|
|
DD OP_STRB_I
|
|
DD OP_LIDX
|
|
DD OP_LIDX_B
|
|
DD OP_IDXADDR
|
|
DD OP_IDXADDR_B
|
|
DD OP_ALIGN_PRI
|
|
DD OP_ALIGN_ALT
|
|
DD OP_LCTRL
|
|
DD OP_SCTRL
|
|
DD OP_MOVE_PRI
|
|
DD OP_MOVE_ALT
|
|
DD OP_XCHG
|
|
DD OP_PUSH_PRI
|
|
DD OP_PUSH_ALT
|
|
DD OP_PUSH_R_PRI
|
|
DD OP_PUSH_C
|
|
DD OP_PUSH
|
|
DD OP_PUSH_S
|
|
DD OP_POP_PRI
|
|
DD OP_POP_ALT
|
|
DD OP_STACK
|
|
DD OP_HEAP
|
|
DD OP_PROC
|
|
DD OP_RET
|
|
DD OP_RETN
|
|
DD OP_CALL
|
|
DD OP_CALL_PRI
|
|
DD OP_JUMP
|
|
DD OP_JREL
|
|
DD OP_JZER
|
|
DD OP_JNZ
|
|
DD OP_JEQ
|
|
DD OP_JNEQ
|
|
DD OP_JLESS
|
|
DD OP_JLEQ
|
|
DD OP_JGRTR
|
|
DD OP_JGEQ
|
|
DD OP_JSLESS
|
|
DD OP_JSLEQ
|
|
DD OP_JSGRTR
|
|
DD OP_JSGEQ
|
|
DD OP_SHL
|
|
DD OP_SHR
|
|
DD OP_SSHR
|
|
DD OP_SHL_C_PRI
|
|
DD OP_SHL_C_ALT
|
|
DD OP_SHR_C_PRI
|
|
DD OP_SHR_C_ALT
|
|
DD OP_SMUL
|
|
DD OP_SDIV
|
|
DD OP_SDIV_ALT
|
|
DD OP_UMUL
|
|
DD OP_UDIV
|
|
DD OP_UDIV_ALT
|
|
DD OP_ADD
|
|
DD OP_SUB
|
|
DD OP_SUB_ALT
|
|
DD OP_AND
|
|
DD OP_OR
|
|
DD OP_XOR
|
|
DD OP_NOT
|
|
DD OP_NEG
|
|
DD OP_INVERT
|
|
DD OP_ADD_C
|
|
DD OP_SMUL_C
|
|
DD OP_ZERO_PRI
|
|
DD OP_ZERO_ALT
|
|
DD OP_ZERO
|
|
DD OP_ZERO_S
|
|
DD OP_SIGN_PRI
|
|
DD OP_SIGN_ALT
|
|
DD OP_EQ
|
|
DD OP_NEQ
|
|
DD OP_LESS
|
|
DD OP_LEQ
|
|
DD OP_GRTR
|
|
DD OP_GEQ
|
|
DD OP_SLESS
|
|
DD OP_SLEQ
|
|
DD OP_SGRTR
|
|
DD OP_SGEQ
|
|
DD OP_EQ_C_PRI
|
|
DD OP_EQ_C_ALT
|
|
DD OP_INC_PRI
|
|
DD OP_INC_ALT
|
|
DD OP_INC
|
|
DD OP_INC_S
|
|
DD OP_INC_I
|
|
DD OP_DEC_PRI
|
|
DD OP_DEC_ALT
|
|
DD OP_DEC
|
|
DD OP_DEC_S
|
|
DD OP_DEC_I
|
|
DD OP_MOVS
|
|
DD OP_CMPS
|
|
DD OP_FILL
|
|
DD OP_HALT
|
|
DD OP_BOUNDS
|
|
DD OP_SYSREQ_PRI
|
|
DD OP_SYSREQ_C
|
|
DD OP_FILE
|
|
DD OP_LINE
|
|
DD OP_SYMBOL
|
|
DD OP_SRANGE
|
|
DD OP_JUMP_PRI
|
|
DD OP_SWITCH
|
|
DD OP_CASETBL
|
|
DD OP_SWAP_PRI
|
|
DD OP_SWAP_ALT
|
|
DD OP_PUSHADDR
|
|
DD OP_NOP
|
|
DD OP_SYSREQ_D
|
|
DD OP_SYMTAG
|
|
DD OP_BREAK
|
|
DD OP_FLOAT_MUL
|
|
DD OP_FLOAT_DIV
|
|
DD OP_FLOAT_ADD
|
|
DD OP_FLOAT_SUB
|
|
DD OP_FLOAT_TO
|
|
DD OP_FLOAT_ROUND
|
|
DD OP_FLOAT_CMP
|