int otherTest() { lc3 lc3; lc3_init(&lc3); ldb db; ldb_init(&db, &lc3); if(ldb_loadObj(&db,"testcases/Project1.obj")!=OPEN) return -1; lc3.mem[0x30f0] = 25; lc3.mem[0x30f1] = 4; //ldb_setUnconBP(&db,0x3001); //ldb_setBP(&db, 0x3001, 1, bp_neq, bp_reg, 0, 0xbeef); ldb_run(&db); for(int i = 0; i < GPR_NUM; i++) { printf("R%d : x%04x | %d\n",i,lc3.registers[i],(int16_t)lc3.registers[i]); } for(int i = 0; i < 8; i++) { printf("x%x : x%04x | %d\n",0x3000+i,lc3.mem[0x3000+i],(int16_t)lc3.mem[0x3000+i]); } printf("x%x : x%04x | %d\n",0x30f2,lc3.mem[0x30f2],(int16_t)lc3.mem[0x30f2]); printf("%llu cycles\n",(long long unsigned int)db.cycleCount); ldb_dump_lc3_r(&db,"dump/dump.lc3rdump"); ldb_dump_lc3_t(&db,"dump/dump.lc3tdump"); ldb_dump_lc3_b(&db,"dump/dump.lc3bdump"); return 0; }
/** OnInit * * Called when the machine needs to be initialized */ void ComplxFrame::OnInit(void) { static bool first = true; lc3_init(state, true); if (console != NULL) delete console; console = new LC3Console(this); state.input = &console->inputStream; state.reader = complx_reader; state.peek = complx_peek; state.writer = complx_writer; // For keyboard interrupts state.interrupt_test.push_back(complx_step); console->Show(); int x, y; GetScreenPosition(&x, &y); if (first) { Move(x + console->GetSize().GetX() / 2, y); console->Move(x - console->GetSize().GetX() / 2, y); first = false; } else { console->Move(x - console->GetSize().GetX(), y); } lc3_set_true_traps(state, menuStateTrueTraps->IsChecked()); state.interrupt_enabled = menuStateInterrupts->IsChecked(); state.max_stack_size = stack_size; state.max_call_stack_size = call_stack_size; }
/** DoLoadFile * * Handles loading an assembly file into the simulator */ void ComplxFrame::DoLoadFile(const wxFileName& filename) { //CleanUp(); lc3_state dummy_state; lc3_init(dummy_state); // Save the symbols std::map<std::string, unsigned short> symbol_table = state.symbols; std::map<unsigned short, std::string> rev_symbol_table = state.rev_symbols; state.symbols.clear(); state.rev_symbols.clear(); lc3_remove_plugins(state); try { lc3_assemble(dummy_state, filename.GetFullPath().ToStdString(), false); lc3_assemble(state, filename.GetFullPath().ToStdString()); } catch (LC3AssembleException e) { wxMessageBox(wxString::Format("BAD STUDENT! %s", e.what()), _("Loading ") + filename.GetFullName() + _(" Failed")); goto merge; } catch (std::vector<LC3AssembleException> e) { std::stringstream oss; for (unsigned int i = 0; i < e.size(); i++) oss << e[i].what() << std::endl; wxMessageBox(wxString::Format("BAD STUDENT! %s", oss.str()), _("Loading ") + filename.GetFullName() + _(" Failed")); goto merge; } //if (DoAssemble(filename)) return; currentFile = filename; SetTitle(wxString::Format("Complx - %s", filename.GetFullPath())); merge: std::map<std::string, unsigned short>::const_iterator i; std::map<unsigned short, std::string>::const_iterator j; for (i = symbol_table.begin(); i != symbol_table.end(); ++i) { state.symbols[i->first] = i->second; } for (j = rev_symbol_table.begin(); j != rev_symbol_table.end(); ++j) { state.rev_symbols[j->first] = j->second; } //DoLoad(filename); UpdateStatus(); UpdateRegisters(); UpdateMemory(); }
void do_load(const std::string& filename) { lc3_init(state); try { lc3_assemble(state, filename); } catch (LC3AssembleException e) { fprintf(stderr, "[ERROR] %s failed to assemble. %s\n", filename.c_str(), e.what().c_str()); return; } current_filename = filename; memory->Update(); }
void do_reload(void) { if (current_filename.empty()) return; lc3_init(state); try { lc3_assemble(state, current_filename); } catch (LC3AssembleException e) { fprintf(stderr, "[ERROR] %s failed to assemble. %s\n", current_filename.c_str(), e.what().c_str()); return; } memory->Update(); }
int dumpTest() { lc3 lc3; lc3_init(&lc3); ldb db; ldb_init(&db, &lc3); if(ldb_dumpload_lc3_b(&db,"dump/dump.lc3bdump")!=OPEN) return -1; for(int i = 0; i < GPR_NUM; i++) { printf("R%d : x%04x | %d\n",i,lc3.registers[i],(int16_t)lc3.registers[i]); } for(int i = 0; i < 8; i++) { printf("x%x : x%04x | %d\n",0x3000+i,lc3.mem[0x3000+i],(int16_t)lc3.mem[0x3000+i]); } printf("x%x : x%04x | %d\n",0x30f2,lc3.mem[0x30f2],(int16_t)lc3.mem[0x30f2]); printf("%llu cycles\n",(long long unsigned int)db.cycleCount); return 0; }
int test() { unsigned int cycles = 0; printf("Hello world\n"); lc3 lc3; lc3_init(&lc3); for(lc3.mem[0xFFFE] |= 0x8000 ; lc3_cycle(&lc3) != HALT;cycles++); for(int i = 0; i < GPR_NUM; i++) { printf("R%d : x%04x | %d\n",i,lc3.registers[i],(int16_t)lc3.registers[i]); } for(int i = 0; i < 8; i++) { printf("x%x : x%04x | %d\n",0x3000+i,lc3.mem[0x3000+i],(int16_t)lc3.mem[0x3000+i]); } printf("%d cycles\n",cycles); return 0; }
int debuggerTest() { lc3 lc3; lc3_init(&lc3); ldb db; ldb_init(&db, &lc3); if(ldb_loadObj(&db,"testcases/lsi.obj") != OPEN) return -1; //ldb_setUnconBP(&db,0x3001); ldb_setBP(&db, 0x3001, 1, ldb_neq, ldb_reg, 0, 0xbeef); ldb_run(&db); for(int i = 0; i < GPR_NUM; i++) { printf("R%d : x%04x | %d\n",i,lc3.registers[i],(int16_t)lc3.registers[i]); } for(int i = 0; i < 8; i++) { printf("x%x : x%04x | %d\n",0x3000+i,lc3.mem[0x3000+i],(int16_t)lc3.mem[0x3000+i]); } printf("%llu cycles\n",(long long unsigned int) db.cycleCount); return 0; }
void lc3_run_test_case(lc3_test& test, const std::string& filename, int seed) { lc3_state state; // Preliminary stuff if (seed != -1) srand(seed); lc3_init(state, test.randomize, test.randomize); if (test.true_traps) lc3_set_true_traps(state, 1); if (test.interrupt_enabled) state.interrupt_enabled = 1; bool disable_plugins = test.disable_plugins; state.max_stack_size = 0; state.max_call_stack_size = -1; state.in_lc3test = true; try { LC3AssembleOptions options; options.multiple_errors = false; options.warnings_as_errors = false; options.process_debug_comments = false; options.enable_warnings = false; options.disable_plugins = disable_plugins; lc3_assemble(state, filename, options); } catch (LC3AssembleException e) { throw e.what(); } std::stringstream* newinput = new std::stringstream(); // Set up test environment for (unsigned int i = 0; i < test.input.size(); i++) { lc3_test_input& input = test.input[i]; int value_calc; int address_calc = 0; unsigned short effective_address; ///TODO flip the condition here so that if new types are added you don't have to check for it here... if (input.type != TEST_IO && input.type != TEST_REGISTER && input.type != TEST_PC && input.type != TEST_SUBROUTINE && lc3_calculate(state, input.address, address_calc) == -1) throw "An address expression " + input.address + " was not formed correctly."; else if (input.type == TEST_REGISTER) { if (input.address.size() != 2) throw "Register format is RX where x is between 0-7 found: " + input.address; address_calc = input.address[1] - '0'; if (address_calc > 7 || address_calc < 0) throw "Invalid register " + input.address; } else lc3_calculate(state, input.address, address_calc); effective_address = (unsigned short) address_calc; switch (input.type) { case TEST_VALUE: if (lc3_calculate(state, input.value, value_calc)) throw "<in test-value> A value expression " + input.value + " was malformed."; state.mem[effective_address] = (short) value_calc; break; case TEST_REGISTER: if (lc3_calculate(state, input.registerval, value_calc)) throw "<in test-register> A value expression " + input.registerval + " was malformed."; state.regs[effective_address] = (short) value_calc; break; case TEST_PC: if (lc3_calculate(state, input.pcval, value_calc)) throw "<in test-pc> A value expression " + input.pcval + " was malformed."; state.pc = (unsigned short) value_calc; break; case TEST_POINTER: if (lc3_calculate(state, input.pointer, value_calc)) throw "<in test-pointer> An expression was " + input.pointer + " malformed."; state.mem[(unsigned short) state.mem[effective_address]] = (short) value_calc; break; case TEST_STRING: for (unsigned int j = 0; j < input.text.size(); j++) state.mem[state.mem[effective_address] + j] = input.text[j]; state.mem[(unsigned short) (state.mem[effective_address] + input.text.size())] = 0; break; case TEST_ARRAY: for (unsigned int j = 0; j < input.array.size(); j++) { if (lc3_calculate(state, input.array[j], value_calc)) throw "<in test-array> An expression was " + input.array[j] + " malformed."; state.mem[(unsigned short) (state.mem[effective_address] + j)] = (short) value_calc; } break; case TEST_IO: newinput->str(input.io); break; case TEST_SUBROUTINE: break; default: throw "Unknown test type"; } if (input.type == TEST_SUBROUTINE) { lc3_subr_input& subr = input.subroutine; int pc; int r7; int r6; int r5; if (lc3_calculate(state, subr.name, pc) == -1) throw "<in test-subr> invalid subroutine name given " + subr.name; if (lc3_calculate(state, subr.stack, r6) == -1) throw "<in test-subr> stack expression was malformed " + subr.stack; if (lc3_calculate(state, subr.r7, r7) == -1) throw "<in test-subr> r7 expression was malformed " + subr.r7; if (lc3_calculate(state, subr.r5, r5) == -1) throw "<in test-subr> r5 expression was malformed " + subr.r5; state.pc = (unsigned short) pc; state.regs[6] = (unsigned short)(r6 - subr.params.size()); state.regs[7] = (unsigned short) r7; state.regs[5] = (unsigned short) r5; state.mem[state.regs[7]] = 0xF025; for (unsigned int j = 0; j < subr.params.size(); j++) { if (lc3_calculate(state, subr.params[j], value_calc)) throw "<in test-subr> param expression " + subr.params[j] + " was malformed."; state.mem[(unsigned short)state.regs[6] + j] = (short) value_calc; } // This fixes the issue in which a subroutine is being tested, but it makes calls to other subroutines who takes a // different number of parameters than the subroutine under test. // If the file uses subroutine annotations then overwrite it. for (const auto& info : subr.subroutines) { int address = 0; if (lc3_calculate(state, info.name, address) == -1) throw "<in test-subr> invalid subroutine name given " + info.name; lc3_subroutine_info test_info = info; test_info.address = (unsigned short) address; state.subroutines[(unsigned short)address] = test_info; } } } state.input = newinput; // Setup output capture device std::stringstream* newoutput = new std::stringstream(); state.output = newoutput; std::stringstream* newwarning = new std::stringstream(); state.warning = newwarning; if (test.has_max_executions) { unsigned long i = 0; // Do this num times or until halted. while (i < test.max_executions && !state.halted) { //printf("%04x: %s (%x)\n", state.pc, lc3_disassemble(state, state.mem[state.pc]).c_str(), (unsigned short)state.mem[state.pc]); /*printf("R0 %6d|x%04x\tR1 %6d|x%04x\tR2 %6d|x%04x\tR3 %6d|x%04x\nR4 %6d|x%04x\tR5 %6d|x%04x\tR6 %6d|x%04x\tR7 %6d|x%04x\nCC: %s\tPC: %04x\n\n", state.regs[0], (unsigned short)state.regs[0], state.regs[1], (unsigned short)state.regs[1], state.regs[2], (unsigned short)state.regs[2], state.regs[3], (unsigned short)state.regs[3], state.regs[4], (unsigned short)state.regs[4], state.regs[5], (unsigned short)state.regs[5], state.regs[6], (unsigned short)state.regs[6], state.regs[7], (unsigned short)state.regs[7], (state.n ? "N" : (state.z ? "Z" : "P")), (unsigned short) state.pc);*/ // Step one instruction lc3_step(state); // Increment instruction count i++; } //lc3_run(state, test.max_executions); } else lc3_run(state); // Fill in the output values test.has_halted = state.halted; test.executions = state.executions; test.warnings = state.warnings; test.warning = newwarning->str(); bool test_passed = true; unsigned int test_points = 0; unsigned int test_max_points = 0; // Check test environment for (unsigned int i = 0; i < test.output.size(); i++) { std::stringstream expected; std::stringstream actual; lc3_test_output& output = test.output[i]; int value_calc; short short_cmp; int address_calc = 0; unsigned short effective_address; std::string str; std::vector<short> arrayexpected; std::vector<short> arrayactual; if (output.type != TEST_IO && output.type != TEST_REGISTER && output.type != TEST_PC && lc3_calculate(state, output.address, address_calc) == -1) throw "An address expression " + output.address + " was not formed correctly."; else if (output.type == TEST_REGISTER) { address_calc = output.address[1] - '0'; if (address_calc > 7) throw "Invalid register " + output.address; } effective_address = (unsigned short) address_calc; output.passed = true; output.earned = 0; switch (output.type) { case TEST_VALUE: if (lc3_calculate(state, output.value, value_calc)) throw "<in test-value> An expression " + output.value + " was malformed."; short_cmp = (short) value_calc; output.passed = lc3_test_check(output, &state.mem[effective_address], &short_cmp); actual << state.mem[effective_address]; expected << short_cmp; break; case TEST_REGISTER: if (lc3_calculate(state, output.registerval, value_calc)) throw "<in test-register> An expression " + output.registerval + " was malformed."; short_cmp = (short) value_calc; output.passed = lc3_test_check(output, &state.regs[effective_address], &short_cmp); actual << state.regs[effective_address]; expected << short_cmp; break; case TEST_PC: if (lc3_calculate(state, output.pcval, value_calc)) throw "<in test-pc> An expression " + output.pcval + " was malformed."; short_cmp = (short) value_calc; output.passed = lc3_test_check(output, &state.pc, &short_cmp); actual << state.pc; expected << short_cmp; break; case TEST_POINTER: if (lc3_calculate(state, output.pointer, value_calc)) throw "<in test-pointer> An expression " + output.pointer + " was malformed."; short_cmp = (short) value_calc; output.passed = lc3_test_check(output, &state.mem[(unsigned short)state.mem[effective_address]], &short_cmp); actual << state.mem[(unsigned short)state.mem[effective_address]]; expected << short_cmp; break; case TEST_STRING: value_calc = (unsigned short)state.mem[effective_address]; short_cmp = state.mem[(unsigned short)value_calc]; while(short_cmp > 0 && short_cmp <= 255) { actual.put((char) short_cmp); value_calc++; short_cmp = state.mem[(unsigned short)value_calc]; } str = actual.str(); output.passed = lc3_test_check(output, &str, &output.text); expected << output.text; break; case TEST_ARRAY: for (unsigned int j = 0; j < output.array.size(); j++) { if (lc3_calculate(state, output.array[j], value_calc)) throw "<in test-array> An expression " + output.array[j] + " was malformed."; arrayexpected.push_back(state.mem[(unsigned short)(state.mem[effective_address] + j)]); arrayactual.push_back((short)value_calc); actual << state.mem[(unsigned short)(state.mem[effective_address] + j)] << " "; expected << (short)value_calc << " "; } output.passed = lc3_test_check(output, &arrayactual, &arrayexpected); break; case TEST_IO: str = newoutput->str(); output.passed = lc3_test_check(output, &str, &output.io); actual << str; expected << output.io; break; case TEST_SUBROUTINE: break; default: throw "Unknown test type"; } if (output.type != TEST_SUBROUTINE) { if (output.passed) output.earned = output.points; } if (output.type == TEST_SUBROUTINE) { std::stringstream extra; lc3_subr_output& subr = output.subroutine; std::vector<short> expected_stack; std::vector<short> actual_stack; std::vector<short> locals; std::vector<short> params; for (int j = (int)subr.locals.size() - 1; j >= 0; j--) { if (lc3_calculate(state, subr.locals[j], value_calc)) throw "<in test-subr> A local variable expression " + subr.locals[i] + "was malformed."; expected_stack.push_back((short)value_calc); locals.push_back((short) value_calc); } int r7; int r6; int r5; int answer; if (lc3_calculate(state, subr.stack, r6) == -1) throw "<in test-subr> stack expression " + subr.stack + " was malformed"; if (lc3_calculate(state, subr.r7, r7) == -1) throw "<in test-subr> r7 expression " + subr.r7 + " was malformed"; if (lc3_calculate(state, subr.r5, r5) == -1) throw "<in test-subr> r5 expression " + subr.r5 + " was malformed"; if (lc3_calculate(state, subr.answer, answer) == -1) throw "<in test-subr> answer expression " + subr.answer + " was malformed"; expected_stack.push_back((short)r5); expected_stack.push_back((short)r7); expected_stack.push_back((short)answer); for (unsigned int j = 0; j < subr.params.size(); j++) { if (lc3_calculate(state, subr.params[j], value_calc)) throw "<in test-subr> A param expression " + subr.params[j] + " was malformed."; expected_stack.push_back((short)value_calc); params.push_back((short) value_calc); } // Code to get the students stack frame unsigned short actual_r6 = (unsigned short) r6; if (state.first_level_calls.size() >= 1) { const auto& call_info = state.first_level_calls[0]; unsigned short subr_location = call_info.address; if (state.subroutines.find(subr_location) == state.subroutines.end()) { extra << " [WARNING] Could not determine number of parameters for subroutine " << lc3_sym_rev_lookup(state, subr_location) << " at address " << std::hex << "0x" << subr_location << "\n"; } unsigned short start = call_info.r6 + call_info.params.size(); // Screams... if (start >= actual_r6) extra << " [WARNING] Could not get students stack frame.\n" " Is the student managing the stack correctly?\n"; else actual_stack.assign(state.mem + start, state.mem + actual_r6); } else if (state.first_level_calls.empty()) { int num_params = subr.params.size(); // Get at least the parameters student could probably not save anything... actual_stack.assign(state.mem + (actual_r6 - num_params), state.mem + actual_r6); // Get additional addresses modified unsigned short start = actual_r6 - num_params - 1; while (state.memory_ops.find(start) != state.memory_ops.end()) { if (!state.memory_ops[start].writes) break; actual_stack.insert(actual_stack.begin(), state.mem[start]); start--; } } for (unsigned int j = 0; j < expected_stack.size(); j++) expected << std::hex << "0x" << expected_stack[j] << " "; expected << " r5: " << std::hex << "0x" << (short)r5 << " r6: " << std::hex << "0x" << (actual_r6 - subr.params.size() - 1) << " r7: " << std::hex << "0x" << (short)(r7 + 1); for (unsigned int j = 0; j < actual_stack.size(); j++) actual << std::hex << "0x" << actual_stack[j] << " "; actual << " r5: " << std::hex << "0x" << state.regs[5] << " r6: " << std::hex << "0x" << state.regs[6] << " r7: " << std::hex << "0x" << state.regs[7]; // now that I have all information available time for some checks. std::map<short, int> actual_stack_map; for (unsigned int j = 0; j < actual_stack.size(); j++) actual_stack_map[actual_stack[j]] += 1; int points = 0; // If they get something wrong then it will also be wrong in edit distance // so cut some slack if you get a value wrong. int ed_forgiveness = 0; if (actual_stack_map[(short)answer] > 0) { actual_stack_map[(short)answer] -= 1; points += subr.points_answer; extra << CHECK << ANSWER_FOUND << " +" << subr.points_answer << ".\n"; } else { ed_forgiveness++; extra << MISS << ANSWER_FOUND << " -" << subr.points_answer << ".\n"; } if (state.regs[6] == (short)(actual_r6 - subr.params.size() - 1)) { points += subr.points_r6; extra << CHECK << R6_FOUND << " +" << subr.points_r6 << ".\n"; } else { extra << MISS << R6_FOUND << " -" << subr.points_r6 << ".\n"; } if (actual_stack_map[(short)r7] > 0 && state.regs[7] == (short)(r7+1)) { actual_stack_map[(short)r7] -= 1; points += subr.points_r7; extra << CHECK << R7_FOUND << " +" << subr.points_r7 << ".\n"; } else { // Don't count if just r7 was clobbered if (actual_stack_map[(short)r7] <= 0) ed_forgiveness++; extra << MISS << R7_FOUND << " -" << subr.points_r7 << ".\n"; } if (actual_stack_map[(short)r5] > 0 && state.regs[5] == (short)r5) { actual_stack_map[(short)r5] -= 1; points += subr.points_r5; extra << CHECK << R5_FOUND << " +" << subr.points_r5 << ".\n"; } else { if (actual_stack_map[(short)r5] <= 0) ed_forgiveness++; extra << MISS << R5_FOUND << " -" << subr.points_r5 << ".\n"; } for (unsigned int j = 0; j < params.size(); j++) { if (actual_stack_map[params[j]] > 0) { actual_stack_map[params[j]] -= 1; points += subr.points_params; extra << CHECK << params[j] << " " << PARAM_FOUND << " +" << subr.points_params << ".\n"; } else { ed_forgiveness++; extra << MISS << params[j] << " " << PARAM_FOUND << " -" << subr.points_params << ".\n"; } } bool all_locals_wrong = true; for (unsigned int j = 0; j < locals.size(); j++) { if (actual_stack_map[locals[j]] > 0) { actual_stack_map[locals[j]] -= 1; points += subr.points_locals; all_locals_wrong = false; extra << CHECK << locals[j] << " " << LOCAL_FOUND << " +" << subr.points_locals << ".\n"; } else { ed_forgiveness++; extra << MISS << locals[j] << " " << LOCAL_FOUND << " -" << subr.points_locals << ".\n"; } } // Subroutine calls check. std::set<lc3_subroutine_call_info, lc3_subroutine_call_info_cmp> actual_calls(state.first_level_calls.begin(), state.first_level_calls.end()); std::set<lc3_subroutine_call_info, lc3_subroutine_call_info_cmp> expected_calls; for (const auto& expected_call : subr.calls) { lc3_subroutine_call_info info; int addr = lc3_sym_lookup(state, expected_call.name); if (addr == -1) throw "Invalid subroutine name given in <call> " + expected_call.name; for (unsigned int i = 0; i < expected_call.params.size(); i++) { int param; if (lc3_calculate(state, expected_call.params[i], param) == -1) throw "<in test-subr/call> param expression " + expected_call.params[i] + " was malformed"; info.params.push_back(param); } info.address = addr; info.r6 = 0; expected_calls.insert(info); } for (const auto& call : expected_calls) { std::stringstream call_name; call_name << lc3_sym_rev_lookup(state, call.address) << "("; if (state.subroutines.find(call.address) == state.subroutines.end()) call_name << "?"; for (unsigned int i = 0; i < call.params.size(); i++) { call_name << std::hex << "0x" << call.params[i]; if (i != call.params.size() - 1) call_name << ","; } call_name << ")"; if (actual_calls.find(call) != actual_calls.end()) { extra << CHECK << "Call " << call_name.str() << " made correctly.\n"; points += subr.points_calls; } else { extra << MISS << "Call " << call_name.str() << " was not made.\n"; } } for (const auto& call : actual_calls) { std::stringstream call_name; std::string name = lc3_sym_rev_lookup(state, call.address); if (name.empty()) call_name << "0x" << std::hex << call.address << "("; else call_name << name << "("; if (state.subroutines.find(call.address) == state.subroutines.end()) call_name << "?"; for (unsigned int i = 0; i < call.params.size(); i++) { call_name << std::hex << "0x" << call.params[i]; if (i != call.params.size() - 1) call_name << ","; } call_name << ")"; if (expected_calls.find(call) == expected_calls.end()) { extra << MISS << "Unexpected Call " << call_name.str() << " made.\n"; } } // Read answer check sigh... if (subr.points_read_answer > 0) { for (const auto& call : actual_calls) { if (expected_calls.find(call) != expected_calls.end() && !call.params.empty()) { if (state.memory_ops[call.r6 - 1].reads > 0) { extra << CHECK << "Read answer from stack.\n"; points += subr.points_read_answer; } else extra << MISS << "Did not read answer from stack.\n"; } } } // If all local variables are wrong then it can be argued that they was saving registers // And forgot to save locals... if (all_locals_wrong) { // Bro do you even calling convention if (actual_stack.size() > subr.params.size() + 3) // Truncate stack to last num_params + 3 elements the stuff we care about (don't do expected since ed forgiveness handles it). actual_stack.erase(actual_stack.begin(), actual_stack.begin() + (actual_stack.size() - subr.params.size() - 3)); if (!subr.locals.empty()) extra << " All locals were not found, so locals aren't included in structure check.\n"; } else { if (actual_stack.size() > expected_stack.size()) expected_stack.insert(expected_stack.begin(), actual_stack.begin(), actual_stack.begin() + (actual_stack.size() - expected_stack.size())); } int ed_grade = edit_distance(actual_stack, expected_stack); points -= (ed_grade - ed_forgiveness) * subr.deductions_edist; int mistakes = ed_grade - ed_forgiveness; if (mistakes == 0) extra << " Found no structural mistakes in the stack. No changes needed.\n"; else extra << " Found " << mistakes << " structural mistakes in stack -" << subr.deductions_edist * mistakes << ".\n"; output.passed = (ed_grade == 0) && (ed_forgiveness == 0); output.extra_output += extra.str(); output.earned = points; } test_passed = test_passed && output.passed; test_points += output.earned; test_max_points += output.points; output.expected = expected.str(); output.actual = actual.str(); } // Tear down delete state.input; delete state.output; delete state.warning; test.passed = test_passed; test.points = test_points; test.max_points = test_max_points; }
/** DoLoadFile * * Handles loading an assembly file into the simulator */ void ComplxFrame::DoLoadFile(const LoadingOptions& opts) { auto* config = wxConfigBase::Get(); wxFileName filename(opts.file); bool randomize_registers = opts.registers == RANDOMIZE; bool randomize_memory = opts.memory == RANDOMIZE; short fill_registers = opts.registers; short fill_memory = opts.memory; lc3_init(state, randomize_registers, randomize_memory, fill_registers, fill_memory); state.pc = opts.pc; PostInit(); // Now the actual loading if (opts.file.empty()) return; lc3_state dummy_state; lc3_init(dummy_state); // Save the symbols std::map<std::string, unsigned short> symbol_table = state.symbols; std::map<unsigned short, std::string> rev_symbol_table = state.rev_symbols; state.symbols.clear(); state.rev_symbols.clear(); lc3_remove_plugins(state); bool tvt_modification = false; bool ivt_modification = false; bool subroutine_found = false; try { ///TODO should only make one call to lc3_assemble. std::vector<code_range> ranges; LC3AssembleOptions options; options.multiple_errors = false; lc3_assemble(dummy_state, filename.GetFullPath().ToStdString(), options); options.multiple_errors = true; options.warnings_as_errors = false; options.process_debug_comments = true; options.enable_warnings = false; options.disable_plugins = false; lc3_assemble(state, filename.GetFullPath().ToStdString(), ranges, options); // Update list of addresses modified for Show only Code/Data option. modified_addresses.clear(); for (const auto& code_range : ranges) modified_addresses.push_back(ViewRange(code_range.location, code_range.location + code_range.size)); /// TODO Automatically determine state of true traps and interrupts via the code ranges. // Dummy call to update hidden addresses. wxCommandEvent event; OnUpdateHideAddresses(event); // Check for TVT and IVT modification for (const auto& code_range : ranges) { if ((code_range.location >= 0 && code_range.location <= 0xFF) || (code_range.location + code_range.size >= 0 && code_range.location + code_range.size <= 0xFF)) tvt_modification = true; if ((code_range.location >= 0x100 && code_range.location <= 0x1FF) || (code_range.location + code_range.size >= 0x100 && code_range.location + code_range.size <= 0x1FF)) ivt_modification = true; } subroutine_found = DetectSubroutine(ranges); } catch (LC3AssembleException e) { wxMessageBox(wxString::Format("ERROR! %s", e.what()), wxString::Format("Loading %s failed", filename.GetFullName())); goto merge; } catch (std::vector<LC3AssembleException> e) { std::stringstream oss; for (unsigned int i = 0; i < e.size(); i++) oss << e[i].what() << std::endl; wxMessageBox(wxString::Format("ERROR! %s", oss.str()), wxString::Format("Loading %s failed", filename.GetFullName())); goto merge; } lc3_set_true_traps(state, opts.true_traps || tvt_modification); state.interrupt_enabled = opts.interrupts || ivt_modification; console->SetInput(opts.console_input); state.strict_execution = opts.strict_execution; // Update menus menuStateTrueTraps->Check(opts.true_traps || tvt_modification); menuStateInterrupts->Check(opts.interrupts || ivt_modification); menuStateStrictExecution->Check(opts.strict_execution); if (tvt_modification) { bool tvt_popup = config->Read("/firsttimetrap", "").IsEmpty(); if (tvt_popup) { wxMessageBox("Pardon the interruption!\n" "It appears you have loaded a file with a custom trap.\n" "This will automatically enable true traps mode.\n" "This will allow you to step into the code for the standard traps (IN,OUT,GETC,PUTS,HALT) and your own custom trap.\n" "This notice to to remind you of the above, executing HALT will jump to some random code, but I assure you this random code is the code to HALT the LC-3.\n" "If you'd rather stop the execution right at the HALT statement then put a breakpoint on your HALT statement.\n", "Notice"); config->Write("/firsttimetrap", "1"); } } if (subroutine_found) { wxCommandEvent event; OnControlModeAdvanced(event); bool subroutine_popup = config->Read("/firsttimesubroutine", "").IsEmpty(); if (subroutine_popup) { wxMessageBox("Pardon the interruption!\n" "It appears you have loaded a file with a custom trap or subroutine.\n" "You may notice 3 new buttons in the control area.\n" "Next Line\n Allows you to STEP OVER a subroutine or trap, meaning it will skip over it (but still execute it).\n" "Prev Line\n Allows you to BACK STEP OVER a subroutine or trap.\n" "Finish\n Allows you to STEP OUT of a subroutine, it finishes execution of it.\n\n" "Another thing to note if you want to always step over/out a subroutine to select the subroutine label and select mark as blackbox.\n" "If you use step on a JSR/JSRR/TRAP instruction that is blackboxed it will never step into it.\n" "For more information Read The Manual :)\n" , "Notice"); config->Write("/firsttimesubroutine", "1"); } } SetTitle(wxString::Format("%s - %s", base_title, filename.GetFullPath())); merge: std::map<std::string, unsigned short>::const_iterator i; std::map<unsigned short, std::string>::const_iterator j; for (i = symbol_table.begin(); i != symbol_table.end(); ++i) { state.symbols[i->first] = i->second; } for (j = rev_symbol_table.begin(); j != rev_symbol_table.end(); ++j) { state.rev_symbols[j->first] = j->second; } UpdateStatus(); UpdateRegisters(); UpdateMemory(); // Save in reload options reload_options = opts; // Update timestamps wxFileName file_loaded(reload_options.file); reload_options.file_modification_time = file_loaded.GetModificationTime(); }
void do_randomize(void) { lc3_init(state, true, true); registers->Update(); memory->Update(); }
void do_reset(void) { lc3_init(state); registers->Update(); memory->Update(); }
LC3BasicTest() { lc3_init(state, false, false); }
int main(int argc, char **argv) { FILE *prog; lc3machine mach; /* We expect only one argument for the program... */ if (argc != 2) { fprintf(stderr, "Usage: %s file.obj\n", argv[0]); return 1; } /* We want to open the file and make sure that it exists. */ prog = fopen(argv[1], "rb"); if (!prog) { fprintf(stderr, "Could not find file %s\n", argv[1]); return 2; } /* Make a call to lc3_init to initialize your lc3machine */ lc3_init(&mach); /* Make a call to lc3_load to load the program */ lc3_load(&mach, prog); fclose(prog); /* Print out start of program */ printf("LC-3 simulator and debugger\n"); printf("Written by Ryan Goodrich\n"); /* Run this loop until we are told to stop debugging. */ unsigned char emptyPrompt = 0; char userInput[30]; int letter; int inputIndex = 0; while (1) { // check if there is a prompt on the screen if (!emptyPrompt) printf("%s", PROMPT), emptyPrompt = 1; else { // get the user input while ((letter = getchar()) != '\n') userInput[inputIndex < 30 ? inputIndex ++ : inputIndex] = letter; // check if input is exceeded buffer if (inputIndex > 29) printf("ERR: Input overflow\n"); // run command if valid else { // clean out the rest of the buffer if (inputIndex) { for (int i = inputIndex; i < 30; i ++) userInput[i] = 0; } // run command cmd_runprompt(&mach, userInput); } // rest input and prompt emptyPrompt = inputIndex = 0; } } return 0; }