summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS90
-rw-r--r--MODIFIED43
-rw-r--r--Mkfiles/Makefile.dj2
-rw-r--r--Mkfiles/Makefile.emx145
-rw-r--r--Mkfiles/Makefile.vc2
-rw-r--r--README.1st187
-rw-r--r--Readme76
-rw-r--r--assemble.c2
-rw-r--r--doc/Makefile.in15
-rw-r--r--doc/nasmdoc.src1032
-rw-r--r--doc/rdsrc.pl37
-rw-r--r--insns.dat287
-rw-r--r--insns.h2
-rw-r--r--labels.c110
-rw-r--r--labels.h3
-rw-r--r--listing.c6
-rw-r--r--listing.h1
-rw-r--r--macros.c9
-rw-r--r--nasm.c285
-rw-r--r--nasm.h32
-rw-r--r--outaout.c2
-rw-r--r--outelf.c6
-rw-r--r--outobj.c44
-rw-r--r--outrdf2.c58
-rw-r--r--parser.c80
-rw-r--r--preproc.c529
-rw-r--r--proc32.ash441
-rw-r--r--rdoff/Makefile.dj75
-rw-r--r--rdoff/Makefile.emx76
-rw-r--r--rdoff/Makefile.in12
-rw-r--r--rdoff/Makefile.sc113
-rw-r--r--rdoff/README12
-rw-r--r--rdoff/ldrdf.c304
-rw-r--r--rdoff/multboot.h27
-rw-r--r--rdoff/rdf2bin.c17
-rw-r--r--rdoff/rdf2ihx.c189
-rw-r--r--rdoff/rdfdump.c29
-rw-r--r--rdoff/rdfload.c7
-rw-r--r--rdoff/rdoff.c26
-rw-r--r--rdoff/rdoff.h33
-rw-r--r--rdoff/symtab.c4
-rw-r--r--scitech.txt213
-rw-r--r--standard.mac10
-rw-r--r--test/bintest.asm4
-rw-r--r--test/test1.asm62
-rw-r--r--test/test2.asm18
-rw-r--r--test/test2a.asm22
-rw-r--r--test/test3.asm45
-rw-r--r--test/test4.asm16
-rw-r--r--test/test4a.asm16
-rw-r--r--test/test4b.asm17
-rw-r--r--test/test4c.asm17
-rw-r--r--test/test5.asm43
-rw-r--r--test/test6.asm9
54 files changed, 4336 insertions, 606 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 00000000..2fa097dc
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,90 @@
+This is the AUTHORS file for the NASM project located at:
+http://nasm.rm-f.net/
+
+Names should be inserted as follows:
+
+N: Name Here
+E: Email Here
+D: Description Here
+D: Additional Description Here.... and so on
+
+Such is life.
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+N: Julian Hall
+E: Jules@acris.co.uk
+D: Original author and co-conspirator
+
+N: Simon Tatham
+E: anakin@pobox.com
+D: Original author and co-conspirator
+
+N: Nelson Rush
+E: palisade@users.sourceforge.net
+D: Some guy.
+
+N: Frank Kotler
+E: fbkotler@nettaxi.com
+D: Bug smashing.
+D: Documentation - "KATMAI" and "3DNow!" instructions supported by 0.98
+
+N: Stephen Silver
+E: nasm@argentum.freeserve.co.uk
+D: Documentation - "3dNow!" instructions and misc.
+D: insns.dat fixes and new instructions.
+
+N: AMD Inc. (names of developers here?)
+E:
+D: 3DNow instructions
+D: New Athlon instructions
+D: Makefile.vc fix
+
+N: John Coffman
+E: johninsd@users.sourceforge.net
+D: added Jcc optimizations; CPU level checks
+D: bug fixes, compilation fixes
+
+N: Yuri Zaporogets
+E: yuriz@users.sourceforge.net
+D: RDOFF support
+
+N: H. Peter Anvin
+E: hpa@zytor.com
+D: Organized 0.98 release and Linux binaries
+
+N: John Fine
+E: johnfine@earthlink.net
+D: Preprocessor and OBJ (OMF) output format driver
+D: Organized DOS versions of 0.98 release
+
+N: Kendall Bennet
+E: KendallB@scitechsoft.com
+D: NASM enhancements
+D: macros
+D: Syntax modifications
+
+N: Gary Clark
+E:
+D: AMD 3DNow! instructions
+
+N: Andrew Crabtree
+E:
+D: Debugging support
+
+N: Rafael R. Sevilla
+E: dido@pacific.net.ph
+D: RDF2HEX utility
+
+N: Jaime Tejedor Gómez, aka Metalbrain
+E: metalbrain_coder@gmx.net
+D: jecxz bug fix
+
+N: James Seter
+E: pharos@zsnes.com
+D: --POSTFIX, --PREFIX switches
+D: ?
+
+N: Edward J. Beroset
+E: beroset@mindspring.com
+D: added %substr and %strlen
+
diff --git a/MODIFIED b/MODIFIED
index 58987e85..eead729e 100644
--- a/MODIFIED
+++ b/MODIFIED
@@ -1,3 +1,46 @@
+01/28/01 - fbk - added Stepane Denis' SSE2 instructions to a *working*
+ version of the code - some earlier versions were based on
+ broken code - sorry 'bout that. version "0.98.07"
+
+01/28/01 - fbk - cosmetic modifications to nasm.c, nasm.h,
+ AUTHORS, MODIFIED
+
+01/18/01 - fbk - "metalbrain"s jecxz bug fix in insns.dat
+ - alter nasmdoc.src to match - version "0.98.06f"
+
+01/09/01 - fbk - removed the "outforms.h" file - it appears to be
+ someone's old backup of "outform.h". version "0.98.06e"
+
+01/09/01 - fbk - finally added the fix for the "multiple %includes bug",
+ known since 7/27/99 - reported originally (?) and sent to
+ us by Austin Lunnen - he reports that John Fine had a fix
+ within the day. Here it is...
+
+---- Nelson Rush resigns from the group. Big thanks to Nelson for
+ his leadership and enthusiasm in getting these changes
+ incorporated into Nasm!
+
+---- fbk - [list +], [list -] directives - ineptly implemented, should
+ be re-written or removed, perhaps.
+
+---- Brian Raiter / fbk - "elfso bug" fix - applied to aoutb format
+ as well - testing might be desirable...
+
+08/07/00 - James Seter - -postfix, -prefix command line switches.
+
+---- Yuri Zaporogets - rdoff utility changes.
+
+John Coffman's changes:
+For the JMP and other optimizations see the file README03.txt.
+
+Kendall Bennett's changes:
+For changes since the 0.98 release see the file scitech.txt. Note
+ that you must define "TASM_COMPAT" at compile-time
+ to get the Tasm Ideal Mode compatibility.
+
+----------------------------------------------
+... this is the 0.98 "modified" file ...
+--------------------------------------------------
This file details changes since NASM 0.98p3. All the releases in this
file have been produced by H. Peter Anvin <hpa@zytor.com>.
diff --git a/Mkfiles/Makefile.dj b/Mkfiles/Makefile.dj
index fb337481..7cb2399d 100644
--- a/Mkfiles/Makefile.dj
+++ b/Mkfiles/Makefile.dj
@@ -13,7 +13,7 @@
# You may need to adjust these values.
-CC = gcc -s
+CC = gcc
CFLAGS = -O2 -I.
# You _shouldn't_ need to adjust anything below this line.
diff --git a/Mkfiles/Makefile.emx b/Mkfiles/Makefile.emx
new file mode 100644
index 00000000..bb7ef0f9
--- /dev/null
+++ b/Mkfiles/Makefile.emx
@@ -0,0 +1,145 @@
+# Generated automatically from Makefile.in by configure.
+# $Id$
+#
+# Auto-configuring Makefile for the Netwide Assembler.
+#
+# 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.
+
+srcdir = .
+prefix = /usr/local
+exec_prefix = ${prefix}
+bindir = ${exec_prefix}/bin
+mandir = ${prefix}/man
+
+CC = gcc
+CFLAGS = -s -Zomf -O2 -fomit-frame-pointer -Wall -pedantic \
+ -I$(srcdir) -I. -DTASM_COMPAT
+LDFLAGS = -s -Zomf -Zexe -Zcrtdll
+LIBS = -lgcc
+
+INSTALL = ./install-sh -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+
+NROFF = echo
+
+.SUFFIXES: .c .i .s .o .1 .man
+
+.PHONY: all doc rdf install clean distclean cleaner spotless install_rdf
+.PHONY: install_doc everything install_everything
+
+.c.o:
+ $(CC) -c $(CFLAGS) -o $@ $<
+
+.c.s:
+ $(CC) -S $(CFLAGS) -o $@ $<
+
+.c.i:
+ $(CC) -E $(CFLAGS) -o $@ $<
+
+.1.man:
+ $(NROFF) -man $< > $@
+
+NASM = nasm.o nasmlib.o float.o insnsa.o assemble.o labels.o \
+ parser.o outform.o outbin.o outaout.o outcoff.o outelf.o \
+ outobj.o outas86.o outrdf.o outrdf2.o outdbg.o zoutieee.o \
+ preproc.o listing.o eval.o
+
+NDISASM = ndisasm.o disasm.o sync.o nasmlib.o insnsd.o
+
+all: nasm ndisasm nasm.man ndisasm.man
+ $(MAKE) -C rdoff -f Makefile.emx all
+
+nasm: $(NASM)
+ $(CC) $(LDFLAGS) -o nasm $(NASM) $(LIBS)
+
+ndisasm: $(NDISASM)
+ $(CC) $(LDFLAGS) -o ndisasm $(NDISASM) $(LIBS)
+
+assemble.o: assemble.c nasm.h insnsi.h nasmlib.h assemble.h insns.h
+disasm.o: disasm.c nasm.h insnsi.h disasm.h sync.h insns.h names.c insnsn.c
+eval.o: eval.c eval.h nasm.h insnsi.h nasmlib.h
+float.o: float.c nasm.h insnsi.h
+insnsa.o: insnsa.c nasm.h insnsi.h insns.h
+insnsd.o: insnsd.c nasm.h insnsi.h insns.h
+labels.o: labels.c nasm.h insnsi.h nasmlib.h
+listing.o: listing.c nasm.h insnsi.h nasmlib.h listing.h
+nasm.o: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labels.h \
+ outform.h listing.h
+nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
+ndisasm.o: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
+outaout.o: outaout.c nasm.h insnsi.h nasmlib.h outform.h
+outas86.o: outas86.c nasm.h insnsi.h nasmlib.h outform.h
+outbin.o: outbin.c nasm.h insnsi.h nasmlib.h outform.h
+outcoff.o: outcoff.c nasm.h insnsi.h nasmlib.h outform.h
+outdbg.o: outdbg.c nasm.h insnsi.h nasmlib.h outform.h
+outelf.o: outelf.c nasm.h insnsi.h nasmlib.h outform.h
+outform.o: outform.c outform.h nasm.h insnsi.h
+outobj.o: outobj.c nasm.h insnsi.h nasmlib.h outform.h
+outrdf.o: outrdf.c nasm.h insnsi.h nasmlib.h outform.h
+outrdf2.o: outrdf2.c nasm.h insnsi.h nasmlib.h outform.h
+parser.o: parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
+preproc.o: preproc.c nasm.h insnsi.h nasmlib.h macros.c
+sync.o: sync.c sync.h
+zoutieee.o: zoutieee.c nasm.h insnsi.h nasmlib.h outform.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: insns.dat insns.pl
+ perl $(srcdir)/insns.pl -a $(srcdir)/insns.dat
+insnsd.c: insns.dat insns.pl
+ perl $(srcdir)/insns.pl -d $(srcdir)/insns.dat
+insnsi.h: insns.dat insns.pl
+ perl $(srcdir)/insns.pl -i $(srcdir)/insns.dat
+insnsn.c: insns.dat insns.pl
+ perl $(srcdir)/insns.pl -n $(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
+
+install: nasm ndisasm
+ $(INSTALL_PROGRAM) nasm $(INSTALLROOT)$(bindir)/nasm
+ $(INSTALL_PROGRAM) ndisasm $(INSTALLROOT)$(bindir)/ndisasm
+ $(INSTALL_DATA) $(srcdir)/nasm.1 $(INSTALLROOT)$(mandir)/man1/nasm.1
+ $(INSTALL_DATA) $(srcdir)/ndisasm.1 $(INSTALLROOT)$(mandir)/man1/ndisasm.1
+
+clean:
+ rm -f *.o *.s *.i nasm ndisasm
+ cd rdoff && $(MAKE) clean
+
+distclean: clean
+ rm -f config.* Makefile *~ *.bak *.lst *.bin
+ cd rdoff && $(MAKE) distclean
+
+cleaner: clean
+ rm -f insnsa.c insnsd.c insnsi.h insnsn.c macros.c *.man
+ cd doc && $(MAKE) clean
+
+spotless: distclean cleaner
+
+rdf:
+ cd rdoff && $(MAKE)
+
+rdf_install install_rdf:
+ cd rdoff && $(MAKE) install
+
+doc:
+ cd doc && $(MAKE) all
+
+doc_install install_doc:
+ cd doc && $(MAKE) install
+
+everything: all doc rdf
+
+install_everything: everything install install_doc install_rdf
+
diff --git a/Mkfiles/Makefile.vc b/Mkfiles/Makefile.vc
index 1e0ef1c4..0bc4f68d 100644
--- a/Mkfiles/Makefile.vc
+++ b/Mkfiles/Makefile.vc
@@ -34,7 +34,7 @@ all : nasm$(SUFFIX)$(EXE) ndisasm$(SUFFIX)$(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
+LINKOBJS = a*.obj e*.obj f*.obj insnsa.obj l*.obj na*.obj o*.obj p*.obj z*.obj
nasm$(SUFFIX)$(EXE): $(NASMOBJS)
cl /Fenasm$(SUFFIX).exe $(LINKOBJS)
diff --git a/README.1st b/README.1st
new file mode 100644
index 00000000..b1bf2dad
--- /dev/null
+++ b/README.1st
@@ -0,0 +1,187 @@
+This is a specially patched version of NASM. It can be used to supplement
+building of Crystal Space, the Open Source 3D Engine project. You can find
+Crystal Space at the following locations:
+
+http://crystal.linuxgames.com/
+http://crystal.sourceforge.net/
+
+Details of changes in this version of NASM follow.
+
+-*- A new keyword %xdefine and its case-insensitive counterpart %ixdefine.
+ They work almost the same way as %define and %idefine but expand
+ the definition immediately, not on the invocation. Something like a cross
+ between %define and %assign. The "x" suffix stands for "eXpand", so
+ "xdefine" can be deciphered as "expand-and-define". Thus you can do
+ things like this:
+
+ %assign ofs 0
+
+ %macro arg 1
+ %xdefine %1 dword [esp+ofs]
+ %assign ofs ofs+4
+ %endmacro
+
+-*- Changed the place where the expansion of %$name macros are expanded.
+ Now they are converted into ..@ctxnum.name form when detokenizing, so
+ there are no quirks as before when using %$name arguments to macros,
+ in macros etc. For example:
+
+ %macro abc 1
+ %define %1 hello
+ %endm
+
+ abc %$here
+ %$here
+
+ Now last line will be expanded to "hello" as expected. This also allows
+ for lots of goodies, a good example are extended "proc" macros included
+ in this archive.
+
+-*- Added a check for "cstk" in smacro_defined() before calling get_ctx() -
+ this allows for things like:
+
+ %ifdef %$abc
+ %endif
+
+ to work without warnings even in no context.
+
+-*- Added a check for "cstk" in %if*ctx and %elif*ctx directives -
+ this allows to use %ifctx without excessive warnings. If there is
+ no active context, %ifctx goes through "false" branch.
+
+-*- Removed "user error: " prefix with %error directive: it just clobbers the
+ output and has absolutely no functionality. Besides, this allows to write
+ macros that does not differ from build-in functions in any way.
+
+-*- Added expansion of string that is output by %error directive. Now you
+ can do things like:
+
+ %define hello(x) Hello, x!
+
+ %define %$name andy
+ %error "hello(%$name)"
+
+ Same happened with %include directive.
+
+-*- Now all directives that expect an identifier will try to expand and
+ concatenate everything without whitespaces in between before usage.
+ For example, with "unfixed" nasm the commands
+
+ %define %$abc hello
+ %define __%$abc goodbye
+ __%$abc
+
+ would produce "incorrect" output: last line will expand to
+
+ hello goodbyehello
+
+ Not quite what you expected, eh? :-) The answer is that preprocessor
+ treats the %define construct as if it would be
+
+ %define __ %$abc goodbye
+
+ (note the white space between __ and %$abc). After my "fix" it
+ will "correctly" expand into
+
+ goodbye
+
+ as expected. Note that I use quotes around words "correct", "incorrect"
+ etc because this is rather a feature not a bug; however current behaviour
+ is more logical (and allows more advanced macro usage :-).
+
+ Same change was applied to:
+ %push,%macro,%imacro,%define,%idefine,%xdefine,%ixdefine,
+ %assign,%iassign,%undef
+
+-*- A new directive [WARNING {+|-}warning-id] have been added. It works only
+ if the assembly phase is enabled (i.e. it doesn't work with nasm -e).
+
+-*- A new warning type: macro-selfref. By default this warning is disabled;
+ when enabled NASM warns when a macro self-references itself; for example
+ the following source:
+
+ [WARNING macro-selfref]
+
+ %macro push 1-*
+ %rep %0
+ push %1
+ %rotate 1
+ %endrep
+ %endmacro
+
+ push eax,ebx,ecx
+
+ will produce a warning, but if we remove the first line we won't see it
+ anymore (which is The Right Thing To Do {tm} IMHO since C preprocessor
+ eats such constructs without warnings at all).
+
+-*- Added a "error" routine to preprocessor which always will set ERR_PASS1
+ bit in severity_code. This removes annoying repeated errors on first
+ and second passes from preprocessor.
+
+-*- Added the %+ operator in single-line macros for concatenating two
+ identifiers. Usage example:
+
+ %define _myfunc _otherfunc
+ %define cextern(x) _ %+ x
+ cextern (myfunc)
+
+ After first expansion, third line will become "_myfunc". After this
+ expansion is performed again so it becomes "_otherunc".
+
+-*- Now if preprocessor is in a non-emmitting state, no warning or error
+ will be emmitted. Example:
+
+ %if 1
+ mov eax,ebx
+ %else
+ put anything you want between these two brackets,
+ even macro-parameter references %1 or local labels %$zz
+ or macro-local labels %%zz - no warning will be emmitted.
+ %endif
+
+-*- Context-local variables on expansion as a last resort are looked up
+ in outer contexts. For example, the following piece:
+
+ %push outer
+ %define %$a [esp]
+
+ %push inner
+ %$a
+ %pop
+ %pop
+
+ will expand correctly the fourth line to [esp]; if we'll define another
+ %$a inside the "inner" context, it will take precedence over outer
+ definition. However, this modification has been applied only to
+ expand_smacro and not to smacro_define: as a consequence expansion
+ looks in outer contexts, but %ifdef won't look in outer contexts.
+
+ This behaviour is needed because we don't want nested contexts to
+ act on already defined local macros. Example:
+
+ %define %$arg1 [esp+4]
+ test eax,eax
+ if nz
+ mov eax,%$arg1
+ endif
+
+ In this example the "if" mmacro enters into the "if" context, so %$arg1
+ is not valid anymore inside "if". Of course it could be worked around
+ by using explicitely %$$arg1 but this is ugly IMHO.
+
+-------------------------------// fixes for 0.98 //-----------------------------
+
+-*- Fixed memory leak in %undef. The origline wasn't freed before
+ exiting on success.
+
+-----------------------------// Fixes for 0.98.01 //----------------------------
+
+-*- Fixed trap in preprocessor when line expanded to empty set of tokens.
+ This happens, for example, in the following case:
+
+ #define SOMETHING
+ SOMETHING
+
+
+Andrew Zabolotny <bit@eltech.ru>
diff --git a/Readme b/Readme
index 6e7c56c7..dbbd18da 100644
--- a/Readme
+++ b/Readme
@@ -1,53 +1,49 @@
-This directory contains the necessary files to port the C compiler
-``LCC'' (available by FTP from sunsite.doc.ic.ac.uk in the directory
-/computing/programming/languages/c/lcc) to compile for Linux (a.out or
-ELF) or other supported operating systems by using NASM as a back-end
-code generator.
-This patch has been tested on lcc version 4.0.
+ NetWide Assembler for the SciTech MGL
+ -------------------------------------
-To install:
+This is a modified distribution of NASM, the Netwide Assembler. NASM
+is a prototype general-purpose x86 assembler. It will currently output
+flat-form binary files, a.out, COFF and ELF Unix object files,
+Microsoft Win32 and 16-bit DOS object files, OS/2 object files, the
+as86 object format, and a home-grown format called RDF.
-- Copy `x86nasm.md' into the `src' directory of the lcc tree.
+This version of NASM has been modified by SciTech Software such that it
+can be used to assemble source code in the SciTech MGL graphics library,
+and understands enough of TASM assembler syntax such that both NASM
+and TASM can be used to generate assembler modules for the MGL graphics
+library. A complete macro package is provided as part of the SciTech
+MGL that provides macros to help in building modules that will work with
+either assembler.
-- Copy either `lin-elf.c' or `lin-aout.c' into the `etc' directory.
+A pre-compiled binary of NASM is provided as part of the SciTech MGL
+graphics library, however you may re-build the assembler from the sources
+provided. To do so make sure you have the SciTech Makefile Utilties
+correctly configured for your compiler, and then simly type:
-- With previous versions, you had to modify x86-nasm.md if you weren't
- using ELF. There is now inbuilt support within NASM in the shape
- of the __CDECL__ macro, so this modification is no longer necessary.
+ unset DBG
+ dmake OPT=1
-- Make the following changes to `bind.c' in the `src' directory:
+to build an optimised, non-debug version of the assembler. If you wish
+to rebuild for a different OS other than DOS or Win32, you will need to
+first compile the DMAKE make program for your OS. See the DMAKE source
+code for more information.
- - Near the top of the file, add a line that reads
- extern Interface x86nasmIR;
+Licensing issues:
+-----------------
- - In the `bindings' array, add the lines
- "x86-nasm", &x86nasmIR,
- "x86/nasm", &x86nasmIR,
- (in sensible looking places...)
+For information about how you can distribute and use NASM, see the
+file Licence.
- A sample `bind.c' has been provided to show what the result of
- this might look like. You might be able to get away with using it
- directly...
+The NASM web page is at http://www.cryogen.com/Nasm/
-- Modify the lcc makefile to include rules for x86nasm.o: this will
- have to be done in about three places. Just copy any line with
- `x86' on it and modify it to read `x86nasm' everywhere. (Except
- that in the list of object files that rcc is made up from, do
- remember to ensure that every line but the last has a trailing
- backslash...)
+Bug reports specific to the SciTech MGL should be posted to SciTech
+Software MGL newsgroups:
-- You may have to modify the contents of `lin-elf.c' or `lin-aout.c'
- to reflect the true locations of files such as crt0.o, crt1.o,
- ld-linux.so and so forth. If you don't know where to find these,
- compile a short C program with `gcc -v' and see what command line
- gcc feeds to `ld'.
+ news://news.scitechsoft.com/scitech.mgl.developer
-- You should now be able to build lcc, using `lin-elf.c' or
- `lin-aout.c' as the system-dependent part of the `lcc' wrapper
- program.
+Bug reports (and patches if you can) for NASM itself that are not SciTech
+MGL related should be sent to the authors at:
-- Symlink x86nasm.c into the `src' directory before attempting the
- triple test, or the compile will fail.
-
-- Now it should pass the triple test, on either ELF or a.out. Voila!
+ Julian Hall <jules@earthcorp.com>
+ Simon Tatham <anakin@pobox.com>
diff --git a/assemble.c b/assemble.c
index 21c5729a..98bb5074 100644
--- a/assemble.c
+++ b/assemble.c
@@ -152,7 +152,7 @@ static int jmp_match (long segment, long offset, int bits,
if (c != 0370) return 0;
- if (ins->oprs[0].opflags & OPFLAG_FORWARD) return 1; /* match a forward reference */
+ if (ins->oprs[0].opflags & OPFLAG_FORWARD) return (! pass0); /*1;*/ /* match a forward reference */
isize = calcsize (segment, offset, bits, ins, code);
if (ins->oprs[0].segment != segment) return 0;
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 78fafa3b..a7f2ab98 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -24,7 +24,9 @@ OUT = nasm.info
all: $(OUT)
-.SUFFIXES: .src .texi .info .ps .rtf .hpj .dvi .ps .txt .pl
+os2: nasm.inf
+
+.SUFFIXES: .src .texi .info .ps .rtf .hpj .dvi .ps .txt .pl .ipf .inf
# Consider html, txt and src output a side effect
.src.texi:
@@ -37,11 +39,18 @@ nasm.info: nasmdoc.texi
$(MAKEINFO) $<
mv -f *.info *.info-* info
+# Rules for building an OS/2 book
+.texi.ipf:
+ texi2ipf $< >$@
+
+nasm.inf: nasmdoc.ipf
+ ipfc -i -s $< $@
+
clean:
- -rm -f *.rtf *.hpj *.texi *.ph *.gid
+ -rm -f *.rtf *.hpj *.texi *.ph *.gid *.ipf
spotless: clean
- -rm -rf html info *.hlp *.txt *.ps
+ -rm -rf html info *.hlp *.txt *.ps *.inf
install: all
$(INSTALL_DATA) info/* $(INSTALLROOT)$(infodir)
diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src
index 29657073..c047f1f9 100644
--- a/doc/nasmdoc.src
+++ b/doc/nasmdoc.src
@@ -1536,6 +1536,49 @@ The expression passed to \c{%assign} is a \i{critical expression}
a relocatable reference such as a code or data address, or anything
involving a register).
+\H{strlen} \i{String Handling in Macros}: \i\c{%strlen} and \i\c{%substr}
+
+It's often useful to be able to handle strings in macros. NASM
+supports two simple string handling macro operators from which
+more complex operations can be constructed.
+
+\S{strlen} \i{String Length}: \i\c{%strlen}
+
+The \c{%strlen} macro is like \c{%assign} macro in that it creates
+(or redefines) a numeric value to a macro. The difference is that
+with \c{%strlen}, the numeric value is the length of a string. An
+example of the use of this would be:
+
+\c %strlen charcnt 'my string'
+
+In this example, \c{charcnt} would receive the value 8, just as
+if an \c{%assign} had been used. In this example, \c{'my string'}
+was a literal string but it could also have been a single-line
+macro that expands to a string, as in the following example:
+
+\c %define sometext 'my string'
+\c %strlen charcnt sometext
+
+As in the first case, this would result in \c{charcnt} being
+assigned the value of 8.
+
+\S{substr} \i{Sub-strings}: \i\c{%substr}
+
+Individual letters in strings can be extracted using \c{%substr}.
+An example of its use is probably more useful than the description:
+
+\c %substr mychar 'xyz' 1 ; equivalent to %define mychar 'x'
+\c %substr mychar 'xyz' 2 ; equivalent to %define mychar 'y'
+\c %substr mychar 'xyz' 3 ; equivalent to %define mychar 'z'
+
+In this example, mychar gets the value of 'y'. As with \c{%strlen}
+(see \k{strlen}), the first parameter is the single-line macro to
+be created and the second is the string. The third parameter
+specifies which character is to be selected. Note that the first
+index is 1, not 0 and the last index is equal to the value that
+\c{%strlen} would assign given the same string. Index values out
+of range result in an empty string.
+
\H{mlmacro} \i{Multi-Line Macros}: \I\c{%imacro}\i\c{%macro}
Multi-line macros are much more like the type of macro seen in MASM
@@ -5620,6 +5663,19 @@ sign-extended to the length of the first operand. In these cases,
the \c{BYTE} qualifier is necessary to force NASM to generate this
form of the instruction.
+\H{insADDPS} \i\c{ADDPS}: Packed Single FP ADD
+
+\c ADDPS xmmreg,mem128 ; 0f 58 /r [KATMAI,SSE]
+\c ADDPS xmmreg,xmmreg ; 0f 58 /r [KATMAI,SSE]
+
+\c{ADDPS} performs addition on each of four packed SP FP
+number items dst(0-31):=dst(0-31)+src(0-31), ..(63-32), etc.
+
+\H{insADDSS} \i\c{ADDSS}: Scalar Single FP ADD
+
+\c ADDSS xmmreg,mem128 ; f3 0f 58 /r [KATMAI,SSE]
+\c ADDSS xmmreg,xmmreg ; f3 0f 58 /r [KATMAI,SSE]
+
\H{insAND} \i\c{AND}: Bitwise AND
\c AND r/m8,reg8 ; 20 /r [8086]
@@ -5655,6 +5711,18 @@ form of the instruction.
The MMX instruction \c{PAND} (see \k{insPAND}) performs the same
operation on the 64-bit MMX registers.
+\H{insANDNPS} \i\c{ANDNPS}: Bitwise Logical AND NOT For Single FP
+
+\c ANDNPS xmmreg,mem128 ; 0f 55 /r [KATMAI,SSE]
+\c ANDNPS xmmreg,xmmreg ; 0f 55 /r [KATMAI,SSE]
+
+
+\H{insANDPS} \i\c{ANDPS}: Bitwise Logical AND For Single FP
+
+\c ANDPS xmmreg,mem128 ; 0f 54 /r [KATMAI,SSE]
+\c ANDPS xmmreg,xmmreg ; 0f 54 /r [KATMAI,SSE]
+
+
\H{insARPL} \i\c{ARPL}: Adjust RPL Field of Selector
\c ARPL r/m16,reg16 ; 63 /r [286,PRIV]
@@ -5872,6 +5940,102 @@ sign-extended to the length of the first operand. In these cases,
the \c{BYTE} qualifier is necessary to force NASM to generate this
form of the instruction.
+
+\H{insCMPEQPS} \i\c{CMPEQPS}: Packed Single FP Compare (CMPPS)
+
+\c CMPEQPS xmmreg,memory ; 0f c2 /r ib [KATMAI,SSE]
+\c CMPEQPS xmmreg,xmmreg ; [KATMAI,SSE]
+
+\c{CMPPS} with condition set, re CMPPS.
+
+\H{insCMPEQSS} \i\c{CMPEQSS}: Scalar Single FP Compare (CMPSS)
+
+\c CMPEQSS xmmreg,memory ; ?? [KATMAI,SSE]
+\c CMPEQSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{CMPSS} with condition set, re CMPPS.
+
+\H{insCMPLEPS} \i\c{CMPLEPS}: Packed Single FP Compare (CMPPS)
+
+\c CMPLEPS xmmreg,memory ; ?? [KATMAI,SSE]
+\c CMPLEPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+
+\H{insCMPLESS} \i\c{CMPLESS}: Scalar Single FP Compare (CMPSS)
+
+\c CMPLESS xmmreg,memory ; ?? [KATMAI,SSE]
+\c CMPLESS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+
+\H{insCMPLTPS} \i\c{CMPLTPS}: Packed Single FP Compare (CMPPS)
+
+\c CMPLTPS xmmreg,memory ; ?? [KATMAI,SSE]
+\c CMPLTPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+
+\H{insCMPLTSS} \i\c{CMPLTSS}: Scalar Single FP Compare (CMPSS)
+
+\c CMPLTSS xmmreg,memory ; ?? [KATMAI,SSE]
+\c CMPLTSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+
+\H{insCMPNEQPS} \i\c{CMPNEQPS}: Packed Single FP Compare (CMPPS)
+
+\c CMPNEQPS xmmreg,memory ; ?? [KATMAI,SSE]
+\c CMPNEQPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+
+\H{insCMPNEQSS} \i\c{CMPNEQSS}: Scalar Single FP Compare (CMPSS)
+
+\c CMPNEQSS xmmreg,memory ; ?? [KATMAI,SSE]
+\c CMPNEQSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+
+\H{insCMPNLEPS} \i\c{CMPNLEPS}: Packed Single FP Compare (CMPPS)
+
+\c CMPNLEPS xmmreg,memory ; ?? [KATMAI,SSE]
+\c CMPNLEPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+
+\H{insCMPNLESS} \i\c{CMPNLESS}: Scalar Single FP Compare (CMPSS)
+
+\c CMPNLESS xmmreg,memory ; ?? [KATMAI,SSE]
+\c CMPNLESS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+
+\H{insCMPNLTPS} \i\c{CMPNLTPS}: Packed Single FP Compare (CMPPS)
+
+\c CMPNLTPS xmmreg,memory ; ?? [KATMAI,SSE]
+\c CMPNLTPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+
+\H{insCMPNLTSS} \i\c{CMPNLTSS}: Scalar Single FP Compare (CMPSS)
+
+\c CMPNLTSS xmmreg,memory ; ?? [KATMAI,SSE]
+\c CMPNLTSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+
+\H{insCMPORDPS} \i\c{CMPORDPS}: Packed Single FP Compare (CMPPS)
+
+\c CMPORDPS xmmreg,memory ; ?? [KATMAI,SSE]
+\c CMPORDPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+
+\H{insCMPORDSS} \i\c{CMPORDSS}: Scalar Single FP Compare (CMPSS)
+
+\c CMPORDSS xmmreg,memory ; ?? [KATMAI,SSE]
+\c CMPORDSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+
+\H{insCMPPS} \i\c{CMPPS}: Packed Single FP Compare
+
+\c CMPPS xmmreg,memory,immediate ; ?? [KATMAI,SSE,SB,AR2]
+\c CMPPS xmmreg,xmmreg,immediate ; ?? [KATMAI,SSE,SB,AR2]
+
+\c{CMP(cc)PS} and \c{CMP(cc)SS} conditions (cc):
+EQ, LT, LE, UNORD, NEQ, NLT, NLE, ORD
+
+
\H{insCMPSB} \i\c{CMPSB}, \i\c{CMPSW}, \i\c{CMPSD}: Compare Strings
\c CMPSB ; A6 [8086]
@@ -5903,6 +6067,29 @@ The \c{REPE} and \c{REPNE} prefixes (equivalently, \c{REPZ} and
\c{ECX} - again, the address size chooses which) times until the
first unequal or equal byte is found.
+
+
+\H{insCMPSS} \i\c{CMPSS}: Scalar Single FP Compare
+
+\c CMPSS xmmreg,memory,immediate ; ?? [KATMAI,SSE,SB,AR2]
+\c CMPSS xmmreg,xmmreg,immediate ; ?? [KATMAI,SSE,SB,AR2]
+
+\c{CMP(cc)PS} and \c{CMP(cc)SS} conditions (cc):
+EQ, LT, LE, UNORD, NEQ, NLT, NLE, ORD
+
+
+\H{insCMPUNORDPS} \i\c{CMPUNORDPS}: Packed Single FP Compare (CMPPS)
+
+\c CMPUNORDPS xmmreg,memory ; ?? [KATMAI,SSE]
+\c CMPUNORDPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+
+\H{insCMPUNORDSS} \i\c{CMPUNORDSS}: Scalar Single FP Compare (CMPSS)
+
+\c CMPUNORDSS xmmreg,memory ; ?? [KATMAI,SSE]
+\c CMPUNORDSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+
\H{insCMPXCHG} \i\c{CMPXCHG}, \i\c{CMPXCHG486}: Compare and Exchange
\c CMPXCHG r/m8,reg8 ; 0F B0 /r [PENT]
@@ -5948,6 +6135,14 @@ value in \c{EDX:EAX}. If they are equal, it sets the zero flag and
stores \c{ECX:EBX} into the memory area. If they are unequal, it
clears the zero flag and leaves the memory area untouched.
+\H{insCOMISS} \i\c{COMISS}: Scalar Ordered Single-FP Compare and Set EFLAGS
+
+\c COMISS xmmreg,memory ; ?? [KATMAI,SSE]
+\c COMISS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+Set Z, P, C according to comparison, clear O, S, A bits of EFLAGS.
+Z=P=C=1 for "unordered" result (QNaN).
+
\H{insCPUID} \i\c{CPUID}: Get CPU Identification Code
\c CPUID ; 0F A2 [PENT]
@@ -5987,6 +6182,50 @@ Buffers).
For more information on the data returned from \c{CPUID}, see the
documentation on Intel's web site.
+
+\H{insCVTPI2PS} \i\c{CVTPI2PS}:
+Packed Signed INT32 to Packed Single-FP Conversion
+
+\c CVTPI2PS xmmreg,mem64 ; ?? [KATMAI,SSE,MMX]
+\c CVTPI2PS xmmreg,mmxreg ; ?? [KATMAI,SSE,MMX]
+
+
+\H{insCVTPS2PI} \i\c{CVTPS2PI}:
+Packed Single-FP to Packed INT32 Conversion
+
+\c CVTPS2PI mmxreg,mem64 ; ?? [KATMAI,SSE,MMX]
+\c CVTPS2PI mmxreg,xmmreg ; ?? [KATMAI,SSE,MMX]
+
+
+\H{insCVTSI2SS} \i\c{CVTSI2SS}:
+Scalar Signed INT32 to Single-FP Conversion
+
+\c CVTSI2SS xmmreg,memory ; ?? [KATMAI,SSE,SD,AR1]
+\c CVTSI2SS xmmreg,reg32 ; ?? [KATMAI,SSE]
+
+
+
+\H{insCVTSS2SI} \i\c{CVTSS2SI}:
+Scalar Single-FP to Signed INT32 Conversion
+
+\c CVTSS2SI reg32,memory ; ?? [KATMAI,SSE]
+\c CVTSS2SI reg32,xmmreg ; ?? [KATMAI,SSE]
+
+
+\H{insCVTTPS2PI} \i\c{CVTTPS2PI}:
+Packed Single-FP to Packed INT32 Conversion
+
+\c CVTTPS2PI mmxreg,memory ; ?? [KATMAI,SSE,MMX]
+\c CVTTPS2PI mmxreg,xmmreg ; ?? [KATMAI,SSE,MMX]
+
+
+\H{insCVTTSS2SI} \i\c{CVTTSS2SI}:
+Scalr Single-FP to Signed INT32 Conversion
+
+\c CVTTSS2SI reg32,memory ; ?? [KATMAI,SSE]
+\c CVTTSS2SI reg32,xmmreg ; ?? [KATMAI,SSE]
+
+
\H{insDAA} \i\c{DAA}, \i\c{DAS}: Decimal Adjustments
\c DAA ; 27 [8086]
@@ -6043,6 +6282,24 @@ the quotient is stored in \c{EAX} and the remainder in \c{EDX}.
Signed integer division is performed by the \c{IDIV} instruction:
see \k{insIDIV}.
+\H{insDIVPS} \i\c{DIVPS}: Packed Single-FP Divide
+
+\c DIVPS xmmreg,memory ; 0F,5E,/r [KATMAI,SSE]
+\c DIVPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{DIVPS}The DIVPS instruction divides the packed SP FP numbers
+of both their operands.
+
+
+\H{insDIVSS} \i\c{DIVSS}: Scalar Single-FP Divide
+
+\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
+of both operands; the upper three fields are passed through from xmm1.
+
+
\H{insEMMS} \i\c{EMMS}: Empty MMX State
\c EMMS ; 0F 77 [PENT,MMX]
@@ -6323,6 +6580,14 @@ operand.
once it has finished. \c{FDIVRP} operates like \c{FDIVR TO}, but
pops the register stack once it has finished.
+
+\H{insFEMMS} \i\c{FEMMS}: 3dnow instruction (duh!)
+
+\c FEMMS 0,0,0 ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
\H{insFFREE} \i\c{FFREE}: Flag Floating-Point Register as Unused
\c FFREE fpureg ; DD C0+r [8086,FPU]
@@ -6754,6 +7019,35 @@ denormal. It also sets the C1 flag to the sign of the number.
\c{FXCH} exchanges \c{ST0} with a given FPU register. The no-operand
form exchanges \c{ST0} with \c{ST1}.
+\H{insFXRSTOR} \i\c{FXRSTOR}: Restore FP and MMXTM State and
+Streaming SIMD Extension State
+
+\c FXRSTOR memory ; 0F,AE,/1 [P6,SSE,FPU]
+
+\c{FXRSTOR}The FXRSTOR instruction reloads the FP and MMXTM technology
+state, and the Streaming SIMD Extension state (environment and registers),
+from the memory area defined by m512byte. This data should have been
+written by a previous FXSAVE.
+
+
+\H{insFXSAVE} \i\c{FXSAVE}: Store FP and MMXTM State
+ and Streaming SIMD
+
+\c FXSAVE memory ; 0F,AE,/0 [P6,SSE,FPU]
+
+
+\c{FXSAVE}The FXSAVE instruction writes the current FP and
+ MMXTM technology state, and Streaming SIMD Extension state
+ (environment and registers), to the specified destination
+ defined by m512byte. It does this without checking for pending
+ unmasked floating-point exceptions (similar to the operation of
+ FNSAVE). Unlike the FSAVE/FNSAVE instructions, the processor
+retains the contents of the FP and MMXTM technology state and
+ Streaming SIMD Extension state in the processor after the state
+ has been saved. This instruction has been optimized to maximize
+ floating-point save performance.
+
+
\H{insFXTRACT} \i\c{FXTRACT}: Extract Exponent and Significand
\c FXTRACT ; D9 F4 [8086,FPU]
@@ -7007,8 +7301,8 @@ on the default \c{BITS} setting at the time.
\H{insJCXZ} \i\c{JCXZ}, \i\c{JECXZ}: Jump if CX/ECX Zero
-\c JCXZ imm ; o16 E3 rb [8086]
-\c JECXZ imm ; o32 E3 rb [386]
+\c JCXZ imm ; a16 E3 rb [8086]
+\c JECXZ imm ; a32 E3 rb [386]
\c{JCXZ} performs a short jump (with maximum range 128 bytes) if and
only if the contents of the \c{CX} register is 0. \c{JECXZ} does the
@@ -7118,6 +7412,17 @@ loads the \e{next} 16 bits from memory into \c{DS}. \c{LES},
\c{LFS}, \c{LGS} and \c{LSS} work in the same way but use the other
segment registers.
+
+\H{insLDMXCSR} \i\c{LDMXCSR}: Load Streaming SIMD Extension
+ Control/Status
+
+\c LDMXCSR memory ; 0F,AE,/2 [KATMAI,SSE,SD]
+
+\c{LDMXCSR} The MXCSR control/status register is used to enable
+ masked/unmasked exception handling, to set rounding modes, to
+ set flush-to-zero mode, and to view exception status flags.
+
+
\H{insLEA} \i\c{LEA}: Load Effective Address
\c LEA reg16,mem ; o16 8D /r [8086]
@@ -7260,6 +7565,73 @@ loaded into the destination (first) operand.
descriptor specified by the segment selector given as its operand,
and loads them into the Task Register.
+
+\H{insMASKMOVQ} \i\c{MASKMOVQ}: Byte Mask Write
+
+\c MASKMOVQ mmxreg,mmxreg ; 0F,F7,/r [KATMAI,MMX]
+
+\c{MASKMOVQ} Data is stored from the mm1 register to the location
+ specified by the di/edi register (using DS segment). The size
+ of the store depends on the address-size attribute. The most
+ significant bit in each byte of the mask register mm2 is used
+ to selectively write the data (0 = no write, 1 = write) on a
+ per-byte basis.
+
+
+\H{insMAXPS} \i\c{MAXPS}: Packed Single-FP Maximum
+
+\c MAXPS xmmreg,memory ; 0F,5F,/r [KATMAI,SSE]
+\c MAXPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{MAXPS}The MAXPS instruction returns the maximum SP FP numbers
+ from XMM1 and XMM2/Mem.If the values being compared are both
+ zeroes, source2 (xmm2/m128) would be returned. If source2
+ (xmm2/m128) is an sNaN, this sNaN is forwarded unchanged
+ to the destination (i.e., a quieted version of the sNaN
+ is not returned).
+
+
+\H{insMAXSS} \i\c{MAXSS}: Scalar Single-FP Maximum
+
+\c MAXSS xmmreg,memory ; F3,0F,5F,/r [KATMAI,SSE]
+\c MAXSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{MAXSS}The MAXSS instruction returns the maximum SP FP number
+ from the lower SP FP numbers of XMM1 and XMM2/Mem; the upper
+ three fields are passed through from xmm1. If the values being
+ compared are both zeroes, source2 (xmm2/m128) will be returned.
+ If source2 (xmm2/m128) is an sNaN, this sNaN is forwarded
+ unchanged to the destination (i.e., a quieted version of the
+ sNaN is not returned).
+
+
+\H{insMINPS} \i\c{MINPS}: Packed Single-FP Minimum
+
+\c MINPS xmmreg,memory ; 0F,5D,/r [KATMAI,SSE]
+\c MINPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{MINPS} The MINPS instruction returns the minimum SP FP
+ numbers from XMM1 and XMM2/Mem. If the values being compared
+ are both zeroes, source2 (xmm2/m128) would be returned. If
+ source2 (xmm2/m128) is an sNaN, this sNaN is forwarded unchanged
+ to the destination (i.e., a quieted version of the sNaN is
+ not returned).
+
+
+\H{insMINSS} \i\c{MINSS}: Scalar Single-FP Minimum
+
+\c MINSS xmmreg,memory ; F3,0F,5D,/r [KATMAI,SSE]
+\c MINSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{MINSS} The MINSS instruction returns the minimum SP FP number
+ from the lower SP FP numbers from XMM1 and XMM2/Mem; the upper
+ three fields are passed through from xmm1. If the values being
+ compared are both zeroes, source2 (xmm2/m128) would be returned.
+ If source2 (xmm2/m128) is an sNaN, this sNaN is forwarded
+ unchanged to the destination (i.e., a quieted version of the
+ sNaN is not returned).
+
+
\H{insMOV} \i\c{MOV}: Move Data
\c MOV r/m8,reg8 ; 88 /r [8086]
@@ -7311,6 +7683,21 @@ undefined.
\c{CR4} is only a supported register on the Pentium and above.
+\H{insMOVAPS} \i\c{MOVAPS}: Move Aligned Four Packed Single-FP
+
+\c MOVAPS xmmreg,memory ; 0F,28,/r [KATMAI,SSE]
+\c MOVAPS memory,xmmreg ; 0F,29,/r [KATMAI,SSE]
+\c MOVAPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+\c MOVAPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{MOVAPS} The linear address corresponds to the address of the
+ least-significant byte of the referenced memory data. When a
+ memory address is indicated, the 16 bytes of data at memory
+ location m128 are loaded or stored. When the register-register
+ form of this operation is used, the content of the 128-bit
+ source register is copied into the 128-bit destination register.
+
+
\H{insMOVD} \i\c{MOVD}: Move Doubleword to/from MMX Register
\c MOVD mmxreg,r/m32 ; 0F 6E /r [PENT,MMX]
@@ -7320,6 +7707,57 @@ undefined.
destination (first) operand. When the destination is a 64-bit MMX
register, the top 32 bits are set to zero.
+
+\H{insMOVHLPS} \i\c{MOVHLPS}: High to Low Packed Single-FP
+
+\c MOVHLPS xmmreg,xmmreg ; OF,12,/r [KATMAI,SSE]
+
+\c{MOVHLPS} The upper 64-bits of the source register xmm2 are
+ loaded into the lower 64-bits of the 128-bit register xmm1,
+ and the upper 64-bits of xmm1 are left unchanged.
+
+
+\H{insMOVHPS} \i\c{MOVHPS}: Move High Packed Single-FP
+
+\c MOVHPS xmmreg,memory ; 0F,16,/r [KATMAI,SSE]
+\c MOVHPS memory,xmmreg ; 0F,17,/r [KATMAI,SSE]
+\c MOVHPS xmmreg,xmmreg ; ?? [KATMAI,SSE,ND]
+
+\c{MOVHPS} The linear address corresponds to the address of the
+ least-significant byte of the referenced memory data. When the
+ load form of this operation is used, m64 is loaded into the
+ upper 64-bits of the 128-bit register xmm, and the lower 64-bits
+ are left unchanged.
+
+
+\H{insMOVMSKPS} \i\c{MOVMSKPS}: Move Mask To Integer
+
+\c MOVMSKPS reg32,xmmreg ; 0F,50,/r [KATMAI,SSE]
+
+\c{MOVMSKPS} The MOVMSKPS instruction returns to the integer
+ register r32 a 4-bit mask formed of the most significant bits
+ of each SP FP number of its operand.
+
+
+\H{insMOVNTPS} \i\c{MOVNTPS}: Move Aligned Four Packed Single-FP
+ Non Temporal
+
+\c MOVNTPS memory,xmmreg ; 0F,2B, /r [KATMAI,SSE]
+
+\c{MOVNTPS} The linear address corresponds to the address of the
+ least-significant byte of the referenced memory data. This store
+ instruction minimizes cache pollution.
+
+
+\H{insMOVNTQ} \i\c{MOVNTQ}: Move 64 Bits Non Temporal
+
+\c MOVNTQ memory,mmxreg ; 0F,E7,/r [KATMAI,MMX,SM]
+
+\c{MOVNTQ} The linear address corresponds to the address of the
+ least-significant byte of the referenced memory data. This store
+ instruction minimizes cache pollution.
+
+
\H{insMOVQ} \i\c{MOVQ}: Move Quadword to/from MMX Register
\c MOVQ mmxreg,r/m64 ; 0F 6F /r [PENT,MMX]
@@ -7328,6 +7766,8 @@ register, the top 32 bits are set to zero.
\c{MOVQ} copies 64 bits from its source (second) operand into its
destination (first) operand.
+
+
\H{insMOVSB} \i\c{MOVSB}, \i\c{MOVSW}, \i\c{MOVSD}: Move String
\c MOVSB ; A4 [8086]
@@ -7356,6 +7796,22 @@ addressing registers by 2 or 4 instead of 1.
The \c{REP} prefix may be used to repeat the instruction \c{CX} (or
\c{ECX} - again, the address size chooses which) times.
+\H{insMOVSS} \i\c{MOVSS}: Move Scalar Single-FP
+
+\c MOVSS xmmreg,memory ; F3,0F,10,/r [KATMAI,SSE]
+\c MOVSS memory,xmmreg ; F3,0F,11,/r [KATMAI,SSE]
+\c MOVSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+\c MOVSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{MOVSS} The linear address corresponds to the address of
+ the least-significant byte of the referenced memory data.
+ When a memory address is indicated, the four bytes of data
+ at memory location m32 are loaded or stored. When the load
+ form of this operation is used, the 32 bits from memory are
+ copied into the lower 32 bits of the 128-bit register xmm,
+ the 96 most significant bits being cleared.
+
+
\H{insMOVSX} \i\c{MOVSX}, \i\c{MOVZX}: Move Data with Sign or Zero Extend
\c MOVSX reg16,r/m8 ; o16 0F BE /r [386]
@@ -7371,6 +7827,24 @@ its destination (first) operand, and copies the result into the
destination operand. \c{MOVZX} does the same, but zero-extends
rather than sign-extending.
+
+\H{insMOVUPS} \i\c{MOVUPS}: Move Unaligned Four Packed Single-FP
+
+\c MOVUPS xmmreg,memory ; 0F,10,/r [KATMAI,SSE]
+\c MOVUPS memory,xmmreg ; 0F,11,/r [KATMAI,SSE]
+\c MOVUPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+\c MOVUPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{MOVUPS} The linear address corresponds to the address of the
+ least-significant byte of the referenced memory data. When a
+ memory address is indicated, the 16 bytes of data at memory
+ location m128 are loaded to the 128-bit multimedia register
+ xmm or stored from the 128-bit multimedia register xmm. When
+ the register-register form of this operation is used, the content
+ of the 128-bit source register is copied into 128-bit register
+ xmm. No assumption is made about alignment.
+
+
\H{insMUL} \i\c{MUL}: Unsigned Integer Multiply
\c MUL r/m8 ; F6 /4 [8086]
@@ -7393,6 +7867,27 @@ the product is stored in \c{EDX:EAX}.
Signed integer multiplication is performed by the \c{IMUL}
instruction: see \k{insIMUL}.
+\H{insMULPS} \i\c{MULPS}: Packed Single-FP Multiply
+
+\c MULPS xmmreg,memory ; 0F,59,/r [KATMAI,SSE]
+\c MULPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+
+\c{MULPS} The MULPS instructions multiply the packed SP FP
+ numbers of both their operands.
+
+
+\H{insMULSS} \i\c{MULSS}: Scalar Single-FP Multiply
+
+
+\c MULSS xmmreg,memory ; F3,0F,59,/r [KATMAI,SSE]
+\c MULSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{MULSS}The MULSS instructions multiply the lowest SP FP
+ numbers of both their operands; the upper three fields
+ are passed through from xmm1.
+
+
\H{insNEG} \i\c{NEG}, \i\c{NOT}: Two's and One's Complement
\c NEG r/m8 ; F6 /3 [8086]
@@ -7451,6 +7946,15 @@ form of the instruction.
The MMX instruction \c{POR} (see \k{insPOR}) performs the same
operation on the 64-bit MMX registers.
+\H{insORPS} \i\c{ORPS}: Bit-wise Logical OR for Single-FP Data
+
+\c ORPS xmmreg,memory ; 0F,56,/r [KATMAI,SSE]
+\c ORPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{ORPS} The ORPS instructions return a bit-wise logical
+ OR between xmm1 and xmm2/mem.
+
+
\H{insOUT} \i\c{OUT}: Output Data to I/O Port
\c OUT imm8,AL ; E6 ib [8086]
@@ -7580,6 +8084,38 @@ operands as vectors of eight unsigned bytes, and calculates the
average of the corresponding bytes in the operands. The resulting
vector of eight averages is stored in the first operand.
+
+\H{insPAVGB} \i\c{PAVGB}: Packed Average
+
+\c PAVGB mmxreg,mmxreg ; 0F,E0, /r [KATMAI,MMX]
+\c PAVGB mmxreg,memory ; 0F,E3, /r [KATMAI,MMX,SM]
+
+
+\H{insPAVGW} \i\c{PAVGW}: Packed Average
+
+\c PAVGW mmxreg,mmxreg ; ?? [KATMAI,MMX]
+\c PAVGW mmxreg,memory ; ?? [KATMAI,MMX,SM]
+
+\c{PAVGB} The PAVG instructions add the unsigned data elements
+ of the source operand to the unsigned data elements of the
+ destination register, along with a carry-in. The results of
+ the add are then each independently right-shifted by one bit
+ position. The high order bits of each element are filled with
+ the carry bits of the corresponding sum. The destination operand
+ is an MMXTM technology register. The source operand can either
+ be an MMXTM technology register or a 64-bit memory operand.
+ The PAVGB instruction operates on packed unsigned bytes, and
+ the PAVGW instruction operates on packed unsigned words.
+
+
+\H{insPAVGUSB} \i\c{PAVGUSB}: 3dnow instruction (duh!)
+
+\c PAVGUSB mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PAVGUSB mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
\H{insPCMPEQB} \i\c{PCMPxx}: MMX Packed Comparison
\c PCMPEQB mmxreg,r/m64 ; 0F 74 /r [PENT,MMX]
@@ -7609,7 +8145,7 @@ integer) than that of the second (source) operand.
\H{insPDISTIB} \i\c{PDISTIB}: MMX Packed Distance and Accumulate
with Implied Register
-\c PDISTIB mmxreg,mem64 ; 0F 54 /r [CYRIX,MMX]
+\c PDISTIB mmxreg,mem64 ; 0F 54 /r [CYRIX,MMX]
\c{PDISTIB}, specific to the Cyrix MMX extensions, treats its two
input operands as vectors of eight unsigned bytes. For each byte
@@ -7624,6 +8160,167 @@ The implied output register is found in the same way as \c{PADDSIW}
Note that \c{PDISTIB} cannot take a register as its second source
operand.
+
+\H{insPEXTRW} \i\c{PEXTRW}: Extract Word
+
+\c PEXTRW reg32,mmxreg,immediate ; 0F,C5,/r,ib [KATMAI,MMX,SB,AR2]
+
+\c{PEXTRW}PEXTRW instruction moves the word in MM (selected by the
+ two least significant bits of imm8) to the lower half of a 32-bit
+ integer register.
+
+
+\H{insPF2ID} \i\c{PF2ID}: 3dnow instruction (duh!)
+
+\c PF2ID mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PF2ID mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPFACC} \i\c{PFACC}: 3dnow instruction (duh!)
+
+\c PFACC mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PFACC mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPFADD} \i\c{PFADD}: 3dnow instruction (duh!)
+
+\c PFADD mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PFADD mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPFCMPEQ} \i\c{PFCMPEQ}: 3dnow instruction (duh!)
+
+\c PFCMPEQ mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PFCMPEQ mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPFCMPGE} \i\c{PFCMPGE}: 3dnow instruction (duh!)
+
+\c PFCMPGE mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PFCMPGE mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPFCMPGT} \i\c{PFCMPGT}: 3dnow instruction (duh!)
+
+\c PFCMPGT mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PFCMPGT mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPFMAX} \i\c{PFMAX}: 3dnow instruction (duh!)
+
+\c PFMAX mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PFMAX mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPFMIN} \i\c{PFMIN}: 3dnow instruction (duh!)
+
+\c PFMIN mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PFMIN mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPFMUL} \i\c{PFMUL}: 3dnow instruction (duh!)
+
+\c PFMUL mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PFMUL mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPFRCP} \i\c{PFRCP}: 3dnow instruction (duh!)
+
+\c PFRCP mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PFRCP mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPFRCPIT1} \i\c{PFRCPIT1}: 3dnow instruction (duh!)
+
+\c PFRCPIT1 mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PFRCPIT1 mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPFRCPIT2} \i\c{PFRCPIT2}: 3dnow instruction (duh!)
+
+\c PFRCPIT2 mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PFRCPIT2 mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPFRSQIT1} \i\c{PFRSQIT1}: 3dnow instruction (duh!)
+
+\c PFRSQIT1 mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PFRSQIT1 mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPFRSQRT} \i\c{PFRSQRT}: 3dnow instruction (duh!)
+
+\c PFRSQRT mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PFRSQRT mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPFSUB} \i\c{PFSUB}: 3dnow instruction (duh!)
+
+\c PFSUB mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PFSUB mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPFSUBR} \i\c{PFSUBR}: 3dnow instruction (duh!)
+
+\c PFSUBR mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PFSUBR mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPI2FD} \i\c{PI2FD}: 3dnow instruction (duh!)
+
+\c PI2FD mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PI2FD mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPINSRW} \i\c{PINSRW}: Insert Word
+
+\c PINSRW mmxreg,reg16,immediate ;0F,C4,/r,ib [KATMAI,MMX,SB,AR2]
+\c PINSRW mmxreg,reg32,immediate ; ?? [KATMAI,MMX,SB,AR2,ND]
+\c PINSRW mmxreg,memory,immediate ; ?? [KATMAI,MMX,SB,AR2]
+\c PINSRW mmxreg,memory|bits16,immediate ; ?? [KATMAI,MMX,SB,AR2,ND]
+
+\c{PINSRW} The PINSRW instruction loads a word from the lower half
+ of a 32-bit integer register (or from memory) and inserts it in
+ the MM destination register, at a position defined by the two
+ least significant bits of the imm8 constant. The insertion is
+ done in such a way that the three other words from the
+ destination register are left untouched.
+
+
\H{insPMACHRIW} \i\c{PMACHRIW}: MMX Packed Multiply and Accumulate
with Rounding
@@ -7658,6 +8355,51 @@ values of the words in corresponding positions, and sets each word
of the destination (first) operand to whichever of the two words in
that position had the larger absolute value.
+\H{insPMAXSW} \i\c{PMAXSW}: Packed Signed Integer Word Maximum
+
+\c PMAXSW mmxreg,mmxreg ; 0F,EE, /r [KATMAI,MMX]
+\c PMAXSW mmxreg,memory ; ?? [KATMAI,MMX,SM]
+
+\c{PMAXSW} The PMAXSW instruction returns the maximum between
+ the four signed words in MM1 and MM2/Mem.
+
+
+\H{insPMAXUB} \i\c{PMAXUB}: Packed Unsigned Integer Byte Maximum
+
+\c PMAXUB mmxreg,mmxreg ; 0F,DE, /r [KATMAI,MMX]
+\c PMAXUB mmxreg,memory ; ?? [KATMAI,MMX,SM]
+
+\c{PMAXUB} The PMAXUB instruction returns the maximum between
+ the eight unsigned words in MM1 and MM2/Mem.
+
+
+\H{insPMINSW} \i\c{PMINSW}: Packed Signed Integer Word Minimum
+
+\c PMINSW mmxreg,mmxreg ; 0F,EA, /r [KATMAI,MMX]
+\c PMINSW mmxreg,memory ; ?? [KATMAI,MMX,SM]
+
+\c{PMINSW} The PMINSW instruction returns the minimum between
+ the four signed words in MM1 and MM2/Mem.
+
+
+\H{insPMINUB} \i\c{PMINUB}: Packed Unsigned Integer Byte Minimum
+
+\c PMINUB mmxreg,mmxreg ; 0F,DA, /r [KATMAI,MMX]
+\c PMINUB mmxreg,memory ; ?? [KATMAI,MMX,SM]
+
+\c{PMINUB}The PMINUB instruction returns the minimum between
+ the eight unsigned words in MM1 and MM2/Mem.
+
+
+\H{insPMOVMSKB} \i\c{PMOVMSKB}: Move Byte Mask To Integer
+
+\c PMOVMSKB reg32,mmxreg ; 0F,D7,/r [KATMAI,MMX]
+
+\c{PMOVMSKB} The PMOVMSKB instruction returns an 8-bit mask
+ formed of the most significant bits of each byte of its
+ source operand.
+
+
\H{insPMULHRW} \i\c{PMULHRW}, \i\c{PMULHRIW}: MMX Packed Multiply
High with Rounding
@@ -7677,6 +8419,26 @@ For \c{PMULHRW}, the destination operand is the first operand; for
\c{PMULHRIW} the destination operand is implied by the first operand
in the manner of \c{PADDSIW} (\k{insPADDSIW}).
+
+\H{insPMULHRWA} \i\c{PMULHRWA}: 3dnow instruction (duh!)
+
+\c PMULHRWA mmxreg,memory ; ?? [PENT,3DNOW,SM]
+\c PMULHRWA mmxreg,mmxreg ; ?? [PENT,3DNOW]
+
+3dnow instruction (duh!)
+
+
+\H{insPMULHUW} \i\c{PMULHUW}: Packed Multiply High Unsigned
+
+\c PMULHUW mmxreg,mmxreg ; 0F,E4,/r [KATMAI,MMX]
+\c PMULHUW mmxreg,memory ; ?? [KATMAI,MMX,SM]
+
+\c{PMULHUW} The PMULHUW instruction multiplies the four unsigned
+ words in the destination operand with the four unsigned words
+ in the source operand. The high-order 16 bits of the 32-bit
+ intermediate results are written to the destination operand.
+
+
\H{insPMULHW} \i\c{PMULHW}, \i\c{PMULLW}: MMX Packed Multiply
\c PMULHW mmxreg,r/m64 ; 0F E5 /r [PENT,MMX]
@@ -7690,6 +8452,7 @@ signed doubleword results.
destination (first) operand; \c{PMULLW} stores the bottom 16 bits of
each doubleword in the destination operand.
+
\H{insPMVccZB} \i\c{PMVccZB}: MMX Packed Conditional Move
\c PMVZB mmxreg,mem64 ; 0F 58 /r [CYRIX,MMX]
@@ -7721,7 +8484,7 @@ source operand.
\c POP r/m16 ; o16 8F /0 [8086]
\c POP r/m32 ; o32 8F /0 [386]
-\c POP CS ; 0F [8086,UNDOC]
+\c POP CS ; 0F [8086,UNDOC]
\c POP DS ; 1F [8086]
\c POP ES ; 07 [8086]
\c POP SS ; 17 [8086]
@@ -7801,6 +8564,84 @@ See also \c{PUSHF} (\k{insPUSHF}).
corresponding bits of the two inputs was 1), and stores the result
in the destination (first) operand.
+
+\H{insPREFETCHNTA} \i\c{PREFETCHNTA}: Prefetch
+
+\c PREFETCHNTA memory ; 0F,18,/0 [KATMAI]
+
+\c{PREFETCHNTA} Move data specified by address closer to the
+ processor using the nta hint.
+
+
+\H{insPREFETCHT0} \i\c{PREFETCHT0}: Prefetch
+
+\c PREFETCHT0 memory ; 0F,18,/1 [KATMAI]
+
+\c{PREFETCHT0} Move data specified by address closer to the
+ processor using the t0 hint.
+
+
+\H{insPREFETCHT1} \i\c{PREFETCHT1}: Prefetch
+
+\c PREFETCHT1 memory ; 0F,18,/2 [KATMAI]
+
+\c{PREFETCHT1}Move data specified by address closer to the
+ processor using the t1 hint.
+
+
+\H{insPREFETCHT2} \i\c{PREFETCHT2}: Prefetch
+
+\c PREFETCHT2 memory ; 0F,18,/3 [KATMAI]
+
+\c{PREFETCHT2} Move data specified by address closer to the
+ processor using the t2 hint.
+
+
+\H{insPREFETCH} \i\c{PREFETCH}: 3dnow instruction (duh!)
+
+\c PREFETCH memory ; ?? [PENT,3DNOW,SM]
+
+3dnow instruction (duh!)
+
+
+\H{insPREFETCHW} \i\c{PREFETCHW}: 3dnow instruction (duh!)
+
+\c PREFETCHW memory ; ?? [PENT,3DNOW,SM]
+
+3dnow instruction (duh!)
+
+
+
+
+
+\H{insPSADBW} \i\c{PSADBW}: Packed Sum of Absolute Differences
+
+\c PSADBW mmxreg,mmxreg ; 0F,F6, /r [KATMAI,MMX]
+\c PSADBW mmxreg,memory ; ?? [KATMAI,MMX,SM]
+
+\c{PSADBW} The PSADBW instruction computes the absolute value of
+ the difference of unsigned bytes for mm1 and mm2/m64. These
+ differences are then summed to produce a word result in the lower
+ 16-bit field; the upper three words are cleared. The destination
+ operand is an MMXTM technology register. The source operand can
+ either be an MMXTM technology register or a 64-bit memory operand.
+
+
+\H{insPSHUFW} \i\c{PSHUFW}: Packed Shuffle Word
+
+\c PSHUFW mmxreg,mmxreg,immediate ; 0F,70,/r,ib [KATMAI,MMX,SB,AR2]
+\c PSHUFW mmxreg,memory,immediate ; ?? [KATMAI,MMX,SM2,SB,AR2]
+
+\c{PSHUFW} The PSHUF instruction uses the imm8 operand to select
+ which of the four words in MM2/Mem will be placed in each of the
+ words in MM1. Bits 1 and 0 of imm8 encode the source for
+ destination word 0 (MM1[15-0]), bits 3 and 2 encode for word 1,
+ bits 5 and 4 encode for word 2, and bits 7 and 6 encode for
+ word 3 (MM1[63-48]). Similarly, the two-bit encoding represents
+ which source word is to be used, e.g., a binary encoding of 10
+ indicates that source word 2 (MM2/Mem[47-32]) will be used.
+
+
\H{insPSLLD} \i\c{PSLLx}, \i\c{PSRLx}, \i\c{PSRAx}: MMX Bit Shifts
\c PSLLW mmxreg,r/m64 ; 0F F1 /r [PENT,MMX]
@@ -8061,6 +8902,28 @@ You can force the longer (286 and upwards, beginning with a \c{C1}
byte) form of \c{RCL foo,1} by using a \c{BYTE} prefix: \c{RCL
foo,BYTE 1}. Similarly with \c{RCR}.
+
+\H{insRCPPS} \i\c{RCPPS}: Packed Single-FP Reciprocal
+
+\c RCPPS xmmreg,memory ; 0F,53,/r [KATMAI,SSE]
+\c RCPPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{RCPPS}RCPPS returns an approximation of the reciprocal of the
+ SP FP numbers from xmm2/m128. The maximum error for this
+ approximation is: Error <=1.5x2-12
+
+
+\H{insRCPSS} \i\c{RCPSS}: Scalar Single-FP Reciprocal
+
+\c RCPSS xmmreg,memory ; F3,0F,53,/r [KATMAI,SSE]
+\c RCPSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{RCPSS}RCPSS returns an approximation of the reciprocal of the
+ lower SP FP number from xmm2/m32; the upper three fields are
+ passed through from xmm1. The maximum error for this
+ approximation is: |Error| <= 1.5x2-12
+
+
\H{insRDMSR} \i\c{RDMSR}: Read Model-Specific Registers
\c RDMSR ; 0F 32 [PENT]
@@ -8145,6 +9008,28 @@ foo,BYTE 1}. Similarly with \c{ROR}.
\c{RSM} returns the processor to its normal operating mode when it
was in System-Management Mode.
+
+\H{insRSQRTPS} \i\c{RSQRTPS}:Packed Single-FP Square Root Reciprocal
+
+\c RSQRTPS xmmreg,memory ; 0F,52,/r [KATMAI,SSE]
+\c RSQRTPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{RSQRTPS} RSQRTPS returns an approximation of the reciprocal
+ of the square root of the SP FP numbers rom xmm2/m128. The
+ maximum error for this approximation is: Error| <= 1.5x2-12
+
+
+\H{insRSQRTSS} \i\c{RSQRTSS}:Scalar Single-FP Square Root Reciprocal
+
+\c RSQRTSS xmmreg,memory ; F3,0F,52,/r [KATMAI,SSE]
+\c RSQRTSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{RSQRTSS} RSQRTSS returns an approximation of the reciprocal
+ of the square root of the lowest SP FP number from xmm2/m32;
+ the upper three fields are passed through from xmm1. The maximum
+ error for this approximation is: |Error| <= 1.5x2-12
+
+
\H{insSAHF} \i\c{SAHF}: Store AH to Flags
\c SAHF ; 9E [8086]
@@ -8193,7 +9078,7 @@ foo,BYTE 1}. Similarly with \c{SAR}.
\H{insSALC} \i\c{SALC}: Set AL from Carry Flag
-\c SALC ; D6 [8086,UNDOC]
+\c SALC ; D6 [8086,UNDOC]
\c{SALC} is an early undocumented instruction similar in concept to
\c{SETcc} (\k{insSETcc}). Its function is to set \c{AL} to zero if
@@ -8273,6 +9158,36 @@ first unequal or equal byte is found.
\c{SETcc} sets the given 8-bit operand to zero if its condition is
not satisfied, and to 1 if it is.
+
+\H{insSFENCE} \i\c{SFENCE}: Store Fence
+
+\c SFENCE 0,0,0 ; 0F AE /7 [KATMAI]
+
+\c{SFENCE} Weakly ordered memory types can enable higher
+ performance through such techniques as out-of-order issue,
+ write-combining, and write-collapsing. Memory ordering issues
+ can arise between a producer and a consumer of data and there
+ are a number of common usage models which may be affected by
+ weakly ordered stores:
+ 1. library functions, which use weakly ordered memory
+ to write results
+ 2. compiler-generated code, which also benefit from writing
+ weakly-ordered results
+ 3. hand-written code
+ The degree to which a consumer of data knows that the data is
+ weakly ordered can vary for these cases. As a result, the SFENCE
+ instruction provides a performance-efficient way of ensuring
+ ordering between routines that produce weakly-ordered results
+ and routines that consume this data. The SFENCE is ordered with
+ respect to stores and other SFENCE instructions.
+ SFENCE uses the following ModRM encoding:
+ Mod (7:6) = 11B
+ Reg/Opcode (5:3) = 111B
+ R/M (2:0) = 000B
+ All other ModRM encodings are defined to be reserved, and use
+ of these encodings risks incompatibility with future processors.
+
+
\H{insSGDT} \i\c{SGDT}, \i\c{SIDT}, \i\c{SLDT}: Store Descriptor Table Pointers
\c SGDT mem ; 0F 01 /0 [286,PRIV]
@@ -8359,6 +9274,18 @@ EAX,EBX,4} would update \c{EAX} to hold \c{0xF0123456}.
The number of bits to shift by is given by the third operand. Only
the bottom 5 bits of the shift count are considered.
+
+\H{insSHUFPS} \i\c{SHUFPS}: Shuffle Single-FP
+
+\c SHUFPS xmmreg,memory,immediate ; 0F,C6,/r, ib [KATMAI,SSE,SB,AR2]
+\c SHUFPS xmmreg,xmmreg,immediate ; ?? [KATMAI,SSE,SB,AR2]
+
+\c{SHUFPS} The SHUFPS instruction is able to shuffle any of the
+ four SP FP numbers from xmm1 to the lower two destination fields;
+ the upper two destination fields are generated from a shuffle of
+ any of the four SP FP numbers from xmm2/m128.
+
+
\H{insSMI} \i\c{SMI}: System Management Interrupt
\c SMI ; F1 [386,UNDOC]
@@ -8375,6 +9302,25 @@ machine into system-management mode, a special debugging mode.
the Machine Status Word, on 286 processors) into the destination
operand. See also \c{LMSW} (\k{insLMSW}).
+
+\H{insSQRTPS} \i\c{SQRTPS}: Packed Single-FP Square Root
+
+\c SQRTPS xmmreg,memory ; 0F,51,/r [KATMAI,SSE]
+\c SQRTPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{SQRTPS} The SQRTPS instruction returns the square root of
+ the packed SP FP numbers from xmm2/m128.
+
+
+\H{insSQRTSS} \i\c{SQRTSS}: Scalar Single-FP Square Root
+
+\c SQRTSS xmmreg,memory ; F3,0F,51,/r [KATMAI,SSE]
+\c SQRTSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{SQRTSS} The SQRTSS instructions return the square root of
+ the lowest SP FP numbers of their operand.
+
+
\H{insSTC} \i\c{STC}, \i\c{STD}, \i\c{STI}: Set Flags
\c STC ; F9 [8086]
@@ -8389,6 +9335,21 @@ To clear the carry, direction, or interrupt flags, use the \c{CLC},
\c{CLD} and \c{CLI} instructions (\k{insCLC}). To invert the carry
flag, use \c{CMC} (\k{insCMC}).
+
+\H{insSTMXCSR} \i\c{STMXCSR}: Store Streaming SIMD Extension
+ Control/Status
+
+\c STMXCSR memory ; 0F,AE,/3 [KATMAI,SSE,SD]
+
+\c{STMXCSR} The MXCSR control/status register is used to enable
+ masked/unmasked exception handling, to set rounding modes,
+ to set flush-to-zero mode, and to view exception status flags.
+ Refer to LDMXCSR for a description of the format of MXCSR.
+ The linear address corresponds to the address of the
+ least-significant byte of the referenced memory data.
+ The reserved bits in the MXCSR are stored as zeroes.
+
+
\H{insSTOSB} \i\c{STOSB}, \i\c{STOSW}, \i\c{STOSD}: Store Byte to String
\c STOSB ; AA [8086]
@@ -8457,6 +9418,24 @@ sign-extended to the length of the first operand. In these cases,
the \c{BYTE} qualifier is necessary to force NASM to generate this
form of the instruction.
+\H{insSUBPS} \i\c{SUBPS}: Packed Single-FP Subtract
+
+\c SUBPS xmmreg,memory ; 0F,5C,/r [KATMAI,SSE]
+\c SUBPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{SUBPS}T he SUBPS instruction subtracts the packed SP FP
+ numbers of both their operands.
+
+
+\H{insSUBSS} \i\c{SUBSS}: Scalar Single-FP Subtract
+
+\c SUBSS xmmreg,memory ; F3,0F,5C, /r [KATMAI,SSE]
+\c SUBSS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{SUBSS} The SUBSS instruction subtracts the lower SP FP
+ numbers of both their operands.
+
+
\H{insTEST} \i\c{TEST}: Test Bits (notional bitwise AND)
\c TEST r/m8,reg8 ; 84 /r [8086]
@@ -8475,6 +9454,19 @@ form of the instruction.
affects the flags as if the operation had taken place, but does not
store the result of the operation anywhere.
+\H{insUCOMISS} \i\c{UCOMISS}: Unordered Scalar Single-FP compare
+ and set EFLAGS
+
+\c UCOMISS xmmreg,memory ; 0F,2E,/r [KATMAI,SSE]
+\c UCOMISS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{UCOMISS} The UCOMISS instructions compare the two lowest scalar
+ SP FP numbers, and set the ZF,PF,CF bits in the EFLAGS register
+ as described above. In addition, the OF, SF, and AF bits in the
+ EFLAGS register are zeroed out. The unordered predicate is
+ returned if either source operand is a NaN (qNaN or sNaN).
+
+
\H{insUMOV} \i\c{UMOV}: User Move Data
\c UMOV r/m8,reg8 ; 0F 10 /r [386,UNDOC]
@@ -8490,6 +9482,27 @@ access user memory (as opposed to host memory). It is used just like
an ordinary memory/register or register/register \c{MOV}
instruction, but accesses user space.
+
+\H{insUNPCKHPS} \i\c{UNPCKHPS}: Unpack High Packed Single-FP Data
+
+\c UNPCKHPS xmmreg,memory ; 0F,15,/r [KATMAI,SSE]
+\c UNPCKHPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{UNPCKHPS} The UNPCKHPS instruction performs an interleaved
+ unpack of the high-order data elements of XMM1 and XMM2/Mem.
+ It ignores the lower half of the sources.
+
+
+\H{insUNPCKLPS} \i\c{UNPCKLPS}: Unpack Low Packed Single-FP Data
+
+\c UNPCKLPS xmmreg,memory ; 0F,14,/r [KATMAI,SSE]
+\c UNPCKLPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{UNPCKLPS} The UNPCKLPS instruction performs an interleaved
+ unpack of the low-order data elements of XMM1 and XMM2/Mem.
+ It ignores the upper half part of the sources.
+
+
\H{insVERR} \i\c{VERR}, \i\c{VERW}: Verify Segment Readability/Writability
\c VERR r/m16 ; 0F 00 /4 [286,PRIV]
@@ -8629,3 +9642,12 @@ form of the instruction.
The MMX instruction \c{PXOR} (see \k{insPXOR}) performs the same
operation on the 64-bit MMX registers.
+
+
+\H{insXORPS} \i\c{XORPS}: Bit-wise Logical Xor for Single-FP Data
+
+\c XORPS xmmreg,memory ; 0F,57,/r [KATMAI,SSE]
+\c XORPS xmmreg,xmmreg ; ?? [KATMAI,SSE]
+
+\c{XORPS} The XORPS instruction returns a bit-wise logical XOR
+ between XMM1 and XMM2/Mem.
diff --git a/doc/rdsrc.pl b/doc/rdsrc.pl
index 38044b16..b174dd29 100644
--- a/doc/rdsrc.pl
+++ b/doc/rdsrc.pl
@@ -5,11 +5,6 @@
# TODO:
#
-# PS output:
-# - show page numbers in printed output
-# - think about double-sided support (start all chapters on RHS,
-# ie odd-numbered, pages).
-#
# Ellipsis support would be nice.
# Source-form features:
@@ -1091,6 +1086,7 @@ sub write_ps {
# now) to the length of the current page. Also, _put_ this line on
# the current page, and allocate it a y-coordinate.
if ($ltypes[$i] =~ /^chap$/) {
+ $pnum += 1 - ($pnum & 1); # advance to odd numbered page if necessary
$plen = 100; # ADJUSTABLE: space taken up by a chapter heading
$ycoord[$i] = 0; # chapter heading: y-coord doesn't matter
} else {
@@ -1234,7 +1230,7 @@ sub write_ps {
last PAGE if $i > $#psindex;
}
}
- &ps_trailer;
+ &ps_trailer($page);
close PS;
select STDOUT;
}
@@ -1263,6 +1259,10 @@ sub ps_header {
'/es /Helvetica-Oblique findfont 12 scalefont def',
'/cs /Courier-Bold findfont 12 scalefont def',
'/n 16#6E def /e 16#65 def /c 16#63 def',
+ '/pageodd {',
+ ' 550 50 moveto ns setfont dup stringwidth pop neg 0 rmoveto show',
+ '} def',
+ '/pageeven { 50 50 moveto ns setfont show } def',
'/chapter {',
' 100 620 moveto',
' {',
@@ -1383,14 +1383,18 @@ sub ps_header {
}
sub ps_trailer {
- &ps_donepg;
+ my ($oldpg) = @_;
+ &ps_donepg($oldpg);
print "%%Trailer\nrestore\n%%EOF\n";
}
sub ps_throw_pg {
my ($oldpg, $newpg) = @_;
- &ps_donepg;
- &ps_initpg($newpg);
+ while ($oldpg < $newpg) {
+ &ps_donepg($oldpg);
+ $oldpg++;
+ &ps_initpg($oldpg);
+ }
}
sub ps_initpg {
@@ -1400,7 +1404,12 @@ sub ps_initpg {
}
sub ps_donepg {
- print "%%PageTrailer\nrestore showpage\n";
+ my ($pgnum) = @_;
+ if ($pgnum & 1) {
+ print "%%PageTrailer\n($pgnum)pageodd restore showpage\n";
+ } else {
+ print "%%PageTrailer\n($pgnum)pageeven restore showpage\n";
+ }
}
sub ps_out_line {
@@ -1516,7 +1525,7 @@ sub write_texi {
select TEXT;
# Preamble.
- print "\input texinfo \@c -*-texinfo-*-\n";
+ print "\\input texinfo \@c -*-texinfo-*-\n";
print "\@c \%**start of header\n";
print "\@setfilename nasm.info\n";
print "\@dircategory Programming\n";
@@ -1550,7 +1559,7 @@ sub write_texi {
print "\@end titlepage\n";
print "\n";
print "\@node Top, $tstruct_next{'Top'}, (dir), (dir)\n";
- print "\@top\n";
+ print "\@top Netwide Assembler\n";
print "\n";
print "\@ifinfo\n";
print "This file documents NASM, the Netwide Assembler: an assembler\n";
@@ -1606,7 +1615,9 @@ sub write_texi {
$title .= $ww unless $ww eq "\001";
}
print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
- print " $tstruct_up{$node}\n\@unnumbered $title\n";
+ print " $tstruct_up{$node}\n";
+ $hdr = ($ptype eq "subh" ? "\@unnumberedsubsec" : "\@unnumberedsec");
+ print "$hdr $title\n";
} elsif ($ptype eq "code") {
# Code paragraph. Surround with @example / @end example.
print "\@example\n";
diff --git a/insns.dat b/insns.dat
index 08bb7116..cc678c5c 100644
--- a/insns.dat
+++ b/insns.dat
@@ -291,6 +291,7 @@ FDIVRP fpureg,fpu0 \1\xDE\10\xF0 8086,FPU
FEMMS void \2\x0F\x0E PENT,3DNOW
FENI void \3\x9B\xDB\xE0 8086,FPU
FFREE fpureg \1\xDD\10\xC0 8086,FPU
+FFREEP fpureg \1\xDF\10\xC0 P6,FPU,UNDOC
FIADD mem32 \300\1\xDA\200 8086,FPU
FIADD mem16 \300\1\xDE\200 8086,FPU
FICOM mem32 \300\1\xDA\202 8086,FPU
@@ -459,8 +460,8 @@ INVLPG mem \300\2\x0F\x01\207 486,PRIV
IRET void \322\1\xCF 8086
IRETD void \321\1\xCF 386
IRETW void \320\1\xCF 8086
-JCXZ imm \320\1\xE3\50 8086
-JECXZ imm \321\1\xE3\50 386
+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 \322\1\xE9\64 8086
@@ -887,9 +888,10 @@ 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\101 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
SAL rm8,unity \300\1\xD0\204 8086,ND
SAL rm8,reg_cl \300\1\xD2\204 8086,ND
@@ -1062,6 +1064,7 @@ VERW mem \300\1\x0F\17\205 286,PROT
VERW mem16 \300\1\x0F\17\205 286,PROT
VERW reg16 \300\1\x0F\17\205 286,PROT
WAIT void \1\x9B 8086
+FWAIT void \1\x9B 8086
WBINVD void \2\x0F\x09 486,PRIV
WRSHR void \2\x0F\x37 P6,CYRIX,SMM
WRMSR void \2\x0F\x30 PENT,PRIV
@@ -1143,7 +1146,7 @@ ANDPS xmmreg,mem \301\2\x0F\x54\110 KATMAI,S
ANDPS xmmreg,xmmreg \2\x0F\x54\110 KATMAI,SSE
CMPEQPS xmmreg,mem \301\331\2\x0F\xC2\110\1\x00 KATMAI,SSE
CMPEQPS xmmreg,xmmreg \331\2\x0F\xC2\110\1\x00 KATMAI,SSE
-CMPEQSS xmmreg,mem \301\333\2\x0F\xC2\110\1\0x00 KATMAI,SSE
+CMPEQSS xmmreg,mem \301\333\2\x0F\xC2\110\1\x00 KATMAI,SSE
CMPEQSS xmmreg,xmmreg \333\2\x0F\xC2\110\1\x00 KATMAI,SSE
CMPLEPS xmmreg,mem \301\331\2\x0F\xC2\110\1\x02 KATMAI,SSE
CMPLEPS xmmreg,xmmreg \331\2\x0F\xC2\110\1\x02 KATMAI,SSE
@@ -1303,3 +1306,279 @@ 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
+
+; 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 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
diff --git a/insns.h b/insns.h
index 294dd271..21358461 100644
--- a/insns.h
+++ b/insns.h
@@ -62,6 +62,7 @@ struct itemplate {
#define IF_MMX 0x00004000UL /* it's an MMX instruction */
#define IF_3DNOW 0x00008000UL /* it's a 3DNow! instruction */
#define IF_SSE 0x00010000UL /* it's a SSE (KNI, MMX2) instruction */
+#define IF_SSE2 0x00020000UL /* it's a SSE2 instruction */
#define IF_PMASK 0xFF000000UL /* the mask for processor types */
#define IF_PLEVEL 0x0F000000UL /* the mask for processor instr. level */
/* also the highest possible processor */
@@ -74,6 +75,7 @@ struct itemplate {
#define IF_PENT 0x05000000UL /* Pentium instruction */
#define IF_P6 0x06000000UL /* P6 instruction */
#define IF_KATMAI 0x07000000UL /* Katmai instructions */
+#define IF_WILLAMETTE 0x08000000UL /* Willamette instructions */
#define IF_CYRIX 0x10000000UL /* Cyrix-specific instruction */
#define IF_AMD 0x20000000UL /* AMD-specific instruction */
diff --git a/labels.c b/labels.c
index c47d34c4..f1378478 100644
--- a/labels.c
+++ b/labels.c
@@ -15,8 +15,24 @@
/*
* A local label is one that begins with exactly one period. Things
* that begin with _two_ periods are NASM-specific things.
+ *
+ * If TASM compatibility is enabled, a local label can also begin with
+ * @@, 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] != '.') : \
+ ((l)[0] == '.' && (l)[1] != '.'))
+#define islocalchar(c) \
+ (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))
@@ -71,6 +87,9 @@ static char *prevlabel;
static int initialised = FALSE;
+char lprefix[PREFIX_MAX] = {0};
+char lpostfix[PREFIX_MAX] = {0};
+
/*
* Internal routine: finds the `union label' corresponding to the
* given label name. Creates a new one, if it isn't found, and if
@@ -160,7 +179,8 @@ void redefine_label (char *label, long segment, long offset, char *special,
int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
{
union label *lptr;
-
+ int exi;
+
/* This routine possibly ought to check for phase errors. Most assemblers
* check for phase errors at this point. I don't know whether phase errors
* are even possible, nor whether they are checked somewhere else
@@ -185,18 +205,50 @@ void redefine_label (char *label, long segment, long offset, char *special,
error (ERR_PANIC, "can't find label `%s' on pass two", label);
if (!islocal(label)) {
- if (*label != '.' && lptr->defn.is_norm)
+ if (!islocalchar(*label) && lptr->defn.is_norm)
prevlabel = lptr->defn.label;
}
global_offset_changed |= (lptr->defn.offset != offset);
lptr->defn.offset = offset;
+
+if (pass0 == 1) {
+ exi = !!(lptr->defn.is_global & GLOBAL_BIT);
+ if (exi)
+ {
+ char *xsymbol;
+ int slen;
+ slen = strlen(lprefix);
+ slen += strlen(lptr->defn.label);
+ slen += strlen(lpostfix);
+ slen++; /* room for that null char */
+ xsymbol = nasm_malloc(slen);
+ sprintf(xsymbol,"%s%s%s",lprefix,lptr->defn.label,lpostfix);
+
+ ofmt->symdef (xsymbol, segment, offset, exi,
+ special ? special : lptr->defn.special);
+ ofmt->current_dfmt->debug_deflabel (xsymbol, segment, offset, exi,
+ special ? special : lptr->defn.special);
+/** nasm_free(xsymbol); ! outobj.c stores the pointer; ouch!!! **/
+ }
+ else
+ {
+ if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
+ ofmt->symdef (lptr->defn.label, segment, offset, exi,
+ special ? special : lptr->defn.special);
+ ofmt->current_dfmt->debug_deflabel (label, segment, offset, exi,
+ special ? special : lptr->defn.special);
+ }
+ }
+} /* if (pass0 == 1) */
+
}
void define_label (char *label, long segment, long offset, char *special,
int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
{
union label *lptr;
+ int exi;
#ifdef DEBUG
#if DEBUG<3
@@ -212,26 +264,48 @@ void define_label (char *label, long segment, long offset, char *special,
}
lptr->defn.is_global |= DEFINED_BIT;
if (isextrn)
- lptr->defn.is_global |= EXTERN_BIT;
+ lptr->defn.is_global |= EXTERN_BIT;
- if (label[0] != '.' && is_norm) /* not local, but not special either */
- prevlabel = lptr->defn.label;
- else if (label[0] == '.' && label[1] != '.' && !*prevlabel)
- error(ERR_NONFATAL, "attempt to define a local label before any"
- " non-local labels");
+ if (!islocalchar(label[0]) && is_norm) /* not local, but not special either */
+ prevlabel = lptr->defn.label;
+ else if (islocal(label) && !*prevlabel) {
+ error(ERR_NONFATAL, "attempt to define a local label before any"
+ " non-local labels");
+ }
lptr->defn.segment = segment;
lptr->defn.offset = offset;
- lptr->defn.is_norm = (label[0] != '.' && is_norm);
-
- if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
- ofmt->symdef (lptr->defn.label, segment, offset,
- !!(lptr->defn.is_global & GLOBAL_BIT),
- special ? special : lptr->defn.special);
- ofmt->current_dfmt->debug_deflabel (label, segment, offset,
- !!(lptr->defn.is_global & GLOBAL_BIT),
- special ? special : lptr->defn.special);
+ lptr->defn.is_norm = (!islocalchar(label[0]) && is_norm);
+
+if (pass0 == 1 || (!is_norm && !isextrn && (segment&1))) {
+ exi = !!(lptr->defn.is_global & GLOBAL_BIT);
+ if (exi)
+ {
+ char *xsymbol;
+ int slen;
+ slen = strlen(lprefix);
+ slen += strlen(lptr->defn.label);
+ slen += strlen(lpostfix);
+ slen++; /* room for that null char */
+ xsymbol = nasm_malloc(slen);
+ sprintf(xsymbol,"%s%s%s",lprefix,lptr->defn.label,lpostfix);
+
+ ofmt->symdef (xsymbol, segment, offset, exi,
+ special ? special : lptr->defn.special);
+ ofmt->current_dfmt->debug_deflabel (xsymbol, segment, offset, exi,
+ special ? special : lptr->defn.special);
+/** nasm_free(xsymbol); ! outobj.c stores the pointer; ouch!!! **/
+ }
+ else
+ {
+ if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
+ ofmt->symdef (lptr->defn.label, segment, offset, exi,
+ special ? special : lptr->defn.special);
+ ofmt->current_dfmt->debug_deflabel (label, segment, offset, exi,
+ special ? special : lptr->defn.special);
+ }
}
+} /* if (pass0 == 1) */
}
void define_common (char *label, long segment, long size, char *special,
@@ -246,7 +320,7 @@ void define_common (char *label, long segment, long size, char *special,
}
lptr->defn.is_global |= DEFINED_BIT;
- if (label[0] != '.') /* not local, but not special either */
+ if (!islocalchar(label[0])) /* not local, but not special either */
prevlabel = lptr->defn.label;
else
error(ERR_NONFATAL, "attempt to define a local label as a "
diff --git a/labels.h b/labels.h
index b78c8564..11c55194 100644
--- a/labels.h
+++ b/labels.h
@@ -6,6 +6,9 @@
* distributed in the NASM archive.
*/
+extern char lprefix[PREFIX_MAX];
+extern char lpostfix[PREFIX_MAX];
+
int lookup_label (char *label, long *segment, long *offset);
int is_extern (char *label);
void define_label (char *label, long segment, long offset, char *special,
diff --git a/listing.c b/listing.c
index af8a9bf8..570e7fb8 100644
--- a/listing.c
+++ b/listing.c
@@ -124,7 +124,7 @@ static void list_output (long offset, void *data, unsigned long type)
{
long typ, size;
- if (!listp || suppress)
+ if (!listp || suppress || user_nolist) /* fbk - 9/2/00 */
return;
typ = type & OUT_TYPMASK;
@@ -201,6 +201,10 @@ static void list_line (int type, char *line)
{
if (!listp)
return;
+ if (user_nolist){ /* fbk - 9/2/00 */
+ listlineno++;
+ return;
+ }
if (mistack && mistack->inhibiting)
{
diff --git a/listing.h b/listing.h
index c3ac153f..55db4f90 100644
--- a/listing.h
+++ b/listing.h
@@ -10,5 +10,6 @@
#define NASM_LISTING_H
extern ListGen nasmlist;
+extern int user_nolist; /* fbk - 9/1/00 */
#endif
diff --git a/macros.c b/macros.c
index 8a47c808..ed70a75e 100644
--- a/macros.c
+++ b/macros.c
@@ -57,12 +57,6 @@ static char *stdmac[] = {
"%imacro bits 1+.nolist",
"[bits %1]",
"%endmacro",
- "%imacro use16 0.nolist",
- "[bits 16]",
- "%endmacro",
- "%imacro use32 0.nolist",
- "[bits 32]",
- "%endmacro",
"%imacro global 1-*.nolist",
"%rep %0",
"[global %1]",
@@ -75,8 +69,5 @@ static char *stdmac[] = {
"%rotate 1",
"%endrep",
"%endmacro",
- "%imacro cpu 1+.nolist",
- "[cpu %1]",
- "%endmacro",
NULL
};
diff --git a/nasm.c b/nasm.c
index 841640cd..1123ee30 100644
--- a/nasm.c
+++ b/nasm.c
@@ -38,18 +38,21 @@ static void register_output_formats(void);
static void usage(void);
static int using_debug_info;
+#ifdef TASM_COMPAT
+int tasm_compatible_mode = FALSE;
+#endif
static char inname[FILENAME_MAX];
static char outname[FILENAME_MAX];
static char listname[FILENAME_MAX];
static int globallineno; /* for forward-reference tracking */
-static int pass = 0;
+/* static int pass = 0; */
static struct ofmt *ofmt = NULL;
static FILE *error_file; /* Where to write error messages */
static FILE *ofile = NULL;
-static int optimizing = 10; /* number of optimization passes to take */
+static int optimizing = 0; /* number of optimization passes to take */
static int sb, cmd_sb = 16; /* by default */
static unsigned long cmd_cpu = IF_PLEVEL; /* highest level by default */
static unsigned long cpu = IF_PLEVEL; /* passed to insn_size & assemble.c */
@@ -73,8 +76,6 @@ enum op_type {
};
static enum op_type operating_mode;
-/* used by error function to report location */
-
/*
* Which of the suppressible warnings are suppressed. Entry zero
* doesn't do anything. Initial defaults are given here.
@@ -128,6 +129,7 @@ static Preproc no_pp = {
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)
{
@@ -140,6 +142,7 @@ static void nasm_fputs(char *line, FILE *ofile)
int main(int argc, char **argv)
{
+ pass0 = 1;
want_usage = terminate_after_phase = FALSE;
nasm_set_malloc_error (report_error);
@@ -184,7 +187,7 @@ int main(int argc, char **argv)
if (outname[0] == '\0')
ofmt->filename (inname, outname, report_error);
ofile = NULL;
- printf("%s: %s", outname, inname);
+ fprintf(stdout, "%s: %s", outname, inname);
while ( (line = preproc->getline()) )
nasm_free (line);
preproc->cleanup();
@@ -209,7 +212,7 @@ int main(int argc, char **argv)
location.known = FALSE;
- pass = 1;
+/* pass = 1; */
preproc->reset (inname, 2, report_error, evaluate, &nasmlist);
while ( (line = preproc->getline()) ) {
/*
@@ -326,6 +329,22 @@ static char *get_param (char *p, char *q, int *advance)
return NULL;
}
+struct textargs
+{
+ char *label;
+ int value;
+};
+
+#define OPT_PREFIX 0
+#define OPT_POSTFIX 1
+struct textargs textopts[] =
+{
+ {"prefix",OPT_PREFIX},
+ {"postfix",OPT_POSTFIX},
+ {NULL,0}
+};
+
+
int stopoptions = 0;
static int process_arg (char *p, char *q)
{
@@ -338,9 +357,6 @@ static int process_arg (char *p, char *q)
if (p[0]=='-' && ! stopoptions)
{
switch (p[1]) {
- case '-': /* -- => stop processing options */
- stopoptions = 1;
- break;
case 's':
error_file = stdout;
break;
@@ -370,7 +386,7 @@ static int process_arg (char *p, char *q)
ofmt->current_dfmt = ofmt->debug_formats[0];
} else if (p[1]=='O') { /* Optimization level */
if (!isdigit(*param)) report_error(ERR_FATAL,
- "command line optimization level must be 0..3");
+ "command line optimization level must be 0..3 or <nn>");
optimizing = atoi(param);
if (optimizing <= 0) optimizing = 0;
else if (optimizing <= 3) optimizing *= 5; /* 5 passes for each level */
@@ -385,7 +401,7 @@ static int process_arg (char *p, char *q)
} else if (p[1]=='l') { /* listing file */
strcpy (listname, param);
} else if (p[1]=='E') { /* error messages file */
- error_file = fopen(param, "wt");
+ error_file = fopen(param, "w");
if ( !error_file ) {
error_file = stderr; /* Revert to default! */
report_error (ERR_FATAL | ERR_NOFILE | ERR_USAGE,
@@ -410,6 +426,10 @@ static int process_arg (char *p, char *q)
"[-l listfile]\n"
" [options...] [--] filename\n"
" or nasm -r for version info\n\n"
+#ifdef TASM_COMPAT
+ " -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"
@@ -448,8 +468,17 @@ 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
#ifdef DEBUG
printf("Compiled with -DDEBUG on " __DATE__ "\n");
#endif
@@ -479,6 +508,66 @@ static int process_arg (char *p, char *q)
case 'M':
operating_mode = op_depend;
break;
+
+ case '-':
+ {
+ int s;
+
+ if (p[2]==0) { /* -- => stop processing options */
+ stopoptions = 1;
+ break;
+ }
+ for(s=0; textopts[s].label; s++)
+ {
+ if(!nasm_stricmp(p+2, textopts[s].label))
+ {
+ break;
+ }
+ }
+
+ switch(s)
+ {
+
+ case OPT_PREFIX:
+ case OPT_POSTFIX:
+ {
+ if (!q)
+ {
+ report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
+ "option `--%s' requires an argument",
+ p+2);
+ break;
+ }
+ else
+ {
+ advance = 1, param = q;
+ }
+
+ if(s == OPT_PREFIX)
+ {
+ strncpy(lprefix,param,PREFIX_MAX-1);
+ lprefix[PREFIX_MAX-1]=0;
+ break;
+ }
+ if(s == OPT_POSTFIX)
+ {
+ strncpy(lpostfix,param,POSTFIX_MAX-1);
+ lpostfix[POSTFIX_MAX-1]=0;
+ break;
+ }
+ break;
+ }
+ default:
+ {
+ report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
+ "unrecognised option `--%s'",
+ p+2);
+ break;
+ }
+ }
+ break;
+ }
+
default:
if (!ofmt->setinfo(GI_SWITCH,&p))
report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
@@ -562,11 +651,41 @@ static void process_respfile (FILE *rfile)
}
}
+/* Function to process args from a string of args, rather than the
+ * 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 = ' ';
+
+ p = args;
+ if (*p && *p != '-')
+ separator = *p++;
+ arg = NULL;
+ 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
+
static void parse_cmdline(int argc, char **argv)
{
FILE *rfile;
- char *envreal, *envcopy=NULL, *p, *q, *arg, *prevarg;
+ char *envreal, *envcopy=NULL, *p, *arg;
+#ifndef TASM_COMPAT
+ char *q, *prevarg;
char separator = ' ';
+#endif
*inname = *outname = *listname = '\0';
@@ -577,6 +696,9 @@ 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++;
@@ -591,6 +713,7 @@ static void parse_cmdline(int argc, char **argv)
}
if (arg)
process_arg (arg, NULL);
+#endif
nasm_free (envcopy);
}
@@ -601,6 +724,31 @@ 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
+ * to have multiple arguments on a single line, which is
+ * different to the -@resp file processing below for regular
+ * NASM.
+ */
+ char *str = malloc(2048);
+ FILE *f = fopen(&argv[0][1],"r");
+ if (!str) {
+ printf("out of memory");
+ exit(-1);
+ }
+ if (f) {
+ while (fgets(str,2048,f)) {
+ process_args(str);
+ }
+ fclose(f);
+ }
+ free(str);
+ 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"))) {
@@ -629,7 +777,7 @@ static void assemble_file (char *fname)
long seg, offs;
struct tokenval tokval;
expr * e;
- int pass_max;
+ int pass, pass_max;
int pass_cnt = 0; /* count actual passes */
if (cmd_sb == 32 && cmd_cpu < IF_386)
@@ -637,18 +785,21 @@ static void assemble_file (char *fname)
"32-bit segment size requires a higher cpu");
pass_max = optimizing + 2; /* passes 1, optimizing, then 2 */
- for (pass = 1; pass <= pass_max; pass++) {
+ pass0 = !optimizing; /* start at 1 if not optimizing */
+ for (pass = 1; pass <= pass_max && pass0 <= 2; pass++) {
int pass1, pass2;
ldfunc def_label;
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;
- if (pass == pass_max) {
+ if (pass0 == 2) {
if (*listname)
nasmlist.init(listname, report_error);
}
@@ -687,7 +838,8 @@ static void assemble_file (char *fname)
}
break;
case 2: /* [EXTERN label:special] */
- if (pass == pass_max) {
+ if (*value == '$') value++; /* skip initial $ if present */
+ if (pass0 == 2) {
q = value;
while (*q && *q != ':')
q++;
@@ -695,9 +847,7 @@ static void assemble_file (char *fname)
*q++ = '\0';
ofmt->symdef(value, 0L, 0L, 3, q);
}
- } else if (pass == 1) { /* pass == 1 */
- if (*value == '$')
- value++; /* skip initial $ if present */
+ } else if (pass0 == 1) { /* pass == 1 */
q = value;
validid = TRUE;
if (!isidstart(*q))
@@ -722,13 +872,14 @@ static void assemble_file (char *fname)
define_label (value, seg_alloc(), 0L, NULL, FALSE, TRUE,
ofmt, report_error);
}
- } /* else pass == 1 */
+ } /* else pass0 == 1 */
break;
case 3: /* [BITS bits] */
sb = get_bits(value);
break;
case 4: /* [GLOBAL symbol:special] */
- if (pass == pass_max) { /* pass 2 */
+ if (*value == '$') value++; /* skip initial $ if present */
+ if (pass0 == 2) { /* pass 2 */
q = value;
while (*q && *q != ':')
q++;
@@ -736,9 +887,7 @@ static void assemble_file (char *fname)
*q++ = '\0';
ofmt->symdef(value, 0L, 0L, 3, q);
}
- } else if (pass == 1) { /* pass == 1 */
- if (*value == '$')
- value++; /* skip initial $ if present */
+ } else if (pass2 == 1) { /* pass == 1 */
q = value;
validid = TRUE;
if (!isidstart(*q))
@@ -762,7 +911,8 @@ static void assemble_file (char *fname)
} /* pass == 1 */
break;
case 5: /* [COMMON symbol size:special] */
- if (pass == 1) {
+ if (*value == '$') value++; /* skip initial $ if present */
+ if (pass0 == 1) {
p = value;
validid = TRUE;
if (!isidstart(*p))
@@ -800,7 +950,7 @@ static void assemble_file (char *fname)
} else
report_error (ERR_NONFATAL, "no size specified in"
" COMMON declaration");
- } else if (pass == pass_max) { /* pass == 2 */
+ } else if (pass0 == 2) { /* pass == 2 */
q = value;
while (*q && *q != ':') {
if (isspace(*q))
@@ -821,7 +971,7 @@ static void assemble_file (char *fname)
NULL);
if (e) {
if (!is_reloc(e))
- report_error (pass==1 ? ERR_NONFATAL : ERR_PANIC,
+ report_error (pass0==1 ? ERR_NONFATAL : ERR_PANIC,
"cannot use non-relocatable expression as "
"ABSOLUTE address");
else {
@@ -878,17 +1028,32 @@ static void assemble_file (char *fname)
case 9: /* cpu */
cpu = get_cpu (value);
break;
+ case 10: /* fbk 9/2/00 */ /* [LIST {+|-}] */
+ while (*value && isspace(*value))
+ value++;
+
+ if (*value == '+') {
+ user_nolist = 0;
+ }
+ else {
+ if (*value == '-') {
+ user_nolist = 1;
+ }
+ else {
+ report_error (ERR_NONFATAL, "invalid parameter to \"list\" directive");
+ }
+ }
+ break;
default:
- if (!ofmt->directive (line+1, value, pass1))
+ if (!ofmt->directive (line+1, value, pass2))
report_error (pass1==1 ? ERR_NONFATAL : ERR_PANIC,
"unrecognised directive [%s]",
line+1);
- break;
}
}
else /* it isn't a directive */
{
- parse_line (pass2, line, &output_ins,
+ parse_line (pass1, line, &output_ins,
report_error, evaluate,
def_label);
@@ -1026,33 +1191,38 @@ static void assemble_file (char *fname)
} else { /* instruction isn't an EQU */
if (pass1 == 1) {
+
long l = insn_size (location.segment, offs, sb, cpu,
&output_ins, report_error);
- if (using_debug_info && output_ins.opcode != -1) {
+
+ /* if (using_debug_info) && output_ins.opcode != -1)*/
+ if (using_debug_info); /* fbk 12/29/00 */
+
+ {
/* 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;
- break;
+ typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_BYTE;
+ break;
case I_RESW:
- typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_WORD;
- break;
+ typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_WORD;
+ break;
case I_RESD:
- typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_DWORD;
- break;
+ typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_DWORD;
+ break;
case I_RESQ:
- typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_QWORD;
- break;
+ typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_QWORD;
+ break;
case I_REST:
- typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_TBYTE;
- break;
- case I_DB:
- typeinfo |= TY_BYTE;
- break;
+ typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_TBYTE;
+ break;
+ case I_DB:
+ typeinfo |= TY_BYTE;
+ break;
case I_DW:
- typeinfo |= TY_WORD;
- break;
+ typeinfo |= TY_WORD;
+ break;
case I_DD:
if (output_ins.eops_float)
typeinfo |= TY_FLOAT;
@@ -1062,13 +1232,16 @@ static void assemble_file (char *fname)
case I_DQ:
typeinfo |= TY_QWORD;
break;
- case I_DT:
+ case I_DT:
typeinfo |= TY_TBYTE;
break;
default:
typeinfo = TY_LABEL;
+
}
+
ofmt->current_dfmt->debug_typevalue(typeinfo);
+
}
if (l != -1) {
offs += l;
@@ -1104,13 +1277,17 @@ static void assemble_file (char *fname)
usage();
exit (1);
}
- pass_cnt++;
- if (pass>1 && !global_offset_changed && pass<pass_max) pass = pass_max-1;
+ pass_cnt++;
+ if (pass>1 && !global_offset_changed) {
+ pass0++;
+ if (pass0==2) pass = pass_max - 1;
+ } else if (!optimizing) pass0++;
+
} /* for (pass=1; pass<=2; pass++) */
nasmlist.cleanup();
#if 1
- if (optimizing)
+ if (optimizing && using_debug_info) /* -On and -g switches */
fprintf(error_file,
"info:: assembly required 1+%d+1 passes\n", pass_cnt-2);
#endif
@@ -1175,6 +1352,8 @@ static int getkw (char *buf, char **value)
return 8;
if (!nasm_stricmp(p, "cpu"))
return 9;
+ if (!nasm_stricmp(p, "list")) /* fbk 9/2/00 */
+ return 10;
return -1;
}
@@ -1193,7 +1372,7 @@ static void report_error (int severity, char *fmt, ...)
/*
* See if it's a pass-one only warning and we're not in pass one.
*/
- if ((severity & ERR_PASS1) && pass != 1)
+ if ((severity & ERR_PASS1) && pass0 == 2)
return;
if (severity & ERR_NOFILE)
@@ -1363,7 +1542,7 @@ static unsigned long get_cpu (char *value)
if (!nasm_stricmp(value, "p3") ||
!nasm_stricmp(value, "katmai") ) return IF_KATMAI;
- report_error (pass ? ERR_NONFATAL : ERR_FATAL, "unknown 'cpu' type");
+ report_error (pass0<2 ? ERR_NONFATAL : ERR_FATAL, "unknown 'cpu' type");
return IF_PLEVEL; /* the maximum level */
}
@@ -1381,7 +1560,7 @@ static int get_bits (char *value)
i = 16;
}
} else {
- report_error(pass ? ERR_NONFATAL : ERR_FATAL,
+ report_error(pass0<2 ? ERR_NONFATAL : ERR_FATAL,
"`%s' is not a valid segment size; must be 16 or 32",
value);
i = 16;
diff --git a/nasm.h b/nasm.h
index 75202aac..34ebacbf 100644
--- a/nasm.h
+++ b/nasm.h
@@ -13,7 +13,7 @@
#define NASM_MAJOR_VER 0
#define NASM_MINOR_VER 98
-#define NASM_VER "0.98.03"
+#define NASM_VER "0.98.08"
#ifndef NULL
#define NULL 0
@@ -33,6 +33,16 @@
#define FILENAME_MAX 256
#endif
+#ifndef PREFIX_MAX
+#define PREFIX_MAX 10
+#endif
+
+#ifndef POSTFIX_MAX
+#define POSTFIX_MAX 10
+#endif
+
+
+
/*
* Name pollution problems: <time.h> on Digital UNIX pulls in some
* strange hardware header file which sees fit to define R_SP. We
@@ -78,13 +88,15 @@ typedef void (*efunc) (int severity, char *fmt, ...);
/*
* These codes define specific types of suppressible warning.
*/
+
+#define ERR_WARN_MASK 0x0000FF00 /* the mask for this feature */
+#define ERR_WARN_SHR 8 /* how far to shift right */
+
#define ERR_WARN_MNP 0x00000100 /* macro-num-parameters warning */
#define ERR_WARN_MSR 0x00000200 /* macro self-reference */
#define ERR_WARN_OL 0x00000300 /* orphan label (no colon, and
* alone on line) */
#define ERR_WARN_NOV 0x00000400 /* numeric overflow */
-#define ERR_WARN_MASK 0x0000FF00 /* the mask for this feature */
-#define ERR_WARN_SHR 8 /* how far to shift right */
#define ERR_WARN_MAX 4 /* the highest numbered one */
/*
@@ -844,4 +856,18 @@ 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
+ * "pass0" assumes the values: 0, 0, ..., 0, 1, 2
+ * where 0 = optimizing pass
+ * 1 = pass 1
+ * 2 = pass 2
+ */
+
+int pass0; /* this is globally known */
+
#endif
diff --git a/outaout.c b/outaout.c
index b82109a9..22ac2296 100644
--- a/outaout.c
+++ b/outaout.c
@@ -341,6 +341,7 @@ static void aout_deflabel (char *name, long segment, long offset,
struct tokenval tokval;
expr *e;
int fwd = FALSE;
+ char *saveme=stdscan_bufptr; /* bugfix? fbk 8/10/00 */
if (!bsd) {
error(ERR_NONFATAL, "Linux a.out does not support"
@@ -369,6 +370,7 @@ static void aout_deflabel (char *name, long segment, long offset,
sym->size = reloc_value(e);
}
}
+ stdscan_bufptr=saveme; /* bugfix? fbk 8/10/00 */
}
special_used = TRUE;
}
diff --git a/outelf.c b/outelf.c
index 0b77c017..13a93ab3 100644
--- a/outelf.c
+++ b/outelf.c
@@ -346,6 +346,10 @@ static void elf_deflabel (char *name, long segment, long offset,
struct Symbol *sym;
int special_used = FALSE;
+#if defined(DEBUG) && DEBUG>2
+fprintf(stderr, " elf_deflabel: %s, seg=%ld, off=%ld, is_global=%d, %s\n",
+ name, segment, offset, is_global, special);
+#endif
if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
/*
* This is a NASM special symbol. We never allow it into
@@ -496,6 +500,7 @@ static void elf_deflabel (char *name, long segment, long offset,
struct tokenval tokval;
expr *e;
int fwd = FALSE;
+ char *saveme=stdscan_bufptr; /* bugfix? fbk 8/10/00 */
while (special[n] && isspace(special[n]))
n++;
@@ -518,6 +523,7 @@ static void elf_deflabel (char *name, long segment, long offset,
else
sym->size = reloc_value(e);
}
+ stdscan_bufptr=saveme; /* bugfix? fbk 8/10/00 */
}
special_used = TRUE;
}
diff --git a/outobj.c b/outobj.c
index f4619d9e..0490ba15 100644
--- a/outobj.c
+++ b/outobj.c
@@ -105,7 +105,8 @@ enum RecordID { /* record ID codes */
FIXUPP = 0x9C, /* fixups (relocations) */
FIXU32 = 0x9D, /* 32-bit fixups (relocations) */
- MODEND = 0x8A /* module end */
+ MODEND = 0x8A, /* module end */
+ MODE32 = 0x8B /* module end for 32-bit objects */
};
enum ComentID { /* ID codes for comment records */
@@ -142,6 +143,7 @@ static void ori_null(ObjRecord *orp);
static ObjRecord *obj_commit(ObjRecord *orp);
static int obj_uppercase; /* Flag: all names in uppercase */
+static int obj_use32; /* Flag: at least one segment is 32-bit */
/*
* Clear an ObjRecord structure. (Never reallocates).
@@ -590,6 +592,9 @@ static long obj_entry_seg, obj_entry_ofs;
struct ofmt of_obj;
+/* The current segment */
+static struct Segment *current_seg;
+
static long obj_segment (char *, int, int *);
static void obj_write_file(int debuginfo);
static int obj_directive (char *, char *, int);
@@ -620,7 +625,9 @@ static void obj_init (FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval)
grptail = &grphead;
obj_entry_seg = NO_SEG;
obj_uppercase = FALSE;
+ obj_use32 = FALSE;
passtwo = 0;
+ current_seg = NULL;
of_obj.current_dfmt->init (&of_obj,NULL,fp,errfunc);
}
@@ -740,6 +747,11 @@ static void obj_deflabel (char *name, long segment,
int i;
int used_special = FALSE; /* have we used the special text? */
+#if defined(DEBUG) && DEBUG>2
+fprintf(stderr, " obj_deflabel: %s, seg=%ld, off=%ld, is_global=%d, %s\n",
+ name, segment, offset, is_global, special);
+#endif
+
/*
* If it's a special-retry from pass two, discard it.
*/
@@ -829,7 +841,17 @@ static void obj_deflabel (char *name, long segment,
ext->next = NULL;
exttail = &ext->next;
ext->name = name;
+ /* Place by default all externs into the current segment */
ext->defwrt_type = DEFWRT_NONE;
+ if (current_seg) {
+ if (current_seg->grp) {
+ ext->defwrt_type = DEFWRT_GROUP;
+ ext->defwrt_ptr.grp = current_seg->grp;
+ } else {
+ ext->defwrt_type = DEFWRT_SEGMENT;
+ ext->defwrt_ptr.seg = current_seg;
+ }
+ }
if (is_global == 2) {
ext->commonsize = offset;
ext->commonelem = 1; /* default FAR */
@@ -1088,7 +1110,7 @@ static void obj_write_fixup (ObjRecord *orp, int bytes,
if (segto->use32)
forp->type = FIXU32;
else
- forp->type = FIXUPP;
+ forp->type = FIXUPP;
}
if (seg % 2) {
@@ -1224,8 +1246,13 @@ static long obj_segment (char *name, int pass, int *bits)
* using the pointer it gets passed. That way we save memory,
* by sponging off the label manager.
*/
+#if defined(DEBUG) && DEBUG>=3
+fprintf(stderr," obj_segment: < %s >, pass=%d, *bits=%d\n",
+ name, pass, *bits);
+#endif
if (!name) {
*bits = 16;
+ current_seg = NULL;
return first_seg;
} else {
struct Segment *seg;
@@ -1271,6 +1298,7 @@ static long obj_segment (char *name, int pass, int *bits)
*bits = 32;
else
*bits = 16;
+ current_seg = seg;
return seg->index;
}
}
@@ -1398,6 +1426,9 @@ static long obj_segment (char *name, int pass, int *bits)
}
}
+ /* We need to know whenever we have at least one 32-bit segment */
+ obj_use32 |= seg->use32;
+
obj_seg_needs_update = seg;
if (seg->align >= SEG_ABS)
deflabel (name, NO_SEG, seg->align - SEG_ABS,
@@ -1447,6 +1478,7 @@ static long obj_segment (char *name, int pass, int *bits)
*bits = 32;
else
*bits = 16;
+ current_seg = seg;
return seg->index;
}
}
@@ -2178,7 +2210,7 @@ static void obj_write_file (int debuginfo)
}
}
if (orp->used)
- obj_emit (orp);
+ obj_emit (orp);
/*
* Write the LEDATA/FIXUPP pairs.
@@ -2191,9 +2223,10 @@ static void obj_write_file (int debuginfo)
/*
* Write the MODEND module end marker.
*/
- orp->type = MODEND;
+ orp->type = obj_use32 ? MODE32 : MODEND;
orp->ori = ori_null;
if (entry_seg_ptr) {
+ orp->type = entry_seg_ptr->use32 ? MODE32 : MODEND;
obj_byte (orp, 0xC1);
seg = entry_seg_ptr;
if (seg->grp) {
@@ -2324,7 +2357,8 @@ static void dbgbi_linnum (const char *lnfname, long lineno, long segto)
if (!seg)
error (ERR_PANIC, "lineno directed to nonexistent segment?");
- for (fn = fnhead; fn; fn = fnhead->next)
+/* for (fn = fnhead; fn; fn = fnhead->next) */
+ for (fn = fnhead; fn; fn = fn->next) /* fbk - Austin Lunnen - John Fine*/
if (!nasm_stricmp(lnfname,fn->name))
break;
if (!fn) {
diff --git a/outrdf2.c b/outrdf2.c
index 4ae6799b..be33643d 100644
--- a/outrdf2.c
+++ b/outrdf2.c
@@ -74,18 +74,18 @@ struct ExportRec {
char label[33]; /* zero terminated as above. max len = 32 chars */
};
-struct DLLRec {
- byte type; /* must be 4 */
- byte reclen; /* equals 1+library name */
- char libname[128]; /* name of library to link with at load time */
-};
-
struct BSSRec {
byte type; /* must be 5 */
- byte reclen; /* equeals 4 */
+ byte reclen; /* equals 4 */
long amount; /* number of bytes BSS to reserve */
};
+struct DLLModRec {
+ byte type; /* 4 for DLLRec, 8 for ModRec */
+ byte reclen; /* 1+lib name length for DLLRec, 1+mod name length */
+ char name[128]; /* library to link at load time or module name */
+};
+
#define COUNT_SEGTYPES 9
static char * segmenttypes[COUNT_SEGTYPES] = {
@@ -321,11 +321,14 @@ static void write_bss_rec(struct BSSRec *r)
headerlength += r->reclen + 2;
}
-static void write_dll_rec(struct DLLRec *r)
+/*
+ * Write library record. Also used for module name records.
+ */
+static void write_dllmod_rec(struct DLLModRec *r)
{
saa_wbytes(header,&r->type,1);
saa_wbytes(header,&r->reclen,1);
- saa_wbytes(header,r->libname,strlen(r->libname) + 1);
+ saa_wbytes(header,r->name,strlen(r->name) + 1);
headerlength += r->reclen + 2;
}
@@ -334,12 +337,11 @@ static void rdf2_deflabel(char *name, long segment, long offset,
{
struct ExportRec r;
struct ImportRec ri;
-#ifdef VERBOSE_WARNINGS
- static int warned_common = 0;
-#endif
static int farsym = 0;
static int i;
+ if (is_global != 1) return;
+
if (special) {
while(*special == ' ' || *special == '\t') special++;
@@ -358,16 +360,6 @@ static void rdf2_deflabel(char *name, long segment, long offset,
return;
}
- if (is_global == 2) {
-#ifdef VERBOSE_WARNINGS
- if (!warned_common) {
- error(ERR_WARNING,"common declarations not supported: using extern");
- warned_common = 1;
- }
-#endif
- is_global = 1;
- }
-
for (i = 0; i < nsegments; i++) {
if (segments[i].segnumber == segment>>1) break;
}
@@ -635,13 +627,24 @@ static long rdf2_segbase (long segment) {
}
static int rdf2_directive (char *directive, char *value, int pass) {
- struct DLLRec r;
-
+ struct DLLModRec r;
+
if (! strcmp(directive, "library")) {
if (pass == 1) {
r.type = 4;
- strcpy(r.libname, value);
- write_dll_rec(&r);
+ r.reclen=strlen(value)+1;
+ strcpy(r.name, value);
+ write_dllmod_rec(&r);
+ }
+ return 1;
+ }
+
+ if (! strcmp(directive, "module")) {
+ if (pass == 1) {
+ r.type = 8;
+ r.reclen=strlen(value)+1;
+ strcpy(r.name, value);
+ write_dllmod_rec(&r);
}
return 1;
}
@@ -658,6 +661,9 @@ static char *rdf2_stdmac[] = {
"%imacro library 1+.nolist",
"[library %1]",
"%endmacro",
+ "%imacro module 1+.nolist",
+ "[module %1]",
+ "%endmacro",
"%macro __NASM_CDecl__ 1",
"%endmacro",
NULL
diff --git a/parser.c b/parser.c
index 0a85c9e1..385c2184 100644
--- a/parser.c
+++ b/parser.c
@@ -421,28 +421,68 @@ insn *parse_line (int pass, char *buffer, insn *result,
if (i == '[' || i == '&') { /* memory reference */
mref = TRUE;
bracket = (i == '[');
- i = stdscan(NULL, &tokval);
+ i = stdscan(NULL, &tokval);
if (i == TOKEN_SPECIAL) { /* check for address size override */
- switch ((int)tokval.t_integer) {
- case S_NOSPLIT:
- result->oprs[operand].eaflags |= EAF_TIMESTWO;
- break;
- case S_BYTE:
- result->oprs[operand].eaflags |= EAF_BYTEOFFS;
- break;
- case S_WORD:
- result->oprs[operand].addr_size = 16;
- result->oprs[operand].eaflags |= EAF_WORDOFFS;
- break;
- case S_DWORD:
- case S_LONG:
- result->oprs[operand].addr_size = 32;
- result->oprs[operand].eaflags |= EAF_WORDOFFS;
- break;
- default:
- error (ERR_NONFATAL, "invalid size specification in"
- " effective address");
+#ifdef TASM_COMPAT
+ if (tasm_compatible_mode) {
+ switch ((int)tokval.t_integer) {
+ /* For TASM compatibility a size override inside the
+ * brackets changes the size of the operand, not the
+ * address type of the operand as it does in standard
+ * NASM syntax. Hence:
+ *
+ * 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, but we never use anything
+ * but 32-bit flat model addressing in our code.
+ */
+ case S_BYTE:
+ result->oprs[operand].type |= BITS8;
+ break;
+ case S_WORD:
+ result->oprs[operand].type |= BITS16;
+ break;
+ case S_DWORD:
+ case S_LONG:
+ result->oprs[operand].type |= BITS32;
+ break;
+ case S_QWORD:
+ result->oprs[operand].type |= BITS64;
+ break;
+ case S_TWORD:
+ result->oprs[operand].type |= BITS80;
+ break;
+ default:
+ error (ERR_NONFATAL, "invalid operand size specification");
+ }
+ } else {
+#endif
+ /* Standard NASM compatible syntax */
+ switch ((int)tokval.t_integer) {
+ case S_NOSPLIT:
+ result->oprs[operand].eaflags |= EAF_TIMESTWO;
+ break;
+ case S_BYTE:
+ result->oprs[operand].eaflags |= EAF_BYTEOFFS;
+ break;
+ case S_WORD:
+ result->oprs[operand].addr_size = 16;
+ result->oprs[operand].eaflags |= EAF_WORDOFFS;
+ break;
+ case S_DWORD:
+ case S_LONG:
+ result->oprs[operand].addr_size = 32;
+ result->oprs[operand].eaflags |= EAF_WORDOFFS;
+ break;
+ default:
+ error (ERR_NONFATAL, "invalid size specification in"
+ " effective address");
+ }
+#ifdef TASM_COMPAT
}
+#endif
i = stdscan(NULL, &tokval);
}
} else { /* immediate operand, or register */
diff --git a/preproc.c b/preproc.c
index 5753cf2c..87c128f7 100644
--- a/preproc.c
+++ b/preproc.c
@@ -262,6 +262,9 @@ 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",
@@ -269,11 +272,21 @@ static char *directives[] = {
"%endrep", "%error", "%exitrep", "%iassign", "%idefine", "%if",
"%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifnctx",
"%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnnum",
- "%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include", "%ixdefine",
- "%line", "%macro", "%pop", "%push", "%rep", "%repl", "%rotate",
- "%undef", "%xdefine"
+ "%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"
};
enum {
+#ifdef TASM_COMPAT
+ 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,
@@ -281,11 +294,46 @@ enum {
PP_ENDREP, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF,
PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFNCTX,
PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNNUM,
- PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE, PP_IXDEFINE,
- PP_LINE, PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE,
- PP_UNDEF, PP_XDEFINE
+ 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
};
+#ifdef TASM_COMPAT
+
+/* For TASM compatibility we need to be able to recognise TASM compatible
+ * conditional compilation directives. Using the NASM pre-processor does
+ * not work, so we look for them specifically from the following list and
+ * then jam in the equivalent NASM directive into the input stream.
+ */
+
+#ifndef MAX
+# define MAX(a,b) ( ((a) > (b)) ? (a) : (b))
+#endif
+
+enum {
+ TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
+ TM_IFNDEF, TM_INCLUDE, TM_LOCAL
+};
+
+static char *tasm_directives[] = {
+ "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
+ "ifndef", "include", "local"
+};
+
+static int StackSize = 4;
+static char *StackPointer = "ebp";
+static int ArgOffset = 8;
+static int LocalOffset = 4;
+
+#endif
static Context *cstk;
static Include *istk;
@@ -351,7 +399,7 @@ 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 make_tok_num(Token *tok, long val);
static void error (int severity, char *fmt, ...);
/*
@@ -362,13 +410,72 @@ 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)
+{
+ int i, j, k, m, len;
+ char *p = line, *oldline, oldchar;
+
+ /* Skip whitespace */
+ while (isspace(*p) && *p != 0)
+ p++;
+
+ /* Binary search for the directive name */
+ i = -1;
+ j = sizeof(tasm_directives) / sizeof(*tasm_directives);
+ len = 0;
+ while (!isspace(p [len]) && p [len] != 0)
+ len++;
+ 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) {
+ /* 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;
+ len = strlen(p);
+ oldline = line;
+ line = nasm_malloc(len + 2);
+ 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 {
+ memcpy(line + 1, p, len + 1);
+ }
+ nasm_free(oldline);
+ return line;
+ } else if (m < 0) {
+ j = k;
+ } else
+ i = k;
+ }
+ p [len] = oldchar;
+ }
+ return line;
+}
+#endif
+
/*
* The pre-preprocessing stage... This function translates line
* number indications as they emerge from GNU cpp (`# lineno "file"
* 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;
@@ -385,6 +492,10 @@ static char *prepreproc(char *line)
sprintf(line, "%%line %d %.*s", lineno, fnlen, fname);
nasm_free (oldline);
}
+#ifdef TASM_COMPAT
+ if (tasm_compatible_mode)
+ return check_tasm_directive(line);
+#endif
return line;
}
@@ -639,7 +750,12 @@ static Token *tokenise (char *line)
type = TOK_STRING;
while (*p && *p != c)
p++;
- if (*p) p++;
+ if (*p) {
+ p++;
+ }
+ else {
+ error(ERR_WARNING, "unterminated string");
+ }
}
else if (isnumstart(*p)) {
/*
@@ -914,6 +1030,20 @@ static Context *get_ctx (char *name, int all_contexts)
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)
+{
+ int pos = strlen(s);
+ if (s[pos-1] != '\\' && s[pos-1] != '/') {
+ s[pos] = '/';
+ s[pos+1] = '\0';
+ }
+}
+#endif
+
/*
* Open an include file. This routine must always return a valid
* file pointer if it returns - it's responsible for throwing an
@@ -927,9 +1057,20 @@ static FILE *inc_fopen(char *file)
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);
+ 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)
{
@@ -1241,6 +1382,9 @@ void expand_macros_in_string (char **p)
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;
@@ -1324,6 +1468,201 @@ static int do_directive (Token *tline)
}
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.
+ */
+ 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);
+ 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;
+ }
+ tline = tline->next;
+ if (!tline || tline->type != TOK_ID) {
+ error (ERR_NONFATAL,"`%%arg' 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);
+
+ /* 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;
+ } 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);
+ do_directive(tokenise(directive));
+ offset += size;
+
+ /* Now define the assign to setup the enter_c macro correctly */
+ 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)
+ tline = tline->next;
+ } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
+ free_tlist (origline);
+ return 3;
+#endif
case PP_CLEAR:
if (tline->next)
@@ -1940,6 +2279,178 @@ static int do_directive (Token *tline)
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);
+ 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;
+
+ t = tline;
+ while (tok_type_(t, TOK_WHITESPACE))
+ t = t->next;
+ /* 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;
+
+ /*
+ * 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);
+ 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;
+
+ t = tline->next;
+ while (tok_type_(t, TOK_WHITESPACE))
+ t = t->next;
+
+ /* 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) {
+ free_tlist(tline);
+ free_tlist(origline);
+ return 3;
+ }
+ 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->text[1] = t->text[evalresult->value];
+ }
+ else {
+ macro_start->text[2] = '\0';
+ }
+ 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;
diff --git a/proc32.ash b/proc32.ash
new file mode 100644
index 00000000..f513b733
--- /dev/null
+++ b/proc32.ash
@@ -0,0 +1,441 @@
+;--------=========xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=========--------
+;
+; Copyright (C) 1999 by Andrew Zabolotny
+; Miscelaneous NASM macros that makes use of new preprocessor features
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Library General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Library General Public License for more details.
+;
+; You should have received a copy of the GNU Library General Public
+; License along with this library; if not, write to the Free
+; Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+;
+;--------=========xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=========--------
+
+; The macros in this file provides support for writing 32-bit C-callable
+; NASM routines. For a short description of every macros see the
+; corresponding comment before every one. Simple usage example:
+;
+; proc sin,1
+; targ %$angle
+; fld %$angle
+; fsin
+; endproc sin
+
+%ifndef __PROC32_ASH__
+%define __PROC32_ASH__
+
+[WARNING -macro-selfref]
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; Mangle a name to be compatible with the C compiler
+; Arguments:
+; The name
+; Example:
+; cname (my_func)
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%ifdef EXTERNC_UNDERSCORE
+ %define cname(x) _ %+ x
+%else
+ %define cname(x) x
+%endif
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; Import an external C procedure definition
+; Arguments:
+; The name of external C procedure
+; Example:
+; cextern printf
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%macro cextern 1
+ %xdefine %1 cname(%1)
+ %ifidni __OUTPUT_FORMAT__,obj
+ extern %1:wrt FLAT
+ %else
+ extern %1
+ %endif
+%endmacro
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; Export an C procedure definition
+; Arguments:
+; The name of C procedure
+; Example:
+; cglobal my_printf
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%macro cglobal 1
+ %xdefine %1 cname(%1)
+ global %1
+%endmacro
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; Misc macros to deal with PIC shared libraries
+; Comment:
+; Note that we have a different syntax for working with and without
+; PIC shared libraries. In a PIC environment we should load first
+; the address of the variable into a register and then work through
+; that address, i.e: mov eax,myvar; mov [eax],1
+; In a non-PIC environment we should directly write: mov myvar,1
+; Example:
+; extvar myvar
+; GetGOT
+; %ifdef PIC
+; mov ebx,myvar ; get offset of myvar into ebx
+; %else
+; lea ebx,myvar
+; %endif
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%ifdef PIC
+ cextern _GLOBAL_OFFSET_TABLE_
+ %macro GetGOT 0
+ %ifdef .$proc.stkofs
+ %assign .$proc.stkofs .$proc.stkofs+4
+ %endif
+ call %$Get_GOT
+ %$Get_GOT:
+ pop ebx
+ add ebx,_GLOBAL_OFFSET_TABLE_ + $$ - %$Get_GOT wrt ..gotpc
+ %endmacro
+ %macro extvar 1
+ cextern %1
+ %xdefine %1 [ebx+%1 wrt ..got]
+ %endmacro
+%else
+ %define GetGOT
+ %macro extvar 1
+ cextern %1
+ %endmacro
+%endif
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; Begin a procedure definition
+; For performance reasons we don't use stack frame pointer EBP,
+; instead we're using the [esp+xx] addressing. Because of this
+; you should be careful when you work with stack pointer.
+; The push/pop instructions are macros that are defined to
+; deal correctly with these issues.
+; Arguments:
+; First argument - the procedure name
+; Second optional argument - the number of bytes for local variables
+; The following arguments could specify the registers that should be
+; pushed at beginning of procedure and popped before exiting
+; Example:
+; proc MyTestProc
+; proc MyTestProc,4,ebx,esi,edi
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%macro proc 1-3+ 0
+ cglobal %1
+ %push %1
+ align 16
+%1:
+ %xdefine %$proc.name %1
+ ; total size of local arguments
+ %assign %$proc.locsize (%2+3) & 0xFFFC
+ ; offset from esp to argument
+ %assign %$proc.argofs 4+%$proc.locsize
+ ; additional offset to args (tracks push/pops)
+ %assign .$proc.stkofs 0
+ ; offset from esp to local arguments
+ %assign %$proc.locofs 0
+ ; Now push the registers that we should save
+ %define %$proc.save %3
+ %if %$proc.locsize != 0
+ sub esp,%$proc.locsize
+ %endif
+ push %$proc.save
+%endmacro
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; Declare an argument passed on stack
+; This macro defines two additional macros:
+; first (with the name given by first argument) - [esp+xx]
+; second (with a underscore appended to first argument) - esp+xx
+; Arguments:
+; First argument defines the procedure argument name
+; Second optional parameter defines the size of the argument
+; Default value is 4 (a double word)
+; Example:
+; arg .my_float
+; arg .my_double,8
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%macro arg 1-2 4
+ %ifndef %$proc.argofs
+ %error "`arg' not in a proc context"
+ %else
+ ; Trick: temporary undefine .$proc.stkofs so that it won't be expanded
+ %assign %%. .$proc.stkofs
+ %undef .$proc.stkofs
+ %xdefine %{1}_ esp+%$proc.argofs+.$proc.stkofs
+ %xdefine %1 [esp+%$proc.argofs+.$proc.stkofs]
+ %assign .$proc.stkofs %%.
+ %assign %$proc.argofs %2+%$proc.argofs
+ %endif
+%endmacro
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; Declare an local variable
+; first (with the name given by first argument) - [esp+xx]
+; second (with a slash prefixing the first argument) - esp+xx
+; Arguments:
+; First argument defines the procedure argument name
+; Second optional parameter defines the size of the argument
+; Default value is 4 (a double word)
+; Example:
+; loc .int_value
+; loc .double_value,8
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%macro loc 1-2 4
+ %ifndef %$proc.locofs
+ %error "`loc' not in a proc context"
+ %elif %$proc.locofs + %2 > %$proc.locsize
+ %error "local stack space exceeded"
+ %else
+ %assign %%. .$proc.stkofs
+ %undef .$proc.stkofs
+ %xdefine %{1}_ esp+%$proc.locofs+.$proc.stkofs
+ %xdefine %1 [esp+%$proc.locofs+.$proc.stkofs]
+ %assign .$proc.stkofs %%.
+ %assign %$proc.locofs %$proc.locofs+%2
+ %endif
+%endmacro
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; Get the type of given size into context-local variable %$type
+; Arguments:
+; Size of type we want (1,2,4,8 or 10)
+; Example:
+; type 4 ; gives "dword"
+; type 10 ; gives "tword"
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%macro type 1
+ %if %1 = 1
+ %define %$type byte
+ %elif %1 = 2
+ %define %$type word
+ %elif %1 = 4
+ %define %$type dword
+ %elif %1 = 8
+ %define %$type qword
+ %elif %1 = 10
+ %define %$type tword
+ %else
+ %define %$. %1
+ %error "unknown type for argument size %$."
+ %endif
+%endmacro
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; Same as `arg' but prepends "word", "dword" etc (typed arg)
+; first (with the name given by first argument) - dword [esp+xx]
+; second (with a slash prefixing the first argument) - esp+xx
+; Arguments:
+; Same as for `arg'
+; Example:
+; targ .my_float ; .my_float is now "dword [esp+xxx]"
+; targ .my_double,8 ; .my_double is now "qword [esp+xxx]"
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%macro targ 1-2 4
+ %ifndef %$proc.argofs
+ %error "`targ' not in a proc context"
+ %else
+ arg %1,%2
+ type %2
+ %assign %%. .$proc.stkofs
+ %undef .$proc.stkofs
+ %xdefine %1 %$type %1
+ %assign .$proc.stkofs %%.
+ %endif
+%endmacro
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; Same as `loc' but prepends "word", "dword" etc (typed loc)
+; first (with the name given by first argument) - dword [esp+xx]
+; second (with a slash prefixing the first argument) - esp+xx
+; Arguments:
+; Same as for `loc'
+; Example:
+; tloc int_value
+; tloc double_value,8
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%macro tloc 1-2 4
+ %ifndef %$proc.locofs
+ %error "`tloc' not in a proc context"
+ %else
+ loc %1,%2
+ type %2
+ %assign %%. .$proc.stkofs
+ %undef .$proc.stkofs
+ %xdefine %1 %$type %1
+ %assign .$proc.stkofs %%.
+ %endif
+%endmacro
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; Finish a procedure
+; Gives an error if proc/endproc pairs mismatch
+; Defines an label called __end_(procedure name)
+; which is useful for calculating function size
+; Arguments:
+; (optional) The name of procedure
+; Example:
+; endproc MyTestProc
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%push tmp ; trick: define a dummy context to avoid error in next line
+%macro endproc 0-1 %$proc.name
+ %ifndef %$proc.argofs
+ %error "`endproc' not in a proc context"
+ %elifnidn %$proc.name,%1
+ %define %$. %1
+ %error "endproc names mismatch: expected `%$proc.name'"
+ %error "but got `%$.' instead"
+ %elif %$proc.locofs < %$proc.locsize
+ %error "unused local space declared (used %$proc.locofs, requested %$proc.locsize)"
+ %else
+%$exit:
+ ; Now pop the registers that we should restore on exit
+ pop %$proc.save
+ %if %$proc.locsize != 0
+ add esp,%$proc.locsize
+ %endif
+ ret
+__end_%1:
+ %pop
+ %endif
+%endmacro
+%pop
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; A replacement for "push" for use within procedures
+; Arguments:
+; any number of registers which will be push'ed successively
+; Example:
+; push eax,ebx,ecx,edx
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%macro push 0-*
+; dummy comment to avoid problems with "push" on the same line with a label
+ %rep %0
+ push %1
+ %rotate 1
+ %assign .$proc.stkofs .$proc.stkofs+4
+ %endrep
+%endmacro
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; A replacement for "pop" for use within procedures
+; Arguments:
+; any number of registers which will be pop'ed in reverse order
+; Example:
+; pop eax,ebx,ecx,edx
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%macro pop 0-*
+; dummy comment to avoid problems with "pop" on the same line with a label
+ %rep %0
+ %rotate -1
+ pop %1
+ %assign .$proc.stkofs .$proc.stkofs-4
+ %endrep
+%endmacro
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; Replacements for "pushfd" and "popfd" that takes care of esp
+; Example:
+; pushfd
+; popfd
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%macro pushfd 0
+ pushfd
+ %assign .$proc.stkofs .$proc.stkofs+4
+%endmacro
+%macro popfd 0
+ popfd
+ %assign .$proc.stkofs .$proc.stkofs-4
+%endmacro
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; Exit from current procedure (optionally on given condition)
+; Arguments:
+; Either none or a condition code
+; Example:
+; exit
+; exit nz
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%macro exit 0-1 mp
+ j%1 near %$exit
+%endmacro
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; start an conditional branch
+; Arguments:
+; A condition code
+; second (optional) argument - "short" (by default - "near")
+; Example:
+; if nz
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%macro if 1-2 near
+; dummy comment to avoid problems with "if" on the same line with a label
+ %push if
+ j%-1 %2 %$elseif
+%endmacro
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; define the "else" branch of a conditional statement
+; Arguments:
+; optionaly: "short" if jmp to endif is less than 128 bytes away
+; Example:
+; else
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%macro else 0-1
+ %ifnctx if
+ %error "`else' without matching `if'"
+ %else
+ jmp %1 %$endif
+%$elseif:
+ %define %$elseif_defined
+ %endif
+%endmacro
+
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+; Summary:
+; Finish am conditional statement
+; Arguments:
+; none
+; Example:
+; endif
+;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
+%macro endif 0
+ %ifnctx if
+ %error "`endif' without matching `if'"
+ %else
+ %ifndef %$elseif_defined
+%$elseif:
+ %endif
+%$endif:
+ %pop
+ %endif
+%endmacro
+
+%endif ; __PROC32_ASH__
diff --git a/rdoff/Makefile.dj b/rdoff/Makefile.dj
new file mode 100644
index 00000000..20997395
--- /dev/null
+++ b/rdoff/Makefile.dj
@@ -0,0 +1,75 @@
+# Generated automatically from Makefile.in by configure.
+#
+# Auto-configuring Makefile for RDOFF object file utils; part of the
+# Netwide Assembler
+#
+# 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.
+
+# You may need to adjust these values.
+
+prefix = /djgpp
+CC = gcc -s
+CFLAGS = -O2 -I..
+
+# You _shouldn't_ need to adjust anything below this line.
+
+exec_prefix = ${prefix}
+bindir = ${exec_prefix}/bin
+mandir = ${prefix}/man
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+LN_S = ln -s
+
+LDRDFLIBS = rdoff.o ../nasmlib.o symtab.o hash.o collectn.o rdlib.o segtab.o
+RDXLIBS = rdoff.o rdfload.o symtab.o hash.o collectn.o
+
+.c.o:
+ $(CC) -c $(CFLAGS) $*.c
+
+all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+
+rdfdump: rdfdump.o
+ $(CC) -o rdfdump rdfdump.o
+
+ldrdf: ldrdf.o $(LDRDFLIBS)
+ $(CC) -o ldrdf ldrdf.o $(LDRDFLIBS)
+rdx: rdx.o $(RDXLIBS)
+ $(CC) -o rdx rdx.o $(RDXLIBS)
+rdflib: rdflib.o
+ $(CC) -o rdflib rdflib.o
+rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
+ $(CC) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
+rdf2com:
+ $(LN_S) rdf2bin rdf2com
+
+rdf2bin.o: rdf2bin.c
+rdfdump.o: rdfdump.c
+rdoff.o: rdoff.c rdoff.h
+ldrdf.o: ldrdf.c rdoff.h ../nasmlib.h symtab.h collectn.h rdlib.h
+symtab.o: symtab.c symtab.h hash.h
+collectn.o: collectn.c collectn.h
+rdx.o: rdx.c rdoff.h rdfload.h symtab.h
+rdfload.o: rdfload.c rdfload.h rdoff.h collectn.h symtab.h
+rdlib.o: rdlib.c rdlib.h
+rdflib.o: rdflib.c
+hash.o: hash.c hash.h
+segtab.o: segtab.c segtab.h
+
+nasmlib.o: ../nasmlib.c ../nasmlib.h ../names.c ../nasm.h
+ $(CC) -c $(CFLAGS) ../nasmlib.c
+
+clean:
+ rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+
+install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+ $(INSTALL_PROGRAM) rdfdump $(bindir)/rdfdump
+ $(INSTALL_PROGRAM) ldrdf $(bindir)/ldrdf
+ $(INSTALL_PROGRAM) rdx $(bindir)/rdx
+ $(INSTALL_PROGRAM) rdflib $(bindir)/rdflib
+ $(INSTALL_PROGRAM) rdf2bin $(bindir)/rdf2bin
+ cd $(bindir); $(LN_S) rdf2bin rdf2com
diff --git a/rdoff/Makefile.emx b/rdoff/Makefile.emx
new file mode 100644
index 00000000..fbaa934c
--- /dev/null
+++ b/rdoff/Makefile.emx
@@ -0,0 +1,76 @@
+# Generated automatically from Makefile.in by configure.
+# $Id$
+#
+# Auto-configuring Makefile for RDOFF object file utils; part of the
+# Netwide Assembler
+#
+# 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.
+
+top_srcdir = ..
+srcdir = .
+prefix = /usr/local
+exec_prefix = ${prefix}
+bindir = ${exec_prefix}/bin
+mandir = ${prefix}/man
+
+CC = gcc
+CFLAGS = -s -Zomf -O2 -fomit-frame-pointer -Wall -ansi -pedantic -I$(srcdir) -I$(top_srcdir)
+LDFLAGS = -s -Zomf -Zexe -Zcrtdll
+LIBS = -lgcc
+
+INSTALL = .././install-sh -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+
+LDRDFLIBS = rdoff.o nasmlib.o symtab.o collectn.o rdlib.o segtab.o hash.o
+RDXLIBS = rdoff.o rdfload.o symtab.o collectn.o hash.o
+
+.c.o:
+ $(CC) -c $(CFLAGS) -o $@ $<
+
+all: rdfdump ldrdf rdx rdflib rdf2bin
+
+rdfdump: rdfdump.o
+ $(CC) $(LDFLAGS) -o rdfdump rdfdump.o $(LIBS)
+ldrdf: ldrdf.o $(LDRDFLIBS)
+ $(CC) $(LDFLAGS) -o ldrdf ldrdf.o $(LDRDFLIBS) $(LIBS)
+rdx: rdx.o $(RDXLIBS)
+ $(CC) $(LDFLAGS) -o rdx rdx.o $(RDXLIBS) $(LIBS)
+rdflib: rdflib.o
+ $(CC) $(LDFLAGS) -o rdflib rdflib.o $(LIBS)
+rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
+ $(CC) $(LDFLAGS) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o $(LIBS)
+
+rdf2bin.o: rdf2bin.c
+rdfdump.o: rdfdump.c
+rdoff.o: rdoff.c rdoff.h
+ldrdf.o: ldrdf.c rdoff.h $(top_srcdir)/nasmlib.h symtab.h collectn.h rdlib.h
+symtab.o: symtab.c symtab.h
+collectn.o: collectn.c collectn.h
+rdx.o: rdx.c rdoff.h rdfload.h symtab.h
+rdfload.o: rdfload.c rdfload.h rdoff.h collectn.h symtab.h
+rdlib.o: rdlib.c rdlib.h
+rdflib.o: rdflib.c
+segtab.o: segtab.c
+
+nasmlib.o: $(top_srcdir)/nasmlib.c
+ $(CC) -c $(CFLAGS) -o $@ $(top_srcdir)/nasmlib.c
+
+clean:
+ rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+
+spotless: clean
+ rm -f Makefile
+
+distclean: spotless
+
+install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+ $(INSTALL_PROGRAM) rdfdump $(INSTALLROOT)$(bindir)/rdfdump
+ $(INSTALL_PROGRAM) ldrdf $(INSTALLROOT)$(bindir)/ldrdf
+ $(INSTALL_PROGRAM) rdx $(INSTALLROOT)$(bindir)/rdx
+ $(INSTALL_PROGRAM) rdflib $(INSTALLROOT)$(bindir)/rdflib
+ $(INSTALL_PROGRAM) rdf2bin $(INSTALLROOT)$(bindir)/rdf2bin
+ cd $(INSTALLROOT)$(bindir) && rm -f rdf2com && $(LN_S) rdf2bin rdf2com
diff --git a/rdoff/Makefile.in b/rdoff/Makefile.in
index 37cc1119..46efc0ac 100644
--- a/rdoff/Makefile.in
+++ b/rdoff/Makefile.in
@@ -29,9 +29,9 @@ LDRDFLIBS = rdoff.o nasmlib.o symtab.o collectn.o rdlib.o segtab.o hash.o
RDXLIBS = rdoff.o rdfload.o symtab.o collectn.o hash.o
.c.o:
- $(CC) -c $(CFLAGS) -o $@ $<
+ $(CC) -c $(CFLAGS) $<
-all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
rdfdump: rdfdump.o
$(CC) $(LDFLAGS) -o rdfdump rdfdump.o
@@ -45,7 +45,10 @@ rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
$(CC) $(LDFLAGS) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
rdf2com:
rm -f rdf2com && $(LN_S) rdf2bin rdf2com
+rdf2ihx: rdf2ihx.o $(RDXLIBS) nasmlib.o
+ $(CC) $(LDFLAGS) -o rdf2ihx rdf2ihx.o $(RDXLIBS) nasmlib.o
+rdf2ihx.o: rdf2ihx.c
rdf2bin.o: rdf2bin.c
rdfdump.o: rdfdump.c
rdoff.o: rdoff.c rdoff.h
@@ -62,17 +65,18 @@ nasmlib.o: $(top_srcdir)/nasmlib.c
$(CC) -c $(CFLAGS) $(top_srcdir)/nasmlib.c
clean:
- rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+ rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
spotless: clean
rm -f Makefile
distclean: spotless
-install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
$(INSTALL_PROGRAM) rdfdump $(INSTALLROOT)$(bindir)/rdfdump
$(INSTALL_PROGRAM) ldrdf $(INSTALLROOT)$(bindir)/ldrdf
$(INSTALL_PROGRAM) rdx $(INSTALLROOT)$(bindir)/rdx
$(INSTALL_PROGRAM) rdflib $(INSTALLROOT)$(bindir)/rdflib
$(INSTALL_PROGRAM) rdf2bin $(INSTALLROOT)$(bindir)/rdf2bin
+ $(INSTALL_PROGRAM) rdf2ihx $(INSTALLROOT)$(bindir)/rdf2ihx
cd $(INSTALLROOT)$(bindir) && rm -f rdf2com && $(LN_S) rdf2bin rdf2com
diff --git a/rdoff/Makefile.sc b/rdoff/Makefile.sc
index fca911ad..7b45fe7e 100644
--- a/rdoff/Makefile.sc
+++ b/rdoff/Makefile.sc
@@ -1,57 +1,56 @@
-# Makefile for RDOFF object file utils; part of the Netwide Assembler
-#
-# 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 for use under Unix (probably fairly
-# portably).
-
-CC = sc
-CCFLAGS = -I..\ -c -a1 -mn -Nc -w2 -w7 -o+time -5
-LINK = link
-LINKFLAGS = /noi /exet:NT /su:console
-
-OBJ=obj
-EXE=.exe
-
-NASMLIB = ..\nasmlib.$(OBJ)
-NASMLIB_H = ..\nasmlib.h
-LDRDFLIBS = rdoff.$(OBJ) $(NASMLIB) symtab.$(OBJ) collectn.$(OBJ) rdlib.$(OBJ)
-RDXLIBS = rdoff.$(OBJ) rdfload.$(OBJ) symtab.$(OBJ) collectn.$(OBJ)
-
-.c.$(OBJ):
- $(CC) $(CCFLAGS) $*.c
-
-all : rdfdump$(EXE) ldrdf$(EXE) rdx$(EXE) rdflib$(EXE) rdf2bin$(EXE) rdf2com$(EXE)
-
-rdfdump$(EXE) : rdfdump.$(OBJ)
- $(LINK) $(LINKFLAGS) rdfdump.$(OBJ), rdfdump$(EXE);
-ldrdf$(EXE) : ldrdf.$(OBJ) $(LDRDFLIBS)
- $(LINK) $(LINKFLAGS) ldrdf.$(OBJ) $(LDRDFLIBS), ldrdf$(EXE);
-rdx$(EXE) : rdx.$(OBJ) $(RDXLIBS)
- $(LINK) $(LINKFLAGS) rdx.$(OBJ) $(RDXLIBS), rdx$(EXE);
-rdflib$(EXE) : rdflib.$(OBJ)
- $(LINK) $(LINKFLAGS) rdflib.$(OBJ), rdflib$(EXE);
-rdf2bin$(EXE) : rdf2bin.$(OBJ) $(RDXLIBS) $(NASMLIB)
- $(LINK) $(LINKFLAGS) rdf2bin.$(OBJ) $(RDXLIBS) $(NASMLIB), rdf2bin$(EXE);
-rdf2com$(EXE) : rdf2bin$(EXE)
- copy rdf2bin$(EXE) rdf2com$(EXE)
-
-rdf2bin.$(OBJ) : rdf2bin.c
-rdfdump.$(OBJ) : rdfdump.c
-rdoff.$(OBJ) : rdoff.c rdoff.h
-ldrdf.$(OBJ) : ldrdf.c rdoff.h $(NASMLIB_H) symtab.h collectn.h rdlib.h
-symtab.$(OBJ) : symtab.c symtab.h
-collectn.$(OBJ) : collectn.c collectn.h
-rdx.$(OBJ) : rdx.c rdoff.h rdfload.h symtab.h
-rdfload.$(OBJ) : rdfload.c rdfload.h rdoff.h collectn.h symtab.h
-rdlib.$(OBJ) : rdlib.c rdlib.h
-rdflib.$(OBJ) : rdflib.c
-
-clean :
- del *.$(OBJ) rdfdump$(EXE) ldrdf$(EXE) rdx$(EXE) rdflib$(EXE) rdf2bin$(EXE)
-
-
- \ No newline at end of file
+# Makefile for RDOFF object file utils; part of the Netwide Assembler
+#
+# 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 for use under Unix (probably fairly
+# portably).
+
+CC = sc
+CCFLAGS = -I..\ -c -a1 -mn -Nc -w2 -w7 -o+time -5
+LINK = link
+LINKFLAGS = /noi /exet:NT /su:console
+
+OBJ=obj
+EXE=.exe
+
+NASMLIB = ..\nasmlib.$(OBJ)
+NASMLIB_H = ..\nasmlib.h
+LDRDFLIBS = rdoff.$(OBJ) $(NASMLIB) symtab.$(OBJ) collectn.$(OBJ) rdlib.$(OBJ)
+RDXLIBS = rdoff.$(OBJ) rdfload.$(OBJ) symtab.$(OBJ) collectn.$(OBJ)
+
+.c.$(OBJ):
+ $(CC) $(CCFLAGS) $*.c
+
+all : rdfdump$(EXE) ldrdf$(EXE) rdx$(EXE) rdflib$(EXE) rdf2bin$(EXE) rdf2com$(EXE)
+
+rdfdump$(EXE) : rdfdump.$(OBJ)
+ $(LINK) $(LINKFLAGS) rdfdump.$(OBJ), rdfdump$(EXE);
+ldrdf$(EXE) : ldrdf.$(OBJ) $(LDRDFLIBS)
+ $(LINK) $(LINKFLAGS) ldrdf.$(OBJ) $(LDRDFLIBS), ldrdf$(EXE);
+rdx$(EXE) : rdx.$(OBJ) $(RDXLIBS)
+ $(LINK) $(LINKFLAGS) rdx.$(OBJ) $(RDXLIBS), rdx$(EXE);
+rdflib$(EXE) : rdflib.$(OBJ)
+ $(LINK) $(LINKFLAGS) rdflib.$(OBJ), rdflib$(EXE);
+rdf2bin$(EXE) : rdf2bin.$(OBJ) $(RDXLIBS) $(NASMLIB)
+ $(LINK) $(LINKFLAGS) rdf2bin.$(OBJ) $(RDXLIBS) $(NASMLIB), rdf2bin$(EXE);
+rdf2com$(EXE) : rdf2bin$(EXE)
+ copy rdf2bin$(EXE) rdf2com$(EXE)
+
+rdf2bin.$(OBJ) : rdf2bin.c
+rdfdump.$(OBJ) : rdfdump.c
+rdoff.$(OBJ) : rdoff.c rdoff.h
+ldrdf.$(OBJ) : ldrdf.c rdoff.h $(NASMLIB_H) symtab.h collectn.h rdlib.h
+symtab.$(OBJ) : symtab.c symtab.h
+collectn.$(OBJ) : collectn.c collectn.h
+rdx.$(OBJ) : rdx.c rdoff.h rdfload.h symtab.h
+rdfload.$(OBJ) : rdfload.c rdfload.h rdoff.h collectn.h symtab.h
+rdlib.$(OBJ) : rdlib.c rdlib.h
+rdflib.$(OBJ) : rdflib.c
+
+clean :
+ del *.$(OBJ) rdfdump$(EXE) ldrdf$(EXE) rdx$(EXE) rdflib$(EXE) rdf2bin$(EXE)
+
+
diff --git a/rdoff/README b/rdoff/README
index 29f9aa03..66988d2d 100644
--- a/rdoff/README
+++ b/rdoff/README
@@ -4,16 +4,8 @@ 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. 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.
+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.
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/ldrdf.c b/rdoff/ldrdf.c
index 72f87255..3d9d749e 100644
--- a/rdoff/ldrdf.c
+++ b/rdoff/ldrdf.c
@@ -29,13 +29,14 @@
#include <stdlib.h>
#include <string.h>
+#include "multboot.h"
#include "rdoff.h"
#include "symtab.h"
#include "collectn.h"
#include "rdlib.h"
#include "segtab.h"
-#define LDRDF_VERSION "1.00 alpha 1"
+#define LDRDF_VERSION "1.02"
#define RDF_MAXSEGS 64
/* #define STINGY_MEMORY */
@@ -91,6 +92,44 @@ struct librarynode * lastlib = NULL;
/* the symbol table */
void * symtab = NULL;
+/* objects search path */
+char * objpath = NULL;
+
+/* libraries search path */
+char * libpath = NULL;
+
+/* error file */
+static FILE * error_file;
+
+#ifdef _MULTBOOT_H
+
+/* loading address for multiboot header */
+unsigned MBHloadAddr;
+
+/*
+ * Tiny code that moves RDF loader to its working memory region:
+ * mov esi,SOURCE_ADDR ; BE xx xx xx xx
+ * mov edi,DEST_ADDR ; BF xx xx xx xx
+ * mov esp,edi ; 89 FC
+ * push edi ; 57
+ * mov ecx,RDFLDR_LENGTH/4 ; B9 xx xx xx xx
+ * cld ; FC
+ * rep movsd ; F3 A5
+ * ret ; C3
+ */
+
+#define RDFLDR_LENGTH 4096 /* Loader will be moved to unused */
+#define RDFLDR_DESTLOC 0xBF000 /* video page */
+
+unsigned char RDFloaderMover[]={
+ 0xBE, 0, 0, 0, 0, 0xBF, 0, 0xF0, 0xB, 0,
+ 0x89, 0xFC, 0x57,
+ 0xB9, 0, 4, 0, 0,
+ 0xFC, 0xF3, 0xA5, 0xC3
+};
+
+#endif
+
/* the header of the output file, built up stage by stage */
rdf_headerbuf * newheader = NULL;
@@ -107,7 +146,13 @@ struct ldrdfoptions {
int verbose;
int align;
int warnUnresolved;
+ int errorUnresolved;
int strip;
+ int respfile;
+ int stderr_redir;
+ int objpath;
+ int libpath;
+ int addMBheader;
} options;
int errorcount = 0; /* determines main program exit status */
@@ -305,11 +350,26 @@ void processmodule(const char * filename, struct modulenode * mod)
break;
case 3: /* exported symbol */
- if (mod->seginfo[(int)hr->e.segment].dest_seg == -1)
- continue;
- symtab_add(hr->e.label, mod->seginfo[(int)hr->e.segment].dest_seg,
- mod->seginfo[(int)hr->e.segment].reloc + hr->e.offset);
+ {
+ int destseg;
+ long destreloc;
+
+ if (hr->e.segment == 2)
+ {
+ destreloc = bss_length;
+ if (destreloc % options.align != 0)
+ destreloc += options.align - (destreloc % options.align);
+ destseg = 2;
+ }
+ else
+ {
+ if ((destseg = mod->seginfo[(int)hr->e.segment].dest_seg) == -1)
+ continue;
+ destreloc = mod->seginfo[(int)hr->e.segment].reloc;
+ }
+ symtab_add(hr->e.label, destseg, destreloc + hr->e.offset);
break;
+ }
case 5: /* BSS reservation */
/*
@@ -353,6 +413,22 @@ void processmodule(const char * filename, struct modulenode * mod)
}
+
+/*
+ * Look in list for module by its name.
+ */
+int lookformodule(const char *name)
+ {
+ struct modulenode *curr=modules;
+
+ while(curr) {
+ if (!strcmp(name,curr->name)) return 1;
+ curr = curr->next;
+ }
+ return 0;
+ }
+
+
/*
* allocnewseg()
* findsegment()
@@ -415,7 +491,7 @@ void symtab_add(const char * symbol, int segment, long offset)
* symbol previously defined
*/
if (segment < 0) return;
- fprintf (stderr, "warning: `%s' redefined\n", symbol);
+ fprintf (error_file, "warning: `%s' redefined\n", symbol);
return;
}
@@ -502,6 +578,7 @@ void add_library(const char * name)
}
lastlib = lastlib->next;
}
+ lastlib->next = NULL;
if (rdl_open(lastlib, name)) {
rdl_perror("ldrdf", name);
errorcount++;
@@ -528,7 +605,7 @@ int search_libraries()
void * header;
int segment;
long offset;
- int doneanything = 0, keepfile;
+ int doneanything = 0, pass = 1, keepfile;
rdfheaderrec * hr;
cur = libraries;
@@ -536,10 +613,12 @@ int search_libraries()
while (cur)
{
if (options.verbose > 2)
- printf("scanning library `%s'...\n", cur->name);
+ printf("scanning library `%s', pass %d...\n", cur->name, pass);
for (i = 0; rdl_openmodule(cur, i, &f) == 0; i++)
{
+ if (pass == 2 && lookformodule(f.name)) continue;
+
if (options.verbose > 3)
printf(" looking in module `%s'\n", f.name);
@@ -591,15 +670,25 @@ int search_libraries()
lastmodule = lastmodule->next;
memcpy(&lastmodule->f, &f, sizeof(f));
lastmodule->name = strdup(f.name);
+ lastmodule->next = NULL;
processmodule(f.name, lastmodule);
break;
}
if (!keepfile)
- rdfclose(&f);
+ {
+ free(f.name);
+ f.name = NULL;
+ f.fp = NULL;
+ }
}
if (rdl_error != 0 && rdl_error != RDL_ENOTFOUND)
rdl_perror("ldrdf", cur->name);
+
cur = cur->next;
+ if (cur == NULL && pass == 1) {
+ cur = libraries;
+ pass++;
+ }
}
return doneanything;
@@ -614,8 +703,8 @@ int search_libraries()
*/
void write_output(const char * filename)
{
- FILE * f = fopen(filename, "wb");
- rdf_headerbuf * rdfheader = rdfnewheader();
+ FILE * f;
+ rdf_headerbuf * rdfheader;
struct modulenode * cur;
int i, availableseg, seg, localseg, isrelative;
void * header;
@@ -625,18 +714,43 @@ void write_output(const char * filename)
long offset;
byte * data;
- if (!f) {
+ if ((f = fopen(filename, "wb"))==NULL) {
fprintf(stderr, "ldrdf: couldn't open %s for output\n", filename);
exit(1);
}
- if (!rdfheader) {
+ if ((rdfheader=rdfnewheader())==NULL) {
fprintf(stderr, "ldrdf: out of memory\n");
exit(1);
}
+
+ /*
+ * Add multiboot header if appropriate option is specified.
+ * Multiboot record *MUST* be the first record in output file.
+ */
+ if (options.addMBheader) {
+ if (options.verbose)
+ puts("\nadding multiboot header record");
+
+ hr = (rdfheaderrec *) malloc(sizeof(struct MultiBootHdrRec));
+ hr->mbh.type = 9;
+ hr->mbh.reclen = sizeof(struct tMultiBootHeader)+RDFLDRMOVER_SIZE;
+
+ hr->mbh.mb.Magic = MB_MAGIC;
+ hr->mbh.mb.Flags = MB_FL_KLUDGE;
+ hr->mbh.mb.Checksum = ~(MB_MAGIC+MB_FL_KLUDGE-1);
+ hr->mbh.mb.HeaderAddr = MBHloadAddr+16;
+ hr->mbh.mb.LoadAddr = MBHloadAddr;
+ hr->mbh.mb.Entry = MBHloadAddr+16+sizeof(struct tMultiBootHeader);
+
+ memcpy(hr->mbh.mover,RDFloaderMover,RDFLDRMOVER_SIZE);
+
+ rdfaddheader(rdfheader,hr);
+ free(hr);
+ }
if (options.verbose)
printf ("\nbuilding output module (%d segments)\n", nsegs);
-
+
/*
* Allocate the memory for the segments. We may be better off
* building the output module one segment at a time when running
@@ -645,6 +759,8 @@ void write_output(const char * filename)
*/
for (i = 0; i < nsegs; i++)
{
+ outputseg[i].data=NULL;
+ if(!outputseg[i].length) continue;
outputseg[i].data = malloc(outputseg[i].length);
if (!outputseg[i].data) {
fprintf(stderr, "ldrdf: out of memory\n");
@@ -714,7 +830,7 @@ void write_output(const char * filename)
* and the BSS segment (doh!)
*/
add_seglocation (&segs, 2, 2, cur->bss_reloc);
-
+
while ((hr = rdfgetheaderrec(&cur->f)))
{
switch(hr->type) {
@@ -786,7 +902,7 @@ void write_output(const char * filename)
case 1:
offset += *data;
if (offset < -127 || offset > 128)
- fprintf(stderr, "warning: relocation out of range "
+ fprintf(error_file, "warning: relocation out of range "
"at %s(%02x:%08lx)\n", cur->name,
(int)hr->r.segment, hr->r.offset);
*data = (char) offset;
@@ -794,7 +910,7 @@ void write_output(const char * filename)
case 2:
offset += * (short *)data;
if (offset < -32767 || offset > 32768)
- fprintf(stderr, "warning: relocation out of range "
+ fprintf(error_file, "warning: relocation out of range "
"at %s(%02x:%08lx)\n", cur->name,
(int)hr->r.segment, hr->r.offset);
* (short *)data = (short) offset;
@@ -832,8 +948,9 @@ void write_output(const char * filename)
se = symtabFind(symtab, hr->i.label);
if (!se || se->segment == -1) {
if (options.warnUnresolved) {
- fprintf(stderr, "warning: unresolved reference to `%s'"
+ fprintf(error_file, "warning: unresolved reference to `%s'"
" in module `%s'\n", hr->i.label, cur->name);
+ if (options.errorUnresolved==1) errorcount++;
}
/*
* we need to allocate a segment number for this
@@ -900,6 +1017,16 @@ void write_output(const char * filename)
rdfaddheader(rdfheader, hr);
break;
+ case 8: /* module name */
+ /*
+ * insert module name record if export symbols
+ * are not stripped.
+ */
+ if (options.strip) break;
+
+ rdfaddheader(rdfheader, hr);
+ break;
+
case 6: /* segment fixup */
/*
* modify the segment numbers if necessary, and
@@ -939,7 +1066,7 @@ void write_output(const char * filename)
free(header);
done_seglocations(&segs);
- }
+ }
/*
* combined BSS reservation for the entire results
@@ -957,6 +1084,18 @@ void write_output(const char * filename)
if (i == 2) continue;
rdfaddsegment (rdfheader, outputseg[i].length);
}
+
+ if (options.addMBheader) {
+ struct MultiBootHdrRec *mbhrec = (struct MultiBootHdrRec *)(rdfheader->buf->buffer);
+ unsigned l = membuflength(rdfheader->buf) + 14 +
+ 10*rdfheader->nsegments + rdfheader->seglength;
+ unsigned *ldraddr = (unsigned *)(mbhrec->mover+1);
+
+ mbhrec->mb.LoadEndAddr = MBHloadAddr+l+10+RDFLDR_LENGTH;
+ mbhrec->mb.BSSendAddr = mbhrec->mb.LoadEndAddr;
+ *ldraddr = MBHloadAddr+l+10;
+ }
+
rdfwriteheader(f, rdfheader);
rdfdoneheader(rdfheader);
/*
@@ -996,14 +1135,15 @@ void usage()
printf(" ldrdf [options] object modules ... [-llibrary ...]\n");
printf(" ldrdf -r\n");
printf("options:\n");
- printf(" -v[=n] increases verbosity by 1, or sets it to n\n");
- printf(" -a nn sets segment alignment value (default 16)\n");
- printf(" -s strips exported symbols\n");
- printf(" -x warn about unresolved symbols\n");
- printf(" -o name write output in file 'name'\n");
- printf("\n");
- printf("Note: no library searching is performed. Please specify full\n");
- printf("paths to all files referenced.\n");
+ printf(" -v[=n] increases verbosity by 1, or sets it to n\n");
+ printf(" -a nn sets segment alignment value (default 16)\n");
+ printf(" -s strips exported symbols\n");
+ printf(" -x warn about unresolved symbols\n");
+ printf(" -o name write output in file 'name'\n");
+ printf(" -j path specify objects search path\n");
+ printf(" -L path specify libraries search path\n");
+ printf(" -mbh [address] add multiboot header to output file. Default\n");
+ printf(" loading address is 0x110000\n");
exit(0);
}
@@ -1011,12 +1151,15 @@ int main(int argc, char ** argv)
{
char * outname = "aout.rdf";
int moduleloaded = 0;
+ char *respstrings[128] = {0, };
options.verbose = 0;
options.align = 16;
options.warnUnresolved = 0;
options.strip = 0;
-
+
+ error_file = stderr;
+
argc --, argv ++;
if (argc == 0) usage();
while (argc && **argv == '-' && argv[0][1] != 'l')
@@ -1041,7 +1184,7 @@ int main(int argc, char ** argv)
case 'a':
options.align = atoi(argv[1]);
if (options.align <= 0) {
- fprintf(stderr,
+ fprintf(stderr,
"ldrdf: -a expects a positive number argument\n");
exit(1);
}
@@ -1052,17 +1195,94 @@ int main(int argc, char ** argv)
break;
case 'x':
options.warnUnresolved = 1;
+ if (argv[0][2]=='e')
+ options.errorUnresolved = 1;
break;
case 'o':
outname = argv[1];
argv++, argc--;
break;
+ case 'j':
+ if (!objpath)
+ {
+ options.objpath = 1;
+ objpath = argv[1];
+ argv++, argc--;
+ break;
+ }
+ else
+ {
+ fprintf(stderr,"ldrdf: more than one objects search path specified\n");
+ exit(1);
+ }
+ case 'L':
+ if (!libpath)
+ {
+ options.libpath = 1;
+ libpath = argv[1];
+ argv++, argc--;
+ break;
+ }
+ else
+ {
+ fprintf(stderr,"ldrdf: more than one libraries search path specified\n");
+ exit(1);
+ }
+ case '@': {
+ int i=0;
+ char buf[256];
+ FILE *f;
+
+ options.respfile = 1;
+ if (argv[1] != NULL) f = fopen(argv[1],"r");
+ else
+ {
+ fprintf(stderr,"ldrdf: no response file name specified\n");
+ exit(1);
+ }
+
+ if (f == NULL)
+ {
+ fprintf(stderr,"ldrdf: unable to open response file\n");
+ exit(1);
+ }
+ argc-=2;
+ while(fgets(buf,sizeof(buf)-1,f)!=NULL)
+ {
+ char *p;
+ if (buf[0]=='\n') continue;
+ if ((p = strchr(buf,'\n')) != 0)
+ *p=0;
+ if (i >= 128)
+ {
+ fprintf(stderr,"ldrdf: too many input files\n");
+ exit(1);
+ }
+ *(respstrings+i) = newstr(buf);
+ argc++, i++;
+ }
+ goto done;
+ }
+ case '2':
+ options.stderr_redir = 1;
+ error_file = stdout;
+ break;
+ case 'm':
+ if (argv[0][2] == 'b' && argv[0][3] == 'h') {
+ if (argv[1][0] != '-') {
+ MBHloadAddr = atoi(argv[1]);
+ } else {
+ MBHloadAddr = MB_DEFAULTLOADADDR;
+ }
+ options.addMBheader = 1;
+ break;
+ }
default:
usage();
}
argv++, argc--;
}
-
+done:
if (options.verbose > 4) {
printf("ldrdf invoked with options:\n");
printf(" section alignment: %d bytes\n", options.align);
@@ -1071,6 +1291,14 @@ int main(int argc, char ** argv)
printf(" strip symbols\n");
if (options.warnUnresolved)
printf(" warn about unresolved symbols\n");
+ if (options.errorUnresolved)
+ printf(" error if unresolved symbols\n");
+ if (options.objpath)
+ printf(" objects search path: %s\n",objpath);
+ if (options.libpath)
+ printf(" libraries search path: %s\n",libpath);
+ if (options.addMBheader)
+ printf(" loading address for multiboot header: 0x%X\n",MBHloadAddr);
printf("\n");
}
@@ -1082,12 +1310,17 @@ int main(int argc, char ** argv)
exit(1);
}
+ if (*respstrings) argv = respstrings;
while (argc)
{
if (!strncmp(*argv, "-l", 2)) /* library */
- add_library(*argv + 2);
+ {
+ if(libpath) add_library(newstrcat(libpath,*argv + 2));
+ else add_library(*argv + 2);
+ }
else {
- loadmodule(*argv);
+ if(objpath) loadmodule(newstrcat(objpath,*argv));
+ else loadmodule(*argv);
moduleloaded = 1;
}
argv++, argc--;
@@ -1098,7 +1331,7 @@ int main(int argc, char ** argv)
return 0;
}
-
+
search_libraries();
if (options.verbose > 2)
@@ -1109,9 +1342,6 @@ int main(int argc, char ** argv)
write_output(outname);
- if (errorcount > 0)
- exit(1);
-
+ if (errorcount > 0) exit(1);
return 0;
}
-
diff --git a/rdoff/multboot.h b/rdoff/multboot.h
new file mode 100644
index 00000000..9669e49e
--- /dev/null
+++ b/rdoff/multboot.h
@@ -0,0 +1,27 @@
+/******************************************************************************
+ multboot.h - MultiBoot header definitions.
+ ******************************************************************************/
+
+#ifndef _MULTBOOT_H
+#define _MULTBOOT_H
+
+#define MB_MAGIC 0x1BADB002
+
+#define MB_FL_PGALIGN 1 /* Align boot modules on page */
+#define MB_FL_MEMINFO 2 /* Must pass memory info to OS */
+#define MB_FL_KLUDGE 0x10000 /* a.out kludge present */
+
+struct tMultiBootHeader {
+ unsigned Magic;
+ unsigned Flags;
+ unsigned Checksum;
+ unsigned HeaderAddr;
+ unsigned LoadAddr;
+ unsigned LoadEndAddr;
+ unsigned BSSendAddr;
+ unsigned Entry;
+};
+
+#define MB_DEFAULTLOADADDR 0x110000 /* Default loading address */
+
+#endif
diff --git a/rdoff/rdf2bin.c b/rdoff/rdf2bin.c
index 21ea97d3..938b4a92 100644
--- a/rdoff/rdf2bin.c
+++ b/rdoff/rdf2bin.c
@@ -29,7 +29,7 @@ int main(int argc, char **argv)
int tmp;
FILE *of;
char * padding;
- int codepad, datapad;
+ int codepad, datapad, bsspad=0;
if (argc < 2) {
puts("Usage: rdf2bin [-o relocation-origin] [-p segment-alignment] "
@@ -58,6 +58,13 @@ int main(int argc, char **argv)
fprintf(stderr,"rdf2bin: invalid parameter: %s\n",*argv);
return 1;
}
+ } else if (! strcmp(*argv,"-b")) {
+ argv++, argc--;
+ bsspad = readnum(*argv, &tmp);
+ if (tmp) {
+ fprintf(stderr,"rdf2bin: invalid parameter: %s\n",*argv);
+ return 1;
+ }
} else
break;
@@ -69,8 +76,7 @@ int main(int argc, char **argv)
}
m = rdfload(*argv);
- if (! m)
- {
+ if (! m) {
rdfperror("rdf2bin",*argv);
return 1;
}
@@ -119,6 +125,11 @@ int main(int argc, char **argv)
fprintf(stderr,"rdf2bin: error writing to %s\n", *argv);
return 1;
}
+
+ if (bsspad) {
+ void *p = calloc(bsspad-=(m->bssrel - origin),1);
+ fwrite(p,1,bsspad,of);
+ }
fclose(of);
return 0;
diff --git a/rdoff/rdf2ihx.c b/rdoff/rdf2ihx.c
new file mode 100644
index 00000000..c6dd8e3e
--- /dev/null
+++ b/rdoff/rdf2ihx.c
@@ -0,0 +1,189 @@
+/* rdf2ihx: convert an RDOFF object file to Intel Hex format. This is based
+ on rdf2bin. Note that this program only writes 16-bit HEX. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "rdfload.h"
+#include "rdoff.h"
+#include "nasmlib.h"
+#include "symtab.h"
+
+long origin = 0;
+int align = 16;
+
+/* This function writes a single n-byte data record to of. Maximum value
+ for n is 255. */
+static int write_data_record(FILE *of, int ofs, int nbytes,
+ unsigned char *data)
+{
+ int i, iofs;
+ unsigned int checksum;
+
+ iofs = ofs;
+ fprintf(of, ":%02X%04X00", nbytes, ofs);
+ checksum = 0;
+ for (i=0; i<nbytes; i++) {
+ fprintf(of, "%02X", data[i]);
+ ofs++;
+ checksum += data[i];
+ }
+ checksum = checksum + /* current checksum */
+ nbytes + /* RECLEN (one byte) */
+ ((iofs >> 8) & 0xff) + /* high byte of load offset */
+ (iofs & 0xff); /* low byte of load offset */
+ checksum = ~checksum + 1;
+ fprintf(of, "%02X\n", checksum&0xff);
+ return(ofs);
+}
+
+int main(int argc, char **argv)
+{
+ rdfmodule *m;
+ int tmp;
+ FILE *of;
+ char *padding;
+ unsigned char *segbin[2];
+ int pad[2], segn, ofs, i;
+ long segaddr;
+ unsigned int checksum;
+ symtabEnt *s;
+
+ if (argc < 2) {
+ puts("Usage: rdf2ihx [-o relocation-origin] [-p segment-alignment] "
+ "input-file output-file");
+ return(1);
+ }
+
+ argv++, argc--;
+
+ while (argc > 2) {
+ if (strcmp(*argv,"-o") == 0) {
+ argv++, argc--;
+ origin = readnum(*argv, &tmp);
+ if (tmp) {
+ fprintf(stderr,"rdf2ihx: invalid parameter: %s\n",*argv);
+ return 1;
+ }
+ } else if (strcmp(*argv,"-p") == 0) {
+ argv++, argc--;
+ align = readnum(*argv, &tmp);
+ if (tmp) {
+ fprintf(stderr,"rdf2ihx: invalid parameter: %s\n",*argv);
+ return 1;
+ }
+ } else
+ break;
+ argv++, argc--;
+ }
+ if (argc < 2) {
+ puts("rdf2bin: required parameter missing");
+ return -1;
+ }
+ m = rdfload(*argv);
+
+ if (!m) {
+ rdfperror("rdf2bin",*argv);
+ return 1;
+ }
+ printf("relocating %s: origin=%lx, align=%d\n",*argv, origin, align);
+
+ m->textrel = origin;
+ m->datarel = origin + m->f.seg[0].length;
+ if (m->datarel % align != 0) {
+ pad[0] = align - (m->datarel % align);
+ m->datarel += pad[0];
+ } else {
+ pad[0] = 0;
+ }
+
+ m->bssrel = m->datarel + m->f.seg[1].length;
+ if (m->bssrel % align != 0) {
+ pad[1] = align - (m->bssrel % align);
+ m->bssrel += pad[1];
+ } else {
+ pad[1] = 0;
+ }
+
+ printf("code: %08lx\ndata: %08lx\nbss: %08lx\n",
+ m->textrel, m->datarel, m->bssrel);
+
+ rdf_relocate(m);
+
+ argv++;
+
+ of = fopen(*argv,"w");
+ if (!of) {
+ fprintf(stderr,"rdf2ihx: could not open output file %s\n",*argv);
+ return(1);
+ }
+
+ padding = malloc(align);
+ if (!padding) {
+ fprintf(stderr,"rdf2ihx: out of memory\n");
+ return(1);
+ }
+
+ /* write extended segment address record */
+ fprintf(of, ":02000002"); /* Record mark, reclen, load offset & rectyp
+ fields for ext. seg. address record */
+ segaddr = ((origin >> 16) & 0xffff); /* segment address */
+ fprintf(of, "%04X", (unsigned int)(segaddr & 0xffff));
+ checksum = 0x02 + /* reclen */
+ 0x0000 + /* Load Offset */
+ 0x02 + /* Rectyp */
+ (segaddr & 0xff) + /* USBA low */
+ ((segaddr >> 8) & 0xff); /* USBA high */
+ checksum = ~checksum + 1; /* two's-complement the checksum */
+ fprintf(of, "%02X\n", checksum & 0xff);
+
+ /* See if there's a '_main' symbol in the symbol table */
+ if ((s=symtabFind(m->symtab, "_main")) == NULL) {
+ printf("No _main symbol found, no start segment address record added\n");
+ } else {
+ printf("_main symbol found at %04x:%04x\n", s->segment,
+ (unsigned int)(s->offset & 0xffff));
+ /* Create a start segment address record for the _main symbol. */
+ segaddr = ((s->segment & 0xffff) << 16) + ((s->offset) & 0xffff);
+ fprintf(of, ":04000003"); /* Record mark, reclen, load offset & rectyp
+ fields for start seg. addr. record */
+ fprintf(of, "%08lX", segaddr); /* CS/IP field */
+ checksum = 0x04 + /* reclen */
+ 0x0000 + /* load offset */
+ 0x03 + /* Rectyp */
+ (segaddr & 0xff) + /* low-low byte of segaddr */
+ ((segaddr >> 8) & 0xff) + /* low-high byte of segaddr */
+ ((segaddr >> 16) & 0xff) + /* high-low byte of segaddr */
+ ((segaddr >> 24) & 0xff); /* high-high byte of segaddr */
+ checksum = ~checksum + 1; /* two's complement */
+ fprintf(of, "%02X\n", checksum & 0xff);
+ }
+
+ /* Now it's time to write data records from the code and data segments in.
+ This current version doesn't check for segment overflow; proper behavior
+ should be to output a segment address record for the code and data
+ segments. Something to do. */
+ ofs = 0;
+ segbin[0] = m->t;
+ segbin[1] = m->d;
+ for (segn=0; segn<2; segn++) {
+ int mod, adr;
+
+ if (m->f.seg[segn].length == 0)
+ continue;
+ for (i=0; i+15<m->f.seg[segn].length; i+=16) {
+ ofs = write_data_record(of, ofs, 16, &segbin[segn][i]);
+ }
+ if ((mod=m->f.seg[segn].length & 0x000f) != 0) {
+ adr = m->f.seg[segn].length & 0xfff0;
+ ofs = write_data_record(of, ofs, mod, &segbin[segn][adr]);
+ }
+ }
+ /* output an end of file record */
+ fprintf(of, ":00000001FF\n");
+
+ fclose(of);
+ return 0;
+}
+
diff --git a/rdoff/rdfdump.c b/rdoff/rdfdump.c
index cb79a64d..347fdb17 100644
--- a/rdoff/rdfdump.c
+++ b/rdoff/rdfdump.c
@@ -2,6 +2,8 @@
#include <stdlib.h>
#include <string.h>
+#include "multboot.h"
+
FILE *infile;
typedef unsigned short int16;
@@ -35,6 +37,7 @@ void print_header(long length, int rdf_version) {
unsigned char reclen;
long o,ll;
int16 rs;
+ struct tMultiBootHeader *mb;
while (length > 0) {
fread(&t,1,1,infile);
@@ -47,7 +50,7 @@ void print_header(long length, int rdf_version) {
fread(&s,1,1,infile);
fread(&o,4,1,infile);
fread(&l,1,1,infile);
- fread(&rs,2,1,infile);
+ fread(&rs,2,1,infile);
printf(" %s: location (%04x:%08lx), length %d, "
"referred seg %04x\n", t == 1 ? "relocation" : "seg relocation",
(int)s,translatelong(o),(int)l,
@@ -98,7 +101,8 @@ void print_header(long length, int rdf_version) {
printf(" export: (%04x:%08lx) = %s\n",(int)s,translatelong(o),buf);
if (rdf_version == 1) length -= ll + 6;
break;
- case 4: /* DLL record */
+ case 4: /* DLL and Module records */
+ case 8:
ll = 0;
if (rdf_version == 1) {
@@ -108,10 +112,11 @@ void print_header(long length, int rdf_version) {
}
else
{
- for (; ll < reclen - 1; ll++)
+ for (; ll < reclen; ll++)
fread(&buf[ll],1,1,infile);
}
- printf(" dll: %s\n",buf);
+ if (t==4) printf(" dll: %s\n",buf);
+ else printf(" module: %s\n",buf);
if (rdf_version == 1) length -= ll + 1;
break;
case 5: /* BSS reservation */
@@ -121,9 +126,19 @@ void print_header(long length, int rdf_version) {
if (rdf_version > 1 && reclen != 4)
printf(" warning: reclen != 4\n");
break;
+
+ case 9: /* MultiBoot header record */
+ fread(buf,reclen,1,infile);
+ mb = (struct tMultiBootHeader *)buf;
+ printf(" multiboot header: load address=0x%X, size=0x%X, entry=0x%X\n",
+ mb->LoadAddr, mb->LoadEndAddr - mb->LoadAddr, mb->Entry);
+ break;
default:
printf(" unrecognised record (type %d",(int)t);
- if (rdf_version > 1) printf(", length %d",(int)reclen);
+ if (rdf_version > 1) {
+ printf(", length %d",(int)reclen);
+ fseek(infile,reclen,SEEK_CUR);
+ }
printf(")\n");
if (rdf_version == 1) length --;
}
@@ -158,7 +173,7 @@ int main(int argc,char **argv) {
long headerlength = 0;
long objectlength = 0;
- puts("RDOFF Dump utility v2.0 (C) Copyright 1996 Julian R Hall");
+ puts("RDOFF Dump utility v2.1\n(c) Copyright 1996,99,2000 Julian R Hall, Yuri M Zaporogets");
if (argc < 2) {
fputs("Usage: rdfdump [-v] <filename>\n",stderr);
@@ -178,7 +193,7 @@ int main(int argc,char **argv) {
infile = fopen(argv[1],"rb");
if (! infile) {
- fprintf(stderr,"rdfdump: Could not open %s",argv[1]);
+ fprintf(stderr,"rdfdump: Could not open %s\n",argv[1]);
exit(1);
}
diff --git a/rdoff/rdfload.c b/rdoff/rdfload.c
index 5b981034..4737282e 100644
--- a/rdoff/rdfload.c
+++ b/rdoff/rdfload.c
@@ -29,12 +29,13 @@ extern int rdf_errno;
rdfmodule * rdfload(const char *filename)
{
- rdfmodule * f = malloc(sizeof(rdfmodule));
+ rdfmodule * f;
long bsslength = 0;
char * hdr;
rdfheaderrec *r;
- if (f == NULL)
+ f = malloc(sizeof(rdfmodule));
+ if (f == NULL)
{
rdf_errno = 6; /* out of memory */
return NULL;
@@ -92,7 +93,7 @@ rdfmodule * rdfload(const char *filename)
}
f->b = malloc ( bsslength );
- if (! f->b )
+ if (bsslength && (!f->b))
{
free(f->t);
free(f->d);
diff --git a/rdoff/rdoff.c b/rdoff/rdoff.c
index 7f4937ac..e7d8b764 100644
--- a/rdoff/rdoff.c
+++ b/rdoff/rdoff.c
@@ -24,6 +24,7 @@
#include <string.h>
#include <errno.h>
+#include "multboot.h"
#include "rdoff.h"
#define newstr(str) strcpy(malloc(strlen(str) + 1),str)
@@ -49,13 +50,14 @@ memorybuffer * newmembuf()
memorybuffer * t;
t = malloc(sizeof(memorybuffer));
+ if (!t) return NULL;
t->length = 0;
t->next = NULL;
return t;
}
-void membufwrite(memorybuffer *b, void *data, int bytes)
+void membufwrite(memorybuffer *const b, void *data, int bytes)
{
int16 w;
long l;
@@ -276,7 +278,10 @@ int rdfopenhere(rdffile *f, FILE *fp, int *refcount, const char *name)
int rdfclose(rdffile *f)
{
if (! f->refcount || ! --(*f->refcount))
- fclose(f->fp);
+ {
+ fclose(f->fp);
+ f->fp = NULL;
+ }
free(f->name);
return 0;
@@ -400,6 +405,10 @@ rdfheaderrec *rdfgetheaderrec(rdffile *f)
RI32(r.b.amount);
break;
+ case 8: /* Module name record */
+ RS(r.m.modname,127);
+ break;
+
default:
#ifdef STRICT_ERRORS
rdf_errno = 8; /* unknown header record */
@@ -420,7 +429,7 @@ void rdfheaderrewind(rdffile *f)
rdf_headerbuf * rdfnewheader(void)
{
- rdf_headerbuf * hb = malloc(sizeof(hb));
+ rdf_headerbuf * hb = malloc(sizeof(rdf_headerbuf));
if (hb == NULL) return NULL;
hb->buf = newmembuf();
@@ -468,6 +477,16 @@ int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
membufwrite(h->buf,&r->b.amount,-4);
break ;
+ case 8: /* Module name */
+ membufwrite(h->buf,&r->m.modname,strlen(r->m.modname) + 1);
+ break ;
+
+#ifdef _MULTBOOT_H
+ case 9: /* MultiBoot header */
+ membufwrite(h->buf,&r->mbh.mb,sizeof(struct tMultiBootHeader)+RDFLDRMOVER_SIZE);
+ break ;
+#endif
+
default:
#ifdef STRICT_ERRORS
return (rdf_errno = 8);
@@ -509,3 +528,4 @@ void rdfdoneheader(rdf_headerbuf * h)
freemembuf(h->buf);
free(h);
}
+
diff --git a/rdoff/rdoff.h b/rdoff/rdoff.h
index e23ffa40..0c572315 100644
--- a/rdoff/rdoff.h
+++ b/rdoff/rdoff.h
@@ -9,7 +9,7 @@
* as acknowledgement is given in an appropriate manner to its authors,
* with instructions of how to obtain a copy via ftp.
*/
-
+
#ifndef _RDOFF_H
#define _RDOFF_H "RDOFF2 support routines v0.3"
@@ -48,7 +48,7 @@ struct ImportRec {
struct ExportRec {
byte type; /* must be 3 */
byte reclen; /* content length */
- byte segment; /* segment referred to (0/1) */
+ byte segment; /* segment referred to (0/1/2) */
long offset; /* offset within segment */
char label[33]; /* zero terminated as above. max len = 32 chars */
};
@@ -65,6 +65,28 @@ struct BSSRec {
long amount; /* number of bytes BSS to reserve */
};
+struct ModRec {
+ byte type; /* must be 8 */
+ byte reclen; /* content length */
+ char modname[128]; /* module name */
+};
+
+#ifdef _MULTBOOT_H
+
+#define RDFLDRMOVER_SIZE 22
+
+struct MultiBootHdrRec {
+ byte type; /* must be 9 */
+ byte reclen; /* content length */
+#ifdef __GNUC__
+ struct tMultiBootHeader mb __attribute__ ((packed)); /* MultiBoot header */
+#else
+ struct tMultiBootHeader mb;
+#endif
+ byte mover[RDFLDRMOVER_SIZE]; /* Mover of RDF loader */
+};
+#endif
+
/* GenericRec - contains the type and length field, plus a 128 byte
char array 'data', which will probably never be used! */
@@ -82,6 +104,10 @@ typedef union RDFHeaderRec {
struct ExportRec e; /* type == 3 */
struct DLLRec d; /* type == 4 */
struct BSSRec b; /* type == 5 */
+ struct ModRec m; /* type == 8 */
+#ifdef _MULTBOOT_H
+ struct MultiBootHdrRec mbh; /* type == 9 */
+#endif
} rdfheaderrec;
struct SegmentHeaderRec {
@@ -167,4 +193,7 @@ int rdfaddsegment(rdf_headerbuf *h, long seglength);
int rdfwriteheader(FILE *fp,rdf_headerbuf *h);
void rdfdoneheader(rdf_headerbuf *h);
+/* This is needed by linker to write multiboot header record */
+int membuflength(memorybuffer *b);
+
#endif /* _RDOFF_H */
diff --git a/rdoff/symtab.c b/rdoff/symtab.c
index 4959a5d4..8570f981 100644
--- a/rdoff/symtab.c
+++ b/rdoff/symtab.c
@@ -9,6 +9,7 @@
*/
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <malloc.h>
#include "symtab.h"
@@ -106,6 +107,7 @@ symtabDump(void *stab, FILE* of)
{
symtab mytab = (symtab)stab;
int i;
+ char *SegNames[3]={"code","data","bss"};
fprintf(of, "Symbol table is ...\n");
for (i=0; i < SYMTABSIZE; ++i) {
@@ -116,7 +118,7 @@ symtabDump(void *stab, FILE* of)
}
while(l) {
fprintf(of, "%-32s %s:%08lx (%ld)\n",l->ent.name,
- l->ent.segment ? "data" : "code" ,
+ SegNames[l->ent.segment],
l->ent.offset, l->ent.flags);
l = l->next;
}
diff --git a/scitech.txt b/scitech.txt
new file mode 100644
index 00000000..049694f5
--- /dev/null
+++ b/scitech.txt
@@ -0,0 +1,213 @@
+
+ The Netwide Assembler: NASM
+ ===========================
+
+--------------------------------------------------------------------------------
+ SciTech MGL Modifications
+--------------------------------------------------------------------------------
+
+All changes can be compiled in and out using the TASM_COMPAT macros,
+and when compiled without TASM_COMPAT defined we get the exact same
+binary as the unmodified 0.98 sources.
+
+standard.mac:
+macros.c:
+ . Added macros to ignore TASM directives before first include
+
+nasm.h:
+ . Added extern declaration for tasm_compatible_mode
+
+nasm.c:
+ . Added global variable tasm_compatible_mode
+ . Added command line switch for TASM compatible mode (-t)
+ . Changed version command line to reflect when compiled with TASM additions
+ . Added response file processing to allow all arguments on a single
+ line (response file is @resp rather than -@resp for NASM format).
+
+labels.c:
+ . Changes islocal() macro to support TASM style @@local labels.
+ . Added islocalchar() macro to support TASM style @@local labels.
+
+parser.c:
+ . Added support for TASM style memory references (ie: mov [DWORD eax],10
+ rather than the NASM style mov DWORD [eax],10).
+
+preproc.c:
+ . Added new directives, %arg, %local, %stacksize to directives table
+ . Added support for TASM style directives without a leading % symbol.
+
+--------------------------------------------------------------------------------
+ Integrated a block of changes from Andrew Zabolotny <bit@eltech.ru>:
+--------------------------------------------------------------------------------
+
+-*- A new keyword %xdefine and its case-insensitive counterpart %ixdefine.
+ They work almost the same way as %define and %idefine but expand
+ the definition immediately, not on the invocation. Something like a cross
+ between %define and %assign. The "x" suffix stands for "eXpand", so
+ "xdefine" can be deciphered as "expand-and-define". Thus you can do
+ things like this:
+
+ %assign ofs 0
+
+ %macro arg 1
+ %xdefine %1 dword [esp+ofs]
+ %assign ofs ofs+4
+ %endmacro
+
+-*- Changed the place where the expansion of %$name macros are expanded.
+ Now they are converted into ..@ctxnum.name form when detokenizing, so
+ there are no quirks as before when using %$name arguments to macros,
+ in macros etc. For example:
+
+ %macro abc 1
+ %define %1 hello
+ %endm
+
+ abc %$here
+ %$here
+
+ Now last line will be expanded into "hello" as expected. This also allows
+ for lots of goodies, a good example are extended "proc" macros included
+ in this archive.
+
+-*- Added a check for "cstk" in smacro_defined() before calling get_ctx() -
+ this allows for things like:
+
+ %ifdef %$abc
+ %endif
+
+ to work without warnings even in no context.
+
+-*- Added a check for "cstk" in %if*ctx and %elif*ctx directives -
+ this allows to use %ifctx without excessive warnings. If there is
+ no active context, %ifctx goes through "false" branch.
+
+-*- Removed "user error: " prefix with %error directive: it just clobbers the
+ output and has absolutely no functionality. Besides, this allows to write
+ macros that does not differ from built-in functions in any way.
+
+-*- Added expansion of string that is output by %error directive. Now you
+ can do things like:
+
+ %define hello(x) Hello, x!
+
+ %define %$name andy
+ %error "hello(%$name)"
+
+ Same happened with %include directive.
+
+-*- Now all directives that expect an identifier will try to expand and
+ concatenate everything without whitespaces in between before usage.
+ For example, with "unfixed" nasm the commands
+
+ %define %$abc hello
+ %define __%$abc goodbye
+ __%$abc
+
+ would produce "incorrect" output: last line will expand to
+
+ hello goodbyehello
+
+ Not quite what you expected, eh? :-) The answer is that preprocessor
+ treats the %define construct as if it would be
+
+ %define __ %$abc goodbye
+
+ (note the white space between __ and %$abc). After my "fix" it
+ will "correctly" expand into
+
+ goodbye
+
+ as expected. Note that I use quotes around words "correct", "incorrect"
+ etc because this is rather a feature not a bug; however current behaviour
+ is more logical (and allows more advanced macro usage :-).
+
+ Same change was applied to:
+ %push,%macro,%imacro,%define,%idefine,%xdefine,%ixdefine,
+ %assign,%iassign,%undef
+
+-*- A new directive [WARNING {+|-}warning-id] have been added. It works only
+ if the assembly phase is enabled (i.e. it doesn't work with nasm -e).
+
+-*- A new warning type: macro-selfref. By default this warning is disabled;
+ when enabled NASM warns when a macro self-references itself; for example
+ the following source:
+
+ [WARNING macro-selfref]
+
+ %macro push 1-*
+ %rep %0
+ push %1
+ %rotate 1
+ %endrep
+ %endmacro
+
+ push eax,ebx,ecx
+
+ will produce a warning, but if we remove the first line we won't see it
+ anymore (which is The Right Thing To Do {tm} IMHO since C preprocessor
+ eats such constructs without warnings at all).
+
+-*- Added a "error" routine to preprocessor which always will set ERR_PASS1
+ bit in severity_code. This removes annoying repeated errors on first
+ and second passes from preprocessor.
+
+-*- Added the %+ operator in single-line macros for concatenating two
+ identifiers. Usage example:
+
+ %define _myfunc _otherfunc
+ %define cextern(x) _ %+ x
+ cextern (myfunc)
+
+ After first expansion, third line will become "_myfunc". After this
+ expansion is performed again so it becomes "_otherunc".
+
+-*- Now if preprocessor is in a non-emmitting state, no warning or error
+ will be emmitted. Example:
+
+ %if 1
+ mov eax,ebx
+ %else
+ put anything you want between these two brackets,
+ even macro-parameter references %1 or local labels %$zz
+ or macro-local labels %%zz - no warning will be emmitted.
+ %endif
+
+-*- Context-local variables on expansion as a last resort are looked up
+ in outer contexts. For example, the following piece:
+
+ %push outer
+ %define %$a [esp]
+
+ %push inner
+ %$a
+ %pop
+ %pop
+
+ will expand correctly the fourth line to [esp]; if we'll define another
+ %$a inside the "inner" context, it will take precedence over outer
+ definition. However, this modification has been applied only to
+ expand_smacro and not to smacro_define: as a consequence expansion
+ looks in outer contexts, but %ifdef won't look in outer contexts.
+
+ This behaviour is needed because we don't want nested contexts to
+ act on already defined local macros. Example:
+
+ %define %$arg1 [esp+4]
+ test eax,eax
+ if nz
+ mov eax,%$arg1
+ endif
+
+ In this example the "if" mmacro enters into the "if" context, so %$arg1
+ is not valid anymore inside "if". Of course it could be worked around
+ by using explicitely %$$arg1 but this is ugly IMHO.
+
+-*- Fixed memory leak in %undef. The origline wasn't freed before
+ exiting on success.
+
+-*- Fixed trap in preprocessor when line expanded to empty set of tokens.
+ This happens, for example, in the following case:
+
+ #define SOMETHING
+ SOMETHING
diff --git a/standard.mac b/standard.mac
index 05905d61..58e65df5 100644
--- a/standard.mac
+++ b/standard.mac
@@ -96,3 +96,13 @@ __SECT__
[cpu %1]
%endmacro
+
+; Macros to make NASM ignore some TASM directives before the first include
+; directive.
+
+%idefine IDEAL
+%idefine JUMPS
+%idefine P386
+%idefine P486
+%idefine P586
+%idefine END
diff --git a/test/bintest.asm b/test/bintest.asm
index 6799b387..94d2bf7f 100644
--- a/test/bintest.asm
+++ b/test/bintest.asm
@@ -26,7 +26,7 @@
jmp start ; [6]
-end mov ax,0x4c00 ; [1]
+endX mov ax,0x4c00 ; [1]
int 0x21
start mov byte [bss_sym],',' ; [1] [8]
@@ -49,7 +49,7 @@ start mov byte [bss_sym],',' ; [1] [8]
datasym db 'hello world', 13, 10, '$' ; [2]
bssptr dw bss_sym ; [2] [11]
dataptr dw datasym+5 ; [2] [10]
-textptr dw end ; [2] [9]
+textptr dw endX ; [2] [9]
SECTION .bss
diff --git a/test/test1.asm b/test/test1.asm
deleted file mode 100644
index ce24ca15..00000000
--- a/test/test1.asm
+++ /dev/null
@@ -1,62 +0,0 @@
- segment text
- bits 16
-
- imul edx,[addr],10
- imul eax,20
- imul edx,eax,130
-
- push 0x40
- push word 0x40
- push word 4095
- push byte 0x40
- push dword 0x40
- push dword 4095
-
- add ax,1
- add bx,1
- cmp cx,0
- sub dx,3
- sbb si,-1
- xor ax,0xffff
- xor ax,-1
- xor bx,0xffff
- xor bx,-1
-
-
- adc bx,add1
- adc bx,-7
- adc bx,-128
- adc bx,-129
- adc bx,addr
- adc bx,byte -7
-add1: adc bx,word -7
- adc bx,add1
- resb 256
-addr: nop
- adc bx,addr
- adc eax,5
- adc eax,500
- adc eax,byte 5
- adc ax,4
- adc ebx,7
- adc ebx,700
- adc ebx,byte 7
- adc ecx,1
- adc eax,1
-
- shr edx,mmm
- shr edx,one
- adc ebx,byte mmm
-m1: adc ebx,mmm
-mmm equ 9
-m2: adc ebx,mmm
-one equ 1
- shr edx,mmm
- shr edx,one
- shr edx,1
-tend dw tend
-
- segment data
- db 'abc'
- db '', 12, 13, 0
-
diff --git a/test/test2.asm b/test/test2.asm
deleted file mode 100644
index 5bbb034c..00000000
--- a/test/test2.asm
+++ /dev/null
@@ -1,18 +0,0 @@
- USE16
- CPU 386
-
-debugdump001:
-goo: jmp foo
- jc near foo
- mov ax,[si+5]
- mov ax,[si-7]
- mov ax,[si+n]
- nop
- resb 10
-foo: jmp goo
- jc goo
- jmp short goo
-debugdump002: push 0
-n equ 3
-
-
diff --git a/test/test2a.asm b/test/test2a.asm
deleted file mode 100644
index 2ed09a76..00000000
--- a/test/test2a.asm
+++ /dev/null
@@ -1,22 +0,0 @@
- use32
- cpu P3
-
-debugdump001:
-goo: jmp foo
-; cpu 386
- jc near foo
- mov ax,[si+5]
- mov ax,[si-7]
- mov ax,[si+n]
- align 16
-; cpu 486
- bswap edx
-; cpu 186
- resb 10
-foo: jmp goo
- jc goo
- jmp short goo
-debugdump002: push 0
-n equ 3
-
-
diff --git a/test/test3.asm b/test/test3.asm
deleted file mode 100644
index 457ed44d..00000000
--- a/test/test3.asm
+++ /dev/null
@@ -1,45 +0,0 @@
-debugdump001:
- jc baker
- jmp able - 20
- jmp able
-baker: nop
- times 125 nop
-able: jmp baker
- jmp baker + 20
- times 122 nop
- jmp able
-loc: nop
- jc able+20
-
- jmp able1 - 20
- jmp able1
-baker1: nop
- times 126 nop
-able1: jmp near baker1
- jmp baker1 + 20
- times 122 nop
- jmp able1
-loc1: nop
-
-able2: jmp baker2
- times 124 nop
- jmp able2
- nop
-baker2: nop
-
-
-
-able3: jmp baker3
- times 124 nop
- jmp able3
- nop
- nop
-baker3: nop
-debugdump099: nop
-
-
-
-
-
-
-
diff --git a/test/test4.asm b/test/test4.asm
deleted file mode 100644
index 357553e2..00000000
--- a/test/test4.asm
+++ /dev/null
@@ -1,16 +0,0 @@
- cpu 186
-
-start: jmp able
- xor ax,ax
- jc start
- jnc able
- jc charlie
- times 100 nop
-able: jc start
- times 100 nop
-baker: jc start
- times 100 nop
-charlie: jc baker
- jnc able
- jmp start
-end: db 0
diff --git a/test/test4a.asm b/test/test4a.asm
deleted file mode 100644
index bbf85a31..00000000
--- a/test/test4a.asm
+++ /dev/null
@@ -1,16 +0,0 @@
- cpu 386
-
-start: jmp able
- xor ax,ax
- jc start
- jnc able
- jc charlie
- times 100 nop
-able: jc start
- times 100 nop
-baker: jc start
- times 100 nop
-charlie: jc baker
- jnc able
- jmp start
-end: db 0
diff --git a/test/test4b.asm b/test/test4b.asm
deleted file mode 100644
index 63448817..00000000
--- a/test/test4b.asm
+++ /dev/null
@@ -1,17 +0,0 @@
- use32
- cpu 186
-
-start: jmp able
- xor ax,ax
- jc start
- jnc able
- jc charlie
- times 100 nop
-able: jc start
- times 100 nop
-baker: jc start
- times 100 nop
-charlie: jc baker
- jnc able
- jmp start
-end: db 0
diff --git a/test/test4c.asm b/test/test4c.asm
deleted file mode 100644
index 5d873490..00000000
--- a/test/test4c.asm
+++ /dev/null
@@ -1,17 +0,0 @@
- use32
- cpu 386
-
-start: jmp able
- xor ax,ax
- jc start
- jnc able
- jc charlie
- times 100 nop
-able: jc start
- times 100 nop
-baker: jc start
- times 100 nop
-charlie: jc baker
- jnc able
- jmp start
-end: db 0
diff --git a/test/test5.asm b/test/test5.asm
deleted file mode 100644
index 12b0ee42..00000000
--- a/test/test5.asm
+++ /dev/null
@@ -1,43 +0,0 @@
-%macro pushm 1-*
-%rep %0
-%rotate -1
-push %1
-%endrep
-%endmacro
-
-%macro popm 1-*
-%rep %0
-pop %1
-%rotate 1
-%endrep
-%endmacro
-
-%macro pusha 0
-push ax
-push cx
-push dx
-push bx
-push bp
-mov bp,sp
-lea bp,[bp+10]
-xchg bp,[bp-10]
-push bp
-push si
-push di
-%endmacro
-
-%macro popa 0
-pop di
-pop si
-pop bp
-pop bx
-pop bx
-pop dx
-pop cx
-pop ax
-%endmacro
-
- pushm ax,bx,cx,dx
- popm ax,bx,cx,dx
- pusha
- popa
diff --git a/test/test6.asm b/test/test6.asm
deleted file mode 100644
index cf6dca0d..00000000
--- a/test/test6.asm
+++ /dev/null
@@ -1,9 +0,0 @@
-; test6.asm
-; assemble with; nasm -O2 ...
-;
-%rep 20000
- jmp forward
-%endrep
-forward: dd forward
-
- \ No newline at end of file