From af9fe8f5976d3bd36312514687de32f1f8a84cca Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 1 May 2017 21:44:24 -0700 Subject: [PATCH] Don't sort opcodes; move all pseudo-ops to the beginning We don't need to sort opcodes anymore, since we are using an O(1) hash and not binary search. Instead, sort them in the order they first appear in insns.dat; this lets us move all the pseudo-ops to a contiguous range at the start of the file, for more efficient handling. Change the functions that process pseudo-ops accordingly. Signed-off-by: H. Peter Anvin --- asm/assemble.c | 4 ++-- asm/parser.c | 4 ++-- common/common.c | 58 ---------------------------------------------- include/insns.h | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++------- x86/insns.dat | 4 +++- x86/insns.pl | 15 ++++++++---- 6 files changed, 81 insertions(+), 76 deletions(-) diff --git a/asm/assemble.c b/asm/assemble.c index 1a784560..73d2e171 100644 --- a/asm/assemble.c +++ b/asm/assemble.c @@ -555,7 +555,7 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction) data.sign = OUT_WRAP; data.bits = bits; - wsize = idata_bytes(instruction->opcode); + wsize = db_bytes(instruction->opcode); if (wsize == -1) return 0; @@ -790,7 +790,7 @@ int64_t insn_size(int32_t segment, int64_t offset, int bits, insn *instruction) int32_t isize, osize, wsize; isize = 0; - wsize = idata_bytes(instruction->opcode); + wsize = db_bytes(instruction->opcode); nasm_assert(wsize > 0); list_for_each(e, instruction->eops) { diff --git a/asm/parser.c b/asm/parser.c index d701d7fd..62104e12 100644 --- a/asm/parser.c +++ b/asm/parser.c @@ -666,7 +666,7 @@ is_float: eop->type = EOT_DB_STRING; result->eops_float = true; - eop->stringlen = idata_bytes(result->opcode); + eop->stringlen = db_bytes(result->opcode); if (eop->stringlen > 16) { nasm_error(ERR_NONFATAL, "floating-point constant" " encountered in DY or DZ instruction"); @@ -1129,7 +1129,7 @@ is_expression: * Transform RESW, RESD, RESQ, REST, RESO, RESY, RESZ into RESB. */ if (opcode_is_resb(result->opcode)) { - result->oprs[0].offset *= resv_bytes(result->opcode); + result->oprs[0].offset *= resb_bytes(result->opcode); result->oprs[0].offset *= result->times; result->times = 1; result->opcode = I_RESB; diff --git a/common/common.c b/common/common.c index 5a546207..13237994 100644 --- a/common/common.c +++ b/common/common.c @@ -62,61 +62,3 @@ const char *prefix_name(int token) return prefix_names[prefix]; } - -/* - * initialized data bytes length from opcode - */ -int idata_bytes(int opcode) -{ - switch (opcode) { - case I_DB: - return 1; - case I_DW: - return 2; - case I_DD: - return 4; - case I_DQ: - return 8; - case I_DT: - return 10; - case I_DO: - return 16; - case I_DY: - return 32; - case I_DZ: - return 64; - case I_none: - return -1; - default: - return 0; - } -} - -/* - * Uninitialized data bytes length from opcode - */ -int resv_bytes(int opcode) -{ - switch (opcode) { - case I_RESB: - return 1; - case I_RESW: - return 2; - case I_RESD: - return 4; - case I_RESQ: - return 8; - case I_REST: - return 10; - case I_RESO: - return 16; - case I_RESY: - return 32; - case I_RESZ: - return 64; - case I_none: - return -1; - default: - return 0; - } -} diff --git a/include/insns.h b/include/insns.h index 0a1cd741..7c1896bc 100644 --- a/include/insns.h +++ b/include/insns.h @@ -48,23 +48,79 @@ extern const uint8_t nasm_bytecodes[]; */ #define ITEMPLATE_END {-1,-1,{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1},NULL,0} -/* Width of Dx and RESx instructions */ -int const_func idata_bytes(enum opcode opcode); -int const_func resv_bytes(enum opcode opcode); - /* * Pseudo-op tests */ /* DB-type instruction (DB, DW, ...) */ -static inline bool opcode_is_db(enum opcode opcode) +static inline bool const_func opcode_is_db(enum opcode opcode) { - return idata_bytes(opcode) > 0; + return opcode >= I_DB && opcode < I_RESB; } /* RESB-type instruction (RESB, RESW, ...) */ -static inline bool opcode_is_resb(enum opcode opcode) +static inline bool const_func opcode_is_resb(enum opcode opcode) +{ + return opcode >= I_RESB && opcode < I_INCBIN; +} + +/* Width of Dx and RESx instructions */ + +/* + * initialized data bytes length from opcode + */ +static inline int const_func db_bytes(int opcode) +{ + switch (opcode) { + case I_DB: + return 1; + case I_DW: + return 2; + case I_DD: + return 4; + case I_DQ: + return 8; + case I_DT: + return 10; + case I_DO: + return 16; + case I_DY: + return 32; + case I_DZ: + return 64; + case I_none: + return -1; + default: + return 0; + } +} + +/* + * Uninitialized data bytes length from opcode + */ +static inline int resb_bytes(enum opcode opcode) { - return resv_bytes(opcode) > 0; + switch (opcode) { + case I_RESB: + return 1; + case I_RESW: + return 2; + case I_RESD: + return 4; + case I_RESQ: + return 8; + case I_REST: + return 10; + case I_RESO: + return 16; + case I_RESY: + return 32; + case I_RESZ: + return 64; + case I_none: + return -1; + default: + return 0; + } } #endif /* NASM_INSNS_H */ diff --git a/x86/insns.dat b/x86/insns.dat index 00f25711..73b0a85a 100644 --- a/x86/insns.dat +++ b/x86/insns.dat @@ -48,6 +48,8 @@ ; ;# Special instructions... +; These MUST be first in this file and must maintain the pattern of +; Dx by size, RESx by size, and INCBIN in that order. DB ignore ignore ignore DW ignore ignore ignore DD ignore ignore ignore @@ -64,6 +66,7 @@ REST ignore ignore ignore RESO ignore ignore ignore RESY ignore ignore ignore RESZ ignore ignore ignore +INCBIN ignore ignore ignore ;# Conventional instructions AAA void [ 37] 8086,NOLONG @@ -652,7 +655,6 @@ INC rm8 [m: hle fe /0] 8086,LOCK INC rm16 [m: hle o16 ff /0] 8086,LOCK INC rm32 [m: hle o32 ff /0] 386,LOCK INC rm64 [m: hle o64 ff /0] X64,LOCK -INCBIN ignore ignore ignore INSB void [ 6c] 186 INSD void [ o32 6d] 386 INSW void [ o16 6d] 186 diff --git a/x86/insns.pl b/x86/insns.pl index e6d3eee1..5845ed89 100755 --- a/x86/insns.pl +++ b/x86/insns.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl ## -------------------------------------------------------------------------- ## -## Copyright 1996-2016 The NASM Authors - All Rights Reserved +## Copyright 1996-2017 The NASM Authors - All Rights Reserved ## See the file AUTHORS included with the NASM distribution for ## the specific copyright holders. ## @@ -89,6 +89,7 @@ open(F, '<', $fname) || die "unable to open $fname"; $line = 0; $insns = 0; +$n_opcodes = $n_opcodes_cc = 0; while () { $line++; chomp; @@ -146,10 +147,14 @@ while () { } if ( $fields[0] =~ /cc$/ ) { # Conditional instruction - $k_opcodes_cc{$fields[0]}++; + if (!defined($k_opcodes_cc{$fields[0]})) { + $k_opcodes_cc{$fields[0]} = $n_opcodes_cc++; + } } else { # Unconditional instruction - $k_opcodes{$fields[0]}++; + if (!defined($k_opcodes{$fields[0]})) { + $k_opcodes{$fields[0]} = $n_opcodes++; + } } if ($formatted && !$nd) { push @big, $formatted; @@ -189,8 +194,8 @@ foreach $bl (@bytecode_list) { } undef @bytecode_list; -@opcodes = sort keys(%k_opcodes); -@opcodes_cc = sort keys(%k_opcodes_cc); +@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); if ( $output eq 'b') { print STDERR "Writing $oname...\n"; -- 2.11.4.GIT