modernc.org/ccgo/v3@v3.16.14/lib/testdata/CompCert-3.6/test/c/vmach.c (about) 1 /* A bytecode interpreter for a simple virtual machine */ 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 6 #define STACKSIZE 256 7 8 enum wordcode_instruct { 9 WCALL1, WCALL1_pop1, WCONST, WCONST_pop1, WBRANCHIF, WBRANCHIF_pop1, 10 WCALL3, WRETURN, WBRANCH, WLTINT, WADDINT, WOFFSETINT, WDUP, WGRAB, WSTOP 11 }; 12 13 #define Opcode (instr & 0xFF) 14 #define Byte1 ((instr >> 8) & 0xFF) 15 #define Byte2 ((instr >> 16) & 0xFF) 16 #define Byte3 (instr >> 24) 17 #define Op1 sp[Byte1] 18 #define Op2 sp[Byte2] 19 #define Op3 sp[Byte3] 20 #define Imm8s ((int)instr >> 24) 21 #define Imm16u (instr >> 16) 22 #define Imm16s ((int)instr >> 16) 23 #define Imm24u (instr >> 8) 24 #define Imm24s ((int)instr >> 8) 25 #define Adjust1 (sp += instr & 1) 26 #define Adjust2 (sp += instr & 3) 27 #define Adjustbyte1 (sp += Byte1) 28 #define Adjustbyte2 (sp += Byte2) 29 #define Adjustbyte3 (sp += Byte3) 30 #define Extrabyte1(w) (w & 0xFF) 31 #define Extrabyte2(w) ((w >> 8) & 0xFF) 32 #define Extrabyte3(w) ((w >> 16) & 0xFF) 33 #define Extrabyte4(w) (w >> 24) 34 #define Extraop1(w) sp[Extrabyte1(w)] 35 #define Extraop2(w) sp[Extrabyte2(w)] 36 #define Extraop3(w) sp[Extrabyte3(w)] 37 #define Extraop4(w) sp[Extrabyte4(w)] 38 #define Push1(x) \ 39 sp-=1, sp[0]=x 40 #define Push2(x,y) \ 41 sp-=2, sp[1]=x, sp[0]=y 42 #define Push3(x,y,z) \ 43 sp-=3, sp[2]=x, sp[1]=y, sp[0]=z 44 #define Push4(x,y,z,t) \ 45 sp-=4, sp[3]=x, sp[2]=y, sp[1]=z, sp[0]=t 46 #define Push5(x,y,z,t,u) \ 47 sp-=5, sp[4]=x, sp[3]=y, sp[2]=z, sp[1]=t, sp[0]=u 48 #define Push6(x,y,z,t,u,v) \ 49 sp-=6, sp[5]=x, sp[4]=y, sp[3]=z, sp[2]=t, sp[1]=u, sp[0]=v 50 #define Push7(x,y,z,t,u,v,w) \ 51 sp-=7, sp[6]=x, sp[5]=y, sp[4]=z, sp[3]=t, sp[2]=u, sp[1]=v, sp[0]=w 52 53 long stack[STACKSIZE]; 54 55 long wordcode_interp(unsigned int* code) 56 { 57 long * sp; 58 unsigned int * pc; 59 unsigned int instr; 60 int extra_args = 0; 61 62 sp = stack + STACKSIZE; 63 pc = code; 64 while (1) { 65 instr = *pc++; 66 switch (Opcode) { 67 68 case WCALL1: case WCALL1_pop1: { 69 long arg = Op1; 70 Adjust1; 71 Push3((long)pc, extra_args, arg); 72 pc += Imm16s; 73 extra_args = 0; 74 break; 75 } 76 case WCONST: case WCONST_pop1: { 77 Adjust1; 78 Push1(Imm24s); 79 break; 80 } 81 case WBRANCHIF: case WBRANCHIF_pop1: { 82 long arg = Op1; 83 Adjust1; 84 if (arg) pc += Imm16s; 85 break; 86 } 87 case WCALL3: { 88 unsigned int ext = *pc++; 89 long arg1 = Extraop1(ext); 90 long arg2 = Extraop2(ext); 91 long arg3 = Extraop3(ext); 92 Adjustbyte1; 93 Push5((long)pc, extra_args, arg3, arg2, arg1); 94 pc += Imm16s; 95 extra_args = 2; 96 break; 97 } 98 case WRETURN: { 99 long res = Op1; 100 Adjustbyte2; 101 if (extra_args > 0) { 102 printf("Over-application.\n"); 103 exit(2); 104 } else { 105 extra_args = sp[0]; 106 pc = (unsigned int *) sp[1]; 107 sp += 1; 108 *sp = res; 109 } 110 break; 111 } 112 case WBRANCH: { 113 Adjustbyte1; 114 pc += Imm16s; 115 break; 116 } 117 case WLTINT: { 118 long arg1 = Op1, arg2 = Op2; 119 Adjustbyte3; 120 Push1(arg1 < arg2); 121 break; 122 } 123 case WADDINT: { 124 long arg1 = Op1, arg2 = Op2; 125 Adjustbyte3; 126 Push1(arg1 + arg2); 127 break; 128 } 129 case WOFFSETINT: { 130 long arg = Op1; 131 Adjustbyte2; 132 Push1(arg + Imm8s); 133 break; 134 } 135 case WDUP: { 136 long arg = Op1; 137 Push1(arg); 138 break; 139 } 140 case WGRAB: { 141 int required = Byte1; 142 if (extra_args >= required) { 143 extra_args -= required; 144 } else { 145 printf("Partial application.\n"); 146 exit(2); 147 } 148 break; 149 } 150 case WSTOP: { 151 long res = Op1; 152 Adjustbyte2; 153 return res; 154 break; 155 } 156 } 157 } 158 } 159 160 #define I(a,b,c,d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24)) 161 162 unsigned int wordcode_fib[] = { 163 /* 0 */ I(WCONST, 30, 0, 0), 164 /* 1 */ I(WCALL1_pop1, 0, 3-1-1, 0), 165 /* 2 */ I(WSTOP, 0, 1, 0), 166 /* 3 */ I(WCONST, 2, 0, 0), 167 /* 4 */ I(WLTINT, 1, 0, 1), 168 /* 5 */ I(WBRANCHIF_pop1, 0, 12-5-1, 0), 169 /* 6 */ I(WOFFSETINT, 0, 0, -1), 170 /* 7 */ I(WCALL1_pop1, 0, 3-7-1, 0), 171 /* 8 */ I(WOFFSETINT, 1, 0, -2), 172 /* 9 */ I(WCALL1_pop1, 0, 3-9-1, 0), 173 /* 10 */ I(WADDINT, 0, 1, 2), 174 /* 11 */ I(WRETURN, 0, 2, 0), 175 /* 12 */ I(WCONST, 1, 0, 0), 176 /* 13 */ I(WRETURN, 0, 2, 0) 177 }; 178 unsigned int wordcode_tak[] = { 179 /* 0 */ I(WCONST, 6, 0, 0), 180 /* 1 */ I(WCONST, 12, 0, 0), 181 /* 2 */ I(WCONST, 18, 0, 0), 182 /* 3 */ I(WCALL3, 3, 6-3-2, 0), 183 /* 4 */ I(0, 1, 2, 0), 184 /* 5 */ I(WSTOP, 0, 1, 0), 185 /* 6 */ I(WGRAB, 2, 0, 0), /* z y x */ 186 /* 7 */ I(WLTINT, 1, 0, 0), /* z y x (y<x) */ 187 /* 8 */ I(WBRANCHIF_pop1, 0, 11-8-1, 0), 188 /* 9 */ I(WDUP, 2, 0, 0), 189 /* 10 */ I(WRETURN, 0, 4, 0), 190 /* 11 */ I(WOFFSETINT, 0, 0, -1), /* z y x (x-1) */ 191 /* 12 */ I(WCALL3, 1, 6-12-2, 0), 192 /* 13 */ I(0, 2, 3, 0), /* z y x tx */ 193 /* 14 */ I(WOFFSETINT, 2, 0, -1), /* z y x tx (y-1) */ 194 /* 15 */ I(WCALL3, 1, 6-15-2, 0), 195 /* 16 */ I(0, 4, 2, 0), /* z y x tx ty */ 196 /* 17 */ I(WOFFSETINT, 4, 0, -1), /* z y x tx ty (z-1) */ 197 /* 18 */ I(WCALL3, 1, 6-18-2, 0), 198 /* 19 */ I(0, 3, 4, 0), /* z y x tx ty tz */ 199 /* 20 */ I(WCALL3, 3, 6-20-2, 0), 200 /* 21 */ I(2, 1, 0, 0), /* z y x res */ 201 /* 22 */ I(WRETURN, 0, 4, 0), 202 }; 203 204 int main(int argc, char ** argv) 205 { 206 printf("fib(30) = %ld\n", wordcode_interp(wordcode_fib)); 207 printf("tak(18, 12, 6) = %ld\n", wordcode_interp(wordcode_tak)); 208 209 return 0; 210 } 211