decompiled_code:
unsigned __int64 __fastcall pos_shift(int a1, int a2)
{
int v2; // eax

switch ( a1 )
{
case 0:
v2 = 0;
break;
case 1:
a2 = -a2;
v2 = 0;
break;
case 2:
v2 = a2;
a2 = 0;
break;
case 3:
v2 = -a2;
a2 = 0;
break;
case 4:
v2 = 0;
a2 = 0;
break;
case 5:
v2 = 0;
a2 = 0;
break;
default:
v2 = 0;
a2 = 0;
break;
}
return __PAIR64__(v2, a2);
}

canonical_decompiled_code:
unsigned __int64 __fastcall func1(int a1, int a2)
{
int v2; // eax

switch ( a1 )
{
case 0:
v2 = 0;
break;
case 1:
a2 = -a2;
v2 = 0;
break;
case 2:
v2 = a2;
a2 = 0;
break;
case 3:
v2 = -a2;
a2 = 0;
break;
case 4:
v2 = 0;
a2 = 0;
break;
case 5:
v2 = 0;
a2 = 0;
break;
default:
v2 = 0;
a2 = 0;
break;
}
return __PAIR64__(v2, a2);
}

original_code:
static inline struct position pos_shift(enum orientation o, int dist)
{
 struct position dp = {0, 0, 0};
 switch (o) {
 case PX:
  dp.x = dist;
  break;
 case NX:
  dp.x = -dist;
  break;
 case PY:
  dp.y = dist;
  break;
 case NY:
  dp.y = -dist;
  break;
 case PZ:
  dp.z = dist;
  break;
 case NZ:
  dp.z = -dist;
  break;
 default: break;
 }
 return dp;
}

variable_types: enum orientation { PX=0, NX=1, PY=2, NY=3, PZ=4, NZ=5, ORIENTATION_NUM=6 }

variable_types: dist int

variable_types:
dp
struct position { int x; }


rotated

repo: jjonir/alchem

original_code:
static inline enum orientation rotated(enum orientation o, enum orientation dir)
{
 const enum orientation rot_tab[ORIENTATION_NUM][ORIENTATION_NUM] = {
  {PX, PX, PZ, NZ, PY, NY},
  {NX, NX, NZ, PZ, NY, PY},
  {PZ, NZ, PY, PY, NX, PX},
  {NZ, PZ, NY, NY, PX, NX},
  {NY, PY, NX, PX, PZ, PZ},
  {PY, NY, PX, NX, NZ, NZ}
 };
 return rot_tab[o][dir];
}

canonical_original_code:
static inline enum orientation rotated(enum orientation o, enum orientation dir)
{
 enum orientation rot_tab[-1][-1] = {
  {PX, PX, PZ, NZ, PY, NY},
  {NX, NX, NZ, PZ, NY, PY},
  {PZ, NZ, PY, PY, NX, PX},
  {NZ, PZ, NY, NY, PX, NX},
  {NY, PY, NX, PX, PZ, PZ},
  {PY, NY, PX, NX, NZ, NZ}
 };
 return rot_tab[o][dir];
}

variable_types: enum orientation { PX=0, NX=1, PY=2, NY=3, PZ=4, NZ=5, ORIENTATION_NUM=6 } [-1][-1]


decompiled_code:
void __fastcall list_del(__int64 a1)
{
_list_del(*(_QWORD **)(a1 + 8), *(_QWORD *)a1);
*(_QWORD *)a1 = 0LL;
*(_QWORD *)(a1 + 8) = 0LL;
}

original_code:
static inline void list_del(struct list_head *entry)
{
 __list_del(entry->prev, entry->next);
 entry->next = (void *) 0;
 entry->prev = (void *) 0;
}

variable_types: struct list_head { struct list_head *next; } *

return_type: void


decompiled_code:
_BOOL8 __fastcall list_empty(_QWORD *a1)
{
return *a1 == (_QWORD)a1;
}

canonical_decompiled_code:
_BOOL8 __fastcall func8(_QWORD *a1)
{
return *a1 == (_QWORD)a1;
}

original_code:
static inline int list_empty(struct list_head *head)
{
 return head->next == head;
}

return_type: int

user_defined_types: struct list_head { struct list_head *next; }


decompiled_code:
__int64 __fastcall get_head_pos(__int64 a1)
{
__int64 v1; // rax

v1 = pos_shift(*(_DWORD *)(a1 + 12), *(_DWORD *)(a1 + 16));
return pos_add(*(_QWORD *)a1, *(unsigned int *)(a1 + 8), v1);
}

original_code:
struct position get_head_pos(struct manipulator *m) {
 struct position ret;
 ret = pos_add(m->pos, pos_shift(m->orient, m->length));
 return ret;
}

variable_types: struct manipulator { struct position pos; enum orientation { PX=0, NX=1, PY=2, NY=3, PZ=4, NZ=5, ORIENTATION_NUM=6 } orient; int length; enum head_state { HEAD_OPEN=0, HEAD_CLOSED=1 } head_state; int grabbed; struct list_head { struct list_head *next; } inst_list; struct inst { struct list_head list; enum op { ROT_PX=0, ROT_PY=1, ROT_PZ=2, ROT_NX=3, ROT_NY=4, ROT_NZ=5, EXTEND=6, RETRACT=7, OPEN_HEAD=8, CLOSE_HEAD=9, NOP=10 } op; } *pc; } *

variable_types:
ret
struct position { int x; }

return_type: struct position { int x; }

user_defined_types: struct manipulator { struct position pos; enum orientation orient; int length; enum head_state head_state; int grabbed; struct list_head inst_list; struct inst *pc; }

user_defined_types: struct inst { struct list_head list; enum op op; }


decompiled_code:
void __fastcall delete_glyph(void *a1)
{
free(a1);
}

canonical_decompiled_code:
void __fastcall func0(void *a1)
{
free(a1);
}

original_code:
void delete_glyph(struct glyph *g)
{
 free(g);
}

variable_types: struct glyph { struct position { int x; } pos; enum glyph_op { BOND=0, UNBOND=1, SOURCE=2, TRANSMUTE=3 } op; int type; struct atom { struct list_head { struct list_head *next; } compound; int bonds[-1]; struct position pos; enum element { ATOM_NONE=0, ATOM_H=1, ATOM_HE=2, ATOM_LI=3, ATOM_BE=4, ATOM_AL=5, ATOM_C=6, ATOM_N=7, ATOM_O=8, ATOM_F=9, ATOM_AR=10, ATOM_END=11 } element; } *a; } *

user_defined_types: struct glyph { struct position pos; enum glyph_op op; int type; struct atom *a; }

user_defined_types: struct atom { struct list_head compound; int bonds[-1]; struct position pos; enum element element; }


act

decompiled_code:
__int64 __fastcall act(__int64 a1, _QWORD *a2)
{
__int64 result; // rax

result = *((unsigned int *)a2 + 3);
switch ( (_DWORD)result )
{
case 1:
return remove_bond(a1, *a2, *((unsigned int *)a2 + 2), *((unsigned int *)a2 + 4));
case 2:
if ( !a2[3] )
{
result = new_atom(*((unsigned int *)a2 + 4), *a2, *((unsigned int *)a2 + 2));
a2[3] = result;
}
break;
case 0:
result = add_bond(a1, *a2, *((unsigned int *)a2 + 2), *((unsigned int *)a2 + 4));
break;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func1(__int64 a1, _QWORD *a2)
{
__int64 result; // rax

result = *((unsigned int *)a2 + 3);
switch ( (_DWORD)result )
{
case 1:
return remove_bond(a1, *a2, *((unsigned int *)a2 + 2), *((unsigned int *)a2 + 4));
case 2:
if ( !a2[3] )
{
result = new_atom(*((unsigned int *)a2 + 4), *a2, *((unsigned int *)a2 + 2));
a2[3] = result;
}
break;
case 0:
result = add_bond(a1, *a2, *((unsigned int *)a2 + 2), *((unsigned int *)a2 + 4));
break;
}
return result;
}

original_code:
void act(struct workspace *w, struct glyph *g)
{
 switch(g->op) {
 case BOND:
  add_bond(w, g->pos, (enum orientation)g->type);
  break;
 case UNBOND:
  remove_bond(w, g->pos, (enum orientation)g->type);
  break;
 case SOURCE:
  if (g->a == ((void *)0))
   g->a = new_atom((enum element)g->type, g->pos);
  break;
 case TRANSMUTE:
  break;
 default:
  break;
 }
}

variable_types: struct workspace { struct position { int x; } size; struct item { enum item_type { ITEM_NONE=0, ITEM_ATOM=1, ITEM_MANIPULATOR=2, ITEM_GLYPH=3 } type; void *item; } *items; struct position pos; } *

variable_types: struct glyph { struct position pos; enum glyph_op { BOND=0, UNBOND=1, SOURCE=2, TRANSMUTE=3 } op; int type; struct atom { struct list_head { struct list_head *next; } compound; int bonds[-1]; struct position pos; enum element { ATOM_NONE=0, ATOM_H=1, ATOM_HE=2, ATOM_LI=3, ATOM_BE=4, ATOM_AL=5, ATOM_C=6, ATOM_N=7, ATOM_O=8, ATOM_F=9, ATOM_AR=10, ATOM_END=11 } element; } *a; } *

user_defined_types: enum orientation { PX=0, NX=1, PY=2, NY=3, PZ=4, NZ=5, ORIENTATION_NUM=6 }

user_defined_types: struct workspace { struct position size; struct item *items; struct position pos; }

user_defined_types: struct item { enum item_type type; void *item; }


decompiled_code:
__int64 init_io()
{
const char *v1; // [rsp+0h] [rbp-18h] BYREF
int v2[3]; // [rsp+Ch] [rbp-Ch] BYREF

v2[0] = 1;
v1 = "alchem";
glutInit(v2, &v1);
glutInitDisplayMode(18LL);
glutInitWindowPosition(100LL, 100LL);
glutInitWindowSize(1000LL, 700LL);
return glutCreateWindow("alchem");
}

canonical_decompiled_code:
__int64 func4()
{
const char *v1; // [rsp+0h] [rbp-18h] BYREF
int v2[3]; // [rsp+Ch] [rbp-Ch] BYREF

v2[0] = 1;
v1 = "alchem";
glutInit(v2, &v1);
glutInitDisplayMode(18LL);
glutInitWindowPosition(100LL, 100LL);
glutInitWindowSize(1000LL, 700LL);
return glutCreateWindow("alchem");
}

original_code:
void init_io(void)
{
 initscr();
 cbreak();
 noecho();
 keypad(stdscr, 1);
 curs_set(0);
}

canonical_original_code:
void init_io()
{
 initscr();
 cbreak();
 noecho();
 keypad(stdscr, 1);
 curs_set(0);
}


decompiled_code:
void end_io()
{
;
}

canonical_decompiled_code:
void func5()
{
;
}

original_code:
void end_io(void)
{
 endwin();
}

canonical_original_code:
void end_io()
{
 endwin();
}


decompiled_code:
__int64 __fastcall edit_workspace_loop(__int64 a1)
{
w_io = a1;
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutMotionFunc(motion);
return glutMainLoop();
}

canonical_decompiled_code:
__int64 __fastcall func6(__int64 a1)
{
w_io = a1;
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutMotionFunc(motion);
return glutMainLoop();
}

original_code:
void edit_workspace_loop(struct workspace *w)
{
 int cmd;
 do {
  display(w);
  cmd = process_input_blocking(w);
 } while (cmd != -1);
}

variable_types: cmd int

user_defined_types: enum item_type { ITEM_NONE=0, ITEM_ATOM=1, ITEM_MANIPULATOR=2, ITEM_GLYPH=3 }


decompiled_code:
__int64 __fastcall draw_manipulator(int *a1)
{
glPushMatrix();
glTranslatef((float)*a1, (float)-a1[1], (float)a1[2]);
switch ( a1[3] )
{
case 0:
glRotatef(90.0, 0.0, 1.0);
break;
case 1:
glRotatef(-90.0, 0.0, 1.0);
break;
case 2:
glRotatef(90.0, COERCE_DOUBLE((unsigned __int64)LC5), 0.0);
break;
case 3:
glRotatef(-90.0, COERCE_DOUBLE((unsigned __int64)LC5), 0.0);
break;
case 5:
glRotatef(180.0, 0.0, 1.0);
break;
default:
break;
}
glColor3f(1.0, 0.0);
glutWireSphere(40LL, 40LL, 0.25);
glColor3f(0.0, COERCE_DOUBLE((unsigned __int64)LC5));
glutWireCone(20LL, 5LL, 0.125, (double)a1[4]);
return glPopMatrix();
}

canonical_decompiled_code:
__int64 __fastcall func7(int *a1)
{
glPushMatrix();
glTranslatef((float)*a1, (float)-a1[1], (float)a1[2]);
switch ( a1[3] )
{
case 0:
glRotatef(90.0, 0.0, 1.0);
break;
case 1:
glRotatef(-90.0, 0.0, 1.0);
break;
case 2:
glRotatef(90.0, COERCE_DOUBLE((unsigned __int64)LC5), 0.0);
break;
case 3:
glRotatef(-90.0, COERCE_DOUBLE((unsigned __int64)LC5), 0.0);
break;
case 5:
glRotatef(180.0, 0.0, 1.0);
break;
default:
break;
}
glColor3f(1.0, 0.0);
glutWireSphere(40LL, 40LL, 0.25);
glColor3f(0.0, COERCE_DOUBLE((unsigned __int64)LC5));
glutWireCone(20LL, 5LL, 0.125, (double)a1[4]);
return glPopMatrix();
}

variable_types: struct manipulator { struct position { int x; } pos; enum orientation { PX=0, NX=1, PY=2, NY=3, PZ=4, NZ=5, ORIENTATION_NUM=6 } orient; int length; enum head_state { HEAD_OPEN=0, HEAD_CLOSED=1 } head_state; int grabbed; struct list_head { struct list_head *next; } inst_list; struct inst { struct list_head list; enum op { ROT_PX=0, ROT_PY=1, ROT_PZ=2, ROT_NX=3, ROT_NY=4, ROT_NZ=5, EXTEND=6, RETRACT=7, OPEN_HEAD=8, CLOSE_HEAD=9, NOP=10 } op; } *pc; } *

variable_types: dx int

variable_types: dy int

variable_types: x int

variable_types: y int


decompiled_code:
__int64 __fastcall draw_glyph(int *a1)
{
int v1; // eax

glPushMatrix();
glTranslatef((float)*a1, (float)-a1[1], (float)a1[2]);
v1 = a1[3];
switch ( v1 )
{
case 1:
glColor3f(1.0, 0.0);
glutWireTorus(40LL, 40LL, 0.25, 0.5);
break;
case 2:
glColor3f(0.0, 0.0);
glutWireCube(0.5, 0.0, 1.0);
break;
case 0:
glColor3f(0.0, COERCE_DOUBLE((unsigned __int64)LC5));
glutWireTorus(40LL, 40LL, 0.25, 0.5);
break;
}
return glPopMatrix();
}

canonical_decompiled_code:
__int64 __fastcall func8(int *a1)
{
int v1; // eax

glPushMatrix();
glTranslatef((float)*a1, (float)-a1[1], (float)a1[2]);
v1 = a1[3];
switch ( v1 )
{
case 1:
glColor3f(1.0, 0.0);
glutWireTorus(40LL, 40LL, 0.25, 0.5);
break;
case 2:
glColor3f(0.0, 0.0);
glutWireCube(0.5, 0.0, 1.0);
break;
case 0:
glColor3f(0.0, COERCE_DOUBLE((unsigned __int64)LC5));
glutWireTorus(40LL, 40LL, 0.25, 0.5);
break;
}
return glPopMatrix();
}

original_code:
void draw_glyph(struct glyph *g)
{
 struct position adj;
 switch(g->op) {
 case BOND:
  (wmove((stdscr),((3*g->pos.y+2)),((4*g->pos.x+3))) == (-1) ? (-1) : waddch((stdscr),(('+'))));
  adj = pos_add(g->pos, pos_shift((enum orientation)g->type, 1));
  (wmove((stdscr),((3*adj.y+2)),((4*adj.x+3))) == (-1) ? (-1) : waddch((stdscr),(('+'))));
  break;
 case UNBOND:
  (wmove((stdscr),((3*g->pos.y+2)),((4*g->pos.x+3))) == (-1) ? (-1) : waddch((stdscr),(('-'))));
  adj = pos_add(g->pos, pos_shift((enum orientation)g->type, 1));
  (wmove((stdscr),((3*adj.y+2)),((4*adj.x+3))) == (-1) ? (-1) : waddch((stdscr),(('-'))));
  break;
 case SOURCE:
  (wmove((stdscr),((3*g->pos.y+1)),((4*g->pos.x))) == (-1) ? (-1) : waddch((stdscr),(('<'))));
  (wmove((stdscr),((3*g->pos.y+1)),((4*g->pos.x+3))) == (-1) ? (-1) : waddch((stdscr),(('>'))));
  break;
 case TRANSMUTE:
  break;
 default:
  break;
 }
}

variable_types:
adj
struct position { int x; }

user_defined_types: enum glyph_op { BOND=0, UNBOND=1, SOURCE=2, TRANSMUTE=3 }

user_defined_types: enum element { ATOM_NONE=0, ATOM_H=1, ATOM_HE=2, ATOM_LI=3, ATOM_BE=4, ATOM_AL=5, ATOM_C=6, ATOM_N=7, ATOM_O=8, ATOM_F=9, ATOM_AR=10, ATOM_END=11 }


decompiled_code:
__int64 __fastcall draw_atom(int *a1)
{
glPushMatrix();
glTranslatef((float)a1[10], (float)-a1[11], (float)a1[12]);
glColor3f(0.5, COERCE_DOUBLE((unsigned __int64)LC13));
glutSolidSphere(40LL, 40LL, 0.2);
return glPopMatrix();
}

canonical_decompiled_code:
__int64 __fastcall func9(int *a1)
{
glPushMatrix();
glTranslatef((float)a1[10], (float)-a1[11], (float)a1[12]);
glColor3f(0.5, COERCE_DOUBLE((unsigned __int64)LC13));
glutSolidSphere(40LL, 40LL, 0.2);
return glPopMatrix();
}

original_code:
void draw_atom(struct atom *a)
{
 enum orientation dir;
 struct position adj;
 (wmove((stdscr),((3*a->pos.y+1)),((4*a->pos.x+1))) == (-1) ? (-1) : waddnstr((stdscr),((element_string(a->element))),-1));
 for (dir = 0; dir < ORIENTATION_NUM; dir++) {
  if (a->bonds[dir] > 0) {
   adj = pos_add(a->pos, pos_shift(dir, 1));
   draw_bond(a->pos, adj);
  }
 }
}

variable_types: struct atom { struct list_head { struct list_head *next; } compound; int bonds[-1]; struct position { int x; } pos; enum element { ATOM_NONE=0, ATOM_H=1, ATOM_HE=2, ATOM_LI=3, ATOM_BE=4, ATOM_AL=5, ATOM_C=6, ATOM_N=7, ATOM_O=8, ATOM_F=9, ATOM_AR=10, ATOM_END=11 } element; } *

variable_types: enum orientation { PX=0, NX=1, PY=2, NY=3, PZ=4, NZ=5, ORIENTATION_NUM=6 }


display

decompiled_code:
__int64 display()
{
signed int *v0; // rbp
unsigned int i; // er15
int *v3; // rdi
signed int k; // ebx
int *v5; // rax
int *v6; // rax
signed int j; // er14

v0 = (signed int *)w_io;
glClear(16640LL);
glLoadIdentity();
glTranslatef(0.0, 0.0, -2.0);
draw_grid();
for ( i = 0; v0[2] > (int)i; ++i )
{
for ( j = 0; v0[1] > j; ++j )
{
for ( k = 0; *v0 > k; ++k )
{
v5 = (int *)atom_at(v0, __PAIR64__(j, k), i);
if ( v5 )
draw_atom(v5);
v3 = (int *)glyph_at(v0, __PAIR64__(j, k), i);
if ( v3 )
{
draw_glyph(v3);
}
else
{
v6 = (int *)manipulator_at(v0, __PAIR64__(j, k), i);
if ( v6 )
draw_manipulator(v6);
}
}
}
}
return glutSwapBuffers();
}

canonical_decompiled_code:
__int64 func11()
{
signed int *v0; // rbp
unsigned int i; // er15
int *v3; // rdi
signed int k; // ebx
int *v5; // rax
int *v6; // rax
signed int j; // er14

v0 = (signed int *)w_io;
glClear(16640LL);
glLoadIdentity();
glTranslatef(0.0, 0.0, -2.0);
func10();
for ( i = 0; v0[2] > (int)i; ++i )
{
for ( j = 0; v0[1] > j; ++j )
{
for ( k = 0; *v0 > k; ++k )
{
v5 = (int *)atom_at(v0, __PAIR64__(j, k), i);
if ( v5 )
func9(v5);
v3 = (int *)glyph_at(v0, __PAIR64__(j, k), i);
if ( v3 )
{
func8(v3);
}
else
{
v6 = (int *)manipulator_at(v0, __PAIR64__(j, k), i);
if ( v6 )
func7(v6);
}
}
}
}
return glutSwapBuffers();
}

original_code:
void display(struct workspace *w)
{
 struct position pos;
 struct atom *a;
 struct manipulator *m;
 struct glyph *g;
 wclear(stdscr);
 for (pos.z = 0; pos.z < 1; pos.z++) for (pos.y = 0; pos.y < w->size.y; pos.y++) for (pos.x = 0; pos.x < w->size.x; pos.x++) {
  if (((pos.x == w->pos.x) && (pos.y == w->pos.y) && (pos.z == w->pos.z)))
   wattr_on(stdscr, (attr_t)((((chtype)((1U)) << ((8) + 8)))), ((void *)0));
  if ((a = atom_at(w, pos)) != ((void *)0)) {
   draw_atom(a);
  } else if ((m = manipulator_at(w, pos)) != ((void *)0)) {
   draw_manipulator(m);
  } else if ((g = glyph_at(w, pos)) != ((void *)0)) {
   draw_glyph(g);
  } else {
   (wmove((stdscr),((3*pos.y+1)),((4*pos.x+1))) == (-1) ? (-1) : waddch((stdscr),(('.'))));
  }
  if (((pos.x == w->pos.x) && (pos.y == w->pos.y) && (pos.z == w->pos.z)))
   wattr_off(stdscr, (attr_t)((((chtype)((1U)) << ((8) + 8)))), ((void *)0));
 }
 if ((m = manipulator_at(w, w->pos)) != ((void *)0)) {
  print_inst_list(m, 4 * w->size.x + 1);
  wattr_on(stdscr, (attr_t)((((chtype)((1U)) << ((8) + 8)))), ((void *)0));
  draw_manipulator(m);
  wattr_off(stdscr, (attr_t)((((chtype)((1U)) << ((8) + 8)))), ((void *)0));
 }
 wrefresh(stdscr);
}

variable_types:
pos
struct position { int x; }

user_defined_types: enum head_state { HEAD_OPEN=0, HEAD_CLOSED=1 }

user_defined_types: enum op { ROT_PX=0, ROT_PY=1, ROT_PZ=2, ROT_NX=3, ROT_NY=4, ROT_NZ=5, EXTEND=6, RETRACT=7, OPEN_HEAD=8, CLOSE_HEAD=9, NOP=10 }


decompiled_code:
__int64 __fastcall pos_add(__int64 a1, __int64 a2, __int64 a3)
{
__int64 v4; // [rsp+0h] [rbp-14h]

LODWORD(v4) = a1 + a3;
HIDWORD(v4) = HIDWORD(a3) + HIDWORD(a1);
return v4;
}

canonical_decompiled_code:
__int64 __fastcall func0(__int64 a1, __int64 a2, __int64 a3)
{
__int64 v4; // [rsp+0h] [rbp-14h]

LODWORD(v4) = a1 + a3;
HIDWORD(v4) = HIDWORD(a3) + HIDWORD(a1);
return v4;
}

original_code:
static inline struct position pos_add(struct position a, struct position b)
{
 struct position p = {
  a.x + b.x,
  a.y + b.y,
  a.z + b.z
 };
 return p;
}

variable_types:
a
struct position

variable_types:
b
struct position

variable_types:
p
struct position { int x; }


decompiled_code:
__int64 __fastcall pos_sub(__int64 a1, __int64 a2, __int64 a3)
{
__int64 v4; // [rsp+0h] [rbp-14h]

LODWORD(v4) = a1 - a3;
HIDWORD(v4) = HIDWORD(a1) - HIDWORD(a3);
return v4;
}

canonical_decompiled_code:
__int64 __fastcall func1(__int64 a1, __int64 a2, __int64 a3)
{
__int64 v4; // [rsp+0h] [rbp-14h]

LODWORD(v4) = a1 - a3;
HIDWORD(v4) = HIDWORD(a1) - HIDWORD(a3);
return v4;
}

original_code:
static inline struct position pos_sub(struct position a, struct position b)
{
 struct position p = {
  a.x - b.x,
  a.y - b.y,
  a.z - b.z
 };
 return p;
}


opposite

decompiled_code:
__int64 __fastcall opposite(int a1)
{
__int64 result; // rax

switch ( a1 )
{
case 0:
result = 1LL;
break;
case 1:
result = 0LL;
break;
case 2:
result = 3LL;
break;
case 3:
result = 2LL;
break;
case 4:
result = 5LL;
break;
case 5:
result = 4LL;
break;
default:
result = 6LL;
break;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func3(int a1)
{
__int64 result; // rax

switch ( a1 )
{
case 0:
result = 1LL;
break;
case 1:
result = 0LL;
break;
case 2:
result = 3LL;
break;
case 3:
result = 2LL;
break;
case 4:
result = 5LL;
break;
case 5:
result = 4LL;
break;
default:
result = 6LL;
break;
}
return result;
}

original_code:
static inline enum orientation opposite(enum orientation o)
{
 switch (o) {
 case PX: return NX;
 case NX: return PX;
 case PY: return NY;
 case NY: return PY;
 case PZ: return NZ;
 case NZ: return PZ;
 default: return ORIENTATION_NUM;
 }
}

return_type: enum orientation { PX=0, NX=1, PY=2, NY=3, PZ=4, NZ=5, ORIENTATION_NUM=6 }


decompiled_code:
__int64 __fastcall decode_lval(unsigned __int16 a1, unsigned __int16 a2)
{
__int64 result; // rax

if ( a1 <= 7u )
{
strcpy(lval, (&gpr_table)[a1]);
result = 0LL;
}
else if ( a1 <= 0xFu )
{
sprintf(lval, "[%s]", (&gpr_table)[a1 - 8]);
result = 0LL;
}
else if ( a1 <= 0x17u )
{
sprintf(lval, "[0x%.4x+%s]", a2, (&gpr_table)[a1 - 16]);
result = 1LL;
}
else
{
switch ( a1 )
{
case 0x18u:
strcpy(lval, "push");
result = 0LL;
break;
case 0x19u:
strcpy(lval, "peek");
result = 0LL;
break;
case 0x1Au:
sprintf(lval, "[sp+0x%.4x]", a2);
result = 1LL;
break;
case 0x1Bu:
strcpy(lval, "sp");
result = 0LL;
break;
case 0x1Cu:
strcpy(lval, "pc");
result = 0LL;
break;
case 0x1Du:
strcpy(lval, "ex");
result = 0LL;
break;
case 0x1Eu:
sprintf(lval, "[0x%.4x]", a2);
result = 1LL;
break;
case 0x1Fu:
sprintf(lval, "0x%.4x", a2);
result = 1LL;
break;
default:
result = 0LL;
break;
}
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func7(unsigned __int16 a1, unsigned __int16 a2)
{
__int64 result; // rax

if ( a1 <= 7u )
{
strcpy(lval, (&gpr_table)[a1]);
result = 0LL;
}
else if ( a1 <= 0xFu )
{
sprintf(lval, "[%s]", (&gpr_table)[a1 - 8]);
result = 0LL;
}
else if ( a1 <= 0x17u )
{
sprintf(lval, "[0x%.4x+%s]", a2, (&gpr_table)[a1 - 16]);
result = 1LL;
}
else
{
switch ( a1 )
{
case 0x18u:
strcpy(lval, "push");
result = 0LL;
break;
case 0x19u:
strcpy(lval, "peek");
result = 0LL;
break;
case 0x1Au:
sprintf(lval, "[sp+0x%.4x]", a2);
result = 1LL;
break;
case 0x1Bu:
strcpy(lval, "sp");
result = 0LL;
break;
case 0x1Cu:
strcpy(lval, "pc");
result = 0LL;
break;
case 0x1Du:
strcpy(lval, "ex");
result = 0LL;
break;
case 0x1Eu:
sprintf(lval, "[0x%.4x]", a2);
result = 1LL;
break;
case 0x1Fu:
sprintf(lval, "0x%.4x", a2);
result = 1LL;
break;
default:
result = 0LL;
break;
}
}
return result;
}

original_code:
int decode_lval(uint16_t val, uint16_t next)
{
 int rv = 0;
 if (val < 0x08) {
  sprintf(lval, "%s", gpr_table[val]);
 } else if (val < 0x10) {
  sprintf(lval, "[%s]", gpr_table[val - 0x08]);
 } else if (val < 0x18) {
  rv = 1;
  sprintf(lval, "[0x%.4x+%s]", next, gpr_table[val - 0x10]);
 } else {
  switch (val) {
  case 0x18:
   sprintf(lval, "push");
   break;
  case 0x19:
   sprintf(lval, "peek");
   break;
  case 0x1a:
   rv = 1;
   sprintf(lval, "[sp+0x%.4x]", next);
   break;
  case 0x1b:
   sprintf(lval, "sp");
   break;
  case 0x1c:
   sprintf(lval, "pc");
   break;
  case 0x1d:
   sprintf(lval, "ex");
   break;
  case 0x1e:
   rv = 1;
   sprintf(lval, "[0x%.4x]", next);
   break;
  case 0x1f:
   rv = 1;
   sprintf(lval, "0x%.4x", next);
   break;
  default:
   break;
  }
 }
 return rv;
}

canonical_original_code:
int decode_lval(unsigned short val, unsigned short next)
{
 int rv = 0;
 if (val < 0x08) {
  sprintf(lval, "%s", gpr_table[val]);
 } else if (val < 0x10) {
  sprintf(lval, "[%s]", gpr_table[val - 0x08]);
 } else if (val < 0x18) {
  rv = 1;
  sprintf(lval, "[0x%.4x+%s]", next, gpr_table[val - 0x10]);
 } else {
  switch (val) {
  case 0x18:
   sprintf(lval, "push");
   break;
  case 0x19:
   sprintf(lval, "peek");
   break;
  case 0x1a:
   rv = 1;
   sprintf(lval, "[sp+0x%.4x]", next);
   break;
  case 0x1b:
   sprintf(lval, "sp");
   break;
  case 0x1c:
   sprintf(lval, "pc");
   break;
  case 0x1d:
   sprintf(lval, "ex");
   break;
  case 0x1e:
   rv = 1;
   sprintf(lval, "[0x%.4x]", next);
   break;
  case 0x1f:
   rv = 1;
   sprintf(lval, "0x%.4x", next);
   break;
  default:
   break;
  }
 }
 return rv;
}

variable_types:
val
unsigned short

variable_types:
next
unsigned short

variable_types: rv int


decompiled_code:
__int64 __fastcall decode_rval(signed __int16 a1, unsigned __int16 a2)
{
unsigned int v2; // ebx
char v4[40]; // [rsp+0h] [rbp-28h] BYREF

if ( (unsigned __int16)a1 > 0x1Fu )
{
sprintf(rval, "0x%.4x", (unsigned int)(a1 - 33));
v2 = 0;
}
else if ( a1 == 24 )
{
strcpy(rval, "pop");
v2 = 0;
}
else
{
strncpy(v4, lval, 0x10uLL);
v2 = decode_lval(a1, a2);
strncpy(rval, lval, 0x10uLL);
strncpy(lval, v4, 0x10uLL);
}
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func8(signed __int16 a1, unsigned __int16 a2)
{
unsigned int v2; // ebx
char v4[40]; // [rsp+0h] [rbp-28h] BYREF

if ( (unsigned __int16)a1 > 0x1Fu )
{
sprintf(rval, "0x%.4x", (unsigned int)(a1 - 33));
v2 = 0;
}
else if ( a1 == 24 )
{
strcpy(rval, "pop");
v2 = 0;
}
else
{
strncpy(v4, lval, 0x10uLL);
v2 = func7(a1, a2);
strncpy(rval, lval, 0x10uLL);
strncpy(lval, v4, 0x10uLL);
}
return v2;
}

original_code:
int decode_rval(uint16_t val, uint16_t next)
{
 int rv = 0;
 char temp[16];
 if (val >= 0x20) {
  sprintf(rval, "0x%.4x", (int16_t)val - 0x21);
 } else if (val == 0x18) {
  sprintf(rval, "pop");
 } else {
  strncpy(temp, lval, 16);
  rv = decode_lval(val, next);
  strncpy(rval, lval, 16);
  strncpy(lval, temp, 16);
 }
 return rv;
}

canonical_original_code:
int decode_rval(unsigned short val, unsigned short next)
{
 int rv = 0;
 char temp[16];
 if (val >= 0x20) {
  sprintf(rval, "0x%.4x", (short)val - 0x21);
 } else if (val == 0x18) {
  sprintf(rval, "pop");
 } else {
  strncpy(temp, lval, 16);
  rv = decode_lval(val, next);
  strncpy(rval, lval, 16);
  strncpy(lval, temp, 16);
 }
 return rv;
}

variable_types:
temp
char [16]


decompiled_code:
__int64 __fastcall decode_inst(unsigned __int16 *a1, char *a2)
{
unsigned __int16 v2; // bx
__int16 v3; // r13
unsigned int v4; // er14
int v6; // er14

v2 = *a1;
v3 = *a1 & 0x1F;
if ( v3 )
{
v6 = decode_rval(v2 >> 10, a1[1]) + 1;
v4 = decode_lval((v2 >> 5) & 0x1F, a1[v6]) + v6;
sprintf(a2, "%s %s, %s", (const char *)*(&opcode_table + (v3 & 0x1F)), lval, rval);
}
else if ( ((v2 >> 5) & 0x1F) != 0 )
{
v4 = decode_rval(v2 >> 10, a1[1]) + 1;
sprintf(a2, "%s %s", (const char *)*(&spc_opcode_table + ((v2 >> 5) & 0x1F)), rval);
}
else
{
sprintf(a2, "dat 0x%.4x", v2);
v4 = 1;
}
return v4;
}

original_code:
int decode_inst(uint16_t *inst, char *buf)
{
 int words = 1;
 uint16_t word;
 word = inst[0];
 if (word & 0x1F) {
  words += decode_rval((word >> 10) & 0x3F, inst[words]);
  words += decode_lval((word >> 5) & 0x1F, inst[words]);
  sprintf(buf, "%s %s, %s", opcode_table[word & 0x1F], lval, rval);
 } else if ((word >> 5) & 0x1F) {
  words += decode_rval((word >> 10) & 0x3F, inst[words]);
  sprintf(buf, "%s %s", spc_opcode_table[(word >> 5) & 0x1F], rval);
 } else {
  sprintf(buf, "dat 0x%.4x", word);
 }
 return words;
}

canonical_original_code:
int decode_inst(unsigned short *inst, char *buf)
{
 int words = 1;
 unsigned short word;
 word = inst[0];
 if (word & 0x1F) {
  words += decode_rval((word >> 10) & 0x3F, inst[words]);
  words += decode_lval((word >> 5) & 0x1F, inst[words]);
  sprintf(buf, "%s %s, %s", opcode_table[word & 0x1F], lval, rval);
 } else if ((word >> 5) & 0x1F) {
  words += decode_rval((word >> 10) & 0x3F, inst[words]);
  sprintf(buf, "%s %s", spc_opcode_table[(word >> 5) & 0x1F], rval);
 } else {
  sprintf(buf, "dat 0x%.4x", word);
 }
 return words;
}

variable_types:
inst
unsigned short *

variable_types:
buf
char *

variable_types: words int

variable_types:
word
unsigned short


main

canonical_name: main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
const void **v3; // rbp
const char **v4; // r13
unsigned __int16 v5; // r12
int i; // ebx
const char *v7; // r14
const char *v8; // rax
FILE *v9; // rbp
int v10; // er13
__int64 v11; // rax
unsigned __int16 v12; // dx
int v13; // eax
unsigned __int16 v14; // dx
int v15; // ebp
char v17[32]; // [rsp+0h] [rbp-20048h] BYREF
unsigned __int16 ptr[65556]; // [rsp+20h] [rbp-20028h] BYREF

if ( argc <= 1 )
goto LABEL_12;
v3 = (const void **)(argv + 1);
v4 = &argv[(unsigned int)(argc - 2) + 2];
v5 = -1;
LOWORD(i) = 0;
v7 = 0LL;
do
{
v8 = (const char *)*v3;
if ( !memcmp(*v3, "--start=", 8uLL) )
{
LOWORD(i) = atoi(v8 + 8);
}
else if ( !memcmp(*v3, "--end=", 6uLL) )
{
v5 = atoi(v8 + 6);
}
else
{
v7 = (const char *)*v3;
}
++v3;
}
while ( v3 != (const void **)v4 );
if ( !v7 )
{
LABEL_12:
fwrite("usage: disasm <fname> [--start=<start>] [--end=<end>]\n", 1uLL, 0x36uLL, _bss_start);
exit(1);
}
v9 = fopen(v7, "rb");
v10 = fread(ptr, 2uLL, 0x10000uLL, v9);
fclose(v9);
if ( v10 <= 0 )
{
v12 = 0;
}
else
{
v11 = 0LL;
v12 = 0;
while ( 1 )
{
if ( ptr[v11] )
v12 = v11;
if ( v11 == v10 - 1 )
break;
++v11;
}
}
v13 = v12 + 1;
v14 = v12 + 1;
if ( v13 < v5 )
v5 = v14;
for ( i = (unsigned __int16)i; i <= v5; i += v15 )
{
v15 = decode_inst(&ptr[i], v17);
printf("0x%.4X: %s\n", (unsigned int)i, v17);
}
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
const void **v3; // rbp
const char **v4; // r13
unsigned __int16 v5; // r12
int i; // ebx
const char *v7; // r14
const char *v8; // rax
FILE *v9; // rbp
int v10; // er13
__int64 v11; // rax
unsigned __int16 v12; // dx
int v13; // eax
unsigned __int16 v14; // dx
int v15; // ebp
char v17[32]; // [rsp+0h] [rbp-20048h] BYREF
unsigned __int16 ptr[65556]; // [rsp+20h] [rbp-20028h] BYREF

if ( argc <= 1 )
goto LABEL_12;
v3 = (const void **)(argv + 1);
v4 = &argv[(unsigned int)(argc - 2) + 2];
v5 = -1;
LOWORD(i) = 0;
v7 = 0LL;
do
{
v8 = (const char *)*v3;
if ( !memcmp(*v3, "--start=", 8uLL) )
{
LOWORD(i) = atoi(v8 + 8);
}
else if ( !memcmp(*v3, "--end=", 6uLL) )
{
v5 = atoi(v8 + 6);
}
else
{
v7 = (const char *)*v3;
}
++v3;
}
while ( v3 != (const void **)v4 );
if ( !v7 )
{
LABEL_12:
fwrite("usage: disasm <fname> [--start=<start>] [--end=<end>]\n", 1uLL, 0x36uLL, _bss_start);
exit(1);
}
v9 = fopen(v7, "rb");
v10 = fread(ptr, 2uLL, 0x10000uLL, v9);
fclose(v9);
if ( v10 <= 0 )
{
v12 = 0;
}
else
{
v11 = 0LL;
v12 = 0;
while ( 1 )
{
if ( ptr[v11] )
v12 = v11;
if ( v11 == v10 - 1 )
break;
++v11;
}
}
v13 = v12 + 1;
v14 = v12 + 1;
if ( v13 < v5 )
v5 = v14;
for ( i = (unsigned __int16)i; i <= v5; i += v15 )
{
v15 = func9(&ptr[i], v17);
printf("0x%.4X: %s\n", (unsigned int)i, v17);
}
return 0;
}

original_code:
int main(int argc, char *argv[])
{
 ++argv, --argc;
 if (argc > 0)
  yyin = fopen(argv[0], "r");
 else
  yyin = stdin;
 while(yylex());
 return 0;
}

variable_types: argc int

variable_types:
argv
char *[]


hwq

decompiled_code:
__int64 __fastcall hwq(unsigned __int16 *a1)
{
write_register(0LL, *a1);
write_register(1LL, HIWORD(*(_DWORD *)a1));
write_register(2LL, a1[2]);
write_register(3LL, a1[4]);
return write_register(4LL, a1[5]);
}

canonical_decompiled_code:
__int64 __fastcall func7(unsigned __int16 *a1)
{
func13(0LL, *a1);
func13(1LL, HIWORD(*(_DWORD *)a1));
func13(2LL, a1[2]);
func13(3LL, a1[4]);
return func13(4LL, a1[5]);
}

original_code:
void hwq(struct hw_builtin *hw)
{
 write_register(REG_A, hw->id & 0xFFFF);
 write_register(REG_B, hw->id >> 16);
 write_register(REG_C, hw->version);
 write_register(REG_X, hw->mfg & 0xFFFF);
 write_register(REG_Y, hw->mfg >> 16);
}

variable_types: struct hw_builtin { unsigned int id; unsigned short version; unsigned int mfg; void (*init)(); int (*interrupt)(); void (*step)(); } *


main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
__int64 v4; // rbx
char *v5; // rax
bool v6; // cf
bool v7; // zf
const char *v8; // rdi
__int64 v9; // rcx
char *v10; // rsi
char v12[56]; // [rsp+0h] [rbp-38h] BYREF

v3 = fcntl(0, 3, envp);
BYTE1(v3) |= 8u;
fcntl(0, 4, v3);
v4 = get_hw();
puts(*argv);
fflush(stdout);
puts("ready");
fflush(stdout);
while ( !feof(stdin) )
{
(*(void (**)(void))(v4 + 32))();
v5 = fgets(v12, 32, stdin);
v6 = 0;
v7 = v5 == 0LL;
if ( v5 )
{
v8 = "hwi\n";
v9 = 5LL;
v10 = v12;
do
{
if ( !v9 )
break;
v6 = (unsigned __int8)*v10 < (unsigned int)*v8;
v7 = *v10++ == *v8++;
--v9;
}
while ( v7 );
if ( (!v6 && !v7) == v6 )
{
(*(void (__fastcall **)(const char *, char *))(v4 + 24))(v8, v10);
}
else if ( !strcmp(v12, "hwq\n") )
{
hwq((unsigned __int16 *)v4);
}
puts("done");
fflush(stdout);
}
}
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
__int64 v4; // rbx
char *v5; // rax
bool v6; // cf
bool v7; // zf
const char *v8; // rdi
__int64 v9; // rcx
char *v10; // rsi
char v12[56]; // [rsp+0h] [rbp-38h] BYREF

v3 = fcntl(0, 3, envp);
BYTE1(v3) |= 8u;
fcntl(0, 4, v3);
v4 = func19();
puts(*argv);
fflush(stdout);
puts("ready");
fflush(stdout);
while ( !feof(stdin) )
{
(*(void (**)(void))(v4 + 32))();
v5 = fgets(v12, 32, stdin);
v6 = 0;
v7 = v5 == 0LL;
if ( v5 )
{
v8 = "hwi\n";
v9 = 5LL;
v10 = v12;
do
{
if ( !v9 )
break;
v6 = (unsigned __int8)*v10 < (unsigned int)*v8;
v7 = *v10++ == *v8++;
--v9;
}
while ( v7 );
if ( (!v6 && !v7) == v6 )
{
(*(void (__fastcall **)(const char *, char *))(v4 + 24))(v8, v10);
}
else if ( !strcmp(v12, "hwq\n") )
{
func7((unsigned __int16 *)v4);
}
puts("done");
fflush(stdout);
}
}
return 0;
}

original_code:
int main(int argc, char *argv[])
{
 struct hw_builtin *hw;
 char input[32];
 char *status;
 fcntl(0, 4, fcntl(0, 3) | 04000);
 hw = get_hw();
 printf("%s\n", argv[0]);
 fflush(stdout);
 printf("ready\n");
 fflush(stdout);
 while (!feof(stdin)) {
  (*hw->step)();
  status = fgets(input, 32, stdin);
  if (((void *)0) != status) {
   if (strcmp(input, "hwi\n") == 0)
    (*hw->interrupt)();
   else if (strcmp(input, "hwq\n") == 0)
    hwq(hw);
   printf("done\n");
   fflush(stdout);
  }
 }
 return 0;
}

variable_types:
input
char [32]

variable_types:
status
char *

user_defined_types: struct hw_builtin { unsigned int id; unsigned short version; unsigned int mfg; void (*init)(); int (*interrupt)(); void (*step)(); }


decompiled_code:
int set_input_blocking()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) &= 0xF7u;
return fcntl(0, 4, v0);
}

canonical_decompiled_code:
int func8()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) &= 0xF7u;
return fcntl(0, 4, v0);
}

original_code:
void set_input_blocking(void)
{
 int fl = fcntl(0, 3);
 fcntl(0, 4, fl & ~04000);
}

canonical_original_code:
void set_input_blocking()
{
 int fl = fcntl(0, 3);
 fcntl(0, 4, fl & ~04000);
}

variable_types: fl int


decompiled_code:
int set_input_nonblocking()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) |= 8u;
return fcntl(0, 4, v0);
}

canonical_decompiled_code:
int func9()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) |= 8u;
return fcntl(0, 4, v0);
}

original_code:
void set_input_nonblocking(void)
{
 int fl = fcntl(0, 3);
 fcntl(0, 4, fl | 04000);
}

canonical_original_code:
void set_input_nonblocking()
{
 int fl = fcntl(0, 3);
 fcntl(0, 4, fl | 04000);
}


decompiled_code:
__int64 get_uint16()
{
unsigned __int16 v1; // [rsp+Eh] [rbp-2Ah]
char s[40]; // [rsp+10h] [rbp-28h] BYREF

set_input_blocking();
fgets(s, 32, stdin);
set_input_nonblocking();
__isoc99_sscanf();
return v1;
}

canonical_decompiled_code:
__int64 func10()
{
unsigned __int16 v1; // [rsp+Eh] [rbp-2Ah]
char s[40]; // [rsp+10h] [rbp-28h] BYREF

func8();
fgets(s, 32, stdin);
func9();
__isoc99_sscanf();
return v1;
}

original_code:
uint16_t get_uint16(void)
{
 char buf[32];
 uint16_t ret;
 set_input_blocking();
 fgets(buf, 32, stdin);
 set_input_nonblocking();
 sscanf(buf, "%hu", &ret);
 return ret;
}

canonical_original_code:
unsigned short get_uint16()
{
 char buf[32];
 unsigned short ret;
 set_input_blocking();
 fgets(buf, 32, stdin);
 set_input_nonblocking();
 sscanf(buf, "%hu", &ret);
 return ret;
}

variable_types:
buf
char [32]

variable_types:
ret
unsigned short

return_type: unsigned short


decompiled_code:
int lem_init()
{
return clock_gettime(0, &tp_prev);
}

canonical_decompiled_code:
int func16()
{
return clock_gettime(0, &tp_prev);
}

original_code:
void lem_init(void)
{
 clock_gettime(0, &tp_prev);
}

canonical_original_code:
void lem_init()
{
 clock_gettime(0, &tp_prev);
}


decompiled_code:
int lem_step()
{
unsigned __int64 v0; // rax
int v1; // ebx
int v2; // ebx
int i; // er12
char *v4; // rax
__int16 v5; // dx
struct timespec v7; // [rsp+0h] [rbp-368h] BYREF
__int16 v8[384]; // [rsp+10h] [rbp-358h] BYREF
char v9[88]; // [rsp+310h] [rbp-58h] BYREF

strcpy(v9, " ");
clock_gettime(0, &v7);
v0 = 60 * (v7.tv_nsec + 1000000000 * (v7.tv_sec - tp_prev.tv_sec) - tp_prev.tv_nsec);
if ( v0 > 0x3B9AC9FF )
{
mvprintw(vram_top - 1, vram_left - 1, "+--------------------------------+");
v1 = 0;
if ( connected )
{
LODWORD(v0) = read_memory(vram, 0x180u, v8);
if ( custom_font )
return v0;
v2 = -(int)v9;
for ( i = 0; i != 12; ++i )
{
v4 = v9;
do
{
v5 = v8[(unsigned __int16)(v2 + (_WORD)v4)];
if ( (_BYTE)v5 )
*v4 = v5;
else
*v4 = 32;
++v4;
}
while ( v4 != &v9[32] );
v9[32] = 0;
mvprintw(vram_top + i, vram_left - 1, "|%s|", v9);
LOWORD(v2) = v2 + 32;
}
}
else
{
do
mvprintw(vram_top + v1++, vram_left - 1, "|%s|", v9);
while ( v1 != 12 );
}
mvprintw(vram_top + 12, vram_left - 1, "+--------------------------------+");
LODWORD(v0) = wrefresh(stdscr__NCURSES6_TINFO_5_0_19991023);
}
return v0;
}

original_code:
void lem_step(void)
{
 uint16_t row, col, index;
 char row_buf[33] = "                                ";
 uint16_t vram_buf[384];
 struct timespec tp_cur;
 uint64_t ns;
 clock_gettime(0, &tp_cur);
 ns = (tp_cur.tv_sec - tp_prev.tv_sec) * 1000000000;
 ns += (tp_cur.tv_nsec - tp_prev.tv_nsec);
 if ((ns * 60 / 1000000000) == 0)
  return;
 mvprintw(vram_top - 1, vram_left - 1, "+--------------------------------+");
 if (connected) {
  read_memory(vram, 384, vram_buf);
  if (custom_font)
   return;
  for (row = 0; row < 12; row++) {
   for (col = 0; col < 32; col++) {
    index = row * 32 + col;
    row_buf[col] = (char)vram_buf[index];
    if (row_buf[col] == 0)
     row_buf[col] = ' ';
   }
   row_buf[col] = 0;
   mvprintw(vram_top + row, vram_left - 1, "|%s|", row_buf);
  }
 } else {
  for (row = 0; row < 12; row++) {
   mvprintw(vram_top + row, vram_left - 1, "|%s|", row_buf);
  }
 }
 mvprintw(vram_top + 12, vram_left - 1, "+--------------------------------+");
 wrefresh(stdscr);
}

canonical_original_code:
void lem_step()
{
 unsigned short row; unsigned short col; unsigned short index;
 char row_buf[33] = "                                ";
 unsigned short vram_buf[384];
 struct timespec tp_cur;
 unsigned long ns;
 clock_gettime(0, &tp_cur);
 ns = (tp_cur.tv_sec - tp_prev.tv_sec) * 1000000000;
 ns += (tp_cur.tv_nsec - tp_prev.tv_nsec);
 if ((ns * 60 / 1000000000) == 0)
  return;
 mvprintw(vram_top - 1, vram_left - 1, "+--------------------------------+");
 if (connected) {
  read_memory(vram, 384, vram_buf);
  if (custom_font)
   return;
  for (row = 0; row < 12; row++) {
   for (col = 0; col < 32; col++) {
    index = row * 32 + col;
    row_buf[col] = (char)vram_buf[index];
    if (row_buf[col] == 0)
     row_buf[col] = ' ';
   }
   row_buf[col] = 0;
   mvprintw(vram_top + row, vram_left - 1, "|%s|", row_buf);
  }
 } else {
  for (row = 0; row < 12; row++) {
   mvprintw(vram_top + row, vram_left - 1, "|%s|", row_buf);
  }
 }
 mvprintw(vram_top + 12, vram_left - 1, "+--------------------------------+");
 wrefresh(stdscr);
}

variable_types:
row
unsigned short

variable_types:
col
unsigned short

variable_types:
index
unsigned short

variable_types: struct timespec { long tv_sec; long tv_nsec; }

variable_types:
ns
unsigned long


decompiled_code:
__int64 lem_interrupt()
{
unsigned __int16 v0; // bx
unsigned __int16 v1; // ax
unsigned __int16 v2; // bp

v0 = read_register(1u);
v1 = read_register(0);
if ( v1 == 4 )
{
write_memory(v0, 0x100u, font);
v0 = 256;
}
else
{
v2 = v1;
if ( v1 > 4u )
{
if ( v1 == 5 )
{
write_memory(v0, 0x10u, pal);
v0 = 16;
}
else
{
v0 = 0;
}
}
else if ( v1 )
{
if ( v1 == 1 )
{
custom_font = 1;
if ( v0 )
v0 = 0;
}
else
{
v0 = 0;
}
}
else if ( v0 )
{
if ( !connected )
clock_gettime(0, &tp_prev);
connected = 1;
vram = v0;
v0 = v2;
}
else
{
connected = 0;
}
}
return v0;
}

canonical_decompiled_code:
__int64 func18()
{
unsigned __int16 v0; // bx
unsigned __int16 v1; // ax
unsigned __int16 v2; // bp

v0 = func11(1u);
v1 = func11(0);
if ( v1 == 4 )
{
func14(v0, 0x100u, font);
v0 = 256;
}
else
{
v2 = v1;
if ( v1 > 4u )
{
if ( v1 == 5 )
{
func14(v0, 0x10u, pal);
v0 = 16;
}
else
{
v0 = 0;
}
}
else if ( v1 )
{
if ( v1 == 1 )
{
custom_font = 1;
if ( v0 )
v0 = 0;
}
else
{
v0 = 0;
}
}
else if ( v0 )
{
if ( !connected )
clock_gettime(0, &tp_prev);
connected = 1;
vram = v0;
v0 = v2;
}
else
{
connected = 0;
}
}
return v0;
}

original_code:
int lem_interrupt(void)
{
 uint16_t cycles = 0;
 uint16_t b = read_register(REG_B);
 switch (read_register(REG_A)) {
 case 0:
  if (b) {
   if (connected == 0) {
    clock_gettime(0, &tp_prev);
   }
   connected = 1;
   vram = b;
  } else {
   connected = 0;
  }
  break;
 case 1:
  if (b) {
   custom_font = 1;
   font_ram = b;
  } else {
   custom_font = 1;
  }
  break;
 case 2:
  if (b) {
   custom_pal = 1;
   pal_ram = b;
  } else {
   custom_pal = 1;
  }
  break;
 case 3:
  border_col = b;
  break;
 case 4:
  write_memory(b, 256, font);
  cycles = 256;
  break;
 case 5:
  write_memory(b, 16, pal);
  cycles = 16;
  break;
 default:
  break;
 }
 return cycles;
}

canonical_original_code:
int lem_interrupt()
{
 unsigned short cycles = 0;
 unsigned short b = read_register(REG_B);
 switch (read_register(REG_A)) {
 case 0:
  if (b) {
   if (connected == 0) {
    clock_gettime(0, &tp_prev);
   }
   connected = 1;
   vram = b;
  } else {
   connected = 0;
  }
  break;
 case 1:
  if (b) {
   custom_font = 1;
   font_ram = b;
  } else {
   custom_font = 1;
  }
  break;
 case 2:
  if (b) {
   custom_pal = 1;
   pal_ram = b;
  } else {
   custom_pal = 1;
  }
  break;
 case 3:
  border_col = b;
  break;
 case 4:
  write_memory(b, 256, font);
  cycles = 256;
  break;
 case 5:
  write_memory(b, 16, pal);
  cycles = 16;
  break;
 default:
  break;
 }
 return cycles;
}

variable_types:
cycles
unsigned short

variable_types:
b
unsigned short


decompiled_code:
__int64 __fastcall read_register(unsigned __int16 a1)
{
printf("reg r %hu\n", a1);
fflush(stdout);
return get_uint16();
}

canonical_decompiled_code:
__int64 __fastcall func11(unsigned __int16 a1)
{
printf("reg r %hu\n", a1);
fflush(stdout);
return func10();
}

original_code:
uint16_t read_register(uint16_t reg)
{
 printf("reg r %hu\n", reg);
 fflush(stdout);
 return get_uint16();
}

canonical_original_code:
unsigned short read_register(unsigned short reg)
{
 printf("reg r %hu\n", reg);
 fflush(stdout);
 return get_uint16();
}

variable_types:
reg
unsigned short


decompiled_code:
int __fastcall read_memory(unsigned __int16 a1, unsigned __int16 a2, _WORD *a3)
{
int result; // eax
_WORD *v5; // rbx

printf("mem r %hu %hu\n", a1, a2);
result = fflush(stdout);
if ( a2 )
{
v5 = a3;
do
{
result = get_uint16();
*v5++ = result;
}
while ( v5 != &a3[a2] );
}
return result;
}

canonical_decompiled_code:
int __fastcall func12(unsigned __int16 a1, unsigned __int16 a2, _WORD *a3)
{
int result; // eax
_WORD *v5; // rbx

printf("mem r %hu %hu\n", a1, a2);
result = fflush(stdout);
if ( a2 )
{
v5 = a3;
do
{
result = func10();
*v5++ = result;
}
while ( v5 != &a3[a2] );
}
return result;
}

original_code:
void read_memory(uint16_t addr, uint16_t len, uint16_t *buf)
{
 int i;
 printf("mem r %hu %hu\n", addr, len);
 fflush(stdout);
 for (i = 0; i < len; i++)
  buf[i] = get_uint16();
}

canonical_original_code:
void read_memory(unsigned short addr, unsigned short len, unsigned short *buf)
{
 int i;
 printf("mem r %hu %hu\n", addr, len);
 fflush(stdout);
 for (i = 0; i < len; i++)
  buf[i] = get_uint16();
}

variable_types:
addr
unsigned short

variable_types:
len
unsigned short

variable_types:
buf
unsigned short *

variable_types: i int


decompiled_code:
int __fastcall write_register(unsigned __int16 a1, unsigned __int16 a2)
{
printf("reg w %hu %hu\n", a1, a2);
return fflush(stdout);
}

canonical_decompiled_code:
int __fastcall func13(unsigned __int16 a1, unsigned __int16 a2)
{
printf("reg w %hu %hu\n", a1, a2);
return fflush(stdout);
}

original_code:
void write_register(uint16_t reg, uint16_t val)
{
 printf("reg w %hu %hu\n", reg, val);
 fflush(stdout);
}

canonical_original_code:
void write_register(unsigned short reg, unsigned short val)
{
 printf("reg w %hu %hu\n", reg, val);
 fflush(stdout);
}

variable_types:
val
unsigned short


decompiled_code:
int __fastcall write_memory(unsigned __int16 a1, unsigned __int16 a2, unsigned __int16 *a3)
{
unsigned __int16 *v4; // rbx

printf("mem w %hu %hu", a1, a2);
fflush(stdout);
if ( a2 )
{
v4 = a3;
do
{
printf(" %hu", *v4);
fflush(stdout);
++v4;
}
while ( v4 != &a3[a2] );
}
putchar(10);
return fflush(stdout);
}

canonical_decompiled_code:
int __fastcall func14(unsigned __int16 a1, unsigned __int16 a2, unsigned __int16 *a3)
{
unsigned __int16 *v4; // rbx

printf("mem w %hu %hu", a1, a2);
fflush(stdout);
if ( a2 )
{
v4 = a3;
do
{
printf(" %hu", *v4);
fflush(stdout);
++v4;
}
while ( v4 != &a3[a2] );
}
putchar(10);
return fflush(stdout);
}

original_code:
void write_memory(uint16_t addr, uint16_t len, uint16_t *buf)
{
 int i;
 printf("mem w %hu %hu", addr, len);
 fflush(stdout);
 for (i = 0; i < len; i++) {
  printf(" %hu", buf[i]);
  fflush(stdout);
 }
 printf("\n");
 fflush(stdout);
}

canonical_original_code:
void write_memory(unsigned short addr, unsigned short len, unsigned short *buf)
{
 int i;
 printf("mem w %hu %hu", addr, len);
 fflush(stdout);
 for (i = 0; i < len; i++) {
  printf(" %hu", buf[i]);
  fflush(stdout);
 }
 printf("\n");
 fflush(stdout);
}


decompiled_code:
int __fastcall raise_interrupt(unsigned __int16 a1)
{
printf("int %hu\n", a1);
return fflush(stdout);
}

canonical_decompiled_code:
int __fastcall func15(unsigned __int16 a1)
{
printf("int %hu\n", a1);
return fflush(stdout);
}

original_code:
void raise_interrupt(uint16_t msg)
{
 printf("int %hu\n", msg);
 fflush(stdout);
}

canonical_original_code:
void raise_interrupt(unsigned short msg)
{
 printf("int %hu\n", msg);
 fflush(stdout);
}

variable_types:
msg
unsigned short


original_code:
struct hw_builtin *get_hw(void)
{
 return lem1802(1, 1);
}

canonical_original_code:
struct hw_builtin *get_hw()
{
 return lem1802(1, 1);
}

return_type: struct hw_builtin { unsigned int id; unsigned short version; unsigned int mfg; void (*init)(); int (*interrupt)(); void (*step)(); } *


readline

decompiled_code:
__int64 __fastcall readline(int fd, void *buf, int a3)
{
char *v4; // rbx
__int64 result; // rax

memset(buf, 0, a3);
v4 = (char *)buf;
do
{
read(fd, v4, 1uLL);
result = (unsigned int)(1 - (_DWORD)buf + (_DWORD)v4);
if ( a3 <= (int)result )
break;
++v4;
}
while ( *(v4 - 1) != 10 );
return result;
}

canonical_decompiled_code:
__int64 __fastcall func0(int fd, void *buf, int a3)
{
char *v4; // rbx
__int64 result; // rax

memset(buf, 0, a3);
v4 = (char *)buf;
do
{
read(fd, v4, 1uLL);
result = (unsigned int)(1 - (_DWORD)buf + (_DWORD)v4);
if ( a3 <= (int)result )
break;
++v4;
}
while ( *(v4 - 1) != 10 );
return result;
}

original_code:
void readline(int fd, char *buf, int max)
{
 int i = 0;
 memset(buf, 0, max);
 do {
  read(fd, &buf[i], 1);
  i++;
 } while ((i < max) && (buf[i - 1] != '\n'));
}

variable_types: fd int

variable_types:
buf
char *

variable_types: max int


decompiled_code:
bool __fastcall module_waitreply(int *a1)
{
size_t v2; // rax
int v3; // edi
bool v4; // zf
bool result; // al
int v6; // edi
char v7[32]; // [rsp+0h] [rbp-68h] BYREF
char buf[44]; // [rsp+20h] [rbp-48h] BYREF
unsigned __int16 v9; // [rsp+4Ch] [rbp-1Ch] BYREF
unsigned __int16 v10; // [rsp+4Eh] [rbp-1Ah] BYREF

do
{
readline(a1[1], buf, 32);
v6 = dbgline++;
mvprintw(v6, dbgrow, "from module: %s", buf);
if ( dbgline > 46 )
{
dbgline = 27;
dbgrow += 30;
}
refresh();
if ( !memcmp(buf, "reg r", 5uLL) )
{
_isoc99_sscanf(buf, "reg r %hu", &v10);
v10 = read_register(v10);
sprintf(v7, format, v10);
v2 = strlen(v7);
write(*a1, v7, v2);
v3 = dbgline++;
mvprintw(v3, dbgrow, "to module: %s", v7);
if ( dbgline > 46 )
{
dbgline = 27;
dbgrow += 30;
}
refresh();
}
else if ( !memcmp(buf, "reg w", 5uLL) )
{
_isoc99_sscanf(buf, "reg w %hu %hu", &v10, &v9);
write_register(v10, v9);
}
else if ( !memcmp(buf, "mem r", 5uLL) )
{
_isoc99_sscanf(buf, "mem r %hu %hu", &v10, &v9);
}
else if ( !memcmp(buf, "mem w", 5uLL) )
{
_isoc99_sscanf(buf, "mem w %hu %hu", &v10, &v9);
}
v4 = strcmp(buf, "done\n") == 0;
result = !v4;
}
while ( !v4 );
return result;
}

canonical_decompiled_code:
bool __fastcall func1(int *a1)
{
size_t v2; // rax
int v3; // edi
bool v4; // zf
bool result; // al
int v6; // edi
char v7[32]; // [rsp+0h] [rbp-68h] BYREF
char buf[44]; // [rsp+20h] [rbp-48h] BYREF
unsigned __int16 v9; // [rsp+4Ch] [rbp-1Ch] BYREF
unsigned __int16 v10; // [rsp+4Eh] [rbp-1Ah] BYREF

do
{
func0(a1[1], buf, 32);
v6 = dbgline++;
mvprintw(v6, dbgrow, "from module: %s", buf);
if ( dbgline > 46 )
{
dbgline = 27;
dbgrow += 30;
}
refresh();
if ( !memcmp(buf, "reg r", 5uLL) )
{
_isoc99_sscanf(buf, "reg r %hu", &v10);
v10 = read_register(v10);
sprintf(v7, format, v10);
v2 = strlen(v7);
write(*a1, v7, v2);
v3 = dbgline++;
mvprintw(v3, dbgrow, "to module: %s", v7);
if ( dbgline > 46 )
{
dbgline = 27;
dbgrow += 30;
}
refresh();
}
else if ( !memcmp(buf, "reg w", 5uLL) )
{
_isoc99_sscanf(buf, "reg w %hu %hu", &v10, &v9);
write_register(v10, v9);
}
else if ( !memcmp(buf, "mem r", 5uLL) )
{
_isoc99_sscanf(buf, "mem r %hu %hu", &v10, &v9);
}
else if ( !memcmp(buf, "mem w", 5uLL) )
{
_isoc99_sscanf(buf, "mem w %hu %hu", &v10, &v9);
}
v4 = strcmp(buf, "done\n") == 0;
result = !v4;
}
while ( !v4 );
return result;
}

original_code:
void module_waitreply(struct hw_module *hw)
{
 uint16_t arg1, arg2;
 char buf[32], reply[32];
 do {
  readline(hw->rx, buf, 32);
  do { mvprintw(dbgline++, dbgrow, "from module: %s", buf); if (dbgline > 46) { dbgline = 27; dbgrow += 30; } refresh(); } while (0);;
  if (strncmp(buf, "reg r", 5) == 0) {
   sscanf(buf, "reg r %hu", &arg1);
   arg1 = read_register(arg1);
   sprintf(reply, "%i\n", arg1);
   write(hw->tx, reply, strlen(reply));
   do { mvprintw(dbgline++, dbgrow, "to module: %s", reply); if (dbgline > 46) { dbgline = 27; dbgrow += 30; } refresh(); } while (0);;
  } else if (strncmp(buf, "reg w", 5) == 0) {
   sscanf(buf, "reg w %hu %hu", &arg1, &arg2);
   write_register(arg1, arg2);
  } else if (strncmp(buf, "mem r", 5) == 0) {
   sscanf(buf, "mem r %hu %hu", &arg1, &arg2);
  } else if (strncmp(buf, "mem w", 5) == 0) {
   sscanf(buf, "mem w %hu %hu", &arg1, &arg2);
  }
 } while (strcmp(buf, "done\n") != 0);
}

canonical_original_code:
void module_waitreply(struct hw_module *hw)
{
 unsigned short arg1; unsigned short arg2;
 char buf[32]; char reply[32];
 do {
  readline(hw->rx, buf, 32);
  do { mvprintw(dbgline++, dbgrow, "from module: %s", buf); if (dbgline > 46) { dbgline = 27; dbgrow += 30; } refresh(); } while (0);;
  if (strncmp(buf, "reg r", 5) == 0) {
   sscanf(buf, "reg r %hu", &arg1);
   arg1 = read_register(arg1);
   sprintf(reply, "%i\n", arg1);
   write(hw->tx, reply, strlen(reply));
   do { mvprintw(dbgline++, dbgrow, "to module: %s", reply); if (dbgline > 46) { dbgline = 27; dbgrow += 30; } refresh(); } while (0);;
  } else if (strncmp(buf, "reg w", 5) == 0) {
   sscanf(buf, "reg w %hu %hu", &arg1, &arg2);
   write_register(arg1, arg2);
  } else if (strncmp(buf, "mem r", 5) == 0) {
   sscanf(buf, "mem r %hu %hu", &arg1, &arg2);
  } else if (strncmp(buf, "mem w", 5) == 0) {
   sscanf(buf, "mem w %hu %hu", &arg1, &arg2);
  }
 } while (strcmp(buf, "done\n") != 0);
}

variable_types:
hw
struct hw_module { int tx; } *

variable_types:
buf
char [32]

variable_types:
reply
char [32]


decompiled_code:
char __fastcall hardware_step(unsigned __int16 a1)
{
int v1; // eax
int v2; // edx
bool v3; // zf
int v4; // edi
char v6[46]; // [rsp+0h] [rbp-38h] BYREF
unsigned __int16 v7; // [rsp+2Eh] [rbp-Ah] BYREF

LOBYTE(v1) = a1;
v2 = hardware[2 * a1];
if ( v2 == 1 )
{
LOBYTE(v1) = (*(__int64 (**)(void))(hardware[2 * a1 + 1] + 32))();
}
else if ( v2 == 2 )
{
v1 = readline_async(*(_DWORD *)(hardware[2 * a1 + 1] + 4), v6, 32);
if ( v1 )
{
v3 = memcmp(v6, "int", 3uLL) == 0;
LOBYTE(v1) = !v3;
if ( v3 )
{
v4 = dbgline++;
mvprintw(v4, dbgrow, "from module: %s", v6);
if ( dbgline > 46 )
{
dbgline = 27;
dbgrow += 30;
}
refresh();
_isoc99_sscanf(v6, "int %hu", &v7);
LOBYTE(v1) = raise_interrupt(v7);
}
}
}
return v1;
}

canonical_decompiled_code:
char __fastcall func4(unsigned __int16 a1)
{
int v1; // eax
int v2; // edx
bool v3; // zf
int v4; // edi
char v6[46]; // [rsp+0h] [rbp-38h] BYREF
unsigned __int16 v7; // [rsp+2Eh] [rbp-Ah] BYREF

LOBYTE(v1) = a1;
v2 = hardware[2 * a1];
if ( v2 == 1 )
{
LOBYTE(v1) = (*(__int64 (**)(void))(hardware[2 * a1 + 1] + 32))();
}
else if ( v2 == 2 )
{
v1 = func3(*(_DWORD *)(hardware[2 * a1 + 1] + 4), v6, 32);
if ( v1 )
{
v3 = memcmp(v6, "int", 3uLL) == 0;
LOBYTE(v1) = !v3;
if ( v3 )
{
v4 = dbgline++;
mvprintw(v4, dbgrow, "from module: %s", v6);
if ( dbgline > 46 )
{
dbgline = 27;
dbgrow += 30;
}
refresh();
_isoc99_sscanf(v6, "int %hu", &v7);
LOBYTE(v1) = raise_interrupt(v7);
}
}
}
return v1;
}

original_code:
void hardware_step(uint16_t where)
{
 uint16_t arg;
 char buf[32];
 switch(hardware[where].type) {
 case HARDWARE_BUILTIN:
  hardware[where].hw.builtin->step();
  break;
 case HARDWARE_MODULE:
  if (readline_async(hardware[where].hw.module->rx, buf, 32)) {
   if (strncmp(buf, "int", 3) == 0) {
    do { mvprintw(dbgline++, dbgrow, "from module: %s", buf); if (dbgline > 46) { dbgline = 27; dbgrow += 30; } refresh(); } while (0);;
    sscanf(buf, "int %hu", &arg);
    raise_interrupt(arg);
   } else {
   }
  }
  break;
 default:
  break;
 }
}

canonical_original_code:
void hardware_step(unsigned short where)
{
 unsigned short arg;
 char buf[32];
 switch(hardware[where].type) {
 case HARDWARE_BUILTIN:
  hardware[where].hw.builtin->step();
  break;
 case HARDWARE_MODULE:
  if (readline_async(hardware[where].hw.module->rx, buf, 32)) {
   if (strncmp(buf, "int", 3) == 0) {
    do { mvprintw(dbgline++, dbgrow, "from module: %s", buf); if (dbgline > 46) { dbgline = 27; dbgrow += 30; } refresh(); } while (0);;
    sscanf(buf, "int %hu", &arg);
    raise_interrupt(arg);
   } else {
   }
  }
  break;
 default:
  break;
 }
}

variable_types:
where
unsigned short

variable_types:
arg
unsigned short


decompiled_code:
__int64 attach_hardware_builtin()
{
unsigned __int16 v0; // ax
__int64 *v1; // rbx
unsigned __int16 v2; // ax
__int64 *v3; // rbx
__int64 result; // rax

v0 = attached++;
v1 = &hardware[2 * v0];
*(_DWORD *)v1 = 1;
v1[1] = lem1802(2LL, 46LL);
v2 = attached++;
v3 = &hardware[2 * v2];
*(_DWORD *)v3 = 1;
result = generic_clock();
v3[1] = result;
return result;
}

canonical_decompiled_code:
__int64 func5()
{
unsigned __int16 v0; // ax
__int64 *v1; // rbx
unsigned __int16 v2; // ax
__int64 *v3; // rbx
__int64 result; // rax

v0 = attached++;
v1 = &hardware[2 * v0];
*(_DWORD *)v1 = 1;
v1[1] = lem1802(2LL, 46LL);
v2 = attached++;
v3 = &hardware[2 * v2];
*(_DWORD *)v3 = 1;
result = generic_clock();
v3[1] = result;
return result;
}

original_code:
void attach_hardware_builtin(void)
{
 uint16_t where;
 where = attached++;
 hardware[where].type = HARDWARE_BUILTIN;
 hardware[where].hw.builtin = lem1802(2, 46);
 where = attached++;
 hardware[where].type = HARDWARE_BUILTIN;
 hardware[where].hw.builtin = generic_clock();
}

canonical_original_code:
void attach_hardware_builtin()
{
 unsigned short where;
 where = attached++;
 hardware[where].type = HARDWARE_BUILTIN;
 hardware[where].hw.builtin = lem1802(2, 46);
 where = attached++;
 hardware[where].type = HARDWARE_BUILTIN;
 hardware[where].hw.builtin = generic_clock();
}


decompiled_code:
__int64 __fastcall attach_hardware_module(char *arg)
{
unsigned __int16 v1; // ax
__int64 *v2; // rbx
_DWORD *v3; // rax
int v4; // edi
_BYTE v6[32]; // [rsp+0h] [rbp-38h] BYREF
int v7[2]; // [rsp+20h] [rbp-18h] BYREF
int pipedes[2]; // [rsp+28h] [rbp-10h] BYREF

pipe(pipedes);
pipe(v7);
if ( !fork() )
{
close(0);
dup(pipedes[0]);
close(pipedes[1]);
close(1);
dup(v7[1]);
close(v7[0]);
execlp(arg, arg, 0LL);
fprintf(stderr, "error exec'ing %s\n", arg);
perror("execlp");
}
close(pipedes[0]);
close(v7[1]);
v1 = attached++;
v2 = &hardware[2 * v1];
*(_DWORD *)v2 = 2;
v3 = malloc(8uLL);
v2[1] = (__int64)v3;
*v3 = pipedes[1];
v4 = v7[0];
v3[1] = v7[0];
readline(v4, v6, 32);
readline(v7[0], v6, 32);
return 0LL;
}

canonical_decompiled_code:
__int64 __fastcall func6(char *arg)
{
unsigned __int16 v1; // ax
__int64 *v2; // rbx
_DWORD *v3; // rax
int v4; // edi
_BYTE v6[32]; // [rsp+0h] [rbp-38h] BYREF
int v7[2]; // [rsp+20h] [rbp-18h] BYREF
int pipedes[2]; // [rsp+28h] [rbp-10h] BYREF

pipe(pipedes);
pipe(v7);
if ( !fork() )
{
close(0);
dup(pipedes[0]);
close(pipedes[1]);
close(1);
dup(v7[1]);
close(v7[0]);
execlp(arg, arg, 0LL);
fprintf(stderr, "error exec'ing %s\n", arg);
perror("execlp");
}
close(pipedes[0]);
close(v7[1]);
v1 = attached++;
v2 = &hardware[2 * v1];
*(_DWORD *)v2 = 2;
v3 = malloc(8uLL);
v2[1] = (__int64)v3;
*v3 = pipedes[1];
v4 = v7[0];
v3[1] = v7[0];
func0(v4, v6, 32);
func0(v7[0], v6, 32);
return 0LL;
}

original_code:
int attach_hardware_module(const char *name)
{
 uint16_t where;
 int tx_fds[2], rx_fds[2];
 char buf[32];
 pipe(tx_fds);
 pipe(rx_fds);
 if (fork() == 0) {
  close(0);
  dup(tx_fds[0]);
  close(tx_fds[1]);
  close(1);
  dup(rx_fds[1]);
  close(rx_fds[0]);
  execlp(name, name, ((void *)0));
  fprintf(stderr, "error exec\'ing %s\n", name);
  perror("execlp");
 }
 close(tx_fds[0]);
 close(rx_fds[1]);
 where = attached++;
 hardware[where].type = HARDWARE_MODULE;
 hardware[where].hw.module = (struct hw_module *)malloc(sizeof(struct hw_module));
 hardware[where].hw.module->tx = tx_fds[1];
 hardware[where].hw.module->rx = rx_fds[0];
 readline(rx_fds[0], buf, 32);
 readline(rx_fds[0], buf, 32);
 return 0;
}

canonical_original_code:
int attach_hardware_module(char *name)
{
 unsigned short where;
 int tx_fds[2]; int rx_fds[2];
 char buf[32];
 pipe(tx_fds);
 pipe(rx_fds);
 if (fork() == 0) {
  close(0);
  dup(tx_fds[0]);
  close(tx_fds[1]);
  close(1);
  dup(rx_fds[1]);
  close(rx_fds[0]);
  execlp(name, name, ((void *)0));
  fprintf(stderr, "error exec\'ing %s\n", name);
  perror("execlp");
 }
 close(tx_fds[0]);
 close(rx_fds[1]);
 where = attached++;
 hardware[where].type = HARDWARE_MODULE;
 hardware[where].hw.module = (struct hw_module *)malloc(sizeof(struct hw_module));
 hardware[where].hw.module->tx = tx_fds[1];
 hardware[where].hw.module->rx = rx_fds[0];
 readline(rx_fds[0], buf, 32);
 readline(rx_fds[0], buf, 32);
 return 0;
}

variable_types:
name
char *


decompiled_code:
char __fastcall hardware_hwi(unsigned __int16 a1)
{
int v1; // eax

v1 = hardware[2 * a1];
if ( v1 )
{
if ( v1 == 1 )
{
LOBYTE(v1) = (*(__int64 (**)(void))(hardware[2 * a1 + 1] + 24))();
}
else if ( v1 == 2 )
{
LOBYTE(v1) = module_cmd((int *)hardware[2 * a1 + 1], "hwi\n", 4);
}
}
return v1;
}

canonical_decompiled_code:
char __fastcall func7(unsigned __int16 a1)
{
int v1; // eax

v1 = hardware[2 * a1];
if ( v1 )
{
if ( v1 == 1 )
{
LOBYTE(v1) = (*(__int64 (**)(void))(hardware[2 * a1 + 1] + 24))();
}
else if ( v1 == 2 )
{
LOBYTE(v1) = func2((int *)hardware[2 * a1 + 1], "hwi\n", 4);
}
}
return v1;
}

original_code:
void hardware_hwi(uint16_t where)
{
 if (hardware[where].type != HARDWARE_NONE) {
  switch(hardware[where].type) {
  case HARDWARE_BUILTIN:
   hardware[where].hw.builtin->interrupt();
   break;
  case HARDWARE_MODULE:
   module_cmd(hardware[where].hw.module, "hwi\n", 4);
   break;
  default:
   break;
  }
 }
}

canonical_original_code:
void hardware_hwi(unsigned short where)
{
 if (hardware[where].type != HARDWARE_NONE) {
  switch(hardware[where].type) {
  case HARDWARE_BUILTIN:
   hardware[where].hw.builtin->interrupt();
   break;
  case HARDWARE_MODULE:
   module_cmd(hardware[where].hw.module, "hwi\n", 4);
   break;
  default:
   break;
  }
 }
}


decompiled_code:
char __fastcall hardware_hwq(unsigned __int16 a1)
{
int v1; // eax
__int64 v2; // rbx

v1 = hardware[2 * a1];
if ( v1 == 1 )
{
v2 = 2LL * a1;
write_register(0LL, *(unsigned __int16 *)hardware[v2 + 1]);
write_register(1LL, HIWORD(*(_DWORD *)hardware[v2 + 1]));
write_register(2LL, *(unsigned __int16 *)(hardware[v2 + 1] + 4));
write_register(3LL, *(unsigned __int16 *)(hardware[v2 + 1] + 8));
LOBYTE(v1) = write_register(4LL, *(unsigned __int16 *)(hardware[v2 + 1] + 10));
}
else if ( v1 == 2 )
{
LOBYTE(v1) = module_cmd((int *)hardware[2 * a1 + 1], "hwq\n", 4);
}
return v1;
}

canonical_decompiled_code:
char __fastcall func8(unsigned __int16 a1)
{
int v1; // eax
__int64 v2; // rbx

v1 = hardware[2 * a1];
if ( v1 == 1 )
{
v2 = 2LL * a1;
write_register(0LL, *(unsigned __int16 *)hardware[v2 + 1]);
write_register(1LL, HIWORD(*(_DWORD *)hardware[v2 + 1]));
write_register(2LL, *(unsigned __int16 *)(hardware[v2 + 1] + 4));
write_register(3LL, *(unsigned __int16 *)(hardware[v2 + 1] + 8));
LOBYTE(v1) = write_register(4LL, *(unsigned __int16 *)(hardware[v2 + 1] + 10));
}
else if ( v1 == 2 )
{
LOBYTE(v1) = func2((int *)hardware[2 * a1 + 1], "hwq\n", 4);
}
return v1;
}

original_code:
void hardware_hwq(uint16_t where)
{
 switch (hardware[where].type) {
 case HARDWARE_NONE:
  break;
 case HARDWARE_BUILTIN:
  write_register(REG_A, hardware[where].hw.builtin->id & 0xFFFF);
  write_register(REG_B, hardware[where].hw.builtin->id >> 16);
  write_register(REG_C, hardware[where].hw.builtin->version);
  write_register(REG_X, hardware[where].hw.builtin->mfg & 0xFFFF);
  write_register(REG_Y, hardware[where].hw.builtin->mfg >> 16);
  break;
 case HARDWARE_MODULE:
  module_cmd(hardware[where].hw.module, "hwq\n", 4);
  break;
 default:
  break;
 }
}

canonical_original_code:
void hardware_hwq(unsigned short where)
{
 switch (hardware[where].type) {
 case HARDWARE_NONE:
  break;
 case HARDWARE_BUILTIN:
  write_register(REG_A, hardware[where].hw.builtin->id & 0xFFFF);
  write_register(REG_B, hardware[where].hw.builtin->id >> 16);
  write_register(REG_C, hardware[where].hw.builtin->version);
  write_register(REG_X, hardware[where].hw.builtin->mfg & 0xFFFF);
  write_register(REG_Y, hardware[where].hw.builtin->mfg >> 16);
  break;
 case HARDWARE_MODULE:
  module_cmd(hardware[where].hw.module, "hwq\n", 4);
  break;
 default:
  break;
 }
}


decompiled_code:
char hardware_step_all()
{
void *v0; // rbx
char result; // al

v0 = 0LL;
do
{
result = 16 * (_BYTE)v0;
if ( LODWORD(hardware[2 * (_QWORD)v0]) )
result = hardware_step((unsigned __int16)v0);
v0 = (char *)v0 + 1;
}
while ( v0 != &unk_10000 );
return result;
}

canonical_decompiled_code:
char func9()
{
void *v0; // rbx
char result; // al

v0 = 0LL;
do
{
result = 16 * (_BYTE)v0;
if ( LODWORD(hardware[2 * (_QWORD)v0]) )
result = func4((unsigned __int16)v0);
v0 = (char *)v0 + 1;
}
while ( v0 != &unk_10000 );
return result;
}

original_code:
void hardware_step_all(void)
{
 int i;
 for (i = 0; i < 0x10000; i++)
  if (hardware[i].type != HARDWARE_NONE)
   hardware_step(i);
}

canonical_original_code:
void hardware_step_all()
{
 int i;
 for (i = 0; i < 0x10000; i++)
  if (hardware[i].type != HARDWARE_NONE)
   hardware_step(i);
}


decompiled_code:
__int64 hardware_get_attached()
{
return (unsigned __int16)attached;
}

canonical_decompiled_code:
__int64 func10()
{
return (unsigned __int16)attached;
}

original_code:
uint16_t hardware_get_attached(void)
{
 return attached;
}

canonical_original_code:
unsigned short hardware_get_attached()
{
 return attached;
}


decompiled_code:
void __fastcall clock_tick(__int16 a1)
{
clock_time += a1;
}

canonical_decompiled_code:
void __fastcall func0(__int16 a1)
{
clock_time += a1;
}

original_code:
void clock_tick(uint16_t cycles)
{
 clock_time += cycles;
}

canonical_original_code:
void clock_tick(unsigned short cycles)
{
 clock_time += cycles;
}

variable_types:
cycles
unsigned short


decompiled_code:
__int16 *next_word_addr()
{
unsigned __int16 v0; // ax

clock_tick(1);
v0 = registers[8];
registers[8] = v0 + 1;
return &memory[v0];
}

canonical_decompiled_code:
__int16 *func1()
{
unsigned __int16 v0; // ax

func0(1);
v0 = registers[8];
registers[8] = v0 + 1;
return &memory[v0];
}

original_code:
uint16_t *next_word_addr(void)
{
 clock_tick(1);
 return &memory[registers.PC++];
}

canonical_original_code:
unsigned short *next_word_addr()
{
 clock_tick(1);
 return &memory[registers.PC++];
}

return_type: unsigned short *


decompiled_code:
__int64 next_word()
{
return (unsigned __int16)*next_word_addr();
}

canonical_decompiled_code:
__int64 func2()
{
return (unsigned __int16)*func1();
}

original_code:
uint16_t next_word(void)
{
 return *next_word_addr();
}

canonical_original_code:
unsigned short next_word()
{
 return *next_word_addr();
}


decompiled_code:
__int64 __fastcall decode_rvalue(int a1)
{
__int64 result; // rax
unsigned __int16 v2; // ax

if ( (_WORD)a1 == 24 )
{
v2 = registers[9];
registers[9] = v2 + 1;
result = (unsigned __int16)memory[v2];
}
else
{
result = (unsigned int)(a1 - 33);
if ( (unsigned __int16)a1 <= 0x1Fu )
result = (unsigned __int16)*decode_lvalue(a1);
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func3(int a1)
{
__int64 result; // rax
unsigned __int16 v2; // ax

if ( (_WORD)a1 == 24 )
{
v2 = registers[9];
registers[9] = v2 + 1;
result = (unsigned __int16)memory[v2];
}
else
{
result = (unsigned int)(a1 - 33);
if ( (unsigned __int16)a1 <= 0x1Fu )
result = (unsigned __int16)*decode_lvalue(a1);
}
return result;
}

original_code:
uint16_t decode_rvalue(uint16_t val)
{
 if (val == 0x18)
  return memory[registers.SP++];
 else if (val < 0x20)
  return *decode_lvalue(val);
 else
  return val - 0x21;
}

canonical_original_code:
unsigned short decode_rvalue(unsigned short val)
{
 if (val == 0x18)
  return memory[registers.SP++];
 else if (val < 0x20)
  return *decode_lvalue(val);
 else
  return val - 0x21;
}


skip

decompiled_code:
unsigned __int64 skip()
{
unsigned __int16 v0; // ax
__int16 v1; // dx
__int16 v2; // si
unsigned __int64 result; // rax

do
{
clock_tick(1);
v0 = next_word();
v1 = v0 & 0x1F;
v2 = (v0 >> 5) & 0x1F;
if ( (v0 & 0x8000u) == 0 && ((0xC4FF0000uLL >> (v0 >> 10)) & 1) != 0 )
++registers[8];
result = 0xC4FF0000uLL >> v2;
if ( ((0xC4FF0000uLL >> v2) & 1) != 0 )
++registers[8];
}
while ( (unsigned __int16)(v1 - 16) <= 7u );
return result;
}

canonical_original_code:
void skip()
{
 unsigned short inst; unsigned short op; unsigned short val_a; unsigned short val_b;
 do {
  clock_tick(1);
  inst = next_word();
  op = inst & 0x1F;
  val_b = (inst >> 5) & 0x1F;
  val_a = (inst >> 10) & 0x3F;
  if (((val_a >= 0x10) && (val_a <= 0x17)) ||
    (val_a == 0x1A) || (val_a == 0x1E) || (val_a == 0x1F))
   registers.PC++;
  if (((val_b >= 0x10) && (val_b <= 0x17)) ||
    (val_b == 0x1A) || (val_b == 0x1E) || (val_b == 0x1F))
   registers.PC++;
 } while ((op >= 0x10) && (op <= 0x17));
}

variable_types:
inst
unsigned short

variable_types:
op
unsigned short


decompiled_code:
void __fastcall ex_spc(unsigned __int16 a1)
{
__int16 v2; // bp
unsigned __int16 v3; // di
__int16 *v4; // rbx
unsigned __int16 v5; // ax
__int16 v6; // si
unsigned __int16 v7; // ax

v2 = (a1 >> 5) & 0x1F;
clock_tick(spc_inst_clocks[(a1 >> 5) & 0x1F]);
if ( v2 )
{
v3 = a1 >> 10;
if ( (a1 & 0x8000u) != 0 )
{
v5 = decode_rvalue(v3);
switch ( v2 )
{
case 1:
LABEL_5:
v6 = registers[9];
registers[9] = v6 - 1;
memory[(unsigned __int16)(v6 - 1)] = registers[8];
registers[8] = v5;
break;
case 8:
LABEL_7:
queue_interrupt(v5);
break;
case 10:
LABEL_9:
registers[11] = v5;
break;
case 11:
LABEL_10:
interrupts_enabled = 1;
v7 = registers[9];
registers[0] = memory[v7];
registers[9] = v7 + 2;
registers[8] = memory[(unsigned __int16)(v7 + 1)];
break;
case 12:
LABEL_11:
interrupts_enabled = v5 == 0;
break;
case 16:
v4 = 0LL;
LABEL_13:
if ( v4 )
*v4 = hardware_get_attached();
break;
case 17:
LABEL_15:
hardware_hwq(v5);
break;
case 18:
LABEL_16:
hardware_hwi(v5);
break;
default:
return;
}
}
else
{
v4 = decode_lvalue(v3 & 0x1F);
v5 = *v4;
switch ( v2 )
{
case 1:
goto LABEL_5;
case 8:
goto LABEL_7;
case 9:
*v4 = registers[11];
break;
case 10:
goto LABEL_9;
case 11:
goto LABEL_10;
case 12:
goto LABEL_11;
case 16:
goto LABEL_13;
case 17:
goto LABEL_15;
case 18:
goto LABEL_16;
default:
return;
}
}
}
}

canonical_decompiled_code:
void __fastcall func5(unsigned __int16 a1)
{
__int16 v2; // bp
unsigned __int16 v3; // di
__int16 *v4; // rbx
unsigned __int16 v5; // ax
__int16 v6; // si
unsigned __int16 v7; // ax

v2 = (a1 >> 5) & 0x1F;
func0(spc_inst_clocks[(a1 >> 5) & 0x1F]);
if ( v2 )
{
v3 = a1 >> 10;
if ( (a1 & 0x8000u) != 0 )
{
v5 = func3(v3);
switch ( v2 )
{
case 1:
LABEL_5:
v6 = registers[9];
registers[9] = v6 - 1;
memory[(unsigned __int16)(v6 - 1)] = registers[8];
registers[8] = v5;
break;
case 8:
LABEL_7:
queue_interrupt(v5);
break;
case 10:
LABEL_9:
registers[11] = v5;
break;
case 11:
LABEL_10:
interrupts_enabled = 1;
v7 = registers[9];
registers[0] = memory[v7];
registers[9] = v7 + 2;
registers[8] = memory[(unsigned __int16)(v7 + 1)];
break;
case 12:
LABEL_11:
interrupts_enabled = v5 == 0;
break;
case 16:
v4 = 0LL;
LABEL_13:
if ( v4 )
*v4 = hardware_get_attached();
break;
case 17:
LABEL_15:
hardware_hwq(v5);
break;
case 18:
LABEL_16:
hardware_hwi(v5);
break;
default:
return;
}
}
else
{
v4 = decode_lvalue(v3 & 0x1F);
v5 = *v4;
switch ( v2 )
{
case 1:
goto LABEL_5;
case 8:
goto LABEL_7;
case 9:
*v4 = registers[11];
break;
case 10:
goto LABEL_9;
case 11:
goto LABEL_10;
case 12:
goto LABEL_11;
case 16:
goto LABEL_13;
case 17:
goto LABEL_15;
case 18:
goto LABEL_16;
default:
return;
}
}
}
}

original_code:
void ex_spc(uint16_t inst)
{
 uint16_t op, rvalue, *lvalue;
 op = (inst >> 5) & 0x1F;
 clock_tick(spc_inst_clocks[op]);
 if (op == RES) {
  return;
 }
 if (((inst >> 10) & 0x3F) < 0x20) {
  lvalue = decode_lvalue((inst >> 10) & 0x1F);
  rvalue = *lvalue;
 } else {
  lvalue = ((void *)0);
  rvalue = decode_rvalue((inst >> 10) & 0x3F);
 }
 switch (op) {
 case JSR:
  memory[--registers.SP] = registers.PC;
  registers.PC = rvalue;
  break;
 case INT:
  queue_interrupt(rvalue);
  break;
 case IAG:
  if (lvalue != ((void *)0))
   *lvalue = registers.IA;
  break;
 case IAS:
  registers.IA = rvalue;
  break;
 case RFI:
  interrupts_enabled = 1;
  registers.A = memory[registers.SP++];
  registers.PC = memory[registers.SP++];
  break;
 case IAQ:
  if (rvalue == 0)
   interrupts_enabled = 1;
  else
   interrupts_enabled = 0;
  break;
 case HWN:
  if (lvalue != ((void *)0))
   *lvalue = hardware_get_attached();
  break;
 case HWQ:
  hardware_hwq(rvalue);
  break;
 case HWI:
  hardware_hwi(rvalue);
  break;
 default:
  break;
 }
}

canonical_original_code:
void ex_spc(unsigned short inst)
{
 unsigned short op; unsigned short rvalue; unsigned short *lvalue;
 op = (inst >> 5) & 0x1F;
 clock_tick(spc_inst_clocks[op]);
 if (op == RES) {
  return;
 }
 if (((inst >> 10) & 0x3F) < 0x20) {
  lvalue = decode_lvalue((inst >> 10) & 0x1F);
  rvalue = *lvalue;
 } else {
  lvalue = ((void *)0);
  rvalue = decode_rvalue((inst >> 10) & 0x3F);
 }
 switch (op) {
 case JSR:
  memory[--registers.SP] = registers.PC;
  registers.PC = rvalue;
  break;
 case INT:
  queue_interrupt(rvalue);
  break;
 case IAG:
  if (lvalue != ((void *)0))
   *lvalue = registers.IA;
  break;
 case IAS:
  registers.IA = rvalue;
  break;
 case RFI:
  interrupts_enabled = 1;
  registers.A = memory[registers.SP++];
  registers.PC = memory[registers.SP++];
  break;
 case IAQ:
  if (rvalue == 0)
   interrupts_enabled = 1;
  else
   interrupts_enabled = 0;
  break;
 case HWN:
  if (lvalue != ((void *)0))
   *lvalue = hardware_get_attached();
  break;
 case HWQ:
  hardware_hwq(rvalue);
  break;
 case HWI:
  hardware_hwi(rvalue);
  break;
 default:
  break;
 }
}

variable_types:
rvalue
unsigned short

variable_types:
lvalue
unsigned short *


ex

decompiled_code:
void ex()
{
unsigned __int16 v0; // ax
unsigned __int16 v1; // bx
__int16 v2; // bp
unsigned __int16 v3; // r12
__int16 *v4; // rax
__int16 *v5; // rsi
unsigned __int16 v6; // dx
unsigned __int16 v7; // cx
unsigned __int16 v8; // ax
unsigned __int16 v9; // dx

v0 = next_word();
v1 = v0;
v2 = v0 & 0x1F;
if ( (v0 & 0x1F) != 0 )
{
clock_tick(inst_clocks[v0 & 0x1F] - 1);
v3 = decode_rvalue(v1 >> 10);
v4 = decode_lvalue((v1 >> 5) & 0x1F);
v5 = v4;
switch ( v2 )
{
case 0:
case 24:
case 25:
case 28:
case 29:
return;
case 1:
*v4 = v3;
break;
case 2:
registers[10] = (v3 + (unsigned int)(unsigned __int16)*v4) >> 16;
*v4 += v3;
break;
case 3:
registers[10] = ((unsigned __int16)*v4 - (unsigned int)v3) >> 16;
*v4 -= v3;
break;
case 4:
registers[10] = (v3 * (unsigned int)(unsigned __int16)*v4) >> 16;
*v4 *= v3;
break;
case 5:
registers[10] = (v3 * (unsigned int)(unsigned __int16)*v4) >> 16;
*v4 *= v3;
break;
case 6:
if ( v3 )
{
registers[10] = ((unsigned __int16)*v4 << 16) / (unsigned int)v3;
*v4 = (unsigned __int16)*v4 / v3;
}
else
{
registers[10] = 0;
*v4 = 0;
}
break;
case 7:
if ( v3 )
{
registers[10] = ((unsigned __int16)*v4 << 16) / v3;
*v4 /= (__int16)v3;
}
else
{
registers[10] = 0;
*v4 = 0;
}
break;
case 8:
if ( v3 )
*v4 = (unsigned __int16)*v4 % v3;
else
*v4 = 0;
break;
case 9:
if ( v3 )
*v4 %= (__int16)v3;
else
*v4 = 0;
break;
case 10:
*v4 &= v3;
break;
case 11:
*v4 |= v3;
break;
case 12:
*v4 ^= v3;
break;
case 13:
registers[10] = (unsigned int)((unsigned __int16)*v4 << 16) >> v3;
*v4 = (int)(unsigned __int16)*v4 >> v3;
break;
case 14:
registers[10] = (unsigned int)((unsigned __int16)*v4 << 16) >> v3;
*v4 >>= v3;
break;
case 15:
registers[10] = (unsigned int)((unsigned __int16)*v4 << v3) >> 16;
*v4 = (unsigned __int16)*v4 << v3;
break;
case 16:
if ( ((unsigned __int16)*v4 & v3) == 0 )
goto LABEL_43;
break;
case 17:
if ( ((unsigned __int16)*v4 & v3) != 0 )
goto LABEL_43;
break;
case 18:
if ( *v4 != v3 )
goto LABEL_43;
break;
case 19:
if ( *v4 == v3 )
goto LABEL_43;
break;
case 20:
if ( (unsigned __int16)*v4 <= v3 )
goto LABEL_43;
break;
case 21:
if ( *v4 <= (__int16)v3 )
goto LABEL_43;
break;
case 22:
if ( (unsigned __int16)*v4 >= v3 )
goto LABEL_43;
break;
case 23:
if ( *v4 >= (__int16)v3 )
LABEL_43:
skip();
break;
case 26:
v6 = *v4;
v7 = registers[10];
*v4 += v7 + v3;
registers[10] = (v6 + v7 + (unsigned int)v3) >> 16;
break;
case 27:
v8 = *v4;
v9 = registers[10];
*v5 = v8 - v3 - v9;
registers[10] = (v8 - (v3 + (unsigned int)v9)) >> 16;
break;
case 30:
*v4 = v3;
++registers[6];
++registers[7];
break;
case 31:
*v4 = v3;
--registers[6];
--registers[7];
break;
}
}
else
{
ex_spc(v0);
}
}

canonical_decompiled_code:
void func6()
{
unsigned __int16 v0; // ax
unsigned __int16 v1; // bx
__int16 v2; // bp
unsigned __int16 v3; // r12
__int16 *v4; // rax
__int16 *v5; // rsi
unsigned __int16 v6; // dx
unsigned __int16 v7; // cx
unsigned __int16 v8; // ax
unsigned __int16 v9; // dx

v0 = func2();
v1 = v0;
v2 = v0 & 0x1F;
if ( (v0 & 0x1F) != 0 )
{
func0(inst_clocks[v0 & 0x1F] - 1);
v3 = func3(v1 >> 10);
v4 = decode_lvalue((v1 >> 5) & 0x1F);
v5 = v4;
switch ( v2 )
{
case 0:
case 24:
case 25:
case 28:
case 29:
return;
case 1:
*v4 = v3;
break;
case 2:
registers[10] = (v3 + (unsigned int)(unsigned __int16)*v4) >> 16;
*v4 += v3;
break;
case 3:
registers[10] = ((unsigned __int16)*v4 - (unsigned int)v3) >> 16;
*v4 -= v3;
break;
case 4:
registers[10] = (v3 * (unsigned int)(unsigned __int16)*v4) >> 16;
*v4 *= v3;
break;
case 5:
registers[10] = (v3 * (unsigned int)(unsigned __int16)*v4) >> 16;
*v4 *= v3;
break;
case 6:
if ( v3 )
{
registers[10] = ((unsigned __int16)*v4 << 16) / (unsigned int)v3;
*v4 = (unsigned __int16)*v4 / v3;
}
else
{
registers[10] = 0;
*v4 = 0;
}
break;
case 7:
if ( v3 )
{
registers[10] = ((unsigned __int16)*v4 << 16) / v3;
*v4 /= (__int16)v3;
}
else
{
registers[10] = 0;
*v4 = 0;
}
break;
case 8:
if ( v3 )
*v4 = (unsigned __int16)*v4 % v3;
else
*v4 = 0;
break;
case 9:
if ( v3 )
*v4 %= (__int16)v3;
else
*v4 = 0;
break;
case 10:
*v4 &= v3;
break;
case 11:
*v4 |= v3;
break;
case 12:
*v4 ^= v3;
break;
case 13:
registers[10] = (unsigned int)((unsigned __int16)*v4 << 16) >> v3;
*v4 = (int)(unsigned __int16)*v4 >> v3;
break;
case 14:
registers[10] = (unsigned int)((unsigned __int16)*v4 << 16) >> v3;
*v4 >>= v3;
break;
case 15:
registers[10] = (unsigned int)((unsigned __int16)*v4 << v3) >> 16;
*v4 = (unsigned __int16)*v4 << v3;
break;
case 16:
if ( ((unsigned __int16)*v4 & v3) == 0 )
goto LABEL_43;
break;
case 17:
if ( ((unsigned __int16)*v4 & v3) != 0 )
goto LABEL_43;
break;
case 18:
if ( *v4 != v3 )
goto LABEL_43;
break;
case 19:
if ( *v4 == v3 )
goto LABEL_43;
break;
case 20:
if ( (unsigned __int16)*v4 <= v3 )
goto LABEL_43;
break;
case 21:
if ( *v4 <= (__int16)v3 )
goto LABEL_43;
break;
case 22:
if ( (unsigned __int16)*v4 >= v3 )
goto LABEL_43;
break;
case 23:
if ( *v4 >= (__int16)v3 )
LABEL_43:
func4();
break;
case 26:
v6 = *v4;
v7 = registers[10];
*v4 += v7 + v3;
registers[10] = (v6 + v7 + (unsigned int)v3) >> 16;
break;
case 27:
v8 = *v4;
v9 = registers[10];
*v5 = v8 - v3 - v9;
registers[10] = (v8 - (v3 + (unsigned int)v9)) >> 16;
break;
case 30:
*v4 = v3;
++registers[6];
++registers[7];
break;
case 31:
*v4 = v3;
--registers[6];
--registers[7];
break;
}
}
else
{
func5(v0);
}
}

original_code:
void ex(void)
{
 uint16_t inst, op, *lvalue, rvalue, temp_EX;
 inst = next_word();
 op = inst & 0x1F;
 if (op == SPC) {
  ex_spc(inst);
  return;
 }
 clock_tick(inst_clocks[op] - 1);
 rvalue = decode_rvalue((inst >> 10) & 0x3F);
 lvalue = decode_lvalue((inst >> 5) & 0x1F);
 switch (op) {
 case SET:
  *lvalue = rvalue;
  break;
 case ADD:
  registers.EX = (((uint32_t)*lvalue + (uint32_t)rvalue) >> 16) & 0xFFFF;
  *lvalue += rvalue;
  break;
 case SUB:
  registers.EX = (((int32_t)*lvalue - (int32_t)rvalue) >> 16) & 0xFFFF;
  *lvalue -= rvalue;
  break;
 case MUL:
  registers.EX = (((uint32_t)*lvalue * (uint32_t)rvalue) >> 16) & 0xFFFF;
  *lvalue *= rvalue;
  break;
 case MLI:
  registers.EX = (((int32_t)*lvalue * (int32_t)rvalue) >> 16) & 0xFFFF;
  *(int16_t *)lvalue *= (int16_t)rvalue;
  break;
 case DIV:
  if (rvalue == 0) {
   registers.EX = 0;
   *lvalue = 0;
  } else {
   registers.EX = (((uint32_t)*lvalue << 16) / (uint32_t)rvalue) & 0xFFFF;
   *lvalue /= rvalue;
  }
  break;
 case DVI:
  if (rvalue == 0) {
   registers.EX = 0;
   *lvalue = 0;
  } else {
   registers.EX = (((int32_t)*lvalue << 16) / (int32_t)rvalue) & 0xFFFF;
   *(int16_t *)lvalue /= (int16_t)rvalue;
  }
  break;
 case MOD:
  if (rvalue == 0)
   *lvalue = 0;
  else
   *lvalue %= rvalue;
  break;
 case MDI:
  if (rvalue == 0)
   *lvalue = 0;
  else
   *(int16_t *)lvalue %= (int16_t)rvalue;
  break;
 case AND:
  *lvalue &= rvalue;
  break;
 case BOR:
  *lvalue |= rvalue;
  break;
 case XOR:
  *lvalue ^= rvalue;
  break;
 case SHR:
  registers.EX = (((uint32_t)*lvalue << 16) >> rvalue) & 0xFFFF;
  *lvalue >>= rvalue;
  break;
 case ASR:
  registers.EX = (((uint32_t)*lvalue << 16) >> rvalue) & 0xFFFF;
  *(int16_t *)lvalue >>= rvalue;
  break;
 case SHL:
  registers.EX = (((uint32_t)*lvalue << rvalue) >> 16) & 0xFFFF;
  *lvalue <<= rvalue;
  break;
 case IFB:
  if ((*lvalue & rvalue) == 0)
   skip();
  break;
 case IFC:
  if ((*lvalue & rvalue) != 0)
   skip();
  break;
 case IFE:
  if (*lvalue != rvalue)
   skip();
  break;
 case IFN:
  if (*lvalue == rvalue)
   skip();
  break;
 case IFG:
  if (*lvalue <= rvalue)
   skip();
  break;
 case IFA:
  if (*(int16_t *)lvalue <= (int16_t)rvalue)
   skip();
  break;
 case IFL:
  if (*lvalue >= rvalue)
   skip();
  break;
 case IFU:
  if (*(int16_t *)lvalue >= (int16_t)rvalue)
   skip();
  break;
 case ADX:
  temp_EX = (((uint32_t)*lvalue + (uint32_t)rvalue +
       (uint32_t)registers.EX) >> 16) & 0xFFFF;
  *lvalue += (rvalue + registers.EX);
  registers.EX = temp_EX;
  break;
 case SBX:
  temp_EX = (((int32_t)*lvalue - ((int32_t)rvalue +
       (int32_t)registers.EX)) >> 16) & 0xFFFF;
  *lvalue -= (rvalue + registers.EX);
  registers.EX = temp_EX;
  break;
 case STI:
  *lvalue = rvalue;
  registers.I += 1;
  registers.J += 1;
  break;
 case STD:
  *lvalue = rvalue;
  registers.I -= 1;
  registers.J -= 1;
  break;
 default:
  break;
 }
}

canonical_original_code:
void ex()
{
 unsigned short inst; unsigned short op; unsigned short *lvalue; unsigned short rvalue; unsigned short temp_EX;
 inst = next_word();
 op = inst & 0x1F;
 if (op == SPC) {
  ex_spc(inst);
  return;
 }
 clock_tick(inst_clocks[op] - 1);
 rvalue = decode_rvalue((inst >> 10) & 0x3F);
 lvalue = decode_lvalue((inst >> 5) & 0x1F);
 switch (op) {
 case SET:
  *lvalue = rvalue;
  break;
 case ADD:
  registers.EX = (((unsigned int)*lvalue + (unsigned int)rvalue) >> 16) & 0xFFFF;
  *lvalue += rvalue;
  break;
 case SUB:
  registers.EX = (((int)*lvalue - (int)rvalue) >> 16) & 0xFFFF;
  *lvalue -= rvalue;
  break;
 case MUL:
  registers.EX = (((unsigned int)*lvalue * (unsigned int)rvalue) >> 16) & 0xFFFF;
  *lvalue *= rvalue;
  break;
 case MLI:
  registers.EX = (((int)*lvalue * (int)rvalue) >> 16) & 0xFFFF;
  *(short *)lvalue *= (short)rvalue;
  break;
 case DIV:
  if (rvalue == 0) {
   registers.EX = 0;
   *lvalue = 0;
  } else {
   registers.EX = (((unsigned int)*lvalue << 16) / (unsigned int)rvalue) & 0xFFFF;
   *lvalue /= rvalue;
  }
  break;
 case DVI:
  if (rvalue == 0) {
   registers.EX = 0;
   *lvalue = 0;
  } else {
   registers.EX = (((int)*lvalue << 16) / (int)rvalue) & 0xFFFF;
   *(short *)lvalue /= (short)rvalue;
  }
  break;
 case MOD:
  if (rvalue == 0)
   *lvalue = 0;
  else
   *lvalue %= rvalue;
  break;
 case MDI:
  if (rvalue == 0)
   *lvalue = 0;
  else
   *(short *)lvalue %= (short)rvalue;
  break;
 case AND:
  *lvalue &= rvalue;
  break;
 case BOR:
  *lvalue |= rvalue;
  break;
 case XOR:
  *lvalue ^= rvalue;
  break;
 case SHR:
  registers.EX = (((unsigned int)*lvalue << 16) >> rvalue) & 0xFFFF;
  *lvalue >>= rvalue;
  break;
 case ASR:
  registers.EX = (((unsigned int)*lvalue << 16) >> rvalue) & 0xFFFF;
  *(short *)lvalue >>= rvalue;
  break;
 case SHL:
  registers.EX = (((unsigned int)*lvalue << rvalue) >> 16) & 0xFFFF;
  *lvalue <<= rvalue;
  break;
 case IFB:
  if ((*lvalue & rvalue) == 0)
   skip();
  break;
 case IFC:
  if ((*lvalue & rvalue) != 0)
   skip();
  break;
 case IFE:
  if (*lvalue != rvalue)
   skip();
  break;
 case IFN:
  if (*lvalue == rvalue)
   skip();
  break;
 case IFG:
  if (*lvalue <= rvalue)
   skip();
  break;
 case IFA:
  if (*(short *)lvalue <= (short)rvalue)
   skip();
  break;
 case IFL:
  if (*lvalue >= rvalue)
   skip();
  break;
 case IFU:
  if (*(short *)lvalue >= (short)rvalue)
   skip();
  break;
 case ADX:
  temp_EX = (((unsigned int)*lvalue + (unsigned int)rvalue +
       (unsigned int)registers.EX) >> 16) & 0xFFFF;
  *lvalue += (rvalue + registers.EX);
  registers.EX = temp_EX;
  break;
 case SBX:
  temp_EX = (((int)*lvalue - ((int)rvalue +
       (int)registers.EX)) >> 16) & 0xFFFF;
  *lvalue -= (rvalue + registers.EX);
  registers.EX = temp_EX;
  break;
 case STI:
  *lvalue = rvalue;
  registers.I += 1;
  registers.J += 1;
  break;
 case STD:
  *lvalue = rvalue;
  registers.I -= 1;
  registers.J -= 1;
  break;
 default:
  break;
 }
}


decompiled_code:
void sim_init()
{
;
}

canonical_decompiled_code:
void func7()
{
;
}

original_code:
void sim_init(void)
{
}

canonical_original_code:
void sim_init()
{
}


decompiled_code:
__int64 sim_step()
{
int v0; // ebx

v0 = (unsigned __int16)clock_time;
ex();
if ( interrupts_enabled )
trigger_next_queued_interrupt();
hardware_step_all();
return (unsigned int)(unsigned __int16)clock_time - v0;
}

canonical_decompiled_code:
__int64 func8()
{
int v0; // ebx

v0 = (unsigned __int16)clock_time;
func6();
if ( interrupts_enabled )
trigger_next_queued_interrupt();
hardware_step_all();
return (unsigned int)(unsigned __int16)clock_time - v0;
}

original_code:
uint16_t sim_step(void)
{
 int clock_before = clock_time;
 ex();
 if (interrupts_enabled)
  trigger_next_queued_interrupt();
 hardware_step_all();
 return clock_time - clock_before;
}

canonical_original_code:
unsigned short sim_step()
{
 int clock_before = clock_time;
 ex();
 if (interrupts_enabled)
  trigger_next_queued_interrupt();
 hardware_step_all();
 return clock_time - clock_before;
}


decompiled_code:
void __noreturn run_dcpu16()
{
while ( 1 )
sim_step();
}

canonical_decompiled_code:
void __noreturn func9()
{
while ( 1 )
func8();
}

original_code:
void run_dcpu16(void)
{
 while (1) {
  sim_step();
 }
}

canonical_original_code:
void run_dcpu16()
{
 while (1) {
  sim_step();
 }
}


decompiled_code:
void __noreturn CATCH_FIRE()
{
exit(1);
}

canonical_decompiled_code:
void __noreturn func10()
{
exit(1);
}

original_code:
void CATCH_FIRE(void)
{
 exit(1);
}

canonical_original_code:
void CATCH_FIRE()
{
 exit(1);
}


hwq

decompiled_code:
__int64 __fastcall hwq(unsigned __int16 *a1)
{
write_register(0LL, *a1);
write_register(1LL, HIWORD(*(_DWORD *)a1));
write_register(2LL, a1[2]);
write_register(3LL, a1[4]);
return write_register(4LL, a1[5]);
}

canonical_decompiled_code:
__int64 __fastcall func7(unsigned __int16 *a1)
{
func13(0LL, *a1);
func13(1LL, HIWORD(*(_DWORD *)a1));
func13(2LL, a1[2]);
func13(3LL, a1[4]);
return func13(4LL, a1[5]);
}

original_code:
void hwq(struct hw_builtin *hw)
{
 write_register(REG_A, hw->id & 0xFFFF);
 write_register(REG_B, hw->id >> 16);
 write_register(REG_C, hw->version);
 write_register(REG_X, hw->mfg & 0xFFFF);
 write_register(REG_Y, hw->mfg >> 16);
}

variable_types: struct hw_builtin { unsigned int id; unsigned short version; unsigned int mfg; void (*init)(); int (*interrupt)(); void (*step)(); } *


main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
__int64 v4; // rbx
char *v5; // rax
bool v6; // cf
bool v7; // zf
const char *v8; // rdi
__int64 v9; // rcx
char *v10; // rsi
char v12[56]; // [rsp+0h] [rbp-38h] BYREF

v3 = fcntl(0, 3, envp);
BYTE1(v3) |= 8u;
fcntl(0, 4, v3);
v4 = get_hw();
puts(*argv);
fflush(stdout);
puts("ready");
fflush(stdout);
while ( !feof(stdin) )
{
(*(void (**)(void))(v4 + 32))();
v5 = fgets(v12, 32, stdin);
v6 = 0;
v7 = v5 == 0LL;
if ( v5 )
{
v8 = "hwi\n";
v9 = 5LL;
v10 = v12;
do
{
if ( !v9 )
break;
v6 = (unsigned __int8)*v10 < (unsigned int)*v8;
v7 = *v10++ == *v8++;
--v9;
}
while ( v7 );
if ( (!v6 && !v7) == v6 )
{
(*(void (__fastcall **)(const char *, char *))(v4 + 24))(v8, v10);
}
else if ( !strcmp(v12, "hwq\n") )
{
hwq((unsigned __int16 *)v4);
}
puts("done");
fflush(stdout);
}
}
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
__int64 v4; // rbx
char *v5; // rax
bool v6; // cf
bool v7; // zf
const char *v8; // rdi
__int64 v9; // rcx
char *v10; // rsi
char v12[56]; // [rsp+0h] [rbp-38h] BYREF

v3 = fcntl(0, 3, envp);
BYTE1(v3) |= 8u;
fcntl(0, 4, v3);
v4 = func20();
puts(*argv);
fflush(stdout);
puts("ready");
fflush(stdout);
while ( !feof(stdin) )
{
(*(void (**)(void))(v4 + 32))();
v5 = fgets(v12, 32, stdin);
v6 = 0;
v7 = v5 == 0LL;
if ( v5 )
{
v8 = "hwi\n";
v9 = 5LL;
v10 = v12;
do
{
if ( !v9 )
break;
v6 = (unsigned __int8)*v10 < (unsigned int)*v8;
v7 = *v10++ == *v8++;
--v9;
}
while ( v7 );
if ( (!v6 && !v7) == v6 )
{
(*(void (__fastcall **)(const char *, char *))(v4 + 24))(v8, v10);
}
else if ( !strcmp(v12, "hwq\n") )
{
func7((unsigned __int16 *)v4);
}
puts("done");
fflush(stdout);
}
}
return 0;
}

original_code:
int main(int argc, char *argv[])
{
 struct hw_builtin *hw;
 char input[32];
 char *status;
 fcntl(0, 4, fcntl(0, 3) | 04000);
 hw = get_hw();
 printf("%s\n", argv[0]);
 fflush(stdout);
 printf("ready\n");
 fflush(stdout);
 while (!feof(stdin)) {
  (*hw->step)();
  status = fgets(input, 32, stdin);
  if (((void *)0) != status) {
   if (strcmp(input, "hwi\n") == 0)
    (*hw->interrupt)();
   else if (strcmp(input, "hwq\n") == 0)
    hwq(hw);
   printf("done\n");
   fflush(stdout);
  }
 }
 return 0;
}

variable_types: argc int

variable_types:
argv
char *[]

variable_types:
input
char [32]

variable_types:
status
char *


decompiled_code:
int set_input_blocking()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) &= 0xF7u;
return fcntl(0, 4, v0);
}

canonical_decompiled_code:
int func8()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) &= 0xF7u;
return fcntl(0, 4, v0);
}

original_code:
void set_input_blocking(void)
{
 int fl = fcntl(0, 3);
 fcntl(0, 4, fl & ~04000);
}

canonical_original_code:
void set_input_blocking()
{
 int fl = fcntl(0, 3);
 fcntl(0, 4, fl & ~04000);
}

variable_types: fl int


decompiled_code:
int set_input_nonblocking()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) |= 8u;
return fcntl(0, 4, v0);
}

canonical_decompiled_code:
int func9()
{
unsigned int v0; // eax

v0 = fcntl(0, 3);
BYTE1(v0) |= 8u;
return fcntl(0, 4, v0);
}

original_code:
void set_input_nonblocking(void)
{
 int fl = fcntl(0, 3);
 fcntl(0, 4, fl | 04000);
}

canonical_original_code:
void set_input_nonblocking()
{
 int fl = fcntl(0, 3);
 fcntl(0, 4, fl | 04000);
}


decompiled_code:
__int64 get_uint16()
{
unsigned __int16 v1; // [rsp+Eh] [rbp-2Ah]
char s[40]; // [rsp+10h] [rbp-28h] BYREF

set_input_blocking();
fgets(s, 32, stdin);
set_input_nonblocking();
__isoc99_sscanf();
return v1;
}

canonical_decompiled_code:
__int64 func10()
{
unsigned __int16 v1; // [rsp+Eh] [rbp-2Ah]
char s[40]; // [rsp+10h] [rbp-28h] BYREF

func8();
fgets(s, 32, stdin);
func9();
__isoc99_sscanf();
return v1;
}

original_code:
uint16_t get_uint16(void)
{
 char buf[32];
 uint16_t ret;
 set_input_blocking();
 fgets(buf, 32, stdin);
 set_input_nonblocking();
 sscanf(buf, "%hu", &ret);
 return ret;
}

canonical_original_code:
unsigned short get_uint16()
{
 char buf[32];
 unsigned short ret;
 set_input_blocking();
 fgets(buf, 32, stdin);
 set_input_nonblocking();
 sscanf(buf, "%hu", &ret);
 return ret;
}

variable_types:
ret
unsigned short


decompiled_code:
void clk_init()
{
;
}

canonical_decompiled_code:
void func16()
{
;
}

original_code:
void clk_init(void)
{
}

canonical_original_code:
void clk_init()
{
}


decompiled_code:
void clk_step()
{
int v0; // ebx
unsigned __int64 v1; // rax
struct timespec v2; // [rsp+0h] [rbp-18h] BYREF

if ( clk_enabled )
{
v0 = ticks;
clock_gettime(0, &v2);
v1 = 60 * (v2.tv_nsec + 1000000000 * (v2.tv_sec - t0.tv_sec) - t0.tv_nsec) / 0x3B9ACA00uLL / clk_scale;
ticks = v1;
if ( int_enabled )
{
if ( v0 != (_DWORD)v1 )
raise_interrupt(int_msg);
}
}
}

canonical_decompiled_code:
void func17()
{
int v0; // ebx
unsigned __int64 v1; // rax
struct timespec v2; // [rsp+0h] [rbp-18h] BYREF

if ( clk_enabled )
{
v0 = ticks;
clock_gettime(0, &v2);
v1 = 60 * (v2.tv_nsec + 1000000000 * (v2.tv_sec - t0.tv_sec) - t0.tv_nsec) / 0x3B9ACA00uLL / clk_scale;
ticks = v1;
if ( int_enabled )
{
if ( v0 != (_DWORD)v1 )
func15(int_msg);
}
}
}

original_code:
void clk_step(void)
{
 struct timespec tp;
 uint64_t ns;
 int old_ticks = ticks;
 if (clk_enabled) {
  clock_gettime(0, &tp);
  ns = (tp.tv_sec - t0.tv_sec) * 1000000000;
  ns += (tp.tv_nsec - t0.tv_nsec);
  ticks = ns * 60 / 1000000000 / clk_scale;
  if (int_enabled && (old_ticks != ticks))
   raise_interrupt(int_msg);
 }
}

canonical_original_code:
void clk_step()
{
 struct timespec tp;
 unsigned long ns;
 int old_ticks = ticks;
 if (clk_enabled) {
  clock_gettime(0, &tp);
  ns = (tp.tv_sec - t0.tv_sec) * 1000000000;
  ns += (tp.tv_nsec - t0.tv_nsec);
  ticks = ns * 60 / 1000000000 / clk_scale;
  if (int_enabled && (old_ticks != ticks))
   raise_interrupt(int_msg);
 }
}

variable_types: struct timespec { long tv_sec; long tv_nsec; }

variable_types:
ns
unsigned long


decompiled_code:
__int64 clk_interrupt()
{
unsigned __int16 v0; // bx
__int16 v1; // ax

v0 = read_register(1u);
v1 = read_register(0);
switch ( v1 )
{
case 1:
write_register(2u, ticks);
break;
case 2:
if ( v0 )
{
int_enabled = 1;
int_msg = v0;
}
else
{
int_enabled = 0;
}
break;
case 0:
if ( v0 )
{
clk_enabled = 1;
clock_gettime(0, &t0);
clk_scale = v0;
}
else
{
clk_enabled = 0;
}
break;
}
return 0LL;
}

canonical_decompiled_code:
__int64 func18()
{
unsigned __int16 v0; // bx
__int16 v1; // ax

v0 = func11(1u);
v1 = func11(0);
switch ( v1 )
{
case 1:
func13(2u, ticks);
break;
case 2:
if ( v0 )
{
int_enabled = 1;
int_msg = v0;
}
else
{
int_enabled = 0;
}
break;
case 0:
if ( v0 )
{
clk_enabled = 1;
clock_gettime(0, &t0);
clk_scale = v0;
}
else
{
clk_enabled = 0;
}
break;
}
return 0LL;
}

original_code:
int clk_interrupt(void)
{
 uint16_t b = read_register(REG_B);
 switch(read_register(REG_A)) {
 case 0:
  if (b) {
   clk_enabled = 1;
   clock_gettime(0, &t0);
   clk_scale = b;
  } else {
   clk_enabled = 0;
  }
  break;
 case 1:
  write_register(REG_C, ticks);
  break;
 case 2:
  if (b) {
   int_enabled = 1;
   int_msg = b;
  } else {
   int_enabled = 0;
  }
  break;
 default:
  break;
 }
 return 0;
}

canonical_original_code:
int clk_interrupt()
{
 unsigned short b = read_register(REG_B);
 switch(read_register(REG_A)) {
 case 0:
  if (b) {
   clk_enabled = 1;
   clock_gettime(0, &t0);
   clk_scale = b;
  } else {
   clk_enabled = 0;
  }
  break;
 case 1:
  write_register(REG_C, ticks);
  break;
 case 2:
  if (b) {
   int_enabled = 1;
   int_msg = b;
  } else {
   int_enabled = 0;
  }
  break;
 default:
  break;
 }
 return 0;
}

variable_types:
b
unsigned short


decompiled_code:
__m128i *generic_clock()
{
__m128i *result; // rax

result = (__m128i *)malloc(0x28uLL);
*result = _mm_load_si128((const __m128i *)&clk_builtin);
result[1] = _mm_load_si128((const __m128i *)&xmmword_4040B0);
result[2].m128i_i64[0] = (__int64)off_4040C0;
return result;
}

canonical_decompiled_code:
__m128i *func19()
{
__m128i *result; // rax

result = (__m128i *)malloc(0x28uLL);
*result = _mm_load_si128((const __m128i *)&clk_builtin);
result[1] = _mm_load_si128((const __m128i *)&xmmword_4040B0);
result[2].m128i_i64[0] = (__int64)off_4040C0;
return result;
}

original_code:
struct hw_builtin *generic_clock(void)
{
 struct hw_builtin *clk;
 clk = (struct hw_builtin *)malloc(sizeof(struct hw_builtin));
 *clk = clk_builtin;
 return clk;
}

canonical_original_code:
struct hw_builtin *generic_clock()
{
 struct hw_builtin *clk;
 clk = (struct hw_builtin *)malloc(sizeof(struct hw_builtin));
 *clk = clk_builtin;
 return clk;
}


decompiled_code:
__int64 __fastcall read_register(unsigned __int16 a1)
{
printf("reg r %hu\n", a1);
fflush(stdout);
return get_uint16();
}

canonical_decompiled_code:
__int64 __fastcall func11(unsigned __int16 a1)
{
printf("reg r %hu\n", a1);
fflush(stdout);
return func10();
}

original_code:
uint16_t read_register(uint16_t reg)
{
 printf("reg r %hu\n", reg);
 fflush(stdout);
 return get_uint16();
}

canonical_original_code:
unsigned short read_register(unsigned short reg)
{
 printf("reg r %hu\n", reg);
 fflush(stdout);
 return get_uint16();
}

variable_types:
reg
unsigned short


decompiled_code:
int __fastcall read_memory(unsigned __int16 a1, unsigned __int16 a2, _WORD *a3)
{
int result; // eax
_WORD *v5; // rbx

printf("mem r %hu %hu\n", a1, a2);
result = fflush(stdout);
if ( a2 )
{
v5 = a3;
do
{
result = get_uint16();
*v5++ = result;
}
while ( v5 != &a3[a2] );
}
return result;
}

canonical_decompiled_code:
int __fastcall func12(unsigned __int16 a1, unsigned __int16 a2, _WORD *a3)
{
int result; // eax
_WORD *v5; // rbx

printf("mem r %hu %hu\n", a1, a2);
result = fflush(stdout);
if ( a2 )
{
v5 = a3;
do
{
result = func10();
*v5++ = result;
}
while ( v5 != &a3[a2] );
}
return result;
}

original_code:
void read_memory(uint16_t addr, uint16_t len, uint16_t *buf)
{
 int i;
 printf("mem r %hu %hu\n", addr, len);
 fflush(stdout);
 for (i = 0; i < len; i++)
  buf[i] = get_uint16();
}

canonical_original_code:
void read_memory(unsigned short addr, unsigned short len, unsigned short *buf)
{
 int i;
 printf("mem r %hu %hu\n", addr, len);
 fflush(stdout);
 for (i = 0; i < len; i++)
  buf[i] = get_uint16();
}

variable_types:
addr
unsigned short

variable_types:
len
unsigned short

variable_types:
buf
unsigned short *

variable_types: i int


decompiled_code:
int __fastcall write_register(unsigned __int16 a1, unsigned __int16 a2)
{
printf("reg w %hu %hu\n", a1, a2);
return fflush(stdout);
}

canonical_decompiled_code:
int __fastcall func13(unsigned __int16 a1, unsigned __int16 a2)
{
printf("reg w %hu %hu\n", a1, a2);
return fflush(stdout);
}

original_code:
void write_register(uint16_t reg, uint16_t val)
{
 printf("reg w %hu %hu\n", reg, val);
 fflush(stdout);
}

canonical_original_code:
void write_register(unsigned short reg, unsigned short val)
{
 printf("reg w %hu %hu\n", reg, val);
 fflush(stdout);
}

variable_types:
val
unsigned short


decompiled_code:
int __fastcall write_memory(unsigned __int16 a1, unsigned __int16 a2, unsigned __int16 *a3)
{
unsigned __int16 *v4; // rbx

printf("mem w %hu %hu", a1, a2);
fflush(stdout);
if ( a2 )
{
v4 = a3;
do
{
printf(" %hu", *v4);
fflush(stdout);
++v4;
}
while ( v4 != &a3[a2] );
}
putchar(10);
return fflush(stdout);
}

canonical_decompiled_code:
int __fastcall func14(unsigned __int16 a1, unsigned __int16 a2, unsigned __int16 *a3)
{
unsigned __int16 *v4; // rbx

printf("mem w %hu %hu", a1, a2);
fflush(stdout);
if ( a2 )
{
v4 = a3;
do
{
printf(" %hu", *v4);
fflush(stdout);
++v4;
}
while ( v4 != &a3[a2] );
}
putchar(10);
return fflush(stdout);
}

original_code:
void write_memory(uint16_t addr, uint16_t len, uint16_t *buf)
{
 int i;
 printf("mem w %hu %hu", addr, len);
 fflush(stdout);
 for (i = 0; i < len; i++) {
  printf(" %hu", buf[i]);
  fflush(stdout);
 }
 printf("\n");
 fflush(stdout);
}

canonical_original_code:
void write_memory(unsigned short addr, unsigned short len, unsigned short *buf)
{
 int i;
 printf("mem w %hu %hu", addr, len);
 fflush(stdout);
 for (i = 0; i < len; i++) {
  printf(" %hu", buf[i]);
  fflush(stdout);
 }
 printf("\n");
 fflush(stdout);
}


decompiled_code:
int __fastcall raise_interrupt(unsigned __int16 a1)
{
printf("int %hu\n", a1);
return fflush(stdout);
}

canonical_decompiled_code:
int __fastcall func15(unsigned __int16 a1)
{
printf("int %hu\n", a1);
return fflush(stdout);
}

original_code:
void raise_interrupt(uint16_t msg)
{
 printf("int %hu\n", msg);
 fflush(stdout);
}

canonical_original_code:
void raise_interrupt(unsigned short msg)
{
 printf("int %hu\n", msg);
 fflush(stdout);
}

variable_types:
msg
unsigned short


decompiled_code:
__m128i *get_hw()
{
return generic_clock();
}

original_code:
struct hw_builtin *get_hw(void)
{
 return generic_clock();
}

canonical_original_code:
struct hw_builtin *get_hw()
{
 return generic_clock();
}


decompiled_code:
__int64 __fastcall queue_interrupt(__int16 a1)
{
__int64 result; // rax

LODWORD(result) = (unsigned __int8)last_unused_interrupt;
if ( (unsigned __int8)last_unused_interrupt + 1 == (unsigned __int8)next_interrupt )
return CATCH_FIRE();
++last_unused_interrupt;
result = (int)result;
interrupts[(int)result] = a1;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func0(__int16 a1)
{
__int64 result; // rax

LODWORD(result) = (unsigned __int8)last_unused_interrupt;
if ( (unsigned __int8)last_unused_interrupt + 1 == (unsigned __int8)next_interrupt )
return CATCH_FIRE();
++last_unused_interrupt;
result = (int)result;
interrupts[(int)result] = a1;
return result;
}

original_code:
void queue_interrupt(uint16_t msg)
{
 if ((last_unused_interrupt + 1) == next_interrupt)
  CATCH_FIRE();
 else
  interrupts[last_unused_interrupt++] = msg;
}

canonical_original_code:
void queue_interrupt(unsigned short msg)
{
 if ((last_unused_interrupt + 1) == next_interrupt)
  CATCH_FIRE();
 else
  interrupts[last_unused_interrupt++] = msg;
}


decompiled_code:
__int64 __fastcall trigger_interrupt(__int16 a1)
{
__int16 v1; // dx
__int16 v2; // ax
__int64 result; // rax

v1 = registers[11];
if ( v1 )
{
v2 = registers[9];
memory[(unsigned __int16)(v2 - 1)] = registers[8];
LOWORD(result) = v2 - 2;
registers[9] = result;
result = (unsigned __int16)result;
memory[(unsigned __int16)result] = registers[0];
registers[8] = v1;
registers[0] = a1;
interrupts_enabled = 0;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func1(__int16 a1)
{
__int16 v1; // dx
__int16 v2; // ax
__int64 result; // rax

v1 = registers[11];
if ( v1 )
{
v2 = registers[9];
memory[(unsigned __int16)(v2 - 1)] = registers[8];
LOWORD(result) = v2 - 2;
registers[9] = result;
result = (unsigned __int16)result;
memory[(unsigned __int16)result] = registers[0];
registers[8] = v1;
registers[0] = a1;
interrupts_enabled = 0;
}
return result;
}

original_code:
void trigger_interrupt(uint16_t msg)
{
 if (registers.IA != 0) {
  memory[--registers.SP] = registers.PC;
  memory[--registers.SP] = registers.A;
  registers.PC = registers.IA;
  registers.A = msg;
  interrupts_enabled = 0;
 }
}

canonical_original_code:
void trigger_interrupt(unsigned short msg)
{
 if (registers.IA != 0) {
  memory[--registers.SP] = registers.PC;
  memory[--registers.SP] = registers.A;
  registers.PC = registers.IA;
  registers.A = msg;
  interrupts_enabled = 0;
 }
}