//
//  Copyright © 1997,1998 Forest Edge Software, All Rights Reserved
//
//  Program:    VAX Emulator, a "Virtual VAX" for Mac OS Computers
//
//  Author:     Tom Cole
//
//  Module:     vax.pch
//
//  Purpose:    This header file contains or links to the most commonly used
//              structure and symbol definitions for the emulator.  This is
//              included in every single compilation unit of the emulator.
//
//              Note that this is a ".pch" or pre-compiled header.  If changes
//              are made to this, it will be recompiled automatically for use
//              in subsequent builds.  Note that this is also the first compilation
//              unit in the "order of compilation" list in the project manager!
//
//
//  History:    02/23/98        Added uniform header
//              02/24/98        Rearranged elements, added blocking comments
//              09/24/98        Support floating parsing, change comment to ";"
//                                  and command separator to "\".
//              11/20/98        Added vm section to vax structure.
//
//              01/27/99        Added numerous small elements to the VAX
//                                  structure to support compiling CASE
//                                  pseudo-opcodes, and allowing forward
//                                  references in those expressions.
//              02/01/99        Rearranged struct VAX elements to create
//                                  natural alignments.

/*
 *  I N C L U D E S   F R O M   N A T I V E   E N V I R O N M E N T
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>




/*
 *  U T I L I T Y   A N D   D E B U G G I N G   M A C R O S
 */


//  Determine if this is a debug build or not.  Currently we do this
//  by seeing if the compiler is doing profiling, which is normally
//  turned on for DEBUG mode.

#if __profile__ == 1 
#define DEBUG
#endif


//  Macro to set condition bits based on comparing two values, done after
//  most instructions set the destination.

#define SETCONDITIONBITS( v1, v2 ) \
    { vax-> pslw.n = ( v1 < v2 ); vax-> pslw.z = ( v1 == v2 ); }


//  Specify the behavior of the ASSERT macro, which is empty in an
//  optimized build, and defined in a debug build. 


#ifdef DEBUG
#define ASSERT( cond, msg ) \
    if(!(cond)) { \
        printf( "!! Assertion failure %s\n", msg ); \
        return VAX_ASSERT; \
    }
#else
#define ASSERT( cond, msg )

#endif


//  Macro for creating global definitions.  In only one module (typically
//  the driver, the symbol GLOBAL is defined.  This makes GLOBALINIT macros
//  create the defining instance.  Otherwise, GLOBALINIT creates external
//  references instead.

#ifdef GLOBAL
#define GLOBALINIT( data_structure, init_value ) \
data_structure = init_value;
#else 
#define GLOBALINT( data_structure, init_value ) \
extern data_structure;
#endif

//  Architecture definitions go here.
//
//  BIGENDIAN   1 if big endian, else 0
//

#ifdef macintosh
#define BIGENDIAN 1

#else
#define BIGENDIAN 0

#endif


/*
 *  D E F I N E D   C O N S T A N T S
 */


//  Displacement size masks and names

#define K_NOFORWARD   -1        /* Flag means no forward reference allowed */

#define K_ADDR_SIZE   0x000F
#define K_ADDR_MODE   0x00F0

#define K_ADDR_BASE   0x0000
#define K_ADDR_B      0x0001
#define K_ADDR_W      0x0002
#define K_ADDR_L      0x0004
#define K_ADDR_Q      0x0008

#define K_DISP_BASE   0x0010

#define K_DISP_B      0x0011
#define K_DISP_W      0x0012
#define K_DISP_L      0x0014
#define K_DISP_Q      0x0018

#define K_BRANCH_BASE 0x0020

#define K_BRANCH_B    0x0021
#define K_BRANCH_W    0x0022
#define K_BRANCH_L    0x0024
#define K_BRANCH_Q    0x0028

#define K_CASE_BASE   0x0040
#define K_CASE_W      0x0042


//  Operand decoded locations, used to determine accessability for operands

#define OP_MEMORY       0x00            //  Operand reference memory location (MBZ!)
#define OP_REGISTER     0x01            //  Operand references VAX register
#define OP_TEMPORARY    0x03            //  Operand references temporary register 
                                        //      which means readonly and non-addressable
                                    
//  Machine exception names

#define EXC_UNUSED      0x00
#define EXC_CHECK       0x04        //  Machine check
#define EXC_KSNV        0x08        //  Kernel stack not valid
#define EXC_POWER       0x0C        //  Power failure
#define EXC_PRIV        0x10        //  Priveleged or reserved fault
#define EXC_CUSTOMER    0x14        //  Customer reserved instruction
#define EXC_RESOP       0x18        //  Reserved operand fault
#define EXC_RESADDR     0x1C        //  Reserved addressing mode fault
#define EXC_ACCVIO      0x20        //  Access control violation
#define EXC_TNV         0x24        //  Translation not valid
#define EXC_TP          0x28        //  Trace pending fault
#define EXC_BPT         0x2C        //  Breakpoint fault
#define EXC_COMPAT      0x30        //  Compatability mode fault (PDP-11)
#define EXC_ARITH       0x34        //  Arithmetic fault
#define EXC_CHMK        0x40        //  Change mode to kernel
#define EXC_CHME        0x44        //  Change mode to executive
#define EXC_CHMS        0x48        //  Change mode to supervisor
#define EXC_CHMU        0x4C        //  Change mode to user
#define EXC_SBI         0x50        //  SBI SILO COMPARE
#define EXC_CMRD        0x54        //  Corrected Memory read data
#define EXC_SBIALERT    0x58        //  SBI Alert
#define EXC_SBIFAULT    0x5C        //  SBI fault
#define EXC_MWT         0x60        //  Memory write timeout
#define EXC_SOFTWARE1   0x84        //  Software level 1
#define EXC_SOFTWARE2   0x88        //  Software level 2
#define EXC_SOFTWARE3   0x8C        //  Software level 3
#define EXC_SOFTWARE4   0x90        //  Software level 4
#define EXC_SOFTWARE5   0x94        //  Software level 5
#define EXC_SOFTWARE6   0x98        //  Software level 6
#define EXC_SOFTWARE7   0x9C        //  Software level 7
#define EXC_SOFTWARE8   0xA0        //  Software level 8
#define EXC_SOFTWARE9   0xA4        //  Software level 9
#define EXC_SOFTWARE10  0xA8        //  Software level 10
#define EXC_SOFTWARE11  0xAC        //  Software level 11
#define EXC_SOFTWARE12  0xB0        //  Software level 12
#define EXC_SOFTWARE13  0xB4        //  Software level 13
#define EXC_SOFTWARE14  0xB8        //  Software level 14
#define EXC_SOFTWARE15  0xBC        //  Software level 15
#define EXC_CONREAD     0xF8        //  Console read
#define EXC_CONWRITE    0xFC        //  Console write

//  Flags to describe symbols

#define SYM_NONE     0          /* No flags set */
#define SYM_ENTRY    0x0001     /* This symbol is an entry point */
#define SYM_FREFS    0x0002     /* This symbol has forward refs  */
#define SYM_LABEL    0x0004     /* This symbols is a label */
#define SYM_LOCAL    0x0008     /* This symbol was defined as a local */

//  Characteristics of the virutal VAX machine state

#define MAXREG      63          /* Number of registers, 0-15 architecturally */
                                /* defined, the rest are temporaries, etc.   */

#define MAXPRIVREG  63          /* Number of privileged registers */


//  Addressing mode values, used in handling opcode operands and
//  privileged register access modes.

#define OP_NL       0       // Operand not used
#define OP_RD       1       // Operand is readonly
#define OP_WR       2       // Operand is writeonly
#define OP_MD       3       // Operand is updated in place
#define OP_AD       4       // Operand is an address
#define OP_VA       5       // Operand is a variable bitfield address
#define OP_BR       6       // Operand is a displacement branch
#define OP_IM       7       // Operand is an implicit immediate operand

//  Access mode definitions for PSL, page tables, etc.

#define AM_KERNEL       0
#define AM_EXECUTIVE    1
#define AM_SUPERVISOR   2
#define AM_USER         3

//  Misc debug flags

#define DBG_SYMBOLS      0x00000001        // Symbol table debugging
#define DBG_DEBUG        0x00000002        // Invoke the native debugger if possible
#define DBG_MEMORY       0x00000004        // Debug memory
#define DBG_INTERRUPTS   0x00000008
#define DBG_EXCEPTIONS   0x00000010
#define DBG_VM           0x00000020        // Debug virtual memory mapping
#define DBG_TB           0x00000040        // Debug translation caching

#define DBG_P1           0x00010000        // Misc debugging flag 1
#define DBG_P2           0x00020000        // Misc debugging flag 1
#define DBG_P3           0x00040000        // Misc debugging flag 1
#define DBG_P4           0x00080000        // Misc debugging flag 1



//  Define the register mnemonics.  These are used as "vax-> NAME" where "vax" is
//  the handle to the virtual machine and "NAME" is the name of the register.

#define KSP             preg[ 0 ]
#define ESP             preg[ 1 ]
#define SSP             preg[ 2 ]
#define USP             preg[ 3 ]
#define ISP             preg[ 4 ]
#define P0BR            preg[ 8 ]
#define P0LR            preg[ 9 ]
#define P1BR            preg[ 10 ]
#define P1LR            preg[ 11 ]
#define SBR             preg[ 12 ]
#define SLR             preg[ 13 ]
#define PCBB            preg[ 16 ]
#define SCBB            preg[ 17 ]
#define IPL             preg[ 18 ]
#define ASTLVL          preg[ 19 ]
#define SIRR            preg[ 20 ]
#define SISR            preg[ 21 ]
#define ICCS            preg[ 24 ]
#define NICR            preg[ 25 ]
#define ICR             preg[ 26 ]
#define TODR            preg[ 27 ]
#define RXCS            preg[ 32 ]
#define RXDB            preg[ 33 ]
#define TXCS            preg[ 34 ]
#define TXDB            preg[ 35 ]
#define TBDR            preg[ 36 ]  /* 11/730 specific */
#define MAPEN           preg[ 56 ]
#define TBIA            preg[ 57 ]
#define TBIS            preg[ 58 ]
#define PMR             preg[ 61 ]
#define SID             preg[ 62 ]
#define TBCHK           preg[ 63 ]


//  Definitions for accessing the VAX register file

#define VAXREG( n )     reg[ n ]


//  Mnemonics for the first 6 temporary registers, used for
//  character instructions.

#define T0  VAXREG(16)
#define T1  VAXREG(17)
#define T2  VAXREG(18)
#define T3  VAXREG(19)
#define T4  VAXREG(20)
#define T5  VAXREG(21)


//  Mnemonics for the standard register file

#define R15 VAXREG(15)
#define R14 VAXREG(14)
#define R13 VAXREG(13)
#define R12 VAXREG(12)
#define R11 VAXREG(11)
#define R10 VAXREG(10)
#define R9  VAXREG(9)
#define R8  VAXREG(8)
#define R7  VAXREG(7)
#define R6  VAXREG(6)
#define R5  VAXREG(5)
#define R4  VAXREG(4)
#define R3  VAXREG(3)
#define R2  VAXREG(2)
#define R1  VAXREG(1)
#define R0  VAXREG(0)

//  Overloaded mnemonics for the pre-defined registers

#define PC  VAXREG(15)
#define SP  VAXREG(14)
#define FP  VAXREG(13)
#define AP  VAXREG(12)


//  Miscellaneous constants

#define CONSOLE_COMMENT         ';'         /*  Default comment delimiter   */
#define CONSOLE_SEPARATOR       '\\'        /*  Default command separator   */




/*
 *  S T R U C T U R E   D E F I N I T I O N S
 */

//  Forward branch resolutions.  This list is empty for symbols that are
//  resolved, and non-empty for forward references during an ASM block.

struct FSYMBOL { 
    struct FSYMBOL *    next;
    LONGWORD                location;
    LONGWORD                displacement;   /* 8, 16, or 32 */
};


//  This structure defines the symbol table used by the console

struct SYMBOL {
    struct SYMBOL *     next;       /* Linked list of all symbols */
    struct FSYMBOL *    forward;    /* Linked list of forward resolutions */
    LONGWORD                flags;
    LONGWORD                value;
    char                name[ 1 ];
};

//  This structure is used to create a list of break points

struct BREAKSTR {
    struct BREAKSTR *   next;
    ULONGWORD   pc;
};


//  This is the structure into which an instruction is decoded.  After decode
//  phase, the address list contains the real memory locations of each of the
//  operands, whether in the register file or in the physical memory array.

struct OPCODE {
    unsigned char   extended;           // Extended opcode value (normally zero)
    unsigned char   function;           // Opcode value
    short           index;              // Index into instruction array (normally same as function)
    LONGWORD            access;             // Operand access mode bit array
    unsigned char   count;              // Count of operands
    unsigned char * address[ 6 ];       // Resolved addresses of each operand
    LONGWORD            VAXaddr[ 6 ];       // VAX memory address for each operand
    char            size[ 6 ];          // Natural data size for each operand
    char            is_register[ 6 ];   // Flag indicating if register (vs. memory) operand
    char            name[ 128 ];        // Name of the instruction for disassembly/etc.
};



//  The processor status longword bit fields.

struct PSL_BITS {
    unsigned int        cm:1;       //  Compatibility mode (PDP-11)
    unsigned int        tp:1;       //  Trace pending
    unsigned int        mbz3:2;     
    unsigned int        fpd:1;      //  First part done
    unsigned int        is:1;       //  Interrupt stack
    unsigned int        cur_mod:2;  //  Current access mode
    unsigned int        prv_mod:2;  //  Previous access mode
    unsigned int        mbz2:1;
    unsigned int        ipl:5;      //  Interrupt priority level
    unsigned int        mbz1:8;
    unsigned int        dv:1;       //  Decimal overflow enable
    unsigned int        fu:1;       //  Floating underflow enable
    unsigned int        iv:1;       //  Integer overflow enable
    unsigned int        t:1;        //  Trace enable
    unsigned int        n:1;        //  Negative result
    unsigned int        z:1;        //  Zero result
    unsigned int        v:1;        //  Overflow result
    unsigned int        c:1;        //  Carry bit result


};

//  This is information used to timeslice; i.e. it helps the emulator know how
//  often to let other things run on the Mac so the emulator doesn't lock up
//  the system.  The cost of this, of course, is speed.  The quantum values
//  are expressed in VAX instructions; i.e. how many instructions do we let
//  execute before yielding?  We also yield on any console I/O operation.

struct QUANTUM {
    LONGWORD    initial;        //  Initial setting, zero means no yeild
    LONGWORD    current;        //  The current setting.
};

//  The processor status longword bit fields re-expressed as SHORT values for speed

struct PSL_W {
    ULONGWORD      cm;         //  Compatibility mode (PDP-11)
    ULONGWORD      tp;         //  Trace pending
    ULONGWORD      fpd;        //  First part done
    ULONGWORD      is;         //  Interrupt stack
    ULONGWORD      cur_mod;    //  Current access mode
    ULONGWORD      prv_mod;    //  Previous access mode
    ULONGWORD      ipl;        //  Interrupt priority level
    ULONGWORD      dv;         //  Decimal overflow enable
    ULONGWORD      fu;         //  Floating underflow enable
    ULONGWORD      iv;         //  Integer overflow enable
    ULONGWORD      t;          //  Trace enable
    ULONGWORD      n;          //  Negative result
    ULONGWORD      z;          //  Zero result
    ULONGWORD      v;          //  Overflow result
    ULONGWORD      c;          //  Carry bit result
};

//  Virtual memory accounting structure.  We have one of these for each region. 
//  They are set up by the VMINIT command, and are stored in the virtual machine
//  so a SHOW VM command can display them.

struct VMREGION {
    char            name[ 4 ];
    LONGWORD            pte_count, size;
    ULONGWORD   v_start, v_end;
    ULONGWORD   p_start, p_end;
};

//  The virtual machine state.  This is passed as the first parameter
//  to nearly every routine, allowing the virtual VAX to be stateless, 
//  and ultimately rednerable as a self-contained runtime library.

struct VAX {
    
    ULONGWORD reg[ MAXREG + 1];         // Registers, i.e. R0 is r[0], plus 48 temporaries
    ULONGWORD preg[ MAXPRIVREG + 1 ];   // Privileged registers 0-63
    
    LONGWORD            debug;          //  Misc debug flags go here.    


    struct PSL_W pslw;              //  Copy of psl bits as longs for speedy access.
    
    ULONGWORD   instruction_PC; //  The PC of the currently executing instruction
    LONGWORD    exception;              //  Last exception processed
    LONGWORD    timebase;               //  Used with TickCount to create TODR values.
    LONGWORD    treg;                   //  Index into reusable temporary registers

    LONGWORD    halted;                 //  Flagged when HALT occurs
    unsigned char * memory;         //  Address of physical memory, normally at first_word
    LONGWORD    memsize;                //  Size of physical memory
    
    struct FAULT {
        LONGWORD            code;           //  Exception code
        ULONGWORD   pc;             //  Faulting PC
        ULONGWORD   psl;            //  PSL at the time
        ULONGWORD   signal_args[7]; //  count, and up to 6 parameters
    } fault;
    
    struct QUANTUM  quantum;        //  Info on time slicing for emulator.

    struct CONSOLE {
    
        LONGWORD        radix;          //  Default radix for constants
        LONGWORD        disasm;         //  Disassembly flag on instruction execution
        LONGWORD        running;        //  Accepting commands?
        LONGWORD        verify;         //  Display .com files as executed?
        LONGWORD        assembler_mode; //  Active ASM mode?
        LONGWORD        singlestep;     //  Flagged when we single step
        LONGWORD        tbcache;        //  Do we do VM TB caching?
        LONGWORD        vmtrace;        //  Trace VM operations?
        LONGWORD        CALL_active;    //  Are we running under CALL console cmd?
        LONGWORD        CALL_PC;        //  Saved PC from CALL command
        LONGWORD        CALL_FP;        //  Saved FP from CALL command
        struct OPCODE opcode;       //  Used for DISASM command
        struct SYMBOL * system_symbols; // Predefined system symbol values.
        struct SYMBOL * symbols;    //  Symbol table for console
        struct SYMBOL * last_symbol;    //  last symbol found or set
        ULONGWORD   deposit;        //  Address of next deposit/assemble
        char        *scale;             //  Array of scale factors for each operand
        struct BREAKSTR * breakpoint_list;  // List of active breakpoints.
        LONGWORD        flags;          //  Misc console flags
        ULONGWORD min_deposit;  //  Lowest address data stored in
        ULONGWORD max_deposit;  //  Highest address data stored in
        ULONGWORD instruction_count; // Instruction count for TIME command
        char        comment;        //  Comment character
        char        separator;      //  Command separator character
        char      * prompt;         //  The command prompt string.
        LONGWORD        p0_deposit; 
        LONGWORD        s0_deposit;
    } console;

    struct ASM {
        LONGWORD        index;          //  Index into the instruction array we're working on.
        LONGWORD        opcount;        //  Which operand are we working on now?
        LONGWORD        scale;          //  Scale of item we are working on.
        LONGWORD        displacement;   //  For symbols, what displacement size are we using?
        ULONGWORD location;     //  For symbols, where will be put the data?
        LONGWORD        was_forward;    //  Last symbol was forward reference?
        LONGWORD        flags;          //  Misc assembler flags
        LONGWORD        case_base;      //  Start of .CASE blocks else zero
        char        cur_entry[64];  //  Current .entry we're using
        char        comment[ 64 ];  //  Buffer for disassembly comment, if any
    } assembler;


    struct VMREGION region[ 3 ];    //  Info about each VM region.
    LONGWORD            vm_initialized; //  Have we initialized VM?
    
    double          last_float;     //  Last floating value parsed
    
    union PSL {
        struct PSL_BITS     bit;    // references are vax-> psl.bit.v
        ULONGWORD   reg;        // or entire reg  vax-> psl.reg
    } psl;

    LONGWORD    first_word;             //  physical memory starts here
};




/*
 *  A D D I T I O N A L   I N C L U D E S
 */

//  Return code values

#include "vaxrc.h"

//  Routine prototypes


#include "vaxproto.h"
