BR 2592476: Treat WAIT as a prefix even though it's really an instruction
authorH. Peter Anvin <hpa@zytor.com>
Sun, 22 Feb 2009 02:22:56 +0000 (18:22 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Sun, 22 Feb 2009 02:22:56 +0000 (18:22 -0800)
WAIT is technically an instruction, but from an assembler standpoint
it behaves as if it had been a prefix.  In particular, it has to be
ordered *before* any real hardware prefixes.

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

index 2668857..ad7ea70 100644 (file)
  *                 \336-\337 are still listed as prefixes in the disassembler.
  * \340          - reserve <operand 0> bytes of uninitialized storage.
  *                 Operand 0 had better be a segmentless constant.
+ * \341                 - this instruction needs a WAIT "prefix"
  * \344,\345     - the PUSH/POP (respectively) codes for CS, DS, ES, SS
  *                 (POP is never used for CS) depending on operand 0
  * \346,\347     - the second byte of PUSH/POP codes for FS, GS, depending
@@ -464,6 +465,9 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
                     for (j = 0; j < MAXPREFIX; j++) {
                         uint8_t c = 0;
                         switch (instruction->prefixes[j]) {
+                       case P_WAIT:
+                           c = 0x9B;
+                           break;
                         case P_LOCK:
                             c = 0xF0;
                             break;
@@ -1023,6 +1027,11 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
                 length += ins->oprs[0].offset;
             break;
 
+       case 0341:
+           if (!ins->prefixes[PPS_WAIT])
+               ins->prefixes[PPS_WAIT] = P_WAIT;
+           break;
+
        case4(0344):
             length++;
             break;
@@ -1674,6 +1683,9 @@ static void gencode(int32_t segment, int64_t offset, int bits,
             }
             break;
 
+       case 0341:
+           break;
+
         case 0344:
         case 0345:
            bytes[0] = c & 1;
index c320f90..63fd37b 100644 (file)
--- a/disasm.c
+++ b/disasm.c
@@ -46,6 +46,7 @@ struct prefix_info {
     uint8_t asp;               /* Address size prefix present */
     uint8_t rep;               /* Rep prefix present */
     uint8_t seg;               /* Segment override prefix present */
+    uint8_t wait;              /* WAIT "prefix" present */
     uint8_t lock;              /* Lock prefix present */
     uint8_t vex[3];            /* VEX prefix present */
     uint8_t vex_m;             /* VEX.M field */
@@ -370,6 +371,7 @@ static int matches(const struct itemplate *t, uint8_t *data,
     uint8_t *origdata = data;
     bool a_used = false, o_used = false;
     enum prefixes drep = 0;
+    enum prefixes dwait = 0;
     uint8_t lock = prefix->lock;
     int osize = prefix->osize;
     int asize = prefix->asize;
@@ -397,6 +399,8 @@ static int matches(const struct itemplate *t, uint8_t *data,
     else if (prefix->rep == 0xF3)
         drep = P_REP;
 
+    dwait = prefix->wait ? P_WAIT : 0;
+
     while ((c = *r++) != 0) {
        op1 = (c & 3) + ((opex & 1) << 2);
        op2 = ((c >> 3) & 3) + ((opex & 2) << 1);
@@ -840,6 +844,12 @@ static int matches(const struct itemplate *t, uint8_t *data,
        case 0340:
            return false;
 
+       case 0341:
+           if (prefix->wait != 0x9B)
+               return false;
+           dwait = 0;
+           break;
+
        case4(0344):
            ins->oprs[0].basereg = (*data++ >> 3) & 7;
            break;
@@ -919,6 +929,7 @@ static int matches(const struct itemplate *t, uint8_t *data,
            return false;
         ins->prefixes[PPS_LREP] = drep;
     }
+    ins->prefixes[PPS_WAIT] = dwait;
     if (!o_used) {
        if (osize != ((segsize == 16) ? 16 : 32)) {
            enum prefixes pfx = 0;
@@ -995,6 +1006,10 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
             prefix.rep = *data++;
            break;
 
+       case 0x9B:
+           prefix.wait = *data++;
+           break;
+
        case 0xF0:
             prefix.lock = *data++;
            break;
@@ -1173,41 +1188,11 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
      *      the return value is "sane."  Maybe a macro wrapper could
      *      be used for that purpose.
      */
-    for (i = 0; i < MAXPREFIX; i++)
-        switch (ins.prefixes[i]) {
-       case P_LOCK:
-           slen += snprintf(output + slen, outbufsize - slen, "lock ");
-           break;
-        case P_REP:
-            slen += snprintf(output + slen, outbufsize - slen, "rep ");
-            break;
-        case P_REPE:
-            slen += snprintf(output + slen, outbufsize - slen, "repe ");
-            break;
-        case P_REPNE:
-            slen += snprintf(output + slen, outbufsize - slen, "repne ");
-            break;
-        case P_A16:
-            slen += snprintf(output + slen, outbufsize - slen, "a16 ");
-            break;
-        case P_A32:
-            slen += snprintf(output + slen, outbufsize - slen, "a32 ");
-            break;
-        case P_A64:
-            slen += snprintf(output + slen, outbufsize - slen, "a64 ");
-            break;
-        case P_O16:
-            slen += snprintf(output + slen, outbufsize - slen, "o16 ");
-            break;
-        case P_O32:
-            slen += snprintf(output + slen, outbufsize - slen, "o32 ");
-            break;
-        case P_O64:
-            slen += snprintf(output + slen, outbufsize - slen, "o64 ");
-            break;
-       default:
-           break;
-        }
+    for (i = 0; i < MAXPREFIX; i++) {
+       const char *prefix = prefix_name(ins.prefixes[i]);
+       if (prefix)
+           slen += snprintf(output+slen, outbufsize-slen, "%s ", prefix);
+    }
 
     i = (*p)->opcode;
     if (i >= FIRST_COND_OPCODE)
index eab4e94..f99c926 100644 (file)
--- a/insns.dat
+++ b/insns.dat
@@ -328,7 +328,7 @@ FBLD                mem                             \1\xDF\204                                      8086,FPU
 FBSTP          mem80                           \1\xDF\206                                      8086,FPU
 FBSTP          mem                             \1\xDF\206                                      8086,FPU
 FCHS           void                            \2\xD9\xE0                                      8086,FPU
-FCLEX          void                            \3\x9B\xDB\xE2                                  8086,FPU
+FCLEX          void                            \341\2\xDB\xE2                                  8086,FPU
 FCMOVB         fpureg                          \1\xDA\10\xC0                                   P6,FPU
 FCMOVB         fpu0,fpureg                     \1\xDA\11\xC0                                   P6,FPU
 FCMOVB         void                            \2\xDA\xC1                                      P6,FPU,ND
@@ -372,7 +372,7 @@ FCOMP               void                            \2\xD8\xD9                                      8086,FPU,ND
 FCOMPP         void                            \2\xDE\xD9                                      8086,FPU
 FCOS           void                            \2\xD9\xFF                                      386,FPU
 FDECSTP                void                            \2\xD9\xF6                                      8086,FPU
-FDISI          void                            \3\x9B\xDB\xE1                                  8086,FPU
+FDISI          void                            \341\2\xDB\xE1                                  8086,FPU
 FDIV           mem32                           \1\xD8\206                                      8086,FPU
 FDIV           mem64                           \1\xDC\206                                      8086,FPU
 FDIV           fpureg|to                       \1\xDC\10\xF8                                   8086,FPU
@@ -394,7 +394,7 @@ FDIVRP              fpureg                          \1\xDE\10\xF0                                   8086,FPU
 FDIVRP         fpureg,fpu0                     \1\xDE\10\xF0                                   8086,FPU
 FDIVRP         void                            \2\xDE\xF1                                      8086,FPU,ND
 FEMMS          void                            \2\x0F\x0E                                      PENT,3DNOW
-FENI           void                            \3\x9B\xDB\xE0                                  8086,FPU
+FENI           void                            \341\2\xDB\xE0                                  8086,FPU
 FFREE          fpureg                          \1\xDD\10\xC0                                   8086,FPU
 FFREE          void                            \2\xDD\xC1                                      8086,FPU
 FFREEP         fpureg                          \1\xDF\10\xC0                                   286,FPU,UNDOC
@@ -415,7 +415,7 @@ FILD                mem64                           \1\xDF\205                                      8086,FPU
 FIMUL          mem32                           \1\xDA\201                                      8086,FPU
 FIMUL          mem16                           \1\xDE\201                                      8086,FPU
 FINCSTP                void                            \2\xD9\xF7                                      8086,FPU
-FINIT          void                            \3\x9B\xDB\xE3                                  8086,FPU
+FINIT          void                            \341\2\xDB\xE3                                  8086,FPU
 FIST           mem32                           \1\xDB\202                                      8086,FPU
 FIST           mem16                           \1\xDF\202                                      8086,FPU
 FISTP          mem32                           \1\xDB\203                                      8086,FPU
@@ -468,7 +468,7 @@ FPREM1              void                            \2\xD9\xF5                                      386,FPU
 FPTAN          void                            \2\xD9\xF2                                      8086,FPU
 FRNDINT                void                            \2\xD9\xFC                                      8086,FPU
 FRSTOR         mem                             \1\xDD\204                                      8086,FPU
-FSAVE          mem                             \2\x9B\xDD\206                                  8086,FPU
+FSAVE          mem                             \341\1\xDD\206                                  8086,FPU
 FSCALE         void                            \2\xD9\xFD                                      8086,FPU
 FSETPM         void                            \2\xDB\xE4                                      286,FPU
 FSIN           void                            \2\xD9\xFE                                      386,FPU
@@ -478,15 +478,15 @@ FST               mem32                           \1\xD9\202                                      8086,FPU
 FST            mem64                           \1\xDD\202                                      8086,FPU
 FST            fpureg                          \1\xDD\10\xD0                                   8086,FPU
 FST            void                            \2\xDD\xD1                                      8086,FPU,ND
-FSTCW          mem                             \2\x9B\xD9\207                                  8086,FPU,SW
-FSTENV         mem                             \2\x9B\xD9\206                                  8086,FPU
+FSTCW          mem                             \341\1\xD9\207                                  8086,FPU,SW
+FSTENV         mem                             \341\1\xD9\206                                  8086,FPU
 FSTP           mem32                           \1\xD9\203                                      8086,FPU
 FSTP           mem64                           \1\xDD\203                                      8086,FPU
 FSTP           mem80                           \1\xDB\207                                      8086,FPU
 FSTP           fpureg                          \1\xDD\10\xD8                                   8086,FPU
 FSTP           void                            \2\xDD\xD9                                      8086,FPU,ND
-FSTSW          mem                             \2\x9B\xDD\207                                  8086,FPU,SW
-FSTSW          reg_ax                          \3\x9B\xDF\xE0                                  286,FPU
+FSTSW          mem                             \341\1\xDD\207                                  8086,FPU,SW
+FSTSW          reg_ax                          \341\2\xDF\xE0                                  286,FPU
 FSUB           mem32                           \1\xD8\204                                      8086,FPU
 FSUB           mem64                           \1\xDC\204                                      8086,FPU
 FSUB           fpureg|to                       \1\xDC\10\xE8                                   8086,FPU
@@ -1295,8 +1295,7 @@ VERR              reg16                           \2\x0F\x00\204                                  286,PROT
 VERW           mem                             \2\x0F\x00\205                                  286,PROT
 VERW           mem16                           \2\x0F\x00\205                                  286,PROT
 VERW           reg16                           \2\x0F\x00\205                                  286,PROT
-WAIT           void                            \1\x9B                                          8086
-FWAIT          void                            \1\x9B                                          8086
+FWAIT          void                            \341                                            8086
 WBINVD         void                            \2\x0F\x09                                      486,PRIV
 WRSHR          rm32                            \321\2\x0F\x37\200                              P6,CYRIX,SMM
 WRMSR          void                            \2\x0F\x30                                      PENT,PRIV
diff --git a/nasm.h b/nasm.h
index 814019c..77c6aa4 100644 (file)
--- a/nasm.h
+++ b/nasm.h
@@ -612,6 +612,7 @@ enum prefixes {                     /* instruction prefixes */
     P_A16 = PREFIX_ENUM_START, P_A32, P_A64, P_ASP,
     P_LOCK, P_O16, P_O32, P_O64, P_OSP,
     P_REP, P_REPE, P_REPNE, P_REPNZ, P_REPZ, P_TIMES,
+    P_WAIT,
     PREFIX_ENUM_LIMIT
 };
 
@@ -673,6 +674,7 @@ typedef struct extop {          /* extended operand */
    Note that LOCK and REP are in the same slot.  This is
    an x86 architectural constraint. */
 enum prefix_pos {
+    PPS_WAIT,                  /* WAIT (technically not a prefix!) */
     PPS_LREP,                  /* Lock or REP prefix */
     PPS_SEG,                   /* Segment override prefix */
     PPS_OSIZE,                 /* Operand size prefix */
index 8796879..94c9dda 100644 (file)
--- a/nasmlib.c
+++ b/nasmlib.c
@@ -511,8 +511,8 @@ void standard_extension(char *inname, char *outname, char *extension,
  * Common list of prefix names
  */
 static const char *prefix_names[] = {
-    "a16", "a32", "lock", "o16", "o32", "rep", "repe", "repne",
-    "repnz", "repz", "times"
+    "a16", "a32", "a64", "asp", "lock", "o16", "o32", "o64", "osp",
+    "rep", "repe", "repne", "repnz", "repz", "times", "wait"
 };
 
 const char *prefix_name(int token)
index 6893c98..91b7abf 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -46,6 +46,8 @@ void parser_global_info(struct ofmt *output, struct location * locp)
 static int prefix_slot(enum prefixes prefix)
 {
     switch (prefix) {
+    case P_WAIT:
+       return PPS_WAIT;
     case R_CS:
     case R_DS:
     case R_SS:
index 128bc67..ff2946b 100644 (file)
@@ -18,6 +18,7 @@ repne
 repnz
 repz
 times
+wait
 
 % TOKEN_SPECIAL, 0, S_*
 abs