Created
July 19, 2019 11:39
-
-
Save chfast/efe66fe59cca075858925eeef4737281 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdio.h> | |
#include <time.h> | |
int32_t interp(unsigned char *code, int initval) | |
{ | |
int pc = 0; | |
int32_t val = initval; | |
while(1) { | |
switch(code[pc++]) { | |
case 0: | |
return val; | |
case 1: | |
val++; | |
break; | |
case 2: | |
val--; | |
break; | |
case 3: | |
val *= 2; | |
break; | |
case 4: | |
val /= 2; | |
break; | |
case 5: | |
val += 3; | |
break; | |
case 6: | |
val = -val; | |
break; | |
case 7: | |
val %= code[pc++]; | |
break; | |
case 8: | |
{ | |
int label = code[pc++]; | |
if (!val) | |
pc = label; | |
break; | |
} | |
case 9: | |
{ | |
int cond = code[pc++]; | |
int label1 = code[pc++]; | |
int label2 = code[pc++]; | |
if (val < cond) | |
pc = label1; | |
else | |
pc = label2; | |
break; | |
} | |
} | |
} | |
return val; | |
} | |
int32_t interp_cgoto2(unsigned char* code, int initval) | |
{ | |
static void* dispatch_table[] = { &&do_halt, &&do_inc, &&do_dec, &&do_mul2, | |
&&do_div2, &&do_add7, &&do_neg, &&do_mod, &&do_jmpz, &&do_jmplt }; | |
int pc = 0; | |
int32_t val = initval; | |
goto *dispatch_table[code[pc++]]; | |
while (1) { | |
do_halt: // 0 | |
return val; | |
do_inc: // 1 | |
val++; | |
goto *dispatch_table[code[pc++]]; | |
continue; | |
do_dec: // 2 | |
val--; | |
goto *dispatch_table[code[pc++]]; | |
continue; | |
do_mul2: // 3 | |
val *= 2; | |
goto *dispatch_table[code[pc++]]; | |
continue; | |
do_div2: // 4 | |
val /= 2; | |
goto *dispatch_table[code[pc++]]; | |
continue; | |
do_add7: // 5 | |
val += 3; | |
goto *dispatch_table[code[pc++]]; | |
continue; | |
do_neg: // 6 | |
val = -val; | |
goto *dispatch_table[code[pc++]]; | |
continue; | |
do_mod: // 7 | |
val %= code[pc++]; | |
goto *dispatch_table[code[pc++]]; | |
continue; | |
do_jmpz: // 8 | |
{ | |
int label = code[pc++]; | |
if (!val) | |
pc = label; | |
goto *dispatch_table[code[pc++]]; | |
continue; | |
} | |
do_jmplt: // 9 | |
{ | |
int cond = code[pc++]; | |
int label1 = code[pc++]; | |
int label2 = code[pc++]; | |
if (val < cond) | |
pc = label1; | |
else | |
pc = label2; | |
goto *dispatch_table[code[pc++]]; | |
continue; | |
} | |
} | |
} | |
int main(int argc, char *argv[]) { | |
unsigned char code[] = { | |
1, // inc | |
// start: | |
1, // inc | |
9, 0, 6, 0, // jmplt(0, end, start) | |
// end: | |
0, // hlt | |
}; | |
// printf("Calc finish: %x\n", interp(code, 0)); | |
// printf("Calc finish: %x\n", interp_cgoto2(code, 0)); | |
clock_t start, finish; | |
double cpu_time_used; | |
start = clock(); | |
for (int i = 0; i < 4; i++) | |
printf("%x\n", interp_cgoto2(code, 0)); | |
finish = clock(); | |
cpu_time_used = ((double) (finish - start)) / CLOCKS_PER_SEC; | |
printf("CGOTO took: %f\n", cpu_time_used); | |
start = clock(); | |
for (int i = 0; i < 4; i++) | |
printf("%x\n", interp(code, 0)); | |
finish = clock(); | |
cpu_time_used = ((double) (finish - start)) / CLOCKS_PER_SEC; | |
printf("SWITCH took: %f\n", cpu_time_used); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment