The University of Queensland Homepage
School of ITEE ITEE Main Website

 Using the New Jersey Machine Code Toolkit
The Binary Translation Group have installed version 0.5 of the New Jersey Machine Code Toolkit. To use the toolkit, you just need to add it to your path:
PATH=$PATH:/net/olympic/u6/olympic/tools/NJ/base
Make sure that the old version is NOT in your path:
/homes/ldl/nj/base
You use the toolkit in your makefiles as just "tools". For further information, see the main toolkit page at this web address.

You may wish to copy the mclib.h file from here to your work directory, or else make sure you have a "-I /net/olympic/u6/olympic/tools/NJ/base" in your makefiles, so gcc can find mclib.h.

Making the toolkit

To make the toolkit, you first need to set up icon. To do this, temporarily set these environment variables:
PATH=$PATH:/net/olympic/u6/olympic/tools/icon/icon.9.3
IPATH=/net/olympic/u6/olympic/tools/icon/icon.9.3/lib
LPATH=/net/olympic/u6/olympic/tools/icon/icon.9.3/include
FPATH=/net/olympic/u6/olympic/tools/icon/icon.9.3/bin
Then you can switch to the New Jersey Toolkit directory, and perform the following steps:
cd /net/olympic/u6/olympic/tools/ NJ/base
icont tools
gcc -c -I. mclib.c
Check that all is well by typing "tools -v"; this should display a usage summary.

Using the Indirect Decoders

Norman has added special switches for our purposes. This causes the toolkit to generate a decoder that returns a special struct with a ".tag" field and a union of all the information that you might need about the instruction.

To generate the decoder, you first need some help files, usually called <machine>-enc.c and .h . You generate these with the -data, -encoder and -indirect options, like this:

sparc-enc.c: sparc-enc.h
        # sparc-dis.c will be generated at the same time as sparc-dis.h

sparc-enc.h:
        ${TOOLKIT} -no-reloc -verbose -data -indirect sprk\:sparcConst \
        -encoder sparc-enc ${SPECS}
The -indirect sprk:sparcConst argument means to generate a variable called sprk of type sparcConst which is a large struct of pointers to functions. There will be one function for each instruction.

Now you need a decoder, which is generated as follows:

sparc-dis.c: sparc-dis.m
        ${TOOLKIT} -no-reloc -verbose -data \
        -matcher sparc-dis.m -decoder sparc-dis.c ${SPECS} sparc-dis.spec 
sparc-dis.m:
        ${TOOLKIT} -no-reloc -verbose -data -indirect sprk\:sparcConst \
        -symdis sparc-dis ${SPECS}
        mv sparc-dis.m sparc-dis-temp.m
        sed "/^  | sethi(/d" < sparc-dis-temp.m > sparc-dis.m
        # Could rm sparc-dis-temp here if all is well
This generates a matcher file, then translates the matcher file into a source (.c) file. Note that there is presently a bug that requires the sethi match statement to be removed, and this is done by the sed line.

To use all this, you need a piece of code something like this:

  instruction_Instance sprk;

  while (!feof(f))
  {
    uOrgPC = gLogPC;
    inst = disassemble_instruction(gLogPC, sprk);
    sparc_semant(inst, uOrgPC);
  }
The function disassemble_instruction is generated for you in sparc-dis.c. You have to write a module (say sparc-semant.c) with the function sparc_semant() which might look like this:
#include "sparc-enc.h"

void sparc_semant(instruction_Instance inst, unsigned gLogPC)
{
  switch(inst.tag)
  {
    case LDUB_TAG:
      printf("%08X\tldub\t[", gLogPC);
      printaddr(inst.u.LDUB.address);
      printf("],");
      printreg(inst.u.LDUB.rd);
      printf("\n");
      break;

    case JMPL_TAG:
      printf("%04X\tjmpl\t", gLogPC);
      printaddr(inst.u.JMPL.address_);
      printf(", ");
      printreg(inst.u.JMPL.rd);
      break;

    default:
      printf("%04X\tmov\t", gLogPC);
      printf("Undecoded instruction\n");
  }
}
You may also have to provide the disassembler with a function fetch that takes a logical PC and a number of bits. For example, the first call to an i386 fetch function disassembling a .com file would have the arguments 0x100 and 8. Beware of endianness in this function! For the toolkit version 0.5, you will need a fetch function according to your disassembler spec.