#define BC_LOG 1 #define BC_ASSERTS 1 #if BC_LOG #define bc_log(...) log_info(__VA_ARGS__) #else #define bc_log(...) #endif // // *Begin* of enum generated using code_generating_script.py // enum Operation: U16{ BC_END_OF_INSTRUCTIONS, BC_POP_STACK, BC_PUSH_STACK, BC_LOAD_CONSTANT, BC_STORE_CONSTANT, BC_CALL, BC_CALL_RETURN, BC_LOAD_FROM_MEMORY64, BC_LOAD_FROM_MEMORY32, BC_LOAD_FROM_MEMORY16, BC_LOAD_FROM_MEMORY8, BC_STORE_TO_MEMORY64, BC_STORE_TO_MEMORY32, BC_STORE_TO_MEMORY16, BC_STORE_TO_MEMORY8, BC_ADD_S64, BC_SUB_S64, BC_DIV_S64, BC_MUL_S64, BC_MOD_S64, BC_SHR_S64, BC_SHL_S64, BC_BITAND_S64, BC_BITOR_S64, BC_BITXOR_S64, BC_BITNOT_S64, BC_EQ_S64, BC_NEQ_S64, BC_GT_S64, BC_LT_S64, BC_OR_S64, BC_GTE_S64, BC_LTE_S64, BC_ADD_U64, BC_SUB_U64, BC_DIV_U64, BC_MUL_U64, BC_MOD_U64, BC_SHR_U64, BC_SHL_U64, BC_BITAND_U64, BC_BITOR_U64, BC_BITXOR_U64, BC_BITNOT_U64, BC_EQ_U64, BC_NEQ_U64, BC_GT_U64, BC_LT_U64, BC_OR_U64, BC_GTE_U64, BC_LTE_U64, BC_ADD_F64, BC_SUB_F64, BC_DIV_F64, BC_MUL_F64, BC_EQ_F64, BC_NEQ_F64, BC_GT_F64, BC_LT_F64, BC_GTE_F64, BC_LTE_F64, }; const char *op_name[] = { "BC_END_OF_INSTRUCTIONS", "BC_POP_STACK", "BC_PUSH_STACK", "BC_LOAD_CONSTANT", "BC_STORE_CONSTANT", "BC_CALL", "BC_CALL_RETURN", "BC_LOAD_FROM_MEMORY64", "BC_LOAD_FROM_MEMORY32", "BC_LOAD_FROM_MEMORY16", "BC_LOAD_FROM_MEMORY8", "BC_STORE_TO_MEMORY64", "BC_STORE_TO_MEMORY32", "BC_STORE_TO_MEMORY16", "BC_STORE_TO_MEMORY8", "BC_ADD_S64", "BC_SUB_S64", "BC_DIV_S64", "BC_MUL_S64", "BC_MOD_S64", "BC_SHR_S64", "BC_SHL_S64", "BC_BITAND_S64", "BC_BITOR_S64", "BC_BITXOR_S64", "BC_BITNOT_S64", "BC_EQ_S64", "BC_NEQ_S64", "BC_GT_S64", "BC_LT_S64", "BC_OR_S64", "BC_GTE_S64", "BC_LTE_S64", "BC_ADD_U64", "BC_SUB_U64", "BC_DIV_U64", "BC_MUL_U64", "BC_MOD_U64", "BC_SHR_U64", "BC_SHL_U64", "BC_BITAND_U64", "BC_BITOR_U64", "BC_BITXOR_U64", "BC_BITNOT_U64", "BC_EQ_U64", "BC_NEQ_U64", "BC_GT_U64", "BC_LT_U64", "BC_OR_U64", "BC_GTE_U64", "BC_LTE_U64", "BC_ADD_F64", "BC_SUB_F64", "BC_DIV_F64", "BC_MUL_F64", "BC_EQ_F64", "BC_NEQ_F64", "BC_GT_F64", "BC_LT_F64", "BC_GTE_F64", "BC_LTE_F64", }; // // *End* of enum generated using code_generating_script.py // union Register{ F64 f64; S64 s64; S64 *pointer_s64; F64 *pointer_f64; U8 *pointer; U64 *pointer64; U64 *pointer_u64; U32 *pointer_u32; U16 *pointer_u16; U8 *pointer_u8; U64 u64; U32 u32; U16 u16; U8 u8; }; static_assert(sizeof(Register) == 8, "not 8 bytes"); struct Instruction{ Operation operation; S32 index_c; union{ struct{ S32 index_a; S32 index_b; }; Register constant; }; U32 di; // @debug_id U32 debug_type_flag; Token *debug_pos; }; struct Call_Frame{ Call_Frame *previous_call; Instruction *saved_instruction_pointer; Register_Index first_register_index_in_window; }; struct Bc{ U32 dis; // @debug_ids U8 *stack_base; U8 *stack_pointer; U8 *stack_top; Call_Frame *top_call; Array registers; Array used_registers; Array free_registers; Instruction *instruction_pointer; Arena instructions; Arena memory; Arena stack; // We reserve 4 gibs and allocate only 4 kibs to make sure we know when we // accidently overshoot the stack by 2 gigabytes woo yeee }; // // Allocating and releasing is for codegen ! // function Register_Index allocate_register(Bc *b){ Register_Index result = -1; if(b->free_registers.len == 0) result = b->registers.addi({}); else result = b->free_registers.pop(); b->used_registers.add(result); return result; } function void release_register(Bc *b, Register_Index reg){ if(reg == -1) return; B32 found = false; For(b->used_registers){ if(it == reg){ b->used_registers.unordered_remove(&it); found = true; break; } } assert_msg(found, "Trying to release register that is not used"); b->free_registers.add(reg); } function Bc create_bytecode_interp(){ Bc b = {}; b.registers = array_make(pctx->heap, 1024); b.free_registers = array_make(pctx->heap, 1024); b.used_registers = array_make(pctx->heap, 1024); { arena_init(&b.instructions, "Bytecode instructions"_s); arena_push_size(&b.instructions, 16); // Commit arena_clear(&b.instructions); } { arena_init(&b.stack, "Bytecode stack"_s); arena_push_size(&b.stack, kib(4)); // Setup a 4 kilobyte stack } arena_init(&b.memory, "Bytecode memory"_s); return b; } function void destroy_bytecode_interp(Bc *b){ arena_release(&b->instructions); arena_release(&b->stack); arena_release(&b->memory); } function Instruction * new_instruction(Bc *b, Token *pos){ Instruction *i = exp_alloc_type(&b->instructions, Instruction); b->instruction_pointer = i + 1; i->di = b->dis++; i->debug_pos = pos; return i; } function Instruction * emit_call(Bc *b, Token *pos, Register_Index register_with_call_address){ auto i = new_instruction(b, pos); i->operation = BC_CALL; i->index_a = register_with_call_address; return i; } function void emit_return(Bc *b, Token *pos){ auto i = new_instruction(b, pos); i->operation = BC_CALL_RETURN; } function Instruction * emit_load_constant(Bc *b, Token *pos, Register_Index dst, Value value){ auto i = new_instruction(b, pos); i->operation = BC_LOAD_CONSTANT; i->index_c = dst; if(value.type){ i->debug_type_flag = value.type->kind; switch(value.type->kind){ case TYPE_POINTER: CASE_UINT: i->constant.u64 = bigint_as_unsigned(&value.big_int_val); break; CASE_SINT: i->constant.s64 = bigint_as_signed(&value.big_int_val); break; CASE_FLOAT: i->constant.f64 = value.f64_val; break; case TYPE_TYPE: i->constant.u64 = value.type_val->type_id; break; invalid_default_case; } } return i; } function Instruction * emit_load_constant_address(Bc *b, Token *pos, Register_Index dst, void *address){ auto i = new_instruction(b, pos); i->operation = BC_LOAD_CONSTANT; i->index_c = dst; i->constant.u64 = (U64)address; i->debug_type_flag = TYPE_POINTER; return i; } function void emit_push(Bc *b, Token *pos, Register_Index src){ auto i = new_instruction(b, pos); i->operation = BC_PUSH_STACK; i->index_a = src; } function void emit_pop(Bc *b, Token *pos, Register_Index dst){ auto i = new_instruction(b, pos); i->operation = BC_POP_STACK; i->index_c = dst; } function void emit_memory(Bc *b, Token *pos, Operation ins, Register_Index dst, Register_Index src){ auto i = new_instruction(b, pos); i->operation = ins; i->index_c = dst; i->index_a = src; } function void emit_arithmetic(Bc *b, Token *pos, Operation ins, Register_Index left, Register_Index right, Register_Index dst){ Instruction *i = new_instruction(b, pos); i->operation = ins; i->index_a = left; i->index_b = right; i->index_c = dst; } function void emit_end(Bc *b){ Instruction *i = new_instruction(b, 0); i->operation = BC_END_OF_INSTRUCTIONS; } #define R(x) (b->registers[b->top_call->first_register_index_in_window + (x)]) // Get register #define bc_stack_push(b, T) (T *)bc_stack_push_size(b, sizeof(T)) function U8 * bc_stack_push_size(Bc *b, U64 size){ U8 *result = (U8 *)b->stack_pointer; b->stack_pointer += size; assert(b->stack_pointer < b->stack_top); return result; } function Call_Frame * bc_push_call_frame(Bc *b, Register_Index function_address_register){ auto call = bc_stack_push(b, Call_Frame); call->first_register_index_in_window = function_address_register; call->previous_call = b->top_call; call->saved_instruction_pointer = 0; b->stack_pointer = b->stack_base = (U8 *)(call+1); b->top_call = call; return call; } function void run_bytecode_interp(Bc *b){ b->instruction_pointer = (Instruction *)b->instructions.memory.data; b->stack_pointer = b->stack_base = b->stack.memory.data; b->stack_top = (b->stack.memory.data + b->stack.len); bc_push_call_frame(b, 0); for(;;){ Instruction *instr = b->instruction_pointer++; #if BC_ASSERTS print_token_line(instr->debug_pos); assert_msg(b->stack_pointer < b->stack_top, "Bytecode stack overflow"); assert_msg(b->stack_pointer >= b->stack_base, "Bytecode stack underflow"); assert_msg(b->top_call->first_register_index_in_window < b->registers.cap, "Bytecode interpreter bug, register pointer is pointing over last possible register"); #endif bc_log("i%u[0x%llx] %s ", instr->di, instr, op_name[instr->operation]); switch(instr->operation){ invalid_default_case; case BC_PUSH_STACK:{ U64 *stack = (U64 *)b->stack_pointer; b->stack_pointer += sizeof(U64); U64 src = R(instr->index_a).u64; bc_log("r%u(src) [0x%llx|%lld|%f]", instr->index_a, src, src, src); *stack = src; }break; case BC_POP_STACK:{ b->stack_pointer -= sizeof(U64); U64 *stack = (U64 *)b->stack_pointer; bc_log("r%u(dst) [0x%llx|%lld|%f]", instr->index_c, *stack, *stack, *stack); R(instr->index_c).u64 = *stack; }break; case BC_LOAD_CONSTANT: { R(instr->index_c) = instr->constant; #if BC_LOG switch(instr->debug_type_flag){ case TYPE_S64: bc_log("dst[r%u] S64[%lld]", instr->index_c, instr->constant.s64); break; case TYPE_U64: bc_log("dst[r%u] U64[%llu]", instr->index_c, instr->constant.u64); break; case TYPE_F64: bc_log("dst[r%u] F64[%f]" , instr->index_c, instr->constant.f64); break; case TYPE_POINTER: bc_log("dst[r%u] Pointer[0x%llx]" , instr->index_c, instr->constant.pointer64); break; invalid_default_case; } #endif }break; case BC_CALL:{ Register_Index register_with_call_address = instr->index_a; Call_Frame *call = bc_push_call_frame(b, register_with_call_address); call->saved_instruction_pointer = b->instruction_pointer; b->instruction_pointer = (Instruction *)R(register_with_call_address).pointer; }break; case BC_CALL_RETURN:{ Call_Frame *call = b->top_call; Call_Frame *prev = call->previous_call; assert(prev); b->stack_base = (U8 *)(prev + 1); b->stack_pointer = (U8 *)call; b->top_call = prev; }break; case BC_END_OF_INSTRUCTIONS:{ goto end_of_program; }break; // // *Begin* of switch_cases generated using code_generating_script.py // case BC_LOAD_FROM_MEMORY64:{ U64 *load_address = R(instr->index_a).pointer_u64; R(instr->index_c).u64 = *load_address; bc_log("load_address[r%u, %llx] dst[r%u] [0x%llx|%lld|%f]", instr->index_a, load_address, instr->index_c, R(instr->index_c).u64, R(instr->index_c).u64, R(instr->index_c).u64); }break; case BC_STORE_TO_MEMORY64:{ U64 *store_address = R(instr->index_c).pointer_u64; *store_address = R(instr->index_a).u64; bc_log("src[r%u] store_address[r%u, %llx] value_written[0x%llx|%lld|%f]", instr->index_a, instr->index_c, store_address, *store_address, *store_address, *store_address); }break; case BC_LOAD_FROM_MEMORY32:{ U32 *load_address = R(instr->index_a).pointer_u32; R(instr->index_c).u32 = *load_address; bc_log("load_address[r%u, %llx] dst[r%u] [0x%llx|%lld|%f]", instr->index_a, load_address, instr->index_c, R(instr->index_c).u32, R(instr->index_c).u32, R(instr->index_c).u32); }break; case BC_STORE_TO_MEMORY32:{ U32 *store_address = R(instr->index_c).pointer_u32; *store_address = R(instr->index_a).u32; bc_log("src[r%u] store_address[r%u, %llx] value_written[0x%llx|%lld|%f]", instr->index_a, instr->index_c, store_address, *store_address, *store_address, *store_address); }break; case BC_LOAD_FROM_MEMORY16:{ U16 *load_address = R(instr->index_a).pointer_u16; R(instr->index_c).u16 = *load_address; bc_log("load_address[r%u, %llx] dst[r%u] [0x%llx|%lld|%f]", instr->index_a, load_address, instr->index_c, R(instr->index_c).u16, R(instr->index_c).u16, R(instr->index_c).u16); }break; case BC_STORE_TO_MEMORY16:{ U16 *store_address = R(instr->index_c).pointer_u16; *store_address = R(instr->index_a).u16; bc_log("src[r%u] store_address[r%u, %llx] value_written[0x%llx|%lld|%f]", instr->index_a, instr->index_c, store_address, *store_address, *store_address, *store_address); }break; case BC_LOAD_FROM_MEMORY8:{ U8 *load_address = R(instr->index_a).pointer_u8; R(instr->index_c).u8 = *load_address; bc_log("load_address[r%u, %llx] dst[r%u] [0x%llx|%lld|%f]", instr->index_a, load_address, instr->index_c, R(instr->index_c).u8, R(instr->index_c).u8, R(instr->index_c).u8); }break; case BC_STORE_TO_MEMORY8:{ U8 *store_address = R(instr->index_c).pointer_u8; *store_address = R(instr->index_a).u8; bc_log("src[r%u] store_address[r%u, %llx] value_written[0x%llx|%lld|%f]", instr->index_a, instr->index_c, store_address, *store_address, *store_address, *store_address); }break; case BC_ADD_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left + right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] + [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_SUB_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left - right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] - [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_DIV_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left / right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] / [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_MUL_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left * right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] * [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_MOD_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left % right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] % [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_SHR_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left >> right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] >> [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_SHL_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left << right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] << [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_BITAND_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left & right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] & [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_BITOR_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left | right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] | [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_BITXOR_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left ^ right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] ^ [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_BITNOT_S64:{ S64 left = (S64)R(instr->index_a).s64; S64 result = ~left; S64 *dst = R(instr->index_c).pointer_s64; *dst = result; bc_log("~ [%lld] = [%lld]", left, result); }break; case BC_EQ_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left == right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] == [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_NEQ_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left != right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] != [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_GT_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left > right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] > [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_LT_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left < right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] < [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_OR_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left || right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] || [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_GTE_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left >= right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] >= [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_LTE_S64:{ S64 left = R(instr->index_a).s64; S64 right = R(instr->index_b).s64; S64 result = left <= right; R(instr->index_c).s64 = result; bc_log("[r%d, %lld] <= [r%d, %lld] = [r%d, %lld]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_ADD_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left + right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] + [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_SUB_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left - right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] - [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_DIV_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left / right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] / [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_MUL_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left * right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] * [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_MOD_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left % right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] % [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_SHR_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left >> right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] >> [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_SHL_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left << right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] << [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_BITAND_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left & right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] & [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_BITOR_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left | right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] | [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_BITXOR_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left ^ right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] ^ [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_BITNOT_U64:{ U64 left = (U64)R(instr->index_a).u64; U64 result = ~left; U64 *dst = R(instr->index_c).pointer_u64; *dst = result; bc_log("~ [%llu] = [%llu]", left, result); }break; case BC_EQ_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left == right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] == [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_NEQ_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left != right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] != [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_GT_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left > right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] > [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_LT_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left < right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] < [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_OR_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left || right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] || [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_GTE_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left >= right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] >= [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_LTE_U64:{ U64 left = R(instr->index_a).u64; U64 right = R(instr->index_b).u64; U64 result = left <= right; R(instr->index_c).u64 = result; bc_log("[r%d, %llu] <= [r%d, %llu] = [r%d, %llu]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_ADD_F64:{ F64 left = R(instr->index_a).f64; F64 right = R(instr->index_b).f64; F64 result = left + right; R(instr->index_c).f64 = result; bc_log("[r%d, %f] + [r%d, %f] = [r%d, %f]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_SUB_F64:{ F64 left = R(instr->index_a).f64; F64 right = R(instr->index_b).f64; F64 result = left - right; R(instr->index_c).f64 = result; bc_log("[r%d, %f] - [r%d, %f] = [r%d, %f]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_DIV_F64:{ F64 left = R(instr->index_a).f64; F64 right = R(instr->index_b).f64; F64 result = left / right; R(instr->index_c).f64 = result; bc_log("[r%d, %f] / [r%d, %f] = [r%d, %f]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_MUL_F64:{ F64 left = R(instr->index_a).f64; F64 right = R(instr->index_b).f64; F64 result = left * right; R(instr->index_c).f64 = result; bc_log("[r%d, %f] * [r%d, %f] = [r%d, %f]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_EQ_F64:{ F64 left = R(instr->index_a).f64; F64 right = R(instr->index_b).f64; F64 result = left == right; R(instr->index_c).f64 = result; bc_log("[r%d, %f] == [r%d, %f] = [r%d, %f]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_NEQ_F64:{ F64 left = R(instr->index_a).f64; F64 right = R(instr->index_b).f64; F64 result = left != right; R(instr->index_c).f64 = result; bc_log("[r%d, %f] != [r%d, %f] = [r%d, %f]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_GT_F64:{ F64 left = R(instr->index_a).f64; F64 right = R(instr->index_b).f64; F64 result = left > right; R(instr->index_c).f64 = result; bc_log("[r%d, %f] > [r%d, %f] = [r%d, %f]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_LT_F64:{ F64 left = R(instr->index_a).f64; F64 right = R(instr->index_b).f64; F64 result = left < right; R(instr->index_c).f64 = result; bc_log("[r%d, %f] < [r%d, %f] = [r%d, %f]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_GTE_F64:{ F64 left = R(instr->index_a).f64; F64 right = R(instr->index_b).f64; F64 result = left >= right; R(instr->index_c).f64 = result; bc_log("[r%d, %f] >= [r%d, %f] = [r%d, %f]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; case BC_LTE_F64:{ F64 left = R(instr->index_a).f64; F64 right = R(instr->index_b).f64; F64 result = left <= right; R(instr->index_c).f64 = result; bc_log("[r%d, %f] <= [r%d, %f] = [r%d, %f]", instr->index_a, left, instr->index_b, right, instr->index_c, result); }break; // // *End* of switch_cases generated using code_generating_script.py // } bc_log("\n"); } end_of_program:; }