void do_run(void) { state.halted = 0; lc3_run(state); memory->Update(); registers->Update(); }
void do_step(unsigned int times) { state.halted = 0; lc3_run(state, times); memory->Update(); registers->Update(); }
/** Entry * * */ void* LC3RunThread::Entry() { ///TODO consider writing this without rewriting next_line/prev_line. int depth = 0; lc3_instr instr; bool interrupt_begin = false; state.halted = 0; switch(run_mode) { case RUNMODE_RUN: while(!state.halted) { lc3_step(state); if (TestDestroy()) break; Yield(); } break; case RUNMODE_RUNFOR: if (runtime > 0) lc3_run(state, runtime); else lc3_rewind(state, -runtime); break; case RUNMODE_STEP: lc3_step(state); break; case RUNMODE_BACK: lc3_back(state); break; case RUNMODE_FINISH: depth = 1; case RUNMODE_NEXTLINE: // Subroutine depth do { // Get Next Instruction. instr = lc3_decode(state, state.mem[state.pc]); // So if we get a JSR/JSRR or if we get a TRAP and true traps are enabled if (instr.data.opcode == JSR_INSTR || (instr.data.opcode == TRAP_INSTR && state.true_traps)) depth++; // If we get a RET instruction JMP R7 if (instr.data.opcode == JMP_INSTR && instr.jmp.base_r == 7) depth--; // If we get an RTI instruction if (instr.data.opcode == RTI_INSTR) depth--; // Execute lc3_step(state); // If we got interrupted if (state.interrupt_enabled && state.undo_stack.back().changes == LC3_INTERRUPT_BEGIN) depth++; if (TestDestroy()) break; Yield(); } while (depth != 0 && !state.halted); break; case RUNMODE_PREVLINE: // Subroutine depth depth = 0; do { if (!state.undo_stack.empty()) { lc3_state_change& last = state.undo_stack.back(); // Can't backstep through interrupt if (last.changes == LC3_INTERRUPT_BEGIN) break; // Get rid of all processed interrupts. while (last.changes == LC3_INTERRUPT && !state.undo_stack.empty()) { lc3_back(state); last = state.undo_stack.back(); if (TestDestroy()) break; Yield(); } } // Execute (Have to do this first you can't assume mem[pc - 1] was the last // instruction due to jumps. lc3_back(state); // Get the instruction that got you where you are. lc3_instr instr = lc3_decode(state, state.mem[state.pc]); // If we get a RET instruction JMP R7 if (instr.data.opcode == JMP_INSTR && instr.jmp.base_r == 7) depth++; // So if we get a JSR/JSRR or if we get a TRAP and true traps are enabled if (instr.data.opcode == JSR_INSTR || (instr.data.opcode == TRAP_INSTR && state.true_traps)) depth--; if (TestDestroy()) break; Yield(); // Don't have to handle interrupts here... } while (depth != 0 && !state.halted && !state.undo_stack.empty()); break; case RUNMODE_REWIND: // Do this until no more changes. while (!state.undo_stack.empty() && !interrupt_begin) { lc3_state_change& last = state.undo_stack.back(); interrupt_begin = (last.changes == LC3_INTERRUPT_BEGIN); // Backstep lc3_back(state); if (TestDestroy()) break; Yield(); } break; } wxQueueEvent(frame, new wxThreadEvent(wxEVT_COMMAND_RUNTHREAD_COMPLETED)); return NULL; }
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; }
/** cmd_runprompt * * Determine what the user input is and run * * @param mach A pointer to the lc3 simulator * @param prompt A pointer to the string the user provided * @param lastCommand The last command index to be run */ void cmd_runprompt(lc3machine* mach, char * prompt) { // copy prompt char promptCopy[30]; strcpy(promptCopy, prompt); // break appart command by spaces char * command; command = strtok(promptCopy, " "); // check if command is a quit if (strcmp(command, "quit") == 0 || strcmp(command, "q") == 0) exit(0); // check if command is to step else if (strcmp(command, "step") == 0 || strcmp(command, "s") == 0) { // get number of lines to step command = strtok(NULL, " "); int lines = command == NULL ? 1 : atoi(command); lc3_run(mach, lines); } // check if command is continue else if (strcmp(command, "continue") == 0 || strcmp(command, "c") == 0 || strcmp(command, "run") == 0) { lc3_run(mach, -1); } // check if want the registers else if (strcmp(command, "registers") == 0 || strcmp(command, "r") == 0) { cmd_registers(mach); } // check if command is to dump memory else if (strcmp(command, "dump") == 0) { // check if the command is valid if ((command = strtok(NULL, " ")) == NULL) { printf("ERR: Input invalid: Starting memory index required\n"); return; } // get starting location char * pEnd; int dumpStart = (int) strtol(command, &pEnd, 16); // get ending locaiton command = strtok(NULL, " "); int dumpEnd = command == NULL ? dumpStart : ((int) strtol(command, &pEnd, 16)); // dump the core cmd_dump(mach, dumpStart, dumpEnd); } // check if command is to set memory else if (strcmp(command, "setaddr") == 0) { // check if the command is valid if ((command = strtok(NULL, " ")) == NULL) { printf("ERR: Input invalid: Memory address required\n"); return; } // get address char * pEnd; int address = (int) strtol(command, &pEnd, 16); // check if the command is valid if ((command = strtok(NULL, " ")) == NULL) { printf("ERR: Input invalid: Memory value required\n"); return; } // set value cmd_setaddr(mach, address, atoi(command)); } // check if command is to set memory else if (strcmp(command, "setreg") == 0) { // check if the command is valid if ((command = strtok(NULL, " ")) == NULL) { printf("ERR: Input invalid: Register number required\n"); return; } // get register int reg = atoi(command + 1); // check if the command is valid if ((command = strtok(NULL, " ")) == NULL) { printf("ERR: Input invalid: Register value required\n"); return; } // set value cmd_setreg(mach, reg, atoi(command)); } // check if command is for help else if (strcmp(command, "help") == 0) { printf("step [n]\n\tExecutes n instructions (n defaults to 1)\nquit\n\tQuits the simulator\ncontinue\n\tRuns until the program halts\nregisters\n\tPrints all registers, pc, and cc values\ndump start [end]\n\tDumps the contents of memory from the starting address to the end (if not provided will just print one value)\nsetaddr addr value\n\tSets the value at the provided address\nsetreg Rn value\n\tSets register n with the provided value\nhelp\n\tDisplays this menu\n"); } // command not found else printf("ERR: Input invalid. Type 'help' for a list of instructions\n"); }