Implement "oword" (128 bits) as a first-class size
authorH. Peter Anvin <hpa@zytor.com>
Tue, 18 Sep 2007 20:01:32 +0000 (13:01 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Tue, 18 Sep 2007 20:01:32 +0000 (13:01 -0700)
Implement oword, reso, do, as well as the SO flag to instructions.  No
instructions are actually flagged with SO yet, but this allows us to
specify 128-bit sizes in instruction patterns.

assemble.c
insns.dat
insns.h
nasm.h
parser.c
tokens.dat

index ec3b112..e538454 100644 (file)
@@ -1720,6 +1720,9 @@ static int matches(const struct itemplate *itemp, insn * instruction, int bits)
        case IF_SQ:
             size[i] = BITS64;
            break;
+       case IF_SO:
+           size[i] = BITS128;
+           break;
        default:
            break;
         }
@@ -1742,6 +1745,10 @@ static int matches(const struct itemplate *itemp, insn * instruction, int bits)
             asize = BITS64;
             oprs = itemp->operands;
            break;
+       case IF_SO:
+            asize = BITS128;
+            oprs = itemp->operands;
+           break;
        default:
            break;
         }
index 5214ee5..f95b157 100644 (file)
--- a/insns.dat
+++ b/insns.dat
 ; see the comment at the top of assemble.c.  For a detailed description
 ; of the flags (fourth field), please see insns.h.
 ;
+
+; Special instructions...
+DB        ignore              ignore                        ignore
+DW        ignore              ignore                        ignore
+DD        ignore              ignore                        ignore
+DQ        ignore              ignore                        ignore
+DT        ignore              ignore                        ignore
+DO        ignore              ignore                        ignore
+RESB      imm                 \340                          8086
+RESW      ignore              ignore                        ignore
+RESD      ignore              ignore                        ignore
+RESQ      ignore              ignore                        ignore
+REST      ignore              ignore                        ignore
+RESO      ignore              ignore                        ignore
+
+; Conventional instructions
 AAA       void                \1\x37                        8086,NOLONG
 AAD       void                \2\xD5\x0A                    8086,NOLONG
 AAD       imm                 \1\xD5\24                     8086,SB,NOLONG
@@ -270,8 +286,6 @@ CWD       void                \320\1\x99                    8086
 CWDE      void                \321\1\x98                    386
 DAA       void                \1\x27                        8086,NOLONG
 DAS       void                \1\x2F                        8086,NOLONG
-DB        ignore              ignore                        ignore
-DD        ignore              ignore                        ignore
 DEC       reg16               \320\10\x48                   8086,NOLONG
 DEC       reg32               \321\10\x48                   386,NOLONG
 DEC       rm8                 \300\1\xFE\201                8086
@@ -282,9 +296,6 @@ DIV       rm8                 \300\1\xF6\206                8086
 DIV       rm16                \320\300\1\xF7\206            8086
 DIV       rm32                \321\300\1\xF7\206            386
 DIV       rm64                \324\300\1\xF7\206            X64
-DQ        ignore              ignore                        ignore
-DT        ignore              ignore                        ignore
-DW        ignore              ignore                        ignore
 EMMS      void                \2\x0F\x77                    PENT,MMX
 ENTER     imm,imm             \1\xC8\30\25                  186
 EQU       imm                 \0                            8086
@@ -1029,11 +1040,6 @@ RDMSR     void                \2\x0F\x32                    PENT,PRIV
 RDPMC     void                \2\x0F\x33                    P6
 RDTSC     void                \2\x0F\x31                    PENT
 RDTSCP    void                \3\x0F\x01\xF9                X64
-RESB      imm                 \340                          8086
-RESD      ignore              ignore                        ignore
-RESQ      ignore              ignore                        ignore
-REST      ignore              ignore                        ignore
-RESW      ignore              ignore                        ignore
 RET       void                \1\xC3                        8086
 RET       imm                 \1\xC2\30                     8086,SW
 RETF      void                \1\xCB                        8086
diff --git a/insns.h b/insns.h
index c7fa75a..b5d6caf 100644 (file)
--- a/insns.h
+++ b/insns.h
@@ -68,6 +68,7 @@ extern const struct itemplate * const * const itable[];
 #define IF_SW     0x00000008UL  /* unsized operands can't be non-word */
 #define IF_SD     0x0000000CUL  /* unsized operands can't be non-dword */
 #define IF_SQ     0x00000010UL  /* unsized operands can't be non-qword */
+#define IF_SO     0x00000014UL  /* unsized operands can't be non-oword */
 #define IF_SMASK  0x0000001CUL  /* mask for unsized argument size */
 #define IF_AR0   0x00000020UL  /* SB, SW, SD applies to argument 0 */
 #define IF_AR1   0x00000040UL  /* SB, SW, SD applies to argument 1 */
diff --git a/nasm.h b/nasm.h
index f5d6494..f4afad3 100644 (file)
--- a/nasm.h
+++ b/nasm.h
@@ -375,7 +375,7 @@ enum {
  *
  * The bits are assigned as follows:
  *
- * Bits 0-7: sizes
+ * Bits 0-7, 29: sizes
  *  0:  8 bits (BYTE)
  *  1: 16 bits (WORD)
  *  2: 32 bits (DWORD)
@@ -384,6 +384,7 @@ enum {
  *  5: FAR
  *  6: NEAR
  *  7: SHORT
+ * 29: 128 bits (OWORD)
  *
  * Bits 8-11 modifiers
  *  8: TO
@@ -454,12 +455,13 @@ typedef uint32_t opflags_t;
 #define BITS32         0x00000004L
 #define BITS64         0x00000008L   /* x64 and FPU only */
 #define BITS80         0x00000010L   /* FPU only */
+#define BITS128                0x20000000L
 #define FAR            0x00000020L   /* grotty: this means 16:16 or */
                                        /* 16:32, like in CALL/JMP */
 #define NEAR           0x00000040L
 #define SHORT          0x00000080L   /* and this means what it says :) */
 
-#define SIZE_MASK      0x000000FFL   /* all the size attributes */
+#define SIZE_MASK      0x200000FFL   /* all the size attributes */
 
 /* Modifiers */
 #define MODIFIER_MASK  0x00000f00L
@@ -959,8 +961,8 @@ struct dfmt {
  */
 
 enum special_tokens {
-    S_ABS, S_BYTE, S_DWORD, S_FAR, S_LONG, S_NEAR, S_NOSPLIT, S_QWORD, S_REL,
-    S_SHORT, S_STRICT, S_TO, S_TWORD, S_WORD
+    S_ABS, S_BYTE, S_DWORD, S_FAR, S_LONG, S_NEAR, S_NOSPLIT,
+    S_OWORD, S_QWORD, S_REL, S_SHORT, S_STRICT, S_TO, S_TWORD, S_WORD
 };
 
 /*
index 16164d7..ca12a09 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -175,23 +175,25 @@ insn *parse_line(int pass, char *buffer, insn * result,
      * For the moment, EQU has the same difficulty, so we'll
      * include that.
      */
-    if (result->opcode == I_RESB || result->opcode == I_RESW || result->opcode == I_RESD || result->opcode == I_RESQ || result->opcode == I_REST || result->opcode == I_EQU || result->opcode == I_INCBIN) {    /* fbk */
+    if (result->opcode == I_RESB || result->opcode == I_RESW ||
+       result->opcode == I_RESD || result->opcode == I_RESQ ||
+       result->opcode == I_REST || result->opcode == I_RESO ||
+       result->opcode == I_EQU || result->opcode == I_INCBIN) {
         critical = pass0;
     } else
         critical = (pass == 2 ? 2 : 0);
 
-    if (result->opcode == I_DB ||
-        result->opcode == I_DW ||
-        result->opcode == I_DD ||
-        result->opcode == I_DQ ||
-        result->opcode == I_DT || result->opcode == I_INCBIN) {
+    if (result->opcode == I_DB || result->opcode == I_DW ||
+        result->opcode == I_DD || result->opcode == I_DQ ||
+        result->opcode == I_DT || result->opcode == I_DO ||
+       result->opcode == I_INCBIN) {
         extop *eop, **tail = &result->eops, **fixptr;
         int oper_num = 0;
 
         result->eops_float = FALSE;
 
         /*
-         * Begin to read the DB/DW/DD/DQ/DT/INCBIN operands.
+         * Begin to read the DB/DW/DD/DQ/DT/DO/INCBIN operands.
          */
         while (1) {
             i = stdscan(NULL, &tokval);
@@ -234,6 +236,8 @@ insn *parse_line(int pass, char *buffer, insn * result,
                         eop->stringlen = 8;
                     else if (result->opcode == I_DT)
                         eop->stringlen = 10;
+                   else if (result->opcode == I_DO)
+                       eop->stringlen = 16;
                     else {
                         error(ERR_NONFATAL, "floating-point constant"
                               " encountered in `D%c' instruction",
@@ -245,8 +249,7 @@ insn *parse_line(int pass, char *buffer, insn * result,
                          */
                         eop->stringlen = 0;
                     }
-                    eop =
-                        nasm_realloc(eop, sizeof(extop) + eop->stringlen);
+                    eop = nasm_realloc(eop, sizeof(extop) + eop->stringlen);
                     tail = &eop->next;
                     *fixptr = eop;
                     eop->stringval = (char *)eop + sizeof(extop);
@@ -384,6 +387,11 @@ insn *parse_line(int pass, char *buffer, insn * result,
                     result->oprs[operand].type |= BITS80;
                 setsize = 1;
                 break;
+            case S_OWORD:
+                if (!setsize)
+                    result->oprs[operand].type |= BITS128;
+                setsize = 1;
+                break;
             case S_TO:
                 result->oprs[operand].type |= TO;
                 break;
@@ -440,6 +448,9 @@ insn *parse_line(int pass, char *buffer, insn * result,
                     case S_TWORD:
                         result->oprs[operand].type |= BITS80;
                         break;
+                    case S_OWORD:
+                        result->oprs[operand].type |= BITS128;
+                        break;
                     default:
                         error(ERR_NONFATAL,
                               "invalid operand size specification");
@@ -751,7 +762,7 @@ insn *parse_line(int pass, char *buffer, insn * result,
         result->oprs[operand++].type = 0;
 
     /*
-     * Transform RESW, RESD, RESQ, REST into RESB.
+     * Transform RESW, RESD, RESQ, REST, RESO into RESB.
      */
     switch (result->opcode) {
     case I_RESW:
@@ -770,6 +781,10 @@ insn *parse_line(int pass, char *buffer, insn * result,
         result->opcode = I_RESB;
         result->oprs[0].offset *= 10;
         break;
+    case I_RESO:
+        result->opcode = I_RESB;
+        result->oprs[0].offset *= 16;
+        break;
     default:
        break;
     }
index 6acaba4..c84b8fb 100644 (file)
@@ -23,6 +23,7 @@ far
 long
 near
 nosplit
+oword
 qword
 rel
 short