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 }