diff options
author | H. Peter Anvin <hpa@zytor.com> | 2002-04-30 21:01:08 +0000 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2002-04-30 21:01:08 +0000 |
commit | 734b188090539eddf08e61c317415f566446691b (patch) | |
tree | abc7516f5a80c8b0810f5018125eb5f95717ca76 | |
parent | 1cd0e2d5bf50b2cc482cad7beb8f7dee6a81d57b (diff) | |
download | nasm-734b188090539eddf08e61c317415f566446691b.tar.gz nasm-734b188090539eddf08e61c317415f566446691b.tar.bz2 nasm-734b188090539eddf08e61c317415f566446691b.zip |
NASM 0.98.09
-rw-r--r-- | AUTHORS | 2 | ||||
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | Mkfiles/Makefile.b32 | 49 | ||||
-rw-r--r-- | Mkfiles/Makefile.dl | 46 | ||||
-rw-r--r-- | assemble.c | 4 | ||||
-rw-r--r-- | doc/makedocs.bat | 254 | ||||
-rw-r--r-- | doc/nasmdoc.src | 149 | ||||
-rw-r--r-- | insns.dat | 794 | ||||
-rw-r--r-- | labels.c | 5 | ||||
-rw-r--r-- | listing.c | 2 | ||||
-rw-r--r-- | macros.pl | 38 | ||||
-rw-r--r-- | misc/scitech.mac | 1223 | ||||
-rw-r--r-- | nasm.c | 160 | ||||
-rw-r--r-- | nasm.h | 6 | ||||
-rw-r--r-- | nasmlib.c | 4 | ||||
-rw-r--r-- | outaout.c | 4 | ||||
-rw-r--r-- | outas86.c | 2 | ||||
-rw-r--r-- | outbin.c | 683 | ||||
-rw-r--r-- | outcoff.c | 8 | ||||
-rw-r--r-- | outelf.c | 2 | ||||
-rw-r--r-- | outform.h | 2 | ||||
-rw-r--r-- | outobj.c | 2 | ||||
-rw-r--r-- | parser.c | 16 | ||||
-rw-r--r-- | preproc.c | 4438 | ||||
-rw-r--r-- | rdoff/Makefile.in | 4 | ||||
-rw-r--r-- | rdoff/README | 12 | ||||
-rw-r--r-- | rdoff/ldrdf1.c | 728 | ||||
-rw-r--r-- | standard.mac | 22 | ||||
-rw-r--r-- | zoutieee.c | 8 |
29 files changed, 5133 insertions, 3536 deletions
@@ -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 + @@ -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}). @@ -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 @@ -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)) @@ -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; @@ -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®&, val32 +else + add reg, val16 +endif +ENDM + +MACRO _sub reg, val16, val32 +ifdef flatmodel + sub e®&, 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 +endif +ENDM + +MACRO sgnhi reg +ifdef flatmodel + movsx e®&,reg +endif +ENDM + +; Macro to load an extended register with an integer value in either mode + +MACRO loadint reg,val +ifdef flatmodel + mov e®&,val +else + xor e®&,e®& + 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 @@ -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) { @@ -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 @@ -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])) { @@ -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); @@ -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; /* @@ -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 = §ions; } -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, @@ -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, @@ -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) @@ -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 @@ -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; @@ -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; } @@ -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, ¶ms); + count_mmac_params(tline->next, &nparam, ¶ms); /* * 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, ¶ms); - if (!m) { + m = is_mmacro(t, ¶ms); + 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 @@ -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, |