# SIMPle VIRtual machine (SIMPVIR)

All data used in defining simpvir is 32 bit integers or 32 bit integer arrays. Simpvir is stack based. A given simpvir program can mimick a heap by defining arrays as global variables placed at the top of the stack. The stack size is 22000000 (88MB) to accomodate the schant scheme vm. The assembler mnemonics for simpvir laid out in the following discussion have the form of scheme s-expressions. A return_stack is defined for saving return addresses of function and procedure calls. Its size is arbitrarily set to 50000. A program counter (pc) starts at 0, indexing bytecodes (really 32 bit integers) in a code array arbitrarily set at size 50000. frame_start indexes the current stack frame. It is changed on function or procedure entry and exit.

## Binary Numeric Opcodes

Perform the specified binary numeric operation on the second from the top stack operand x with the top of the stack operand y. Pop the top two operands and push the result.

      (add)
      Opcode value: 9
      The result is x + y

      (sub)
      Opcode value: 10
      The result is x - y

      (mul)
      Opcode value: 11
      The result is x * y

      (div)
      Opcode value: 12
      The result is x / y

      (mod)
      Opcode value: 13
      The result is x % y

      (shl)
      Opcode value: 16
      The result is x << y

      (shr)
      Opcode value: 17
      The result is x >> y

      (bitor)
      Opcode value: 18
      The result is x | y

      (bitand)
      Opcode value: 19
      The result is x & y

      (bitxor)
      Opcode value: 45
      The result is x ^ y

      (and)
      Opcode value: 31
      x and y are either 0 or 1. The result is
      the logical and of x and y.

      (or)
      Opcode value: 32
      x and y are either 0 or 1. The result is
      the logical or of x and y.

## Binary Numeric Predicate Opcodes

Perform the specified numeric predicate binary operation on the second from the top stack operand x with the top of the stack operand y. If the comparison is true the result is 1. If the comparison is false the result is 0. Pop the top two operands and push the result.

      (eq)
      Opcode value: 24
      The result is x == y

      (lt)
      Opcode value: 25
      The result is x < y

      (gt)
      Opcode value: 26
      The result is x > y

      (le)
      Opcode value: 27
      The result is x <= y

      (ge)
      Opcode value: 28
      The result is x >= y

      (ne)
      Opcode value: 29
      The result is x != y

## Unary Numeric Opcodes

Perform the specified unary numeric operation with the top of the stack operand x. Pop the top operand and push the result.

      (abs)
      Opcode value: 14
      The result is the absolute value of x

      (negate)
      Opcode value: 15
      The result is the negative value of x

      (bitnot)
      Opcode value: 20
      The result is the binary ones complement value of x

      (not)
      Opcode value: 30
      If x is 1 the result is 0. If x is 0
      the result is 1.

## Branching Opcodes

      (btr n)
      Opcode value: 21
      Pop the condition code off the top of the stack.
      If the condition code is positive branch to index n otherwise
      execute the next instruction.

      (bfl n)
      Opcode value: 22
      Pop the condition code off the top of the stack.
      If the condition code is 0 branch to index n otherwise
      execute the next instruction.

      (br n)
      Opcode value: 23
      Branch to index n.

      (call n)
      Opcode value: 33
      Push the index of the instruction following the call on the return stack.
      Branch to index n.

      (return)
      Opcode value: 34
      Pop the return index off the top of the return stack. Branch
      to the return index.

      (exit)
      Opcode value: 39
      Terminate execution of the program.

      (brtable (i0 j0) (i1 j1) ... (in-1 jn-1))
      Opcode value: 41
      This opcode implements a mult-case branch table with
      n choices. The branch selector is i. i ranges from 0 to n-1. Pop the
      selector i off the top of the stack. Branch to the j sub
      i table choice.

## Stack Opcodes

      (push n)
      Opcode value: 7
      Push the value n on the top of the stack.

      (pop)
      Opcode value: 8
      Pop the top of the stack.
      Do nothing with the popped value.

      (stack-ref)
      Opcode value: 5
      Set n to the value on the top of the stack.
      Replace the top of the stack with the value in the stack at index n.

      (stack-set)
      Opcode value: 6
      Pop the top of the stack into n.
      Pop the next value on the stack into val.
      Set the stack value indexed by n to val.

## Stack Frame Opcodes

      (top-level-begin start offset)
      Opcode value: 0
      This is among the first opcodes a program should encounter.
      Set frame_start to start which is 0 and is the initial index into
      the stack. Set the top of the stack index to offset. This effectively
      sets aside storage on the stack for all global variables. They are in the
      range 0 .. offset - 1.

      (function-proc-begin n_formal_parameters n_vars dyn_link_offset)
      Opcode value: 1
      n_formal_parameters is the number of formal parameters in the function
      or procedure call.
      Associated actual parameters are at the begining of the stack frame indexed
      by frame_start. n_vars is the number of combined stack slots for the
      actual parameters, local variables and one slot for saving the value of
      frame_start upon function call into the dynamic link. dyn_link_offset
      is the offset for accessing the dynamic link on the stack frame. When the
      function completes the frame_start is restored from the value of
      the dynamic link. Note that the value of dyn_link_offset is always one less
      than n_vars.

      (function-end dyn_link_offset)
      Opcode value: 2
      dyn_link_offset is the offset for accessing the dynamic link on the stack
      frame. When the function completes the frame_start is restored from
      the value of the dynamic link. The function return value is assumed to have
      been saved in the first slot of the stack frame when this opcode completes.

      (proc-end dyn_link_offset)
      Opcode value: 3
      dyn_link_offset is the offset for accessing the dynamic link on the stack
      frame. When the procedure completes the frame_start is restored from
      the value of the dynamic link.

      (frame-offset)
      Opcode value: 4
      Opcode deprecated.

      (stack-ref-n n)
      Opcode value: 42
      Set idx to n + frame_start.
      Set val to the stack value
      indexed by idx. Push val on the top of the stack.

      (stack-set-n n)
      Opcode value: 43
      Set idx to n + frame_start.
      Pop the top of the stack
      into val. Set the stack value indexed by idx to val.

## I/O Opcodes

      (read-char)
      Opcode value: 35
      If the end of file has been reached do nothing. Read a character from
      standard input. Push -1 on the top of the stack if an end of file is reached
      and indicate that the end of file is reached, otherwise push the read
      character on the top of the stack.

      (eof-object?)
      Opcode value: 36
      If an end of file has been reached from a prior read-char the
      result is 1 otherwise 0. Push the result on the top of the stack.

      (display)
      Opcode value: 37
      Print the value of the integer on the top of the stack
      to standard output.
      Pop the top of the stack.

      (newline)
      Opcode value: 38
      Print a newline character to standard output.

      (write-char)
      Opcode value: 40
      Print the ascii character on the top of the stack to standard output.
      Pop the top of the stack.

      (write-string n)
      Opcode value: 44
      Print n ascii characters starting from the top of the stack to standard
      output. The characters are packed two to a 32 bit integer.  Pop each block
      of two characters from the top of the stack after it is printed.

## Usage

To execute a file consisting of simpvir bytecodes do.

./simpvir < bytecodes

The first word in bytcodes is the number of bytecodes to follow.