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.
This commit is contained in:
H. Peter Anvin 2009-02-21 18:22:56 -08:00
parent f8ad53216f
commit c2acf7b047
7 changed files with 49 additions and 48 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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

2
nasm.h
View File

@ -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 */

View File

@ -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)

View File

@ -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:

View File

@ -18,6 +18,7 @@ repne
repnz
repz
times
wait
% TOKEN_SPECIAL, 0, S_*
abs