#include "ovm.h" #include void ovm_free(ovm_t *ovm) { if (!ovm) return; g_slice_free1(ovm->limit * sizeof(instruction_t), ovm->instructions); g_slice_free1(ovm->limit * sizeof(gdouble), ovm->values); g_slice_free(ovm_t, ovm); } ovm_t* ovm_load(const gchar *filename) { GError *err = NULL; gchar *buf = NULL, *cur; gsize len = 0, i; instruction_t *oi; gdouble *vi; ovm_t *ovm = g_slice_new(ovm_t); ovm->limit = 0x4000; ovm->instructions = g_slice_alloc0(ovm->limit * sizeof(instruction_t)); ovm->values = g_slice_alloc0(ovm->limit * sizeof(gdouble)); if (!g_file_get_contents(filename, &buf, &len, &err)) { fprintf (stderr, "Unable to read file: %s\n", err->message); g_error_free (err); exit(1); } oi = ovm->instructions; vi = ovm->values; for (cur = buf, i = 0; i < len; i++) { *vi++ = *(gdouble*)buf; buf += sizeof(gdouble); *oi++ = *(guint32*)buf; buf += sizeof(guint32); if (++i < len) { *oi++ = *(guint32*)buf; buf += sizeof(guint32); *vi++ = *(gdouble*)buf; buf += sizeof(gdouble); } else { break; } } ovm->used = i; return ovm; } static const gchar* cmp_op_strings[] = { "<", "<=", "==", ">=", ">" }; void ovm_print_c(ovm_t *ovm, const gchar *filename) { guint i; instruction_t *oi = ovm->instructions; gdouble *vi = ovm->values; guint64 *uvi = (guint64*) ovm->values; guchar *usedv = g_slice_alloc0(ovm->used*sizeof(guchar)); GString *str = g_string_sized_new(0), *buf = g_string_sized_new(0); int f = g_open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0644); if (-1 == f) { fprintf(stderr, "Couldn't open file %s: %s\n", filename, g_strerror(errno)); exit(2); } g_string_append_len(buf, CONST_STR_LEN( "void ovm_step(gdouble scenario, gdouble *in, gdouble *out) {\n" )); #define USED(i) (usedv[i] = TRUE, i) for (i = 0; i < ovm->used; i++) { g_string_printf(str, "\t/* Invalid command: 0x%X */\n", (guint) oi[i]); switch (instr_dop(oi[i])) { case OP_STYPE: switch (instr_sop(oi[i])) { case SOP_NOOP: g_string_printf(str, "/* NOOP */\n"); g_string_truncate(str, 0); break; case SOP_CMPZ: g_string_printf(str, "\tovm_status = (v%u.d %s 0.0);\n", USED(instr_sop_r1(oi[i])), cmp_op_strings[instr_sop_cmp(oi[i])]); break; case SOP_SQRT: g_string_printf(str, "\tv%u.d = sqrt(v%u.d);\n", USED(i), USED(instr_sop_r1(oi[i]))); break; case SOP_COPY: g_string_printf(str, "\tv%u.d = v%u.d;\n", USED(i), USED(instr_sop_r1(oi[i]))); break; case SOP_IN: if (0x3e80 == instr_sop_r1(oi[i])) { g_string_printf(str, "\tv%u.d = scenario;\n", USED(i)); } else { g_string_printf(str, "\tv%u.d = in[%u];\n", USED(i), instr_sop_r1(oi[i])); } break; } break; case OP_ADD: g_string_printf(str, "\tv%u.d = v%u.d + v%u.d;\n", USED(i), USED(instr_dop_r1(oi[i])), USED(instr_dop_r2(oi[i]))); break; case OP_SUB: g_string_printf(str, "\tv%u.d = v%u.d - v%u.d;\n", USED(i), USED(instr_dop_r1(oi[i])), USED(instr_dop_r2(oi[i]))); break; case OP_MULT: g_string_printf(str, "\tv%u.d = v%u.d * v%u.d;\n", USED(i), USED(instr_dop_r1(oi[i])), USED(instr_dop_r2(oi[i]))); break; case OP_DIV: g_string_printf(str, "\tv%u.d = (v%u.d == 0.0) ? 0.0 : v%u.d / v%u.d;\n", USED(i), USED(instr_dop_r2(oi[i])), USED(instr_dop_r1(oi[i])), instr_dop_r2(oi[i])); break; case OP_OUT: g_string_printf(str, "\tout[%u] = v%u.d;\n", instr_dop_r1(oi[i]), USED(instr_dop_r2(oi[i]))); break; case OP_PHI: g_string_printf(str, "\tv%u.d = ovm_status ? v%u.d : v%u.d;\n", USED(i), USED(instr_dop_r1(oi[i])), USED(instr_dop_r2(oi[i]))); break; } g_string_append_len(buf, GSTR_LEN(str)); } #undef USED g_string_append_len(buf, CONST_STR_LEN( "}\n" "\n" )); write(f, CONST_STR_LEN( "#include \"task.h\"\n" "#include \n" "\n" "typedef union { gdouble d; guint64 i; } double_int;\n" "\n" "static gboolean ovm_status = FALSE;\n" "\n" "static double_int v0" )); for (i = 1; i < ovm->used; i++) { if (!usedv[i]) continue; g_string_printf(str, ", v%u", i); write(f, GSTR_LEN(str)); } write(f, CONST_STR_LEN( ";\n" "\n" "void ovm_init() {\n" "\tovm_status = FALSE;\n" "\n" )); for (i = 0; i < ovm->used; i++) { if (!usedv[i]) continue; g_string_printf(str, "\tv%u.i = G_GUINT64_CONSTANT(%" G_GUINT64_FORMAT "); /* %f */ \n", i, uvi[i], vi[i]); write(f, GSTR_LEN(str)); } write(f, CONST_STR_LEN( "}\n" "\n" )); write(f, GSTR_LEN(buf)); close(f); g_string_free(str, TRUE); g_string_free(buf, TRUE); }