/** 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(); }
/** 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(); }
/** lc3_init * * Initializes the state of the lc3 * * @param state An LC3 state * @param randomize_registers if true randomizes registers * @param randomize_memory if true randomizes memory * @param fill_value ignored if randomize_XXX is true otherwise sets registers/memory to this value (except R7). */ void lc3_init(lc3_state& state, bool randomize_registers, bool randomize_memory, short fill_value) { // Set Registers state.regs[0] = randomize_registers ? lc3_random() : fill_value; state.regs[1] = randomize_registers ? lc3_random() : fill_value; state.regs[2] = randomize_registers ? lc3_random() : fill_value; state.regs[3] = randomize_registers ? lc3_random() : fill_value; state.regs[4] = randomize_registers ? lc3_random() : fill_value; state.regs[5] = randomize_registers ? lc3_random() : fill_value; state.regs[6] = randomize_registers ? lc3_random() : fill_value; state.regs[7] = randomize_registers ? lc3_random() : 0x490; // PC is initially at address 3000 state.pc = 0x3000; // User mode state.privilege = 1; state.priority = 0; // Set Control Flags state.n = 0; state.z = 1; state.p = 0; // Set Additional Flags state.halted = 0; state.true_traps = 0; state.warnings = 0; state.executions = 0; state.interrupt_enabled = 0; // Clear subroutine info state.max_call_stack_size = -1; state.call_stack.clear(); // Set Stack Flags state.max_stack_size = -1; state.undo_stack.clear(); // Set I/O Stuff state.input = &std::cin; state.reader = lc3_read_char; state.peek = lc3_peek_char; state.output = &std::cout; state.writer = lc3_do_write_char; state.warning = &std::cout; // Clear memory if (randomize_memory) { lc3_randomize(state); } else { for (unsigned int i = 0; i < 65536; i++) state.mem[i] = fill_value; } // Add LC3 OS memcpy(state.mem, lc3_os, LC3_OS_SIZE * sizeof(unsigned short)); // Clear plugins lc3_remove_plugins(state); // Clear Symbol Table state.symbols.clear(); state.rev_symbols.clear(); // Clear Breakpoints and all that jazz state.breakpoints.clear(); state.blackboxes.clear(); state.comments.clear(); state.reg_watchpoints.clear(); state.mem_watchpoints.clear(); state.subroutines.clear(); // Clear pending interrupts state.interrupts.clear(); state.interrupt_test.clear(); state.interrupt_vector = -1; state.savedssp = 0x3000; state.savedusp = 0xF000; state.memory_ops.clear(); state.total_reads = 0; state.total_writes = 0; state.in_lc3test = false; }