# though, so it isn't necessary to have Perl just to recompile NASM
# from the distribution.
+insnsb.c: insns.dat insns.pl
+ $(PERL) $(srcdir)/insns.pl -b $(srcdir)/insns.dat
insnsa.c: insns.dat insns.pl
$(PERL) $(srcdir)/insns.pl -a $(srcdir)/insns.dat
insnsd.c: insns.dat insns.pl
# This target generates all files that require perl.
# This allows easier generation of distribution (see dist target).
-PERLREQ = macros.c insnsa.c insnsd.c insnsi.h insnsn.c \
+PERLREQ = macros.c insnsb.c insnsa.c insnsd.c insnsi.h insnsn.c \
regs.c regs.h regflags.c regdis.c regvals.c tokhash.c tokens.h \
version.h version.mac pptok.h pptok.c
perlreq: $(PERLREQ)
regs.h version.h
hashtbl.$(O): hashtbl.c compiler.h config.h hashtbl.h insnsi.h nasm.h \
nasmlib.h regs.h version.h
-insnsa.$(O): insnsa.c compiler.h config.h insns.h insnsi.h nasm.h nasmlib.h \
- regs.h tokens.h version.h
-insnsd.$(O): insnsd.c compiler.h config.h insns.h insnsi.h nasm.h nasmlib.h \
+insnsa.$(O): insnsa.c compiler.h config.h insns.h insnsb.c insnsi.h nasm.h \
+ nasmlib.h regs.h tokens.h version.h
+insnsb.$(O): insnsb.c compiler.h config.h insns.h insnsi.h nasm.h nasmlib.h \
regs.h tokens.h version.h
+insnsd.$(O): insnsd.c compiler.h config.h insns.h insnsb.c insnsi.h nasm.h \
+ nasmlib.h regs.h tokens.h version.h
insnsn.$(O): insnsn.c
labels.$(O): labels.c compiler.h config.h hashtbl.h insnsi.h nasm.h \
nasmlib.h regs.h version.h
BUILD_CFLAGS = $(CFLAGS) /I$(srcdir)/inttypes
INTERNAL_CFLAGS = /I$(srcdir) /I. /DHAVE__SNPRINTF /DHAVE__VSNPRINTF
ALL_CFLAGS = $(BUILD_CFLAGS) $(INTERNAL_CFLAGS)
-LDFLAGS =
-LIBS =
+LDFLAGS =
+LIBS =
PERL = perl -I$(srcdir)/perllib
# Binary suffixes
# though, so it isn't necessary to have Perl just to recompile NASM
# from the distribution.
+insnsb.c: insns.dat insns.pl
+ $(PERL) $(srcdir)/insns.pl -b $(srcdir)/insns.dat
insnsa.c: insns.dat insns.pl
$(PERL) $(srcdir)/insns.pl -a $(srcdir)/insns.dat
insnsd.c: insns.dat insns.pl
# This target generates all files that require perl.
# This allows easier generation of distribution (see dist target).
-PERLREQ = macros.c insnsa.c insnsd.c insnsi.h insnsn.c \
+PERLREQ = macros.c insnsb.c insnsa.c insnsd.c insnsi.h insnsn.c \
regs.c regs.h regflags.c regdis.c regvals.c tokhash.c tokens.h \
version.h version.mac pptok.h pptok.c
perlreq: $(PERLREQ)
version.h
hashtbl.$(O): hashtbl.c compiler.h hashtbl.h insnsi.h nasm.h nasmlib.h \
regs.h version.h
-insnsa.$(O): insnsa.c compiler.h insns.h insnsi.h nasm.h nasmlib.h regs.h \
- tokens.h version.h
-insnsd.$(O): insnsd.c compiler.h insns.h insnsi.h nasm.h nasmlib.h regs.h \
+insnsa.$(O): insnsa.c compiler.h insns.h insnsb.c insnsi.h nasm.h nasmlib.h \
+ regs.h tokens.h version.h
+insnsb.$(O): insnsb.c compiler.h insns.h insnsi.h nasm.h nasmlib.h regs.h \
tokens.h version.h
+insnsd.$(O): insnsd.c compiler.h insns.h insnsb.c insnsi.h nasm.h nasmlib.h \
+ regs.h tokens.h version.h
insnsn.$(O): insnsn.c
labels.$(O): labels.c compiler.h hashtbl.h insnsi.h nasm.h nasmlib.h regs.h \
version.h
regs.h version.h
hashtbl.o: hashtbl.c compiler.h config.h hashtbl.h insnsi.h nasm.h nasmlib.h \
regs.h version.h
-insnsa.o: insnsa.c compiler.h config.h insns.h insnsi.h nasm.h nasmlib.h \
- regs.h tokens.h version.h
-insnsd.o: insnsd.c compiler.h config.h insns.h insnsi.h nasm.h nasmlib.h \
+insnsa.o: insnsa.c compiler.h config.h insns.h insnsb.c insnsi.h nasm.h \
+ nasmlib.h regs.h tokens.h version.h
+insnsb.o: insnsb.c compiler.h config.h insns.h insnsi.h nasm.h nasmlib.h \
regs.h tokens.h version.h
+insnsd.o: insnsd.c compiler.h config.h insns.h insnsb.c insnsi.h nasm.h \
+ nasmlib.h regs.h tokens.h version.h
insnsn.o: insnsn.c
labels.o: labels.c compiler.h config.h hashtbl.h insnsi.h nasm.h nasmlib.h \
regs.h version.h
mandir = $(prefix)\man
CC = wcl386
-DEBUG =
+DEBUG =
CFLAGS = -6 -ox -wx -ze -fpi $(DEBUG)
BUILD_CFLAGS = $(CFLAGS) $(TARGET_FLAGS) # -I$(srcdir)/inttypes
INTERNAL_CFLAGS = -I$(srcdir) -I. -DHAVE_SNPRINTF -DHAVE_VSNPRINTF
ALL_CFLAGS = $(BUILD_CFLAGS) $(INTERNAL_CFLAGS)
LD = $(CC)
LDFLAGS = $(ALL_CFLAGS)
-LIBS =
+LIBS =
PERL = perl -I$(srcdir)/perllib
STRIP = wstrip
# though, so it isn't necessary to have Perl just to recompile NASM
# from the distribution.
+insnsb.c: insns.dat insns.pl
+ $(PERL) $(srcdir)/insns.pl -b $(srcdir)/insns.dat
insnsa.c: insns.dat insns.pl
$(PERL) $(srcdir)/insns.pl -a $(srcdir)/insns.dat
insnsd.c: insns.dat insns.pl
# This target generates all files that require perl.
# This allows easier generation of distribution (see dist target).
-PERLREQ = macros.c insnsa.c insnsd.c insnsi.h insnsn.c &
+PERLREQ = macros.c insnsb.c insnsa.c insnsd.c insnsi.h insnsn.c &
regs.c regs.h regflags.c regdis.c regvals.c tokhash.c tokens.h &
version.h version.mac pptok.h pptok.c
perlreq: $(PERLREQ)
version.h
hashtbl.$(O): hashtbl.c compiler.h hashtbl.h insnsi.h nasm.h nasmlib.h &
regs.h version.h
-insnsa.$(O): insnsa.c compiler.h insns.h insnsi.h nasm.h nasmlib.h regs.h &
- tokens.h version.h
-insnsd.$(O): insnsd.c compiler.h insns.h insnsi.h nasm.h nasmlib.h regs.h &
+insnsa.$(O): insnsa.c compiler.h insns.h insnsb.c insnsi.h nasm.h nasmlib.h &
+ regs.h tokens.h version.h
+insnsb.$(O): insnsb.c compiler.h insns.h insnsi.h nasm.h nasmlib.h regs.h &
tokens.h version.h
+insnsd.$(O): insnsd.c compiler.h insns.h insnsb.c insnsi.h nasm.h nasmlib.h &
+ regs.h tokens.h version.h
insnsn.$(O): insnsn.c
labels.$(O): labels.c compiler.h hashtbl.h insnsi.h nasm.h nasmlib.h regs.h &
version.h
# > building on DOS, Windows, or OS/2, as they share the same C
# > library headers. But when cross-compiling from (or to) Linux, it
# > is crucial.
-# >
+# >
# > This may be accomplished by setting the INCLUDE env var in the
# > makefile, or setting OS2_INCLUDE, DOS_INCLUDE, NT_INCLUDE env vars
# > *and* making sure that the proper -bt switch is used, or passing a
mandir = $(prefix)/man
CC = wcl386
-DEBUG =
+DEBUG =
CFLAGS = -6 -ox -wx -ze -fpi $(DEBUG)
BUILD_CFLAGS = $(CFLAGS) $(TARGET_FLAGS) # -I$(srcdir)/inttypes
INTERNAL_CFLAGS = -I$(srcdir) -I. \
ALL_CFLAGS = $(BUILD_CFLAGS) $(INTERNAL_CFLAGS)
LD = $(CC)
LDFLAGS = $(ALL_CFLAGS)
-LIBS =
+LIBS =
PERL = perl -I$(srcdir)/perllib
STRIP = wstrip
# though, so it isn't necessary to have Perl just to recompile NASM
# from the distribution.
+insnsb.c: insns.dat insns.pl
+ $(PERL) $(srcdir)/insns.pl -b $(srcdir)/insns.dat
insnsa.c: insns.dat insns.pl
$(PERL) $(srcdir)/insns.pl -a $(srcdir)/insns.dat
insnsd.c: insns.dat insns.pl
# This target generates all files that require perl.
# This allows easier generation of distribution (see dist target).
-PERLREQ = macros.c insnsa.c insnsd.c insnsi.h insnsn.c \
+PERLREQ = macros.c insnsb.c insnsa.c insnsd.c insnsi.h insnsn.c \
regs.c regs.h regflags.c regdis.c regvals.c tokhash.c tokens.h \
version.h version.mac pptok.h pptok.c
perlreq: $(PERLREQ)
version.h
hashtbl.$(O): hashtbl.c compiler.h hashtbl.h insnsi.h nasm.h nasmlib.h \
regs.h version.h
-insnsa.$(O): insnsa.c compiler.h insns.h insnsi.h nasm.h nasmlib.h regs.h \
- tokens.h version.h
-insnsd.$(O): insnsd.c compiler.h insns.h insnsi.h nasm.h nasmlib.h regs.h \
+insnsa.$(O): insnsa.c compiler.h insns.h insnsb.c insnsi.h nasm.h nasmlib.h \
+ regs.h tokens.h version.h
+insnsb.$(O): insnsb.c compiler.h insns.h insnsi.h nasm.h nasmlib.h regs.h \
tokens.h version.h
+insnsd.$(O): insnsd.c compiler.h insns.h insnsb.c insnsi.h nasm.h nasmlib.h \
+ regs.h tokens.h version.h
insnsn.$(O): insnsn.c
labels.$(O): labels.c compiler.h hashtbl.h insnsi.h nasm.h nasmlib.h regs.h \
version.h
static struct ofmt *outfmt;
static ListGen *list;
-static int64_t calcsize(int32_t, int64_t, int, insn *, const char *);
-static void gencode(int32_t, int64_t, int, insn *, const char *, int64_t);
+static int64_t calcsize(int32_t, int64_t, int, insn *, const uint8_t *);
+static void gencode(int32_t, int64_t, int, insn *, const uint8_t *, int64_t);
static int matches(const struct itemplate *, insn *, int bits);
static int32_t regflag(const operand *);
static int32_t regval(const operand *);
}
static int jmp_match(int32_t segment, int64_t offset, int bits,
- insn * ins, const char *code)
+ insn * ins, const uint8_t *code)
{
int64_t isize;
uint8_t c = code[0];
m += jmp_match(segment, offset, bits, instruction, temp->code);
if (m == 100) { /* matches! */
- const char *codes = temp->code;
+ const uint8_t *codes = temp->code;
int64_t insn_size = calcsize(segment, offset, bits,
instruction, codes);
itimes = instruction->times;
if (m == 100) {
/* we've matched an instruction. */
int64_t isize;
- const char *codes = temp->code;
+ const uint8_t *codes = temp->code;
int j;
isize = calcsize(segment, offset, bits, instruction, codes);
return v32 >= -128 && v32 <= 127;
}
static int64_t calcsize(int32_t segment, int64_t offset, int bits,
- insn * ins, const char *codes)
+ insn * ins, const uint8_t *codes)
{
int64_t length = 0;
uint8_t c;
}
static void gencode(int32_t segment, int64_t offset, int bits,
- insn * ins, const char *codes, int64_t insn_end)
+ insn * ins, const uint8_t *codes, int64_t insn_end)
{
static char condval[] = { /* conditional opcodes */
0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
enum opcode opcode; /* the token, passed from "parser.c" */
int operands; /* number of operands */
opflags_t opd[MAX_OPERANDS]; /* bit flags for operand types */
- const char *code; /* the code it assembles to */
+ const uint8_t *code; /* the code it assembles to */
uint32_t flags; /* some flags */
};
undef $output;
foreach $arg ( @ARGV ) {
if ( $arg =~ /^\-/ ) {
- if ( $arg =~ /^\-([adin])$/ ) {
+ if ( $arg =~ /^\-([abdin])$/ ) {
$output = $1;
} else {
die "$0: Unknown option: ${arg}\n";
open (F, $fname) || die "unable to open $fname";
%dinstables = ();
+@bytecode_list = ();
$line = 0;
$insns = 0;
close F;
+#
+# Generate the bytecode array. At this point, @bytecode_list contains
+# the full set of bytecodes.
+#
+
+# Sort by descending length
+@bytecode_list = sort { scalar(@$b) <=> scalar(@$a) } @bytecode_list;
+@bytecode_array = ();
+%bytecode_pos = ();
+$bytecode_next = 0;
+foreach $bl (@bytecode_list) {
+ my $h = hexstr(@$bl);
+ next if (defined($bytecode_pos{$h}));
+
+ push(@bytecode_array, $bl);
+ while ($h ne '') {
+ $bytecode_pos{$h} = $bytecode_next;
+ $h = substr($h, 2);
+ $bytecode_next++;
+ }
+}
+undef @bytecode_list;
+
@opcodes = sort keys(%k_opcodes);
@opcodes_cc = sort keys(%k_opcodes_cc);
+if ( !defined($output) || $output eq 'b') {
+ print STDERR "Writing insnsb.c...\n";
+
+ open B, ">insnsb.c";
+
+ print B "/* This file auto-generated from insns.dat by insns.pl" .
+ " - don't edit it */\n\n";
+
+ print B "#include \"nasm.h\"\n";
+ print B "#include \"insns.h\"\n\n";
+
+ print B "static const uint8_t nasm_bytecodes[$bytecode_next] = {\n";
+
+ $p = 0;
+ foreach $bl (@bytecode_array) {
+ printf B " /* %4d */ ", $p;
+ foreach $d (@$bl) {
+ printf B "%#o,", $d;
+ $p++;
+ }
+ printf B "\n";
+ }
+ print B "};\n";
+
+ close B;
+}
+
if ( !defined($output) || $output eq 'a' ) {
print STDERR "Writing insnsa.c...\n";
print A "/* This file auto-generated from insns.dat by insns.pl" .
" - don't edit it */\n\n";
- print A "#include \"nasm.h\"\n";
- print A "#include \"insns.h\"\n";
- print A "\n";
+
+ print A "#include \"insnsb.c\"\n\n";
foreach $i (@opcodes, @opcodes_cc) {
print A "static const struct itemplate instrux_${i}[] = {\n";
$aname = "aa_$i";
foreach $j (@$aname) {
- print A " $j\n";
+ print A " ", codesubst($j), "\n";
}
print A " ITEMPLATE_END\n};\n\n";
}
print D "/* This file auto-generated from insns.dat by insns.pl" .
" - don't edit it */\n\n";
- print D "#include \"nasm.h\"\n";
- print D "#include \"insns.h\"\n";
- print D "\n";
+
+ print D "#include \"insnsb.c\"\n\n";
print D "static const struct itemplate instrux[] = {\n";
$n = 0;
foreach $j (@big) {
- printf D " /* %4d */ %s\n", $n++, $j;
+ printf D " /* %4d */ %s\n", $n++, codesubst($j);
}
print D "};\n";
sub format {
my ($opcode, $operands, $codes, $flags) = @_;
my $num, $nd = 0;
+ my @bytecode;
return (undef, undef) if $operands eq "ignore";
$flags =~ s/(\|IF_ND|IF_ND\|)//, $nd = 1 if $flags =~ /IF_ND/;
$flags = "IF_" . $flags;
- ("{I_$opcode, $num, {$operands}, \"$codes\", $flags},", $nd);
+ @bytecode = (decodify($codes), 0);
+ push(@bytecode_list, [@bytecode]);
+ $codes = hexstr(@bytecode);
+
+ ("{I_$opcode, $num, {$operands}, \@\@CODES-$codes\@\@, $flags},", $nd);
+}
+
+#
+# Look for @@CODES-xxx@@ sequences and replace them with the appropriate
+# offset into nasm_bytecodes
+#
+sub codesubst($) {
+ my($s) = @_;
+ my $n;
+
+ while ($s =~ /\@\@CODES-([0-9A-F]+)\@\@/) {
+ my $pos = $bytecode_pos{$1};
+ if (!defined($pos)) {
+ die "$0: no position assigned to byte code $1\n";
+ }
+ $s = $` . "nasm_bytecodes+${pos}" . "$'";
+ }
+ return $s;
}
sub addprefix ($@) {
return @codes;
}
+# Turn a numeric list into a hex string
+sub hexstr(@) {
+ my $s = '';
+ my $c;
+
+ foreach $c (@_) {
+ $s .= sprintf("%02X", $c);
+ }
+ return $s;
+}
+
# Here we determine the range of possible starting bytes for a given
# instruction. We need only consider the codes:
# \1 \2 \3 mean literal bytes, of course