/* I, Luca Saiu, author of this script, hereby release it into the public domain
   up to the extent permitted by law. */

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

union value
{
  void *label;
  long i;
  union value *p;
};

int
main (void)
{
  long regs[10];

  union value program []
    = { // Assign 2000000000 into %r0.
        {.label = && label_set},  // 0
        {.i = 2000000000},        // 1
        {.i = 0},                 // 2

        // Assign -1 into %r1.
        {.label = && label_set},  // 3
        {.i = -1},                // 4
        {.i = 1},                 // 5

        // Sum %r0 and %r1 into %r0.
        {.label = && label_add},  // 6
        {.i = 0},                 // 7
        {.i = 1},                 // 8
        {.i = 0},                 // 9

        /* // Sum %r0 and the immediate -1 into %r0. */
        /* {.label = && label_addi}, // 6 */
        /* {.i = 0},                 // 7 */
        /* {.i = -1},                // 8 */
        /* {.i = 0},                 // 9 */

        /* // Decrement %r0. */
        /* {.label = && label_decr}, // 6 */
        /* {.i = 0},                 // 7 */

        /* // Branch to the 7th program word.
           {.label = && label_b},
           {.p = program + 6}, */

        /* // Print %r0.
           {.label = && label_print},
           {.i = 0}, */

        // If %r0 is non-zero branch to the
        // seventh program word.
        {.label = && label_bnz},
        {.i = 0},
        {.p = program + 6},

        // Do nothing.
        {.label = && label_nop},

        // A useless branch to the next instruction.
        {.label = && label_b},
        {.p = program + 16},

        // Exit the interpreter.
        {.label = && label_end} };

  const union value *insn = program;
  goto * insn->label;

 label_nop: asm volatile ("# label_nop");
  insn ++;
  goto * insn->label;

 label_set: asm volatile ("# label_set");
  regs[insn[2].i] = insn[1].i;
  insn += 3;
  goto * insn->label;

 label_add: asm volatile ("# label_add");
  regs[insn[3].i] = regs[insn[1].i] + regs[insn[2].i];
  insn += 4;
  goto * insn->label;

 label_addi: asm volatile ("# label_addi");
  regs[insn[3].i] = regs[insn[1].i] + insn[2].i;
  insn += 4;
  goto * insn->label;

 label_decr: asm volatile ("# label_decr");
  regs[insn[3].i] --;
  insn += 2;
  goto * insn->label;

 label_b: asm volatile ("# label_b");
  insn = insn[1].p;
  goto * insn->label;

 label_bnz: asm volatile ("# label_bnz");
  if (regs[insn[1].i] != 0)
    insn = insn[2].p;
  else
    insn += 3;
  goto * insn->label;

 label_print: asm volatile ("# label_print");
  printf ("%li\n", regs[insn[1].i]);
  insn += 2;
  goto * insn->label;

 label_end: asm volatile ("# label_end");
  exit (EXIT_SUCCESS);
}
