asm_dip/toolchain/fasm2/include/macro/proc64.inc

492 lines
9.6 KiB
PHP
Raw Normal View History

2024-11-24 21:04:53 -08:00
define fastcall? fastcall
fastcall.r1 equ rcx
fastcall.rd1 equ ecx
fastcall.rw1 equ cx
fastcall.rb1 equ cl
fastcall.rf1 equ xmm0
fastcall.r2 equ rdx
fastcall.rd2 equ edx
fastcall.rw2 equ dx
fastcall.rb2 equ dl
fastcall.rf2 equ xmm1
fastcall.r3 equ r8
fastcall.rd3 equ r8d
fastcall.rw3 equ r8w
fastcall.rb3 equ r8b
fastcall.rf3 equ xmm2
fastcall.r4 equ r9
fastcall.rd4 equ r9d
fastcall.rw4 equ r9w
fastcall.rb4 equ r9b
fastcall.rf4 equ xmm3
fastcall?.frame = -1
macro frame?
local size
define fastcall?.frame_size size
fastcall?.frame =: 0
sub rsp,size
end macro
macro end?.frame?
match size, fastcall?.frame_size
size := fastcall?.frame
add rsp,size
end match
restore fastcall?.frame,fastcall?.frame_size
end macro
macro endf?
end frame
end macro
macro fastcall?.inline_string var
local data,continue
jmp continue
if sizeof.TCHAR > 1
align sizeof.TCHAR,90h
end if
match value, var
data TCHAR value,0
end match
redefine var data
continue:
end macro
macro fastcall?: proc*,args&
local offset,framesize,type,value
if framesize & fastcall?.frame < 0
sub rsp,framesize
end if
offset = 0
local nest,called
called = 0
iterate arg, args
nest = 0
match =invoke? func, arg
nest = %
else match =fastcall? func, arg
nest = %
end match
if nest
if called
mov [rsp+8*(called-1)],rax
end if
frame
arg
end frame
called = nest
end if
end iterate
iterate arg, args
match =float? val, arg
type = 'f'
value reequ val
SSE.parse_operand@src val
else match =addr? val, arg
type = 'a'
value reequ val
x86.parse_operand@src [val]
else match =invoke? func, arg
if called = %
type = 0
value reequ rax
x86.parse_operand@src rax
else
type = 'r'
end if
else match =fastcall? func, arg
if called = %
type = 0
value reequ rax
x86.parse_operand@src rax
else
type = 'r'
end if
else match first=,rest, arg
type = 's'
value reequ arg
else
type = 0
value reequ arg
SSE.parse_operand@src arg
if @src.type = 'imm' & @src.size = 0
if value eqtype ''
type = 's'
end if
end if
end match
if type = 's'
fastcall.inline_string value
type = 'a'
end if
if % < 5
if type = 'f'
if @src.size = 8 | ~ @src.size | @src.type = 'mmreg'
if @src.type = 'imm'
mov rax,value
movq fastcall.rf#%,rax
else
movq fastcall.rf#%,value
end if
else if @src.size = 4
if @src.type = 'imm'
mov eax,value
movd fastcall.rf#%,eax
else
movd fastcall.rf#%,value
end if
else
err 'invalid argument ',`arg
end if
else
if type = 'a'
lea fastcall.r#%,[value]
else
if type = 'r'
@src.size = 8
@src.type = 'mem'
value equ [rsp+8*(%-1)]
end if
if @src.size = 8 | ~ @src.size
if @src.type <> 'reg' | ~ @src.imm eq fastcall.r#%
mov fastcall.r#%,value
end if
else if @src.size = 4
if @src.type <> 'reg' | ~ @src.imm eq fastcall.rd#%
mov fastcall.rd#%,value
end if
else if @src.size = 2
if @src.type <> 'reg' | ~ @src.imm eq fastcall.rw#%
mov fastcall.rw#%,value
end if
else if @src.size = 1
if @src.type <> 'reg' | ~ @src.imm eq fastcall.rb#%
mov fastcall.rb#%,value
end if
else
err 'invalid argument ',`arg
end if
end if
end if
else
if type = 'r'
; already on stack
else if @src.type = 'reg'
mov [rsp+offset],value
else if @src.type = 'mem'
if type = 'a'
lea rax,[value]
mov [rsp+offset],rax
else
if @src.size = 8 | ~ @src.size
mov rax,value
mov [rsp+offset],rax
else if @src.size = 4
mov eax,value
mov [rsp+offset],eax
else if @src.size = 2
mov ax,value
mov [rsp+offset],ax
else if @src.size = 1
mov al,value
mov [rsp+offset],al
else
err 'invalid argument ',`arg
end if
end if
else if @src.type = 'imm'
if @src.size = 8 | ~ @src.size
if (value) relativeto 0 & (value) - 1 shl 64 >= -80000000h & (value) < 1 shl 64
mov rax,(value) - 1 shl 64
mov [rsp+offset],rax
else if (value) relativeto 0 & ( (value) >= 80000000h | (value) < -80000000h )
mov rax,value
mov [rsp+offset],rax
else
mov qword [rsp+offset],value
end if
else if @src.size = 4
mov dword [rsp+offset],value
else if @src.size = 2
mov word [rsp+offset],value
else if @src.size = 1
mov byte [rsp+offset],value
else
err 'invalid argument ',`arg
end if
else if type = 'f' & @src.type = 'mmreg' & @src.size = 16
movq [rsp+offset],value
else
err 'invalid argument ',`arg
end if
end if
offset = offset + 8
end iterate
pcountcheck proc,offset/8
if offset < 20h
offset = 20h
end if
framesize = offset + offset and 8
call proc
if framesize & fastcall?.frame < 0
add rsp,framesize
else if fastcall?.frame >= 0 & framesize > fastcall?.frame
fastcall?.frame = framesize
end if
end macro
macro invoke?: proc*,args&
fastcall [proc],args
end macro
macro cinvoke?: proc*,args&
fastcall [proc],args
end macro
macro pcountcheck? proc*,args*
end macro
define pcountsuffix %
prologue@proc equ prologuedef
macro prologuedef procname,flag,parmbytes,localbytes,reglist
local loc,fill
loc = (localbytes+15) and (not 15)
parmbase@proc equ rbp+16
localbase@proc equ rbp-loc
push rbp
mov rbp,rsp
if loc+fill
sub rsp,loc+fill
end if
match any, reglist
iterate reg, reglist
push reg
if % = %%
fill := 8*(% and 1)
end if
end iterate
else
fill := 0
end match
end macro
epilogue@proc equ epiloguedef
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
iterate reg, reglist
indx %%-%+1
pop reg
end iterate
leave
retn
end macro
close@proc equ
macro proc? statement&
local _local,params,flag,regs,parmbytes,localbytes,current,tmp,initlocal
macro endp?!
localbytes = current
purge ret?,locals?,endl?,proclocal?
match close:reglist, close@proc,<regs>
close name,flag,parmbytes,localbytes,reglist
end match
end match
end namespace
end if
end match
purge endp?
end macro
match name declaration, statement :
if used name
name:
namespace name
outscope match local?, proclocal
match =stdcall? args :, declaration
define params args
flag = 11b
else match =stdcall? :, declaration
define params
flag = 11b
else match =c? args :, declaration
define params args
flag = 10001b
else match =c? :, declaration
define params
flag = 10001b
else match args :, declaration
define params args
flag = 0
else
define params
flag = 0
end match
define regs
match =uses? list, params
define params list
while 1
match =, tail, params
define params tail
break
else match reg tail, params&
match more&, tail
define params more
else
define params
end match
if % = 1
regs equ reg
else
regs equ regs,reg
end if
else
break
end match
end while
else match =, tail, params
define params tail
end match
match prologue:reglist, prologue@proc:<regs>
prologue name,flags,parmbytes,localbytes,reglist
end match
virtual at parmbase@proc
namespace name
match args, params
iterate arg, args
match argname:type, arg
label argname:type
rb type
else
?arg dq ?
end match
end iterate
end match
parmbytes := $-(parmbase@proc)
match p, pcountsuffix
name#p = parmbytes/8
end match
end namespace
end virtual
macro ret? operand
match any, operand
retn operand
else
match epilogue:reglist, epilogue@proc:<regs>
epilogue name,flag,parmbytes,localbytes,reglist
end match
end match
end macro
current = 0
macro initlocal
local area,pointer,length,value
area::
pointer = localbase@proc+current
length = $@ - (localbase@proc) - current
current = $ - (localbase@proc)
end virtual
while length > 0
if length < 2
load value:byte from area:pointer
mov byte [pointer],value
pointer = pointer + 1
length = length - 1
else if length < 4
load value:word from area:pointer
mov word [pointer],value
pointer = pointer + 2
length = length - 2
else if length < 8
load value:dword from area:pointer
mov dword [pointer],value
pointer = pointer + 4
length = length - 4
else
load value:qword from area:pointer
if value < 80000000h | value >= 1 shl 64 - 80000000h
mov qword [pointer],value
pointer = pointer + 8
length = length - 8
else
mov dword [pointer],value and 0FFFFFFFFh
pointer = pointer + 4
length = length - 4
end if
end if
end while
virtual at localbase@proc+current
end macro
macro locals?
virtual at localbase@proc+current
iterate dword, dword,qword
macro dword? value
if value relativeto 0
emit dword: value
else
initlocal
local pointer
pointer := $
end virtual
mov dword [pointer],value
virtual at pointer+4
current = $ - (localbase@proc)
end if
end macro
end iterate
macro ? line&
line
if $ > $@
initlocal
end if
end macro
end macro
macro endl?
purge ?, dword?,qword?
initlocal
end virtual
end macro
macro proclocal? args&
locals
iterate arg, args
match varname[count]:type, arg
?varname dbx type:count dup ?
else match varname:type, arg
?varname dbx type, ?
else match varname[count], arg
?varname rq count
else match varname type, arg
?varname type
else
?arg dq ?
end match
end iterate
endl
end macro
end macro