diff --git a/breakpoint_memory.cpp b/breakpoint_memory.cpp index 811fcc9..dea0644 100644 --- a/breakpoint_memory.cpp +++ b/breakpoint_memory.cpp @@ -22,10 +22,16 @@ std::optional breakpoint_memory::is_triggered() const { uint16_t v = 0; - if (is_virtual) - v = b->peek_word(rm_cur, addr); // FIXME rm_cur - else + if (is_virtual) { + auto temp = b->peek_word(rm_cur, addr); // FIXME rm_cur + if (temp.has_value() == false) + return { }; + + v = temp.value(); + } + else { v = b->read_physical(addr); + } auto it = values.find(v); if (it == values.end()) diff --git a/bus.cpp b/bus.cpp index 2a3bed6..cedd517 100644 --- a/bus.cpp +++ b/bus.cpp @@ -854,13 +854,13 @@ uint16_t bus::read_word(const uint16_t a, const d_i_space_t s) return read(a, wm_word, rm_cur, s); } -uint16_t bus::peek_word(const int run_mode, const uint16_t a) +std::optional bus::peek_word(const int run_mode, const uint16_t a) { auto meta = mmu_->calculate_physical_address(run_mode, a); uint32_t io_base = mmu_->get_io_base(); - if (meta.physical_instruction >= io_base) // TODO: I/O always returns 0xffff - return 0xffff; + if (meta.physical_instruction >= io_base) + return { }; return m->read_word(meta.physical_instruction); } @@ -882,7 +882,6 @@ uint8_t bus::read_unibus_byte(const uint32_t a) void bus::write_unibus_byte(const uint32_t a, const uint8_t v) { TRACE("write_unibus_byte[%08o]=%03o", a, v); - if (a < m->get_memory_size()) m->write_byte(a, v); } diff --git a/bus.h b/bus.h index f744206..780d70b 100644 --- a/bus.h +++ b/bus.h @@ -126,7 +126,7 @@ class bus: public device uint8_t read_byte(const uint16_t a) override { return read(a, wm_byte, rm_cur); } uint16_t read_word(const uint16_t a, const d_i_space_t s); uint16_t read_word(const uint16_t a) override { return read_word(a, i_space); } - uint16_t peek_word(const int run_mode, const uint16_t a); + std::optional peek_word(const int run_mode, const uint16_t a); uint8_t read_unibus_byte(const uint32_t a); uint16_t read_physical(const uint32_t a); diff --git a/console_ncurses.cpp b/console_ncurses.cpp index c1d59bb..4f7ef4b 100644 --- a/console_ncurses.cpp +++ b/console_ncurses.cpp @@ -148,7 +148,7 @@ void console_ncurses::panel_update_thread() uint16_t current_PC = c->getPC(); memory_addresses_t rc = b->getMMU()->calculate_physical_address(run_mode, current_PC); - uint16_t current_instr = b->peek_word(run_mode, current_PC); + auto current_instr = b->peek_word(run_mode, current_PC); auto data = c->disassemble(current_PC); @@ -167,8 +167,14 @@ void console_ncurses::panel_update_thread() for(uint8_t b=0; b<16; b++) mvwprintw(w_panel->win, 1, 1 + 16 - b, "%c", current_PSW & (1 << b) ? '1' : '0'); - for(uint8_t b=0; b<16; b++) - mvwprintw(w_panel->win, 1, 1 + 16 - b + 17, "%c", current_instr & (1 << b) ? '1' : '0'); + if (current_instr.has_value()) { + for(uint8_t b=0; b<16; b++) + mvwprintw(w_panel->win, 1, 1 + 16 - b + 17, "%c", current_instr.value() & (1 << b) ? '1' : '0'); + } + else { + for(uint8_t b=0; b<16; b++) + mvwprintw(w_panel->win, 1, 1 + 16 - b + 17, "-"); + } mvwprintw(w_panel->win, 4, 1, "LEDs:"); diff --git a/cpu.cpp b/cpu.cpp index b274adf..e0ea878 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -1898,15 +1898,20 @@ void cpu::trap(uint16_t vector, const int new_ipl, const bool is_interrupt) while(0); } -cpu::operand_parameters cpu::addressing_to_string(const uint8_t mode_register, const uint16_t pc, const word_mode_t word_mode) const +std::optional cpu::addressing_to_string(const uint8_t mode_register, const uint16_t pc, const word_mode_t word_mode) const { assert(mode_register < 64); int run_mode = getPSW_runmode(); - uint16_t next_word = b->peek_word(run_mode, pc & 65535); + auto temp = b->peek_word(run_mode, pc & 65535); + if (temp.has_value() == false) + return { }; + uint16_t next_word = temp.value(); int reg = mode_register & 7; uint16_t mask = word_mode == wm_byte ? 0xff : 0xffff; + std::optional temp2; + std::string reg_name; if (reg == 6) reg_name = "SP"; @@ -1917,49 +1922,111 @@ cpu::operand_parameters cpu::addressing_to_string(const uint8_t mode_register, c switch(mode_register >> 3) { case 0: - return { reg_name, 2, -1, uint16_t(get_register(reg) & mask) }; + return { { reg_name, 2, -1, uint16_t(get_register(reg) & mask) } }; case 1: - return { format("(%s)", reg_name.c_str()), 2, -1, uint16_t(b->peek_word(run_mode, get_register(reg)) & mask) }; + temp2 = b->peek_word(run_mode, get_register(reg)); + if (temp2.has_value() == false) + return { }; + + return { { format("(%s)", reg_name.c_str()), 2, -1, uint16_t(temp2.value() & mask) } }; case 2: if (reg == 7) - return { format("#%06o", next_word), 4, int(next_word), uint16_t(next_word & mask) }; + return { { format("#%06o", next_word), 4, int(next_word), uint16_t(next_word & mask) } }; + + temp2 = b->peek_word(run_mode, get_register(reg)); + if (temp2.has_value() == false) + return { }; - return { format("(%s)+", reg_name.c_str()), 2, -1, uint16_t(b->peek_word(run_mode, get_register(reg)) & mask) }; + return { { format("(%s)+", reg_name.c_str()), 2, -1, uint16_t(temp2.value() & mask) } }; case 3: - if (reg == 7) - return { format("@#%06o", next_word), 4, int(next_word), uint16_t(b->peek_word(run_mode, next_word) & mask) }; + if (reg == 7) { + temp2 = b->peek_word(run_mode, next_word); + if (temp2.has_value() == false) + return { }; + + return { { format("@#%06o", next_word), 4, int(next_word), uint16_t(temp2.value() & mask) } }; + } - return { format("@(%s)+", reg_name.c_str()), 2, -1, uint16_t(b->peek_word(run_mode, b->peek_word(run_mode, get_register(reg))) & mask) }; + temp2 = b->peek_word(run_mode, get_register(reg)); + if (temp2.has_value() == false) + return { }; + + temp2 = b->peek_word(run_mode, temp2.value()); + if (temp2.has_value() == false) + return { }; + + return { { format("@(%s)+", reg_name.c_str()), 2, -1, uint16_t(temp2.value() & mask) } }; case 4: - return { format("-(%s)", reg_name.c_str()), 2, -1, uint16_t(b->peek_word(run_mode, get_register(reg) - (word_mode == wm_word || reg >= 6 ? 2 : 1)) & mask) }; + temp2 = b->peek_word(run_mode, get_register(reg) - (word_mode == wm_word || reg >= 6 ? 2 : 1)); + if (temp2.has_value() == false) + return { }; + + return { { format("-(%s)", reg_name.c_str()), 2, -1, uint16_t(temp2.value() & mask) } }; case 5: - return { format("@-(%s)", reg_name.c_str()), 2, -1, uint16_t(b->peek_word(run_mode, b->peek_word(run_mode, get_register(reg) - 2)) & mask) }; + temp2 = b->peek_word(run_mode, get_register(reg) - 2); + if (temp2.has_value() == false) + return { }; + + temp2 = b->peek_word(run_mode, temp2.value()); + if (temp2.has_value() == false) + return { }; + + return { { format("@-(%s)", reg_name.c_str()), 2, -1, uint16_t(temp2.value() & mask) } }; case 6: - if (reg == 7) - return { format("%06o", (pc + next_word + 2) & 65535), 4, int(next_word), uint16_t(b->peek_word(run_mode, get_register(reg) + next_word) & mask) }; + if (reg == 7) { + temp2 = b->peek_word(run_mode, get_register(reg) + next_word); + if (temp2.has_value() == false) + return { }; + + return { { format("%06o", (pc + next_word + 2) & 65535), 4, int(next_word), uint16_t(temp2.value() & mask) } }; + } - return { format("%o(%s)", next_word, reg_name.c_str()), 4, int(next_word), uint16_t(b->peek_word(run_mode, get_register(reg) + next_word) & mask) }; + temp2 = b->peek_word(run_mode, get_register(reg) + next_word); + if (temp2.has_value() == false) + return { }; + + return { { format("%o(%s)", next_word, reg_name.c_str()), 4, int(next_word), uint16_t(temp2.value() & mask) } }; case 7: - if (reg == 7) - return { format("@%06o", next_word), 4, int(next_word), uint16_t(b->peek_word(run_mode, b->peek_word(run_mode, get_register(reg) + next_word)) & mask) }; + if (reg == 7) { + temp2 = b->peek_word(run_mode, get_register(reg) + next_word); + if (temp2.has_value() == false) + return { }; + + temp2 = b->peek_word(run_mode, temp2.value()); + if (temp2.has_value() == false) + return { }; - return { format("@%o(%s)", next_word, reg_name.c_str()), 4, int(next_word), uint16_t(b->peek_word(run_mode, b->peek_word(run_mode, get_register(reg) + next_word)) & mask) }; + return { { format("@%06o", next_word), 4, int(next_word), uint16_t(temp2.value() & mask) } }; + } + + temp2 = b->peek_word(run_mode, get_register(reg) + next_word); + if (temp2.has_value() == false) + return { }; + + temp2 = b->peek_word(run_mode, temp2.value()); + if (temp2.has_value() == false) + return { }; + + return { { format("@%o(%s)", next_word, reg_name.c_str()), 4, int(next_word), uint16_t(temp2.value() & mask) } }; } - return { "??", 0, -1, 0123456 }; + return { }; } std::map > cpu::disassemble(const uint16_t addr) const { - uint16_t instruction = b->peek_word(getPSW_runmode(), addr); + auto temp = b->peek_word(getPSW_runmode(), addr); + if (temp.has_value() == false) + return { }; + uint16_t instruction = temp.value(); word_mode_t word_mode = instruction & 0x8000 ? wm_byte : wm_word; std::string word_mode_str = word_mode == wm_byte ? "B" : ""; uint8_t ado_opcode = (instruction >> 9) & 7; // additional double operand @@ -1981,7 +2048,10 @@ std::map > cpu::disassemble(const uint16_t // TODO: 100000011 if (do_opcode == 0b000) { - auto dst_text { addressing_to_string(dst_register, (addr + 2) & 65535, word_mode) }; + auto addressing = addressing_to_string(dst_register, (addr + 2) & 65535, word_mode); + if (addressing.has_value() == false) + return { }; + auto dst_text { addressing.value() }; auto next_word = dst_text.instruction_part; @@ -2074,7 +2144,10 @@ std::map > cpu::disassemble(const uint16_t name = "?"; else { std::string src_text = format("R%d", (instruction >> 6) & 7); - auto dst_text { addressing_to_string(dst_register, (addr + 2) & 65535, word_mode) }; + auto addressing = addressing_to_string(dst_register, (addr + 2) & 65535, word_mode); + if (addressing.has_value() == false) + return { }; + auto dst_text { addressing.value() }; auto next_word = dst_text.instruction_part; @@ -2144,7 +2217,10 @@ std::map > cpu::disassemble(const uint16_t } // source - auto src_text { addressing_to_string(src_register, (addr + 2) & 65535, word_mode) }; + auto addressing_src = addressing_to_string(src_register, (addr + 2) & 65535, word_mode); + if (addressing_src.has_value() == false) + return { }; + auto src_text { addressing_src.value() }; auto next_word_src = src_text.instruction_part; if (next_word_src != -1) @@ -2153,7 +2229,10 @@ std::map > cpu::disassemble(const uint16_t work_values.push_back(src_text.work_value); // destination - auto dst_text { addressing_to_string(dst_register, (addr + src_text.length) & 65535, word_mode) }; + auto addressing_dst = addressing_to_string(dst_register, (addr + src_text.length) & 65535, word_mode); + if (addressing_dst.has_value() == false) + return { }; + auto dst_text { addressing_dst.value() }; auto next_word_dst = dst_text.instruction_part; if (next_word_dst != -1) @@ -2304,7 +2383,10 @@ std::map > cpu::disassemble(const uint16_t text = format("TRAP %o", instruction & 255); if ((instruction & ~0b111111) == 0b0000000001000000) { - auto dst_text { addressing_to_string(dst_register, (addr + 2) & 65535, word_mode) }; + auto addressing = addressing_to_string(dst_register, (addr + 2) & 65535, word_mode); + if (addressing.has_value() == false) + return { }; + auto dst_text { addressing.value() }; auto next_word = dst_text.instruction_part; if (next_word != -1) @@ -2316,7 +2398,10 @@ std::map > cpu::disassemble(const uint16_t } if ((instruction & 0b1111111000000000) == 0b0000100000000000) { - auto dst_text { addressing_to_string(dst_register, (addr + 2) & 65535, word_mode) }; + auto addressing = addressing_to_string(dst_register, (addr + 2) & 65535, word_mode); + if (addressing.has_value() == false) + return { }; + auto dst_text { addressing.value() }; auto next_word = dst_text.instruction_part; if (next_word != -1) diff --git a/cpu.h b/cpu.h index bae5032..1d5ce10 100644 --- a/cpu.h +++ b/cpu.h @@ -105,7 +105,7 @@ class cpu uint16_t work_value; }; - operand_parameters addressing_to_string(const uint8_t mode_register, const uint16_t pc, const word_mode_t word_mode) const; + std::optional addressing_to_string(const uint8_t mode_register, const uint16_t pc, const word_mode_t word_mode) const; void add_to_stack_trace(const uint16_t p); void pop_from_stack_trace(); diff --git a/debugger.cpp b/debugger.cpp index 189ccbb..be9f612 100644 --- a/debugger.cpp +++ b/debugger.cpp @@ -431,6 +431,8 @@ void configure_disk(bus *const b, console *const cnsl) int disassemble(cpu *const c, console *const cnsl, const uint16_t pc, const bool instruction_only) { auto data = c->disassemble(pc); + if (data.empty()) + return 2; // problem! auto registers = data["registers"]; auto psw = data["psw"][0]; @@ -933,11 +935,20 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto for(int i=0; ipeek_word(c->getPSW_runmode(), cur_addr) : b->read_physical(cur_addr); + uint16_t val = 0; - if (val == -1) { - cnsl->put_string_lf(format("Can't read from %06o\n", cur_addr)); - break; + if (parts[2] == "v") { + auto v = b->peek_word(c->getPSW_runmode(), cur_addr); + + if (v.has_value() == false) { + cnsl->put_string_lf(format("Can't read from %06o\n", cur_addr)); + break; + } + + val = v.value(); + } + else { + val = b->read_physical(cur_addr); } if (n == 1)