From 21db33fa971a86e63dd2383a41611d7e3223ca4e Mon Sep 17 00:00:00 2001 From: "e.gavrin" Date: Mon, 7 Jul 2014 23:18:49 +0400 Subject: [PATCH] added opcodes --- src/libcoreint/interpreter.c | 25 +- src/libcoreint/opcode-structures.h | 358 +++++++++++++++++++++++++++-- src/libcoreint/opcodes.c | 69 +++++- src/libcoreint/opcodes.h | 103 ++++++++- 4 files changed, 518 insertions(+), 37 deletions(-) diff --git a/src/libcoreint/interpreter.c b/src/libcoreint/interpreter.c index 4a531e8b5..0c96e0b81 100644 --- a/src/libcoreint/interpreter.c +++ b/src/libcoreint/interpreter.c @@ -20,12 +20,26 @@ gen_bytecode () { __int_data.pos = 0; + /* + while (true) { + LEDToggle (LED3); + LEDToggle (LED6); + LEDToggle (LED7); + LEDToggle (LED4); + LEDToggle (LED10); + LEDToggle (LED8); + LEDToggle (LED9); + LEDToggle (LED5); + + wait(500); + } + */ save_op_data (getop_loop_inf (1)); save_op_data (getop_call_1 (0, 12)); save_op_data (getop_call_1 (0, 13)); save_op_data (getop_call_1 (0, 14)); save_op_data (getop_call_1 (0, 15)); - //save_op_data (getop_jmp (0)); + save_op_data (getop_jmp (0)); #ifdef __MCU // It's mandatory to restart app! @@ -49,9 +63,8 @@ run_int () init_int (); while (true) - { - printf ("size %lu\n", sizeof (OPCODE)); - OPCODE *curr = &__program[__int_data.pos]; - __int_data.func[curr->op_idx](*curr); - } + { + OPCODE *curr = &__program[__int_data.pos]; + __int_data.func[curr->op_idx](*curr); + } } diff --git a/src/libcoreint/opcode-structures.h b/src/libcoreint/opcode-structures.h index f14bc2862..592c27377 100644 --- a/src/libcoreint/opcode-structures.h +++ b/src/libcoreint/opcode-structures.h @@ -23,11 +23,10 @@ OP_DEF (name, type##_DECL( __VA_ARGS__ ) ); \ OPCODE getop_##name ( type ); -#define T_IDX uint8_t #define T_IDX_IDX T_IDX, T_IDX #define T_IDX_IDX_IDX T_IDX, T_IDX, T_IDX -#define T_IDX_DECL(name) uint8_t name +#define T_IDX_DECL(name) T_IDX name #define T_IDX_IDX_DECL(name1, name2) \ T_IDX_DECL( name1 ) ; \ T_IDX_DECL( name2 ) @@ -36,25 +35,352 @@ T_IDX_DECL( name2 ); \ T_IDX_DECL( name3 ) +// All conditional jumps should be followed by a JMP instruction, which holds +// the target of conditional JMP. If condition is TRUE, than JMP to the target. +// Otherwise they fall through to the instruction after the JMP. +// if (true) { JMP } else { INSTR_AFTER_JMP } +// NOTE: We cannot swap L < R to R > L, because of floating-point semantics. -OP_CODE_DECL(nop, T_IDX, opcode_idx); -OP_CODE_DECL(jmp, T_IDX, opcode_idx); -OP_CODE_DECL(loop_inf, T_IDX, opcode_idx); +/** L < R */ +OP_CODE_DECL (is_less_than, T_IDX_IDX, + value_left, + value_right); -OP_CODE_DECL(call_1, T_IDX_IDX, - name_literal_idx, - arg1_literal_idx); +/** L <= R */ +OP_CODE_DECL (is_less_or_equal, T_IDX_IDX, + value_left, + value_right); -OP_CODE_DECL(call_2, T_IDX_IDX_IDX, - name_literal_idx, - arg1_literal_idx, - arg2_literal_idx); +/** L > R */ +OP_CODE_DECL (is_greater_than, T_IDX_IDX, + value_left, + value_right); -OP_CODE_DECL(call_n, T_IDX_IDX_IDX, - name_literal_idx, - arg1_literal_idx, - arg2_literal_idx); +/** L >= R */ +OP_CODE_DECL (is_greater_or_equal, T_IDX_IDX, + value_left, + value_right); +/** L == R */ +OP_CODE_DECL (is_equal_value, T_IDX_IDX, + value_left, + value_right); + +/** L != R */ +OP_CODE_DECL (is_not_equal_value, T_IDX_IDX, + value_left, + value_right); + +/** L === R */ +OP_CODE_DECL (is_equal_value_type, T_IDX_IDX, + value_left, + value_right); + +/** L !== R */ +OP_CODE_DECL (is_not_equal_value_type, T_IDX_IDX, + value_left, + value_right); + +/** Instruction tests if BOOLEAN value is TRUE and JMP to DST */ +OP_CODE_DECL (is_true_jmp, T_IDX_IDX, + value, + opcode); + +/** Instruction tests if BOOLEAN value is FALSE and JMP to DST */ +OP_CODE_DECL (is_false_jmp, T_IDX_IDX, + value, + opcode); + +/** Unconditional JMP to the specified opcode index */ +OP_CODE_DECL (jmp, T_IDX, + opcode_idx); + +/** Unconditional JMP on opcode_count up */ +OP_CODE_DECL (jmp_up, T_IDX, + opcode_count); + +/** Unconditional JMP on opcode_count down */ +OP_CODE_DECL (jmp_down, T_IDX, + opcode_count); + +/** dst = L + R */ +OP_CODE_DECL (addition, T_IDX_IDX_IDX, + dst, + var_left, + var_right); + +/** dst = L - R */ +OP_CODE_DECL (substraction, T_IDX_IDX_IDX, + dst, + var_left, + var_right); + +/** dst = L / R */ +OP_CODE_DECL (division, T_IDX_IDX_IDX, + dst, + var_left, + var_right); + +/** dst = L * R */ +OP_CODE_DECL (multiplication, T_IDX_IDX_IDX, + dst, + var_left, + var_right); + +/** dst = L % R */ +OP_CODE_DECL (remainder, T_IDX_IDX_IDX, + dst, + var_left, + var_right); + +/** dst = L << R */ +OP_CODE_DECL (b_shift_left, T_IDX_IDX_IDX, + dst, + var_left, + var_right); + +/** dst = L >> R */ +OP_CODE_DECL (b_shift_right, T_IDX_IDX_IDX, + dst, + var_left, + var_right); + +/** dst = L >>> R */ +OP_CODE_DECL (b_shift_uright, T_IDX_IDX_IDX, + dst, + var_left, + var_right); + +// Binary bitwise operators. +// Operands is a set of 32 bits +// Returns numerical. + +/** dst = L & R */ +OP_CODE_DECL (b_and, T_IDX_IDX_IDX, + dst, + var_left, + var_right); + +/** dst = L | R */ +OP_CODE_DECL (b_or, T_IDX_IDX_IDX, + dst, + var_left, + var_right); + +/** dst = L ^ R */ +OP_CODE_DECL (b_xor, T_IDX_IDX_IDX, + dst, + var_left, + var_right); + +// Binary logical operators. +// Operands are booleans. +// Return boolean. + +/** dst = L && R */ +OP_CODE_DECL (logical_and, T_IDX_IDX_IDX, + dst, + var_left, + var_right); + +/** dst = L || R */ +OP_CODE_DECL (logical_or, T_IDX_IDX_IDX, + dst, + var_left, + var_right); + +// Assignment operators. +// Assign value to LEFT operand based on value of RIGHT operand. + +/** L = R */ +OP_CODE_DECL (assignment, T_IDX_IDX, + value_left, + value_right); + +/** L *= R */ +OP_CODE_DECL (assignment_multiplication, T_IDX_IDX, + value_left, + value_right); + +/** L /= R */ +OP_CODE_DECL (assignment_devision, T_IDX_IDX, + value_left, + value_right); + +/** L %= R */ +OP_CODE_DECL (assignment_remainder, T_IDX_IDX, + value_left, + value_right); + +/** L += R */ +OP_CODE_DECL (assignment_addition, T_IDX_IDX, + value_left, + value_right); + +/** L -= R */ +OP_CODE_DECL (assignment_substruction, T_IDX_IDX, + value_left, + value_right); + +/** L <<= R */ +OP_CODE_DECL (assignment_shift_left, T_IDX_IDX, + value_left, + value_right); + +/** L >>= R */ +OP_CODE_DECL (assignment_shift_right, T_IDX_IDX, + value_left, + value_right); + +/** L >>>= R */ +OP_CODE_DECL (assignment_shift_uright, T_IDX_IDX, + value_left, + value_right); + +/** L &= R */ +OP_CODE_DECL (assignment_b_and, T_IDX_IDX, + value_left, + value_right); + +/** L ^= R */ +OP_CODE_DECL (assignment_b_xor, T_IDX_IDX, + value_left, + value_right); + +/** L |= R */ +OP_CODE_DECL (assignment_b_or, T_IDX_IDX, + value_left, + value_right); + +// Functions calls, declarations and argument handling + +/** name(arg1); */ +OP_CODE_DECL (call_1, T_IDX_IDX, + name_lit_idx, + arg1_lit_idx); + +/** name(arg1, arg2); */ +OP_CODE_DECL (call_2, T_IDX_IDX_IDX, + name_lit_idx, + arg1_lit_idx, + arg2_lit_idx); + +/** name(arg1, arg2, ... */ +OP_CODE_DECL (call_n, T_IDX_IDX_IDX, + name_lit_idx, + arg1_lit_idx, + arg2_lit_idx); + +/** name(arg1); */ +OP_CODE_DECL (func_decl_1, T_IDX_IDX, + name_lit_idx, + arg1_lit_idx); + +/** name(arg1, arg2); */ +OP_CODE_DECL (func_decl_2, T_IDX_IDX_IDX, + name_lit_idx, + arg1_lit_idx, + arg2_lit_idx); + +/** name(arg1, arg2, ... */ +OP_CODE_DECL (func_decl_n, T_IDX_IDX_IDX, + name_lit_idx, + arg1_lit_idx, + arg2_lit_idx); + +/** ..., arg1, ... */ +OP_CODE_DECL (varg_1, T_IDX, + arg1_lit_idx); + +/** ..., arg1); */ +OP_CODE_DECL (varg_1_end, T_IDX, + arg1_lit_idx); + +/** ..., arg1, arg2, ... */ +OP_CODE_DECL (varg_2, T_IDX_IDX, + arg1_lit_idx, + arg2_lit_idx); + +/** ..., arg1, arg2); */ +OP_CODE_DECL (varg_2_end, T_IDX_IDX, + arg1_lit_idx, + arg2_lit_idx); + +/** arg1, arg2, arg3, ... */ +OP_CODE_DECL (varg_3, T_IDX_IDX_IDX, + arg1_lit_idx, + arg2_lit_idx, + arg3_lit_idx); + +/** arg1, arg2, arg3); */ +OP_CODE_DECL (varg_3_end, T_IDX_IDX_IDX, + arg1_lit_idx, + arg2_lit_idx, + arg3_lit_idx); + +/** return value; */ +OP_CODE_DECL (retval, T_IDX, + ret_value); + +// LOOPS +// Lately, all loops should be translated into different JMPs in an optimizer. + +/** End of body of infinite loop should be ended with unconditional JMP + * to loop_root (ie. next op after loop condition) */ +OP_CODE_DECL (loop_inf, T_IDX, + loop_root); + +/** Numeric loop initialization. + * for (start,stop,step) + */ +OP_CODE_DECL (loop_init_num, T_IDX_IDX_IDX, + start, + stop, + step); + +/** Check loop (condition). + * if (loop cond is true) + * { next_op } + * else + * { goto after_loop_op; } + */ +OP_CODE_DECL (loop_precond_begin_num, T_IDX_IDX, + condition, + after_loop_op); + +/** i++; + * Increment iterator on step and JMP to PRECOND + */ +OP_CODE_DECL (loop_precond_end_num, T_IDX_IDX_IDX, + iterator, + step, + precond_begin); + +/** do {...} while (cond); + * If condition is true, JMP to BODY_ROOT + */ +OP_CODE_DECL (loop_postcond, T_IDX_IDX, + condition, + body_root); + +//// TODO +///** for vars...in iter, state, ctl */ +//OP_CODE_DECL (loop_init, T_IDX_IDX_IDX, +// start_idx, stop_idx, step_idx); +///** loop (condition) */ +//OP_CODE_DECL (loop_cond_pre_begin, T_IDX_IDX, +// condition, body_root); +///** i++;*/ +//OP_CODE_DECL (loop_cond_pre_end, T_IDX, +// iterator, body_root); + +/** Array ops for ILMIR*/ +//OP_CODE_DECL (array_copy, T_IDX_IDX, /** L = R */ +// var_left, var_right); +//OP_CODE_DECL (array_set, T_IDX_IDX_IDX, /** array[index] = src */ +// dst, var_left, var_right); +//OP_CODE_DECL (array_get, T_IDX_IDX_IDX, /** dst = array[index] */ +// dst, array, index); #endif /* OPCODE_STRUCTURES_H */ diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index b3c996ff0..4eb2f9ec1 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "error.h" #include "opcodes.h" #include "interpreter.h" @@ -22,16 +23,70 @@ save_op_data (OPCODE opdata) __program[__int_data.pos++] = opdata; } +void opfunc_loop_init_num (OPCODE opdata) { unreachable (); } +void opfunc_loop_precond_begin_num (OPCODE opdata) { unreachable (); } +void opfunc_loop_precond_end_num (OPCODE opdata) { unreachable (); } +void opfunc_loop_postcond (OPCODE opdata) { unreachable (); } +void opfunc_call_2 (OPCODE opdata) { unreachable (); } +void opfunc_call_n (OPCODE opdata) { unreachable (); } +void opfunc_func_decl_1 (OPCODE opdata) { unreachable (); } +void opfunc_func_decl_2 (OPCODE opdata) { unreachable (); } +void opfunc_func_decl_n (OPCODE opdata) { unreachable (); } +void opfunc_varg_1 (OPCODE opdata) { unreachable (); } +void opfunc_varg_1_end (OPCODE opdata) { unreachable (); } +void opfunc_varg_2 (OPCODE opdata) { unreachable (); } +void opfunc_varg_2_end (OPCODE opdata) { unreachable (); } +void opfunc_varg_3 (OPCODE opdata) { unreachable (); } +void opfunc_varg_3_end (OPCODE opdata) { unreachable (); } +void opfunc_retval (OPCODE opdata) { unreachable (); } +void opfunc_assignment (OPCODE opdata) { unreachable (); } +void opfunc_assignment_multiplication (OPCODE opdata) { unreachable (); } +void opfunc_assignment_devision (OPCODE opdata) { unreachable (); } +void opfunc_assignment_remainder (OPCODE opdata) { unreachable (); } +void opfunc_assignment_addition (OPCODE opdata) { unreachable (); } +void opfunc_assignment_substruction (OPCODE opdata) { unreachable (); } +void opfunc_assignment_shift_left (OPCODE opdata) { unreachable (); } +void opfunc_assignment_shift_right (OPCODE opdata) { unreachable (); } +void opfunc_assignment_shift_uright (OPCODE opdata) { unreachable (); } +void opfunc_assignment_b_and (OPCODE opdata) { unreachable (); } +void opfunc_assignment_b_xor (OPCODE opdata) { unreachable (); } +void opfunc_assignment_b_or (OPCODE opdata) { unreachable (); } +void opfunc_logical_and (OPCODE opdata) { unreachable (); } +void opfunc_logical_or (OPCODE opdata) { unreachable (); } +void opfunc_b_and (OPCODE opdata) { unreachable (); } +void opfunc_b_or (OPCODE opdata) { unreachable (); } +void opfunc_b_xor (OPCODE opdata) { unreachable (); } +void opfunc_b_shift_left (OPCODE opdata) { unreachable (); } +void opfunc_b_shift_right (OPCODE opdata) { unreachable (); } +void opfunc_b_shift_uright (OPCODE opdata) { unreachable (); } +void opfunc_addition (OPCODE opdata) { unreachable (); } +void opfunc_substraction (OPCODE opdata) { unreachable (); } +void opfunc_division (OPCODE opdata) { unreachable (); } +void opfunc_multiplication (OPCODE opdata) { unreachable (); } +void opfunc_remainder (OPCODE opdata) { unreachable (); } +void opfunc_jmp_up (OPCODE opdata) { unreachable (); } +void opfunc_jmp_down (OPCODE opdata) { unreachable (); } +void opfunc_is_true_jmp (OPCODE opdata) { unreachable (); } +void opfunc_is_false_jmp (OPCODE opdata) { unreachable (); } +void opfunc_is_less_than (OPCODE opdata) { unreachable (); } +void opfunc_is_less_or_equal (OPCODE opdata) { unreachable (); } +void opfunc_is_greater_than (OPCODE opdata) { unreachable (); } +void opfunc_is_greater_or_equal (OPCODE opdata) { unreachable (); } +void opfunc_is_equal_value (OPCODE opdata) { unreachable (); } +void opfunc_is_not_equal_value (OPCODE opdata) { unreachable (); } +void opfunc_is_equal_value_type (OPCODE opdata) { unreachable (); } +void opfunc_is_not_equal_value_type (OPCODE opdata) { unreachable (); } + void opfunc_loop_inf (OPCODE opdata) { #ifdef __HOST printf ("%d::loop_inf:idx:%d\n", __int_data.pos, - opdata.data.loop_inf.opcode_idx); + opdata.data.loop_inf.loop_root); #endif - __int_data.pos = opdata.data.loop_inf.opcode_idx; + __int_data.pos = opdata.data.loop_inf.loop_root; } void @@ -40,8 +95,8 @@ opfunc_call_1 (OPCODE opdata) #ifdef __HOST printf ("%d::op_call_1:idx:%d:%d\n", __int_data.pos, - opdata.data.call_1.name_literal_idx, - opdata.data.call_1.arg1_literal_idx); + opdata.data.call_1.name_lit_idx, + opdata.data.call_1.arg1_lit_idx); #endif __int_data.pos++; @@ -76,8 +131,8 @@ getop_call_1 (T_IDX arg1, T_IDX arg2) OPCODE opdata; opdata.op_idx = call_1; - opdata.data.call_1.name_literal_idx = arg1; - opdata.data.call_1.arg1_literal_idx = arg2; + opdata.data.call_1.name_lit_idx = arg1; + opdata.data.call_1.arg1_lit_idx = arg2; return opdata; } @@ -88,7 +143,7 @@ getop_loop_inf (T_IDX arg1) OPCODE opdata; opdata.op_idx = loop_inf; - opdata.data.loop_inf.opcode_idx = arg1; + opdata.data.loop_inf.loop_root = arg1; return opdata; } diff --git a/src/libcoreint/opcodes.h b/src/libcoreint/opcodes.h index 4131b323f..a48ba9e26 100644 --- a/src/libcoreint/opcodes.h +++ b/src/libcoreint/opcodes.h @@ -28,16 +28,102 @@ #define OP_ENUM_FIELD(name) name , #define OP_FUNC_DECL(name) void opfunc_##name (OPCODE); +/** A single bytecode instruction is 32bit wide and has an 8bit opcode field + and several operand of 8 of 16 bit.*/ + +// OPCODE FIELD TYPES +#define T_IDX uint8_t /** index values */ + OPCODE; typedef void (*opfunc)(OPCODE); -#define OP_LIST(op) \ - op(loop_inf) \ - op(call_1) \ - op(jmp) \ - //op(call_2) \ - op(call_n) \ - op(nop) +#define OP_LOOPS(op) \ + op(loop_inf) \ + op(loop_init_num) \ + op(loop_precond_begin_num) \ + op(loop_precond_end_num) \ + op(loop_postcond) + +#define OP_CALLS_AND_ARGS(op) \ + op(call_1) \ + op(call_2) \ + op(call_n) \ + op(func_decl_1) \ + op(func_decl_2) \ + op(func_decl_n) \ + op(varg_1) \ + op(varg_1_end) \ + op(varg_2) \ + op(varg_2_end) \ + op(varg_3) \ + op(varg_3_end) \ + op(retval) + +#define OP_ASSIGNMENTS(op) \ + op(assignment) \ + op(assignment_multiplication) \ + op(assignment_devision) \ + op(assignment_remainder) \ + op(assignment_addition) \ + op(assignment_substruction) \ + op(assignment_shift_left) \ + op(assignment_shift_right) \ + op(assignment_shift_uright) \ + op(assignment_b_and) \ + op(assignment_b_xor) \ + op(assignment_b_or) + +#define OP_B_SHIFTS(op) \ + op(b_shift_left) \ + op(b_shift_right) \ + op(b_shift_uright) + +#define OP_B_BITWISE(op) \ + op(b_and) \ + op(b_or) \ + op(b_xor) + +#define OP_B_LOGICAL(op) \ + op(logical_and) \ + op(logical_or) + +#define OP_ARITHMETIC(op) \ + op(addition) \ + op(substraction) \ + op(division) \ + op(multiplication) \ + op(remainder) + +#define OP_UNCONDITIONAL_JUMPS(op) \ + op(jmp) \ + op(jmp_up) \ + op(jmp_down) + +#define OP_UNARY_OPS(op) \ + op(is_true_jmp) \ + op(is_false_jmp) + +#define OP_CONDITIONAL_JUMPS(op) \ + OP_UNARY_OPS(op) \ + op(is_less_than) \ + op(is_less_or_equal) \ + op(is_greater_than) \ + op(is_greater_or_equal) \ + op(is_equal_value) \ + op(is_not_equal_value) \ + op(is_equal_value_type) \ + op(is_not_equal_value_type) + +#define OP_LIST(op) \ + OP_LOOPS(op) \ + OP_CALLS_AND_ARGS(op) \ + OP_ASSIGNMENTS(op) \ + OP_B_LOGICAL(op) \ + OP_B_BITWISE(op) \ + OP_B_SHIFTS(op) \ + OP_ARITHMETIC(op) \ + OP_UNCONDITIONAL_JUMPS(op) \ + OP_CONDITIONAL_JUMPS(op) #include "opcode-structures.h" @@ -54,7 +140,8 @@ union __opdata OP_LIST (OP_FUNC_DECL) -OPCODE{ +OPCODE +{ T_IDX op_idx; union __opdata data; }