mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-02-17 17:19:35 +08:00
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:
parent
f8ad53216f
commit
c2acf7b047
12
assemble.c
12
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;
|
||||
|
55
disasm.c
55
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)
|
||||
|
21
insns.dat
21
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
|
||||
|
2
nasm.h
2
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 */
|
||||
|
@ -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)
|
||||
|
2
parser.c
2
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:
|
||||
|
@ -18,6 +18,7 @@ repne
|
||||
repnz
|
||||
repz
|
||||
times
|
||||
wait
|
||||
|
||||
% TOKEN_SPECIAL, 0, S_*
|
||||
abs
|
||||
|
Loading…
Reference in New Issue
Block a user