From: nasm-bot f. C. G. <gor...@gm...> - 2013-10-24 12:33:24
|
Commit-ID: 351838cd18eb2f7911ae3420438c95e689a8a1df Gitweb: http://repo.or.cz/w/nasm.git?a=commitdiff;h=351838cd18eb2f7911ae3420438c95e689a8a1df Author: Cyrill Gorcunov <gor...@gm...> AuthorDate: Mon, 7 Oct 2013 00:31:24 +0400 Committer: Cyrill Gorcunov <gor...@gm...> CommitDate: Mon, 14 Oct 2013 11:42:36 +0400 insns.pl: Start using instruction flags generator There are known problems FIXME'ed in the code Signed-off-by: Cyrill Gorcunov <gor...@gm...> --- Makefile.in | 9 +++-- assemble.c | 27 ++++++++------- disasm.c | 6 ++-- insns.h | 113 +++--------------------------------------------------------- insns.pl | 22 ++++++++---- 5 files changed, 46 insertions(+), 131 deletions(-) diff --git a/Makefile.in b/Makefile.in index e1846ce..b25b0e2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -83,10 +83,11 @@ NASM = nasm.$(O) nasmlib.$(O) ver.$(O) \ strfunc.$(O) tokhash.$(O) regvals.$(O) regflags.$(O) \ ilog2.$(O) \ lib/strlcpy.$(O) \ - preproc-nop.$(O) + preproc-nop.$(O) \ + iflag.$(O) NDISASM = ndisasm.$(O) disasm.$(O) sync.$(O) nasmlib.$(O) ver.$(O) \ - insnsd.$(O) insnsb.$(O) insnsn.$(O) regs.$(O) regdis.$(O) + insnsd.$(O) insnsb.$(O) insnsn.$(O) regs.$(O) regdis.$(O) iflag.$(O) #-- End File Lists --# all: nasm$(X) ndisasm$(X) nasm.1 ndisasm.1 rdf @@ -102,6 +103,10 @@ ndisasm$(X): $(NDISASM) $(XOBJS) # though, so it isn't necessary to have Perl just to recompile NASM # from the distribution. +insns.pl: insns-iflags.pl + +iflag.c iflag.h: insns.dat insns.pl + $(PERL) $(srcdir)/insns.pl -t $(srcdir)/insns.dat insnsb.c: insns.dat insns.pl $(PERL) $(srcdir)/insns.pl -b $(srcdir)/insns.dat insnsa.c: insns.dat insns.pl diff --git a/assemble.c b/assemble.c index a38e56e..249be31 100644 --- a/assemble.c +++ b/assemble.c @@ -1267,7 +1267,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits, } if (has_prefix(ins, PPS_LOCK, P_LOCK) && lockcheck && - (!(temp->flags & IF_LOCK) || !is_class(MEMORY, ins->oprs[0].type))) { + (!itemp_has(temp,IF_LOCK) || !is_class(MEMORY, ins->oprs[0].type))) { errfunc(ERR_WARNING | ERR_WARN_LOCK | ERR_PASS2 , "instruction is not lockable"); } @@ -1947,7 +1947,7 @@ static enum match_result find_match(const struct itemplate **tempp, else m = MERR_INVALOP; } else if (m == MERR_OPSIZEMISSING && - (temp->flags & IF_SMASK) != IF_SX) { + itemp_smask(temp) != IF_SMASK) { /* * Missing operand size and a candidate for fuzzy matching... */ @@ -2030,7 +2030,7 @@ static enum match_result matches(const struct itemplate *itemp, /* * Is it legal? */ - if (!(optimizing > 0) && (itemp->flags & IF_OPT)) + if (!(optimizing > 0) && itemp_has(itemp, IF_OPT)) return MERR_INVALOP; /* @@ -2043,7 +2043,7 @@ static enum match_result matches(const struct itemplate *itemp, /* * Process size flags */ - switch (itemp->flags & IF_SMASK) { + switch (itemp_smask(itemp)) { case IF_SB: asize = BITS8; break; @@ -2086,9 +2086,9 @@ static enum match_result matches(const struct itemplate *itemp, break; } - if (itemp->flags & IF_ARMASK) { + if (itemp_has(itemp, IF_ARMASK)) { /* S- flags only apply to a specific operand */ - i = ((itemp->flags & IF_ARMASK) >> IF_ARSHFT) - 1; + i = itemp_arg(itemp); memset(size, 0, sizeof size); size[i] = asize; } else { @@ -2149,7 +2149,7 @@ static enum match_result matches(const struct itemplate *itemp, } } else if (is_register(instruction->oprs[i].basereg) && nasm_regvals[instruction->oprs[i].basereg] >= 16 && - !(itemp->flags & IF_AVX512)) { + !itemp_has(itemp, IF_AVX512)) { return MERR_ENCMISMATCH; } } @@ -2160,8 +2160,8 @@ static enum match_result matches(const struct itemplate *itemp, /* * Check operand sizes */ - if (itemp->flags & (IF_SM | IF_SM2)) { - oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands); + if (itemp_has(itemp, IF_SM) || itemp_has(itemp, IF_SM2)) { + oprs = (itemp_has(itemp, IF_SM2) ? 2 : itemp->operands); for (i = 0; i < oprs; i++) { asize = itemp->opd[i] & SIZE_MASK; if (asize) { @@ -2182,20 +2182,21 @@ static enum match_result matches(const struct itemplate *itemp, /* * Check template is okay at the set cpu level + * FIXME */ - if (((itemp->flags & IF_PLEVEL) > cpu)) - return MERR_BADCPU; +// if (((itemp->flags & IF_PLEVEL) > cpu)) +// return MERR_BADCPU; /* * Verify the appropriate long mode flag. */ - if ((itemp->flags & (bits == 64 ? IF_NOLONG : IF_LONG))) + if (itemp_has(itemp, (bits == 64 ? IF_NOLONG : IF_LONG))) return MERR_BADMODE; /* * If we have a HLE prefix, look for the NOHLE flag */ - if ((itemp->flags & IF_NOHLE) && + if (itemp_has(itemp, IF_NOHLE) && (has_prefix(instruction, PPS_REP, P_XACQUIRE) || has_prefix(instruction, PPS_REP, P_XRELEASE))) return MERR_BADHLE; diff --git a/disasm.c b/disasm.c index 9a5f9ad..de50e5f 100644 --- a/disasm.c +++ b/disasm.c @@ -404,7 +404,7 @@ static int matches(const struct itemplate *t, uint8_t *data, ins->rex = prefix->rex; memset(ins->prefixes, 0, sizeof ins->prefixes); - if (t->flags & (segsize == 64 ? IF_NOLONG : IF_LONG)) + if (itemp_has(t, (segsize == 64 ? IF_NOLONG : IF_LONG))) return false; if (prefix->rep == 0xF2) @@ -1150,7 +1150,9 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, */ if (works) { int i, nprefix; - goodness = ((*p)->flags & IF_PFMASK) ^ prefer; + /* FIXME */ +// goodness = ((*p)->flags & IF_PFMASK) ^ prefer; + goodness = 0; nprefix = 0; for (i = 0; i < MAXPREFIX; i++) if (tmp_ins.prefixes[i]) diff --git a/insns.h b/insns.h index b12d4eb..5d39a97 100644 --- a/insns.h +++ b/insns.h @@ -11,6 +11,7 @@ #include "nasm.h" #include "tokens.h" +#include "iflag.h" /* if changed, ITEMPLATE_END should be also changed accordingly */ struct itemplate { @@ -19,7 +20,7 @@ struct itemplate { opflags_t opd[MAX_OPERANDS]; /* bit flags for operand types */ decoflags_t deco[MAX_OPERANDS]; /* bit flags for operand decorators */ const uint8_t *code; /* the code it assembles to */ - iflags_t flags; /* some flags */ + uint32_t iflag_idx; /* some flags referenced by index */ }; /* Disassembler table structure */ @@ -48,113 +49,9 @@ extern const uint8_t nasm_bytecodes[]; #define ITEMPLATE_END {-1,-1,{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1},NULL,0} /* - * Instruction template flags. These specify which processor - * targets the instruction is eligible for, whether it is - * privileged or undocumented, and also specify extra error - * checking on the matching of the instruction. - * - * IF_SM stands for Size Match: any operand whose size is not - * explicitly specified by the template is `really' intended to be - * the same size as the first size-specified operand. - * Non-specification is tolerated in the input instruction, but - * _wrong_ specification is not. - * - * IF_SM2 invokes Size Match on only the first _two_ operands, for - * three-operand instructions such as SHLD: it implies that the - * first two operands must match in size, but that the third is - * required to be _unspecified_. - * - * IF_SB invokes Size Byte: operands with unspecified size in the - * template are really bytes, and so no non-byte specification in - * the input instruction will be tolerated. IF_SW similarly invokes - * Size Word, and IF_SD invokes Size Doubleword. - * - * (The default state if neither IF_SM nor IF_SM2 is specified is - * that any operand with unspecified size in the template is - * required to have unspecified size in the instruction too...) - * - * iflags_t is defined to store these flags. + * FIXME This are to get rid off! */ - -#define IF_SM 0x00000001UL /* size match */ -#define IF_SM2 0x00000002UL /* size match first two operands */ -#define IF_SB 0x00000004UL /* unsized operands can't be non-byte */ -#define IF_SW 0x00000008UL /* unsized operands can't be non-word */ -#define IF_SD 0x0000000CUL /* unsized operands can't be non-dword */ -#define IF_SQ 0x00000010UL /* unsized operands can't be non-qword */ -#define IF_SO 0x00000014UL /* unsized operands can't be non-oword */ -#define IF_SY 0x00000018UL /* unsized operands can't be non-yword */ -#define IF_SZ 0x0000001CUL /* unsized operands can't be non-zword */ -#define IF_SIZE 0x00000038UL /* unsized operands must match the bitsize */ -#define IF_SX 0x0000003CUL /* unsized operands not allowed */ -#define IF_SMASK 0x0000003CUL /* mask for unsized argument size */ -#define IF_AR0 0x00000040UL /* SB, SW, SD applies to argument 0 */ -#define IF_AR1 0x00000080UL /* SB, SW, SD applies to argument 1 */ -#define IF_AR2 0x000000C0UL /* SB, SW, SD applies to argument 2 */ -#define IF_AR3 0x00000100UL /* SB, SW, SD applies to argument 3 */ -#define IF_AR4 0x00000140UL /* SB, SW, SD applies to argument 4 */ -#define IF_ARMASK 0x000001C0UL /* mask for unsized argument spec */ -#define IF_ARSHFT 6 /* LSB in IF_ARMASK */ -#define IF_OPT 0x00000200UL /* optimizing assembly only */ -/* The next 3 bits aren't actually used for anything */ -#define IF_PRIV 0x00000000UL /* it's a privileged instruction */ -#define IF_SMM 0x00000000UL /* it's only valid in SMM */ -#define IF_PROT 0x00000000UL /* it's protected mode only */ -#define IF_LOCK 0x00000400UL /* lockable if operand 0 is memory */ -#define IF_NOLONG 0x00000800UL /* it's not available in long mode */ -#define IF_LONG 0x00001000UL /* long mode instruction */ -#define IF_NOHLE 0x00002000UL /* HLE prefixes forbidden */ -/* These flags are currently not used for anything - intended for insn set */ -#define IF_UNDOC 0x8000000000UL /* it's an undocumented instruction */ -#define IF_HLE 0x4000000000UL /* HACK NEED TO REORGANIZE THESE BITS */ -#define IF_AVX512 0x2000000000UL /* it's an AVX-512F (512b) instruction */ -#define IF_FPU 0x0100000000UL /* it's an FPU instruction */ -#define IF_MMX 0x0200000000UL /* it's an MMX instruction */ -#define IF_3DNOW 0x0300000000UL /* it's a 3DNow! instruction */ -#define IF_SSE 0x0400000000UL /* it's a SSE (KNI, MMX2) instruction */ -#define IF_SSE2 0x0500000000UL /* it's a SSE2 instruction */ -#define IF_SSE3 0x0600000000UL /* it's a SSE3 (PNI) instruction */ -#define IF_VMX 0x0700000000UL /* it's a VMX instruction */ -#define IF_SSSE3 0x0800000000UL /* it's an SSSE3 instruction */ -#define IF_SSE4A 0x0900000000UL /* AMD SSE4a */ -#define IF_SSE41 0x0A00000000UL /* it's an SSE4.1 instruction */ -#define IF_SSE42 0x0B00000000UL /* HACK NEED TO REORGANIZE THESE BITS */ -#define IF_SSE5 0x0C00000000UL /* HACK NEED TO REORGANIZE THESE BITS */ -#define IF_AVX 0x0D00000000UL /* it's an AVX (128b) instruction */ -#define IF_AVX2 0x0E00000000UL /* it's an AVX2 (256b) instruction */ -#define IF_FMA 0x1000000000UL /* HACK NEED TO REORGANIZE THESE BITS */ -#define IF_BMI1 0x1100000000UL /* HACK NEED TO REORGANIZE THESE BITS */ -#define IF_BMI2 0x1200000000UL /* HACK NEED TO REORGANIZE THESE BITS */ -#define IF_TBM 0x1300000000UL /* HACK NEED TO REORGANIZE THESE BITS */ -#define IF_RTM 0x1400000000UL /* HACK NEED TO REORGANIZE THESE BITS */ -#define IF_INVPCID 0x1500000000UL /* HACK NEED TO REORGANIZE THESE BITS */ -#define IF_AVX512CD (0x1600000000UL|IF_AVX512) /* AVX-512 Conflict Detection insns */ -#define IF_AVX512ER (0x1700000000UL|IF_AVX512) /* AVX-512 Exponential and Reciprocal */ -#define IF_AVX512PF (0x1800000000UL|IF_AVX512) /* AVX-512 Prefetch instructions */ -#define IF_INSMASK 0xFF00000000UL /* the mask for instruction set types */ -#define IF_PMASK 0xFF000000UL /* the mask for processor types */ -#define IF_PLEVEL 0x0F000000UL /* the mask for processor instr. level */ - /* also the highest possible processor */ -#define IF_8086 0x00000000UL /* 8086 instruction */ -#define IF_186 0x01000000UL /* 186+ instruction */ -#define IF_286 0x02000000UL /* 286+ instruction */ -#define IF_386 0x03000000UL /* 386+ instruction */ -#define IF_486 0x04000000UL /* 486+ instruction */ -#define IF_PENT 0x05000000UL /* Pentium instruction */ -#define IF_P6 0x06000000UL /* P6 instruction */ -#define IF_KATMAI 0x07000000UL /* Katmai instructions */ -#define IF_WILLAMETTE 0x08000000UL /* Willamette instructions */ -#define IF_PRESCOTT 0x09000000UL /* Prescott instructions */ -#define IF_X86_64 0x0A000000UL /* x86-64 instruction (long or legacy mode) */ -#define IF_NEHALEM 0x0B000000UL /* Nehalem instruction */ -#define IF_WESTMERE 0x0C000000UL /* Westmere instruction */ -#define IF_SANDYBRIDGE 0x0D000000UL /* Sandy Bridge instruction */ -#define IF_FUTURE 0x0E000000UL /* Future processor (not yet disclosed) */ -#define IF_X64 (IF_LONG|IF_X86_64) -#define IF_IA64 0x0F000000UL /* IA64 instructions (in x86 mode) */ -#define IF_CYRIX 0x10000000UL /* Cyrix-specific instruction */ -#define IF_AMD 0x20000000UL /* AMD-specific instruction */ -#define IF_SPMASK 0x30000000UL /* specific processor types mask */ -#define IF_PFMASK (IF_INSMASK|IF_SPMASK) /* disassembly "prefer" mask */ +#define iflags_t uint64_t +#define IF_PLEVEL 1 #endif /* NASM_INSNS_H */ diff --git a/insns.pl b/insns.pl index 8d1f0ee..3c33f02 100755 --- a/insns.pl +++ b/insns.pl @@ -37,6 +37,8 @@ # # Parse insns.dat and produce generated source code files +require 'insns-iflags.pl'; + # Opcode prefixes which need their own opcode tables # LONGER PREFIXES FIRST! @disasm_prefixes = qw(0F24 0F25 0F38 0F3A 0F7A 0FA6 0FA7 0F); @@ -67,7 +69,7 @@ print STDERR "Reading insns.dat...\n"; undef $output; foreach $arg ( @ARGV ) { if ( $arg =~ /^\-/ ) { - if ( $arg =~ /^\-([abdin])$/ ) { + if ( $arg =~ /^\-([abdint])$/ ) { $output = $1; } else { die "$0: Unknown option: ${arg}\n"; @@ -393,6 +395,10 @@ if ( !defined($output) || $output eq 'n' ) { close N; } +if ( !defined($output) || $output eq 't') { + write_iflags(); +} + printf STDERR "Done: %d instructions\n", $insns; # Count primary bytecodes, for statistics @@ -424,7 +430,7 @@ sub count_bytecodes(@) { sub format_insn($$$$$) { my ($opcode, $operands, $codes, $flags, $relax) = @_; - my $num, $nd = 0; + my $num, $nd = 0, $rawflags, $flagsindex; my @bytecode; my $op, @ops, $opp, @opx, @oppx, @decos, @opevex; my @iflags = ( "FPU", "MMX", "3DNOW", "SSE", "SSE2", @@ -492,16 +498,20 @@ sub format_insn($$$$$) { } # format the flags - $flags =~ s/,/|IF_/g; - $flags =~ s/(\|IF_ND|IF_ND\|)//, $nd = 1 if $flags =~ /IF_ND/; - $flags = "IF_" . $flags; + $nd = 1 if $flags =~ /(^|\,)ND($|\,)/; + $flags =~ s/(^|\,)ND($|\,)/\1/g; + $flags =~ s/(^|\,)X64($|\,)/\1LONG,X86_64\2/g; + $rawflags = $flags; + $flagsindex = insns_flag_index(split(',',$flags)); + + die "Error in flags $rawflags" if not defined($flagsindex); @bytecode = (decodify($codes, $relax), 0); push(@bytecode_list, [@bytecode]); $codes = hexstr(@bytecode); count_bytecodes(@bytecode); - ("{I_$opcode, $num, {$operands}, $decorators, \@\@CODES-$codes\@\@, $flags},", $nd); + ("{I_$opcode, $num, {$operands}, $decorators, \@\@CODES-$codes\@\@, $flagsindex},", $nd); } # |