Merge branch 'nasm-2.09.xx'
authorCyrill Gorcunov <gorcunov@gmail.com>
Sun, 3 Jul 2011 20:51:53 +0000 (00:51 +0400)
committerCyrill Gorcunov <gorcunov@gmail.com>
Sun, 3 Jul 2011 20:51:53 +0000 (00:51 +0400)
Conflicts:
version

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
55 files changed:
Makefile.in
SubmittingPatches [new file with mode: 0644]
assemble.c
configure.in
directiv.pl
disasm.c
doc/changes.src
doc/nasmdoc.src
eval.c
insns.dat
insns.h
insns.pl
lcc/README [deleted file]
lcc/bind.c [deleted file]
lcc/lin-aout.c [deleted file]
lcc/lin-elf.c [deleted file]
lcc/x86nasm.md [deleted file]
macros.pl
nasm.c
nasm.h
nasm.spec.in
nasmlib.c
nasmlib.h
opflags.h
output/outcoff.c
output/outelf32.c
output/outelf64.c
parser.c
perllib/phash.ph
phash.pl
pptok.dat
pptok.pl
preproc.c
quote.c
test/align13.asm
test/align13s.asm
test/alonesym-obj.asm
test/bcd.asm
test/br2003451.asm
test/br2030823.asm
test/br3005117.asm
test/br3026808.asm
test/br3028880.asm
test/br3058845.asm
test/br3066383.asm
test/br3074517.asm [new file with mode: 0644]
test/br3092924.asm [new file with mode: 0644]
test/br3104312.asm [new file with mode: 0644]
test/imm64.asm
test/movd.asm [new file with mode: 0644]
test/prefix66.asm [new file with mode: 0644]
test/sreg.asm [new file with mode: 0644]
test/vgather.asm [new file with mode: 0644]
tokhash.pl
version

index 781952f..89f2bed 100644 (file)
@@ -36,15 +36,21 @@ MKDIR               = mkdir
 RM             = rm
 
 STRIP          = strip
+FIND           = find
 
 # Binary suffixes
 O               = @OBJEXT@
 X               = @EXEEXT@
 
+# Debug stuff
+ifeq ($(TRACE),1)
+       CFLAGS += -DNASM_TRACE
+endif
+
 .SUFFIXES: .c .i .s .$(O) .1 .man
 
-.PHONY: all doc rdf install clean distclean cleaner spotless install_rdf
-.PHONY: install_doc everything install_everything strip perlreq dist
+.PHONY: all doc rdf install clean distclean cleaner spotless install_rdf test
+.PHONY: install_doc everything install_everything strip perlreq dist tags TAGS
 
 .c.$(O):
        $(CC) -c $(ALL_CFLAGS) -o $@ $<
@@ -186,6 +192,7 @@ clean:
        $(RM) -f lib/*.$(O) lib/*.s lib/*.i
        $(RM) -f output/*.$(O) output/*.s output/*.i
        $(RM) -f nasm$(X) ndisasm$(X)
+       $(RM) -f tags TAGS
        cd rdoff && $(MAKE) clean
 
 distclean: clean
@@ -209,6 +216,19 @@ strip:
 rdf: nasmlib.$(O)
        cd rdoff && $(MAKE) all
 
+TAGS:
+       $(RM) -f TAGS
+       $(FIND) . -name '*.[hcS]' -print | xargs etags -a
+
+tags:
+       $(RM) -f tags
+       $(FIND) . -name '*.[hcS]' -print | xargs ctags -a
+
+cscope:
+       $(RM) -f cscope.out cscope.files
+       $(FIND) . -name '*.[hcS]' -print > cscope.files
+       cscope -b -f cscope.out
+
 rdf_install install_rdf:
        cd rdoff && $(MAKE) install
 
diff --git a/SubmittingPatches b/SubmittingPatches
new file mode 100644 (file)
index 0000000..168ab64
--- /dev/null
@@ -0,0 +1,116 @@
+How to submit patches into the NASM
+===================================
+
+Actually the rules are pretty simple
+
+Obtaining the source code
+-------------------------
+
+The NASM sources are tracked by Git SCM at http://repo.or.cz/w/nasm.git
+repository. You either could download packed sources or use git tool itself
+
+        git clone git://repo.or.cz/nasm.git
+
+Changin the source code
+-----------------------
+
+When you change the NASM source code keep in mind -- we prefer tabs and
+indentations to be 4 characters width, space filled.
+
+Other "rules" could be learned from NASM sources -- just make your code
+to look similar.
+
+Producing patch
+---------------
+
+There are at least two ways to make it right.
+
+ 1) git format-patch
+
+    You might need to read documentation on Git SCM how to prepare patch
+    for mail submission. Take a look on http://book.git-scm.com/ and/or
+    http://git-scm.com/documentation for details. It should not be hard
+    at all.
+
+ 2) Use "diff -up"
+    Use "diff -up" or "diff -uprN" to create patches.
+
+Signing your work
+-----------------
+
+To improve tracking of who did what we've introduced a "sign-off" procedure
+on patches that are being emailed around.
+
+The sign-off is a simple line at the end of the explanation for the
+patch, which certifies that you wrote it or otherwise have the right to
+pass it on as a open-source patch.  The rules are pretty simple: if you
+can certify the below:
+
+        Developer's Certificate of Origin 1.1
+
+        By making a contribution to this project, I certify that:
+
+        (a) The contribution was created in whole or in part by me and I
+            have the right to submit it under the open source license
+            indicated in the file; or
+
+        (b) The contribution is based upon previous work that, to the best
+            of my knowledge, is covered under an appropriate open source
+            license and I have the right under that license to submit that
+            work with modifications, whether created in whole or in part
+            by me, under the same open source license (unless I am
+            permitted to submit under a different license), as indicated
+            in the file; or
+
+        (c) The contribution was provided directly to me by some other
+            person who certified (a), (b) or (c) and I have not modified
+            it.
+
+       (d) I understand and agree that this project and the contribution
+           are public and that a record of the contribution (including all
+           personal information I submit with it, including my sign-off) is
+           maintained indefinitely and may be redistributed consistent with
+           this project or the open source license(s) involved.
+
+then you just add a line saying
+
+        Signed-off-by: Random J Developer <random@developer.example.org>
+
+using your real name (please, no pseudonyms or anonymous contributions if
+it possible)
+
+An example of patch message
+---------------------------
+
+From: Random J Developer <random@developer.example.org>
+Subject: [PATCH] Short patch description
+
+Long patch description (could be skipped if patch
+is trivial enough)
+
+Signed-off-by: Random J Developer <random@developer.example.org>
+---
+Patch body here
+
+Mailing patches
+---------------
+
+The patches should be sent to NASM development mailing list
+
+    nasm-devel@lists.sourceforge.net
+
+Please make sure the email client you're using doesn't screw
+your patch (line wrapping and so on).
+
+Wait for response
+-----------------
+
+Be patient. Most NASM developers are pretty busy people so if
+there is no immediate response on your patch -- don't
+be surprised, sometimes a patch may fly around a week(s) before
+gets reviewed. But definitely the patches will not go to /dev/null.
+
+    ---
+    With best regards,
+    NASM-team
index 1ee7f7f..ed5ef8e 100644 (file)
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 1996-2010 The NASM Authors - All Rights Reserved
+ *   Copyright 1996-2011 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
  *                 370 is used for Jcc, 371 is used for JMP.
  * \373          - assemble 0x03 if bits==16, 0x05 if bits==32;
  *                 used for conditional jump over longer jump
+ * \374          - this instruction takes an XMM VSIB memory EA
+ * \375          - this instruction takes an YMM VSIB memory EA
  */
 
 #include "compiler.h"
@@ -184,10 +186,11 @@ enum match_result {
 };
 
 typedef struct {
-    int sib_present;                 /* is a SIB byte necessary? */
-    int bytes;                       /* # of bytes of offset needed */
-    int size;                        /* lazy - this is sib+bytes+1 */
-    uint8_t modrm, sib, rex, rip;    /* the bytes themselves */
+    enum ea_type type;            /* what kind of EA is this? */
+    int sib_present;              /* is a SIB byte necessary? */
+    int bytes;                    /* # of bytes of offset needed */
+    int size;                     /* lazy - this is sib+bytes+1 */
+    uint8_t modrm, sib, rex, rip; /* the bytes themselves */
 } ea;
 
 static uint32_t cpu;            /* cpu level received from nasm.c */
@@ -207,9 +210,10 @@ static opflags_t regflag(const operand *);
 static int32_t regval(const operand *);
 static int rexflags(int, opflags_t, int);
 static int op_rexflags(const operand *, int);
-static ea *process_ea(operand *, ea *, int, int, int, opflags_t);
 static void add_asp(insn *, int);
 
+static enum ea_type process_ea(operand *, ea *, int, int, int, opflags_t);
+
 static int has_prefix(insn * ins, enum prefix_pos pos, enum prefixes prefix)
 {
     return ins->prefixes[pos] == prefix;
@@ -796,8 +800,10 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
     int op1, op2;
     struct operand *opx;
     uint8_t opex = 0;
+    enum ea_type eat;
 
     ins->rex = 0;               /* Ensure REX is reset */
+    eat = EA_SCALAR;            /* Expect a scalar EA */
 
     if (ins->prefixes[PPS_OSIZE] == P_O64)
         ins->rex |= REX_W;
@@ -976,12 +982,28 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
             break;
 
         case 0320:
-            length += (bits != 16);
+        {
+            enum prefixes pfx = ins->prefixes[PPS_OSIZE];
+            if (pfx == P_O16)
+                break;
+            if (pfx != P_none)
+                errfunc(ERR_WARNING | ERR_PASS2, "invalid operand size prefix");
+            else
+                ins->prefixes[PPS_OSIZE] = P_O16;
             break;
+        }
 
         case 0321:
-            length += (bits == 16);
+        {
+            enum prefixes pfx = ins->prefixes[PPS_OSIZE];
+            if (pfx == P_O32)
+                break;
+            if (pfx != P_none)
+                errfunc(ERR_WARNING | ERR_PASS2, "invalid operand size prefix");
+            else
+                ins->prefixes[PPS_OSIZE] = P_O32;
             break;
+        }
 
         case 0322:
             break;
@@ -1071,6 +1093,14 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
             length++;
             break;
 
+        case 0374:
+            eat = EA_XMMVSIB;
+            break;
+
+        case 0375:
+            eat = EA_YMMVSIB;
+            break;
+
         case4(0100):
         case4(0110):
         case4(0120):
@@ -1099,8 +1129,8 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
                     rflags = 0;
                     rfield = c & 7;
                 }
-                if (!process_ea(opy, &ea_data, bits,
-                                ins->addr_size, rfield, rflags)) {
+                if (process_ea(opy, &ea_data, bits,ins->addr_size,
+                               rfield, rflags) != eat) {
                     errfunc(ERR_NONFATAL, "invalid effective address");
                     return -1;
                 } else {
@@ -1200,7 +1230,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
                     insn * ins, const struct itemplate *temp,
                     int64_t insn_end)
 {
-    static char condval[] = {   /* conditional opcodes */
+    static const char condval[] = {   /* conditional opcodes */
         0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
         0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
         0x0, 0xA, 0xA, 0xB, 0x8, 0x4
@@ -1213,6 +1243,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
     struct operand *opx;
     const uint8_t *codes = temp->code;
     uint8_t opex = 0;
+    enum ea_type eat = EA_SCALAR;
 
     while (*codes) {
         c = *codes++;
@@ -1636,32 +1667,8 @@ static void gencode(int32_t segment, int64_t offset, int bits,
             break;
 
         case 0320:
-        {
-            enum prefixes pfx = ins->prefixes[PPS_OSIZE];
-            if (pfx != P_O16 && pfx != P_none)
-                nasm_error(ERR_WARNING, "Invalid operand size prefix");
-            if (pfx != P_O16 && bits != 16) {
-                ins->prefixes[PPS_OSIZE] = P_O16;
-                *bytes = 0x66;
-                out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
-                offset += 1;
-            }
-            break;
-        }
-
         case 0321:
-        {
-            enum prefixes pfx = ins->prefixes[PPS_OSIZE];
-            if (pfx != P_O32 && pfx != P_none)
-                nasm_error(ERR_WARNING, "Invalid operand size prefix");
-            if (pfx != P_O32 && bits == 16) {
-                ins->prefixes[PPS_OSIZE] = P_O32;
-                *bytes = 0x66;
-                out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
-                offset += 1;
-            }
             break;
-        }
 
         case 0322:
         case 0323:
@@ -1801,6 +1808,14 @@ static void gencode(int32_t segment, int64_t offset, int bits,
             offset += 1;
             break;
 
+        case 0374:
+            eat = EA_XMMVSIB;
+            break;
+
+        case 0375:
+            eat = EA_YMMVSIB;
+            break;
+
         case4(0100):
         case4(0110):
         case4(0120):
@@ -1832,8 +1847,8 @@ static void gencode(int32_t segment, int64_t offset, int bits,
                     rfield = c & 7;
                 }
 
-                if (!process_ea(opy, &ea_data, bits, ins->addr_size,
-                                rfield, rflags)) {
+                if (process_ea(opy, &ea_data, bits, ins->addr_size,
+                               rfield, rflags) != eat) {
                     errfunc(ERR_NONFATAL, "invalid effective address");
                 }
 
@@ -2056,6 +2071,12 @@ static enum match_result matches(const struct itemplate *itemp,
         return MERR_INVALOP;
 
     /*
+     * Is it legal?
+     */
+    if (!(optimizing > 0) && (itemp->flags & IF_OPT))
+       return MERR_INVALOP;
+
+    /*
      * Check that no spurious colons or TOs are present
      */
     for (i = 0; i < itemp->operands; i++)
@@ -2215,11 +2236,12 @@ static enum match_result matches(const struct itemplate *itemp,
     return MOK_GOOD;
 }
 
-static ea *process_ea(operand * input, ea * output, int bits,
-                      int addrbits, int rfield, opflags_t rflags)
+static enum ea_type process_ea(operand * input, ea * output, int bits,
+                               int addrbits, int rfield, opflags_t rflags)
 {
     bool forw_ref = !!(input->opflags & OPFLAG_UNKNOWN);
 
+    output->type = EA_SCALAR;
     output->rip = false;
 
     /* REX flags for the rfield operand */
@@ -2230,12 +2252,12 @@ static ea *process_ea(operand * input, ea * output, int bits,
         opflags_t f;
 
         if (!is_register(input->basereg))
-            return NULL;
+            goto err;
         f = regflag(input);
         i = nasm_regvals[input->basereg];
 
         if (REG_EA & ~f)
-            return NULL;        /* Invalid EA register */
+            goto err;
 
         output->rex |= op_rexflags(input, REX_B | REX_P | REX_W | REX_H);
 
@@ -2302,26 +2324,117 @@ static ea *process_ea(operand * input, ea * output, int bits,
                 bx = 0;
             }
 
-            /* check for a 32/64-bit memory reference... */
-            if ((ix|bx) & (BITS32|BITS64)) {
+            /* if either one are a vector register... */
+            if ((ix|bx) & (XMMREG|YMMREG) & ~REG_EA) {
+                int32_t sok = BITS32 | BITS64;
+                int32_t o = input->offset;
+                int mod, scale, index, base;
+
+                printf("bt = %x, bx = %x, it = %x, ix = %x, s = %d\n",
+                       bt, bx, it, ix, s);
+
+                /*
+                 * For a vector SIB, one has to be a vector and the other,
+                 * if present, a GPR.  The vector must be the index operand.
+                 */
+                if (it == -1 || (bx & (XMMREG|YMMREG) & ~REG_EA)) {
+                    if (s == 0)
+                        s = 1;
+                    else if (s != 1)
+                        goto err;
+
+                    t = bt, bt = it, it = t;
+                    x = bx, bx = ix, ix = x;
+                }
+
+                if (bt != -1) {
+                    if (REG_GPR & ~bx)
+                        goto err;
+                    if (!(REG64 & ~bx) || !(REG32 & ~bx))
+                        sok &= bx;
+                    else
+                        goto err;
+                }
+
+                /*
+                 * While we're here, ensure the user didn't specify
+                 * WORD or QWORD
+                 */
+                if (input->disp_size == 16 || input->disp_size == 64)
+                    goto err;
+
+                if (addrbits == 16 ||
+                    (addrbits == 32 && !(sok & BITS32)) ||
+                    (addrbits == 64 && !(sok & BITS64)))
+                    goto err;
+
+                output->type = (ix & YMMREG & ~REG_EA)
+                    ? EA_YMMVSIB : EA_XMMVSIB;
+
+                output->rex |= rexflags(it, ix, REX_X);
+                output->rex |= rexflags(bt, bx, REX_B);
+
+                index = it & 7; /* it is known to be != -1 */
+
+                switch (s) {
+                case 1:
+                    scale = 0;
+                    break;
+                case 2:
+                    scale = 1;
+                    break;
+                case 4:
+                    scale = 2;
+                    break;
+                case 8:
+                    scale = 3;
+                    break;
+                default:   /* then what the smeg is it? */
+                    goto err;    /* panic */
+                }
+                
+                if (bt == -1) {
+                    base = 5;
+                    mod = 0;
+                } else {
+                    base = (bt & 7);
+                    if (base != REG_NUM_EBP && o == 0 &&
+                        seg == NO_SEG && !forw_ref &&
+                        !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
+                        mod = 0;
+                    else if (input->eaflags & EAF_BYTEOFFS ||
+                             (o >= -128 && o <= 127 &&
+                              seg == NO_SEG && !forw_ref &&
+                              !(input->eaflags & EAF_WORDOFFS)))
+                        mod = 1;
+                    else
+                        mod = 2;
+                }
+
+                output->sib_present = true;
+                output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
+                output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
+                output->sib = (scale << 6) | (index << 3) | base;
+            } else if ((ix|bx) & (BITS32|BITS64)) {
                 /*
                  * it must be a 32/64-bit memory reference. Firstly we have
                  * to check that all registers involved are type E/Rxx.
                  */
-                int32_t sok = BITS32 | BITS64, o = input->offset;
+                int32_t sok = BITS32 | BITS64;
+                int32_t o = input->offset;
 
                 if (it != -1) {
                     if (!(REG64 & ~ix) || !(REG32 & ~ix))
                         sok &= ix;
                     else
-                        return NULL;
+                        goto err;
                 }
 
                 if (bt != -1) {
                     if (REG_GPR & ~bx)
-                        return NULL; /* Invalid register */
+                        goto err; /* Invalid register */
                     if (~sok & bx & SIZE_MASK)
-                        return NULL; /* Invalid size */
+                        goto err; /* Invalid size */
                     sok &= bx;
                 }
 
@@ -2330,12 +2443,12 @@ static ea *process_ea(operand * input, ea * output, int bits,
                  * WORD or QWORD
                  */
                 if (input->disp_size == 16 || input->disp_size == 64)
-                    return NULL;
+                    goto err;
 
                 if (addrbits == 16 ||
                     (addrbits == 32 && !(sok & BITS32)) ||
                     (addrbits == 64 && !(sok & BITS64)))
-                    return NULL;
+                    goto err;
 
                 /* now reorganize base/index */
                 if (s == 1 && bt != it && bt != -1 && it != -1 &&
@@ -2365,7 +2478,7 @@ static ea *process_ea(operand * input, ea * output, int bits,
                 }
                 if (it == REG_NUM_ESP ||
                     (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
-                    return NULL;        /* wrong, for various reasons */
+                    goto err;        /* wrong, for various reasons */
 
                 output->rex |= rexflags(it, ix, REX_X);
                 output->rex |= rexflags(bt, bx, REX_B);
@@ -2418,7 +2531,7 @@ static ea *process_ea(operand * input, ea * output, int bits,
                         scale = 3;
                         break;
                     default:   /* then what the smeg is it? */
-                        return NULL;    /* panic */
+                        goto err;    /* panic */
                     }
 
                     if (bt == -1) {
@@ -2450,19 +2563,19 @@ static ea *process_ea(operand * input, ea * output, int bits,
 
                 /* check for 64-bit long mode */
                 if (addrbits == 64)
-                    return NULL;
+                    goto err;
 
                 /* check all registers are BX, BP, SI or DI */
                 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI && b != R_DI) ||
                     (i != -1 && i != R_BP && i != R_BX && i != R_SI && i != R_DI))
-                    return NULL;
+                    goto err;
 
                 /* ensure the user didn't specify DWORD/QWORD */
                 if (input->disp_size == 32 || input->disp_size == 64)
-                    return NULL;
+                    goto err;
 
                 if (s != 1 && i != -1)
-                    return NULL;        /* no can do, in 16-bit EA */
+                    goto err;        /* no can do, in 16-bit EA */
                 if (b == -1 && i != -1) {
                     int tmp = b;
                     b = i;
@@ -2475,12 +2588,12 @@ static ea *process_ea(operand * input, ea * output, int bits,
                 }
                 /* have BX/BP as base, SI/DI index */
                 if (b == i)
-                    return NULL;        /* shouldn't ever happen, in theory */
+                    goto err;        /* shouldn't ever happen, in theory */
                 if (i != -1 && b != -1 &&
                     (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
-                    return NULL;        /* invalid combinations */
+                    goto err;        /* invalid combinations */
                 if (b == -1)            /* pure offset: handled above */
-                    return NULL;        /* so if it gets to here, panic! */
+                    goto err;        /* so if it gets to here, panic! */
 
                 rm = -1;
                 if (i != -1)
@@ -2513,7 +2626,7 @@ static ea *process_ea(operand * input, ea * output, int bits,
                         break;
                     }
                 if (rm == -1)           /* can't happen, in theory */
-                    return NULL;        /* so panic if it does */
+                    goto err;        /* so panic if it does */
 
                 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
                     !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
@@ -2533,7 +2646,10 @@ static ea *process_ea(operand * input, ea * output, int bits,
     }
 
     output->size = 1 + output->sib_present + output->bytes;
-    return output;
+    return output->type;
+
+err:
+    return output->type = EA_INVALID;
 }
 
 static void add_asp(insn *ins, int addrbits)
index c23bac1..8c6a429 100644 (file)
@@ -152,5 +152,14 @@ if test $ac_cv_prog_make_vpathok = no; then
   done
 fi
 
+dnl
+dnl support cchace
+dnl
+AC_ARG_WITH([ccache],
+            [AC_HELP_STRING([--with-ccache],
+                            [Compile with ccache])],
+          [CC="ccache $CC"],
+          [])
+
 AC_OUTPUT_COMMANDS([mkdir -p output])
 AC_OUTPUT(Makefile rdoff/Makefile doc/Makefile)
index 684f542..0417f56 100755 (executable)
@@ -95,7 +95,7 @@ if ($output eq 'h') {
     }
 
     @hashinfo = gen_perfect_hash(\%directive);
-    if (!defined(@hashinfo)) {
+    if (!@hashinfo) {
        die "$0: no hash found\n";
     }
 
index 6320852..5943966 100644 (file)
--- a/disasm.c
+++ b/disasm.c
@@ -218,7 +218,8 @@ static uint8_t *do_drex(uint8_t *data, insn *ins)
  * Process an effective address (ModRM) specification.
  */
 static uint8_t *do_ea(uint8_t *data, int modrm, int asize,
-                     int segsize, operand * op, insn *ins)
+                     int segsize, enum ea_type type,
+                      operand *op, insn *ins)
 {
     int mod, rm, scale, index, base;
     int rex;
@@ -227,7 +228,7 @@ static uint8_t *do_ea(uint8_t *data, int modrm, int asize,
     mod = (modrm >> 6) & 03;
     rm = modrm & 07;
 
-    if (mod != 3 && rm == 4 && asize != 16)
+    if (mod != 3 && asize != 16 && rm == 4)
        sib = *data++;
 
     if (ins->rex & REX_D) {
@@ -253,6 +254,10 @@ static uint8_t *do_ea(uint8_t *data, int modrm, int asize,
          * Exception: mod=0,rm=6 does not specify [BP] as one might
          * expect, but instead specifies [disp16].
          */
+
+        if (type != EA_SCALAR)
+            return NULL;
+
         op->indexreg = op->basereg = -1;
         op->scale = 1;          /* always, in 16 bits */
         switch (rm) {
@@ -341,6 +346,7 @@ static uint8_t *do_ea(uint8_t *data, int modrm, int asize,
            mod = 2;            /* fake disp32 */
         }
 
+
         if (rm == 4) {          /* process SIB */
             scale = (sib >> 6) & 03;
             index = (sib >> 3) & 07;
@@ -350,7 +356,11 @@ static uint8_t *do_ea(uint8_t *data, int modrm, int asize,
 
            if (index == 4 && !(rex & REX_X))
                op->indexreg = -1; /* ESP/RSP cannot be an index */
-           else if (a64)
+           else if (type == EA_XMMVSIB)
+               op->indexreg = nasm_rd_xmmreg[index | ((rex & REX_X) ? 8 : 0)];
+           else if (type == EA_YMMVSIB)
+               op->indexreg = nasm_rd_ymmreg[index | ((rex & REX_X) ? 8 : 0)];
+            else if (a64)
                op->indexreg = nasm_rd_reg64[index | ((rex & REX_X) ? 8 : 0)];
            else
                op->indexreg = nasm_rd_reg32[index | ((rex & REX_X) ? 8 : 0)];
@@ -365,6 +375,9 @@ static uint8_t *do_ea(uint8_t *data, int modrm, int asize,
 
            if (segsize == 16)
                op->disp_size = 32;
+        } else if (type != EA_SCALAR) {
+            /* Can't have VSIB without SIB */
+            return NULL;
         }
 
         switch (mod) {
@@ -410,6 +423,7 @@ static int matches(const struct itemplate *t, uint8_t *data,
     int s_field_for = -1;      /* No 144/154 series code encountered */
     bool vex_ok = false;
     int regmask = (segsize == 64) ? 15 : 7;
+    enum ea_type eat = EA_SCALAR;
 
     for (i = 0; i < MAX_OPERANDS; i++) {
        ins->oprs[i].segment = ins->oprs[i].disp_size =
@@ -573,7 +587,7 @@ static int matches(const struct itemplate *t, uint8_t *data,
        {
            int modrm = *data++;
             opx->segment |= SEG_RMREG;
-            data = do_ea(data, modrm, asize, segsize, opy, ins);
+            data = do_ea(data, modrm, asize, segsize, eat, opy, ins);
            if (!data)
                return false;
             opx->basereg = ((modrm >> 3) & 7) + (ins->rex & REX_R ? 8 : 0);
@@ -668,7 +682,7 @@ static int matches(const struct itemplate *t, uint8_t *data,
             int modrm = *data++;
             if (((modrm >> 3) & 07) != (c & 07))
                 return false;   /* spare field doesn't match up */
-            data = do_ea(data, modrm, asize, segsize, opy, ins);
+            data = do_ea(data, modrm, asize, segsize, eat, opy, ins);
            if (!data)
                return false;
            break;
@@ -915,6 +929,14 @@ static int matches(const struct itemplate *t, uint8_t *data,
            a_used = true;
            break;
 
+        case 0374:
+            eat = EA_XMMVSIB;
+            break;
+
+        case 0375:
+            eat = EA_YMMVSIB;
+            break;
+
        default:
            return false;       /* Unknown code */
        }
index 19a4873..c4fdf62 100644 (file)
@@ -7,6 +7,17 @@
 The NASM 2 series support x86-64, and is the production version of NASM
 since 2007.
 
+\S{cl-2.10} Version 2.10
+
+\b When optimization is enabled, \c{mov r64,imm} now optimizes to the
+  shortest form possible between:
+
+\c      mov r32,imm32                   ;  5 bytes
+\c      mov r64,imm32                   ;  7 bytes
+\c      mov r64,imm64                   ; 10 bytes
+
+To force a specific form, use the \c{STRICT} keyword, see \k{strict}.
+
 
 \S{cl-2.09.09} Version 2.09.09
 
index 82cbf51..34e8386 100644 (file)
@@ -2415,20 +2415,21 @@ things like
 \c         silly {13,10}, crlf             ; crlf:      db 13,10
 
 
-\#\S{mlrmacro} \i{Recursive Multi-Line Macros}: \I\c{%irmacro}\i\c{%rmacro}
-\#
-\#A multi-line macro cannot be referenced within itself, in order to
-\#prevent accidental infinite recursion.
-\#
-\#Recursive multi-line macros allow for self-referencing, with the
-\#caveat that the user is aware of the existence, use and purpose of
-\#recursive multi-line macros. There is also a generous, but sane, upper
-\#limit to the number of recursions, in order to prevent run-away memory
-\#consumption in case of accidental infinite recursion.
-\#
-\#As with non-recursive multi-line macros, recursive multi-line macros are
-\#\i{case-sensitive}, unless you define them using the alternative
-\#directive \c{%irmacro}.
+\S{mlrmacro} \i{Recursive Multi-Line Macros}: \I\c{%irmacro}\i\c{%rmacro}
+
+A multi-line macro cannot be referenced within itself, in order to
+prevent accidental infinite recursion and allow instruction overloading.
+
+Recursive multi-line macros allow for self-referencing, with the
+caveat that the user is aware of the existence, use and purpose of
+recursive multi-line macros. There is also a generous, but sane, upper
+limit to the number of recursions, in order to prevent run-away memory
+consumption in case of accidental infinite recursion.
+
+As with non-recursive multi-line macros, recursive multi-line macros are
+\i{case-sensitive}, unless you define them using the alternative
+directive \c{%irmacro}.
+
 
 \S{mlmacover} Overloading Multi-Line Macros\I{overloading, multi-line macros}
 
@@ -2887,20 +2888,21 @@ does \e{not} remove the macro \c{bar}, since the argument
 specification does not match exactly.
 
 
-\#\S{exitmacro} Exiting Multi-Line Macros: \i\c{%exitmacro}
-\#
-\#Multi-line macro expansions can be arbitrarily terminated with
-\#the \c{%exitmacro} directive.
-\#
-\#For example:
-\#
-\#\c %macro foo 1-3
-\#\c         ; Do something
-\#\c     %if<condition>
-\#\c         %exitmacro
-\#\c     %endif
-\#\c         ; Do something
-\#\c %endmacro
+\S{exitmacro} Exiting Multi-Line Macros: \i\c{%exitmacro}
+
+Multi-line macro expansions can be arbitrarily terminated with
+the \c{%exitmacro} directive.
+
+For example:
+
+\c %macro foo 1-3
+\c         ; Do something
+\c     %if<condition>
+\c         %exitmacro
+\c     %endif
+\c         ; Do something
+\c %endmacro
+
 
 \H{condasm} \i{Conditional Assembly}\I\c{%if}
 
@@ -3221,6 +3223,17 @@ Note a maximum repeat count is limited by 62 bit number, though it
 is hardly possible that you ever need anything bigger.
 
 
+\H{while} \i{Conditional Loops}: \i\c{%while}
+
+The directives \c{%while} and \i\c{%endwhile} combine preprocessor
+loops with conditional assembly, allowing the enclosed chunk of
+code to be replicated as long as certain conditions are met:
+
+\c %while<condition>
+\c     ; some code which only repeats while <condition> is met
+\c %endwhile
+
+
 \H{files} Source Files and Dependencies
 
 These commands allow you to split your sources into multiple files.
@@ -3793,6 +3806,14 @@ variable, for example:
 \c %defstr C_colon      %!'C:'
 
 
+\S{final} \i\c{%final} Directive
+
+The \c{%final} directive is used to delay preprocessing of a line
+until all other "normal" preprocessing is complete.  Multiple
+\c{%final} directives are processed in the opposite order of their
+declaration, last one first and first one last.
+
+
 \H{stdmac} \i{Standard Macros}
 
 NASM defines a set of standard macros, which are already defined
diff --git a/eval.c b/eval.c
index bfbf281..e526723 100644 (file)
--- a/eval.c
+++ b/eval.c
@@ -877,7 +877,7 @@ static expr *expr6(int critical)
                         return NULL;
                     } else {
                         if (opflags)
-                            *opflags |= 1;
+                            *opflags |= OPFLAG_FORWARD;
                         type = EXPR_UNKNOWN;
                         label_seg = NO_SEG;
                         label_ofs = 1;
index 7574dc3..742e13f 100644 (file)
--- a/insns.dat
+++ b/insns.dat
@@ -1,6 +1,6 @@
 ;; --------------------------------------------------------------------------
 ;;
-;;   Copyright 1996-2010 The NASM Authors - All Rights Reserved
+;;   Copyright 1996-2011 The NASM Authors - All Rights Reserved
 ;;   See the file AUTHORS included with the NASM distribution for
 ;;   the specific copyright holders.
 ;;
@@ -770,12 +770,18 @@ MFENCE            void                            \3\x0F\xAE\xF0                                  X64,AMD
 MONITOR                void                            \3\x0F\x01\xC8                                  PRESCOTT
 MONITOR                reg_eax,reg_ecx,reg_edx         \3\x0F\x01\xC8                                  PRESCOTT,ND
 MONITOR                reg_rax,reg_ecx,reg_edx         \3\x0F\x01\xC8                                  X64,ND
-MOV            mem,reg_sreg                    \1\x8C\101                                      8086,SM
+MOV            mem,reg_sreg                    \1\x8C\101                                      8086,SW
 MOV            reg16,reg_sreg                  \320\1\x8C\101                                  8086
 MOV            reg32,reg_sreg                  \321\1\x8C\101                                  386
-MOV            reg_sreg,mem                    \1\x8E\110                                      8086,SM
-MOV            reg_sreg,reg16                  \1\x8E\110                                      8086
-MOV            reg_sreg,reg32                  \1\x8E\110                                      386
+MOV            reg64,reg_sreg                  \323\1\x8C\101                                  X64,OPT,ND
+MOV            rm64,reg_sreg                   \324\1\x8C\101                                  X64
+MOV            reg_sreg,mem                    \1\x8E\110                                      8086,SW
+MOV            reg_sreg,reg16                  \1\x8E\110                                      8086,OPT,ND
+MOV            reg_sreg,reg32                  \1\x8E\110                                      386,OPT,ND
+MOV            reg_sreg,reg64                  \323\1\x8E\110                                  X64,OPT,ND
+MOV            reg_sreg,reg16                  \320\1\x8E\110                                  8086
+MOV            reg_sreg,reg32                  \321\1\x8E\110                                  386
+MOV            reg_sreg,rm64                   \324\1\x8E\110                                  X64
 MOV            reg_al,mem_offs                 \1\xA0\45                                       8086,SM
 MOV            reg_ax,mem_offs                 \320\1\xA1\45                                   8086,SM
 MOV            reg_eax,mem_offs                \321\1\xA1\45                                   386,SM
@@ -813,6 +819,8 @@ MOV         reg64,reg64                     \324\1\x8B\110                                  X64
 MOV            reg8,imm                        \10\xB0\21                                      8086,SM
 MOV            reg16,imm                       \320\10\xB8\31                                  8086,SM
 MOV            reg32,imm                       \321\10\xB8\41                                  386,SM
+MOV            reg64,udword64                  \323\10\xB8\41                                  X64,SM,OPT,ND
+MOV            reg64,sdword64                  \324\1\xC7\200\255                              X64,SM,OPT,ND
 MOV            reg64,imm                       \324\10\xB8\55                                  X64,SM
 MOV            rm8,imm                         \1\xC6\200\21                                   8086,SM
 MOV            rm16,imm                        \320\1\xC7\200\31                               8086,SM
@@ -822,14 +830,10 @@ MOV               rm64,imm32                      \324\1\xC7\200\255                              X64
 MOV            mem,imm8                        \1\xC6\200\21                                   8086,SM
 MOV            mem,imm16                       \320\1\xC7\200\31                               8086,SM
 MOV            mem,imm32                       \321\1\xC7\200\41                               386,SM
-MOVD           mmxreg,mem                      \360\2\x0F\x6E\110                              PENT,MMX,SD
-MOVD           mmxreg,reg32                    \360\2\x0F\x6E\110                              PENT,MMX
-MOVD           mem,mmxreg                      \360\2\x0F\x7E\101                              PENT,MMX,SD
-MOVD           reg32,mmxreg                    \360\2\x0F\x7E\101                              PENT,MMX
-MOVD           xmmreg,mem                      \360\320\2\x0F\x6E\110                          X64,SD
-MOVD           xmmreg,reg32                    \360\320\2\x0F\x6E\110                          X64
-MOVD           mem,xmmreg                      \360\320\2\x0F\x7E\101                          X64,SD
-MOVD           reg32,xmmreg                    \360\320\2\x0F\x7E\101                          X64,SSE
+MOVD           mmxreg,rm32                     \360\2\x0F\x6E\110                              PENT,MMX,SSE2
+MOVD           rm32,mmxreg                     \360\2\x0F\x7E\101                              PENT,MMX,SSE2
+MOVD           xmmreg,rm32                     \360\320\2\x0F\x6E\110                          SSE2
+MOVD           rm32,xmmreg                     \360\320\2\x0F\x7E\101                          SSE2
 MOVQ           mmxreg,mmxrm                    \360\323\2\x0F\x6F\110                          PENT,MMX,SQ
 MOVQ           mmxrm,mmxreg                    \360\323\2\x0F\x7F\101                          PENT,MMX,SQ
 MOVQ           mmxreg,rm64                     \360\2\x0F\x6E\110                              X64,MMX
@@ -1423,35 +1427,35 @@ SETcc           mem                             \1\x0F\330\x90\200                              386,SB
 SETcc          reg8                            \1\x0F\330\x90\200                              386
 
 ;# Katmai Streaming SIMD instructions (SSE -- a.k.a. KNI, XMM, MMX2)
-ADDPS          xmmreg,xmmrm                    \360\2\x0F\x58\110                              KATMAI,SSE
-ADDSS          xmmreg,xmmrm                    \363\2\x0F\x58\110                              KATMAI,SSE,SD
-ANDNPS         xmmreg,xmmrm                    \360\2\x0F\x55\110                              KATMAI,SSE
-ANDPS          xmmreg,xmmrm                    \360\2\x0F\x54\110                              KATMAI,SSE
-CMPEQPS                xmmreg,xmmrm                    \360\2\x0F\xC2\110\1\x00                        KATMAI,SSE
-CMPEQSS                xmmreg,xmmrm                    \363\2\x0F\xC2\110\1\x00                        KATMAI,SSE
-CMPLEPS                xmmreg,xmmrm                    \360\2\x0F\xC2\110\1\x02                        KATMAI,SSE
-CMPLESS                xmmreg,xmmrm                    \363\2\x0F\xC2\110\1\x02                        KATMAI,SSE
-CMPLTPS                xmmreg,xmmrm                    \360\2\x0F\xC2\110\1\x01                        KATMAI,SSE
-CMPLTSS                xmmreg,xmmrm                    \363\2\x0F\xC2\110\1\x01                        KATMAI,SSE
-CMPNEQPS       xmmreg,xmmrm                    \360\2\x0F\xC2\110\1\x04                        KATMAI,SSE
-CMPNEQSS       xmmreg,xmmrm                    \363\2\x0F\xC2\110\1\x04                        KATMAI,SSE
-CMPNLEPS       xmmreg,xmmrm                    \360\2\x0F\xC2\110\1\x06                        KATMAI,SSE
-CMPNLESS       xmmreg,xmmrm                    \363\2\x0F\xC2\110\1\x06                        KATMAI,SSE
-CMPNLTPS       xmmreg,xmmrm                    \360\2\x0F\xC2\110\1\x05                        KATMAI,SSE
-CMPNLTSS       xmmreg,xmmrm                    \363\2\x0F\xC2\110\1\x05                        KATMAI,SSE
-CMPORDPS       xmmreg,xmmrm                    \360\2\x0F\xC2\110\1\x07                        KATMAI,SSE
-CMPORDSS       xmmreg,xmmrm                    \363\2\x0F\xC2\110\1\x07                        KATMAI,SSE
-CMPUNORDPS     xmmreg,xmmrm                    \360\2\x0F\xC2\110\1\x03                        KATMAI,SSE
-CMPUNORDSS     xmmreg,xmmrm                    \363\2\x0F\xC2\110\1\x03                        KATMAI,SSE
+ADDPS          xmmreg,xmmrm128                 \360\2\x0F\x58\110                              KATMAI,SSE
+ADDSS          xmmreg,xmmrm32                  \363\2\x0F\x58\110                              KATMAI,SSE
+ANDNPS         xmmreg,xmmrm128                 \360\2\x0F\x55\110                              KATMAI,SSE
+ANDPS          xmmreg,xmmrm128                 \360\2\x0F\x54\110                              KATMAI,SSE
+CMPEQPS                xmmreg,xmmrm128                 \360\2\x0F\xC2\110\1\x00                        KATMAI,SSE
+CMPEQSS                xmmreg,xmmrm32                  \363\2\x0F\xC2\110\1\x00                        KATMAI,SSE
+CMPLEPS                xmmreg,xmmrm128                 \360\2\x0F\xC2\110\1\x02                        KATMAI,SSE
+CMPLESS                xmmreg,xmmrm32                  \363\2\x0F\xC2\110\1\x02                        KATMAI,SSE
+CMPLTPS                xmmreg,xmmrm128                 \360\2\x0F\xC2\110\1\x01                        KATMAI,SSE
+CMPLTSS                xmmreg,xmmrm32                  \363\2\x0F\xC2\110\1\x01                        KATMAI,SSE
+CMPNEQPS       xmmreg,xmmrm128                 \360\2\x0F\xC2\110\1\x04                        KATMAI,SSE
+CMPNEQSS       xmmreg,xmmrm32                  \363\2\x0F\xC2\110\1\x04                        KATMAI,SSE
+CMPNLEPS       xmmreg,xmmrm128                 \360\2\x0F\xC2\110\1\x06                        KATMAI,SSE
+CMPNLESS       xmmreg,xmmrm32                  \363\2\x0F\xC2\110\1\x06                        KATMAI,SSE
+CMPNLTPS       xmmreg,xmmrm128                 \360\2\x0F\xC2\110\1\x05                        KATMAI,SSE
+CMPNLTSS       xmmreg,xmmrm32                  \363\2\x0F\xC2\110\1\x05                        KATMAI,SSE
+CMPORDPS       xmmreg,xmmrm128                 \360\2\x0F\xC2\110\1\x07                        KATMAI,SSE
+CMPORDSS       xmmreg,xmmrm32                  \363\2\x0F\xC2\110\1\x07                        KATMAI,SSE
+CMPUNORDPS     xmmreg,xmmrm128                 \360\2\x0F\xC2\110\1\x03                        KATMAI,SSE
+CMPUNORDSS     xmmreg,xmmrm32                  \363\2\x0F\xC2\110\1\x03                        KATMAI,SSE
 ; CMPPS/CMPSS must come after the specific ops; that way the disassembler will find the
 ; specific ops first and only disassemble illegal ones as cmpps/cmpss.
 CMPPS          xmmreg,mem,imm                  \360\2\x0F\xC2\110\26                           KATMAI,SSE,SB,AR2
 CMPPS          xmmreg,xmmreg,imm               \360\2\x0F\xC2\110\26                           KATMAI,SSE,SB,AR2
 CMPSS          xmmreg,mem,imm                  \363\2\x0F\xC2\110\26                           KATMAI,SSE,SB,AR2
 CMPSS          xmmreg,xmmreg,imm               \363\2\x0F\xC2\110\26                           KATMAI,SSE,SB,AR2
-COMISS         xmmreg,xmmrm                    \360\2\x0F\x2F\110                              KATMAI,SSE
-CVTPI2PS       xmmreg,mmxrm                    \360\2\x0F\x2A\110                              KATMAI,SSE,MMX,SQ
-CVTPS2PI       mmxreg,xmmrm                    \360\2\x0F\x2D\110                              KATMAI,SSE,MMX,SQ
+COMISS         xmmreg,xmmrm32                  \360\2\x0F\x2F\110                              KATMAI,SSE
+CVTPI2PS       xmmreg,mmxrm64                  \360\2\x0F\x2A\110                              KATMAI,SSE,MMX
+CVTPS2PI       mmxreg,xmmrm64                  \360\2\x0F\x2D\110                              KATMAI,SSE,MMX
 CVTSI2SS       xmmreg,mem                      \363\2\x0F\x2A\110                              KATMAI,SSE,SD,AR1,ND
 CVTSI2SS       xmmreg,rm32                     \363\2\x0F\x2A\110                              KATMAI,SSE,SD,AR1
 CVTSI2SS       xmmreg,rm64                     \324\363\2\x0F\x2A\110                          X64,SSE,SQ,AR1
@@ -1462,52 +1466,46 @@ CVTSS2SI        reg64,mem                       \324\363\2\x0F\x2D\110                          X64,SSE,SD,AR1
 CVTTPS2PI      mmxreg,xmmrm                    \360\2\x0F\x2C\110                              KATMAI,SSE,MMX,SQ
 CVTTSS2SI      reg32,xmmrm                     \363\2\x0F\x2C\110                              KATMAI,SSE,SD,AR1
 CVTTSS2SI      reg64,xmmrm                     \324\363\2\x0F\x2C\110                          X64,SSE,SD,AR1
-DIVPS          xmmreg,xmmrm                    \360\2\x0F\x5E\110                              KATMAI,SSE
-DIVSS          xmmreg,xmmrm                    \363\2\x0F\x5E\110                              KATMAI,SSE
-LDMXCSR                mem                             \2\x0F\xAE\202                                  KATMAI,SSE,SD
-MAXPS          xmmreg,xmmrm                    \360\2\x0F\x5F\110                              KATMAI,SSE
-MAXSS          xmmreg,xmmrm                    \363\2\x0F\x5F\110                              KATMAI,SSE
-MINPS          xmmreg,xmmrm                    \360\2\x0F\x5D\110                              KATMAI,SSE
-MINSS          xmmreg,xmmrm                    \363\2\x0F\x5D\110                              KATMAI,SSE
-MOVAPS         xmmreg,mem                      \360\2\x0F\x28\110                              KATMAI,SSE
-MOVAPS         mem,xmmreg                      \360\2\x0F\x29\101                              KATMAI,SSE
-MOVAPS         xmmreg,xmmreg                   \360\2\x0F\x28\110                              KATMAI,SSE
-MOVAPS         xmmreg,xmmreg                   \360\2\x0F\x29\101                              KATMAI,SSE
-MOVHPS         xmmreg,mem                      \360\2\x0F\x16\110                              KATMAI,SSE
-MOVHPS         mem,xmmreg                      \360\2\x0F\x17\101                              KATMAI,SSE
+DIVPS          xmmreg,xmmrm128                 \360\2\x0F\x5E\110                              KATMAI,SSE
+DIVSS          xmmreg,xmmrm32                  \363\2\x0F\x5E\110                              KATMAI,SSE
+LDMXCSR                mem32                           \2\x0F\xAE\202                                  KATMAI,SSE
+MAXPS          xmmreg,xmmrm128                 \360\2\x0F\x5F\110                              KATMAI,SSE
+MAXSS          xmmreg,xmmrm32                  \363\2\x0F\x5F\110                              KATMAI,SSE
+MINPS          xmmreg,xmmrm128                 \360\2\x0F\x5D\110                              KATMAI,SSE
+MINSS          xmmreg,xmmrm32                  \363\2\x0F\x5D\110                              KATMAI,SSE
+MOVAPS         xmmreg,xmmrm128                 \360\2\x0F\x28\110                              KATMAI,SSE
+MOVAPS         xmmrm128,xmmreg                 \360\2\x0F\x29\101                              KATMAI,SSE
+MOVHPS         xmmreg,mem64                    \360\2\x0F\x16\110                              KATMAI,SSE
+MOVHPS         mem64,xmmreg                    \360\2\x0F\x17\101                              KATMAI,SSE
 MOVLHPS                xmmreg,xmmreg                   \360\2\x0F\x16\110                              KATMAI,SSE
-MOVLPS         xmmreg,mem                      \360\2\x0F\x12\110                              KATMAI,SSE
-MOVLPS         mem,xmmreg                      \360\2\x0F\x13\101                              KATMAI,SSE
+MOVLPS         xmmreg,mem64                    \360\2\x0F\x12\110                              KATMAI,SSE
+MOVLPS         mem64,xmmreg                    \360\2\x0F\x13\101                              KATMAI,SSE
 MOVHLPS                xmmreg,xmmreg                   \360\2\x0F\x12\110                              KATMAI,SSE
 MOVMSKPS       reg32,xmmreg                    \360\2\x0F\x50\110                              KATMAI,SSE
 MOVMSKPS       reg64,xmmreg                    \360\324\2\x0F\x50\110                          X64,SSE
-MOVNTPS                mem,xmmreg                      \360\2\x0F\x2B\101                              KATMAI,SSE
-MOVSS          xmmreg,mem                      \363\2\x0F\x10\110                              KATMAI,SSE
-MOVSS          mem,xmmreg                      \363\2\x0F\x11\101                              KATMAI,SSE
+MOVNTPS                mem128,xmmreg                   \360\2\x0F\x2B\101                              KATMAI,SSE
+MOVSS          xmmreg,xmmrm32                  \363\2\x0F\x10\110                              KATMAI,SSE
+MOVSS          mem32,xmmreg                    \363\2\x0F\x11\101                              KATMAI,SSE
 MOVSS          xmmreg,xmmreg                   \363\2\x0F\x10\110                              KATMAI,SSE
-MOVSS          xmmreg,xmmreg                   \363\2\x0F\x11\101                              KATMAI,SSE
-MOVUPS         xmmreg,mem                      \360\2\x0F\x10\110                              KATMAI,SSE
-MOVUPS         mem,xmmreg                      \360\2\x0F\x11\101                              KATMAI,SSE
-MOVUPS         xmmreg,xmmreg                   \360\2\x0F\x10\110                              KATMAI,SSE
-MOVUPS         xmmreg,xmmreg                   \360\2\x0F\x11\101                              KATMAI,SSE
-MULPS          xmmreg,xmmrm                    \360\2\x0F\x59\110                              KATMAI,SSE
-MULSS          xmmreg,xmmrm                    \363\2\x0F\x59\110                              KATMAI,SSE
-ORPS           xmmreg,xmmrm                    \360\2\x0F\x56\110                              KATMAI,SSE
-RCPPS          xmmreg,xmmrm                    \360\2\x0F\x53\110                              KATMAI,SSE
-RCPSS          xmmreg,xmmrm                    \363\2\x0F\x53\110                              KATMAI,SSE
-RSQRTPS                xmmreg,xmmrm                    \360\2\x0F\x52\110                              KATMAI,SSE
-RSQRTSS                xmmreg,xmmrm                    \363\2\x0F\x52\110                              KATMAI,SSE
-SHUFPS         xmmreg,mem,imm                  \360\2\x0F\xC6\110\26                           KATMAI,SSE,SB,AR2
-SHUFPS         xmmreg,xmmreg,imm               \360\2\x0F\xC6\110\26                           KATMAI,SSE,SB,AR2
-SQRTPS         xmmreg,xmmrm                    \360\2\x0F\x51\110                              KATMAI,SSE
-SQRTSS         xmmreg,xmmrm                    \363\2\x0F\x51\110                              KATMAI,SSE
-STMXCSR                mem                             \2\x0F\xAE\203                                  KATMAI,SSE,SD
-SUBPS          xmmreg,xmmrm                    \360\2\x0F\x5C\110                              KATMAI,SSE
-SUBSS          xmmreg,xmmrm                    \363\2\x0F\x5C\110                              KATMAI,SSE
-UCOMISS                xmmreg,xmmrm                    \360\2\x0F\x2E\110                              KATMAI,SSE
-UNPCKHPS       xmmreg,xmmrm                    \360\2\x0F\x15\110                              KATMAI,SSE
-UNPCKLPS       xmmreg,xmmrm                    \360\2\x0F\x14\110                              KATMAI,SSE
-XORPS          xmmreg,xmmrm                    \360\2\x0F\x57\110                              KATMAI,SSE
+MOVUPS         xmmreg,xmmrm128                 \360\2\x0F\x10\110                              KATMAI,SSE
+MOVUPS         xmmrm128,xmmreg                 \360\2\x0F\x11\101                              KATMAI,SSE
+MULPS          xmmreg,xmmrm128                 \360\2\x0F\x59\110                              KATMAI,SSE
+MULSS          xmmreg,xmmrm32                  \363\2\x0F\x59\110                              KATMAI,SSE
+ORPS           xmmreg,xmmrm128                 \360\2\x0F\x56\110                              KATMAI,SSE
+RCPPS          xmmreg,xmmrm128                 \360\2\x0F\x53\110                              KATMAI,SSE
+RCPSS          xmmreg,xmmrm32                  \363\2\x0F\x53\110                              KATMAI,SSE
+RSQRTPS                xmmreg,xmmrm128                 \360\2\x0F\x52\110                              KATMAI,SSE
+RSQRTSS                xmmreg,xmmrm32                  \363\2\x0F\x52\110                              KATMAI,SSE
+SHUFPS         xmmreg,xmmrm128,imm8            \360\2\x0F\xC6\110\26                           KATMAI,SSE
+SQRTPS         xmmreg,xmmrm128                 \360\2\x0F\x51\110                              KATMAI,SSE
+SQRTSS         xmmreg,xmmrm32                  \363\2\x0F\x51\110                              KATMAI,SSE
+STMXCSR                mem32                           \2\x0F\xAE\203                                  KATMAI,SSE
+SUBPS          xmmreg,xmmrm128                 \360\2\x0F\x5C\110                              KATMAI,SSE
+SUBSS          xmmreg,xmmrm32                  \363\2\x0F\x5C\110                              KATMAI,SSE
+UCOMISS                xmmreg,xmmrm32                  \360\2\x0F\x2E\110                              KATMAI,SSE
+UNPCKHPS       xmmreg,xmmrm128                 \360\2\x0F\x15\110                              KATMAI,SSE
+UNPCKLPS       xmmreg,xmmrm128                 \360\2\x0F\x14\110                              KATMAI,SSE
+XORPS          xmmreg,xmmrm128                 \360\2\x0F\x57\110                              KATMAI,SSE
 
 ;# Introduced in Deschutes but necessary for SSE support
 FXRSTOR                mem                             [m:     0f ae /1]                               P6,SSE,FPU
@@ -1701,8 +1699,8 @@ CMPUNORDPD        xmmreg,xmmrm                    \361\2\x0F\xC2\110\1\x03                        WILLAMETTE,SSE2,SO
 CMPUNORDSD     xmmreg,xmmrm                    \362\2\x0F\xC2\110\1\x03                        WILLAMETTE,SSE2
 ; CMPPD/CMPSD must come after the specific ops; that way the disassembler will find the
 ; specific ops first and only disassemble illegal ones as cmppd/cmpsd.
-CMPPD          xmmreg,xmmrm,imm                \361\2\x0F\xC2\110\26                           WILLAMETTE,SSE2,SM2,SB,AR2
-CMPSD          xmmreg,xmmrm,imm                \362\2\x0F\xC2\110\26                           WILLAMETTE,SSE2,SB,AR2
+CMPPD          xmmreg,xmmrm128,imm8            \361\2\x0F\xC2\110\26                           WILLAMETTE,SSE2
+CMPSD          xmmreg,xmmrm128,imm8            \362\2\x0F\xC2\110\26                           WILLAMETTE,SSE2
 COMISD         xmmreg,xmmrm                    \361\2\x0F\x2F\110                              WILLAMETTE,SSE2
 CVTDQ2PD       xmmreg,xmmrm                    \363\2\x0F\xE6\110                              WILLAMETTE,SSE2,SQ
 CVTDQ2PS       xmmreg,xmmrm                    \360\2\x0F\x5B\110                              WILLAMETTE,SSE2,SO
@@ -1762,9 +1760,9 @@ SQRTSD            xmmreg,xmmrm                    \362\2\x0F\x51\110                              WILLAMETTE,SSE2
 SUBPD          xmmreg,xmmrm                    \361\2\x0F\x5C\110                              WILLAMETTE,SSE2,SO
 SUBSD          xmmreg,xmmrm                    \362\2\x0F\x5C\110                              WILLAMETTE,SSE2
 UCOMISD                xmmreg,xmmrm                    \361\2\x0F\x2E\110                              WILLAMETTE,SSE2
-UNPCKHPD       xmmreg,xmmrm                    \361\2\x0F\x15\110                              WILLAMETTE,SSE2,SO
-UNPCKLPD       xmmreg,xmmrm                    \361\2\x0F\x14\110                              WILLAMETTE,SSE2,SO
-XORPD          xmmreg,xmmrm                    \361\2\x0F\x57\110                              WILLAMETTE,SSE2,SO
+UNPCKHPD       xmmreg,xmmrm128                 \361\2\x0F\x15\110                              WILLAMETTE,SSE2
+UNPCKLPD       xmmreg,xmmrm128                 \361\2\x0F\x14\110                              WILLAMETTE,SSE2
+XORPD          xmmreg,xmmrm128                 \361\2\x0F\x57\110                              WILLAMETTE,SSE2
 
 ;# Prescott New Instructions (SSE3)
 ADDSUBPD       xmmreg,xmmrm                    \361\2\x0F\xD0\110                              PRESCOTT,SSE3,SO
@@ -2436,6 +2434,7 @@ VMOVUPS           xmmrm128,xmmreg                 [mr:    vex.128.0f 11 /r]                       AVX,SANDYBRIDGE
 VMOVUPS                ymmreg,ymmrm256                 [rm:    vex.256.0f 10 /r]                       AVX,SANDYBRIDGE
 VMOVUPS                ymmrm256,ymmreg                 [mr:    vex.256.0f 11 /r]                       AVX,SANDYBRIDGE
 VMPSADBW       xmmreg,xmmreg*,xmmrm128,imm8    [rvmi:  vex.nds.128.66.0f3a 42 /r ib]           AVX,SANDYBRIDGE
+VMPSADBW       ymmreg,ymmreg*,ymmrm256,imm8    [rvmi:  vex.nds.256.66.0f3a 42 /r ib]           FUTURE,AVX2
 VMULPD         xmmreg,xmmreg*,xmmrm128         [rvm:   vex.nds.128.66.0f 59 /r]                AVX,SANDYBRIDGE
 VMULPD         ymmreg,ymmreg*,ymmrm256         [rvm:   vex.nds.256.66.0f 59 /r]                AVX,SANDYBRIDGE
 VMULPS         xmmreg,xmmreg*,xmmrm128         [rvm:   vex.nds.128.0f 59 /r]                   AVX,SANDYBRIDGE
@@ -2443,14 +2442,17 @@ VMULPS          ymmreg,ymmreg*,ymmrm256         [rvm:   vex.nds.256.0f 59 /r]                   AVX,SANDYBRIDGE
 VMULSD         xmmreg,xmmreg*,xmmrm64          [rvm:   vex.nds.lig.f2.0f 59 /r]                AVX,SANDYBRIDGE
 VMULSS         xmmreg,xmmreg*,xmmrm32          [rvm:   vex.nds.lig.f3.0f 59 /r]                AVX,SANDYBRIDGE
 VORPD          xmmreg,xmmreg*,xmmrm128         [rvm:   vex.nds.128.66.0f 56 /r]                AVX,SANDYBRIDGE
-VORPD          ymmreg,ymmreg*,ymmrm256         [rvm:   vex.nds.256.66.0f 56 /r]                AVX,SANDYBRIDGE
+VORPD          ymmreg,ymmreg*,ymmrm256         [rvm:   vex.nds.256.66.0f 56 /r]                FUTURE,AVX2
 VORPS          xmmreg,xmmreg*,xmmrm128         [rvm:   vex.nds.128.0f 56 /r]                   AVX,SANDYBRIDGE
 VORPS          ymmreg,ymmreg*,ymmrm256         [rvm:   vex.nds.256.0f 56 /r]                   AVX,SANDYBRIDGE
 VPABSB         xmmreg,xmmrm128                 [rm:    vex.128.66.0f38 1c /r]                  AVX,SANDYBRIDGE
+VPABSB         ymmreg,ymmrm256                 [rm:    vex.256.66.0f38 1c /r]                  FUTURE,AVX2
 VPABSW         xmmreg,xmmrm128                 [rm:    vex.128.66.0f38 1d /r]                  AVX,SANDYBRIDGE
 VPABSD         xmmreg,xmmrm128                 [rm:    vex.128.66.0f38 1e /r]                  AVX,SANDYBRIDGE
 VPACKSSWB      xmmreg,xmmreg*,xmmrm128         [rvm:   vex.nds.128.66.0f 63 /r]                AVX,SANDYBRIDGE
+VPACKSSWB      ymmreg,ymmreg*,ymmrm256         [rvm:   vex.nds.256.66.0f 63 /r]                FUTURE,AVX2
 VPACKSSDW      xmmreg,xmmreg*,xmmrm128         [rvm:   vex.nds.128.66.0f 6b /r]                AVX,SANDYBRIDGE
+VPACKSSDW      ymmreg,ymmreg*,ymmrm256         [rvm:   vex.nds.256.66.0f 6b /r]                FUTURE,AVX2
 VPACKUSWB      xmmreg,xmmreg*,xmmrm128         [rvm:   vex.nds.128.66.0f 67 /r]                AVX,SANDYBRIDGE
 VPACKUSDW      xmmreg,xmmreg*,xmmrm128         [rvm:   vex.nds.128.66.0f38 2b /r]              AVX,SANDYBRIDGE
 VPADDB         xmmreg,xmmreg*,xmmrm128         [rvm:   vex.nds.128.66.0f fc /r]                AVX,SANDYBRIDGE
@@ -2480,6 +2482,7 @@ VPCMPGTB  xmmreg,xmmreg*,xmmrm128         [rvm:   vex.nds.128.66.0f 64 /r]                AVX,SANDYBRIDG
 VPCMPGTW       xmmreg,xmmreg*,xmmrm128         [rvm:   vex.nds.128.66.0f 65 /r]                AVX,SANDYBRIDGE
 VPCMPGTD       xmmreg,xmmreg*,xmmrm128         [rvm:   vex.nds.128.66.0f 66 /r]                AVX,SANDYBRIDGE
 VPCMPGTQ       xmmreg,xmmreg*,xmmrm128         [rvm:   vex.nds.128.66.0f 37 /r]                AVX,SANDYBRIDGE
+VPERMD         ymmreg,ymmreg,ymmrm256          [rvm:   vex.nds.256.66.0f38.w0 36 /r]           FUTURE,AVX2
 VPERMILPD      xmmreg,xmmreg,xmmrm128          [rvm:   vex.nds.128.66.0f38.w0 0d /r]           AVX,SANDYBRIDGE
 VPERMILPD      ymmreg,ymmreg,ymmrm256          [rvm:   vex.nds.256.66.0f38.w0 0d /r]           AVX,SANDYBRIDGE
 VPERMILPD      xmmreg,xmmrm128,imm8            [rmi:   vex.128.66.0f3a.w0 05 /r ib]            AVX,SANDYBRIDGE
@@ -2488,7 +2491,7 @@ VPERMILPS xmmreg,xmmreg,xmmrm128          [rvm:   vex.nds.128.66.0f38.w0 0c /r]           AVX,SANDY
 VPERMILPS      ymmreg,ymmreg,ymmrm256          [rvm:   vex.nds.256.66.0f38.w0 0c /r]           AVX,SANDYBRIDGE
 VPERMILPS      xmmreg,xmmrm128,imm8            [rmi:   vex.128.66.0f3a.w0 04 /r ib]            AVX,SANDYBRIDGE
 VPERMILPS      ymmreg,ymmrm256,imm8            [rmi:   vex.256.66.0f3a.w0 04 /r ib]            AVX,SANDYBRIDGE
-VPERM2F128     ymmreg,ymmreg,ymmrm256,imm8             [rvmi:  vex.nds.256.66.0f3a.w0 06 /r ib]        AVX,SANDYBRIDGE
+VPERM2F128     ymmreg,ymmreg,ymmrm256,imm8     [rvmi:  vex.nds.256.66.0f3a.w0 06 /r ib]        AVX,SANDYBRIDGE
 VPEXTRB                reg64,xmmreg,imm8               [mri:   vex.128.66.0f3a.w0 14 /r ib]            AVX,SANDYBRIDGE,LONG
 VPEXTRB                reg32,xmmreg,imm8               [mri:   vex.128.66.0f3a.w0 14 /r ib]            AVX,SANDYBRIDGE
 VPEXTRB                mem8,xmmreg,imm8                [mri:   vex.128.66.0f3a.w0 14 /r ib]            AVX,SANDYBRIDGE
@@ -3115,6 +3118,11 @@ VPSHLQ           xmmreg,xmmreg*,xmmrm128         [rvm:   xop.m9.w1.nds.l0.p0 97 /r]              AMD,SSE5
 VPSHLW         xmmreg,xmmrm128*,xmmreg         [rmv:   xop.m9.w0.nds.l0.p0 95 /r]              AMD,SSE5
 VPSHLW         xmmreg,xmmreg*,xmmrm128         [rvm:   xop.m9.w1.nds.l0.p0 95 /r]              AMD,SSE5
 
+;# AVX2
+VGATHERDPD     xmmreg,mem32,xmmreg             [rmv:   vm32x vex.dds.128.66.0f38.w1 92 /r]     FUTURE,AVX2
+VGATHERQPD     xmmreg,mem64,xmmreg             [rmv:   vm64x vex.dds.128.66.0f38.w1 93 /r]     FUTURE,AVX2
+VGATHERDPD     ymmreg,mem32,ymmreg             [rmv:   vm32x vex.dds.256.66.0f38.w1 92 /r]     FUTURE,AVX2
+VGATHERQPD     ymmreg,mem64,ymmreg             [rmv:   vm64y vex.dds.256.66.0f38.w1 92 /r]     FUTURE,AVX2
 
 ;# Systematic names for the hinting nop instructions
 ; These should be last in the file
diff --git a/insns.h b/insns.h
index 4f3dd80..173a416 100644 (file)
--- a/insns.h
+++ b/insns.h
@@ -87,6 +87,7 @@ extern const uint8_t nasm_bytecodes[];
 #define IF_AR4   0x00000140UL  /* SB, SW, SD applies to argument 4 */
 #define IF_ARMASK 0x000001C0UL  /* mask for unsized argument spec */
 #define IF_ARSHFT 6            /* LSB in IF_ARMASK */
+#define IF_OPT    0x00000200UL  /* optimizing assembly only */
 /* The next 3 bits aren't actually used for anything */
 #define IF_PRIV   0x00000000UL  /* it's a privileged instruction */
 #define IF_SMM    0x00000000UL  /* it's only valid in SMM */
@@ -107,11 +108,12 @@ extern const uint8_t nasm_bytecodes[];
 #define IF_SSE42  0x00800000UL  /* HACK NEED TO REORGANIZE THESE BITS */
 #define IF_SSE5   0x00800000UL  /* HACK NEED TO REORGANIZE THESE BITS */
 #define IF_AVX    0x00800000UL  /* HACK NEED TO REORGANIZE THESE BITS */
+#define IF_AVX2   0x00800000UL  /* HACK NEED TO REORGANIZE THESE BITS */
 #define IF_FMA    0x00800000UL  /* HACK NEED TO REORGANIZE THESE BITS */
 #define IF_PMASK  0xFF000000UL  /* the mask for processor types */
 #define IF_PLEVEL 0x0F000000UL  /* the mask for processor instr. level */
                                 /* also the highest possible processor */
-#define IF_PFMASK 0xF01FFF00UL  /* the mask for disassembly "prefer" */
+#define IF_PFMASK 0xF01FF800UL  /* the mask for disassembly "prefer" */
 #define IF_8086   0x00000000UL  /* 8086 instruction */
 #define IF_186    0x01000000UL  /* 186+ instruction */
 #define IF_286    0x02000000UL  /* 286+ instruction */
index 5ffdce2..0b29757 100755 (executable)
--- a/insns.pl
+++ b/insns.pl
@@ -1,7 +1,7 @@
 #!/usr/bin/perl
 ## --------------------------------------------------------------------------
-##   
-##   Copyright 1996-2009 The NASM Authors - All Rights Reserved
+##
+##   Copyright 1996-2010 The NASM Authors - All Rights Reserved
 ##   See the file AUTHORS included with the NASM distribution for
 ##   the specific copyright holders.
 ##
@@ -15,7 +15,7 @@
 ##     copyright notice, this list of conditions and the following
 ##     disclaimer in the documentation and/or other materials provided
 ##     with the distribution.
-##     
+##
 ##     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 ##     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 ##     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
@@ -52,9 +52,9 @@ $vex_classes = scalar(@vex_class);
 for ($c = 0; $c < $vex_classes; $c++) {
     $vexmap{$vex_class[$c]} = $c;
     for ($m = 0; $m < 32; $m++) {
-       for ($p = 0; $p < 4; $p++) {
-           push(@vexlist, sprintf("%s%02X%01X", $vex_class[$c], $m, $p));
-       }
+        for ($p = 0; $p < 4; $p++) {
+            push(@vexlist, sprintf("%s%02X%01X", $vex_class[$c], $m, $p));
+        }
     }
 }
 @disasm_prefixes = (@vexlist, @disasm_prefixes);
@@ -67,13 +67,13 @@ print STDERR "Reading insns.dat...\n";
 undef $output;
 foreach $arg ( @ARGV ) {
     if ( $arg =~ /^\-/ ) {
-       if  ( $arg =~ /^\-([abdin])$/ ) {
-           $output = $1;
-       } else {
-           die "$0: Unknown option: ${arg}\n";
-       }
+        if  ( $arg =~ /^\-([abdin])$/ ) {
+            $output = $1;
+        } else {
+            die "$0: Unknown option: ${arg}\n";
+        }
     } else {
-       push (@args, $arg);
+        push (@args, $arg);
     }
 }
 
@@ -91,72 +91,72 @@ while (<F>) {
     next if ( /^\s*(\;.*|)$/ );   # comments or blank lines
 
     unless (/^\s*(\S+)\s+(\S+)\s+(\S+|\[.*\])\s+(\S+)\s*$/) {
-       warn "line $line does not contain four fields\n";
-       next;
+        warn "line $line does not contain four fields\n";
+        next;
     }
     @fields = ($1, $2, $3, $4);
     @field_list = ([@fields, 0]);
 
     if ($fields[1] =~ /\*/) {
-       # This instruction has relaxed form(s)
-       if ($fields[2] !~ /^\[/) {
-           warn "line $line has an * operand but uses raw bytecodes\n";
-           next;
-       }
-
-       $opmask = 0;
-       @ops = split(/,/, $fields[1]);
-       for ($oi = 0; $oi < scalar @ops; $oi++) {
-           if ($ops[$oi] =~ /\*$/) {
-               if ($oi == 0) {
-                   warn "line $line has a first operand with a *\n";
-                   next;
-               }
-               $opmask |= 1 << $oi;
-           }
-       }
-
-       for ($oi = 1; $oi < (1 << scalar @ops); $oi++) {
-           if (($oi & ~$opmask) == 0) {
-               my @xops = ();
-               my $omask = ~$oi;
-               for ($oj = 0; $oj < scalar(@ops); $oj++) {
-                   if ($omask & 1) {
-                       push(@xops, $ops[$oj]);
-                   }
-                   $omask >>= 1;
-               }
-               push(@field_list, [$fields[0], join(',', @xops),
-                                  $fields[2], $fields[3], $oi]);
-           }
-       }
+        # This instruction has relaxed form(s)
+        if ($fields[2] !~ /^\[/) {
+            warn "line $line has an * operand but uses raw bytecodes\n";
+            next;
+        }
+
+        $opmask = 0;
+        @ops = split(/,/, $fields[1]);
+        for ($oi = 0; $oi < scalar @ops; $oi++) {
+            if ($ops[$oi] =~ /\*$/) {
+                if ($oi == 0) {
+                    warn "line $line has a first operand with a *\n";
+                    next;
+                }
+                $opmask |= 1 << $oi;
+            }
+        }
+
+        for ($oi = 1; $oi < (1 << scalar @ops); $oi++) {
+            if (($oi & ~$opmask) == 0) {
+                my @xops = ();
+                my $omask = ~$oi;
+                for ($oj = 0; $oj < scalar(@ops); $oj++) {
+                    if ($omask & 1) {
+                        push(@xops, $ops[$oj]);
+                    }
+                    $omask >>= 1;
+                }
+                push(@field_list, [$fields[0], join(',', @xops),
+                     $fields[2], $fields[3], $oi]);
+            }
+        }
     }
 
     foreach $fptr (@field_list) {
-       @fields = @$fptr;
-       ($formatted, $nd) = format_insn(@fields);
-       if ($formatted) {
-           $insns++;
-           $aname = "aa_$fields[0]";
-           push @$aname, $formatted;
-       }
-       if ( $fields[0] =~ /cc$/ ) {
-           # Conditional instruction
-           $k_opcodes_cc{$fields[0]}++;
-       } else {
-           # Unconditional instruction
-           $k_opcodes{$fields[0]}++;
-       }
-       if ($formatted && !$nd) {
-           push @big, $formatted;
-           my @sseq = startseq($fields[2], $fields[4]);
-           foreach $i (@sseq) {
-               if (!defined($dinstables{$i})) {
-                   $dinstables{$i} = [];
-               }
-               push(@{$dinstables{$i}}, $#big);
-           }
-       }
+        @fields = @$fptr;
+        ($formatted, $nd) = format_insn(@fields);
+        if ($formatted) {
+            $insns++;
+            $aname = "aa_$fields[0]";
+            push @$aname, $formatted;
+        }
+        if ( $fields[0] =~ /cc$/ ) {
+            # Conditional instruction
+            $k_opcodes_cc{$fields[0]}++;
+        } else {
+            # Unconditional instruction
+            $k_opcodes{$fields[0]}++;
+        }
+        if ($formatted && !$nd) {
+            push @big, $formatted;
+            my @sseq = startseq($fields[2], $fields[4]);
+            foreach $i (@sseq) {
+                if (!defined($dinstables{$i})) {
+                    $dinstables{$i} = [];
+                }
+                push(@{$dinstables{$i}}, $#big);
+            }
+        }
     }
 }
 
@@ -178,9 +178,9 @@ foreach $bl (@bytecode_list) {
 
     push(@bytecode_array, $bl);
     while ($h ne '') {
-       $bytecode_pos{$h} = $bytecode_next;
-       $h = substr($h, 2);
-       $bytecode_next++;
+        $bytecode_pos{$h} = $bytecode_next;
+        $h = substr($h, 2);
+        $bytecode_next++;
     }
 }
 undef @bytecode_list;
@@ -203,12 +203,12 @@ if ( !defined($output) || $output eq 'b') {
 
     $p = 0;
     foreach $bl (@bytecode_array) {
-       printf B "    /* %5d */ ", $p;
-       foreach $d (@$bl) {
-           printf B "%#o,", $d;
-           $p++;
-       }
-       printf B "\n";
+        printf B "    /* %5d */ ", $p;
+        foreach $d (@$bl) {
+            printf B "%#o,", $d;
+            $p++;
+        }
+        printf B "\n";
     }
     print B "};\n";
 
@@ -217,12 +217,12 @@ if ( !defined($output) || $output eq 'b') {
     print B " * Bytecode frequencies (including reuse):\n";
     print B " *\n";
     for ($i = 0; $i < 32; $i++) {
-       print B " *";
-       for ($j = 0; $j < 256; $j += 32) {
-           print B " |" if ($j);
-           printf B " %3o:%4d", $i+$j, $bytecode_count[$i+$j];
-       }
-       print B "\n";
+        print B " *";
+        for ($j = 0; $j < 256; $j += 32) {
+            print B " |" if ($j);
+            printf B " %3o:%4d", $i+$j, $bytecode_count[$i+$j];
+        }
+        print B "\n";
     }
     print B " */\n";
 
@@ -241,16 +241,16 @@ if ( !defined($output) || $output eq 'a' ) {
     print A "#include \"insns.h\"\n\n";
 
     foreach $i (@opcodes, @opcodes_cc) {
-       print A "static const struct itemplate instrux_${i}[] = {\n";
-       $aname = "aa_$i";
-       foreach $j (@$aname) {
-           print A "    ", codesubst($j), "\n";
-       }
-       print A "    ITEMPLATE_END\n};\n\n";
+        print A "static const struct itemplate instrux_${i}[] = {\n";
+        $aname = "aa_$i";
+        foreach $j (@$aname) {
+            print A "    ", codesubst($j), "\n";
+        }
+        print A "    ITEMPLATE_END\n};\n\n";
     }
     print A "const struct itemplate * const nasm_instructions[] = {\n";
     foreach $i (@opcodes, @opcodes_cc) {
-       print A "    instrux_${i},\n";
+        print A "    instrux_${i},\n";
     }
     print A "};\n";
 
@@ -271,69 +271,69 @@ if ( !defined($output) || $output eq 'd' ) {
     print D "static const struct itemplate instrux[] = {\n";
     $n = 0;
     foreach $j (@big) {
-       printf D "    /* %4d */ %s\n", $n++, codesubst($j);
+        printf D "    /* %4d */ %s\n", $n++, codesubst($j);
     }
     print D "};\n";
 
     foreach $h (sort(keys(%dinstables))) {
-       next if ($h eq '');     # Skip pseudo-instructions
-       print D "\nstatic const struct itemplate * const itable_${h}[] = {\n";
-       foreach $j (@{$dinstables{$h}}) {
-           print D "    instrux + $j,\n";
-       }
-       print D "};\n";
+        next if ($h eq ''); # Skip pseudo-instructions
+            print D "\nstatic const struct itemplate * const itable_${h}[] = {\n";
+        foreach $j (@{$dinstables{$h}}) {
+            print D "    instrux + $j,\n";
+        }
+        print D "};\n";
     }
 
     @prefix_list = ();
     foreach $h (@disasm_prefixes, '') {
-       for ($c = 0; $c < 256; $c++) {
-           $nn = sprintf("%s%02X", $h, $c);
-           if ($is_prefix{$nn} || defined($dinstables{$nn})) {
-               # At least one entry in this prefix table
-               push(@prefix_list, $h);
-               $is_prefix{$h} = 1;
-               last;
-           }
-       }
+        for ($c = 0; $c < 256; $c++) {
+            $nn = sprintf("%s%02X", $h, $c);
+            if ($is_prefix{$nn} || defined($dinstables{$nn})) {
+                # At least one entry in this prefix table
+                push(@prefix_list, $h);
+                $is_prefix{$h} = 1;
+                last;
+            }
+        }
     }
 
     foreach $h (@prefix_list) {
-       print D "\n";
-       print D "static " unless ($h eq '');
-       print D "const struct disasm_index ";
-       print D ($h eq '') ? 'itable' : "itable_$h";
-       print D "[256] = {\n";
-       for ($c = 0; $c < 256; $c++) {
-           $nn = sprintf("%s%02X", $h, $c);
-           if ($is_prefix{$nn}) {
-               die "$fname: ambiguous decoding of $nn\n"
-                   if (defined($dinstables{$nn}));
-               printf D "    /* 0x%02x */ { itable_%s, -1 },\n", $c, $nn;
-           } elsif (defined($dinstables{$nn})) {
-               printf D "    /* 0x%02x */ { itable_%s, %u },\n", $c,
-                   $nn, scalar(@{$dinstables{$nn}});
-           } else {
-               printf D "    /* 0x%02x */ { NULL, 0 },\n", $c;
-           }
-       }
-       print D "};\n";
+        print D "\n";
+        print D "static " unless ($h eq '');
+        print D "const struct disasm_index ";
+        print D ($h eq '') ? 'itable' : "itable_$h";
+        print D "[256] = {\n";
+        for ($c = 0; $c < 256; $c++) {
+            $nn = sprintf("%s%02X", $h, $c);
+            if ($is_prefix{$nn}) {
+                die "$fname: ambiguous decoding of $nn\n"
+                    if (defined($dinstables{$nn}));
+                printf D "    /* 0x%02x */ { itable_%s, -1 },\n", $c, $nn;
+            } elsif (defined($dinstables{$nn})) {
+                printf D "    /* 0x%02x */ { itable_%s, %u },\n", $c,
+                       $nn, scalar(@{$dinstables{$nn}});
+            } else {
+                printf D "    /* 0x%02x */ { NULL, 0 },\n", $c;
+            }
+        }
+        print D "};\n";
     }
 
     printf D "\nconst struct disasm_index * const itable_vex[%d][32][4] =\n",
         $vex_classes;
     print D "{\n";
     for ($c = 0; $c < $vex_classes; $c++) {
-       print D "    {\n";
-       for ($m = 0; $m < 32; $m++) {
-           print D "        { ";
-           for ($p = 0; $p < 4; $p++) {
-               $vp = sprintf("%s%02X%01X", $vex_class[$c], $m, $p);
-               printf D "%-15s",
-                   ($is_prefix{$vp} ? sprintf("itable_%s,", $vp) : 'NULL,');
-           }
-           print D "},\n";
-       }
-       print D "    },\n";
+        print D "    {\n";
+        for ($m = 0; $m < 32; $m++) {
+            print D "        { ";
+            for ($p = 0; $p < 4; $p++) {
+                $vp = sprintf("%s%02X%01X", $vex_class[$c], $m, $p);
+                printf D "%-15s",
+                       ($is_prefix{$vp} ? sprintf("itable_%s,", $vp) : 'NULL,');
+            }
+            print D "},\n";
+        }
+        print D "    },\n";
     }
     print D "};\n";
 
@@ -355,10 +355,10 @@ if ( !defined($output) || $output eq 'i' ) {
     print I "enum opcode {\n";
     $maxlen = 0;
     foreach $i (@opcodes, @opcodes_cc) {
-       print I "\tI_${i},\n";
-       $len = length($i);
-       $len++ if ( $i =~ /cc$/ ); # Condition codes can be 3 characters long
-       $maxlen = $len if ( $len > $maxlen );
+        print I "\tI_${i},\n";
+        $len = length($i);
+        $len++ if ( $i =~ /cc$/ ); # Condition codes can be 3 characters long
+        $maxlen = $len if ( $len > $maxlen );
     }
     print I "\tI_none = -1\n";
     print I "};\n\n";
@@ -381,12 +381,12 @@ if ( !defined($output) || $output eq 'n' ) {
     print N "const char * const nasm_insn_names[] = {";
     $first = 1;
     foreach $i (@opcodes, @opcodes_cc) {
-       print N "," if ( !$first );
-       $first = 0;
-       $ilower = $i;
-       $ilower =~ s/cc$//;     # Remove conditional cc suffix
-       $ilower =~ tr/A-Z/a-z/; # Change to lower case (Perl 4 compatible)
-       print N "\n\t\"${ilower}\"";
+        print N "," if ( !$first );
+        $first = 0;
+        $ilower = $i;
+        $ilower =~ s/cc$//;             # Remove conditional cc suffix
+        $ilower =~ tr/A-Z/a-z/;         # Change to lower case (Perl 4 compatible)
+        print N "\n\t\"${ilower}\"";
     }
     print N "\n};\n";
     close N;
@@ -398,24 +398,24 @@ printf STDERR "Done: %d instructions\n", $insns;
 sub count_bytecodes(@) {
     my $skip = 0;
     foreach my $bc (@_) {
-       if ($skip) {
-           $skip--;
-           next;
-       }
-       $bytecode_count[$bc]++;
-       if ($bc >= 01 && $bc <= 04) {
-           $skip = $bc;
-       } elsif (($bc & ~03) == 010) {
-           $skip = 1;
-       } elsif (($bc & ~013) == 0144) {
-           $skip = 1;
-       } elsif ($bc == 0172) {
-           $skip = 1;
-       } elsif ($bc >= 0260 && $bc <= 0270) {
-           $skip = 2;
-       } elsif ($bc == 0330) {
-           $skip = 1;
-       }
+        if ($skip) {
+            $skip--;
+            next;
+        }
+        $bytecode_count[$bc]++;
+        if ($bc >= 01 && $bc <= 04) {
+            $skip = $bc;
+        } elsif (($bc & ~03) == 010) {
+            $skip = 1;
+        } elsif (($bc & ~013) == 0144) {
+            $skip = 1;
+        } elsif ($bc == 0172) {
+            $skip = 1;
+        } elsif ($bc >= 0260 && $bc <= 0270) {
+            $skip = 2;
+        } elsif ($bc == 0330) {
+            $skip = 1;
+        }
     }
 }
 
@@ -432,38 +432,38 @@ sub format_insn($$$$$) {
     $operands =~ s/:/|colon,/g;
     @ops = ();
     if ($operands ne 'void') {
-       foreach $op (split(/,/, $operands)) {
-           if ($op =~ /^\=([0-9]+)$/) {
-               $op = "same_as|$1";
-           } else {
-               @opx = ();
-               foreach $opp (split(/\|/, $op)) {
-                   @oppx = ();
-                   if ($opp =~ /^(.*[^\d])(8|16|32|64|80|128|256)$/) {
-                       my $ox = $1;
-                       my $on = $2;
-                       if ($ox !~ /^sbyte$/) {
-                           $opp = $ox;
-                           push(@oppx, "bits$on");
-                       }
-                   }
-                   $opp =~ s/^mem$/memory/;
-                   $opp =~ s/^memory_offs$/mem_offs/;
-                   $opp =~ s/^imm$/immediate/;
-                   $opp =~ s/^([a-z]+)rm$/rm_$1/;
-                   $opp =~ s/^rm$/rm_gpr/;
-                   $opp =~ s/^reg$/reg_gpr/;
-                   push(@opx, $opp, @oppx);
-               }
-               $op = join('|', @opx);
-           }
-           push(@ops, $op);
-       }
+        foreach $op (split(/,/, $operands)) {
+            if ($op =~ /^\=([0-9]+)$/) {
+                $op = "same_as|$1";
+            } else {
+                @opx = ();
+                foreach $opp (split(/\|/, $op)) {
+                    @oppx = ();
+                    if ($opp =~ /^(.*[^\d])(8|16|32|64|80|128|256)$/) {
+                        my $ox = $1;
+                        my $on = $2;
+                        if ($ox !~ /^(sbyte|sdword|udword)$/) {
+                            $opp = $ox;
+                            push(@oppx, "bits$on");
+                        }
+                    }
+                    $opp =~ s/^mem$/memory/;
+                    $opp =~ s/^memory_offs$/mem_offs/;
+                    $opp =~ s/^imm$/immediate/;
+                    $opp =~ s/^([a-z]+)rm$/rm_$1/;
+                    $opp =~ s/^rm$/rm_gpr/;
+                    $opp =~ s/^reg$/reg_gpr/;
+                    push(@opx, $opp, @oppx);
+                }
+                $op = join('|', @opx);
+            }
+            push(@ops, $op);
+        }
     }
 
     $num = scalar(@ops);
     while (scalar(@ops) < $MAX_OPERANDS) {
-       push(@ops, '0');
+        push(@ops, '0');
     }
     $operands = join(',', @ops);
     $operands =~ tr/a-z/A-Z/;
@@ -490,11 +490,11 @@ sub codesubst($) {
     my $n;
 
     while ($s =~ /\@\@CODES-([0-9A-F]+)\@\@/) {
-       my $pos = $bytecode_pos{$1};
-       if (!defined($pos)) {
-           die "$fname: no position assigned to byte code $1\n";
-       }
-       $s = $` . "nasm_bytecodes+${pos}" . "$'";
+        my $pos = $bytecode_pos{$1};
+        if (!defined($pos)) {
+            die "$fname: no position assigned to byte code $1\n";
+        }
+        $s = $` . "nasm_bytecodes+${pos}" . "$'";
     }
     return $s;
 }
@@ -505,7 +505,7 @@ sub addprefix ($@) {
     my @l = ();
 
     foreach $x (@list) {
-       push(@l, sprintf("%s%02X", $prefix, $x));
+        push(@l, sprintf("%s%02X", $prefix, $x));
     }
 
     return @l;
@@ -521,24 +521,24 @@ sub decodify($$) {
     my($codestr, $relax) = @_;
 
     if ($codestr =~ /^\s*\[([^\]]*)\]\s*$/) {
-       return byte_code_compile($1, $relax);
+        return byte_code_compile($1, $relax);
     }
 
     my $c = $codestr;
     my @codes = ();
 
     while ($c ne '') {
-       if ($c =~ /^\\x([0-9a-f]+)(.*)$/i) {
-           push(@codes, hex $1);
-           $c = $2;
-           next;
-       } elsif ($c =~ /^\\([0-7]{1,3})(.*)$/) {
-           push(@codes, oct $1);
-           $c = $2;
-           next;
-       } else {
-           die "$fname: unknown code format in \"$codestr\"\n";
-       }
+        if ($c =~ /^\\x([0-9a-f]+)(.*)$/i) {
+            push(@codes, hex $1);
+            $c = $2;
+            next;
+        } elsif ($c =~ /^\\([0-7]{1,3})(.*)$/) {
+            push(@codes, oct $1);
+            $c = $2;
+            next;
+        } else {
+            die "$fname: unknown code format in \"$codestr\"\n";
+        }
     }
 
     return @codes;
@@ -550,7 +550,7 @@ sub hexstr(@) {
     my $c;
 
     foreach $c (@_) {
-       $s .= sprintf("%02X", $c);
+        $s .= sprintf("%02X", $c);
     }
     return $s;
 }
@@ -575,63 +575,63 @@ sub startseq($$) {
     @codes = decodify($codestr, $relax);
 
     while ($c0 = shift(@codes)) {
-       $c1 = $codes[0];
-       if ($c0 >= 01 && $c0 <= 04) {
-           # Fixed byte string
-           my $fbs = $prefix;
-           while (1) {
-               if ($c0 >= 01 && $c0 <= 04) {
-                   while ($c0--) {
-                       $fbs .= sprintf("%02X", shift(@codes));
-                   }
-               } else {
-                   last;
-               }
-               $c0 = shift(@codes);
-           }
-
-           foreach $pfx (@disasm_prefixes) {
-               if (substr($fbs, 0, length($pfx)) eq $pfx) {
-                   $prefix = $pfx;
-                   $fbs = substr($fbs, length($pfx));
-                   last;
-               }
-           }
-
-           if ($fbs ne '') {
-               return ($prefix.substr($fbs,0,2));
-           }
-
-           unshift(@codes, $c0);
-       } elsif ($c0 >= 010 && $c0 <= 013) {
-           return addprefix($prefix, $c1..($c1+7));
-       } elsif (($c0 & ~013) == 0144) {
-           return addprefix($prefix, $c1, $c1|2);
-       } elsif ($c0 == 0330) {
-           return addprefix($prefix, $c1..($c1+15));
-       } elsif ($c0 == 0 || $c0 == 0340) {
-           return $prefix;
-       } elsif ($c0 == 0344) {
-           return addprefix($prefix, 0x06, 0x0E, 0x16, 0x1E);
-       } elsif ($c0 == 0345) {
-           return addprefix($prefix, 0x07, 0x17, 0x1F);
-       } elsif ($c0 == 0346) {
-           return addprefix($prefix, 0xA0, 0xA8);
-       } elsif ($c0 == 0347) {
-           return addprefix($prefix, 0xA1, 0xA9);
-       } elsif (($c0 & ~3) == 0260 || $c0 == 0270) {
-           my $c,$m,$wlp;
-           $m   = shift(@codes);
-           $wlp = shift(@codes);
-           $c = ($m >> 6);
-           $m = $m & 31;
-           $prefix .= sprintf('%s%02X%01X', $vex_class[$c], $m, $wlp & 3);
-       } elsif ($c0 >= 0172 && $c0 <= 174) {
-           shift(@codes);      # Skip is4 control byte
-       } else {
-           # We really need to be able to distinguish "forbidden"
-           # and "ignorable" codes here
-       }
+        $c1 = $codes[0];
+        if ($c0 >= 01 && $c0 <= 04) {
+            # Fixed byte string
+            my $fbs = $prefix;
+            while (1) {
+                if ($c0 >= 01 && $c0 <= 04) {
+                    while ($c0--) {
+                        $fbs .= sprintf("%02X", shift(@codes));
+                    }
+                } else {
+                    last;
+                }
+                $c0 = shift(@codes);
+            }
+
+            foreach $pfx (@disasm_prefixes) {
+                if (substr($fbs, 0, length($pfx)) eq $pfx) {
+                    $prefix = $pfx;
+                    $fbs = substr($fbs, length($pfx));
+                    last;
+                }
+            }
+
+            if ($fbs ne '') {
+                return ($prefix.substr($fbs,0,2));
+            }
+
+            unshift(@codes, $c0);
+        } elsif ($c0 >= 010 && $c0 <= 013) {
+            return addprefix($prefix, $c1..($c1+7));
+        } elsif (($c0 & ~013) == 0144) {
+            return addprefix($prefix, $c1, $c1|2);
+        } elsif ($c0 == 0330) {
+            return addprefix($prefix, $c1..($c1+15));
+        } elsif ($c0 == 0 || $c0 == 0340) {
+            return $prefix;
+        } elsif ($c0 == 0344) {
+            return addprefix($prefix, 0x06, 0x0E, 0x16, 0x1E);
+        } elsif ($c0 == 0345) {
+            return addprefix($prefix, 0x07, 0x17, 0x1F);
+        } elsif ($c0 == 0346) {
+            return addprefix($prefix, 0xA0, 0xA8);
+        } elsif ($c0 == 0347) {
+            return addprefix($prefix, 0xA1, 0xA9);
+        } elsif (($c0 & ~3) == 0260 || $c0 == 0270) {
+            my $c,$m,$wlp;
+            $m   = shift(@codes);
+            $wlp = shift(@codes);
+            $c = ($m >> 6);
+            $m = $m & 31;
+            $prefix .= sprintf('%s%02X%01X', $vex_class[$c], $m, $wlp & 3);
+        } elsif ($c0 >= 0172 && $c0 <= 174) {
+            shift(@codes);     # Skip is4 control byte
+        } else {
+            # We really need to be able to distinguish "forbidden"
+            # and "ignorable" codes here
+        }
     }
     return $prefix;
 }
@@ -669,266 +669,271 @@ sub byte_code_compile($$) {
     my $opex;
 
     unless ($str =~ /^(([^\s:]*)\:|)\s*(.*\S)\s*$/) {
-       die "$fname: $line: cannot parse: [$str]\n";
+        die "$fname: $line: cannot parse: [$str]\n";
     }
     $opr = "\L$2";
     $opc = "\L$3";
 
     my $op = 0;
     for ($i = 0; $i < length($opr); $i++) {
-       my $c = substr($opr,$i,1);
-       if ($c eq '+') {
-           $op--;
-       } else {
-           if ($relax & 1) {
-               $op--;
-           }
-           $relax >>= 1;
-           $oppos{$c} = $op++;
-       }
+        my $c = substr($opr,$i,1);
+        if ($c eq '+') {
+            $op--;
+        } else {
+            if ($relax & 1) {
+                $op--;
+            }
+            $relax >>= 1;
+            $oppos{$c} = $op++;
+        }
     }
 
     $prefix_ok = 1;
     foreach $op (split(/\s*(?:\s|(?=[\/\\]))/, $opc)) {
-       if ($op eq 'o16') {
-           push(@codes, 0320);
-       } elsif ($op eq 'o32') {
-           push(@codes, 0321);
-       } elsif ($op eq 'o64') {  # 64-bit operand size requiring REX.W
-           push(@codes, 0324);
-       } elsif ($op eq 'o64nw') { # Implied 64-bit operand size (no REX.W)
-           push(@codes, 0323);
-       } elsif ($op eq 'a16') {
-           push(@codes, 0310);
-       } elsif ($op eq 'a32') {
-           push(@codes, 0311);
-       } elsif ($op eq 'a64') {
-           push(@codes, 0313);
-       } elsif ($op eq '!osp') {
-           push(@codes, 0364);
-       } elsif ($op eq '!asp') {
-           push(@codes, 0365);
-       } elsif ($op eq 'rex.l') {
-           push(@codes, 0334);
-       } elsif ($op eq 'repe') {
-           push(@codes, 0335);
-       } elsif ($op eq 'nohi') { # Use spl/bpl/sil/dil even without REX
-           push(@codes, 0325);
-       } elsif ($prefix_ok && $op =~ /^(66|f2|f3|np)$/) {
-           # 66/F2/F3 prefix used as an opcode extension, or np = no prefix
-           if ($op eq '66') {
-               push(@codes, 0361);
-           } elsif ($op eq 'f2') {
-               push(@codes, 0362);
-           } elsif ($op eq 'f3') {
-               push(@codes, 0363);
-           } else {
-               push(@codes, 0360);
-           }
-       } elsif ($op =~ /^[0-9a-f]{2}$/) {
-           if (defined($litix) && $litix+$codes[$litix]+1 == scalar @codes &&
-               $codes[$litix] < 4) {
-               $codes[$litix]++;
-               push(@codes, hex $op);
-           } else {
-               $litix = scalar(@codes);
-               push(@codes, 01, hex $op);
-           }
-           $prefix_ok = 0;
-       } elsif ($op eq '/r') {
-           if (!defined($oppos{'r'}) || !defined($oppos{'m'})) {
-               die "$fname: $line: $op requires r and m operands\n";
-           }
-           $opex = (($oppos{'m'} & 4) ? 06 : 0) |
-                   (($oppos{'r'} & 4) ? 05 : 0);
-           push(@codes, $opex) if ($opex);
-           push(@codes, 0100 + (($oppos{'m'} & 3) << 3) + ($oppos{'r'} & 3));
-           $prefix_ok = 0;
-       } elsif ($op =~ m:^/([0-7])$:) {
-           if (!defined($oppos{'m'})) {
-               die "$fname: $line: $op requires m operand\n";
-           }
-           push(@codes, 06) if ($oppos{'m'} & 4);
-           push(@codes, 0200 + (($oppos{'m'} & 3) << 3) + $1);
-           $prefix_ok = 0;
-       } elsif ($op =~ /^(vex|xop)(|\..*)$/) {
-           my $c = $vexmap{$1};
-           my ($m,$w,$l,$p) = (undef,2,undef,0);
-           my $has_nds = 0;
-           my @subops = split(/\./, $op);
-           shift @subops;      # Drop prefix
-           foreach $oq (@subops) {
-               if ($oq eq '128' || $oq eq 'l0' || $oq eq 'lz') {
-                   $l = 0;
-               } elsif ($oq eq '256' || $oq eq 'l1') {
-                   $l = 1;
-               } elsif ($oq eq 'lig') {
-                   $l = 2;
-               } elsif ($oq eq 'w0') {
-                   $w = 0;
-               } elsif ($oq eq 'w1') {
-                   $w = 1;
-               } elsif ($oq eq 'wig') {
-                   $w = 2;
-               } elsif ($oq eq 'ww') {
-                   $w = 3;
-               } elsif ($oq eq 'p0') {
-                   $p = 0;
-               } elsif ($oq eq '66' || $oq eq 'p1') {
-                   $p = 1;
-               } elsif ($oq eq 'f3' || $oq eq 'p2') {
-                   $p = 2;
-               } elsif ($oq eq 'f2' || $oq eq 'p3') {
-                   $p = 3;
-               } elsif ($oq eq '0f') {
-                   $m = 1;
-               } elsif ($oq eq '0f38') {
-                   $m = 2;
-               } elsif ($oq eq '0f3a') {
-                   $m = 3;
-               } elsif ($oq =~ /^m([0-9]+)$/) {
-                   $m = $1+0;
-               } elsif ($oq eq 'nds' || $oq eq 'ndd' || $oq eq 'dds') {
-                   if (!defined($oppos{'v'})) {
-                       die "$fname: $line: vex.$oq without 'v' operand\n";
-                   }
-                   $has_nds = 1;
-               } else {
-                   die "$fname: $line: undefined VEX subcode: $oq\n";
-               }
-           }
-           if (!defined($m) || !defined($w) || !defined($l) || !defined($p)) {
-               die "$fname: $line: missing fields in VEX specification\n";
-           }
-           if (defined($oppos{'v'}) && !$has_nds) {
-               die "$fname: $line: 'v' operand without vex.nds or vex.ndd\n";
-           }
-           push(@codes, defined($oppos{'v'}) ? 0260+($oppos{'v'} & 3) : 0270,
-                ($c << 6)+$m, ($w << 4)+($l << 2)+$p);
-           $prefix_ok = 0;
-       } elsif ($op =~ /^\/drex([01])$/) {
-           my $oc0 = $1;
-           if (!defined($oppos{'d'})) {
-               die "$fname: $line: DREX without a 'd' operand\n";
-           }
-           # Note the use of *unshift* here, as opposed to *push*.
-           # This is because NASM want this byte code at the start of
-           # the instruction sequence, but the AMD documentation puts
-           # this at (roughly) the position of the drex byte itself.
-           # This allows us to match the AMD documentation and still
-           # do the right thing.
-           unshift(@codes, 0160+($oppos{'d'} & 3)+($oc0 ? 4 : 0));
-           unshift(@codes, 05) if ($oppos{'d'} & 4);
-       } elsif ($op =~ /^(ib\,s|ib|ibx|ib\,w|iw|iwd|id|idx|iwdq|rel|rel8|rel16|rel32|iq|seg|ibw|ibd|ibd,s)$/) {
-           if (!defined($oppos{'i'})) {
-               die "$fname: $line: $op without 'i' operand\n";
-           }
-           if ($op eq 'ib,s') { # Signed imm8
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 014+($oppos{'i'} & 3));
-           } elsif ($op eq 'ib') { # imm8
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 020+($oppos{'i'} & 3));
-           } elsif ($op eq 'ib,u') { # Unsigned imm8
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 024+($oppos{'i'} & 3));
-           } elsif ($op eq 'iw') { # imm16
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 030+($oppos{'i'} & 3));
-           } elsif ($op eq 'ibx') { # imm8 sign-extended to opsize
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 0274+($oppos{'i'} & 3));
-           } elsif ($op eq 'iwd') { # imm16 or imm32, depending on opsize
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 034+($oppos{'i'} & 3));
-           } elsif ($op eq 'id') { # imm32
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 040+($oppos{'i'} & 3));
-           } elsif ($op eq 'idx') { # imm32 extended to 64 bits
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 0254+($oppos{'i'} & 3));
-           } elsif ($op eq 'iwdq') { # imm16/32/64, depending on opsize
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 044+($oppos{'i'} & 3));
-           } elsif ($op eq 'rel8') {
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 050+($oppos{'i'} & 3));
-           } elsif ($op eq 'iq') {
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 054+($oppos{'i'} & 3));
-           } elsif ($op eq 'rel16') {
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 060+($oppos{'i'} & 3));
-           } elsif ($op eq 'rel') { # 16 or 32 bit relative operand
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 064+($oppos{'i'} & 3));
-           } elsif ($op eq 'rel32') {
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 070+($oppos{'i'} & 3));
-           } elsif ($op eq 'seg') {
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 074+($oppos{'i'} & 3));
-           } elsif ($op eq 'ibw') { # imm16 that can be bytified
-               if (!defined($s_pos)) {
-                   die "$fname: $line: $op without a +s byte\n";
-               }
-               $codes[$s_pos] += 0144;
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 0140+($oppos{'i'} & 3));
-           } elsif ($op eq 'ibd') { # imm32 that can be bytified
-               if (!defined($s_pos)) {
-                   die "$fname: $line: $op without a +s byte\n";
-               }
-               $codes[$s_pos] += 0154;
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 0150+($oppos{'i'} & 3));
-           } elsif ($op eq 'ibd,s') {
-               # imm32 that can be bytified, sign extended to 64 bits
-               if (!defined($s_pos)) {
-                   die "$fname: $line: $op without a +s byte\n";
-               }
-               $codes[$s_pos] += 0154;
-               push(@codes, 05) if ($oppos{'i'} & 4);
-               push(@codes, 0250+($oppos{'i'} & 3));
-           }
-           $prefix_ok = 0;
-       } elsif ($op eq '/is4') {
-           if (!defined($oppos{'s'})) {
-               die "$fname: $line: $op without 's' operand\n";
-           }
-           if (defined($oppos{'i'})) {
-               push(@codes, 0172, ($oppos{'s'} << 3)+$oppos{'i'});
-           } else {
-               push(@codes, 0174, $oppos{'s'});
-           }
-           $prefix_ok = 0;
-       } elsif ($op =~ /^\/is4\=([0-9]+)$/) {
-           my $imm = $1;
-           if (!defined($oppos{'s'})) {
-               die "$fname: $line: $op without 's' operand\n";
-           }
-           if ($imm < 0 || $imm > 15) {
-               die "$fname: $line: invalid imm4 value for $op: $imm\n";
-           }
-           push(@codes, 0173, ($oppos{'s'} << 4) + $imm);
-           $prefix_ok = 0;
-       } elsif ($op =~ /^([0-9a-f]{2})\+s$/) {
-           if (!defined($oppos{'i'})) {
-               die "$fname: $line: $op without 'i' operand\n";
-           }
-           $s_pos = scalar @codes;
-           push(@codes, 05) if ($oppos{'i'} & 4);
-           push(@codes, $oppos{'i'} & 3, hex $1);
-           $prefix_ok = 0;
-       } elsif ($op =~ /^([0-9a-f]{2})\+c$/) {
-           push(@codes, 0330, hex $1);
-           $prefix_ok = 0;
-       } elsif ($op =~ /^\\([0-7]+|x[0-9a-f]{2})$/) {
-           # Escape to enter literal bytecodes
-           push(@codes, oct $1);
-       } else {
-           die "$fname: $line: unknown operation: $op\n";
-       }
+        if ($op eq 'o16') {
+            push(@codes, 0320);
+        } elsif ($op eq 'o32') {
+            push(@codes, 0321);
+        } elsif ($op eq 'o64') {  # 64-bit operand size requiring REX.W
+            push(@codes, 0324);
+        } elsif ($op eq 'o64nw') { # Implied 64-bit operand size (no REX.W)
+            push(@codes, 0323);
+        } elsif ($op eq 'a16') {
+            push(@codes, 0310);
+        } elsif ($op eq 'a32') {
+            push(@codes, 0311);
+        } elsif ($op eq 'a64') {
+            push(@codes, 0313);
+        } elsif ($op eq '!osp') {
+            push(@codes, 0364);
+        } elsif ($op eq '!asp') {
+            push(@codes, 0365);
+        } elsif ($op eq 'rex.l') {
+            push(@codes, 0334);
+        } elsif ($op eq 'repe') {
+            push(@codes, 0335);
+        } elsif ($op eq 'nohi') { # Use spl/bpl/sil/dil even without REX
+            push(@codes, 0325);
+       } elsif ($op eq 'vsibx' || $op eq 'vm32x' || $op eq 'vm64x') {
+           # This instruction takes XMM VSIB
+           push(@codes, 0374);
+       } elsif ($op eq 'vsiby' || $op eq 'vm32y' || $op eq 'vm64y') {
+           push(@codes, 0375);
+        } elsif ($prefix_ok && $op =~ /^(66|f2|f3|np)$/) {
+            # 66/F2/F3 prefix used as an opcode extension, or np = no prefix
+            if ($op eq '66') {
+                push(@codes, 0361);
+            } elsif ($op eq 'f2') {
+                push(@codes, 0362);
+            } elsif ($op eq 'f3') {
+                push(@codes, 0363);
+            } else {
+                push(@codes, 0360);
+            }
+        } elsif ($op =~ /^[0-9a-f]{2}$/) {
+            if (defined($litix) && $litix+$codes[$litix]+1 == scalar @codes &&
+                $codes[$litix] < 4) {
+                $codes[$litix]++;
+                push(@codes, hex $op);
+            } else {
+                $litix = scalar(@codes);
+                push(@codes, 01, hex $op);
+            }
+            $prefix_ok = 0;
+        } elsif ($op eq '/r') {
+            if (!defined($oppos{'r'}) || !defined($oppos{'m'})) {
+                die "$fname: $line: $op requires r and m operands\n";
+            }
+            $opex = (($oppos{'m'} & 4) ? 06 : 0) |
+                (($oppos{'r'} & 4) ? 05 : 0);
+            push(@codes, $opex) if ($opex);
+            push(@codes, 0100 + (($oppos{'m'} & 3) << 3) + ($oppos{'r'} & 3));
+            $prefix_ok = 0;
+        } elsif ($op =~ m:^/([0-7])$:) {
+            if (!defined($oppos{'m'})) {
+                die "$fname: $line: $op requires m operand\n";
+            }
+            push(@codes, 06) if ($oppos{'m'} & 4);
+            push(@codes, 0200 + (($oppos{'m'} & 3) << 3) + $1);
+            $prefix_ok = 0;
+        } elsif ($op =~ /^(vex|xop)(|\..*)$/) {
+            my $c = $vexmap{$1};
+            my ($m,$w,$l,$p) = (undef,2,undef,0);
+            my $has_nds = 0;
+            my @subops = split(/\./, $op);
+            shift @subops;      # Drop prefix
+                foreach $oq (@subops) {
+                    if ($oq eq '128' || $oq eq 'l0' || $oq eq 'lz') {
+                        $l = 0;
+                    } elsif ($oq eq '256' || $oq eq 'l1') {
+                        $l = 1;
+                    } elsif ($oq eq 'lig') {
+                        $l = 2;
+                    } elsif ($oq eq 'w0') {
+                        $w = 0;
+                    } elsif ($oq eq 'w1') {
+                        $w = 1;
+                    } elsif ($oq eq 'wig') {
+                        $w = 2;
+                    } elsif ($oq eq 'ww') {
+                        $w = 3;
+                    } elsif ($oq eq 'p0') {
+                        $p = 0;
+                    } elsif ($oq eq '66' || $oq eq 'p1') {
+                        $p = 1;
+                    } elsif ($oq eq 'f3' || $oq eq 'p2') {
+                        $p = 2;
+                    } elsif ($oq eq 'f2' || $oq eq 'p3') {
+                        $p = 3;
+                    } elsif ($oq eq '0f') {
+                        $m = 1;
+                    } elsif ($oq eq '0f38') {
+                        $m = 2;
+                    } elsif ($oq eq '0f3a') {
+                        $m = 3;
+                    } elsif ($oq =~ /^m([0-9]+)$/) {
+                        $m = $1+0;
+                    } elsif ($oq eq 'nds' || $oq eq 'ndd' || $oq eq 'dds') {
+                        if (!defined($oppos{'v'})) {
+                            die "$fname: $line: vex.$oq without 'v' operand\n";
+                        }
+                        $has_nds = 1;
+                    } else {
+                        die "$fname: $line: undefined VEX subcode: $oq\n";
+                    }
+                }
+            if (!defined($m) || !defined($w) || !defined($l) || !defined($p)) {
+                die "$fname: $line: missing fields in VEX specification\n";
+            }
+            if (defined($oppos{'v'}) && !$has_nds) {
+                die "$fname: $line: 'v' operand without vex.nds or vex.ndd\n";
+            }
+            push(@codes, defined($oppos{'v'}) ? 0260+($oppos{'v'} & 3) : 0270,
+                 ($c << 6)+$m, ($w << 4)+($l << 2)+$p);
+            $prefix_ok = 0;
+        } elsif ($op =~ /^\/drex([01])$/) {
+            my $oc0 = $1;
+            if (!defined($oppos{'d'})) {
+                die "$fname: $line: DREX without a 'd' operand\n";
+            }
+            # Note the use of *unshift* here, as opposed to *push*.
+            # This is because NASM want this byte code at the start of
+            # the instruction sequence, but the AMD documentation puts
+            # this at (roughly) the position of the drex byte itself.
+            # This allows us to match the AMD documentation and still
+            # do the right thing.
+            unshift(@codes, 0160+($oppos{'d'} & 3)+($oc0 ? 4 : 0));
+            unshift(@codes, 05) if ($oppos{'d'} & 4);
+        } elsif ($op =~ /^(ib\,s|ib|ibx|ib\,w|iw|iwd|id|idx|iwdq|rel|rel8|rel16|rel32|iq|seg|ibw|ibd|ibd,s)$/) {
+            if (!defined($oppos{'i'})) {
+                die "$fname: $line: $op without 'i' operand\n";
+            }
+            if ($op eq 'ib,s') { # Signed imm8
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 014+($oppos{'i'} & 3));
+            } elsif ($op eq 'ib') { # imm8
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 020+($oppos{'i'} & 3));
+            } elsif ($op eq 'ib,u') { # Unsigned imm8
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 024+($oppos{'i'} & 3));
+            } elsif ($op eq 'iw') { # imm16
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 030+($oppos{'i'} & 3));
+            } elsif ($op eq 'ibx') { # imm8 sign-extended to opsize
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 0274+($oppos{'i'} & 3));
+            } elsif ($op eq 'iwd') { # imm16 or imm32, depending on opsize
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 034+($oppos{'i'} & 3));
+            } elsif ($op eq 'id') { # imm32
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 040+($oppos{'i'} & 3));
+            } elsif ($op eq 'idx') { # imm32 extended to 64 bits
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 0254+($oppos{'i'} & 3));
+            } elsif ($op eq 'iwdq') { # imm16/32/64, depending on opsize
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 044+($oppos{'i'} & 3));
+            } elsif ($op eq 'rel8') {
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 050+($oppos{'i'} & 3));
+            } elsif ($op eq 'iq') {
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 054+($oppos{'i'} & 3));
+            } elsif ($op eq 'rel16') {
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 060+($oppos{'i'} & 3));
+            } elsif ($op eq 'rel') { # 16 or 32 bit relative operand
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 064+($oppos{'i'} & 3));
+            } elsif ($op eq 'rel32') {
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 070+($oppos{'i'} & 3));
+            } elsif ($op eq 'seg') {
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 074+($oppos{'i'} & 3));
+            } elsif ($op eq 'ibw') { # imm16 that can be bytified
+                if (!defined($s_pos)) {
+                    die "$fname: $line: $op without a +s byte\n";
+                }
+                $codes[$s_pos] += 0144;
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 0140+($oppos{'i'} & 3));
+            } elsif ($op eq 'ibd') { # imm32 that can be bytified
+                if (!defined($s_pos)) {
+                    die "$fname: $line: $op without a +s byte\n";
+                }
+                $codes[$s_pos] += 0154;
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 0150+($oppos{'i'} & 3));
+            } elsif ($op eq 'ibd,s') {
+                # imm32 that can be bytified, sign extended to 64 bits
+                if (!defined($s_pos)) {
+                    die "$fname: $line: $op without a +s byte\n";
+                }
+                $codes[$s_pos] += 0154;
+                push(@codes, 05) if ($oppos{'i'} & 4);
+                push(@codes, 0250+($oppos{'i'} & 3));
+            }
+            $prefix_ok = 0;
+        } elsif ($op eq '/is4') {
+            if (!defined($oppos{'s'})) {
+                die "$fname: $line: $op without 's' operand\n";
+            }
+            if (defined($oppos{'i'})) {
+                push(@codes, 0172, ($oppos{'s'} << 3)+$oppos{'i'});
+            } else {
+                push(@codes, 0174, $oppos{'s'});
+            }
+            $prefix_ok = 0;
+        } elsif ($op =~ /^\/is4\=([0-9]+)$/) {
+            my $imm = $1;
+            if (!defined($oppos{'s'})) {
+                die "$fname: $line: $op without 's' operand\n";
+            }
+            if ($imm < 0 || $imm > 15) {
+                die "$fname: $line: invalid imm4 value for $op: $imm\n";
+            }
+            push(@codes, 0173, ($oppos{'s'} << 4) + $imm);
+            $prefix_ok = 0;
+        } elsif ($op =~ /^([0-9a-f]{2})\+s$/) {
+            if (!defined($oppos{'i'})) {
+                die "$fname: $line: $op without 'i' operand\n";
+            }
+            $s_pos = scalar @codes;
+            push(@codes, 05) if ($oppos{'i'} & 4);
+            push(@codes, $oppos{'i'} & 3, hex $1);
+            $prefix_ok = 0;
+        } elsif ($op =~ /^([0-9a-f]{2})\+c$/) {
+            push(@codes, 0330, hex $1);
+            $prefix_ok = 0;
+        } elsif ($op =~ /^\\([0-7]+|x[0-9a-f]{2})$/) {
+            # Escape to enter literal bytecodes
+            push(@codes, oct $1);
+        } else {
+            die "$fname: $line: unknown operation: $op\n";
+        }
     }
 
     return @codes;
diff --git a/lcc/README b/lcc/README
deleted file mode 100644 (file)
index 569b9be..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-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) by using NASM as a back-end code generator.
-
-This patch has been tested on lcc version 3.6.
-
-To install:
-
-- Copy `x86nasm.md' into the `src' directory of the lcc tree.
-
-- Copy either `lin-elf.c' or `lin-aout.c' into the `etc' directory.
-
-- If you're installing for a.out, edit `x86nasm.md' and change the
-  conditional after the comment reading "CHANGE THIS FOR a.out" in
-  the `defsymbol' function from `#if 0' to `#if 1'.
-
-- Make the following changes to `bind.c' in the `src' directory:
-
-  - Near the top of the file, add a line that reads
-       extern Interface x86nasmIR;
-
-  - In the `bindings' array, add the lines
-        "x86-nasm",      &x86nasmIR,
-        "x86/nasm",      &x86nasmIR,
-    (in sensible looking places...)
-
-  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...
-
-- 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...)
-
-- 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'.
-
-- 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.
-
-- 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!
diff --git a/lcc/bind.c b/lcc/bind.c
deleted file mode 100644 (file)
index 286431d..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "c.h"
-extern Interface nullIR, symbolicIR;
-extern Interface mipsebIR, mipselIR;
-extern Interface sparcIR, solarisIR;
-extern Interface x86IR, x86nasmIR;
-Binding bindings[] = {
-    "symbolic", &symbolicIR,
-    "mips-irix", &mipsebIR,
-    "mips-ultrix", &mipselIR,
-    "sparc-sun", &sparcIR,
-    "sparc-solaris", &solarisIR,
-    "x86-dos", &x86IR,
-    "x86-nasm", &x86nasmIR,
-    "symbolic/irix", &symbolicIR,       /* omit */
-    "mips/irix", &mipsebIR,     /* omit */
-    "mips/ultrix", &mipselIR,   /* omit */
-    "sparc/sun", &sparcIR,      /* omit */
-    "sparc/solaris", &solarisIR,        /* omit */
-    "x86/dos", &x86IR,          /* omit */
-    "x86/nasm", &x86nasmIR,     /* omit */
-    "null", &nullIR,
-    NULL, NULL
-};
diff --git a/lcc/lin-aout.c b/lcc/lin-aout.c
deleted file mode 100644 (file)
index e4ac48f..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* x86 running linux and using nasm as a.out */
-
-#include <string.h>
-
-#ifndef LCCDIR
-#define LCCDIR "/usr/local/lib/lcc/"
-#endif
-
-#define NASMPATH "/usr/local/bin/nasm"
-
-char *cpp[] = { LCCDIR "cpp", "-D__STDC__=1",
-    "-Di386", "-D__i386", "-D__i386__",
-    "-Dlinux", "-D__linux", "-D__linux__",
-    "-Dunix", "-D__unix", "-D__unix__",
-    "$1", "$2", "$3", 0
-};
-char *include[] = { "-I" LCCDIR "include", "-I/usr/local/include",
-    "-I/usr/include", 0
-};
-char *com[] = { LCCDIR "rcc", "-target=x86/nasm",
-    "$1", "$2", "$3", 0
-};
-char *as[] = { NASMPATH, "-a", "-faout", "-o", "$3", "$1", "$2", 0 };
-char *ld[] = { "/usr/bin/ld", "-m", "i386linux",
-    "-L/usr/i486-linuxaout/lib",
-    "-o", "$3", "$1",
-    "/usr/i486-linuxaout/lib/crt0.o",
-    "$2", "", "-lc", 0
-};
-static char *bbexit = LCCDIR "bbexit.o";
-
-extern char *concat(char *, char *);
-extern int access(const char *, int);
-
-int option(char *arg)
-{
-    if (strncmp(arg, "-lccdir=", 8) == 0) {
-        cpp[0] = concat(&arg[8], "/cpp");
-        include[0] = concat("-I", concat(&arg[8], "/include"));
-        com[0] = concat(&arg[8], "/rcc");
-        bbexit = concat(&arg[8], "/bbexit.o");
-    } else if (strcmp(arg, "-g") == 0) ;
-    else if (strcmp(arg, "-b") == 0 && access(bbexit, 4) == 0)
-        ld[9] = bbexit;
-    else
-        return 0;
-    return 1;
-}
diff --git a/lcc/lin-elf.c b/lcc/lin-elf.c
deleted file mode 100644 (file)
index 693309f..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/* x86 running linux and using nasm as ELF */
-
-#include <string.h>
-
-#ifndef LCCDIR
-#define LCCDIR "/usr/local/lib/lcc/"
-#endif
-
-#define NASMPATH "/usr/local/bin/nasm"
-
-char *cpp[] = { LCCDIR "cpp", "-D__STDC__=1",
-    "-D__ELF__", "-Di386", "-D__i386", "-D__i386__",
-    "-Dlinux", "-D__linux", "-D__linux__",
-    "$1", "$2", "$3", 0
-};
-char *include[] = { "-I" LCCDIR "include", "-I/usr/local/include",
-    "-I/usr/include", 0
-};
-char *com[] = { LCCDIR "rcc", "-target=x86/nasm",
-    "$1", "$2", "$3", 0
-};
-char *as[] = { NASMPATH, "-a", "-felf", "-o", "$3", "$1", "$2", 0 };
-char *ld[] = { "/usr/bin/ld", "-m", "elf_i386",
-    "-dynamic-linker", "/lib/ld-linux.so.1",
-    "-L/usr/i486-linux/lib",
-    "-o", "$3", "$1",
-    "/usr/lib/crt1.o", "/usr/lib/crti.o", "/usr/lib/crtbegin.o",
-    "$2", "",
-    "-lc", "", "/usr/lib/crtend.o", "/usr/lib/crtn.o", 0
-};
-static char *bbexit = LCCDIR "bbexit.o";
-
-extern char *concat(char *, char *);
-extern int access(const char *, int);
-
-int option(char *arg)
-{
-    if (strncmp(arg, "-lccdir=", 8) == 0) {
-        cpp[0] = concat(&arg[8], "/cpp");
-        include[0] = concat("-I", concat(&arg[8], "/include"));
-        com[0] = concat(&arg[8], "/rcc");
-        bbexit = concat(&arg[8], "/bbexit.o");
-    } else if (strcmp(arg, "-g") == 0) ;
-    else if (strcmp(arg, "-b") == 0 && access(bbexit, 4) == 0)
-        ld[13] = bbexit;
-    else
-        return 0;
-    return 1;
-}
diff --git a/lcc/x86nasm.md b/lcc/x86nasm.md
deleted file mode 100644 (file)
index 54d0be6..0000000
+++ /dev/null
@@ -1,703 +0,0 @@
-%{
-enum { EAX=0, ECX=1, EDX=2, EBX=3, ESI=6, EDI=7 };
-#include "c.h"
-#define NODEPTR_TYPE Node
-#define OP_LABEL(p) ((p)->op)
-#define LEFT_CHILD(p) ((p)->kids[0])
-#define RIGHT_CHILD(p) ((p)->kids[1])
-#define STATE_LABEL(p) ((p)->x.state)
-static void address     ARGS((Symbol, Symbol, int));
-static void blkfetch    ARGS((int, int, int, int));
-static void blkloop     ARGS((int, int, int, int, int, int[]));
-static void blkstore    ARGS((int, int, int, int));
-static void defaddress  ARGS((Symbol));
-static void defconst    ARGS((int, Value));
-static void defstring   ARGS((int, char *));
-static void defsymbol   ARGS((Symbol));
-static void doarg       ARGS((Node));
-static void emit2       ARGS((Node));
-static void export      ARGS((Symbol));
-static void clobber     ARGS((Node));
-static void function    ARGS((Symbol, Symbol [], Symbol [], int));
-static void global      ARGS((Symbol));
-static void import      ARGS((Symbol));
-static void local       ARGS((Symbol));
-static void progbeg     ARGS((int, char **));
-static void progend     ARGS((void));
-static void segment     ARGS((int));
-static void space       ARGS((int));
-static void target      ARGS((Node));
-static int ckstack ARGS((Node, int));
-static int memop ARGS((Node));
-static int sametree ARGS((Node, Node));
-static Symbol charreg[32], shortreg[32], intreg[32];
-static Symbol fltreg[32];
-
-static int cseg;
-
-static Symbol quo, rem;
-
-%}
-%start stmt
-%term ADDD=306 ADDF=305 ADDI=309 ADDP=311 ADDU=310
-%term ADDRFP=279
-%term ADDRGP=263
-%term ADDRLP=295
-%term ARGB=41 ARGD=34 ARGF=33 ARGI=37 ARGP=39
-%term ASGNB=57 ASGNC=51 ASGND=50 ASGNF=49 ASGNI=53 ASGNP=55 ASGNS=52
-%term BANDU=390
-%term BCOMU=406
-%term BORU=422
-%term BXORU=438
-%term CALLB=217 CALLD=210 CALLF=209 CALLI=213 CALLV=216
-%term CNSTC=19 CNSTD=18 CNSTF=17 CNSTI=21 CNSTP=23 CNSTS=20 CNSTU=22
-%term CVCI=85 CVCU=86
-%term CVDF=97 CVDI=101
-%term CVFD=114
-%term CVIC=131 CVID=130 CVIS=132 CVIU=134
-%term CVPU=150
-%term CVSI=165 CVSU=166
-%term CVUC=179 CVUI=181 CVUP=183 CVUS=180
-%term DIVD=450 DIVF=449 DIVI=453 DIVU=454
-%term EQD=482 EQF=481 EQI=485
-%term GED=498 GEF=497 GEI=501 GEU=502
-%term GTD=514 GTF=513 GTI=517 GTU=518
-%term INDIRB=73 INDIRC=67 INDIRD=66 INDIRF=65 INDIRI=69 INDIRP=71 INDIRS=68
-%term JUMPV=584
-%term LABELV=600
-%term LED=530 LEF=529 LEI=533 LEU=534
-%term LOADB=233 LOADC=227 LOADD=226 LOADF=225 LOADI=229 LOADP=231 LOADS=228 LOADU=230
-%term LSHI=341 LSHU=342
-%term LTD=546 LTF=545 LTI=549 LTU=550
-%term MODI=357 MODU=358
-%term MULD=466 MULF=465 MULI=469 MULU=470
-%term NED=562 NEF=561 NEI=565
-%term NEGD=194 NEGF=193 NEGI=197
-%term RETD=242 RETF=241 RETI=245
-%term RSHI=373 RSHU=374
-%term SUBD=322 SUBF=321 SUBI=325 SUBP=327 SUBU=326
-%term VREGP=615
-%%
-reg:  INDIRC(VREGP)     "# read register\n"
-reg:  INDIRD(VREGP)     "# read register\n"
-reg:  INDIRF(VREGP)     "# read register\n"
-reg:  INDIRI(VREGP)     "# read register\n"
-reg:  INDIRP(VREGP)     "# read register\n"
-reg:  INDIRS(VREGP)     "# read register\n"
-stmt: ASGNC(VREGP,reg)  "# write register\n"
-stmt: ASGND(VREGP,reg)  "# write register\n"
-stmt: ASGNF(VREGP,reg)  "# write register\n"
-stmt: ASGNI(VREGP,reg)  "# write register\n"
-stmt: ASGNP(VREGP,reg)  "# write register\n"
-stmt: ASGNS(VREGP,reg)  "# write register\n"
-con: CNSTC  "%a"
-con: CNSTI  "%a"
-con: CNSTP  "%a"
-con: CNSTS  "%a"
-con: CNSTU  "%a"
-stmt: reg  ""
-reg: CVIU(reg)  "%0"  notarget(a)
-reg: CVPU(reg)  "%0"  notarget(a)
-reg: CVUI(reg)  "%0"  notarget(a)
-reg: CVUP(reg)  "%0"  notarget(a)
-acon: ADDRGP  "%a"
-acon: con     "%0"
-base: ADDRGP          "%a"
-base: reg             "%0"
-base: ADDI(reg,acon)  "%0 + (%1)"
-base: ADDP(reg,acon)  "%0 + (%1)"
-base: ADDU(reg,acon)  "%0 + (%1)"
-base: ADDRFP  "ebp + %a"
-base: ADDRLP  "ebp + %a"
-index: reg "%0"
-index: LSHI(reg,con1)  "%0*2"
-index: LSHI(reg,con2)  "%0*4"
-index: LSHI(reg,con3)  "%0*8"
-
-con1:  CNSTI  "1"  range(a, 1, 1)
-con1:  CNSTU  "1"  range(a, 1, 1)
-con2:  CNSTI  "2"  range(a, 2, 2)
-con2:  CNSTU  "2"  range(a, 2, 2)
-con3:  CNSTI  "3"  range(a, 3, 3)
-con3:  CNSTU  "3"  range(a, 3, 3)
-index: LSHU(reg,con1)  "%0*2"
-index: LSHU(reg,con2)  "%0*4"
-index: LSHU(reg,con3)  "%0*8"
-addr: base              "[%0]"
-addr: ADDI(index,base)  "[%1 + %0]"
-addr: ADDP(index,base)  "[%1 + %0]"
-addr: ADDU(index,base)  "[%1 + %0]"
-addr: index  "[%0]"
-mem: INDIRC(addr)  "byte %0"
-mem: INDIRI(addr)  "dword %0"
-mem: INDIRP(addr)  "dword %0"
-mem: INDIRS(addr)  "word %0"
-rc:   reg  "%0"
-rc:   con  "%0"
-
-mr:   reg  "%0"
-mr:   mem  "%0"
-
-mrc0: mem  "%0"
-mrc0: rc   "%0"
-mrc1: mem  "%0"  1
-mrc1: rc   "%0"
-
-mrc3: mem  "%0"  3
-mrc3: rc   "%0"
-reg: addr        "lea %c,%0\n"  1
-reg: mrc0        "mov %c,%0\n"  1
-reg: LOADC(reg)  "mov %c,%0\n"  move(a)
-reg: LOADI(reg)  "mov %c,%0\n"  move(a)
-reg: LOADP(reg)  "mov %c,%0\n"  move(a)
-reg: LOADS(reg)  "mov %c,%0\n"  move(a)
-reg: LOADU(reg)  "mov %c,%0\n"  move(a)
-reg: ADDI(reg,mrc1)  "?mov %c,%0\nadd %c,%1\n"  1
-reg: ADDP(reg,mrc1)  "?mov %c,%0\nadd %c,%1\n"  1
-reg: ADDU(reg,mrc1)  "?mov %c,%0\nadd %c,%1\n"  1
-reg: SUBI(reg,mrc1)  "?mov %c,%0\nsub %c,%1\n"  1
-reg: SUBP(reg,mrc1)  "?mov %c,%0\nsub %c,%1\n"  1
-reg: SUBU(reg,mrc1)  "?mov %c,%0\nsub %c,%1\n"  1
-reg: BANDU(reg,mrc1)  "?mov %c,%0\nand %c,%1\n"  1
-reg: BORU(reg,mrc1)   "?mov %c,%0\nor %c,%1\n"   1
-reg: BXORU(reg,mrc1)  "?mov %c,%0\nxor %c,%1\n"  1
-stmt: ASGNI(addr,ADDI(mem,con1))  "inc %1\n"  memop(a)
-stmt: ASGNI(addr,ADDU(mem,con1))  "inc %1\n"  memop(a)
-stmt: ASGNP(addr,ADDP(mem,con1))  "inc %1\n"  memop(a)
-stmt: ASGNI(addr,SUBI(mem,con1))  "dec %1\n"  memop(a)
-stmt: ASGNI(addr,SUBU(mem,con1))  "dec %1\n"  memop(a)
-stmt: ASGNP(addr,SUBP(mem,con1))  "dec %1\n"  memop(a)
-stmt: ASGNI(addr,ADDI(mem,rc))   "add %1,%2\n"  memop(a)
-stmt: ASGNI(addr,ADDU(mem,rc))   "add %1,%2\n"  memop(a)
-stmt: ASGNI(addr,SUBI(mem,rc))   "sub %1,%2\n"  memop(a)
-stmt: ASGNI(addr,SUBU(mem,rc))   "sub %1,%2\n"  memop(a)
-
-stmt: ASGNI(addr,BANDU(mem,rc))  "and %1,%2\n"  memop(a)
-stmt: ASGNI(addr,BORU(mem,rc))   "or %1,%2\n"   memop(a)
-stmt: ASGNI(addr,BXORU(mem,rc))  "xor %1,%2\n"  memop(a)
-reg: BCOMU(reg)  "?mov %c,%0\nnot %c\n"  2
-reg: NEGI(reg)   "?mov %c,%0\nneg %c\n"  2
-
-stmt: ASGNI(addr,BCOMU(mem))  "not %1\n"  memop(a)
-stmt: ASGNI(addr,NEGI(mem))   "neg %1\n"  memop(a)
-reg: LSHI(reg,rc5)  "?mov %c,%0\nsal %c,%1\n"  2
-reg: LSHU(reg,rc5)  "?mov %c,%0\nshl %c,%1\n"  2
-reg: RSHI(reg,rc5)  "?mov %c,%0\nsar %c,%1\n"  2
-reg: RSHU(reg,rc5)  "?mov %c,%0\nshr %c,%1\n"  2
-
-stmt: ASGNI(addr,LSHI(mem,rc5))  "sal %1,%2\n"  memop(a)
-stmt: ASGNI(addr,LSHU(mem,rc5))  "shl %1,%2\n"  memop(a)
-stmt: ASGNI(addr,RSHI(mem,rc5))  "sar %1,%2\n"  memop(a)
-stmt: ASGNI(addr,RSHU(mem,rc5))  "shr %1,%2\n"  memop(a)
-
-rc5: CNSTI  "%a"  range(a, 0, 31)
-rc5: reg    "cl"
-reg: MULI(reg,mrc3)  "?mov %c,%0\nimul %c,%1\n"  14
-reg: MULI(con,mr)    "imul %c,%1,%0\n"  13
-reg: MULU(reg,mr)  "mul %1\n"  13
-reg: DIVU(reg,reg)  "xor edx,edx\ndiv %1\n"
-reg: MODU(reg,reg)  "xor edx,edx\ndiv %1\n"
-reg: DIVI(reg,reg)  "cdq\nidiv %1\n"
-reg: MODI(reg,reg)  "cdq\nidiv %1\n"
-reg: CVIU(reg)  "mov %c,%0\n"  move(a)
-reg: CVPU(reg)  "mov %c,%0\n"  move(a)
-reg: CVUI(reg)  "mov %c,%0\n"  move(a)
-reg: CVUP(reg)  "mov %c,%0\n"  move(a)
-reg: CVCI(INDIRC(addr))  "movsx %c,byte %0\n"  3
-reg: CVCU(INDIRC(addr))  "movzx %c,byte %0\n"  3
-reg: CVSI(INDIRS(addr))  "movsx %c,word %0\n"  3
-reg: CVSU(INDIRS(addr))  "movzx %c,word %0\n"  3
-reg: CVCI(reg)  "# extend\n"  3
-reg: CVCU(reg)  "# extend\n"  3
-reg: CVSI(reg)  "# extend\n"  3
-reg: CVSU(reg)  "# extend\n"  3
-
-reg: CVIC(reg)  "# truncate\n"  1
-reg: CVIS(reg)  "# truncate\n"  1
-reg: CVUC(reg)  "# truncate\n"  1
-reg: CVUS(reg)  "# truncate\n"  1
-stmt: ASGNC(addr,rc)  "mov byte %0,%1\n"   1
-stmt: ASGNI(addr,rc)  "mov dword %0,%1\n"  1
-stmt: ASGNP(addr,rc)  "mov dword %0,%1\n"  1
-stmt: ASGNS(addr,rc)  "mov word %0,%1\n"   1
-stmt: ARGI(mrc3)  "push dword %0\n"  1
-stmt: ARGP(mrc3)  "push dword %0\n"  1
-stmt: ASGNB(reg,INDIRB(reg))  "mov ecx,%a\nrep movsb\n"
-stmt: ARGB(INDIRB(reg))  "sub esp,%a\nmov edi,esp\nmov ecx,%a\nrep movsb\n"
-
-memf: INDIRD(addr)        "qword %0"
-memf: INDIRF(addr)        "dword %0"
-memf: CVFD(INDIRF(addr))  "dword %0"
-reg: memf  "fld %0\n"  3
-stmt: ASGND(addr,reg)        "fstp qword %0\n"  7
-stmt: ASGNF(addr,reg)        "fstp dword %0\n"  7
-stmt: ASGNF(addr,CVDF(reg))  "fstp dword %0\n"  7
-stmt: ARGD(reg)  "sub esp,8\nfstp qword [esp]\n"
-stmt: ARGF(reg)  "sub esp,4\nfstp dword [esp]\n"
-reg: NEGD(reg)  "fchs\n"
-reg: NEGF(reg)  "fchs\n"
-reg: ADDD(reg,memf)  "fadd %1\n"
-reg: ADDD(reg,reg)  "faddp st1\n"
-reg: ADDF(reg,memf)  "fadd %1\n"
-reg: ADDF(reg,reg)  "faddp st1\n"
-reg: DIVD(reg,memf)  "fdiv %1\n"
-reg: DIVD(reg,reg)  "fdivp st1\n"
-reg: DIVF(reg,memf)  "fdiv %1\n"
-reg: DIVF(reg,reg)  "fdivp st1\n"
-reg: MULD(reg,memf)  "fmul %1\n"
-reg: MULD(reg,reg)  "fmulp st1\n"
-reg: MULF(reg,memf)  "fmul %1\n"
-reg: MULF(reg,reg)  "fmulp st1\n"
-reg: SUBD(reg,memf)  "fsub %1\n"
-reg: SUBD(reg,reg)  "fsubp st1\n"
-reg: SUBF(reg,memf)  "fsub %1\n"
-reg: SUBF(reg,reg)  "fsubp st1\n"
-reg: CVFD(reg)  "# CVFD\n"
-reg: CVDF(reg)  "sub esp,4\nfstp dword [esp]\nfld dword [esp]\nadd esp,4\n"  12
-
-stmt: ASGNI(addr,CVDI(reg))  "fistp dword %0\n"  29
-reg: CVDI(reg)  "sub esp,4\nfistp dword [esp]\npop %c\n" 31
-
-reg: CVID(INDIRI(addr))  "fild dword %0\n"  10
-reg: CVID(reg)  "push %0\nfild dword [esp]\nadd esp,4\n"  12
-
-addrj: ADDRGP  "%a"
-addrj: reg     "%0"  2
-addrj: mem     "%0"  2
-
-stmt:  JUMPV(addrj)  "jmp %0\n"  3
-stmt:  LABELV        "%a:\n"
-stmt: EQI(mem,rc)  "cmp %0,%1\nje near %a\n"   5
-stmt: GEI(mem,rc)  "cmp %0,%1\njge near %a\n"  5
-stmt: GTI(mem,rc)  "cmp %0,%1\njg near %a\n"   5
-stmt: LEI(mem,rc)  "cmp %0,%1\njle near %a\n"  5
-stmt: LTI(mem,rc)  "cmp %0,%1\njl near %a\n"   5
-stmt: NEI(mem,rc)  "cmp %0,%1\njne near %a\n"  5
-stmt: GEU(mem,rc)  "cmp %0,%1\njae near %a\n"  5
-stmt: GTU(mem,rc)  "cmp %0,%1\nja  near %a\n"  5
-stmt: LEU(mem,rc)  "cmp %0,%1\njbe near %a\n"  5
-stmt: LTU(mem,rc)  "cmp %0,%1\njb  near %a\n"  5
-stmt: EQI(reg,mrc1)  "cmp %0,%1\nje near %a\n"   4
-stmt: GEI(reg,mrc1)  "cmp %0,%1\njge near %a\n"  4
-stmt: GTI(reg,mrc1)  "cmp %0,%1\njg near %a\n"   4
-stmt: LEI(reg,mrc1)  "cmp %0,%1\njle near %a\n"  4
-stmt: LTI(reg,mrc1)  "cmp %0,%1\njl near %a\n"   4
-stmt: NEI(reg,mrc1)  "cmp %0,%1\njne near %a\n"  4
-
-stmt: GEU(reg,mrc1)  "cmp %0,%1\njae near %a\n"  4
-stmt: GTU(reg,mrc1)  "cmp %0,%1\nja near %a\n"   4
-stmt: LEU(reg,mrc1)  "cmp %0,%1\njbe near %a\n"  4
-stmt: LTU(reg,mrc1)  "cmp %0,%1\njb near %a\n"   4
-cmpf: memf  " %0"
-cmpf: reg   "p"
-stmt: EQD(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\nje near %a\n"
-stmt: GED(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njbe near %a\n"
-stmt: GTD(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njb near %a\n"
-stmt: LED(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njae near %a\n"
-stmt: LTD(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\nja near %a\n"
-stmt: NED(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njne near %a\n"
-
-stmt: EQF(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\nje near %a\n"
-stmt: GEF(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njbe near %a\n"
-stmt: GTF(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njb near %a\n"
-stmt: LEF(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njae near %a\n"
-stmt: LTF(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\nja near %a\n"
-stmt: NEF(cmpf,reg)  "fcomp%0\nfstsw ax\nsahf\njne near %a\n"
-reg:  CALLI(addrj)  "call %0\nadd esp,%a\n"
-stmt: CALLV(addrj)  "call %0\nadd esp,%a\n"
-reg: CALLF(addrj)  "call %0\nadd esp,%a\n"
-reg: CALLD(addrj)  "call %0\nadd esp,%a\n"
-
-stmt: RETI(reg)  "# ret\n"
-stmt: RETF(reg)  "# ret\n"
-stmt: RETD(reg)  "# ret\n"
-%%
-static void progbeg(argc, argv) int argc; char *argv[]; {
-       int i;
-
-       {
-               union {
-                       char c;
-                       int i;
-               } u;
-               u.i = 0;
-               u.c = 1;
-               swap = (u.i == 1) != IR->little_endian;
-       }
-       parseflags(argc, argv);
-       intreg[EAX] = mkreg("eax", EAX, 1, IREG);
-       intreg[EDX] = mkreg("edx", EDX, 1, IREG);
-       intreg[ECX] = mkreg("ecx", ECX, 1, IREG);
-       intreg[EBX] = mkreg("ebx", EBX, 1, IREG);
-       intreg[ESI] = mkreg("esi", ESI, 1, IREG);
-       intreg[EDI] = mkreg("edi", EDI, 1, IREG);
-       shortreg[EAX] = mkreg("ax", EAX, 1, IREG);
-       shortreg[ECX] = mkreg("cx", ECX, 1, IREG);
-       shortreg[EDX] = mkreg("dx", EDX, 1, IREG);
-       shortreg[EBX] = mkreg("bx", EBX, 1, IREG);
-       shortreg[ESI] = mkreg("si", ESI, 1, IREG);
-       shortreg[EDI] = mkreg("di", EDI, 1, IREG);
-
-       charreg[EAX]  = mkreg("al", EAX, 1, IREG);
-       charreg[ECX]  = mkreg("cl", ECX, 1, IREG);
-       charreg[EDX]  = mkreg("dl", EDX, 1, IREG);
-       charreg[EBX]  = mkreg("bl", EBX, 1, IREG);
-       for (i = 0; i < 8; i++)
-               fltreg[i] = mkreg("%d", i, 0, FREG);
-       rmap[C] = mkwildcard(charreg);
-       rmap[S] = mkwildcard(shortreg);
-       rmap[P] = rmap[B] = rmap[U] = rmap[I] = mkwildcard(intreg);
-       rmap[F] = rmap[D] = mkwildcard(fltreg);
-       tmask[IREG] = (1<<EDI) | (1<<ESI) | (1<<EBX)
-                   | (1<<EDX) | (1<<ECX) | (1<<EAX);
-       vmask[IREG] = 0;
-       tmask[FREG] = 0xff;
-       vmask[FREG] = 0;
-       cseg = 0;
-       quo = mkreg("eax", EAX, 1, IREG);
-       quo->x.regnode->mask |= 1<<EDX;
-       rem = mkreg("edx", EDX, 1, IREG);
-       rem->x.regnode->mask |= 1<<EAX;
-}
-static void segment(n) int n; {
-       if (n == cseg)
-               return;
-       cseg = n;
-       if (cseg == CODE)
-               print("[section .text]\n");
-       else if (cseg == DATA || cseg == LIT)
-               print("[section .data]\n");
-       else if (cseg == BSS)
-               print("[section .bss]\n");
-}
-static void progend() {
-
-}
-static void target(p) Node p; {
-       assert(p);
-       switch (p->op) {
-       case RSHI: case RSHU: case LSHI: case LSHU:
-               if (generic(p->kids[1]->op) != CNST
-               && !(   generic(p->kids[1]->op) == INDIR
-                    && p->kids[1]->kids[0]->op == VREG+P
-                    && p->kids[1]->syms[RX]->u.t.cse
-                    && generic(p->kids[1]->syms[RX]->u.t.cse->op) == CNST
-)) {
-                       rtarget(p, 1, intreg[ECX]);
-                       setreg(p, intreg[EAX]);
-               }
-               break;
-       case MULU:
-               setreg(p, quo);
-               rtarget(p, 0, intreg[EAX]);
-               break;
-       case DIVI: case DIVU:
-               setreg(p, quo);
-               rtarget(p, 0, intreg[EAX]);
-               rtarget(p, 1, intreg[ECX]);
-               break;
-       case MODI: case MODU:
-               setreg(p, rem);
-               rtarget(p, 0, intreg[EAX]);
-               rtarget(p, 1, intreg[ECX]);
-               break;
-       case ASGNB:
-               rtarget(p, 0, intreg[EDI]);
-               rtarget(p->kids[1], 0, intreg[ESI]);
-               break;
-       case ARGB:
-               rtarget(p->kids[0], 0, intreg[ESI]);
-               break;
-       case CALLI: case CALLV:
-               setreg(p, intreg[EAX]);
-               break;
-       case RETI:
-               rtarget(p, 0, intreg[EAX]);
-               break;
-       }
-}
-
-static void clobber(p) Node p; {
-       static int nstack = 0;
-
-       assert(p);
-       nstack = ckstack(p, nstack);
-       assert(p->count > 0 || nstack == 0);
-       switch (p->op) {
-       case ASGNB: case ARGB:
-               spill(1<<ECX | 1<<ESI | 1<<EDI, IREG, p);
-               break;
-       case EQD: case LED: case GED: case LTD: case GTD: case NED:
-       case EQF: case LEF: case GEF: case LTF: case GTF: case NEF:
-               spill(1<<EAX, IREG, p);
-               break;
-       case CALLD: case CALLF:
-               spill(1<<EDX | 1<<EAX, IREG, p);
-               break;
-       }
-}
-#define isfp(p) (optype((p)->op)==F || optype((p)->op)==D)
-
-static int ckstack(p, n) Node p; int n; {
-       int i;
-
-       for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
-               if (isfp(p->x.kids[i]))
-                       n--;
-       if (isfp(p) && p->count > 0)
-               n++;
-       if (n > 8)
-               error("expression too complicated\n");
-       debug(fprint(2, "(ckstack(%x)=%d)\n", p, n));
-       assert(n >= 0);
-       return n;
-}
-static int memop(p) Node p; {
-       assert(p);
-       assert(generic(p->op) == ASGN);
-       assert(p->kids[0]);
-       assert(p->kids[1]);
-       if (generic(p->kids[1]->kids[0]->op) == INDIR
-       && sametree(p->kids[0], p->kids[1]->kids[0]->kids[0]))
-               return 3;
-       else
-               return LBURG_MAX;
-}
-static int sametree(p, q) Node p, q; {
-       return p == NULL && q == NULL
-       || p && q && p->op == q->op && p->syms[0] == q->syms[0]
-               && sametree(p->kids[0], q->kids[0])
-               && sametree(p->kids[1], q->kids[1]);
-}
-static void emit2(p) Node p; {
-#define preg(f) ((f)[getregnum(p->x.kids[0])]->x.name)
-
-       if (p->op == CVCI)
-               print("movsx %s,%s\n", p->syms[RX]->x.name
-, preg(charreg));
-       else if (p->op == CVCU)
-               print("movzx %s,%s\n", p->syms[RX]->x.name
-, preg(charreg));
-       else if (p->op == CVSI)
-               print("movsx %s,%s\n", p->syms[RX]->x.name
-, preg(shortreg));
-       else if (p->op == CVSU)
-               print("movzx %s,%s\n", p->syms[RX]->x.name
-, preg(shortreg));
-       else if (p->op == CVIC || p->op == CVIS
-             || p->op == CVUC || p->op == CVUS) {
-               char *dst = shortreg[getregnum(p)]->x.name;
-               char *src = preg(shortreg);
-               if (dst != src)
-                       print("mov %s,%s\n", dst, src);
-       }
-}
-
-static void doarg(p) Node p; {
-       assert(p && p->syms[0]);
-       mkactual(4, p->syms[0]->u.c.v.i);
-}
-static void blkfetch(k, off, reg, tmp)
-int k, off, reg, tmp; {}
-static void blkstore(k, off, reg, tmp)
-int k, off, reg, tmp; {}
-static void blkloop(dreg, doff, sreg, soff, size, tmps)
-int dreg, doff, sreg, soff, size, tmps[]; {}
-static void local(p) Symbol p; {
-       if (isfloat(p->type))
-               p->sclass = AUTO;
-       if (askregvar(p, rmap[ttob(p->type)]) == 0)
-               mkauto(p);
-}
-static void function(f, caller, callee, n)
-Symbol f, callee[], caller[]; int n; {
-       int i;
-
-       print("%s:\n", f->x.name);
-       print("push ebx\n");
-       print("push esi\n");
-       print("push edi\n");
-       print("push ebp\n");
-       print("mov ebp,esp\n");
-usedmask[0] = usedmask[1] = 0;
-freemask[0] = freemask[1] = ~(unsigned)0;
-       offset = 16 + 4;
-       for (i = 0; callee[i]; i++) {
-               Symbol p = callee[i];
-               Symbol q = caller[i];
-               assert(q);
-               p->x.offset = q->x.offset = offset;
-               p->x.name = q->x.name = stringf("%d", p->x.offset);
-               p->sclass = q->sclass = AUTO;
-               offset += roundup(q->type->size, 4);
-       }
-       assert(caller[i] == 0);
-       offset = maxoffset = 0;
-       gencode(caller, callee);
-       framesize = roundup(maxoffset, 4);
-       if (framesize > 0)
-               print("sub esp,%d\n", framesize);
-       emitcode();
-       print("mov esp,ebp\n");
-       print("pop ebp\n");
-       print("pop edi\n");
-       print("pop esi\n");
-       print("pop ebx\n");
-       print("ret\n");
-}
-static void defsymbol(p) Symbol p; {
-       if (p->scope >= LOCAL && p->sclass == STATIC)
-               p->x.name = stringf("L%d", genlabel(1));
-       else if (p->generated)
-               p->x.name = stringf("$L%s", p->name);
-       else if (p->scope == GLOBAL || p->sclass == EXTERN)
-       /* CHANGE THIS FOR a.out */
-#if 0
-               p->x.name = stringf("$_%s", p->name);
-#else
-               p->x.name = stringf("$%s", p->name);
-#endif
-       else if (p->scope == CONSTANTS
-       && (isint(p->type) || isptr(p->type))
-       && p->name[0] == '0' && p->name[1] == 'x')
-               p->x.name = stringf("0%sH", &p->name[2]);
-       else
-               p->x.name = p->name;
-}
-static void address(q, p, n) Symbol q, p; int n; {
-       if (p->scope == GLOBAL
-       || p->sclass == STATIC || p->sclass == EXTERN)
-               q->x.name = stringf("%s%s%d",
-                       p->x.name, n >= 0 ? "+" : "", n);
-       else {
-               q->x.offset = p->x.offset + n;
-               q->x.name = stringd(q->x.offset);
-       }
-}
-static void defconst(ty, v) int ty; Value v; {
-       switch (ty) {
-               case C: print("db %d\n",   v.uc); return;
-               case S: print("dw %d\n",   v.ss); return;
-               case I: print("dd %d\n",   v.i ); return;
-               case U: print("dd 0%xH\n", v.u ); return;
-               case P: print("dd 0%xH\n", v.p ); return;
-               case F:
-                       print("dd 0%xH\n", *(unsigned *)&v.f);
-                       return;
-               case D: {
-                       unsigned *p = (unsigned *)&v.d;
-                       print("dd 0%xH,0%xH\n", p[swap], p[1 - swap]);
-                       return;
-                       }
-       }
-       assert(0);
-}
-static void defaddress(p) Symbol p; {
-       print("dd %s\n", p->x.name);
-}
-static void defstring(n, str) int n; char *str; {
-       char *s;
-       int inquote = 1;
-
-       print("db '");
-
-       for (s = str; s < str + n; s++)
-       {
-               if ((*s & 0x7F) == *s && *s >= ' ' && *s != '\'') {
-                       if (!inquote){
-                               print(", '");
-                               inquote = 1;
-                       }
-                       print("%c",*s);
-               }
-               else
-               {
-                       if (inquote){
-                               print("', ");
-                               inquote = 0;
-                       }
-                       else
-                               print(", ");
-                       print("%d",*s);
-               }
-       }
-       if (inquote) print("'");
-       print("\n");
-}
-static void export(p) Symbol p; {
-       print("[global %s]\n", p->x.name);
-}
-static void import(p) Symbol p; {
-       if (p->ref > 0) {
-               print("[extern %s]\n", p->x.name);
-       }
-}
-static void global(p) Symbol p; {
-       int i;
-
-       if (p->u.seg == BSS)
-               print("resb ($-$$) & %d\n",
-                       p->type->align > 4 ? 3 : p->type->align-1);
-       else
-               print("times ($-$$) & %d nop\n",
-                       p->type->align > 4 ? 3 : p->type->align-1);
-       print("%s:\n", p->x.name);
-       if (p->u.seg == BSS)
-               print("resb %d\n", p->type->size);
-}
-static void space(n) int n; {
-       int i;
-
-       if (cseg != BSS)
-               print("times %d db 0\n", n);
-}
-Interface x86nasmIR = {
-       1, 1, 0,  /* char */
-       2, 2, 0,  /* short */
-       4, 4, 0,  /* int */
-       4, 4, 1,  /* float */
-       8, 4, 1,  /* double */
-       4, 4, 0,  /* T * */
-       0, 4, 0,  /* struct; so that ARGB keeps stack aligned */
-       1,        /* little_endian */
-       0,        /* mulops_calls */
-       0,        /* wants_callb */
-       1,        /* wants_argb */
-       0,        /* left_to_right */
-       0,        /* wants_dag */
-       address,
-       blockbeg,
-       blockend,
-       defaddress,
-       defconst,
-       defstring,
-       defsymbol,
-       emit,
-       export,
-       function,
-       gen,
-       global,
-       import,
-       local,
-       progbeg,
-       progend,
-       segment,
-       space,
-       0, 0, 0, 0, 0, 0, 0,
-       {1, blkfetch, blkstore, blkloop,
-           _label,
-           _rule,
-           _nts,
-           _kids,
-           _opname,
-           _arity,
-           _string,
-           _templates,
-           _isinstruction,
-           _ntname,
-           emit2,
-           doarg,
-           target,
-           clobber,
-}
-};
index 911da8d..14524ec 100755 (executable)
--- a/macros.pl
+++ b/macros.pl
@@ -57,12 +57,14 @@ sub charcify(@) {
        if ($o < 32 || $o > 126 || $c eq '"' || $c eq "\\") {
            $l .= sprintf("%3d,", $o);
        } else {
+           $c =~ s/\'/\\'/;    # << sanitize single quote. 
            $l .= "\'".$c."\',";
        }
     }
     return $l;
 }
 
+
 #
 # Generate macros.c
 #
diff --git a/nasm.c b/nasm.c
index 36be46e..2522232 100644 (file)
--- a/nasm.c
+++ b/nasm.c
@@ -122,7 +122,8 @@ static struct RAA *offsets;
 static struct SAA *forwrefs;    /* keep track of forward references */
 static const struct forwrefinfo *forwref;
 
-static Preproc *preproc;
+static struct preproc_ops *preproc;
+
 enum op_type {
     op_normal,                  /* Preprocess and assemble */
     op_preprocess,              /* Preprocess only */
@@ -168,10 +169,11 @@ static const struct warning {
  * not preprocess their source file.
  */
 
-static void no_pp_reset(char *, int, ListGen *, StrList **);
+static void no_pp_reset(char *file, int pass, ListGen *listgen, StrList **deplist);
 static char *no_pp_getline(void);
-static void no_pp_cleanup(int);
-static Preproc no_pp = {
+static void no_pp_cleanup(int pass);
+
+static struct preproc_ops no_pp = {
     no_pp_reset,
     no_pp_getline,
     no_pp_cleanup
@@ -1248,10 +1250,22 @@ static void assemble_file(char *fname, StrList **depend_ptr)
                     }
                     break;
                 case D_SECTALIGN:        /* [SECTALIGN n] */
-                    {
-                        if (*value) {
-                            unsigned int align = atoi(value);
-                            if (!is_power2(align)) {
+                    if (*value) {
+                        stdscan_reset();
+                        stdscan_set(value);
+                        tokval.t_type = TOKEN_INVALID;
+                        e = evaluate(stdscan, NULL, &tokval, NULL, pass2, nasm_error, NULL);
+                        if (e) {
+                            unsigned int align = (unsigned int)e->value;
+                            if ((uint64_t)e->value > 0x7fffffff) {
+                                /*
+                                 * FIXME: Please make some sane message here
+                                 * ofmt should have some 'check' method which
+                                 * would report segment alignment bounds.
+                                 */
+                                nasm_error(ERR_FATAL,
+                                           "incorrect segment alignment `%s'", value);
+                            } else if (!is_power2(align)) {
                                 nasm_error(ERR_NONFATAL,
                                            "segment alignment `%s' is not power of two",
                                             value);
diff --git a/nasm.h b/nasm.h
index ff77553..453a57c 100644 (file)
--- a/nasm.h
+++ b/nasm.h
@@ -352,28 +352,28 @@ typedef struct string_list {
 /*
  * preprocessors ought to look like this:
  */
-typedef struct preproc_ops {
+struct preproc_ops {
     /*
      * Called at the start of a pass; given a file name, the number
      * of the pass, an error reporting function, an evaluator
      * function, and a listing generator to talk to.
      */
-    void (*reset) (char *, int, ListGen *, StrList **);
+    void (*reset)(char *file, int pass, ListGen *listgen, StrList **deplist);
 
     /*
      * Called to fetch a line of preprocessed source. The line
      * returned has been malloc'ed, and so should be freed after
      * use.
      */
-    char *(*getline) (void);
+    char *(*getline)(void);
 
     /*
      * Called at the end of a pass.
      */
-    void (*cleanup) (int);
-} Preproc;
+    void (*cleanup)(int pass);
+};
 
-extern Preproc nasmpp;
+extern struct preproc_ops nasmpp;
 
 /*
  * ----------------------------------------------------------------
@@ -400,10 +400,6 @@ extern Preproc nasmpp;
 #define isnumstart(c)  ( nasm_isdigit(c) || (c)=='$' )
 #define isnumchar(c)   ( nasm_isalnum(c) || (c)=='_' )
 
-/* This returns the numeric value of a given 'digit'. */
-
-#define numvalue(c)  ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
-
 /*
  * Data-type flags that get passed to listing-file routines.
  */
@@ -511,7 +507,6 @@ typedef struct operand {    /* operand to an instruction */
 #define OPFLAG_EXTERN          2       /* operand is an external reference */
 #define OPFLAG_UNKNOWN         4       /* operand is an unknown reference */
                                        /* (always a forward reference also) */
-
 typedef struct extop {          /* extended operand */
     struct extop *next;         /* linked list */
     char *stringval;           /* if it's a string, then here it is */
@@ -522,6 +517,13 @@ typedef struct extop {          /* extended operand */
     enum extop_type type;      /* defined above */
 } extop;
 
+enum ea_type {
+    EA_INVALID,                 /* Not a valid EA at all */
+    EA_SCALAR,                  /* Scalar EA */
+    EA_XMMVSIB,                 /* XMM vector EA */
+    EA_YMMVSIB,                 /* XMM vector EA */
+};
+
 /* Prefix positions: each type of prefix goes in a specific slot.
    This affects the final ordering of the assembled output, which
    shouldn't matter to the processor, but if you have stylistic
index 1b70521..f1f9295 100644 (file)
@@ -10,15 +10,15 @@ Source: http://www.nasm.us/pub/nasm/releasebuilds/%{nasm_version}/nasm-%{nasm_ve
 URL: http://www.nasm.us/
 BuildRoot: /tmp/rpm-build-nasm
 Prefix: %{_prefix}
-BuildPrereq: perl
+BuildRequires: perl
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-Requires(post): /sbin/install-info
-Requires(preun): /sbin/install-info
 
 %package doc
 Summary: Extensive documentation for NASM
 Group: Development/Languages
-Prereq: /sbin/install-info
+BuildRequires: ghostscript, texinfo
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
 
 %package rdoff
 Summary: Tools for the RDOFF binary format, sometimes used with NASM.
index d70f6c2..d1e564f 100644 (file)
--- a/nasmlib.c
+++ b/nasmlib.c
@@ -291,8 +291,7 @@ char *nasm_strsep(char **stringp, const char *delim)
 #endif
 
 
-#define lib_isnumchar(c)   (nasm_isalnum(c) || (c) == '$' || (c) == '_')
-#define numvalue(c)  ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
+#define lib_isnumchar(c)    (nasm_isalnum(c) || (c) == '$' || (c) == '_')
 
 static int radix_letter(char c)
 {
index 2c335e1..cddb6b9 100644 (file)
--- a/nasmlib.h
+++ b/nasmlib.h
@@ -205,6 +205,8 @@ int nasm_memicmp(const char *, const char *, size_t);
 char *nasm_strsep(char **stringp, const char *delim);
 #endif
 
+/* This returns the numeric value of a given 'digit'. */
+#define numvalue(c)         ((c) >= 'a' ? (c) - 'a' + 10 : (c) >= 'A' ? (c) - 'A' + 10 : (c) - '0')
 
 /*
  * Convert a string into a number, using NASM number rules. Sets
@@ -246,12 +248,29 @@ void standard_extension(char *inname, char *outname, char *extension);
  *
  *  list_for_each - regular iterator over list
  *  list_for_each_safe - the same but safe against list items removal
+ *  list_last - find the last element in a list
  */
 #define list_for_each(pos, head)                        \
     for (pos = head; pos; pos = pos->next)
 #define list_for_each_safe(pos, n, head)                \
     for (pos = head, n = (pos ? pos->next : NULL); pos; \
         pos = n, n = (n ? n->next : NULL))
+#define list_last(pos, head)                            \
+    for (pos = head; pos && pos->next; pos = pos->next) \
+        ;
+#define list_reverse(head, prev, next)                  \
+    do {                                                \
+        if (!head || !head->next)                       \
+            break;                                      \
+        prev = NULL;                                    \
+        while (head) {                                  \
+            next = head->next;                          \
+            head->next = prev;                          \
+            prev = head;                                \
+            head = next;                                \
+        }                                               \
+        head = prev;                                    \
+    } while (0)
 
 /*
  * Power of 2 align helpers
index b491244..c2b72b0 100644 (file)
--- a/opflags.h
+++ b/opflags.h
  * 23: 256 bits (YWORD)
  * 29: 128 bits (OWORD)
  *
- * Bits 8-11 modifiers
+ * Bits 8-10 modifiers
  *  8: TO
  *  9: COLON
  * 10: STRICT
- * 11: (reserved)
  *
  * Bits 12-15: type of operand
  * 12: REGISTER
@@ -78,7 +77,7 @@
  * 14: MEMORY (always has REGMEM attribute as well)
  * 15: REGMEM (valid EA operand)
  *
- * Bits 16-19, 28: subclasses
+ * Bits 11, 16-19, 28: subclasses
  * With REG_CDT:
  * 16: REG_CREG (CRx)
  * 17: REG_DREG (DRx)
  * 17: BYTENESS16 (-128..127)
  * 18: BYTENESS32 (-128..127)
  * 19: BYTENESS64 (-128..127)
+ * 28: SDWORD64 (-2^31..2^31-1)
+ * 11: UDWORD64 (0..2^32-1)
  *
  * Bits 20-22, 24-27: register classes
  * 20: REG_CDT (CRx, DRx, TRx)
  * 26: RM_XMM (XMMREG)
  * 27: RM_YMM (YMMREG)
  *
- * Bit 31 is currently unallocated.
- *
  * 30: SAME_AS
  * Special flag only used in instruction patterns; means this operand
  * has to be identical to another operand.  Currently only supported
@@ -151,7 +150,7 @@ typedef uint32_t opflags_t;
 #define SIZE_MASK       0x208000FFU   /* all the size attributes */
 
 /* Modifiers */
-#define MODIFIER_MASK   0x00000f00U
+#define MODIFIER_MASK   0x00000700U
 #define TO              0x00000100U   /* reverse effect in FADD, FSUB &c */
 #define COLON           0x00000200U   /* operand is followed by a colon */
 #define STRICT          0x00000400U   /* do not optimize this operand */
@@ -197,7 +196,7 @@ typedef uint32_t opflags_t;
 #define REG_EIP         0x00801004U   /* EIP relative addressing */
 
 /* Special GPRs */
-#define REG_SMASK       0x100f0000U   /* a mask for the following */
+#define REG_SMASK       0x100f0800U   /* a mask for the following */
 #define REG_ACCUM       0x00219000U   /* accumulator: AL, AX, EAX, RAX */
 #define REG_AL          0x00219001U
 #define REG_AX          0x00219002U
@@ -232,6 +231,8 @@ typedef uint32_t opflags_t;
 #define SBYTE32         0x00042000U   /* for op r32,immediate instrs. */
 #define SBYTE64         0x00082000U   /* for op r64,immediate instrs. */
 #define BYTENESS        0x000e0000U   /* for testing for byteness */
+#define SDWORD64       0x10002000U   /* for op r64,simm32 instrs. */
+#define UDWORD64       0x00002800U   /* for op r64,uimm32 instrs. */
 
 /* special flags */
 #define SAME_AS         0x40000000U
index 5c1de01..6c72806 100644 (file)
@@ -285,16 +285,11 @@ static int coff_make_section(char *name, uint32_t flags)
 {
     struct Section *s;
 
-    s = nasm_malloc(sizeof(*s));
+    s = nasm_zalloc(sizeof(*s));
 
     if (flags != BSS_FLAGS)
         s->data = saa_init(1);
-    else
-        s->data = NULL;
-    s->head = NULL;
     s->tail = &s->head;
-    s->len = 0;
-    s->nrelocs = 0;
     if (!strcmp(name, ".text"))
         s->index = def_seg;
     else
index a85acf0..7feb802 100644 (file)
@@ -300,25 +300,21 @@ static int elf_make_section(char *name, int type, int flags, int align)
 {
     struct Section *s;
 
-    s = nasm_malloc(sizeof(*s));
+    s = nasm_zalloc(sizeof(*s));
 
     if (type != SHT_NOBITS)
         s->data = saa_init(1L);
-    s->head = NULL;
     s->tail = &s->head;
-    s->len = s->size = 0;
-    s->nrelocs = 0;
     if (!strcmp(name, ".text"))
         s->index = def_seg;
     else
         s->index = seg_alloc();
     add_sectname("", name);
-    s->name = nasm_malloc(1 + strlen(name));
-    strcpy(s->name, name);
-    s->type = type;
-    s->flags = flags;
-    s->align = align;
-    s->gsyms = NULL;
+
+    s->name     = nasm_strdup(name);
+    s->type     = type;
+    s->flags    = flags;
+    s->align    = align;
 
     if (nsects >= sectlen)
         sects = nasm_realloc(sects, (sectlen += SECT_DELTA) * sizeof(*sects));
@@ -606,16 +602,12 @@ static void elf_add_reloc(struct Section *sect, int32_t segment, int type)
 {
     struct Reloc *r;
 
-    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
+    r = *sect->tail = nasm_zalloc(sizeof(struct Reloc));
     sect->tail = &r->next;
-    r->next = NULL;
 
     r->address = sect->len;
-    if (segment == NO_SEG)
-        r->symbol = 0;
-    else {
+    if (segment != NO_SEG) {
         int i;
-        r->symbol = 0;
         for (i = 0; i < nsects; i++)
             if (segment == sects[i]->index)
                 r->symbol = i + 2;
@@ -691,11 +683,11 @@ static int32_t elf_add_gsym_reloc(struct Section *sect,
 
     r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
     sect->tail = &r->next;
-    r->next = NULL;
 
-    r->address = sect->len;
-    r->symbol = GLOBAL_TEMP_BASE + sym->globnum;
-    r->type = type;
+    r->next     = NULL;
+    r->address  = sect->len;
+    r->symbol   = GLOBAL_TEMP_BASE + sym->globnum;
+    r->type     = type;
 
     sect->nrelocs++;
 
index 9807c2a..46cc6aa 100644 (file)
@@ -308,25 +308,21 @@ static int elf_make_section(char *name, int type, int flags, int align)
 {
     struct Section *s;
 
-    s = nasm_malloc(sizeof(*s));
+    s = nasm_zalloc(sizeof(*s));
 
     if (type != SHT_NOBITS)
         s->data = saa_init(1L);
-    s->head = NULL;
     s->tail = &s->head;
-    s->len = s->size = 0;
-    s->nrelocs = 0;
     if (!strcmp(name, ".text"))
         s->index = def_seg;
     else
         s->index = seg_alloc();
     add_sectname("", name);
-    s->name = nasm_malloc(1 + strlen(name));
-    strcpy(s->name, name);
-    s->type = type;
-    s->flags = flags;
-    s->align = align;
-    s->gsyms = NULL;
+
+    s->name     = nasm_strdup(name);
+    s->type     = type;
+    s->flags    = flags;
+    s->align    = align;
 
     if (nsects >= sectlen)
         sects = nasm_realloc(sects, (sectlen += SECT_DELTA) * sizeof(*sects));
@@ -614,17 +610,15 @@ static void elf_add_reloc(struct Section *sect, int32_t segment,
                           int64_t offset, int type)
 {
     struct Reloc *r;
-    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));
+
+    r = *sect->tail = nasm_zalloc(sizeof(struct Reloc));
     sect->tail = &r->next;
-    r->next = NULL;
 
     r->address = sect->len;
     r->offset = offset;
-    if (segment == NO_SEG)
-        r->symbol = 0;
-    else {
+
+    if (segment != NO_SEG) {
         int i;
-        r->symbol = 0;
         for (i = 0; i < nsects; i++)
             if (segment == sects[i]->index)
                 r->symbol = i + 2;
@@ -1692,9 +1686,7 @@ static void stabs64_generate(void)
 
     ptr = stabslines;
 
-    allfiles = (char **)nasm_malloc(numlinestabs * sizeof(char *));
-    for (i = 0; i < numlinestabs; i++)
-        allfiles[i] = 0;
+    allfiles = (char **)nasm_zalloc(numlinestabs * sizeof(char *));
     numfiles = 0;
     while (ptr) {
         if (numfiles == 0) {
index f3c60b2..42ac109 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -843,7 +843,8 @@ is_expression:
                 if(optimizing >= 0 && !(result->oprs[operand].type & STRICT))
                 {
                     /* Be optimistic */
-                    result->oprs[operand].type |= SBYTE16 | SBYTE32 | SBYTE64;
+                    result->oprs[operand].type |=
+                       SBYTE16 | SBYTE32 | SBYTE64 | UDWORD64 | SDWORD64;
                 }
             } else if (is_reloc(value)) {       /* it's immediate */
                 result->oprs[operand].type |= IMMEDIATE;
@@ -865,6 +866,11 @@ is_expression:
                             result->oprs[operand].type |= SBYTE32;
                        if (v16 >= -128 && v16 <= 127)
                             result->oprs[operand].type |= SBYTE16;
+                       if ((uint64_t)v64 <= UINT64_C(0xffffffff))
+                           result->oprs[operand].type |= UDWORD64;
+                       if (v64 >= -INT64_C(0x80000000) &&
+                           v64 <=  INT64_C(0x7fffffff))
+                           result->oprs[operand].type |= SDWORD64;
                     }
                 }
             } else {            /* it's a register */
index 6b31f0a..936978a 100644 (file)
@@ -161,7 +161,7 @@ sub gen_perfect_hash($) {
        for ($j = 0; $j < $maxj; $j++) {
            $sv = $random_sv_vectors[$j];
            @hashinfo = gen_hash_n($n, $sv, $href, $run++);
-           return @hashinfo if (defined(@hashinfo));
+           return @hashinfo if (@hashinfo);
        }
        $n <<= 1;
     }
@@ -170,32 +170,6 @@ sub gen_perfect_hash($) {
 }
 
 #
-# Read input file
-#
-sub read_input() {
-    my $key,$val;
-    my %out;
-    my $x = 0;
-
-    while (defined($l = <STDIN>)) {
-       chomp $l;
-       $l =~ s/\s*(\#.*|)$//;
-
-       next if ($l eq '');
-
-       if ($l =~ /^([^=]+)\=([^=]+)$/) {
-           $out{$1} = $2;
-           $x = $2;
-       } else {
-           $out{$l} = $x;
-       }
-       $x++;
-    }
-
-    return %out;
-}
-
-#
 # Verify that the hash table is actually correct...
 #
 sub verify_hash_table($$)
index e1071b2..3ef6e71 100755 (executable)
--- a/phash.pl
+++ b/phash.pl
 require 'phash.ph';
 
 #
+# Read input file
+#
+sub read_input() {
+    my $key,$val;
+    my %out;
+    my $x = 0;
+
+    while (defined($l = <STDIN>)) {
+       chomp $l;
+       $l =~ s/\s*(\#.*|)$//;
+
+       next if ($l eq '');
+
+       if ($l =~ /^([^=]+)\=([^=]+)$/) {
+           $out{$1} = $2;
+           $x = $2;
+       } else {
+           $out{$l} = $x;
+       }
+       $x++;
+    }
+
+    return %out;
+}
+
+#
 # Main program
 #
 sub main() {
@@ -49,7 +75,7 @@ sub main() {
     %data = read_input();
     @hashinfo = gen_perfect_hash(\%data);
 
-    if (!defined(@hashinfo)) {
+    if (!@hashinfo) {
        die "$0: no hash found\n";
     }
 
index b78d138..7680356 100644 (file)
--- a/pptok.dat
+++ b/pptok.dat
 %arg
 %assign
 %clear
+%comment
 %define
 %defstr
 %deftok
 %depend
 %elif*
 %else
+%endcomment
 %endif
 %endm
 %endmacro
 %endrep
+%endwhile
 %error
 %exitmacro
 %exitrep
+%exitwhile
 %fatal
+%final
 %iassign
 %idefine
 %idefstr
@@ -92,4 +97,5 @@
 %unmacro
 %use
 %warning
+%while*
 %xdefine
index c9738d3..be85b94 100755 (executable)
--- a/pptok.pl
+++ b/pptok.pl
@@ -164,7 +164,7 @@ if ($what eq 'c') {
     }
 
     my @hashinfo = gen_perfect_hash(\%tokens);
-    if (!defined(@hashinfo)) {
+    if (!@hashinfo) {
        die "$0: no hash found\n";
     }
 
index 07179e1..50ad5cb 100644 (file)
--- a/preproc.c
+++ b/preproc.c
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 1996-2010 The NASM Authors - All Rights Reserved
+ *   Copyright 1996-2011 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
@@ -82,8 +82,8 @@
 #include "tables.h"
 
 typedef struct SMacro SMacro;
-typedef struct MMacro MMacro;
-typedef struct MMacroInvocation MMacroInvocation;
+typedef struct ExpDef ExpDef;
+typedef struct ExpInv ExpInv;
 typedef struct Context Context;
 typedef struct Token Token;
 typedef struct Blocks Blocks;
@@ -114,64 +114,6 @@ struct SMacro {
 };
 
 /*
- * Store the definition of a multi-line macro. This is also used to
- * store the interiors of `%rep...%endrep' blocks, which are
- * effectively self-re-invoking multi-line macros which simply
- * don't have a name or bother to appear in the hash tables. %rep
- * blocks are signified by having a NULL `name' field.
- *
- * In a MMacro describing a `%rep' block, the `in_progress' field
- * isn't merely boolean, but gives the number of repeats left to
- * run.
- *
- * The `next' field is used for storing MMacros in hash tables; the
- * `next_active' field is for stacking them on istk entries.
- *
- * When a MMacro is being expanded, `params', `iline', `nparam',
- * `paramlen', `rotate' and `unique' are local to the invocation.
- */
-struct MMacro {
-    MMacro *next;
-    MMacroInvocation *prev;     /* previous invocation */
-    char *name;
-    int nparam_min, nparam_max;
-    bool casesense;
-    bool plus;                  /* is the last parameter greedy? */
-    bool nolist;                /* is this macro listing-inhibited? */
-    int64_t in_progress;        /* is this macro currently being expanded? */
-    int32_t max_depth;          /* maximum number of recursive expansions allowed */
-    Token *dlist;               /* All defaults as one list */
-    Token **defaults;           /* Parameter default pointers */
-    int ndefs;                  /* number of default parameters */
-    Line *expansion;
-
-    MMacro *next_active;
-    MMacro *rep_nest;           /* used for nesting %rep */
-    Token **params;             /* actual parameters */
-    Token *iline;               /* invocation line */
-    unsigned int nparam, rotate;
-    int *paramlen;
-    uint64_t unique;
-    int lineno;                 /* Current line number on expansion */
-    uint64_t condcnt;           /* number of if blocks... */
-};
-
-
-/* Store the definition of a multi-line macro, as defined in a
- * previous recursive macro expansion.
- */
-struct MMacroInvocation {
-    MMacroInvocation *prev;     /* previous invocation */
-    Token **params;             /* actual parameters */
-    Token *iline;               /* invocation line */
-    unsigned int nparam, rotate;
-    int *paramlen;
-    uint64_t unique;
-    uint64_t condcnt;
-};
-
-
-/*
  * The context stack is composed of a linked list of these.
  */
 struct Context {
@@ -230,34 +172,98 @@ struct Token {
 };
 
 /*
- * Multi-line macro definitions are stored as a linked list of
+ * Expansion definitions are stored as a linked list of
  * these, which is essentially a container to allow several linked
  * lists of Tokens.
  *
  * Note that in this module, linked lists are treated as stacks
  * wherever possible. For this reason, Lines are _pushed_ on to the
- * `expansion' field in MMacro structures, so that the linked list,
- * if walked, would give the macro lines in reverse order; this
- * means that we can walk the list when expanding a macro, and thus
- * push the lines on to the `expansion' field in _istk_ in reverse
- * order (so that when popped back off they are in the right
- * order). It may seem cockeyed, and it relies on my design having
- * an even number of steps in, but it works...
- *
- * Some of these structures, rather than being actual lines, are
- * markers delimiting the end of the expansion of a given macro.
- * This is for use in the cycle-tracking and %rep-handling code.
- * Such structures have `finishes' non-NULL, and `first' NULL. All
- * others have `finishes' NULL, but `first' may still be NULL if
- * the line is blank.
+ * `last' field in ExpDef structures, so that the linked list,
+ * if walked, would emit the expansion lines in the proper order.
  */
 struct Line {
     Line *next;
-    MMacro *finishes;
     Token *first;
 };
 
 /*
+ * Expansion Types
+ */
+enum pp_exp_type {
+    EXP_NONE = 0, EXP_PREDEF,
+    EXP_MMACRO, EXP_REP,
+    EXP_IF, EXP_WHILE,
+    EXP_COMMENT, EXP_FINAL,
+    EXP_MAX = INT_MAX       /* Keep compiler from reducing the range */
+};
+
+/*
+ * Store the definition of an expansion, in which is any
+ * preprocessor directive that has an ending pair.
+ *
+ * This design allows for arbitrary expansion/recursion depth,
+ * upto the DEADMAN_LIMIT.
+ *
+ * The `next' field is used for storing ExpDef in hash tables; the
+ * `prev' field is for the global `expansions` linked-list.
+ */
+struct ExpDef {
+    ExpDef *prev;               /* previous definition */
+    ExpDef *next;               /* next in hash table */
+    enum pp_exp_type type;      /* expansion type */
+    char *name;                 /* definition name */
+    int nparam_min, nparam_max;
+    bool casesense;
+    bool plus;                  /* is the last parameter greedy? */
+    bool nolist;                /* is this expansion listing-inhibited? */
+    Token *dlist;               /* all defaults as one list */
+    Token **defaults;           /* parameter default pointers */
+    int ndefs;                  /* number of default parameters */
+
+    int prepend;                /* label prepend state */
+    Line *label;
+    Line *line;
+    Line *last;
+    int linecount;              /* number of lines within expansion */
+
+    int64_t def_depth;          /* current number of definition pairs deep */
+    int64_t cur_depth;          /* current number of expansions */
+    int64_t max_depth;          /* maximum number of expansions allowed */
+
+    int state;                  /* condition state */
+    bool ignoring;              /* ignoring definition lines */
+};
+
+/*
+ * Store the invocation of an expansion.
+ *
+ * The `prev' field is for the `istk->expansion` linked-list.
+ *
+ * When an expansion is being expanded, `params', `iline', `nparam',
+ * `paramlen', `rotate' and `unique' are local to the invocation.
+ */
+struct ExpInv {
+    ExpInv *prev;               /* previous invocation */
+    enum pp_exp_type type;      /* expansion type */
+    ExpDef *def;                /* pointer to expansion definition */
+    char *name;                 /* invocation name */
+    Line *label;                /* pointer to label */
+    char *label_text;           /* pointer to label text */
+    Line *current;              /* pointer to current line in invocation */
+
+    Token **params;             /* actual parameters */
+    Token *iline;               /* invocation line */
+    unsigned int nparam, rotate;
+    int *paramlen;
+
+    uint64_t unique;
+    bool emitting;
+    int lineno;                 /* current line number in expansion */
+    int linnum;                 /* line number at invocation */
+    int relno;                  /* relative line number at invocation */
+};
+
+/*
  * To handle an arbitrary level of file inclusion, we maintain a
  * stack (ie linked list) of these things.
  */
@@ -265,10 +271,10 @@ struct Include {
     Include *next;
     FILE *fp;
     Cond *conds;
-    Line *expansion;
+    ExpInv *expansion;
     char *fname;
     int lineno, lineinc;
-    MMacro *mstk;       /* stack of active macros/reps */
+    int mmac_depth;
 };
 
 /*
@@ -288,10 +294,6 @@ struct IncPath {
  * included from within the true branch of a `%if' won't terminate
  * it and cause confusion: instead, rightly, it'll cause an error.)
  */
-struct Cond {
-    Cond *next;
-    int state;
-};
 enum {
     /*
      * These states are for use just after %if or %elif: IF_TRUE
@@ -328,8 +330,7 @@ enum {
 #define DIRECTIVE_FOUND     1
 
 /*
- * This define sets the upper limit for smacro and recursive mmacro
- * expansions
+ * This define sets the upper limit for smacro and expansions
  */
 #define DEADMAN_LIMIT (1 << 20)
 
@@ -359,15 +360,6 @@ static const enum pp_conds inverse_ccs[] = {
     c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
 };
 
-/*
- * Directive names.
- */
-/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
-static int is_condition(enum preproc_token arg)
-{
-    return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
-}
-
 /* 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
@@ -404,9 +396,9 @@ static bool do_predef;
 static ListGen *list;
 
 /*
- * The current set of multi-line macros we have defined.
+ * The current set of expansion definitions we have defined.
  */
-static struct hash_table mmacros;
+static struct hash_table expdefs;
 
 /*
  * The current set of single-line macros we have defined.
@@ -414,15 +406,25 @@ static struct hash_table mmacros;
 static struct hash_table smacros;
 
 /*
- * The multi-line macro we are currently defining, or the %rep
- * block we are currently reading, if any.
+ * Linked List of all active expansion definitions
+ */
+struct ExpDef *expansions = NULL;
+
+/*
+ * The expansion we are currently defining
  */
-static MMacro *defining;
+static ExpDef *defining = NULL;
 
 static uint64_t nested_mac_count;
 static uint64_t nested_rep_count;
 
 /*
+ * Linked-list of lines to preprocess, prior to cleanup
+ */
+static Line *finals = NULL;
+static bool in_final = false;
+
+/*
  * The number of macro parameters to allocate space for at a time.
  */
 #define PARAM_DELTA 16
@@ -458,8 +460,7 @@ static Blocks blocks = { NULL, NULL };
 static Token *expand_mmac_params(Token * tline);
 static Token *expand_smacro(Token * tline);
 static Token *expand_id(Token * tline);
-static Context *get_ctx(const char *name, const char **namep,
-                        bool all_contexts);
+static Context *get_ctx(const char *name, const char **namep);
 static void make_tok_num(Token * tok, int64_t val);
 static void error(int severity, const char *fmt, ...);
 static void error_precond(int severity, const char *fmt, ...);
@@ -467,7 +468,11 @@ static void *new_Block(size_t size);
 static void delete_Blocks(void);
 static Token *new_Token(Token * next, enum pp_token_type type,
                         const char *text, int txtlen);
+static Token *copy_Token(Token * tline);
 static Token *delete_Token(Token * t);
+static Line *new_Line(void);
+static ExpDef *new_ExpDef(int exp_type);
+static ExpInv *new_ExpInv(int exp_type, ExpDef *ed);
 
 /*
  * Macros for safe checking of token pointers, avoid *(NULL)
@@ -478,6 +483,97 @@ static Token *delete_Token(Token * t);
 #define tok_isnt_(x,v)  ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
 
 /*
+ * A few helpers for single macros
+ */
+
+/* We might be not smacro parameter at all */
+static bool is_smacro_param(Token *t)
+{
+    return t->type >= TOK_SMAC_PARAM;
+}
+
+/* smacro parameters are counted in a special way */
+static int smacro_get_param_idx(Token *t)
+{
+    return t->type - TOK_SMAC_PARAM;
+}
+
+/* encode smacro parameter index */
+static int smacro_set_param_idx(Token *t, unsigned int index)
+{
+    return t->type = TOK_SMAC_PARAM + index;
+}
+
+#ifdef NASM_TRACE
+
+#define stringify(x)  #x
+
+#define nasm_trace(msg, ...)    printf("(%s:%d): " msg "\n", __func__, __LINE__, ##__VA_ARGS__)
+#define nasm_dump_token(t)      nasm_raw_dump_token(t, __FILE__, __LINE__, __func__);
+#define nasm_dump_stream(t)     nasm_raw_dump_stream(t, __FILE__, __LINE__, __func__);
+
+/* FIXME: we really need some compound type here instead of inplace code */
+static const char *nasm_get_tok_type_str(enum pp_token_type type)
+{
+#define SWITCH_TOK_NAME(type)       \
+    case (type):                    \
+        return stringify(type)
+
+    switch (type) {
+    SWITCH_TOK_NAME(TOK_NONE);
+    SWITCH_TOK_NAME(TOK_WHITESPACE);
+    SWITCH_TOK_NAME(TOK_COMMENT);
+    SWITCH_TOK_NAME(TOK_ID);
+    SWITCH_TOK_NAME(TOK_PREPROC_ID);
+    SWITCH_TOK_NAME(TOK_STRING);
+    SWITCH_TOK_NAME(TOK_NUMBER);
+    SWITCH_TOK_NAME(TOK_FLOAT);
+    SWITCH_TOK_NAME(TOK_SMAC_END);
+    SWITCH_TOK_NAME(TOK_OTHER);
+    SWITCH_TOK_NAME(TOK_INTERNAL_STRING);
+    SWITCH_TOK_NAME(TOK_PREPROC_Q);
+    SWITCH_TOK_NAME(TOK_PREPROC_QQ);
+    SWITCH_TOK_NAME(TOK_PASTE);
+    SWITCH_TOK_NAME(TOK_INDIRECT);
+    SWITCH_TOK_NAME(TOK_SMAC_PARAM);
+    SWITCH_TOK_NAME(TOK_MAX);
+    }
+
+    return NULL;
+}
+
+static void nasm_raw_dump_token(Token *token, const char *file, int line, const char *func)
+{
+    printf("---[%s (%s:%d): %p]---\n", func, file, line, (void *)token);
+    if (token) {
+        Token *t;
+        list_for_each(t, token) {
+            if (t->text)
+                printf("'%s'(%s) ", t->text,
+                       nasm_get_tok_type_str(t->type));
+        }
+        printf("\n\n");
+    }
+}
+
+static void nasm_raw_dump_stream(Token *token, const char *file, int line, const char *func)
+{
+    printf("---[%s (%s:%d): %p]---\n", func, file, line, (void *)token);
+    if (token) {
+        Token *t;
+        list_for_each(t, token)
+            printf("%s", t->text ? t->text : " ");
+        printf("\n\n");
+    }
+}
+
+#else
+#define nasm_trace(msg, ...)
+#define nasm_dump_token(t)
+#define nasm_dump_stream(t)
+#endif
+
+/*
  * nasm_unquote with error if the string contains NUL characters.
  * If the string contains NUL characters, issue an error and return
  * the C len, i.e. truncate at the NUL.
@@ -499,17 +595,11 @@ static size_t nasm_unquote_cstr(char *qstr, enum preproc_token directive)
  */
 static Token *reverse_tokens(Token *t)
 {
-    Token *prev = NULL;
-    Token *next;
+    Token *prev, *next;
 
-    while (t) {
-       next = t->next;
-       t->next = prev;
-       prev = t;
-       t = next;
-    }
+    list_reverse(t, prev, next);
 
-    return prev;
+    return t;
 }
 
 /*
@@ -618,15 +708,25 @@ static void free_llist(Line * list)
 }
 
 /*
- * Free an MMacro
+ * Free an ExpDef
+ */
+static void free_expdef(ExpDef * ed)
+{
+    nasm_free(ed->name);
+    free_tlist(ed->dlist);
+    nasm_free(ed->defaults);
+    free_llist(ed->line);
+    nasm_free(ed);
+}
+
+/*
+ * Free an ExpInv
  */
-static void free_mmacro(MMacro * m)
+static void free_expinv(ExpInv * ei)
 {
-    nasm_free(m->name);
-    free_tlist(m->dlist);
-    nasm_free(m->defaults);
-    free_llist(m->expansion);
-    nasm_free(m);
+    nasm_free(ei->name);
+    nasm_free(ei->label_text);
+    nasm_free(ei);
 }
 
 /*
@@ -649,25 +749,25 @@ static void free_smacro_table(struct hash_table *smt)
     hash_free(smt);
 }
 
-static void free_mmacro_table(struct hash_table *mmt)
+static void free_expdef_table(struct hash_table *edt)
 {
-    MMacro *m, *tmp;
+    ExpDef *ed, *tmp;
     const char *key;
     struct hash_tbl_node *it = NULL;
 
     it = NULL;
-    while ((m = hash_iterate(mmt, &it, &key)) != NULL) {
+    while ((ed = hash_iterate(edt, &it, &key)) != NULL) {
         nasm_free((void *)key);
-        list_for_each_safe(m ,tmp, m)
-            free_mmacro(m);
+        list_for_each_safe(ed ,tmp, ed)
+            free_expdef(ed);
     }
-    hash_free(mmt);
+    hash_free(edt);
 }
 
 static void free_macros(void)
 {
     free_smacro_table(&smacros);
-    free_mmacro_table(&mmacros);
+    free_expdef_table(&expdefs);
 }
 
 /*
@@ -676,7 +776,7 @@ static void free_macros(void)
 static void init_macros(void)
 {
     hash_init(&smacros, HASH_LARGE);
-    hash_init(&mmacros, HASH_LARGE);
+    hash_init(&expdefs, HASH_LARGE);
 }
 
 /*
@@ -726,7 +826,7 @@ hash_findix(struct hash_table *hash, const char *str)
 }
 
 /*
- * read line from standart macros set,
+ * read line from standard macros set,
  * if there no more left -- return NULL
  */
 static char *line_from_stdmac(void)
@@ -767,6 +867,7 @@ static char *line_from_stdmac(void)
             stdmacpos = extrastdmac;
             any_extrastdmac = false;
         } else if (do_predef) {
+            ExpInv *ei;
             Line *pd, *l;
             Token *head, **tail, *t;
 
@@ -785,12 +886,13 @@ static char *line_from_stdmac(void)
                     tail = &(*tail)->next;
                 }
 
-                l           = nasm_malloc(sizeof(Line));
-                l->next     = istk->expansion;
-                l->first    = head;
-                l->finishes = NULL;
-
-                istk->expansion = l;
+                l = new_Line();
+                l->first = head;
+                ei = new_ExpInv(EXP_PREDEF, NULL);
+                ei->current = l;
+                ei->emitting = true;
+                ei->prev = istk->expansion;
+                istk->expansion = ei;
             }
             do_predef = false;
         }
@@ -897,6 +999,13 @@ static Token *tokenize(char *line)
     enum pp_token_type type;
     Token *list = NULL;
     Token *t, **tail = &list;
+    bool verbose = true;
+
+    nasm_trace("Tokenize for '%s'", line);
+
+    if ((defining != NULL) && (defining->ignoring == true)) {
+        verbose = false;
+    }
 
     while (*line) {
         p = line;
@@ -914,14 +1023,10 @@ static Token *tokenize(char *line)
                 type = TOK_PREPROC_ID;
             } else if (*p == '{') {
                 p++;
-                while (*p) {
-                    if (*p == '}')
-                        break;
+                while (*p && *p != '}') {
                     p[-1] = *p;
                     p++;
                 }
-                if (*p != '}')
-                    error(ERR_WARNING | ERR_PASS1, "unterminated %{ construct");
                 p[-1] = '\0';
                 if (*p)
                     p++;
@@ -951,7 +1056,7 @@ static Token *tokenize(char *line)
                 p--;
                 if (*p)
                     *p++ = '\0';
-                if (lvl)
+                if (lvl && verbose)
                     error(ERR_NONFATAL, "unterminated %[ construct");
                 type = TOK_INDIRECT;
             } else if (*p == '?') {
@@ -961,24 +1066,23 @@ static Token *tokenize(char *line)
                     type = TOK_PREPROC_QQ; /* %?? */
                     p++;
                 }
-           } else if (*p == '!') {
-               type = TOK_PREPROC_ID;
-               p++;
-               if (isidchar(*p)) {
-                   do {
-                       p++;
-                   }
-                   while (isidchar(*p));
-               } else if (*p == '\'' || *p == '\"' || *p == '`') {
-                   p = nasm_skip_string(p);
-                   if (*p)
-                       p++;
-                   else
-                       error(ERR_NONFATAL|ERR_PASS1, "unterminated %! string");
-               } else {
-                   /* %! without string or identifier */
-                   type = TOK_OTHER; /* Legacy behavior... */
-               }
+            } else if (*p == '!') {
+                type = TOK_PREPROC_ID;
+                p++;
+                if (isidchar(*p)) {
+                    do {
+                        p++;
+                    } while (isidchar(*p));
+                } else if (*p == '\'' || *p == '\"' || *p == '`') {
+                    p = nasm_skip_string(p);
+                    if (*p)
+                        p++;
+                    else if(verbose)
+                        error(ERR_NONFATAL|ERR_PASS1, "unterminated %! string");
+                } else {
+                    /* %! without string or identifier */
+                    type = TOK_OTHER; /* Legacy behavior... */
+                }
             } else if (isidchar(*p) ||
                        ((*p == '!' || *p == '%' || *p == '$') &&
                         isidchar(p[1]))) {
@@ -1006,7 +1110,7 @@ static Token *tokenize(char *line)
 
             if (*p) {
                 p++;
-            } else {
+            } else if(verbose) {
                 error(ERR_WARNING|ERR_PASS1, "unterminated string");
                 /* Handling unterminated strings by UNV */
                 /* type = -1; */
@@ -1142,6 +1246,9 @@ static Token *tokenize(char *line)
         }
         line = p;
     }
+
+    nasm_dump_token(list);
+
     return list;
 }
 
@@ -1157,14 +1264,13 @@ static void *new_Block(size_t size)
     /* first, get to the end of the linked list */
     while (b->next)
         b = b->next;
+
     /* now allocate the requested chunk */
     b->chunk = nasm_malloc(size);
 
     /* now allocate a new block for the next request */
-    b->next = nasm_malloc(sizeof(Blocks));
-    /* and initialize the contents of the new block */
-    b->next->next = NULL;
-    b->next->chunk = NULL;
+    b->next = nasm_zalloc(sizeof(Blocks));
+
     return b->chunk;
 }
 
@@ -1181,8 +1287,7 @@ static void delete_Blocks(void)
      * free it.
      */
     while (b) {
-        if (b->chunk)
-            nasm_free(b->chunk);
+        nasm_free(b->chunk);
         a = b;
         b = b->next;
         if (a != &blocks)
@@ -1224,6 +1329,34 @@ static Token *new_Token(Token * next, enum pp_token_type type,
     return t;
 }
 
+static Token *copy_Token(Token * tline)
+{
+    Token *t, *tt, *first = NULL, *prev = NULL;
+    int i;
+    for (tt = tline; tt != NULL; tt = tt->next) {
+        if (!freeTokens) {
+            freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
+            for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
+                freeTokens[i].next = &freeTokens[i + 1];
+            freeTokens[i].next = NULL;
+        }
+        t = freeTokens;
+        freeTokens = t->next;
+        t->next = NULL;
+        t->text = tt->text ? nasm_strdup(tt->text) : NULL;
+        t->a.mac = tt->a.mac;
+        t->a.len = tt->a.len;
+        t->type = tt->type;
+        if (prev != NULL) {
+            prev->next = t;
+        } else {
+            first = t;
+        }
+        prev = t;
+    }
+    return first;
+}
+
 static Token *delete_Token(Token * t)
 {
     Token *next = t->next;
@@ -1247,31 +1380,31 @@ static char *detoken(Token * tlist, bool expand_locals)
 
     list_for_each(t, tlist) {
         if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
-           char *v;
-           char *q = t->text;
-
-           v = t->text + 2;
-           if (*v == '\'' || *v == '\"' || *v == '`') {
-               size_t len = nasm_unquote(v, NULL);
-               size_t clen = strlen(v);
-
-               if (len != clen) {
-                   error(ERR_NONFATAL | ERR_PASS1,
-                         "NUL character in %! string");
-                   v = NULL;
-               }
-           }
-
-           if (v) {
-               char *p = getenv(v);
-               if (!p) {
-                   error(ERR_NONFATAL | ERR_PASS1,
-                         "nonexistent environment variable `%s'", v);
-                   p = "";
-               }
-               t->text = nasm_strdup(p);
-           }
-           nasm_free(q);
+            char *v;
+            char *q = t->text;
+
+            v = t->text + 2;
+            if (*v == '\'' || *v == '\"' || *v == '`') {
+                size_t len = nasm_unquote(v, NULL);
+                size_t clen = strlen(v);
+
+                if (len != clen) {
+                    error(ERR_NONFATAL | ERR_PASS1,
+                          "NUL character in %! string");
+                    v = NULL;
+                }
+            }
+
+            if (v) {
+                char *p = getenv(v);
+                if (!p) {
+                    error(ERR_NONFATAL | ERR_PASS1,
+                          "nonexistent environment variable `%s'", v);
+                    p = "";
+                }
+                t->text = nasm_strdup(p);
+            }
+            nasm_free(q);
         }
 
         /* Expand local macros here and not during preprocessing */
@@ -1280,7 +1413,7 @@ static char *detoken(Token * tlist, bool expand_locals)
             t->text[0] == '%' && t->text[1] == '$') {
             const char *q;
             char *p;
-            Context *ctx = get_ctx(t->text, &q, false);
+            Context *ctx = get_ctx(t->text, &q);
             if (ctx) {
                 char buffer[40];
                 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
@@ -1289,6 +1422,25 @@ static char *detoken(Token * tlist, bool expand_locals)
                 t->text = p;
             }
         }
+
+        /* Expand %? and %?? directives */
+        if ((istk->expansion != NULL) &&
+            ((t->type == TOK_PREPROC_Q) ||
+             (t->type == TOK_PREPROC_QQ))) {
+            ExpInv *ei;
+            for (ei = istk->expansion; ei != NULL; ei = ei->prev){
+                if (ei->type == EXP_MMACRO) {
+                    nasm_free(t->text);
+                    if (t->type == TOK_PREPROC_Q) {
+                        t->text = nasm_strdup(ei->name);
+                    } else {
+                        t->text = nasm_strdup(ei->def->name);
+                    }
+                    break;
+                }
+            }
+        }
+
         if (t->type == TOK_WHITESPACE)
             len++;
         else if (t->text)
@@ -1312,6 +1464,62 @@ static char *detoken(Token * tlist, bool expand_locals)
 }
 
 /*
+ * Initialize a new Line
+ */
+static inline Line *new_Line(void)
+{
+    return (Line *)nasm_zalloc(sizeof(Line));
+}
+
+
+/*
+ * Initialize a new Expansion Definition
+ */
+static ExpDef *new_ExpDef(int exp_type)
+{
+    ExpDef *ed      = (ExpDef*)nasm_zalloc(sizeof(ExpDef));
+    ed->type        = exp_type;
+    ed->casesense   = true;
+    ed->state       = COND_NEVER;
+
+    return ed;
+}
+
+
+/*
+ * Initialize a new Expansion Instance
+ */
+static ExpInv *new_ExpInv(int exp_type, ExpDef *ed)
+{
+    ExpInv *ei  = (ExpInv*)nasm_zalloc(sizeof(ExpInv));
+    ei->type    = exp_type;
+    ei->def     = ed;
+    ei->unique  = ++unique;
+
+    if ((istk->mmac_depth < 1) &&
+        (istk->expansion == NULL) &&
+        (ed != NULL) &&
+        (ed->type != EXP_MMACRO) &&
+        (ed->type != EXP_REP) &&
+        (ed->type != EXP_WHILE)) {
+        ei->linnum = src_get_linnum();
+        src_set_linnum(ei->linnum - ed->linecount - 1);
+    } else {
+        ei->linnum = -1;
+    }
+    if ((istk->expansion == NULL) ||
+        (ei->type == EXP_MMACRO)) {
+        ei->relno = 0;
+    } else {
+        ei->relno = istk->expansion->lineno;
+        if (ed != NULL) {
+            ei->relno -= (ed->linecount + 1);
+        }
+    }
+    return ei;
+}
+
+/*
  * A scanner, suitable for use by the expression evaluator, which
  * operates on a line of Tokens. Expects a pointer to a pointer to
  * the first token in the line to be passed in as its private_data
@@ -1445,19 +1653,13 @@ static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
  * NULL, having _already_ reported an error condition, if the
  * context stack isn't deep enough for the supplied number of $
  * signs.
- * If all_contexts == true, contexts that enclose current are
- * also scanned for such smacro, until it is found; if not -
- * only the context that directly results from the number of $'s
- * in variable's name.
  *
  * If "namep" is non-NULL, set it to the pointer to the macro name
  * tail, i.e. the part beyond %$...
  */
-static Context *get_ctx(const char *name, const char **namep,
-                        bool all_contexts)
+static Context *get_ctx(const char *name, const char **namep)
 {
     Context *ctx;
-    SMacro *m;
     int i;
 
     if (namep)
@@ -1479,6 +1681,7 @@ static Context *get_ctx(const char *name, const char **namep,
         i++;
         ctx = ctx->next;
     }
+
     if (!ctx) {
         error(ERR_NONFATAL, "`%s': context stack is only"
               " %d level%s deep", name, i, (i == 1 ? "" : "s"));
@@ -1488,47 +1691,7 @@ static Context *get_ctx(const char *name, const char **namep,
     if (namep)
         *namep = name;
 
-    if (!all_contexts)
-        return ctx;
-
-    /*
-     * NOTE: In 2.10 we will not need lookup in extarnal
-     * contexts, so this is a gentle way to inform users
-     * about their source code need to be updated
-     */
-
-    /* first round -- check the current context */
-    m = hash_findix(&ctx->localmac, name);
-    while (m) {
-        if (!mstrcmp(m->name, name, m->casesense))
-            return ctx;
-        m = m->next;
-    }
-
-    /* second round - external contexts */
-    while ((ctx = ctx->next)) {
-        /* Search for this smacro in found context */
-        m = hash_findix(&ctx->localmac, name);
-        while (m) {
-            if (!mstrcmp(m->name, name, m->casesense)) {
-                /* NOTE: deprecated as of 2.10 */
-                static int once = 0;
-                if (!once) {
-                    error(ERR_WARNING, "context-local macro expansion"
-                            " fall-through (automatic searching of outer"
-                                                   " contexts) will be deprecated starting in"
-                                                   " NASM 2.10, please see the NASM Manual for"
-                                                   " more information");
-                    once = 1;
-                }
-                error(ERR_WARNING, "`%s': context-local macro expansion fall-through", name);
-                return ctx;
-            }
-            m = m->next;
-        }
-    }
-
-    return NULL;
+    return ctx;
 }
 
 /*
@@ -1563,11 +1726,11 @@ static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
 
     while (1) {
         sl = nasm_malloc(prefix_len+len+1+sizeof sl->next);
+        sl->next = NULL;
         memcpy(sl->str, prefix, prefix_len);
         memcpy(sl->str+prefix_len, file, len+1);
         fp = fopen(sl->str, "r");
         if (fp && dhead && !in_list(*dhead, sl->str)) {
-            sl->next = NULL;
             **dtail = sl;
             *dtail = &sl->next;
         } else {
@@ -1634,7 +1797,7 @@ smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
         smtbl = &ctx->localmac;
     } else if (name[0] == '%' && name[1] == '$') {
         if (cstk)
-            ctx = get_ctx(name, &name, false);
+            ctx = get_ctx(name, &name);
         if (!ctx)
             return false;       /* got to return _something_ */
         smtbl = &ctx->localmac;
@@ -1761,26 +1924,26 @@ static bool if_condition(Token * tline, enum preproc_token ct)
         break;
 
     case PPC_IFENV:
-       tline = expand_smacro(tline);
+        tline = expand_smacro(tline);
         j = false;              /* have we matched yet? */
         while (tline) {
             skip_white_(tline);
             if (!tline || (tline->type != TOK_ID &&
-                          tline->type != TOK_STRING &&
+                           tline->type != TOK_STRING &&
                            (tline->type != TOK_PREPROC_ID ||
-                           tline->text[1] != '!'))) {
+                            tline->text[1] != '!'))) {
                 error(ERR_NONFATAL,
                       "`%s' expects environment variable names",
-                     pp_directives[ct]);
+                      pp_directives[ct]);
                 goto fail;
             }
-           p = tline->text;
-           if (tline->type == TOK_PREPROC_ID)
-               p += 2;         /* Skip leading %! */
-           if (*p == '\'' || *p == '\"' || *p == '`')
-               nasm_unquote_cstr(p, ct);
-           if (getenv(p))
-               j = true;
+            p = tline->text;
+            if (tline->type == TOK_PREPROC_ID)
+                p += 2;         /* Skip leading %! */
+            if (*p == '\'' || *p == '\"' || *p == '`')
+                nasm_unquote_cstr(p, ct);
+            if (getenv(p))
+                j = true;
             tline = tline->next;
         }
         break;
@@ -1845,7 +2008,7 @@ static bool if_condition(Token * tline, enum preproc_token ct)
     case PPC_IFMACRO:
     {
         bool found = false;
-        MMacro searching, *mmac;
+        ExpDef searching, *ed;
 
         skip_white_(tline);
         tline = expand_id(tline);
@@ -1854,14 +2017,9 @@ static bool if_condition(Token * tline, enum preproc_token ct)
                   "`%s' expects a macro name", pp_directives[ct]);
             goto fail;
         }
+        memset(&searching, 0, sizeof(searching));
         searching.name = nasm_strdup(tline->text);
         searching.casesense = true;
-        searching.plus = false;
-        searching.nolist = false;
-        searching.in_progress = 0;
-        searching.max_depth = 0;
-        searching.rep_nest = NULL;
-        searching.nparam_min = 0;
         searching.nparam_max = INT_MAX;
         tline = expand_smacro(tline->next);
         skip_white_(tline);
@@ -1901,17 +2059,15 @@ static bool if_condition(Token * tline, enum preproc_token ct)
             tline = tline->next;
             searching.plus = true;
         }
-        mmac = (MMacro *) hash_findix(&mmacros, searching.name);
-        while (mmac) {
-            if (!strcmp(mmac->name, searching.name) &&
-                (mmac->nparam_min <= searching.nparam_max
-                 || searching.plus)
-                && (searching.nparam_min <= mmac->nparam_max
-                    || mmac->plus)) {
+        ed = (ExpDef *) hash_findix(&expdefs, searching.name);
+        while (ed != NULL) {
+            if (!strcmp(ed->name, searching.name)                           &&
+                (ed->nparam_min <= searching.nparam_max || searching.plus)  &&
+                (searching.nparam_min <= ed->nparam_max || ed->plus)) {
                 found = true;
                 break;
             }
-            mmac = mmac->next;
+            ed = ed->next;
         }
         if (tline && tline->next)
             error(ERR_WARNING|ERR_PASS1,
@@ -2032,7 +2188,7 @@ static bool define_smacro(Context *ctx, const char *mname, bool casesense,
     } else {
         smtbl  = ctx ? &ctx->localmac : &smacros;
         smhead = (SMacro **) hash_findi_add(smtbl, mname);
-        smac = nasm_malloc(sizeof(SMacro));
+        smac = nasm_zalloc(sizeof(SMacro));
         smac->next = *smhead;
         *smhead = smac;
     }
@@ -2076,7 +2232,7 @@ static void undef_smacro(Context *ctx, const char *mname)
 /*
  * Parse a mmacro specification.
  */
-static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
+static bool parse_mmacro_spec(Token *tline, ExpDef *def, const char *directive)
 {
     bool err;
 
@@ -2088,12 +2244,11 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
         return false;
     }
 
-    def->prev = NULL;
     def->name = nasm_strdup(tline->text);
     def->plus = false;
     def->nolist = false;
-    def->in_progress = 0;
-    def->rep_nest = NULL;
+//    def->in_progress = 0;
+//    def->rep_nest = NULL;
     def->nparam_min = 0;
     def->nparam_max = 0;
 
@@ -2147,7 +2302,7 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
         def->dlist = NULL;
         def->defaults = NULL;
     }
-    def->expansion = NULL;
+    def->line = NULL;
 
     if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
         !def->plus)
@@ -2196,13 +2351,12 @@ static int do_directive(Token * tline)
     const char *mname;
     Include *inc;
     Context *ctx;
-    Cond *cond;
-    MMacro *mmac, **mmhead;
-    Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
     Line *l;
+    Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
     struct tokenval tokval;
     expr *evalresult;
-    MMacro *tmp_defining;       /* Used when manipulating rep_nest */
+    ExpDef *ed, *eed, **edhead;
+    ExpInv *ei, *eei;
     int64_t count;
     size_t len;
     int severity;
@@ -2217,72 +2371,15 @@ static int do_directive(Token * tline)
 
     i = pp_token_hash(tline->text);
 
-    /*
-     * FIXME: We zap execution of PP_RMACRO, PP_IRMACRO, PP_EXITMACRO
-     * since they are known to be buggy at moment, we need to fix them
-     * in future release (2.09-2.10)
-     */
-    if (i == PP_RMACRO || i == PP_RMACRO || i == PP_EXITMACRO) {
-        error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
-              tline->text);
-       return NO_DIRECTIVE_FOUND;
-    }
-
-    /*
-     * If we're in a non-emitting branch of a condition construct,
-     * or walking to the end of an already terminated %rep block,
-     * we should ignore all directives except for condition
-     * directives.
-     */
-    if (((istk->conds && !emitting(istk->conds->state)) ||
-         (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
-        return NO_DIRECTIVE_FOUND;
-    }
-
-    /*
-     * If we're defining a macro or reading a %rep block, we should
-     * ignore all directives except for %macro/%imacro (which nest),
-     * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
-     * If we're in a %rep block, another %rep nests, so should be let through.
-     */
-    if (defining && i != PP_MACRO && i != PP_IMACRO &&
-        i != PP_RMACRO &&  i != PP_IRMACRO &&
-        i != PP_ENDMACRO && i != PP_ENDM &&
-        (defining->name || (i != PP_ENDREP && i != PP_REP))) {
-        return NO_DIRECTIVE_FOUND;
-    }
-
-    if (defining) {
-        if (i == PP_MACRO || i == PP_IMACRO ||
-            i == PP_RMACRO || i == PP_IRMACRO) {
-            nested_mac_count++;
-            return NO_DIRECTIVE_FOUND;
-        } else if (nested_mac_count > 0) {
-            if (i == PP_ENDMACRO) {
-                nested_mac_count--;
-                return NO_DIRECTIVE_FOUND;
-            }
-        }
-        if (!defining->name) {
-            if (i == PP_REP) {
-                nested_rep_count++;
-                return NO_DIRECTIVE_FOUND;
-            } else if (nested_rep_count > 0) {
-                if (i == PP_ENDREP) {
-                    nested_rep_count--;
-                    return NO_DIRECTIVE_FOUND;
-                }
-            }
-        }
-    }
-
     switch (i) {
     case PP_INVALID:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
               tline->text);
         return NO_DIRECTIVE_FOUND;      /* didn't get it */
 
     case PP_STACKSIZE:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         /* 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.
@@ -2332,6 +2429,7 @@ static int do_directive(Token * tline)
         return DIRECTIVE_FOUND;
 
     case PP_ARG:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         /* TASM like ARG directive to define arguments to functions, in
          * the following form:
          *
@@ -2401,6 +2499,7 @@ static int do_directive(Token * tline)
         return DIRECTIVE_FOUND;
 
     case PP_LOCAL:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         /* TASM like LOCAL directive to define local variables for a
          * function, in the following form:
          *
@@ -2482,6 +2581,7 @@ static int do_directive(Token * tline)
         return DIRECTIVE_FOUND;
 
     case PP_CLEAR:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         if (tline->next)
             error(ERR_WARNING|ERR_PASS1,
                   "trailing garbage after `%%clear' ignored");
@@ -2491,6 +2591,7 @@ static int do_directive(Token * tline)
         return DIRECTIVE_FOUND;
 
     case PP_DEPEND:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         t = tline->next = expand_smacro(tline->next);
         skip_white_(t);
         if (!t || (t->type != TOK_STRING &&
@@ -2516,6 +2617,7 @@ static int do_directive(Token * tline)
         return DIRECTIVE_FOUND;
 
     case PP_INCLUDE:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         t = tline->next = expand_smacro(tline->next);
         skip_white_(t);
 
@@ -2531,9 +2633,8 @@ static int do_directive(Token * tline)
         p = t->text;
         if (t->type != TOK_INTERNAL_STRING)
             nasm_unquote_cstr(p, i);
-        inc = nasm_malloc(sizeof(Include));
+        inc = nasm_zalloc(sizeof(Include));
         inc->next = istk;
-        inc->conds = NULL;
         inc->fp = inc_fopen(p, dephead, &deptail, pass == 0);
         if (!inc->fp) {
             /* -MG given but file not found */
@@ -2543,7 +2644,6 @@ static int do_directive(Token * tline)
             inc->lineno = src_set_linnum(0);
             inc->lineinc = 1;
             inc->expansion = NULL;
-            inc->mstk = NULL;
             istk = inc;
             list->uplevel(LIST_INCLUDE);
         }
@@ -2551,6 +2651,7 @@ static int do_directive(Token * tline)
         return DIRECTIVE_FOUND;
 
     case PP_USE:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
     {
         static macros_t *use_pkg;
         const char *pkg_macro = NULL;
@@ -2586,6 +2687,7 @@ static int do_directive(Token * tline)
     case PP_PUSH:
     case PP_REPL:
     case PP_POP:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         tline = tline->next;
         skip_white_(tline);
         tline = expand_id(tline);
@@ -2606,7 +2708,7 @@ static int do_directive(Token * tline)
         }
 
         if (i == PP_PUSH) {
-            ctx = nasm_malloc(sizeof(Context));
+            ctx = nasm_zalloc(sizeof(Context));
             ctx->next = cstk;
             hash_init(&ctx->localmac, HASH_SMALL);
             ctx->name = p;
@@ -2645,6 +2747,7 @@ static int do_directive(Token * tline)
         goto issue_error;
 
 issue_error:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
     {
         /* Only error out if this is the final pass */
         if (pass != 2 && i != PP_FATAL)
@@ -2671,39 +2774,58 @@ issue_error:
     }
 
     CASE_PP_IF:
-        if (istk->conds && !emitting(istk->conds->state))
+        if (defining != NULL) {
+            if (defining->type == EXP_IF) {
+                defining->def_depth ++;
+            }
+            return NO_DIRECTIVE_FOUND;
+        }
+        if ((istk->expansion != NULL) &&
+            (istk->expansion->emitting == false)) {
             j = COND_NEVER;
-        else {
+        else {
             j = if_condition(tline->next, i);
             tline->next = NULL; /* it got freed */
-            j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
-        }
-        cond = nasm_malloc(sizeof(Cond));
-        cond->next = istk->conds;
-        cond->state = j;
-        istk->conds = cond;
-        if(istk->mstk)
-            istk->mstk->condcnt ++;
+            j = (((j < 0) ? COND_NEVER : j) ? COND_IF_TRUE : COND_IF_FALSE);
+        }
+        ed = new_ExpDef(EXP_IF);
+        ed->state = j;
+        ed->nolist = NULL;
+        ed->def_depth = 0;
+        ed->cur_depth = 0;
+        ed->max_depth = 0;
+        ed->ignoring = ((ed->state == COND_IF_TRUE) ? false : true);
+        ed->prev = defining;
+        defining = ed;
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
     CASE_PP_ELIF:
-        if (!istk->conds)
+        if (defining != NULL) {
+            if ((defining->type != EXP_IF) || (defining->def_depth > 0)) {
+                return NO_DIRECTIVE_FOUND;
+            }
+        }
+        if ((defining == NULL) || (defining->type != EXP_IF)) {
             error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
-        switch(istk->conds->state) {
+        }
+        switch (defining->state) {
         case COND_IF_TRUE:
-            istk->conds->state = COND_DONE;
+            defining->state = COND_DONE;
+            defining->ignoring = true;
             break;
 
         case COND_DONE:
         case COND_NEVER:
+            defining->ignoring = true;
             break;
 
         case COND_ELSE_TRUE:
         case COND_ELSE_FALSE:
             error_precond(ERR_WARNING|ERR_PASS1,
                           "`%%elif' after `%%else' ignored");
-            istk->conds->state = COND_NEVER;
+            defining->state = COND_NEVER;
+            defining->ignoring = true;
             break;
 
         case COND_IF_FALSE:
@@ -2717,53 +2839,80 @@ issue_error:
              */
             j = if_condition(expand_mmac_params(tline->next), i);
             tline->next = NULL; /* it got freed */
-            istk->conds->state =
+            defining->state =
                 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
+            defining->ignoring = ((defining->state == COND_IF_TRUE) ? false : true);
             break;
         }
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
     case PP_ELSE:
+        if (defining != NULL) {
+            if ((defining->type != EXP_IF) || (defining->def_depth > 0)) {
+                return NO_DIRECTIVE_FOUND;
+            }
+        }
         if (tline->next)
             error_precond(ERR_WARNING|ERR_PASS1,
                           "trailing garbage after `%%else' ignored");
-        if (!istk->conds)
-            error(ERR_FATAL, "`%%else': no matching `%%if'");
-        switch(istk->conds->state) {
+        if ((defining == NULL) || (defining->type != EXP_IF)) {
+            error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
+        }
+        switch (defining->state) {
         case COND_IF_TRUE:
         case COND_DONE:
-            istk->conds->state = COND_ELSE_FALSE;
+            defining->state = COND_ELSE_FALSE;
+            defining->ignoring = true;
             break;
 
         case COND_NEVER:
+            defining->ignoring = true;
             break;
 
         case COND_IF_FALSE:
-            istk->conds->state = COND_ELSE_TRUE;
+            defining->state = COND_ELSE_TRUE;
+            defining->ignoring = false;
             break;
 
         case COND_ELSE_TRUE:
         case COND_ELSE_FALSE:
             error_precond(ERR_WARNING|ERR_PASS1,
                           "`%%else' after `%%else' ignored.");
-            istk->conds->state = COND_NEVER;
+            defining->state = COND_NEVER;
+            defining->ignoring = true;
             break;
         }
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
     case PP_ENDIF:
+        if (defining != NULL) {
+            if (defining->type == EXP_IF) {
+                if (defining->def_depth > 0) {
+                    defining->def_depth --;
+                    return NO_DIRECTIVE_FOUND;
+                }
+            } else {
+                return NO_DIRECTIVE_FOUND;
+            }
+        }
         if (tline->next)
             error_precond(ERR_WARNING|ERR_PASS1,
                           "trailing garbage after `%%endif' ignored");
-        if (!istk->conds)
-            error(ERR_FATAL, "`%%endif': no matching `%%if'");
-        cond = istk->conds;
-        istk->conds = cond->next;
-        nasm_free(cond);
-        if(istk->mstk)
-            istk->mstk->condcnt --;
+        if ((defining == NULL) || (defining->type != EXP_IF)) {
+            error(ERR_NONFATAL, "`%%endif': no matching `%%if'");
+            return DIRECTIVE_FOUND;
+        }
+        ed = defining;
+        defining = ed->prev;
+        ed->prev = expansions;
+        expansions = ed;
+        ei = new_ExpInv(EXP_IF, ed);
+        ei->current = ed->line;
+        ei->emitting = true;
+        ei->prev = istk->expansion;
+        istk->expansion = ei;
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
@@ -2771,71 +2920,91 @@ issue_error:
     case PP_IRMACRO:
     case PP_MACRO:
     case PP_IMACRO:
-        if (defining) {
-            error(ERR_FATAL, "`%s': already defining a macro",
-                  pp_directives[i]);
-            return DIRECTIVE_FOUND;
+        if (defining != NULL) {
+            if (defining->type == EXP_MMACRO) {
+                defining->def_depth ++;
+            }
+            return NO_DIRECTIVE_FOUND;
         }
-        defining = nasm_malloc(sizeof(MMacro));
-        defining->max_depth =
+        ed = new_ExpDef(EXP_MMACRO);
+        ed->max_depth =
             (i == PP_RMACRO) || (i == PP_IRMACRO) ? DEADMAN_LIMIT : 0;
-        defining->casesense = (i == PP_MACRO) || (i == PP_RMACRO);
-        if (!parse_mmacro_spec(tline, defining, pp_directives[i])) {
-            nasm_free(defining);
-            defining = NULL;
+        ed->casesense = (i == PP_MACRO) || (i == PP_RMACRO);
+        if (!parse_mmacro_spec(tline, ed, pp_directives[i])) {
+            nasm_free(ed);
+            ed = NULL;
             return DIRECTIVE_FOUND;
         }
-
-        mmac = (MMacro *) hash_findix(&mmacros, defining->name);
-        while (mmac) {
-            if (!strcmp(mmac->name, defining->name) &&
-                (mmac->nparam_min <= defining->nparam_max
-                 || defining->plus)
-                && (defining->nparam_min <= mmac->nparam_max
-                    || mmac->plus)) {
-                error(ERR_WARNING|ERR_PASS1,
-                      "redefining multi-line macro `%s'", defining->name);
-                return DIRECTIVE_FOUND;
+        ed->def_depth = 0;
+        ed->cur_depth = 0;
+        ed->max_depth = (ed->max_depth + 1);
+        ed->ignoring = false;
+        ed->prev = defining;
+        defining = ed;
+
+        eed = (ExpDef *) hash_findix(&expdefs, ed->name);
+        while (eed) {
+            if (!strcmp(eed->name, ed->name)                    &&
+                (eed->nparam_min <= ed->nparam_max || ed->plus) &&
+                (ed->nparam_min <= eed->nparam_max || eed->plus)) {
+                    error(ERR_WARNING|ERR_PASS1,
+                          "redefining multi-line macro `%s'", ed->name);
+                    return DIRECTIVE_FOUND;
             }
-            mmac = mmac->next;
+            eed = eed->next;
         }
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
     case PP_ENDM:
     case PP_ENDMACRO:
-        if (! (defining && defining->name)) {
+        if (defining != NULL) {
+            if (defining->type == EXP_MMACRO) {
+                if (defining->def_depth > 0) {
+                    defining->def_depth --;
+                    return NO_DIRECTIVE_FOUND;
+                }
+            } else {
+                return NO_DIRECTIVE_FOUND;
+            }
+        }
+        if (!(defining) || (defining->type != EXP_MMACRO)) {
             error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
             return DIRECTIVE_FOUND;
         }
-        mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
-        defining->next = *mmhead;
-        *mmhead = defining;
-        defining = NULL;
+        edhead = (ExpDef **) hash_findi_add(&expdefs, defining->name);
+        defining->next = *edhead;
+        *edhead = defining;
+        ed = defining;
+        defining = ed->prev;
+        ed->prev = expansions;
+        expansions = ed;
+        ed = NULL;
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
     case PP_EXITMACRO:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         /*
          * We must search along istk->expansion until we hit a
-         * macro-end marker for a macro with a name. Then we
-         * bypass all lines between exitmacro and endmacro.
+         * macro invocation. Then we disable the emitting state(s)
+         * between exitmacro and endmacro.
          */
-        list_for_each(l, istk->expansion)
-            if (l->finishes && l->finishes->name)
+        for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
+            if(ei->type == EXP_MMACRO) {
                 break;
+            }
+        }
 
-        if (l) {
+        if (ei != NULL) {
             /*
-             * Remove all conditional entries relative to this
-             * macro invocation. (safe to do in this context)
+             * Set all invocations leading back to the macro
+             * invocation to a non-emitting state.
              */
-            for ( ; l->finishes->condcnt > 0; l->finishes->condcnt --) {
-                cond = istk->conds;
-                istk->conds = cond->next;
-                nasm_free(cond);
+            for (eei = istk->expansion; eei != ei; eei = eei->prev) {
+                eei->emitting = false;
             }
-            istk->expansion = l;
+            eei->emitting = false;
         } else {
             error(ERR_NONFATAL, "`%%exitmacro' not within `%%macro' block");
         }
@@ -2844,26 +3013,33 @@ issue_error:
 
     case PP_UNMACRO:
     case PP_UNIMACRO:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
     {
-        MMacro **mmac_p;
-        MMacro spec;
+        ExpDef **ed_p;
+        ExpDef spec;
 
         spec.casesense = (i == PP_UNMACRO);
         if (!parse_mmacro_spec(tline, &spec, pp_directives[i])) {
             return DIRECTIVE_FOUND;
         }
-        mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
-        while (mmac_p && *mmac_p) {
-            mmac = *mmac_p;
-            if (mmac->casesense == spec.casesense &&
-                !mstrcmp(mmac->name, spec.name, spec.casesense) &&
-                mmac->nparam_min == spec.nparam_min &&
-                mmac->nparam_max == spec.nparam_max &&
-                mmac->plus == spec.plus) {
-                *mmac_p = mmac->next;
-                free_mmacro(mmac);
+        ed_p = (ExpDef **) hash_findi(&expdefs, spec.name, NULL);
+        while (ed_p && *ed_p) {
+            ed = *ed_p;
+            if (ed->casesense == spec.casesense &&
+                !mstrcmp(ed->name, spec.name, spec.casesense) &&
+                ed->nparam_min == spec.nparam_min &&
+                ed->nparam_max == spec.nparam_max &&
+                ed->plus == spec.plus) {
+                if (ed->cur_depth > 0) {
+                    error(ERR_NONFATAL, "`%s' ignored on active macro",
+                          pp_directives[i]);
+                    break;
+                } else {
+                    *ed_p = ed->next;
+                    free_expdef(ed);
+                }
             } else {
-                mmac_p = &mmac->next;
+                ed_p = &ed->next;
             }
         }
         free_tlist(origline);
@@ -2872,6 +3048,7 @@ issue_error:
     }
 
     case PP_ROTATE:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         if (tline->next && tline->next->type == TOK_WHITESPACE)
             tline = tline->next;
         if (!tline->next) {
@@ -2897,26 +3074,33 @@ issue_error:
             error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
             return DIRECTIVE_FOUND;
         }
-        mmac = istk->mstk;
-        while (mmac && !mmac->name)     /* avoid mistaking %reps for macros */
-            mmac = mmac->next_active;
-        if (!mmac) {
+        for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
+            if (ei->type == EXP_MMACRO) {
+                break;
+            }
+        }
+        if (ei == NULL) {
             error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
-        } else if (mmac->nparam == 0) {
+        } else if (ei->nparam == 0) {
             error(ERR_NONFATAL,
                   "`%%rotate' invoked within macro without parameters");
         } else {
-            int rotate = mmac->rotate + reloc_value(evalresult);
+            int rotate = ei->rotate + reloc_value(evalresult);
 
-            rotate %= (int)mmac->nparam;
+            rotate %= (int)ei->nparam;
             if (rotate < 0)
-                rotate += mmac->nparam;
-
-            mmac->rotate = rotate;
+                rotate += ei->nparam;
+            ei->rotate = rotate;
         }
         return DIRECTIVE_FOUND;
 
     case PP_REP:
+        if (defining != NULL) {
+            if (defining->type == EXP_REP) {
+                defining->def_depth ++;
+            }
+            return NO_DIRECTIVE_FOUND;
+        }
         nolist = false;
         do {
             tline = tline->next;
@@ -2958,26 +3142,28 @@ issue_error:
             count = 0;
         }
         free_tlist(origline);
-
-        tmp_defining = defining;
-        defining = nasm_malloc(sizeof(MMacro));
-        defining->prev = NULL;
-        defining->name = NULL;  /* flags this macro as a %rep block */
-        defining->casesense = false;
-        defining->plus = false;
-        defining->nolist = nolist;
-        defining->in_progress = count;
-        defining->max_depth = 0;
-        defining->nparam_min = defining->nparam_max = 0;
-        defining->defaults = NULL;
-        defining->dlist = NULL;
-        defining->expansion = NULL;
-        defining->next_active = istk->mstk;
-        defining->rep_nest = tmp_defining;
+        ed = new_ExpDef(EXP_REP);
+        ed->nolist = nolist;
+        ed->def_depth = 0;
+        ed->cur_depth = 1;
+        ed->max_depth = (count - 1);
+        ed->ignoring = false;
+        ed->prev = defining;
+        defining = ed;
         return DIRECTIVE_FOUND;
 
     case PP_ENDREP:
-        if (!defining || defining->name) {
+        if (defining != NULL) {
+            if (defining->type == EXP_REP) {
+                if (defining->def_depth > 0) {
+                    defining->def_depth --;
+                    return NO_DIRECTIVE_FOUND;
+                }
+            } else {
+                return NO_DIRECTIVE_FOUND;
+            }
+        }
+        if ((defining == NULL) || (defining->type != EXP_REP)) {
             error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
             return DIRECTIVE_FOUND;
         }
@@ -2993,34 +3179,46 @@ issue_error:
          * continues) until the whole expansion is forcibly removed
          * from istk->expansion by a %exitrep.
          */
-        l = nasm_malloc(sizeof(Line));
-        l->next = istk->expansion;
-        l->finishes = defining;
-        l->first = NULL;
-        istk->expansion = l;
-
-        istk->mstk = defining;
-
-        list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
-        tmp_defining = defining;
-        defining = defining->rep_nest;
+        ed = defining;
+        defining = ed->prev;
+        ed->prev = expansions;
+        expansions = ed;
+        ei = new_ExpInv(EXP_REP, ed);
+        ei->current = ed->line;
+        ei->emitting = ((ed->max_depth > 0) ? true : false);
+        list->uplevel(ed->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
+        ei->prev = istk->expansion;
+        istk->expansion = ei;
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
     case PP_EXITREP:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         /*
          * We must search along istk->expansion until we hit a
-         * macro-end marker for a macro with no name. Then we set
-         * its `in_progress' flag to 0.
+         * rep invocation. Then we disable the emitting state(s)
+         * between exitrep and endrep.
          */
-        list_for_each(l, istk->expansion)
-            if (l->finishes && !l->finishes->name)
+        for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
+            if (ei->type == EXP_REP) {
                 break;
+            }
+        }
 
-        if (l)
-            l->finishes->in_progress = 1;
-        else
+        if (ei != NULL) {
+            /*
+             * Set all invocations leading back to the rep
+             * invocation to a non-emitting state.
+             */
+            for (eei = istk->expansion; eei != ei; eei = eei->prev) {
+                eei->emitting = false;
+            }
+            eei->emitting = false;
+            eei->current = NULL;
+            eei->def->cur_depth = eei->def->max_depth;
+        } else {
             error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
+        }
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
@@ -3028,6 +3226,7 @@ issue_error:
     case PP_IXDEFINE:
     case PP_DEFINE:
     case PP_IDEFINE:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         casesense = (i == PP_DEFINE || i == PP_XDEFINE);
 
         tline = tline->next;
@@ -3042,7 +3241,7 @@ issue_error:
             return DIRECTIVE_FOUND;
         }
 
-        ctx = get_ctx(tline->text, &mname, false);
+        ctx = get_ctx(tline->text, &mname);
         last = tline;
         param_start = tline = tline->next;
         nparam = 0;
@@ -3071,7 +3270,10 @@ issue_error:
                     free_tlist(origline);
                     return DIRECTIVE_FOUND;
                 }
-                tline->type = TOK_SMAC_PARAM + nparam++;
+
+                smacro_set_param_idx(tline, nparam);
+                nparam++;
+
                 tline = tline->next;
                 skip_white_(tline);
                 if (tok_is_(tline, ",")) {
@@ -3097,7 +3299,7 @@ issue_error:
         while (t) {
             if (t->type == TOK_ID) {
                 list_for_each(tt, param_start)
-                    if (tt->type >= TOK_SMAC_PARAM &&
+                    if (is_smacro_param(tt) &&
                         !strcmp(tt->text, t->text))
                         t->type = tt->type;
             }
@@ -3119,6 +3321,7 @@ issue_error:
         return DIRECTIVE_FOUND;
 
     case PP_UNDEF:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         tline = tline->next;
         skip_white_(tline);
         tline = expand_id(tline);
@@ -3135,13 +3338,14 @@ issue_error:
         }
 
         /* Find the context that symbol belongs to */
-        ctx = get_ctx(tline->text, &mname, false);
+        ctx = get_ctx(tline->text, &mname);
         undef_smacro(ctx, mname);
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
     case PP_DEFSTR:
     case PP_IDEFSTR:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         casesense = (i == PP_DEFSTR);
 
         tline = tline->next;
@@ -3156,7 +3360,7 @@ issue_error:
             return DIRECTIVE_FOUND;
         }
 
-        ctx = get_ctx(tline->text, &mname, false);
+        ctx = get_ctx(tline->text, &mname);
         last = tline;
         tline = expand_smacro(tline->next);
         last->next = NULL;
@@ -3165,11 +3369,9 @@ issue_error:
             tline = delete_Token(tline);
 
         p = detoken(tline, false);
-        macro_start = nasm_malloc(sizeof(*macro_start));
-        macro_start->next = NULL;
+        macro_start = nasm_zalloc(sizeof(*macro_start));
         macro_start->text = nasm_quote(p, strlen(p));
         macro_start->type = TOK_STRING;
-        macro_start->a.mac = NULL;
         nasm_free(p);
 
         /*
@@ -3183,6 +3385,7 @@ issue_error:
 
     case PP_DEFTOK:
     case PP_IDEFTOK:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         casesense = (i == PP_DEFTOK);
 
         tline = tline->next;
@@ -3197,7 +3400,7 @@ issue_error:
             free_tlist(origline);
             return DIRECTIVE_FOUND;
         }
-        ctx = get_ctx(tline->text, &mname, false);
+        ctx = get_ctx(tline->text, &mname);
         last = tline;
         tline = expand_smacro(tline->next);
         last->next = NULL;
@@ -3215,11 +3418,11 @@ issue_error:
             return DIRECTIVE_FOUND;
         }
 
-       /*
-        * Convert the string to a token stream.  Note that smacros
-        * are stored with the token stream reversed, so we have to
-        * reverse the output of tokenize().
-        */
+        /*
+         * Convert the string to a token stream.  Note that smacros
+         * are stored with the token stream reversed, so we have to
+         * reverse the output of tokenize().
+         */
         nasm_unquote_cstr(t->text, i);
         macro_start = reverse_tokens(tokenize(t->text));
 
@@ -3234,6 +3437,7 @@ issue_error:
         return DIRECTIVE_FOUND;
 
     case PP_PATHSEARCH:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
     {
         FILE *fp;
         StrList *xsl = NULL;
@@ -3252,7 +3456,7 @@ issue_error:
             free_tlist(origline);
             return DIRECTIVE_FOUND;
         }
-        ctx = get_ctx(tline->text, &mname, false);
+        ctx = get_ctx(tline->text, &mname);
         last = tline;
         tline = expand_smacro(tline->next);
         last->next = NULL;
@@ -3280,13 +3484,10 @@ issue_error:
             p = xsl->str;
             fclose(fp);         /* Don't actually care about the file */
         }
-        macro_start = nasm_malloc(sizeof(*macro_start));
-        macro_start->next = NULL;
+        macro_start = nasm_zalloc(sizeof(*macro_start));
         macro_start->text = nasm_quote(p, strlen(p));
         macro_start->type = TOK_STRING;
-        macro_start->a.mac = NULL;
-        if (xsl)
-            nasm_free(xsl);
+        nasm_free(xsl);
 
         /*
          * We now have a macro name, an implicit parameter count of
@@ -3300,6 +3501,7 @@ issue_error:
     }
 
     case PP_STRLEN:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         casesense = true;
 
         tline = tline->next;
@@ -3313,7 +3515,7 @@ issue_error:
             free_tlist(origline);
             return DIRECTIVE_FOUND;
         }
-        ctx = get_ctx(tline->text, &mname, false);
+        ctx = get_ctx(tline->text, &mname);
         last = tline;
         tline = expand_smacro(tline->next);
         last->next = NULL;
@@ -3330,10 +3532,8 @@ issue_error:
             return DIRECTIVE_FOUND;
         }
 
-        macro_start = nasm_malloc(sizeof(*macro_start));
-        macro_start->next = NULL;
+        macro_start = nasm_zalloc(sizeof(*macro_start));
         make_tok_num(macro_start, nasm_unquote(t->text, NULL));
-        macro_start->a.mac = NULL;
 
         /*
          * We now have a macro name, an implicit parameter count of
@@ -3346,6 +3546,7 @@ issue_error:
         return DIRECTIVE_FOUND;
 
     case PP_STRCAT:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         casesense = true;
 
         tline = tline->next;
@@ -3359,7 +3560,7 @@ issue_error:
             free_tlist(origline);
             return DIRECTIVE_FOUND;
         }
-        ctx = get_ctx(tline->text, &mname, false);
+        ctx = get_ctx(tline->text, &mname);
         last = tline;
         tline = expand_smacro(tline->next);
         last->next = NULL;
@@ -3407,6 +3608,7 @@ issue_error:
         return DIRECTIVE_FOUND;
 
     case PP_SUBSTR:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
     {
         int64_t start, count;
         size_t len;
@@ -3424,7 +3626,7 @@ issue_error:
             free_tlist(origline);
             return DIRECTIVE_FOUND;
         }
-        ctx = get_ctx(tline->text, &mname, false);
+        ctx = get_ctx(tline->text, &mname);
         last = tline;
         tline = expand_smacro(tline->next);
         last->next = NULL;
@@ -3463,7 +3665,7 @@ issue_error:
         while (tok_type_(tt, TOK_WHITESPACE))
             tt = tt->next;
         if (!tt) {
-            count = 1;  /* Backwards compatibility: one character */
+            count = 1;             /* Backwards compatibility: one character */
         } else {
             tokval.t_type = TOKEN_INVALID;
             evalresult = evaluate(ppscan, tptr, &tokval, NULL,
@@ -3482,7 +3684,6 @@ issue_error:
         }
 
         len = nasm_unquote(t->text, NULL);
-
         /* make start and count being in range */
         if (start < 0)
             start = 0;
@@ -3493,11 +3694,9 @@ issue_error:
         if (!len || count < 0 || start >=(int64_t)len)
             start = -1, count = 0; /* empty string */
 
-        macro_start = nasm_malloc(sizeof(*macro_start));
-        macro_start->next = NULL;
+        macro_start = nasm_zalloc(sizeof(*macro_start));
         macro_start->text = nasm_quote((start < 0) ? "" : t->text + start, count);
         macro_start->type = TOK_STRING;
-        macro_start->a.mac = NULL;
 
         /*
          * We now have a macro name, an implicit parameter count of
@@ -3512,6 +3711,7 @@ issue_error:
 
     case PP_ASSIGN:
     case PP_IASSIGN:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         casesense = (i == PP_ASSIGN);
 
         tline = tline->next;
@@ -3526,7 +3726,7 @@ issue_error:
             free_tlist(origline);
             return DIRECTIVE_FOUND;
         }
-        ctx = get_ctx(tline->text, &mname, false);
+        ctx = get_ctx(tline->text, &mname);
         last = tline;
         tline = expand_smacro(tline->next);
         last->next = NULL;
@@ -3554,10 +3754,8 @@ issue_error:
             return DIRECTIVE_FOUND;
         }
 
-        macro_start = nasm_malloc(sizeof(*macro_start));
-        macro_start->next = NULL;
+        macro_start = nasm_zalloc(sizeof(*macro_start));
         make_tok_num(macro_start, reloc_value(evalresult));
-        macro_start->a.mac = NULL;
 
         /*
          * We now have a macro name, an implicit parameter count of
@@ -3569,6 +3767,7 @@ issue_error:
         return DIRECTIVE_FOUND;
 
     case PP_LINE:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
         /*
          * Syntax is `%line nnn[+mmm] [filename]'
          */
@@ -3601,6 +3800,160 @@ issue_error:
         free_tlist(origline);
         return DIRECTIVE_FOUND;
 
+    case PP_WHILE:
+        if (defining != NULL) {
+            if (defining->type == EXP_WHILE) {
+                defining->def_depth ++;
+            }
+            return NO_DIRECTIVE_FOUND;
+        }
+        l = NULL;
+        if ((istk->expansion != NULL) &&
+             (istk->expansion->emitting == false)) {
+            j = COND_NEVER;
+        } else {
+            l = new_Line();
+            l->first = copy_Token(tline->next);
+            j = if_condition(tline->next, i);
+            tline->next = NULL; /* it got freed */
+            j = (((j < 0) ? COND_NEVER : j) ? COND_IF_TRUE : COND_IF_FALSE);
+        }
+        ed = new_ExpDef(EXP_WHILE);
+        ed->state = j;
+        ed->cur_depth = 1;
+        ed->max_depth = DEADMAN_LIMIT;
+        ed->ignoring = ((ed->state == COND_IF_TRUE) ? false : true);
+        if (ed->ignoring == false) {
+            ed->line = l;
+            ed->last = l;
+        } else if (l != NULL) {
+            delete_Token(l->first);
+            nasm_free(l);
+            l = NULL;
+        }
+        ed->prev = defining;
+        defining = ed;
+        free_tlist(origline);
+        return DIRECTIVE_FOUND;
+
+    case PP_ENDWHILE:
+        if (defining != NULL) {
+            if (defining->type == EXP_WHILE) {
+                if (defining->def_depth > 0) {
+                    defining->def_depth --;
+                    return NO_DIRECTIVE_FOUND;
+                }
+            } else {
+                return NO_DIRECTIVE_FOUND;
+            }
+        }
+        if (tline->next != NULL) {
+            error_precond(ERR_WARNING|ERR_PASS1,
+                          "trailing garbage after `%%endwhile' ignored");
+        }
+        if ((defining == NULL) || (defining->type != EXP_WHILE)) {
+            error(ERR_NONFATAL, "`%%endwhile': no matching `%%while'");
+            return DIRECTIVE_FOUND;
+        }
+        ed = defining;
+        defining = ed->prev;
+        if (ed->ignoring == false) {
+            ed->prev = expansions;
+            expansions = ed;
+            ei = new_ExpInv(EXP_WHILE, ed);
+            ei->current = ed->line->next;
+            ei->emitting = true;
+            ei->prev = istk->expansion;
+            istk->expansion = ei;
+        } else {
+            nasm_free(ed);
+        }
+        free_tlist(origline);
+        return DIRECTIVE_FOUND;
+
+    case PP_EXITWHILE:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
+        /*
+         * We must search along istk->expansion until we hit a
+         * while invocation. Then we disable the emitting state(s)
+         * between exitwhile and endwhile.
+         */
+        for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
+            if (ei->type == EXP_WHILE) {
+                break;
+            }
+        }
+
+        if (ei != NULL) {
+            /*
+             * Set all invocations leading back to the while
+             * invocation to a non-emitting state.
+             */
+            for (eei = istk->expansion; eei != ei; eei = eei->prev) {
+                eei->emitting = false;
+            }
+            eei->emitting = false;
+            eei->current = NULL;
+            eei->def->cur_depth = eei->def->max_depth;
+        } else {
+            error(ERR_NONFATAL, "`%%exitwhile' not within `%%while' block");
+        }
+        free_tlist(origline);
+        return DIRECTIVE_FOUND;
+
+    case PP_COMMENT:
+        if (defining != NULL) {
+            if (defining->type == EXP_COMMENT) {
+                defining->def_depth ++;
+            }
+        return NO_DIRECTIVE_FOUND;
+        }
+        ed = new_ExpDef(EXP_COMMENT);
+        ed->ignoring = true;
+        ed->prev = defining;
+        defining = ed;
+        free_tlist(origline);
+        return DIRECTIVE_FOUND;
+
+    case PP_ENDCOMMENT:
+        if (defining != NULL) {
+            if (defining->type == EXP_COMMENT) {
+                if (defining->def_depth > 0) {
+                    defining->def_depth --;
+                    return NO_DIRECTIVE_FOUND;
+                }
+            } else {
+                return NO_DIRECTIVE_FOUND;
+            }
+        }
+        if ((defining == NULL) || (defining->type != EXP_COMMENT)) {
+            error(ERR_NONFATAL, "`%%endcomment': no matching `%%comment'");
+            return DIRECTIVE_FOUND;
+        }
+        ed = defining;
+        defining = ed->prev;
+        nasm_free(ed);
+        free_tlist(origline);
+        return DIRECTIVE_FOUND;
+
+    case PP_FINAL:
+        if (defining != NULL) return NO_DIRECTIVE_FOUND;
+        if (in_final != false) {
+            error(ERR_FATAL, "`%%final' cannot be used recursively");
+        }
+        tline = tline->next;
+        skip_white_(tline);
+        if (tline == NULL) {
+            error(ERR_NONFATAL, "`%%final' expects at least one parameter");
+        } else {
+            l = new_Line();
+            l->first = copy_Token(tline);
+            l->next = finals;
+            finals = l;
+        }
+        free_tlist(origline);
+        return DIRECTIVE_FOUND;
+
     default:
         error(ERR_FATAL,
               "preprocessor directive `%s' not yet implemented",
@@ -3717,10 +4070,12 @@ static bool paste_tokens(Token **head, const struct tokseq_match *m,
                     char *tmp, *p;
 
                     while (tt && (PP_CONCAT_MASK(tt->type) & m[i].mask_tail)) {
-                        len += strlen(tt->text);
-                        tt = tt->next;
+                         len += strlen(tt->text);
+                         tt = tt->next;
                     }
 
+                    nasm_dump_token(tt);
+
                     /*
                      * Now tt points to the first token after
                      * the potential paste area...
@@ -3762,7 +4117,7 @@ static bool paste_tokens(Token **head, const struct tokseq_match *m,
 /*
  * expands to a list of tokens from %{x:y}
  */
-static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
+static Token *expand_mmac_params_range(ExpInv *ei, Token *tline, Token ***last)
 {
     Token *t = tline, **tt, *tm, *head;
     char *pos;
@@ -3783,12 +4138,12 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
         goto err;
 
     /* the values should be sane */
-    if ((fst > (int)mac->nparam || fst < (-(int)mac->nparam)) ||
-        (lst > (int)mac->nparam || lst < (-(int)mac->nparam)))
+    if ((fst > (int)ei->nparam || fst < (-(int)ei->nparam)) ||
+        (lst > (int)ei->nparam || lst < (-(int)ei->nparam)))
         goto err;
 
-    fst = fst < 0 ? fst + (int)mac->nparam + 1: fst;
-    lst = lst < 0 ? lst + (int)mac->nparam + 1: lst;
+    fst = fst < 0 ? fst + (int)ei->nparam + 1: fst;
+    lst = lst < 0 ? lst + (int)ei->nparam + 1: lst;
 
     /* counted from zero */
     fst--, lst--;
@@ -3796,15 +4151,15 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
     /*
      * it will be at least one token
      */
-    tm = mac->params[(fst + mac->rotate) % mac->nparam];
+    tm = ei->params[(fst + ei->rotate) % ei->nparam];
     t = new_Token(NULL, tm->type, tm->text, 0);
     head = t, tt = &t->next;
     if (fst < lst) {
         for (i = fst + 1; i <= lst; i++) {
             t = new_Token(NULL, TOK_OTHER, ",", 0);
             *tt = t, tt = &t->next;
-            j = (i + mac->rotate) % mac->nparam;
-            tm = mac->params[j];
+            j = (i + ei->rotate) % ei->nparam;
+            tm = ei->params[j];
             t = new_Token(NULL, tm->type, tm->text, 0);
             *tt = t, tt = &t->next;
         }
@@ -3812,8 +4167,8 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
         for (i = fst - 1; i >= lst; i--) {
             t = new_Token(NULL, TOK_OTHER, ",", 0);
             *tt = t, tt = &t->next;
-            j = (i + mac->rotate) % mac->nparam;
-            tm = mac->params[j];
+            j = (i + ei->rotate) % ei->nparam;
+            tm = ei->params[j];
             t = new_Token(NULL, tm->type, tm->text, 0);
             *tt = t, tt = &t->next;
         }
@@ -3842,6 +4197,8 @@ static Token *expand_mmac_params(Token * tline)
     tail = &thead;
     thead = NULL;
 
+    nasm_dump_stream(tline);
+
     while (tline) {
         if (tline->type == TOK_PREPROC_ID &&
             (((tline->text[1] == '+' || tline->text[1] == '-') && tline->text[2])   ||
@@ -3852,15 +4209,17 @@ static Token *expand_mmac_params(Token * tline)
             char tmpbuf[30];
             unsigned int n;
             int i;
-            MMacro *mac;
+            ExpInv *ei;
 
             t = tline;
             tline = tline->next;
 
-            mac = istk->mstk;
-            while (mac && !mac->name)   /* avoid mistaking %reps for macros */
-                mac = mac->next_active;
-            if (!mac) {
+            for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
+                if (ei->type == EXP_MMACRO) {
+                    break;
+                }
+            }
+            if (ei == NULL) {
                 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
             } else {
                 pos = strchr(t->text, ':');
@@ -3871,24 +4230,29 @@ static Token *expand_mmac_params(Token * tline)
                          * forms %1, %-1, %+1, %%foo, %0.
                          */
                     case '0':
-                        type = TOK_NUMBER;
-                        snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
-                        text = nasm_strdup(tmpbuf);
+                        if ((strlen(t->text) > 2) && (t->text[2] == '0')) {
+                            type = TOK_ID;
+                            text = nasm_strdup(ei->label_text);
+                        } else {
+                            type = TOK_NUMBER;
+                            snprintf(tmpbuf, sizeof(tmpbuf), "%d", ei->nparam);
+                            text = nasm_strdup(tmpbuf);
+                        }
                         break;
                     case '%':
                         type = TOK_ID;
                         snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
-                                 mac->unique);
+                                 ei->unique);
                         text = nasm_strcat(tmpbuf, t->text + 2);
                         break;
                     case '-':
                         n = atoi(t->text + 2) - 1;
-                        if (n >= mac->nparam)
+                        if (n >= ei->nparam)
                             tt = NULL;
                         else {
-                            if (mac->nparam > 1)
-                                n = (n + mac->rotate) % mac->nparam;
-                            tt = mac->params[n];
+                            if (ei->nparam > 1)
+                                n = (n + ei->rotate) % ei->nparam;
+                            tt = ei->params[n];
                         }
                         cc = find_cc(tt);
                         if (cc == -1) {
@@ -3909,12 +4273,12 @@ static Token *expand_mmac_params(Token * tline)
                         break;
                     case '+':
                         n = atoi(t->text + 2) - 1;
-                        if (n >= mac->nparam)
+                        if (n >= ei->nparam)
                             tt = NULL;
                         else {
-                            if (mac->nparam > 1)
-                                n = (n + mac->rotate) % mac->nparam;
-                            tt = mac->params[n];
+                            if (ei->nparam > 1)
+                                n = (n + ei->rotate) % ei->nparam;
+                            tt = ei->params[n];
                         }
                         cc = find_cc(tt);
                         if (cc == -1) {
@@ -3929,15 +4293,15 @@ static Token *expand_mmac_params(Token * tline)
                         break;
                     default:
                         n = atoi(t->text + 1) - 1;
-                        if (n >= mac->nparam)
+                        if (n >= ei->nparam)
                             tt = NULL;
                         else {
-                            if (mac->nparam > 1)
-                                n = (n + mac->rotate) % mac->nparam;
-                            tt = mac->params[n];
+                            if (ei->nparam > 1)
+                                n = (n + ei->rotate) % ei->nparam;
+                            tt = ei->params[n];
                         }
                         if (tt) {
-                            for (i = 0; i < mac->paramlen[n]; i++) {
+                            for (i = 0; i < ei->paramlen[n]; i++) {
                                 *tail = new_Token(NULL, tt->type, tt->text, 0);
                                 tail = &(*tail)->next;
                                 tt = tt->next;
@@ -3951,7 +4315,7 @@ static Token *expand_mmac_params(Token * tline)
                      * seems we have a parameters range here
                      */
                     Token *head, **last;
-                    head = expand_mmac_params_range(mac, t, &last);
+                    head = expand_mmac_params_range(ei, t, &last);
                     if (head != t) {
                         *tail = head;
                         *last = tline;
@@ -4013,6 +4377,8 @@ static Token *expand_mmac_params(Token * tline)
         paste_tokens(&thead, t, ARRAY_SIZE(t), false);
     }
 
+    nasm_dump_token(thead);
+
     return thead;
 }
 
@@ -4069,7 +4435,7 @@ again:
             if (tline->type == TOK_ID) {
                 head = (SMacro *)hash_findix(&smacros, mname);
             } else if (tline->type == TOK_PREPROC_ID) {
-                ctx = get_ctx(mname, &mname, true);
+                ctx = get_ctx(mname, &mname);
                 head = ctx ? (SMacro *)hash_findix(&ctx->localmac, mname) : NULL;
             } else
                 head = NULL;
@@ -4264,19 +4630,23 @@ again:
                     m->in_progress = true;
                     tline = tt;
                     list_for_each(t, m->expansion) {
-                        if (t->type >= TOK_SMAC_PARAM) {
+                        if (is_smacro_param(t)) {
                             Token *pcopy = tline, **ptail = &pcopy;
-                            Token *ttt, *pt;
-                            int i;
-
-                            ttt = params[t->type - TOK_SMAC_PARAM];
-                            i = paramsize[t->type - TOK_SMAC_PARAM];
-                            while (--i >= 0) {
-                                pt = *ptail = new_Token(tline, ttt->type,
-                                                        ttt->text, 0);
-                                ptail = &pt->next;
+                            Token *ttt;
+                            int i, idx;
+
+                            idx = smacro_get_param_idx(t);
+                            ttt = params[idx];
+
+                            /*
+                             * We need smacro paramters appended.
+                             */
+                            for (i = paramsize[idx]; i > 0; i--) {
+                                *ptail = new_Token(tline, ttt->type, ttt->text, 0);
+                                ptail = &(*ptail)->next;
                                 ttt = ttt->next;
                             }
+
                             tline = pcopy;
                         } else if (t->type == TOK_PREPROC_Q) {
                             tt = new_Token(tline, TOK_ID, mname, 0);
@@ -4392,9 +4762,9 @@ static Token *expand_id(Token * tline)
 
     cur = tline;
     while (cur->next &&
-           (cur->next->type == TOK_ID ||
-            cur->next->type == TOK_PREPROC_ID
-            || cur->next->type == TOK_NUMBER))
+           (cur->next->type == TOK_ID           ||
+            cur->next->type == TOK_PREPROC_ID   ||
+            cur->next->type == TOK_NUMBER))
         cur = cur->next;
 
     /* If identifier consists of just one token, don't expand */
@@ -4422,30 +4792,30 @@ static Token *expand_id(Token * tline)
 
 /*
  * Determine whether the given line constitutes a multi-line macro
- * call, and return the MMacro structure called if so. Doesn't have
+ * call, and return the ExpDef structure called if so. Doesn't have
  * to check for an initial label - that's taken care of in
  * expand_mmacro - but must check numbers of parameters. Guaranteed
  * to be called with tline->type == TOK_ID, so the putative macro
  * name is easy to find.
  */
-static MMacro *is_mmacro(Token * tline, Token *** params_array)
+static ExpDef *is_mmacro(Token * tline, Token *** params_array)
 {
-    MMacro *head, *m;
+    ExpDef *head, *ed;
     Token **params;
     int nparam;
 
-    head = (MMacro *) hash_findix(&mmacros, tline->text);
+    head = (ExpDef *) hash_findix(&expdefs, tline->text);
 
     /*
      * Efficiency: first we see if any macro exists with the given
      * name. If not, we can return NULL immediately. _Then_ we
      * count the parameters, and then we look further along the
-     * list if necessary to find the proper MMacro.
+     * list if necessary to find the proper ExpDef.
      */
-    list_for_each(m, head)
-        if (!mstrcmp(m->name, tline->text, m->casesense))
+    list_for_each(ed, head)
+        if (!mstrcmp(ed->name, tline->text, ed->casesense))
             break;
-    if (!m)
+    if (!ed)
         return NULL;
 
     /*
@@ -4455,36 +4825,23 @@ static MMacro *is_mmacro(Token * tline, Token *** params_array)
     count_mmac_params(tline->next, &nparam, &params);
 
     /*
-     * So we know how many parameters we've got. Find the MMacro
+     * So we know how many parameters we've got. Find the ExpDef
      * structure that handles this number.
      */
-    while (m) {
-        if (m->nparam_min <= nparam
-            && (m->plus || nparam <= m->nparam_max)) {
-            /*
-             * This one is right. Just check if cycle removal
-             * prohibits us using it before we actually celebrate...
-             */
-            if (m->in_progress > m->max_depth) {
-                if (m->max_depth > 0) {
-                    error(ERR_WARNING,
-                          "reached maximum recursion depth of %i",
-                          m->max_depth);
-                }
-                nasm_free(params);
-                return NULL;
-            }
+    while (ed) {
+        if (ed->nparam_min <= nparam
+            && (ed->plus || nparam <= ed->nparam_max)) {
             /*
              * It's right, and we can use it. Add its default
              * parameters to the end of our list if necessary.
              */
-            if (m->defaults && nparam < m->nparam_min + m->ndefs) {
+            if (ed->defaults && nparam < ed->nparam_min + ed->ndefs) {
                 params =
                     nasm_realloc(params,
-                                 ((m->nparam_min + m->ndefs +
+                                 ((ed->nparam_min + ed->ndefs +
                                    1) * sizeof(*params)));
-                while (nparam < m->nparam_min + m->ndefs) {
-                    params[nparam] = m->defaults[nparam - m->nparam_min];
+                while (nparam < ed->nparam_min + ed->ndefs) {
+                    params[nparam] = ed->defaults[nparam - ed->nparam_min];
                     nparam++;
                 }
             }
@@ -4493,8 +4850,8 @@ static MMacro *is_mmacro(Token * tline, Token *** params_array)
              * we're in Plus mode), ignore parameters beyond
              * nparam_max.
              */
-            if (m->plus && nparam > m->nparam_max)
-                nparam = m->nparam_max;
+            if (ed->plus && nparam > ed->nparam_max)
+                nparam = ed->nparam_max;
             /*
              * Then terminate the parameter list, and leave.
              */
@@ -4504,14 +4861,14 @@ static MMacro *is_mmacro(Token * tline, Token *** params_array)
             }
             params[nparam] = NULL;
             *params_array = params;
-            return m;
+            return ed;
         }
         /*
          * This one wasn't right: look for the next one with the
          * same name.
          */
-        list_for_each(m, m->next)
-            if (!mstrcmp(m->name, tline->text, m->casesense))
+        list_for_each(ed, ed->next)
+            if (!mstrcmp(ed->name, tline->text, ed->casesense))
                 break;
     }
 
@@ -4526,64 +4883,19 @@ static MMacro *is_mmacro(Token * tline, Token *** params_array)
     return NULL;
 }
 
-
-/*
- * Save MMacro invocation specific fields in
- * preparation for a recursive macro expansion
- */
-static void push_mmacro(MMacro *m)
-{
-    MMacroInvocation *i;
-
-    i = nasm_malloc(sizeof(MMacroInvocation));
-    i->prev = m->prev;
-    i->params = m->params;
-    i->iline = m->iline;
-    i->nparam = m->nparam;
-    i->rotate = m->rotate;
-    i->paramlen = m->paramlen;
-    i->unique = m->unique;
-    i->condcnt = m->condcnt;
-    m->prev = i;
-}
-
-
-/*
- * Restore MMacro invocation specific fields that were
- * saved during a previous recursive macro expansion
- */
-static void pop_mmacro(MMacro *m)
-{
-    MMacroInvocation *i;
-
-    if (m->prev) {
-        i = m->prev;
-        m->prev = i->prev;
-        m->params = i->params;
-        m->iline = i->iline;
-        m->nparam = i->nparam;
-        m->rotate = i->rotate;
-        m->paramlen = i->paramlen;
-        m->unique = i->unique;
-        m->condcnt = i->condcnt;
-        nasm_free(i);
-    }
-}
-
-
 /*
  * Expand the multi-line macro call made by the given line, if
  * there is one to be expanded. If there is, push the expansion on
- * istk->expansion and return 1. Otherwise return 0.
+ * istk->expansion and return true. Otherwise return false.
  */
-static int expand_mmacro(Token * tline)
+static bool expand_mmacro(Token * tline)
 {
-    Token *startline = tline;
     Token *label = NULL;
     int dont_prepend = 0;
-    Token **params, *t, *mtok, *tt;
-    MMacro *m;
-    Line *l, *ll;
+    Token **params, *t;
+    Line *l = NULL;
+    ExpDef *ed;
+    ExpInv *ei;
     int i, nparam, *paramlen;
     const char *mname;
 
@@ -4591,10 +4903,9 @@ static int expand_mmacro(Token * tline)
     skip_white_(t);
     /*    if (!tok_type_(t, TOK_ID))  Lino 02/25/02 */
     if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
-        return 0;
-    mtok = t;
-    m = is_mmacro(t, &params);
-    if (m) {
+        return false;
+    ed = is_mmacro(t, &params);
+    if (ed != NULL) {
         mname = t->text;
     } else {
         Token *last;
@@ -4614,8 +4925,8 @@ static int expand_mmacro(Token * tline)
             if (tok_type_(t, TOK_WHITESPACE))
                 last = t, t = t->next;
         }
-        if (!tok_type_(t, TOK_ID) || !(m = is_mmacro(t, &params)))
-            return 0;
+        if (!tok_type_(t, TOK_ID) || !(ed = is_mmacro(t, &params)))
+            return false;
         last->next = NULL;
         mname = t->text;
         tline = t;
@@ -4631,7 +4942,7 @@ static int expand_mmacro(Token * tline)
 
     for (i = 0; params[i]; i++) {
         int brace = false;
-        int comma = (!m->plus || i < nparam - 1);
+        int comma = (!ed->plus || i < nparam - 1);
 
         t = params[i];
         skip_white_(t);
@@ -4652,127 +4963,111 @@ static int expand_mmacro(Token * tline)
         }
     }
 
+    if (ed->cur_depth >= ed->max_depth) {
+        if (ed->max_depth > 1) {
+            error(ERR_WARNING,
+                  "reached maximum macro recursion depth of %i for %s",
+                  ed->max_depth,ed->name);
+        }
+        return false;
+    } else {
+        ed->cur_depth ++;
+    }
+
     /*
-     * OK, we have a MMacro structure together with a set of
-     * parameters. We must now go through the expansion and push
-     * copies of each Line on to istk->expansion. Substitution of
+     * OK, we have found a ExpDef structure representing a
+     * previously defined mmacro. Create an expansion invocation
+     * and point it back to the expansion definition. Substitution of
      * parameter tokens and macro-local tokens doesn't get done
      * until the single-line macro substitution process; this is
      * because delaying them allows us to change the semantics
      * later through %rotate.
-     *
-     * First, push an end marker on to istk->expansion, mark this
-     * macro as in progress, and set up its invocation-specific
-     * variables.
      */
-    ll = nasm_malloc(sizeof(Line));
-    ll->next = istk->expansion;
-    ll->finishes = m;
-    ll->first = NULL;
-    istk->expansion = ll;
+    ei = new_ExpInv(EXP_MMACRO, ed);
+    ei->name = nasm_strdup(mname);
+    //ei->label = label;
+    //ei->label_text = detoken(label, false);
+    ei->current = ed->line;
+    ei->emitting = true;
+    //ei->iline = tline;
+    ei->params = params;
+    ei->nparam = nparam;
+    ei->rotate = 0;
+    ei->paramlen = paramlen;
+    ei->lineno = 0;
+
+    ei->prev = istk->expansion;
+    istk->expansion = ei;
 
     /*
-     * Save the previous MMacro expansion in the case of
-     * macro recursion
+     * Special case: detect %00 on first invocation; if found,
+     * avoid emitting any labels that precede the mmacro call.
+     * ed->prepend is set to -1 when %00 is detected, else 1.
      */
-    if (m->max_depth && m->in_progress)
-        push_mmacro(m);
-
-    m->in_progress ++;
-    m->params = params;
-    m->iline = tline;
-    m->nparam = nparam;
-    m->rotate = 0;
-    m->paramlen = paramlen;
-    m->unique = unique++;
-    m->lineno = 0;
-    m->condcnt = 0;
-
-    m->next_active = istk->mstk;
-    istk->mstk = m;
-
-    list_for_each(l, m->expansion) {
-        Token **tail;
-
-        ll = nasm_malloc(sizeof(Line));
-        ll->finishes = NULL;
-        ll->next = istk->expansion;
-        istk->expansion = ll;
-        tail = &ll->first;
-
-        list_for_each(t, l->first) {
-            Token *x = t;
-            switch (t->type) {
-            case TOK_PREPROC_Q:
-                tt = *tail = new_Token(NULL, TOK_ID, mname, 0);
-                break;
-            case TOK_PREPROC_QQ:
-                tt = *tail = new_Token(NULL, TOK_ID, m->name, 0);
-                break;
-            case TOK_PREPROC_ID:
-                if (t->text[1] == '0' && t->text[2] == '0') {
+    if (ed->prepend == 0) {
+        for (l = ed->line; l != NULL; l = l->next) {
+            for (t = l->first; t != NULL; t = t->next) {
+                if ((t->type == TOK_PREPROC_ID) &&
+                    (strlen(t->text) == 3) &&
+                    (t->text[1] == '0') && (t->text[2] == '0')) {
                     dont_prepend = -1;
-                    x = label;
-                    if (!x)
-                        continue;
+                    break;
                 }
-                /* fall through */
-            default:
-                tt = *tail = new_Token(NULL, x->type, x->text, 0);
+            }
+            if (dont_prepend < 0) {
                 break;
             }
-            tail = &tt->next;
         }
-        *tail = NULL;
+        ed->prepend = ((dont_prepend < 0) ? -1 : 1);
     }
 
     /*
      * If we had a label, push it on as the first line of
      * the macro expansion.
      */
-    if (label) {
-        if (dont_prepend < 0)
-            free_tlist(startline);
-        else {
-            ll = nasm_malloc(sizeof(Line));
-            ll->finishes = NULL;
-            ll->next = istk->expansion;
-            istk->expansion = ll;
-            ll->first = startline;
-            if (!dont_prepend) {
-                while (label->next)
-                    label = label->next;
-                label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
+    if (label != NULL) {
+        if (ed->prepend < 0) {
+            ei->label_text = detoken(label, false);
+        } else {
+            if (dont_prepend == 0) {
+                t = label;
+                while (t->next != NULL) {
+                    t = t->next;
+                }
+                t->next = new_Token(NULL, TOK_OTHER, ":", 0);
             }
+            l = new_Line();
+            l->first = copy_Token(label);
+            l->next = ei->current;
+            ei->current = l;
         }
     }
 
-    list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
+    list->uplevel(ed->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
 
-    return 1;
+    istk->mmac_depth++;
+    return true;
 }
 
 /* The function that actually does the error reporting */
 static void verror(int severity, const char *fmt, va_list arg)
 {
     char buff[1024];
-    MMacro *mmac = NULL;
-    int delta = 0;
 
     vsnprintf(buff, sizeof(buff), fmt, arg);
 
-    /* get %macro name */
-    if (istk && istk->mstk) {
-        mmac = istk->mstk;
-        /* but %rep blocks should be skipped */
-        while (mmac && !mmac->name)
-            mmac = mmac->next_active, delta++;
-    }
-
-    if (mmac)
-        nasm_error(severity, "(%s:%d) %s",
-                   mmac->name, mmac->lineno - delta, buff);
-    else
+    if (istk && istk->mmac_depth > 0) {
+        ExpInv *ei = istk->expansion;
+        int lineno = ei->lineno;
+        while (ei) {
+            if (ei->type == EXP_MMACRO)
+                break;
+            lineno += ei->relno;
+            ei = ei->prev;
+        }
+        nasm_error(severity, "(%s:%d) %s", ei->def->name,
+                   lineno, buff);
+    else
         nasm_error(severity, "%s", buff);
 }
 
@@ -4783,11 +5078,6 @@ static void verror(int severity, const char *fmt, va_list arg)
 static void error(int severity, const char *fmt, ...)
 {
     va_list arg;
-
-    /* If we're in a dead branch of IF or something like it, ignore the error */
-    if (istk && istk->conds && !emitting(istk->conds->state))
-        return;
-
     va_start(arg, fmt);
     verror(severity, fmt, arg);
     va_end(arg);
@@ -4804,7 +5094,10 @@ static void error_precond(int severity, const char *fmt, ...)
     va_list arg;
 
     /* Only ignore the error if it's really in a dead branch */
-    if (istk && istk->conds && istk->conds->state == COND_NEVER)
+    if ((istk != NULL) &&
+        (istk->expansion != NULL) &&
+        (istk->expansion->type == EXP_IF) &&
+        (istk->expansion->def->state == COND_NEVER))
         return;
 
     va_start(arg, fmt);
@@ -4818,13 +5111,8 @@ pp_reset(char *file, int apass, ListGen * listgen, StrList **deplist)
     Token *t;
 
     cstk = NULL;
-    istk = nasm_malloc(sizeof(Include));
-    istk->next = NULL;
-    istk->conds = NULL;
-    istk->expansion = NULL;
-    istk->mstk = NULL;
+    istk = nasm_zalloc(sizeof(Include));
     istk->fp = fopen(file, "r");
-    istk->fname = NULL;
     src_set_fname(nasm_strdup(file));
     src_set_linnum(0);
     istk->lineinc = 1;
@@ -4832,6 +5120,8 @@ pp_reset(char *file, int apass, ListGen * listgen, StrList **deplist)
         error(ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'",
               file);
     defining = NULL;
+    finals = NULL;
+    in_final = false;
     nested_mac_count = 0;
     nested_rep_count = 0;
     init_macros();
@@ -4866,10 +5156,8 @@ pp_reset(char *file, int apass, ListGen * listgen, StrList **deplist)
      * all the other builtins, because it is special -- it varies between
      * passes.
      */
-    t = nasm_malloc(sizeof(*t));
-    t->next = NULL;
+    t = nasm_zalloc(sizeof(*t));
     make_tok_num(t, apass);
-    t->a.mac = NULL;
     define_smacro(NULL, "__PASS__", true, 0, t);
 }
 
@@ -4877,114 +5165,104 @@ static char *pp_getline(void)
 {
     char *line;
     Token *tline;
+    ExpDef *ed;
+    ExpInv *ei;
+    Line *l;
+    int j;
 
     while (1) {
         /*
-         * Fetch a tokenized line, either from the macro-expansion
+         * Fetch a tokenized line, either from the expansion
          * buffer or from the input file.
          */
         tline = NULL;
-        while (istk->expansion && istk->expansion->finishes) {
-            Line *l = istk->expansion;
-            if (!l->finishes->name && l->finishes->in_progress > 1) {
-                Line *ll;
 
-                /*
-                 * This is a macro-end marker for a macro with no
-                 * name, which means it's not really a macro at all
-                 * but a %rep block, and the `in_progress' field is
-                 * more than 1, meaning that we still need to
-                 * repeat. (1 means the natural last repetition; 0
-                 * means termination by %exitrep.) We have
-                 * therefore expanded up to the %endrep, and must
-                 * push the whole block on to the expansion buffer
-                 * again. We don't bother to remove the macro-end
-                 * marker: we'd only have to generate another one
-                 * if we did.
-                 */
-                l->finishes->in_progress--;
-                list_for_each(l, l->finishes->expansion) {
-                    Token *t, *tt, **tail;
-
-                    ll = nasm_malloc(sizeof(Line));
-                    ll->next = istk->expansion;
-                    ll->finishes = NULL;
-                    ll->first = NULL;
-                    tail = &ll->first;
-
-                    list_for_each(t, l->first) {
-                        if (t->text || t->type == TOK_WHITESPACE) {
-                            tt = *tail = new_Token(NULL, t->type, t->text, 0);
-                            tail = &tt->next;
-                        }
+        while (1) {             /* until we get a line we can use */
+            /*
+             * Fetch a tokenized line from the expansion buffer
+             */
+            if (istk->expansion != NULL) {
+                ei = istk->expansion;
+                if (ei->current != NULL) {
+                    if (ei->emitting == false) {
+                        ei->current = NULL;
+                        continue;
                     }
-
-                    istk->expansion = ll;
-                }
-            } else {
-                /*
-                 * Check whether a `%rep' was started and not ended
-                 * within this macro expansion. This can happen and
-                 * should be detected. It's a fatal error because
-                 * I'm too confused to work out how to recover
-                 * sensibly from it.
-                 */
-                if (defining) {
-                    if (defining->name)
-                        error(ERR_PANIC,
-                              "defining with name in expansion");
-                    else if (istk->mstk->name)
-                        error(ERR_FATAL,
-                              "`%%rep' without `%%endrep' within"
-                              " expansion of macro `%s'",
-                              istk->mstk->name);
-                }
-
-                /*
-                 * FIXME:  investigate the relationship at this point between
-                 * istk->mstk and l->finishes
-                 */
-                {
-                    MMacro *m = istk->mstk;
-                    istk->mstk = m->next_active;
-                    if (m->name) {
-                        /*
-                         * This was a real macro call, not a %rep, and
-                         * therefore the parameter information needs to
-                         * be freed.
-                         */
-                        if (m->prev) {
-                            pop_mmacro(m);
-                            l->finishes->in_progress --;
-                        } else {
-                            nasm_free(m->params);
-                            free_tlist(m->iline);
-                            nasm_free(m->paramlen);
-                            l->finishes->in_progress = 0;
+                    l = ei->current;
+                    ei->current = l->next;
+                    ei->lineno++;
+                    tline = copy_Token(l->first);
+                    if (((ei->type == EXP_REP) ||
+                         (ei->type == EXP_MMACRO) ||
+                         (ei->type == EXP_WHILE))
+                        && (ei->def->nolist == false)) {
+                        char *p = detoken(tline, false);
+                        list->line(LIST_MACRO, p);
+                        nasm_free(p);
+                    }
+                    if (ei->linnum > -1) {
+                        src_set_linnum(src_get_linnum() + 1);
+                    }
+                    break;
+                } else if ((ei->type == EXP_REP) &&
+                           (ei->def->cur_depth < ei->def->max_depth)) {
+                    ei->def->cur_depth ++;
+                    ei->current = ei->def->line;
+                    ei->lineno = 0;
+                    continue;
+                } else if ((ei->type == EXP_WHILE) &&
+                           (ei->def->cur_depth < ei->def->max_depth)) {
+                    ei->current = ei->def->line;
+                    ei->lineno = 0;
+                    tline = copy_Token(ei->current->first);
+                    j = if_condition(tline, PP_WHILE);
+                    tline = NULL;
+                    j = (((j < 0) ? COND_NEVER : j) ? COND_IF_TRUE : COND_IF_FALSE);
+                    if (j == COND_IF_TRUE) {
+                        ei->current = ei->current->next;
+                        ei->def->cur_depth ++;
+                    } else {
+                        ei->emitting = false;
+                        ei->current = NULL;
+                        ei->def->cur_depth = ei->def->max_depth;
+                    }
+                    continue;
+                } else {
+                    istk->expansion = ei->prev;
+                    ed = ei->def;
+                    if (ed != NULL) {
+                        if ((ei->emitting == true) &&
+                            (ed->max_depth == DEADMAN_LIMIT) &&
+                            (ed->cur_depth == DEADMAN_LIMIT)
+                           ) {
+                            error(ERR_FATAL, "runaway expansion detected, aborting");
                         }
-                    } else
-                        free_mmacro(m);
+                        if (ed->cur_depth > 0) {
+                            ed->cur_depth --;
+                        } else if (ed->type != EXP_MMACRO) {
+                            expansions = ed->prev;
+                            free_expdef(ed);
+                        }
+                        if ((ei->type == EXP_REP) ||
+                            (ei->type == EXP_MMACRO) ||
+                            (ei->type == EXP_WHILE)) {
+                            list->downlevel(LIST_MACRO);
+                            if (ei->type == EXP_MMACRO) {
+                                istk->mmac_depth--;
+                            }
+                        }
+                    }
+                    if (ei->linnum > -1) {
+                        src_set_linnum(ei->linnum);
+                    }
+                    free_expinv(ei);
+                    continue;
                 }
-                istk->expansion = l->next;
-                nasm_free(l);
-                list->downlevel(LIST_MACRO);
             }
-        }
-        while (1) {             /* until we get a line we can use */
 
-            if (istk->expansion) {      /* from a macro expansion */
-                char *p;
-                Line *l = istk->expansion;
-                if (istk->mstk)
-                    istk->mstk->lineno++;
-                tline = l->first;
-                istk->expansion = l->next;
-                nasm_free(l);
-                p = detoken(tline, false);
-                list->line(LIST_MACRO, p);
-                nasm_free(p);
-                break;
-            }
+            /*
+             * Read in line from input and tokenize
+             */
             line = read_line();
             if (line) {         /* from the current input file */
                 line = prepreproc(line);
@@ -4992,44 +5270,46 @@ static char *pp_getline(void)
                 nasm_free(line);
                 break;
             }
+
             /*
              * The current file has ended; work down the istk
              */
             {
                 Include *i = istk;
                 fclose(i->fp);
-                if (i->conds) {
-                    /* nasm_error can't be conditionally suppressed */
-                    nasm_error(ERR_FATAL,
-                               "expected `%%endif' before end of file");
+                if (i->expansion != NULL) {
+                    error(ERR_FATAL,
+                          "end of file while still in an expansion");
                 }
                 /* only set line and file name if there's a next node */
                 if (i->next) {
                     src_set_linnum(i->lineno);
                     nasm_free(src_set_fname(nasm_strdup(i->fname)));
                 }
+                if ((i->next == NULL) && (finals != NULL)) {
+                    in_final = true;
+                    ei = new_ExpInv(EXP_FINAL, NULL);
+                    ei->emitting = true;
+                    ei->current = finals;
+                    istk->expansion = ei;
+                    finals = NULL;
+                    continue;
+                }
                 istk = i->next;
                 list->downlevel(LIST_INCLUDE);
                 nasm_free(i);
-                if (!istk)
-                    return NULL;
-                if (istk->expansion && istk->expansion->finishes)
-                    break;
+                if (istk == NULL) {
+                    if (finals != NULL) {
+                        in_final = true;
+                    } else {
+                        return NULL;
+                    }
+                }
+                continue;
             }
         }
 
-        /*
-         * We must expand MMacro parameters and MMacro-local labels
-         * _before_ we plunge into directive processing, to cope
-         * with things like `%define something %1' such as STRUC
-         * uses. Unless we're _defining_ a MMacro, in which case
-         * those tokens should be left alone to go into the
-         * definition; and unless we're in a non-emitting
-         * condition, in which case we don't want to meddle with
-         * anything.
-         */
-        if (!defining && !(istk->conds && !emitting(istk->conds->state))
-            && !(istk->mstk && !istk->mstk->in_progress)) {
+        if (defining == NULL) {
             tline = expand_mmac_params(tline);
         }
 
@@ -5038,41 +5318,39 @@ static char *pp_getline(void)
          */
         if (do_directive(tline) == DIRECTIVE_FOUND) {
             continue;
-        } else if (defining) {
+        } else if (defining != NULL) {
             /*
-             * We're defining a multi-line macro. We emit nothing
-             * at all, and just
-             * shove the tokenized line on to the macro definition.
+             * We're defining an expansion. We emit nothing at all,
+             * and just shove the tokenized line on to the definition.
              */
-            Line *l = nasm_malloc(sizeof(Line));
-            l->next = defining->expansion;
-            l->first = tline;
-            l->finishes = NULL;
-            defining->expansion = l;
+            if (defining->ignoring == false) {
+                Line *l = new_Line();
+                l->first = tline;
+                if (defining->line == NULL) {
+                    defining->line = l;
+                    defining->last = l;
+                } else {
+                    defining->last->next = l;
+                    defining->last = l;
+                }
+            } else {
+                free_tlist(tline);
+            }
+            defining->linecount++;
             continue;
-        } else if (istk->conds && !emitting(istk->conds->state)) {
+        } else if ((istk->expansion != NULL) &&
+                   (istk->expansion->emitting != true)) {
             /*
-             * We're in a non-emitting branch of a condition block.
+             * We're in a non-emitting branch of an expansion.
              * Emit nothing at all, not even a blank line: when we
-             * emerge from the condition we'll give a line-number
+             * emerge from the expansion we'll give a line-number
              * directive so we keep our place correctly.
              */
             free_tlist(tline);
             continue;
-        } else if (istk->mstk && !istk->mstk->in_progress) {
-            /*
-             * We're in a %rep block which has been terminated, so
-             * we're walking through to the %endrep without
-             * emitting anything. Emit nothing at all, not even a
-             * blank line: when we emerge from the %rep block we'll
-             * give a line-number directive so we keep our place
-             * correctly.
-             */
-            free_tlist(tline);
-            continue;
         } else {
             tline = expand_smacro(tline);
-            if (!expand_mmacro(tline)) {
+            if (expand_mmacro(tline) != true) {
                 /*
                  * De-tokenize the line again, and emit it.
                  */
@@ -5080,36 +5358,37 @@ static char *pp_getline(void)
                 free_tlist(tline);
                 break;
             } else {
-                continue;       /* expand_mmacro calls free_tlist */
+                continue;
             }
         }
     }
-
     return line;
 }
 
 static void pp_cleanup(int pass)
 {
-    if (defining) {
-        if (defining->name) {
-            error(ERR_NONFATAL,
-                  "end of file while still defining macro `%s'",
-                  defining->name);
-        } else {
-            error(ERR_NONFATAL, "end of file while still in %%rep");
+    if (defining != NULL) {
+        error(ERR_NONFATAL, "end of file while still defining an expansion");
+        while (defining != NULL) {
+            ExpDef *ed = defining;
+            defining = ed->prev;
+            free_expdef(ed);
         }
-
-        free_mmacro(defining);
         defining = NULL;
     }
-    while (cstk)
+    while (cstk != NULL)
         ctx_pop();
     free_macros();
-    while (istk) {
+    while (istk != NULL) {
         Include *i = istk;
         istk = istk->next;
         fclose(i->fp);
         nasm_free(i->fname);
+        while (i->expansion != NULL) {
+            ExpInv *ei = i->expansion;
+            i->expansion = ei->prev;
+            free_expinv(ei);
+        }
         nasm_free(i);
     }
     while (cstk)
@@ -5121,8 +5400,7 @@ static void pp_cleanup(int pass)
         delete_Blocks();
         while ((i = ipath)) {
             ipath = i->next;
-            if (i->path)
-                nasm_free(i->path);
+            nasm_free(i->path);
             nasm_free(i);
         }
     }
@@ -5130,11 +5408,10 @@ static void pp_cleanup(int pass)
 
 void pp_include_path(char *path)
 {
-    IncPath *i;
+    IncPath *i = nasm_zalloc(sizeof(IncPath));
 
-    i = nasm_malloc(sizeof(IncPath));
-    i->path = path ? nasm_strdup(path) : NULL;
-    i->next = NULL;
+    if (path)
+        i->path = nasm_strdup(path);
 
     if (ipath) {
         IncPath *j = ipath;
@@ -5155,10 +5432,9 @@ void pp_pre_include(char *fname)
     space = new_Token(name, TOK_WHITESPACE, NULL, 0);
     inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
 
-    l = nasm_malloc(sizeof(Line));
+    l = new_Line();
     l->next = predef;
     l->first = inc;
-    l->finishes = NULL;
     predef = l;
 }
 
@@ -5177,10 +5453,9 @@ void pp_pre_define(char *definition)
     if (equals)
         *equals = '=';
 
-    l = nasm_malloc(sizeof(Line));
+    l = new_Line();
     l->next = predef;
     l->first = def;
-    l->finishes = NULL;
     predef = l;
 }
 
@@ -5193,18 +5468,15 @@ void pp_pre_undefine(char *definition)
     def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
     space->next = tokenize(definition);
 
-    l = nasm_malloc(sizeof(Line));
+    l = new_Line();
     l->next = predef;
     l->first = def;
-    l->finishes = NULL;
     predef = l;
 }
 
 /*
- * Added by Keith Kanios:
- *
  * This function is used to assist with "runtime" preprocessor
- * directives. (e.g. pp_runtime("%define __BITS__ 64");)
+ * directives, e.g. pp_runtime("%define __BITS__ 64");
  *
  * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
  * PASS A VALID STRING TO THIS FUNCTION!!!!!
@@ -5233,7 +5505,7 @@ static void make_tok_num(Token * tok, int64_t val)
     tok->type = TOK_NUMBER;
 }
 
-Preproc nasmpp = {
+struct preproc_ops nasmpp = {
     pp_reset,
     pp_getline,
     pp_cleanup
diff --git a/quote.c b/quote.c
index e45dfb2..fe1c97d 100644 (file)
--- a/quote.c
+++ b/quote.c
@@ -42,8 +42,6 @@
 #include "nasmlib.h"
 #include "quote.h"
 
-#define numvalue(c)  ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
-
 char *nasm_quote(char *str, size_t len)
 {
     char c, c1, *p, *q, *nstr, *ep;
index 556373f..4a41a77 100644 (file)
@@ -1,3 +1,6 @@
+;Testname=unoptimized; Arguments=-O0 -fbin -oalign13.bin; Files=stdout stderr align13.bin
+;Testname=optimized; Arguments=-Ox -fbin -oalign13.bin; Files=stdout stderr align13.bin
+
 ; Test of non-power-of-2 alignment
 
        bits 32
index dab21a2..7f78317 100644 (file)
@@ -1,4 +1,8 @@
+;Testname=unoptimized; Arguments=-O0 -fbin -oalign13s.bin; Files=stdout stderr align13s.bin
+;Testname=optimized; Arguments=-Ox -fbin -oalign13s.bin; Files=stdout stderr align13s.bin
+
 ; Test of non-power-of-2 alignment
+
 %use smartalign
 
        bits 32
index 6be4d5d..8db3a2c 100644 (file)
@@ -1,3 +1,6 @@
+;Testname=unoptimized; Arguments=-O0 -fobj -oalonesym-obj.obj; Files=stdout stderr alonesym-obj.obj
+;Testname=optimized; Arguments=-Ox -fobj -oalonesym-obj.obj; Files=stdout stderr alonesym-obj.obj
+
 section         DOS32DATA align=16 public use32 FLAT class=DOS32DATA
 
                 global sym0000
index bb45ca6..b58d81a 100644 (file)
@@ -1,3 +1,5 @@
+;Testname=optimized; Arguments=-Ox -fbin -obcd.bin; Files=stdout stderr bcd.bin
+
        dt 765432109876543210p
        dt -765432109876543210p
        dt +765432109876543210p
index fb309a9..74e3234 100644 (file)
@@ -1,3 +1,5 @@
+;Testname=optimized; Arguments=-Ox -fbin -obr2003451.bin; Files=stdout stderr br2003451.bin
+
        cpu 8086
        org 0
 
index ce7ba43..fd8f5eb 100644 (file)
@@ -1,4 +1,6 @@
-       bits 64
+;Testname=optimized; Arguments=-Ox -fbin -obr2030823.bin; Files=stdout stderr br2030823.bin
+
+bits 64
        VFMADDPD xmm0, xmm1, [0], xmm3
        VFMADDPD xmm0, xmm1, xmm2, [0]
        VFMADDPD ymm0, ymm1, [0], ymm3
index 4e7a5b5..66a46f8 100644 (file)
@@ -1,3 +1,5 @@
+;Testname=br3005117; Arguments=-Ox -felf -obr3005117.o; Files=stdout stderr br3005117.o
+
 %macro B_STRUC 1-*
 %push foo
 %define %$strucname %1
index 5c61c95..d84923a 100644 (file)
@@ -1,3 +1,5 @@
+;Testname=br3026808; Arguments=-Ox -fbin -obr3026808.o; Files=stdout stderr br3026808.o
+
 %imacro proc 1
        %push proc
        %assign %$arg 1
index 20c8bd0..b6b2cf2 100644 (file)
@@ -1,3 +1,5 @@
+;Testname=br3028880; Arguments=-Ox -fbin -obr3028880.o; Files=stdout stderr br3028880.o
+
 %macro import 1
        %define %%incfile %!PROJECTBASEDIR/%{1}.inc
 %endmacro
index b0de560..c42f5d5 100644 (file)
@@ -11,4 +11,4 @@ cmp eax, 0xFFFF_FFFF
 
 BITS 64
 cmp ax, 0xFFFF
-cmp eax, 0xFFFF_FFFF    ; shouldn't warn, but does currently
+cmp eax, 0xFFFF_FFFF
index 09222ac..d6a8646 100644 (file)
@@ -1,3 +1,5 @@
+;Testname=br3066383; Arguments=-Ox -fbin -obr3066383.bin; Files=stdout stderr br3066383.bin
+
 ;
 ; this is a for BR3005117
 ; http://sourceforge.net/tracker/?func=detail&aid=3005117&group_id=6208&atid=106208
diff --git a/test/br3074517.asm b/test/br3074517.asm
new file mode 100644 (file)
index 0000000..9697809
--- /dev/null
@@ -0,0 +1,12 @@
+;%define UNDEFINED
+%macro macro 0
+    %ifndef UNDEFINED
+        %rep 1
+            %fatal This should display "fatal: (m:3)"
+        %endrep
+    %endif
+    %fatal This should display "fatal: (m:6)" if 'UNDEFINED' defined
+%endmacro
+
+macro
+
diff --git a/test/br3092924.asm b/test/br3092924.asm
new file mode 100644 (file)
index 0000000..3f9cde0
--- /dev/null
@@ -0,0 +1,25 @@
+%define RNUM   0x10000  ; max of relocations in a section is 0xffff
+
+section        .data1
+       r1 dd RNUM
+
+section        .data2
+       r2 dd RNUM
+
+%macro x1 1
+       mov eax, [r1 + %1]
+%endmacro
+
+%macro x2 1
+       mov eax, [r2 + %1]
+%endmacro
+
+section        .text1
+
+       %assign i 0
+       %rep RNUM
+               x1 i
+               x2 i
+               %assign i i+1
+       %endrep
+
diff --git a/test/br3104312.asm b/test/br3104312.asm
new file mode 100644 (file)
index 0000000..0dee16b
--- /dev/null
@@ -0,0 +1,11 @@
+%if 1 < 8000_0002h\r
+ %warning No bug with 8000_0002h\r
+%else\r
+ %warning Bug with 8000_0002h\r
+%endif\r
+\r
+%if 1 < 8000_0001h\r
+ %warning No bug with 8000_0001h\r
+%else\r
+ %warning Bug with 8000_0001h\r
+%endif\r
index d90a064..a114044 100644 (file)
@@ -9,3 +9,53 @@
        mov [rax],dword 11223344h               ; 32-bit operation
        mov qword [rax],11223344h
        mov qword [rax],dword 11223344h
+
+       mov rax,0_ffffffff_8899aabbh
+       mov rax,dword 0_ffffffff_8899aabbh
+       mov eax,0_ffffffff_8899aabbh
+       mov [rax],dword 0_ffffffff_8899aabbh    ; 32-bit operation
+       mov qword [rax],0_ffffffff_8899aabbh
+       mov qword [rax],dword 0_ffffffff_8899aabbh
+
+       mov rax,7fffffffh
+       mov rax,80000000h
+       mov rax,0_ffffffffh
+       mov rax,1_00000000h
+       mov rax,0_ffffffff_7fffffffh
+       mov rax,0_ffffffff_80000000h
+
+       mov rax,0_11223344_8899aabbh
+       mov rax,dword 0_11223344_8899aabbh
+       mov eax,0_11223344_8899aabbh
+       mov [rax],dword 0_11223344_8899aabbh    ; 32-bit operation
+       mov qword [rax],0_11223344_8899aabbh
+       mov qword [rax],dword 0_11223344_8899aabbh
+       
+       mov rax,strict 11223344h
+       mov rax,strict dword 11223344h
+       mov eax,strict 11223344h
+       mov [rax],strict dword 11223344h                ; 32-bit operation
+       mov qword [rax],strict 11223344h
+       mov qword [rax],strict dword 11223344h
+
+       mov rax,strict 0_ffffffff_8899aabbh
+       mov rax,strict dword 0_ffffffff_8899aabbh
+       mov eax,strict 0_ffffffff_8899aabbh
+       mov [rax],strict dword 0_ffffffff_8899aabbh     ; 32-bit operation
+       mov qword [rax],strict 0_ffffffff_8899aabbh
+       mov qword [rax],strict dword 0_ffffffff_8899aabbh
+
+       mov rax,strict 7fffffffh
+       mov rax,strict 80000000h
+       mov rax,strict 0_ffffffffh
+       mov rax,strict 1_00000000h
+       mov rax,strict 0_ffffffff_7fffffffh
+       mov rax,strict 0_ffffffff_80000000h
+
+       mov rax,strict 0_11223344_8899aabbh
+       mov rax,strict dword 0_11223344_8899aabbh
+       mov eax,strict 0_11223344_8899aabbh
+       mov [rax],strict dword 0_11223344_8899aabbh     ; 32-bit operation
+       mov qword [rax],strict 0_11223344_8899aabbh
+       mov qword [rax],strict dword 0_11223344_8899aabbh
+       
diff --git a/test/movd.asm b/test/movd.asm
new file mode 100644 (file)
index 0000000..42df0af
--- /dev/null
@@ -0,0 +1,12 @@
+;Testname=optimized; Arguments=-Ox -fbin -omovd.bin; Files=stdout stderr movd.bin
+[BITS 32]
+       movd    mm0,eax
+       movd    mm0,[eax]
+       movd    [eax],mm0
+       movd    eax,mm0
+
+       movd    xmm0,eax
+       movd    xmm0,[eax]
+
+       movd    [eax],xmm0
+       movd    eax,xmm0
diff --git a/test/prefix66.asm b/test/prefix66.asm
new file mode 100644 (file)
index 0000000..4d9eb00
--- /dev/null
@@ -0,0 +1,28 @@
+;Testname=test; Arguments=-fbin -oprefix66.bin; Files=stdout stderr prefix66.bin
+
+BITS 16
+cmp ax, 1
+o16 cmp ax, 1
+o32 cmp ax, 1
+
+cmp eax, 1
+o16 cmp eax, 1
+o32 cmp eax, 1
+
+BITS 32
+cmp ax, 1
+o16 cmp ax, 1
+o32 cmp ax, 1
+
+cmp eax, 1
+o16 cmp eax, 1
+o32 cmp eax, 1
+
+BITS 64
+cmp ax, 1
+o16 cmp ax, 1
+o32 cmp ax, 1
+
+cmp eax, 1
+o16 cmp eax, 1
+o32 cmp eax, 1
diff --git a/test/sreg.asm b/test/sreg.asm
new file mode 100644 (file)
index 0000000..11449a5
--- /dev/null
@@ -0,0 +1,65 @@
+       bits 64
+       mov es,rax
+       mov ss,rax
+       mov ds,rax
+       mov fs,rax
+       mov gs,rax
+       mov es,eax
+       mov ss,eax
+       mov ds,eax
+       mov fs,eax
+       mov gs,eax
+       mov es,ax
+       mov ss,ax
+       mov ds,ax
+       mov fs,ax
+       mov gs,ax
+       mov es,[rsi]
+       mov ss,[rsi]
+       mov ds,[rsi]
+       mov fs,[rsi]
+       mov gs,[rsi]
+       mov es,word [rsi]
+       mov ss,word [rsi]
+       mov ds,word [rsi]
+       mov fs,word [rsi]
+       mov gs,word [rsi]
+       mov es,qword [rsi]
+       mov ss,qword [rsi]
+       mov ds,qword [rsi]
+       mov fs,qword [rsi]
+       mov gs,qword [rsi]
+       mov rax,es
+       mov rax,cs
+       mov rax,ss
+       mov rax,ds
+       mov rax,fs
+       mov rax,gs
+       mov eax,es
+       mov eax,ss
+       mov eax,ds
+       mov eax,fs
+       mov eax,fs
+       mov ax,es
+       mov ax,ss
+       mov ax,ds
+       mov ax,fs
+       mov ax,gs
+       mov [rdi],es
+       mov [rdi],cs
+       mov [rdi],ss
+       mov [rdi],ds
+       mov [rdi],fs
+       mov [rdi],gs
+       mov word [rdi],es
+       mov word [rdi],cs
+       mov word [rdi],ss
+       mov word [rdi],ds
+       mov word [rdi],fs
+       mov word [rdi],gs
+       mov qword [rdi],es
+       mov qword [rdi],cs
+       mov qword [rdi],ss
+       mov qword [rdi],ds
+       mov qword [rdi],fs
+       mov qword [rdi],gs
diff --git a/test/vgather.asm b/test/vgather.asm
new file mode 100644 (file)
index 0000000..4012bf2
--- /dev/null
@@ -0,0 +1,76 @@
+       bits 64
+
+       vgatherdpd xmm0,[rcx+xmm2],xmm3
+       vgatherqpd xmm0,[rcx+xmm2],xmm3
+       vgatherdpd ymm0,[rcx+xmm2],ymm3
+       vgatherqpd ymm0,[rcx+ymm2],ymm3
+
+       vgatherdpd xmm0,[rcx+xmm2*1],xmm3
+       vgatherqpd xmm0,[rcx+xmm2*1],xmm3
+       vgatherdpd ymm0,[rcx+xmm2*1],ymm3
+       vgatherqpd ymm0,[rcx+ymm2*1],ymm3
+
+       vgatherdpd xmm0,[rcx+xmm2*2],xmm3
+       vgatherqpd xmm0,[rcx+xmm2*2],xmm3
+       vgatherdpd ymm0,[rcx+xmm2*2],ymm3
+       vgatherqpd ymm0,[rcx+ymm2*2],ymm3
+
+       vgatherdpd xmm0,[rcx+xmm2*4],xmm3
+       vgatherqpd xmm0,[rcx+xmm2*4],xmm3
+       vgatherdpd ymm0,[rcx+xmm2*4],ymm3
+       vgatherqpd ymm0,[rcx+ymm2*4],ymm3
+
+       vgatherdpd xmm0,[rcx+xmm2*8],xmm3
+       vgatherqpd xmm0,[rcx+xmm2*8],xmm3
+       vgatherdpd ymm0,[rcx+xmm2*8],ymm3
+       vgatherqpd ymm0,[rcx+ymm2*8],ymm3
+
+       vgatherdpd xmm0,[xmm2],xmm3
+       vgatherqpd xmm0,[xmm2],xmm3
+       vgatherdpd ymm0,[xmm2],ymm3
+       vgatherqpd ymm0,[ymm2],ymm3
+
+       vgatherdpd xmm0,[xmm2*1],xmm3
+       vgatherqpd xmm0,[xmm2*1],xmm3
+       vgatherdpd ymm0,[xmm2*1],ymm3
+       vgatherqpd ymm0,[ymm2*1],ymm3
+
+       vgatherdpd xmm0,[xmm2*2],xmm3
+       vgatherqpd xmm0,[xmm2*2],xmm3
+       vgatherdpd ymm0,[xmm2*2],ymm3
+       vgatherqpd ymm0,[ymm2*2],ymm3
+
+       vgatherdpd xmm0,[xmm2*4],xmm3
+       vgatherqpd xmm0,[xmm2*4],xmm3
+       vgatherdpd ymm0,[xmm2*4],ymm3
+       vgatherqpd ymm0,[ymm2*4],ymm3
+
+       vgatherdpd xmm0,[xmm2*8],xmm3
+       vgatherqpd xmm0,[xmm2*8],xmm3
+       vgatherdpd ymm0,[xmm2*8],ymm3
+       vgatherqpd ymm0,[ymm2*8],ymm3
+
+       vgatherdpd xmm0,[xmm2+rcx],xmm3
+       vgatherqpd xmm0,[xmm2+rcx],xmm3
+       vgatherdpd ymm0,[xmm2+rcx],ymm3
+       vgatherqpd ymm0,[ymm2+rcx],ymm3
+
+       vgatherdpd xmm0,[xmm2*1+rcx],xmm3
+       vgatherqpd xmm0,[xmm2*1+rcx],xmm3
+       vgatherdpd ymm0,[xmm2*1+rcx],ymm3
+       vgatherqpd ymm0,[ymm2*1+rcx],ymm3
+
+       vgatherdpd xmm0,[xmm2*2+rcx],xmm3
+       vgatherqpd xmm0,[xmm2*2+rcx],xmm3
+       vgatherdpd ymm0,[xmm2*2+rcx],ymm3
+       vgatherqpd ymm0,[ymm2*2+rcx],ymm3
+
+       vgatherdpd xmm0,[xmm2*4+rcx],xmm3
+       vgatherqpd xmm0,[xmm2*4+rcx],xmm3
+       vgatherdpd ymm0,[xmm2*4+rcx],ymm3
+       vgatherqpd ymm0,[ymm2*4+rcx],ymm3
+
+       vgatherdpd xmm0,[xmm2*8+rcx],xmm3
+       vgatherqpd xmm0,[xmm2*8+rcx],xmm3
+       vgatherdpd ymm0,[xmm2*8+rcx],ymm3
+       vgatherqpd ymm0,[ymm2*8+rcx],ymm3
index 0c69c03..6c05802 100755 (executable)
@@ -183,7 +183,7 @@ if ($output eq 'h') {
     #
 
     @hashinfo = gen_perfect_hash(\%tokens);
-    if (!defined(@hashinfo)) {
+    if (!@hashinfo) {
        die "$0: no hash found\n";
     }
 
diff --git a/version b/version
index aa45e1d..deff077 100644 (file)
--- a/version
+++ b/version
@@ -1 +1 @@
-2.09.09
+2.10rc6