diff options
author | H. Peter Anvin <hpa@zytor.com> | 2008-05-21 11:05:39 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2008-05-21 11:05:39 -0700 |
commit | 2fb033af18c55d5e4412507b9a1bd513e8a6f2ff (patch) | |
tree | a96835d700178ff1ec1814dacd8bd1b46861c36a /disasm.c | |
parent | eb9e0938403b63e6478d6d874285a39e9984dbda (diff) | |
download | nasm-2fb033af18c55d5e4412507b9a1bd513e8a6f2ff.tar.gz |
Disassembler: select table based on VEX prefixes
We can use the new VEX prefixes to select into a large table of new
opcode spaces. Since the table is (currently) sparse, add logic so we
don't end up producing tons of empty tables for no good reason.
This is also necessary since VEX is likely to reuse opcode bytes that
would appear as prefixes at some point, which would cause conflicts
with the regular tables.
Diffstat (limited to 'disasm.c')
-rw-r--r-- | disasm.c | 15 |
1 files changed, 14 insertions, 1 deletions
@@ -1021,6 +1021,8 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, segover = NULL; origdata = data; + ix = itable; + end_prefix = false; while (!end_prefix) { switch (*data) { @@ -1028,9 +1030,11 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, case 0xF3: prefix.rep = *data++; break; + case 0xF0: prefix.lock = *data++; break; + case 0x2E: segover = "cs", prefix.seg = *data++; break; @@ -1049,6 +1053,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, case 0x65: segover = "gs", prefix.seg = *data++; break; + case 0x66: prefix.osize = (segsize == 16) ? 32 : 16; prefix.osp = *data++; @@ -1057,6 +1062,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, prefix.asize = (segsize == 32) ? 16 : 32; prefix.asp = *data++; break; + case 0xC4: case 0xC5: if (segsize == 64 || (data[1] & 0xc0) == 0xc0) { @@ -1078,8 +1084,11 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, prefix.vex_v = (~prefix.vex[1] >> 3) & 15; prefix.vex_lp = prefix.vex[1] & 7; } + + ix = itable_VEX[prefix.vex_m][prefix.vex_lp]; end_prefix = true; break; + case REX_P + 0x0: case REX_P + 0x1: case REX_P + 0x2: @@ -1103,6 +1112,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, } end_prefix = true; break; + default: end_prefix = true; break; @@ -1113,8 +1123,11 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, best_p = NULL; best_pref = INT_MAX; + if (!ix) + return 0; /* No instruction table at all... */ + dp = data; - ix = itable + *dp++; + ix += *dp++; while (ix->n == -1) { ix = (const struct disasm_index *)ix->p + *dp++; } |