text: 
  #include "config.h"
  
  #include <orc/orc.h>
  #include <orc/orcparse.h>
  
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <ctype.h>
  
  void output_code_emulate (OrcProgram *p, FILE *output);
  
  int verbose = 0;
  int error = 0;
  int compat;
  
  char *target = "sse";
  
  #define ORC_VERSION(a,b,c,d) ((a)*1000000 + (b)*10000 + (c)*100 + (d))
  #define REQUIRE(a,b,c,d) do { \
    if (ORC_VERSION((a),(b),(c),(d)) > compat) { \
      fprintf(stderr, "Feature used that is incompatible with --compat\n"); \
      exit (1); \
    } \
  } while (0)
  
  void help (void)
  {
    printf("Usage:\n");
    printf("  generate-emulation [OPTION...]\n");
    printf("\n");
    printf("Help Options:\n");
    printf("  -h, --help              Show help options\n");
    printf("\n");
    printf("Application Options:\n");
    printf("  -o, --output FILE       Write output to FILE\n");
    printf("      --header            Write header instead of .c file\n");
    printf("\n");
  
    exit (0);
  }
  
  int
  main (int argc, char *argv[])
  {
    char *output_file = NULL;
    char *input_file = NULL;
    FILE *output;
    int i;
    OrcOpcodeSet *opcode_set;
    int output_header = FALSE;
  
    orc_init ();
  
    for(i=1;i<argc;i++) {
      if (strcmp (argv[i], "--output") == 0 ||
          strcmp(argv[i], "-o") == 0) {
        if (i+1 < argc) {
          output_file = argv[i+1];
          i++;
        } else {
          help();
        }
      } else if (strcmp (argv[i], "--header") == 0) {
        output_header = TRUE;
      } else if (strncmp(argv[i], "-", 1) == 0) {
        printf("Unknown option: %s\n", argv[i]);
        exit (1);
      } else {
        if (input_file == NULL) {
          input_file = argv[i];
        } else {
          printf("More than one input file specified: %s\n", argv[i]);
          exit (1);
        }
      }
    }
  
    if (output_file == NULL) {
      output_file = output_header ? "out.h" : "out.c";
      printf("Writing to file: %s\n", output_file);
    }
  
    output = fopen (output_file, "w");
    if (!output) {
      printf("Could not write output file: %s\n", output_file);
      exit(1);
    }
  
    opcode_set = orc_opcode_set_get ("sys");
  
    fprintf(output, "\n");
    fprintf(output, "/* autogenerated by generate-emulation */\n");
    fprintf(output, "\n");
  
    if (output_header) {
      fprintf(output, "#ifndef _ORC_EMULATE_OPCODES_H_\n");
      fprintf(output, "#define _ORC_EMULATE_OPCODES_H_\n");
      fprintf(output, "\n");
      for(i=0;i<opcode_set->n_opcodes;i++){
        OrcStaticOpcode *opcode = opcode_set->opcodes + i;
  
        fprintf(output,
            "void emulate_%s (OrcOpcodeExecutor *ex, int i, int n);\n",
            opcode->name);
      }
      fprintf(output, "\n");
      fprintf(output, "#endif\n");
      fprintf(output, "\n");
    } else {
    
      fprintf(output, "#ifdef HAVE_CONFIG_H\n");
      fprintf(output, "#include \"config.h\"\n");
      fprintf(output, "#endif\n");
      fprintf(output, "#include <math.h>\n");
      fprintf(output, "#include <orc/orc.h>\n");
      fprintf(output, "\n");
      fprintf(output, "%s", orc_target_get_asm_preamble ("c"));
      fprintf(output, "\n");
  
      for(i=0;i<opcode_set->n_opcodes;i++){
        char s[40];
        OrcProgram *program;
        OrcStaticOpcode *opcode = opcode_set->opcodes + i;
        int args[4] = { -1, -1, -1, -1 };
        int n_args = 0;
  
        program = orc_program_new ();
  
        sprintf(s, "emulate_%s", opcode->name);
        orc_program_set_name (program, s);
  
        if (opcode->dest_size[0] != 0) {
          if (opcode->flags & ORC_STATIC_OPCODE_ACCUMULATOR) {
            args[n_args++] =
              orc_program_add_accumulator (program, opcode->dest_size[0], "d1");
          } else {
            args[n_args++] =
              orc_program_add_destination (program, opcode->dest_size[0], "d1");
          }
        }
        if (opcode->dest_size[1] != 0) {
          args[n_args++] =
            orc_program_add_destination (program, opcode->dest_size[1], "d2");
        }
        if (opcode->src_size[0] != 0) {
          if (opcode->src_size[1] == 0 &&
              opcode->flags & ORC_STATIC_OPCODE_SCALAR) {
            args[n_args++] =
              orc_program_add_parameter (program, opcode->src_size[0], "s1");
          } else {
            args[n_args++] =
              orc_program_add_source (program, opcode->src_size[0], "s1");
          }
        }
        if (opcode->src_size[1] != 0) {
          if (opcode->flags & ORC_STATIC_OPCODE_SCALAR) {
            args[n_args++] =
              orc_program_add_parameter (program, opcode->src_size[1], "s2");
          } else {
            args[n_args++] =
              orc_program_add_source (program, opcode->src_size[1], "s2");
          }
        }
        if (opcode->src_size[2] != 0) {
          if (opcode->flags & ORC_STATIC_OPCODE_SCALAR) {
            args[n_args++] =
              orc_program_add_parameter (program, opcode->src_size[2], "s3");
          } else {
            args[n_args++] =
              orc_program_add_source (program, opcode->src_size[2], "s3");
          }
        }
  
        orc_program_append_2 (program, opcode->name, 0, args[0], args[1],
            args[2], args[3]);
  
        output_code_emulate (program, output);
      }
    }
  
    fclose (output);
  
    if (error) exit(1);
  
    return 0;
  }
  
  
  const char *varnames[] = {
    "d1", "d2", "d3", "d4",
    "s1", "s2", "s3", "s4",
    "s5", "s6", "s7", "s8",
    "a1", "a2", "a3", "d4",
    "c1", "c2", "c3", "c4",
    "c5", "c6", "c7", "c8",
    "p1", "p2", "p3", "p4",
    "p5", "p6", "p7", "p8",
    "t1", "t2", "t3", "t4",
    "t5", "t6", "t7", "t8",
    "t9", "t10", "t11", "t12",
    "t13", "t14", "t15", "t16"
  };
  
  const char *enumnames[] = {
    "ORC_VAR_D1", "ORC_VAR_D2", "ORC_VAR_D3", "ORC_VAR_D4",
    "ORC_VAR_S1", "ORC_VAR_S2", "ORC_VAR_S3", "ORC_VAR_S4",
    "ORC_VAR_S5", "ORC_VAR_S6", "ORC_VAR_S7", "ORC_VAR_S8",
    "ORC_VAR_A1", "ORC_VAR_A2", "ORC_VAR_A3", "ORC_VAR_A4",
    "ORC_VAR_C1", "ORC_VAR_C2", "ORC_VAR_C3", "ORC_VAR_C4",
    "ORC_VAR_C5", "ORC_VAR_C6", "ORC_VAR_C7", "ORC_VAR_C8",
    "ORC_VAR_P1", "ORC_VAR_P2", "ORC_VAR_P3", "ORC_VAR_P4",
    "ORC_VAR_P5", "ORC_VAR_P6", "ORC_VAR_P7", "ORC_VAR_P8",
    "ORC_VAR_T1", "ORC_VAR_T2", "ORC_VAR_T3", "ORC_VAR_T4",
    "ORC_VAR_T5", "ORC_VAR_T6", "ORC_VAR_T7", "ORC_VAR_T8",
    "ORC_VAR_T9", "ORC_VAR_T10", "ORC_VAR_T11", "ORC_VAR_T12",
    "ORC_VAR_T13", "ORC_VAR_T14", "ORC_VAR_T15", "ORC_VAR_T16"
  };
  
  #if 0
  void
  output_prototype (OrcProgram *p, FILE *output)
  {
    OrcVariable *var;
    int i;
    int need_comma;
  
    fprintf(output, "%s (", p->name);
    need_comma = FALSE;
    for(i=0;i<4;i++){
      var = &p->vars[ORC_VAR_D1 + i];
      if (var->size) {
        if (need_comma) fprintf(output, ", ");
        if (var->type_name) {
          fprintf(output, "%s * %s", var->type_name,
              varnames[ORC_VAR_D1 + i]);
        } else {
          fprintf(output, "orc_uint%d * %s", var->size*8,
              varnames[ORC_VAR_D1 + i]);
        }
        if (p->is_2d) {
          fprintf(output, ", int %s_stride", varnames[ORC_VAR_D1 + i]);
        }
        need_comma = TRUE;
      }
    }
    for(i=0;i<4;i++){
      var = &p->vars[ORC_VAR_A1 + i];
      if (var->size) {
        if (need_comma) fprintf(output, ", ");
        if (var->type_name) {
          fprintf(output, "%s * %s", var->type_name,
              varnames[ORC_VAR_A1 + i]);
        } else {
          fprintf(output, "orc_uint%d * %s", var->size*8,
              varnames[ORC_VAR_A1 + i]);
        }
        need_comma = TRUE;
      }
    }
    for(i=0;i<8;i++){
      var = &p->vars[ORC_VAR_S1 + i];
      if (var->size) {
        if (need_comma) fprintf(output, ", ");
        if (var->type_name) {
          fprintf(output, "const %s * %s", var->type_name,
              varnames[ORC_VAR_S1 + i]);
        } else {
          fprintf(output, "const orc_uint%d * %s", var->size*8,
              varnames[ORC_VAR_S1 + i]);
        }
        if (p->is_2d) {
          fprintf(output, ", int %s_stride", varnames[ORC_VAR_S1 + i]);
        }
        need_comma = TRUE;
      }
    }
    for(i=0;i<8;i++){
      var = &p->vars[ORC_VAR_P1 + i];
      if (var->size) {
        if (need_comma) fprintf(output, ", ");
        if (var->is_float_param) {
          REQUIRE(0,4,5,1);
        }
        fprintf(output, "%s %s",
            var->is_float_param ? "float" : "int",
            varnames[ORC_VAR_P1 + i]);
        need_comma = TRUE;
      }
    }
    if (p->constant_n == 0) {
      if (need_comma) fprintf(output, ", ");
      fprintf(output, "int n");
      need_comma = TRUE;
    }
    if (p->is_2d && p->constant_m == 0) {
      if (need_comma) fprintf(output, ", ");
      fprintf(output, "int m");
    }
    fprintf(output, ")");
  }
  
  void
  output_code_header (OrcProgram *p, FILE *output)
  {
    fprintf(output, "void ");
    output_prototype (p, output);
    fprintf(output, ";\n");
  }
  #endif
  
  void
  output_code_emulate (OrcProgram *p, FILE *output)
  {
  
    fprintf(output, "void\n");
    if (p->constant_n) {
      fprintf(output, "%s (OrcOpcodeExecutor *ex, int offset)\n", p->name);
    } else {
      fprintf(output, "%s (OrcOpcodeExecutor *ex, int offset, int n)\n", p->name);
    }
    fprintf(output, "{\n");
    {
      OrcCompileResult result;
  
      result = orc_program_compile_full (p, orc_target_get_by_name("c"),
          ORC_TARGET_C_BARE | ORC_TARGET_C_OPCODE);
      if (ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) {
        fprintf(output, "%s\n", orc_program_get_asm_code (p));
      } else {
        printf("Failed to compile %s\n", p->name);
        error = TRUE;
      }
    }
    fprintf(output, "}\n");
    fprintf(output, "\n");
  
  }
  
  
  