static void generate_return(code_block *parent, return_statement *ret) { function *fn = ret->target; bool non_void = !is_void(fn->return_type); if (non_void == !ret->value) { fprintf(stderr, "return from void function with return or non-void without " "return\n"); abort(); } size_t param_count = 1 + non_void; if (non_void) { parent = generate_expression(parent, ret->value); } parent->tail.type = GOTO; parent->tail.parameter_count = param_count; parent->tail.parameters = xmalloc(sizeof(size_t) * param_count); if (non_void) { parent->tail.parameters[1] = last_instruction(parent); } parent->tail.parameters[0] = 0; parent->tail.first_block = next_instruction(parent); size_t return_index = instruction_type(parent, 0)->struct_index; code_struct *return_struct = get_code_struct(parent->system, return_index); type *return_block_type = return_struct->fields[0].field_type; code_instruction *unwrap = new_instruction(parent, 2); unwrap->operation.type = O_GET_FIELD; unwrap->type = copy_type(return_block_type); unwrap->parameters[0] = 0; // return structs are always the first argument unwrap->parameters[1] = 0; // blockref position in all return structs }
void run_cpu(cpu* i) { i->status = 1; i->running = 1; //printf("\n\t---------------------------------------------------------------------\n"); while(i->running) { // Get the next instruction: i->opcode = get_opcode(i); // Increment the pointer to the next instruction: next_instruction(i, 1); // OpCodes: switch(i->opcode) { // // @opcode: SET // @args: 2 // b: Register Address // a: Set Value // @description: // This opcode takes 2 parameters, b and a. It'll set [a] (value of a) to b (the memory address of // the pointer) // // @todo: Add support for stack memory addresses. // case SET: // Create a new scope so we can create variables, etc... { // Use b as the index of the register array. // Because the registers' addreses range from [0x00-0x07], we can // treat them as integers, converting them to [0-7]. set_register(i, get_arg(i, 0), get_arg(i, 1)); debug_opcode(i, "SET", 2); next_instruction(i, 2); // 2 arguments. break; } case ADD: { set_register_ex(i, get_register_value(i, get_arg(i, 0), 3) + get_arg(i, 1)); if (get_register_ex_value(i) > 0xffff) { // Overflow: set_register_ex(i, 0x001); i->overflow = 1; set_register(i, get_arg(i, 0), 0x00); } else { set_register(i, get_arg(i, 0), get_register_ex_value(i)); set_register_ex(i, 0x000); } debug_opcode(i, "ADD", 2); next_instruction(i, 2); // 2 arguments. break; } case SUB: { set_register_ex(i, get_register_value(i, get_arg(i, 0), 3) - get_arg(i, 1)); if ( get_arg(i, 1) > get_register_value(i, get_arg(i, 0), 3)) { // Overflow: set_register_ex(i, 0xffff); i->underflow = 1; set_register(i, get_arg(i, 0), 0x00); } else { set_register(i, get_arg(i, 0), get_register_ex_value(i)); set_register_ex(i, 0x000); } debug_opcode(i, "SUB", 2); next_instruction(i, 2); // 2 arguments. break; } // Store in the stack: case MUL: set_register_ex(i, get_register_value(i, get_arg(i, 0), 3) * get_arg(i, 1)); set_register(i, get_arg(i, 0), get_register_ex_value(i)); set_register_ex(i, get_register_ex_value(i) >> 16); debug_opcode(i, "MUL", 2); next_instruction(i, 2); // 2 arguments. break; case MLI: break; case DIV: if (get_arg(i, 1) == 0) { set_register_ex(i, 0); set_register(i, get_arg(i, 0), 0); } else { set_register_ex(i, get_register_value(i, get_arg(i, 0), 3) / get_arg(i, 1)); set_register(i, get_arg(i, 0), get_register_ex_value(i)); } debug_opcode(i, "DIV", 2); next_instruction(i, 2); // 2 arguments. break; case DVI: break; default: printf("\n\n%s\n\n\n\t\tInstruction Fault at: [%s%s%i%s%s] -> 0x%x\n\n\n%s\n", COLORS_BG_RED, COLORS_BG_BLACK, COLORS_LIGHT_BLUE, i->registers->pc, COLORS_RESET, COLORS_BG_RED, i->program->code[i->registers->pc], COLORS_RESET ); i->status = 0; dump_registers(i, 0); return; break; } // Check the size of the instructions left. if (i->registers->pc >= i->program->size) { i->running = 0; break; } } }