summaryrefslogtreecommitdiff
path: root/disasm.c
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 /disasm.c
parentf8ad53216f09f731cc9440fd599b64eb9ce433d8 (diff)
downloadnasm-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.c55
1 files changed, 20 insertions, 35 deletions
diff --git a/disasm.c b/disasm.c
index c320f90..63fd37b 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)