Copyright (c) 2012 The Native Client Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that be
found in the LICENSE file.

************************************************************************
 NOTE: The Scons version of enuminst is documented in README_scons.txt.
 It has less functionality than the Makefile version.
************************************************************************

Exhaustive instruction enumeration test for x86 Native Client decoder.
Limited testing of validator.

This test performs an exhaustive enumeration of x86 instructions,
comparing two or more decoders. Specific decoders it can compare are:
   * the old Native Client production decoders (both 32- and 64-bit)
   * the new ragel-based Native Client decoders
   * the XED decoder from Intel

For each instruction enuminst can compare:
   * instruction validity (still being worked on in x86-32)
   * instruction length
   * opcodes (64-bit only)


Building enuminsts-32 and enuminsts-64

Enuminsts can be built in 32- and 64-bit variants using:
   % make BITS=32 clean enuminsts-64
   % make BITS=64 clean enuminsts-32
To build for Ragel use:
   % make BITS=64 RAGEL=1 clean enuminsts-64
The Makefile does not do proper dependency checking, so please use
a clean build. The build will fail if the required NaCl libraries
are not already built.

By default, the build assumes that you have downloaded a (Pin) version of
xed. See variable PINV in Makefile to see the version assumed.  You can
specify the xed on the command line, allowing use other versions of xed.

Running enuminsts
--------------------
The instructions that follow are for enuminsts-64; the same identical
instructions should work for enuminsts-32 as well.

Enuminsts requires that you specify one or more filters to indicate how
to process instructions produced by the enumeration. For example:
   % enuminsts-64 --legal=nacl --illegal=xed --print=xed
will filter instructions that decode for NaCl but don't decode for Xed,
and then uses Xed to print the instructions. You can induce additional
NaCl validation checking with the --nacllegal flag:
   % enuminsts-64 --nacllegal --illegal=nacl --legal=ragel --print=ragel
This causes enuminsts to apply limited validator checks (instruction
type) in addition to decoder problems.

Enuminsts-64 supports a --help option to see all command-line options:
   % ./enuminsts-32 --help


Testing against the NaCl baseline
---------------------------------
TODO(kschimpf): rewrite this section. It seems incorrect.

Included in this directory is (one or more) frozen versions of the
enumerator, named "enuminsts-XX-NNNNN" where XX in {32, 64}, and NNNNN
is the nacl revision number used to generate the executable.

The (shell) file "enuminsts-64-baseline" is a canned script that pipes
a run of "enuminsts-XX-NNNNN" into "enuminsts-64", using the input
decoder on the output generated by "enuminsts-XX-NNNNN". The command
line arguments to "enuminsts-64-baseline" are passed to the latter
executable "enuminsts-64".

To see possible (valid) arguments, run:

   .> ./enuminsts-64-baseline --help

The purpose of this run is that the baseline has been defined so that
it generates a large, valid set of x86-64 instructions, and then
(though enuminsts-64) allows you to run these instructions on any of
the valid decoders.

To run a decoder DDD on the set of (legal) baseline instructions, run:

  .> ./enuminsts-64-baseline --DDD

Note: you can add additional command line arguments. To see them, add
the "--Help" option to the command line.

Building enuminsts with a XED decoder
-------------------------------------

Before building enuminsts with a xed decoder, you must download
Intel's xed decoder, distributed as part of PIN. It is available for
free from

   http://www.pintool.org.

The default for the Makefile is PIN version 2.10-45467. However, any
version can be used if you specify "PINV=VVVVVVVVVVV" (where
VVVVVVVVVV is the PIN version you downloaded). To build enuminsts
with xed, run

   .> make BITS=XX PINV=VVVVVVVVVVV XED=1

where BITS in {32, 64} and VVVVVVVVVV is the PIN version you
downloaded. This will build the executable enuminsts-XX-xed.

Building a new baseline
-----------------------

To build a new baseline, you need to build a frozen executable
of the form enuminsts-XX-NNNNN by running the command:

   .> make BITS=64 NACLV=NNNNN

where NNNNN is the revision number of the corresponding generated NaCl
(scons) libraries. This will build executable
"enuminsts-64-NNNNN". You also need to build a copy of enuminsts with
a xed decoder (see "Building enuminsts with a xed decoder").

Once both executables have been built, edit shell file
enuminsts-64-legal to define the command line arguments you believe
will generate legal instructions, and pipe the corresponding opcode
sequences to the output (i.e. use options --opcode_bytes or
--opcode_bytes_plus_dec).

To test that you have generated the correct command line arguments,
run:
TODO(kschimpf): check this; looks wrong.
   .> ./enuminsts-64-baseline-test

This shell file will perform two runs of enuminsts-64-legal. The first
will compare the set of generated instructions against the xed decoder
to find instructions that are legal in both. The second will then
compare the set of generated instructions against the xed decoder to
find instructions that are not understood by xed.  If you have your
arguments right, no error messages will be reported in either step.

If enuminsts-64-baseline-test doesn't generate any errors, you have
found an acceptable new baseline, and you can install it. If you get
errors, but are only generated in the first pass, you can still use
enuminsts-64-baseline for the baseline. However, any instruction for
which an error is reported in the first pass, will not be generated by
the baseline.

If you get errors in the second pass (which tests if the generated
instructions are invalid according to xed), you need to change your
parameters in enuminsts-64-legal.  These errors represent bad
instruction opcodes that will be generated by the baseline.

Brad's Notes on testing Ragel:
------------------------------
enuminsts-64 --legal=nacl --legal=ragel
    Compare lengths of instructions that decode for both nacl and ragel.
    As of April 2012 there were a lot of these.

enuminsts-64 --illegal=nacl --legal=ragel --print=ragel
    Identifies instructions decoded by ragel but not by nacl

enuminsts-64 --legal=nacl --illegal=ragel --print=nacl
    Identifies instructions decoded by nacl but not by ragel

When Ragel supports a partial-validation mode, checking if a single
instruction might be legal (ignoring inter-instruction rules) these
tests should be useful:

enuminsts-64 --nacllegal --legal=nacl --illegal=ragel --print=ragel
      Print's instructions accepted by NaCl but not Ragel

enuminsts-64 --nacllegal --legal=ragel --illegal=nacl print=nacl
      Print's instructions legal for Ragel but not NaCl.
      Currently, no problems!

enuminsts-64 --nacl --ragel
      Compares instruction length only.
