diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-02-21 18:22:56 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-02-21 18:22:56 -0800 |
commit | c2acf7b047492a6d1cbc4ac3aeafc3812fdcc46b (patch) | |
tree | b1459da6cf2de42b60b68f3b68f6192fd1840921 /disasm.c | |
parent | f8ad53216f09f731cc9440fd599b64eb9ce433d8 (diff) | |
download | nasm-c2acf7b047492a6d1cbc4ac3aeafc3812fdcc46b.tar.gz nasm-c2acf7b047492a6d1cbc4ac3aeafc3812fdcc46b.tar.bz2 nasm-c2acf7b047492a6d1cbc4ac3aeafc3812fdcc46b.zip |
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.
Diffstat (limited to 'disasm.c')
-rw-r--r-- | disasm.c | 55 |
1 files changed, 20 insertions, 35 deletions
@@ -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) |