diff --git a/ovm/.gitignore b/ovm/.gitignore new file mode 100644 index 0000000..6c3c9d2 --- /dev/null +++ b/ovm/.gitignore @@ -0,0 +1,2 @@ +kdebuild +ovm.kdev4 diff --git a/ovm/CMakeLists.txt b/ovm/CMakeLists.txt new file mode 100644 index 0000000..cab5733 --- /dev/null +++ b/ovm/CMakeLists.txt @@ -0,0 +1,62 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0 FATAL_ERROR) + +PROJECT(ovm C) + +MACRO(ADD_TARGET_PROPERTIES _target _name) + SET(_properties) + FOREACH(_prop ${ARGN}) + SET(_properties "${_properties} ${_prop}") + ENDFOREACH(_prop) + GET_TARGET_PROPERTY(_old_properties ${_target} ${_name}) + MESSAGE("adding property to ${_target} ${_name}:" ${_properties}) + IF(NOT _old_properties) + # in case it's NOTFOUND + SET(_old_properties) + ENDIF(NOT _old_properties) + SET_TARGET_PROPERTIES(${_target} PROPERTIES ${_name} "${_old_properties} ${_properties}") +ENDMACRO(ADD_TARGET_PROPERTIES) + +INCLUDE(CheckCSourceCompiles) +INCLUDE(CheckIncludeFiles) +INCLUDE(CheckFunctionExists) +INCLUDE(CheckVariableExists) +INCLUDE(CheckTypeSize) +INCLUDE(CheckLibraryExists) +INCLUDE(CMakeDetermineCCompiler) +INCLUDE(FindThreads) +INCLUDE(FindPkgConfig) + +# glib/gthread +pkg_check_modules(GTHREAD REQUIRED gthread-2.0) +# pkg_check_modules(GMODULE REQUIRED gmodule-2.0) + +ADD_EXECUTABLE(ovmjit + ovmjit.c + ovm.c +) + +ADD_EXECUTABLE(task1 + bin1.c + task.c + task1.c +) + +SET(WARN_FLAGS "-g -O2 -g2 -Wall -Wmissing-declarations -Wdeclaration-after-statement -Wcast-align -Wsign-compare -Wnested-externs -Wpointer-arith -Wl,--as-needed") +# -Werror -Wbad-function-cast -Wmissing-prototypes + +SET(COMMON_LDFLAGS "${GTHREAD_LDFLAGS} ${WARN_FLAGS}") +SET(COMMON_CFLAGS "${GTHREAD_CFLAGS} ${WARN_FLAGS}") + +ADD_TARGET_PROPERTIES(ovmjit LINK_FLAGS ${COMMON_LDFLAGS}) +ADD_TARGET_PROPERTIES(ovmjit COMPILE_FLAGS ${COMMON_CFLAGS}) + +ADD_TARGET_PROPERTIES(task1 LINK_FLAGS -lm ${COMMON_LDFLAGS}) +ADD_TARGET_PROPERTIES(task1 COMPILE_FLAGS ${COMMON_CFLAGS}) + +IF(CMAKE_COMPILER_IS_GNUCC) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -g -Wshadow -W -pedantic") + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0") + SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_WITHDEBINFO} -O2") + ADD_DEFINITIONS(-D_GNU_SOURCE) +ENDIF(CMAKE_COMPILER_IS_GNUCC) diff --git a/ovm/base.h b/ovm/base.h new file mode 100644 index 0000000..ff48de6 --- /dev/null +++ b/ovm/base.h @@ -0,0 +1,26 @@ +#ifndef OVM_BASE_H +#define OVM_BASE_H + +#define L_GOFFSET_FORMAT G_GINT64_FORMAT +#define L_GOFFSET_MODIFIER G_GINT64_MODIFIER + +#define CONST_STR_LEN(x) (x), sizeof(x) - 1 + +#define GSTR_LEN(x) (x) ? (x)->str : "", (x) ? (x)->len : 0 +#define GSTR_SAFE_STR(x) ((x && x->str) ? x->str : "(null)") + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/ovm/bin1.c b/ovm/bin1.c new file mode 120000 index 0000000..6443991 --- /dev/null +++ b/ovm/bin1.c @@ -0,0 +1 @@ +../task/bin1.c \ No newline at end of file diff --git a/ovm/bin2.c b/ovm/bin2.c new file mode 120000 index 0000000..8926aa9 --- /dev/null +++ b/ovm/bin2.c @@ -0,0 +1 @@ +../task/bin2.c \ No newline at end of file diff --git a/ovm/bin3.c b/ovm/bin3.c new file mode 120000 index 0000000..3ed0c45 --- /dev/null +++ b/ovm/bin3.c @@ -0,0 +1 @@ +../task/bin3.c \ No newline at end of file diff --git a/ovm/ovm.c b/ovm/ovm.c new file mode 100644 index 0000000..572b379 --- /dev/null +++ b/ovm/ovm.c @@ -0,0 +1,168 @@ + +#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); +} diff --git a/ovm/ovm.h b/ovm/ovm.h new file mode 100644 index 0000000..c1ca6bc --- /dev/null +++ b/ovm/ovm.h @@ -0,0 +1,66 @@ +#ifndef OVM_OVM_H +#define OVM_OVM_H + +#include "base.h" + +typedef guint32 instruction_t; +typedef enum { + OP_STYPE = 0x0, + OP_ADD = 0x1, + OP_SUB = 0x2, + OP_MULT = 0x3, + OP_DIV = 0x4, + OP_OUT = 0x5, + OP_PHI = 0x6 +} dop_t; +typedef enum { + SOP_NOOP = 0x0, + SOP_CMPZ = 0x1, + SOP_SQRT = 0x2, + SOP_COPY = 0x3, + SOP_IN = 0x4 +} sop_t; +typedef enum { + CMP_LTZ = 0x0, /* < */ + CMP_LEZ = 0x1, /* <= */ + CMP_EQZ = 0x2, /* == */ + CMP_GEZ = 0x3, /* >= */ + CMP_GTZ = 0x4 /* > */ +} cmp_t; + +static inline dop_t instr_dop(instruction_t i) { + return i >> 28; +} + +static inline sop_t instr_sop(instruction_t i) { + return i >> 24; /* upper bits are 0 */ +} + +static inline guint instr_dop_r1(instruction_t i) { + return (i >> 14) & 0x3FFF; +} + +static inline guint instr_dop_r2(instruction_t i) { + return i & 0x3FFF; +} + +static inline cmp_t instr_sop_cmp(instruction_t i) { + return (i >> 20) & 0xF; +} + +static inline guint instr_sop_r1(instruction_t i) { + return i & 0x3FFF; +} + +typedef struct { + gsize limit, used; + instruction_t *instructions; + gdouble *values; + guint32 pc; +} ovm_t; + +void ovm_free(ovm_t *ovm); +ovm_t* ovm_load(const gchar *filename); +void ovm_print_c(ovm_t *ovm, const gchar *filename); + +#endif diff --git a/ovm/ovmjit.c b/ovm/ovmjit.c new file mode 100644 index 0000000..f06bb76 --- /dev/null +++ b/ovm/ovmjit.c @@ -0,0 +1,17 @@ + +#include "ovm.h" + +int main(int argc, char** argv) { + ovm_t *ovm; + + if (argc < 3) { + fprintf(stderr, "Wrong syntax. %s in out\n", argv[0]); + exit(1); + } + + ovm = ovm_load(argv[1]); + ovm_print_c(ovm, argv[2]); + ovm_free(ovm); + + return 0; +} diff --git a/ovm/task.c b/ovm/task.c new file mode 100644 index 0000000..73bc4d8 --- /dev/null +++ b/ovm/task.c @@ -0,0 +1,19 @@ + +#include "task.h" + +void task_free(task_t *task) { + if (!task) return; + g_slice_free1(task->in_size * sizeof(gdouble), task->in); + g_slice_free1(task->out_size * sizeof(gdouble), task->out); + g_slice_free(task_t, task); +} + +task_t* task_new(gdouble scenario, guint in_size, guint out_size) { + task_t *task = g_slice_new(task_t); + task->scenario = scenario; + task->in_size = in_size; + task->out_size = out_size; + task->in = g_slice_alloc0(task->in_size * sizeof(gdouble)); + task->out = g_slice_alloc0(task->out_size * sizeof(gdouble)); + return task; +} diff --git a/ovm/task.h b/ovm/task.h new file mode 100644 index 0000000..5b360ac --- /dev/null +++ b/ovm/task.h @@ -0,0 +1,28 @@ +#ifndef OVM_TASK_H +#define OVM_TASK_H + +#include "base.h" + +typedef struct { + gdouble scenario; + guint in_size, out_size; + gdouble *in, *out; +} task_t; + +typedef void (*task_app_t)(task_t *task); + +task_t* task_new(gdouble scenario, guint in_size, guint out_size); +void task_free(task_t *task); + +void ovm_init(); +void ovm_step(gdouble scenario, gdouble *in, gdouble *out); + +static inline void task_run(task_t *task, task_app_t app) { + ovm_init(); + while (task->out[0] == 0.0) { + app(task); + ovm_step(task->scenario, task->in, task->out); + } +} + +#endif \ No newline at end of file diff --git a/ovm/task1.c b/ovm/task1.c new file mode 100644 index 0000000..e4a2955 --- /dev/null +++ b/ovm/task1.c @@ -0,0 +1,6 @@ + +#include "base.h" + +int main(int argc, char **argv) { + return 0; +} \ No newline at end of file diff --git a/task/.gitignore b/task/.gitignore new file mode 100644 index 0000000..064a8d8 --- /dev/null +++ b/task/.gitignore @@ -0,0 +1 @@ +*.c diff --git a/task/Makefile b/task/Makefile new file mode 100644 index 0000000..e8e431c --- /dev/null +++ b/task/Makefile @@ -0,0 +1,20 @@ + +OVMJIT=../ovm/kdebuild/ovmjit + +.SUFFIXES: .c .obf .o + +FILES_OBF=bin1.obf bin2.obf bin3.obf +FILES_C=$(FILES_OBF:.obf=.c) + +.PHONY: all sources clean + +all: sources + +%.c: %.obf $(OVMJIT) + @echo Creatin $@ from $< + @$(OVMJIT) $< $@ + +sources: $(FILES_C) + +clean: + rm -f $(FILES_C) diff --git a/task/bin1.obf b/task/bin1.obf new file mode 100644 index 0000000..e00142e Binary files /dev/null and b/task/bin1.obf differ diff --git a/task/bin2.obf b/task/bin2.obf new file mode 100644 index 0000000..7d14154 Binary files /dev/null and b/task/bin2.obf differ diff --git a/task/bin3.obf b/task/bin3.obf new file mode 100644 index 0000000..041005a Binary files /dev/null and b/task/bin3.obf differ diff --git a/task/task.pdf b/task/task.pdf new file mode 100644 index 0000000..6917c2b Binary files /dev/null and b/task/task.pdf differ