dxx-rebirth/include/psmacros.inc
Bradley Bell f05dc678f0 This commit was generated by cvs2svn to compensate for changes in r5,
which included commits to RCS files with non-trunk default branches.
2001-01-19 03:34:09 +00:00

331 lines
6.7 KiB
PHP

; THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
; SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
; END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
; ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
; IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
; SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
; FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
; CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
; AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
; COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
;Shortcuts for casting
w equ word ptr
b equ byte ptr
;The macros @ArgCount() & @ArgRev() are from the file MACROS.INC, provided
;with MASM. I have included them here because MACROS.INC has bugs, so I
;couldn't just include it.
; Utility Macros - Version 1.0 - for Microsoft Macro Assembler 6.0
; (C) Copyright Microsoft Corporation, 1987,1988,1989,1990
;* @ArgCount - Macro function returns the number of arguments in a
;* VARARG list.
;*
;* Params: arglist - arguments to be counted
@ArgCount MACRO arglist:VARARG
LOCAL count
count = 0
FOR arg, <arglist>
count = count + 1
ENDM
EXITM %count
ENDM
;* @ArgRev - Macro function returns a reversed order version of a
;* VARARG list.
;*
;* Shows: Operators - <> ! %
;* String directive - SUBSTR
;* Predefined function - @SizeStr
;*
;* Params: arglist - arguments to be reversed
@ArgRev MACRO arglist:vararg
LOCAL txt, arg
txt TEXTEQU <>
% FOR arg, <arglist>
txt CATSTR <arg>, <!,>, txt
ENDM
txt SUBSTR txt, 1, @SizeStr( %txt ) - 1
txt CATSTR <!<>, txt, <!>>
EXITM txt
ENDM
;These macros are used for decalaring external vars and functions
;this macro is used to declare several symbols of the same type
;usage is: extdef type,sym0,sym1,...
extdef macro type,syms:vararg
for sym,<syms>
externdef sym:type
endm
endm
;this macro is used to generate ext<type> macros
extgen macro type,id
ext&id macro syms:vararg
extdef type,syms
endm
endm
;macros for common types, such as word (extw), byte (extb), & near (extn)
extgen word,w
extgen byte,b
extgen dword,d
extgen near,n
;compute the absolute value of eax. afterwards, edx=sign (0 or -1)
abs_eax macro
cdq
xor eax,edx
sub eax,edx
endm
;PUSHM & POPM are used for multiple registers. Note that POPM pops in the
;reverse order from PUSHM, so the list of regs shouls be the same for both.
;You can also define a constant which is a register list, and use it as the
;argument to both macros.
;push multiple registers
pushm macro args:vararg
local arg
for arg,<args>
push arg
endm
endm
;pop multiple registers
popm macro args:vararg
local arg
% for arg,@ArgRev(args)
pop arg
endm
endm
;PUSHLONG pushes a long, zero extending the argument if necessary
;it trashes no registers
pushlong macro arg
local s
s = TYPE arg
if s EQ 0 ;constant, I think
push arg
elseif s LT 4
push eax
movzx eax,arg
xchg eax,[esp]
else
push arg
endif
endm
;PUSHML is pushm using pushlong
pushml macro args:vararg
local arg
for arg,<args>
pushlong arg
endm
endm
;DBSTR stores a string with occurances of \n converted to newlines
;this macro expects quotes around the string
;
;note the 'fudge' variable. This fixes an odd problem with the way
;the string macros deal with backslashes - @InStr() treats them like
;any other character, but @SubStr() ignores them
dbstr macro str
local pos,oldpos,len,fudge
oldpos = 2 ;skip initial quote
fudge = 0
len = @SizeStr(str)
pos = @InStr(oldpos,str,<\n>)
while pos GE oldpos
if pos GT oldpos
%db '&@SubStr(<&str>,&oldpos-&fudge,&pos-&oldpos)'
endif
db 10
oldpos = pos+2
fudge = fudge+1
pos = @InStr(oldpos,<str>,<\n>)
endm
if oldpos LT len
;;; %db '&@SubStr(&str,&oldpos-&fudge,&len-&oldpos-1)'
%db '&@SubStr(&str,&oldpos-&fudge,&len-&oldpos)'
endif
endm
;MPRINTF is a macro interface to the mprintf funcion. It puts the format
;string in the code segment at the current location, pushes the args, and
;calls mprintf. If window is not specified, zero is assumed
mprintf macro window:=<0>,format:req,args:vararg
local string,skip
ifndef NDEBUG
ifndef NMONO
extn mprintf_
jmp skip
string label byte
dbstr format
db 0
skip:
ifnb <args>
% pushml @ArgRev(args)
endif
pushml offset string,window
call mprintf_
add esp,(@ArgCount(args)+2)*4 ;fix stack
endif
endif
endm
;MPRINTF_AT - version of mprintf with coordinates
mprintf_at macro window:=<0>,row,col,format:req,args:vararg
local string,skip
ifndef NDEBUG
ifndef NMONO
extn mprintf_at_
jmp skip
string label byte
dbstr format
db 0
skip:
ifnb <args>
% pushml @ArgRev(args)
endif
pushml offset string,col,row,window
call mprintf_at_
add esp,(@ArgCount(args)+4)*4 ;fix stack
endif
endif
endm
;DEBUG calls mprintf with window 0, preserving all registers and flags
;is is conditionall assembled based on the DEBUG_ON flags
debug macro format:req,args:vararg
ifndef NDEBUG
pushf ;save flags
push eax ;mprintf trashes eax
mprintf ,format,args
pop eax
popf
endif
endm
;DEBUG_AT - version of debug with coordinates
debug_at macro row,col,format:req,args:vararg
ifndef NDEBUG
pushf ;save flags
push eax ;mprintf trashes eax
mprintf_at ,row,col,format,args
pop eax
popf
endif
endm
;Debugging breakpoint macros
;print a message, and do an int3 to pop into the debugger
debug_brk macro str
ifndef NDEBUG
debug str
int 3
endif
endm
break_if macro cc,str
local skip,yes_break
ifndef NDEBUG
j&cc yes_break
jmp skip
yes_break: debug_brk str
skip:
endif
endm
;returns the bit number of the highest bit
@HighBit macro n
local t,c
if n EQ 0
exitm <-1> ;error!
else
t = n
c = 0
while t GT 1
t = t SHR 1
c = c+1
endm
exitm <c>
endif
endm
;returns the bit number of the lowest bit
@LowBit macro n
;local t,c
local c
if n EQ 0
exitm <-1> ;error!
else
t = n
c = 0
while (t and 1) EQ 0
t = t SHR 1
c = c+1
endm
exitm <c>
endif
endm
;"multiply" the given register by a constant, using whatever method is
;best for the given constant
imulc macro reg,c
local low,high
if c EQ 0
xor reg,reg
elseif c EQ 1
elseif c EQ 3
lea reg,[reg*2+reg]
elseif c EQ 5
lea reg,[reg*4+reg]
elseif c EQ 6
lea reg,[reg*2+reg] ;*3
shl reg,1 ;*6
elseif c EQ 9
lea reg,[reg*8+reg]
elseif c EQ 36
lea reg,[reg*8+reg]
sal reg,2
else
low = @LowBit(c)
high = @HighBit(c)
if low EQ high
shl reg,@LowBit(c)
else
imul reg,c
echo Warning: Using imul, to perform multiply by &c
;; .err
endif
endif
endm