summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2002-04-30 21:01:08 +0000
committerH. Peter Anvin <hpa@zytor.com>2002-04-30 21:01:08 +0000
commit734b188090539eddf08e61c317415f566446691b (patch)
treeabc7516f5a80c8b0810f5018125eb5f95717ca76
parent1cd0e2d5bf50b2cc482cad7beb8f7dee6a81d57b (diff)
downloadnasm-734b188090539eddf08e61c317415f566446691b.tar.gz
nasm-734b188090539eddf08e61c317415f566446691b.tar.bz2
nasm-734b188090539eddf08e61c317415f566446691b.zip
NASM 0.98.09
-rw-r--r--AUTHORS2
-rw-r--r--Makefile.in2
-rw-r--r--Mkfiles/Makefile.b3249
-rw-r--r--Mkfiles/Makefile.dl46
-rw-r--r--assemble.c4
-rw-r--r--doc/makedocs.bat254
-rw-r--r--doc/nasmdoc.src149
-rw-r--r--insns.dat794
-rw-r--r--labels.c5
-rw-r--r--listing.c2
-rw-r--r--macros.pl38
-rw-r--r--misc/scitech.mac1223
-rw-r--r--nasm.c160
-rw-r--r--nasm.h6
-rw-r--r--nasmlib.c4
-rw-r--r--outaout.c4
-rw-r--r--outas86.c2
-rw-r--r--outbin.c683
-rw-r--r--outcoff.c8
-rw-r--r--outelf.c2
-rw-r--r--outform.h2
-rw-r--r--outobj.c2
-rw-r--r--parser.c16
-rw-r--r--preproc.c4438
-rw-r--r--rdoff/Makefile.in4
-rw-r--r--rdoff/README12
-rw-r--r--rdoff/ldrdf1.c728
-rw-r--r--standard.mac22
-rw-r--r--zoutieee.c8
29 files changed, 5133 insertions, 3536 deletions
diff --git a/AUTHORS b/AUTHORS
index 2fa097d..fb10957 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,5 +1,5 @@
This is the AUTHORS file for the NASM project located at:
-http://nasm.rm-f.net/
+http://nasm.2y.net/
Names should be inserted as follows:
diff --git a/Makefile.in b/Makefile.in
index 3d31f56..52a772a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -15,7 +15,7 @@ bindir = @bindir@
mandir = @mandir@
CC = @CC@
-CFLAGS = @CFLAGS@ @GCCFLAGS@ -I$(srcdir) -I.
+CFLAGS = @CFLAGS@ @GCCFLAGS@ -I$(srcdir) -I.
LDFLAGS = @LDFLAGS@
INSTALL = @INSTALL@
diff --git a/Mkfiles/Makefile.b32 b/Mkfiles/Makefile.b32
index 2e642d0..d83e6e0 100644
--- a/Mkfiles/Makefile.b32
+++ b/Mkfiles/Makefile.b32
@@ -7,13 +7,19 @@
#
# This Makefile is designed to build NASM with the latest
# version of Borland C++Builder and has been tested with
-# Borland C++ 5.3 (Borland C++Builder 3.0) and Borland C++ 5.4
-# (Borland C++Builder 4.0) in combination with
-# Borland MAKE versions 5.1 and 5.2
+# Borland C++ 5.5 (Borland C++Builder 5.0) in combination
+# Borland MAKE 5.2
+#
+# Additionally, the free Borland C++ Compiler 5.5 is supported;
+# see
+#
+# http://www.borland.com/bcppbuilder/freecompiler/
#
# MAKEFILE is maintained by Stefan.Hoffmeister@Econos.de
#
+srcdir=.
+BINDIR=e:\devel\bcb5\cbuilder5\bin
# If "BINDIR=C:\...." has not been defined on the command line
# assume that the binary files are in the same directory as the
@@ -35,15 +41,19 @@
CC=$(BINDIR)\bcc32
-CCFLAGS=-tWC -c -O2 -A
+CCFLAGS=-q -Q -tWC -c -O2 -A -w-8057
+ # /q: Suppress compiler identification banner
+ # /Q: Extended compiler error information
# /-tWC: Windows console mode application
# /c: Compile, do not link
# /O2: Optimize for speed
# /A: ANSI compatible code only
+ # /-w-8057: Turn off "Parameter <param> never used in function <func>" warning
LINK=$(BINDIR)\ilink32
-LINKFLAGS=/V4.0 /x /c /ap /L$(BINDIR)\..\LIB # /L -> default LIB directory
+LINKFLAGS=/V4.0 /q /x /c /ap /L$(BINDIR)\..\LIB # /L -> default LIB directory
# /V4.0: marked as Win95 / NT application in PE header
+ # /q: suppress command-line banner
# /x: no map file
# /c: case sensitive link
# /ap: link for 32-bit console application
@@ -131,7 +141,30 @@ parser.$(OBJ): parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insns
preproc.$(OBJ): preproc.c macros.c preproc.h nasm.h insnsi.h nasmlib.h
sync.$(OBJ): sync.c sync.h
+# These source files are automagically generated from a single
+# instruction-table file by a Perl script. They're distributed,
+# though, so it isn't necessary to have Perl just to recompile NASM
+# from the distribution.
+
+insnsa.c: InstructionData
+insnsd.c: InstructionData
+insnsi.h: InstructionData
+insnsn.c: InstructionData
+
+InstructionData: insns.dat insns.pl
+ perl $(srcdir)/insns.pl -a $(srcdir)/insns.dat
+
+# This source file is generated from the standard macros file
+# `standard.mac' by another Perl script. Again, it's part of the
+# standard distribution.
+
+macros.c: standard.mac macros.pl
+ perl $(srcdir)/macros.pl $(srcdir)/standard.mac
+
clean:
- del *.obj
- del nasm$(SUFFIX)$(EXE)
- del ndisasm$(SUFFIX)$(EXE)
+ @-del /S *.obj 2> NUL 1>&2
+ @-del /S *.il? 2> NUL 1>&2
+ @-del /S *.tds 2> NUL 1>&2
+ @-del /S *.~* 2> NUL 1>&2
+ @-del /S nasm$(SUFFIX)$(EXE) 2> NUL 1>&2
+ @-del /S ndisasm$(SUFFIX)$(EXE) 2> NUL 1>&2
diff --git a/Mkfiles/Makefile.dl b/Mkfiles/Makefile.dl
new file mode 100644
index 0000000..db53e57
--- /dev/null
+++ b/Mkfiles/Makefile.dl
@@ -0,0 +1,46 @@
+# Makefile for the Netwide Assembler under 16-bit DOS
+#
+# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+# Julian Hall. All rights reserved. The software is
+# redistributable under the licence given in the file "Licence"
+# distributed in the NASM archive.
+#
+# This Makefile is designed to build NASM using David Lindauer's
+# cc386
+
+CC = cc386 /C+N
+LINK = valx -case -use32 -map
+LINKFLAGS =
+LIBRARIES =
+OBJ = obj
+
+.c.obj:
+ $(CC) $&
+ &nasm -fobj $&.ASM
+
+NDISASMOBJS = ndisasm.$(OBJ) disasm.$(OBJ) sync.$(OBJ) nasmlib.$(OBJ) \
+ insnsd.$(OBJ)
+
+NASMOBJS = nasm.$(OBJ) nasmlib.$(OBJ) eval.$(OBJ) float.$(OBJ) insnsa.$(OBJ) \
+ assemble.$(OBJ) labels.$(OBJ) parser.$(OBJ) outform.$(OBJ) \
+ outbin.$(OBJ) outaout.$(OBJ) outcoff.$(OBJ) outelf.$(OBJ) \
+ outobj.$(OBJ) outas86.$(OBJ) outrdf.$(OBJ) outrdf2.$(OBJ) outdbg.$(OBJ) \
+ preproc.$(OBJ) listing.$(OBJ) zoutieee.$(OBJ)
+
+all : nasm.exe ndisasm.exe
+
+# We have to have a horrible kludge here to get round the 128 character
+# limit, as usual...
+LINKOBJS = a*.obj e*.obj f*.obj insnsa.obj l*.obj na*.obj o*.obj p*.obj z*.obj
+nasm.exe: $(NASMOBJS)
+ $(LINK) \cc386\lib\c0dos $(LINKOBJS:.obj=),nasm,nasm,\cc386\lib\cldos
+
+ndisasm.exe: $(NDISASMOBJS)
+ $(LINK) \cc386\lib\c0dos.obj $(NDISASMOBJS:.obj=),ndisasm,ndisasm,\cc386\lib\cldos
+
+clean :
+ del *.asm
+ del *.obj
+ del *.map
+ del *.exe
+
diff --git a/assemble.c b/assemble.c
index 98bb507..8058979 100644
--- a/assemble.c
+++ b/assemble.c
@@ -546,7 +546,9 @@ static int is_sbyte (insn *ins, int op, int size)
int ret;
ret = !(ins->forw_ref && ins->oprs[op].opflags ) && /* dead in the water on forward reference or External */
- ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
+ !(ins->oprs[op].type & (BITS16|BITS32)) && /* John Coffman's 3/24/01 patch - fbk - 10/16/01 */
+ ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
+
v = ins->oprs[op].offset;
if (size==16) v = (signed short)v; /* sign extend if 16 bits */
diff --git a/doc/makedocs.bat b/doc/makedocs.bat
new file mode 100644
index 0000000..70db811
--- /dev/null
+++ b/doc/makedocs.bat
@@ -0,0 +1,254 @@
+@echo off
+if "%1"=="clean" goto makeclean
+if "%1"=="CLEAN" goto makeclean
+if "%1"=="spotless" goto spotless
+if "%1"=="SPOTLESS" goto spotless
+if "%1"=="install" goto install
+if "%1"=="INSTALL" goto install
+
+cls
+echo.
+echo.
+echo.
+echo Usage:
+echo.
+echo makedocs - no parameters - makes all Docs
+echo makedocs install - installs already made docs in subdirectories
+echo makedocs clean - removes docs from current directory
+echo makedocs spotless - removes all - including default install dirs
+echo.
+echo.
+echo.
+echo.
+echo Makedocs(.bat), with no parameters will create Nasm Documentation
+echo in several formats: plain ascii text, ps, html, rtf, Windows help
+echo format, and if you've got an "info" system installed, info format.
+echo.
+echo.
+echo This requires Perl, and almost 4MB disk space.
+echo.
+echo.
+choice " Proceed with making docs? "
+if errorlevel 2 goto exit
+
+:makeall
+
+echo.
+echo.
+echo This takes a while. Stretch!
+echo.
+echo.
+
+perl rdsrc.pl<nasmdoc.src
+echo.
+echo.
+choice " Make *info* files? "
+if errorlevel 2 goto noinfo
+:makeinfo
+echo.
+echo.
+makeinfo nasmdoc.tex
+
+:noinfo
+
+:install
+
+if not exist nasmdoc.txt goto nofiles
+if not exist nasmdoc0.htm goto nofiles
+if not exist nasmdo10.htm goto nofiles
+if not exist nasmdoc.hpj goto nofiles
+if not exist nasmdoc.rtf goto nofiles
+if not exist nasmdoc.ps goto nofiles
+if not exist nasmdoc.tex goto nofiles
+goto gotfiles
+:nofiles
+echo.
+echo.
+echo.
+echo.
+echo Alert! Files missing!
+echo.
+echo.
+choice " Would you like to make them now? "
+if errorlevel 2 goto exit
+goto makeall
+
+:gotfiles
+
+:: get current path
+
+set oldprompt=%prompt%
+echo @prompt set nasdoc=$p>temp1.bat
+command /c temp1.bat>temp2.bat
+call temp2
+del temp1.bat
+del temp2.bat
+set prompt=%oldprompt%
+set oldprompt=
+
+echo.
+echo.
+echo.
+echo.
+echo Current Directory is %nasdoc%
+echo Nasm Documentation will be installed under this
+echo as %nasdoc%\text\nasmdoc.txt, etc.
+echo.
+echo.
+choice " Change this directory? "
+if errorlevel 2 goto dirok
+
+echo.
+echo.
+echo.
+echo.
+echo Directory *above* the directory you name (at least) should exist.
+echo Nasm documentation will be installed *under* the directory you
+echo name. E.G. \docs\nasm\html, etc. No trailing backslash!
+echo.
+echo.
+
+echo Enter new name for base directory:
+set input=
+fc con nul /lb1 /n|date|find "1:">magic.bat
+echo set input=%%5>enter.bat
+call magic
+set nasdoc=%input%
+del magic.bat
+del enter.bat
+set input=
+
+echo.
+echo.
+md %nasdoc%
+echo.
+echo.
+
+choice " Install Text docs in %nasdoc%\text ? "
+if errorlevel 2 goto notext
+md %nasdoc%\text
+copy nasmdoc.txt %nasdoc%\text
+:notext
+
+choice " Install Html docs in %nasdoc%\html ? "
+if errorlevel 2 goto nohtml
+md %nasdoc%\html
+copy *.htm %nasdoc%\html
+:nohtml
+
+choice " Install Info docs in %nasdoc%\info ? "
+if errorlevel 2 goto noinfodocs
+if not exist nasm.inf goto inofiles
+if not exist nasm.i9 goto inofiles
+goto gotifiles
+:inofiles
+echo.
+echo.
+echo Alert! Files missing!
+echo.
+echo.
+choice " Would you like to make them now? "
+if errorlevel 2 goto noinfodocs
+if not exist nasmdoc.tex goto makeall
+goto makeinfo
+
+:gotifiles
+
+md %nasdoc%\info
+copy nasm.i* %nasdoc%\info
+:noinfodocs
+
+choice " Install Winhelp docs in %nasdoc%\winhelp ? "
+if errorlevel 2 goto nowinhelp
+md %nasdoc%\winhelp
+copy nasmdoc.rtf %nasdoc%\winhelp
+copy nasmdoc.hpj %nasdoc%\winhelp
+:nowinhelp
+
+choice " Install Postscript docs in %nasdoc%\ps ? "
+if errorlevel 2 goto nops
+md %nasdoc%\ps
+copy nasmdoc.ps %nasdoc%\ps
+:nops
+goto cleanup
+
+:dirok
+
+choice " Install Text docs in .\text ? "
+if errorlevel 2 goto notext2
+md text
+copy nasmdoc.txt text
+:notext2
+
+choice " Install Html docs in .\html ? "
+if errorlevel 2 goto nohtml2
+md html
+copy *.htm html
+:nohtml2
+
+choice " Install Info docs in .\info ? "
+if errorlevel 2 goto nid2
+
+if not exist nasm.inf goto inof2
+if not exist nasm.i9 goto inof2
+goto gifiles2
+:inof2
+echo.
+echo.
+echo Alert! Files missing!
+echo.
+echo.
+choice " Would you like to make them now? "
+if errorlevel 2 goto nid2
+if not exist nasmdoc.tex goto makeall
+goto makeinfo
+
+:gifiles2
+
+md info
+copy nasm.i* info
+:nid2
+
+choice " Install Winhelp docs in .\winhelp ? "
+if errorlevel 2 goto nwhelp2
+md winhelp
+copy nasmdoc.rtf winhelp
+copy nasmdoc.hpj winhelp
+:nwhelp2
+
+choice " Install Postscript docs in .\ps ? "
+if errorlevel 2 goto nops2
+md ps
+copy nasmdoc.ps ps
+:nops2
+
+
+:cleanup
+set nasdoc=
+
+echo.
+echo.
+echo.
+echo.
+choice " Remove all files created, but not installed?"
+if not errorlevel 2 goto makeclean
+
+goto exit
+
+:spotless
+deltree /y text
+deltree /y html
+deltree /y info
+deltree /y winhelp
+deltree /y ps
+
+:makeclean
+del *.htm
+del *.rtf
+del *.hpj
+del *.txt
+del *.tex
+del *.ps
+del nasm.i*
+
+:exit
diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src
index c047f1f..f91861b 100644
--- a/doc/nasmdoc.src
+++ b/doc/nasmdoc.src
@@ -592,6 +592,39 @@ and increase compilation speeds. The \c{-a} option, requiring no
argument, instructs NASM to replace its powerful \i{preprocessor}
with a \i{stub preprocessor} which does nothing.
+\S{opt-t} The \i\c{-t} option: Enable TASM Compatibility Mode
+
+NASM includes a limited form of compatibility with Borland's TASM.
+When NASM's -t option is used, the following changes are made:
+
+\b local labels may be prefixed with \c{@@} instead of \c{.}
+
+\b TASM-style response files beginning with \c{@} may be specified on
+the command line. This is different from the \c{-@resp} style that NASM
+natively supports.
+
+\b size override is supported within brackets. In TASM compatible mode,
+a size override inside square brackets changes the size of the operand,
+and not the address type of the operand as it does in NASM syntax. E.g.
+\c{mov eax,[DWORD val]} is valid syntax in TASM compatibility mode.
+Note that you lose the ability to override the default address type for
+the instruction.
+
+\b \c{%arg} preprocessor directive is supported which is similar to
+TASM's ARG directive.
+
+\b \c{%local} preprocessor directive
+
+\b \c{%stacksize} preprocessor directive
+
+\b unprefixed forms of some directives supported (arg, elif, else,
+endif, if, ifdef, ifdifi, ifndef, include, local)
+
+\b more...
+
+For more information on the directives, see the section on TASM
+Compatiblity preprocessor directives in \k{tasmcompat}.
+
\S{opt-w} The \i\c{-w} Option: Enable or Disable Assembly \i{Warnings}
NASM can observe many conditions during the course of assembly which
@@ -2585,6 +2618,111 @@ boundary, for example, is a waste of effort. Again, NASM does not
check that the section's alignment characteristics are sensible for
the use of \c{ALIGN} or \c{ALIGNB}.
+\H{tasmcompat} \i{TASM Compatible Preprocessor Directives}
+
+The following preprocessor directives may only be used when TASM
+compatibility is turned on using the \c{-t} command line switch
+(This switch is described in \k{opt-t}.)
+
+\b\c{%arg} (see \k{arg})
+
+\b\c{%stacksize} (see \k{stacksize})
+
+\b\c{%local} (see \k{local})
+
+\S{arg} \i\c{%arg} Directive
+
+The \c{%arg} directive is used to simplify the handling of
+parameters passed on the stack. Stack based parameter passing
+is used by many high level languages, including C, C++ and Pascal.
+
+While NASM comes with macros which attempt to duplicate this
+functionality (see \k{16cmacro}), the syntax is not particularly
+convenient to use and is not TASM compatible. Here is an example
+which shows the use of \c{%arg} without any external macros:
+
+\c some_function:
+\c %push mycontext ; save the current context
+\c %stacksize large ; tell NASM to use bp
+\c %arg i:word, j_ptr:word
+\c mov ax,[i]
+\c mov bx,[j_ptr]
+\c add ax,[bx]
+\c ret
+\c %pop ; restore original context
+
+This is similar to the procedure defined in \k{16cmacro} and adds
+the value in i to the value pointed to by j_ptr and returns the
+sum in the ax register. See \k{pushpop} for an explanation of
+\c{push} and \c{pop} and the use of context stacks.
+
+\S{stacksize} \i\c{%stacksize} Directive
+
+The \c{%stacksize} directive is used in conjunction with the
+\c{%arg} (see \k{arg}) and the \c{%local} (see \k{local}) directives.
+It tells NASM the default size to use for subsequent \c{%arg} and
+\c{%local} directives. The \c{%stacksize} directive takes one
+required argument which is one of \c{flat}, \c{large} or \c{small}.
+
+\c %stacksize flat
+
+This form causes NASM to use stack-based parameter addressing
+relative to \c{ebp} and it assumes that a near form of call was used
+to get to this label (i.e. that \c{eip} is on the stack).
+
+\c %stacksize large
+
+This form uses \c{bp} to do stack-based parameter addressing and
+assumes that a far form of call was used to get to this address
+(i.e. that \c{ip} and \c{cs} are on the stack).
+
+\c %stacksize small
+
+This form also uses \c{bp} to address stack parameters, but it is
+different from \c{large} because it also assumes that the old value
+of bp is pushed onto the stack (i.e. it expects an \c{ENTER}
+instruction). In other words, it expects that \c{bp}, \c{ip} and
+\c{cs} are on the top of the stack, underneath any local space which
+may have been allocated by \c{ENTER}. This form is probably most
+useful when used in combination with the \c{%local} directive
+(see \k{local}).
+
+\S{local} \i\c{%local} Directive
+
+The \c{%local} directive is used to simplify the use of local
+temporary stack variables allocated in a stack frame. Automatic
+local variables in C are an example of this kind of variable. The
+\c{%local} directive is most useful when used with the \c{%stacksize}
+(see \k{stacksize} and is also compatible with the \c{%arg} directive
+(see \k{arg}). It allows simplified reference to variables on the
+stack which have been allocated typically by using the \c{ENTER}
+instruction (see \k{insENTER} for a description of that instruction).
+An example of its use is the following:
+
+\c silly_swap:
+\c %push mycontext ; save the current context
+\c %stacksize small ; tell NASM to use bp
+\c %assign %$localsize 0 ; see text for explanation
+\c %local old_ax:word, old_dx:word
+\c enter %$localsize,0 ; see text for explanation
+\c mov [old_ax],ax ; swap ax & bx
+\c mov [old_dx],dx ; and swap dx & cx
+\c mov ax,bx
+\c mov dx,cx
+\c mov bx,[old_ax]
+\c mov cx,[old_dx]
+\c leave ; restore old bp
+\c ret ;
+\c %pop ; restore original context
+
+The \c{%$localsize} variable is used internally by the
+\c{%local} directive and \e{must} be defined within the
+current context before the \c{%local} directive may be used.
+Failure to do so will result in one expression syntax error for
+each \c{%local} variable declared. It then may be used in
+the construction of an appropriately sized ENTER instruction
+as shown in the example.
+
\C{directive} \i{Assembler Directives}
NASM, though it attempts to avoid the bureaucracy of assemblers like
@@ -4173,6 +4311,9 @@ directory, is a file \c{c16.mac} of macros. It defines three macros:
used for C-style procedure definitions, and they automate a lot of
the work involved in keeping track of the calling convention.
+(An alternative, TASM compatible form of \c{arg} is also now built
+into NASM's preprocessor. See \k{tasmcompat} for details.)
+
An example of an assembly function using the macro set is given
here:
@@ -5371,7 +5512,7 @@ The encodings for the various classes of register are:
\b \i{Segment registers}: \c{ES} is 0, \c{CS} is 1, \c{SS} is 2, \c{DS}
is 3, \c{FS} is 4, and \c{GS} is 5.
-\b \I{floating-point, registers}{Floating-point registers}: \c{ST0}
+\b \I{floating-point, registers}Floating-point registers: \c{ST0}
is 0, \c{ST1} is 1, \c{ST2} is 2, \c{ST3} is 3, \c{ST4} is 4,
\c{ST5} is 5, \c{ST6} is 6, and \c{ST7} is 7.
@@ -6296,7 +6437,7 @@ of both their operands.
\c DIVSS xmmreg,memory ; F3,0F,5E,/r [KATMAI,SSE]
\c DIVSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
-c\{DIVSS}-The DIVSS instructions divide the lowest SP FP numbers
+\c{DIVSS}-The DIVSS instructions divide the lowest SP FP numbers
of both operands; the upper three fields are passed through from xmm1.
@@ -6404,7 +6545,7 @@ register stack.
\c{FCHS} negates the number in \c{ST0}: negative numbers become
positive, and vice versa.
-\H{insFCLEX} \i\c{FCLEX}, \{FNCLEX}: Clear Floating-Point Exceptions
+\H{insFCLEX} \i\c{FCLEX}, \c{FNCLEX}: Clear Floating-Point Exceptions
\c FCLEX ; 9B DB E2 [8086,FPU]
\c FNCLEX ; DB E2 [8086,FPU]
@@ -7964,7 +8105,7 @@ operation on the 64-bit MMX registers.
\c OUT DX,AX ; o16 EF [8086]
\c OUT DX,EAX ; o32 EF [386]
-\c{IN} writes the contents of the given source register to the
+\c{OUT} writes the contents of the given source register to the
specified I/O port. The port number may be specified as an immediate
value if it is between 0 and 255, and otherwise must be stored in
\c{DX}. See also \c{IN} (\k{insIN}).
diff --git a/insns.dat b/insns.dat
index cc678c5..e167a77 100644
--- a/insns.dat
+++ b/insns.dat
@@ -6,7 +6,7 @@
; redistributable under the licence given in the file "Licence"
; distributed in the NASM archive.
;
-; Format of file: all four fields must be present on every functional
+; Format of file: All four fields must be present on every functional
; line. Hence `void' for no-operand instructions, and `\0' for such
; as EQU. If the last three fields are all `ignore', no action is
; taken except to register the opcode as being present.
@@ -37,14 +37,14 @@ ADC rm16,imm8 \320\300\1\x83\202\15 8086
ADC rm32,imm8 \321\300\1\x83\202\15 386
ADC reg_al,imm \1\x14\21 8086,SM
ADC reg_ax,imm \320\1\x15\31 8086,SM
-ADC reg_eax,sbyte \321\1\x83\202\15 386,ND
+ADC reg_eax,sbyte \321\1\x83\202\15 386,ND
ADC reg_eax,imm \321\1\x15\41 386,SM
ADC rm8,imm \300\1\x80\202\21 8086,SM
-ADC rm16,imm \320\300\134\1\x81\202\131 8086,SM,ND
-ADC rm32,imm \321\300\144\1\x81\202\141 386,SM,ND
+ADC rm16,imm \320\300\134\1\x81\202\131 8086,SM,ND
+ADC rm32,imm \321\300\144\1\x81\202\141 386,SM,ND
ADC mem,imm8 \300\1\x80\202\21 8086,SM
-ADC mem,imm16 \320\300\134\1\x81\202\131 8086,SM,ND
-ADC mem,imm32 \321\300\144\1\x81\202\141 386,SM,ND
+ADC mem,imm16 \320\300\134\1\x81\202\131 8086,SM,ND
+ADC mem,imm32 \321\300\144\1\x81\202\141 386,SM,ND
ADD mem,reg8 \300\17\101 8086,SM
ADD reg8,reg8 \300\17\101 8086
ADD mem,reg16 \320\300\1\x01\101 8086,SM
@@ -61,14 +61,14 @@ ADD rm16,imm8 \320\300\1\x83\200\15 8086
ADD rm32,imm8 \321\300\1\x83\200\15 386
ADD reg_al,imm \1\x04\21 8086,SM
ADD reg_ax,imm \320\1\x05\31 8086,SM
-ADD reg_eax,sbyte \321\1\x83\200\15 386,ND
+ADD reg_eax,sbyte \321\1\x83\200\15 386,ND
ADD reg_eax,imm \321\1\x05\41 386,SM
ADD rm8,imm \300\1\x80\200\21 8086,SM
-ADD rm16,imm \320\300\134\1\x81\200\131 8086,SM,ND
-ADD rm32,imm \321\300\144\1\x81\200\141 386,SM,ND
+ADD rm16,imm \320\300\134\1\x81\200\131 8086,SM,ND
+ADD rm32,imm \321\300\144\1\x81\200\141 386,SM,ND
ADD mem,imm8 \300\1\x80\200\21 8086,SM
-ADD mem,imm16 \320\300\134\1\x81\200\131 8086,SM,ND
-ADD mem,imm32 \321\300\144\1\x81\200\141 386,SM,ND
+ADD mem,imm16 \320\300\134\1\x81\200\131 8086,SM,ND
+ADD mem,imm32 \321\300\144\1\x81\200\141 386,SM,ND
AND mem,reg8 \300\1\x20\101 8086,SM
AND reg8,reg8 \300\1\x20\101 8086
AND mem,reg16 \320\300\1\x21\101 8086,SM
@@ -85,14 +85,14 @@ AND rm16,imm8 \320\300\1\x83\204\15 8086
AND rm32,imm8 \321\300\1\x83\204\15 386
AND reg_al,imm \1\x24\21 8086,SM
AND reg_ax,imm \320\1\x25\31 8086,SM
-AND reg_eax,sbyte \321\1\x83\204\15 386,ND
+AND reg_eax,sbyte \321\1\x83\204\15 386,ND
AND reg_eax,imm \321\1\x25\41 386,SM
AND rm8,imm \300\1\x80\204\21 8086,SM
-AND rm16,imm \320\300\134\1\x81\204\131 8086,SM,ND
-AND rm32,imm \321\300\144\1\x81\204\141 386,SM,ND
+AND rm16,imm \320\300\134\1\x81\204\131 8086,SM,ND
+AND rm32,imm \321\300\144\1\x81\204\141 386,SM,ND
AND mem,imm8 \300\1\x80\204\21 8086,SM
-AND mem,imm16 \320\300\134\1\x81\204\131 8086,SM,ND
-AND mem,imm32 \321\300\144\1\x81\204\141 386,SM,ND
+AND mem,imm16 \320\300\134\1\x81\204\131 8086,SM,ND
+AND mem,imm32 \321\300\144\1\x81\204\141 386,SM,ND
ARPL mem,reg16 \300\1\x63\101 286,PROT,SM
ARPL reg16,reg16 \300\1\x63\101 286,PROT
BOUND reg16,mem \320\301\1\x62\110 186
@@ -178,14 +178,14 @@ CMP rm16,imm8 \320\300\1\x83\207\15 8086
CMP rm32,imm8 \321\300\1\x83\207\15 386
CMP reg_al,imm \1\x3C\21 8086,SM
CMP reg_ax,imm \320\1\x3D\31 8086,SM
-CMP reg_eax,sbyte \321\1\x83\207\15 386,ND
+CMP reg_eax,sbyte \321\1\x83\207\15 386,ND
CMP reg_eax,imm \321\1\x3D\41 386,SM
CMP rm8,imm \300\1\x80\207\21 8086,SM
-CMP rm16,imm \320\300\134\1\x81\207\131 8086,SM,ND
-CMP rm32,imm \321\300\144\1\x81\207\141 386,SM,ND
+CMP rm16,imm \320\300\134\1\x81\207\131 8086,SM,ND
+CMP rm32,imm \321\300\144\1\x81\207\141 386,SM,ND
CMP mem,imm8 \300\1\x80\207\21 8086,SM
-CMP mem,imm16 \320\300\134\1\x81\207\131 8086,SM,ND
-CMP mem,imm32 \321\300\144\1\x81\207\141 386,SM,ND
+CMP mem,imm16 \320\300\134\1\x81\207\131 8086,SM,ND
+CMP mem,imm32 \321\300\144\1\x81\207\141 386,SM,ND
CMPSB void \332\1\xA6 8086
CMPSD void \332\321\1\xA7 386
CMPSW void \332\320\1\xA7 8086
@@ -424,16 +424,16 @@ IMUL reg32,mem \321\301\2\x0F\xAF\110 386,SM
IMUL reg32,reg32 \321\2\x0F\xAF\110 386
IMUL reg16,mem,imm8 \320\301\1\x6B\110\16 186,SM
IMUL reg16,reg16,imm8 \320\301\1\x6B\110\16 186
-IMUL reg16,mem,imm \320\301\135\1\x69\110\132 186,SM
-IMUL reg16,reg16,imm \320\135\1\x69\110\132 186,SM
+IMUL reg16,mem,imm \320\301\135\1\x69\110\132 186,SM
+IMUL reg16,reg16,imm \320\135\1\x69\110\132 186,SM
IMUL reg32,mem,imm8 \321\301\1\x6B\110\16 386,SM
IMUL reg32,reg32,imm8 \321\1\x6B\110\16 386
-IMUL reg32,mem,imm \321\301\145\1\x69\110\142 386,SM
-IMUL reg32,reg32,imm \321\145\1\x69\110\142 386,SM
+IMUL reg32,mem,imm \321\301\145\1\x69\110\142 386,SM
+IMUL reg32,reg32,imm \321\145\1\x69\110\142 386,SM
IMUL reg16,imm8 \320\1\x6B\100\15 186
-IMUL reg16,imm \320\134\1\x69\100\131 186,SM
+IMUL reg16,imm \320\134\1\x69\100\131 186,SM
IMUL reg32,imm8 \321\1\x6B\100\15 386
-IMUL reg32,imm \321\144\1\x69\100\141 386,SM
+IMUL reg32,imm \321\144\1\x69\100\141 386,SM
IN reg_al,imm \1\xE4\25 8086,SB
IN reg_ax,imm \320\1\xE5\25 8086,SB
IN reg_eax,imm \321\1\xE5\25 386,SB
@@ -463,7 +463,7 @@ IRETW void \320\1\xCF 8086
JCXZ imm \310\1\xE3\50 8086
JECXZ imm \311\1\xE3\50 386
JMP imm|short \1\xEB\50 8086
-JMP imm \370\1\xEB\50 8086,ND
+JMP imm \370\1\xEB\50 8086,ND
JMP imm \322\1\xE9\64 8086
JMP imm|near \322\1\xE9\64 8086,ND
JMP imm|far \322\1\xEA\34\37 8086,ND
@@ -542,21 +542,21 @@ LSS reg32,mem \321\301\2\x0F\xB2\110 386
LTR mem \300\1\x0F\17\203 286,PROT,PRIV
LTR mem16 \300\1\x0F\17\203 286,PROT,PRIV
LTR reg16 \300\1\x0F\17\203 286,PROT,PRIV
-MOV mem,reg_cs \320\300\1\x8C\201 8086,SM
-MOV mem,reg_dess \320\300\1\x8C\101 8086,SM
-MOV mem,reg_fsgs \320\300\1\x8C\101 386,SM
+MOV mem,reg_cs \300\1\x8C\201 8086,SM
+MOV mem,reg_dess \300\1\x8C\101 8086,SM
+MOV mem,reg_fsgs \300\1\x8C\101 386,SM
MOV reg16,reg_cs \320\300\1\x8C\201 8086
MOV reg16,reg_dess \320\300\1\x8C\101 8086
MOV reg16,reg_fsgs \320\300\1\x8C\101 386
-MOV rm32,reg_cs \321\300\1\x8C\201 8086
-MOV rm32,reg_dess \321\300\1\x8C\101 8086
-MOV rm32,reg_fsgs \321\300\1\x8C\101 386
-MOV reg_dess,mem \320\301\1\x8E\110 8086,SM
-MOV reg_fsgs,mem \320\301\1\x8E\110 386,SM
-MOV reg_dess,reg16 \320\301\1\x8E\110 8086
-MOV reg_fsgs,reg16 \320\301\1\x8E\110 386
-MOV reg_dess,rm32 \321\301\1\x8E\110 8086
-MOV reg_fsgs,rm32 \321\301\1\x8E\110 386
+MOV reg32,reg_cs \321\300\1\x8C\201 8086
+MOV reg32,reg_dess \321\300\1\x8C\101 8086
+MOV reg32,reg_fsgs \321\300\1\x8C\101 386
+MOV reg_dess,mem \301\1\x8E\110 8086,SM
+MOV reg_fsgs,mem \301\1\x8E\110 386,SM
+MOV reg_dess,reg16 \301\1\x8E\110 8086
+MOV reg_fsgs,reg16 \301\1\x8E\110 386
+MOV reg_dess,reg32 \301\1\x8E\110 8086
+MOV reg_fsgs,reg32 \301\1\x8E\110 386
MOV reg_al,mem_offs \301\1\xA0\35 8086,SM
MOV reg_ax,mem_offs \301\320\1\xA1\35 8086,SM
MOV reg_eax,mem_offs \301\321\1\xA1\35 386,SM
@@ -637,14 +637,14 @@ OR rm16,imm8 \320\300\1\x83\201\15 8086
OR rm32,imm8 \321\300\1\x83\201\15 386
OR reg_al,imm \1\x0C\21 8086,SM
OR reg_ax,imm \320\1\x0D\31 8086,SM
-OR reg_eax,sbyte \321\1\x83\201\15 386,ND
+OR reg_eax,sbyte \321\1\x83\201\15 386,ND
OR reg_eax,imm \321\1\x0D\41 386,SM
OR rm8,imm \300\1\x80\201\21 8086,SM
-OR rm16,imm \320\300\134\1\x81\201\131 8086,SM,ND
-OR rm32,imm \321\300\144\1\x81\201\141 386,SM,ND
+OR rm16,imm \320\300\134\1\x81\201\131 8086,SM,ND
+OR rm32,imm \321\300\144\1\x81\201\141 386,SM,ND
OR mem,imm8 \300\1\x80\201\21 8086,SM
-OR mem,imm16 \320\300\134\1\x81\201\131 8086,SM,ND
-OR mem,imm32 \321\300\144\1\x81\201\141 386,SM,ND
+OR mem,imm16 \320\300\134\1\x81\201\131 8086,SM,ND
+OR mem,imm32 \321\300\144\1\x81\201\141 386,SM,ND
OUT imm,reg_al \1\xE6\24 8086,SB
OUT imm,reg_ax \320\1\xE7\24 8086,SB
OUT imm,reg_eax \321\1\xE7\24 386,SB
@@ -888,8 +888,8 @@ ROR rm16,imm \320\300\1\xC1\201\25 186,SB
ROR rm32,unity \321\300\1\xD1\201 386
ROR rm32,reg_cl \321\300\1\xD3\201 386
ROR rm32,imm \321\300\1\xC1\201\25 386,SB
-RSDC reg_sreg,mem80 \301\2\x0F\x79\110 486,CYRIX,SMM
-RSLDT mem80 \300\2\x0F\x7B\200 486,CYRIX,SMM
+RSDC reg_sreg,mem80 \301\2\x0F\x79\110 486,CYRIX,SMM
+RSLDT mem80 \300\2\x0F\x7B\200 486,CYRIX,SMM
RSM void \2\x0F\xAA PENT,SMM
RSTS mem80 \300\2\x0F\x7D\200 486,CYRIX,SMM
SAHF void \1\x9E 8086
@@ -928,14 +928,14 @@ SBB rm16,imm8 \320\300\1\x83\203\15 8086
SBB rm32,imm8 \321\300\1\x83\203\15 8086
SBB reg_al,imm \1\x1C\21 8086,SM
SBB reg_ax,imm \320\1\x1D\31 8086,SM
-SBB reg_eax,sbyte \321\1\x83\203\15 386,ND
+SBB reg_eax,sbyte \321\1\x83\203\15 386,ND
SBB reg_eax,imm \321\1\x1D\41 386,SM
SBB rm8,imm \300\1\x80\203\21 8086,SM
-SBB rm16,imm \320\300\134\1\x81\203\131 8086,SM,ND
-SBB rm32,imm \321\300\144\1\x81\203\141 386,SM,ND
+SBB rm16,imm \320\300\134\1\x81\203\131 8086,SM,ND
+SBB rm32,imm \321\300\144\1\x81\203\141 386,SM,ND
SBB mem,imm8 \300\1\x80\203\21 8086,SM
-SBB mem,imm16 \320\300\134\1\x81\203\131 8086,SM,ND
-SBB mem,imm32 \321\300\144\1\x81\203\141 386,SM,ND
+SBB mem,imm16 \320\300\134\1\x81\203\131 8086,SM,ND
+SBB mem,imm32 \321\300\144\1\x81\203\141 386,SM,ND
SCASB void \332\1\xAE 8086
SCASD void \332\321\1\xAF 386
SCASW void \332\320\1\xAF 8086
@@ -1010,21 +1010,21 @@ SUB rm16,imm8 \320\300\1\x83\205\15 8086
SUB rm32,imm8 \321\300\1\x83\205\15 386
SUB reg_al,imm \1\x2C\21 8086,SM
SUB reg_ax,imm \320\1\x2D\31 8086,SM
-SUB reg_eax,sbyte \321\1\x83\205\15 386,ND
+SUB reg_eax,sbyte \321\1\x83\205\15 386,ND
SUB reg_eax,imm \321\1\x2D\41 386,SM
SUB rm8,imm \300\1\x80\205\21 8086,SM
-SUB rm16,imm \320\300\134\1\x81\205\131 8086,SM,ND
-SUB rm32,imm \321\300\144\1\x81\205\141 386,SM,ND
+SUB rm16,imm \320\300\134\1\x81\205\131 8086,SM,ND
+SUB rm32,imm \321\300\144\1\x81\205\141 386,SM,ND
SUB mem,imm8 \300\1\x80\205\21 8086,SM
-SUB mem,imm16 \320\300\134\1\x81\205\131 8086,SM,ND
-SUB mem,imm32 \321\300\144\1\x81\205\141 386,SM,ND
-SVDC mem80,reg_sreg \300\2\x0F\x78\101 486,CYRIX,SMM
+SUB mem,imm16 \320\300\134\1\x81\205\131 8086,SM,ND
+SUB mem,imm32 \321\300\144\1\x81\205\141 386,SM,ND
+SVDC mem80,reg_sreg \300\2\x0F\x78\101 486,CYRIX,SMM
SVLDT mem80 \300\2\x0F\x7A\200 486,CYRIX,SMM
SVTS mem80 \300\2\x0F\x7C\200 486,CYRIX,SMM
SYSCALL void \2\x0F\x05 P6,AMD
SYSENTER void \2\x0F\x34 P6
SYSEXIT void \2\x0F\x36 P6,PRIV
-SYSRET void \2\x0F\x07 P6,PRIV,AMD
+SYSRET void \2\x0F\x07 P6,PRIV,AMD
TEST mem,reg8 \300\1\x84\101 8086,SM
TEST reg8,reg8 \300\1\x84\101 8086
TEST mem,reg16 \320\300\1\x85\101 8086,SM
@@ -1112,14 +1112,14 @@ XOR rm16,imm8 \320\300\1\x83\206\15 8086
XOR rm32,imm8 \321\300\1\x83\206\15 386
XOR reg_al,imm \1\x34\21 8086,SM
XOR reg_ax,imm \320\1\x35\31 8086,SM
-XOR reg_eax,sbyte \321\1\x83\206\15 386,ND
+XOR reg_eax,sbyte \321\1\x83\206\15 386,ND
XOR reg_eax,imm \321\1\x35\41 386,SM
XOR rm8,imm \300\1\x80\206\21 8086,SM
-XOR rm16,imm \320\300\134\1\x81\206\131 8086,SM,ND
-XOR rm32,imm \321\300\144\1\x81\206\141 386,SM,ND
+XOR rm16,imm \320\300\134\1\x81\206\131 8086,SM,ND
+XOR rm32,imm \321\300\144\1\x81\206\141 386,SM,ND
XOR mem,imm8 \300\1\x80\206\21 8086,SM
-XOR mem,imm16 \320\300\134\1\x81\206\131 8086,SM,ND
-XOR mem,imm32 \321\300\144\1\x81\206\141 386,SM,ND
+XOR mem,imm16 \320\300\134\1\x81\206\131 8086,SM,ND
+XOR mem,imm32 \321\300\144\1\x81\206\141 386,SM,ND
CMOVcc reg16,mem \320\301\1\x0F\330\x40\110 P6,SM
CMOVcc reg16,reg16 \320\301\1\x0F\330\x40\110 P6
CMOVcc reg32,mem \321\301\1\x0F\330\x40\110 P6,SM
@@ -1128,9 +1128,9 @@ Jcc imm|near \322\1\x0F\330\x80\64 386
Jcc imm16|near \320\1\x0F\330\x80\64 386
Jcc imm32|near \321\1\x0F\330\x80\64 386
Jcc imm|short \330\x70\50 8086,ND
-Jcc imm \370\330\x70\50 8086,ND
-Jcc imm \1\x0F\330\x80\64 386,ND
-Jcc imm \330\x71\373\1\xE9\64 8086,ND
+Jcc imm \370\330\x70\50 8086,ND
+Jcc imm \1\x0F\330\x80\64 386,ND
+Jcc imm \330\x71\373\1\xE9\64 8086,ND
Jcc imm \330\x70\50 8086
SETcc mem \300\1\x0F\330\x90\200 386,SB
SETcc reg8 \300\1\x0F\330\x90\200 386
@@ -1177,11 +1177,11 @@ CMPUNORDPS xmmreg,xmmreg \331\2\x0F\xC2\110\1\x03 KATMAI,S
CMPUNORDSS xmmreg,mem \301\333\2\x0F\xC2\110\1\x03 KATMAI,SSE
CMPUNORDSS xmmreg,xmmreg \333\2\x0F\xC2\110\1\x03 KATMAI,SSE
; CMPPS/CMPSS must come after the specific ops; that way the disassembler will find the
-; specific ops first and only disassemble illegal ones as cmpps.
-CMPPS xmmreg,mem,imm \301\331\2\x0F\xC2\110\22 KATMAI,SSE,SB,AR2
-CMPPS xmmreg,xmmreg,imm \331\2\x0F\xC2\110\22 KATMAI,SSE,SB,AR2
-CMPSS xmmreg,mem,imm \301\333\2\x0F\xC2\110\22 KATMAI,SSE,SB,AR2
-CMPSS xmmreg,xmmreg,imm \333\2\x0F\xC2\110\22 KATMAI,SSE,SB,AR2
+; specific ops first and only disassemble illegal ones as cmpps/cmpss.
+CMPPS xmmreg,mem,imm \301\331\2\x0F\xC2\110\26 KATMAI,SSE,SB,AR2
+CMPPS xmmreg,xmmreg,imm \331\2\x0F\xC2\110\26 KATMAI,SSE,SB,AR2
+CMPSS xmmreg,mem,imm \301\333\2\x0F\xC2\110\26 KATMAI,SSE,SB,AR2
+CMPSS xmmreg,xmmreg,imm \333\2\x0F\xC2\110\26 KATMAI,SSE,SB,AR2
COMISS xmmreg,mem \301\2\x0F\x2F\110 KATMAI,SSE
COMISS xmmreg,xmmreg \2\x0F\x2F\110 KATMAI,SSE
CVTPI2PS xmmreg,mem \301\331\2\x0F\x2A\110 KATMAI,SSE,MMX
@@ -1222,7 +1222,7 @@ MOVLPS mem,xmmreg \300\2\x0F\x13\101 KATMAI,S
MOVLPS xmmreg,xmmreg \2\x0F\x12\101 KATMAI,SSE,ND
MOVHLPS xmmreg,xmmreg \2\x0F\x12\110 KATMAI,SSE
MOVMSKPS reg32,xmmreg \2\x0F\x50\110 KATMAI,SSE
-MOVNTPS mem,xmmreg \2\x0F\x2B\101 KATMAI,SSE
+MOVNTPS mem,xmmreg \300\2\x0F\x2B\101 KATMAI,SSE
MOVSS xmmreg,mem \301\333\2\x0F\x10\110 KATMAI,SSE
MOVSS mem,xmmreg \300\333\2\x0F\x11\101 KATMAI,SSE
MOVSS xmmreg,xmmreg \333\2\x0F\x10\110 KATMAI,SSE
@@ -1245,8 +1245,8 @@ RSQRTPS xmmreg,mem \301\331\2\x0F\x52\110 KATMAI,S
RSQRTPS xmmreg,xmmreg \331\2\x0F\x52\110 KATMAI,SSE
RSQRTSS xmmreg,mem \301\333\2\x0F\x52\110 KATMAI,SSE
RSQRTSS xmmreg,xmmreg \333\2\x0F\x52\110 KATMAI,SSE
-SHUFPS xmmreg,mem,imm \301\2\x0F\xC6\110\22 KATMAI,SSE,SB,AR2
-SHUFPS xmmreg,xmmreg,imm \2\x0F\xC6\110\22 KATMAI,SSE,SB,AR2
+SHUFPS xmmreg,mem,imm \301\2\x0F\xC6\110\26 KATMAI,SSE,SB,AR2
+SHUFPS xmmreg,xmmreg,imm \2\x0F\xC6\110\26 KATMAI,SSE,SB,AR2
SQRTPS xmmreg,mem \301\331\2\x0F\x51\110 KATMAI,SSE
SQRTPS xmmreg,xmmreg \331\2\x0F\x51\110 KATMAI,SSE
SQRTSS xmmreg,mem \301\333\2\x0F\x51\110 KATMAI,SSE
@@ -1265,11 +1265,11 @@ UNPCKLPS xmmreg,xmmreg \2\x0F\x14\110 KATMAI,S
XORPS xmmreg,mem \301\2\x0F\x57\110 KATMAI,SSE
XORPS xmmreg,xmmreg \2\x0F\x57\110 KATMAI,SSE
-; Introduced in Dechutes but necessary for SSE support
+; Introduced in Deschutes but necessary for SSE support
FXRSTOR mem \300\2\x0F\xAE\201 P6,SSE,FPU
FXSAVE mem \300\2\x0F\xAE\200 P6,SSE,FPU
-; These instructions aren't SSE-specific; they are generic memory operations
+; These instructions are not SSE-specific; they are generic memory operations
; and work even if CR4.OSFXFR == 0
PREFETCHNTA mem \300\2\x0F\x18\200 KATMAI
PREFETCHT0 mem \300\2\x0F\x18\201 KATMAI
@@ -1278,307 +1278,351 @@ PREFETCHT2 mem \300\2\x0F\x18\203 KATMAI
SFENCE void \3\x0F\xAE\xF8 KATMAI
; New MMX instructions introduced in Katmai
-MASKMOVQ mmxreg,mmxreg \2\x0F\xF7\110 KATMAI,MMX
-MOVNTQ mem,mmxreg \2\x0F\xE7\101 KATMAI,MMX,SM
-PAVGB mmxreg,mmxreg \2\x0F\xE0\110 KATMAI,MMX
-PAVGB mmxreg,mem \301\2\x0F\xE0\110 KATMAI,MMX,SM
-PAVGW mmxreg,mmxreg \2\x0F\xE3\110 KATMAI,MMX
-PAVGW mmxreg,mem \301\2\x0F\xE3\110 KATMAI,MMX,SM
-PEXTRW reg32,mmxreg,imm \2\x0F\xC5\110\22 KATMAI,MMX,SB,AR2
+MASKMOVQ mmxreg,mmxreg \2\x0F\xF7\110 KATMAI,MMX
+MOVNTQ mem,mmxreg \300\2\x0F\xE7\101 KATMAI,MMX,SM
+PAVGB mmxreg,mmxreg \2\x0F\xE0\110 KATMAI,MMX
+PAVGB mmxreg,mem \301\2\x0F\xE0\110 KATMAI,MMX,SM
+PAVGW mmxreg,mmxreg \2\x0F\xE3\110 KATMAI,MMX
+PAVGW mmxreg,mem \301\2\x0F\xE3\110 KATMAI,MMX,SM
+PEXTRW reg32,mmxreg,imm \2\x0F\xC5\110\26 KATMAI,MMX,SB,AR2
; PINSRW is documented as using a reg32, but it's really using only 16 bit
; -- accept either, but be truthful in disassembly
-PINSRW mmxreg,reg16,imm \2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2
-PINSRW mmxreg,reg32,imm \2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2,ND
-PINSRW mmxreg,mem,imm \301\2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2
-PINSRW mmxreg,mem16,imm \301\2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2,ND
-PMAXSW mmxreg,mmxreg \2\x0F\xEE\110 KATMAI,MMX
-PMAXSW mmxreg,mem \301\2\x0F\xEE\110 KATMAI,MMX,SM
-PMAXUB mmxreg,mmxreg \2\x0F\xDE\110 KATMAI,MMX
-PMAXUB mmxreg,mem \301\2\x0F\xDE\110 KATMAI,MMX,SM
-PMINSW mmxreg,mmxreg \2\x0F\xEA\110 KATMAI,MMX
-PMINSW mmxreg,mem \301\2\x0F\xEA\110 KATMAI,MMX,SM
-PMINUB mmxreg,mmxreg \2\x0F\xDA\110 KATMAI,MMX
-PMINUB mmxreg,mem \301\2\x0F\xDA\110 KATMAI,MMX,SM
-PMOVMSKB reg32,mmxreg \2\x0F\xD7\110 KATMAI,MMX
-PMULHUW mmxreg,mmxreg \2\x0F\xE4\110 KATMAI,MMX
-PMULHUW mmxreg,mem \301\2\x0F\xE4\110 KATMAI,MMX,SM
-PSADBW mmxreg,mmxreg \2\x0F\xF6\110 KATMAI,MMX
-PSADBW mmxreg,mem \301\2\x0F\xF6\110 KATMAI,MMX,SM
-PSHUFW mmxreg,mmxreg,imm \2\x0F\x70\110\22 KATMAI,MMX,SB,AR2
-PSHUFW mmxreg,mem,imm \301\2\x0F\x70\110\22 KATMAI,MMX,SM2,SB,AR2
+PINSRW mmxreg,reg16,imm \2\x0F\xC4\110\26 KATMAI,MMX,SB,AR2
+PINSRW mmxreg,reg32,imm \2\x0F\xC4\110\26 KATMAI,MMX,SB,AR2,ND
+PINSRW mmxreg,mem,imm \301\2\x0F\xC4\110\26 KATMAI,MMX,SB,AR2
+PINSRW mmxreg,mem16,imm \301\2\x0F\xC4\110\26 KATMAI,MMX,SB,AR2,ND
+PMAXSW mmxreg,mmxreg \2\x0F\xEE\110 KATMAI,MMX
+PMAXSW mmxreg,mem \301\2\x0F\xEE\110 KATMAI,MMX,SM
+PMAXUB mmxreg,mmxreg \2\x0F\xDE\110 KATMAI,MMX
+PMAXUB mmxreg,mem \301\2\x0F\xDE\110 KATMAI,MMX,SM
+PMINSW mmxreg,mmxreg \2\x0F\xEA\110 KATMAI,MMX
+PMINSW mmxreg,mem \301\2\x0F\xEA\110 KATMAI,MMX,SM
+PMINUB mmxreg,mmxreg \2\x0F\xDA\110 KATMAI,MMX
+PMINUB mmxreg,mem \301\2\x0F\xDA\110 KATMAI,MMX,SM
+PMOVMSKB reg32,mmxreg \2\x0F\xD7\110 KATMAI,MMX
+PMULHUW mmxreg,mmxreg \2\x0F\xE4\110 KATMAI,MMX
+PMULHUW mmxreg,mem \301\2\x0F\xE4\110 KATMAI,MMX,SM
+PSADBW mmxreg,mmxreg \2\x0F\xF6\110 KATMAI,MMX
+PSADBW mmxreg,mem \301\2\x0F\xF6\110 KATMAI,MMX,SM
+PSHUFW mmxreg,mmxreg,imm \2\x0F\x70\110\22 KATMAI,MMX,SB,AR2
+PSHUFW mmxreg,mem,imm \301\2\x0F\x70\110\22 KATMAI,MMX,SM2,SB,AR2
-; The five new Athlon instructions
-PF2IW mmxreg,mem \301\2\x0F\x0F\110\01\x1C PENT,3DNOW,SM
-PF2IW mmxreg,mmxreg \2\x0F\x0F\110\01\x1C PENT,3DNOW
-PFNACC mmxreg,mem \301\2\x0F\x0F\110\01\x8A PENT,3DNOW,SM
-PFNACC mmxreg,mmxreg \2\x0F\x0F\110\01\x8A PENT,3DNOW
-PFPNACC mmxreg,mem \301\2\x0F\x0F\110\01\x8E PENT,3DNOW,SM
-PFPNACC mmxreg,mmxreg \2\x0F\x0F\110\01\x8E PENT,3DNOW
-PI2FW mmxreg,mem \301\2\x0F\x0F\110\01\x0C PENT,3DNOW,SM
-PI2FW mmxreg,mmxreg \2\x0F\x0F\110\01\x0C PENT,3DNOW
-PSWAPD mmxreg,mem \301\2\x0F\x0F\110\01\xBB PENT,3DNOW,SM
-PSWAPD mmxreg,mmxreg \2\x0F\x0F\110\01\xBB PENT,3DNOW
+; AMD Enhanced 3DNow! (Athlon) instructions
+PF2IW mmxreg,mem \301\2\x0F\x0F\110\01\x1C PENT,3DNOW,SM
+PF2IW mmxreg,mmxreg \2\x0F\x0F\110\01\x1C PENT,3DNOW
+PFNACC mmxreg,mem \301\2\x0F\x0F\110\01\x8A PENT,3DNOW,SM
+PFNACC mmxreg,mmxreg \2\x0F\x0F\110\01\x8A PENT,3DNOW
+PFPNACC mmxreg,mem \301\2\x0F\x0F\110\01\x8E PENT,3DNOW,SM
+PFPNACC mmxreg,mmxreg \2\x0F\x0F\110\01\x8E PENT,3DNOW
+PI2FW mmxreg,mem \301\2\x0F\x0F\110\01\x0C PENT,3DNOW,SM
+PI2FW mmxreg,mmxreg \2\x0F\x0F\110\01\x0C PENT,3DNOW
+PSWAPD mmxreg,mem \301\2\x0F\x0F\110\01\xBB PENT,3DNOW,SM
+PSWAPD mmxreg,mmxreg \2\x0F\x0F\110\01\xBB PENT,3DNOW
-; Introduced in Willamette
-; opcode parameters assembly range
-MASKMOVDQU xmmreg,xmmreg \3\x66\x0F\xF7 WILLAMETTE
-CLFLUSH mem \2\x0F\xAE WILLAMETTE
-MOVNTDQ xmmreg,mem \3\x66\x0F\xEF WILLAMETTE
-MOVNTI reg32,mem \2\x0F\xC3 WILLAMETTE
-PAUSE void \2\xF3\x90 WILLAMETTE
-LFENCE void \3\x0F\xAE\xF8 WILLAMETTE
-MFENCE void \3\x0F\xAE\xF8 WILLAMETTE
+; Willamette SSE2 Cacheability Instructions
+MASKMOVDQU xmmreg,xmmreg \3\x66\x0F\xF7\110 WILLAMETTE,SSE2
+; CLFLUSH needs its own feature flag implemented one day
+CLFLUSH mem \300\2\x0F\xAE\207 WILLAMETTE,SSE2
+MOVNTDQ mem,xmmreg \300\3\x66\x0F\xE7\101 WILLAMETTE,SSE2,SM
+MOVNTI mem,reg32 \300\2\x0F\xC3\101 WILLAMETTE,SSE2,SM
+MOVNTPD mem,xmmreg \300\3\x66\x0F\x2B\101 WILLAMETTE,SSE2,SM
+PAUSE void \333\1\x90 WILLAMETTE,SSE2
+LFENCE void \3\x0F\xAE\xE8 WILLAMETTE,SSE2
+MFENCE void \3\x0F\xAE\xF0 WILLAMETTE,SSE2
+
+; Willamette MMX instructions (SSE2 SIMD Integer Instructions)
+MOVD xmmreg,reg32 \3\x66\x0F\x6E\110 WILLAMETTE,SSE2
+MOVD reg32,xmmreg \3\x66\x0F\x7E\101 WILLAMETTE,SSE2
+MOVD mem,xmmreg \300\3\x66\x0F\x7E\101 WILLAMETTE,SSE2
+MOVD xmmreg,mem \301\3\x66\x0F\x6E\110 WILLAMETTE,SSE2
+MOVDQA xmmreg,xmmreg \3\x66\x0F\x6F\110 WILLAMETTE,SSE2
+MOVDQA mem,xmmreg \300\3\x66\x0F\x7F\101 WILLAMETTE,SSE2,SM
+MOVDQA xmmreg,mem \301\3\x66\x0F\x6F\110 WILLAMETTE,SSE2,SM
+MOVDQA xmmreg,xmmreg \3\x66\x0F\x7F\110 WILLAMETTE,SSE2
+MOVDQU xmmreg,xmmreg \333\2\x0F\x6F\110 WILLAMETTE,SSE2
+MOVDQU mem,xmmreg \333\300\2\x0F\x7F\101 WILLAMETTE,SSE2,SM
+MOVDQU xmmreg,mem \301\333\2\x0F\x6F\110 WILLAMETTE,SSE2,SM
+MOVDQU xmmreg,xmmreg \333\2\x0F\x7F\110 WILLAMETTE,SSE2
+MOVDQ2Q mmxreg,xmmreg \3\xF2\x0F\xD6\110 WILLAMETTE,SSE2
+MOVQ xmmreg,xmmreg \333\2\x0F\x7E\110 WILLAMETTE,SSE2
+MOVQ xmmreg,xmmreg \3\x66\x0F\xD6\110 WILLAMETTE,SSE2
+MOVQ mem,xmmreg \300\3\x66\x0F\xD6\101 WILLAMETTE,SSE2
+MOVQ xmmreg,mem \301\333\2\x0F\x7E\110 WILLAMETTE,SSE2
+MOVQ2DQ xmmreg,mmxreg \333\2\x0F\xD6\110 WILLAMETTE,SSE2
+PACKSSWB xmmreg,xmmreg \3\x66\x0F\x63\110 WILLAMETTE,SSE2
+PACKSSWB xmmreg,mem \301\3\x66\x0F\x63\110 WILLAMETTE,SSE2,SM
+PACKSSDW xmmreg,xmmreg \3\x66\x0F\x6B\110 WILLAMETTE,SSE2
+PACKSSDW xmmreg,mem \301\3\x66\x0F\x6B\110 WILLAMETTE,SSE2,SM
+PACKUSWB xmmreg,xmmreg \3\x66\x0F\x67\110 WILLAMETTE,SSE2
+PACKUSWB xmmreg,mem \301\3\x66\x0F\x67\110 WILLAMETTE,SSE2,SM
+PADDB xmmreg,xmmreg \3\x66\x0F\xFC\110 WILLAMETTE,SSE2
+PADDB xmmreg,mem \301\3\x66\x0F\xFC\110 WILLAMETTE,SSE2,SM
+PADDW xmmreg,xmmreg \3\x66\x0F\xFD\110 WILLAMETTE,SSE2
+PADDW xmmreg,mem \301\3\x66\x0F\xFD\110 WILLAMETTE,SSE2,SM
+PADDD xmmreg,xmmreg \3\x66\x0F\xFE\110 WILLAMETTE,SSE2
+PADDD xmmreg,mem \301\3\x66\x0F\xFE\110 WILLAMETTE,SSE2,SM
+PADDQ mmxreg,mmxreg \2\x0F\xD4\110 WILLAMETTE,SSE2
+PADDQ mmxreg,mem \301\2\x0F\xD4\110 WILLAMETTE,SSE2,SM
+PADDQ xmmreg,xmmreg \3\x66\x0F\xD4\110 WILLAMETTE,SSE2
+PADDQ xmmreg,mem \301\3\x66\x0F\xD4\110 WILLAMETTE,SSE2,SM
+PADDSB xmmreg,mem \301\3\x66\x0F\xEC\110 WILLAMETTE,SSE2,SM
+PADDSB xmmreg,xmmreg \3\x66\x0F\xEC\110 WILLAMETTE,SSE2
+PADDSW xmmreg,mem \301\3\x66\x0F\xED\110 WILLAMETTE,SSE2,SM
+PADDSW xmmreg,xmmreg \3\x66\x0F\xED\110 WILLAMETTE,SSE2
+PADDUSB xmmreg,mem \301\3\x66\x0F\xDC\110 WILLAMETTE,SSE2,SM
+PADDUSB xmmreg,xmmreg \3\x66\x0F\xDC\110 WILLAMETTE,SSE2
+PADDUSW xmmreg,mem \301\3\x66\x0F\xDD\110 WILLAMETTE,SSE2,SM
+PADDUSW xmmreg,xmmreg \3\x66\x0F\xDD\110 WILLAMETTE,SSE2
+PAND xmmreg,xmmreg \3\x66\x0F\xDB\110 WILLAMETTE,SSE2
+PAND xmmreg,mem \301\3\x66\x0F\xDB\110 WILLAMETTE,SSE2,SM
+PANDN xmmreg,xmmreg \3\x66\x0F\xDF\110 WILLAMETTE,SSE2
+PANDN xmmreg,mem \301\3\x66\x0F\xDF\110 WILLAMETTE,SSE2,SM
+PAVGB xmmreg,xmmreg \3\x66\x0F\xE0\110 WILLAMETTE,SSE2
+PAVGB xmmreg,mem \301\3\x66\x0F\xE0\110 WILLAMETTE,SSE2,SM
+PAVGW xmmreg,xmmreg \3\x66\x0F\xE3\110 WILLAMETTE,SSE2
+PAVGW xmmreg,mem \301\3\x66\x0F\xE3\110 WILLAMETTE,SSE2,SM
+PCMPEQB xmmreg,xmmreg \3\x66\x0F\x74\110 WILLAMETTE,SSE2
+PCMPEQB xmmreg,mem \301\3\x66\x0F\x74\110 WILLAMETTE,SSE2,SM
+PCMPEQW xmmreg,xmmreg \3\x66\x0F\x75\110 WILLAMETTE,SSE2
+PCMPEQW xmmreg,mem \301\3\x66\x0F\x75\110 WILLAMETTE,SSE2,SM
+PCMPEQD xmmreg,xmmreg \3\x66\x0F\x76\110 WILLAMETTE,SSE2
+PCMPEQD xmmreg,mem \301\3\x66\x0F\x76\110 WILLAMETTE,SSE2,SM
+PCMPGTB xmmreg,xmmreg \3\x66\x0F\x64\110 WILLAMETTE,SSE2
+PCMPGTB xmmreg,mem \301\3\x66\x0F\x64\110 WILLAMETTE,SSE2,SM
+PCMPGTW xmmreg,xmmreg \3\x66\x0F\x65\110 WILLAMETTE,SSE2
+PCMPGTW xmmreg,mem \301\3\x66\x0F\x65\110 WILLAMETTE,SSE2,SM
+PCMPGTD xmmreg,xmmreg \3\x66\x0F\x66\110 WILLAMETTE,SSE2
+PCMPGTD xmmreg,mem \301\3\x66\x0F\x66\110 WILLAMETTE,SSE2,SM
+PEXTRW reg32,xmmreg,imm \3\x66\x0F\xC5\110\26 WILLAMETTE,SSE2,SB,AR2
+PINSRW xmmreg,reg16,imm \3\x66\x0F\xC4\110\26 WILLAMETTE,SSE2,SB,AR2
+PINSRW xmmreg,reg32,imm \3\x66\x0F\xC4\110\26 WILLAMETTE,SSE2,SB,AR2,ND
+PINSRW xmmreg,mem,imm \301\3\x66\x0F\xC4\110\26 WILLAMETTE,SSE2,SB,AR2
+PINSRW xmmreg,mem16,imm \301\3\x66\x0F\xC4\110\26 WILLAMETTE,SSE2,SB,AR2,ND
+PMADDWD xmmreg,mem \301\3\x66\x0F\xF5\110 WILLAMETTE,SSE2,SM
+PMADDWD xmmreg,xmmreg \3\x66\x0F\xF5\110 WILLAMETTE,SSE2
+PMAXSW xmmreg,xmmreg \3\x66\x0F\xEE\110 WILLAMETTE,SSE2
+PMAXSW xmmreg,mem \301\3\x66\x0F\xEE\110 WILLAMETTE,SSE2,SM
+PMAXUB xmmreg,xmmreg \3\x66\x0F\xDE\110 WILLAMETTE,SSE2
+PMAXUB xmmreg,mem \301\3\x66\x0F\xDE\110 WILLAMETTE,SSE2,SM
+PMINSW xmmreg,xmmreg \3\x66\x0F\xEA\110 WILLAMETTE,SSE2
+PMINSW xmmreg,mem \301\3\x66\x0F\xEA\110 WILLAMETTE,SSE2,SM
+PMINUB xmmreg,xmmreg \3\x66\x0F\xDA\110 WILLAMETTE,SSE2
+PMINUB xmmreg,mem \301\3\x66\x0F\xDA\110 WILLAMETTE,SSE2,SM
+PMOVMSKB reg32,xmmreg \3\x66\x0F\xD7\110 WILLAMETTE,SSE2
+PMULHUW xmmreg,xmmreg \3\x66\x0F\xE4\110 WILLAMETTE,SSE2
+PMULHUW xmmreg,mem \301\3\x66\x0F\xE4\110 WILLAMETTE,SSE2,SM
+PMULHW xmmreg,mem \301\3\x66\x0F\xE5\110 WILLAMETTE,SSE2,SM
+PMULHW xmmreg,xmmreg \3\x66\x0F\xE5\110 WILLAMETTE,SSE2
+PMULLW xmmreg,mem \301\3\x66\x0F\xD5\110 WILLAMETTE,SSE2,SM
+PMULLW xmmreg,xmmreg \3\x66\x0F\xD5\110 WILLAMETTE,SSE2
+PMULUDQ mmxreg,mmxreg \2\x0F\xF4\110 WILLAMETTE,SSE2
+PMULUDQ mmxreg,mem \301\2\x0F\xF4\110 WILLAMETTE,SSE2,SM
+PMULUDQ xmmreg,xmmreg \3\x66\x0F\xF4\110 WILLAMETTE,SSE2
+PMULUDQ xmmreg,mem \301\3\x66\x0F\xF4\110 WILLAMETTE,SSE2,SM
+POR xmmreg,mem \301\3\x66\x0F\xEB\110 WILLAMETTE,SSE2,SM
+POR xmmreg,xmmreg \3\x66\x0F\xEB\110 WILLAMETTE,SSE2
+PSADBW xmmreg,xmmreg \3\x66\x0F\xF6\110 WILLAMETTE,SSE2
+PSADBW xmmreg,mem \301\3\x66\x0F\xF6\110 WILLAMETTE,SSE2,SM
+PSHUFD xmmreg,xmmreg,imm \3\x66\x0F\x70\110\22 WILLAMETTE,SSE2,SB,AR2
+PSHUFD xmmreg,mem,imm \301\3\x66\x0F\x70\110\22 WILLAMETTE,SSE2,SM2,SB,AR2
+PSHUFHW xmmreg,xmmreg,imm \333\2\x0F\x70\110\22 WILLAMETTE,SSE2,SB,AR2
+PSHUFHW xmmreg,mem,imm \301\333\2\x0F\x70\110\22 WILLAMETTE,SSE2,SM2,SB,AR2
+PSHUFLW xmmreg,xmmreg,imm \3\xF2\x0F\x70\110\22 WILLAMETTE,SSE2,SB,AR2
+PSHUFLW xmmreg,mem,imm \301\3\xF2\x0F\x70\110\22 WILLAMETTE,SSE2,SM2,SB,AR2
+PSLLDQ xmmreg,imm \3\x66\x0F\x73\207\25 WILLAMETTE,SSE2,SB,AR1
+PSLLW xmmreg,mem \301\3\x66\x0F\xF1\110 WILLAMETTE,SSE2,SM
+PSLLW xmmreg,xmmreg \3\x66\x0F\xF1\110 WILLAMETTE,SSE2
+PSLLW xmmreg,imm \3\x66\x0F\x71\206\25 WILLAMETTE,SSE2,SB,AR1
+PSLLD xmmreg,mem \301\3\x66\x0F\xF2\110 WILLAMETTE,SSE2,SM
+PSLLD xmmreg,xmmreg \3\x66\x0F\xF2\110 WILLAMETTE,SSE2
+PSLLD xmmreg,imm \3\x66\x0F\x72\206\25 WILLAMETTE,SSE2,SB,AR1
+PSLLQ xmmreg,mem \301\3\x66\x0F\xF3\110 WILLAMETTE,SSE2,SM
+PSLLQ xmmreg,xmmreg \3\x66\x0F\xF3\110 WILLAMETTE,SSE2
+PSLLQ xmmreg,imm \3\x66\x0F\x73\206\25 WILLAMETTE,SSE2,SB,AR1
+PSRAW xmmreg,mem \301\3\x66\x0F\xE1\110 WILLAMETTE,SSE2,SM
+PSRAW xmmreg,xmmreg \3\x66\x0F\xE1\110 WILLAMETTE,SSE2
+PSRAW xmmreg,imm \3\x66\x0F\x71\204\25 WILLAMETTE,SSE2,SB,AR1
+PSRAD xmmreg,mem \301\3\x66\x0F\xE2\110 WILLAMETTE,SSE2,SM
+PSRAD xmmreg,xmmreg \3\x66\x0F\xE2\110 WILLAMETTE,SSE2
+PSRAD xmmreg,imm \3\x66\x0F\x72\204\25 WILLAMETTE,SSE2,SB,AR1
+PSRLDQ xmmreg,imm \3\x66\x0F\x73\203\25 WILLAMETTE,SSE2,SB,AR1
+PSRLW xmmreg,mem \301\3\x66\x0F\xD1\110 WILLAMETTE,SSE2,SM
+PSRLW xmmreg,xmmreg \3\x66\x0F\xD1\110 WILLAMETTE,SSE2
+PSRLW xmmreg,imm \3\x66\x0F\x71\202\25 WILLAMETTE,SSE2,SB,AR1
+PSRLD xmmreg,mem \301\3\x66\x0F\xD2\110 WILLAMETTE,SSE2,SM
+PSRLD xmmreg,xmmreg \3\x66\x0F\xD2\110 WILLAMETTE,SSE2
+PSRLD xmmreg,imm \3\x66\x0F\x72\202\25 WILLAMETTE,SSE2,SB,AR1
+PSRLQ xmmreg,mem \301\3\x66\x0F\xD3\110 WILLAMETTE,SSE2,SM
+PSRLQ xmmreg,xmmreg \3\x66\x0F\xD3\110 WILLAMETTE,SSE2
+PSRLQ xmmreg,imm \3\x66\x0F\x73\202\25 WILLAMETTE,SSE2,SB,AR1
+PSUBB xmmreg,mem \301\3\x66\x0F\xF8\110 WILLAMETTE,SSE2,SM
+PSUBB xmmreg,xmmreg \3\x66\x0F\xF8\110 WILLAMETTE,SSE2
+PSUBW xmmreg,mem \301\3\x66\x0F\xF9\110 WILLAMETTE,SSE2,SM
+PSUBW xmmreg,xmmreg \3\x66\x0F\xF9\110 WILLAMETTE,SSE2
+PSUBD xmmreg,mem \301\3\x66\x0F\xFA\110 WILLAMETTE,SSE2,SM
+PSUBD xmmreg,xmmreg \3\x66\x0F\xFA\110 WILLAMETTE,SSE2
+PSUBQ mmxreg,mmxreg \2\x0F\xFB\110 WILLAMETTE,SSE2
+PSUBQ mmxreg,mem \301\2\x0F\xFB\110 WILLAMETTE,SSE2,SM
+PSUBQ xmmreg,xmmreg \3\x66\x0F\xFB\110 WILLAMETTE,SSE2
+PSUBQ xmmreg,mem \301\3\x66\x0F\xFB\110 WILLAMETTE,SSE2,SM
+PSUBSB xmmreg,mem \301\3\x66\x0F\xE8\110 WILLAMETTE,SSE2,SM
+PSUBSB xmmreg,xmmreg \3\x66\x0F\xE8\110 WILLAMETTE,SSE2
+PSUBSW xmmreg,mem \301\3\x66\x0F\xE9\110 WILLAMETTE,SSE2,SM
+PSUBSW xmmreg,xmmreg \3\x66\x0F\xE9\110 WILLAMETTE,SSE2
+PSUBUSB xmmreg,mem \301\3\x66\x0F\xD8\110 WILLAMETTE,SSE2,SM
+PSUBUSB xmmreg,xmmreg \3\x66\x0F\xD8\110 WILLAMETTE,SSE2
+PSUBUSW xmmreg,mem \301\3\x66\x0F\xD9\110 WILLAMETTE,SSE2,SM
+PSUBUSW xmmreg,xmmreg \3\x66\x0F\xD9\110 WILLAMETTE,SSE2
+PUNPCKHBW xmmreg,mem \301\3\x66\x0F\x68\110 WILLAMETTE,SSE2,SM
+PUNPCKHBW xmmreg,xmmreg \3\x66\x0F\x68\110 WILLAMETTE,SSE2
+PUNPCKHWD xmmreg,mem \301\3\x66\x0F\x69\110 WILLAMETTE,SSE2,SM
+PUNPCKHWD xmmreg,xmmreg \3\x66\x0F\x69\110 WILLAMETTE,SSE2
+PUNPCKHDQ xmmreg,mem \301\3\x66\x0F\x6A\110 WILLAMETTE,SSE2,SM
+PUNPCKHDQ xmmreg,xmmreg \3\x66\x0F\x6A\110 WILLAMETTE,SSE2
+PUNPCKHQDQ xmmreg,xmmreg \3\x66\x0F\x6D\110 WILLAMETTE,SSE2
+PUNPCKHQDQ xmmreg,mem \301\3\x66\x0F\x6D\110 WILLAMETTE,SSE2,SM
+PUNPCKLBW xmmreg,mem \301\3\x66\x0F\x60\110 WILLAMETTE,SSE2,SM
+PUNPCKLBW xmmreg,xmmreg \3\x66\x0F\x60\110 WILLAMETTE,SSE2
+PUNPCKLWD xmmreg,mem \301\3\x66\x0F\x61\110 WILLAMETTE,SSE2,SM
+PUNPCKLWD xmmreg,xmmreg \3\x66\x0F\x61\110 WILLAMETTE,SSE2
+PUNPCKLDQ xmmreg,mem \301\3\x66\x0F\x62\110 WILLAMETTE,SSE2,SM
+PUNPCKLDQ xmmreg,xmmreg \3\x66\x0F\x62\110 WILLAMETTE,SSE2
+PUNPCKLQDQ xmmreg,xmmreg \3\x66\x0F\x6C\110 WILLAMETTE,SSE2
+PUNPCKLQDQ xmmreg,mem \301\3\x66\x0F\x6C\110 WILLAMETTE,SSE2,SM
+PXOR xmmreg,mem \301\3\x66\x0F\xEF\110 WILLAMETTE,SSE2,SM
+PXOR xmmreg,xmmreg \3\x66\x0F\xEF\110 WILLAMETTE,SSE2
-; Willamette MMX instructions (SSE2)
-MOVD xmmreg,reg32 \3\x66\x0F\x6E WILLAMETTE
-MOVD reg32,xmmreg \3\x66\x0F\x7E WILLAMETTE
-MOVD mem,xmmreg \3\x66\x0F\x7E WILLAMETTE
-MOVD xmmreg,mem \3\x66\x0F\x6E WILLAMETTE
-MOVDQA xmmreg,reg32 \3\x66\x0F\x6F WILLAMETTE
-MOVDQA mem,xmmreg \3\x66\x0F\x7F WILLAMETTE
-MOVDQA xmmreg,mem \3\x66\x0F\x6F WILLAMETTE
-MOVDQA reg32,xmmreg \3\x66\x0F\x7F WILLAMETTE
-MOVDQU xmmreg,reg32 \3\xF3\x0F\x6F WILLAMETTE
-MOVDQU mem,xmmreg \3\xF3\x0F\x7F WILLAMETTE
-MOVDQU xmmreg,mem \3\xF3\x0F\x6F WILLAMETTE
-MOVDQU reg32,xmmreg \3\xF3\x0F\x7F WILLAMETTE
-MOVQ2DQ mmxreg,xmmreg \3\xF2\x0F\xD6 WILLAMETTE
-PACKSSWB xmmreg,xmmreg \3\x66\x0F\x63 WILLAMETTE
-PACKSSWB xmmreg,mem \3\x66\x0F\x63 WILLAMETTE
-PACKSSDW xmmreg,xmmreg \3\x66\x0F\x6B WILLAMETTE
-PACKSSDW xmmreg,mem \3\x66\x0F\x6B WILLAMETTE
-PACKUSWB xmmreg,xmmreg \3\x66\x0F\x67 WILLAMETTE
-PACKUSWB xmmreg,mem \3\x66\x0F\x67 WILLAMETTE
-PADDQ xmmreg,mmxreg \3\x66\x0F\xD4 WILLAMETTE
-PADDQ xmmreg,mem \3\x66\x0F\xD4 WILLAMETTE
-PADDD xmmreg,xmmreg \3\x66\x0F\xFE WILLAMETTE
-PADDD xmmreg,mem \3\x66\x0F\xFE WILLAMETTE
-PADDSB xmmreg,mem \3\x66\x0F\xEC WILLAMETTE
-PADDSB xmmreg,xmmreg \3\x66\x0F\xEC WILLAMETTE
-PADDSW xmmreg,mem \3\x66\x0F\xED WILLAMETTE
-PADDSW xmmreg,xmmreg \3\x66\x0F\xED WILLAMETTE
-PADDUSB xmmreg,mem \3\x66\x0F\xDC WILLAMETTE
-PADDUSB xmmreg,xmmreg \3\x66\x0F\xDC WILLAMETTE
-PADDUSW xmmreg,mem \3\x66\x0F\xDD WILLAMETTE
-PADDUSW xmmreg,xmmreg \3\x66\x0F\xDD WILLAMETTE
-PAND xmmreg,xmmreg \3\x66\x0F\xDB WILLAMETTE
-PAND xmmreg,mem \3\x66\x0F\xDB WILLAMETTE
-PANDN xmmreg,xmmreg \3\x66\x0F\xDF WILLAMETTE
-PANDN xmmreg,mem \3\x66\x0F\xDF WILLAMETTE
-PAVGB xmmreg,xmmreg \3\x66\x0F\xE0 WILLAMETTE
-PAVGB xmmreg,mem \3\x66\x0F\xE0 WILLAMETTE
-PAVGW xmmreg,xmmreg \3\x66\x0F\xE3 WILLAMETTE
-PAVGW xmmreg,mem \3\x66\x0F\xE3 WILLAMETTE
-PCMPEQB xmmreg,xmmreg \3\x66\x0F\x74 WILLAMETTE
-PCMPEQB xmmreg,mem \3\x66\x0F\x74 WILLAMETTE
-PCMPEQW xmmreg,xmmreg \3\x66\x0F\x75 WILLAMETTE
-PCMPEQW xmmreg,mem \3\x66\x0F\x75 WILLAMETTE
-PCMPEQD xmmreg,xmmreg \3\x66\x0F\x76 WILLAMETTE
-PCMPEQD xmmreg,mem \3\x66\x0F\x76 WILLAMETTE
-PCMPGTB xmmreg,xmmreg \3\x66\x0F\x64 WILLAMETTE
-PCMPGTB xmmreg,mem \3\x66\x0F\x64 WILLAMETTE
-PCMPGTW xmmreg,xmmreg \3\x66\x0F\x65 WILLAMETTE
-PCMPGTW xmmreg,mem \3\x66\x0F\x65 WILLAMETTE
-PCMPGTD xmmreg,xmmreg \3\x66\x0F\x66 WILLAMETTE
-PCMPGTD xmmreg,mem \3\x66\x0F\x66 WILLAMETTE
-PEXTRW reg32,xmmreg,imm8 \3\x66\x0F\xC5\110\22 WILLAMETTE
-PINSRW xmmreg,reg16,imm \3\x66\x0F\xC4\110\22 WILLAMETTE,MMX,SB,AR2
-PINSRW xmmreg,reg32,imm \3\x66\x0F\xC4\110\22 WILLAMETTE,MMX,SB,AR2,ND
-PINSRW xmmreg,mem,imm \301\3\x66\x0F\xC4\110\22 WILLAMETTE,MMX,SB,AR2
-PINSRW xmmreg,mem16,imm \301\3\x66\x0F\xC4\110\22 WILLAMETTE,MMX,SB,AR2,ND
-PMAXSW xmmreg,xmmreg \3\x66\x0F\xEE\110 WILLAMETTE,MMX
-PMAXSW xmmreg,mem \301\3\x66\x0F\xEE\110 WILLAMETTE,MMX,SM
-PMAXUB xmmreg,xmmreg \3\x66\x0F\xDE\110 WILLAMETTE,MMX
-PMAXUB xmmreg,mem \301\3\x66\x0F\xDE\110 WILLAMETTE,MMX,SM
-PMINSW xmmreg,xmmreg \3\x66\x0F\xEA\110 WILLAMETTE,MMX
-PMINSW xmmreg,mem \301\3\x66\x0F\xEA\110 WILLAMETTE,MMX,SM
-PMINUB xmmreg,xmmreg \3\x66\x0F\xDA\110 WILLAMETTE,MMX
-PMINUB xmmreg,mem \301\3\x66\x0F\xDA\110 WILLAMETTE,MMX,SM
-PMOVMSKB reg32,xmmreg \3\x66\x0F\xD7\110 WILLAMETTE,MMX
-PMULHUW xmmreg,xmmreg \3\x66\x0F\xE4\110 WILLAMETTE,MMX
-PMULHUW xmmreg,mem \301\3\x66\x0F\xE4\110 WILLAMETTE,MMX,SM
-PSADBW xmmreg,xmmreg \3\x66\x0F\xF6\110 WILLAMETTE,MMX
-PSADBW xmmreg,mem \301\3\x66\x0F\xF6\110 WILLAMETTE,MMX,SM
-PSHUFD xmmreg,xmmreg,imm \3\x66\x0F\x70\110\22 WILLAMETTE,MMX,SB,AR2
-PSHUFD xmmreg,mem,imm \301\3\x66\x0F\x70\110\22 WILLAMETTE,MMX,SM2,SB,AR2
-PMADDWD xmmreg,mem \301\3\x66\x0F\xF5\110 WILLAMETTE,MMX,SM
-PMADDWD xmmreg,xmmreg \3\x66\x0F\xF5\110 WILLAMETTE,MMX
-PMULLW xmmreg,mem \301\3\x66\x0F\xD5\110 WILLAMETTE,MMX,SM
-PMULLW xmmreg,xmmreg \3\x66\x0F\xD5\110 WILLAMETTE,MMX
-PMULUDQ mmxreg,mmxreg \2\x0F\xF4 WILLAMETTE
-PMULUDQ mmxreg,mem \2\x0F\xF4 WILLAMETTE
-PMULUDQ xmmreg,xmmreg \3\x66\x0F\xF4 WILLAMETTE
-PMULUDQ xmmreg,mem \3\x66\x0F\xF4 WILLAMETTE
-POR xmmreg,mem \301\3\x66\x0F\xEB\110 WILLAMETTE,MMX,SM
-POR xmmreg,xmmreg \3\x66\x0F\xEB\110 WILLAMETTE,MMX
-PSHUFLW xmmreg,xmmreg,imm8 \3\xF2\x0F\x70 WILLAMETTE
-PSHUFLW xmmreg,mem,imm8 \3\xF2\x0F\x70 WILLAMETTE
-PSHUFHW xmmreg,xmmreg,imm8 \3\xF3\x0F\x70 WILLAMETTE
-PSHUFHW xmmreg,mem,imm8 \3\xF3\x0F\x70 WILLAMETTE
-PSLLDQ xmmreg,imm8 \3\x66\x0F\x73 WILLAMETTE
-PSLLD xmmreg,mem \301\3\x66\x0F\xF2\110 WILLAMETTE,MMX,SM
-PSLLD xmmreg,xmmreg \3\x66\x0F\xF2\110 WILLAMETTE,MMX
-PSLLD xmmreg,imm \3\x66\x0F\x72\206\25 WILLAMETTE,MMX
-PSLLQ xmmreg,mem \301\3\x66\x0F\xF3\110 WILLAMETTE,MMX,SM
-PSLLQ xmmreg,xmmreg \3\x66\x0F\xF3\110 WILLAMETTE,MMX
-PSLLQ xmmreg,imm \3\x66\x0F\x73\206\25 WILLAMETTE,MMX
-PSLLW xmmreg,mem \301\3\x66\x0F\xF1\110 WILLAMETTE,MMX,SM
-PSLLW xmmreg,xmmreg \3\x66\x0F\xF1\110 WILLAMETTE,MMX
-PSLLW xmmreg,imm \3\x66\x0F\x71\206\25 WILLAMETTE,MMX
-PSRAD xmmreg,mem \301\3\x66\x0F\xE2\110 WILLAMETTE,MMX,SM
-PSRAD xmmreg,xmmreg \3\x66\x0F\xE2\110 WILLAMETTE,MMX
-PSRAD xmmreg,imm \3\x66\x0F\x72\204\25 WILLAMETTE,MMX
-PSRAW xmmreg,mem \301\3\x66\x0F\xE1\110 WILLAMETTE,MMX,SM
-PSRAW xmmreg,xmmreg \3\x66\x0F\xE1\110 WILLAMETTE,MMX
-PSRAW xmmreg,imm \3\x66\x0F\x71\204\25 WILLAMETTE,MMX
-PSRLW xmmreg,imm \3\x66\x0F\x73\202\25 WILLAMETTE,MMX
-PSRLD xmmreg,mem \301\3\x66\x0F\xD2\110 WILLAMETTE,MMX,SM
-PSRLD xmmreg,xmmreg \3\x66\x0F\xD2\110 WILLAMETTE,MMX
-PSRLD xmmreg,imm \3\x66\x0F\x72\202\25 WILLAMETTE,MMX
-PSRLQ xmmreg,mem \301\3\x66\x0F\xD3\110 WILLAMETTE,MMX,SM
-PSRLQ xmmreg,xmmreg \3\x66\x0F\xD3\110 WILLAMETTE,MMX
-PSRLQ xmmreg,imm \3\x66\x0F\x73\202\25 WILLAMETTE,MMX
-PSRLW xmmreg,mem \301\3\x66\x0F\xD1\110 WILLAMETTE,MMX,SM
-PSRLW xmmreg,xmmreg \3\x66\x0F\xD1\110 WILLAMETTE,MMX
-PSRLW xmmreg,imm \3\x66\x0F\x71\202\25 WILLAMETTE,MMX
-PSUBQ mmxreg,mmxreg \2\x0F\xFB WILLAMETTE
-PSUBQ mmxreg,mem \2\x0F\xFB WILLAMETTE
-PSUBQ xmmreg,xmmreg \3\x66\x0F\xFB WILLAMETTE
-PSUBQ xmmreg,mem \3\x66\x0F\xFB WILLAMETTE
-PSUBB xmmreg,mem \301\3\x66\x0F\xF8\110 WILLAMETTE,MMX,SM
-PSUBB xmmreg,xmmreg \3\x66\x0F\xF8\110 WILLAMETTE,MMX
-PSUBD xmmreg,mem \301\3\x66\x0F\xFA\110 WILLAMETTE,MMX,SM
-PSUBD xmmreg,xmmreg \3\x66\x0F\xFA\110 WILLAMETTE,MMX
-PSUBSB xmmreg,mem \301\3\x66\x0F\xE8\110 WILLAMETTE,MMX,SM
-PSUBSB xmmreg,xmmreg \3\x66\x0F\xE8\110 WILLAMETTE,MMX
-PSUBSW xmmreg,mem \301\3\x66\x0F\xE9\110 WILLAMETTE,MMX,SM
-PSUBSW xmmreg,xmmreg \3\x66\x0F\xE9\110 WILLAMETTE,MMX
-PSUBUSB xmmreg,mem \301\3\x66\x0F\xD8\110 WILLAMETTE,MMX,SM
-PSUBUSB xmmreg,xmmreg \3\x66\x0F\xD8\110 WILLAMETTE,MMX
-PSUBUSW xmmreg,mem \301\3\x66\x0F\xD9\110 WILLAMETTE,MMX,SM
-PSUBUSW xmmreg,xmmreg \3\x66\x0F\xD9\110 WILLAMETTE,MMX
-PSUBW xmmreg,mem \301\3\x66\x0F\xF9\110 WILLAMETTE,MMX,SM
-PSUBW xmmreg,xmmreg \3\x66\x0F\xF9\110 WILLAMETTE,MMX
-PUNPCKHBW xmmreg,mem \301\3\x66\x0F\x68\110 WILLAMETTE,MMX,SM
-PUNPCKHBW xmmreg,xmmreg \3\x66\x0F\x68\110 WILLAMETTE,MMX
-PUNPCKHDQ xmmreg,mem \301\3\x66\x0F\x6A\110 WILLAMETTE,MMX,SM
-PUNPCKHDQ xmmreg,xmmreg \3\x66\x0F\x6A\110 WILLAMETTE,MMX
-PUNPCKHWD xmmreg,mem \301\3\x66\x0F\x69\110 WILLAMETTE,MMX,SM
-PUNPCKHWD xmmreg,xmmreg \3\x66\x0F\x69\110 WILLAMETTE,MMX
-PUNPCKLBW xmmreg,mem \301\3\x66\x0F\x60\110 WILLAMETTE,MMX,SM
-PUNPCKLBW xmmreg,xmmreg \3\x66\x0F\x60\110 WILLAMETTE,MMX
-PUNPCKLDQ xmmreg,mem \301\3\x66\x0F\x62\110 WILLAMETTE,MMX,SM
-PUNPCKLDQ xmmreg,xmmreg \3\x66\x0F\x62\110 WILLAMETTE,MMX
-PUNPCKLWD xmmreg,mem \301\3\x66\x0F\x61\110 WILLAMETTE,MMX,SM
-PUNPCKLWD xmmreg,xmmreg \3\x66\x0F\x61\110 WILLAMETTE,MMX
-PUNPCKLQDQ xmmreg,xmmreg \3\x66\x0F\x6C\110 WILLAMETTE
-PUNPCKLQDQ xmmreg,mem \301\3\x66\x0F\x6C\110 WILLAMETTE
-PUNPCKHQDQ xmmreg,xmmreg \3\x66\x0F\x6D\110 WILLAMETTE
-PUNPCKHQDQ xmmreg,mem \301\3\x66\x0F\x6D\110 WILLAMETTE
-PXOR xmmreg,mem \301\3\x66\x0F\xEF\110 WILLAMETTE,MMX,SM
-PXOR xmmreg,xmmreg \3\x66\x0F\xEF\110 WILLAMETTE,MMX
; Willamette Streaming SIMD instructions (SSE2)
-; opcode parameters assembly range
-ADDPD xmmreg,xmmreg \3\x66\x0F\x58 WILLAMETTE,SSE2
-ADDPD mem,xmmreg \3\x66\x0F\x58 WILLAMETTE,SSE2
-ADDSD xmmreg,xmmreg \3\xF2\x0F\x58 WILLAMETTE,SSE2
-ADDSD mem,xmmreg \3\xF2\x0F\x58 WILLAMETTE,SSE2
-ANDNPD xmmreg,xmmreg \3\x66\x0F\x54 WILLAMETTE,SSE2
-ANDNPD mem,xmmreg \3\x66\x0F\x54 WILLAMETTE,SSE2
-ANDDPD xmmreg,xmmreg \3\x66\x0F\x55 WILLAMETTE,SSE2
-ANDDPD mem,xmmreg \3\x66\x0F\x55 WILLAMETTE,SSE2
-CMPPD xmmreg,xmmreg,imm8 \3\x66\x0F\xC2 WILLAMETTE,SSE2
-CMPPD mem,xmmreg,imm8 \3\x66\x0F\xC2 WILLAMETTE,SSE2
-CMPSD xmmreg,xmmreg,imm8 \1\xA7 WILLAMETTE,SSE2
-CMPSD mem,xmmreg,imm8 \1\xA7 WILLAMETTE,SSE2
-COMISD xmmreg,xmmreg \3\x66\x0F\x2F WILLAMETTE,SSE2
-COMISD mem,xmmreg \3\x66\x0F\x2F WILLAMETTE,SSE2
-CVTPI2PD mmxreg,xmmreg \3\x66\x0F\x2A WILLAMETTE,SSE2
-CVTPI2PD mem,xmmreg \3\x66\x0F\x2A WILLAMETTE,SSE2
-CVTPD2PI xmmreg,mmxreg \3\x66\x0F\x2C WILLAMETTE,SSE2
-CVTPD2PI mem,mmxreg \3\x66\x0F\x2C WILLAMETTE,SSE2
-CVTSI2SD reg32,xmmreg \3\xF2\x0F\x2A WILLAMETTE,SSE2
-CVTSI2SD mem,xmmreg \3\xF2\x0F\x2A WILLAMETTE,SSE2
-CVTSD2SI xmmreg,reg32 \3\xF2\x0F\x2D WILLAMETTE,SSE2
-CVTSD2SI mem,reg32 \3\xF2\x0F\x2D WILLAMETTE,SSE2
-CVTPD2PS xmmreg,xmmreg \2\x0F\x2A WILLAMETTE,SSE2
-CVTPD2PS mem,xmmreg \2\x0F\x2A WILLAMETTE,SSE2
-CVTPS2PD xmmreg,xmmreg \2\x0F\x5A WILLAMETTE,SSE2
-CVTPS2PD mem,xmmreg \2\x0F\x5A WILLAMETTE,SSE2
-CVTSD2SS xmmreg,xmmreg \3\xF2\x0F\x5A WILLAMETTE,SSE2
-CVTSD2SS mem,xmmreg \3\xF2\x0F\x5A WILLAMETTE,SSE2
-CVTSS2SD xmmreg,xmmreg \3\xF3\x0F\x5A WILLAMETTE,SSE2
-CVTSS2SD mem,xmmreg \3\xF3\x0F\x5A WILLAMETTE,SSE2
-CVTPD2DQ xmmreg,xmmreg \3\xF2\x0F\xE6 WILLAMETTE,SSE2
-CVTPD2DQ mem,xmmreg \3\xF2\x0F\xE6 WILLAMETTE,SSE2
-CVTDQ2PD xmmreg,xmmreg \3\xF3\x0F\xE6 WILLAMETTE,SSE2
-CVTDQ2PD mem,xmmreg \3\xF3\x0F\xE6 WILLAMETTE,SSE2
-CVTDQ2PS xmmreg,xmmreg \2\x0F\x5B WILLAMETTE,SSE2
-CVTDQ2PS mem,xmmreg \2\x0F\x5B WILLAMETTE,SSE2
-CVTPS2DQ xmmreg,xmmreg \3\x66\x0F\x5B WILLAMETTE,SSE2
-CVTPS2DQ mem,xmmreg \3\x66\x0F\x5B WILLAMETTE,SSE2
-CVTTPD2PI mmxreg,xmmreg \3\x66\x0F\x2C WILLAMETTE,SSE2
-CVTTPD2PI mem,xmmreg \3\x66\x0F\x2C WILLAMETTE,SSE2
-CVTTPD2DQ mmxreg,xmmreg \3\x66\x0F\xE6 WILLAMETTE,SSE2
-CVTTPD2DQ mem,xmmreg \3\x66\x0F\xE6 WILLAMETTE,SSE2
-CVTTPS2DQ mmxreg,xmmreg \3\xF3\x0F\x5B WILLAMETTE,SSE2
-CVTTPS2DQ mem,xmmreg \3\xF3\x0F\x5B WILLAMETTE,SSE2
-CVTTPS2PI mmxreg,xmmreg \3\x0F\x2C WILLAMETTE,SSE2
-CVTTPS2PI mem,xmmreg \3\x0F\x2C WILLAMETTE,SSE2
-CVTTSD2SI mmxreg,xmmreg \3\xF2\x0F\x2C WILLAMETTE,SSE2
-CVTTSD2SI mem,xmmreg \3\xF2\x0F\x2C WILLAMETTE,SSE2
-CVTTSS2SI mmxreg,xmmreg \3\xF3\x0F\x2C WILLAMETTE,SSE2
-CVTTSS2SI mem,xmmreg \3\xF3\x0F\x2C WILLAMETTE,SSE2
-DIVPD xmmreg,xmmreg \3\x66\x0F\x5E WILLAMETTE,SSE2
-DIVPD mem,xmmreg \3\x66\x0F\x5E WILLAMETTE,SSE2
-DIVSD xmmreg,xmmreg \3\xF2\x0F\x5E WILLAMETTE,SSE2
-DIVSD mem,xmmreg \3\xF2\x0F\x5E WILLAMETTE,SSE2
-MAXPD xmmreg,xmmreg \3\x66\x0F\x5F WILLAMETTE,SSE2
-MAXPD mem,xmmreg \3\x66\x0F\x5F WILLAMETTE,SSE2
-MAXSD xmmreg,xmmreg \3\xF2\x0F\x5F WILLAMETTE,SSE2
-MAXSD mem,xmmreg \3\xF2\x0F\x5F WILLAMETTE,SSE2
-MINPD xmmreg,xmmreg \3\x66\x0F\x5D WILLAMETTE,SSE2
-MINPD mem,xmmreg \3\x66\x0F\x5D WILLAMETTE,SSE2
-MINSD xmmreg,xmmreg \3\xF2\x0F\x5D WILLAMETTE,SSE2
-MINSD mem,xmmreg \3\xF2\x0F\x5D WILLAMETTE,SSE2
-MOVAPD xmmreg,xmmreg \3\x66\x0F\x28 WILLAMETTE,SSE2
-MOVAPD xmmreg,xmmreg \3\x66\x0F\x29 WILLAMETTE,SSE2
-MOVAPD mem,xmmreg \3\x66\x0F\x29 WILLAMETTE,SSE2
-MOVAPD xmmreg,mem \3\x66\x0F\x28 WILLAMETTE,SSE2
-MOVHPD mem,xmmreg \3\x66\x0F\x17 WILLAMETTE,SSE2
-MOVHPD xmmreg,xmmreg \3\x66\x0F\x16 WILLAMETTE,SSE2
-MOVLPD mem,xmmreg \3\x66\x0F\x13 WILLAMETTE,SSE2
-MOVLPD xmmreg,xmmreg \3\x66\x0F\x12 WILLAMETTE,SSE2
-MOVMSKPD xmmreg,reg32 \3\x66\x0F\x50 WILLAMETTE,SSE2
-MOVSD xmmreg,xmmreg \3\xF2\x0F\x10 WILLAMETTE,SSE2
-MOVSD xmmreg,xmmreg \3\xF2\x0F\x11 WILLAMETTE,SSE2
-MOVSD mem,xmmreg \3\xF2\x0F\x11 WILLAMETTE,SSE2
-MOVSD xmmreg,mem \3\xF2\x0F\x10 WILLAMETTE,SSE2
-MOVUPD xmmreg,xmmreg \3\x66\x0F\x10 WILLAMETTE,SSE2
-MOVUPD xmmreg,xmmreg \3\x66\x0F\x11 WILLAMETTE,SSE2
-MOVUPD mem,xmmreg \3\x66\x0F\x11 WILLAMETTE,SSE2
-MOVUPD xmmreg,mem \3\x66\x0F\x10 WILLAMETTE,SSE2
-MULPD xmmreg,xmmreg \3\x66\x0F\x59 WILLAMETTE,SSE2
-MULPD mem,xmmreg \3\x66\x0F\x59 WILLAMETTE,SSE2
-MULSD xmmreg,xmmreg \3\xF2\x0F\x59 WILLAMETTE,SSE2
-MULSD mem,xmmreg \3\xF2\x0F\x59 WILLAMETTE,SSE2
-ORPD mem,xmmreg \3\x66\x0F\x56 WILLAMETTE,SSE2
-ORPD xmmreg,xmmreg,imm8 \3\x66\x0F\x56 WILLAMETTE,SSE2
-SHUFPD xmmreg,xmmreg,imm8 \3\x66\x0F\xC6 WILLAMETTE,SSE2
-SHUFPD mem,xmmreg \3\x66\x0F\xC6 WILLAMETTE,SSE2
-SQRTPD xmmreg,xmmreg \3\x66\x0F\x51 WILLAMETTE,SSE2
-SQRTPD mem,xmmreg \3\x66\x0F\x51 WILLAMETTE,SSE2
-SQRTSD xmmreg,xmmreg \3\xF2\x0F\x51 WILLAMETTE,SSE2
-SQRTSD mem,xmmreg \3\xF2\x0F\x51 WILLAMETTE,SSE2
-SUBPD xmmreg,xmmreg \3\x66\x0F\x5C WILLAMETTE,SSE2
-SUBPD mem,xmmreg \3\x66\x0F\x5C WILLAMETTE,SSE2
-SUBSD xmmreg,xmmreg \3\xF2\x0F\x5C WILLAMETTE,SSE2
-SUBSD mem,xmmreg \3\xF2\x0F\x5C WILLAMETTE,SSE2
-UCOMISD xmmreg,xmmreg \3\x66\x0F\x2E WILLAMETTE,SSE2
-UCOMISD mem,xmmreg \3\x66\x0F\x2E WILLAMETTE,SSE2
-UNPCKHPD xmmreg,xmmreg \3\x66\x0F\x15 WILLAMETTE,SSE2
-UNPCKHPD mem,xmmreg \3\x66\x0F\x15 WILLAMETTE,SSE2
-UNPCKLPD xmmreg,xmmreg \3\x66\x0F\x14 WILLAMETTE,SSE2
-UNPCKLPD mem,xmmreg \3\x66\x0F\x14 WILLAMETTE,SSE2
-XORPD xmmreg,xmmreg \3\x66\x0F\x57 WILLAMETTE,SSE2
-XORPD mem,xmmreg \3\x66\x0F\x57 WILLAMETTE,SSE2
+ADDPD xmmreg,xmmreg \331\3\x66\x0F\x58\110 WILLAMETTE,SSE2
+ADDPD xmmreg,mem \301\331\3\x66\x0F\x58\110 WILLAMETTE,SSE2,SM
+ADDSD xmmreg,xmmreg \331\3\xF2\x0F\x58\110 WILLAMETTE,SSE2
+ADDSD xmmreg,mem \301\331\3\xF2\x0F\x58\110 WILLAMETTE,SSE2
+ANDNPD xmmreg,xmmreg \331\3\x66\x0F\x55\110 WILLAMETTE,SSE2
+ANDNPD xmmreg,mem \301\331\3\x66\x0F\x55\110 WILLAMETTE,SSE2,SM
+ANDPD xmmreg,xmmreg \331\3\x66\x0F\x54\110 WILLAMETTE,SSE2
+ANDPD xmmreg,mem \301\331\3\x66\x0F\x54\110 WILLAMETTE,SSE2,SM
+CMPEQPD xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x00 WILLAMETTE,SSE2,SM
+CMPEQPD xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x00 WILLAMETTE,SSE2
+CMPEQSD xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x00 WILLAMETTE,SSE2
+CMPEQSD xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x00 WILLAMETTE,SSE2
+CMPLEPD xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x02 WILLAMETTE,SSE2,SM
+CMPLEPD xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x02 WILLAMETTE,SSE2
+CMPLESD xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x02 WILLAMETTE,SSE2
+CMPLESD xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x02 WILLAMETTE,SSE2
+CMPLTPD xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x01 WILLAMETTE,SSE2,SM
+CMPLTPD xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x01 WILLAMETTE,SSE2
+CMPLTSD xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x01 WILLAMETTE,SSE2
+CMPLTSD xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x01 WILLAMETTE,SSE2
+CMPNEQPD xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x04 WILLAMETTE,SSE2,SM
+CMPNEQPD xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x04 WILLAMETTE,SSE2
+CMPNEQSD xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x04 WILLAMETTE,SSE2
+CMPNEQSD xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x04 WILLAMETTE,SSE2
+CMPNLEPD xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x06 WILLAMETTE,SSE2,SM
+CMPNLEPD xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x06 WILLAMETTE,SSE2
+CMPNLESD xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x06 WILLAMETTE,SSE2
+CMPNLESD xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x06 WILLAMETTE,SSE2
+CMPNLTPD xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x05 WILLAMETTE,SSE2,SM
+CMPNLTPD xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x05 WILLAMETTE,SSE2
+CMPNLTSD xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x05 WILLAMETTE,SSE2
+CMPNLTSD xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x05 WILLAMETTE,SSE2
+CMPORDPD xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x07 WILLAMETTE,SSE2,SM
+CMPORDPD xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x07 WILLAMETTE,SSE2
+CMPORDSD xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x07 WILLAMETTE,SSE2
+CMPORDSD xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x07 WILLAMETTE,SSE2
+CMPUNORDPD xmmreg,mem \301\331\3\x66\x0F\xC2\110\1\x03 WILLAMETTE,SSE2,SM
+CMPUNORDPD xmmreg,xmmreg \331\3\x66\x0F\xC2\110\1\x03 WILLAMETTE,SSE2
+CMPUNORDSD xmmreg,mem \301\331\3\xF2\x0F\xC2\110\1\x03 WILLAMETTE,SSE2
+CMPUNORDSD xmmreg,xmmreg \331\3\xF2\x0F\xC2\110\1\x03 WILLAMETTE,SSE2
+; CMPPD/CMPSD must come after the specific ops; that way the disassembler will find the
+; specific ops first and only disassemble illegal ones as cmppd/cmpsd.
+CMPPD xmmreg,xmmreg,imm \331\3\x66\x0F\xC2\110\26 WILLAMETTE,SSE2,SB,AR2
+CMPPD xmmreg,mem,imm \301\331\3\x66\x0F\xC2\110\26 WILLAMETTE,SSE2,SM2,SB,AR2
+CMPSD xmmreg,xmmreg,imm \331\3\xF2\x0F\xC2\110\26 WILLAMETTE,SSE2,SB,AR2
+CMPSD xmmreg,mem,imm \301\331\3\xF2\x0F\xC2\110\26 WILLAMETTE,SSE2,SB,AR2
+COMISD xmmreg,xmmreg \331\3\x66\x0F\x2F\110 WILLAMETTE,SSE2
+COMISD xmmreg,mem \301\331\3\x66\x0F\x2F\110 WILLAMETTE,SSE2
+CVTDQ2PD xmmreg,xmmreg \333\2\x0F\xE6\110 WILLAMETTE,SSE2
+CVTDQ2PD xmmreg,mem \301\333\2\x0F\xE6\110 WILLAMETTE,SSE2
+CVTDQ2PS xmmreg,xmmreg \2\x0F\x5B\110 WILLAMETTE,SSE2
+CVTDQ2PS xmmreg,mem \301\2\x0F\x5B\110 WILLAMETTE,SSE2,SM
+CVTPD2DQ xmmreg,xmmreg \3\xF2\x0F\xE6\110 WILLAMETTE,SSE2
+CVTPD2DQ xmmreg,mem \301\3\xF2\x0F\xE6\110 WILLAMETTE,SSE2,SM
+CVTPD2PI mmxreg,xmmreg \3\x66\x0F\x2D\110 WILLAMETTE,SSE2
+CVTPD2PI mmxreg,mem \301\3\x66\x0F\x2D\110 WILLAMETTE,SSE2
+CVTPD2PS xmmreg,xmmreg \3\x66\x0F\x5A\110 WILLAMETTE,SSE2
+CVTPD2PS xmmreg,mem \301\3\x66\x0F\x5A\110 WILLAMETTE,SSE2,SM
+CVTPI2PD xmmreg,mmxreg \3\x66\x0F\x2A\110 WILLAMETTE,SSE2
+CVTPI2PD xmmreg,mem \301\3\x66\x0F\x2A\110 WILLAMETTE,SSE2
+CVTPS2DQ xmmreg,xmmreg \3\x66\x0F\x5B\110 WILLAMETTE,SSE2
+CVTPS2DQ xmmreg,mem \301\3\x66\x0F\x5B\110 WILLAMETTE,SSE2,SM
+CVTPS2PD xmmreg,xmmreg \2\x0F\x5A\110 WILLAMETTE,SSE2
+CVTPS2PD xmmreg,mem \301\2\x0F\x5A\110 WILLAMETTE,SSE2
+CVTSD2SI reg32,xmmreg \3\xF2\x0F\x2D\110 WILLAMETTE,SSE2
+CVTSD2SI reg32,mem \301\3\xF2\x0F\x2D\110 WILLAMETTE,SSE2
+CVTSD2SS xmmreg,xmmreg \3\xF2\x0F\x5A\110 WILLAMETTE,SSE2
+CVTSD2SS xmmreg,mem \301\3\xF2\x0F\x5A\110 WILLAMETTE,SSE2
+CVTSI2SD xmmreg,reg32 \3\xF2\x0F\x2A\110 WILLAMETTE,SSE2
+CVTSI2SD xmmreg,mem \301\3\xF2\x0F\x2A\110 WILLAMETTE,SSE2
+CVTSS2SD xmmreg,xmmreg \333\2\x0F\x5A\110 WILLAMETTE,SSE2
+CVTSS2SD xmmreg,mem \301\333\2\x0F\x5A\110 WILLAMETTE,SSE2
+CVTTPD2PI mmxreg,xmmreg \3\x66\x0F\x2C\110 WILLAMETTE,SSE2
+CVTTPD2PI mmxreg,mem \301\3\x66\x0F\x2C\110 WILLAMETTE,SSE2
+CVTTPD2DQ xmmreg,xmmreg \3\x66\x0F\xE6\110 WILLAMETTE,SSE2
+CVTTPD2DQ xmmreg,mem \301\3\x66\x0F\xE6\110 WILLAMETTE,SSE2,SM
+CVTTPS2DQ xmmreg,xmmreg \333\2\x0F\x5B\110 WILLAMETTE,SSE2
+CVTTPS2DQ xmmreg,mem \301\333\2\x0F\x5B\110 WILLAMETTE,SSE2,SM
+CVTTSD2SI reg32,xmmreg \3\xF2\x0F\x2C\110 WILLAMETTE,SSE2
+CVTTSD2SI reg32,mem \301\3\xF2\x0F\x2C\110 WILLAMETTE,SSE2
+DIVPD xmmreg,xmmreg \3\x66\x0F\x5E\110 WILLAMETTE,SSE2
+DIVPD xmmreg,mem \301\3\x66\x0F\x5E\110 WILLAMETTE,SSE2,SM
+DIVSD xmmreg,xmmreg \3\xF2\x0F\x5E\110 WILLAMETTE,SSE2
+DIVSD xmmreg,mem \301\3\xF2\x0F\x5E\110 WILLAMETTE,SSE2
+MAXPD xmmreg,xmmreg \3\x66\x0F\x5F\110 WILLAMETTE,SSE2
+MAXPD xmmreg,mem \301\3\x66\x0F\x5F\110 WILLAMETTE,SSE2,SM
+MAXSD xmmreg,xmmreg \3\xF2\x0F\x5F\110 WILLAMETTE,SSE2
+MAXSD xmmreg,mem \301\3\xF2\x0F\x5F\110 WILLAMETTE,SSE2
+MINPD xmmreg,xmmreg \3\x66\x0F\x5D\110 WILLAMETTE,SSE2
+MINPD xmmreg,mem \301\3\x66\x0F\x5D\110 WILLAMETTE,SSE2,SM
+MINSD xmmreg,xmmreg \3\xF2\x0F\x5D\110 WILLAMETTE,SSE2
+MINSD xmmreg,mem \301\3\xF2\x0F\x5D\110 WILLAMETTE,SSE2
+MOVAPD xmmreg,xmmreg \3\x66\x0F\x28\110 WILLAMETTE,SSE2
+MOVAPD xmmreg,xmmreg \3\x66\x0F\x29\110 WILLAMETTE,SSE2
+MOVAPD mem,xmmreg \300\3\x66\x0F\x29\101 WILLAMETTE,SSE2,SM
+MOVAPD xmmreg,mem \301\3\x66\x0F\x28\110 WILLAMETTE,SSE2,SM
+MOVHPD mem,xmmreg \300\3\x66\x0F\x17\101 WILLAMETTE,SSE2
+MOVHPD xmmreg,mem \301\3\x66\x0F\x16\110 WILLAMETTE,SSE2
+MOVLPD mem,xmmreg \300\3\x66\x0F\x13\101 WILLAMETTE,SSE2
+MOVLPD xmmreg,mem \301\3\x66\x0F\x12\110 WILLAMETTE,SSE2
+MOVMSKPD reg32,xmmreg \3\x66\x0F\x50\110 WILLAMETTE,SSE2
+MOVSD xmmreg,xmmreg \3\xF2\x0F\x10\110 WILLAMETTE,SSE2
+MOVSD xmmreg,xmmreg \3\xF2\x0F\x11\110 WILLAMETTE,SSE2
+MOVSD mem,xmmreg \300\3\xF2\x0F\x11\101 WILLAMETTE,SSE2
+MOVSD xmmreg,mem \301\3\xF2\x0F\x10\110 WILLAMETTE,SSE2
+MOVUPD xmmreg,xmmreg \3\x66\x0F\x10\110 WILLAMETTE,SSE2
+MOVUPD xmmreg,xmmreg \3\x66\x0F\x11\110 WILLAMETTE,SSE2
+MOVUPD mem,xmmreg \300\3\x66\x0F\x11\101 WILLAMETTE,SSE2,SM
+MOVUPD xmmreg,mem \301\3\x66\x0F\x10\110 WILLAMETTE,SSE2,SM
+MULPD xmmreg,xmmreg \3\x66\x0F\x59\110 WILLAMETTE,SSE2
+MULPD xmmreg,mem \301\3\x66\x0F\x59\110 WILLAMETTE,SSE2,SM
+MULSD xmmreg,xmmreg \3\xF2\x0F\x59\110 WILLAMETTE,SSE2
+MULSD xmmreg,mem \301\3\xF2\x0F\x59\110 WILLAMETTE,SSE2
+ORPD xmmreg,mem \301\3\x66\x0F\x56\110 WILLAMETTE,SSE2,SM
+ORPD xmmreg,xmmreg \3\x66\x0F\x56\110 WILLAMETTE,SSE2
+SHUFPD xmmreg,xmmreg,imm \3\x66\x0F\xC6\110\26 WILLAMETTE,SSE2,SB,AR2
+SHUFPD xmmreg,mem,imm \301\3\x66\x0F\xC6\110\26 WILLAMETTE,SSE2,SM,SB,AR2
+SQRTPD xmmreg,xmmreg \3\x66\x0F\x51\110 WILLAMETTE,SSE2
+SQRTPD xmmreg,mem \301\3\x66\x0F\x51\110 WILLAMETTE,SSE2,SM
+SQRTSD xmmreg,xmmreg \3\xF2\x0F\x51\110 WILLAMETTE,SSE2
+SQRTSD xmmreg,mem \301\3\xF2\x0F\x51\110 WILLAMETTE,SSE2
+SUBPD xmmreg,xmmreg \3\x66\x0F\x5C\110 WILLAMETTE,SSE2
+SUBPD xmmreg,mem \301\3\x66\x0F\x5C\110 WILLAMETTE,SSE2,SM
+SUBSD xmmreg,xmmreg \3\xF2\x0F\x5C\110 WILLAMETTE,SSE2
+SUBSD xmmreg,mem \301\3\xF2\x0F\x5C\110 WILLAMETTE,SSE2
+UCOMISD xmmreg,xmmreg \3\x66\x0F\x2E\110 WILLAMETTE,SSE2
+UCOMISD xmmreg,mem \301\3\x66\x0F\x2E\110 WILLAMETTE,SSE2
+UNPCKHPD xmmreg,xmmreg \3\x66\x0F\x15\110 WILLAMETTE,SSE2
+UNPCKHPD mem,xmmreg \300\3\x66\x0F\x15\101 WILLAMETTE,SSE2,SM
+UNPCKLPD xmmreg,xmmreg \3\x66\x0F\x14\110 WILLAMETTE,SSE2
+UNPCKLPD xmmreg,mem \301\3\x66\x0F\x14\110 WILLAMETTE,SSE2,SM
+XORPD xmmreg,xmmreg \3\x66\x0F\x57\110 WILLAMETTE,SSE2
+XORPD xmmreg,mem \301\3\x66\x0F\x57\110 WILLAMETTE,SSE2,SM
diff --git a/labels.c b/labels.c
index f137847..c793904 100644
--- a/labels.c
+++ b/labels.c
@@ -20,7 +20,6 @@
* @@, so @@local is a TASM compatible local label. Note that we only
* check for the first @ symbol, although TASM requires both.
*/
-#ifdef TASM_COMPAT
#define islocal(l) \
(tasm_compatible_mode ? \
(((l)[0] == '.' || (l)[0] == '@') && (l)[1] != '.') : \
@@ -29,10 +28,6 @@
(tasm_compatible_mode ? \
((c) == '.' || (c) == '@') : \
((c) == '.'))
-#else
-#define islocal(l) ((l)[0] == '.' && (l)[1] != '.')
-#define islocalchar(c) ((c) == '.')
-#endif
#define LABEL_BLOCK 32 /* no. of labels/block */
#define LBLK_SIZE (LABEL_BLOCK*sizeof(union label))
diff --git a/listing.c b/listing.c
index 570e7fb..5efc6db 100644
--- a/listing.c
+++ b/listing.c
@@ -122,7 +122,7 @@ static void list_out (long offset, char *str)
static void list_output (long offset, void *data, unsigned long type)
{
- long typ, size;
+ unsigned long typ, size;
if (!listp || suppress || user_nolist) /* fbk - 9/2/00 */
return;
diff --git a/macros.pl b/macros.pl
index 0a12bb0..e1d9ed0 100644
--- a/macros.pl
+++ b/macros.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/perl -w
#
# macros.pl produce macros.c from standard.mac
#
@@ -6,6 +6,11 @@
# Julian Hall. All rights reserved. The software is
# redistributable under the licence given in the file "Licence"
# distributed in the NASM archive.
+use strict;
+
+my $fname;
+my $line = 0;
+my $index = 0;
$fname = "standard.mac" unless $fname = $ARGV[0];
open INPUT,$fname || die "unable to open $fname\n";
@@ -15,14 +20,25 @@ print OUTPUT "/* This file auto-generated from standard.mac by macros.pl" .
" - don't edit it */\n\nstatic char *stdmac[] = {\n";
while (<INPUT>) {
- chomp;
- # this regexp ought to match anything at all, so why bother with
- # a sensible error message ;-)
- die "swirly thing alert" unless /^\s*((\s*([^"';\s]+|"[^"]*"|'[^']*'))*)/;
- $_ = $1;
- s/\\/\\\\/g;
- s/"/\\"/g;
- print OUTPUT " \"$_\",\n" if length > 0;
+ $line++;
+ chomp;
+ if (m/^\s*((\s*([^"';\s]+|"[^"]*"|'[^']*'))*)\s*(;.*)?$/) {
+ $_ = $1;
+ s/\\/\\\\/g;
+ s/"/\\"/g;
+ if (length > 0) {
+ print OUTPUT " \"$_\",\n";
+ if ($index >= 0) {
+ if (m/__NASM_MAJOR__/) {
+ $index = -$index;
+ } else {
+ $index++;
+ }
+ }
+ }
+ } else {
+ die "$fname:$line: error unterminated quote";
+ }
}
-
-print OUTPUT " NULL\n};\n"
+$index = -$index;
+print OUTPUT " NULL\n};\n#define TASM_MACRO_COUNT $index\n"
diff --git a/misc/scitech.mac b/misc/scitech.mac
new file mode 100644
index 0000000..26f85f4
--- /dev/null
+++ b/misc/scitech.mac
@@ -0,0 +1,1223 @@
+;****************************************************************************
+;*
+;* ========================================================================
+;*
+;* The contents of this file are subject to the SciTech MGL Public
+;* License Version 1.0 (the "License"); you may not use this file
+;* except in compliance with the License. You may obtain a copy of
+;* the License at http://www.scitechsoft.com/mgl-license.txt
+;*
+;* Software distributed under the License is distributed on an
+;* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+;* implied. See the License for the specific language governing
+;* rights and limitations under the License.
+;*
+;* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
+;*
+;* The Initial Developer of the Original Code is SciTech Software, Inc.
+;* All Rights Reserved.
+;*
+;* ========================================================================
+;*
+;* Language: NetWide Assembler (NASM) or Turbo Assembler (TASM)
+;* Environment: Any Intel Environment
+;*
+;* Description: Macros to provide memory model independant assembly language
+;* module for C programming. Supports the large and flat memory
+;* models.
+;*
+;* The defines that you should use when assembling modules that
+;* use this macro package are:
+;*
+;* __LARGE__ Assemble for 16-bit large model
+;* __FLAT__ Assemble for 32-bit FLAT memory model
+;* __NOU__ No underscore for all external C labels
+;* __NOU_VAR__ No underscore for global variables only
+;*
+;* The default settings are for 16-bit large memory model with
+;* leading underscores for symbol names.
+;*
+;* The main intent of the macro file is to enable programmers
+;* to write _one_ set of source that can be assembled to run
+;* in either 16 bit real and protected modes or 32 bit
+;* protected mode without the need to riddle the code with
+;* 'if flatmodel' style conditional assembly (it is still there
+;* but nicely hidden by a macro layer that enhances the
+;* readability and understandability of the resulting code).
+;*
+;****************************************************************************
+
+; Include the appropriate version in here depending on the assembler. NASM
+; appears to always try and parse code, even if it is in a non-compiling
+; block of a ifdef expression, and hence crashes if we include the TASM
+; macro package in the same header file. Hence we split the macros up into
+; two separate header files.
+
+ifdef __NASM_MAJOR__
+
+;============================================================================
+; Macro package when compiling with NASM.
+;============================================================================
+
+; Turn off underscores for globals if disabled for all externals
+
+%ifdef __NOU__
+%define __NOU_VAR__
+%endif
+
+; Define the __WINDOWS__ symbol if we are compiling for any Windows
+; environment
+
+%ifdef __WINDOWS16__
+%define __WINDOWS__ 1
+%endif
+%ifdef __WINDOWS32__
+%define __WINDOWS__ 1
+%define __WINDOWS32_386__ 1
+%endif
+
+; Macros for accessing 'generic' registers
+
+%ifdef __FLAT__
+%idefine _ax eax
+%idefine _bx ebx
+%idefine _cx ecx
+%idefine _dx edx
+%idefine _si esi
+%idefine _di edi
+%idefine _bp ebp
+%idefine _sp esp
+%idefine _es
+%idefine UCHAR BYTE ; Size of a character
+%idefine USHORT WORD ; Size of a short
+%idefine UINT DWORD ; Size of an integer
+%idefine ULONG DWORD ; Size of a long
+%idefine BOOL DWORD ; Size of a boolean
+%idefine DPTR DWORD ; Size of a data pointer
+%idefine FDPTR FWORD ; Size of a far data pointer
+%idefine NDPTR DWORD ; Size of a near data pointer
+%idefine CPTR DWORD ; Size of a code pointer
+%idefine FCPTR FWORD ; Size of a far code pointer
+%idefine NCPTR DWORD ; Size of a near code pointer
+%idefine FPTR NEAR ; Distance for function pointers
+%idefine DUINT dd ; Declare a integer variable
+%idefine intsize 4
+%idefine flatmodel 1
+%else
+%idefine _ax ax
+%idefine _bx bx
+%idefine _cx cx
+%idefine _dx dx
+%idefine _si si
+%idefine _di di
+%idefine _bp bp
+%idefine _sp sp
+%idefine _es es:
+%idefine UCHAR BYTE ; Size of a character
+%idefine USHORT WORD ; Size of a short
+%idefine UINT WORD ; Size of an integer
+%idefine ULONG DWORD ; Size of a long
+%idefine BOOL WORD ; Size of a boolean
+%idefine DPTR DWORD ; Size of a data pointer
+%idefine FDPTR DWORD ; Size of a far data pointer
+%idefine NDPTR WORD ; Size of a near data pointer
+%idefine CPTR DWORD ; Size of a code pointer
+%idefine FCPTR DWORD ; Size of a far code pointer
+%idefine NCPTR WORD ; Size of a near code pointer
+%idefine FPTR FAR ; Distance for function pointers
+%idefine DUINT dw ; Declare a integer variable
+%idefine intsize 2
+%endif
+%idefine invert ~
+%idefine offset
+%idefine use_nasm
+
+; Convert all jumps to near jumps, since NASM does not so this automatically
+
+%idefine jo jo near
+%idefine jno jno near
+%idefine jz jz near
+%idefine jnz jnz near
+%idefine je je near
+%idefine jne jne near
+%idefine jb jb near
+%idefine jbe jbe near
+%idefine ja ja near
+%idefine jae jae near
+%idefine jl jl near
+%idefine jle jle near
+%idefine jg jg near
+%idefine jge jge near
+%idefine jc jc near
+%idefine jnc jnc near
+%idefine js js near
+%idefine jns jns near
+
+%ifdef DOUBLE
+%idefine REAL QWORD
+%idefine DREAL dq
+%else
+%idefine REAL DWORD
+%idefine DREAL dd
+%endif
+
+; Boolean truth values (same as those in debug.h)
+
+%idefine False 0
+%idefine True 1
+%idefine No 0
+%idefine Yes 1
+%idefine Yes 1
+
+; Macro to be invoked at the start of all modules to set up segments for
+; later use. Does nothing for NASM.
+
+%imacro header 1
+%endmacro
+
+; Macro to begin a data segment
+
+%imacro begdataseg 1
+%ifdef __GNUC__
+segment .data public class=DATA use32 flat
+%else
+%ifdef flatmodel
+segment _DATA public align=4 class=DATA use32 flat
+%else
+segment _DATA public align=4 class=DATA use16
+%endif
+%endif
+%endmacro
+
+; Macro to end a data segment
+
+%imacro enddataseg 1
+%endmacro
+
+; Macro to begin a code segment
+
+%imacro begcodeseg 1
+%ifdef __GNUC__
+segment .text public class=CODE use32 flat
+%else
+%ifdef flatmodel
+segment _TEXT public align=16 class=CODE use32 flat
+%else
+segment %1_TEXT public align=16 class=CODE use16
+%endif
+%endif
+%endmacro
+
+; Macro to begin a near code segment
+
+%imacro begcodeseg_near 0
+%ifdef __GNUC__
+segment .text public class=CODE use32 flat
+%else
+%ifdef flatmodel
+segment _TEXT public align=16 class=CODE use32 flat
+%else
+segment _TEXT public align=16 class=CODE use16
+%endif
+%endif
+%endmacro
+
+; Macro to end a code segment
+
+%imacro endcodeseg 1
+%endmacro
+
+; Macro to end a near code segment
+
+%imacro endcodeseg_near 0
+%endmacro
+
+; Macro for an extern C symbol. If the C compiler requires leading
+; underscores, then the underscores are added to the symbol names, otherwise
+; they are left off. The symbol name is referenced in the assembler code
+; using the non-underscored symbol name.
+
+%imacro cextern 2
+%ifdef __NOU_VAR__
+extern %1
+%else
+extern _%1
+%define %1 _%1
+%endif
+%endmacro
+
+%imacro cexternfunc 2
+%ifdef __NOU__
+extern %1
+%else
+extern _%1
+%define %1 _%1
+%endif
+%endmacro
+
+; Macro for a public C symbol. If the C compiler requires leading
+; underscores, then the underscores are added to the symbol names, otherwise
+; they are left off. The symbol name is referenced in the assembler code
+; using the non-underscored symbol name.
+
+%imacro cpublic 1
+%ifdef __NOU_VAR__
+global %1
+%1:
+%else
+global _%1
+_%1:
+%define %1 _%1
+%endif
+%endmacro
+
+; Macro for an global C symbol. If the C compiler requires leading
+; underscores, then the underscores are added to the symbol names, otherwise
+; they are left off. The symbol name is referenced in the assembler code
+; using the non-underscored symbol name.
+
+%imacro cglobal 1
+%ifdef __NOU_VAR__
+global %1
+%else
+global _%1
+%define %1 _%1
+%endif
+%endmacro
+
+; Macro for an global C function symbol. If the C compiler requires leading
+; underscores, then the underscores are added to the symbol names, otherwise
+; they are left off. The symbol name is referenced in the assembler code
+; using the non-underscored symbol name.
+
+%imacro cglobalfunc 1
+%ifdef __NOU__
+global %1
+%else
+global _%1
+%define %1 _%1
+%endif
+%endmacro
+
+; Macro to start a C callable function. This will be a far function for
+; 16-bit code, and a near function for 32-bit code.
+
+%imacro cprocstatic 1
+%push cproc
+%1:
+%ifdef flatmodel
+%stacksize flat
+%define ret retn
+%else
+%stacksize large
+%define ret retf
+%endif
+%assign %$localsize 0
+%endmacro
+
+%imacro cprocstart 1
+%push cproc
+ cglobalfunc %1
+%1:
+%ifdef flatmodel
+%stacksize flat
+%define ret retn
+%else
+%stacksize large
+%define ret retf
+%endif
+%assign %$localsize 0
+%endmacro
+
+; This macro sets up a procedure to be exported from a 16 bit DLL. Since the
+; calling conventions are always _far _pascal for 16 bit DLL's, we actually
+; rename this routine with an extra underscore with 'C' calling conventions
+; and a small DLL stub will be provided by the high level code to call the
+; assembler routine.
+
+%imacro cprocstartdll16 1
+%ifdef __WINDOWS16__
+cprocstart _%1
+%else
+cprocstart %1
+%endif
+%endmacro
+
+; Macro to start a C callable near function.
+
+%imacro cprocnear 1
+%push cproc
+ cglobalfunc %1
+%1:
+%define ret retn
+%ifdef flatmodel
+%stacksize flat
+%else
+%stacksize small
+%endif
+%assign %$localsize 0
+%endmacro
+
+; Macro to start a C callable far function.
+
+%imacro cprocfar 1
+%push cproc
+ cglobalfunc %1
+%1:
+%define ret retf
+%ifdef flatmodel
+%stacksize flat
+%else
+%stacksize large
+%endif
+%assign %$localsize 0
+%endmacro
+
+; Macro to end a C function
+
+%imacro cprocend 0
+%pop
+%endmacro
+
+; Macros for entering and exiting C callable functions. Note that we must
+; always save and restore the SI and DI registers for C functions, and for
+; 32 bit C functions we also need to save and restore EBX and clear the
+; direction flag.
+
+%imacro enter_c 0
+ push _bp
+ mov _bp,_sp
+%ifnidn %$localsize,0
+ sub _sp,%$localsize
+%endif
+%ifdef flatmodel
+ push ebx
+%endif
+ push _si
+ push _di
+%endmacro
+
+%imacro leave_c 0
+ pop _di
+ pop _si
+%ifdef flatmodel
+ pop ebx
+ cld
+%endif
+%ifnidn %$localsize,0
+ mov _sp,_bp
+%endif
+ pop _bp
+%endmacro
+
+%imacro use_ebx 0
+%ifdef flatmodel
+ push ebx
+%endif
+%endmacro
+
+%imacro unuse_ebx 0
+%ifdef flatmodel
+ pop ebx
+%endif
+%endmacro
+
+; Macros for saving and restoring the value of DS,ES,FS,GS when it is to
+; be used in assembly routines. This evaluates to nothing in the flat memory
+; model, but is saves and restores DS in the large memory model.
+
+%imacro use_ds 0
+%ifndef flatmodel
+ push ds
+%endif
+%endmacro
+
+%imacro unuse_ds 0
+%ifndef flatmodel
+ pop ds
+%endif
+%endmacro
+
+%imacro use_es 0
+%ifndef flatmodel
+ push es
+%endif
+%endmacro
+
+%imacro unuse_es 0
+%ifndef flatmodel
+ pop es
+%endif
+%endmacro
+
+; Macros for loading the address of a data pointer into a segment and
+; index register pair. The %imacro explicitly loads DS or ES in the 16 bit
+; memory model, or it simply loads the offset into the register in the flat
+; memory model since DS and ES always point to all addressable memory. You
+; must use the correct _REG (ie: _BX) %imacros for documentation purposes.
+
+%imacro _lds 2
+%ifdef flatmodel
+ mov %1,%2
+%else
+ lds %1,%2
+%endif
+%endmacro
+
+%imacro _les 2
+%ifdef flatmodel
+ mov %1,%2
+%else
+ les %1,%2
+%endif
+%endmacro
+
+; Macros for adding and subtracting a value from registers. Two value are
+; provided, one for 16 bit modes and another for 32 bit modes (the extended
+; register is used in 32 bit modes).
+
+%imacro _add 3
+%ifdef flatmodel
+ add e%1, %3
+%else
+ add %1, %2
+%endif
+%endmacro
+
+%imacro _sub 3
+%ifdef flatmodel
+ sub e%1, %3
+%else
+ sub %1, %2
+%endif
+%endmacro
+
+; Macro to clear the high order word for the 32 bit extended registers.
+; This is used to convert an unsigned 16 bit value to an unsigned 32 bit
+; value, and will evaluate to nothing in 16 bit modes.
+
+%imacro clrhi 1
+%ifdef flatmodel
+ movzx e%1,%1
+%endif
+%endmacro
+
+%imacro sgnhi 1
+%ifdef flatmodel
+ movsx e%1,%1
+%endif
+%endmacro
+
+; Macro to load an extended register with an integer value in either mode
+
+%imacro loadint 2
+%ifdef flatmodel
+ mov e%1,%2
+%else
+ xor e%1,e%1
+ mov %1,%2
+%endif
+%endmacro
+
+; Macros to load and store integer values with string instructions
+
+%imacro LODSINT 0
+%ifdef flatmodel
+ lodsd
+%else
+ lodsw
+%endif
+%endmacro
+
+%imacro STOSINT 0
+%ifdef flatmodel
+ stosd
+%else
+ stosw
+%endif
+%endmacro
+
+; Macros to provide resb, resw, resd compatibility with NASM
+
+%imacro dclb 1
+times %1 db 0
+%endmacro
+
+%imacro dclw 1
+times %1 dw 0
+%endmacro
+
+%imacro dcld 1
+times %1 dd 0
+%endmacro
+
+; macros to declare assembler function stubs for function structures
+
+%imacro BEGIN_STUBS_DEF 2
+begdataseg _STUBS
+%ifdef __NOU_VAR__
+extern %1
+%define STUBS_START %1
+%else
+extern _%1
+%define STUBS_START _%1
+%endif
+enddataseg _STUBS
+begcodeseg _STUBS
+%assign off %2
+%endmacro
+
+%imacro DECLARE_STUB 1
+%ifdef __NOU__
+ global %1
+%1:
+%else
+ global _%1
+_%1:
+%endif
+ jmp [DWORD STUBS_START+off]
+%assign off off+4
+%endmacro
+
+%imacro DECLARE_STDCALL 2
+%ifdef STDCALL_MANGLE
+ global _%1@%2
+_%1@%2:
+%else
+%ifdef __GNUC__
+ global _%1
+_%1:
+%else
+ global %1
+%1:
+%endif
+%endif
+ jmp [DWORD STUBS_START+off]
+%assign off off+4
+%endmacro
+
+%imacro END_STUBS_DEF 0
+endcodeseg _STUBS
+%endmacro
+
+; macros to declare assembler import stubs for binary loadable drivers
+
+%imacro BEGIN_IMPORTS_DEF 1
+BEGIN_STUBS_DEF %1,4
+%endmacro
+
+%imacro DECLARE_IMP 1
+DECLARE_STUB %1
+%endmacro
+
+%imacro END_IMPORTS_DEF 0
+END_STUBS_DEF
+%endmacro
+
+else ; __NASM_MAJOR__
+
+;============================================================================
+; Macro package when compiling with TASM.
+;============================================================================
+
+; Turn off underscores for globals if disabled for all externals
+
+ifdef __NOU__
+__NOU_VAR__ = 1
+endif
+
+; Define the __WINDOWS__ symbol if we are compiling for any Windows
+; environment
+
+ifdef __WINDOWS16__
+__WINDOWS__ = 1
+endif
+ifdef __WINDOWS32__
+__WINDOWS__ = 1
+__WINDOWS32_386__ = 1
+endif
+ifdef __WIN386__
+__WINDOWS__ = 1
+__WINDOWS32_386__ = 1
+endif
+ifdef __VXD__
+__WINDOWS__ = 1
+__WINDOWS32_386__ = 1
+ MASM
+ .386
+ NO_SEGMENTS = 1
+ include vmm.inc ; IGNORE DEPEND
+ include vsegment.inc ; IGNORE DEPEND
+ IDEAL
+endif
+
+; Macros for accessing 'generic' registers
+
+ifdef __FLAT__
+ _ax EQU eax ; EAX is used for accumulator
+ _bx EQU ebx ; EBX is used for accumulator
+ _cx EQU ecx ; ECX is used for looping
+ _dx EQU edx ; EDX is used for data register
+ _si EQU esi ; ESI is the source index register
+ _di EQU edi ; EDI is the destination index register
+ _bp EQU ebp ; EBP is used for base pointer register
+ _sp EQU esp ; ESP is used for stack pointer register
+ _es EQU ; ES and DS are the same in 32 bit PM
+ typedef UCHAR BYTE ; Size of a character
+ typedef USHORT WORD ; Size of a short
+ typedef UINT DWORD ; Size of an integer
+ typedef ULONG DWORD ; Size of a long
+ typedef BOOL DWORD ; Size of a boolean
+ typedef DPTR DWORD ; Size of a data pointer
+ typedef FDPTR FWORD ; Size of a far data pointer
+ typedef NDPTR DWORD ; Size of a near data pointer
+ typedef CPTR DWORD ; Size of a code pointer
+ typedef FCPTR FWORD ; Size of a far code pointer
+ typedef NCPTR DWORD ; Size of a near code pointer
+ typedef DUINT DWORD ; Declare a integer variable
+ FPTR EQU NEAR ; Distance for function pointers
+ intsize = 4 ; Size of an integer
+ flatmodel = 1 ; This is a flat memory model
+ P386 ; Turn on 386 code generation
+ MODEL FLAT ; Set up for 32 bit simplified FLAT model
+else
+ _ax EQU ax ; AX is used for accumulator
+ _bx EQU bx ; BX is used for accumulator
+ _cx EQU cx ; CX is used for looping
+ _dx EQU dx ; DX is used for data register
+ _si EQU si ; SI is the source index register
+ _di EQU di ; DI is the destination index register
+ _bp EQU bp ; BP is used for base pointer register
+ _sp EQU sp ; SP is used for stack pointer register
+ _es EQU es: ; ES is used for segment override
+ typedef UCHAR BYTE ; Size of a character
+ typedef USHORT WORD ; Size of a short
+ typedef UINT WORD ; Size of an integer
+ typedef ULONG DWORD ; Size of a long
+ typedef BOOL WORD ; Size of a boolean
+ typedef DPTR DWORD ; Size of a data pointer
+ typedef FDPTR DWORD ; Size of a far data pointer
+ typedef NDPTR WORD ; Size of a near data pointer
+ typedef CPTR DWORD ; Size of a code pointer
+ typedef FCPTR DWORD ; Size of a far code pointer
+ typedef NCPTR WORD ; Size of a near code pointer
+ typedef DUINT WORD ; Declare a integer variable
+ FPTR EQU FAR ; Distance for function pointers
+ intsize = 2 ; Size of an integer
+ P386 ; Turn on 386 code generation
+endif
+ invert EQU not
+
+; Provide a typedef for real floating point numbers
+
+ifdef DOUBLE
+typedef REAL QWORD
+typedef DREAL QWORD
+else
+typedef REAL DWORD
+typedef DREAL DWORD
+endif
+
+; Macros to access the floating point stack registers to convert them
+; from NASM style to TASM style
+
+st0 EQU st(0)
+st1 EQU st(1)
+st2 EQU st(2)
+st3 EQU st(3)
+st4 EQU st(4)
+st5 EQU st(5)
+st6 EQU st(6)
+st7 EQU st(7)
+st8 EQU st(8)
+
+; Boolean truth values (same as those in debug.h)
+
+ifndef __VXD__
+False = 0
+True = 1
+No = 0
+Yes = 1
+Yes = 1
+endif
+
+; Macros for the _DATA data segment. This segment contains initialised data.
+
+MACRO begdataseg name
+ifdef __VXD__
+ MASM
+VXD_LOCKED_DATA_SEG
+ IDEAL
+else
+ifdef flatmodel
+ DATASEG
+else
+SEGMENT _DATA DWORD PUBLIC USE16 'DATA'
+endif
+endif
+ENDM
+
+MACRO enddataseg name
+ifdef __VXD__
+ MASM
+VXD_LOCKED_DATA_ENDS
+ IDEAL
+else
+ifndef flatmodel
+ENDS _DATA
+endif
+endif
+ENDM
+
+; Macro for the main code segment.
+
+MACRO begcodeseg name
+ifdef __VXD__
+ MASM
+VXD_LOCKED_CODE_SEG
+ IDEAL
+else
+ifdef flatmodel
+ CODESEG
+ ASSUME CS:FLAT,DS:FLAT,SS:FLAT
+else
+SEGMENT &name&_TEXT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:&name&_TEXT,DS:_DATA
+endif
+endif
+ENDM
+
+; Macro for a near code segment
+
+MACRO begcodeseg_near
+ifdef flatmodel
+ CODESEG
+ ASSUME CS:FLAT,DS:FLAT,SS:FLAT
+else
+SEGMENT _TEXT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:_TEXT,DS:_DATA
+endif
+ENDM
+
+MACRO endcodeseg name
+ifdef __VXD__
+ MASM
+VXD_LOCKED_CODE_ENDS
+ IDEAL
+else
+ifndef flatmodel
+ENDS &name&_TEXT
+endif
+endif
+ENDM
+
+MACRO endcodeseg_near
+ifndef flatmodel
+ENDS _TEXT
+endif
+ENDM
+
+; Macro to be invoked at the start of all modules to set up segments for
+; later use.
+
+MACRO header name
+begdataseg name
+enddataseg name
+ENDM
+
+; Macro for an extern C symbol. If the C compiler requires leading
+; underscores, then the underscores are added to the symbol names, otherwise
+; they are left off. The symbol name is referenced in the assembler code
+; using the non-underscored symbol name.
+
+MACRO cextern name,size
+ifdef __NOU_VAR__
+ EXTRN name:size
+else
+ EXTRN _&name&:size
+name EQU _&name&
+endif
+ENDM
+
+MACRO cexternfunc name,size
+ifdef __NOU__
+ EXTRN name:size
+else
+ EXTRN _&name&:size
+name EQU _&name&
+endif
+ENDM
+
+MACRO stdexternfunc name,args,size
+ifdef STDCALL_MANGLE
+ EXTRN _&name&@&num_args&:size
+name EQU _&name&@&num_args
+else
+ EXTRN name:size
+endif
+ENDM
+
+; Macro for a public C symbol. If the C compiler requires leading
+; underscores, then the underscores are added to the symbol names, otherwise
+; they are left off. The symbol name is referenced in the assembler code
+; using the non-underscored symbol name.
+
+MACRO cpublic name
+ifdef __NOU_VAR__
+name:
+ PUBLIC name
+else
+_&name&:
+ PUBLIC _&name&
+name EQU _&name&
+endif
+ENDM
+
+; Macro for an global C symbol. If the C compiler requires leading
+; underscores, then the underscores are added to the symbol names, otherwise
+; they are left off. The symbol name is referenced in the assembler code
+; using the non-underscored symbol name.
+
+MACRO cglobal name
+ifdef __NOU_VAR__
+ PUBLIC name
+else
+ PUBLIC _&name&
+name EQU _&name&
+endif
+ENDM
+
+; Macro for an global C function symbol. If the C compiler requires leading
+; underscores, then the underscores are added to the symbol names, otherwise
+; they are left off. The symbol name is referenced in the assembler code
+; using the non-underscored symbol name.
+
+MACRO cglobalfunc name
+ifdef __NOU__
+ PUBLIC name
+else
+ PUBLIC _&name&
+name EQU _&name&
+endif
+ENDM
+
+; Macro to start a C callable function. This will be a far function for
+; 16-bit code, and a near function for 32-bit code.
+
+MACRO cprocstatic name ; Set up model independant private proc
+ifdef flatmodel
+PROC name NEAR
+else
+PROC name FAR
+endif
+LocalSize = 0
+ENDM
+
+MACRO cprocstart name ; Set up model independant proc
+ifdef flatmodel
+ifdef __NOU__
+PROC name NEAR
+else
+PROC _&name& NEAR
+endif
+else
+ifdef __NOU__
+PROC name FAR
+else
+PROC _&name& FAR
+endif
+endif
+LocalSize = 0
+ cglobalfunc name
+ENDM
+
+MACRO cprocnear name ; Set up near proc
+ifdef __NOU__
+PROC name NEAR
+else
+PROC _&name& NEAR
+endif
+LocalSize = 0
+ cglobalfunc name
+ENDM
+
+MACRO cprocfar name ; Set up far proc
+ifdef __NOU__
+PROC name FAR
+else
+PROC _&name& FAR
+endif
+LocalSize = 0
+ cglobalfunc name
+ENDM
+
+MACRO cprocend ; End procedure macro
+ENDP
+ENDM
+
+; This macro sets up a procedure to be exported from a 16 bit DLL. Since the
+; calling conventions are always _far _pascal for 16 bit DLL's, we actually
+; rename this routine with an extra underscore with 'C' calling conventions
+; and a small DLL stub will be provided by the high level code to call the
+; assembler routine.
+
+MACRO cprocstartdll16 name
+ifdef __WINDOWS16__
+cprocstart _&name&
+else
+cprocstart name
+endif
+ENDM
+
+; Macros for entering and exiting C callable functions. Note that we must
+; always save and restore the SI and DI registers for C functions, and for
+; 32 bit C functions we also need to save and restore EBX and clear the
+; direction flag.
+
+MACRO save_c_regs
+ifdef flatmodel
+ push ebx
+endif
+ push _si
+ push _di
+ENDM
+
+MACRO enter_c
+ push _bp
+ mov _bp,_sp
+ IFDIFI <LocalSize>,<0>
+ sub _sp,LocalSize
+ ENDIF
+ save_c_regs
+ENDM
+
+MACRO restore_c_regs
+ pop _di
+ pop _si
+ifdef flatmodel
+ pop ebx
+endif
+ENDM
+
+MACRO leave_c
+ restore_c_regs
+ cld
+ IFDIFI <LocalSize>,<0>
+ mov _sp,_bp
+ ENDIF
+ pop _bp
+ENDM
+
+MACRO use_ebx
+ifdef flatmodel
+ push ebx
+endif
+ENDM
+
+MACRO unuse_ebx
+ifdef flatmodel
+ pop ebx
+endif
+ENDM
+
+; Macros for saving and restoring the value of DS,ES,FS,GS when it is to
+; be used in assembly routines. This evaluates to nothing in the flat memory
+; model, but is saves and restores DS in the large memory model.
+
+MACRO use_ds
+ifndef flatmodel
+ push ds
+endif
+ENDM
+
+MACRO unuse_ds
+ifndef flatmodel
+ pop ds
+endif
+ENDM
+
+MACRO use_es
+ifndef flatmodel
+ push es
+endif
+ENDM
+
+MACRO unuse_es
+ifndef flatmodel
+ pop es
+endif
+ENDM
+
+; Macros for loading the address of a data pointer into a segment and
+; index register pair. The macro explicitly loads DS or ES in the 16 bit
+; memory model, or it simply loads the offset into the register in the flat
+; memory model since DS and ES always point to all addressable memory. You
+; must use the correct _REG (ie: _BX) macros for documentation purposes.
+
+MACRO _lds reg, addr
+ifdef flatmodel
+ mov reg,addr
+else
+ lds reg,addr
+endif
+ENDM
+
+MACRO _les reg, addr
+ifdef flatmodel
+ mov reg,addr
+else
+ les reg,addr
+endif
+ENDM
+
+; Macros for adding and subtracting a value from registers. Two value are
+; provided, one for 16 bit modes and another for 32 bit modes (the extended
+; register is used in 32 bit modes).
+
+MACRO _add reg, val16, val32
+ifdef flatmodel
+ add e&reg&, val32
+else
+ add reg, val16
+endif
+ENDM
+
+MACRO _sub reg, val16, val32
+ifdef flatmodel
+ sub e&reg&, val32
+else
+ sub reg, val16
+endif
+ENDM
+
+; Macro to clear the high order word for the 32 bit extended registers.
+; This is used to convert an unsigned 16 bit value to an unsigned 32 bit
+; value, and will evaluate to nothing in 16 bit modes.
+
+MACRO clrhi reg
+ifdef flatmodel
+ movzx e&reg&,reg
+endif
+ENDM
+
+MACRO sgnhi reg
+ifdef flatmodel
+ movsx e&reg&,reg
+endif
+ENDM
+
+; Macro to load an extended register with an integer value in either mode
+
+MACRO loadint reg,val
+ifdef flatmodel
+ mov e&reg&,val
+else
+ xor e&reg&,e&reg&
+ mov reg,val
+endif
+ENDM
+
+; Macros to load and store integer values with string instructions
+
+MACRO LODSINT
+ifdef flatmodel
+ lodsd
+else
+ lodsw
+endif
+ENDM
+
+MACRO STOSINT
+ifdef flatmodel
+ stosd
+else
+ stosw
+endif
+ENDM
+
+; Macros to provide resb, resw, resd compatibility with NASM
+
+MACRO dclb count
+db count dup (0)
+ENDM
+
+MACRO dclw count
+dw count dup (0)
+ENDM
+
+MACRO dcld count
+dd count dup (0)
+ENDM
+
+; Macros to provide resb, resw, resd compatibility with NASM
+
+MACRO resb count
+db count dup (?)
+ENDM
+
+MACRO resw count
+dw count dup (?)
+ENDM
+
+MACRO resd count
+dd count dup (?)
+ENDM
+
+; Macros to declare assembler stubs for function structures
+
+MACRO BEGIN_STUBS_DEF name, firstOffset
+begdataseg _STUBS
+ifdef __NOU_VAR__
+ EXTRN name:DWORD
+STUBS_START = name
+else
+ EXTRN _&name&:DWORD
+name EQU _&name&
+STUBS_START = _&name
+endif
+enddataseg _STUBS
+begcodeseg _STUBS
+off = firstOffset
+ENDM
+
+MACRO DECLARE_STUB name
+ifdef __NOU__
+name:
+ PUBLIC name
+else
+_&name:
+ PUBLIC _&name
+endif
+ jmp [DWORD STUBS_START+off]
+off = off + 4
+ENDM
+
+MACRO DECLARE_STDCALL name,num_args
+ifdef STDCALL_MANGLE
+_&name&@&num_args&:
+ PUBLIC _&name&@&num_args&
+else
+name:
+ PUBLIC name
+endif
+ jmp [DWORD STUBS_START+off]
+off = off + 4
+ENDM
+
+MACRO END_STUBS_DEF
+endcodeseg _STUBS
+ENDM
+
+MACRO BEGIN_IMPORTS_DEF name
+BEGIN_STUBS_DEF name,4
+ENDM
+
+MACRO DECLARE_IMP name
+DECLARE_STUB name
+ENDM
+
+MACRO END_IMPORTS_DEF
+END_STUBS_DEF
+ENDM
+
+endif
diff --git a/nasm.c b/nasm.c
index 1123ee3..cd7f714 100644
--- a/nasm.c
+++ b/nasm.c
@@ -38,9 +38,8 @@ static void register_output_formats(void);
static void usage(void);
static int using_debug_info;
-#ifdef TASM_COMPAT
int tasm_compatible_mode = FALSE;
-#endif
+int pass0;
static char inname[FILENAME_MAX];
static char outname[FILENAME_MAX];
@@ -131,7 +130,7 @@ static int want_usage;
static int terminate_after_phase;
int user_nolist = 0; /* fbk 9/2/00 */
-static void nasm_fputs(char *line, FILE *ofile)
+static void nasm_fputs(char *line, FILE *ofile)
{
if (ofile) {
fputs(line, ofile);
@@ -140,7 +139,7 @@ static void nasm_fputs(char *line, FILE *ofile)
puts(line);
}
-int main(int argc, char **argv)
+int main(int argc, char **argv)
{
pass0 = 1;
want_usage = terminate_after_phase = FALSE;
@@ -151,7 +150,7 @@ int main(int argc, char **argv)
preproc = &nasmpp;
operating_mode = op_normal;
-
+
error_file = stderr;
seg_init();
@@ -160,7 +159,7 @@ int main(int argc, char **argv)
parse_cmdline(argc, argv);
- if (terminate_after_phase)
+ if (terminate_after_phase)
{
if (want_usage)
usage();
@@ -201,7 +200,7 @@ int main(int argc, char **argv)
char *file_name = NULL;
long prior_linnum=0;
int lineinc=0;
-
+
if (*outname) {
ofile = fopen(outname, "w");
if (!ofile)
@@ -209,9 +208,9 @@ int main(int argc, char **argv)
"unable to open output file `%s'", outname);
} else
ofile = NULL;
-
+
location.known = FALSE;
-
+
/* pass = 1; */
preproc->reset (inname, 2, report_error, evaluate, &nasmlist);
while ( (line = preproc->getline()) ) {
@@ -280,7 +279,7 @@ int main(int argc, char **argv)
* so we're leaving out the one here.
* fclose (ofile);
*/
-
+
remove(outname);
if (listname[0])
remove(listname);
@@ -288,10 +287,10 @@ int main(int argc, char **argv)
}
break;
}
-
+
if (want_usage)
usage();
-
+
raa_free (offsets);
saa_free (forwrefs);
eval_cleanup ();
@@ -354,7 +353,7 @@ static int process_arg (char *p, char *q)
if (!p || !p[0])
return 0;
- if (p[0]=='-' && ! stopoptions)
+ if (p[0]=='-' && ! stopoptions)
{
switch (p[1]) {
case 's':
@@ -364,9 +363,11 @@ static int process_arg (char *p, char *q)
case 'O':
case 'f':
case 'p':
+ case 'P':
case 'd':
case 'D':
case 'i':
+ case 'I':
case 'l':
case 'E':
case 'F':
@@ -425,20 +426,18 @@ static int process_arg (char *p, char *q)
printf("usage: nasm [-@ response file] [-o outfile] [-f format] "
"[-l listfile]\n"
" [options...] [--] filename\n"
- " or nasm -r for version info\n\n"
-#ifdef TASM_COMPAT
+ " or nasm -r for version info (obsolete)\n"
+ " or nasm -v for version info (preferred)\n\n"
" -t Assemble in SciTech TASM compatible mode\n"
" -g Generate debug information in selected format.\n"
-#endif
" -e preprocess only (writes output to stdout by default)\n"
" -a don't preprocess (assemble only)\n"
" -M generate Makefile dependencies on stdout\n\n"
" -E<file> redirect error messages to file\n"
" -s redirect error messages to stdout\n\n"
- " -g enable debug info\n"
" -F format select a debugging format\n\n"
" -I<path> adds a pathname to the include file path\n"
- " -O<digit> optimize branch offsets -O0 disables, -O2 default\n"
+ " -O<digit> optimize branch offsets (-O0 disables, default)\n"
" -P<file> pre-includes a file\n"
" -D<macro>[=<value>] pre-defines a macro\n"
" -U<macro> undefines a macro\n"
@@ -468,20 +467,16 @@ static int process_arg (char *p, char *q)
dfmt_list(ofmt, stdout);
exit(0);
break;
-#ifdef TASM_COMPAT
case 't':
tasm_compatible_mode = TRUE;
break;
-#endif
case 'r':
-#ifdef TASM_COMPAT
- printf("NASM version %s - SciTech TASM compatible additions\n", NASM_VER);
-#else
- printf("NASM version %s\n", NASM_VER);
-#endif
+ case 'v':
+ printf("NASM version %s compiled "
#ifdef DEBUG
- printf("Compiled with -DDEBUG on " __DATE__ "\n");
+ "with -DDEBUG "
#endif
+ "on " __DATE__ "\n", NASM_VER);
exit (0); /* never need usage message here */
break;
case 'e': /* preprocess only */
@@ -507,7 +502,7 @@ static int process_arg (char *p, char *q)
break;
case 'M':
operating_mode = op_depend;
- break;
+ break;
case '-':
{
@@ -575,8 +570,8 @@ static int process_arg (char *p, char *q)
p[1]);
break;
}
- }
- else
+ }
+ else
{
if (*inname) {
report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
@@ -655,7 +650,6 @@ static void process_respfile (FILE *rfile)
* argv array. Used by the environment variable and response file
* processing.
*/
-#ifdef TASM_COMPAT
static void process_args (char *args) {
char *p, *q, *arg, *prevarg;
char separator = ' ';
@@ -676,16 +670,11 @@ static void process_args (char *args) {
if (arg)
process_arg (arg, NULL);
}
-#endif
static void parse_cmdline(int argc, char **argv)
{
FILE *rfile;
char *envreal, *envcopy=NULL, *p, *arg;
-#ifndef TASM_COMPAT
- char *q, *prevarg;
- char separator = ' ';
-#endif
*inname = *outname = *listname = '\0';
@@ -696,24 +685,7 @@ static void parse_cmdline(int argc, char **argv)
arg = NULL;
if (envreal) {
envcopy = nasm_strdup(envreal);
-#ifdef TASM_COMPAT
process_args(envcopy);
-#else
- p = envcopy;
- if (*p && *p != '-')
- separator = *p++;
- while (*p) {
- q = p;
- while (*p && *p != separator) p++;
- while (*p == separator) *p++ = '\0';
- prevarg = arg;
- arg = q;
- if (process_arg (prevarg, arg))
- arg = NULL;
- }
- if (arg)
- process_arg (arg, NULL);
-#endif
nasm_free (envcopy);
}
@@ -724,7 +696,6 @@ static void parse_cmdline(int argc, char **argv)
{
int i;
argv++;
-#ifdef TASM_COMPAT
if (argv[0][0] == '@') {
/* We have a response file, so process this as a set of
* arguments like the environment variable. This allows us
@@ -748,7 +719,6 @@ static void parse_cmdline(int argc, char **argv)
argc--;
argv++;
}
-#endif
if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@') {
if ((p = get_param (argv[0], argc > 1 ? argv[1] : NULL, &i))) {
if ((rfile = fopen(p, "r"))) {
@@ -793,9 +763,9 @@ static void assemble_file (char *fname)
pass1 = pass < pass_max ? 1 : 2; /* seq is 1, 1, 1,..., 1, 2 */
pass2 = pass > 1 ? 2 : 1; /* seq is 1, 2, 2,..., 2, 2 */
/* pass0 seq is 0, 0, 0,..., 1, 2 */
-
+
def_label = pass > 1 ? redefine_label : define_label;
-
+
sb = cmd_sb; /* set 'bits' to command line default */
cpu = cmd_cpu;
@@ -817,13 +787,13 @@ static void assemble_file (char *fname)
if (pass == 1) location.known = TRUE;
location.offset = offs = GET_CURR_OFFS;
- while ( (line = preproc->getline()) )
+ while ( (line = preproc->getline()) )
{
globallineno++;
/* here we parse our directives; this is not handled by the 'real'
* parser. */
- if ( (i = getkw (line, &value)) )
+ if ( (i = getkw (line, &value)) )
{
switch (i) {
case 1: /* [SEGMENT n] */
@@ -1046,7 +1016,7 @@ static void assemble_file (char *fname)
break;
default:
if (!ofmt->directive (line+1, value, pass2))
- report_error (pass1==1 ? ERR_NONFATAL : ERR_PANIC,
+ report_error (pass1==1 ? ERR_NONFATAL : ERR_PANIC,
"unrecognised directive [%s]",
line+1);
}
@@ -1054,7 +1024,7 @@ static void assemble_file (char *fname)
else /* it isn't a directive */
{
parse_line (pass1, line, &output_ins,
- report_error, evaluate,
+ report_error, evaluate,
def_label);
if (!optimizing && pass == 2) {
@@ -1069,12 +1039,12 @@ static void assemble_file (char *fname)
}
- if (!optimizing && output_ins.forw_ref)
+ if (!optimizing && output_ins.forw_ref)
{
if (pass == 1) {
- for(i = 0; i < output_ins.operands; i++)
+ for(i = 0; i < output_ins.operands; i++)
{
- if (output_ins.oprs[i].opflags & OPFLAG_FORWARD)
+ if (output_ins.oprs[i].opflags & OPFLAG_FORWARD)
{
struct forwrefinfo *fwinf =
(struct forwrefinfo *)saa_wstruct(forwrefs);
@@ -1103,7 +1073,7 @@ static void assemble_file (char *fname)
*/
if (output_ins.operands >= 2 &&
- (output_ins.oprs[1].opflags & OPFLAG_FORWARD))
+ (output_ins.oprs[1].opflags & OPFLAG_FORWARD))
{
output_ins.oprs[1].type &= ~(ONENESS|BYTENESS);
}
@@ -1127,18 +1097,18 @@ static void assemble_file (char *fname)
else if (output_ins.label[0] != '.' ||
output_ins.label[1] != '.' ||
- output_ins.label[2] == '@')
+ output_ins.label[2] == '@')
{
if (output_ins.operands == 1 &&
(output_ins.oprs[0].type & IMMEDIATE) &&
- output_ins.oprs[0].wrt == NO_SEG)
+ output_ins.oprs[0].wrt == NO_SEG)
{
int isext = output_ins.oprs[0].opflags & OPFLAG_EXTERN;
def_label (output_ins.label,
output_ins.oprs[0].segment,
output_ins.oprs[0].offset,
NULL, FALSE, isext, ofmt, report_error);
- }
+ }
else if (output_ins.operands == 2 &&
(output_ins.oprs[0].type & IMMEDIATE) &&
(output_ins.oprs[0].type & COLON) &&
@@ -1146,13 +1116,13 @@ static void assemble_file (char *fname)
output_ins.oprs[0].wrt == NO_SEG &&
(output_ins.oprs[1].type & IMMEDIATE) &&
output_ins.oprs[1].segment == NO_SEG &&
- output_ins.oprs[1].wrt == NO_SEG)
+ output_ins.oprs[1].wrt == NO_SEG)
{
def_label (output_ins.label,
output_ins.oprs[0].offset | SEG_ABS,
output_ins.oprs[1].offset,
NULL, FALSE, FALSE, ofmt, report_error);
- }
+ }
else
report_error(ERR_NONFATAL, "bad syntax for EQU");
}
@@ -1163,7 +1133,7 @@ static void assemble_file (char *fname)
*/
if (output_ins.label[0] == '.' &&
output_ins.label[1] == '.' &&
- output_ins.label[2] != '@')
+ output_ins.label[2] != '@')
{
if (output_ins.operands == 1 &&
(output_ins.oprs[0].type & IMMEDIATE)) {
@@ -1171,19 +1141,19 @@ static void assemble_file (char *fname)
output_ins.oprs[0].segment,
output_ins.oprs[0].offset,
NULL, FALSE, FALSE, ofmt, report_error);
- }
+ }
else if (output_ins.operands == 2 &&
(output_ins.oprs[0].type & IMMEDIATE) &&
(output_ins.oprs[0].type & COLON) &&
output_ins.oprs[0].segment == NO_SEG &&
(output_ins.oprs[1].type & IMMEDIATE) &&
- output_ins.oprs[1].segment == NO_SEG)
+ output_ins.oprs[1].segment == NO_SEG)
{
define_label (output_ins.label,
output_ins.oprs[0].offset | SEG_ABS,
output_ins.oprs[1].offset,
NULL, FALSE, FALSE, ofmt, report_error);
- }
+ }
else
report_error(ERR_NONFATAL, "bad syntax for EQU");
}
@@ -1196,26 +1166,26 @@ static void assemble_file (char *fname)
&output_ins, report_error);
/* if (using_debug_info) && output_ins.opcode != -1)*/
- if (using_debug_info); /* fbk 12/29/00 */
+ if (using_debug_info) /* fbk 03/25/01 */
{
/* this is done here so we can do debug type info */
long typeinfo = TYS_ELEMENTS(output_ins.operands);
switch (output_ins.opcode) {
case I_RESB:
- typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_BYTE;
+ typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_BYTE;
break;
case I_RESW:
- typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_WORD;
+ typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_WORD;
break;
case I_RESD:
- typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_DWORD;
+ typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_DWORD;
break;
case I_RESQ:
- typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_QWORD;
+ typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_QWORD;
break;
case I_REST:
- typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_TBYTE;
+ typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_TBYTE;
break;
case I_DB:
typeinfo |= TY_BYTE;
@@ -1247,7 +1217,7 @@ static void assemble_file (char *fname)
offs += l;
SET_CURR_OFFS (offs);
}
- /*
+ /*
* else l == -1 => invalid instruction, which will be
* flagged as an error on pass 2
*/
@@ -1282,7 +1252,7 @@ static void assemble_file (char *fname)
pass0++;
if (pass0==2) pass = pass_max - 1;
} else if (!optimizing) pass0++;
-
+
} /* for (pass=1; pass<=2; pass++) */
nasmlist.cleanup();
@@ -1290,11 +1260,11 @@ static void assemble_file (char *fname)
if (optimizing && using_debug_info) /* -On and -g switches */
fprintf(error_file,
"info:: assembly required 1+%d+1 passes\n", pass_cnt-2);
-#endif
+#endif
} /* exit from assemble_file (...) */
-static int getkw (char *buf, char **value)
+static int getkw (char *buf, char **value)
{
char *p, *q;
@@ -1330,7 +1300,7 @@ static int getkw (char *buf, char **value)
while (*buf!=']') buf++;
*buf++ = '\0';
}
-#if 0
+#if 0
for (q=p; *q; q++)
*q = tolower(*q);
#endif
@@ -1357,7 +1327,7 @@ static int getkw (char *buf, char **value)
return -1;
}
-static void report_error (int severity, char *fmt, ...)
+static void report_error (int severity, char *fmt, ...)
{
va_list ap;
@@ -1397,7 +1367,7 @@ static void report_error (int severity, char *fmt, ...)
case ERR_DEBUG:
fputs("debug: ", error_file); break;
}
-
+
va_start (ap, fmt);
vfprintf (error_file, fmt, ap);
fputc ('\n', error_file);
@@ -1429,12 +1399,12 @@ static void report_error (int severity, char *fmt, ...)
}
}
-static void usage(void)
+static void usage(void)
{
fputs("type `nasm -h' for help\n", error_file);
}
-static void register_output_formats(void)
+static void register_output_formats(void)
{
ofmt = ofmt_register (report_error);
}
@@ -1447,7 +1417,7 @@ static ListGen *no_pp_list;
static long no_pp_lineinc;
static void no_pp_reset (char *file, int pass, efunc error, evalfunc eval,
- ListGen *listgen)
+ ListGen *listgen)
{
src_set_fname(nasm_strdup(file));
src_set_linnum(0);
@@ -1462,7 +1432,7 @@ static void no_pp_reset (char *file, int pass, efunc error, evalfunc eval,
(void) eval; /* placate compilers */
}
-static char *no_pp_getline (void)
+static char *no_pp_getline (void)
{
char *buffer, *p, *q;
int bufsize;
@@ -1521,20 +1491,20 @@ static char *no_pp_getline (void)
return buffer;
}
-static void no_pp_cleanup (void)
+static void no_pp_cleanup (void)
{
fclose(no_pp_fp);
}
static unsigned long get_cpu (char *value)
{
-
+
if (!strcmp(value, "8086")) return IF_8086;
if (!strcmp(value, "186")) return IF_186;
if (!strcmp(value, "286")) return IF_286;
if (!strcmp(value, "386")) return IF_386;
if (!strcmp(value, "486")) return IF_486;
- if (!strcmp(value, "586") ||
+ if (!strcmp(value, "586") ||
!nasm_stricmp(value, "pentium") ) return IF_PENT;
if (!strcmp(value, "686") ||
!nasm_stricmp(value, "ppro") ||
@@ -1543,7 +1513,7 @@ static unsigned long get_cpu (char *value)
!nasm_stricmp(value, "katmai") ) return IF_KATMAI;
report_error (pass0<2 ? ERR_NONFATAL : ERR_FATAL, "unknown 'cpu' type");
-
+
return IF_PLEVEL; /* the maximum level */
}
@@ -1551,7 +1521,7 @@ static unsigned long get_cpu (char *value)
static int get_bits (char *value)
{
int i;
-
+
if ((i = atoi(value)) == 16) return i; /* set for a 16-bit segment */
else if (i == 32) {
if (cpu < IF_386) {
diff --git a/nasm.h b/nasm.h
index 34ebacb..d4079dc 100644
--- a/nasm.h
+++ b/nasm.h
@@ -13,7 +13,7 @@
#define NASM_MAJOR_VER 0
#define NASM_MINOR_VER 98
-#define NASM_VER "0.98.08"
+#define NASM_VER "0.98.09"
#ifndef NULL
#define NULL 0
@@ -856,9 +856,7 @@ struct dfmt {
#define elements(x) ( sizeof(x) / sizeof(*(x)) )
-#ifdef TASM_COMPAT
extern int tasm_compatible_mode;
-#endif
/*
* This declaration passes the "pass" number to all other modules
@@ -868,6 +866,6 @@ extern int tasm_compatible_mode;
* 2 = pass 2
*/
-int pass0; /* this is globally known */
+extern int pass0; /* this is globally known */
#endif
diff --git a/nasmlib.c b/nasmlib.c
index 64f2b7f..f556d99 100644
--- a/nasmlib.c
+++ b/nasmlib.c
@@ -757,9 +757,9 @@ int stdscan (void *private_data, struct tokenval *tv)
if ((tv->t_integer=bsi(ourcopy, special_names,
elements(special_names)))>=0)
return tv->t_type = TOKEN_SPECIAL;
- if (!strcmp(ourcopy, "seg"))
+ if (!nasm_stricmp(ourcopy, "seg"))
return tv->t_type = TOKEN_SEG;
- if (!strcmp(ourcopy, "wrt"))
+ if (!nasm_stricmp(ourcopy, "wrt"))
return tv->t_type = TOKEN_WRT;
return tv->t_type = TOKEN_ID;
} else if (*stdscan_bufptr == '$' && !isnumchar(stdscan_bufptr[1])) {
diff --git a/outaout.c b/outaout.c
index 22ac229..b8e74be 100644
--- a/outaout.c
+++ b/outaout.c
@@ -825,10 +825,10 @@ static void aout_write_relocs (struct Reloc *r)
static void aout_write_syms (void)
{
- int i;
+ unsigned long i;
saa_rewind (syms);
- for (i=0; i<nsyms; i++) {
+ for (i = 0; i < nsyms; i++) {
struct Symbol *sym = saa_rstruct(syms);
fwritelong (sym->strpos, aoutfp);
fwritelong ((long)sym->type & ~SYM_WITH_SIZE, aoutfp);
diff --git a/outas86.c b/outas86.c
index eb02186..8c69567 100644
--- a/outas86.c
+++ b/outas86.c
@@ -350,7 +350,7 @@ static void as86_out (long segto, void *data, unsigned long type,
static void as86_write(void)
{
- int i;
+ unsigned long i;
long symlen, seglen, segsize;
/*
diff --git a/outbin.c b/outbin.c
index a3289cf..95ac5da 100644
--- a/outbin.c
+++ b/outbin.c
@@ -1,5 +1,5 @@
-/* outbin.c output routines for the Netwide Assembler to produce
- * flat-form binary files
+/* outbin.c output routines for the Netwide Assembler to produce
+ * flat-form binary files
*
* The Netwide Assembler is copyright (C) 1996 Simon Tatham and
* Julian Hall. All rights reserved. The software is
@@ -7,6 +7,13 @@
* distributed in the NASM archive.
*/
+/*
+ * version with multiple sections support
+ *
+ * sections go in order defined by their org's if present
+ * if no org present, sections go in sequence they appear.
+ */
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -22,11 +29,16 @@ static FILE *fp;
static efunc error;
static struct Section {
+ struct Section *next;
struct SAA *contents;
long length;
- long index;
-} textsect, datasect;
-static long bsslen, bssindex;
+ long org; /* assigned org */
+ long pos; /* file position of section ?? */
+ long pad; /* padding bytes to next section in file */
+ long index; /* the NASM section id */
+ long align; /* section alignment, cannot be absolute addr */
+ char *name;
+} *sections, **sectail;
static struct Reloc {
struct Reloc *next;
@@ -37,12 +49,10 @@ static struct Reloc {
struct Section *target;
} *relocs, **reloctail;
-static long data_align, bss_align;
-
-static long start_point;
+static long current_section;
static void add_reloc (struct Section *s, long bytes, long secref,
- long secrel)
+ long secrel)
{
struct Reloc *r;
@@ -56,307 +66,491 @@ static void add_reloc (struct Section *s, long bytes, long secref,
r->target = s;
}
-static void bin_init (FILE *afp, efunc errfunc, ldfunc ldef, evalfunc eval)
+static struct Section *find_section_by_name(char *name)
+{
+ struct Section *s;
+
+ for (s = sections; s; s = s->next)
+ if (!strcmp(s->name,name))
+ break;
+
+ return s;
+}
+
+static struct Section *find_section_by_index(long index)
+{
+ struct Section *s;
+
+ for (s = sections; s; s = s->next)
+ if ( s->index == index )
+ break;
+
+ return s;
+}
+
+static struct Section *alloc_section(char *name)
+{
+ struct Section *s;
+
+ s = find_section_by_name(name);
+ if(s)
+ error(ERR_PANIC, "section %s re-defined", name);
+
+ s = nasm_malloc(sizeof(struct Section));
+ *sectail = s;
+ sectail = &s->next;
+ s->next = NULL;
+
+ s->contents = saa_init(1L);
+ s->length = 0;
+ s->pos = 0;
+ s->org = -1; /* default org is -1 because we want
+ * to adjust sections one after another
+ */
+ s->index = seg_alloc();
+ s->align = 4;
+ s->pad = 0;
+ s->name = nasm_strdup(name);
+
+ return s;
+}
+
+static void bin_init (FILE *afp, efunc errfunc, ldfunc ldef, evalfunc eval)
{
fp = afp;
+ error = errfunc;
(void) eval; /* Don't warn that this parameter is unused */
+ (void) ldef; /* placate optimisers */
- error = errfunc;
- (void) ldef; /* placate optimisers */
-
- start_point = 0L; /* default */
- textsect.contents = saa_init(1L);
- datasect.contents = saa_init(1L);
- textsect.length = datasect.length = 0;
- textsect.index = seg_alloc();
- datasect.index = seg_alloc();
- bsslen = 0;
- bssindex = seg_alloc();
- relocs = NULL;
+ current_section = -1L;
+ relocs = NULL;
reloctail = &relocs;
- data_align = bss_align = 4;
+ sections = NULL;
+ sectail = &sections;
}
-static void bin_cleanup (int debuginfo)
+static void bin_cleanup (int debuginfo)
{
- struct Reloc *r;
- long datapos, datagap, bsspos;
-
- (void) debuginfo;
-
- datapos = start_point + textsect.length;
- datapos = (datapos + data_align-1) & ~(data_align-1);
- datagap = datapos - (start_point + textsect.length);
- bsspos = datapos + datasect.length;
- bsspos = (bsspos + bss_align-1) & ~(bss_align-1);
-
- saa_rewind (textsect.contents);
- saa_rewind (datasect.contents);
-
- for (r = relocs; r; r = r->next)
- {
- unsigned char *p, *q, mydata[4];
- long l;
-
- saa_fread (r->target->contents, r->posn, mydata, r->bytes);
- p = q = mydata;
- l = *p++;
- if (r->bytes > 1) {
- l += ((long)*p++) << 8;
- if (r->bytes == 4) {
- l += ((long)*p++) << 16;
- l += ((long)*p++) << 24;
- }
- }
-
- if (r->secref == textsect.index)
- l += start_point;
- else if (r->secref == datasect.index)
- l += datapos;
- else if (r->secref == bssindex)
- l += bsspos;
-
- if (r->secrel == textsect.index)
- l -= start_point;
- else if (r->secrel == datasect.index)
- l -= datapos;
- else if (r->secrel == bssindex)
- l -= bsspos;
-
- if (r->bytes == 4)
- WRITELONG(q, l);
- else if (r->bytes == 2)
- WRITESHORT(q, l);
- else
- *q++ = l & 0xFF;
- saa_fwrite (r->target->contents, r->posn, mydata, r->bytes);
- }
- saa_fpwrite (textsect.contents, fp);
- if (datasect.length > 0) {
- while (datagap--)
- fputc('\0', fp);
- saa_fpwrite (datasect.contents, fp);
- }
- fclose (fp);
- saa_free (textsect.contents);
- saa_free (datasect.contents);
- while (relocs) {
- r = relocs->next;
- nasm_free (relocs);
- relocs = r;
- }
+ struct Section *outsections, **outstail;
+ struct Section *s, *o, *ls, *lo;
+ struct Reloc *r;
+ long least_org;
+
+ (void) debuginfo;
+
+ /* sort sections by their orgs
+ * sections without org follow their natural order
+ * after the org'd sections
+ */
+ outsections = NULL;
+ outstail = &outsections;
+
+ while( 1 )
+ {
+ least_org = 0x7fffffff;
+
+ ls = lo = NULL;
+ for( s = sections, o = NULL; s; o = s, s = s->next )
+ if( s->org != -1 && s->org < least_org )
+ {
+ least_org = s->org;
+ ls = s;
+ lo = o;
+ }
+
+ if(ls) /* relink to outsections */
+ {
+#ifdef DEBUG
+ fprintf(stdout, "bin_cleanup: relinking section %s org %ld\n", ls->name, ls->org);
+#endif
+ /* unlink from sections */
+ if(lo)
+ lo->next = ls->next;
+ else
+ if(ls == sections)
+ sections = ls->next;
+
+ /* link in to outsections */
+ if( ls->length > 0 )
+ {
+ *outstail = ls;
+ outstail = &ls->next;
+ ls->next = NULL;
+ }
+ }
+ else
+ break;
+ }
+
+ /* link outsections at start of sections */
+ *outstail = sections;
+ sections = outsections;
+
+ /* calculate sections positions */
+ for(s = sections, o = NULL; s; s = s->next)
+ {
+ if(!strcmp(s->name,".bss")) continue; /* don't count .bss yet */
+
+ if(o)
+ {
+ /* if section doesn't have its
+ * own org, align from prev section
+ */
+ if( s->org == -1 )
+ s->org = o->org + o->length;
+
+ /* check orgs */
+ if( s->org - o->org < o->length )
+ error( ERR_PANIC, "sections %s and %s overlap!", o->name, s->name );
+
+ /* align previous section */
+ o->pad = ((o->pos + o->length + o->align-1) & ~(o->align-1)) - (o->pos + o->length);
+
+ if( s->org - o->org > o->length )
+ {
+#ifdef DEBUG
+ fprintf(stdout, "forced padding: %ld\n", s->org - o->org - o->length);
+#endif
+ o->pad = s->org - o->org - o->length;
+ }
+
+ s->pos += o->pos + o->length + o->pad;
+ s->org = s->pos + sections->org;
+ }
+
+#ifdef DEBUG
+ fprintf(stdout, "bin_cleanup: section %s at %ld(%lx) org %ld(%lx) prev <pos %ld(%lx)+size %ld(%lx)+pad %ld(%lx)> size %ld(%lx) align %ld(%lx)\n",
+ s->name, s->pos, s->pos, s->org, s->org, o?o->pos:0, o?o->pos:0,
+ o?o->length:0, o?o->length:0, o?o->pad:0, o?o->pad:0, s->length, s->length,
+ s->align, s->align);
+#endif
+
+ /* prepare for relocating by the way */
+ saa_rewind( s->contents );
+
+ o = s;
+ }
+
+ /* adjust .bss */
+ s = find_section_by_name(".bss");
+ if(s)
+ {
+ s->org = o->org + o->length + o->pad;
+
+#ifdef DEBUG
+ fprintf(stdout, "bin_cleanup: section %s at %ld org %ld prev (pos %ld+size %ld+pad %ld) size %ld align %ld\n",
+ s->name, s->pos, s->org, o?o->pos:0, o?o->length:0, o?o->pad:0, s->length, s->align);
+#endif
+ }
+
+ /* apply relocations */
+ for (r = relocs; r; r = r->next)
+ {
+ unsigned char *p, *q, mydata[4];
+ long l;
+
+ saa_fread (r->target->contents, r->posn, mydata, r->bytes);
+ p = q = mydata;
+ l = *p++;
+
+ if (r->bytes > 1) {
+ l += ((long)*p++) << 8;
+ if (r->bytes == 4) {
+ l += ((long)*p++) << 16;
+ l += ((long)*p++) << 24;
+ }
+ }
+
+ s = find_section_by_index(r->secref);
+ if(s)
+ l += s->org;
+
+ s = find_section_by_index(r->secrel);
+ if(s)
+ l -= s->org;
+
+ if (r->bytes == 4)
+ WRITELONG(q, l);
+ else if (r->bytes == 2)
+ WRITESHORT(q, l);
+ else
+ *q++ = l & 0xFF;
+ saa_fwrite (r->target->contents, r->posn, mydata, r->bytes);
+ }
+
+ /* write sections to file */
+ for(s = outsections; s; s = s->next)
+ {
+ if(s->length > 0 && strcmp(s->name,".bss"))
+ {
+#ifdef DEBUG
+ fprintf(stdout, "bin_cleanup: writing section %s\n", s->name);
+#endif
+ saa_fpwrite (s->contents, fp);
+ if( s->next )
+ while( s->pad-- > 0 )
+ fputc('\0', fp);
+ /* could pad with nops, since we don't
+ * know if this is code section or not
+ */
+ }
+ }
+
+ fclose (fp);
+
+ while (relocs) {
+ r = relocs->next;
+ nasm_free (relocs);
+ relocs = r;
+ }
+
+ while (outsections) {
+ s = outsections->next;
+ saa_free (outsections->contents);
+ nasm_free (outsections->name);
+ nasm_free (outsections);
+ outsections = s;
+ }
}
static void bin_out (long segto, void *data, unsigned long type,
- long segment, long wrt)
+ long segment, long wrt)
{
unsigned char *p, mydata[4];
- struct Section *s;
+ struct Section *s, *sec;
long realbytes;
if (wrt != NO_SEG) {
- wrt = NO_SEG; /* continue to do _something_ */
- error (ERR_NONFATAL, "WRT not supported by binary output format");
+ wrt = NO_SEG; /* continue to do _something_ */
+ error (ERR_NONFATAL, "WRT not supported by binary output format");
}
/*
* handle absolute-assembly (structure definitions)
*/
if (segto == NO_SEG) {
- if ((type & OUT_TYPMASK) != OUT_RESERVE)
- error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
- " space");
- return;
+ if ((type & OUT_TYPMASK) != OUT_RESERVE)
+ error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
+ " space");
+ return;
}
- if (segto == bssindex) { /* BSS */
- if ((type & OUT_TYPMASK) != OUT_RESERVE)
- error(ERR_WARNING, "attempt to initialise memory in the"
- " BSS section: ignored");
- s = NULL;
- } else if (segto == textsect.index) {
- s = &textsect;
- } else if (segto == datasect.index) {
- s = &datasect;
- } else {
- error(ERR_WARNING, "attempt to assemble code in"
- " segment %d: defaulting to `.text'", segto);
- s = &textsect;
+ /*
+ * Find the segment we are targetting.
+ */
+ s = find_section_by_index(segto);
+ if (!s)
+ error (ERR_PANIC, "code directed to nonexistent segment?");
+
+ if (!strcmp(s->name, ".bss")) { /* BSS */
+ if ((type & OUT_TYPMASK) != OUT_RESERVE)
+ error(ERR_WARNING, "attempt to initialise memory in the"
+ " BSS section: ignored");
+ s = NULL;
}
- if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
- if (segment != NO_SEG &&
- segment != textsect.index &&
- segment != datasect.index &&
- segment != bssindex) {
- if (segment % 2)
- error(ERR_NONFATAL, "binary output format does not support"
- " segment base references");
- else
- error(ERR_NONFATAL, "binary output format does not support"
- " external references");
- segment = NO_SEG;
- }
- if (s) {
- if (segment != NO_SEG)
- add_reloc (s, type & OUT_SIZMASK, segment, -1L);
- p = mydata;
- if ((type & OUT_SIZMASK) == 4)
- WRITELONG (p, *(long *)data);
- else
- WRITESHORT (p, *(long *)data);
- saa_wbytes (s->contents, mydata, type & OUT_SIZMASK);
- s->length += type & OUT_SIZMASK;
- } else
- bsslen += type & OUT_SIZMASK;
- } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
- type &= OUT_SIZMASK;
- p = data;
- if (s) {
- saa_wbytes (s->contents, data, type);
- s->length += type;
- } else
- bsslen += type;
- } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
- if (s) {
- error(ERR_WARNING, "uninitialised space declared in"
- " %s section: zeroing",
- (segto == textsect.index ? "code" : "data"));
- }
- type &= OUT_SIZMASK;
- if (s) {
- saa_wbytes (s->contents, NULL, type);
- s->length += type;
- } else
- bsslen += type;
- }
- else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
- (type & OUT_TYPMASK) == OUT_REL4ADR)
- {
- realbytes = ((type & OUT_TYPMASK) == OUT_REL4ADR ? 4 : 2);
- if (segment != NO_SEG &&
- segment != textsect.index &&
- segment != datasect.index &&
- segment != bssindex) {
- if (segment % 2)
- error(ERR_NONFATAL, "binary output format does not support"
- " segment base references");
- else
- error(ERR_NONFATAL, "binary output format does not support"
- " external references");
- segment = NO_SEG;
- }
- if (s) {
- add_reloc (s, realbytes, segment, segto);
- p = mydata;
- if (realbytes == 4)
- WRITELONG (p, *(long*)data - realbytes - s->length);
- else
- WRITESHORT (p, *(long*)data - realbytes - s->length);
- saa_wbytes (s->contents, mydata, realbytes);
- s->length += realbytes;
- } else
- bsslen += realbytes;
- }
+ if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
+
+ if (segment != NO_SEG && !find_section_by_index(segment)) {
+ if (segment % 2)
+ error(ERR_NONFATAL, "binary output format does not support"
+ " segment base references");
+ else
+ error(ERR_NONFATAL, "binary output format does not support"
+ " external references");
+ segment = NO_SEG;
+ }
+
+ if (s) {
+ if (segment != NO_SEG)
+ add_reloc (s, type & OUT_SIZMASK, segment, -1L);
+ p = mydata;
+ if ((type & OUT_SIZMASK) == 4)
+ WRITELONG (p, *(long *)data);
+ else
+ WRITESHORT (p, *(long *)data);
+ saa_wbytes (s->contents, mydata, type & OUT_SIZMASK);
+ s->length += type & OUT_SIZMASK;
+ } else {
+ sec = find_section_by_name(".bss");
+ if(!sec)
+ error(ERR_PANIC, ".bss section is not present");
+ sec->length += type & OUT_SIZMASK;
+ }
+
+ } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
+ type &= OUT_SIZMASK;
+ p = data;
+ if (s) {
+ saa_wbytes (s->contents, data, type);
+ s->length += type;
+ } else {
+ sec = find_section_by_name(".bss");
+ if(!sec)
+ error(ERR_PANIC, ".bss section is not present");
+ sec->length += type;
+ }
+
+ } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
+ if (s) {
+ error(ERR_WARNING, "uninitialised space declared in"
+ " %s section: zeroing", s->name);
+ }
+ type &= OUT_SIZMASK;
+ if (s) {
+ saa_wbytes (s->contents, NULL, type);
+ s->length += type;
+ } else {
+ sec = find_section_by_name(".bss");
+ if(!sec)
+ error(ERR_PANIC, ".bss section is not present");
+ sec->length += type;
+ }
+ }
+ else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
+ (type & OUT_TYPMASK) == OUT_REL4ADR)
+ {
+ realbytes = ((type & OUT_TYPMASK) == OUT_REL4ADR ? 4 : 2);
+
+ if (segment != NO_SEG && !find_section_by_index(segment)) {
+ if (segment % 2)
+ error(ERR_NONFATAL, "binary output format does not support"
+ " segment base references");
+ else
+ error(ERR_NONFATAL, "binary output format does not support"
+ " external references");
+ segment = NO_SEG;
+ }
+
+ if (s) {
+ add_reloc (s, realbytes, segment, segto);
+ p = mydata;
+ if (realbytes == 4)
+ WRITELONG (p, *(long*)data - realbytes - s->length);
+ else
+ WRITESHORT (p, *(long*)data - realbytes - s->length);
+ saa_wbytes (s->contents, mydata, realbytes);
+ s->length += realbytes;
+ } else {
+ sec = find_section_by_name(".bss");
+ if(!sec)
+ error(ERR_PANIC, ".bss section is not present");
+ sec->length += realbytes;
+ }
+ }
}
static void bin_deflabel (char *name, long segment, long offset,
- int is_global, char *special)
+ int is_global, char *special)
{
-
(void) segment; /* Don't warn that this parameter is unused */
(void) offset; /* Don't warn that this parameter is unused */
if (special)
- error (ERR_NONFATAL, "binary format does not support any"
- " special symbol types");
+ error (ERR_NONFATAL, "binary format does not support any"
+ " special symbol types");
if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
- error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
- return;
+ error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
+ return;
}
if (is_global == 2) {
- error (ERR_NONFATAL, "binary output format does not support common"
- " variables");
+ error (ERR_NONFATAL, "binary output format does not support common"
+ " variables");
}
}
-static long bin_secname (char *name, int pass, int *bits)
+static long bin_secname (char *name, int pass, int *bits)
{
int sec_index;
long *sec_align;
char *p;
+ struct Section *sec;
(void) pass; /* Don't warn that this parameter is unused */
/*
- * Default is 16 bits.
+ * Default is 16 bits .text segment
*/
- if (!name)
- *bits = 16;
-
- if (!name)
- return textsect.index;
-
- p = name;
- while (*p && !isspace(*p)) p++;
- if (*p) *p++ = '\0';
- if (!strcmp(name, ".text")) {
- sec_index = textsect.index;
- sec_align = NULL;
- } else if (!strcmp(name, ".data")) {
- sec_index = datasect.index;
- sec_align = &data_align;
- } else if (!strcmp(name, ".bss")) {
- sec_index = bssindex;
- sec_align = &bss_align;
- } else
- return NO_SEG;
+ if (!name)
+ {
+ *bits = 16;
+ sec = find_section_by_name(".text");
+ if(!sec) sec = alloc_section(".text");
+ sec->org = 0; /* default .text org */
+ current_section = sec->index;
+ return sec->index;
+ }
+
+ p = name;
+ while (*p && !isspace(*p)) p++;
+ if (*p) *p++ = '\0';
+ if (!strcmp(name, ".text")) {
+ sec = find_section_by_name(".text");
+ if(!sec) sec = alloc_section(".text");
+ sec_index = sec->index;
+ sec_align = NULL;
+ } else {
+ sec = find_section_by_name(name);
+ if(!sec) sec = alloc_section(name);
+ sec_index = sec->index;
+ sec_align = &sec->align;
+ }
if (*p) {
- if (!nasm_strnicmp(p,"align=",6)) {
- if (sec_align == NULL)
- error(ERR_NONFATAL, "cannot specify an alignment to"
- " the `.text' section");
- else if (p[6+strspn(p+6,"0123456789")])
- error(ERR_NONFATAL, "argument to `align' is not numeric");
- else {
- unsigned int align = atoi(p+6);
- if (!align || ((align-1) & align))
- error(ERR_NONFATAL, "argument to `align' is not a"
- " power of two");
- else
- *sec_align = align;
- }
- }
+ if (!nasm_strnicmp(p,"align=",6)) {
+ if (sec_align == NULL)
+ error(ERR_NONFATAL, "cannot specify an alignment to"
+ " the .text section");
+ else if (p[6+strspn(p+6,"0123456789")])
+ error(ERR_NONFATAL, "argument to `align' is not numeric");
+ else {
+ unsigned int align = atoi(p+6);
+ if (!align || ((align-1) & align))
+ error(ERR_NONFATAL, "argument to `align' is not a"
+ " power of two");
+ else
+ *sec_align = align;
+ }
}
+ }
- return sec_index;
+ current_section = sec->index;
+ return sec_index;
}
-static long bin_segbase (long segment)
+static long bin_segbase (long segment)
{
return segment;
}
-static int bin_directive (char *directive, char *value, int pass)
+static int bin_directive (char *directive, char *value, int pass)
{
- int rn_error;
+ struct Section *s;
+ int rn_error;
- (void) pass; /* Don't warn that this parameter is unused */
+ (void) pass; /* Don't warn that this parameter is unused */
- if (!strcmp(directive, "org")) {
- start_point = readnum (value, &rn_error);
- if (rn_error)
- error (ERR_NONFATAL, "argument to ORG should be numeric");
- return 1;
- } else
- return 0;
+ if (!nasm_stricmp(directive, "org")) {
+ if(current_section == -1)
+ error(ERR_PANIC, "org of cosmic space specified");
+
+ s = find_section_by_index(current_section);
+ if(!s)
+ error(ERR_PANIC, "current_section points nowhere");
+
+ s->org = readnum (value, &rn_error);
+ if (rn_error)
+ error (ERR_NONFATAL, "argument to ORG should be numeric");
+ return 1;
+ }
+
+ return 0;
}
-static void bin_filename (char *inname, char *outname, efunc error)
+static void bin_filename (char *inname, char *outname, efunc error)
{
standard_extension (inname, outname, "", error);
}
@@ -375,8 +569,9 @@ static int bin_set_info(enum geninfo type, char **val)
{
return 0;
}
+
struct ofmt of_bin = {
- "flat-form binary files (e.g. DOS .COM, .SYS)",
+ "flat-form binary files (e.g. DOS .COM, .SYS) multisection support test",
"bin",
NULL,
null_debug_arr,
diff --git a/outcoff.c b/outcoff.c
index f546a8e..cf2b075 100644
--- a/outcoff.c
+++ b/outcoff.c
@@ -651,10 +651,10 @@ static void coff_symbol (char *name, long strpos, long value,
fputc (aux, coffp);
}
-static void coff_write_symbols (void)
+static void coff_write_symbols (void)
{
char filename[18];
- int i;
+ unsigned long i;
/*
* The `.file' record, and the file name auxiliary record.
@@ -669,7 +669,7 @@ static void coff_write_symbols (void)
*/
memset (filename, 0, 18); /* useful zeroed buffer */
- for (i=0; i<nsects; i++) {
+ for (i = 0; i < nsects; i++) {
coff_symbol (sects[i]->name, 0L, 0L, i+1, 3, 1);
fwritelong (sects[i]->len, coffp);
fwriteshort (sects[i]->nrelocs, coffp);
@@ -685,7 +685,7 @@ static void coff_write_symbols (void)
* The real symbols.
*/
saa_rewind (syms);
- for (i=0; i<nsyms; i++) {
+ for (i = 0; i < nsyms; i++) {
struct Symbol *sym = saa_rstruct (syms);
coff_symbol (sym->strpos == -1 ? sym->name : NULL,
sym->strpos, sym->value, sym->section,
diff --git a/outelf.c b/outelf.c
index 13a93ab..38f4a56 100644
--- a/outelf.c
+++ b/outelf.c
@@ -105,7 +105,7 @@ extern struct ofmt of_elf;
#define SYM_DATA 0x01
#define SYM_FUNCTION 0x02
-#define GLOBAL_TEMP_BASE 6 /* bigger than any constant sym id */
+#define GLOBAL_TEMP_BASE 15 /* bigger than any constant sym id */
#define SEG_ALIGN 16 /* alignment of sections in file */
#define SEG_ALIGN_1 (SEG_ALIGN-1)
diff --git a/outform.h b/outform.h
index 564bbba..18d4768 100644
--- a/outform.h
+++ b/outform.h
@@ -149,7 +149,7 @@
#endif
#endif
-/* finally... override any format specifically specifed to be off */
+/* finally... override any format specifically specified to be off */
#ifdef OF_NO_BIN
#undef OF_BIN
#endif
diff --git a/outobj.c b/outobj.c
index 0490ba1..4d8b6c9 100644
--- a/outobj.c
+++ b/outobj.c
@@ -977,7 +977,7 @@ static void obj_write_fixup (ObjRecord *orp, int bytes,
static void obj_out (long segto, void *data, unsigned long type,
long segment, long wrt)
{
- long size, realtype;
+ unsigned long size, realtype;
unsigned char *ucdata;
long ldata;
struct Segment *seg;
diff --git a/parser.c b/parser.c
index 385c218..00dfcad 100644
--- a/parser.c
+++ b/parser.c
@@ -423,7 +423,6 @@ insn *parse_line (int pass, char *buffer, insn *result,
bracket = (i == '[');
i = stdscan(NULL, &tokval);
if (i == TOKEN_SPECIAL) { /* check for address size override */
-#ifdef TASM_COMPAT
if (tasm_compatible_mode) {
switch ((int)tokval.t_integer) {
/* For TASM compatibility a size override inside the
@@ -458,7 +457,6 @@ insn *parse_line (int pass, char *buffer, insn *result,
error (ERR_NONFATAL, "invalid operand size specification");
}
} else {
-#endif
/* Standard NASM compatible syntax */
switch ((int)tokval.t_integer) {
case S_NOSPLIT:
@@ -480,9 +478,7 @@ insn *parse_line (int pass, char *buffer, insn *result,
error (ERR_NONFATAL, "invalid size specification in"
" effective address");
}
-#ifdef TASM_COMPAT
}
-#endif
i = stdscan(NULL, &tokval);
}
} else { /* immediate operand, or register */
@@ -589,7 +585,7 @@ insn *parse_line (int pass, char *buffer, insn *result,
else if (e->value != 1) /* If both want to be index */
{
- error(ERR_NONFATAL, "invalid effective address");
+ error(ERR_NONFATAL, "beroset-p-592-invalid effective address");
result->opcode = -1;
return result;
}
@@ -600,7 +596,7 @@ insn *parse_line (int pass, char *buffer, insn *result,
if (e->type != 0) { /* is there an offset? */
if (e->type <= EXPR_REG_END) /* in fact, is there an error? */
{
- error (ERR_NONFATAL, "invalid effective address");
+ error (ERR_NONFATAL, "beroset-p-603-invalid effective address");
result->opcode = -1;
return result;
}
@@ -627,14 +623,14 @@ insn *parse_line (int pass, char *buffer, insn *result,
* Look for a segment base type.
*/
if (e->type && e->type < EXPR_SEGBASE) {
- error (ERR_NONFATAL, "invalid effective address");
+ error (ERR_NONFATAL, "beroset-p-630-invalid effective address");
result->opcode = -1;
return result;
}
while (e->type && e->value == 0)
e++;
if (e->type && e->value != 1) {
- error (ERR_NONFATAL, "invalid effective address");
+ error (ERR_NONFATAL, "beroset-p-637-invalid effective address");
result->opcode = -1;
return result;
}
@@ -647,7 +643,7 @@ insn *parse_line (int pass, char *buffer, insn *result,
while (e->type && e->value == 0)
e++;
if (e->type) {
- error (ERR_NONFATAL, "invalid effective address");
+ error (ERR_NONFATAL, "beroset-p-650-invalid effective address");
result->opcode = -1;
return result;
}
@@ -660,7 +656,7 @@ insn *parse_line (int pass, char *buffer, insn *result,
}
if (e->type != 0) { /* there'd better be nothing left! */
- error (ERR_NONFATAL, "invalid effective address");
+ error (ERR_NONFATAL, "beroset-p-663-invalid effective address");
result->opcode = -1;
return result;
}
diff --git a/preproc.c b/preproc.c
index 87c128f..488517b 100644
--- a/preproc.c
+++ b/preproc.c
@@ -56,7 +56,8 @@ typedef struct IncPath IncPath;
/*
* Store the definition of a single-line macro.
*/
-struct SMacro {
+struct SMacro
+{
SMacro *next;
char *name;
int casesense;
@@ -82,32 +83,34 @@ struct SMacro {
* When a MMacro is being expanded, `params', `iline', `nparam',
* `paramlen', `rotate' and `unique' are local to the invocation.
*/
-struct MMacro {
+struct MMacro
+{
MMacro *next;
char *name;
int casesense;
int nparam_min, nparam_max;
- int plus; /* is the last parameter greedy? */
- int nolist; /* is this macro listing-inhibited? */
+ int plus; /* is the last parameter greedy? */
+ int nolist; /* is this macro listing-inhibited? */
int in_progress;
- Token *dlist; /* All defaults as one list */
- Token **defaults; /* Parameter default pointers */
- int ndefs; /* number of default parameters */
+ Token *dlist; /* All defaults as one list */
+ Token **defaults; /* Parameter default pointers */
+ int ndefs; /* number of default parameters */
Line *expansion;
MMacro *next_active;
- MMacro *rep_nest; /* used for nesting %rep */
- Token **params; /* actual parameters */
- Token *iline; /* invocation line */
+ MMacro *rep_nest; /* used for nesting %rep */
+ Token **params; /* actual parameters */
+ Token *iline; /* invocation line */
int nparam, rotate, *paramlen;
unsigned long unique;
- int lineno; /* Current line number on expansion */
+ int lineno; /* Current line number on expansion */
};
/*
* The context stack is composed of a linked list of these.
*/
-struct Context {
+struct Context
+{
Context *next;
SMacro *localmac;
char *name;
@@ -133,13 +136,15 @@ struct Context {
* mechanism as an alternative to trying to find a sensible type of
* quote to use on the filename we were passed.
*/
-struct Token {
+struct Token
+{
Token *next;
char *text;
- SMacro *mac; /* associated macro for TOK_SMAC_END */
+ SMacro *mac; /* associated macro for TOK_SMAC_END */
int type;
};
-enum {
+enum
+{
TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,
TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM,
TOK_INTERNAL_STRING
@@ -167,7 +172,8 @@ enum {
* others have `finishes' NULL, but `first' may still be NULL if
* the line is blank.
*/
-struct Line {
+struct Line
+{
Line *next;
MMacro *finishes;
Token *first;
@@ -177,14 +183,15 @@ struct Line {
* To handle an arbitrary level of file inclusion, we maintain a
* stack (ie linked list) of these things.
*/
-struct Include {
+struct Include
+{
Include *next;
FILE *fp;
Cond *conds;
Line *expansion;
char *fname;
int lineno, lineinc;
- MMacro *mstk; /* stack of active macros/reps */
+ MMacro *mstk; /* stack of active macros/reps */
};
/*
@@ -192,7 +199,8 @@ struct Include {
* prepended, in turn, to the name of an include file, in an
* attempt to find the file if it's not in the current directory.
*/
-struct IncPath {
+struct IncPath
+{
IncPath *next;
char *path;
};
@@ -204,11 +212,13 @@ struct IncPath {
* included from within the true branch of a `%if' won't terminate
* it and cause confusion: instead, rightly, it'll cause an error.)
*/
-struct Cond {
+struct Cond
+{
Cond *next;
int state;
};
-enum {
+enum
+{
/*
* These states are for use just after %if or %elif: IF_TRUE
* means the condition has evaluated to truth so we are
@@ -247,7 +257,8 @@ static char *conditions[] = {
"na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
"np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
};
-enum {
+enum
+{
c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_S, c_Z
@@ -262,9 +273,7 @@ static int inverse_ccs[] = {
* Directive names.
*/
static char *directives[] = {
-#ifdef TASM_COMPAT
"%arg",
-#endif
"%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef",
"%elifid", "%elifidn", "%elifidni", "%elifnctx", "%elifndef",
"%elifnid", "%elifnidn", "%elifnidni", "%elifnnum", "%elifnstr",
@@ -274,19 +283,14 @@ static char *directives[] = {
"%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnnum",
"%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include",
"%ixdefine", "%line",
-#ifdef TASM_COMPAT
"%local",
-#endif
"%macro", "%pop", "%push", "%rep", "%repl", "%rotate",
-#ifdef TASM_COMPAT
"%stacksize",
-#endif
- "%strlen", "%substr", "%undef", "%xdefine"
+ "%strlen", "%substr", "%undef", "%xdefine"
};
-enum {
-#ifdef TASM_COMPAT
+enum
+{
PP_ARG,
-#endif
PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF,
PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFNCTX, PP_ELIFNDEF,
PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNNUM, PP_ELIFNSTR,
@@ -296,17 +300,12 @@ enum {
PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNNUM,
PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE,
PP_IXDEFINE, PP_LINE,
-#ifdef TASM_COMPAT
PP_LOCAL,
-#endif
PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE,
-#ifdef TASM_COMPAT
PP_STACKSIZE,
-#endif
- PP_STRLEN, PP_SUBSTR, PP_UNDEF, PP_XDEFINE
+ PP_STRLEN, PP_SUBSTR, PP_UNDEF, PP_XDEFINE
};
-#ifdef TASM_COMPAT
/* For TASM compatibility we need to be able to recognise TASM compatible
* conditional compilation directives. Using the NASM pre-processor does
@@ -318,7 +317,8 @@ enum {
# define MAX(a,b) ( ((a) > (b)) ? (a) : (b))
#endif
-enum {
+enum
+{
TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
TM_IFNDEF, TM_INCLUDE, TM_LOCAL
};
@@ -333,18 +333,17 @@ static char *StackPointer = "ebp";
static int ArgOffset = 8;
static int LocalOffset = 4;
-#endif
static Context *cstk;
static Include *istk;
static IncPath *ipath = NULL;
-static efunc __error; /* Pointer to client-provided error reporting function */
+static efunc __error; /* Pointer to client-provided error reporting function */
static evalfunc evaluate;
static int pass; /* HACK: pass 0 = generate dependencies only */
-static unsigned long unique; /* unique identifier numbers */
+static unsigned long unique; /* unique identifier numbers */
static Line *predef = NULL;
@@ -393,14 +392,22 @@ static char **extrastdmac = NULL;
int any_extrastdmac;
/*
+ * Tokens are allocated in blocks to improve speed
+ */
+#define TOKEN_BLOCKSIZE 4096
+static Token *freeTokens = NULL;
+
+/*
* Forward declarations.
*/
-static Token *expand_mmac_params (Token *tline);
-static Token *expand_smacro (Token *tline);
-static Token *expand_id (Token *tline);
-static Context *get_ctx (char *name, int all_contexts);
-static void make_tok_num(Token *tok, long val);
-static void error (int severity, char *fmt, ...);
+static Token *expand_mmac_params(Token * tline);
+static Token *expand_smacro(Token * tline);
+static Token *expand_id(Token * tline);
+static Context *get_ctx(char *name, int all_contexts);
+static void make_tok_num(Token * tok, long val);
+static void error(int severity, char *fmt, ...);
+static Token *new_Token(Token * next, int type, char *text, int txtlen);
+static Token *delete_Token(Token * t);
/*
* Macros for safe checking of token pointers, avoid *(NULL)
@@ -410,13 +417,13 @@ static void error (int severity, char *fmt, ...);
#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
-#ifdef TASM_COMPAT
/* Handle TASM specific directives, which do not contain a % in
* front of them. We do it here because I could not find any other
* place to do it for the moment, and it is a hack (ideally it would
* be nice to be able to use the NASM pre-processor to do it).
*/
-static char *check_tasm_directive(char *line)
+static char *
+check_tasm_directive(char *line)
{
int i, j, k, m, len;
char *p = line, *oldline, oldchar;
@@ -429,45 +436,53 @@ static char *check_tasm_directive(char *line)
i = -1;
j = sizeof(tasm_directives) / sizeof(*tasm_directives);
len = 0;
- while (!isspace(p [len]) && p [len] != 0)
+ while (!isspace(p[len]) && p[len] != 0)
len++;
- if (len) {
- oldchar = p [len];
- p [len] = 0;
- while (j - i > 1) {
+ if (len)
+ {
+ oldchar = p[len];
+ p[len] = 0;
+ while (j - i > 1)
+ {
k = (j + i) / 2;
- m = nasm_stricmp(p, tasm_directives [k]);
- if (m == 0) {
+ m = nasm_stricmp(p, tasm_directives[k]);
+ if (m == 0)
+ {
/* We have found a directive, so jam a % in front of it
* so that NASM will then recognise it as one if it's own.
*/
- p [len] = oldchar;
+ p[len] = oldchar;
len = strlen(p);
oldline = line;
line = nasm_malloc(len + 2);
- line [0] = '%';
- if (k == TM_IFDIFI) {
+ line[0] = '%';
+ if (k == TM_IFDIFI)
+ {
/* NASM does not recognise IFDIFI, so we convert it to
* %ifdef BOGUS. This is not used in NASM comaptible
* code, but does need to parse for the TASM macro
* package.
*/
- strcpy(line + 1,"ifdef BOGUS");
- } else {
+ strcpy(line + 1, "ifdef BOGUS");
+ }
+ else
+ {
memcpy(line + 1, p, len + 1);
}
nasm_free(oldline);
return line;
- } else if (m < 0) {
+ }
+ else if (m < 0)
+ {
j = k;
- } else
+ }
+ else
i = k;
}
- p [len] = oldchar;
+ p[len] = oldchar;
}
return line;
}
-#endif
/*
* The pre-preprocessing stage... This function translates line
@@ -475,27 +490,27 @@ static char *check_tasm_directive(char *line)
* flags') into NASM preprocessor line number indications (`%line
* lineno file').
*/
-static char *prepreproc(char *line)
+static char *
+prepreproc(char *line)
{
int lineno, fnlen;
char *fname, *oldline;
- if (line[0] == '#' && line[1] == ' ') {
+ if (line[0] == '#' && line[1] == ' ')
+ {
oldline = line;
- fname = oldline+2;
+ fname = oldline + 2;
lineno = atoi(fname);
fname += strspn(fname, "0123456789 ");
if (*fname == '"')
fname++;
fnlen = strcspn(fname, "\"");
- line = nasm_malloc(20+fnlen);
+ line = nasm_malloc(20 + fnlen);
sprintf(line, "%%line %d %.*s", lineno, fnlen, fname);
- nasm_free (oldline);
+ nasm_free(oldline);
}
-#ifdef TASM_COMPAT
if (tasm_compatible_mode)
return check_tasm_directive(line);
-#endif
return line;
}
@@ -505,7 +520,8 @@ static char *prepreproc(char *line)
* invariant under case changes. We implement this by applying a
* perfectly normal hash function to the uppercase of the string.
*/
-static int hash(char *s)
+static int
+hash(char *s)
{
unsigned int h = 0;
int i = 0;
@@ -518,10 +534,11 @@ static int hash(char *s)
};
- while (*s) {
+ while (*s)
+ {
h += multipliers[i] * (unsigned char) (toupper(*s));
s++;
- if (++i >= sizeof(multipliers)/sizeof(*multipliers))
+ if (++i >= sizeof(multipliers) / sizeof(*multipliers))
i = 0;
}
h %= NHASH;
@@ -531,62 +548,65 @@ static int hash(char *s)
/*
* Free a linked list of tokens.
*/
-static void free_tlist (Token *list)
+static void
+free_tlist(Token * list)
{
- Token *t;
- while (list) {
- t = list;
- list = list->next;
- nasm_free (t->text);
- nasm_free (t);
+ while (list)
+ {
+ list = delete_Token(list);
}
}
/*
* Free a linked list of lines.
*/
-static void free_llist (Line *list)
+static void
+free_llist(Line * list)
{
Line *l;
- while (list) {
+ while (list)
+ {
l = list;
list = list->next;
- free_tlist (l->first);
- nasm_free (l);
+ free_tlist(l->first);
+ nasm_free(l);
}
}
/*
* Free an MMacro
*/
-static void free_mmacro (MMacro *m)
+static void
+free_mmacro(MMacro * m)
{
- nasm_free (m->name);
- free_tlist (m->dlist);
- nasm_free (m->defaults);
- free_llist (m->expansion);
- nasm_free (m);
+ nasm_free(m->name);
+ free_tlist(m->dlist);
+ nasm_free(m->defaults);
+ free_llist(m->expansion);
+ nasm_free(m);
}
/*
* Pop the context stack.
*/
-static void ctx_pop (void)
+static void
+ctx_pop(void)
{
Context *c = cstk;
SMacro *smac, *s;
cstk = cstk->next;
smac = c->localmac;
- while (smac) {
+ while (smac)
+ {
s = smac;
smac = smac->next;
- nasm_free (s->name);
- free_tlist (s->expansion);
- nasm_free (s);
+ nasm_free(s->name);
+ free_tlist(s->expansion);
+ nasm_free(s);
}
- nasm_free (c->name);
- nasm_free (c);
+ nasm_free(c->name);
+ nasm_free(c);
}
#define BUF_DELTA 512
@@ -596,15 +616,18 @@ static void ctx_pop (void)
* return lines from the standard macro set if this has not already
* been done.
*/
-static char *read_line (void)
+static char *
+read_line(void)
{
char *buffer, *p, *q;
int bufsize;
- if (stdmacpos) {
- if (*stdmacpos) {
+ if (stdmacpos)
+ {
+ if (*stdmacpos)
+ {
char *ret = nasm_strdup(*stdmacpos++);
- if (!*stdmacpos && any_extrastdmac)
+ if (!*stdmacpos && any_extrastdmac)
{
stdmacpos = extrastdmac;
any_extrastdmac = FALSE;
@@ -616,21 +639,19 @@ static char *read_line (void)
* most convenient way to implement the pre-include and
* pre-define features.
*/
- if (!*stdmacpos)
+ if (!*stdmacpos)
{
Line *pd, *l;
- Token *head, **tail, *t, *tt;
+ Token *head, **tail, *t;
- for (pd = predef; pd; pd = pd->next) {
+ for (pd = predef; pd; pd = pd->next)
+ {
head = NULL;
tail = &head;
- for (t = pd->first; t; t = t->next) {
- tt = *tail = nasm_malloc(sizeof(Token));
- tt->next = NULL;
- tail = &tt->next;
- tt->type = t->type;
- tt->text = nasm_strdup(t->text);
- tt->mac = t->mac; /* always NULL here, in fact */
+ for (t = pd->first; t; t = t->next)
+ {
+ *tail = new_Token(NULL, t->type, t->text, 0);
+ tail = &(*tail)->next;
}
l = nasm_malloc(sizeof(Line));
l->next = istk->expansion;
@@ -640,8 +661,9 @@ static char *read_line (void)
}
}
return ret;
- }
- else {
+ }
+ else
+ {
stdmacpos = NULL;
}
}
@@ -649,24 +671,28 @@ static char *read_line (void)
bufsize = BUF_DELTA;
buffer = nasm_malloc(BUF_DELTA);
p = buffer;
- while (1) {
- q = fgets(p, bufsize-(p-buffer), istk->fp);
+ while (1)
+ {
+ q = fgets(p, bufsize - (p - buffer), istk->fp);
if (!q)
break;
p += strlen(p);
- if (p > buffer && p[-1] == '\n') {
+ if (p > buffer && p[-1] == '\n')
+ {
break;
}
- if (p-buffer > bufsize-10) {
- long offset = p-buffer;
+ if (p - buffer > bufsize - 10)
+ {
+ long offset = p - buffer;
bufsize += BUF_DELTA;
buffer = nasm_realloc(buffer, bufsize);
- p = buffer+offset; /* prevent stale-pointer problems */
+ p = buffer + offset; /* prevent stale-pointer problems */
}
}
- if (!q && p == buffer) {
- nasm_free (buffer);
+ if (!q && p == buffer)
+ {
+ nasm_free(buffer);
return NULL;
}
@@ -685,7 +711,7 @@ static char *read_line (void)
*/
buffer[strcspn(buffer, "\032")] = '\0';
- list->line (LIST_READ, buffer);
+ list->line(LIST_READ, buffer);
return buffer;
}
@@ -695,53 +721,71 @@ static char *read_line (void)
* don't need to parse the value out of e.g. numeric tokens: we
* simply split one string into many.
*/
-static Token *tokenise (char *line)
+static Token *
+tokenise(char *line)
{
char *p = line;
int type;
Token *list = NULL;
Token *t, **tail = &list;
- while (*line) {
+ while (*line)
+ {
p = line;
- if (*p == '%' &&
- (isdigit(p[1]) ||
- ((p[1] == '-' || p[1] == '+') && isdigit(p[2])) ||
- ((p[1] == '+') && (isspace (p[2]) || !p[2]))))
+ if (*p == '%')
{
- p++;
- do {
- p++;
- } while (isdigit(*p));
- type = TOK_PREPROC_ID;
- }
- else if (*p == '%' && p[1] == '{') {
- p += 2;
- while (*p && *p != '}') {
- p[-1] = *p;
p++;
- }
- p[-1] = '\0';
- if (*p) p++;
- type = TOK_PREPROC_ID;
+ if ( isdigit(*p) ||
+ ((*p == '-' || *p == '+') && isdigit(p[1])) ||
+ ((*p == '+') && (isspace(p[1]) || !p[1])))
+ {
+ do
+ {
+ p++;
+ }
+ while (isdigit(*p));
+ type = TOK_PREPROC_ID;
+ }
+ else if (*p == '{')
+ {
+ p++;
+ while (*p && *p != '}')
+ {
+ p[-1] = *p;
+ p++;
+ }
+ p[-1] = '\0';
+ if (*p)
+ p++;
+ type = TOK_PREPROC_ID;
+ }
+ else if (isidchar(*p) ||
+ ((*p == '!' || *p == '%' || *p == '$') &&
+ isidchar(p[1])))
+ {
+ do
+ {
+ p++;
+ }
+ while (isidchar(*p));
+ type = TOK_PREPROC_ID;
+ }
+ else
+ {
+ type = TOK_OTHER;
+ if (*p == '%')
+ p++;
+ }
}
- else if (*p == '%' && (isidchar(p[1]) ||
- ((p[1] == '!' || p[1] == '%' || p[1] == '$') &&
- isidchar(p[2]))))
+ else if (isidstart(*p) || (*p == '$' && isidstart(p[1])))
{
- p++;
- do {
- p++;
- } while (isidchar(*p));
- type = TOK_PREPROC_ID;
- }
- else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
type = TOK_ID;
p++;
while (*p && isidchar(*p))
p++;
}
- else if (*p == '\'' || *p == '"') {
+ else if (*p == '\'' || *p == '"')
+ {
/*
* A string token.
*/
@@ -750,14 +794,17 @@ static Token *tokenise (char *line)
type = TOK_STRING;
while (*p && *p != c)
p++;
- if (*p) {
- p++;
- }
- else {
- error(ERR_WARNING, "unterminated string");
- }
- }
- else if (isnumstart(*p)) {
+ if (*p)
+ {
+ p++;
+ }
+ else
+ {
+ error(ERR_WARNING, "unterminated string");
+ }
+ }
+ else if (isnumstart(*p))
+ {
/*
* A number token.
*/
@@ -765,8 +812,9 @@ static Token *tokenise (char *line)
p++;
while (*p && isnumchar(*p))
p++;
- }
- else if (isspace(*p)) {
+ }
+ else if (isspace(*p))
+ {
type = TOK_WHITESPACE;
p++;
while (*p && isspace(*p))
@@ -776,16 +824,21 @@ static Token *tokenise (char *line)
* pretending it's a comment; whitespace just before a
* comment gets lumped into the comment.
*/
- if (!*p || *p == ';') {
+ if (!*p || *p == ';')
+ {
type = TOK_COMMENT;
- while (*p) p++;
+ while (*p)
+ p++;
}
- }
- else if (*p == ';') {
+ }
+ else if (*p == ';')
+ {
type = TOK_COMMENT;
- while (*p) p++;
- }
- else {
+ while (*p)
+ p++;
+ }
+ else
+ {
/*
* Anything else is an operator of some kind. We check
* for all the double-character operators (>>, <<, //,
@@ -794,30 +847,25 @@ static Token *tokenise (char *line)
*/
type = TOK_OTHER;
if ((p[0] == '>' && p[1] == '>') ||
- (p[0] == '<' && p[1] == '<') ||
- (p[0] == '/' && p[1] == '/') ||
- (p[0] == '%' && p[1] == '%') ||
- (p[0] == '<' && p[1] == '=') ||
- (p[0] == '>' && p[1] == '=') ||
- (p[0] == '=' && p[1] == '=') ||
- (p[0] == '!' && p[1] == '=') ||
- (p[0] == '<' && p[1] == '>') ||
- (p[0] == '&' && p[1] == '&') ||
- (p[0] == '|' && p[1] == '|') ||
- (p[0] == '^' && p[1] == '^'))
+ (p[0] == '<' && p[1] == '<') ||
+ (p[0] == '/' && p[1] == '/') ||
+ (p[0] == '<' && p[1] == '=') ||
+ (p[0] == '>' && p[1] == '=') ||
+ (p[0] == '=' && p[1] == '=') ||
+ (p[0] == '!' && p[1] == '=') ||
+ (p[0] == '<' && p[1] == '>') ||
+ (p[0] == '&' && p[1] == '&') ||
+ (p[0] == '|' && p[1] == '|') ||
+ (p[0] == '^' && p[1] == '^'))
{
p++;
}
p++;
}
- if (type != TOK_COMMENT) {
- *tail = t = nasm_malloc (sizeof(Token));
+ if (type != TOK_COMMENT)
+ {
+ *tail = t = new_Token(NULL, type, line, p - line);
tail = &t->next;
- t->next = NULL;
- t->type = type;
- t->text = nasm_malloc(1+p-line);
- strncpy(t->text, line, p-line);
- t->text[p-line] = '\0';
}
line = p;
}
@@ -825,22 +873,74 @@ static Token *tokenise (char *line)
return list;
}
+
+/*
+ * this function creates a new Token and passes a pointer to it
+ * back to the caller. It sets the type and text elements, and
+ * also the mac and next elements to NULL.
+ */
+static Token *
+new_Token(Token * next, int type, char *text, int txtlen)
+{
+ Token *t;
+ int i;
+
+ if (freeTokens == NULL)
+ {
+ freeTokens = nasm_malloc(TOKEN_BLOCKSIZE * sizeof(Token));
+ for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
+ freeTokens[i].next = &freeTokens[i + 1];
+ freeTokens[i].next = NULL;
+ }
+ t = freeTokens;
+ freeTokens = t->next;
+ t->next = next;
+ t->mac = NULL;
+ t->type = type;
+ if (type == TOK_WHITESPACE || text == NULL)
+ {
+ t->text = NULL;
+ }
+ else
+ {
+ if (txtlen == 0)
+ txtlen = strlen(text);
+ t->text = nasm_malloc(1 + txtlen);
+ strncpy(t->text, text, txtlen);
+ t->text[txtlen] = '\0';
+ }
+ return t;
+}
+
+static Token *
+delete_Token(Token * t)
+{
+ Token *next = t->next;
+ nasm_free(t->text);
+ t->next = freeTokens ? freeTokens->next : NULL;
+ freeTokens = t;
+ return next;
+}
+
/*
* Convert a line of tokens back into text.
* If expand_locals is not zero, identifiers of the form "%$*xxx"
* will be transformed into ..@ctxnum.xxx
*/
-static char *detoken (Token *tlist, int expand_locals)
+static char *
+detoken(Token * tlist, int expand_locals)
{
Token *t;
int len;
char *line, *p;
len = 0;
- for (t = tlist; t; t = t->next) {
- if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
- char *p = getenv(t->text+2);
- nasm_free (t->text);
+ for (t = tlist; t; t = t->next)
+ {
+ if (t->type == TOK_PREPROC_ID && t->text[1] == '!')
+ {
+ char *p = getenv(t->text + 2);
+ nasm_free(t->text);
if (p)
t->text = nasm_strdup(p);
else
@@ -848,29 +948,43 @@ static char *detoken (Token *tlist, int expand_locals)
}
/* Expand local macros here and not during preprocessing */
if (expand_locals &&
- t->type == TOK_PREPROC_ID && t->text &&
- t->text[0] == '%' && t->text [1] == '$') {
- Context *ctx = get_ctx (t->text, FALSE);
- if (ctx) {
- char buffer [40];
+ t->type == TOK_PREPROC_ID && t->text &&
+ t->text[0] == '%' && t->text[1] == '$')
+ {
+ Context *ctx = get_ctx(t->text, FALSE);
+ if (ctx)
+ {
+ char buffer[40];
char *p, *q = t->text + 2;
- q += strspn (q, "$");
- sprintf (buffer, "..@%lu.", ctx->number);
- p = nasm_malloc (strlen(buffer)+strlen(q)+1);
- strcpy (p, buffer);
- strcat (p, q);
- nasm_free (t->text);
+ q += strspn(q, "$");
+ sprintf(buffer, "..@%lu.", ctx->number);
+ p = nasm_strcat(buffer, q);
+ nasm_free(t->text);
t->text = p;
}
}
- if (t->text)
+ if (t->type == TOK_WHITESPACE)
+ {
+ len++;
+ }
+ else if (t->text)
+ {
len += strlen(t->text);
+ }
}
- p = line = nasm_malloc(len+1);
- for (t = tlist; t; t = t->next) {
- if (t->text) {
- strcpy (p, t->text);
+ p = line = nasm_malloc(len + 1);
+ for (t = tlist; t; t = t->next)
+ {
+ if (t->type == TOK_WHITESPACE)
+ {
+ *p = ' ';
+ p++;
+ *p = '\0';
+ }
+ else if (t->text)
+ {
+ strcpy(p, t->text);
p += strlen(p);
}
}
@@ -884,16 +998,19 @@ static char *detoken (Token *tlist, int expand_locals)
* the first token in the line to be passed in as its private_data
* field.
*/
-static int ppscan(void *private_data, struct tokenval *tokval)
+static int
+ppscan(void *private_data, struct tokenval *tokval)
{
Token **tlineptr = private_data;
Token *tline;
- do {
+ do
+ {
tline = *tlineptr;
*tlineptr = tline ? tline->next : NULL;
- } while (tline && (tline->type == TOK_WHITESPACE ||
- tline->type == TOK_COMMENT));
+ }
+ while (tline && (tline->type == TOK_WHITESPACE ||
+ tline->type == TOK_COMMENT));
if (!tline)
return tokval->t_type = TOKEN_EOS;
@@ -903,9 +1020,11 @@ static int ppscan(void *private_data, struct tokenval *tokval)
if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[1])
return tokval->t_type = TOKEN_BASE;
- if (tline->type == TOK_ID) {
+ if (tline->type == TOK_ID)
+ {
tokval->t_charptr = tline->text;
- if (tline->text[0] == '$') {
+ if (tline->text[0] == '$')
+ {
tokval->t_charptr++;
return tokval->t_type = TOKEN_ID;
}
@@ -920,7 +1039,8 @@ static int ppscan(void *private_data, struct tokenval *tokval)
return tokval->t_type = TOKEN_ID;
}
- if (tline->type == TOK_NUMBER) {
+ if (tline->type == TOK_NUMBER)
+ {
int rn_error;
tokval->t_integer = readnum(tline->text, &rn_error);
@@ -930,7 +1050,8 @@ static int ppscan(void *private_data, struct tokenval *tokval)
return tokval->t_type = TOKEN_NUM;
}
- if (tline->type == TOK_STRING) {
+ if (tline->type == TOK_STRING)
+ {
int rn_warn;
char q, *r;
int l;
@@ -939,29 +1060,41 @@ static int ppscan(void *private_data, struct tokenval *tokval)
q = *r++;
l = strlen(r);
- if (l == 0 || r[l-1] != q)
+ if (l == 0 || r[l - 1] != q)
return tokval->t_type = TOKEN_ERRNUM;
- tokval->t_integer = readstrnum(r, l-1, &rn_warn);
+ tokval->t_integer = readstrnum(r, l - 1, &rn_warn);
if (rn_warn)
- error(ERR_WARNING|ERR_PASS1,
- "character constant too long");
+ error(ERR_WARNING | ERR_PASS1, "character constant too long");
tokval->t_charptr = NULL;
return tokval->t_type = TOKEN_NUM;
}
- if (tline->type == TOK_OTHER) {
- if (!strcmp(tline->text, "<<")) return tokval->t_type = TOKEN_SHL;
- if (!strcmp(tline->text, ">>")) return tokval->t_type = TOKEN_SHR;
- if (!strcmp(tline->text, "//")) return tokval->t_type = TOKEN_SDIV;
- if (!strcmp(tline->text, "%%")) return tokval->t_type = TOKEN_SMOD;
- if (!strcmp(tline->text, "==")) return tokval->t_type = TOKEN_EQ;
- if (!strcmp(tline->text, "<>")) return tokval->t_type = TOKEN_NE;
- if (!strcmp(tline->text, "!=")) return tokval->t_type = TOKEN_NE;
- if (!strcmp(tline->text, "<=")) return tokval->t_type = TOKEN_LE;
- if (!strcmp(tline->text, ">=")) return tokval->t_type = TOKEN_GE;
- if (!strcmp(tline->text, "&&")) return tokval->t_type = TOKEN_DBL_AND;
- if (!strcmp(tline->text, "^^")) return tokval->t_type = TOKEN_DBL_XOR;
- if (!strcmp(tline->text, "||")) return tokval->t_type = TOKEN_DBL_OR;
+ if (tline->type == TOK_OTHER)
+ {
+ if (!strcmp(tline->text, "<<"))
+ return tokval->t_type = TOKEN_SHL;
+ if (!strcmp(tline->text, ">>"))
+ return tokval->t_type = TOKEN_SHR;
+ if (!strcmp(tline->text, "//"))
+ return tokval->t_type = TOKEN_SDIV;
+ if (!strcmp(tline->text, "%%"))
+ return tokval->t_type = TOKEN_SMOD;
+ if (!strcmp(tline->text, "=="))
+ return tokval->t_type = TOKEN_EQ;
+ if (!strcmp(tline->text, "<>"))
+ return tokval->t_type = TOKEN_NE;
+ if (!strcmp(tline->text, "!="))
+ return tokval->t_type = TOKEN_NE;
+ if (!strcmp(tline->text, "<="))
+ return tokval->t_type = TOKEN_LE;
+ if (!strcmp(tline->text, ">="))
+ return tokval->t_type = TOKEN_GE;
+ if (!strcmp(tline->text, "&&"))
+ return tokval->t_type = TOKEN_DBL_AND;
+ if (!strcmp(tline->text, "^^"))
+ return tokval->t_type = TOKEN_DBL_XOR;
+ if (!strcmp(tline->text, "||"))
+ return tokval->t_type = TOKEN_DBL_OR;
}
/*
@@ -976,9 +1109,10 @@ static int ppscan(void *private_data, struct tokenval *tokval)
* simple wrapper which calls either strcmp or nasm_stricmp
* depending on the value of the `casesense' parameter.
*/
-static int mstrcmp(char *p, char *q, int casesense)
+static int
+mstrcmp(char *p, char *q, int casesense)
{
- return casesense ? strcmp(p,q) : nasm_stricmp(p,q);
+ return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
}
/*
@@ -991,7 +1125,8 @@ static int mstrcmp(char *p, char *q, int casesense)
* only the context that directly results from the number of $'s
* in variable's name.
*/
-static Context *get_ctx (char *name, int all_contexts)
+static Context *
+get_ctx(char *name, int all_contexts)
{
Context *ctx;
SMacro *m;
@@ -1000,49 +1135,55 @@ static Context *get_ctx (char *name, int all_contexts)
if (!name || name[0] != '%' || name[1] != '$')
return NULL;
- if (!cstk) {
- error (ERR_NONFATAL, "`%s': context stack is empty", name);
+ if (!cstk)
+ {
+ error(ERR_NONFATAL, "`%s': context stack is empty", name);
return NULL;
}
- for (i = strspn (name+2, "$"), ctx = cstk; (i > 0) && ctx; i--) {
+ for (i = strspn(name + 2, "$"), ctx = cstk; (i > 0) && ctx; i--)
+ {
ctx = ctx->next;
i--;
}
- if (!ctx) {
- error (ERR_NONFATAL, "`%s': context stack is only"
- " %d level%s deep", name, i-1, (i==2 ? "" : "s"));
- return NULL;
- }
+ if (!ctx)
+ {
+ error(ERR_NONFATAL, "`%s': context stack is only"
+ " %d level%s deep", name, i - 1, (i == 2 ? "" : "s"));
+ return NULL;
+ }
if (!all_contexts)
- return ctx;
+ return ctx;
- do {
+ do
+ {
/* Search for this smacro in found context */
m = ctx->localmac;
- while (m) {
+ while (m)
+ {
if (!mstrcmp(m->name, name, m->casesense))
return ctx;
m = m->next;
}
ctx = ctx->next;
- } while (ctx);
+ }
+ while (ctx);
return NULL;
}
-#ifdef TASM_COMPAT
/* Add a slash to the end of a path if it is missing. We use the
* forward slash to make it compatible with Unix systems.
*/
-static void backslash(char *s)
+static void
+backslash(char *s)
{
int pos = strlen(s);
- if (s[pos-1] != '\\' && s[pos-1] != '/') {
+ if (s[pos - 1] != '\\' && s[pos - 1] != '/')
+ {
s[pos] = '/';
- s[pos+1] = '\0';
+ s[pos + 1] = '\0';
}
}
-#endif
/*
* Open an include file. This routine must always return a valid
@@ -1051,38 +1192,34 @@ static void backslash(char *s)
* the include path one by one until it finds the file or reaches
* the end of the path.
*/
-static FILE *inc_fopen(char *file)
+static FILE *
+inc_fopen(char *file)
{
FILE *fp;
char *prefix = "", *combine;
IncPath *ip = ipath;
static int namelen = 0;
-#ifdef TASM_COMPAT
int len = strlen(file);
-#endif
- while (1) {
-#ifdef TASM_COMPAT
- combine = nasm_malloc(strlen(prefix)+1+len+1);
+ while (1)
+ {
+ combine = nasm_malloc(strlen(prefix) + 1 + len + 1);
strcpy(combine, prefix);
if (prefix[0] != 0)
backslash(combine);
strcat(combine, file);
-#else
- combine = nasm_strcat(prefix,file);
-#endif
fp = fopen(combine, "r");
if (pass == 0 && fp)
{
- namelen += strlen(combine) + 1;
- if (namelen > 62)
- {
- printf(" \\\n ");
- namelen = 2;
- }
- printf(" %s", combine);
+ namelen += strlen(combine) + 1;
+ if (namelen > 62)
+ {
+ printf(" \\\n ");
+ namelen = 2;
+ }
+ printf(" %s", combine);
}
- nasm_free (combine);
+ nasm_free(combine);
if (fp)
return fp;
if (!ip)
@@ -1091,9 +1228,8 @@ static FILE *inc_fopen(char *file)
ip = ip->next;
}
- error (ERR_FATAL,
- "unable to open include file `%s'", file);
- return NULL; /* never reached - placate compilers */
+ error(ERR_FATAL, "unable to open include file `%s'", file);
+ return NULL; /* never reached - placate compilers */
}
/*
@@ -1117,26 +1253,32 @@ static FILE *inc_fopen(char *file)
* with %$ the context will be automatically computed. If all_contexts
* is true, macro will be searched in outer contexts as well.
*/
-static int smacro_defined (Context *ctx, char *name, int nparam, SMacro **defn,
- int nocase)
+static int
+smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,
+ int nocase)
{
SMacro *m;
if (ctx)
m = ctx->localmac;
- else if (name[0] == '%' && name[1] == '$') {
+ else if (name[0] == '%' && name[1] == '$')
+ {
if (cstk)
- ctx = get_ctx (name, FALSE);
+ ctx = get_ctx(name, FALSE);
if (!ctx)
- return FALSE; /* got to return _something_ */
+ return FALSE; /* got to return _something_ */
m = ctx->localmac;
- } else
+ }
+ else
m = smacros[hash(name)];
- while (m) {
+ while (m)
+ {
if (!mstrcmp(m->name, name, m->casesense && nocase) &&
- (nparam <= 0 || m->nparam == 0 || nparam == m->nparam)) {
- if (defn) {
+ (nparam <= 0 || m->nparam == 0 || nparam == m->nparam))
+ {
+ if (defn)
+ {
if (nparam == m->nparam || nparam == -1)
*defn = m;
else
@@ -1156,14 +1298,17 @@ static int smacro_defined (Context *ctx, char *name, int nparam, SMacro **defn,
* code, and also to mark off the default parameters when provided
* in a %macro definition line.
*/
-static void count_mmac_params (Token *t, int *nparam, Token ***params)
+static void
+count_mmac_params(Token * t, int *nparam, Token *** params)
{
int paramsize, brace;
*nparam = paramsize = 0;
*params = NULL;
- while (t) {
- if (*nparam >= paramsize) {
+ while (t)
+ {
+ if (*nparam >= paramsize)
+ {
paramsize += PARAM_DELTA;
*params = nasm_realloc(*params, sizeof(**params) * paramsize);
}
@@ -1174,22 +1319,25 @@ static void count_mmac_params (Token *t, int *nparam, Token ***params)
(*params)[(*nparam)++] = t;
while (tok_isnt_(t, brace ? "}" : ","))
t = t->next;
- if (t) { /* got a comma/brace */
+ if (t)
+ { /* got a comma/brace */
t = t->next;
- if (brace) {
+ if (brace)
+ {
/*
* Now we've found the closing brace, look further
* for the comma.
*/
skip_white_(t);
- if (tok_isnt_(t, ",")) {
- error (ERR_NONFATAL,
- "braces do not enclose all of macro parameter");
+ if (tok_isnt_(t, ","))
+ {
+ error(ERR_NONFATAL,
+ "braces do not enclose all of macro parameter");
while (tok_isnt_(t, ","))
t = t->next;
}
if (t)
- t = t->next; /* eat the comma */
+ t = t->next; /* eat the comma */
}
}
}
@@ -1201,158 +1349,207 @@ static void count_mmac_params (Token *t, int *nparam, Token ***params)
*
* We must free the tline we get passed.
*/
-static int if_condition (Token *tline, int i)
+static int
+if_condition(Token * tline, int i)
{
- int j, casesense;
- Token * t, * tt, ** tptr, * origline;
+ int j, casesense;
+ Token *t, *tt, **tptr, *origline;
struct tokenval tokval;
- expr * evalresult;
+ expr *evalresult;
origline = tline;
- switch (i) {
- case PP_IFCTX: case PP_ELIFCTX:
- case PP_IFNCTX: case PP_ELIFNCTX:
- j = FALSE; /* have we matched yet? */
- while (cstk && tline) {
- skip_white_(tline);
- if (!tline || tline->type != TOK_ID) {
- error(ERR_NONFATAL,
- "`%s' expects context identifiers", directives[i]);
- free_tlist (origline);
- return -1;
+ switch (i)
+ {
+ case PP_IFCTX:
+ case PP_ELIFCTX:
+ case PP_IFNCTX:
+ case PP_ELIFNCTX:
+ j = FALSE; /* have we matched yet? */
+ while (cstk && tline)
+ {
+ skip_white_(tline);
+ if (!tline || tline->type != TOK_ID)
+ {
+ error(ERR_NONFATAL,
+ "`%s' expects context identifiers",
+ directives[i]);
+ free_tlist(origline);
+ return -1;
+ }
+ if (!nasm_stricmp(tline->text, cstk->name))
+ j = TRUE;
+ tline = tline->next;
}
- if (!nasm_stricmp(tline->text, cstk->name))
- j = TRUE;
- tline = tline->next;
- }
- if (i == PP_IFNCTX || i == PP_ELIFNCTX)
- j = !j;
- free_tlist (origline);
- return j;
-
- case PP_IFDEF: case PP_ELIFDEF:
- case PP_IFNDEF: case PP_ELIFNDEF:
- j = FALSE; /* have we matched yet? */
- while (tline) {
- skip_white_(tline);
- if (!tline || (tline->type != TOK_ID &&
- (tline->type != TOK_PREPROC_ID ||
- tline->text[1] != '$'))) {
+ if (i == PP_IFNCTX || i == PP_ELIFNCTX)
+ j = !j;
+ free_tlist(origline);
+ return j;
+
+ case PP_IFDEF:
+ case PP_ELIFDEF:
+ case PP_IFNDEF:
+ case PP_ELIFNDEF:
+ j = FALSE; /* have we matched yet? */
+ while (tline)
+ {
+ skip_white_(tline);
+ if (!tline || (tline->type != TOK_ID &&
+ (tline->type != TOK_PREPROC_ID ||
+ tline->text[1] != '$')))
+ {
+ error(ERR_NONFATAL,
+ "`%%if%sdef' expects macro identifiers",
+ (i == PP_ELIFNDEF ? "n" : ""));
+ free_tlist(origline);
+ return -1;
+ }
+ if (smacro_defined(NULL, tline->text, 0, NULL, 1))
+ j = TRUE;
+ tline = tline->next;
+ }
+ if (i == PP_IFNDEF || i == PP_ELIFNDEF)
+ j = !j;
+ free_tlist(origline);
+ return j;
+
+ case PP_IFIDN:
+ case PP_ELIFIDN:
+ case PP_IFNIDN:
+ case PP_ELIFNIDN:
+ case PP_IFIDNI:
+ case PP_ELIFIDNI:
+ case PP_IFNIDNI:
+ case PP_ELIFNIDNI:
+ tline = expand_smacro(tline);
+ t = tt = tline;
+ while (tok_isnt_(tt, ","))
+ tt = tt->next;
+ if (!tt)
+ {
error(ERR_NONFATAL,
- "`%%if%sdef' expects macro identifiers",
- (i==PP_ELIFNDEF ? "n" : ""));
- free_tlist (origline);
+ "`%s' expects two comma-separated arguments",
+ directives[i]);
+ free_tlist(tline);
return -1;
}
- if (smacro_defined (NULL, tline->text, 0, NULL, 1))
- j = TRUE;
- tline = tline->next;
- }
- if (i == PP_IFNDEF || i == PP_ELIFNDEF)
- j = !j;
- free_tlist (origline);
- return j;
-
- case PP_IFIDN: case PP_ELIFIDN: case PP_IFNIDN: case PP_ELIFNIDN:
- case PP_IFIDNI: case PP_ELIFIDNI: case PP_IFNIDNI: case PP_ELIFNIDNI:
- tline = expand_smacro(tline);
- t = tt = tline;
- while (tok_isnt_(tt, ","))
tt = tt->next;
- if (!tt) {
- error(ERR_NONFATAL, "`%s' expects two comma-separated arguments",
- directives[i]);
- free_tlist (tline);
- return -1;
- }
- tt = tt->next;
- casesense = (i == PP_IFIDN || i == PP_ELIFIDN ||
- i == PP_IFNIDN || i == PP_ELIFNIDN);
- j = TRUE; /* assume equality unless proved not */
- while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
- if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
- error(ERR_NONFATAL, "`%s': more than one comma on line",
- directives[i]);
- free_tlist (tline);
- return -1;
+ casesense = (i == PP_IFIDN || i == PP_ELIFIDN ||
+ i == PP_IFNIDN || i == PP_ELIFNIDN);
+ j = TRUE; /* assume equality unless proved not */
+ while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt)
+ {
+ if (tt->type == TOK_OTHER && !strcmp(tt->text, ","))
+ {
+ error(ERR_NONFATAL, "`%s': more than one comma on line",
+ directives[i]);
+ free_tlist(tline);
+ return -1;
+ }
+ if (t->type == TOK_WHITESPACE)
+ {
+ t = t->next;
+ continue;
+ }
+ else if (tt->type == TOK_WHITESPACE)
+ {
+ tt = tt->next;
+ continue;
+ }
+ else if (tt->type != t->type ||
+ mstrcmp(tt->text, t->text, casesense))
+ {
+ j = FALSE; /* found mismatching tokens */
+ break;
+ }
+ else
+ {
+ t = t->next;
+ tt = tt->next;
+ continue;
+ }
}
- if (t->type == TOK_WHITESPACE) {
- t = t->next;
- continue;
- } else if (tt->type == TOK_WHITESPACE) {
- tt = tt->next;
- continue;
- } else if (tt->type != t->type ||
- (casesense ? strcmp(tt->text, t->text) :
- nasm_stricmp(tt->text, t->text))) {
- j = FALSE; /* found mismatching tokens */
- break;
- } else {
+ if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
+ j = FALSE; /* trailing gunk on one end or other */
+ if (i == PP_IFNIDN || i == PP_ELIFNIDN ||
+ i == PP_IFNIDNI || i == PP_ELIFNIDNI)
+ j = !j;
+ free_tlist(tline);
+ return j;
+
+ case PP_IFID:
+ case PP_ELIFID:
+ case PP_IFNID:
+ case PP_ELIFNID:
+ case PP_IFNUM:
+ case PP_ELIFNUM:
+ case PP_IFNNUM:
+ case PP_ELIFNNUM:
+ case PP_IFSTR:
+ case PP_ELIFSTR:
+ case PP_IFNSTR:
+ case PP_ELIFNSTR:
+ tline = expand_smacro(tline);
+ t = tline;
+ while (tok_type_(t, TOK_WHITESPACE))
t = t->next;
- tt = tt->next;
- continue;
+ j = FALSE; /* placate optimiser */
+ if (t)
+ switch (i)
+ {
+ case PP_IFID:
+ case PP_ELIFID:
+ case PP_IFNID:
+ case PP_ELIFNID:
+ j = (t->type == TOK_ID);
+ break;
+ case PP_IFNUM:
+ case PP_ELIFNUM:
+ case PP_IFNNUM:
+ case PP_ELIFNNUM:
+ j = (t->type == TOK_NUMBER);
+ break;
+ case PP_IFSTR:
+ case PP_ELIFSTR:
+ case PP_IFNSTR:
+ case PP_ELIFNSTR:
+ j = (t->type == TOK_STRING);
+ break;
+ }
+ if (i == PP_IFNID || i == PP_ELIFNID ||
+ i == PP_IFNNUM || i == PP_ELIFNNUM ||
+ i == PP_IFNSTR || i == PP_ELIFNSTR)
+ j = !j;
+ free_tlist(tline);
+ return j;
+
+ case PP_IF:
+ case PP_ELIF:
+ t = tline = expand_smacro(tline);
+ tptr = &t;
+ tokval.t_type = TOKEN_INVALID;
+ evalresult = evaluate(ppscan, tptr, &tokval,
+ NULL, pass | CRITICAL, error, NULL);
+ free_tlist(tline);
+ if (!evalresult)
+ return -1;
+ if (tokval.t_type)
+ error(ERR_WARNING,
+ "trailing garbage after expression ignored");
+ if (!is_simple(evalresult))
+ {
+ error(ERR_NONFATAL,
+ "non-constant value given to `%s'", directives[i]);
+ return -1;
}
- }
- if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
- j = FALSE; /* trailing gunk on one end or other */
- if (i == PP_IFNIDN || i == PP_ELIFNIDN ||
- i == PP_IFNIDNI || i == PP_ELIFNIDNI)
- j = !j;
- free_tlist (tline);
- return j;
-
- case PP_IFID: case PP_ELIFID: case PP_IFNID: case PP_ELIFNID:
- case PP_IFNUM: case PP_ELIFNUM: case PP_IFNNUM: case PP_ELIFNNUM:
- case PP_IFSTR: case PP_ELIFSTR: case PP_IFNSTR: case PP_ELIFNSTR:
- tline = expand_smacro(tline);
- t = tline;
- while (tok_type_(t, TOK_WHITESPACE))
- t = t->next;
- j = FALSE; /* placate optimiser */
- if (t) switch (i) {
- case PP_IFID: case PP_ELIFID: case PP_IFNID: case PP_ELIFNID:
- j = (t->type == TOK_ID);
- break;
- case PP_IFNUM: case PP_ELIFNUM: case PP_IFNNUM: case PP_ELIFNNUM:
- j = (t->type == TOK_NUMBER);
- break;
- case PP_IFSTR: case PP_ELIFSTR: case PP_IFNSTR: case PP_ELIFNSTR:
- j = (t->type == TOK_STRING);
- break;
- }
- if (i == PP_IFNID || i == PP_ELIFNID ||
- i == PP_IFNNUM || i == PP_ELIFNNUM ||
- i == PP_IFNSTR || i == PP_ELIFNSTR)
- j = !j;
- free_tlist (tline);
- return j;
-
- case PP_IF: case PP_ELIF:
- t = tline = expand_smacro(tline);
- tptr = &t;
- tokval.t_type = TOKEN_INVALID;
- evalresult = evaluate (ppscan, tptr, &tokval,
- NULL, pass | CRITICAL, error, NULL);
- free_tlist (tline);
- if (!evalresult)
- return -1;
- if (tokval.t_type)
- error(ERR_WARNING,
- "trailing garbage after expression ignored");
- if (!is_simple(evalresult)) {
- error(ERR_NONFATAL,
- "non-constant value given to `%s'", directives[i]);
- return -1;
- }
- return reloc_value(evalresult) != 0;
-
- default:
- error(ERR_FATAL,
- "preprocessor directive `%s' not yet implemented",
- directives[i]);
- free_tlist (origline);
- return -1; /* yeah, right */
+ return reloc_value(evalresult) != 0;
+
+ default:
+ error(ERR_FATAL,
+ "preprocessor directive `%s' not yet implemented",
+ directives[i]);
+ free_tlist(origline);
+ return -1; /* yeah, right */
}
}
@@ -1361,11 +1558,12 @@ static int if_condition (Token *tline, int i)
* First tokenise the string, apply "expand_smacro" and then de-tokenise back.
* The returned variable should ALWAYS be freed after usage.
*/
-void expand_macros_in_string (char **p)
+void
+expand_macros_in_string(char **p)
{
- Token *line = tokenise (*p);
- line = expand_smacro (line);
- *p = detoken (line, FALSE);
+ Token *line = tokenise(*p);
+ line = expand_smacro(line);
+ *p = detoken(line, FALSE);
}
/*
@@ -1379,12 +1577,11 @@ void expand_macros_in_string (char **p)
*
* bit 0 is set if a directive was found (so the line gets freed)
*/
-static int do_directive (Token *tline)
+static int
+do_directive(Token * tline)
{
int i, j, k, m, nparam, nolist;
-#ifdef TASM_COMPAT
int offset;
-#endif
char *p, *mname;
Include *inc;
Context *ctx;
@@ -1401,21 +1598,30 @@ static int do_directive (Token *tline)
skip_white_(tline);
if (!tok_type_(tline, TOK_PREPROC_ID) ||
- (tline->text[1]=='%' || tline->text[1]=='$' || tline->text[1]=='!'))
+ (tline->text[1] == '%' || tline->text[1] == '$'
+ || tline->text[1] == '!'))
return 0;
i = -1;
- j = sizeof(directives)/sizeof(*directives);
- while (j-i > 1) {
- k = (j+i) / 2;
+ j = sizeof(directives) / sizeof(*directives);
+ while (j - i > 1)
+ {
+ k = (j + i) / 2;
m = nasm_stricmp(tline->text, directives[k]);
if (m == 0) {
- i = k;
- j = -2;
+ if (tasm_compatible_mode) {
+ i = k;
+ j = -2;
+ } else if (k != PP_ARG && k != PP_LOCAL && k != PP_STACKSIZE) {
+ i = k;
+ j = -2;
+ }
break;
- } else if (m < 0) {
+ }
+ else if (m < 0) {
j = k;
- } else
+ }
+ else
i = k;
}
@@ -1426,23 +1632,22 @@ static int do_directive (Token *tline)
* directives.
*/
if (((istk->conds && !emitting(istk->conds->state)) ||
- (istk->mstk && !istk->mstk->in_progress)) &&
- i != PP_IF && i != PP_ELIF &&
- i != PP_IFCTX && i != PP_ELIFCTX &&
- i != PP_IFDEF && i != PP_ELIFDEF &&
- i != PP_IFID && i != PP_ELIFID &&
- i != PP_IFIDN && i != PP_ELIFIDN &&
- i != PP_IFIDNI && i != PP_ELIFIDNI &&
- i != PP_IFNCTX && i != PP_ELIFNCTX &&
- i != PP_IFNDEF && i != PP_ELIFNDEF &&
- i != PP_IFNID && i != PP_ELIFNID &&
- i != PP_IFNIDN && i != PP_ELIFNIDN &&
- i != PP_IFNIDNI && i != PP_ELIFNIDNI &&
- i != PP_IFNNUM && i != PP_ELIFNNUM &&
- i != PP_IFNSTR && i != PP_ELIFNSTR &&
- i != PP_IFNUM && i != PP_ELIFNUM &&
- i != PP_IFSTR && i != PP_ELIFSTR &&
- i != PP_ELSE && i != PP_ENDIF)
+ (istk->mstk && !istk->mstk->in_progress)) &&
+ i != PP_IF && i != PP_ELIF &&
+ i != PP_IFCTX && i != PP_ELIFCTX &&
+ i != PP_IFDEF && i != PP_ELIFDEF &&
+ i != PP_IFID && i != PP_ELIFID &&
+ i != PP_IFIDN && i != PP_ELIFIDN &&
+ i != PP_IFIDNI && i != PP_ELIFIDNI &&
+ i != PP_IFNCTX && i != PP_ELIFNCTX &&
+ i != PP_IFNDEF && i != PP_ELIFNDEF &&
+ i != PP_IFNID && i != PP_ELIFNID &&
+ i != PP_IFNIDN && i != PP_ELIFNIDN &&
+ i != PP_IFNIDNI && i != PP_ELIFNIDNI &&
+ i != PP_IFNNUM && i != PP_ELIFNNUM &&
+ i != PP_IFNSTR && i != PP_ELIFNSTR &&
+ i != PP_IFNUM && i != PP_ELIFNUM &&
+ i != PP_IFSTR && i != PP_ELIFSTR && i != PP_ELSE && i != PP_ENDIF)
{
return 0;
}
@@ -1455,1125 +1660,1247 @@ static int do_directive (Token *tline)
* causes an error, so should be let through.
*/
if (defining && i != PP_MACRO && i != PP_IMACRO &&
- i != PP_ENDMACRO && i != PP_ENDM &&
- (defining->name || (i != PP_ENDREP && i != PP_REP)))
+ i != PP_ENDMACRO && i != PP_ENDM &&
+ (defining->name || (i != PP_ENDREP && i != PP_REP)))
{
return 0;
}
- if (j != -2) {
+ if (j != -2)
+ {
error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
- tline->text);
- return 0; /* didn't get it */
+ tline->text);
+ return 0; /* didn't get it */
}
- switch (i) {
-#ifdef TASM_COMPAT
- case PP_STACKSIZE:
- /* Directive to tell NASM what the default stack size is. The
- * default is for a 16-bit stack, and this can be overriden with
- * %stacksize large.
- * the following form:
- *
- * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
- */
- tline = tline->next;
- if (tline && tline->type == TOK_WHITESPACE)
- tline = tline->next;
- if (!tline || tline->type != TOK_ID) {
- error (ERR_NONFATAL,"`%%stacksize' missing size parameter");
- free_tlist (origline);
- return 3;
- }
- if (nasm_stricmp(tline->text,"flat") == 0) {
- /* All subsequent ARG directives are for a 32-bit stack */
- StackSize = 4;
- StackPointer = "ebp";
- ArgOffset = 8;
- LocalOffset = 4;
- } else if (nasm_stricmp(tline->text,"large") == 0) {
- /* All subsequent ARG directives are for a 16-bit stack,
- * far function call.
- */
- StackSize = 2;
- StackPointer = "bp";
- ArgOffset = 4;
- LocalOffset = 2;
- } else if (nasm_stricmp(tline->text,"small") == 0) {
- /* All subsequent ARG directives are for a 16-bit stack,
- * far function call. We don't support near functions.
+ switch (i)
+ {
+ case PP_STACKSIZE:
+ /* Directive to tell NASM what the default stack size is. The
+ * default is for a 16-bit stack, and this can be overriden with
+ * %stacksize large.
+ * the following form:
+ *
+ * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
*/
- StackSize = 2;
- StackPointer = "bp";
- ArgOffset = 6;
- LocalOffset = 2;
- } else {
- error (ERR_NONFATAL,"`%%stacksize' invalid size type");
- free_tlist (origline);
- return 3;
- }
- free_tlist(origline);
- return 3;
-
- case PP_ARG:
- /* TASM like ARG directive to define arguments to functions, in
- * the following form:
- *
- * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
- */
- offset = ArgOffset;
- do {
- char *arg,directive[256];
- int size = StackSize;
-
- /* Find the argument name */
tline = tline->next;
if (tline && tline->type == TOK_WHITESPACE)
tline = tline->next;
- if (!tline || tline->type != TOK_ID) {
- error (ERR_NONFATAL,"`%%arg' missing argument parameter");
- free_tlist (origline);
+ if (!tline || tline->type != TOK_ID)
+ {
+ error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
+ free_tlist(origline);
return 3;
}
- arg = tline->text;
-
- /* Find the argument size type */
- tline = tline->next;
- if (!tline || tline->type != TOK_OTHER || tline->text[0] != ':') {
- error (ERR_NONFATAL,"Syntax error processing `%%arg' directive");
- free_tlist (origline);
- return 3;
+ if (nasm_stricmp(tline->text, "flat") == 0)
+ {
+ /* All subsequent ARG directives are for a 32-bit stack */
+ StackSize = 4;
+ StackPointer = "ebp";
+ ArgOffset = 8;
+ LocalOffset = 4;
}
- tline = tline->next;
- if (!tline || tline->type != TOK_ID) {
- error (ERR_NONFATAL,"`%%arg' missing size type parameter");
- free_tlist (origline);
- return 3;
+ else if (nasm_stricmp(tline->text, "large") == 0)
+ {
+ /* All subsequent ARG directives are for a 16-bit stack,
+ * far function call.
+ */
+ StackSize = 2;
+ StackPointer = "bp";
+ ArgOffset = 4;
+ LocalOffset = 2;
}
-
- /* Allow macro expansion of type parameter */
- tt = tokenise(tline->text);
- tt = expand_smacro(tt);
- if (nasm_stricmp(tt->text,"byte") == 0) {
- size = MAX(StackSize,1);
- } else if (nasm_stricmp(tt->text,"word") == 0) {
- size = MAX(StackSize,2);
- } else if (nasm_stricmp(tt->text,"dword") == 0) {
- size = MAX(StackSize,4);
- } else if (nasm_stricmp(tt->text,"qword") == 0) {
- size = MAX(StackSize,8);
- } else if (nasm_stricmp(tt->text,"tword") == 0) {
- size = MAX(StackSize,10);
- } else {
- error (ERR_NONFATAL,"Invalid size type for `%%arg' missing directive");
- free_tlist (tt);
- free_tlist (origline);
+ else if (nasm_stricmp(tline->text, "small") == 0)
+ {
+ /* All subsequent ARG directives are for a 16-bit stack,
+ * far function call. We don't support near functions.
+ */
+ StackSize = 2;
+ StackPointer = "bp";
+ ArgOffset = 6;
+ LocalOffset = 2;
+ }
+ else
+ {
+ error(ERR_NONFATAL, "`%%stacksize' invalid size type");
+ free_tlist(origline);
return 3;
}
- free_tlist (tt);
+ free_tlist(origline);
+ return 3;
- /* Now define the macro for the argument */
- sprintf(directive,"%%define %s (%s+%d)", arg, StackPointer, offset);
- do_directive(tokenise(directive));
- offset += size;
+ case PP_ARG:
+ /* TASM like ARG directive to define arguments to functions, in
+ * the following form:
+ *
+ * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
+ */
+ offset = ArgOffset;
+ do
+ {
+ char *arg, directive[256];
+ int size = StackSize;
- /* Move to the next argument in the list */
- tline = tline->next;
- if (tline && tline->type == TOK_WHITESPACE)
+ /* Find the argument name */
tline = tline->next;
- } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
- free_tlist (origline);
- return 3;
-
- case PP_LOCAL:
- /* TASM like LOCAL directive to define local variables for a
- * function, in the following form:
- *
- * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
- *
- * The '= LocalSize' at the end is ignored by NASM, but is
- * required by TASM to define the local parameter size (and used
- * by the TASM macro package).
- */
- offset = LocalOffset;
- do {
- char *local,directive[256];
- int size = StackSize;
+ if (tline && tline->type == TOK_WHITESPACE)
+ tline = tline->next;
+ if (!tline || tline->type != TOK_ID)
+ {
+ error(ERR_NONFATAL, "`%%arg' missing argument parameter");
+ free_tlist(origline);
+ return 3;
+ }
+ arg = tline->text;
- /* Find the argument name */
- tline = tline->next;
- if (tline && tline->type == TOK_WHITESPACE)
+ /* Find the argument size type */
tline = tline->next;
- if (!tline || tline->type != TOK_ID) {
- error (ERR_NONFATAL,"`%%local' missing argument parameter");
- free_tlist (origline);
- return 3;
- }
- local = tline->text;
+ if (!tline || tline->type != TOK_OTHER
+ || tline->text[0] != ':')
+ {
+ error(ERR_NONFATAL,
+ "Syntax error processing `%%arg' directive");
+ free_tlist(origline);
+ return 3;
+ }
+ tline = tline->next;
+ if (!tline || tline->type != TOK_ID)
+ {
+ error(ERR_NONFATAL,
+ "`%%arg' missing size type parameter");
+ free_tlist(origline);
+ return 3;
+ }
- /* Find the argument size type */
- tline = tline->next;
- if (!tline || tline->type != TOK_OTHER || tline->text[0] != ':') {
- error (ERR_NONFATAL,"Syntax error processing `%%local' directive");
- free_tlist (origline);
- return 3;
- }
- tline = tline->next;
- if (!tline || tline->type != TOK_ID) {
- error (ERR_NONFATAL,"`%%local' missing size type parameter");
- free_tlist (origline);
- return 3;
- }
+ /* Allow macro expansion of type parameter */
+ tt = tokenise(tline->text);
+ tt = expand_smacro(tt);
+ if (nasm_stricmp(tt->text, "byte") == 0)
+ {
+ size = MAX(StackSize, 1);
+ }
+ else if (nasm_stricmp(tt->text, "word") == 0)
+ {
+ size = MAX(StackSize, 2);
+ }
+ else if (nasm_stricmp(tt->text, "dword") == 0)
+ {
+ size = MAX(StackSize, 4);
+ }
+ else if (nasm_stricmp(tt->text, "qword") == 0)
+ {
+ size = MAX(StackSize, 8);
+ }
+ else if (nasm_stricmp(tt->text, "tword") == 0)
+ {
+ size = MAX(StackSize, 10);
+ }
+ else
+ {
+ error(ERR_NONFATAL,
+ "Invalid size type for `%%arg' missing directive");
+ free_tlist(tt);
+ free_tlist(origline);
+ return 3;
+ }
+ free_tlist(tt);
- /* Allow macro expansion of type parameter */
- tt = tokenise(tline->text);
- tt = expand_smacro(tt);
- if (nasm_stricmp(tt->text,"byte") == 0) {
- size = MAX(StackSize,1);
- } else if (nasm_stricmp(tt->text,"word") == 0) {
- size = MAX(StackSize,2);
- } else if (nasm_stricmp(tt->text,"dword") == 0) {
- size = MAX(StackSize,4);
- } else if (nasm_stricmp(tt->text,"qword") == 0) {
- size = MAX(StackSize,8);
- } else if (nasm_stricmp(tt->text,"tword") == 0) {
- size = MAX(StackSize,10);
- } else {
- error (ERR_NONFATAL,"Invalid size type for `%%local' missing directive");
- free_tlist (tt);
- free_tlist (origline);
- return 3;
+ /* Now define the macro for the argument */
+ sprintf(directive, "%%define %s (%s+%d)", arg, StackPointer,
+ offset);
+ do_directive(tokenise(directive));
+ offset += size;
+
+ /* Move to the next argument in the list */
+ tline = tline->next;
+ if (tline && tline->type == TOK_WHITESPACE)
+ tline = tline->next;
}
- free_tlist (tt);
+ while (tline && tline->type == TOK_OTHER
+ && tline->text[0] == ',');
+ free_tlist(origline);
+ return 3;
+
+ case PP_LOCAL:
+ /* TASM like LOCAL directive to define local variables for a
+ * function, in the following form:
+ *
+ * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
+ *
+ * The '= LocalSize' at the end is ignored by NASM, but is
+ * required by TASM to define the local parameter size (and used
+ * by the TASM macro package).
+ */
+ offset = LocalOffset;
+ do
+ {
+ char *local, directive[256];
+ int size = StackSize;
+
+ /* Find the argument name */
+ tline = tline->next;
+ if (tline && tline->type == TOK_WHITESPACE)
+ tline = tline->next;
+ if (!tline || tline->type != TOK_ID)
+ {
+ error(ERR_NONFATAL,
+ "`%%local' missing argument parameter");
+ free_tlist(origline);
+ return 3;
+ }
+ local = tline->text;
+
+ /* Find the argument size type */
+ tline = tline->next;
+ if (!tline || tline->type != TOK_OTHER
+ || tline->text[0] != ':')
+ {
+ error(ERR_NONFATAL,
+ "Syntax error processing `%%local' directive");
+ free_tlist(origline);
+ return 3;
+ }
+ tline = tline->next;
+ if (!tline || tline->type != TOK_ID)
+ {
+ error(ERR_NONFATAL,
+ "`%%local' missing size type parameter");
+ free_tlist(origline);
+ return 3;
+ }
+
+ /* Allow macro expansion of type parameter */
+ tt = tokenise(tline->text);
+ tt = expand_smacro(tt);
+ if (nasm_stricmp(tt->text, "byte") == 0)
+ {
+ size = MAX(StackSize, 1);
+ }
+ else if (nasm_stricmp(tt->text, "word") == 0)
+ {
+ size = MAX(StackSize, 2);
+ }
+ else if (nasm_stricmp(tt->text, "dword") == 0)
+ {
+ size = MAX(StackSize, 4);
+ }
+ else if (nasm_stricmp(tt->text, "qword") == 0)
+ {
+ size = MAX(StackSize, 8);
+ }
+ else if (nasm_stricmp(tt->text, "tword") == 0)
+ {
+ size = MAX(StackSize, 10);
+ }
+ else
+ {
+ error(ERR_NONFATAL,
+ "Invalid size type for `%%local' missing directive");
+ free_tlist(tt);
+ free_tlist(origline);
+ return 3;
+ }
+ free_tlist(tt);
- /* Now define the macro for the argument */
- sprintf(directive,"%%define %s (%s-%d)", local, StackPointer, offset);
+ /* Now define the macro for the argument */
+ sprintf(directive, "%%define %s (%s-%d)", local, StackPointer,
+ offset);
do_directive(tokenise(directive));
offset += size;
/* Now define the assign to setup the enter_c macro correctly */
- sprintf(directive,"%%assign %%$localsize %%$localsize+%d", size);
+ sprintf(directive, "%%assign %%$localsize %%$localsize+%d",
+ size);
do_directive(tokenise(directive));
- /* Move to the next argument in the list */
- tline = tline->next;
- if (tline && tline->type == TOK_WHITESPACE)
+ /* Move to the next argument in the list */
tline = tline->next;
- } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
- free_tlist (origline);
- return 3;
-#endif
-
- case PP_CLEAR:
- if (tline->next)
- error(ERR_WARNING,
- "trailing garbage after `%%clear' ignored");
- for (j=0; j<NHASH; j++) {
- while (mmacros[j]) {
- MMacro *m = mmacros[j];
- mmacros[j] = m->next;
- free_mmacro(m);
- }
- while (smacros[j]) {
- SMacro *s = smacros[j];
- smacros[j] = smacros[j]->next;
- nasm_free (s->name);
- free_tlist (s->expansion);
- nasm_free (s);
+ if (tline && tline->type == TOK_WHITESPACE)
+ tline = tline->next;
}
- }
- free_tlist (origline);
- return 3;
-
- case PP_INCLUDE:
- tline = tline->next;
- skip_white_(tline);
- if (!tline || (tline->type != TOK_STRING &&
- tline->type != TOK_INTERNAL_STRING))
- {
- error(ERR_NONFATAL, "`%%include' expects a file name");
- free_tlist (origline);
- return 3; /* but we did _something_ */
- }
- if (tline->next)
- error(ERR_WARNING,
- "trailing garbage after `%%include' ignored");
- if (tline->type != TOK_INTERNAL_STRING) {
- p = tline->text+1; /* point past the quote to the name */
- p[strlen(p)-1] = '\0'; /* remove the trailing quote */
- } else
- p = tline->text; /* internal_string is easier */
- expand_macros_in_string (&p);
- inc = nasm_malloc(sizeof(Include));
- inc->next = istk;
- inc->conds = NULL;
- inc->fp = inc_fopen(p);
- inc->fname = src_set_fname (p);
- inc->lineno = src_set_linnum(0);
- inc->lineinc = 1;
- inc->expansion = NULL;
- inc->mstk = NULL;
- istk = inc;
- list->uplevel (LIST_INCLUDE);
- free_tlist (origline);
- return 5;
-
- case PP_PUSH:
- tline = tline->next;
- skip_white_(tline);
- tline = expand_id (tline);
- if (!tok_type_(tline, TOK_ID)) {
- error(ERR_NONFATAL,
- "`%%push' expects a context identifier");
- free_tlist (origline);
- return 3; /* but we did _something_ */
- }
- if (tline->next)
- error(ERR_WARNING,
- "trailing garbage after `%%push' ignored");
- ctx = nasm_malloc(sizeof(Context));
- ctx->next = cstk;
- ctx->localmac = NULL;
- ctx->name = nasm_strdup(tline->text);
- ctx->number = unique++;
- cstk = ctx;
- free_tlist (origline);
- break;
-
- case PP_REPL:
- tline = tline->next;
- skip_white_(tline);
- tline = expand_id (tline);
- if (!tok_type_(tline, TOK_ID)) {
- error(ERR_NONFATAL,
- "`%%repl' expects a context identifier");
- free_tlist (origline);
- return 3; /* but we did _something_ */
- }
- if (tline->next)
- error(ERR_WARNING,
- "trailing garbage after `%%repl' ignored");
- if (!cstk)
- error(ERR_NONFATAL,
- "`%%repl': context stack is empty");
- else {
- nasm_free (cstk->name);
- cstk->name = nasm_strdup(tline->text);
- }
- free_tlist (origline);
- break;
-
- case PP_POP:
- if (tline->next)
- error(ERR_WARNING,
- "trailing garbage after `%%pop' ignored");
- if (!cstk)
- error(ERR_NONFATAL,
- "`%%pop': context stack is already empty");
- else
- ctx_pop();
- free_tlist (origline);
- break;
-
- case PP_ERROR:
- tline->next = expand_smacro (tline->next);
- tline = tline->next;
- skip_white_(tline);
- if (tok_type_(tline, TOK_STRING)) {
- p = tline->text+1; /* point past the quote to the name */
- p[strlen(p)-1] = '\0'; /* remove the trailing quote */
- expand_macros_in_string (&p);
- error (ERR_NONFATAL, "%s", p);
- nasm_free (p);
- } else {
- p = detoken(tline, FALSE);
- error (ERR_WARNING, "%s", p);
- nasm_free(p);
- }
- free_tlist (origline);
- break;
-
- case PP_IF:
- case PP_IFCTX:
- case PP_IFDEF:
- case PP_IFID:
- case PP_IFIDN:
- case PP_IFIDNI:
- case PP_IFNCTX:
- case PP_IFNDEF:
- case PP_IFNID:
- case PP_IFNIDN:
- case PP_IFNIDNI:
- case PP_IFNNUM:
- case PP_IFNSTR:
- case PP_IFNUM:
- case PP_IFSTR:
- if (istk->conds && !emitting(istk->conds->state))
- j = COND_NEVER;
- else {
- j = if_condition(tline->next, i);
- tline->next = NULL; /* it got freed */
- free_tlist (origline);
- j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
- }
- cond = nasm_malloc(sizeof(Cond));
- cond->next = istk->conds;
- cond->state = j;
- istk->conds = cond;
- return (j == COND_IF_TRUE ? 3 : 1);
-
- case PP_ELIF:
- case PP_ELIFCTX:
- case PP_ELIFDEF:
- case PP_ELIFID:
- case PP_ELIFIDN:
- case PP_ELIFIDNI:
- case PP_ELIFNCTX:
- case PP_ELIFNDEF:
- case PP_ELIFNID:
- case PP_ELIFNIDN:
- case PP_ELIFNIDNI:
- case PP_ELIFNNUM:
- case PP_ELIFNSTR:
- case PP_ELIFNUM:
- case PP_ELIFSTR:
- if (!istk->conds)
- error(ERR_FATAL, "`%s': no matching `%%if'",
- directives[i]);
- if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
- istk->conds->state = COND_NEVER;
- else {
- j = if_condition(expand_mmac_params(tline->next), i);
- tline->next = NULL; /* it got freed */
- free_tlist (origline);
- istk->conds->state = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
- }
- return (istk->conds->state == COND_IF_TRUE ? 5 : 1);
+ while (tline && tline->type == TOK_OTHER
+ && tline->text[0] == ',');
+ free_tlist(origline);
+ return 3;
- case PP_ELSE:
- if (tline->next)
- error(ERR_WARNING,
- "trailing garbage after `%%else' ignored");
- if (!istk->conds)
- error(ERR_FATAL,
- "`%%else': no matching `%%if'");
- if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
- istk->conds->state = COND_ELSE_FALSE;
- else
- istk->conds->state = COND_ELSE_TRUE;
- free_tlist (origline);
- return 5;
-
- case PP_ENDIF:
- if (tline->next)
- error(ERR_WARNING,
- "trailing garbage after `%%endif' ignored");
- if (!istk->conds)
- error(ERR_FATAL,
- "`%%endif': no matching `%%if'");
- cond = istk->conds;
- istk->conds = cond->next;
- nasm_free (cond);
- free_tlist (origline);
- return 5;
-
- case PP_MACRO:
- case PP_IMACRO:
- if (defining)
- error (ERR_FATAL,
- "`%%%smacro': already defining a macro",
- (i == PP_IMACRO ? "i" : ""));
- tline = tline->next;
- skip_white_(tline);
- tline = expand_id (tline);
- if (!tok_type_(tline, TOK_ID)) {
- error (ERR_NONFATAL,
- "`%%%smacro' expects a macro name",
- (i == PP_IMACRO ? "i" : ""));
+ case PP_CLEAR:
+ if (tline->next)
+ error(ERR_WARNING,
+ "trailing garbage after `%%clear' ignored");
+ for (j = 0; j < NHASH; j++)
+ {
+ while (mmacros[j])
+ {
+ MMacro *m = mmacros[j];
+ mmacros[j] = m->next;
+ free_mmacro(m);
+ }
+ while (smacros[j])
+ {
+ SMacro *s = smacros[j];
+ smacros[j] = smacros[j]->next;
+ nasm_free(s->name);
+ free_tlist(s->expansion);
+ nasm_free(s);
+ }
+ }
+ free_tlist(origline);
return 3;
- }
- defining = nasm_malloc(sizeof(MMacro));
- defining->name = nasm_strdup(tline->text);
- defining->casesense = (i == PP_MACRO);
- defining->plus = FALSE;
- defining->nolist = FALSE;
- defining->in_progress = FALSE;
- defining->rep_nest = NULL;
- tline = expand_smacro (tline->next);
- skip_white_(tline);
- if (!tok_type_(tline, TOK_NUMBER)) {
- error (ERR_NONFATAL,
- "`%%%smacro' expects a parameter count",
- (i == PP_IMACRO ? "i" : ""));
- defining->nparam_min = defining->nparam_max = 0;
- } else {
- defining->nparam_min = defining->nparam_max =
- readnum(tline->text, &j);
- if (j)
- error (ERR_NONFATAL,
- "unable to parse parameter count `%s'", tline->text);
- }
- if (tline && tok_is_(tline->next, "-")) {
- tline = tline->next->next;
- if (tok_is_(tline, "*"))
- defining->nparam_max = INT_MAX;
- else if (!tok_type_(tline, TOK_NUMBER))
- error (ERR_NONFATAL,
- "`%%%smacro' expects a parameter count after `-'",
- (i == PP_IMACRO ? "i" : ""));
- else {
- defining->nparam_max = readnum(tline->text, &j);
- if (j)
- error (ERR_NONFATAL,
- "unable to parse parameter count `%s'",
- tline->text);
- if (defining->nparam_min > defining->nparam_max)
- error (ERR_NONFATAL,
- "minimum parameter count exceeds maximum");
+
+ case PP_INCLUDE:
+ tline = tline->next;
+ skip_white_(tline);
+ if (!tline || (tline->type != TOK_STRING &&
+ tline->type != TOK_INTERNAL_STRING))
+ {
+ error(ERR_NONFATAL, "`%%include' expects a file name");
+ free_tlist(origline);
+ return 3; /* but we did _something_ */
}
- }
- if (tline && tok_is_(tline->next, "+")) {
+ if (tline->next)
+ error(ERR_WARNING,
+ "trailing garbage after `%%include' ignored");
+ if (tline->type != TOK_INTERNAL_STRING)
+ {
+ p = tline->text + 1; /* point past the quote to the name */
+ p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
+ }
+ else
+ p = tline->text; /* internal_string is easier */
+ expand_macros_in_string(&p);
+ inc = nasm_malloc(sizeof(Include));
+ inc->next = istk;
+ inc->conds = NULL;
+ inc->fp = inc_fopen(p);
+ inc->fname = src_set_fname(p);
+ inc->lineno = src_set_linnum(0);
+ inc->lineinc = 1;
+ inc->expansion = NULL;
+ inc->mstk = NULL;
+ istk = inc;
+ list->uplevel(LIST_INCLUDE);
+ free_tlist(origline);
+ return 5;
+
+ case PP_PUSH:
tline = tline->next;
- defining->plus = TRUE;
- }
- if (tline && tok_type_(tline->next, TOK_ID) &&
- !nasm_stricmp(tline->next->text, ".nolist"))
- {
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tok_type_(tline, TOK_ID))
+ {
+ error(ERR_NONFATAL, "`%%push' expects a context identifier");
+ free_tlist(origline);
+ return 3; /* but we did _something_ */
+ }
+ if (tline->next)
+ error(ERR_WARNING, "trailing garbage after `%%push' ignored");
+ ctx = nasm_malloc(sizeof(Context));
+ ctx->next = cstk;
+ ctx->localmac = NULL;
+ ctx->name = nasm_strdup(tline->text);
+ ctx->number = unique++;
+ cstk = ctx;
+ free_tlist(origline);
+ break;
+
+ case PP_REPL:
tline = tline->next;
- defining->nolist = TRUE;
- }
- mmac = mmacros[hash(defining->name)];
- while (mmac) {
- if (!strcmp(mmac->name, defining->name) &&
- (mmac->nparam_min<=defining->nparam_max || defining->plus) &&
- (defining->nparam_min<=mmac->nparam_max || mmac->plus))
- {
- error (ERR_WARNING,
- "redefining multi-line macro `%s'", defining->name);
- break;
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tok_type_(tline, TOK_ID))
+ {
+ error(ERR_NONFATAL, "`%%repl' expects a context identifier");
+ free_tlist(origline);
+ return 3; /* but we did _something_ */
}
- mmac = mmac->next;
- }
- /*
- * Handle default parameters.
- */
- if (tline && tline->next) {
- defining->dlist = tline->next;
- tline->next = NULL;
- count_mmac_params (defining->dlist, &defining->ndefs,
- &defining->defaults);
- } else {
- defining->dlist = NULL;
- defining->defaults = NULL;
- }
- defining->expansion = NULL;
- free_tlist (origline);
- return 1;
-
- case PP_ENDM:
- case PP_ENDMACRO:
- if (!defining) {
- error (ERR_NONFATAL, "`%s': not defining a macro",
- tline->text);
- return 3;
- }
- k = hash(defining->name);
- defining->next = mmacros[k];
- mmacros[k] = defining;
- defining = NULL;
- free_tlist (origline);
- return 5;
-
- case PP_ROTATE:
- if (tline->next && tline->next->type == TOK_WHITESPACE)
+ if (tline->next)
+ error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
+ if (!cstk)
+ error(ERR_NONFATAL, "`%%repl': context stack is empty");
+ else
+ {
+ nasm_free(cstk->name);
+ cstk->name = nasm_strdup(tline->text);
+ }
+ free_tlist(origline);
+ break;
+
+ case PP_POP:
+ if (tline->next)
+ error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
+ if (!cstk)
+ error(ERR_NONFATAL,
+ "`%%pop': context stack is already empty");
+ else
+ ctx_pop();
+ free_tlist(origline);
+ break;
+
+ case PP_ERROR:
+ tline->next = expand_smacro(tline->next);
tline = tline->next;
- t = expand_smacro(tline->next);
- tline->next = NULL;
- free_tlist (origline);
- tline = t;
- tptr = &t;
- tokval.t_type = TOKEN_INVALID;
- evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
- free_tlist (tline);
- if (!evalresult)
- return 3;
- if (tokval.t_type)
- error(ERR_WARNING,
- "trailing garbage after expression ignored");
- if (!is_simple(evalresult)) {
- error(ERR_NONFATAL,
- "non-constant value given to `%%rotate'");
- return 3;
- }
- mmac = istk->mstk;
- while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
- mmac = mmac->next_active;
- if (!mmac)
- error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
- mmac->rotate = mmac->rotate + reloc_value(evalresult);
- if (mmac->rotate < 0)
- mmac->rotate = mmac->nparam - (-mmac->rotate) % mmac->nparam;
- mmac->rotate %= mmac->nparam;
- return 1;
-
- case PP_REP:
- nolist = FALSE;
- tline = tline->next;
- if (tline->next && tline->next->type == TOK_WHITESPACE)
+ skip_white_(tline);
+ if (tok_type_(tline, TOK_STRING))
+ {
+ p = tline->text + 1; /* point past the quote to the name */
+ p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
+ expand_macros_in_string(&p);
+ error(ERR_NONFATAL, "%s", p);
+ nasm_free(p);
+ }
+ else
+ {
+ p = detoken(tline, FALSE);
+ error(ERR_WARNING, "%s", p);
+ nasm_free(p);
+ }
+ free_tlist(origline);
+ break;
+
+ case PP_IF:
+ case PP_IFCTX:
+ case PP_IFDEF:
+ case PP_IFID:
+ case PP_IFIDN:
+ case PP_IFIDNI:
+ case PP_IFNCTX:
+ case PP_IFNDEF:
+ case PP_IFNID:
+ case PP_IFNIDN:
+ case PP_IFNIDNI:
+ case PP_IFNNUM:
+ case PP_IFNSTR:
+ case PP_IFNUM:
+ case PP_IFSTR:
+ if (istk->conds && !emitting(istk->conds->state))
+ j = COND_NEVER;
+ else
+ {
+ j = if_condition(tline->next, i);
+ tline->next = NULL; /* it got freed */
+ free_tlist(origline);
+ j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
+ }
+ cond = nasm_malloc(sizeof(Cond));
+ cond->next = istk->conds;
+ cond->state = j;
+ istk->conds = cond;
+ return (j == COND_IF_TRUE ? 3 : 1);
+
+ case PP_ELIF:
+ case PP_ELIFCTX:
+ case PP_ELIFDEF:
+ case PP_ELIFID:
+ case PP_ELIFIDN:
+ case PP_ELIFIDNI:
+ case PP_ELIFNCTX:
+ case PP_ELIFNDEF:
+ case PP_ELIFNID:
+ case PP_ELIFNIDN:
+ case PP_ELIFNIDNI:
+ case PP_ELIFNNUM:
+ case PP_ELIFNSTR:
+ case PP_ELIFNUM:
+ case PP_ELIFSTR:
+ if (!istk->conds)
+ error(ERR_FATAL, "`%s': no matching `%%if'", directives[i]);
+ if (emitting(istk->conds->state)
+ || istk->conds->state == COND_NEVER)
+ istk->conds->state = COND_NEVER;
+ else
+ {
+ j = if_condition(expand_mmac_params(tline->next), i);
+ tline->next = NULL; /* it got freed */
+ free_tlist(origline);
+ istk->conds->state =
+ j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
+ }
+ return (istk->conds->state == COND_IF_TRUE ? 5 : 1);
+
+ case PP_ELSE:
+ if (tline->next)
+ error(ERR_WARNING, "trailing garbage after `%%else' ignored");
+ if (!istk->conds)
+ error(ERR_FATAL, "`%%else': no matching `%%if'");
+ if (emitting(istk->conds->state)
+ || istk->conds->state == COND_NEVER)
+ istk->conds->state = COND_ELSE_FALSE;
+ else
+ istk->conds->state = COND_ELSE_TRUE;
+ free_tlist(origline);
+ return 5;
+
+ case PP_ENDIF:
+ if (tline->next)
+ error(ERR_WARNING,
+ "trailing garbage after `%%endif' ignored");
+ if (!istk->conds)
+ error(ERR_FATAL, "`%%endif': no matching `%%if'");
+ cond = istk->conds;
+ istk->conds = cond->next;
+ nasm_free(cond);
+ free_tlist(origline);
+ return 5;
+
+ case PP_MACRO:
+ case PP_IMACRO:
+ if (defining)
+ error(ERR_FATAL,
+ "`%%%smacro': already defining a macro",
+ (i == PP_IMACRO ? "i" : ""));
tline = tline->next;
- if (tline->next && tline->next->type == TOK_ID &&
- !nasm_stricmp(tline->next->text, ".nolist")) {
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tok_type_(tline, TOK_ID))
+ {
+ error(ERR_NONFATAL,
+ "`%%%smacro' expects a macro name",
+ (i == PP_IMACRO ? "i" : ""));
+ return 3;
+ }
+ defining = nasm_malloc(sizeof(MMacro));
+ defining->name = nasm_strdup(tline->text);
+ defining->casesense = (i == PP_MACRO);
+ defining->plus = FALSE;
+ defining->nolist = FALSE;
+ defining->in_progress = FALSE;
+ defining->rep_nest = NULL;
+ tline = expand_smacro(tline->next);
+ skip_white_(tline);
+ if (!tok_type_(tline, TOK_NUMBER))
+ {
+ error(ERR_NONFATAL,
+ "`%%%smacro' expects a parameter count",
+ (i == PP_IMACRO ? "i" : ""));
+ defining->nparam_min = defining->nparam_max = 0;
+ }
+ else
+ {
+ defining->nparam_min = defining->nparam_max =
+ readnum(tline->text, &j);
+ if (j)
+ error(ERR_NONFATAL,
+ "unable to parse parameter count `%s'",
+ tline->text);
+ }
+ if (tline && tok_is_(tline->next, "-"))
+ {
+ tline = tline->next->next;
+ if (tok_is_(tline, "*"))
+ defining->nparam_max = INT_MAX;
+ else if (!tok_type_(tline, TOK_NUMBER))
+ error(ERR_NONFATAL,
+ "`%%%smacro' expects a parameter count after `-'",
+ (i == PP_IMACRO ? "i" : ""));
+ else
+ {
+ defining->nparam_max = readnum(tline->text, &j);
+ if (j)
+ error(ERR_NONFATAL,
+ "unable to parse parameter count `%s'",
+ tline->text);
+ if (defining->nparam_min > defining->nparam_max)
+ error(ERR_NONFATAL,
+ "minimum parameter count exceeds maximum");
+ }
+ }
+ if (tline && tok_is_(tline->next, "+"))
+ {
+ tline = tline->next;
+ defining->plus = TRUE;
+ }
+ if (tline && tok_type_(tline->next, TOK_ID) &&
+ !nasm_stricmp(tline->next->text, ".nolist"))
+ {
+ tline = tline->next;
+ defining->nolist = TRUE;
+ }
+ mmac = mmacros[hash(defining->name)];
+ while (mmac)
+ {
+ if (!strcmp(mmac->name, defining->name) &&
+ (mmac->nparam_min <= defining->nparam_max
+ || defining->plus)
+ && (defining->nparam_min <= mmac->nparam_max
+ || mmac->plus))
+ {
+ error(ERR_WARNING,
+ "redefining multi-line macro `%s'",
+ defining->name);
+ break;
+ }
+ mmac = mmac->next;
+ }
+ /*
+ * Handle default parameters.
+ */
+ if (tline && tline->next)
+ {
+ defining->dlist = tline->next;
+ tline->next = NULL;
+ count_mmac_params(defining->dlist, &defining->ndefs,
+ &defining->defaults);
+ }
+ else
+ {
+ defining->dlist = NULL;
+ defining->defaults = NULL;
+ }
+ defining->expansion = NULL;
+ free_tlist(origline);
+ return 1;
+
+ case PP_ENDM:
+ case PP_ENDMACRO:
+ if (!defining)
+ {
+ error(ERR_NONFATAL, "`%s': not defining a macro",
+ tline->text);
+ return 3;
+ }
+ k = hash(defining->name);
+ defining->next = mmacros[k];
+ mmacros[k] = defining;
+ defining = NULL;
+ free_tlist(origline);
+ return 5;
+
+ case PP_ROTATE:
+ if (tline->next && tline->next->type == TOK_WHITESPACE)
+ tline = tline->next;
+ t = expand_smacro(tline->next);
+ tline->next = NULL;
+ free_tlist(origline);
+ tline = t;
+ tptr = &t;
+ tokval.t_type = TOKEN_INVALID;
+ evalresult =
+ evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
+ free_tlist(tline);
+ if (!evalresult)
+ return 3;
+ if (tokval.t_type)
+ error(ERR_WARNING,
+ "trailing garbage after expression ignored");
+ if (!is_simple(evalresult))
+ {
+ error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
+ return 3;
+ }
+ mmac = istk->mstk;
+ while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
+ mmac = mmac->next_active;
+ if (!mmac)
+ error(ERR_NONFATAL,
+ "`%%rotate' invoked outside a macro call");
+ mmac->rotate = mmac->rotate + reloc_value(evalresult);
+ if (mmac->rotate < 0)
+ mmac->rotate = mmac->nparam - (-mmac->rotate) % mmac->nparam;
+ mmac->rotate %= mmac->nparam;
+ return 1;
+
+ case PP_REP:
+ nolist = FALSE;
tline = tline->next;
- nolist = TRUE;
- }
- t = expand_smacro(tline->next);
- tline->next = NULL;
- free_tlist (origline);
- tline = t;
- tptr = &t;
- tokval.t_type = TOKEN_INVALID;
- evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
- free_tlist (tline);
- if (!evalresult)
- return 3;
- if (tokval.t_type)
- error(ERR_WARNING,
- "trailing garbage after expression ignored");
- if (!is_simple(evalresult)) {
- error(ERR_NONFATAL,
- "non-constant value given to `%%rep'");
- return 3;
- }
- tmp_defining = defining;
- defining = nasm_malloc(sizeof(MMacro));
- defining->name = NULL; /* flags this macro as a %rep block */
- defining->casesense = 0;
- defining->plus = FALSE;
- defining->nolist = nolist;
- defining->in_progress = reloc_value(evalresult) + 1;
- defining->nparam_min = defining->nparam_max = 0;
- defining->defaults = NULL;
- defining->dlist = NULL;
- defining->expansion = NULL;
- defining->next_active = istk->mstk;
- defining->rep_nest = tmp_defining;
- return 1;
-
- case PP_ENDREP:
- if (!defining || defining->name) {
- error (ERR_NONFATAL,
- "`%%endrep': no matching `%%rep'");
- return 3;
- }
+ if (tline->next && tline->next->type == TOK_WHITESPACE)
+ tline = tline->next;
+ if (tline->next && tline->next->type == TOK_ID &&
+ !nasm_stricmp(tline->next->text, ".nolist"))
+ {
+ tline = tline->next;
+ nolist = TRUE;
+ }
+ t = expand_smacro(tline->next);
+ tline->next = NULL;
+ free_tlist(origline);
+ tline = t;
+ tptr = &t;
+ tokval.t_type = TOKEN_INVALID;
+ evalresult =
+ evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
+ free_tlist(tline);
+ if (!evalresult)
+ return 3;
+ if (tokval.t_type)
+ error(ERR_WARNING,
+ "trailing garbage after expression ignored");
+ if (!is_simple(evalresult))
+ {
+ error(ERR_NONFATAL, "non-constant value given to `%%rep'");
+ return 3;
+ }
+ tmp_defining = defining;
+ defining = nasm_malloc(sizeof(MMacro));
+ defining->name = NULL; /* flags this macro as a %rep block */
+ defining->casesense = 0;
+ defining->plus = FALSE;
+ defining->nolist = nolist;
+ defining->in_progress = reloc_value(evalresult) + 1;
+ defining->nparam_min = defining->nparam_max = 0;
+ defining->defaults = NULL;
+ defining->dlist = NULL;
+ defining->expansion = NULL;
+ defining->next_active = istk->mstk;
+ defining->rep_nest = tmp_defining;
+ return 1;
- /*
- * Now we have a "macro" defined - although it has no name
- * and we won't be entering it in the hash tables - we must
- * push a macro-end marker for it on to istk->expansion.
- * After that, it will take care of propagating itself (a
- * macro-end marker line for a macro which is really a %rep
- * block will cause the macro to be re-expanded, complete
- * with another macro-end marker to ensure the process
- * continues) until the whole expansion is forcibly removed
- * from istk->expansion by a %exitrep.
- */
- l = nasm_malloc(sizeof(Line));
- l->next = istk->expansion;
- l->finishes = defining;
- l->first = NULL;
- istk->expansion = l;
+ case PP_ENDREP:
+ if (!defining || defining->name)
+ {
+ error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
+ return 3;
+ }
- istk->mstk = defining;
+ /*
+ * Now we have a "macro" defined - although it has no name
+ * and we won't be entering it in the hash tables - we must
+ * push a macro-end marker for it on to istk->expansion.
+ * After that, it will take care of propagating itself (a
+ * macro-end marker line for a macro which is really a %rep
+ * block will cause the macro to be re-expanded, complete
+ * with another macro-end marker to ensure the process
+ * continues) until the whole expansion is forcibly removed
+ * from istk->expansion by a %exitrep.
+ */
+ l = nasm_malloc(sizeof(Line));
+ l->next = istk->expansion;
+ l->finishes = defining;
+ l->first = NULL;
+ istk->expansion = l;
- list->uplevel (defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
- tmp_defining = defining;
- defining = defining->rep_nest;
- free_tlist (origline);
- return 1;
+ istk->mstk = defining;
- case PP_EXITREP:
- /*
- * We must search along istk->expansion until we hit a
- * macro-end marker for a macro with no name. Then we set
- * its `in_progress' flag to 0.
- */
- for (l = istk->expansion; l; l = l->next)
- if (l->finishes && !l->finishes->name)
- break;
+ list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
+ tmp_defining = defining;
+ defining = defining->rep_nest;
+ free_tlist(origline);
+ return 1;
- if (l)
- l->finishes->in_progress = 0;
- else
- error (ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
- free_tlist (origline);
- return 1;
-
- case PP_XDEFINE:
- case PP_IXDEFINE:
- case PP_DEFINE:
- case PP_IDEFINE:
- tline = tline->next;
- skip_white_(tline);
- tline = expand_id (tline);
- if (!tline || (tline->type != TOK_ID &&
- (tline->type != TOK_PREPROC_ID ||
- tline->text[1] != '$'))) {
- error (ERR_NONFATAL,
- "`%%%s%sdefine' expects a macro identifier",
- ((i == PP_IDEFINE || i == PP_IXDEFINE) ? "i" : ""),
- ((i == PP_XDEFINE || i == PP_IXDEFINE) ? "x" : ""));
- free_tlist (origline);
- return 3;
- }
+ case PP_EXITREP:
+ /*
+ * We must search along istk->expansion until we hit a
+ * macro-end marker for a macro with no name. Then we set
+ * its `in_progress' flag to 0.
+ */
+ for (l = istk->expansion; l; l = l->next)
+ if (l->finishes && !l->finishes->name)
+ break;
- ctx = get_ctx (tline->text, FALSE);
- if (!ctx)
- smhead = &smacros[hash(tline->text)];
- else
+ if (l)
+ l->finishes->in_progress = 0;
+ else
+ error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
+ free_tlist(origline);
+ return 1;
+
+ case PP_XDEFINE:
+ case PP_IXDEFINE:
+ case PP_DEFINE:
+ case PP_IDEFINE:
+ tline = tline->next;
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tline || (tline->type != TOK_ID &&
+ (tline->type != TOK_PREPROC_ID ||
+ tline->text[1] != '$')))
+ {
+ error(ERR_NONFATAL,
+ "`%%%s%sdefine' expects a macro identifier",
+ ((i == PP_IDEFINE || i == PP_IXDEFINE) ? "i" : ""),
+ ((i == PP_XDEFINE || i == PP_IXDEFINE) ? "x" : ""));
+ free_tlist(origline);
+ return 3;
+ }
+
+ ctx = get_ctx(tline->text, FALSE);
+ if (!ctx)
+ smhead = &smacros[hash(tline->text)];
+ else
smhead = &ctx->localmac;
- mname = tline->text;
- last = tline;
- param_start = tline = tline->next;
- nparam = 0;
+ mname = tline->text;
+ last = tline;
+ param_start = tline = tline->next;
+ nparam = 0;
- /* Expand the macro definition now for %xdefine and %ixdefine */
- if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
- tline = expand_smacro (tline);
+ /* Expand the macro definition now for %xdefine and %ixdefine */
+ if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
+ tline = expand_smacro(tline);
- if (tok_is_(tline, "(")) {
- /*
- * This macro has parameters.
- */
+ if (tok_is_(tline, "("))
+ {
+ /*
+ * This macro has parameters.
+ */
- tline = tline->next;
- while (1) {
- skip_white_(tline);
- if (!tline) {
- error (ERR_NONFATAL,
- "parameter identifier expected");
- free_tlist (origline);
- return 3;
- }
- if (tline->type != TOK_ID) {
- error (ERR_NONFATAL,
- "`%s': parameter identifier expected",
- tline->text);
- free_tlist (origline);
- return 3;
- }
- tline->type = TOK_SMAC_PARAM + nparam++;
tline = tline->next;
- skip_white_(tline);
- if (tok_is_(tline, ",")) {
+ while (1)
+ {
+ skip_white_(tline);
+ if (!tline)
+ {
+ error(ERR_NONFATAL, "parameter identifier expected");
+ free_tlist(origline);
+ return 3;
+ }
+ if (tline->type != TOK_ID)
+ {
+ error(ERR_NONFATAL,
+ "`%s': parameter identifier expected",
+ tline->text);
+ free_tlist(origline);
+ return 3;
+ }
+ tline->type = TOK_SMAC_PARAM + nparam++;
tline = tline->next;
- continue;
+ skip_white_(tline);
+ if (tok_is_(tline, ","))
+ {
+ tline = tline->next;
+ continue;
+ }
+ if (!tok_is_(tline, ")"))
+ {
+ error(ERR_NONFATAL,
+ "`)' expected to terminate macro template");
+ free_tlist(origline);
+ return 3;
+ }
+ break;
}
- if (!tok_is_(tline, ")")) {
- error (ERR_NONFATAL,
- "`)' expected to terminate macro template");
- free_tlist (origline);
+ last = tline;
+ tline = tline->next;
+ }
+ if (tok_type_(tline, TOK_WHITESPACE))
+ last = tline, tline = tline->next;
+ macro_start = NULL;
+ last->next = NULL;
+ t = tline;
+ while (t)
+ {
+ if (t->type == TOK_ID)
+ {
+ for (tt = param_start; tt; tt = tt->next)
+ if (tt->type >= TOK_SMAC_PARAM &&
+ !strcmp(tt->text, t->text))
+ t->type = tt->type;
+ }
+ tt = t->next;
+ t->next = macro_start;
+ macro_start = t;
+ t = tt;
+ }
+ /*
+ * Good. We now have a macro name, a parameter count, and a
+ * token list (in reverse order) for an expansion. We ought
+ * to be OK just to create an SMacro, store it, and let
+ * free_tlist have the rest of the line (which we have
+ * carefully re-terminated after chopping off the expansion
+ * from the end).
+ */
+ if (smacro_defined(ctx, mname, nparam, &smac, i == PP_DEFINE))
+ {
+ if (!smac)
+ {
+ error(ERR_WARNING,
+ "single-line macro `%s' defined both with and"
+ " without parameters", mname);
+ free_tlist(origline);
+ free_tlist(macro_start);
return 3;
}
- break;
+ else
+ {
+ /*
+ * We're redefining, so we have to take over an
+ * existing SMacro structure. This means freeing
+ * what was already in it.
+ */
+ nasm_free(smac->name);
+ free_tlist(smac->expansion);
+ }
}
- last = tline;
- tline = tline->next;
- }
- if (tok_type_(tline, TOK_WHITESPACE))
- last = tline, tline = tline->next;
- macro_start = NULL;
- last->next = NULL;
- t = tline;
- while (t) {
- if (t->type == TOK_ID) {
- for (tt = param_start; tt; tt = tt->next)
- if (tt->type >= TOK_SMAC_PARAM &&
- !strcmp(tt->text, t->text))
- t->type = tt->type;
+ else
+ {
+ smac = nasm_malloc(sizeof(SMacro));
+ smac->next = *smhead;
+ *smhead = smac;
}
- tt = t->next;
- t->next = macro_start;
- macro_start = t;
- t = tt;
- }
- /*
- * Good. We now have a macro name, a parameter count, and a
- * token list (in reverse order) for an expansion. We ought
- * to be OK just to create an SMacro, store it, and let
- * free_tlist have the rest of the line (which we have
- * carefully re-terminated after chopping off the expansion
- * from the end).
- */
- if (smacro_defined (ctx, mname, nparam, &smac, i == PP_DEFINE)) {
- if (!smac) {
- error (ERR_WARNING,
- "single-line macro `%s' defined both with and"
- " without parameters", mname);
- free_tlist (origline);
- free_tlist (macro_start);
+ smac->name = nasm_strdup(mname);
+ smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE));
+ smac->nparam = nparam;
+ smac->expansion = macro_start;
+ smac->in_progress = FALSE;
+ free_tlist(origline);
+ return 3;
+
+ case PP_UNDEF:
+ tline = tline->next;
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tline || (tline->type != TOK_ID &&
+ (tline->type != TOK_PREPROC_ID ||
+ tline->text[1] != '$')))
+ {
+ error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
+ free_tlist(origline);
return 3;
- } else {
- /*
- * We're redefining, so we have to take over an
- * existing SMacro structure. This means freeing
- * what was already in it.
- */
- nasm_free (smac->name);
- free_tlist (smac->expansion);
}
- } else {
- smac = nasm_malloc(sizeof(SMacro));
- smac->next = *smhead;
- *smhead = smac;
- }
- smac->name = nasm_strdup(mname);
- smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE));
- smac->nparam = nparam;
- smac->expansion = macro_start;
- smac->in_progress = FALSE;
- free_tlist (origline);
- return 3;
-
- case PP_UNDEF:
- tline = tline->next;
- skip_white_(tline);
- tline = expand_id (tline);
- if (!tline || (tline->type != TOK_ID &&
- (tline->type != TOK_PREPROC_ID ||
- tline->text[1] != '$'))) {
- error (ERR_NONFATAL,
- "`%%undef' expects a macro identifier");
- free_tlist (origline);
- return 3;
- }
- if (tline->next) {
- error (ERR_WARNING,
- "trailing garbage after macro name ignored");
- }
+ if (tline->next)
+ {
+ error(ERR_WARNING,
+ "trailing garbage after macro name ignored");
+ }
- /* Find the context that symbol belongs to */
- ctx = get_ctx (tline->text, FALSE);
- if (!ctx)
- smhead = &smacros[hash(tline->text)];
- else
- smhead = &ctx->localmac;
+ /* Find the context that symbol belongs to */
+ ctx = get_ctx(tline->text, FALSE);
+ if (!ctx)
+ smhead = &smacros[hash(tline->text)];
+ else
+ smhead = &ctx->localmac;
- mname = tline->text;
- last = tline;
- last->next = NULL;
+ mname = tline->text;
+ last = tline;
+ last->next = NULL;
- /*
- * We now have a macro name... go hunt for it.
- */
- while (smacro_defined (ctx, mname, -1, &smac, 1)) {
- /* Defined, so we need to find its predecessor and nuke it */
- SMacro **s;
- for ( s = smhead ; *s && *s != smac ; s = &(*s)->next );
- if ( *s ) {
- *s = smac->next;
- nasm_free(smac->name);
- free_tlist(smac->expansion);
- nasm_free(smac);
- }
- }
- free_tlist (origline);
- return 3;
-
- case PP_STRLEN:
- tline = tline->next;
- skip_white_(tline);
- tline = expand_id (tline);
- if (!tline || (tline->type != TOK_ID &&
- (tline->type != TOK_PREPROC_ID ||
- tline->text[1] != '$'))) {
- error (ERR_NONFATAL,
- "`%%strlen' expects a macro identifier as first parameter");
- free_tlist (origline);
+ /*
+ * We now have a macro name... go hunt for it.
+ */
+ while (smacro_defined(ctx, mname, -1, &smac, 1))
+ {
+ /* Defined, so we need to find its predecessor and nuke it */
+ SMacro **s;
+ for (s = smhead; *s && *s != smac; s = &(*s)->next);
+ if (*s)
+ {
+ *s = smac->next;
+ nasm_free(smac->name);
+ free_tlist(smac->expansion);
+ nasm_free(smac);
+ }
+ }
+ free_tlist(origline);
return 3;
- }
- ctx = get_ctx (tline->text, FALSE);
- if (!ctx)
- smhead = &smacros[hash(tline->text)];
- else
+
+ case PP_STRLEN:
+ tline = tline->next;
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tline || (tline->type != TOK_ID &&
+ (tline->type != TOK_PREPROC_ID ||
+ tline->text[1] != '$')))
+ {
+ error(ERR_NONFATAL,
+ "`%%strlen' expects a macro identifier as first parameter");
+ free_tlist(origline);
+ return 3;
+ }
+ ctx = get_ctx(tline->text, FALSE);
+ if (!ctx)
+ smhead = &smacros[hash(tline->text)];
+ else
smhead = &ctx->localmac;
- mname = tline->text;
- last = tline;
- tline = expand_smacro (tline->next);
- last->next = NULL;
+ mname = tline->text;
+ last = tline;
+ tline = expand_smacro(tline->next);
+ last->next = NULL;
- t = tline;
- while (tok_type_(t, TOK_WHITESPACE))
+ t = tline;
+ while (tok_type_(t, TOK_WHITESPACE))
t = t->next;
- /* t should now point to the string */
- if (t->type != TOK_STRING) {
+ /* t should now point to the string */
+ if (t->type != TOK_STRING)
+ {
error(ERR_NONFATAL,
"`%%strlen` requires string as second parameter");
free_tlist(tline);
free_tlist(origline);
return 3;
- }
+ }
- macro_start = nasm_malloc(sizeof(*macro_start));
- macro_start->next = NULL;
- make_tok_num(macro_start, strlen(t->text)-2);
- macro_start->mac = NULL;
+ macro_start = nasm_malloc(sizeof(*macro_start));
+ macro_start->next = NULL;
+ make_tok_num(macro_start, strlen(t->text) - 2);
+ macro_start->mac = NULL;
- /*
- * We now have a macro name, an implicit parameter count of
- * zero, and a numeric token to use as an expansion. Create
- * and store an SMacro.
- */
- if (smacro_defined (ctx, mname, 0, &smac, i == PP_STRLEN)) {
- if (!smac)
- error (ERR_WARNING,
- "single-line macro `%s' defined both with and"
- " without parameters", mname);
- else {
- /*
- * We're redefining, so we have to take over an
- * existing SMacro structure. This means freeing
- * what was already in it.
- */
- nasm_free (smac->name);
- free_tlist (smac->expansion);
- }
- }
- else {
- smac = nasm_malloc(sizeof(SMacro));
- smac->next = *smhead;
- *smhead = smac;
- }
- smac->name = nasm_strdup(mname);
- smac->casesense = (i == PP_STRLEN);
- smac->nparam = 0;
- smac->expansion = macro_start;
- smac->in_progress = FALSE;
- free_tlist (tline);
- free_tlist (origline);
- return 3;
-
- case PP_SUBSTR:
- tline = tline->next;
- skip_white_(tline);
- tline = expand_id (tline);
- if (!tline || (tline->type != TOK_ID &&
- (tline->type != TOK_PREPROC_ID ||
- tline->text[1] != '$'))) {
- error (ERR_NONFATAL,
- "`%%substr' expects a macro identifier as first parameter");
- free_tlist (origline);
+ /*
+ * We now have a macro name, an implicit parameter count of
+ * zero, and a numeric token to use as an expansion. Create
+ * and store an SMacro.
+ */
+ if (smacro_defined(ctx, mname, 0, &smac, i == PP_STRLEN))
+ {
+ if (!smac)
+ error(ERR_WARNING,
+ "single-line macro `%s' defined both with and"
+ " without parameters", mname);
+ else
+ {
+ /*
+ * We're redefining, so we have to take over an
+ * existing SMacro structure. This means freeing
+ * what was already in it.
+ */
+ nasm_free(smac->name);
+ free_tlist(smac->expansion);
+ }
+ }
+ else
+ {
+ smac = nasm_malloc(sizeof(SMacro));
+ smac->next = *smhead;
+ *smhead = smac;
+ }
+ smac->name = nasm_strdup(mname);
+ smac->casesense = (i == PP_STRLEN);
+ smac->nparam = 0;
+ smac->expansion = macro_start;
+ smac->in_progress = FALSE;
+ free_tlist(tline);
+ free_tlist(origline);
return 3;
- }
- ctx = get_ctx (tline->text, FALSE);
- if (!ctx)
- smhead = &smacros[hash(tline->text)];
- else
+
+ case PP_SUBSTR:
+ tline = tline->next;
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tline || (tline->type != TOK_ID &&
+ (tline->type != TOK_PREPROC_ID ||
+ tline->text[1] != '$')))
+ {
+ error(ERR_NONFATAL,
+ "`%%substr' expects a macro identifier as first parameter");
+ free_tlist(origline);
+ return 3;
+ }
+ ctx = get_ctx(tline->text, FALSE);
+ if (!ctx)
+ smhead = &smacros[hash(tline->text)];
+ else
smhead = &ctx->localmac;
- mname = tline->text;
- last = tline;
- tline = expand_smacro (tline->next);
- last->next = NULL;
+ mname = tline->text;
+ last = tline;
+ tline = expand_smacro(tline->next);
+ last->next = NULL;
- t = tline->next;
- while (tok_type_(t, TOK_WHITESPACE))
+ t = tline->next;
+ while (tok_type_(t, TOK_WHITESPACE))
t = t->next;
-
- /* t should now point to the string */
- if (t->type != TOK_STRING) {
+
+ /* t should now point to the string */
+ if (t->type != TOK_STRING)
+ {
error(ERR_NONFATAL,
"`%%substr` requires string as second parameter");
free_tlist(tline);
free_tlist(origline);
return 3;
- }
+ }
- tt = t->next;
- tptr = &tt;
- tokval.t_type = TOKEN_INVALID;
- evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
- if (!evalresult) {
+ tt = t->next;
+ tptr = &tt;
+ tokval.t_type = TOKEN_INVALID;
+ evalresult =
+ evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
+ if (!evalresult)
+ {
free_tlist(tline);
free_tlist(origline);
return 3;
- }
- if (!is_simple(evalresult)) {
- error(ERR_NONFATAL,
- "non-constant value given to `%%substr`");
+ }
+ if (!is_simple(evalresult))
+ {
+ error(ERR_NONFATAL, "non-constant value given to `%%substr`");
free_tlist(tline);
free_tlist(origline);
return 3;
- }
+ }
- macro_start = nasm_malloc(sizeof(*macro_start));
- macro_start->next = NULL;
- macro_start->text = nasm_strdup("'''");
- if (evalresult->value > 0 && evalresult->value < strlen(t->text)-1) {
+ macro_start = nasm_malloc(sizeof(*macro_start));
+ macro_start->next = NULL;
+ macro_start->text = nasm_strdup("'''");
+ if (evalresult->value > 0
+ && evalresult->value < strlen(t->text) - 1)
+ {
macro_start->text[1] = t->text[evalresult->value];
- }
- else {
+ }
+ else
+ {
macro_start->text[2] = '\0';
- }
- macro_start->type = TOK_STRING;
- macro_start->mac = NULL;
+ }
+ macro_start->type = TOK_STRING;
+ macro_start->mac = NULL;
- /*
- * We now have a macro name, an implicit parameter count of
- * zero, and a numeric token to use as an expansion. Create
- * and store an SMacro.
- */
- if (smacro_defined (ctx, mname, 0, &smac, i == PP_SUBSTR)) {
- if (!smac)
- error (ERR_WARNING,
- "single-line macro `%s' defined both with and"
- " without parameters", mname);
- else {
- /*
- * We're redefining, so we have to take over an
- * existing SMacro structure. This means freeing
- * what was already in it.
- */
- nasm_free (smac->name);
- free_tlist (smac->expansion);
- }
- }
- else {
- smac = nasm_malloc(sizeof(SMacro));
- smac->next = *smhead;
- *smhead = smac;
- }
- smac->name = nasm_strdup(mname);
- smac->casesense = (i == PP_SUBSTR);
- smac->nparam = 0;
- smac->expansion = macro_start;
- smac->in_progress = FALSE;
- free_tlist (tline);
- free_tlist (origline);
- return 3;
-
-
- case PP_ASSIGN:
- case PP_IASSIGN:
- tline = tline->next;
- skip_white_(tline);
- tline = expand_id (tline);
- if (!tline || (tline->type != TOK_ID &&
- (tline->type != TOK_PREPROC_ID ||
- tline->text[1] != '$'))) {
- error (ERR_NONFATAL,
- "`%%%sassign' expects a macro identifier",
- (i == PP_IASSIGN ? "i" : ""));
- free_tlist (origline);
+ /*
+ * We now have a macro name, an implicit parameter count of
+ * zero, and a numeric token to use as an expansion. Create
+ * and store an SMacro.
+ */
+ if (smacro_defined(ctx, mname, 0, &smac, i == PP_SUBSTR))
+ {
+ if (!smac)
+ error(ERR_WARNING,
+ "single-line macro `%s' defined both with and"
+ " without parameters", mname);
+ else
+ {
+ /*
+ * We're redefining, so we have to take over an
+ * existing SMacro structure. This means freeing
+ * what was already in it.
+ */
+ nasm_free(smac->name);
+ free_tlist(smac->expansion);
+ }
+ }
+ else
+ {
+ smac = nasm_malloc(sizeof(SMacro));
+ smac->next = *smhead;
+ *smhead = smac;
+ }
+ smac->name = nasm_strdup(mname);
+ smac->casesense = (i == PP_SUBSTR);
+ smac->nparam = 0;
+ smac->expansion = macro_start;
+ smac->in_progress = FALSE;
+ free_tlist(tline);
+ free_tlist(origline);
return 3;
- }
- ctx = get_ctx (tline->text, FALSE);
- if (!ctx)
- smhead = &smacros[hash(tline->text)];
- else
+
+
+ case PP_ASSIGN:
+ case PP_IASSIGN:
+ tline = tline->next;
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tline || (tline->type != TOK_ID &&
+ (tline->type != TOK_PREPROC_ID ||
+ tline->text[1] != '$')))
+ {
+ error(ERR_NONFATAL,
+ "`%%%sassign' expects a macro identifier",
+ (i == PP_IASSIGN ? "i" : ""));
+ free_tlist(origline);
+ return 3;
+ }
+ ctx = get_ctx(tline->text, FALSE);
+ if (!ctx)
+ smhead = &smacros[hash(tline->text)];
+ else
smhead = &ctx->localmac;
- mname = tline->text;
- last = tline;
- tline = expand_smacro (tline->next);
- last->next = NULL;
+ mname = tline->text;
+ last = tline;
+ tline = expand_smacro(tline->next);
+ last->next = NULL;
- t = tline;
- tptr = &t;
- tokval.t_type = TOKEN_INVALID;
- evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
- free_tlist (tline);
- if (!evalresult) {
- free_tlist (origline);
- return 3;
- }
+ t = tline;
+ tptr = &t;
+ tokval.t_type = TOKEN_INVALID;
+ evalresult =
+ evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
+ free_tlist(tline);
+ if (!evalresult)
+ {
+ free_tlist(origline);
+ return 3;
+ }
- if (tokval.t_type)
- error(ERR_WARNING,
- "trailing garbage after expression ignored");
+ if (tokval.t_type)
+ error(ERR_WARNING,
+ "trailing garbage after expression ignored");
- if (!is_simple(evalresult)) {
- error(ERR_NONFATAL,
- "non-constant value given to `%%%sassign'",
- (i == PP_IASSIGN ? "i" : ""));
- free_tlist (origline);
- return 3;
- }
+ if (!is_simple(evalresult))
+ {
+ error(ERR_NONFATAL,
+ "non-constant value given to `%%%sassign'",
+ (i == PP_IASSIGN ? "i" : ""));
+ free_tlist(origline);
+ return 3;
+ }
- macro_start = nasm_malloc(sizeof(*macro_start));
- macro_start->next = NULL;
- make_tok_num(macro_start, reloc_value(evalresult));
- macro_start->mac = NULL;
+ macro_start = nasm_malloc(sizeof(*macro_start));
+ macro_start->next = NULL;
+ make_tok_num(macro_start, reloc_value(evalresult));
+ macro_start->mac = NULL;
- /*
- * We now have a macro name, an implicit parameter count of
- * zero, and a numeric token to use as an expansion. Create
- * and store an SMacro.
- */
- if (smacro_defined (ctx, mname, 0, &smac, i == PP_ASSIGN)) {
- if (!smac)
- error (ERR_WARNING,
- "single-line macro `%s' defined both with and"
- " without parameters", mname);
- else {
- /*
- * We're redefining, so we have to take over an
- * existing SMacro structure. This means freeing
- * what was already in it.
- */
- nasm_free (smac->name);
- free_tlist (smac->expansion);
- }
- }
- else {
- smac = nasm_malloc(sizeof(SMacro));
- smac->next = *smhead;
- *smhead = smac;
- }
- smac->name = nasm_strdup(mname);
- smac->casesense = (i == PP_ASSIGN);
- smac->nparam = 0;
- smac->expansion = macro_start;
- smac->in_progress = FALSE;
- free_tlist (origline);
- return 3;
-
- case PP_LINE:
- /*
- * Syntax is `%line nnn[+mmm] [filename]'
- */
- tline = tline->next;
- skip_white_(tline);
- if (!tok_type_(tline, TOK_NUMBER)) {
- error (ERR_NONFATAL, "`%%line' expects line number");
- free_tlist (origline);
+ /*
+ * We now have a macro name, an implicit parameter count of
+ * zero, and a numeric token to use as an expansion. Create
+ * and store an SMacro.
+ */
+ if (smacro_defined(ctx, mname, 0, &smac, i == PP_ASSIGN))
+ {
+ if (!smac)
+ error(ERR_WARNING,
+ "single-line macro `%s' defined both with and"
+ " without parameters", mname);
+ else
+ {
+ /*
+ * We're redefining, so we have to take over an
+ * existing SMacro structure. This means freeing
+ * what was already in it.
+ */
+ nasm_free(smac->name);
+ free_tlist(smac->expansion);
+ }
+ }
+ else
+ {
+ smac = nasm_malloc(sizeof(SMacro));
+ smac->next = *smhead;
+ *smhead = smac;
+ }
+ smac->name = nasm_strdup(mname);
+ smac->casesense = (i == PP_ASSIGN);
+ smac->nparam = 0;
+ smac->expansion = macro_start;
+ smac->in_progress = FALSE;
+ free_tlist(origline);
return 3;
- }
- k = readnum(tline->text, &j);
- m = 1;
- tline = tline->next;
- if (tok_is_(tline, "+")) {
+
+ case PP_LINE:
+ /*
+ * Syntax is `%line nnn[+mmm] [filename]'
+ */
tline = tline->next;
- if (!tok_type_(tline, TOK_NUMBER)) {
- error (ERR_NONFATAL,
- "`%%line' expects line increment");
- free_tlist (origline);
+ skip_white_(tline);
+ if (!tok_type_(tline, TOK_NUMBER))
+ {
+ error(ERR_NONFATAL, "`%%line' expects line number");
+ free_tlist(origline);
return 3;
}
- m = readnum(tline->text, &j);
+ k = readnum(tline->text, &j);
+ m = 1;
tline = tline->next;
- }
- skip_white_(tline);
- src_set_linnum(k);
- istk->lineinc = m;
- if (tline) {
- nasm_free (src_set_fname (detoken (tline, FALSE)));
- }
- free_tlist (origline);
- return 5;
-
- default:
- error(ERR_FATAL,
- "preprocessor directive `%s' not yet implemented",
- directives[i]);
- break;
+ if (tok_is_(tline, "+"))
+ {
+ tline = tline->next;
+ if (!tok_type_(tline, TOK_NUMBER))
+ {
+ error(ERR_NONFATAL, "`%%line' expects line increment");
+ free_tlist(origline);
+ return 3;
+ }
+ m = readnum(tline->text, &j);
+ tline = tline->next;
+ }
+ skip_white_(tline);
+ src_set_linnum(k);
+ istk->lineinc = m;
+ if (tline)
+ {
+ nasm_free(src_set_fname(detoken(tline, FALSE)));
+ }
+ free_tlist(origline);
+ return 5;
+
+ default:
+ error(ERR_FATAL,
+ "preprocessor directive `%s' not yet implemented",
+ directives[i]);
+ break;
}
return 3;
}
@@ -2583,7 +2910,8 @@ static int do_directive (Token *tline)
* nothing else. Return the condition code index if so, or -1
* otherwise.
*/
-static int find_cc (Token *t)
+static int
+find_cc(Token * t)
{
Token *tt;
int i, j, k, m;
@@ -2597,17 +2925,22 @@ static int find_cc (Token *t)
return -1;
i = -1;
- j = sizeof(conditions)/sizeof(*conditions);
- while (j-i > 1) {
- k = (j+i) / 2;
+ j = sizeof(conditions) / sizeof(*conditions);
+ while (j - i > 1)
+ {
+ k = (j + i) / 2;
m = nasm_stricmp(t->text, conditions[k]);
- if (m == 0) {
+ if (m == 0)
+ {
i = k;
j = -2;
break;
- } else if (m < 0) {
+ }
+ else if (m < 0)
+ {
j = k;
- } else
+ }
+ else
i = k;
}
if (j != -2)
@@ -2619,20 +2952,23 @@ static int find_cc (Token *t)
* Expand MMacro-local things: parameter references (%0, %n, %+n,
* %-n) and MMacro-local identifiers (%%foo).
*/
-static Token *expand_mmac_params (Token *tline)
+static Token *
+expand_mmac_params(Token * tline)
{
- Token *t, *tt, *ttt, **tail, *thead;
+ Token *t, *tt, **tail, *thead;
tail = &thead;
thead = NULL;
- while (tline) {
+ while (tline)
+ {
if (tline->type == TOK_PREPROC_ID &&
- (((tline->text[1] == '+' || tline->text[1] == '-') && tline->text [2]) ||
- tline->text[1] == '%' ||
- (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
+ (((tline->text[1] == '+' || tline->text[1] == '-')
+ && tline->text[2]) || tline->text[1] == '%'
+ || (tline->text[1] >= '0' && tline->text[1] <= '9')))
+ {
char *text = NULL;
- int type = 0, cc; /* type = 0 to placate optimisers */
+ int type = 0, cc; /* type = 0 to placate optimisers */
char tmpbuf[30];
int n, i;
MMacro *mac;
@@ -2641,105 +2977,126 @@ static Token *expand_mmac_params (Token *tline)
tline = tline->next;
mac = istk->mstk;
- while (mac && !mac->name) /* avoid mistaking %reps for macros */
+ while (mac && !mac->name) /* avoid mistaking %reps for macros */
mac = mac->next_active;
if (!mac)
error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
- else switch (t->text[1]) {
- /*
- * We have to make a substitution of one of the
- * forms %1, %-1, %+1, %%foo, %0.
- */
- case '0':
- type = TOK_NUMBER;
- sprintf(tmpbuf, "%d", mac->nparam);
- text = nasm_strdup(tmpbuf);
- break;
- case '%':
- type = TOK_ID;
- sprintf(tmpbuf, "..@%lu.", mac->unique);
- text = nasm_strcat(tmpbuf, t->text+2);
- break;
- case '-':
- n = atoi(t->text+2)-1;
- if (n >= mac->nparam)
- tt = NULL;
- else {
- if (mac->nparam > 1)
- n = (n + mac->rotate) % mac->nparam;
- tt = mac->params[n];
- }
- cc = find_cc (tt);
- if (cc == -1) {
- error (ERR_NONFATAL,
- "macro parameter %d is not a condition code",
- n+1);
- text = NULL;
- } else {
- type = TOK_ID;
- if (inverse_ccs[cc] == -1) {
- error (ERR_NONFATAL,
- "condition code `%s' is not invertible",
- conditions[cc]);
- text = NULL;
- } else
- text = nasm_strdup(conditions[inverse_ccs[cc]]);
- }
- break;
- case '+':
- n = atoi(t->text+2)-1;
- if (n >= mac->nparam)
- tt = NULL;
- else {
- if (mac->nparam > 1)
- n = (n + mac->rotate) % mac->nparam;
- tt = mac->params[n];
- }
- cc = find_cc (tt);
- if (cc == -1) {
- error (ERR_NONFATAL,
- "macro parameter %d is not a condition code",
- n+1);
- text = NULL;
- } else {
- type = TOK_ID;
- text = nasm_strdup(conditions[cc]);
- }
- break;
- default:
- n = atoi(t->text+1)-1;
- if (n >= mac->nparam)
- tt = NULL;
- else {
- if (mac->nparam > 1)
- n = (n + mac->rotate) % mac->nparam;
- tt = mac->params[n];
- }
- if (tt) {
- for (i=0; i<mac->paramlen[n]; i++) {
- ttt = *tail = nasm_malloc(sizeof(Token));
- tail = &ttt->next;
- ttt->type = tt->type;
- ttt->text = nasm_strdup(tt->text);
- ttt->mac = NULL;
- tt = tt->next;
- }
+ else
+ switch (t->text[1])
+ {
+ /*
+ * We have to make a substitution of one of the
+ * forms %1, %-1, %+1, %%foo, %0.
+ */
+ case '0':
+ type = TOK_NUMBER;
+ sprintf(tmpbuf, "%d", mac->nparam);
+ text = nasm_strdup(tmpbuf);
+ break;
+ case '%':
+ type = TOK_ID;
+ sprintf(tmpbuf, "..@%lu.", mac->unique);
+ text = nasm_strcat(tmpbuf, t->text + 2);
+ break;
+ case '-':
+ n = atoi(t->text + 2) - 1;
+ if (n >= mac->nparam)
+ tt = NULL;
+ else
+ {
+ if (mac->nparam > 1)
+ n = (n + mac->rotate) % mac->nparam;
+ tt = mac->params[n];
+ }
+ cc = find_cc(tt);
+ if (cc == -1)
+ {
+ error(ERR_NONFATAL,
+ "macro parameter %d is not a condition code",
+ n + 1);
+ text = NULL;
+ }
+ else
+ {
+ type = TOK_ID;
+ if (inverse_ccs[cc] == -1)
+ {
+ error(ERR_NONFATAL,
+ "condition code `%s' is not invertible",
+ conditions[cc]);
+ text = NULL;
+ }
+ else
+ text =
+ nasm_strdup(conditions[inverse_ccs
+ [cc]]);
+ }
+ break;
+ case '+':
+ n = atoi(t->text + 2) - 1;
+ if (n >= mac->nparam)
+ tt = NULL;
+ else
+ {
+ if (mac->nparam > 1)
+ n = (n + mac->rotate) % mac->nparam;
+ tt = mac->params[n];
+ }
+ cc = find_cc(tt);
+ if (cc == -1)
+ {
+ error(ERR_NONFATAL,
+ "macro parameter %d is not a condition code",
+ n + 1);
+ text = NULL;
+ }
+ else
+ {
+ type = TOK_ID;
+ text = nasm_strdup(conditions[cc]);
+ }
+ break;
+ default:
+ n = atoi(t->text + 1) - 1;
+ if (n >= mac->nparam)
+ tt = NULL;
+ else
+ {
+ if (mac->nparam > 1)
+ n = (n + mac->rotate) % mac->nparam;
+ tt = mac->params[n];
+ }
+ if (tt)
+ {
+ for (i = 0; i < mac->paramlen[n]; i++)
+ {
+ *tail =
+ new_Token(NULL, tt->type, tt->text,
+ 0);
+ tail = &(*tail)->next;
+ tt = tt->next;
+ }
+ }
+ text = NULL; /* we've done it here */
+ break;
}
- text = NULL; /* we've done it here */
- break;
+ if (!text)
+ {
+ delete_Token(t);
}
- nasm_free (t->text);
- if (!text) {
- nasm_free (t);
- } else {
+ else
+ {
*tail = t;
tail = &t->next;
t->type = type;
+ nasm_free(t->text);
t->text = text;
t->mac = NULL;
}
continue;
- } else {
+ }
+ else
+ {
t = *tail = tline;
tline = tline->next;
t->mac = NULL;
@@ -2748,37 +3105,35 @@ static Token *expand_mmac_params (Token *tline)
}
*tail = NULL;
t = thead;
- for (; t && (tt=t->next)!=NULL ; t = t->next)
- switch (t->type) {
- case TOK_WHITESPACE:
- if (tt->type == TOK_WHITESPACE) {
- t->next = tt->next;
- nasm_free(tt->text);
- nasm_free(tt);
- }
- break;
- case TOK_ID:
- if (tt->type == TOK_ID || tt->type == TOK_NUMBER) {
- char *tmp = nasm_strcat(t->text, tt->text);
- nasm_free(t->text);
- t->text = tmp;
- t->next = tt->next;
- nasm_free(tt->text);
- nasm_free(tt);
- }
- break;
- case TOK_NUMBER:
- if (tt->type == TOK_NUMBER) {
- char *tmp = nasm_strcat(t->text, tt->text);
- nasm_free(t->text);
- t->text = tmp;
- t->next = tt->next;
- nasm_free(tt->text);
- nasm_free(tt);
- }
- break;
+ for (; t && (tt = t->next) != NULL; t = t->next)
+ switch (t->type)
+ {
+ case TOK_WHITESPACE:
+ if (tt->type == TOK_WHITESPACE)
+ {
+ t->next = delete_Token(tt);
+ }
+ break;
+ case TOK_ID:
+ if (tt->type == TOK_ID || tt->type == TOK_NUMBER)
+ {
+ char *tmp = nasm_strcat(t->text, tt->text);
+ nasm_free(t->text);
+ t->text = tmp;
+ t->next = delete_Token(tt);
+ }
+ break;
+ case TOK_NUMBER:
+ if (tt->type == TOK_NUMBER)
+ {
+ char *tmp = nasm_strcat(t->text, tt->text);
+ nasm_free(t->text);
+ t->text = tmp;
+ t->next = delete_Token(tt);
+ }
+ break;
}
-
+
return thead;
}
@@ -2789,7 +3144,8 @@ static Token *expand_mmac_params (Token *tline)
* Tokens from input to output a lot of the time, rather than
* actually bothering to destroy and replicate.)
*/
-static Token *expand_smacro (Token *tline)
+static Token *
+expand_smacro(Token * tline)
{
Token *t, *tt, *mstart, **tail, *thead;
SMacro *head = NULL, *m;
@@ -2808,239 +3164,260 @@ static Token *expand_smacro (Token *tline)
*/
if (org_tline)
{
- tline = nasm_malloc (sizeof (Token));
- *tline = *org_tline;
+ tline =
+ new_Token(org_tline->next, org_tline->type, org_tline->text,
+ 0);
+ tline->mac = org_tline->mac;
}
-again:
+ again:
tail = &thead;
thead = NULL;
- while (tline) { /* main token loop */
- if ((mname = tline->text)) {
+ while (tline)
+ { /* main token loop */
+ if ((mname = tline->text))
+ {
/* if this token is a local macro, look in local context */
if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
- ctx = get_ctx (mname, TRUE);
- else
+ ctx = get_ctx(mname, TRUE);
+ else
ctx = NULL;
if (!ctx)
head = smacros[hash(mname)];
else
head = ctx->localmac;
- /*
- * We've hit an identifier. As in is_mmacro below, we first
- * check whether the identifier is a single-line macro at
- * all, then think about checking for parameters if
- * necessary.
- */
+ /*
+ * We've hit an identifier. As in is_mmacro below, we first
+ * check whether the identifier is a single-line macro at
+ * all, then think about checking for parameters if
+ * necessary.
+ */
for (m = head; m; m = m->next)
if (!mstrcmp(m->name, mname, m->casesense))
break;
- if (m) {
- mstart = tline;
- params = NULL;
- paramsize = NULL;
- if (m->nparam == 0) {
- /*
- * Simple case: the macro is parameterless. Discard the
- * one token that the macro call took, and push the
- * expansion back on the to-do stack.
- */
- if (!m->expansion)
+ if (m)
+ {
+ mstart = tline;
+ params = NULL;
+ paramsize = NULL;
+ if (m->nparam == 0)
{
- if (!strcmp("__FILE__", m->name)) {
- long num=0;
- src_get(&num, &(tline->text));
- nasm_quote(&(tline->text));
- tline->type = TOK_STRING;
- continue;
- }
- if (!strcmp("__LINE__", m->name)) {
- nasm_free(tline->text);
- make_tok_num(tline, src_get_linnum());
+ /*
+ * Simple case: the macro is parameterless. Discard the
+ * one token that the macro call took, and push the
+ * expansion back on the to-do stack.
+ */
+ if (!m->expansion)
+ {
+ if (!strcmp("__FILE__", m->name))
+ {
+ long num = 0;
+ src_get(&num, &(tline->text));
+ nasm_quote(&(tline->text));
+ tline->type = TOK_STRING;
+ continue;
+ }
+ if (!strcmp("__LINE__", m->name))
+ {
+ nasm_free(tline->text);
+ make_tok_num(tline, src_get_linnum());
+ continue;
+ }
+ tline = delete_Token(tline);
continue;
}
- t = tline;
+ }
+ else
+ {
+ /*
+ * Complicated case: at least one macro with this name
+ * exists and takes parameters. We must find the
+ * parameters in the call, count them, find the SMacro
+ * that corresponds to that form of the macro call, and
+ * substitute for the parameters when we expand. What a
+ * pain.
+ */
tline = tline->next;
- nasm_free (t->text);
- nasm_free (t);
- continue;
+ skip_white_(tline);
+ if (!tok_is_(tline, "("))
+ {
+ /*
+ * This macro wasn't called with parameters: ignore
+ * the call. (Behaviour borrowed from gnu cpp.)
+ */
+ tline = mstart;
+ m = NULL;
+ }
+ else
+ {
+ int paren = 0;
+ int white = 0;
+ brackets = 0;
+ nparam = 0;
+ tline = tline->next;
+ sparam = PARAM_DELTA;
+ params = nasm_malloc(sparam * sizeof(Token *));
+ params[0] = tline;
+ paramsize = nasm_malloc(sparam * sizeof(int));
+ paramsize[0] = 0;
+ for (;; tline = tline->next)
+ { /* parameter loop */
+ if (!tline)
+ {
+ error(ERR_NONFATAL,
+ "macro call expects terminating `)'");
+ break;
+ }
+ if (tline->type == TOK_WHITESPACE
+ && brackets <= 0)
+ {
+ if (paramsize[nparam])
+ white++;
+ else
+ params[nparam] = tline->next;
+ continue; /* parameter loop */
+ }
+ if (tline->type == TOK_OTHER
+ && tline->text[1] == 0)
+ {
+ char ch = tline->text[0];
+ if (ch == ',' && !paren && brackets <= 0)
+ {
+ if (++nparam >= sparam)
+ {
+ sparam += PARAM_DELTA;
+ params = nasm_realloc(params,
+ sparam * sizeof(Token *));
+ paramsize = nasm_realloc(paramsize,
+ sparam * sizeof(int));
+ }
+ params[nparam] = tline->next;
+ paramsize[nparam] = 0;
+ white = 0;
+ continue; /* parameter loop */
+ }
+ if (ch == '{' &&
+ (brackets > 0 || (brackets == 0 &&
+ !paramsize[nparam])))
+ {
+ if (!(brackets++))
+ {
+ params[nparam] = tline->next;
+ continue; /* parameter loop */
+ }
+ }
+ if (ch == '}' && brackets > 0)
+ if (--brackets == 0)
+ {
+ brackets = -1;
+ continue; /* parameter loop */
+ }
+ if (ch == '(' && !brackets)
+ paren++;
+ if (ch == ')' && brackets <= 0)
+ if (--paren < 0)
+ break;
+ }
+ if (brackets < 0)
+ {
+ brackets = 0;
+ error(ERR_NONFATAL, "braces do not "
+ "enclose all of macro parameter");
+ }
+ paramsize[nparam] += white + 1;
+ white = 0;
+ } /* parameter loop */
+ nparam++;
+ while (m && (m->nparam != nparam ||
+ mstrcmp(m->name, mname,
+ m->casesense)))
+ m = m->next;
+ if (!m)
+ error(ERR_WARNING | ERR_WARN_MNP,
+ "macro `%s' exists, "
+ "but not taking %d parameters",
+ mstart->text, nparam);
+ }
}
- } else {
- /*
- * Complicated case: at least one macro with this name
- * exists and takes parameters. We must find the
- * parameters in the call, count them, find the SMacro
- * that corresponds to that form of the macro call, and
- * substitute for the parameters when we expand. What a
- * pain.
- */
- tline = tline->next;
- skip_white_(tline);
- if (!tok_is_(tline, "(")) {
- /*
- * This macro wasn't called with parameters: ignore
- * the call. (Behaviour borrowed from gnu cpp.)
- */
- tline = mstart;
- m = NULL;
- }
- else {
- int paren = 0;
- int white = 0;
- brackets = 0;
- nparam = 0;
- tline = tline->next;
- sparam = PARAM_DELTA;
- params = nasm_malloc (sparam*sizeof(Token *));
- params[0] = tline;
- paramsize = nasm_malloc (sparam*sizeof(int));
- paramsize[0] = 0;
- for (;;tline = tline->next) { /* parameter loop */
- if (!tline) {
- error(ERR_NONFATAL,
- "macro call expects terminating `)'");
- break;
- }
- if (tline->type == TOK_WHITESPACE && brackets<=0) {
- if (paramsize[nparam])
- white++;
- else
- params[nparam] = tline->next;
- continue; /* parameter loop */
- }
- if (tline->type == TOK_OTHER && tline->text[1]==0) {
- char ch = tline->text[0];
- if (ch == ',' && !paren && brackets<=0) {
- if (++nparam >= sparam) {
- sparam += PARAM_DELTA;
- params = nasm_realloc (params,
- sparam*sizeof(Token *));
- paramsize = nasm_realloc (paramsize,
- sparam*sizeof(int));
- }
- params[nparam] = tline->next;
- paramsize[nparam] = 0;
- white = 0;
- continue; /* parameter loop */
- }
- if (ch == '{' &&
- (brackets>0 || (brackets==0 &&
- !paramsize[nparam])))
- {
- if (!(brackets++))
- {
- params[nparam] = tline->next;
- continue; /* parameter loop */
- }
- }
- if (ch == '}' && brackets>0)
- if (--brackets == 0) {
- brackets = -1;
- continue; /* parameter loop */
- }
- if (ch == '(' && !brackets)
- paren++;
- if (ch == ')' && brackets<=0)
- if (--paren < 0)
- break;
- }
- if (brackets<0) {
- brackets = 0;
- error (ERR_NONFATAL, "braces do not "
- "enclose all of macro parameter");
- }
- paramsize[nparam] += white+1;
- white = 0;
- } /* parameter loop */
- nparam++;
- while (m && (m->nparam != nparam ||
- mstrcmp(m->name, mname, m->casesense)))
- m = m->next;
- if (!m)
- error (ERR_WARNING|ERR_WARN_MNP,
- "macro `%s' exists, "
- "but not taking %d parameters",
- mstart->text, nparam);
- }
- }
- if (m && m->in_progress)
- m = NULL;
- if (!m) /* in progess or didn't find '(' or wrong nparam */
- {
- /*
- * Design question: should we handle !tline, which
- * indicates missing ')' here, or expand those
- * macros anyway, which requires the (t) test a few
- * lines down?
- */
- nasm_free (params);
- nasm_free (paramsize);
- tline = mstart;
- } else {
- /*
- * Expand the macro: we are placed on the last token of the
- * call, so that we can easily split the call from the
- * following tokens. We also start by pushing an SMAC_END
- * token for the cycle removal.
- */
- t = tline;
- if (t) {
- tline = t->next;
- t->next = NULL;
+ if (m && m->in_progress)
+ m = NULL;
+ if (!m) /* in progess or didn't find '(' or wrong nparam */
+ {
+ /*
+ * Design question: should we handle !tline, which
+ * indicates missing ')' here, or expand those
+ * macros anyway, which requires the (t) test a few
+ * lines down?
+ */
+ nasm_free(params);
+ nasm_free(paramsize);
+ tline = mstart;
}
- tt = nasm_malloc(sizeof(Token));
- tt->type = TOK_SMAC_END;
- tt->text = NULL;
- tt->mac = m;
- m->in_progress = TRUE;
- tt->next = tline;
- tline = tt;
- for (t = m->expansion; t; t = t->next) {
- if (t->type >= TOK_SMAC_PARAM) {
- Token *pcopy = tline, **ptail = &pcopy;
- Token *ttt, *pt;
- int i;
-
- ttt = params[t->type - TOK_SMAC_PARAM];
- for (i=paramsize[t->type-TOK_SMAC_PARAM]; --i>=0;) {
- pt = *ptail = nasm_malloc(sizeof(Token));
- pt->next = tline;
- ptail = &pt->next;
- pt->text = nasm_strdup(ttt->text);
- pt->type = ttt->type;
- pt->mac = NULL;
- ttt = ttt->next;
+ else
+ {
+ /*
+ * Expand the macro: we are placed on the last token of the
+ * call, so that we can easily split the call from the
+ * following tokens. We also start by pushing an SMAC_END
+ * token for the cycle removal.
+ */
+ t = tline;
+ if (t)
+ {
+ tline = t->next;
+ t->next = NULL;
+ }
+ tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
+ tt->mac = m;
+ m->in_progress = TRUE;
+ tline = tt;
+ for (t = m->expansion; t; t = t->next)
+ {
+ if (t->type >= TOK_SMAC_PARAM)
+ {
+ Token *pcopy = tline, **ptail = &pcopy;
+ Token *ttt, *pt;
+ int i;
+
+ ttt = params[t->type - TOK_SMAC_PARAM];
+ for (i = paramsize[t->type - TOK_SMAC_PARAM];
+ --i >= 0;)
+ {
+ pt = *ptail =
+ new_Token(tline, ttt->type, ttt->text,
+ 0);
+ ptail = &pt->next;
+ ttt = ttt->next;
+ }
+ tline = pcopy;
+ }
+ else
+ {
+ tt = new_Token(tline, t->type, t->text, 0);
+ tline = tt;
}
- tline = pcopy;
- } else {
- tt = nasm_malloc(sizeof(Token));
- tt->type = t->type;
- tt->text = nasm_strdup(t->text);
- tt->mac = NULL;
- tt->next = tline;
- tline = tt;
}
+
+ /*
+ * Having done that, get rid of the macro call, and clean
+ * up the parameters.
+ */
+ nasm_free(params);
+ nasm_free(paramsize);
+ free_tlist(mstart);
+ continue; /* main token loop */
}
-
- /*
- * Having done that, get rid of the macro call, and clean
- * up the parameters.
- */
- nasm_free (params);
- nasm_free (paramsize);
- free_tlist (mstart);
- continue; /* main token loop */
- }
}
}
- if (tline->type == TOK_SMAC_END) {
+ if (tline->type == TOK_SMAC_END)
+ {
tline->mac->in_progress = FALSE;
- t = tline;
- tline = tline->next;
- nasm_free (t);
- } else {
+ tline = delete_Token(tline);
+ }
+ else
+ {
t = *tail = tline;
tline = tline->next;
t->mac = NULL;
@@ -3058,60 +3435,61 @@ again:
*/
t = thead;
rescan = 0;
- while (t) {
+ while (t)
+ {
while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
t = t->next;
if (!t || !t->next)
break;
if (t->next->type == TOK_ID ||
- t->next->type == TOK_PREPROC_ID ||
- t->next->type == TOK_NUMBER) {
- Token *next = t->next->next;
- char *p = nasm_malloc (strlen (t->text) + strlen (t->next->text) + 1);
- strcpy (p, t->text);
- strcat (p, t->next->text);
- nasm_free (t->text);
- nasm_free (t->next->text);
- nasm_free (t->next);
- t->next = next;
- t->text = p;
+ t->next->type == TOK_PREPROC_ID ||
+ t->next->type == TOK_NUMBER)
+ {
+ char *p = nasm_strcat(t->text, t->next->text);
+ nasm_free(t->text);
+ t->next = delete_Token(t->next);
+ t->text = p;
rescan = 1;
- } else if (t->next->type == TOK_WHITESPACE && t->next->next &&
- t->next->next->type == TOK_PREPROC_ID &&
- strcmp (t->next->next->text, "%+") == 0) {
+ }
+ else if (t->next->type == TOK_WHITESPACE && t->next->next &&
+ t->next->next->type == TOK_PREPROC_ID &&
+ strcmp(t->next->next->text, "%+") == 0)
+ {
/* free the next whitespace, the %+ token and next whitespace */
- int i;
- for (i = 1; i <= 3; i++)
- {
- Token *next;
+ int i;
+ for (i = 1; i <= 3; i++)
+ {
if (!t->next || (i != 2 && t->next->type != TOK_WHITESPACE))
break;
- next = t->next->next;
- nasm_free (t->next->text);
- nasm_free (t->next);
- t->next = next;
- } /* endfor */
- } else
- t = t->next;
- }
+ t->next = delete_Token(t->next);
+ } /* endfor */
+ }
+ else
+ t = t->next;
+ }
/* If we concatenaded something, re-scan the line for macros */
- if (rescan) {
+ if (rescan)
+ {
tline = thead;
goto again;
- }
+ }
if (org_tline)
{
- if (thead) {
+ if (thead)
+ {
*org_tline = *thead;
- nasm_free (thead);
- } else
+ /* since we just gave text to org_line, don't free it */
+ thead->text = NULL;
+ delete_Token(thead);
+ }
+ else
{
/* the expression expanded to empty line;
we can't return NULL for some reasons
we just set the line to a single WHITESPACE token. */
- memset (org_tline, 0, sizeof (*org_tline));
- org_tline->text = nasm_strdup (" ");
+ memset(org_tline, 0, sizeof(*org_tline));
+ org_tline->text = NULL;
org_tline->type = TOK_WHITESPACE;
}
thead = org_tline;
@@ -3139,35 +3517,36 @@ again:
* otherwise it will be left as-is) then concatenate all successive
* PP_IDs into one.
*/
-static Token *expand_id (Token *tline)
+static Token *
+expand_id(Token * tline)
{
Token *cur, *oldnext = NULL;
- if (!tline ||
- !tline->next)
+ if (!tline || !tline->next)
return tline;
cur = tline;
while (cur->next &&
- (cur->next->type == TOK_ID ||
- cur->next->type == TOK_PREPROC_ID ||
- cur->next->type == TOK_NUMBER))
+ (cur->next->type == TOK_ID ||
+ cur->next->type == TOK_PREPROC_ID || cur->next->type == TOK_NUMBER))
cur = cur->next;
/* If identifier consists of just one token, don't expand */
if (cur == tline)
return tline;
- if (cur) {
- oldnext = cur->next; /* Detach the tail past identifier */
- cur->next = NULL; /* so that expand_smacro stops here */
+ if (cur)
+ {
+ oldnext = cur->next; /* Detach the tail past identifier */
+ cur->next = NULL; /* so that expand_smacro stops here */
}
- tline = expand_smacro (tline);
+ tline = expand_smacro(tline);
- if (cur) {
+ if (cur)
+ {
/* expand_smacro possibly changhed tline; re-scan for EOL */
- cur = tline;
+ cur = tline;
while (cur && cur->next)
cur = cur->next;
if (cur)
@@ -3185,7 +3564,8 @@ static Token *expand_id (Token *tline)
* to be called with tline->type == TOK_ID, so the putative macro
* name is easy to find.
*/
-static MMacro *is_mmacro (Token *tline, Token ***params_array)
+static MMacro *
+is_mmacro(Token * tline, Token *** params_array)
{
MMacro *head, *m;
Token **params;
@@ -3209,35 +3589,40 @@ static MMacro *is_mmacro (Token *tline, Token ***params_array)
* OK, we have a potential macro. Count and demarcate the
* parameters.
*/
- count_mmac_params (tline->next, &nparam, &params);
+ count_mmac_params(tline->next, &nparam, &params);
/*
* So we know how many parameters we've got. Find the MMacro
* structure that handles this number.
*/
- while (m) {
- if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max)) {
+ while (m)
+ {
+ if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max))
+ {
/*
* This one is right. Just check if cycle removal
* prohibits us using it before we actually celebrate...
*/
- if (m->in_progress) {
+ if (m->in_progress)
+ {
#if 0
- error (ERR_NONFATAL,
- "self-reference in multi-line macro `%s'",
- m->name);
+ error(ERR_NONFATAL,
+ "self-reference in multi-line macro `%s'", m->name);
#endif
- nasm_free (params);
+ nasm_free(params);
return NULL;
}
/*
* It's right, and we can use it. Add its default
* parameters to the end of our list if necessary.
*/
- if (m->defaults && nparam < m->nparam_min + m->ndefs) {
- params = nasm_realloc (params, ((m->nparam_min+m->ndefs+1) *
- sizeof(*params)));
- while (nparam < m->nparam_min + m->ndefs) {
+ if (m->defaults && nparam < m->nparam_min + m->ndefs)
+ {
+ params =
+ nasm_realloc(params,
+ ((m->nparam_min + m->ndefs + 1) * sizeof(*params)));
+ while (nparam < m->nparam_min + m->ndefs)
+ {
params[nparam] = m->defaults[nparam - m->nparam_min];
nparam++;
}
@@ -3252,7 +3637,8 @@ static MMacro *is_mmacro (Token *tline, Token ***params_array)
/*
* Then terminate the parameter list, and leave.
*/
- if (!params) { /* need this special case */
+ if (!params)
+ { /* need this special case */
params = nasm_malloc(sizeof(*params));
nparam = 0;
}
@@ -3273,10 +3659,10 @@ static MMacro *is_mmacro (Token *tline, Token ***params_array)
* After all that, we didn't find one with the right number of
* parameters. Issue a warning, and fail to expand the macro.
*/
- error (ERR_WARNING|ERR_WARN_MNP,
- "macro `%s' exists, but not taking %d parameters",
- tline->text, nparam);
- nasm_free (params);
+ error(ERR_WARNING | ERR_WARN_MNP,
+ "macro `%s' exists, but not taking %d parameters",
+ tline->text, nparam);
+ nasm_free(params);
return NULL;
}
@@ -3285,7 +3671,8 @@ static MMacro *is_mmacro (Token *tline, Token ***params_array)
* there is one to be expanded. If there is, push the expansion on
* istk->expansion and return 1. Otherwise return 0.
*/
-static int expand_mmacro (Token *tline)
+static int
+expand_mmacro(Token * tline)
{
Token *startline = tline;
Token *label = NULL;
@@ -3299,8 +3686,9 @@ static int expand_mmacro (Token *tline)
skip_white_(t);
if (!tok_type_(t, TOK_ID))
return 0;
- m = is_mmacro (t, &params);
- if (!m) {
+ m = is_mmacro(t, &params);
+ if (!m)
+ {
Token *last;
/*
* We have an id which isn't a macro call. We'll assume
@@ -3312,7 +3700,8 @@ static int expand_mmacro (Token *tline)
t = t->next;
if (tok_type_(t, TOK_WHITESPACE))
last = t, t = t->next;
- if (tok_is_(t, ":")) {
+ if (tok_is_(t, ":"))
+ {
dont_prepend = 1;
last = t, t = t->next;
if (tok_type_(t, TOK_WHITESPACE))
@@ -3331,11 +3720,12 @@ static int expand_mmacro (Token *tline)
*/
for (nparam = 0; params[nparam]; nparam++)
;
- paramlen = nparam ? nasm_malloc(nparam*sizeof(*paramlen)) : NULL;
+ paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
- for (i = 0; params[i]; i++) {
+ for (i = 0; params[i]; i++)
+ {
int brace = FALSE;
- int comma = (!m->plus || i < nparam-1);
+ int comma = (!m->plus || i < nparam - 1);
t = params[i];
skip_white_(t);
@@ -3343,13 +3733,14 @@ static int expand_mmacro (Token *tline)
t = t->next, brace = TRUE, comma = FALSE;
params[i] = t;
paramlen[i] = 0;
- while (t) {
+ while (t)
+ {
if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
- break; /* ... because we have hit a comma */
+ break; /* ... because we have hit a comma */
if (comma && t->type == TOK_WHITESPACE && tok_is_(t->next, ","))
- break; /* ... or a space then a comma */
+ break; /* ... or a space then a comma */
if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
- break; /* ... or a brace */
+ break; /* ... or a brace */
t = t->next;
paramlen[i]++;
}
@@ -3386,7 +3777,8 @@ static int expand_mmacro (Token *tline)
m->next_active = istk->mstk;
istk->mstk = m;
- for (l = m->expansion; l; l = l->next) {
+ for (l = m->expansion; l; l = l->next)
+ {
Token **tail;
ll = nasm_malloc(sizeof(Line));
@@ -3395,21 +3787,19 @@ static int expand_mmacro (Token *tline)
istk->expansion = ll;
tail = &ll->first;
- for (t = l->first; t; t = t->next) {
+ for (t = l->first; t; t = t->next)
+ {
Token *x = t;
- if (t->type == TOK_PREPROC_ID &&
- t->text[1]=='0' && t->text[2]=='0')
+ if (t->type == TOK_PREPROC_ID &&
+ t->text[1] == '0' && t->text[2] == '0')
{
dont_prepend = -1;
x = label;
if (!x)
continue;
}
- tt = *tail = nasm_malloc(sizeof(Token));
+ tt = *tail = new_Token(NULL, x->type, x->text, 0);
tail = &tt->next;
- tt->type = x->type;
- tt->text = nasm_strdup(x->text);
- tt->mac = NULL;
}
*tail = NULL;
}
@@ -3418,28 +3808,27 @@ static int expand_mmacro (Token *tline)
* If we had a label, push it on as the first line of
* the macro expansion.
*/
- if (label) {
- if (dont_prepend<0)
+ if (label)
+ {
+ if (dont_prepend < 0)
free_tlist(startline);
- else {
+ else
+ {
ll = nasm_malloc(sizeof(Line));
ll->finishes = NULL;
ll->next = istk->expansion;
istk->expansion = ll;
ll->first = startline;
- if (!dont_prepend) {
+ if (!dont_prepend)
+ {
while (label->next)
label = label->next;
- label->next = tt = nasm_malloc(sizeof(Token));
- tt->next = NULL;
- tt->mac = NULL;
- tt->type = TOK_OTHER;
- tt->text = nasm_strdup(":");
+ label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
}
}
}
- list->uplevel (m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
+ list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
return 1;
}
@@ -3450,28 +3839,30 @@ static int expand_mmacro (Token *tline)
* won't want to see same error twice (preprocessing is done once
* per pass) we will want to show errors only during pass one.
*/
-static void error (int severity, char *fmt, ...)
+static void
+error(int severity, char *fmt, ...)
{
va_list arg;
- char buff [1024];
+ char buff[1024];
/* If we're in a dead branch of IF or something like it, ignore the error */
if (istk->conds && !emitting(istk->conds->state))
return;
- va_start (arg, fmt);
- vsprintf (buff, fmt, arg);
- va_end (arg);
+ va_start(arg, fmt);
+ vsprintf(buff, fmt, arg);
+ va_end(arg);
if (istk->mstk && istk->mstk->name)
- __error (severity|ERR_PASS1, "(%s:%d) %s", istk->mstk->name,
- istk->mstk->lineno, buff);
+ __error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name,
+ istk->mstk->lineno, buff);
else
- __error (severity|ERR_PASS1, "%s", buff);
+ __error(severity | ERR_PASS1, "%s", buff);
}
-static void pp_reset (char *file, int apass, efunc errfunc, evalfunc eval,
- ListGen *listgen)
+static void
+pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
+ ListGen * listgen)
{
int h;
@@ -3488,35 +3879,43 @@ static void pp_reset (char *file, int apass, efunc errfunc, evalfunc eval,
src_set_linnum(0);
istk->lineinc = 1;
if (!istk->fp)
- error (ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'", file);
+ error(ERR_FATAL | ERR_NOFILE, "unable to open input file `%s'", file);
defining = NULL;
- for (h=0; h<NHASH; h++) {
+ for (h = 0; h < NHASH; h++)
+ {
mmacros[h] = NULL;
smacros[h] = NULL;
}
unique = 0;
- stdmacpos = stdmac;
+ if (tasm_compatible_mode) {
+ stdmacpos = stdmac;
+ } else {
+ stdmacpos = &stdmac[TASM_MACRO_COUNT];
+ }
any_extrastdmac = (extrastdmac != NULL);
list = listgen;
evaluate = eval;
pass = apass;
}
-static char *pp_getline (void)
+static char *
+pp_getline(void)
{
char *line;
Token *tline;
- int ret;
- while (1) {
+ while (1)
+ {
/*
* Fetch a tokenised line, either from the macro-expansion
* buffer or from the input file.
*/
tline = NULL;
- while (istk->expansion && istk->expansion->finishes) {
+ while (istk->expansion && istk->expansion->finishes)
+ {
Line *l = istk->expansion;
- if (!l->finishes->name && l->finishes->in_progress > 1) {
+ if (!l->finishes->name && l->finishes->in_progress > 1)
+ {
Line *ll;
/*
@@ -3533,7 +3932,8 @@ static char *pp_getline (void)
* if we did.
*/
l->finishes->in_progress--;
- for (l = l->finishes->expansion; l; l = l->next) {
+ for (l = l->finishes->expansion; l; l = l->next)
+ {
Token *t, *tt, **tail;
ll = nasm_malloc(sizeof(Line));
@@ -3542,20 +3942,20 @@ static char *pp_getline (void)
ll->first = NULL;
tail = &ll->first;
- for (t = l->first; t; t = t->next) {
- if (t->text) {
- tt = *tail = nasm_malloc(sizeof(Token));
- tt->next = NULL;
+ for (t = l->first; t; t = t->next)
+ {
+ if (t->text || t->type == TOK_WHITESPACE)
+ {
+ tt = *tail = new_Token(NULL, t->type, t->text, 0);
tail = &tt->next;
- tt->type = t->type;
- tt->text = nasm_strdup(t->text);
- tt->mac = NULL;
}
}
istk->expansion = ll;
}
- } else {
+ }
+ else
+ {
/*
* Check whether a `%rep' was started and not ended
* within this macro expansion. This can happen and
@@ -3563,23 +3963,24 @@ static char *pp_getline (void)
* I'm too confused to work out how to recover
* sensibly from it.
*/
- if (defining) {
+ if (defining)
+ {
if (defining->name)
- error (ERR_PANIC,
- "defining with name in expansion");
+ error(ERR_PANIC, "defining with name in expansion");
else if (istk->mstk->name)
- error (ERR_FATAL, "`%%rep' without `%%endrep' within"
- " expansion of macro `%s'", istk->mstk->name);
+ error(ERR_FATAL, "`%%rep' without `%%endrep' within"
+ " expansion of macro `%s'", istk->mstk->name);
}
- /*
+ /*
* FIXME: investigate the relationship at this point between
* istk->mstk and l->finishes
*/
{
MMacro *m = istk->mstk;
istk->mstk = m->next_active;
- if (m->name) {
+ if (m->name)
+ {
/*
* This was a real macro call, not a %rep, and
* therefore the parameter information needs to
@@ -3589,35 +3990,38 @@ static char *pp_getline (void)
free_tlist(m->iline);
nasm_free(m->paramlen);
l->finishes->in_progress = FALSE;
- }
+ }
else
free_mmacro(m);
}
istk->expansion = l->next;
- nasm_free (l);
- list->downlevel (LIST_MACRO);
+ nasm_free(l);
+ list->downlevel(LIST_MACRO);
}
}
- while (1) { /* until we get a line we can use */
+ while (1)
+ { /* until we get a line we can use */
- if (istk->expansion) { /* from a macro expansion */
+ if (istk->expansion)
+ { /* from a macro expansion */
char *p;
Line *l = istk->expansion;
if (istk->mstk)
istk->mstk->lineno++;
tline = l->first;
istk->expansion = l->next;
- nasm_free (l);
- p = detoken (tline, FALSE);
- list->line (LIST_MACRO, p);
+ nasm_free(l);
+ p = detoken(tline, FALSE);
+ list->line(LIST_MACRO, p);
nasm_free(p);
break;
}
line = read_line();
- if (line) { /* from the current input file */
+ if (line)
+ { /* from the current input file */
line = prepreproc(line);
tline = tokenise(line);
- nasm_free (line);
+ nasm_free(line);
break;
}
/*
@@ -3629,10 +4033,10 @@ static char *pp_getline (void)
if (i->conds)
error(ERR_FATAL, "expected `%%endif' before end of file");
istk = i->next;
- list->downlevel (LIST_INCLUDE);
+ list->downlevel(LIST_INCLUDE);
src_set_linnum(i->lineno);
- nasm_free ( src_set_fname(i->fname) );
- nasm_free (i);
+ nasm_free(src_set_fname(i->fname));
+ nasm_free(i);
if (!istk)
return NULL;
}
@@ -3654,10 +4058,12 @@ static char *pp_getline (void)
/*
* Check the line to see if it's a preprocessor directive.
*/
- ret = do_directive(tline);
- if (ret & 1) {
- continue;
- } else if (defining) {
+ if (do_directive(tline) & 1)
+ {
+ continue;
+ }
+ else if (defining)
+ {
/*
* We're defining a multi-line macro. We emit nothing
* at all, and just
@@ -3669,7 +4075,9 @@ static char *pp_getline (void)
l->finishes = FALSE;
defining->expansion = l;
continue;
- } else if (istk->conds && !emitting(istk->conds->state)) {
+ }
+ else if (istk->conds && !emitting(istk->conds->state))
+ {
/*
* We're in a non-emitting branch of a condition block.
* Emit nothing at all, not even a blank line: when we
@@ -3678,7 +4086,9 @@ static char *pp_getline (void)
*/
free_tlist(tline);
continue;
- } else if (istk->mstk && !istk->mstk->in_progress) {
+ }
+ else if (istk->mstk && !istk->mstk->in_progress)
+ {
/*
* We're in a %rep block which has been terminated, so
* we're walking through to the %endrep without
@@ -3689,18 +4099,22 @@ static char *pp_getline (void)
*/
free_tlist(tline);
continue;
- } else {
+ }
+ else
+ {
tline = expand_smacro(tline);
- ret = expand_mmacro(tline);
- if (!ret) {
+ if (!expand_mmacro(tline))
+ {
/*
* De-tokenise the line again, and emit it.
*/
line = detoken(tline, TRUE);
- free_tlist (tline);
+ free_tlist(tline);
break;
- } else {
- continue; /* expand_mmacro calls free_tlist */
+ }
+ else
+ {
+ continue; /* expand_mmacro calls free_tlist */
}
}
}
@@ -3708,43 +4122,50 @@ static char *pp_getline (void)
return line;
}
-static void pp_cleanup (void)
+static void
+pp_cleanup(void)
{
int h;
- if (defining) {
- error (ERR_NONFATAL, "end of file while still defining macro `%s'",
- defining->name);
- free_mmacro (defining);
+ if (defining)
+ {
+ error(ERR_NONFATAL, "end of file while still defining macro `%s'",
+ defining->name);
+ free_mmacro(defining);
}
while (cstk)
ctx_pop();
- for (h=0; h<NHASH; h++) {
- while (mmacros[h]) {
+ for (h = 0; h < NHASH; h++)
+ {
+ while (mmacros[h])
+ {
MMacro *m = mmacros[h];
mmacros[h] = mmacros[h]->next;
free_mmacro(m);
}
- while (smacros[h]) {
+ while (smacros[h])
+ {
SMacro *s = smacros[h];
smacros[h] = smacros[h]->next;
- nasm_free (s->name);
- free_tlist (s->expansion);
- nasm_free (s);
+ nasm_free(s->name);
+ free_tlist(s->expansion);
+ nasm_free(s);
}
}
- while (istk) {
+ while (istk)
+ {
Include *i = istk;
istk = istk->next;
fclose(i->fp);
- nasm_free (i->fname);
- nasm_free (i);
+ nasm_free(i->fname);
+ nasm_free(i);
}
while (cstk)
ctx_pop();
}
-void pp_include_path (char *path)
+void
+pp_include_path(char *path)
{
IncPath *i;
@@ -3754,24 +4175,15 @@ void pp_include_path (char *path)
ipath = i;
}
-void pp_pre_include (char *fname)
+void
+pp_pre_include(char *fname)
{
Token *inc, *space, *name;
Line *l;
- inc = nasm_malloc(sizeof(Token));
- inc->next = space = nasm_malloc(sizeof(Token));
- space->next = name = nasm_malloc(sizeof(Token));
- name->next = NULL;
-
- inc->type = TOK_PREPROC_ID;
- inc->text = nasm_strdup("%include");
- space->type = TOK_WHITESPACE;
- space->text = nasm_strdup(" ");
- name->type = TOK_INTERNAL_STRING;
- name->text = nasm_strdup(fname);
-
- inc->mac = space->mac = name->mac = NULL;
+ name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
+ space = new_Token(name, TOK_WHITESPACE, NULL, 0);
+ inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
l = nasm_malloc(sizeof(Line));
l->next = predef;
@@ -3780,29 +4192,22 @@ void pp_pre_include (char *fname)
predef = l;
}
-void pp_pre_define (char *definition)
+void
+pp_pre_define(char *definition)
{
Token *def, *space;
Line *l;
char *equals;
equals = strchr(definition, '=');
-
- def = nasm_malloc(sizeof(Token));
- def->next = space = nasm_malloc(sizeof(Token));
+ space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
+ def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
if (equals)
*equals = ' ';
space->next = tokenise(definition);
if (equals)
*equals = '=';
- def->type = TOK_PREPROC_ID;
- def->text = nasm_strdup("%define");
- space->type = TOK_WHITESPACE;
- space->text = nasm_strdup(" ");
-
- def->mac = space->mac = NULL;
-
l = nasm_malloc(sizeof(Line));
l->next = predef;
l->first = def;
@@ -3810,21 +4215,14 @@ void pp_pre_define (char *definition)
predef = l;
}
-void pp_pre_undefine (char *definition)
+void
+pp_pre_undefine(char *definition)
{
Token *def, *space;
Line *l;
- def = nasm_malloc(sizeof(Token));
- def->next = space = nasm_malloc(sizeof(Token));
- space->next = tokenise(definition);
-
- def->type = TOK_PREPROC_ID;
- def->text = nasm_strdup("%undef");
- space->type = TOK_WHITESPACE;
- space->text = nasm_strdup(" ");
-
- def->mac = space->mac = NULL;
+ space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
+ def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
l = nasm_malloc(sizeof(Line));
l->next = predef;
@@ -3833,12 +4231,14 @@ void pp_pre_undefine (char *definition)
predef = l;
}
-void pp_extra_stdmac (char **macros)
+void
+pp_extra_stdmac(char **macros)
{
extrastdmac = macros;
}
-static void make_tok_num(Token *tok, long val)
+static void
+make_tok_num(Token * tok, long val)
{
char numbuf[20];
sprintf(numbuf, "%ld", val);
diff --git a/rdoff/Makefile.in b/rdoff/Makefile.in
index 46efc0a..5ea14a0 100644
--- a/rdoff/Makefile.in
+++ b/rdoff/Makefile.in
@@ -62,7 +62,9 @@ rdflib.o: rdflib.c
segtab.o: segtab.c
nasmlib.o: $(top_srcdir)/nasmlib.c
- $(CC) -c $(CFLAGS) $(top_srcdir)/nasmlib.c
+## $(CC) -c $(CFLAGS) $(top_srcdir)/nasmlib.c
+ cd $(top_srcdir);make nasmlib.o
+ cp $(top_srcdir)/nasmlib.o $(srcdir)
clean:
rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
diff --git a/rdoff/README b/rdoff/README
index 66988d2..29f9aa0 100644
--- a/rdoff/README
+++ b/rdoff/README
@@ -4,8 +4,16 @@ RDOFF Utils v0.3
The files contained in this directory are the C source code of a set
of tools (and general purpose library files) for the manipulation of
RDOFF version 2 object files. Note that these programs (with the
-exception of 'rdfdump') will NOT work with version 1 object files. Version 1
-of RDOFF is no longer supported. You should be using v2 instead now.
+exception of 'rdfdump') will NOT work with version 1 object files. See
+the subdirectory v1 for programs that perform that task.
+
+Note: If you do not have a v1 subdirectory, you may have unpacked the
+ZIP file without specifying the 'restore directory structure' option -
+delete these files, and run your ZIP extracter again with this option
+turned on ('-d' for PKUNZIP).
+
+RDOFF version 1 is no longer really supported, you should be using
+v2 instead now.
There is also a 'Changes' file, which documents the differences between
RDOFF 1 and 2, and an 'rdoff2.txt' file, with complete documentation for the
diff --git a/rdoff/ldrdf1.c b/rdoff/ldrdf1.c
deleted file mode 100644
index 9e4a215..0000000
--- a/rdoff/ldrdf1.c
+++ /dev/null
@@ -1,728 +0,0 @@
-/* ldrdf.c RDOFF Object File linker/loader main program
- *
- * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
- * Julian Hall. All rights reserved. The software is
- * redistributable under the licence given in the file "Licence"
- * distributed in the NASM archive.
- */
-
-/* TODO: Make the system skip a module (other than the first) if none
- * of the other specified modules contain a reference to it.
- * May require the system to make an extra pass of the modules to be
- * loaded eliminating those that aren't required.
- *
- * Support all the existing documented options...
- *
- * Support libaries (.a files - requires a 'ranlib' type utility)
- * (I think I've got this working, so I've upped the version)
- *
- * -s option to strip resolved symbols from exports. (Could make this an
- * external utility)
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "rdoff.h"
-#include "nasmlib.h"
-#include "symtab.h"
-#include "collectn.h"
-#include "rdlib.h"
-
-#define LDRDF_VERSION "0.30"
-
-/* global variables - those to set options: */
-
-int verbose = 0; /* reflects setting of command line switch */
-int align = 16;
-int errors = 0; /* set by functions to cause halt after current
- stage of processing */
-
-/* the linked list of modules that must be loaded & linked */
-
-struct modulenode {
- rdffile f; /* the file */
- long coderel; /* module's code relocation factor */
- long datarel; /* module's data relocation factor */
- long bssrel; /* module's bss data reloc. factor */
- void * header; /* header location, if loaded */
- char * name; /* filename */
- struct modulenode *next;
-};
-
-#define newstr(str) strcpy(malloc(strlen(str) + 1),str)
-#define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
-
-
-struct modulenode *modules = NULL,*lastmodule = NULL;
-
-/* the linked list of libraries to be searched for missing imported
- symbols */
-
-struct librarynode * libraries = NULL, * lastlib = NULL;
-
-void *symtab; /* The symbol table */
-
-rdf_headerbuf * newheader ; /* New header to be written to output */
-
-/* loadmodule - find the characteristics of a module and add it to the
- * list of those being linked together */
-
-void loadmodule(char *filename)
-{
- struct modulenode *prev;
- if (! modules) {
- modules = malloc(sizeof(struct modulenode));
- lastmodule = modules;
- prev = NULL;
- }
- else {
- lastmodule->next = malloc(sizeof(struct modulenode));
- prev = lastmodule;
- lastmodule = lastmodule->next;
- }
-
- if (! lastmodule) {
- fputs("ldrdf: not enough memory\n",stderr);
- exit(1);
- }
-
- if (rdfopen(&lastmodule->f,filename)) {
- rdfperror("ldrdf",filename);
- exit(1);
- }
-
- lastmodule->header = NULL; /* header hasn't been loaded */
- lastmodule->name = filename;
- lastmodule->next = NULL;
-
- if (prev) {
- lastmodule->coderel = prev->coderel + prev->f.code_len;
- if (lastmodule->coderel % align != 0)
- lastmodule->coderel += align - (lastmodule->coderel % align);
- lastmodule->datarel = prev->datarel + prev->f.data_len;
- if (lastmodule->datarel % align != 0)
- lastmodule->datarel += align - (lastmodule->datarel % align);
- }
- else {
- lastmodule->coderel = 0;
- lastmodule->datarel = 0;
- }
-
- if (verbose)
- printf("%s code = %08lx (+%04lx), data = %08lx (+%04lx)\n",filename,
- lastmodule->coderel,lastmodule->f.code_len,
- lastmodule->datarel,lastmodule->f.data_len);
-
- lastmodule->header = malloc(lastmodule->f.header_len);
- if (!lastmodule->header) {
- fprintf(stderr,"ldrdf: out of memory\n");
- exit(1);
- }
-
- if (rdfloadseg(&lastmodule->f,RDOFF_HEADER,lastmodule->header))
- {
- rdfperror("ldrdf",filename);
- exit(1);
- }
-}
-
-/* load_library add a library to list of libraries to search
- * for undefined symbols
- */
-
-void load_library(char * name)
-{
- if (verbose)
- printf("adding library %s to search path\n",name);
-
- if (! lastlib) {
- lastlib = libraries = malloc(sizeof(struct librarynode));
- }
- else
- {
- lastlib->next = malloc(sizeof(struct librarynode));
- lastlib = lastlib->next;
- }
-
- if (! lastlib) {
- fprintf(stderr, "ldrdf: out of memory\n");
- exit(1);
- }
- strcpy (lastlib->name = malloc (1+strlen(name)), name);
- lastlib->fp = NULL;
- lastlib->referenced = 0;
- lastlib->next = NULL;
-}
-
-
-/* build_symbols() step through each module's header, and locate
- * exported symbols, placing them in a global table
- */
-
-long bsslength;
-
-void mod_addsymbols(struct modulenode * mod)
-{
- rdfheaderrec *r;
- symtabEnt e;
- long cbBss;
-
- mod->bssrel = bsslength;
- cbBss = 0;
- rdfheaderrewind(&mod->f);
- while ((r = rdfgetheaderrec(&mod->f)))
- {
-
- if (r->type == 5) /* Allocate BSS */
- cbBss += r->b.amount;
-
- if (r->type != 3) continue; /* ignore all but export recs */
-
- e.segment = r->e.segment;
- e.offset = r->e.offset +
- (e.segment == 0 ? mod->coderel : /* 0 -> code */
- e.segment == 1 ? mod->datarel : /* 1 -> data */
- mod->bssrel) ; /* 2 -> bss */
-
- e.flags = 0;
- e.name = malloc(strlen(r->e.label) + 1);
- if (! e.name)
- {
- fprintf(stderr,"ldrdf: out of memory\n");
- exit(1);
- }
- strcpy(e.name,r->e.label);
- symtabInsert(symtab,&e);
- }
- bsslength += cbBss;
-}
-
-void build_symbols()
-{
- struct modulenode *mod;
-
- if (verbose) printf("building global symbol table:\n");
- newheader = rdfnewheader();
-
- symtab = symtabNew();
- bsslength = 0; /* keep track of location of BSS symbols */
-
- for (mod = modules; mod; mod = mod->next)
- {
- mod_addsymbols( mod );
- }
- if (verbose)
- {
- symtabDump(symtab,stdout);
- printf("BSS length = %ld bytes\n\n",bsslength);
- }
-}
-
-
-/* scan_libraries() search through headers of modules for undefined
- * symbols, and scan libraries for those symbols,
- * adding library modules found to list of modules
- * to load. */
-
-void scan_libraries(void)
-{
- struct modulenode * mod, * nm;
- struct librarynode * lib;
- rdfheaderrec * r;
- int found;
- char * tmp;
-
- if (verbose) printf("Scanning libraries for unresolved symbols...\n");
-
- mod = modules;
-
- while (mod)
- {
- rdfheaderrewind(&mod->f);
-
- while ((r = rdfgetheaderrec(&mod->f)))
- {
- if (r->type != 2) continue; /* not an import record */
- if ( symtabFind (symtab,r->i.label) )
- continue; /* symbol already defined */
-
- /* okay, we have an undefined symbol... step through
- the libraries now */
- if (verbose >= 2) {
- printf("undefined symbol '%s'...",r->i.label);
- fflush(stdout);
- }
-
- lib = libraries;
- found = 0;
-
- tmp = newstr(r->i.label);
- while (! found && lib)
- {
- /* move this to an outer loop...! */
- nm = malloc(sizeof(struct modulenode));
-
- if (rdl_searchlib(lib,tmp,&nm->f))
- { /* found a module in the library */
-
- /* create a modulenode for it */
-
- if (! nm) {
- fprintf(stderr,"ldrdf: out of memory\n");
- exit(1);
- }
-
- nm->name = newstrcat(lib->name,nm->f.name);
- if (verbose >= 2) printf("found in '%s'\n",nm->name);
-
- nm->coderel = lastmodule->coderel + lastmodule->f.code_len;
- if (nm->coderel % align != 0)
- nm->coderel += align - (nm->coderel % align);
-
- nm->datarel = lastmodule->datarel + lastmodule->f.data_len;
- if (nm->datarel % align != 0)
- nm->datarel += align - (nm->datarel % align);
-
- nm->header = malloc(nm->f.header_len);
- if (! nm->header)
- {
- fprintf(stderr,"ldrdf: out of memory\n");
- exit(1);
- }
-
- if (rdfloadseg(&nm->f,RDOFF_HEADER,nm->header))
- {
- rdfperror("ldrdf",nm->name);
- exit(1);
- }
-
- nm->next = NULL;
- found = 1;
- lastmodule->next = nm;
- lastmodule = nm;
-
- if (verbose)
- printf("%s code = %08lx (+%04lx), data = %08lx "
- "(+%04lx)\n",lastmodule->name,
- lastmodule->coderel,lastmodule->f.code_len,
- lastmodule->datarel,lastmodule->f.data_len);
-
- /* add the module's info to the symbol table */
- mod_addsymbols(nm);
- }
- else
- {
- if (rdl_error) {
- rdl_perror("ldrdf",lib->name);
- exit(1);
- }
- free(nm);
- }
- lib = lib->next;
- }
- free(tmp);
- if (!found && verbose >= 2) printf("not found\n");
- }
- mod = mod->next;
- }
-}
-
-/* load_segments() allocates memory for & loads the code & data segs
- * from the RDF modules
- */
-
-char *text,*data;
-long textlength,datalength;
-
-void load_segments(void)
-{
- struct modulenode *mod;
-
- if (!modules) {
- fprintf(stderr,"ldrdf: nothing to do\n");
- exit(0);
- }
- if (!lastmodule) {
- fprintf(stderr,"ldrdf: panic: module list exists, but lastmodule=NULL\n");
- exit(3);
- }
-
- if (verbose)
- printf("loading modules into memory\n");
-
- /* The following stops 16 bit DOS from crashing whilst attempting to
- work using segments > 64K */
- if (sizeof(int) == 2) { /* expect a 'code has no effect' warning on 32 bit
- platforms... */
- if (lastmodule->coderel + lastmodule->f.code_len > 65535 ||
- lastmodule->datarel + lastmodule->f.data_len > 65535) {
- fprintf(stderr,"ldrdf: segment length has exceeded 64K; use a 32 bit "
- "version.\nldrdf: code size = %05lx, data size = %05lx\n",
- lastmodule->coderel + lastmodule->f.code_len,
- lastmodule->datarel + lastmodule->f.data_len);
- exit(1);
- }
- }
-
- text = malloc(textlength = lastmodule->coderel + lastmodule->f.code_len);
- data = malloc(datalength = lastmodule->datarel + lastmodule->f.data_len);
-
- if (!text || !data) {
- fprintf(stderr,"ldrdf: out of memory\n");
- exit(1);
- }
-
- mod = modules;
- while (mod) { /* load the segments for each module */
- if (verbose >= 2) printf(" loading %s\n",mod->name);
- if (rdfloadseg(&mod->f,RDOFF_CODE,&text[mod->coderel]) ||
- rdfloadseg(&mod->f,RDOFF_DATA,&data[mod->datarel])) {
- rdfperror("ldrdf",mod->name);
- exit(1);
- }
- rdfclose(&mod->f); /* close file; segments remain */
- mod = mod->next;
- }
-}
-
-/* link_segments() step through relocation records in each module's
- * header, fixing up references.
- */
-
-void link_segments(void)
-{
- struct modulenode *mod;
- Collection imports;
- symtabEnt *s;
- long rel,relto;
- char *seg;
- rdfheaderrec *r;
- int bRelative;
-
- if (verbose) printf("linking segments\n");
-
- collection_init(&imports);
-
- for (mod = modules; mod; mod = mod->next) {
- if (verbose >= 2) printf("* processing %s\n",mod->name);
- rdfheaderrewind(&mod->f);
- while((r = rdfgetheaderrec(&mod->f))) {
- if (verbose >= 3) printf("record type: %d\n",r->type);
- switch(r->type) {
- case 1: /* relocation record */
- if (r->r.segment >= 64) { /* Relative relocation; */
- bRelative = 1; /* need to find location relative */
- r->r.segment -= 64; /* to start of this segment */
- relto = r->r.segment == 0 ? mod->coderel : mod->datarel;
- }
- else
- {
- bRelative = 0; /* non-relative - need to relocate
- * at load time */
- relto = 0; /* placate optimiser warnings */
- }
-
- /* calculate absolute offset of reference, not rel to beginning of
- segment */
- r->r.offset += r->r.segment == 0 ? mod->coderel : mod->datarel;
-
- /* calculate the relocation factor to apply to the operand -
- the base address of one of this modules segments if referred
- segment is 0 - 2, or the address of an imported symbol
- otherwise. */
-
- if (r->r.refseg == 0) rel = mod->coderel;
- else if (r->r.refseg == 1) rel = mod->datarel;
- else if (r->r.refseg == 2) rel = mod->bssrel;
- else { /* cross module link - find reference */
- s = *colln(&imports,r->r.refseg - 2);
- if (!s) {
- fprintf(stderr,"ldrdf: link to undefined segment %04x in"
- " %s:%d\n", r->r.refseg,mod->name,r->r.segment);
- errors = 1;
- break;
- }
- rel = s->offset;
-
- r->r.refseg = s->segment; /* change referred segment,
- so that new header is
- correct */
- }
-
- if (bRelative) /* Relative - subtract current segment start */
- rel -= relto;
- else
- { /* Add new relocation header */
- rdfaddheader(newheader,r);
- }
-
- /* Work out which segment we're making changes to ... */
- if (r->r.segment == 0) seg = text;
- else if (r->r.segment == 1) seg = data;
- else {
- fprintf(stderr,"ldrdf: relocation in unknown segment %d in "
- "%s\n", r->r.segment,mod->name);
- errors = 1;
- break;
- }
-
- /* Add the relocation factor to the datum specified: */
-
- if (verbose >= 3)
- printf(" - relocating %d:%08lx by %08lx\n",r->r.segment,
- r->r.offset,rel);
-
- /**** The following code is non-portable. Rewrite it... ****/
- switch(r->r.length) {
- case 1:
- seg[r->r.offset] += (char) rel;
- break;
- case 2:
- *(int16 *)(seg + r->r.offset) += (int16) rel;
- break;
- case 4:
- *(long *)(seg + r->r.offset) += rel;
- break;
- }
- break;
-
- case 2: /* import record */
- s = symtabFind(symtab, r->i.label);
- if (s == NULL) {
- /* Need to add support for dynamic linkage */
- fprintf(stderr,"ldrdf: undefined symbol %s in module %s\n",
- r->i.label,mod->name);
- errors = 1;
- }
- else
- {
- *colln(&imports,r->i.segment - 2) = s;
- if (verbose >= 2)
- printf("imported %s as %04x\n", r->i.label, r->i.segment);
- }
- break;
-
- case 3: /* export; dump to output new version */
- s = symtabFind(symtab, r->e.label);
- if (! s) {
- fprintf(stderr,"ldrdf: internal error - undefined symbol %s "
- "exported in header of '%s'\n",r->e.label,mod->name);
- continue;
- }
- r->e.offset = s->offset;
- rdfaddheader(newheader,r);
- break;
-
- case 4: /* DLL record */
- rdfaddheader(newheader,r); /* copy straight to output */
- break;
- }
- }
- if (rdf_errno != 0) {
- rdfperror("ldrdf",mod->name);
- exit(1);
- }
- collection_reset(&imports);
- }
-}
-
-/* write_output() write linked program out to a file */
-
-void write_output(char *filename)
-{
- FILE * fp;
- rdfheaderrec r;
-
- if (verbose) printf("writing output to '%s'\n",filename);
-
- fp = fopen(filename,"wb");
- if (! fp)
- {
- fprintf(stderr,"ldrdf: could not open '%s' for writing\n",filename);
- exit(1);
- }
-
-
- /* add BSS length count to header... */
- if (bsslength)
- {
- r.type = 5;
- r.b.amount = bsslength;
- rdfaddheader(newheader,&r);
- }
-
- /* Write header */
- rdfwriteheader(fp,newheader);
- rdfdoneheader(newheader);
- newheader = NULL;
-
- /* Write text */
- if (fwrite(&textlength,1,4,fp) != 4
- || fwrite(text,1,textlength,fp) !=textlength)
- {
- fprintf(stderr,"ldrdf: error writing %s\n",filename);
- exit(1);
- }
-
- /* Write data */
- if (fwrite(&datalength,1,4,fp) != 4 ||
- fwrite(data,1,datalength,fp) != datalength)
- {
- fprintf (stderr,"ldrdf: error writing %s\n", filename);
- exit(1);
- }
- fclose(fp);
-}
-
-
-/* main program: interpret command line, and pass parameters on to
- * individual module loaders & the linker
- *
- * Command line format:
- * ldrdf [-o outfile | -x] [-r xxxx] [-v] [--] infile [infile ...]
- *
- * Default action is to output a file named 'aout.rdx'. -x specifies
- * that the linked object program should be executed, rather than
- * written to a file. -r specifies that the object program should
- * be prelocated at address 'xxxx'. This option cannot be used
- * in conjunction with -x.
- */
-
-const char *usagemsg = "usage:\n"
-" ldrdf [-o outfile | -x] [-a x] [-v] [-p x] [--] infile [infile ...]\n"
-" [-l<libname> ...]\n\n"
-" ldrdf -h displays this message\n"
-" ldrdf -r displays version information\n\n"
-" -o selects output filename (default is aout.rdx)\n"
-" -x causes ldrdx to link & execute rather than write to file\n"
-" -a x causes object program to be statically relocated to address 'x'\n"
-" -v turns on verbose mode\n"
-" -p x causes segments to be aligned (padded) to x byte boundaries\n"
-" (default is 16 bytes)\n"
-" -l<name> causes 'name' to be linked in as a library. Note no search is\n"
-" performed - the entire pathname MUST be specified.\n";
-
-void usage(void)
-{
- fputs(usagemsg,stderr);
-}
-
-int main(int argc,char **argv)
-{
- char *ofilename = "aout.rdx";
- long relocateaddr = -1; /* -1 if no relocation is to occur */
- int execute = 0; /* 1 to execute after linking, 0 otherwise */
- int procsw = 1; /* set to 0 by '--' */
- int tmp;
-
- if (argc == 1) {
- usage();
- exit(1);
- }
-
- /* process command line switches, and add modules specified to linked list
- of modules, keeping track of total memory required to load them */
-
- while(argv++,--argc) {
- if (procsw && !strcmp(*argv,"-h")) { /* Help command */
- usage(); exit(1);
- }
- else if (procsw && !strcmp(*argv,"-r")) {
- printf("ldrdf version %s (%s) (%s)\n",LDRDF_VERSION,_RDOFF_H,
- sizeof(int) == 2 ? "16 bit" : "32 bit");
- exit(1);
- }
- else if (procsw && !strcmp(*argv,"-o")) {
- ofilename = *++argv;
- --argc;
- if (execute) {
- fprintf(stderr,"ldrdf: -o and -x switches incompatible\n");
- exit(1);
- }
- if (verbose > 1) printf("output filename set to '%s'\n",ofilename);
- }
- else if (procsw && !strcmp(*argv,"-x")) {
- execute++;
- if (verbose > 1) printf("will execute linked object\n");
- }
- else if (procsw && !strcmp(*argv,"-a")) {
- relocateaddr = readnum(*++argv,&tmp);
- --argc;
- if (tmp) {
- fprintf(stderr,"ldrdf: error in parameter to '-a' switch: '%s'\n",
- *argv);
- exit(1);
- }
- if (execute) {
- fprintf(stderr,"ldrdf: -a and -x switches incompatible\n");
- exit(1);
- }
- if (verbose) printf("will relocate to %08lx\n",relocateaddr);
- }
- else if (procsw && !strcmp(*argv,"-v")) {
- verbose++;
- if (verbose == 1) printf("verbose mode selected\n");
- }
- else if (procsw && !strcmp(*argv,"-p")) {
- align = readnum(*++argv,&tmp);
- --argc;
- if (tmp) {
- fprintf(stderr,"ldrdf: error in parameter to '-p' switch: '%s'\n",
- *argv);
- exit(1);
- }
- if (align != 1 && align != 2 && align != 4 && align != 8 && align != 16
- && align != 32 && align != 256) {
- fprintf(stderr,"ldrdf: %d is an invalid alignment factor - must be"
- "1,2,4,8,16 or 256\n",align);
- exit(1);
- }
- if (verbose > 1) printf("alignment %d selected\n",align);
- }
- else if (procsw && !strncmp(*argv,"-l",2)) {
- load_library(*argv + 2);
- }
- else if (procsw && !strcmp(*argv,"--")) {
- procsw = 0;
- }
- else { /* is a filename */
- if (verbose > 1) printf("processing module %s\n",*argv);
- loadmodule(*argv);
- }
- }
-
- /* we should be scanning for unresolved references, and removing
- unreferenced modules from the list of modules here, so that
- we know about the final size once libraries have been linked in */
-
- build_symbols(); /* build a global symbol table... */
-
- scan_libraries(); /* check for imported symbols not in table,
- and ensure the relevant library modules
- are loaded */
-
- load_segments(); /* having calculated size of reqd segments, load
- each rdoff module's segments into memory */
-
- link_segments(); /* step through each module's header, and resolve
- references to the global symbol table.
- This also does local address fixups. */
-
- if (errors) {
- fprintf(stderr,"ldrdf: there were errors - aborted\n");
- exit(errors);
- }
- if (execute) {
- fprintf(stderr,"ldrdf: module execution not yet supported\n");
- exit(1);
- }
- if (relocateaddr != -1) {
- fprintf(stderr,"ldrdf: static relocation not yet supported\n");
- exit(1);
- }
-
- write_output(ofilename);
- return 0;
-}
diff --git a/standard.mac b/standard.mac
index 58e65df..333cedd 100644
--- a/standard.mac
+++ b/standard.mac
@@ -1,4 +1,15 @@
; Standard macro set for NASM 0.98 -*- nasm -*-
+
+; Macros to make NASM ignore some TASM directives before the first include
+; directive.
+
+ %idefine IDEAL
+ %idefine JUMPS
+ %idefine P386
+ %idefine P486
+ %idefine P586
+ %idefine END
+
; Note that although some user-level forms of directives are defined
; here, not all of them are: the user-level form of a format-specific
; directive should be defined in the module for that directive.
@@ -32,7 +43,7 @@
%define %$strucname %1
[absolute 0]
%$strucname: ; allow definition of `.member' to work sanely
-%endmacro
+%endmacro
%imacro endstruc 0.nolist
%{$strucname}_size:
%pop
@@ -97,12 +108,3 @@ __SECT__
%endmacro
-; Macros to make NASM ignore some TASM directives before the first include
-; directive.
-
-%idefine IDEAL
-%idefine JUMPS
-%idefine P386
-%idefine P486
-%idefine P586
-%idefine END
diff --git a/zoutieee.c b/zoutieee.c
index 0bcdb5c..9784e79 100644
--- a/zoutieee.c
+++ b/zoutieee.c
@@ -158,7 +158,7 @@ extern struct ofmt of_ieee;
static void ieee_data_new(struct ieeeSection *);
static void ieee_write_fixup (long, long, struct ieeeSection *,
- int, long, long);
+ int, unsigned long, long);
static void ieee_install_fixup(struct ieeeSection *, struct ieeeFixupp *);
static long ieee_segment (char *, int, int *);
static void ieee_write_file(int debuginfo);
@@ -369,7 +369,7 @@ static void ieee_deflabel (char *name, long segment,
*/
static void ieee_out (long segto, void *data, unsigned long type,
long segment, long wrt) {
- long size, realtype;
+ unsigned long size, realtype;
unsigned char *ucdata;
long ldata;
struct ieeeSection *seg;
@@ -447,7 +447,7 @@ static void ieee_data_new(struct ieeeSection *segto) {
* If anyone wants to optimize this is a good canditate!
*/
static void ieee_write_fixup (long segment, long wrt, struct ieeeSection * segto,
- int size, long realtype, long offset) {
+ int size, unsigned long realtype, long offset) {
struct ieeeSection *target;
struct ieeeFixupp s;
@@ -1312,7 +1312,7 @@ static void dbgls_linnum (const char *lnfname, long lineno, long segto)
}
ieee_write_byte(seghead, fn->index);
ieee_write_word(seghead, lineno);
- ieee_write_fixup (segto, NO_SEG, seghead, 4,OUT_ADDRESS,seg->currentpos);
+ ieee_write_fixup (segto, NO_SEG, seghead, 4, OUT_ADDRESS, seg->currentpos);
}
static void dbgls_deflabel (char *name, long segment,