Skip to content

Instantly share code, notes, and snippets.

@tonysimpson
Created July 20, 2015 09:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tonysimpson/ddea0c791755ad97a992 to your computer and use it in GitHub Desktop.
Save tonysimpson/ddea0c791755ad97a992 to your computer and use it in GitHub Desktop.
Example of a computed jump based interpreter.
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <windows.h>
typedef struct {
union {
bool bool_value;
int64_t int64_value;
double double_value;
void *void_ptr_value;
};
} unitype;
typedef struct {
uint16_t jump_idx;
int16_t arg;
} instruction;
#define GOTO_INSTRUCTION goto *(&&next + jump_table[instructions->jump_idx])
#define
unitype jump_machine(unitype * constants, instruction * instructions, bool compile) {
static const int jump_table[] = {
0, /* 0 */
&&rel_jump - &&next, /* 1 */
&&load_const_reg1 - &&next, /* 2 */
&&load_const_reg2 - &&next, /* 3 */
&&load_const_reg3 - &&next, /* 4 */
&&add_double_reg1_reg2_reg1 - &&next, /* 5 */
&&compare_double_less_than_reg1_reg3_reg4 - &&next, /* 6 */
&&rel_jump_if_reg4 - &&next, /* 7 */
&&return_reg1 - &&next /* 8 */
};
register unitype reg1;
register unitype reg2;
register unitype reg3;
register unitype reg4;
GOTO_INSTRUCTION;
next:
{
instructions++;
GOTO_INSTRUCTION;
}
rel_jump:
{
instructions += instructions->arg;
GOTO_INSTRUCTION;
}
load_const_reg1:
{
reg1 = constants[instructions->arg];
goto next;
}
load_const_reg2:
{
reg2 = constants[instructions->arg];
goto next;
}
load_const_reg3:
{
reg3 = constants[instructions->arg];
goto next;
}
add_double_reg1_reg2_reg1:
{
reg1.double_value += reg2.double_value;
goto next;
}
compare_double_less_than_reg1_reg3_reg4:
{
reg4.bool_value = reg1.double_value < reg3.double_value;
goto next;
}
rel_jump_if_reg4:
{
if(reg4.bool_value) {
goto rel_jump;
}
goto next;
}
return_reg1:
{
return reg1;
}
}
int main(int argc, char *argv[]) {
unitype constants[] = {{.double_value = 0.5}, {.double_value = 0.75}, {.double_value = 5000000.0}};
instruction instructions[] = {
{2, 0}, /* load 0.5 in reg1 */
{3, 1}, /* load 0.75 in reg2 */
{4, 2}, /* load 5000000.0 in reg3 */
{5, 0}, /* reg1 += reg2, jumps here */
{6, 0}, /* reg4 = reg1 < reg3 */
{7, -2}, /* jump -2 if reg4 */
{8, 0} /* return reg1 */
};
LARGE_INTEGER start, end;
LARGE_INTEGER freq;
double duration;
QueryPerformanceCounter(&start);
unitype result = jump_machine(constants, instructions);
QueryPerformanceCounter(&end);
QueryPerformanceFrequency(&freq);
duration = ((end.QuadPart - start.QuadPart) * 1.0) / freq.QuadPart;
printf("%.09Lg\n", duration);
printf("result %f\n", result.double_value);
fflush(stdout);
QueryPerformanceCounter(&start);
double i = 0.5;
while(i < 5000000.0) {
i += 0.75;
}
QueryPerformanceCounter(&end);
duration = ((end.QuadPart - start.QuadPart) * 1.0) / freq.QuadPart;
printf("%.09Lg\n", duration);
printf("result %f\n", i);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment