From c2acf7b047492a6d1cbc4ac3aeafc3812fdcc46b Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sat, 21 Feb 2009 18:22:56 -0800 Subject: [PATCH] BR 2592476: Treat WAIT as a prefix even though it's really an instruction 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 | 12 ++++++++++++ disasm.c | 55 ++++++++++++++++++++----------------------------------- insns.dat | 21 ++++++++++----------- nasm.h | 2 ++ nasmlib.c | 4 ++-- parser.c | 2 ++ tokens.dat | 1 + 7 files changed, 49 insertions(+), 48 deletions(-) diff --git a/assemble.c b/assemble.c index 2668857a..ad7ea706 100644 --- a/assemble.c +++ b/assemble.c @@ -100,6 +100,7 @@ * \336-\337 are still listed as prefixes in the disassembler. * \340 - reserve 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; diff --git a/disasm.c b/disasm.c index c320f906..63fd37be 100644 --- 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) diff --git a/insns.dat b/insns.dat index eab4e94d..f99c9264 100644 --- 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 814019c6..77c6aa48 100644 --- 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 */ diff --git a/nasmlib.c b/nasmlib.c index 8796879e..94c9ddac 100644 --- 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) diff --git a/parser.c b/parser.c index 6893c981..91b7abf5 100644 --- 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: diff --git a/tokens.dat b/tokens.dat index 128bc670..ff2946be 100644 --- a/tokens.dat +++ b/tokens.dat @@ -18,6 +18,7 @@ repne repnz repz times +wait % TOKEN_SPECIAL, 0, S_* abs -- 2.11.4.GIT