From ad7aca8876a62d35e599a1d453f101badace9ee5 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sun, 12 Jun 2022 15:52:41 +0200 Subject: [PATCH 01/33] Prepare calculate_physical_address for D/I. --- bus.cpp | 28 +++++++++++++++------------- bus.h | 2 +- console_ncurses.cpp | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/bus.cpp b/bus.cpp index bed9dcb..5a15bc3 100644 --- a/bus.cpp +++ b/bus.cpp @@ -279,7 +279,7 @@ uint16_t bus::read(const uint16_t a, const bool word_mode, const bool use_prev, int run_mode = (c->getPSW() >> (use_prev ? 12 : 14)) & 3; - uint32_t m_offset = calculate_physical_address(run_mode, a, !peek_only, false, peek_only); + uint32_t m_offset = calculate_physical_address(run_mode, a, !peek_only, false, peek_only, false); if (word_mode) temp = m -> readByte(m_offset); @@ -291,28 +291,30 @@ uint16_t bus::read(const uint16_t a, const bool word_mode, const bool use_prev, return temp; } -uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, const bool trap_on_failure, const bool is_write, const bool peek_only) +uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, const bool trap_on_failure, const bool is_write, const bool peek_only, const bool is_data) { uint32_t m_offset = 0; if (MMR0 & 1) { const uint8_t apf = a >> 13; // active page field - // TODO: D/I - m_offset = pages[run_mode][0][apf].par * 64; // memory offset TODO: handle 16b int-s + constexpr uint16_t di_ena_mask[4] = { 4, 2, 0, 1 }; + bool d = is_data & (!!(MMR3 & di_ena_mask[run_mode])) ? is_data : false; uint16_t p_offset = a & 8191; // page offset + m_offset = pages[run_mode][d][apf].par * 64; // memory offset TODO: handle 16b int-s + m_offset += p_offset; if (trap_on_failure) { if (MMR0 & (1 << 9)) { - int access_control = pages[run_mode][0][apf].pdr & 7; + int access_control = pages[run_mode][d][apf].pdr & 7; if (is_write && access_control != 6) { // write c->schedule_trap(04); // invalid address - pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I + pages[run_mode][d][apf].pdr |= 1 << 7; MMR0 |= 1 << 13; // read-only @@ -327,7 +329,7 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c if (access_control == 0 || access_control == 1 || access_control == 3 || access_control == 4 || access_control == 7) { c->schedule_trap(04); // invalid address - pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I + pages[run_mode][d][apf].pdr |= 1 << 7; MMR0 |= 1 << 13; // read-only @@ -341,9 +343,9 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c } } - uint16_t pdr_len = (((pages[run_mode][0][apf].pdr >> 8) & 127) + 1) * 64; // TODO: D/I + uint16_t pdr_len = (((pages[run_mode][d][apf].pdr >> 8) & 127) + 1) * 64; - bool direction = pages[run_mode][0][apf].pdr & 8; // TODO: D/I + bool direction = pages[run_mode][d][apf].pdr & 8; if (m_offset >= n_pages * 8192) { DOLOG(debug, !peek_only, "bus::calculate_physical_address %o >= %o", m_offset, n_pages * 8192); @@ -351,7 +353,7 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c MMR0 |= 1 << 15; // non-resident - pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I + pages[run_mode][d][apf].pdr |= 1 << 7; throw 1; } @@ -362,13 +364,13 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c MMR0 |= 1 << 14; // length - pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I + pages[run_mode][d][apf].pdr |= 1 << 7; throw 1; } } - DOLOG(debug, !peek_only, "virtual address %06o maps to physical address %08o (run_mode: %d, apf: %d, par: %08o, poff)", a, m_offset, run_mode, apf, pages[run_mode][0][apf].par * 64, p_offset); // TODO: D/I + DOLOG(debug, !peek_only, "virtual address %06o maps to physical address %08o (run_mode: %d, apf: %d, par: %08o, poff)", a, m_offset, run_mode, apf, pages[run_mode][d][apf].par * 64, p_offset); } else { m_offset = a; @@ -664,7 +666,7 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons int run_mode = (c->getPSW() >> (use_prev ? 12 : 14)) & 3; - uint32_t m_offset = calculate_physical_address(run_mode, a, true, true, false); + uint32_t m_offset = calculate_physical_address(run_mode, a, true, true, false, false); DOLOG(debug, true, "WRITE to %06o/%07o: %o", a, m_offset, value); diff --git a/bus.h b/bus.h index eb50428..8dee308 100644 --- a/bus.h +++ b/bus.h @@ -86,5 +86,5 @@ public: uint16_t get_switch_register() const { return switch_register; } - uint32_t calculate_physical_address(const int run_mode, const uint16_t a, const bool trap_on_failure, const bool is_write, const bool peek_only); + uint32_t calculate_physical_address(const int run_mode, const uint16_t a, const bool trap_on_failure, const bool is_write, const bool peek_only, const bool is_data); }; diff --git a/console_ncurses.cpp b/console_ncurses.cpp index a90b7b6..5720b85 100644 --- a/console_ncurses.cpp +++ b/console_ncurses.cpp @@ -139,7 +139,7 @@ void console_ncurses::panel_update_thread() int run_mode = current_PSW >> 14; uint16_t current_PC = c->getPC(); - uint32_t full_addr = b->calculate_physical_address(run_mode, current_PC, false, false, true); + uint32_t full_addr = b->calculate_physical_address(run_mode, current_PC, false, false, true, false); uint16_t current_instr = b->readWord(current_PC); From c9fa383bfa0ababf9c7c34d88a6af69fea516dc7 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sun, 12 Jun 2022 20:02:05 +0200 Subject: [PATCH 02/33] bus is now enhanced for d/i space --- bus.cpp | 8 ++++---- bus.h | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/bus.cpp b/bus.cpp index 5a15bc3..599a2b6 100644 --- a/bus.cpp +++ b/bus.cpp @@ -51,7 +51,7 @@ void bus::init() MMR3 = 0; } -uint16_t bus::read(const uint16_t a, const bool word_mode, const bool use_prev, const bool peek_only) +uint16_t bus::read(const uint16_t a, const bool word_mode, const bool use_prev, const bool peek_only, const d_i_space_t space) { uint16_t temp = 0; @@ -279,7 +279,7 @@ uint16_t bus::read(const uint16_t a, const bool word_mode, const bool use_prev, int run_mode = (c->getPSW() >> (use_prev ? 12 : 14)) & 3; - uint32_t m_offset = calculate_physical_address(run_mode, a, !peek_only, false, peek_only, false); + uint32_t m_offset = calculate_physical_address(run_mode, a, !peek_only, false, peek_only, space == d_space); if (word_mode) temp = m -> readByte(m_offset); @@ -393,7 +393,7 @@ void bus::addToMMR1(const int8_t delta, const uint8_t reg) MMR1 |= reg; } -uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, const bool use_prev) +uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, const bool use_prev, const d_i_space_t space) { if (a >= 0160000) { if (word_mode) { @@ -666,7 +666,7 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons int run_mode = (c->getPSW() >> (use_prev ? 12 : 14)) & 3; - uint32_t m_offset = calculate_physical_address(run_mode, a, true, true, false, false); + uint32_t m_offset = calculate_physical_address(run_mode, a, true, true, false, space == d_space); DOLOG(debug, true, "WRITE to %06o/%07o: %o", a, m_offset, value); diff --git a/bus.h b/bus.h index 8dee308..0321134 100644 --- a/bus.h +++ b/bus.h @@ -13,6 +13,8 @@ class cpu; class memory; class tty; +typedef enum { d_space, i_space } d_i_space_t; + typedef struct { uint16_t par, pdr; @@ -63,14 +65,14 @@ public: void set_lf_crs_b7(); uint8_t get_lf_crs(); - uint16_t read(const uint16_t a, const bool word_mode, const bool use_prev, const bool peek_only=false); + uint16_t read(const uint16_t a, const bool word_mode, const bool use_prev, const bool peek_only=false, const d_i_space_t s = i_space); uint16_t readByte(const uint16_t a) { return read(a, true, false); } uint16_t readWord(const uint16_t a); uint16_t peekWord(const uint16_t a); uint16_t readUnibusByte(const uint16_t a); - uint16_t write(const uint16_t a, const bool word_mode, uint16_t value, const bool use_prev); + uint16_t write(const uint16_t a, const bool word_mode, uint16_t value, const bool use_prev, const d_i_space_t s = i_space); uint8_t writeByte(const uint16_t a, const uint8_t value) { return write(a, true, value, false); } uint16_t writeWord(const uint16_t a, const uint16_t value); From 81dc6d89245f927c8f79347a36497f23b6dd9d67 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Mon, 13 Jun 2022 21:53:59 +0200 Subject: [PATCH 03/33] trap: read from D-space --- bus.cpp | 4 ++-- bus.h | 4 ++-- cpu.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bus.cpp b/bus.cpp index 2f0a61a..0e896c4 100644 --- a/bus.cpp +++ b/bus.cpp @@ -707,9 +707,9 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons return value; } -uint16_t bus::readWord(const uint16_t a) +uint16_t bus::readWord(const uint16_t a, const d_i_space_t s) { - return read(a, false, false, false); + return read(a, false, false, false, s); } uint16_t bus::peekWord(const uint16_t a) diff --git a/bus.h b/bus.h index 67c03fa..7fb20ab 100644 --- a/bus.h +++ b/bus.h @@ -67,13 +67,13 @@ public: uint16_t read(const uint16_t a, const bool word_mode, const bool use_prev, const bool peek_only=false, const d_i_space_t s = i_space); uint16_t readByte(const uint16_t a) { return read(a, true, false); } - uint16_t readWord(const uint16_t a); + uint16_t readWord(const uint16_t a, const d_i_space_t s = i_space); uint16_t peekWord(const uint16_t a); uint16_t readUnibusByte(const uint16_t a); uint16_t write(const uint16_t a, const bool word_mode, uint16_t value, const bool use_prev, const d_i_space_t s = i_space); - uint8_t writeByte(const uint16_t a, const uint8_t value) { return write(a, true, value, false); } + uint8_t writeByte(const uint16_t a, const uint8_t value) { return write(a, true, value, false); } uint16_t writeWord(const uint16_t a, const uint16_t value); void writeUnibusByte(const uint16_t a, const uint8_t value); diff --git a/cpu.cpp b/cpu.cpp index e596d41..c6e6c22 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -1661,10 +1661,10 @@ void cpu::trap(const uint16_t vector, const int new_ipl) b->addToMMR1(-2, 6); } - setPC(b->readWord(vector + 0)); + setPC(b->readWord(vector + 0, d_space)); // switch to kernel mode & update 'previous mode' - uint16_t new_psw = b->readWord(vector + 2) & 0147777; // mask off old 'previous mode' + uint16_t new_psw = b->readWord(vector + 2, d_space) & 0147777; // mask off old 'previous mode' if (new_ipl != -1) new_psw = (new_psw & ~0xe0) | (new_ipl << 5); new_psw |= (before_psw >> 2) & 030000; // apply new 'previous mode' From 2838695fb68439271d361801cac30fc13cce1e21 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Thu, 10 Nov 2022 13:26:45 +0100 Subject: [PATCH 04/33] debugger enhancements --- cpu.cpp | 2 +- debugger.cpp | 62 +++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/cpu.cpp b/cpu.cpp index e7ca8ec..890c1b7 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -1336,7 +1336,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) set_flags = a != ADDR_PSW; - b -> write(a, false, v, true); // put in '13/12' address space + b->write(a, false, v, true); // put in '13/12' address space } if (set_flags) { diff --git a/debugger.cpp b/debugger.cpp index 0862ede..cdfe0fe 100644 --- a/debugger.cpp +++ b/debugger.cpp @@ -120,6 +120,7 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto { int32_t trace_start_addr = -1; bool tracing = tracing_in; + int n_single_step = 1; cpu *const c = b->getCpu(); @@ -137,8 +138,14 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto if (cmd == "go") single_step = false; - else if (cmd == "single" || cmd == "s") + else if (parts[0] == "single" || parts[0] == "s") { single_step = true; + + if (parts.size() == 2) + n_single_step = atoi(parts[1].c_str()); + else + n_single_step = 1; + } else if ((parts[0] == "sbp" || parts[0] == "cbp") && parts.size() == 2){ uint16_t pc = std::stoi(parts[1].c_str(), nullptr, 8); @@ -211,21 +218,50 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto continue; } else if (parts[0] == "examine" || parts[0] == "e") { - if (parts.size() != 3) + if (parts.size() < 3) cnsl->put_string_lf("parameter missing"); else { - int addr = std::stoi(parts[2], nullptr, 8); - int val = -1; + int addr = std::stoi(parts[2], nullptr, 8); + int val = -1; - if (parts[1] == "B" || parts[1] == "b") - val = b->read(addr, true, false, true); - else if (parts[1] == "W" || parts[1] == "w") - val = b->read(addr, false, false, true); - else + int n = parts.size() == 4 ? atoi(parts[3].c_str()) : 1; + bool word = parts[1] == "w"; + + if (parts[1] != "w" && parts[1] != "b") { cnsl->put_string_lf("expected b or w"); - if (val != -1) - cnsl->put_string_lf(format("value at %06o, octal: %o, hex: %x, dec: %d\n", addr, val, val, val)); + continue; + } + + std::string out; + + for(int i=0; iread(addr + i, true, false, true); + else if (word) + val = b->read(addr + i, false, false, true); + + if (val == -1) { + cnsl->put_string_lf(format("Can't read from %06o\n", addr + i)); + break; + } + + if (n == 1) + cnsl->put_string_lf(format("value at %06o, octal: %o, hex: %x, dec: %d\n", addr + i, val, val, val)); + + if (n > 1) { + if (i > 0) + out += " "; + + if (word) + out += format("%06o", val); + else + out += format("%03o", val); + } + } + + if (n > 1) + cnsl->put_string_lf(out); } continue; @@ -252,7 +288,7 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto #if !defined(ESP32) cnsl->put_string_lf("quit/q - stop emulator"); #endif - cnsl->put_string_lf("examine/e - show memory address ( )"); + cnsl->put_string_lf("examine/e - show memory address ( [])"); cnsl->put_string_lf("reset/r - reset cpu/bus/etc"); cnsl->put_string_lf("single/s - run 1 instruction (implicit 'disassemble' command)"); cnsl->put_string_lf("sbp/cbp/lbp - set/clear/list breakpoint(s)"); @@ -287,7 +323,7 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto c->step_b(); - if (single_step) + if (single_step && --n_single_step == 0) break; } From 6f20ce864f64f61f8d6b469fc2188d67ad8c306c Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Fri, 11 Nov 2022 21:50:24 +0100 Subject: [PATCH 05/33] disassembler fix --- cpu.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/cpu.cpp b/cpu.cpp index 890c1b7..2356c3d 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -359,6 +359,8 @@ bool cpu::putGAM(const uint8_t mode, const int reg, const bool word_mode, const int set = getBitPSW(11); + uint16_t dummy = 0; + switch(mode) { case 0: setRegister(reg, prev_mode, value); @@ -378,8 +380,8 @@ bool cpu::putGAM(const uint8_t mode, const int reg, const bool word_mode, const addRegister(reg, prev_mode, 2); break; case 4: - addRegister(reg, prev_mode, !word_mode || reg == 7 || reg == 6 ? -2 : -1); - b -> write(getRegister(reg, set, prev_mode), word_mode, value, false); + dummy = addRegister(reg, prev_mode, !word_mode || reg == 7 || reg == 6 ? -2 : -1); + b -> write(dummy, word_mode, value, false); break; case 5: addRegister(reg, prev_mode, -2); @@ -1827,8 +1829,6 @@ std::map > cpu::disassemble(const uint16_t auto dst_text { addressing_to_string(dst_register, (addr + 2) & 65535, word_mode) }; auto next_word = dst_text.instruction_part; - if (next_word != -1) - instruction_words.push_back(next_word); work_values.push_back(dst_text.work_value); @@ -1910,14 +1910,15 @@ std::map > cpu::disassemble(const uint16_t if (text.empty() && name.empty() == false) text = name + word_mode_str + space + dst_text.operand; + + if (text.empty() == false && next_word != -1) + instruction_words.push_back(next_word); } else if (do_opcode == 0b111) { std::string src_text = format("R%d", (instruction >> 6) & 7); auto dst_text { addressing_to_string(dst_register, (addr + 2) & 65535, word_mode) }; auto next_word = dst_text.instruction_part; - if (next_word != -1) - instruction_words.push_back(next_word); work_values.push_back(dst_text.work_value); @@ -1949,6 +1950,9 @@ std::map > cpu::disassemble(const uint16_t if (text.empty() && name.empty() == false) text = name + space + src_text + comma + dst_text.operand; + + if (text.empty() == false && next_word != -1) + instruction_words.push_back(next_word); } else { switch(do_opcode) { From 3ef8bd930dda3eb70b9d8c1fc313ebf0680722fb Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sat, 11 Mar 2023 21:13:46 +0100 Subject: [PATCH 06/33] Added: * calculate data/instruction physical addresses from a virtual address memory_addresses_t calculate_physical_address(const int run_mode, const uint16_t a); * check if a 'memory_address_t'-address would cause a fault void check_address(const bool trap_on_failure, const bool is_write, const memory_addresses_t & addr, const bool word_mode, const bool is_data, const int run_mode); --- bus.cpp | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bus.h | 13 +++++- 2 files changed, 151 insertions(+), 2 deletions(-) diff --git a/bus.cpp b/bus.cpp index 84c968f..668c9db 100644 --- a/bus.cpp +++ b/bus.cpp @@ -324,6 +324,146 @@ void bus::setMMR2(const uint16_t value) MMR2 = value; } +memory_addresses_t bus::calculate_physical_address(const int run_mode, const uint16_t a) +{ + const uint8_t apf = a >> 13; // active page field + + uint32_t physical_instruction = pages[run_mode][0][apf].par * 64; + uint32_t physical_data = pages[run_mode][1][apf].par * 64; + + uint16_t p_offset = a & 8191; // page offset + + physical_instruction += p_offset; + physical_data += p_offset; + + if (MMR0 & 1) { // MMU enabled? + if ((MMR3 & 16) == 0) { // offset is 18bit + physical_instruction &= 0x3ffff; + physical_data &= 0x3ffff; + } + } + + return { a, apf, physical_instruction, physical_data }; +} + +void bus::check_address(const bool trap_on_failure, const bool is_write, const memory_addresses_t & addr, const bool word_mode, const bool is_data, const int run_mode) +{ + // check for odd address access + if ((addr.virtual_address & 1) && word_mode == 0) { + if (is_write) + pages[run_mode][is_data][addr.apf].pdr |= 1 << 7; + + c->schedule_trap(004); // invalid access + + throw 5; + } + + if (!trap_on_failure) + return; + + // check access to page + if ((MMR0 & (1 << 9)) || c->get_34()) { + const int access_control = pages[run_mode][is_data][addr.apf].pdr & 7; + + // write + if (is_write && access_control != 6) { + c->schedule_trap(0250); // invalid address + + if (is_write) + pages[run_mode][is_data][addr.apf].pdr |= 1 << 7; + + if ((MMR0 & 0160000) == 0) { + MMR0 &= 017777; + MMR0 |= 1 << 13; // read-only + + MMR0 &= ~(3 << 5); + MMR0 |= run_mode << 5; // TODO: kernel-mode or user-mode when a trap occurs in user-mode? + + MMR0 &= ~14; // add current page + MMR0 |= addr.apf << 1; + } + + DOLOG(debug, true, "MMR0: %06o", MMR0); + + throw 1; + } + + // read + if (!is_write) { + if (access_control == 0 || access_control == 1 || access_control == 3 || access_control == 4 || access_control == 7) { + c->schedule_trap(0250); // invalid address + + if (is_write) + pages[run_mode][is_data][addr.apf].pdr |= 1 << 7; // TODO: D/I + + if ((MMR0 & 0160000) == 0) { + MMR0 &= 017777; + + if (access_control == 0 || access_control == 4) + MMR0 |= 1 << 15; // not resident + else + MMR0 |= 1 << 13; // read-only + + MMR0 &= ~(3 << 5); + MMR0 |= run_mode << 5; + + MMR0 &= ~14; // add current page + MMR0 |= addr.apf << 1; + } + + throw 2; + } + } + } + + // beyond physical range? + if ((is_data && addr.physical_data >= n_pages * 8192) || (!is_data && addr.physical_instruction >= n_pages * 8192)) { + if ((MMR0 & 0160000) == 0) { + MMR0 &= 017777; + MMR0 |= 1 << 15; // non-resident + + MMR0 &= ~14; // add current page + MMR0 |= addr.apf << 1; + + MMR0 &= ~(3 << 5); + MMR0 |= run_mode << 5; + } + + if (is_write) + pages[run_mode][is_data][addr.apf].pdr |= 1 << 7; // TODO: D/I + + c->schedule_trap(04); + + throw 3; + } + + // check if invalid access IN a page + uint16_t pdr_len = (pages[run_mode][is_data][addr.apf].pdr >> 8) & 127; + uint16_t pdr_cmp = (addr.virtual_address >> 6) & 127; + + bool direction = pages[run_mode][is_data][addr.apf].pdr & 8; // TODO: D/I + + if ((pdr_cmp > pdr_len && direction == false) || (pdr_cmp < pdr_len && direction == true)) { + c->schedule_trap(0250); // invalid access + + if ((MMR0 & 0160000) == 0) { + MMR0 &= 017777; + MMR0 |= 1 << 14; // length + + MMR0 &= ~14; // add current page + MMR0 |= addr.apf << 1; + + MMR0 &= ~(3 << 5); + MMR0 |= run_mode << 5; + } + + if (is_write) + pages[run_mode][0][addr.apf].pdr |= 1 << 7; // TODO: D/I + + throw 4; + } +} + uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, const bool trap_on_failure, const bool is_write, const bool peek_only, const bool is_data) { uint32_t m_offset = a; diff --git a/bus.h b/bus.h index a6dd170..4670622 100644 --- a/bus.h +++ b/bus.h @@ -57,8 +57,14 @@ class tty; typedef enum { d_space, i_space } d_i_space_t; -typedef struct -{ +typedef struct { + uint16_t virtual_address; + uint8_t apf; // active page field + uint32_t physical_instruction; + uint32_t physical_data; +} memory_addresses_t; + +typedef struct { uint16_t par, pdr; } page_t; @@ -140,4 +146,7 @@ public: uint16_t get_switch_register() const { return switch_register; } uint32_t calculate_physical_address(const int run_mode, const uint16_t a, const bool trap_on_failure, const bool is_write, const bool peek_only, const bool is_data); + + memory_addresses_t calculate_physical_address(const int run_mode, const uint16_t a); + void check_address(const bool trap_on_failure, const bool is_write, const memory_addresses_t & addr, const bool word_mode, const bool is_data, const int run_mode); }; From e643952a2fa49a8950146a24df85fad02e608cc7 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sat, 11 Mar 2023 21:54:04 +0100 Subject: [PATCH 07/33] log always is now always --- log.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/log.h b/log.h index 23139fe..db07ebf 100644 --- a/log.h +++ b/log.h @@ -14,6 +14,6 @@ void dolog(const log_level_t ll, const char *fmt, ...); #define DOLOG(ll, always, fmt, ...) do { \ extern log_level_t log_level_file, log_level_screen; \ \ - if (always && (ll >= log_level_file || ll >= log_level_screen)) \ + if (always || ll >= log_level_file || ll >= log_level_screen) \ dolog(ll, fmt, ##__VA_ARGS__); \ } while(0) From d68a5af55e2d19b0c1d780557b27647d1d28028c Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sat, 11 Mar 2023 21:54:18 +0100 Subject: [PATCH 08/33] writePhysical --- bus.cpp | 6 ++++++ bus.h | 2 ++ cpu.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- cpu.h | 4 +--- 4 files changed, 65 insertions(+), 6 deletions(-) diff --git a/bus.cpp b/bus.cpp index 668c9db..dcf7897 100644 --- a/bus.cpp +++ b/bus.cpp @@ -864,6 +864,12 @@ void bus::write(const uint16_t a, const bool word_mode, uint16_t value, const bo m->writeWord(m_offset, value); } +void bus::writePhysical(const uint32_t a, const uint16_t value) +{ + DOLOG(debug, true, "physicalWRITE %06o to %o", value, a); + m->writeWord(a, value); +} + uint16_t bus::readWord(const uint16_t a, const d_i_space_t s) { return read(a, false, false, false, s); diff --git a/bus.h b/bus.h index 4670622..9a07fef 100644 --- a/bus.h +++ b/bus.h @@ -130,6 +130,8 @@ public: void writeByte(const uint16_t a, const uint8_t value) { return write(a, true, value, false); } void writeWord(const uint16_t a, const uint16_t value); + void writePhysical(const uint32_t a, const uint16_t value); + void writeUnibusByte(const uint16_t a, const uint8_t value); uint16_t getMMR0() { return MMR0; } diff --git a/cpu.cpp b/cpu.cpp index 2356c3d..629b7d0 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -90,7 +90,6 @@ void cpu::reset() pc = 0; psw = 7 << 5; fpsr = 0; - runMode = false; init_interrupt_queue(); } @@ -449,6 +448,50 @@ uint16_t cpu::getGAMAddress(const uint8_t mode, const int reg, const bool word_m return -1; } +uint16_t cpu::getGAMAddressDI(const uint8_t mode, const int reg, const bool word_mode, const bool prev_mode) +{ + uint16_t next_word = 0; + uint16_t temp = 0; + + int set = getBitPSW(11); + + switch(mode) { + case 0: + // registers are also mapped in memory + return 0177700 + reg; + case 1: + return getRegister(reg, set, prev_mode); + case 2: + temp = getRegister(reg, set, prev_mode); + addRegister(reg, prev_mode, !word_mode || reg == 6 || reg == 7 ? 2 : 1); + return temp; + case 3: + printf("hier001\n"); + temp = b -> readWord(getRegister(reg, set, prev_mode)); + addRegister(reg, prev_mode, 2); + return temp; + case 4: + addRegister(reg, prev_mode, !word_mode || reg == 6 || reg == 7 ? -2 : -1); + return getRegister(reg, set, prev_mode); + case 5: + addRegister(reg, prev_mode, -2); + printf("hier002\n"); + return b -> readWord(getRegister(reg, set, prev_mode)); + case 6: + printf("hier003\n"); + next_word = b -> readWord(getPC()); + addRegister(7, prev_mode, 2); + return getRegister(reg, set, prev_mode) + next_word; + case 7: + printf("hier004\n"); + next_word = b -> readWord(getPC()); + addRegister(7, prev_mode, 2); + return b -> readWord(getRegister(reg, set, prev_mode) + next_word); + } + + return -1; +} + bool cpu::double_operand_instructions(const uint16_t instr) { const bool word_mode = !!(instr & 0x8000); @@ -1334,11 +1377,21 @@ bool cpu::single_operand_instructions(const uint16_t instr) if (dst_mode == 0) setRegister(dst_reg, true, v); else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, false, false); + uint16_t a = getGAMAddressDI(dst_mode, dst_reg, false, false); set_flags = a != ADDR_PSW; - b->write(a, false, v, true); // put in '13/12' address space + if (a >= 0160000) + b->write(a, false, v, true); // put in '13/12' address space + else { + auto phys = b->calculate_physical_address((getPSW() >> 12) & 3, a); + + DOLOG(debug, true, "MTPI/D %06o -> %o / %o", a, phys.physical_instruction, phys.physical_data); + + b->check_address(true, true, phys, false, word_mode, (getPSW() >> 12) & 3); + + b->writePhysical(word_mode ? phys.physical_data : phys.physical_instruction, v); + } } if (set_flags) { diff --git a/cpu.h b/cpu.h index 00ced1b..b5355f9 100644 --- a/cpu.h +++ b/cpu.h @@ -21,7 +21,6 @@ private: uint16_t fpsr { 0 }; uint16_t stackLimitRegister { 0 }; uint8_t scheduled_trap { 0 }; - bool runMode { false }; bool emulateMFPT { false }; uint64_t instruction_count { 0 }; uint64_t running_since { 0 }; @@ -43,6 +42,7 @@ private: void addToMMR1(const uint8_t mode, const uint8_t reg, const bool word_mode); uint16_t getGAMAddress(const uint8_t mode, const int reg, const bool word_mode, const bool MF_MT); + uint16_t getGAMAddressDI(const uint8_t mode, const int reg, const bool word_mode, const bool MF_MT); uint16_t getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode, const bool MF_MT); // returns false when flag registers should not be updated bool putGAM(const uint8_t mode, const int reg, const bool word_mode, const uint16_t value, const bool MF_FT); @@ -100,8 +100,6 @@ public: void setEmulateMFPT(const bool v) { emulateMFPT = v; } - bool getRunMode() { return runMode; } - bool getPSW_c() const; bool getPSW_v() const; bool getPSW_z() const; From a84d9a2a3a6bd6d59fc190e004b2cfb65deaaa0d Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sun, 12 Mar 2023 10:20:47 +0100 Subject: [PATCH 09/33] make log more readable --- debugger.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/debugger.cpp b/debugger.cpp index cdfe0fe..bc9ec4d 100644 --- a/debugger.cpp +++ b/debugger.cpp @@ -308,6 +308,9 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto *cnsl->get_running_flag() = true; while(*stop_event == EVENT_NONE) { + if (!single_step) + DOLOG(debug, false, "---"); + c->step_a(); if (trace_start_addr != -1 && c->getPC() == trace_start_addr) From 60210e4f8268f8829006629f643f39971e2d12be Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sun, 12 Mar 2023 13:19:54 +0100 Subject: [PATCH 10/33] Merge fix for 2fd1da58bbd95855528950bd1e0b7dbb07b789a8 The fault in that merge caused two sets of pc/psw to be pushed on the stack. --- cpu.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/cpu.cpp b/cpu.cpp index 629b7d0..0950aff 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -1778,21 +1778,6 @@ void cpu::trap(uint16_t vector, const int new_ipl, const bool is_interrupt) setPSW(before_psw, false); } } - - setPC(b->readWord(vector + 0, d_space)); - - if (!is_interrupt) - b->setMMR0Bit(12); // it's a trap - - // switch to kernel mode & update 'previous mode' - uint16_t new_psw = b->readWord(vector + 2, d_space) & 0147777; // mask off old 'previous mode' - if (new_ipl != -1) - new_psw = (new_psw & ~0xe0) | (new_ipl << 5); - new_psw |= (before_psw >> 2) & 030000; // apply new 'previous mode' - setPSW(new_psw, false); - - pushStack(before_psw); - pushStack(before_pc); } cpu::operand_parameters cpu::addressing_to_string(const uint8_t mode_register, const uint16_t pc, const bool word_mode) const From 08d8c75d589fee87a11350d2d08a5837c539a703 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sun, 12 Mar 2023 22:32:53 +0100 Subject: [PATCH 11/33] - readPhysical - initialize psw to 0 to match pypdp (for diff) - SUB instruction V-flag may have been incorrect - MFPI/MTPI flags - MFPI readPhysical - bootloader from pypdp (for diff) --- bus.cpp | 26 ++++++++++++++++++++++++-- bus.h | 1 + cpu.cpp | 46 +++++++++++++++++++++++++++++++++++++--------- cpu.h | 2 ++ debugger.cpp | 11 +++++++++++ loaders.cpp | 43 ++++++++++++++++++++++++++++++++++++++----- log.cpp | 2 +- 7 files changed, 114 insertions(+), 17 deletions(-) diff --git a/bus.cpp b/bus.cpp index dcf7897..2f96e8c 100644 --- a/bus.cpp +++ b/bus.cpp @@ -17,7 +17,7 @@ // see also https://github.com/espressif/esp-idf/issues/1934 constexpr int n_pages = 12; #else -constexpr int n_pages = 16; +constexpr int n_pages = 32; #endif constexpr uint16_t di_ena_mask[4] = { 4, 2, 0, 1 }; @@ -867,7 +867,29 @@ void bus::write(const uint16_t a, const bool word_mode, uint16_t value, const bo void bus::writePhysical(const uint32_t a, const uint16_t value) { DOLOG(debug, true, "physicalWRITE %06o to %o", value, a); - m->writeWord(a, value); + + if (a >= n_pages * 8192) { + DOLOG(debug, true, "physicalWRITE to %o: trap 004", a); + c->schedule_trap(004); + } + else { + m->writeWord(a, value); + } +} + +uint16_t bus::readPhysical(const uint32_t a) +{ + if (a >= n_pages * 8192) { + DOLOG(debug, true, "physicalREAD from %o: trap 004", a); + c->schedule_trap(004); + + return 0; + } + else { + uint16_t value = m->readWord(a); + DOLOG(debug, true, "physicalREAD %06o from %o", value, a); + return value; + } } uint16_t bus::readWord(const uint16_t a, const d_i_space_t s) diff --git a/bus.h b/bus.h index 9a07fef..bfb0bbc 100644 --- a/bus.h +++ b/bus.h @@ -130,6 +130,7 @@ public: void writeByte(const uint16_t a, const uint8_t value) { return write(a, true, value, false); } void writeWord(const uint16_t a, const uint16_t value); + uint16_t readPhysical(const uint32_t a); void writePhysical(const uint32_t a, const uint16_t value); void writeUnibusByte(const uint16_t a, const uint8_t value); diff --git a/cpu.cpp b/cpu.cpp index 0950aff..7ccc82a 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -10,6 +10,8 @@ #include "log.h" #include "utils.h" +uint16_t oldpc = 0; + #define SIGN(x, wm) ((wm) ? (x) & 0x80 : (x) & 0x8000) #define IS_0(x, wm) ((wm) ? ((x) & 0xff) == 0 : (x) == 0) @@ -88,7 +90,7 @@ void cpu::reset() memset(regs0_5, 0x00, sizeof regs0_5); memset(sp, 0x00, sizeof sp); pc = 0; - psw = 7 << 5; + psw = 0; // 7 << 5; fpsr = 0; init_interrupt_queue(); } @@ -605,7 +607,8 @@ bool cpu::double_operand_instructions(const uint16_t instr) result = (dst_value - ssrc_value) & 0xffff; if (set_flags) { - setPSW_v(sign(ssrc_value) != sign(dst_value) && sign(ssrc_value) == sign(result)); + //setPSW_v(sign(ssrc_value) != sign(dst_value) && sign(ssrc_value) == sign(result)); + setPSW_v(((ssrc_value ^ dst_value) & 0x8000) && !((dst_value ^ result) & 0x8000)); setPSW_c(uint16_t(dst_value) < uint16_t(ssrc_value)); } } @@ -1346,14 +1349,27 @@ bool cpu::single_operand_instructions(const uint16_t instr) set_flags = a != ADDR_PSW; - // read from previous space - v = b -> read(a, false, true); + if (a >= 0160000) { + // read from previous space + v = b -> read(a, false, true); + } + else { + auto phys = b->calculate_physical_address((getPSW() >> 12) & 3, a); + + //b->check_address(true, true, phys, false, word_mode, (getPSW() >> 12) & 3); + + extern FILE *lfh; + fflush(lfh); + + v = b->readPhysical(word_mode ? phys.physical_data : phys.physical_instruction); + } } if (set_flags) { - setPSW_n(SIGN(v, false)); + setPSW_c(true); setPSW_z(v == 0); - setPSW_v(false); + setPSW_n(SIGN(v, false)); + // deze niet? setPSW_v(false); } // put on current stack @@ -1388,16 +1404,27 @@ bool cpu::single_operand_instructions(const uint16_t instr) DOLOG(debug, true, "MTPI/D %06o -> %o / %o", a, phys.physical_instruction, phys.physical_data); - b->check_address(true, true, phys, false, word_mode, (getPSW() >> 12) & 3); +// FILE *fh = fopen("og2-kek.dat", "a+"); +// fprintf(fh, "%lu %06o MTPI %06o: %06o\n", mtpi_count, oldpc, a, v); +// fclose(fh); + DOLOG(debug, true, "%lu %06o MTPI %06o: %06o", mtpi_count, oldpc, a, v); + + mtpi_count++; + + //b->check_address(true, true, phys, false, word_mode, (getPSW() >> 12) & 3); + + extern FILE *lfh; + fflush(lfh); b->writePhysical(word_mode ? phys.physical_data : phys.physical_instruction, v); } } if (set_flags) { - setPSW_n(SIGN(v, false)); + setPSW_c(true); setPSW_z(v == 0); - setPSW_v(false); + setPSW_n(SIGN(v, false)); + // deze niet? setPSW_v(false); } break; @@ -2281,6 +2308,7 @@ void cpu::step_b() instruction_count++; uint16_t temp_pc = getPC(); + oldpc = temp_pc; if ((b->getMMR0() & 0160000) == 0) b->setMMR2(temp_pc); diff --git a/cpu.h b/cpu.h index b5355f9..ec10c89 100644 --- a/cpu.h +++ b/cpu.h @@ -26,6 +26,8 @@ private: uint64_t running_since { 0 }; bool mode11_70 { true }; + uint64_t mtpi_count { 0 }; + // level, vector std::map > queued_interrupts; std::mutex qi_lock; diff --git a/debugger.cpp b/debugger.cpp index bc9ec4d..cba1882 100644 --- a/debugger.cpp +++ b/debugger.cpp @@ -49,6 +49,17 @@ int disassemble(cpu *const c, console *const cnsl, const int pc, const bool inst instruction.c_str(), MMR0.c_str(), MMR2.c_str() ); + { + std::string temp = format("R0: %s, R1: %s, R2: %s, R3: %s, R4: %s, R5: %s, SP: %s, PC: %06o, PSW: %s, instr: %s", + registers[0].c_str(), registers[1].c_str(), registers[2].c_str(), registers[3].c_str(), registers[4].c_str(), registers[5].c_str(), registers[6].c_str(), pc, + psw.c_str(), + data["instruction-values"][0].c_str() + ); + + FILE *fh = fopen("compare.dat", "a+"); + fprintf(fh, "%s\n", temp.c_str()); + fclose(fh); + } if (cnsl) cnsl->debug(result); diff --git a/loaders.cpp b/loaders.cpp index e6f566b..01079ba 100644 --- a/loaders.cpp +++ b/loaders.cpp @@ -26,11 +26,13 @@ void setBootLoader(bus *const b, const bootloader_t which) cpu *const c = b -> getCpu(); uint16_t offset = 0; + uint16_t start = 0; const uint16_t *bl = nullptr; int size = 0; if (which == BL_RK05) { - offset = 01000; + /* + start = offset = 01000; static uint16_t rk05_code[] = { 0012700, @@ -43,13 +45,44 @@ void setBootLoader(bus *const b, const bootloader_t which) 0100376, 0005007 }; + */ + + // from https://github.com/amakukha/PyPDP11.git + offset = 02000; + start = 02002; + + static uint16_t rk05_code[] = { + 0042113, // "KD" + 0012706, 02000, // MOV #boot_start, SP + 0012700, 0000000, // MOV #unit, R0 ; unit number + 0010003, // MOV R0, R3 + 0000303, // SWAB R3 + 0006303, // ASL R3 + 0006303, // ASL R3 + 0006303, // ASL R3 + 0006303, // ASL R3 + 0006303, // ASL R3 + 0012701, 0177412, // MOV #RKDA, R1 ; csr + 0010311, // MOV R3, (R1) ; load da + 0005041, // CLR -(R1) ; clear ba + 0012741, 0177000, // MOV #-256.*2, -(R1) ; load wc + 0012741, 0000005, // MOV #READ+GO, -(R1) ; read & go + 0005002, // CLR R2 + 0005003, // CLR R3 + 0012704, 02020, // MOV #START+20, R4 + 0005005, // CLR R5 + 0105711, // TSTB (R1) + 0100376, // BPL .-2 + 0105011, // CLRB (R1) + 0005007 // CLR PC + }; bl = rk05_code; - size = 9; + size = sizeof(rk05_code)/sizeof(rk05_code[0]); } else if (which == BL_RL02) { - offset = 01000; + start = offset = 01000; /* from https://www.pdp-11.nl/peripherals/disk/rl-info.html static uint16_t rl02_code[] = { @@ -93,7 +126,7 @@ void setBootLoader(bus *const b, const bootloader_t which) 0005007, }; - size = 10; + size = sizeof(rl02_code)/sizeof(rl02_code[0]); bl = rl02_code; } @@ -101,7 +134,7 @@ void setBootLoader(bus *const b, const bootloader_t which) for(int i=0; i writeWord(offset + i * 2, bl[i]); - c -> setRegister(7, offset); + c -> setRegister(7, start); } uint16_t loadTape(bus *const b, const std::string & file) diff --git a/log.cpp b/log.cpp index e277e41..c4e375a 100644 --- a/log.cpp +++ b/log.cpp @@ -13,7 +13,7 @@ static const char *logfile = strdup("/tmp/myip.log"); log_level_t log_level_file = warning; log_level_t log_level_screen = warning; -static FILE *lfh = nullptr; +FILE *lfh = nullptr; static int lf_uid = -1; static int lf_gid = -1; From 4618c86ffab61e7dc6dc416baf73397411a3e65c Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Mon, 13 Mar 2023 10:10:13 +0100 Subject: [PATCH 12/33] Revert "RTI/RTT shall not change the PSW in user/supervisor mode" This reverts commit 31edf022cc0685bb6f9003ffaecd52dadd1b02ac. Seems to break at least XXDP EKBAD0.BIC --- cpu.cpp | 30 +++++++++++------------------- cpu.h | 2 +- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/cpu.cpp b/cpu.cpp index 7ccc82a..ef72593 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -247,15 +247,17 @@ int cpu::getPSW_spl() const return (psw >> 5) & 7; } -void cpu::setPSW(uint16_t v, const bool limited) +void cpu::setPSW(const uint16_t v, const bool limited) { if (limited) { - v &= 0174037; + psw |= v & 0174000; // current & previous mode can only be increased, 11 can only be set - v |= psw & 0174340; + psw &= 0174000; // retain upper 5 bit + psw |= v & ~0174000; + } + else { + psw = v; } - - psw = v; } bool cpu::check_queued_interrupts() @@ -1628,15 +1630,10 @@ bool cpu::misc_operations(const uint16_t instr) case 0b0000000000000001: // WAIT return true; - case 0b0000000000000010: { // RTI + case 0b0000000000000010: // RTI setPC(popStack()); - - uint16_t replacement_psw = popStack(); - - setPSW(replacement_psw, true); - + setPSW(popStack(), !!((getPSW() >> 12) & 3)); return true; - } case 0b0000000000000011: // BPT trap(014); @@ -1646,15 +1643,10 @@ bool cpu::misc_operations(const uint16_t instr) trap(020); return true; - case 0b0000000000000110: { // RTT + case 0b0000000000000110: // RTT setPC(popStack()); - - uint16_t replacement_psw = popStack(); - - setPSW(replacement_psw, true); - + setPSW(popStack(), !!((getPSW() >> 12) & 3)); return true; - } case 0b0000000000000111: // MFPT if (emulateMFPT) diff --git a/cpu.h b/cpu.h index ec10c89..01508df 100644 --- a/cpu.h +++ b/cpu.h @@ -117,7 +117,7 @@ public: void setBitPSW(const int bit, const bool v); uint16_t getPSW() const { return psw; } - void setPSW(uint16_t v, const bool limited); + void setPSW(const uint16_t v, const bool limited); uint16_t getStackLimitRegister() { return stackLimitRegister; } void setStackLimitRegister(const uint16_t v) { stackLimitRegister = v; } From d7ca61715591f0c8205e9c0e439782cfa6dd20a5 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Mon, 13 Mar 2023 12:25:24 +0100 Subject: [PATCH 13/33] assert --- bus.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bus.cpp b/bus.cpp index 2f96e8c..03113c2 100644 --- a/bus.cpp +++ b/bus.cpp @@ -617,6 +617,8 @@ void bus::write_pdr(const uint32_t a, const int run_mode, const uint16_t value, int page = (a >> 1) & 7; if (word_mode) { + assert(a != 0 || value < 256); + a & 1 ? (pages[run_mode][is_d][page].pdr &= 0xff, pages[run_mode][is_d][page].pdr |= value << 8) : (pages[run_mode][is_d][page].pdr &= 0xff00, pages[run_mode][is_d][page].pdr |= value); } From 050b0f7ea59cddf3a90dc7bc2df96c55fac7b930 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Mon, 13 Mar 2023 13:33:57 +0100 Subject: [PATCH 14/33] clean-up --- cpu.cpp | 48 +----------------------------------------------- cpu.h | 1 - 2 files changed, 1 insertion(+), 48 deletions(-) diff --git a/cpu.cpp b/cpu.cpp index ef72593..fe3b1e0 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -452,50 +452,6 @@ uint16_t cpu::getGAMAddress(const uint8_t mode, const int reg, const bool word_m return -1; } -uint16_t cpu::getGAMAddressDI(const uint8_t mode, const int reg, const bool word_mode, const bool prev_mode) -{ - uint16_t next_word = 0; - uint16_t temp = 0; - - int set = getBitPSW(11); - - switch(mode) { - case 0: - // registers are also mapped in memory - return 0177700 + reg; - case 1: - return getRegister(reg, set, prev_mode); - case 2: - temp = getRegister(reg, set, prev_mode); - addRegister(reg, prev_mode, !word_mode || reg == 6 || reg == 7 ? 2 : 1); - return temp; - case 3: - printf("hier001\n"); - temp = b -> readWord(getRegister(reg, set, prev_mode)); - addRegister(reg, prev_mode, 2); - return temp; - case 4: - addRegister(reg, prev_mode, !word_mode || reg == 6 || reg == 7 ? -2 : -1); - return getRegister(reg, set, prev_mode); - case 5: - addRegister(reg, prev_mode, -2); - printf("hier002\n"); - return b -> readWord(getRegister(reg, set, prev_mode)); - case 6: - printf("hier003\n"); - next_word = b -> readWord(getPC()); - addRegister(7, prev_mode, 2); - return getRegister(reg, set, prev_mode) + next_word; - case 7: - printf("hier004\n"); - next_word = b -> readWord(getPC()); - addRegister(7, prev_mode, 2); - return b -> readWord(getRegister(reg, set, prev_mode) + next_word); - } - - return -1; -} - bool cpu::double_operand_instructions(const uint16_t instr) { const bool word_mode = !!(instr & 0x8000); @@ -1335,7 +1291,6 @@ bool cpu::single_operand_instructions(const uint16_t instr) case 0b00110101: { // MFPD/MFPI // always words: word_mode-bit is to select between MFPI and MFPD - // NOTE: this code does not work for D/I split setups! TODO if ((b->getMMR0() & 0160000) == 0) b->addToMMR1(-2, 6); @@ -1382,7 +1337,6 @@ bool cpu::single_operand_instructions(const uint16_t instr) case 0b00110110: { // MTPI/MTPD // always words: word_mode-bit is to select between MTPI and MTPD - // NOTE: this code does not work for D/I split setups! TODO if ((b->getMMR0() & 0160000) == 0) b->addToMMR1(2, 6); @@ -1395,7 +1349,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) if (dst_mode == 0) setRegister(dst_reg, true, v); else { - uint16_t a = getGAMAddressDI(dst_mode, dst_reg, false, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, false, false); set_flags = a != ADDR_PSW; diff --git a/cpu.h b/cpu.h index 01508df..cb183de 100644 --- a/cpu.h +++ b/cpu.h @@ -44,7 +44,6 @@ private: void addToMMR1(const uint8_t mode, const uint8_t reg, const bool word_mode); uint16_t getGAMAddress(const uint8_t mode, const int reg, const bool word_mode, const bool MF_MT); - uint16_t getGAMAddressDI(const uint8_t mode, const int reg, const bool word_mode, const bool MF_MT); uint16_t getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode, const bool MF_MT); // returns false when flag registers should not be updated bool putGAM(const uint8_t mode, const int reg, const bool word_mode, const uint16_t value, const bool MF_FT); From d785a260d97806e0c7314aea2890d25dbd912fc0 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Mon, 13 Mar 2023 15:46:41 +0100 Subject: [PATCH 15/33] close logfile at exit --- log.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/log.cpp b/log.cpp index c4e375a..0ad9099 100644 --- a/log.cpp +++ b/log.cpp @@ -35,6 +35,8 @@ void setlog(const char *lf, const log_level_t ll_file, const log_level_t ll_scre log_level_file = ll_file; log_level_screen = ll_screen; + + atexit(closelog); } void setloguid(const int uid, const int gid) @@ -45,9 +47,11 @@ void setloguid(const int uid, const int gid) void closelog() { - fclose(lfh); + if (lfh) { + fclose(lfh); - lfh = nullptr; + lfh = nullptr; + } } void dolog(const log_level_t ll, const char *fmt, ...) From 85680260b07bb7b6daee84e2a0e3348437c7d70c Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Fri, 17 Mar 2023 19:27:17 +0100 Subject: [PATCH 16/33] needed to update neopixel library --- ESP32/platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ESP32/platformio.ini b/ESP32/platformio.ini index c05e4b0..e7d8b97 100644 --- a/ESP32/platformio.ini +++ b/ESP32/platformio.ini @@ -11,7 +11,7 @@ framework = arduino monitor_speed = 115200 upload_speed = 1000000 lib_deps = greiman/SdFat@^2.1.2 - adafruit/Adafruit NeoPixel@^1.10.4 + adafruit/Adafruit NeoPixel build_flags = -std=gnu++17 -Ofast -DESP32=1 -ggdb3 -D_GLIBCXX_USE_C99 build_unflags = -std=gnu++11 -Os From 5de6b16cee1e271d71b177dce528f2963069f774 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Fri, 17 Mar 2023 19:38:54 +0100 Subject: [PATCH 17/33] ifdef'd code that would crash the ESP32 --- debugger.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debugger.cpp b/debugger.cpp index cba1882..06d1d22 100644 --- a/debugger.cpp +++ b/debugger.cpp @@ -49,6 +49,7 @@ int disassemble(cpu *const c, console *const cnsl, const int pc, const bool inst instruction.c_str(), MMR0.c_str(), MMR2.c_str() ); +#if !defined(ESP32) { std::string temp = format("R0: %s, R1: %s, R2: %s, R3: %s, R4: %s, R5: %s, SP: %s, PC: %06o, PSW: %s, instr: %s", registers[0].c_str(), registers[1].c_str(), registers[2].c_str(), registers[3].c_str(), registers[4].c_str(), registers[5].c_str(), registers[6].c_str(), pc, @@ -60,6 +61,7 @@ int disassemble(cpu *const c, console *const cnsl, const int pc, const bool inst fprintf(fh, "%s\n", temp.c_str()); fclose(fh); } +#endif if (cnsl) cnsl->debug(result); From e9284e1914b083f8b999f79690d20223d848e8b0 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Fri, 17 Mar 2023 21:17:08 +0100 Subject: [PATCH 18/33] copy/paste fix --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 8f3c283..a40ce57 100644 --- a/main.cpp +++ b/main.cpp @@ -44,7 +44,7 @@ void help() printf("-h this help\n"); printf("-T t.bin load file as a binary tape file (like simh \"load\" command)\n"); printf("-R d.rk load file as a RK05 disk device\n"); - printf("-r d.rk load file as a RL02 disk device\n"); + printf("-r d.rl load file as a RL02 disk device\n"); printf("-p 123 set CPU start pointer to decimal(!) value\n"); printf("-b x enable bootloader (build-in), parameter must be \"rk05\" or \"rl02\"\n"); printf("-n ncurses UI\n"); From 0dda33c754134dad33a2b348dd657e4f958b7fc9 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Fri, 17 Mar 2023 21:17:16 +0100 Subject: [PATCH 19/33] code that would crash ESP32 --- log.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/log.cpp b/log.cpp index 0ad9099..f7e65a5 100644 --- a/log.cpp +++ b/log.cpp @@ -60,11 +60,11 @@ void dolog(const log_level_t ll, const char *fmt, ...) return; if (!lfh) { +#if !defined(ESP32) lfh = fopen(logfile, "a+"); if (!lfh) error_exit(true, "Cannot access log-file %s", logfile); -#if !defined(ESP32) if (lf_uid != -1 && fchown(fileno(lfh), lf_uid, lf_gid) == -1) error_exit(true, "Cannot change logfile (%s) ownership", logfile); @@ -95,8 +95,10 @@ void dolog(const log_level_t ll, const char *fmt, ...) (void)vasprintf(&str, fmt, ap); va_end(ap); +#if !defined(ESP32) if (ll >= log_level_file) fprintf(lfh, "%s%s\n", ts_str, str); +#endif if (ll >= log_level_screen) printf("%s%s\r\n", ts_str, str); From 2c98fa23f5e06aa53c7754de0d9cd880c716378b Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Fri, 17 Mar 2023 21:50:04 +0100 Subject: [PATCH 20/33] according to FKTCA0.BIC, MTPI should not set c and set v to 0 --- cpu.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cpu.cpp b/cpu.cpp index fe3b1e0..d4e8605 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -1377,10 +1377,9 @@ bool cpu::single_operand_instructions(const uint16_t instr) } if (set_flags) { - setPSW_c(true); setPSW_z(v == 0); setPSW_n(SIGN(v, false)); - // deze niet? setPSW_v(false); + setPSW_v(false); } break; From b50b75f1a05cf59635121eba144b925fa00ba2c8 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Fri, 17 Mar 2023 21:52:52 +0100 Subject: [PATCH 21/33] according to FKTCA0.BIC, MFPI should not set c and set v to 0 --- cpu.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cpu.cpp b/cpu.cpp index d4e8605..0ee890a 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -1323,10 +1323,9 @@ bool cpu::single_operand_instructions(const uint16_t instr) } if (set_flags) { - setPSW_c(true); setPSW_z(v == 0); setPSW_n(SIGN(v, false)); - // deze niet? setPSW_v(false); + setPSW_v(false); } // put on current stack From 62205273aa09c19ef07ec7411f8db4d97e3f9451 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Fri, 17 Mar 2023 22:47:37 +0100 Subject: [PATCH 22/33] setpc (debugger) --- debugger.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/debugger.cpp b/debugger.cpp index 06d1d22..3779317 100644 --- a/debugger.cpp +++ b/debugger.cpp @@ -149,8 +149,11 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto if (parts.empty()) continue; - if (cmd == "go") + if (cmd == "go") { single_step = false; + + *stop_event = EVENT_NONE; + } else if (parts[0] == "single" || parts[0] == "s") { single_step = true; @@ -204,6 +207,19 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto continue; } + else if (parts[0] == "setpc") { + if (parts.size() == 2) { + uint16_t new_pc = std::stoi(parts.at(1), nullptr, 8); + c->setPC(new_pc); + + cnsl->put_string_lf(format("Set PC to %06o", new_pc)); + } + else { + cnsl->put_string_lf("setpc requires an (octal address as) parameter"); + } + + continue; + } else if (parts[0] == "trace" || parts[0] == "t") { tracing = !tracing; @@ -308,6 +324,7 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto cnsl->put_string_lf("trace/t - toggle tracing"); cnsl->put_string_lf("strace - start tracing from address - invoke without address to disable"); cnsl->put_string_lf("mmudump - dump MMU settings (PARs/PDRs)"); + cnsl->put_string_lf("setpc - set PC to value"); continue; } From 38369348c3362e63b9bb30e07241483c0e23334c Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sat, 18 Mar 2023 00:56:03 +0100 Subject: [PATCH 23/33] debugger: setmem --- debugger.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/debugger.cpp b/debugger.cpp index 3779317..f8f7827 100644 --- a/debugger.cpp +++ b/debugger.cpp @@ -220,6 +220,23 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto continue; } + else if (parts[0] == "setmem") { + auto a_it = kv.find("a"); + auto v_it = kv.find("v"); + + if (a_it == kv.end() || v_it == kv.end()) + cnsl->put_string_lf("setmem: parameter missing?"); + else { + uint16_t a = std::stoi(a_it->second, nullptr, 8); + uint8_t v = std::stoi(v_it->second, nullptr, 8); + + c->getBus()->writeByte(a, v); + + cnsl->put_string_lf(format("Set %06o to %03o", a, v)); + } + + continue; + } else if (parts[0] == "trace" || parts[0] == "t") { tracing = !tracing; @@ -325,6 +342,7 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto cnsl->put_string_lf("strace - start tracing from address - invoke without address to disable"); cnsl->put_string_lf("mmudump - dump MMU settings (PARs/PDRs)"); cnsl->put_string_lf("setpc - set PC to value"); + cnsl->put_string_lf("setmem - set memory (a=) to value (v=), both in octal, one byte"); continue; } From 3c81b4f9e86138b806a01e2f89d9b75e6bc895a6 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sat, 18 Mar 2023 01:06:37 +0100 Subject: [PATCH 24/33] single step: clear stop_event --- debugger.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/debugger.cpp b/debugger.cpp index f8f7827..2b17e53 100644 --- a/debugger.cpp +++ b/debugger.cpp @@ -49,7 +49,7 @@ int disassemble(cpu *const c, console *const cnsl, const int pc, const bool inst instruction.c_str(), MMR0.c_str(), MMR2.c_str() ); -#if !defined(ESP32) +#if defined(COMPARE_OUTPUT) { std::string temp = format("R0: %s, R1: %s, R2: %s, R3: %s, R4: %s, R5: %s, SP: %s, PC: %06o, PSW: %s, instr: %s", registers[0].c_str(), registers[1].c_str(), registers[2].c_str(), registers[3].c_str(), registers[4].c_str(), registers[5].c_str(), registers[6].c_str(), pc, @@ -161,6 +161,8 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto n_single_step = atoi(parts[1].c_str()); else n_single_step = 1; + + *stop_event = EVENT_NONE; } else if ((parts[0] == "sbp" || parts[0] == "cbp") && parts.size() == 2){ uint16_t pc = std::stoi(parts[1].c_str(), nullptr, 8); From 89435e48d6b22aa998f83b832f2fe5197aed6a02 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sat, 18 Mar 2023 12:28:43 +0100 Subject: [PATCH 25/33] getGAMAddress: reg 6/7 need special handling --- cpu.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/cpu.cpp b/cpu.cpp index 0ee890a..84492b2 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -418,11 +418,21 @@ uint16_t cpu::getGAMAddress(const uint8_t mode, const int reg, const bool word_m uint16_t temp = 0; int set = getBitPSW(11); + int run_mode = psw >> 14; + + constexpr uint16_t sp_pointers[] = { ADDR_KERNEL_SP, ADDR_SV_SP, 0xffff, ADDR_USER_SP }; switch(mode) { case 0: - // registers are also mapped in memory - return 0177700 + reg; + printf("REG: %d\r\n", reg); + // registers are also mapped in memory + if (reg < 6) + return (run_mode == 3 ? ADDR_USER_R : ADDR_KERNEL_R) + reg; + + if (reg == 7) + return ADDR_PC; + + return sp_pointers[run_mode]; case 1: return getRegister(reg, set, prev_mode); case 2: From b88efb312f62f4c8046b8e9cb055ed48e53711f2 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sat, 18 Mar 2023 12:32:58 +0100 Subject: [PATCH 26/33] getGAMAddress does not require the prev_mode flag --- cpu.cpp | 70 ++++++++++++++++++++++++++++----------------------------- cpu.h | 2 +- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/cpu.cpp b/cpu.cpp index 84492b2..b7cc4af 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -412,7 +412,7 @@ bool cpu::putGAM(const uint8_t mode, const int reg, const bool word_mode, const return addr == -1 || addr != ADDR_PSW; } -uint16_t cpu::getGAMAddress(const uint8_t mode, const int reg, const bool word_mode, const bool prev_mode) +uint16_t cpu::getGAMAddress(const uint8_t mode, const int reg, const bool word_mode) { uint16_t next_word = 0; uint16_t temp = 0; @@ -434,29 +434,29 @@ uint16_t cpu::getGAMAddress(const uint8_t mode, const int reg, const bool word_m return sp_pointers[run_mode]; case 1: - return getRegister(reg, set, prev_mode); + return getRegister(reg, set, false); case 2: - temp = getRegister(reg, set, prev_mode); - addRegister(reg, prev_mode, !word_mode || reg == 6 || reg == 7 ? 2 : 1); + temp = getRegister(reg, set, false); + addRegister(reg, false, !word_mode || reg == 6 || reg == 7 ? 2 : 1); return temp; case 3: - temp = b -> readWord(getRegister(reg, set, prev_mode)); - addRegister(reg, prev_mode, 2); + temp = b -> readWord(getRegister(reg, set, false)); + addRegister(reg, false, 2); return temp; case 4: - addRegister(reg, prev_mode, !word_mode || reg == 6 || reg == 7 ? -2 : -1); - return getRegister(reg, set, prev_mode); + addRegister(reg, false, !word_mode || reg == 6 || reg == 7 ? -2 : -1); + return getRegister(reg, set, false); case 5: - addRegister(reg, prev_mode, -2); - return b -> readWord(getRegister(reg, set, prev_mode)); + addRegister(reg, false, -2); + return b -> readWord(getRegister(reg, set, false)); case 6: next_word = b -> readWord(getPC()); - addRegister(7, prev_mode, 2); - return getRegister(reg, set, prev_mode) + next_word; + addRegister(7, false, 2); + return getRegister(reg, set, false) + next_word; case 7: next_word = b -> readWord(getPC()); - addRegister(7, prev_mode, 2); - return b -> readWord(getRegister(reg, set, prev_mode) + next_word); + addRegister(7, false, 2); + return b -> readWord(getRegister(reg, set, false) + next_word); } return -1; @@ -535,7 +535,7 @@ bool cpu::double_operand_instructions(const uint16_t instr) } case 0b100: { // BIC/BICB Bit Clear Word/Byte - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); uint16_t result = b->read(a, word_mode, false) & ~src_value; @@ -549,7 +549,7 @@ bool cpu::double_operand_instructions(const uint16_t instr) } case 0b101: { // BIS/BISB Bit Set Word/Byte - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); uint16_t result = b->read(a, word_mode, false) | src_value; @@ -565,7 +565,7 @@ bool cpu::double_operand_instructions(const uint16_t instr) case 0b110: { // ADD/SUB Add/Subtract Word int16_t ssrc_value = getGAM(src_mode, src_reg, false, false); - uint16_t dst_addr = getGAMAddress(dst_mode, dst_reg, false, false); + uint16_t dst_addr = getGAMAddress(dst_mode, dst_reg, false); int16_t dst_value = b->readWord(dst_addr); int16_t result = 0; @@ -766,7 +766,7 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr) } case 4: { // XOR (word only) - uint16_t a = getGAMAddress(dst_mode, dst_reg, false, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, false); uint16_t vl = b->read(a, false, false) ^ getRegister(reg); bool set_flags = true; @@ -827,7 +827,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) setRegister(dst_reg, false, v); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); v = b->readWord(a); v = ((v & 0xff) << 8) | (v >> 8); @@ -859,7 +859,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) putGAM(dst_mode, dst_reg, false, r, false); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); set_flags = a != ADDR_PSW; @@ -893,7 +893,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) setRegister(dst_reg, false, v); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); uint16_t v = b -> read(a, word_mode, false); if (word_mode) @@ -930,7 +930,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) setRegister(dst_reg, false, v); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); uint16_t v = b -> read(a, word_mode, false); int32_t vl = (v + 1) & (word_mode ? 0xff : 0xffff); @@ -963,7 +963,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) setRegister(dst_reg, false, v); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); uint16_t v = b -> read(a, word_mode, false); int32_t vl = (v - 1) & (word_mode ? 0xff : 0xffff); @@ -997,7 +997,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) setRegister(dst_reg, false, v); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); uint16_t v = -b -> read(a, word_mode, false); b->write(a, word_mode, v, false); @@ -1033,7 +1033,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) setRegister(dst_reg, false, v); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); const uint16_t vo = b -> read(a, word_mode, false); bool org_c = getPSW_c(); uint16_t v = (vo + org_c) & (word_mode ? 0x00ff : 0xffff); @@ -1075,7 +1075,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) setRegister(dst_reg, false, v); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); const uint16_t vo = b -> read(a, word_mode, false); bool org_c = getPSW_c(); uint16_t v = (vo - org_c) & (word_mode ? 0xff : 0xffff); @@ -1132,7 +1132,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) setPSW_v(getPSW_c() ^ getPSW_n()); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); uint16_t t = b -> read(a, word_mode, false); bool new_carry = t & 1; @@ -1179,7 +1179,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) setPSW_v(getPSW_c() ^ getPSW_n()); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); uint16_t t = b -> read(a, word_mode, false); bool new_carry = false; @@ -1234,7 +1234,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) setPSW_v(getPSW_n() ^ getPSW_c()); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); uint16_t v = b -> read(a, word_mode, false); uint16_t add = word_mode ? v & 0xff00 : 0; @@ -1281,7 +1281,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) setRegister(dst_reg, false, v); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); uint16_t vl = b -> read(a, word_mode, false); uint16_t v = (vl << 1) & (word_mode ? 0xff : 0xffff); @@ -1312,7 +1312,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) v = getRegister(dst_reg, getBitPSW(11), true); else { // calculate address in current address space - uint16_t a = getGAMAddress(dst_mode, dst_reg, false, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, false); set_flags = a != ADDR_PSW; @@ -1358,7 +1358,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) if (dst_mode == 0) setRegister(dst_reg, true, v); else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, false, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, false); set_flags = a != ADDR_PSW; @@ -1426,7 +1426,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) } } else { // SXT - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false); + uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); int32_t vl = -getPSW_n(); @@ -1642,7 +1642,7 @@ bool cpu::misc_operations(const uint16_t instr) int dst_reg = instr & 7; bool word_mode = false; - setPC(getGAMAddress(dst_mode, dst_reg, word_mode, false)); + setPC(getGAMAddress(dst_mode, dst_reg, word_mode)); } return true; @@ -1650,7 +1650,7 @@ bool cpu::misc_operations(const uint16_t instr) if ((instr & 0b1111111000000000) == 0b0000100000000000) { // JSR int link_reg = (instr >> 6) & 7; - uint16_t dst_value = getGAMAddress((instr >> 3) & 7, instr & 7, false, false); + uint16_t dst_value = getGAMAddress((instr >> 3) & 7, instr & 7, false); // PUSH link pushStack(getRegister(link_reg)); diff --git a/cpu.h b/cpu.h index cb183de..30cf18d 100644 --- a/cpu.h +++ b/cpu.h @@ -43,7 +43,7 @@ private: uint16_t addRegister(const int nr, const bool prev_mode, const uint16_t value); void addToMMR1(const uint8_t mode, const uint8_t reg, const bool word_mode); - uint16_t getGAMAddress(const uint8_t mode, const int reg, const bool word_mode, const bool MF_MT); + uint16_t getGAMAddress(const uint8_t mode, const int reg, const bool word_mode); uint16_t getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode, const bool MF_MT); // returns false when flag registers should not be updated bool putGAM(const uint8_t mode, const int reg, const bool word_mode, const uint16_t value, const bool MF_FT); From 7245340c20c8f5ea6531707ae67a1c225a1a75e2 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sat, 18 Mar 2023 12:35:14 +0100 Subject: [PATCH 27/33] debug --- cpu.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/cpu.cpp b/cpu.cpp index b7cc4af..74033ff 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -424,7 +424,6 @@ uint16_t cpu::getGAMAddress(const uint8_t mode, const int reg, const bool word_m switch(mode) { case 0: - printf("REG: %d\r\n", reg); // registers are also mapped in memory if (reg < 6) return (run_mode == 3 ? ADDR_USER_R : ADDR_KERNEL_R) + reg; From 57c7a23bd53b26b97c62d9024bfb2ad4e954c691 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sat, 18 Mar 2023 12:50:14 +0100 Subject: [PATCH 28/33] setPSW_flags_nzv --- cpu.cpp | 69 ++++++++++++++++++++------------------------------------- cpu.h | 1 + 2 files changed, 25 insertions(+), 45 deletions(-) diff --git a/cpu.cpp b/cpu.cpp index 74033ff..9c6e951 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -260,6 +260,13 @@ void cpu::setPSW(const uint16_t v, const bool limited) } } +void cpu::setPSW_flags_nzv(const uint16_t value, const bool word_mode) +{ + setPSW_n(SIGN(value, word_mode)); + setPSW_z(IS_0(value, word_mode)); + setPSW_v(false); +} + bool cpu::check_queued_interrupts() { std::unique_lock lck(qi_lock); @@ -496,11 +503,8 @@ bool cpu::double_operand_instructions(const uint16_t instr) addToMMR1(dst_mode, dst_reg, word_mode); - if (set_flags) { - setPSW_n(SIGN(src_value, word_mode)); - setPSW_z(IS_0(src_value, word_mode)); - setPSW_v(false); - } + if (set_flags) + setPSW_flags_nzv(src_value, word_mode); return true; } @@ -526,9 +530,7 @@ bool cpu::double_operand_instructions(const uint16_t instr) uint16_t dst_value = getGAM(dst_mode, dst_reg, word_mode, false); uint16_t result = (dst_value & src_value) & (word_mode ? 0xff : 0xffff); - setPSW_n(SIGN(result, word_mode)); - setPSW_z(IS_0(result, word_mode)); - setPSW_v(false); + setPSW_flags_nzv(result, word_mode); return true; } @@ -538,11 +540,8 @@ bool cpu::double_operand_instructions(const uint16_t instr) uint16_t result = b->read(a, word_mode, false) & ~src_value; - if (put_result(a, dst_mode, dst_reg, word_mode, result)) { - setPSW_n(SIGN(result, word_mode)); - setPSW_z(IS_0(result, word_mode)); - setPSW_v(false); - } + if (put_result(a, dst_mode, dst_reg, word_mode, result)) + setPSW_flags_nzv(result, word_mode); return true; } @@ -552,11 +551,8 @@ bool cpu::double_operand_instructions(const uint16_t instr) uint16_t result = b->read(a, word_mode, false) | src_value; - if (put_result(a, dst_mode, dst_reg, word_mode, result)) { - setPSW_n(SIGN(result, word_mode)); - setPSW_z(IS_0(result, word_mode)); - setPSW_v(false); - } + if (put_result(a, dst_mode, dst_reg, word_mode, result)) + setPSW_flags_nzv(result, word_mode); return true; } @@ -777,11 +773,8 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr) set_flags = a != ADDR_PSW; } - if (set_flags) { - setPSW_n(vl & 0x8000); - setPSW_z(vl == 0); - setPSW_v(false); - } + if (set_flags) + setPSW_flags_nzv(vl, false); return true; } @@ -837,9 +830,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) } if (set_flags) { - setPSW_n(v & 0x80); - setPSW_z((v & 0xff) == 0); - setPSW_v(false); + setPSW_flags_nzv(v, true); setPSW_c(false); } } @@ -884,9 +875,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) else v ^= 0xffff; - setPSW_n(SIGN(v, word_mode)); - setPSW_z(IS_0(v, word_mode)); - setPSW_v(false); + setPSW_flags_nzv(v, word_mode); setPSW_c(true); setRegister(dst_reg, false, v); @@ -903,9 +892,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) bool set_flags = a != ADDR_PSW; if (set_flags) { - setPSW_n(SIGN(v, word_mode)); - setPSW_z(IS_0(v, word_mode)); - setPSW_v(false); + setPSW_flags_nzv(v, word_mode); setPSW_c(true); } @@ -1100,9 +1087,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) case 0b000101111: { // TST/TSTB uint16_t v = getGAM(dst_mode, dst_reg, word_mode, false); - setPSW_n(SIGN(v, word_mode)); - setPSW_z(IS_0(v, word_mode)); - setPSW_v(false); + setPSW_flags_nzv(v, word_mode); setPSW_c(false); break; @@ -1331,11 +1316,8 @@ bool cpu::single_operand_instructions(const uint16_t instr) } } - if (set_flags) { - setPSW_z(v == 0); - setPSW_n(SIGN(v, false)); - setPSW_v(false); - } + if (set_flags) + setPSW_flags_nzv(v, false); // put on current stack pushStack(v); @@ -1384,11 +1366,8 @@ bool cpu::single_operand_instructions(const uint16_t instr) } } - if (set_flags) { - setPSW_z(v == 0); - setPSW_n(SIGN(v, false)); - setPSW_v(false); - } + if (set_flags) + setPSW_flags_nzv(v, false); break; } diff --git a/cpu.h b/cpu.h index 30cf18d..7f0449e 100644 --- a/cpu.h +++ b/cpu.h @@ -114,6 +114,7 @@ public: void setPSW_n(const bool v); void setPSW_spl(const int v); void setBitPSW(const int bit, const bool v); + void setPSW_flags_nzv(const uint16_t value, const bool word_mode); uint16_t getPSW() const { return psw; } void setPSW(const uint16_t v, const bool limited); From be68ad23579a20f1fb8bafa63559d6274155e066 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sat, 18 Mar 2023 14:35:31 +0100 Subject: [PATCH 29/33] code cleanup: unify getGAM/getGAMAddress/putGAM (first step) --- cpu.cpp | 487 +++++++++++++++++++++++--------------------------------- cpu.h | 25 ++- 2 files changed, 218 insertions(+), 294 deletions(-) diff --git a/cpu.cpp b/cpu.cpp index 9c6e951..9e88b0b 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -153,17 +153,17 @@ void cpu::setRegisterLowByte(const int nr, const bool word_mode, const uint16_t } } -bool cpu::put_result(const uint16_t a, const uint8_t dst_mode, const uint8_t dst_reg, const bool word_mode, const uint16_t value) +bool cpu::put_result(const gam_rc_t & g, const uint16_t value) { - if (dst_mode == 0) { - setRegisterLowByte(dst_reg, word_mode, value); + if (g.addr.has_value() == false) { + setRegisterLowByte(g.reg, g.word_mode, value); return true; } - b->write(a, word_mode, value, false); + b->write(g.addr.value(), g.word_mode, value, false); - return a != ADDR_PSW; + return g.addr.value() != ADDR_PSW; } uint16_t cpu::addRegister(const int nr, const bool prev_mode, const uint16_t value) @@ -322,150 +322,84 @@ void cpu::addToMMR1(const uint8_t mode, const uint8_t reg, const bool word_mode) } // GAM = general addressing modes -uint16_t cpu::getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode, const bool prev_mode) +gam_rc_t cpu::getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode, const bool prev_mode, const bool read_value) { - uint16_t next_word = 0; - uint16_t temp = 0; + gam_rc_t g { false, false, false, { }, 0 }; + g.word_mode = word_mode; // word/byte + g.prev_mode = prev_mode; // run mode + g.set = getBitPSW(11); - int set = getBitPSW(11); + uint16_t next_word = 0; switch(mode) { case 0: // 000 - return getRegister(reg, set, prev_mode) & (word_mode ? 0xff : 0xffff); + g.reg = reg; + g.value = getRegister(reg, g.set, prev_mode) & (word_mode ? 0xff : 0xffff); + break; case 1: - return b -> read(getRegister(reg, set, prev_mode), word_mode, prev_mode); + g.addr = getRegister(reg, g.set, prev_mode); + if (read_value) + g.value = b->read(g.addr.value(), word_mode, prev_mode); + break; case 2: - temp = b -> read(getRegister(reg, set, prev_mode), word_mode, prev_mode); + g.addr = getRegister(reg, g.set, prev_mode); + if (read_value) + g.value = b->read(g.addr.value(), word_mode, prev_mode); addRegister(reg, prev_mode, !word_mode || reg == 7 || reg == 6 ? 2 : 1); - return temp; + break; case 3: - temp = b -> read(b -> read(getRegister(reg, set, prev_mode), false, prev_mode), word_mode, prev_mode); + g.addr = b->read(getRegister(reg, g.set, prev_mode), false, prev_mode); + if (read_value) + g.value = b->read(g.addr.value(), word_mode, prev_mode); addRegister(reg, prev_mode, 2); - return temp; + break; case 4: addRegister(reg, prev_mode, !word_mode || reg == 7 || reg == 6 ? -2 : -1); - return b -> read(getRegister(reg, set, prev_mode), word_mode, prev_mode); - case 5: - addRegister(reg, prev_mode, -2); - return b -> read(b -> read(getRegister(reg, set, prev_mode), false, prev_mode), word_mode, prev_mode); - case 6: - next_word = b -> read(getPC(), false, prev_mode); - addRegister(7, prev_mode, + 2); - temp = b -> read(getRegister(reg, set, prev_mode) + next_word, word_mode, prev_mode); - return temp; - case 7: - next_word = b -> read(getPC(), false, prev_mode); - addRegister(7, prev_mode, + 2); - return b -> read(b -> read(getRegister(reg, set, prev_mode) + next_word, false, prev_mode), word_mode, prev_mode); - } - - return -1; -} - -bool cpu::putGAM(const uint8_t mode, const int reg, const bool word_mode, const uint16_t value, bool const prev_mode) -{ - uint16_t next_word = 0; - int addr = -1; - - int set = getBitPSW(11); - - uint16_t dummy = 0; - - switch(mode) { - case 0: - setRegister(reg, prev_mode, value); - break; - case 1: - addr = getRegister(reg, set, prev_mode); - b -> write(addr, word_mode, value, false); - break; - case 2: - addr = getRegister(reg, set, prev_mode); - b -> write(addr, word_mode, value, false); - addRegister(reg, prev_mode, !word_mode || reg == 7 || reg == 6 ? 2 : 1); - break; - case 3: - addr = b -> readWord(getRegister(reg, set, prev_mode)); - b -> write(addr, word_mode, value, false); - addRegister(reg, prev_mode, 2); - break; - case 4: - dummy = addRegister(reg, prev_mode, !word_mode || reg == 7 || reg == 6 ? -2 : -1); - b -> write(dummy, word_mode, value, false); + g.addr = getRegister(reg, g.set, prev_mode); + if (read_value) + g.value = b->read(g.addr.value(), word_mode, prev_mode); break; case 5: addRegister(reg, prev_mode, -2); - addr = b -> readWord(getRegister(reg, set, prev_mode)); - b -> write(addr, word_mode, value, false); + g.addr = b->read(getRegister(reg, g.set, prev_mode), false, prev_mode); + if (read_value) + g.value = b->read(g.addr.value(), word_mode, prev_mode); break; case 6: - next_word = b -> readWord(getPC()); - addRegister(7, prev_mode, 2); - addr = (getRegister(reg, set, prev_mode) + next_word) & 0xffff; - b -> write(addr, word_mode, value, false); + next_word = b -> read(getPC(), false, prev_mode); + addRegister(7, prev_mode, + 2); + g.addr = getRegister(reg, g.set, prev_mode) + next_word; + if (read_value) + g.value = b->read(g.addr.value(), word_mode, prev_mode); break; case 7: - next_word = b -> readWord(getPC()); - addRegister(7, prev_mode, 2); - addr = b -> readWord(getRegister(reg, set, prev_mode) + next_word); - b -> write(addr, word_mode, value, false); - break; - - default: - // error + next_word = b -> read(getPC(), false, prev_mode); + addRegister(7, prev_mode, + 2); + g.addr = b->read(getRegister(reg, g.set, prev_mode) + next_word, false, prev_mode); + if (read_value) + g.value = b->read(g.addr.value(), word_mode, prev_mode); break; } - return addr == -1 || addr != ADDR_PSW; + return g; } -uint16_t cpu::getGAMAddress(const uint8_t mode, const int reg, const bool word_mode) +bool cpu::putGAM(const gam_rc_t & g, const uint16_t value) { - uint16_t next_word = 0; - uint16_t temp = 0; + if (g.addr.has_value()) { + b->write(g.addr.value(), g.word_mode, value, g.prev_mode); - int set = getBitPSW(11); - int run_mode = psw >> 14; - - constexpr uint16_t sp_pointers[] = { ADDR_KERNEL_SP, ADDR_SV_SP, 0xffff, ADDR_USER_SP }; - - switch(mode) { - case 0: - // registers are also mapped in memory - if (reg < 6) - return (run_mode == 3 ? ADDR_USER_R : ADDR_KERNEL_R) + reg; - - if (reg == 7) - return ADDR_PC; - - return sp_pointers[run_mode]; - case 1: - return getRegister(reg, set, false); - case 2: - temp = getRegister(reg, set, false); - addRegister(reg, false, !word_mode || reg == 6 || reg == 7 ? 2 : 1); - return temp; - case 3: - temp = b -> readWord(getRegister(reg, set, false)); - addRegister(reg, false, 2); - return temp; - case 4: - addRegister(reg, false, !word_mode || reg == 6 || reg == 7 ? -2 : -1); - return getRegister(reg, set, false); - case 5: - addRegister(reg, false, -2); - return b -> readWord(getRegister(reg, set, false)); - case 6: - next_word = b -> readWord(getPC()); - addRegister(7, false, 2); - return getRegister(reg, set, false) + next_word; - case 7: - next_word = b -> readWord(getPC()); - addRegister(7, false, 2); - return b -> readWord(getRegister(reg, set, false) + next_word); + return g.addr.value() != ADDR_PSW; } - return -1; + setRegister(g.reg, g.set, g.prev_mode, value); + + return true; +} + +gam_rc_t cpu::getGAMAddress(const uint8_t mode, const int reg, const bool word_mode) +{ + return getGAM(mode, reg, word_mode, false, false); } bool cpu::double_operand_instructions(const uint16_t instr) @@ -484,7 +418,10 @@ bool cpu::double_operand_instructions(const uint16_t instr) const uint8_t src_mode = (src >> 3) & 7; const uint8_t src_reg = src & 7; - const uint16_t src_value = operation == 0b110 ? 0 : getGAM(src_mode, src_reg, word_mode, false); + gam_rc_t g_src { false, false, false, { }, 0 }; + + if (operation != 0b110) + g_src = getGAM(src_mode, src_reg, word_mode, false); const uint8_t dst = instr & 63; const uint8_t dst_mode = (dst >> 3) & 7; @@ -497,14 +434,17 @@ bool cpu::double_operand_instructions(const uint16_t instr) addToMMR1(src_mode, src_reg, word_mode); if (word_mode && dst_mode == 0) - setRegister(dst_reg, false, int8_t(src_value)); // int8_t: sign extension - else - set_flags = putGAM(dst_mode, dst_reg, word_mode, src_value, false); + setRegister(dst_reg, false, int8_t(g_src.value.value())); // int8_t: sign extension + else { + auto g_dst = getGAM(dst_mode, dst_reg, word_mode, false); + + set_flags = putGAM(g_dst, g_src.value.value()); + } addToMMR1(dst_mode, dst_reg, word_mode); if (set_flags) - setPSW_flags_nzv(src_value, word_mode); + setPSW_flags_nzv(g_src.value.value(), word_mode); return true; } @@ -512,23 +452,23 @@ bool cpu::double_operand_instructions(const uint16_t instr) case 0b010: { // CMP/CMPB Compare Word/Byte addToMMR1(src_mode, src_reg, word_mode); - uint16_t dst_value = getGAM(dst_mode, dst_reg, word_mode, false); + auto g_dst = getGAM(dst_mode, dst_reg, word_mode, false); - uint16_t temp = (src_value - dst_value) & (word_mode ? 0xff : 0xffff); + uint16_t temp = (g_src.value.value() - g_dst.value.value()) & (word_mode ? 0xff : 0xffff); addToMMR1(dst_mode, dst_reg, word_mode); setPSW_n(SIGN(temp, word_mode)); setPSW_z(IS_0(temp, word_mode)); - setPSW_v(SIGN((src_value ^ dst_value) & (~dst_value ^ temp), word_mode)); - setPSW_c(src_value < dst_value); + setPSW_v(SIGN((g_src.value.value() ^ g_dst.value.value()) & (~g_dst.value.value() ^ temp), word_mode)); + setPSW_c(g_src.value.value() < g_dst.value.value()); return true; } case 0b011: { // BIT/BITB Bit Test Word/Byte - uint16_t dst_value = getGAM(dst_mode, dst_reg, word_mode, false); - uint16_t result = (dst_value & src_value) & (word_mode ? 0xff : 0xffff); + auto g_dst = getGAM(dst_mode, dst_reg, word_mode, false); + uint16_t result = (g_dst.value.value() & g_src.value.value()) & (word_mode ? 0xff : 0xffff); setPSW_flags_nzv(result, word_mode); @@ -536,51 +476,51 @@ bool cpu::double_operand_instructions(const uint16_t instr) } case 0b100: { // BIC/BICB Bit Clear Word/Byte - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); + auto g_dst = getGAM(dst_mode, dst_reg, word_mode, false); - uint16_t result = b->read(a, word_mode, false) & ~src_value; + uint16_t result = g_dst.value.value() & ~g_src.value.value(); - if (put_result(a, dst_mode, dst_reg, word_mode, result)) + if (put_result(g_dst, result)) setPSW_flags_nzv(result, word_mode); return true; } case 0b101: { // BIS/BISB Bit Set Word/Byte - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); + auto g_dst = getGAM(dst_mode, dst_reg, word_mode, false); - uint16_t result = b->read(a, word_mode, false) | src_value; + uint16_t result = g_dst.value.value() | g_src.value.value(); - if (put_result(a, dst_mode, dst_reg, word_mode, result)) + if (put_result(g_dst, result)) setPSW_flags_nzv(result, word_mode); return true; } case 0b110: { // ADD/SUB Add/Subtract Word - int16_t ssrc_value = getGAM(src_mode, src_reg, false, false); + auto g_ssrc = getGAM(src_mode, src_reg, false, false); - uint16_t dst_addr = getGAMAddress(dst_mode, dst_reg, false); - int16_t dst_value = b->readWord(dst_addr); - int16_t result = 0; + auto g_dst = getGAM(dst_mode, dst_reg, false, false); - bool set_flags = dst_addr != ADDR_PSW; + int16_t result = 0; + + bool set_flags = g_dst.addr.has_value() ? g_dst.addr.value() != ADDR_PSW : true; if (instr & 0x8000) { - result = (dst_value - ssrc_value) & 0xffff; + result = (g_dst.value.value() - g_ssrc.value.value()) & 0xffff; if (set_flags) { - //setPSW_v(sign(ssrc_value) != sign(dst_value) && sign(ssrc_value) == sign(result)); - setPSW_v(((ssrc_value ^ dst_value) & 0x8000) && !((dst_value ^ result) & 0x8000)); - setPSW_c(uint16_t(dst_value) < uint16_t(ssrc_value)); + //setPSW_v(sign(g_ssrc.value.value()) != sign(g_dst.value.value()) && sign(g_ssrc.value.value()) == sign(result)); + setPSW_v(((g_ssrc.value.value() ^ g_dst.value.value()) & 0x8000) && !((g_dst.value.value() ^ result) & 0x8000)); + setPSW_c(uint16_t(g_dst.value.value()) < uint16_t(g_ssrc.value.value())); } } else { - result = (dst_value + ssrc_value) & 0xffff; + result = (g_dst.value.value() + g_ssrc.value.value()) & 0xffff; if (set_flags) { - setPSW_v(sign(ssrc_value) == sign(dst_value) && sign(dst_value) != sign(result)); - setPSW_c(uint16_t(result) < uint16_t(ssrc_value)); + setPSW_v(sign(g_ssrc.value.value()) == sign(g_dst.value.value()) && sign(g_dst.value.value()) != sign(result)); + setPSW_c(uint16_t(result) < uint16_t(g_ssrc.value.value())); } } @@ -589,10 +529,7 @@ bool cpu::double_operand_instructions(const uint16_t instr) setPSW_z(result == 0); } - if (dst_mode == 0) - setRegister(dst_reg, false, result); - else - b->writeWord(dst_addr, result); + putGAM(g_dst, result); return true; } @@ -613,8 +550,11 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr) switch(operation) { case 0: { // MUL - int16_t R1 = getRegister(reg); - int16_t R2 = getGAM(dst_mode, dst_reg, true, false); + int16_t R1 = getRegister(reg); + + auto R2g = getGAM(dst_mode, dst_reg, false, false); + int16_t R2 = R2g.value.value(); + int32_t result = R1 * R2; setRegister(reg, result >> 16); @@ -628,7 +568,8 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr) } case 1: { // DIV - int16_t divider = getGAM(dst_mode, dst_reg, false, false); + auto R2g = getGAM(dst_mode, dst_reg, false, false); + int16_t divider = R2g.value.value(); if (divider == 0) { // divide by zero setPSW_n(false); @@ -666,7 +607,10 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr) case 2: { // ASH uint32_t R = getRegister(reg), oldR = R; - uint16_t shift = getGAM(dst_mode, dst_reg, false, false) & 077; + + auto g_dst = getGAM(dst_mode, dst_reg, false, false); + uint16_t shift = g_dst.value.value() & 077; + bool sign = SIGN(R, false); // extend sign-bit @@ -708,7 +652,10 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr) case 3: { // ASHC uint32_t R0R1 = (getRegister(reg) << 16) | getRegister(reg | 1); - uint16_t shift = getGAM(dst_mode, dst_reg, false, false) & 077; + + auto g_dst = getGAM(dst_mode, dst_reg, false, false); + uint16_t shift = g_dst.value.value() & 077; + bool sign = R0R1 & 0x80000000; setPSW_v(false); @@ -761,17 +708,10 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr) } case 4: { // XOR (word only) - uint16_t a = getGAMAddress(dst_mode, dst_reg, false); - uint16_t vl = b->read(a, false, false) ^ getRegister(reg); - bool set_flags = true; + auto g_dst = getGAM(dst_mode, dst_reg, false, false); + uint16_t vl = g_dst.value.value() ^ getRegister(reg); - if (dst_mode == 0) - putGAM(dst_mode, dst_reg, false, vl, false); - else { - b->write(a, false, vl, false); - - set_flags = a != ADDR_PSW; - } + bool set_flags = putGAM(g_dst, vl); if (set_flags) setPSW_flags_nzv(vl, false); @@ -809,25 +749,13 @@ bool cpu::single_operand_instructions(const uint16_t instr) if (word_mode) // handled elsewhere return false; else { - uint16_t v = 0; + auto g_dst = getGAM(dst_mode, dst_reg, word_mode, false); - if (dst_mode == 0) { - v = getRegister(dst_reg); + uint16_t v = g_dst.value.value(); - v = ((v & 0xff) << 8) | (v >> 8); + v = ((v & 0xff) << 8) | (v >> 8); - setRegister(dst_reg, false, v); - } - else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); - v = b->readWord(a); - - v = ((v & 0xff) << 8) | (v >> 8); - - set_flags = a != ADDR_PSW; - - b->writeWord(a, v); - } + set_flags = putGAM(g_dst, v); if (set_flags) { setPSW_flags_nzv(v, true); @@ -839,71 +767,52 @@ bool cpu::single_operand_instructions(const uint16_t instr) } case 0b000101000: { // CLR/CLRB - if (dst_mode == 0) { - uint16_t r = 0; + { + auto g_dst = getGAM(dst_mode, dst_reg, word_mode, false); + + uint16_t r = 0; // CLRB only clears the least significant byte if (word_mode) - r = getGAM(dst_mode, dst_reg, false, false) & 0xff00; + r = g_dst.value.value() & 0xff00; - putGAM(dst_mode, dst_reg, false, r, false); - } - else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); + bool set_flags = putGAM(g_dst, r); - set_flags = a != ADDR_PSW; - - b -> write(a, word_mode, 0, false); - } - - if (set_flags) { - setPSW_n(false); - setPSW_z(true); - setPSW_v(false); - setPSW_c(false); + if (set_flags) { + setPSW_n(false); + setPSW_z(true); + setPSW_v(false); + setPSW_c(false); + } } break; } case 0b000101001: { // COM/COMB - if (dst_mode == 0) { - uint16_t v = getRegister(dst_reg); + auto a = getGAM(dst_mode, dst_reg, word_mode, false); + uint16_t v = a.value.value(); - if (word_mode) - v ^= 0xff; - else - v ^= 0xffff; + if (word_mode) + v ^= 0xff; + else + v ^= 0xffff; - setPSW_flags_nzv(v, word_mode); + set_flags = putGAM(a, v); + + if (set_flags) { + setPSW_flags_nzv(v, word_mode); setPSW_c(true); - - setRegister(dst_reg, false, v); } - else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); - uint16_t v = b -> read(a, word_mode, false); - if (word_mode) - v ^= 0xff; - else - v ^= 0xffff; - - bool set_flags = a != ADDR_PSW; - - if (set_flags) { - setPSW_flags_nzv(v, word_mode); - setPSW_c(true); - } - - b->write(a, word_mode, v, false); - } break; } case 0b000101010: { // INC/INCB + auto a = getGAM(dst_mode, dst_reg, word_mode, false); + uint16_t v = a.value.value(); + if (dst_mode == 0) { - uint16_t v = getRegister(dst_reg); uint16_t add = word_mode ? v & 0xff00 : 0; v = (v + 1) & (word_mode ? 0xff : 0xffff); @@ -916,11 +825,9 @@ bool cpu::single_operand_instructions(const uint16_t instr) setRegister(dst_reg, false, v); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); - uint16_t v = b -> read(a, word_mode, false); - int32_t vl = (v + 1) & (word_mode ? 0xff : 0xffff); + int32_t vl = (a.value.value() + 1) & (word_mode ? 0xff : 0xffff); - bool set_flags = a != ADDR_PSW; + bool set_flags = a.addr.value() != ADDR_PSW; if (set_flags) { setPSW_n(SIGN(vl, word_mode)); @@ -928,13 +835,14 @@ bool cpu::single_operand_instructions(const uint16_t instr) setPSW_v(word_mode ? vl == 0x80 : v == 0x8000); } - b->write(a, word_mode, vl, false); + b->write(a.addr.value(), word_mode, vl, false); } break; } case 0b000101011: { // DEC/DECB + // TODO unify if (dst_mode == 0) { uint16_t v = getRegister(dst_reg); uint16_t add = word_mode ? v & 0xff00 : 0; @@ -949,11 +857,11 @@ bool cpu::single_operand_instructions(const uint16_t instr) setRegister(dst_reg, false, v); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); - uint16_t v = b -> read(a, word_mode, false); - int32_t vl = (v - 1) & (word_mode ? 0xff : 0xffff); + auto a = getGAM(dst_mode, dst_reg, word_mode, false); + uint16_t v = a.value.value(); + int32_t vl = (v - 1) & (word_mode ? 0xff : 0xffff); - bool set_flags = a != ADDR_PSW; + bool set_flags = a.addr.value() != ADDR_PSW; if (set_flags) { setPSW_n(SIGN(vl, word_mode)); @@ -961,7 +869,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) setPSW_v(word_mode ? vl == 0x7f : vl == 0x7fff); } - b->write(a, word_mode, vl, false); + b->write(a.addr.value(), word_mode, vl, false); } break; @@ -983,12 +891,12 @@ bool cpu::single_operand_instructions(const uint16_t instr) setRegister(dst_reg, false, v); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); - uint16_t v = -b -> read(a, word_mode, false); + auto a = getGAM(dst_mode, dst_reg, word_mode, false); + uint16_t v = -a.value.value(); - b->write(a, word_mode, v, false); + b->write(a.addr.value(), word_mode, v, false); - bool set_flags = a != ADDR_PSW; + bool set_flags = a.addr.value() != ADDR_PSW; if (set_flags) { setPSW_n(SIGN(v, word_mode)); @@ -1019,14 +927,14 @@ bool cpu::single_operand_instructions(const uint16_t instr) setRegister(dst_reg, false, v); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); - const uint16_t vo = b -> read(a, word_mode, false); + auto a = getGAM(dst_mode, dst_reg, word_mode, false); + const uint16_t vo = a.value.value(); bool org_c = getPSW_c(); uint16_t v = (vo + org_c) & (word_mode ? 0x00ff : 0xffff); - b->write(a, word_mode, v, false); + b->write(a.addr.value(), word_mode, v, false); - bool set_flags = a != ADDR_PSW; + bool set_flags = a.addr.value() != ADDR_PSW; if (set_flags) { setPSW_n(SIGN(v, word_mode)); @@ -1061,14 +969,14 @@ bool cpu::single_operand_instructions(const uint16_t instr) setRegister(dst_reg, false, v); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); - const uint16_t vo = b -> read(a, word_mode, false); + auto a = getGAM(dst_mode, dst_reg, word_mode, false); + const uint16_t vo = a.value.value(); bool org_c = getPSW_c(); uint16_t v = (vo - org_c) & (word_mode ? 0xff : 0xffff); - b->write(a, word_mode, v, false); + b->write(a.addr.value(), word_mode, v, false); - bool set_flags = a != ADDR_PSW; + bool set_flags = a.addr.value() != ADDR_PSW; if (set_flags) { setPSW_n(SIGN(v, word_mode)); @@ -1085,7 +993,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) } case 0b000101111: { // TST/TSTB - uint16_t v = getGAM(dst_mode, dst_reg, word_mode, false); + uint16_t v = getGAM(dst_mode, dst_reg, word_mode, false).value.value(); setPSW_flags_nzv(v, word_mode); setPSW_c(false); @@ -1116,8 +1024,8 @@ bool cpu::single_operand_instructions(const uint16_t instr) setPSW_v(getPSW_c() ^ getPSW_n()); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); - uint16_t t = b -> read(a, word_mode, false); + auto a = getGAM(dst_mode, dst_reg, word_mode, false); + uint16_t t = a.value.value(); bool new_carry = t & 1; uint16_t temp = 0; @@ -1126,9 +1034,9 @@ bool cpu::single_operand_instructions(const uint16_t instr) else temp = (t >> 1) | (getPSW_c() << 15); - b->write(a, word_mode, temp, false); + b->write(a.addr.value(), word_mode, temp, false); - bool set_flags = a != ADDR_PSW; + bool set_flags = a.addr.value() != ADDR_PSW; if (set_flags) { setPSW_c(new_carry); @@ -1163,8 +1071,8 @@ bool cpu::single_operand_instructions(const uint16_t instr) setPSW_v(getPSW_c() ^ getPSW_n()); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); - uint16_t t = b -> read(a, word_mode, false); + auto a = getGAM(dst_mode, dst_reg, word_mode, false); + uint16_t t = a.value.value(); bool new_carry = false; uint16_t temp = 0; @@ -1177,9 +1085,9 @@ bool cpu::single_operand_instructions(const uint16_t instr) temp = (t << 1) | getPSW_c(); } - b->write(a, word_mode, temp, false); + b->write(a.addr.value(), word_mode, temp, false); - bool set_flags = a != ADDR_PSW; + bool set_flags = a.addr.value() != ADDR_PSW; if (set_flags) { setPSW_c(new_carry); @@ -1218,8 +1126,8 @@ bool cpu::single_operand_instructions(const uint16_t instr) setPSW_v(getPSW_n() ^ getPSW_c()); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); - uint16_t v = b -> read(a, word_mode, false); + auto a = getGAM(dst_mode, dst_reg, word_mode, false); + uint16_t v = a.value.value(); uint16_t add = word_mode ? v & 0xff00 : 0; bool hb = word_mode ? v & 128 : v & 32768; @@ -1236,9 +1144,9 @@ bool cpu::single_operand_instructions(const uint16_t instr) v |= hb << 15; } - b->write(a, word_mode, v, false); + b->write(a.addr.value(), word_mode, v, false); - bool set_flags = a != ADDR_PSW; + bool set_flags = a.addr.value() != ADDR_PSW; if (set_flags) { setPSW_n(SIGN(v, word_mode)); @@ -1265,11 +1173,11 @@ bool cpu::single_operand_instructions(const uint16_t instr) setRegister(dst_reg, false, v); } else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); - uint16_t vl = b -> read(a, word_mode, false); + auto a = getGAM(dst_mode, dst_reg, word_mode, false); + uint16_t vl = a.value.value(); uint16_t v = (vl << 1) & (word_mode ? 0xff : 0xffff); - bool set_flags = a != ADDR_PSW; + bool set_flags = a.addr.value() != ADDR_PSW; if (set_flags) { setPSW_n(SIGN(v, word_mode)); @@ -1278,7 +1186,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) setPSW_v(getPSW_n() ^ getPSW_c()); } - b->write(a, word_mode, v, false); + b->write(a.addr.value(), word_mode, v, false); } break; } @@ -1296,16 +1204,16 @@ bool cpu::single_operand_instructions(const uint16_t instr) v = getRegister(dst_reg, getBitPSW(11), true); else { // calculate address in current address space - uint16_t a = getGAMAddress(dst_mode, dst_reg, false); + auto a = getGAMAddress(dst_mode, dst_reg, false); - set_flags = a != ADDR_PSW; + set_flags = a.addr.value() != ADDR_PSW; - if (a >= 0160000) { + if (a.addr.value() >= 0160000) { // read from previous space - v = b -> read(a, false, true); + v = b -> read(a.addr.value(), false, true); } else { - auto phys = b->calculate_physical_address((getPSW() >> 12) & 3, a); + auto phys = b->calculate_physical_address((getPSW() >> 12) & 3, a.addr.value()); //b->check_address(true, true, phys, false, word_mode, (getPSW() >> 12) & 3); @@ -1339,21 +1247,21 @@ bool cpu::single_operand_instructions(const uint16_t instr) if (dst_mode == 0) setRegister(dst_reg, true, v); else { - uint16_t a = getGAMAddress(dst_mode, dst_reg, false); + auto a = getGAMAddress(dst_mode, dst_reg, false); - set_flags = a != ADDR_PSW; + set_flags = a.addr.value() != ADDR_PSW; - if (a >= 0160000) - b->write(a, false, v, true); // put in '13/12' address space + if (a.addr.value() >= 0160000) + b->write(a.addr.value(), false, v, true); // put in '13/12' address space else { - auto phys = b->calculate_physical_address((getPSW() >> 12) & 3, a); + auto phys = b->calculate_physical_address((getPSW() >> 12) & 3, a.addr.value()); DOLOG(debug, true, "MTPI/D %06o -> %o / %o", a, phys.physical_instruction, phys.physical_data); // FILE *fh = fopen("og2-kek.dat", "a+"); // fprintf(fh, "%lu %06o MTPI %06o: %06o\n", mtpi_count, oldpc, a, v); // fclose(fh); - DOLOG(debug, true, "%lu %06o MTPI %06o: %06o", mtpi_count, oldpc, a, v); + DOLOG(debug, true, "%lu %06o MTPI %06o: %06o", mtpi_count, oldpc, a.addr.value(), v); mtpi_count++; @@ -1375,7 +1283,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) case 0b000110100: // MARK/MTPS (put something in PSW) if (word_mode) { // MTPS psw &= 0xff00; // only alter lower 8 bits - psw |= getGAM(dst_mode, dst_reg, word_mode, false) & 0xef; // can't change bit 4 + psw |= getGAM(dst_mode, dst_reg, word_mode, false).value.value() & 0xef; // can't change bit 4 } else { setRegister(6, getPC() + dst * 2); @@ -1387,7 +1295,9 @@ bool cpu::single_operand_instructions(const uint16_t instr) break; - case 0b000110111: // MFPS (get PSW to something) / SXT + case 0b000110111: { // MFPS (get PSW to something) / SXT + auto g_dst = getGAM(dst_mode, dst_reg, word_mode, false); + if (word_mode) { // MFPS uint16_t temp = psw & 0xff; bool extend_b7 = psw & 128; @@ -1395,7 +1305,7 @@ bool cpu::single_operand_instructions(const uint16_t instr) if (extend_b7 && dst_mode == 0) temp |= 0xff00; - set_flags = putGAM(dst_mode, dst_reg, word_mode, temp, false); + bool set_flags = putGAM(g_dst, temp); if (set_flags) { setPSW_z(temp == 0); @@ -1404,17 +1314,16 @@ bool cpu::single_operand_instructions(const uint16_t instr) } } else { // SXT - uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode); - int32_t vl = -getPSW_n(); - if (put_result(a, dst_mode, dst_reg, word_mode, vl)) { + if (put_result(g_dst, vl)) { setPSW_z(getPSW_n() == false); setPSW_v(false); } } + } - break; + break; default: return false; @@ -1620,15 +1529,15 @@ bool cpu::misc_operations(const uint16_t instr) int dst_reg = instr & 7; bool word_mode = false; - setPC(getGAMAddress(dst_mode, dst_reg, word_mode)); + setPC(getGAMAddress(dst_mode, dst_reg, word_mode).addr.value()); } return true; } if ((instr & 0b1111111000000000) == 0b0000100000000000) { // JSR - int link_reg = (instr >> 6) & 7; - uint16_t dst_value = getGAMAddress((instr >> 3) & 7, instr & 7, false); + int link_reg = (instr >> 6) & 7; + auto dst_value = getGAMAddress((instr >> 3) & 7, instr & 7, false).addr.value(); // PUSH link pushStack(getRegister(link_reg)); diff --git a/cpu.h b/cpu.h index 7f0449e..e90f0f6 100644 --- a/cpu.h +++ b/cpu.h @@ -5,12 +5,26 @@ #include #include #include +#include #include #include #include #include "bus.h" +typedef struct { + bool word_mode; + bool prev_mode; + bool set; + + union { + std::optional addr; + int reg; + }; + + std::optional value; +} gam_rc_t; + class cpu { private: @@ -43,10 +57,11 @@ private: uint16_t addRegister(const int nr, const bool prev_mode, const uint16_t value); void addToMMR1(const uint8_t mode, const uint8_t reg, const bool word_mode); - uint16_t getGAMAddress(const uint8_t mode, const int reg, const bool word_mode); - uint16_t getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode, const bool MF_MT); - // returns false when flag registers should not be updated - bool putGAM(const uint8_t mode, const int reg, const bool word_mode, const uint16_t value, const bool MF_FT); + + + gam_rc_t getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode, const bool prev_mode, const bool read_value = true); + gam_rc_t getGAMAddress(const uint8_t mode, const int reg, const bool word_mode); + bool putGAM(const gam_rc_t & g, const uint16_t value); // returns false when flag registers should not be updated bool double_operand_instructions(const uint16_t instr); bool additional_double_operand_instructions(const uint16_t instr); @@ -137,5 +152,5 @@ public: uint16_t getRegister(const int nr, const int mode, const bool sp_prev_mode) const; uint16_t getRegister(const int nr) const; - bool put_result(const uint16_t a, const uint8_t dst_mode, const uint8_t dst_reg, const bool word_mode, const uint16_t value); + bool put_result(const gam_rc_t & g, const uint16_t value); }; From a935fe44d7d6edccc9543ef3d2178b075440051e Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sat, 18 Mar 2023 14:45:44 +0100 Subject: [PATCH 30/33] use d-space where required --- bus.cpp | 5 +++++ bus.h | 1 + cpu.cpp | 20 +++++++++++--------- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/bus.cpp b/bus.cpp index 03113c2..935f95e 100644 --- a/bus.cpp +++ b/bus.cpp @@ -464,6 +464,11 @@ void bus::check_address(const bool trap_on_failure, const bool is_write, const m } } +bool bus::get_use_data_space(const int run_mode) +{ + return !!(MMR3 & di_ena_mask[run_mode]); +} + uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, const bool trap_on_failure, const bool is_write, const bool peek_only, const bool is_data) { uint32_t m_offset = a; diff --git a/bus.h b/bus.h index bfb0bbc..7669b89 100644 --- a/bus.h +++ b/bus.h @@ -150,6 +150,7 @@ public: uint32_t calculate_physical_address(const int run_mode, const uint16_t a, const bool trap_on_failure, const bool is_write, const bool peek_only, const bool is_data); + bool get_use_data_space(const int run_mode); memory_addresses_t calculate_physical_address(const int run_mode, const uint16_t a); void check_address(const bool trap_on_failure, const bool is_write, const memory_addresses_t & addr, const bool word_mode, const bool is_data, const int run_mode); }; diff --git a/cpu.cpp b/cpu.cpp index 9e88b0b..1142841 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -331,6 +331,8 @@ gam_rc_t cpu::getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode uint16_t next_word = 0; + d_i_space_t space = reg == 7 ? i_space : (b->get_use_data_space(psw >> 14) ? d_space : i_space); + switch(mode) { case 0: // 000 g.reg = reg; @@ -339,45 +341,45 @@ gam_rc_t cpu::getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode case 1: g.addr = getRegister(reg, g.set, prev_mode); if (read_value) - g.value = b->read(g.addr.value(), word_mode, prev_mode); + g.value = b->read(g.addr.value(), word_mode, prev_mode, false, space); break; case 2: g.addr = getRegister(reg, g.set, prev_mode); if (read_value) - g.value = b->read(g.addr.value(), word_mode, prev_mode); + g.value = b->read(g.addr.value(), word_mode, prev_mode, false, space); addRegister(reg, prev_mode, !word_mode || reg == 7 || reg == 6 ? 2 : 1); break; case 3: - g.addr = b->read(getRegister(reg, g.set, prev_mode), false, prev_mode); + g.addr = b->read(getRegister(reg, g.set, prev_mode), false, prev_mode, space); if (read_value) - g.value = b->read(g.addr.value(), word_mode, prev_mode); + g.value = b->read(g.addr.value(), word_mode, prev_mode, false, d_space); addRegister(reg, prev_mode, 2); break; case 4: addRegister(reg, prev_mode, !word_mode || reg == 7 || reg == 6 ? -2 : -1); g.addr = getRegister(reg, g.set, prev_mode); if (read_value) - g.value = b->read(g.addr.value(), word_mode, prev_mode); + g.value = b->read(g.addr.value(), word_mode, prev_mode, false, d_space); break; case 5: addRegister(reg, prev_mode, -2); - g.addr = b->read(getRegister(reg, g.set, prev_mode), false, prev_mode); + g.addr = b->read(getRegister(reg, g.set, prev_mode), false, prev_mode, space); if (read_value) - g.value = b->read(g.addr.value(), word_mode, prev_mode); + g.value = b->read(g.addr.value(), word_mode, prev_mode, d_space); break; case 6: next_word = b -> read(getPC(), false, prev_mode); addRegister(7, prev_mode, + 2); g.addr = getRegister(reg, g.set, prev_mode) + next_word; if (read_value) - g.value = b->read(g.addr.value(), word_mode, prev_mode); + g.value = b->read(g.addr.value(), word_mode, prev_mode, d_space); break; case 7: next_word = b -> read(getPC(), false, prev_mode); addRegister(7, prev_mode, + 2); g.addr = b->read(getRegister(reg, g.set, prev_mode) + next_word, false, prev_mode); if (read_value) - g.value = b->read(g.addr.value(), word_mode, prev_mode); + g.value = b->read(g.addr.value(), word_mode, prev_mode, d_space); break; } From 020764b22ccd5b34cd1319f575cbf2bf013298cd Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sat, 18 Mar 2023 14:48:17 +0100 Subject: [PATCH 31/33] write-back in correct space --- cpu.cpp | 16 ++++++++-------- cpu.h | 1 + 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/cpu.cpp b/cpu.cpp index 1142841..b957c87 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -324,14 +324,14 @@ void cpu::addToMMR1(const uint8_t mode, const uint8_t reg, const bool word_mode) // GAM = general addressing modes gam_rc_t cpu::getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode, const bool prev_mode, const bool read_value) { - gam_rc_t g { false, false, false, { }, 0 }; + gam_rc_t g { false, false, false, i_space, { }, 0 }; g.word_mode = word_mode; // word/byte g.prev_mode = prev_mode; // run mode g.set = getBitPSW(11); uint16_t next_word = 0; - d_i_space_t space = reg == 7 ? i_space : (b->get_use_data_space(psw >> 14) ? d_space : i_space); + g.space = reg == 7 ? i_space : (b->get_use_data_space(psw >> 14) ? d_space : i_space); switch(mode) { case 0: // 000 @@ -341,16 +341,16 @@ gam_rc_t cpu::getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode case 1: g.addr = getRegister(reg, g.set, prev_mode); if (read_value) - g.value = b->read(g.addr.value(), word_mode, prev_mode, false, space); + g.value = b->read(g.addr.value(), word_mode, prev_mode, false, g.space); break; case 2: g.addr = getRegister(reg, g.set, prev_mode); if (read_value) - g.value = b->read(g.addr.value(), word_mode, prev_mode, false, space); + g.value = b->read(g.addr.value(), word_mode, prev_mode, false, g.space); addRegister(reg, prev_mode, !word_mode || reg == 7 || reg == 6 ? 2 : 1); break; case 3: - g.addr = b->read(getRegister(reg, g.set, prev_mode), false, prev_mode, space); + g.addr = b->read(getRegister(reg, g.set, prev_mode), false, prev_mode, g.space); if (read_value) g.value = b->read(g.addr.value(), word_mode, prev_mode, false, d_space); addRegister(reg, prev_mode, 2); @@ -363,7 +363,7 @@ gam_rc_t cpu::getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode break; case 5: addRegister(reg, prev_mode, -2); - g.addr = b->read(getRegister(reg, g.set, prev_mode), false, prev_mode, space); + g.addr = b->read(getRegister(reg, g.set, prev_mode), false, prev_mode, g.space); if (read_value) g.value = b->read(g.addr.value(), word_mode, prev_mode, d_space); break; @@ -389,7 +389,7 @@ gam_rc_t cpu::getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode bool cpu::putGAM(const gam_rc_t & g, const uint16_t value) { if (g.addr.has_value()) { - b->write(g.addr.value(), g.word_mode, value, g.prev_mode); + b->write(g.addr.value(), g.word_mode, value, g.prev_mode, g.space); return g.addr.value() != ADDR_PSW; } @@ -420,7 +420,7 @@ bool cpu::double_operand_instructions(const uint16_t instr) const uint8_t src_mode = (src >> 3) & 7; const uint8_t src_reg = src & 7; - gam_rc_t g_src { false, false, false, { }, 0 }; + gam_rc_t g_src { false, false, false, i_space, { }, 0 }; if (operation != 0b110) g_src = getGAM(src_mode, src_reg, word_mode, false); diff --git a/cpu.h b/cpu.h index e90f0f6..1d9bb31 100644 --- a/cpu.h +++ b/cpu.h @@ -16,6 +16,7 @@ typedef struct { bool word_mode; bool prev_mode; bool set; + d_i_space_t space; union { std::optional addr; From 076575c405c2c2bc896a3c7208896d19c694311c Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sat, 18 Mar 2023 19:12:42 +0100 Subject: [PATCH 32/33] corrected(?) SYSSIZE registers --- bus.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/bus.cpp b/bus.cpp index 935f95e..0759662 100644 --- a/bus.cpp +++ b/bus.cpp @@ -258,11 +258,15 @@ uint16_t bus::read(const uint16_t a, const bool word_mode, const bool use_prev, // LO size register field must be all 1s, so subtract 1 constexpr uint32_t system_size = n_pages * 8192 / 64 - 1; - if (a == ADDR_SYSSIZE + 2) // system size HI - return system_size >> 16; + if (a == ADDR_SYSSIZE + 2) { // system size HI + printf("accessing system size HI\r\n"); + return ((system_size >> 6) - 1) >> 16; + } - if (a == ADDR_SYSSIZE) // system size LO - return system_size & 65535; + if (a == ADDR_SYSSIZE) { // system size LO + printf("accessing system size LO\r\n"); + return (system_size >> 6) - 1; + } if (a & 1) DOLOG(debug, !peek_only, "bus::readWord: odd address UNHANDLED %o", a); From 0203371f4404bf14133f760e1e3bc51e8ec1ccb2 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Sat, 18 Mar 2023 19:21:54 +0100 Subject: [PATCH 33/33] typo --- bus.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bus.cpp b/bus.cpp index 0759662..b0465ae 100644 --- a/bus.cpp +++ b/bus.cpp @@ -101,7 +101,7 @@ uint16_t bus::read(const uint16_t a, const bool word_mode, const bool use_prev, } if (a == ADDR_PIR) { // PIR - DOLOG(debug, !peek_only, "read PIT"); + DOLOG(debug, !peek_only, "read PIR"); return PIR; }