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 resv_bytes(opcode) > 0; + 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) +{ + 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";