From 21a6553f47b75677b6aabc9a4cfa53022ce26d60 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Thu, 9 Jun 2022 22:07:41 +0200 Subject: [PATCH 1/5] framework for RL02 emulation --- CMakeLists.txt | 1 + rl02.cpp | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ rl02.h | 41 +++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 rl02.cpp create mode 100644 rl02.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 32b5926..c214397 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ add_executable( main.cpp memory.cpp rk05.cpp + rl02.cpp rx02.cpp terminal.cpp tests.cpp diff --git a/rl02.cpp b/rl02.cpp new file mode 100644 index 0000000..3b766f1 --- /dev/null +++ b/rl02.cpp @@ -0,0 +1,99 @@ +// (C) 2022 by Folkert van Heusden +// Released under Apache License v2.0 +#include +#include + +#include "bus.h" +#include "cpu.h" +#include "error.h" +#include "gen.h" +#include "rl02.h" +#include "utils.h" + + +rl02::rl02(const std::vector & files, bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity) : + b(b), + disk_read_acitivity(disk_read_acitivity), + disk_write_acitivity(disk_write_acitivity) +{ + memset(registers, 0x00, sizeof registers); + memset(xfer_buffer, 0x00, sizeof xfer_buffer); + + for(auto file : files) { +#if defined(ESP32) + File32 *fh = new File32(); + + if (!fh->open(file.c_str(), O_RDWR)) { + delete fh; + error_exit(true, "rl02: cannot open \"%s\"", file.c_str()); + } +#else + FILE *fh = fopen(file.c_str(), "rb"); + if (!fh) + error_exit(true, "rl02: cannot open \"%s\"", file.c_str()); +#endif + + fhs.push_back(fh); + } +} + +rl02::~rl02() +{ + for(auto fh : fhs) { +#if defined(ESP32) + fh->close(); + delete fh; +#else + fclose(fh); +#endif + } +} + +uint8_t rl02::readByte(const uint16_t addr) +{ + uint16_t v = readWord(addr & ~1); + + if (addr & 1) + return v >> 8; + + return v; +} + +uint16_t rl02::readWord(const uint16_t addr) +{ + const int reg = (addr - RK05_BASE) / 2; + + // TODO + + D(fprintf(stderr, "RK05 read %s/%o: %06o\n", reg[regnames], addr, vtemp);) + + return vtemp; +} + +void rl02::writeByte(const uint16_t addr, const uint8_t v) +{ + uint16_t vtemp = registers[(addr - RK05_BASE) / 2]; + + if (addr & 1) { + vtemp &= ~0xff00; + vtemp |= v << 8; + } + else { + vtemp &= ~0x00ff; + vtemp |= v; + } + + writeWord(addr, vtemp); +} + +void rl02::writeWord(const uint16_t addr, uint16_t v) +{ +#if defined(ESP32) + digitalWrite(LED_BUILTIN, LOW); +#endif + + +#if defined(ESP32) + digitalWrite(LED_BUILTIN, HIGH); +#endif +} diff --git a/rl02.h b/rl02.h new file mode 100644 index 0000000..3f4dd3d --- /dev/null +++ b/rl02.h @@ -0,0 +1,41 @@ +// (C) 2022 by Folkert van Heusden +// Released under Apache License v2.0 +#pragma once + +#include +#include +#include +#include +#include + +#if defined(ESP32) +#include "esp32.h" +#endif + + +class bus; + +class rl02 +{ +private: + bus *const b; + uint16_t registers[7]; + uint8_t xfer_buffer[512]; +#if defined(ESP32) + std::vector fhs; +#else + std::vector fhs; +#endif + std::atomic_bool *const disk_read_acitivity { nullptr }; + std::atomic_bool *const disk_write_acitivity { nullptr }; + +public: + rl02(const std::vector & files, bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity); + virtual ~rl02(); + + uint8_t readByte(const uint16_t addr); + uint16_t readWord(const uint16_t addr); + + void writeByte(const uint16_t addr, const uint8_t v); + void writeWord(const uint16_t addr, const uint16_t v); +}; From 160ffe5c2626d880d67e2a0482601a27df2e3947 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Thu, 9 Jun 2022 22:19:46 +0200 Subject: [PATCH 2/5] connect rl02 to bus --- CMakeLists.txt | 1 - bus.cpp | 10 +++++-- bus.h | 6 ++--- main.cpp | 14 +++++++++- rk05.cpp | 2 +- rl02.cpp | 13 +++++++-- rl02.h | 6 +++++ rx02.cpp | 72 -------------------------------------------------- rx02.h | 33 ----------------------- 9 files changed, 42 insertions(+), 115 deletions(-) delete mode 100644 rx02.cpp delete mode 100644 rx02.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c214397..e20e176 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,6 @@ add_executable( memory.cpp rk05.cpp rl02.cpp - rx02.cpp terminal.cpp tests.cpp tm-11.cpp diff --git a/bus.cpp b/bus.cpp index e08e8c8..b1fad88 100644 --- a/bus.cpp +++ b/bus.cpp @@ -1,4 +1,4 @@ -// (C) 2018 by Folkert van Heusden +// (C) 2018-2022 by Folkert van Heusden // Released under Apache License v2.0 #include #include @@ -19,6 +19,7 @@ constexpr int n_pages = 12; constexpr int n_pages = 16; #endif + bus::bus() { m = new memory(n_pages * 8192); @@ -33,7 +34,7 @@ bus::~bus() delete c; delete tm11; delete rk05_; - delete rx02_; + delete rl02_; delete tty_; delete m; } @@ -546,6 +547,11 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons return value; } + if (rl02_ && a >= RL02_BASE && a < RL02_END) { + word_mode ? rl02_ -> writeByte(a, value) : rl02_ -> writeWord(a, value); + return value; + } + if (tty_ && a >= PDP11TTY_BASE && a < PDP11TTY_END) { word_mode ? tty_ -> writeByte(a, value) : tty_ -> writeWord(a, value); return value; diff --git a/bus.h b/bus.h index 0ce7138..a1c1260 100644 --- a/bus.h +++ b/bus.h @@ -7,7 +7,7 @@ #include "tm-11.h" #include "rk05.h" -#include "rx02.h" +#include "rl02.h" class cpu; class memory; @@ -24,7 +24,7 @@ private: cpu *c { nullptr }; tm_11 *tm11 { nullptr }; rk05 *rk05_ { nullptr }; - rx02 *rx02_ { nullptr }; + rl02 *rl02_ { nullptr }; tty *tty_ { nullptr }; memory *m { nullptr }; @@ -51,7 +51,7 @@ public: void add_cpu(cpu *const c) { this -> c = c; } void add_tm11(tm_11 *tm11) { this -> tm11 = tm11; } void add_rk05(rk05 *rk05_) { this -> rk05_ = rk05_; } - void add_rx02(rx02 *rx02_) { this -> rx02_ = rx02_; } + void add_rl02(rl02 *rl02_) { this -> rl02_ = rl02_; } void add_tty(tty *tty_) { this -> tty_ = tty_; } cpu *getCpu() { return this->c; } diff --git a/main.cpp b/main.cpp index 508aa7a..195bb27 100644 --- a/main.cpp +++ b/main.cpp @@ -170,12 +170,15 @@ int main(int argc, char *argv[]) c -> setEmulateMFPT(true); std::vector rk05_files; + std::vector rl02_files; + bool testCases = false; bool run_debugger = false; bool tracing = false; bool bootloader = false; + int opt = -1; - while((opt = getopt(argc, argv, "hm:T:R:p:ndtL:b")) != -1) + while((opt = getopt(argc, argv, "hm:T:r:R:p:ndtL:b")) != -1) { switch(opt) { case 'h': @@ -216,6 +219,10 @@ int main(int argc, char *argv[]) rk05_files.push_back(optarg); break; + case 'r': + rl02_files.push_back(optarg); + break; + case 'p': c->setRegister(7, atoi(optarg)); break; @@ -247,6 +254,9 @@ int main(int argc, char *argv[]) if (rk05_files.empty() == false) b->add_rk05(new rk05(rk05_files, b, cnsl->get_disk_read_activity_flag(), cnsl->get_disk_write_activity_flag())); + if (rl02_files.empty() == false) + b->add_rl02(new rl02(rl02_files, b, cnsl->get_disk_read_activity_flag(), cnsl->get_disk_write_activity_flag())); + if (bootloader) setBootLoader(b); @@ -306,5 +316,7 @@ int main(int argc, char *argv[]) delete b; + delete lf; + return 0; } diff --git a/rk05.cpp b/rk05.cpp index eb30ba5..cb76b86 100644 --- a/rk05.cpp +++ b/rk05.cpp @@ -11,7 +11,7 @@ #include "utils.h" -const char * const regnames[] = { +static const char * const regnames[] = { "RK05_DS drivestatus", "RK05_ERROR ", "RK05_CS ctrlstatus", diff --git a/rl02.cpp b/rl02.cpp index 3b766f1..52e80ac 100644 --- a/rl02.cpp +++ b/rl02.cpp @@ -11,6 +11,13 @@ #include "utils.h" +static const char * const regnames[] = { + "control status", + "bus address ", + "disk address ", + "multipurpose " + }; + rl02::rl02(const std::vector & files, bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity) : b(b), disk_read_acitivity(disk_read_acitivity), @@ -63,11 +70,13 @@ uint16_t rl02::readWord(const uint16_t addr) { const int reg = (addr - RK05_BASE) / 2; + uint16_t value = 0; + // TODO - D(fprintf(stderr, "RK05 read %s/%o: %06o\n", reg[regnames], addr, vtemp);) + D(fprintf(stderr, "RK05 read %s/%o: %06o\n", reg[regnames], addr, value);) - return vtemp; + return value; } void rl02::writeByte(const uint16_t addr, const uint8_t v) diff --git a/rl02.h b/rl02.h index 3f4dd3d..d25e96a 100644 --- a/rl02.h +++ b/rl02.h @@ -12,6 +12,12 @@ #include "esp32.h" #endif +#define RL02_CSR 0174400 // control status register +#define RL02_BAR 0174402 // bus address register +#define RL02_DAR 0174404 // disk address register +#define RL02_MPR 0174406 // multi purpose register +#define RL02_BASE RL02_CSR +#define RL02_END (RL02_MPR + 2) class bus; diff --git a/rx02.cpp b/rx02.cpp deleted file mode 100644 index 6b5767f..0000000 --- a/rx02.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// (C) 2018 by Folkert van Heusden -// Released under Apache License v2.0 -#include -#include - -#include "rx02.h" -#include "gen.h" -#include "memory.h" -#include "utils.h" - -rx02::rx02(const std::string & file, memory *const m) : m(m) -{ - offset = 0; - memset(registers, 0x00, sizeof registers); - - fh = fopen(file.c_str(), "rb"); -} - -rx02::~rx02() -{ - fclose(fh); -} - -uint8_t rx02::readByte(const uint16_t addr) -{ - uint16_t v = readWord(addr & ~1); - - if (addr & 1) - return v >> 8; - - return v; -} - -uint16_t rx02::readWord(const uint16_t addr) -{ - const int reg = (addr - RX02_BASE) / 2; - uint16_t vtemp = registers[reg]; - - D(printf("RX02 read addr %o: ", addr);) - - // FIXME - - D(printf("%o\n", vtemp);) - - return vtemp; -} - -void rx02::writeByte(const uint16_t addr, const uint8_t v) -{ - uint16_t vtemp = registers[(addr - RX02_BASE) / 2]; - - if (addr & 1) { - vtemp &= ~0xff00; - vtemp |= v << 8; - } - else { - vtemp &= ~0x00ff; - vtemp |= v; - } - - writeWord(addr, vtemp); -} - -void rx02::writeWord(const uint16_t addr, uint16_t v) -{ - D(printf("RX02 write %o: %o\n", addr, v);) - - // FIXME - - D(printf("set register %o to %o\n", addr, v);) - registers[(addr - RX02_BASE) / 2] = v; -} diff --git a/rx02.h b/rx02.h deleted file mode 100644 index 36146db..0000000 --- a/rx02.h +++ /dev/null @@ -1,33 +0,0 @@ -// (C) 2018 by Folkert van Heusden -// Released under Apache License v2.0 -#pragma once - -#include -#include -#include - -// FIXME namen van defines -#define RX02_BASE 0 -#define RX02_END (1 + 2) - -class memory; - -class rx02 -{ -private: - memory *const m; - uint16_t registers[7]; - uint8_t xfer_buffer[512]; - int offset; - FILE *fh; - -public: - rx02(const std::string & file, memory *const m); - virtual ~rx02(); - - uint8_t readByte(const uint16_t addr); - uint16_t readWord(const uint16_t addr); - - void writeByte(const uint16_t addr, const uint8_t v); - void writeWord(const uint16_t addr, uint16_t v); -}; From 57aca63db05b915b01d9215c5e39cae3f832e123 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Fri, 10 Jun 2022 09:48:02 +0200 Subject: [PATCH 3/5] Implemented RL02 read command --- bus.cpp | 3 ++ main.cpp | 114 +++++++++++++++++++++++++++++++++++++++++------------ rl02.cpp | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- rl02.h | 10 +++-- 4 files changed, 212 insertions(+), 33 deletions(-) diff --git a/bus.cpp b/bus.cpp index b1fad88..4730419 100644 --- a/bus.cpp +++ b/bus.cpp @@ -281,6 +281,9 @@ uint16_t bus::read(const uint16_t a, const bool word_mode, const bool use_prev, if (rk05_ && a >= RK05_BASE && a < RK05_END) return word_mode ? rk05_ -> readByte(a) : rk05_ -> readWord(a); + if (rl02_ && a >= RL02_BASE && a < RL02_END) + return word_mode ? rl02_ -> readByte(a) : rl02_ -> readWord(a); + if (tty_ && a >= PDP11TTY_BASE && a < PDP11TTY_END) return word_mode ? tty_ -> readByte(a) : tty_ -> readWord(a); diff --git a/main.cpp b/main.cpp index 195bb27..85d564e 100644 --- a/main.cpp +++ b/main.cpp @@ -21,6 +21,8 @@ #include "utils.h" +typedef enum { BL_NONE, BL_RK05, BL_RL02 } bootloader_t; + bool withUI { false }; uint32_t event { 0 }; std::atomic_bool terminate { false }; @@ -37,32 +39,85 @@ void loadbin(bus *const b, uint16_t base, const char *const file) fclose(fh); } -void setBootLoader(bus *const b) +void setBootLoader(bus *const b, const bootloader_t which) { - cpu *const c = b -> getCpu(); + cpu *const c = b -> getCpu(); - const uint16_t offset = 01000; - constexpr uint16_t bootrom[] = { - 0012700, - 0177406, - 0012710, - 0177400, - 0012740, - 0000005, - 0105710, - 0100376, - 0005007 - }; + uint16_t offset = 0; + const uint16_t *bl = nullptr; + int size = 0; - FILE *fh = fopen("boot.dat", "wb"); + if (which == BL_RK05) { + offset = 01000; - for(size_t i=0; i writeWord(offset + i * 2, bootrom[i]); - fputc(bootrom[i] & 255, fh); - fputc(bootrom[i] >> 8, fh); + static uint16_t rk05_code[] = { + 0012700, + 0177406, + 0012710, + 0177400, + 0012740, + 0000005, + 0105710, + 0100376, + 0005007 + }; + + bl = rk05_code; + + size = 9; + } + else if (which == BL_RL02) { + offset = 01000; + + /* from https://www.pdp-11.nl/peripherals/disk/rl-info.html + static uint16_t rl02_code[] = { + 0012701, + 0174400, + 0012761, + 0000013, + 0000004, + 0012711, + 0000004, + 0105711, + 0100376, + 0005061, + 0000002, + 0005061, + 0000004, + 0012761, + 0177400, + 0000006, + 0012711, + 0000014, + 0105711, + 0100376, + 0005007 + }; + + size = 21; + */ + + // from http://gunkies.org/wiki/RL11_disk_controller + static uint16_t rl02_code[] = { + 0012700, + 0174400, + 0012760, + 0177400, + 0000006, + 0012710, + 0000014, + 0105710, + 0100376, + 0005007, + }; + + size = 10; + + bl = rl02_code; } - fclose(fh); + for(int i=0; i writeWord(offset + i * 2, bl[i]); c -> setRegister(7, offset); } @@ -150,7 +205,7 @@ void help() printf("-R d.rk load file as a RK05 disk device\n"); printf("-p 123 set CPU start pointer to decimal(!) value\n"); printf("-L f.bin load file into memory at address given by -p (and run it)\n"); - printf("-b enable bootloader (build-in)\n"); + printf("-b x enable bootloader (build-in), parameter must be \"rk05\" or \"rl02\"\n"); printf("-n ncurses UI\n"); printf("-d enable debugger\n"); printf("-t enable tracing (disassemble to stderr, requires -d as well)\n"); @@ -175,10 +230,11 @@ int main(int argc, char *argv[]) bool testCases = false; bool run_debugger = false; bool tracing = false; - bool bootloader = false; + + bootloader_t bootloader = BL_NONE; int opt = -1; - while((opt = getopt(argc, argv, "hm:T:r:R:p:ndtL:b")) != -1) + while((opt = getopt(argc, argv, "hm:T:r:R:p:ndtL:b:")) != -1) { switch(opt) { case 'h': @@ -186,7 +242,13 @@ int main(int argc, char *argv[]) return 1; case 'b': - bootloader = true; + if (strcasecmp(optarg, "rk05") == 0) + bootloader = BL_RK05; + else if (strcasecmp(optarg, "rl02") == 0) + bootloader = BL_RL02; + else + error_exit(false, "Bootload \"%s\" not recognized", optarg); + break; case 'd': @@ -257,8 +319,8 @@ int main(int argc, char *argv[]) if (rl02_files.empty() == false) b->add_rl02(new rl02(rl02_files, b, cnsl->get_disk_read_activity_flag(), cnsl->get_disk_write_activity_flag())); - if (bootloader) - setBootLoader(b); + if (bootloader != BL_NONE) + setBootLoader(b, bootloader); running = cnsl->get_running_flag(); diff --git a/rl02.cpp b/rl02.cpp index 52e80ac..9048057 100644 --- a/rl02.cpp +++ b/rl02.cpp @@ -11,6 +11,9 @@ #include "utils.h" +constexpr int sectors_per_track = 40; +constexpr int bytes_per_sector = 256; + static const char * const regnames[] = { "control status", "bus address ", @@ -68,20 +71,25 @@ uint8_t rl02::readByte(const uint16_t addr) uint16_t rl02::readWord(const uint16_t addr) { - const int reg = (addr - RK05_BASE) / 2; + const int reg = (addr - RL02_BASE) / 2; - uint16_t value = 0; + if (addr == RL02_CSR) { // control status + setBit(registers[reg], 0, true); // drive ready (DRDY) + setBit(registers[reg], 7, true); // controller ready (CRDY) + } + + uint16_t value = registers[reg]; // TODO - D(fprintf(stderr, "RK05 read %s/%o: %06o\n", reg[regnames], addr, value);) + D(fprintf(stderr, "RL02 read %s/%o: %06o\n", regnames[reg], addr, value);) return value; } void rl02::writeByte(const uint16_t addr, const uint8_t v) { - uint16_t vtemp = registers[(addr - RK05_BASE) / 2]; + uint16_t vtemp = registers[(addr - RL02_BASE) / 2]; if (addr & 1) { vtemp &= ~0xff00; @@ -95,12 +103,114 @@ void rl02::writeByte(const uint16_t addr, const uint8_t v) writeWord(addr, vtemp); } +uint32_t rl02::calcOffset(const uint16_t da) +{ + int sector = da & 63; + int track = (da >> 6) & 1023; + + uint32_t offset = (sectors_per_track * track + sector) * bytes_per_sector; + + return offset; +} + void rl02::writeWord(const uint16_t addr, uint16_t v) { #if defined(ESP32) digitalWrite(LED_BUILTIN, LOW); #endif + fprintf(stderr, "RL02 write %06o: %06o\n", addr, v); + + const int reg = (addr - RL02_BASE) / 2; + + registers[reg] = v; + + if (addr == RL02_CSR) { // control status + const uint8_t command = (v >> 1) & 7; + + const bool do_exec = !(v & 128); + + fprintf(stderr, "RL02 set command %d, exec: %d\n", command, do_exec); + + uint32_t disk_offset = calcOffset(registers[(RL02_DAR - RL02_BASE) / 2] & ~1); + int device = 0; // TODO + + if (command == 2) { // get status + registers[(RL02_MPR - RL02_BASE) / 2] = 0; +#if 0 + if (registers[(RL02_DAR - RL02_BASE) / 2] & 2) { // get status -> load status word in MPR + registers[(RL02_MPR - RL02_BASE) / 2] = 5 | // lock on + (1 << 3) | // brushes are home + (1 << 7) | // this is an RL02 + 0; + + fprintf(stderr, "RL02 set MPR for status to %06o\n", registers[(RL02_MPR - RL02_BASE) / 2]); + } +#endif + } + else if (command == 6 || command == 7) { // read data / read data without header check + *disk_read_acitivity = true; + + bool proceed = true; + +#if defined(ESP32) + File32 *fh = fhs.at(device); + + if (!fh->seek(disk_offset)) { + fprintf(stderr, "RL02 seek to %d error %s\n", disk_offset, strerror(errno)); + + proceed = false; + } +#else + FILE *fh = nullptr; + + if (size_t(device) >= fhs.size()) + proceed = false; + else { + fh = fhs.at(device); + + if (fseek(fh, disk_offset, SEEK_SET) == -1) { + fprintf(stderr, "RL02 seek error %s\n", strerror(errno)); + proceed = false; + } + } +#endif + + uint32_t memory_address = registers[(RL02_BAR - RL02_BASE) / 2]; + + uint32_t count = (65536 - registers[(RL02_MPR - RL02_BASE) / 2]) * 2; + + fprintf(stderr, "RL02 read %d bytes (dec) from %d (dec) to %06o (oct)\n", count, disk_offset, memory_address); + + uint32_t p = memory_address; + while(proceed && count > 0) { + uint32_t cur = std::min(uint32_t(sizeof xfer_buffer), count); + +#if defined(ESP32) + yield(); + + if (fh->read(xfer_buffer, cur) != size_t(cur)) + D(fprintf(stderr, "RL02 fread error: %s\n", strerror(errno));) +#else + if (fread(xfer_buffer, 1, cur, fh) != size_t(cur)) + D(fprintf(stderr, "RL02 fread error: %s\n", strerror(errno));) +#endif + + for(uint32_t i=0; iwriteByte(p, xfer_buffer[i]); + + count -= cur; + } + + if (registers[(RL02_CSR - RL02_BASE) / 2] & 64) { // interrupt enable? + fprintf(stderr, "RL02 triggering interrupt\n"); + + b->getCpu()->queue_interrupt(5, 0254); + } + + *disk_read_acitivity = false; + } + } #if defined(ESP32) digitalWrite(LED_BUILTIN, HIGH); diff --git a/rl02.h b/rl02.h index d25e96a..d0da43e 100644 --- a/rl02.h +++ b/rl02.h @@ -24,17 +24,21 @@ class bus; class rl02 { private: - bus *const b; - uint16_t registers[7]; - uint8_t xfer_buffer[512]; + bus *const b; + uint16_t registers[4]; + uint8_t xfer_buffer[512]; + #if defined(ESP32) std::vector fhs; #else std::vector fhs; #endif + std::atomic_bool *const disk_read_acitivity { nullptr }; std::atomic_bool *const disk_write_acitivity { nullptr }; + uint32_t calcOffset(uint16_t); + public: rl02(const std::vector & files, bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity); virtual ~rl02(); From 1d969dfb0038870c73a7b9b172ce32716587ce01 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Fri, 10 Jun 2022 19:54:10 +0200 Subject: [PATCH 4/5] p11 .x11 test files loader --- main.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/main.cpp b/main.cpp index 85d564e..5408588 100644 --- a/main.cpp +++ b/main.cpp @@ -185,6 +185,44 @@ uint16_t loadTape(bus *const b, const char *const file) return start; } +void load_p11_x11(bus *const b, const std::string & file) +{ + FILE *fh = fopen(file.c_str(), "rb"); + if (!fh) + error_exit(true, "Cannot open %s", file.c_str()); + + uint16_t addr = 0; + int n = 0; + + while(!feof(fh)) { + char buffer[4096]; + + if (!fgets(buffer, sizeof buffer, fh)) + break; + + if (n) { + uint8_t byte = strtol(buffer, NULL, 16); + + b->writeByte(addr, byte); + + n--; + + addr++; + } + else { + std::vector parts = split(buffer, " "); + + addr = strtol(parts[0].c_str(), NULL, 16); + n = strtol(parts[1].c_str(), NULL, 16); + } + } + + fclose(fh); + + cpu *const c = b -> getCpu(); + c -> setRegister(7, 0); +} + volatile bool sw = false; void sw_handler(int s) { @@ -347,6 +385,8 @@ int main(int argc, char *argv[]) // loadbin(b, 0, "test.dat"); // c->setRegister(7, 0); +//load_p11_x11(b, "/home/folkert/Projects/PDP-11/work/p11-2.10i/Tests/mtpi.x11"); + cnsl->start_thread(); if (run_debugger) From eb96e71592ebece720cf3bbcddc8d0c26332c479 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Fri, 10 Jun 2022 20:30:00 +0200 Subject: [PATCH 5/5] MFPI/MTPI require special handling for SP --- cpu.cpp | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/cpu.cpp b/cpu.cpp index d520a34..1a37fd1 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -1275,12 +1275,20 @@ bool cpu::single_operand_instructions(const uint16_t instr) if ((b->getMMR1() & 0160000) == 0) b->addToMMR1(-2, 6); - // calculate address in current address space - uint16_t a = getGAMAddress(dst_mode, dst_reg, false, false); - // reed from previous space - uint16_t v = b -> read(a, false, true); + bool set_flags = true; + uint16_t v = 0xffff; - bool set_flags = a != 0177776; + if (dst_mode == 0) + v = getRegister(dst_reg, true); + else { + // calculate address in current address space + uint16_t a = getGAMAddress(dst_mode, dst_reg, false, false); + + set_flags = a != 0177776; + + // read from previous space + v = b -> read(a, false, true); + } if (set_flags) { setPSW_n(SIGN(v, false)); @@ -1304,9 +1312,17 @@ bool cpu::single_operand_instructions(const uint16_t instr) // retrieve word from '15/14'-stack uint16_t v = popStack(); - uint16_t a = getGAMAddress(dst_mode, dst_reg, false, false); + uint16_t a = 0xffff; - bool set_flags = a != 0177776; + bool set_flags = true; + + if (dst_mode == 0) + setRegister(dst_reg, true, v); + else { + a = getGAMAddress(dst_mode, dst_reg, false, false); + + set_flags = a != 0177776; + } if (set_flags) { setPSW_n(SIGN(v, false)); @@ -1314,7 +1330,8 @@ bool cpu::single_operand_instructions(const uint16_t instr) setPSW_v(false); } - b -> write(a, false, v, true); // put in '13/12' address space + if (dst_mode != 0) + b -> write(a, false, v, true); // put in '13/12' address space break; }