From: Cyrill G. <gor...@gm...> - 2013-10-06 21:28:49
|
Hi guys, here is early draft for instruction flags generator, it might look somewhat ugly since I'm far from been perl experienced, still take a look, and tell me what you think. There are some problem remains which I've not yet addressed - need to add flags into AVX512 templates - need to address somehow "goodneds" in disassembler (see second patch and fixme in the code) Cyrill Gorcunov (2): insns-iflags.pl: Introduce instruction flags bitvector generator insns.pl: Start using instruction flags generator Makefile.in | 9 +- assemble.c | 27 +++--- disasm.c | 6 +- insns-iflags.pl | 295 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ insns.h | 113 +--------------------- insns.pl | 22 +++-- 6 files changed, 341 insertions(+), 131 deletions(-) create mode 100644 insns-iflags.pl -- 1.8.3.1 |
From: Cyrill G. <gor...@gm...> - 2013-10-06 21:28:35
|
It been found that 64 bits for instruction flags is too small, so instead we start using indirect addressing scheme to keep instruction flags in bitvectors instead. Using one bitvector per instruction template entry is wastefull (especially if vector grow in future, at moment it's 128 bit length), so we use indirect addressing, which is generated as follow - read instruction flags from insns.dat - flag sequence sorted and joined into one key string - this key string become a hash index - all hash entries are compacted into one array - every instruction template uses array offset instead of flags bitfield Just for info, at moment we have 196 unique flags combination, but since instruction template will use index as unsigned integer, we can use a way more wider combination of flags in future. Signed-off-by: Cyrill Gorcunov <gor...@gm...> --- insns-iflags.pl | 295 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 insns-iflags.pl diff --git a/insns-iflags.pl b/insns-iflags.pl new file mode 100644 index 0000000..bcc7306 --- /dev/null +++ b/insns-iflags.pl @@ -0,0 +1,295 @@ +#!/usr/bin/perl +## -------------------------------------------------------------------------- +## +## Copyright 1996-2013 The NASM Authors - All Rights Reserved +## See the file AUTHORS included with the NASM distribution for +## the specific copyright holders. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following +## conditions are met: +## +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above +## copyright notice, this list of conditions and the following +## disclaimer in the documentation and/or other materials provided +## with the distribution. +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +## CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +## INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +## OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +## EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +## +## -------------------------------------------------------------------------- + +# +# Here we generate instrcution template flags. Note we assume that at moment +# less than 128 bits are used for all flags. If needed it can be extended +# arbitrary, but it'll be needed to extend arrays (they are 4 32 bit elements +# by now). + +# +# The order does matter here. We use some predefined masks to quick test +# for a set of flags, so be carefull moving bits (and +# don't forget to update C code generation then). +my %insns_flag_bit = ( + # + # dword bound, index 0 - specific flags + # + "SM" => [ 0, "size match"], + "SM2" => [ 1, "size match first two operands"], + "SB" => [ 2, "unsized operands can't be non-byte"], + "SW" => [ 3, "unsized operands can't be non-word"], + "SD" => [ 4, "unsized operands can't be non-dword"], + "SQ" => [ 5, "unsized operands can't be non-qword"], + "SO" => [ 6, "unsized operands can't be non-oword"], + "SY" => [ 7, "unsized operands can't be non-yword"], + "SZ" => [ 8, "unsized operands can't be non-zword"], + "SIZE" => [ 9, "unsized operands must match the bitsize"], + "SX" => [ 10, "unsized operands not allowed"], + "AR0" => [ 11, "SB, SW, SD applies to argument 0"], + "AR1" => [ 12, "SB, SW, SD applies to argument 1"], + "AR2" => [ 13, "SB, SW, SD applies to argument 2"], + "AR3" => [ 14, "SB, SW, SD applies to argument 3"], + "AR4" => [ 15, "SB, SW, SD applies to argument 4"], + "OPT" => [ 16, "optimizing assembly only"], + + # + # dword bound, index 1 - instruction filtering flags + # + "PRIV" => [ 32, "it's a privileged instruction"], + "SMM" => [ 33, "it's only valid in SMM"], + "PROT" => [ 34, "it's protected mode only"], + "LOCK" => [ 35, "lockable if operand 0 is memory"], + "NOLONG" => [ 36, "it's not available in long mode"], + "LONG" => [ 37, "long mode instruction"], + "NOHLE" => [ 38, "HLE prefixes forbidden"], + "UNDOC" => [ 39, "it's an undocumented instruction"], + "HLE" => [ 40, "HLE prefixed instruction"], + "FPU" => [ 41, "it's an FPU instruction"], + "MMX" => [ 42, "it's an MMX instruction"], + "3DNOW" => [ 43, "it's a 3DNow! instruction"], + "SSE" => [ 44, "it's a SSE (KNI, MMX2) instruction"], + "SSE2" => [ 45, "it's a SSE2 instruction"], + "SSE3" => [ 46, "it's a SSE3 (PNI) instruction"], + "VMX" => [ 47, "it's a VMX instruction"], + "SSSE3" => [ 48, "it's an SSSE3 instruction"], + "SSE4A" => [ 49, "AMD SSE4a"], + "SSE41" => [ 50, "it's an SSE4.1 instruction"], + "SSE42" => [ 51, ""], + "SSE5" => [ 52, ""], + "AVX" => [ 53, "it's an AVX (128b) instruction"], + "AVX2" => [ 54, "it's an AVX2 (256b) instruction"], + "FMA" => [ 55, ""], + "BMI1" => [ 56, ""], + "BMI2" => [ 57, ""], + "TBM" => [ 58, ""], + "RTM" => [ 59, ""], + "INVPCID" => [ 60, ""], + + # + # dword bound, index 2 - instruction filtering flags + # + "AVX512" => [ 64, "it's an AVX-512F (512b) instruction"], + "AVX512CD" => [ 65, "AVX-512 Conflict Detection insns"], + "AVX512ER" => [ 66, "AVX-512 Exponential and Reciprocal"], + "AVX512PF" => [ 67, "AVX-512 Prefetch instructions"], + + # + # dword bound, index 3 - cpu type flags + # + "8086" => [ 96, "8086 instruction"], + "186" => [ 97, "186+ instruction"], + "286" => [ 98, "286+ instruction"], + "386" => [ 99, "386+ instruction"], + "486" => [100, "486+ instruction"], + "PENT" => [101, "Pentium instruction"], + "P6" => [102, "P6 instruction"], + "KATMAI" => [103, "Katmai instructions"], + "WILLAMETTE" => [104, "Willamette instructions"], + "PRESCOTT" => [105, "Prescott instructions"], + "X86_64" => [106, "x86-64 instruction (long or legacy mode)"], + "NEHALEM" => [107, "Nehalem instruction"], + "WESTMERE" => [108, "Westmere instruction"], + "SANDYBRIDGE" => [109, "Sandy Bridge instruction"], + "FUTURE" => [110, "Future processor (not yet disclosed)"], + "IA64" => [111, "IA64 instructions (in x86 mode)"], + "CYRIX" => [112, "Cyrix-specific instruction"], + "AMD" => [113, "AMD-specific instruction"], +); + +my %insns_flag_hash = (); +my @insns_flag_values = (); + +sub insns_flag_index(@) { + return undef if $_[0] eq "ignore"; + + my @prekey = @_; + my $key = join("", @prekey); + + if (not defined($insns_flag_hash{$key})) { + my @newkey = ([], [], [], []); + my $str = ""; + + for my $i (@prekey) { + die "No key for $i\n" if not defined($insns_flag_bit{$i}); + if ($insns_flag_bit{$i}[0] < 32) { + push @newkey[0], $insns_flag_bit{$i}[0] - 0; + } elsif ($insns_flag_bit{$i}[0] < 64) { + push @newkey[1], $insns_flag_bit{$i}[0] - 32; + } elsif ($insns_flag_bit{$i}[0] < 96) { + push @newkey[2], $insns_flag_bit{$i}[0] - 64; + } elsif ($insns_flag_bit{$i}[0] < 128) { + push @newkey[3], $insns_flag_bit{$i}[0] - 96; + } else { + die "Key value is too big ", $insns_flag_bit{$i}[0], "\n"; + } + } + + for my $j (0 .. $#newkey) { + my $v = ""; + if (scalar(@{$newkey[$j]})) { + $v = join(" | ", map { map { sprintf("(UINT32_C(1) << %d)", $_) } @$_; } $newkey[$j]); + } else { + $v = "0"; + } + $str .= sprintf(".field[%d] = %s, ", $j, $v); + } + + push @insns_flag_values, $str; + $insns_flag_hash{$key} = $#insns_flag_values; + } + + return $insns_flag_hash{$key}; +} + +sub write_iflags() { + print STDERR "Writing iflag.h ...\n"; + + open N, ">iflag.h"; + + print N "/* This file is auto-generated. Don't edit. */\n"; + print N "#ifndef NASM_IFLAG_H__\n"; + print N "#define NASM_IFLAG_H__\n\n"; + + print N "#include <inttypes.h>\n"; + print N "#include \"compiler.h\"\n\n"; + + print N "/*\n"; + print N " * Instruction template flags. These specify which processor\n"; + print N " * targets the instruction is eligible for, whether it is\n"; + print N " * privileged or undocumented, and also specify extra error\n"; + print N " * checking on the matching of the instruction.\n"; + print N " *\n"; + print N " * IF_SM stands for Size Match: any operand whose size is not\n"; + print N " * explicitly specified by the template is `really' intended to be\n"; + print N " * the same size as the first size-specified operand.\n"; + print N " * Non-specification is tolerated in the input instruction, but\n"; + print N " * _wrong_ specification is not.\n"; + print N " *\n"; + print N " * IF_SM2 invokes Size Match on only the first _two_ operands, for\n"; + print N " * three-operand instructions such as SHLD: it implies that the\n"; + print N " * first two operands must match in size, but that the third is\n"; + print N " * required to be _unspecified_.\n"; + print N " *\n"; + print N " * IF_SB invokes Size Byte: operands with unspecified size in the\n"; + print N " * template are really bytes, and so no non-byte specification in\n"; + print N " * the input instruction will be tolerated. IF_SW similarly invokes\n"; + print N " * Size Word, and IF_SD invokes Size Doubleword.\n"; + print N " *\n"; + print N " * (The default state if neither IF_SM nor IF_SM2 is specified is\n"; + print N " * that any operand with unspecified size in the template is\n"; + print N " * required to have unspecified size in the instruction too...)\n"; + print N " *\n"; + print N " * iflags_t is defined to store these flags.\n"; + print N " */\n"; + foreach my $key (sort { $insns_flag_bit{$a}[0] <=> $insns_flag_bit{$b}[0] } keys(%insns_flag_bit)) { + print N sprintf("#define IF_%-16s (%3d) /* %-64s */\n", + $key, $insns_flag_bit{$key}[0], $insns_flag_bit{$key}[1]); + } + + print N "\n"; + print N "typedef struct {\n"; + print N " uint32_t field[4];\n"; + print N "} iflag_t;\n\n"; + + print N "\n"; + print N sprintf("extern iflag_t insns_flags[%d];\n\n", $#insns_flag_values + 1); + + print N "#define IF_GENBIT(bit) (UINT32_C(1) << (bit))\n\n"; + + print N "static inline unsigned int iflag_test(iflag_t *f,unsigned int bit)\n"; + print N "{\n"; + print N " unsigned int index = bit / 32;\n"; + print N " return f->field[index] & (UINT32_C(1) << (bit - (index * 32)));\n"; + print N "}\n\n"; + + print N "static inline void iflag_set(iflag_t *f, unsigned int bit)\n"; + print N "{\n"; + print N " unsigned int index = bit / 32;\n"; + print N " f->field[index] |= (UINT32_C(1) << (bit - (index * 32)));\n"; + print N "}\n\n"; + + print N "static inline void iflag_clear(iflag_t *f, unsigned int bit)\n"; + print N "{\n"; + print N " unsigned int index = bit / 32;\n"; + print N " f->field[index] &= ~(UINT32_C(1) << (bit - (index * 32)));\n"; + print N "}\n\n"; + + print N "/* Use this helper to test instruction template flags */\n"; + print N "#define itemp_has(itemp, bit) iflag_test(&insns_flags[(itemp)->iflag_idx], bit)\n\n"; + + print N "/* Some helpers which are to work with predefined masks */\n"; + print N "#define IF_SMASK \\\n"; + print N " (IF_GENBIT(IF_SB) |\\\n"; + print N " IF_GENBIT(IF_SW) |\\\n"; + print N " IF_GENBIT(IF_SD) |\\\n"; + print N " IF_GENBIT(IF_SQ) |\\\n"; + print N " IF_GENBIT(IF_SO) |\\\n"; + print N " IF_GENBIT(IF_SY) |\\\n"; + print N " IF_GENBIT(IF_SZ))\n"; + print N "#define IF_ARMASK \\\n"; + print N " (IF_GENBIT(IF_AR0) |\\\n"; + print N " IF_GENBIT(IF_AR1) |\\\n"; + print N " IF_GENBIT(IF_AR2) |\\\n"; + print N " IF_GENBIT(IF_AR3) |\\\n"; + print N " IF_GENBIT(IF_AR4))\n"; + + print N "#define itemp_smask(itemp) (insns_flags[(itemp)->iflag_idx].field[0] & IF_SMASK)\n"; + print N "#define itemp_arg(itemp) (((insns_flags[(itemp)->iflag_idx].field[0] & IF_ARMASK) >> IF_AR0) - 1)\n"; + + # FIXME These are not yet addressed + # IF_PLEVEL + # IF_SPMASK + # IF_PFMASK + + print N "\n"; + print N "#endif /* NASM_IFLAG_H__ */\n"; + close N; + + print STDERR "Writing iflag.c ...\n"; + + open N, ">iflag.c"; + + print N "/* This file is auto-generated. Don't edit. */\n"; + print N "#include \"iflag.h\"\n\n"; + print N "/* Global flags referenced from instruction templates */\n"; + print N sprintf("iflag_t insns_flags[%d] = {\n", $#insns_flag_values + 1); + foreach my $i (0 .. $#insns_flag_values) { + print N sprintf(" [%8d] = { %s },\n", $i, $insns_flag_values[$i]); + } + print N "};\n\n"; + close N; +} + +1; -- 1.8.3.1 |
From: Cyrill G. <gor...@gm...> - 2013-10-06 21:34:51
|
On Mon, Oct 07, 2013 at 01:28:23AM +0400, Cyrill Gorcunov wrote: > + > +sub insns_flag_index(@) { > + return undef if $_[0] eq "ignore"; > + > + my @prekey = @_; there should be @prekey = sort(@_); > + my $key = join("", @prekey); |
From: Cyrill G. <gor...@gm...> - 2013-10-06 21:28:35
|
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 60f7dd3..333251b 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); } # -- 1.8.3.1 |
From: H. P. A. <hp...@zy...> - 2013-10-06 21:34:48
|
I would like to suggest that we pick out the flags that are actually used by the assembler for other than CPU feature determination, like the Sx flags, and move them to a separate word and have the rest indirect. On the other hand, perhaps that is a pretty useless distinction? Either way, good work on this! Cyrill Gorcunov <gor...@gm...> wrote: >Hi guys, here is early draft for instruction flags generator, >it might look somewhat ugly since I'm far from been perl experienced, >still take a look, and tell me what you think. > >There are some problem remains which I've not yet addressed > > - need to add flags into AVX512 templates > - need to address somehow "goodneds" in disassembler > (see second patch and fixme in the code) > >Cyrill Gorcunov (2): > insns-iflags.pl: Introduce instruction flags bitvector generator > insns.pl: Start using instruction flags generator > > Makefile.in | 9 +- > assemble.c | 27 +++--- > disasm.c | 6 +- >insns-iflags.pl | 295 >++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > insns.h | 113 +--------------------- > insns.pl | 22 +++-- > 6 files changed, 341 insertions(+), 131 deletions(-) > create mode 100644 insns-iflags.pl -- Sent from my mobile phone. Please pardon brevity and lack of formatting. |
From: Cyrill G. <gor...@gm...> - 2013-10-06 21:39:38
|
On Sun, Oct 06, 2013 at 02:34:10PM -0700, H. Peter Anvin wrote: > I would like to suggest that we pick out the flags that are actually used by the > assembler for other than CPU feature determination, like the Sx flags, > and move them to a separate word and have the rest indirect. > On the other hand, perhaps that is a pretty useless distinction? I think, yes, it makes sence. Note that in first place I intentionally moved Sx, ARG and etc into first dword my %insns_flag_bit = ( # # dword bound, index 0 - specific flags # "SM" => [ 0, "size match"], "SM2" => [ 1, "size match first two operands"], "SB" => [ 2, "unsized operands can't be non-byte"], "SW" => [ 3, "unsized operands can't be non-word"], "SD" => [ 4, "unsized operands can't be non-dword"], "SQ" => [ 5, "unsized operands can't be non-qword"], "SO" => [ 6, "unsized operands can't be non-oword"], "SY" => [ 7, "unsized operands can't be non-yword"], "SZ" => [ 8, "unsized operands can't be non-zword"], "SIZE" => [ 9, "unsized operands must match the bitsize"], "SX" => [ 10, "unsized operands not allowed"], "AR0" => [ 11, "SB, SW, SD applies to argument 0"], "AR1" => [ 12, "SB, SW, SD applies to argument 1"], "AR2" => [ 13, "SB, SW, SD applies to argument 2"], "AR3" => [ 14, "SB, SW, SD applies to argument 3"], "AR4" => [ 15, "SB, SW, SD applies to argument 4"], "OPT" => [ 16, "optimizing assembly only"], > > Either way, good work on this! Lets do a deal, I'll try to finish all this on the week, and then once everything work as expected (ie at least all tests get passed), we re-think about moving these "specific" flags into separate entry, ok? |
From: H. P. A. <hp...@zy...> - 2013-10-06 22:21:15
|
On 10/06/2013 02:39 PM, Cyrill Gorcunov wrote: >> >> Either way, good work on this! > > Lets do a deal, I'll try to finish all this on the week, and then > once everything work as expected (ie at least all tests get passed), > we re-think about moving these "specific" flags into separate entry, > ok? > Totally sounds like a plan. -hpa |