VM1

All aspects of programming on the Commander X16.
Post Reply
rje
Posts: 1263
Joined: Mon Apr 27, 2020 10:00 pm
Location: Dallas Area

VM1

Post by rje »


I don't know if this is worth the effort.  I switch between being excited about it, and just feeling tired.

 

After failing to implement Lox using cc65 (Lox is just too powerful (https://craftinginterpreters.com/the-lox-language.html)), I then borrowed some ideas from http://c-jump.com/CIS77/CPU/IsaDesign/lecture.html and started writing an interpreter.

I wanted something... well something upon which I could build a slow but useful scripting language.

BUT I didn't want Lua's opcodes.  Why not??  Well I felt that perhaps it was not so well suited to the 6502.  Fixed opcode length is not space friendly.  Now I could just ADAPT the opcode set to be variable-length, to be friendlier to a 6502... 

Well anyway, here are my opcodes to "VM1".  They are of the form:

<OPCODE (3 bits)>. <register (2 bits)>. <modifier (3 bits)>

There are four general-purpose, 16 bit registers: A,B,C,D.  I'd want to map those to four of the extended "registers" in the X16's zero page, but I'm not sure.

Some instructions have a two byte operand following it.  For example, the jumps.

 

...I think I should probably have opcodes that load A, X, Y, and do a JSR...

 

 

#define OP_SPECIAL              0
#define OP_OR                   1
#define OP_AND                  2
#define OP_CMP                  3
#define OP_SUB                  4
#define OP_ADD                  5
#define OP_LOD                  6
#define OP_STO                  7

#define REG_A                   0       // LOD into these
#define REG_B                   1
#define REG_C                   2
#define REG_D                   3

#define MEM_A                   0       // STO into these
#define MEM_B                   1
#define MEM_C                   2
#define MEM_D                   3
#define MEM_BIND                4
#define MEM_BOFFSIND            5
#define MEM_OFFSIND             6
#define MEM_CONSTANT            7

#define SPECIAL_ZOP             0       // 000 Opcodes
#define SPECIAL_JMP             1
#define SPECIAL_NOT             2
#define SPECIAL_ILLEGAL         3

#define ZOP_ILLEGAL0            0       // Zero Operand Instructions
#define ZOP_ILLEGAL1            1
#define ZOP_ILLEGAL2            2
#define ZOP_HCF                 3       // Halt, Catch Fire
#define ZOP_ILLEGAL4            4
#define ZOP_ILLEGAL5            5
#define ZOP_ILLEGAL6           6
#define ZOP_PUTSTR            7       // prints string referenced from A (null terminated)

#define JEQ                     0       // Special Jumps
#define JNE                     1
#define JLT                     2
#define JLE                     3
#define JGT                     4
#define JGE                     5
#define JMP                     6
#define JUMP_ILLEGAL            7

 

 

My interpreter loop is mostly just a big ol' switch statement.

... for loop ... *ip gets us the current operator... and the operand, if any ...
      switch(ot.op)
      {
        case OP_OR:   printf("or\n");  r[ot.reg] |= val; break;
        case OP_AND:  printf("and\n"); r[ot.reg] &= val; break;
        case OP_CMP:  printf("cmp\n"); cmp_flag = (r[ot.reg] < val)? -1 : (r[ot.reg] > val); break;
        case OP_SUB:  printf("sub\n"); r[ot.reg] -= val; break;
        case OP_ADD:  printf("add\n"); r[ot.reg] += val; break;
...etc...

Post Reply