summaryrefslogtreecommitdiff
path: root/insns.pl
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-05-20 11:23:18 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-05-20 11:23:18 -0700
commit70a13f5a3701faa71bd2b28390dff622d71c62a6 (patch)
tree4f31e4fc6c2b886cbddba31b9d62e44a87238197 /insns.pl
parentd82dd4f1a38e20b0262f184f492fcb87308ec464 (diff)
downloadnasm-70a13f5a3701faa71bd2b28390dff622d71c62a6.tar.gz
nasm-70a13f5a3701faa71bd2b28390dff622d71c62a6.tar.bz2
nasm-70a13f5a3701faa71bd2b28390dff622d71c62a6.zip
insns.pl: support operands that serve double duty
Sometimes assembly syntax wants to permit a single operand to serve multiple functions; allow this. The disassembler could really use to be smarter about those.
Diffstat (limited to 'insns.pl')
-rw-r--r--insns.pl15
1 files changed, 13 insertions, 2 deletions
diff --git a/insns.pl b/insns.pl
index 713a416..6b6375e 100644
--- a/insns.pl
+++ b/insns.pl
@@ -491,6 +491,9 @@ sub startseq($) {
# i = immediate
# s = register field of is4/imz2 field
#
+# For an operand that should be filled into more than one field,
+# enter it as e.g. "r+v".
+#
sub byte_code_compile($) {
my($str) = @_;
my $opr;
@@ -509,8 +512,14 @@ sub byte_code_compile($) {
$opc = "\L$str";
}
+ my $op = 0;
for ($i = 0; $i < length($opr); $i++) {
- $oppos{substr($opr,$i,1)} = $i;
+ my $c = substr($opr,$i,1);
+ if ($c eq '+') {
+ $op--;
+ } else {
+ $oppos{$c} = $op++;
+ }
}
$prefix_ok = 1;
@@ -597,7 +606,9 @@ sub byte_code_compile($) {
} elsif ($oq =~ /^m([0-9]+)$/) {
$m = $1+0;
} elsif ($oq eq 'nds' || $oq eq 'ndd') {
- return undef if (!defined($oppos{'v'}));
+ if (!defined($oppos{'v'})) {
+ die "$0: $line: vex.$oq without 'v' operand\n";
+ }
} else {
die "$0: $line: undefined VEX subcode: $oq\n";
}