Commit 4db48824 authored by Andy Polyakov's avatar Andy Polyakov
Browse files

perlasm/x86* update: support for 3 and 4 argument instructions.

parent 6786f52a
Loading
Loading
Loading
Loading
+18 −20
Original line number Diff line number Diff line
@@ -627,44 +627,42 @@ while($line=<>) {

    undef $label;
    undef $opcode;
    undef $dst;
    undef $src;
    undef $sz;
    undef @args;

    if ($label=label->re(\$line))	{ print $label->out(); }

    if (directive->re(\$line)) {
	printf "%s",directive->out();
    } elsif ($opcode=opcode->re(\$line)) { ARGUMENT: {
    } elsif ($opcode=opcode->re(\$line)) { ARGUMENT: while (1) {
	my $arg;

	if ($src=register->re(\$line))	{ opcode->size($src->size()); }
	elsif ($src=const->re(\$line))	{ }
	elsif ($src=ea->re(\$line))	{ }
	elsif ($src=expr->re(\$line))	{ }
	if ($arg=register->re(\$line))	{ opcode->size($arg->size()); }
	elsif ($arg=const->re(\$line))	{ }
	elsif ($arg=ea->re(\$line))	{ }
	elsif ($arg=expr->re(\$line))	{ }
	else				{ last ARGUMENT; }

	last ARGUMENT if ($line !~ /^,/);

	$line = substr($line,1); $line =~ s/^\s+//;
	push @args,$arg;

	if ($dst=register->re(\$line))	{ opcode->size($dst->size()); }
	elsif ($dst=const->re(\$line))	{ }
	elsif ($dst=ea->re(\$line))	{ }
	last ARGUMENT if ($line !~ /^,/);

	$line =~ s/^,\s*//;
	} # ARGUMENT:

	$sz=opcode->size();

	if (defined($dst)) {
	if ($#args>=0) {
	    my $insn;
	    if ($gas) {
		printf "\t%s\t%s,%s",	$opcode->out($dst->size()),
					$src->out($sz),$dst->out($sz);
		$insn = $opcode->out($#args>=1?$args[$#args]->size():$sz);
	    } else {
		$insn = $opcode->out();
		@args = reverse(@args);
		undef $sz if ($nasm && $opcode->mnemonic() eq "lea");
		printf "\t%s\t%s,%s",	$opcode->out(),
					$dst->out($sz),$src->out($sz);
	    }
	} elsif (defined($src)) {
	    printf "\t%s\t%s",$opcode->out(),$src->out($sz);
	    for (@args) { $_ = $_->out($sz); }
	    printf "\t%s\t%s", $insn, join(",",@args);
	} else {
	    printf "\t%s",$opcode->out();
	}
+3 −6
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ $i386=0;
sub ::AUTOLOAD
{ my $opcode = $AUTOLOAD;

    die "more than 2 arguments passed to $opcode" if ($#_>1);
    die "more than 4 arguments passed to $opcode" if ($#_>3);

    $opcode =~ s/.*:://;
    if    ($opcode =~ /^push/) { $stack+=4; }
@@ -66,8 +66,8 @@ sub ::rotr { &ror(@_); }
sub ::exch	{ &xchg(@_);	}
sub ::halt	{ &hlt;		}
sub ::movz	{ &movzx(@_);	}
sub ::pushf	{ &::pushfd;	}
sub ::popf	{ &::popfd;	}
sub ::pushf	{ &pushfd;	}
sub ::popf	{ &popfd;	}

# 3 argument instructions
sub ::movq
@@ -79,9 +79,6 @@ sub ::movq
    else
    {	&::generic("movq",@_);			}
}
sub ::pshufw	{ &::emit("pshufw",@_); }
sub ::shld	{ &::emit("shld",@_);   }
sub ::shrd	{ &::emit("shrd",@_);   }

# label management
$lbdecor="L";		# local label decoration, set by package
+12 −29
Original line number Diff line number Diff line
@@ -25,24 +25,20 @@ sub opsize()
# expand opcode with size suffix;
# prefix numeric constants with $;
sub ::generic
{ my($opcode,$dst,$src)=@_;
  my($tmp,$suffix,@arg);

    if (defined($src))
    {	$src =~ s/^(e?[a-dsixphl]{2})$/%$1/o;
	$src =~ s/^(x?mm[0-7])$/%$1/o;
	$src =~ s/^(\-?[0-9]+)$/\$$1/o;
	$src =~ s/^(\-?0x[0-9a-f]+)$/\$$1/o;
	push(@arg,$src);
    }
    if (defined($dst))
    {	$dst =~ s/^(\*?)(e?[a-dsixphl]{2})$/$1%$2/o;
	$dst =~ s/^(x?mm[0-7])$/%$1/o;
	$dst =~ s/^(\-?[0-9]+)$/\$$1/o		if(!defined($src));
	$dst =~ s/^(\-?0x[0-9a-f]+)$/\$$1/o	if(!defined($src));
	push(@arg,$dst);
{ my($opcode,@arg)=@_;
  my($suffix,$dst,$src);

    @arg=reverse(@arg);

    for (@arg)
    {	s/^(\*?)(e?[a-dsixphl]{2})$/$1%$2/o;	# gp registers
	s/^([xy]?mm[0-7])$/%$1/o;		# xmm/mmx registers
	s/^(\-?[0-9]+)$/\$$1/o;			# constants
	s/^(\-?0x[0-9a-f]+)$/\$$1/o;		# constants
    }

    $dst = $arg[$#arg]		if ($#arg>=0);
    $src = $arg[$#arg-1]	if ($#arg>=1);
    if    ($dst =~ m/^%/o)	{ $suffix=&opsize($dst); }
    elsif ($src =~ m/^%/o)	{ $suffix=&opsize($src); }
    else			{ $suffix="l";           }
@@ -71,19 +67,6 @@ sub ::jmp_ptr { &::generic("jmp","*$_[0]"); }

*::bswap = sub	{ &::emit("bswap","%$_[0]");	} if (!$::i386);

*::pshufw = sub
{ my($dst,$src,$magic)=@_;
    &::emit("pshufw","\$$magic","%$src","%$dst");
};
*::shld = sub
{ my($dst,$src,$bits)=@_;
    &::emit("shldl",$bits eq "cl"?"%cl":"\$$bits","%$src","%$dst");
};
*::shrd = sub
{ my($dst,$src,$bits)=@_;
    &::emit("shrdl",$bits eq "cl"?"%cl":"\$$bits","%$src","%$dst");
};

sub ::DWP
{ my($addr,$reg1,$reg2,$idx)=@_;
  my $ret="";
+1 −2
Original line number Diff line number Diff line
@@ -14,8 +14,7 @@ sub ::generic
{ my ($opcode,@arg)=@_;

    # fix hexadecimal constants
    $arg[0] =~ s/0x([0-9a-f]+)/0$1h/oi	if (defined($arg[0]));
    $arg[1] =~ s/0x([0-9a-f]+)/0$1h/oi	if (defined($arg[1]));
    for (@arg) { s/0x([0-9a-f]+)/0$1h/oi; }

    # fix xmm references
    $arg[0] =~ s/\b[A-Z]+WORD\s+PTR/XMMWORD PTR/i if ($arg[1]=~/\bxmm[0-7]\b/i);