f35805c2c5/vm/graphical/vm.c

User picture

Commiter: Charles Childers

Author: Charles Childers

Revision: f35805c2c5


File Size: 11.5 KB

(March 08, 2010 02:15 UTC) About 2 years ago

no core words in 32-128 address range; all C implementations updated with implicit calls

 
Show/hide line numbers
/******************************************************
 * Ngaro
 * Copyright (C) 2008 - 2010, Charles Childers
 ******************************************************/

#include "functions.h"
#include "vm.h"

#include "SDL.h"

/* Variables specific to the VM */
VM_STATE vm;



/******************************************************
 *|F| void init_vm()
 *
 * This zeros out everything in the VM_STATE struct
 * to give us a known starting point.
 ******************************************************/
void init_vm()
{
   int a;
   vm.ip = vm.sp = vm.rsp = 0;
   for (a = 0; a < STACK_DEPTH; a++)
      vm.data[a] = 0;
   for (a = 0; a < ADDRESSES; a++)
      vm.address[a] = 0;
   for (a = 0; a < IMAGE_SIZE; a++)
      vm.image[a] = 0;
   for (a = 0; a < 1024; a++)
      vm.ports[a] = 0;
}



/******************************************************
 *|F| void vm_process()
 *
 * This is a simple switch-based processor with one
 * case for each opcode. It's not the fastest approach,
 * but is easy enough to follow, add on to, and works
 * well enough for my current needs.
 ******************************************************/
void vm_process(int opcode) {
  int a, b;

  switch(opcode)
  {
    /***************************************************/
    /* NOP    Does Nothing. Used for padding           */
    /* Opcode: 0        Stack:  -       Address: -     */
    case VM_NOP:
         break;

    /***************************************************/
    /* LIT    Push the value in the following cell to  */
    /*        the stack                                */
    /* Opcode: 1 n      Stack: -n       Address: -     */
    case VM_LIT:
         vm.sp++;
         vm.ip++;
         TOS = vm.image[vm.ip];
         break;

    /***************************************************/
    /* DUP    Duplicate the value on the top of the    */
    /*        stack                                    */
    /* Opcode: 2        Stack: n-nn     Address: -     */
    case VM_DUP:
         vm.sp++;
         vm.data[vm.sp] = NOS;
         break;

    /***************************************************/
    /* DROP   Drop the value on the top of the stack   */
    /* Opcode: 3        Stack: n-       Address: -     */
    case VM_DROP:
         DROP
         break;

    /***************************************************/
    /* SWAP   Exchange the top two values on the stack */
    /* Opcode: 4        Stack: xy-yx    Address: -     */
    case VM_SWAP:
         a = TOS;
         TOS = NOS;
         NOS = a;
         break;

    /***************************************************/
    /* PUSH   Move the top value on the stack to the   */
    /*        address stack. Remove it from the data   */
    /*        stack.                                   */
    /* Opcode: 5        Stack: n-       Address: -n    */
    case VM_PUSH:
         vm.rsp++;
         TORS = TOS;
         DROP
         break;

    /***************************************************/
    /* POP    Move the top value from the address      */
    /*        stack to the data stack. Remove it from  */
    /*        the address stack.                       */
    /* Opcode: 6        Stack: -n       Address: n-    */
    case VM_POP:
         vm.sp++;
         TOS = TORS;
         vm.rsp--;
         break;

    /***************************************************/
    /* CALL   Call a subroutine whose address is given */
    /*        in the following cell. Push the address  */
    /*        following this instruction to the address*/
    /*         stack.                                  */
    /* Opcode: 7 a       Stack: -      Address: -a     */
    case VM_CALL:
         vm.ip++;
         vm.rsp++;
         TORS = vm.ip;
         vm.ip = vm.image[vm.ip] - 1;
         if (vm.image[vm.ip+1] == 0)
         {
           vm.ip++;
         }
         if (vm.image[vm.ip+1] == 0)
         {
           vm.ip++;
         }
         break;

    /***************************************************/
    /* JUMP   Unconditional jump to the address given  */
    /*        in the following cell.                   */
    /* Opcode: 8 a       Stack: -       Address: -     */
    case VM_JUMP:
         vm.ip++;
         vm.ip = vm.image[vm.ip] - 1;
#ifdef EXPERIMENTAL
         if (vm.image[vm.ip+1] == 0)
         {
           vm.ip++;
         }
         if (vm.image[vm.ip+1] == 0)
         {
           vm.ip++;
         }
#endif
         break;

    /***************************************************/
    /* ;      Return from a subroutine. Control is     */
    /*        passed to the address on the top of the  */
    /*        address stack.                           */
    /* Opcode: 9         Stack: -       Address: a-    */
    case VM_RETURN:
         vm.ip = TORS;
         vm.rsp--;
         break;

    /***************************************************/
    /* >JUMP  Jump to the address in the following     */
    /*        cell if NOS > TOS.                       */
    /* Opcode: 10 a      Stack: xy-     Address: -     */
    case VM_GT_JUMP:
         vm.ip++;
         if(NOS > TOS)
           vm.ip = vm.image[vm.ip] - 1;
         DROP DROP
         break;

    /***************************************************/
    /* <JUMP  Jump to the address in the following     */
    /*        cell if NOS < TOS.                       */
    /* Opcode: 11 a      Stack: xy-     Address: -     */
    case VM_LT_JUMP:
         vm.ip++;
         if(NOS < TOS)
           vm.ip = vm.image[vm.ip] - 1;
         DROP DROP
         break;

    /***************************************************/
    /* !JUMP  Jump to the address in the following     */
    /*        cell if NOS <> TOS.                      */
    /* Opcode: 12 a      Stack: xy-     Address: -     */
    case VM_NE_JUMP:
         vm.ip++;
         if(TOS != NOS)
           vm.ip = vm.image[vm.ip] - 1;
         DROP DROP
         break;

    /***************************************************/
    /* =JUMP  Jump to the address in the following     */
    /*        cell if NOS = TOS.                       */
    /* Opcode: 13 a      Stack: xy-     Address: -     */
    case VM_EQ_JUMP:
         vm.ip++;
         if(TOS == NOS)
           vm.ip = vm.image[vm.ip] - 1;
         DROP DROP
         break;

    /***************************************************/
    /* @      Fetch a value from a memory location     */
    /* Opcode: 14        Stack: a-n     Address: -     */
    case VM_FETCH:
         TOS = vm.image[TOS];
         break;

    /***************************************************/
    /* !      Store a value to a memory location       */
    /* Opcode: 15        Stack: na-     Address: -     */
    case VM_STORE:
         vm.image[TOS] = NOS;
         DROP DROP
         break;

    /***************************************************/
    /* +      Add TOS and NOS, leaving the result      */
    /* Opcode: 16        Stack: xy-z    Address: -     */
    case VM_ADD:
         NOS += TOS;
         DROP
         break;

    /***************************************************/
    /* -      Subtract TOS from NOS, leaving the result*/
    /* Opcode: 17        Stack: xy-z    Address: -     */
    case VM_SUB:
         NOS -= TOS;
         DROP
         break;

    /***************************************************/
    /* *      Multiply TOS by NOS, leaving the result  */
    /* Opcode: 18        Stack: xy-z    Address: -     */
    case VM_MUL:
         NOS *= TOS;
         DROP
         break;

    /***************************************************/
    /* /MOD   Divide NOS by TOS, leaving the quotient  */
    /*        and remainder.                           */
    /* Opcode: 19        Stack: xy-qr   Address: -     */
    case VM_DIVMOD:
         a = TOS;
         b = NOS;
         TOS = b / a;
         NOS = b % a;
         break;

    /***************************************************/
    /* AND    Perform a bitwise and operation on TOS   */
    /*        and NOS.                                 */
    /* Opcode: 20        Stack: xy-z    Address: -     */
    case VM_AND:
         a = TOS;
         b = NOS;
         DROP
         TOS = a & b;
         break;

    /***************************************************/
    /* OR     Perform a bitwise or operation on TOS    */
    /*        and NOS.                                 */
    /* Opcode: 21        Stack: xy-z    Address: -     */
    case VM_OR:
         a = TOS;
         b = NOS;
         DROP
         TOS = a | b;
         break;

    /***************************************************/
    /* XOR    Perform a bitwise xor operation on TOS   */
    /*        and NOS.                                 */
    /* Opcode: 22        Stack: xy-z    Address: -     */
    case VM_XOR:
         a = TOS;
         b = NOS;
         DROP
         TOS = a ^ b;
         break;

    /***************************************************/
    /* <<    Shift NOS left by TOS bits.               */
    /* Opcode: 23        Stack: xy-z    Address: -     */
    case VM_SHL:
         a = TOS;
         b = NOS;
         DROP
         TOS = b << a;
         break;

    /***************************************************/
    /* >>    Shift NOS right by TOS bits.              */
    /* Opcode: 24        Stack: xy-z    Address: -     */
    case VM_SHR:
         a = TOS;
         b = NOS;
         DROP
         TOS = b >>= a;
         break;

    /***************************************************/
    /* 0;    Return from a subroutine if TOS = 0.      */
    /*       If TOS = 0, DROP TOS.                     */
    /*       If TOS <> 0, do nothing                   */
    /* Opcode: 25         Stack: n-     Address: a-    */
    /*                    Stack: n-n    Address: -     */
    case VM_ZERO_EXIT:
         if (TOS == 0)
         {
           DROP
           vm.ip = TORS;
           vm.rsp--;
         }
         break;

    /***************************************************/
    /* 1+    Increase TOS by 1                         */
    /* Opcode: 26        Stack: x-y     Address: -     */
    case VM_INC:
         TOS += 1;
         break;

    /***************************************************/
    /* 1-    Decrease TOS by 1                         */
    /* Opcode: 27        Stack: x-y     Address: -     */
    case VM_DEC:
         TOS -= 1;
         break;

    /***************************************************/
    /* IN    Read a value from an I/O port             */
    /* Opcode: 28        Stack: p-n     Address: -     */
    case VM_IN:
         a = TOS;
         TOS = vm.ports[a];
         vm.ports[a] = 0;
         break;

    /***************************************************/
    /* OUT   Send a value to an I/O port               */
    /* Opcode: 29        Stack: np-     Address: -     */
    case VM_OUT:
         vm.ports[0] = 0;
         vm.ports[TOS] = NOS;
         DROP DROP
         break;

    /***************************************************/
    /* WAIT  Wait for an I/O event to occur.           */
    /* Opcode: 30        Stack: -       Address: -     */
    case VM_WAIT:
         handle_devices(0);
         break;

    /***************************************************/
    /* IMPLICIT CALL                                   */
    /* If we don't recognize the opcode, treat it as a */
    /* subroutine address and CALL it.                 */
    /* Opcode: * a       Stack: -      Address: -a     */
    default:
         vm.rsp++;
         TORS = vm.ip;
         vm.ip = vm.image[vm.ip] - 1;
         if (vm.image[vm.ip+1] == 0)
         {
           vm.ip++;
         }
         if (vm.image[vm.ip+1] == 0)
         {
           vm.ip++;
         }
         break;
  }
}