NAME

NICE - a module to emulate, assemble and disassemble code for the NICE processor (NICE Is Charmingly Elegant)


VERSION

This documentation describes the first fully functional version 0.4.


SYNOPSIS

  # load module, import all functions
  use NICE qw/:all/;
  # some code as line array
  my @code = split /\n/, qq{
    MOVE R1 R0
    MOVE R1 0x125690CD
    HALT
  };
  # arrays for results, passed by reference
  my @bin = ();
  my @errors = ();
  # assemble
  if ( assemble(\@code, \@bin, \@errors) ) {
     print "$_\n" for @bin;
  } else {
     print "$_->{level}: $_->{text} line $_->{line}\n"
        for @errors;
  }
  # init memory and registers
  my $mem     = init_memory(0x800);
  my $reg     = init_registers();
  my $changed = {};
  # load assembled code into memory
  loadbin($mem, \@bin);
  # run program, dump data
  do {
     printf "%08X %08X\n", $_, $reg->[$_] for @$reg;
     print "\n";
     printf "%08X %08X\n", $_, $changed->{$_}
        for sort keys(%$changed);
  } until ( ! step($mem, $reg, $changed) );
  # disassemble from memory
  my @dcode = init_code($mem);
  disassemble($mem, \@dcode);
  printf "%08X %08X\n", $_, $dcode->[$_]
     for 0..$#{$mem};


DESCRIPTION

The NICE module provides functions to assemble, disassemble and run programs written for the NICE processor, an experimental processor designed by Bernd Ulmann <http://www.vaxman.de>.

An overview of the properties can be found at:

http://www.vaxman.de/projects/nice/nice.html


FUNCTIONS

init_registers()

Initializes an array with the 16 32-bit registers of the NICE processor (implemented as Bit::Vector objects). You will need them for executing instructions with the step function.

The return value is a reference to the registers array.

init_memory(<size>)

Initializes a memory array (an array of Bit::Vector objects) for subsequent use with the step or disassembler function. Size is the number of 32bit words to inlitialize.

The return value is a reference to the memory array.

init_code(<mem_aref>)

Initializes an array for storing disassembled code in. By passing it the array reference pointing at the memory, you will get an array with the same number of elements.

The return value is a reference to the code array.

loadbin(<mem_aref>, <bin_aref>)

Loads the binary data from the array referenced by bin_aref into the memory array referenced by mem_aref.

assemble(<coderef>, <binref>, <errorref>)

The assemble function assembles (Surprise, Surprise!) the NICE assembler code given in an array of lines. The result will be put in two corresponding arrays for the resulting binary (if the code could be assembled correctly) and the errors encountered.

The array elements of the binary array will contain one instruction or data word in NICE binary format. This is a simple string with a memory address and the instruction (8 hex nibbles each) separated by a space.

The array elements of the error array will be hashrefs referencing a hash with the structure:

   {
      level => <the errorlevel: 'error', 'warning' or 'info'>,
      text  => <the error description>,
      line  => <the line number, where the error occured>,
   }

In case of failure (one ore more errors with level 'error') the function will return undef and the code array will not be filled. Otherwise it will return a true value.

disassemble(<mem_aref>, <code_aref>, [<changed_mem_href>])

Disassembles code located in a memory array to a corresponding code array. You can disassemble instructions from specific memory locations by suppliying an additional hash with the memory addresses as keys.

This is escpecially useful in combination with the step function, that fills a reference to a hash with the memory addresses as keys and their instructions as values containig only those addresses changed by the last executing cycle.

step(<mem_aref>, <reg_aref>, <changed_mem_href>)

The step function executes (makes the appropriate changes to registers and memory for) the one instruction pointed to by the contents of the program counter in register 15.

If memory data is changed, the addresses and their values are put into the hash referenced by the third parameter. This is useful for displying data without the need for unnessesary refreshing (see disassemble).

It will return a false value if the instruction was a HALT instruction. Otherwise it will return a true value.


TODO

- disassemble from file, filehandle or scalar
- assemble from file, filehandle or scalar
- object interface?

There is no schedule for implementation


BUGS

Error checking in case of buggy or malformed data could be better.


AUTHOR

Bernd Ulmann <ulmann@vaxman.de>, Thomas Kratz <tkr@gnlpf.de>


COPYRIGHT

Copyright (c) 2004 Bernd Ulmann & Thomas Kratz. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.