insns: drop special handling of conditional instructions

Instead of handling conditional instructions ad hoc, generate
individual instruction patterns as normal. This simplifies the code
and makes CMPccXADD support simpler (otherwise it would be necessary
to hack in the handling of a condition code in the middle of an
instruction.)

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin 2022-11-12 12:26:28 -08:00
parent 5fd5426832
commit a2eabbe1d7
10 changed files with 175 additions and 187 deletions

View File

@ -304,17 +304,17 @@ doc/warnings.src : doc/warnings.src.time
@: Side effect
# Assembler token hash
asm/tokhash.c: x86/insns.dat x86/regs.dat asm/tokens.dat asm/tokhash.pl \
asm/tokhash.c: x86/insns.dat x86/insnsn.c asm/tokens.dat asm/tokhash.pl \
perllib/phash.ph
$(RUNPERL) $(srcdir)/asm/tokhash.pl c \
$(srcdir)/x86/insns.dat $(srcdir)/x86/regs.dat \
x86/insnsn.c $(srcdir)/x86/regs.dat \
$(srcdir)/asm/tokens.dat > asm/tokhash.c
# Assembler token metadata
asm/tokens.h: x86/insns.dat x86/regs.dat asm/tokens.dat asm/tokhash.pl \
asm/tokens.h: x86/insns.dat x86/insnsn.c asm/tokens.dat asm/tokhash.pl \
perllib/phash.ph
$(RUNPERL) $(srcdir)/asm/tokhash.pl h \
$(srcdir)/x86/insns.dat $(srcdir)/x86/regs.dat \
x86/insnsn.c $(srcdir)/x86/regs.dat \
$(srcdir)/asm/tokens.dat > asm/tokens.h
# Preprocessor token hash

View File

@ -234,7 +234,7 @@ x86\regs.h: x86\regs.dat x86\regs.pl
WARNFILES = asm\warnings.c include\warnings.h doc\warnings.src
warnings:
$(RM_F) $(WARNFILES)
$(RM_F) $(WARNFILES) $(WARNFILES:=.time)
$(MAKE) asm\warnings.time
asm\warnings.time: $(ALLOBJ_NW:.$(O)=.c)
@ -263,17 +263,17 @@ doc\warnings.src : doc\warnings.src.time
@: Side effect
# Assembler token hash
asm\tokhash.c: x86\insns.dat x86\regs.dat asm\tokens.dat asm\tokhash.pl \
asm\tokhash.c: x86\insns.dat x86\insnsn.c asm\tokens.dat asm\tokhash.pl \
perllib\phash.ph
$(RUNPERL) $(srcdir)\asm\tokhash.pl c \
$(srcdir)\x86\insns.dat $(srcdir)\x86\regs.dat \
x86\insnsn.c $(srcdir)\x86\regs.dat \
$(srcdir)\asm\tokens.dat > asm\tokhash.c
# Assembler token metadata
asm\tokens.h: x86\insns.dat x86\regs.dat asm\tokens.dat asm\tokhash.pl \
asm\tokens.h: x86\insns.dat x86\insnsn.c asm\tokens.dat asm\tokhash.pl \
perllib\phash.ph
$(RUNPERL) $(srcdir)\asm\tokhash.pl h \
$(srcdir)\x86\insns.dat $(srcdir)\x86\regs.dat \
x86\insnsn.c $(srcdir)\x86\regs.dat \
$(srcdir)\asm\tokens.dat > asm\tokens.h
# Preprocessor token hash

View File

@ -247,7 +247,7 @@ x86\regs.h: x86\regs.dat x86\regs.pl
WARNFILES = asm\warnings.c include\warnings.h doc\warnings.src
warnings:
$(RM_F) $(WARNFILES)
$(RM_F) $(WARNFILES) $(WARNFILES:=.time)
$(MAKE) asm\warnings.time
asm\warnings.time: $(ALLOBJ_NW:.$(O)=.c)
@ -276,17 +276,17 @@ doc\warnings.src : doc\warnings.src.time
@: Side effect
# Assembler token hash
asm\tokhash.c: x86\insns.dat x86\regs.dat asm\tokens.dat asm\tokhash.pl &
asm\tokhash.c: x86\insns.dat x86\insnsn.c asm\tokens.dat asm\tokhash.pl &
perllib\phash.ph
$(RUNPERL) $(srcdir)\asm\tokhash.pl c &
$(srcdir)\x86\insns.dat $(srcdir)\x86\regs.dat &
x86\insnsn.c $(srcdir)\x86\regs.dat &
$(srcdir)\asm\tokens.dat > asm\tokhash.c
# Assembler token metadata
asm\tokens.h: x86\insns.dat x86\regs.dat asm\tokens.dat asm\tokhash.pl &
asm\tokens.h: x86\insns.dat x86\insnsn.c asm\tokens.dat asm\tokhash.pl &
perllib\phash.ph
$(RUNPERL) $(srcdir)\asm\tokhash.pl h &
$(srcdir)\x86\insns.dat $(srcdir)\x86\regs.dat &
x86\insnsn.c $(srcdir)\x86\regs.dat &
$(srcdir)\asm\tokens.dat > asm\tokens.h
# Preprocessor token hash

View File

@ -146,8 +146,6 @@
* \325 nohi instruction which always uses spl/bpl/sil/dil
* \326 nof3 instruction not valid with 0xF3 REP prefix. Hint for
disassembler only; for SSE instructions.
* \330 a literal byte follows in the code stream, to be added
* to the condition code value of the instruction.
* \331 norep instruction not valid with REP prefix. Hint for
* disassembler only; for SSE instructions.
* \332 f2i REP prefix (0xF2 byte) used as opcode extension.
@ -1472,10 +1470,6 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
case 0326:
break;
case 0330:
codes++, length++;
break;
case 0331:
break;
@ -2188,10 +2182,6 @@ static void gencode(struct out_data *data, insn *ins)
case 0326:
break;
case 0330:
out_rawbyte(data, *codes++ ^ get_cond_opcode(ins->condition));
break;
case 0331:
break;

View File

@ -748,7 +748,6 @@ restart_parse:
}
result->opcode = tokval.t_integer;
result->condition = tokval.t_inttwo;
/*
* INCBIN cannot be satisfied with incorrectly

View File

@ -40,7 +40,7 @@
require 'phash.ph';
my($output, $insns_dat, $regs_dat, $tokens_dat) = @ARGV;
my($output, $insnsn_c, $regs_dat, $tokens_dat) = @ARGV;
%tokens = ();
@tokendata = ();
@ -53,33 +53,18 @@ my($output, $insns_dat, $regs_dat, $tokens_dat) = @ARGV;
'nle', 'no', 'np', 'ns', 'nz', 'o', 'p', 'pe', 'po', 's', 'z');
#
# Read insns.dat
# Read insnsn.c
#
open(ID, '<', $insns_dat) or die "$0: cannot open $insns_dat: $!\n";
open(ID, '<', $insnsn_c) or die "$0: cannot open $insnsn_c: $!\n";
while (defined($line = <ID>)) {
if ($line =~ /^([\?\@A-Z0-9_]+)(|cc)\s/) {
$insn = $1.$2;
($token = $1) =~ tr/A-Z/a-z/;
next unless ($line =~ /^\s*\"([\?\@a-z0-9_]+)\"/);
if ($2 eq '') {
# Single instruction token
if (!defined($tokens{$token})) {
$tokens{$token} = scalar @tokendata;
push(@tokendata, "\"${token}\", ".length($token).
", TOKEN_INSN, C_none, 0, I_${insn}");
}
} else {
# Conditional instruction
foreach $cc (@conditions) {
my $etok = $token.$cc;
if (!defined($tokens{$etok})) {
$tokens{$etok} = scalar @tokendata;
push(@tokendata, "\"${etok}\", ".length($etok).
", TOKEN_INSN, C_\U$cc\E, 0, I_${insn}");
}
}
}
}
my $token = $1;
next if (defined($tokens{$token})); # This should never happen
$tokens{$token} = scalar @tokendata;
push(@tokendata, "\"${token}\", ".length($token).
", TOKEN_INSN, 0, 0, I_\U${token}");
}
close(ID);

View File

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 1996-2012 The NASM Authors - All Rights Reserved
* Copyright 1996-2022 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@ -506,7 +506,6 @@ static int matches(const struct itemplate *t, uint8_t *data,
ins->oprs[i].segment = ins->oprs[i].disp_size =
(segsize == 64 ? SEG_64BIT : segsize == 32 ? SEG_32BIT : 0);
}
ins->condition = -1;
ins->evex_tuple = 0;
ins->rex = prefix->rex;
memset(ins->prefixes, 0, sizeof ins->prefixes);
@ -957,16 +956,6 @@ static int matches(const struct itemplate *t, uint8_t *data,
ins->rex |= REX_NH;
break;
case 0330:
{
int t = *r++, d = *data++;
if (d < t || d > t + 15)
return 0;
else
ins->condition = d - t;
break;
}
case 0326:
if (prefix->rep == 0xF3)
return 0;
@ -1126,12 +1115,6 @@ static int matches(const struct itemplate *t, uint8_t *data,
return data - origdata;
}
/* Condition names for disassembly, sorted by x86 code */
static const char * const condition_name[16] = {
"o", "no", "c", "nc", "z", "nz", "na", "a",
"s", "ns", "pe", "po", "l", "nl", "ng", "g"
};
int32_t disasm(uint8_t *data, int32_t data_size, char *output, int outbufsize, int segsize,
int64_t offset, int autosync, iflag_t *prefer)
{
@ -1424,12 +1407,8 @@ int32_t disasm(uint8_t *data, int32_t data_size, char *output, int outbufsize, i
}
i = (*p)->opcode;
if (i >= FIRST_COND_OPCODE)
slen += snprintf(output + slen, outbufsize - slen, "%s%s",
nasm_insn_names[i], condition_name[ins.condition]);
else
slen += snprintf(output + slen, outbufsize - slen, "%s",
nasm_insn_names[i]);
slen += snprintf(output + slen, outbufsize - slen, "%s",
nasm_insn_names[i]);
colon = false;
is_evex = !!(ins.rex & REX_EV);

View File

@ -523,13 +523,6 @@ static inline bool is_register(int reg)
return reg >= EXPR_REG_START && reg < REG_ENUM_LIMIT;
}
enum ccode { /* condition code names */
C_A, C_AE, C_B, C_BE, C_C, C_E, C_G, C_GE, C_L, C_LE, C_NA, C_NAE,
C_NB, C_NBE, C_NC, C_NE, C_NG, C_NGE, C_NL, C_NLE, C_NO, C_NP,
C_NS, C_NZ, C_O, C_P, C_PE, C_PO, C_S, C_Z,
C_none = -1
};
/*
* token flags
*/
@ -540,17 +533,6 @@ enum ccode { /* condition code names */
#define TFLAG_WARN (1 << 3) /* warning only, treat as ID */
#define TFLAG_DUP (1 << 4) /* valid ID but also has context-specific use */
static inline uint8_t get_cond_opcode(enum ccode c)
{
static const uint8_t ccode_opcodes[] = {
0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xf, 0xd, 0xc, 0xe, 0x6, 0x2,
0x3, 0x7, 0x3, 0x5, 0xe, 0xc, 0xd, 0xf, 0x1, 0xb, 0x9, 0x5,
0x0, 0xa, 0xa, 0xb, 0x8, 0x4
};
return ccode_opcodes[(int)c];
}
/*
* REX flags
*/
@ -766,7 +748,6 @@ typedef struct insn { /* an instruction itself */
char *label; /* the label defined, or NULL */
int prefixes[MAXPREFIX]; /* instruction prefixes, if any */
enum opcode opcode; /* the opcode - not just the string */
enum ccode condition; /* the condition code, if Jcc/SETcc */
int operands; /* how many operands? 0-3 (more if db et al) */
int addr_size; /* address size */
operand oprs[MAX_OPERANDS]; /* the operands, defined as above */

View File

@ -98,8 +98,10 @@ if_("AMXTILE", "AMX tile configuration instructions");
if_("AMXBF16", "AMX bfloat16 multiplication");
if_("AMXINT8", "AMX 8-bit integer multiplication");
if_("FRED", "Flexible Return and Exception Delivery (FRED)");
if_("RAOINT", "Remote atomic operations (RAO-INT)");
if_("UINTR", "User interrupts");
# Put these last [hpa: why?]
# Put these last to minimize their relevance
if_("OBSOLETE", "Instruction removed from architecture");
if_("NEVER", "Instruction never implemented");
if_("NOP", "Instruction is always a (nonintentional) NOP");

View File

@ -59,10 +59,115 @@ for ($c = 0; $c < $vex_classes; $c++) {
}
}
}
@disasm_prefixes = (@vexlist, @disasm_prefixes);
@disasm_prefixes = (@vexlist, @disasm_prefixes, '');
%disasm_prefixes = map { $_ => 1 } @disasm_prefixes;
@bytecode_count = (0) x 256;
# Push to an array reference, creating the array if needed
sub xpush($@) {
my $ref = shift @_;
$$ref = [] unless (defined($$ref));
return push(@$$ref, @_);
}
# Generate relaxed form patterns if applicable
sub relaxed_forms(@) {
my @field_list = @_;
foreach my $fields (@_) {
next unless ($fields->[1] =~ /\*/);
# This instruction has relaxed form(s)
if ($fields->[2] !~ /^\[/) {
warn "$fname:$line: has an * operand but uses raw bytecodes\n";
next;
}
my $opmask = 0;
my @ops = split(/,/, $fields->[1]);
for (my $oi = 0; $oi < scalar @ops; $oi++) {
if ($ops[$oi] =~ /\*$/) {
if ($oi == 0) {
warn "$fname:$line: has a first operand with a *\n";
next;
}
$opmask |= 1 << $oi;
}
}
for (my $oi = 1; $oi < (1 << scalar @ops); $oi++) {
if (($oi & ~$opmask) == 0) {
my @xops = ();
my $omask = ~$oi;
for ($oj = 0; $oj < scalar(@ops); $oj++) {
if ($omask & 1) {
push(@xops, $ops[$oj]);
}
$omask >>= 1;
}
my @ff = @$fields;
$ff[1] = join(',', @xops);
$ff[4] = $oi;
push(@field_list, [@ff]);
}
}
}
return @field_list;
}
# Condition codes used by the disassembler
my %condd = ( 'o' => 0, 'no' => 1, 'c' => 2, 'nc' => 3,
'z' => 4, 'nz' => 5, 'na' => 6, 'a' => 7,
's' => 8, 'ns' => 9, 'pe' => 10, 'po' => 11,
'l' => 12, 'nl' => 13, 'ng' => 14, 'g' => 15 );
# All condition code aliases
my %conds = ( %condd,
'ae' => 3, 'b' => 2, 'be' => 6, 'e' => 4,
'ge' => 13, 'le' => 14, 'nae' => 2, 'nb' => 3,
'nbe' => 7, 'ne' => 5, 'nge' => 12, 'nle' => 15,
'np' => 11, 'p' => 10 );
# Generate conditional form patterns if applicable
sub conditional_forms(@) {
my @field_list = ();
foreach my $fields (@_) {
# This is a case sensitive match!
if ($fields->[0] !~ /cc/) {
push(@field_list, $fields);
next;
}
if ($fields->[2] !~ /^\[/) {
warn "$fname:$line: conditional instruction using raw bytecodes\n";
next;
}
foreach my $cc (keys(%conds)) {
my @ff = @$fields;
$ff[0] =~ s/cc/\U$cc/;
unless ($ff[2] =~ /^(\[.*?)\b([0-9a-f]{2})\+c\b(.*\])$/) {
warn "$fname:$line: invalid conditional encoding";
next;
}
$ff[2] = $1.sprintf('%02x', hex($2)^$conds{$cc}).$3;
unless (defined($condd{$cc}) || $ff[3] =~ /\bND\b/) {
$ff[3] .= ',ND';
}
push(@field_list, [@ff]);
}
}
return @field_list;
}
print STDERR "Reading insns.dat...\n";
@args = ();
@ -86,10 +191,13 @@ open(F, '<', $fname) || die "unable to open $fname";
%dinstables = ();
@bytecode_list = ();
%aname = ();
$line = 0;
$insns = 0;
$n_opcodes = $n_opcodes_cc = 0;
$n_opcodes = 0;
my @allpatterns = ();
while (<F>) {
$line++;
chomp;
@ -99,71 +207,24 @@ while (<F>) {
warn "line $line does not contain four fields\n";
next;
}
@fields = ($1, $2, $3, $4);
@field_list = ([@fields, 0]);
my @field_list = ([$1, $2, $3, $4, 0]);
@field_list = relaxed_forms(@field_list);
@field_list = conditional_forms(@field_list);
if ($fields[1] =~ /\*/) {
# This instruction has relaxed form(s)
if ($fields[2] !~ /^\[/) {
warn "line $line has an * operand but uses raw bytecodes\n";
next;
}
$opmask = 0;
@ops = split(/,/, $fields[1]);
for ($oi = 0; $oi < scalar @ops; $oi++) {
if ($ops[$oi] =~ /\*$/) {
if ($oi == 0) {
warn "line $line has a first operand with a *\n";
next;
}
$opmask |= 1 << $oi;
}
}
for ($oi = 1; $oi < (1 << scalar @ops); $oi++) {
if (($oi & ~$opmask) == 0) {
my @xops = ();
my $omask = ~$oi;
for ($oj = 0; $oj < scalar(@ops); $oj++) {
if ($omask & 1) {
push(@xops, $ops[$oj]);
}
$omask >>= 1;
}
push(@field_list, [$fields[0], join(',', @xops),
$fields[2], $fields[3], $oi]);
}
}
}
foreach $fptr (@field_list) {
@fields = @$fptr;
($formatted, $nd) = format_insn(@fields);
foreach my $fields (@field_list) {
($formatted, $nd) = format_insn(@$fields);
if ($formatted) {
$insns++;
$aname = "aa_$fields[0]";
push @$aname, $formatted;
}
if ( $fields[0] =~ /cc$/ ) {
# Conditional instruction
if (!defined($k_opcodes_cc{$fields[0]})) {
$k_opcodes_cc{$fields[0]} = $n_opcodes_cc++;
}
} else {
# Unconditional instruction
if (!defined($k_opcodes{$fields[0]})) {
$k_opcodes{$fields[0]} = $n_opcodes++;
}
xpush(\$aname{$fields->[0]}, $formatted);
}
if (!defined($k_opcodes{$fields->[0]})) {
$k_opcodes{$fields->[0]} = $n_opcodes++;
}
if ($formatted && !$nd) {
push @big, $formatted;
my @sseq = startseq($fields[2], $fields[4]);
foreach $i (@sseq) {
if (!defined($dinstables{$i})) {
$dinstables{$i} = [];
}
push(@{$dinstables{$i}}, $#big);
my @sseq = startseq($fields->[2], $fields->[4]);
foreach my $i (@sseq) {
xpush(\$dinstables{$i}, $#big);
}
}
}
@ -194,8 +255,7 @@ foreach $bl (@bytecode_list) {
}
undef @bytecode_list;
@opcodes = sort { $k_opcodes{$a} <=> $k_opcodes{$b} } keys(%k_opcodes);
@opcodes_cc = sort { $k_opcodes_cc{$a} <=> $k_opcodes_cc{$b} } keys(%k_opcodes_cc);
@opcodes = sort { $k_opcodes{$a} <=> $k_opcodes{$b} } keys(%k_opcodes);
if ( $output eq 'b') {
print STDERR "Writing $oname...\n";
@ -249,16 +309,15 @@ if ( $output eq 'a' ) {
print A "#include \"nasm.h\"\n";
print A "#include \"insns.h\"\n\n";
foreach $i (@opcodes, @opcodes_cc) {
foreach $i (@opcodes) {
print A "static const struct itemplate instrux_${i}[] = {\n";
$aname = "aa_$i";
foreach $j (@$aname) {
foreach $j (@{$aname{$i}}) {
print A " ", codesubst($j), "\n";
}
print A " ITEMPLATE_END\n};\n\n";
}
print A "const struct itemplate * const nasm_instructions[] = {\n";
foreach $i (@opcodes, @opcodes_cc) {
foreach $i (@opcodes) {
print A " instrux_${i},\n";
}
print A "};\n";
@ -286,7 +345,7 @@ if ( $output eq 'd' ) {
foreach $h (sort(keys(%dinstables))) {
next if ($h eq ''); # Skip pseudo-instructions
print D "\nstatic const struct itemplate * const itable_${h}[] = {\n";
print D "\nstatic const struct itemplate * const itable_${h}[] = {\n";
foreach $j (@{$dinstables{$h}}) {
print D " instrux + $j,\n";
}
@ -294,7 +353,7 @@ if ( $output eq 'd' ) {
}
@prefix_list = ();
foreach $h (@disasm_prefixes, '') {
foreach $h (@disasm_prefixes) {
for ($c = 0; $c < 256; $c++) {
$nn = sprintf("%s%02X", $h, $c);
if ($is_prefix{$nn} || defined($dinstables{$nn})) {
@ -315,10 +374,15 @@ if ( $output eq 'd' ) {
for ($c = 0; $c < 256; $c++) {
$nn = sprintf("%s%02X", $h, $c);
if ($is_prefix{$nn}) {
die "$fname:$line: ambiguous decoding of $nn\n"
if (defined($dinstables{$nn}));
if ($dinstables{$nn}) {
print STDERR "$fname: ambiguous decoding, prefix $nn aliases:\n";
foreach my $dc (@{$dinstables{$nn}}) {
print STDERR codesubst($big[$dc]), "\n";
}
exit 1;
}
printf D " /* 0x%02x */ { itable_%s, -1 },\n", $c, $nn;
} elsif (defined($dinstables{$nn})) {
} elsif ($dinstables{$nn}) {
printf D " /* 0x%02x */ { itable_%s, %u },\n", $c,
$nn, scalar(@{$dinstables{$nn}});
} else {
@ -362,10 +426,9 @@ if ( $output eq 'i' ) {
print I "#define NASM_INSNSI_H 1\n\n";
print I "enum opcode {\n";
$maxlen = 0;
foreach $i (@opcodes, @opcodes_cc) {
foreach $i (@opcodes) {
print I "\tI_${i},\n";
$len = length($i);
$len++ if ( $i =~ /cc$/ ); # Condition codes can be 3 characters long
$maxlen = $len if ( $len > $maxlen );
}
print I "\tI_none = -1\n";
@ -373,7 +436,6 @@ if ( $output eq 'i' ) {
print I "#define MAX_INSLEN ", $maxlen, "\n";
print I "#define NASM_VEX_CLASSES ", $vex_classes, "\n";
print I "#define NO_DECORATOR\t{", join(',',(0) x $MAX_OPERANDS), "}\n";
print I "#define FIRST_COND_OPCODE I_", $opcodes_cc[0], "\n\n";
print I "#endif /* NASM_INSNSI_H */\n";
close I;
@ -389,14 +451,9 @@ if ( $output eq 'n' ) {
print N "#include \"tables.h\"\n\n";
print N "const char * const nasm_insn_names[] = {";
$first = 1;
foreach $i (@opcodes, @opcodes_cc) {
print N "," if ( !$first );
$first = 0;
$ilower = $i;
$ilower =~ s/cc$//; # Remove conditional cc suffix
$ilower =~ tr/A-Z/a-z/; # Change to lower case (Perl 4 compatible)
print N "\n\t\"${ilower}\"";
foreach $i (@opcodes) {
print N "\n\t\"\L$i\"";
print N ',' if ($i < $#opcodes);
}
print N "\n};\n";
close N;
@ -658,7 +715,6 @@ sub hexstr(@) {
# instruction. We need only consider the codes:
# \[1234] mean literal bytes, of course
# \1[0123] mean byte plus register value
# \330 means byte plus condition code
# \0 or \340 mean give up and return empty set
# \34[4567] mean PUSH/POP of segment registers: special case
# \17[234] skip is4 control byte
@ -691,15 +747,16 @@ sub startseq($$) {
}
foreach $pfx (@disasm_prefixes) {
if (substr($fbs, 0, length($pfx)) eq $pfx) {
my $len = length($pfx);
if (substr($fbs, 0, $len) eq $pfx) {
$prefix = $pfx;
$fbs = substr($fbs, length($pfx));
$fbs = substr($fbs, $len, 2);
last;
}
}
if ($fbs ne '') {
return ($prefix.substr($fbs,0,2));
return ($prefix.$fbs);
}
unshift(@codes, $c0);
@ -707,8 +764,6 @@ sub startseq($$) {
return addprefix($prefix, $c1..($c1+7));
} elsif (($c0 & ~013) == 0144) {
return addprefix($prefix, $c1, $c1|2);
} elsif ($c0 == 0330) {
return addprefix($prefix, $c1..($c1+15));
} elsif ($c0 == 0 || $c0 == 0340) {
return $prefix;
} elsif (($c0 & ~3) == 0260 || $c0 == 0270 ||
@ -729,7 +784,7 @@ sub startseq($$) {
# and "ignorable" codes here
}
}
return $prefix;
return ();
}
# EVEX tuple types offset is 0300. e.g. 0301 is for full vector(fv).
@ -1090,9 +1145,6 @@ sub byte_code_compile($$) {
}
push(@codes, 0173, ($oppos{'s'} << 4) + $imm);
$prefix_ok = 0;
} elsif ($op =~ /^([0-9a-f]{2})\+c$/) {
push(@codes, 0330, hex $1);
$prefix_ok = 0;
} elsif ($op =~ /^([0-9a-f]{2})\+r$/) {
if (!defined($oppos{'r'})) {
die "$fname:$line: $op without 'r' operand\n";