diff options
-rw-r--r-- | disasm.c | 15 | ||||
-rw-r--r-- | insns.h | 1 | ||||
-rw-r--r-- | insns.pl | 46 |
3 files changed, 57 insertions, 5 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++; } @@ -32,6 +32,7 @@ struct disasm_index { /* Tables for the assembler and disassembler, respectively */ extern const struct itemplate * const nasm_instructions[]; extern const struct disasm_index itable[256]; +extern const struct disasm_index * const itable_VEX[32][8]; /* Common table for the byte codes */ extern const uint8_t nasm_bytecodes[]; @@ -14,6 +14,15 @@ # This should match MAX_OPERANDS from nasm.h $MAX_OPERANDS = 5; +# Add VEX prefixes +@vexlist = (); +for ($m = 0; $m < 32; $m++) { + for ($lp = 0; $lp < 8; $lp++) { + push(@vexlist, sprintf("VEX%02X%01X", $m, $lp)); + } +} +@disasm_prefixes = (@vexlist, @disasm_prefixes); + print STDERR "Reading insns.dat...\n"; @args = (); @@ -182,8 +191,20 @@ if ( !defined($output) || $output eq 'd' ) { print D "};\n"; } + @prefix_list = (); foreach $h (@disasm_prefixes, '') { - $is_prefix{$h} = 1; + for ($c = 0; $c < 256; $c++) { + $nn = sprintf("%s%02X", $h, $c); + if ($is_prefix{$nn} || defined($dinstables{$nn})) { + # At least one entry in this prefix table + push(@prefix_list, $h); + $is_prefix{$h} = 1; + last; + } + } + } + + foreach $h (@prefix_list) { print D "\n"; print D "static " unless ($h eq ''); print D "const struct disasm_index "; @@ -202,8 +223,23 @@ if ( !defined($output) || $output eq 'd' ) { printf D " { NULL, 0 },\n"; } } - print D "};\n"; + print D "};\n"; + } + + print D "\nconst struct disasm_index * const itable_VEX[32][8] = {\n"; + for ($m = 0; $m < 32; $m++) { + print D "\t{\n"; + for ($lp = 0; $lp < 8; $lp++) { + $vp = sprintf("VEX%02X%01X", $m, $lp); + if ($is_prefix{$vp}) { + printf D "\t\titable_%s,\n", $vp; + } else { + print D "\t\tNULL,\n"; + } + } + print D "\t},\n"; } + print D "};\n"; close D; } @@ -464,8 +500,10 @@ sub startseq($) { } elsif ($c0 == 0 || $c0 == 0340) { return $prefix; } elsif (($c0 & ~3) == 0260 || $c0 == 0270) { - shift(@codes); # Skip VEX control bytes - shift(@codes); + my $m,$wlp,$vxp; + $m = shift(@codes); + $wlp = shift(@codes); + $prefix .= sprintf('VEX%02X%01X', $m, $wlp & 7); } elsif ($c0 >= 0172 && $c0 <= 174) { shift(@codes); # Skip is4 control byte } else { |