summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-02-21 18:22:56 -0800
committerH. Peter Anvin <hpa@zytor.com>2009-02-21 18:22:56 -0800
commitc2acf7b047492a6d1cbc4ac3aeafc3812fdcc46b (patch)
treeb1459da6cf2de42b60b68f3b68f6192fd1840921
parentf8ad53216f09f731cc9440fd599b64eb9ce433d8 (diff)
downloadnasm-c2acf7b047492a6d1cbc4ac3aeafc3812fdcc46b.tar.gz
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.
-rw-r--r--assemble.c12
-rw-r--r--disasm.c55
-rw-r--r--insns.dat21
-rw-r--r--nasm.h2
-rw-r--r--nasmlib.c4
-rw-r--r--parser.c2
-rw-r--r--tokens.dat1
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 <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;
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