/ src / vm.c
vm.c
  1  #include <stdint.h>
  2  
  3  uint8_t EXTMEM[65536] = {0};
  4  
  5  uint16_t vm_pc;  // stored at INTMEM[32..33]
  6  uint32_t vm_b; // stored at INTMEM[2a..2d]
  7  uint32_t vm_a; // stored at INTMEM[2e..31]
  8  uint8_t vm_dptr; // originally points into extmem[0x7f00-0x7f40]
  9                   // now only indexes x7f_ints
 10  struct vm_flags { // stored at INTMEM[0x25]
 11      int sign:1;
 12      int zero:1;
 13      int carry:1;
 14      int pad:5;
 15  }
 16  
 17  // ops
 18  // 0x80    vm_ret
 19  // if op & 0x80
 20  //    if op == 0x80: quit
 21  //    else: lookuptable[op << 1]()
 22  // else:
 23  //    lookuptable[(op  >> 3) & 0x1e]()
 24  
 25  // hw regs
 26  // 0x7f00 - 0x7f40 16 * int32_t, or 4 byte fixed points
 27  int32_t x7f_ints[16];
 28  
 29  void vm_swapAB(void) {
 30     uint32_t tmp = vm_a;
 31     vm_a = vm_b;
 32     vm_b = tmp;
 33  }
 34  
 35  void vm_storeb@dptr(void) {
 36     // should only be called from ops without 0x80 bit set
 37     // otherwise dptr points into code not extmem 0x7fxx
 38     x7f_ints[vm_dptr]=vm_b;
 39  }
 40  
 41  void vm_overflow(bool carry) {
 42     vm_flags.carry |= carry; // 2db6..2dba
 43     vm_flags.zero = vm_b == 0; // 2dbc..2dc5
 44  }
 45  
 46  void vm_add(void) {
 47     vm_b+=vm_a;
 48     vm_overflow(vm_a > vm_b);
 49  }
 50  
 51  void vm_sub(void) {
 52     vm_b-=vm_a;
 53     vm_overflow(vm_a > vm_b);
 54  }
 55  
 56  void vm_abs(void) {
 57     if(vm_b<0) {
 58        vm_b = 0 - vm_b;
 59        vm_flags.sign = 0;
 60     }
 61  }
 62  
 63  void vm_print(void) {
 64     while(EXTMEM[vm_pc++]!='#') putc(EXTMEM[vm_pc-1]);
 65  }
 66  
 67  void fn2faf(byte acc) {
 68     putc(acc);
 69     vm_flags.carry = 0;
 70     vm_a = 0;
 71     vm_b = 0;
 72     while(1) {
 73        uint8_t c = getc();
 74        if(c<'0' || c>'9') break;
 75        putc(c);
 76        vm_b*=10; // handle overflow
 77        vm_b+=c-0x30;
 78     }
 79     //if(c!=0x5f) {
 80     //   if(c!=0xd) return;
 81        //uint8_t sp = 0x55; what is this?
 82     //   printf("Give number OR");
 83     //}
 84  }
 85  
 86  void fn2f1c(void) {
 87     if(vm_flags.carry==0) {
 88        putc(' ');
 89     } else {
 90        putc('@');
 91     }
 92     vm_a = vm_b;
 93     vm_abs();
 94     if(vm_flags.sign) putc('-');
 95     if(vm_b & 0x8000000 /*2c < 0 */) { //2f3e..2f40
 96        ((uint16_t*)(&vm_b))++; // only increment the upper half
 97     }
 98     uint8_t cf = 0;
 99     for(uint8_t r2 = 0x10; r2 > 0; r2--) {
100        
101     }
102  }
103  
104  void (*optable[])(void) = {
105     vm_swapAB,
106     vm_storeb@dptr,
107     vm_add,
108     vm_sub,
109     //,,
110     vm_storeb@dptrThenSwapAB,
111     //,,,,,,,,,
112     vm_abs,
113     // ,,
114     vm_print,
115  };
116  
117  void vm(uint16_t entrypoint) {
118     while(1) {
119        uint8_t op;
120        vm_pc = entrypoint;
121        uint8_t insn = EXTMEM[vm_pc++];
122        if(insn == 0x80) return;
123        // this check for 0x80 is implementd as jbc acc.7
124        // is acc.7 indeed & 0x80? msb0 or lsb0?
125        if((insn & 0x80) == 0) {
126           vm_dptr = insn & 0xf;
127           vm_a = x7f_ints[vm_dptr]; // 2ce6..2cf8
128           // the following limits the optable idx
129           // to 30 entries max
130           op = (insn >> 3) & 0x1e;
131        } else {
132           // clearing the top acc.7 bit because of jbc acc.7
133           // then rotating insn left by one is like shifting 1
134           op <<= 1; 
135        }
136        optable[op]();
137     }
138  }