commit
d0d2fe76b3
17 changed files with 284 additions and 182 deletions
|
@ -17,6 +17,7 @@ add_executable(
|
||||||
error.cpp
|
error.cpp
|
||||||
kw11-l.cpp
|
kw11-l.cpp
|
||||||
loaders.cpp
|
loaders.cpp
|
||||||
|
log.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
memory.cpp
|
memory.cpp
|
||||||
rk05.cpp
|
rk05.cpp
|
||||||
|
|
157
bus.cpp
157
bus.cpp
|
@ -7,6 +7,7 @@
|
||||||
#include "bus.h"
|
#include "bus.h"
|
||||||
#include "gen.h"
|
#include "gen.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "log.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "tm-11.h"
|
#include "tm-11.h"
|
||||||
#include "tty.h"
|
#include "tty.h"
|
||||||
|
@ -56,36 +57,36 @@ uint16_t bus::read(const uint16_t a, const bool word_mode, const bool use_prev,
|
||||||
|
|
||||||
if (a >= 0160000) {
|
if (a >= 0160000) {
|
||||||
if (word_mode)
|
if (word_mode)
|
||||||
D(fprintf(stderr, "READ I/O %06o in byte mode\n", a);)
|
DOLOG(debug, false, "READ I/O %06o in byte mode", a);
|
||||||
|
|
||||||
if (a == 0177750) { // MAINT
|
if (a == 0177750) { // MAINT
|
||||||
D(fprintf(stderr, "read MAINT\n");)
|
DOLOG(debug, !peek_only, "read MAINT");
|
||||||
return 1; // POWER OK
|
return 1; // POWER OK
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177570) { // console switch & display register
|
if (a == 0177570) { // console switch & display register
|
||||||
D(fprintf(stderr, "read console switch\n");)
|
DOLOG(debug, !peek_only, "read console switch");
|
||||||
|
|
||||||
return debug_mode ? 128 : 0;
|
return debug_mode ? 128 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0172540) { // KW11P programmable clock
|
if (a == 0172540) { // KW11P programmable clock
|
||||||
D(fprintf(stderr, "read programmable clock\n");)
|
DOLOG(debug, !peek_only, "read programmable clock");
|
||||||
return 128;
|
return 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177772) { // PIR
|
if (a == 0177772) { // PIR
|
||||||
D(fprintf(stderr, "read PIT\n");)
|
DOLOG(debug, !peek_only, "read PIT");
|
||||||
return PIR;
|
return PIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177546) { // line frequency clock and status register
|
if (a == 0177546) { // line frequency clock and status register
|
||||||
D(fprintf(stderr, "read line freq clock\n");)
|
DOLOG(debug, !peek_only, "read line freq clock");
|
||||||
return lf_csr;
|
return lf_csr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177514) { // printer, CSR register, LP11
|
if (a == 0177514) { // printer, CSR register, LP11
|
||||||
D(fprintf(stderr, "read LP11 CSR\n");)
|
DOLOG(debug, !peek_only, "read LP11 CSR");
|
||||||
return 0x80;
|
return 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,150 +94,150 @@ uint16_t bus::read(const uint16_t a, const bool word_mode, const bool use_prev,
|
||||||
if (a >= 0172200 && a < 0172220) {
|
if (a >= 0172200 && a < 0172220) {
|
||||||
int page = (a >> 1) & 7;
|
int page = (a >> 1) & 7;
|
||||||
uint16_t t = pages[001][0][page].pdr;
|
uint16_t t = pages[001][0][page].pdr;
|
||||||
D(fprintf(stderr, "read supervisor I PDR for %d: %o\n", page, t);)
|
DOLOG(debug, !peek_only, "read supervisor I PDR for %d: %o", page, t);
|
||||||
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
||||||
}
|
}
|
||||||
else if (a >= 0172220 && a < 0172240) {
|
else if (a >= 0172220 && a < 0172240) {
|
||||||
int page = (a >> 1) & 7;
|
int page = (a >> 1) & 7;
|
||||||
uint16_t t = pages[001][1][page].pdr;
|
uint16_t t = pages[001][1][page].pdr;
|
||||||
D(fprintf(stderr, "read supervisor D PDR for %d: %o\n", page, t);)
|
DOLOG(debug, !peek_only, "read supervisor D PDR for %d: %o", page, t);
|
||||||
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
||||||
}
|
}
|
||||||
else if (a >= 0172240 && a < 0172260) {
|
else if (a >= 0172240 && a < 0172260) {
|
||||||
int page = (a >> 1) & 7;
|
int page = (a >> 1) & 7;
|
||||||
uint16_t t = pages[001][0][page].par;
|
uint16_t t = pages[001][0][page].par;
|
||||||
D(fprintf(stderr, "read supervisor I PAR for %d: %o (phys: %07o)\n", page, t, t * 64);)
|
DOLOG(debug, !peek_only, "read supervisor I PAR for %d: %o (phys: %07o)", page, t, t * 64);
|
||||||
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
||||||
}
|
}
|
||||||
else if (a >= 0172260 && a < 0172300) {
|
else if (a >= 0172260 && a < 0172300) {
|
||||||
int page = (a >> 1) & 7;
|
int page = (a >> 1) & 7;
|
||||||
uint16_t t = pages[001][1][page].par;
|
uint16_t t = pages[001][1][page].par;
|
||||||
D(fprintf(stderr, "read supervisor D PAR for %d: %o (phys: %07o)\n", page, t, t * 64);)
|
DOLOG(debug, !peek_only, "read supervisor D PAR for %d: %o (phys: %07o)", page, t, t * 64);
|
||||||
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
||||||
}
|
}
|
||||||
else if (a >= 0172300 && a < 0172320) {
|
else if (a >= 0172300 && a < 0172320) {
|
||||||
int page = (a >> 1) & 7;
|
int page = (a >> 1) & 7;
|
||||||
uint16_t t = pages[000][0][page].pdr;
|
uint16_t t = pages[000][0][page].pdr;
|
||||||
D(fprintf(stderr, "read kernel I PDR for %d: %o\n", page, t);)
|
DOLOG(debug, !peek_only, "read kernel I PDR for %d: %o", page, t);
|
||||||
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
||||||
}
|
}
|
||||||
else if (a >= 0172320 && a < 0172340) {
|
else if (a >= 0172320 && a < 0172340) {
|
||||||
int page = (a >> 1) & 7;
|
int page = (a >> 1) & 7;
|
||||||
uint16_t t = pages[000][1][page].pdr;
|
uint16_t t = pages[000][1][page].pdr;
|
||||||
D(fprintf(stderr, "read kernel D PDR for %d: %o\n", page, t);)
|
DOLOG(debug, !peek_only, "read kernel D PDR for %d: %o", page, t);
|
||||||
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
||||||
}
|
}
|
||||||
else if (a >= 0172340 && a < 0172360) {
|
else if (a >= 0172340 && a < 0172360) {
|
||||||
int page = (a >> 1) & 7;
|
int page = (a >> 1) & 7;
|
||||||
uint16_t t = pages[000][0][page].par;
|
uint16_t t = pages[000][0][page].par;
|
||||||
D(fprintf(stderr, "read kernel I PAR for %d: %o (phys: %07o)\n", page, t, t * 64);)
|
DOLOG(debug, !peek_only, "read kernel I PAR for %d: %o (phys: %07o)", page, t, t * 64);
|
||||||
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
||||||
}
|
}
|
||||||
else if (a >= 0172360 && a < 0172400) {
|
else if (a >= 0172360 && a < 0172400) {
|
||||||
int page = (a >> 1) & 7;
|
int page = (a >> 1) & 7;
|
||||||
uint16_t t = pages[000][1][page].par;
|
uint16_t t = pages[000][1][page].par;
|
||||||
D(fprintf(stderr, "read kernel D PAR for %d: %o (phys: %07o)\n", page, t, t * 64);)
|
DOLOG(debug, !peek_only, "read kernel D PAR for %d: %o (phys: %07o)", page, t, t * 64);
|
||||||
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
||||||
}
|
}
|
||||||
else if (a >= 0177600 && a < 0177620) {
|
else if (a >= 0177600 && a < 0177620) {
|
||||||
int page = (a >> 1) & 7;
|
int page = (a >> 1) & 7;
|
||||||
uint16_t t = pages[003][0][page].pdr;
|
uint16_t t = pages[003][0][page].pdr;
|
||||||
D(fprintf(stderr, "read userspace I PDR for %d: %o\n", page, t);)
|
DOLOG(debug, !peek_only, "read userspace I PDR for %d: %o", page, t);
|
||||||
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
||||||
}
|
}
|
||||||
else if (a >= 0177620 && a < 0177640) {
|
else if (a >= 0177620 && a < 0177640) {
|
||||||
int page = (a >> 1) & 7;
|
int page = (a >> 1) & 7;
|
||||||
uint16_t t = pages[003][1][page].pdr;
|
uint16_t t = pages[003][1][page].pdr;
|
||||||
D(fprintf(stderr, "read userspace D PDR for %d: %o\n", page, t);)
|
DOLOG(debug, !peek_only, "read userspace D PDR for %d: %o", page, t);
|
||||||
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
||||||
}
|
}
|
||||||
else if (a >= 0177640 && a < 0177660) {
|
else if (a >= 0177640 && a < 0177660) {
|
||||||
int page = (a >> 1) & 7;
|
int page = (a >> 1) & 7;
|
||||||
uint16_t t = pages[003][0][page].par;
|
uint16_t t = pages[003][0][page].par;
|
||||||
D(fprintf(stderr, "read userspace I PAR for %d: %o (phys: %07o)\n", page, t, t * 64);)
|
DOLOG(debug, !peek_only, "read userspace I PAR for %d: %o (phys: %07o)", page, t, t * 64);
|
||||||
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
||||||
}
|
}
|
||||||
else if (a >= 0177660 && a < 0177700) {
|
else if (a >= 0177660 && a < 0177700) {
|
||||||
int page = (a >> 1) & 7;
|
int page = (a >> 1) & 7;
|
||||||
uint16_t t = pages[003][1][page].par;
|
uint16_t t = pages[003][1][page].par;
|
||||||
D(fprintf(stderr, "read userspace D PAR for %d: %o (phys: %07o)\n", page, t, t * 64);)
|
DOLOG(debug, !peek_only, "read userspace D PAR for %d: %o (phys: %07o)", page, t, t * 64);
|
||||||
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
return word_mode ? (a & 1 ? t >> 8 : t & 255) : t;
|
||||||
}
|
}
|
||||||
///////////
|
///////////
|
||||||
|
|
||||||
if (word_mode) {
|
if (word_mode) {
|
||||||
if (a == 0177776) { // PSW
|
if (a == 0177776) { // PSW
|
||||||
D(fprintf(stderr, "readb PSW LSB\n");)
|
DOLOG(debug, !peek_only, "readb PSW LSB");
|
||||||
return c -> getPSW() & 255;
|
return c -> getPSW() & 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177777) {
|
if (a == 0177777) {
|
||||||
D(fprintf(stderr, "readb PSW MSB\n");)
|
DOLOG(debug, !peek_only, "readb PSW MSB");
|
||||||
return c -> getPSW() >> 8;
|
return c -> getPSW() >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177774) { // stack limit register
|
if (a == 0177774) { // stack limit register
|
||||||
D(fprintf(stderr, "readb stack limit register\n");)
|
DOLOG(debug, !peek_only, "readb stack limit register");
|
||||||
return c -> getStackLimitRegister() & 0xff;
|
return c -> getStackLimitRegister() & 0xff;
|
||||||
}
|
}
|
||||||
if (a == 0177775) { // stack limit register
|
if (a == 0177775) { // stack limit register
|
||||||
D(fprintf(stderr, "readb stack limit register\n");)
|
DOLOG(debug, !peek_only, "readb stack limit register");
|
||||||
return c -> getStackLimitRegister() >> 8;
|
return c -> getStackLimitRegister() >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a >= 0177700 && a <= 0177705) { // kernel R0-R5
|
if (a >= 0177700 && a <= 0177705) { // kernel R0-R5
|
||||||
D(fprintf(stderr, "readb kernel R%d\n", a - 0177700);)
|
DOLOG(debug, !peek_only, "readb kernel R%d", a - 0177700);
|
||||||
return c -> getRegister(false, a - 0177700) & 0xff;
|
return c -> getRegister(false, a - 0177700) & 0xff;
|
||||||
}
|
}
|
||||||
if (a >= 0177710 && a <= 0177715) { // user R0-R5
|
if (a >= 0177710 && a <= 0177715) { // user R0-R5
|
||||||
D(fprintf(stderr, "readb user R%d\n", a - 0177710);)
|
DOLOG(debug, !peek_only, "readb user R%d", a - 0177710);
|
||||||
return c -> getRegister(true, a - 0177710) & 0xff;
|
return c -> getRegister(true, a - 0177710) & 0xff;
|
||||||
}
|
}
|
||||||
if (a == 0177706) { // kernel SP
|
if (a == 0177706) { // kernel SP
|
||||||
D(fprintf(stderr, "readb kernel sp\n");)
|
DOLOG(debug, !peek_only, "readb kernel sp");
|
||||||
return c -> getStackPointer(0) & 0xff;
|
return c -> getStackPointer(0) & 0xff;
|
||||||
}
|
}
|
||||||
if (a == 0177707) { // PC
|
if (a == 0177707) { // PC
|
||||||
D(fprintf(stderr, "readb pc\n");)
|
DOLOG(debug, !peek_only, "readb pc");
|
||||||
return c -> getPC() & 0xff;
|
return c -> getPC() & 0xff;
|
||||||
}
|
}
|
||||||
if (a == 0177716) { // supervisor SP
|
if (a == 0177716) { // supervisor SP
|
||||||
D(fprintf(stderr, "readb supervisor sp\n");)
|
DOLOG(debug, !peek_only, "readb supervisor sp");
|
||||||
return c -> getStackPointer(1) & 0xff;
|
return c -> getStackPointer(1) & 0xff;
|
||||||
}
|
}
|
||||||
if (a == 0177717) { // user SP
|
if (a == 0177717) { // user SP
|
||||||
D(fprintf(stderr, "readb user sp\n");)
|
DOLOG(debug, !peek_only, "readb user sp");
|
||||||
return c -> getStackPointer(3) & 0xff;
|
return c -> getStackPointer(3) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177766) { // cpu error register
|
if (a == 0177766) { // cpu error register
|
||||||
D(fprintf(stderr, "readb cpuerr\n");)
|
DOLOG(debug, !peek_only, "readb cpuerr");
|
||||||
return CPUERR & 0xff;
|
return CPUERR & 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (a == 0177572) {
|
if (a == 0177572) {
|
||||||
D(fprintf(stderr, "read MMR0\n");)
|
DOLOG(debug, !peek_only, "read MMR0");
|
||||||
return MMR0;
|
return MMR0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177574) { // MMR1
|
if (a == 0177574) { // MMR1
|
||||||
D(fprintf(stderr, "read MMR1\n");)
|
DOLOG(debug, !peek_only, "read MMR1");
|
||||||
return MMR1;
|
return MMR1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177576) { // MMR2
|
if (a == 0177576) { // MMR2
|
||||||
D(fprintf(stderr, "read MMR2\n");)
|
DOLOG(debug, !peek_only, "read MMR2");
|
||||||
return MMR2;
|
return MMR2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0172516) { // MMR3
|
if (a == 0172516) { // MMR3
|
||||||
D(fprintf(stderr, "read MMR3\n");)
|
DOLOG(debug, !peek_only, "read MMR3");
|
||||||
return MMR3;
|
return MMR3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177776) { // PSW
|
if (a == 0177776) { // PSW
|
||||||
D(fprintf(stderr, "read PSW\n");)
|
DOLOG(debug, !peek_only, "read PSW");
|
||||||
return c -> getPSW();
|
return c -> getPSW();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,32 +246,32 @@ uint16_t bus::read(const uint16_t a, const bool word_mode, const bool use_prev,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a >= 0177700 && a <= 0177705) { // kernel R0-R5
|
if (a >= 0177700 && a <= 0177705) { // kernel R0-R5
|
||||||
D(fprintf(stderr, "read kernel R%d\n", a - 0177700);)
|
DOLOG(debug, !peek_only, "read kernel R%d", a - 0177700);
|
||||||
return c -> getRegister(false, a - 0177700);
|
return c -> getRegister(false, a - 0177700);
|
||||||
}
|
}
|
||||||
if (a >= 0177710 && a <= 0177715) { // user R0-R5
|
if (a >= 0177710 && a <= 0177715) { // user R0-R5
|
||||||
D(fprintf(stderr, "read user R%d\n", a - 0177710);)
|
DOLOG(debug, !peek_only, "read user R%d", a - 0177710);
|
||||||
return c -> getRegister(true, a - 0177710);
|
return c -> getRegister(true, a - 0177710);
|
||||||
}
|
}
|
||||||
if (a == 0177706) { // kernel SP
|
if (a == 0177706) { // kernel SP
|
||||||
D(fprintf(stderr, "read kernel sp\n");)
|
DOLOG(debug, !peek_only, "read kernel sp");
|
||||||
return c -> getStackPointer(0);
|
return c -> getStackPointer(0);
|
||||||
}
|
}
|
||||||
if (a == 0177707) { // PC
|
if (a == 0177707) { // PC
|
||||||
D(fprintf(stderr, "read pc\n");)
|
DOLOG(debug, !peek_only, "read pc");
|
||||||
return c -> getPC();
|
return c -> getPC();
|
||||||
}
|
}
|
||||||
if (a == 0177716) { // supervisor SP
|
if (a == 0177716) { // supervisor SP
|
||||||
D(fprintf(stderr, "read supervisor sp\n");)
|
DOLOG(debug, !peek_only, "read supervisor sp");
|
||||||
return c -> getStackPointer(1);
|
return c -> getStackPointer(1);
|
||||||
}
|
}
|
||||||
if (a == 0177717) { // user SP
|
if (a == 0177717) { // user SP
|
||||||
D(fprintf(stderr, "read user sp\n");)
|
DOLOG(debug, !peek_only, "read user sp");
|
||||||
return c -> getStackPointer(3);
|
return c -> getStackPointer(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177766) { // cpu error register
|
if (a == 0177766) { // cpu error register
|
||||||
D(fprintf(stderr, "read CPUERR\n");)
|
DOLOG(debug, !peek_only, "read CPUERR");
|
||||||
return CPUERR;
|
return CPUERR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,9 +298,9 @@ uint16_t bus::read(const uint16_t a, const bool word_mode, const bool use_prev,
|
||||||
return system_size & 65535;
|
return system_size & 65535;
|
||||||
|
|
||||||
if (a & 1)
|
if (a & 1)
|
||||||
D(fprintf(stderr, "bus::readWord: odd address UNHANDLED %o\n", a);)
|
DOLOG(debug, !peek_only, "bus::readWord: odd address UNHANDLED %o", a);
|
||||||
|
|
||||||
D(fprintf(stderr, "UNHANDLED read %o(%c)\n", a, word_mode ? 'B' : ' ');)
|
DOLOG(debug, !peek_only, "UNHANDLED read %o(%c)", a, word_mode ? 'B' : ' ');
|
||||||
|
|
||||||
// c -> busError();
|
// c -> busError();
|
||||||
|
|
||||||
|
@ -308,19 +309,19 @@ 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;
|
int run_mode = (c->getPSW() >> (use_prev ? 12 : 14)) & 3;
|
||||||
|
|
||||||
uint32_t m_offset = calculate_physical_address(run_mode, a, !peek_only, false);
|
uint32_t m_offset = calculate_physical_address(run_mode, a, !peek_only, false, peek_only);
|
||||||
|
|
||||||
if (word_mode)
|
if (word_mode)
|
||||||
temp = m -> readByte(m_offset);
|
temp = m -> readByte(m_offset);
|
||||||
else
|
else
|
||||||
temp = m -> readWord(m_offset);
|
temp = m -> readWord(m_offset);
|
||||||
|
|
||||||
D(fprintf(stderr, "READ from %06o/%07o: %o\n", a, m_offset, temp);)
|
DOLOG(debug, !peek_only, "READ from %06o/%07o: %o", a, m_offset, temp);
|
||||||
|
|
||||||
return temp;
|
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)
|
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 m_offset = 0;
|
uint32_t m_offset = 0;
|
||||||
|
|
||||||
|
@ -375,7 +376,7 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c
|
||||||
bool direction = pages[run_mode][0][apf].pdr & 8; // TODO: D/I
|
bool direction = pages[run_mode][0][apf].pdr & 8; // TODO: D/I
|
||||||
|
|
||||||
if (m_offset >= n_pages * 8192) {
|
if (m_offset >= n_pages * 8192) {
|
||||||
D(fprintf(stderr, "bus::calculate_physical_address %o >= %o\n", m_offset, n_pages * 8192);)
|
DOLOG(debug, !peek_only, "bus::calculate_physical_address %o >= %o", m_offset, n_pages * 8192);
|
||||||
c->schedule_trap(04); // invalid address
|
c->schedule_trap(04); // invalid address
|
||||||
|
|
||||||
MMR0 |= 1 << 15; // non-resident
|
MMR0 |= 1 << 15; // non-resident
|
||||||
|
@ -386,7 +387,7 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((p_offset >= pdr_len && direction == false) || (p_offset < pdr_len && direction == true)) {
|
if ((p_offset >= pdr_len && direction == false) || (p_offset < pdr_len && direction == true)) {
|
||||||
D(fprintf(stderr, "bus::calculate_physical_address::p_offset %o >= %o\n", p_offset, pdr_len);)
|
DOLOG(debug, !peek_only, "bus::calculate_physical_address::p_offset %o >= %o", p_offset, pdr_len);
|
||||||
c->schedule_trap(0250); // invalid access
|
c->schedule_trap(0250); // invalid access
|
||||||
|
|
||||||
MMR0 |= 1 << 14; // length
|
MMR0 |= 1 << 14; // length
|
||||||
|
@ -397,11 +398,11 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
D(fprintf(stderr, "virtual address %06o maps to physical address %07o (run_mode: %d, par: %07o)\n", a, m_offset, run_mode, pages[run_mode][0][apf].par * 64);) // TODO: D/I
|
DOLOG(debug, !peek_only, "virtual address %06o maps to physical address %07o (run_mode: %d, par: %07o)", a, m_offset, run_mode, pages[run_mode][0][apf].par * 64); // TODO: D/I
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_offset = a;
|
m_offset = a;
|
||||||
D(fprintf(stderr, "virtual address %06o maps to physical address %07o\n", a, m_offset);)
|
DOLOG(debug, !peek_only, "virtual address %06o maps to physical address %07o", a, m_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_offset;
|
return m_offset;
|
||||||
|
@ -425,12 +426,12 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons
|
||||||
if (a >= 0160000) {
|
if (a >= 0160000) {
|
||||||
if (word_mode) {
|
if (word_mode) {
|
||||||
assert(value < 256);
|
assert(value < 256);
|
||||||
D(fprintf(stderr, "WRITE I/O %06o in byte mode\n", a);)
|
DOLOG(debug, true, "WRITE I/O %06o in byte mode", a);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (word_mode) {
|
if (word_mode) {
|
||||||
if (a == 0177776 || a == 0177777) { // PSW
|
if (a == 0177776 || a == 0177777) { // PSW
|
||||||
D(fprintf(stderr, "writeb PSW %s\n", a & 1 ? "MSB" : "LSB");)
|
DOLOG(debug, true, "writeb PSW %s", a & 1 ? "MSB" : "LSB");
|
||||||
uint16_t vtemp = c -> getPSW();
|
uint16_t vtemp = c -> getPSW();
|
||||||
|
|
||||||
if (a & 1)
|
if (a & 1)
|
||||||
|
@ -444,7 +445,7 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177774 || a == 0177775) { // stack limit register
|
if (a == 0177774 || a == 0177775) { // stack limit register
|
||||||
D(fprintf(stderr, "writeb Set stack limit register: %o\n", value);)
|
DOLOG(debug, true, "writeb Set stack limit register: %o", value);
|
||||||
uint16_t v = c -> getStackLimitRegister();
|
uint16_t v = c -> getStackLimitRegister();
|
||||||
|
|
||||||
if (a & 1)
|
if (a & 1)
|
||||||
|
@ -458,44 +459,44 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (a == 0177776) { // PSW
|
if (a == 0177776) { // PSW
|
||||||
D(fprintf(stderr, "write PSW %o\n", value);)
|
DOLOG(debug, true, "write PSW %o", value);
|
||||||
c -> setPSW(value, false);
|
c -> setPSW(value, false);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177774) { // stack limit register
|
if (a == 0177774) { // stack limit register
|
||||||
D(fprintf(stderr, "write Set stack limit register: %o\n", value);)
|
DOLOG(debug, true, "write Set stack limit register: %o", value);
|
||||||
c -> setStackLimitRegister(value);
|
c -> setStackLimitRegister(value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a >= 0177700 && a <= 0177705) { // kernel R0-R5
|
if (a >= 0177700 && a <= 0177705) { // kernel R0-R5
|
||||||
D(fprintf(stderr, "write kernel R%d: %o\n", a - 01777700, value);)
|
DOLOG(debug, true, "write kernel R%d: %o", a - 01777700, value);
|
||||||
c -> setRegister(false, a - 0177700, value);
|
c -> setRegister(false, a - 0177700, value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
if (a >= 0177710 && a <= 0177715) { // user R0-R5
|
if (a >= 0177710 && a <= 0177715) { // user R0-R5
|
||||||
D(fprintf(stderr, "write user R%d: %o\n", a - 01777710, value);)
|
DOLOG(debug, true, "write user R%d: %o", a - 01777710, value);
|
||||||
c -> setRegister(true, a - 0177710, value);
|
c -> setRegister(true, a - 0177710, value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
if (a == 0177706) { // kernel SP
|
if (a == 0177706) { // kernel SP
|
||||||
D(fprintf(stderr, "write kernel SP: %o\n", value);)
|
DOLOG(debug, true, "write kernel SP: %o", value);
|
||||||
c -> setStackPointer(0, value);
|
c -> setStackPointer(0, value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
if (a == 0177707) { // PC
|
if (a == 0177707) { // PC
|
||||||
D(fprintf(stderr, "write PC: %o\n", value);)
|
DOLOG(debug, true, "write PC: %o", value);
|
||||||
c -> setPC(value);
|
c -> setPC(value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
if (a == 0177716) { // supervisor SP
|
if (a == 0177716) { // supervisor SP
|
||||||
D(fprintf(stderr, "write supervisor sp: %o\n", value);)
|
DOLOG(debug, true, "write supervisor sp: %o", value);
|
||||||
c -> setStackPointer(1, value);
|
c -> setStackPointer(1, value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
if (a == 0177717) { // user SP
|
if (a == 0177717) { // user SP
|
||||||
D(fprintf(stderr, "write user sp: %o\n", value);)
|
DOLOG(debug, true, "write user sp: %o", value);
|
||||||
c -> setStackPointer(3, value);
|
c -> setStackPointer(3, value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -506,19 +507,19 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177766) { // cpu error register
|
if (a == 0177766) { // cpu error register
|
||||||
D(fprintf(stderr, "write CPUERR: %o\n", value);)
|
DOLOG(debug, true, "write CPUERR: %o", value);
|
||||||
CPUERR = 0;
|
CPUERR = 0;
|
||||||
return CPUERR;
|
return CPUERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0172516) { // MMR3
|
if (a == 0172516) { // MMR3
|
||||||
D(fprintf(stderr, "write set MMR3: %o\n", value);)
|
DOLOG(debug, true, "write set MMR3: %o", value);
|
||||||
MMR3 = value & 067;
|
MMR3 = value & 067;
|
||||||
return MMR3;
|
return MMR3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177572) { // MMR0
|
if (a == 0177572) { // MMR0
|
||||||
D(fprintf(stderr, "write set MMR0: %o\n", value);)
|
DOLOG(debug, true, "write set MMR0: %o", value);
|
||||||
|
|
||||||
MMR0 = value & ~(3 << 10); // bit 10 & 11 always read as 0
|
MMR0 = value & ~(3 << 10); // bit 10 & 11 always read as 0
|
||||||
|
|
||||||
|
@ -529,13 +530,13 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177772) { // PIR
|
if (a == 0177772) { // PIR
|
||||||
D(fprintf(stderr, "write set PIR: %o\n", value);)
|
DOLOG(debug, true, "write set PIR: %o", value);
|
||||||
PIR = value; // TODO
|
PIR = value; // TODO
|
||||||
return PIR;
|
return PIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == 0177546) { // line frequency clock and status register
|
if (a == 0177546) { // line frequency clock and status register
|
||||||
D(fprintf(stderr, "write set LFC/SR: %o\n", value);)
|
DOLOG(debug, true, "write set LFC/SR: %o", value);
|
||||||
lf_csr = value;
|
lf_csr = value;
|
||||||
return lf_csr;
|
return lf_csr;
|
||||||
}
|
}
|
||||||
|
@ -574,7 +575,7 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons
|
||||||
pages[001][is_d][page].pdr = value;
|
pages[001][is_d][page].pdr = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
D(fprintf(stderr, "write supervisor %c PDR for %d: %o\n", is_d ? 'D' : 'I', page, word_mode ? value & 0xff : value);)
|
DOLOG(debug, true, "write supervisor %c PDR for %d: %o", is_d ? 'D' : 'I', page, word_mode ? value & 0xff : value);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -590,7 +591,7 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons
|
||||||
pages[001][is_d][page].par = value;
|
pages[001][is_d][page].par = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
D(fprintf(stderr, "write supervisor %c PAR for %d: %o (%07o)\n", is_d ? 'D' : 'I', page, word_mode ? value & 0xff : value, pages[001][is_d][page].par * 64);)
|
DOLOG(debug, true, "write supervisor %c PAR for %d: %o (%07o)", is_d ? 'D' : 'I', page, word_mode ? value & 0xff : value, pages[001][is_d][page].par * 64);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -608,7 +609,7 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons
|
||||||
pages[000][is_d][page].pdr = value;
|
pages[000][is_d][page].pdr = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
D(fprintf(stderr, "write kernel %c PDR for %d: %o\n", is_d ? 'D' : 'I', page, word_mode ? value & 0xff : value);)
|
DOLOG(debug, true, "write kernel %c PDR for %d: %o", is_d ? 'D' : 'I', page, word_mode ? value & 0xff : value);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -624,7 +625,7 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons
|
||||||
pages[000][is_d][page].par = value;
|
pages[000][is_d][page].par = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
D(fprintf(stderr, "write kernel %c PAR for %d: %o (%07o)\n", is_d ? 'D' : 'I', page, word_mode ? value & 0xff : value, pages[000][is_d][page].par * 64);)
|
DOLOG(debug, true, "write kernel %c PAR for %d: %o (%07o)", is_d ? 'D' : 'I', page, word_mode ? value & 0xff : value, pages[000][is_d][page].par * 64);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -642,7 +643,7 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons
|
||||||
pages[003][is_d][page].pdr = value;
|
pages[003][is_d][page].pdr = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
D(fprintf(stderr, "write user %c PDR for %d: %o\n", is_d ? 'D' : 'I', page, word_mode ? value & 0xff : value);)
|
DOLOG(debug, true, "write user %c PDR for %d: %o", is_d ? 'D' : 'I', page, word_mode ? value & 0xff : value);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -658,7 +659,7 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons
|
||||||
pages[003][is_d][page].par = value;
|
pages[003][is_d][page].par = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
D(fprintf(stderr, "write user %c PAR for %d: %o (%07o)\n", is_d ? 'D' : 'I', page, word_mode ? value & 0xff : value, pages[003][is_d][page].par * 64);)
|
DOLOG(debug, true, "write user %c PAR for %d: %o (%07o)", is_d ? 'D' : 'I', page, word_mode ? value & 0xff : value, pages[003][is_d][page].par * 64);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -677,14 +678,14 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons
|
||||||
///////////
|
///////////
|
||||||
|
|
||||||
if (a == 0177374) { // TODO
|
if (a == 0177374) { // TODO
|
||||||
fprintf(stderr, "char: %c\n", value & 127);
|
DOLOG(debug, true, "char: %c", value & 127);
|
||||||
return 128;
|
return 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a & 1)
|
if (a & 1)
|
||||||
D(fprintf(stderr, "bus::writeWord: odd address UNHANDLED\n");)
|
DOLOG(info, true, "bus::writeWord: odd address UNHANDLED");
|
||||||
|
|
||||||
D(fprintf(stderr, "UNHANDLED write %o(%c): %o\n", a, word_mode ? 'B' : ' ', value);)
|
DOLOG(info, true, "UNHANDLED write %o(%c): %o", a, word_mode ? 'B' : ' ', value);
|
||||||
|
|
||||||
// c -> busError();
|
// c -> busError();
|
||||||
|
|
||||||
|
@ -693,9 +694,9 @@ 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;
|
int run_mode = (c->getPSW() >> (use_prev ? 12 : 14)) & 3;
|
||||||
|
|
||||||
uint32_t m_offset = calculate_physical_address(run_mode, a, true, true);
|
uint32_t m_offset = calculate_physical_address(run_mode, a, true, true, true);
|
||||||
|
|
||||||
D(fprintf(stderr, "WRITE to %06o/%07o: %o\n", a, m_offset, value);)
|
DOLOG(debug, true, "WRITE to %06o/%07o: %o", a, m_offset, value);
|
||||||
|
|
||||||
if (word_mode)
|
if (word_mode)
|
||||||
m->writeByte(m_offset, value);
|
m->writeByte(m_offset, value);
|
||||||
|
|
2
bus.h
2
bus.h
|
@ -84,5 +84,5 @@ public:
|
||||||
|
|
||||||
uint16_t get_switch_register() const { return switch_register; }
|
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);
|
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);
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "gen.h"
|
#include "gen.h"
|
||||||
|
#include "log.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,7 +169,7 @@ void console::put_char(const char c)
|
||||||
tx = 0;
|
tx = 0;
|
||||||
else if (c == 10) {
|
else if (c == 10) {
|
||||||
if (debug_buffer.empty() == false) {
|
if (debug_buffer.empty() == false) {
|
||||||
D(fprintf(stderr, "TTY: %s\n", debug_buffer.c_str());)
|
DOLOG(::debug, true, "TTY: %s", debug_buffer.c_str());
|
||||||
|
|
||||||
debug_buffer.clear();
|
debug_buffer.clear();
|
||||||
}
|
}
|
||||||
|
@ -209,7 +210,7 @@ void console::put_string(const std::string & what)
|
||||||
|
|
||||||
void console::operator()()
|
void console::operator()()
|
||||||
{
|
{
|
||||||
D(fprintf(stderr, "Console thread started\n");)
|
DOLOG(::debug, true, "Console thread started");
|
||||||
|
|
||||||
set_thread_name("kek::console");
|
set_thread_name("kek::console");
|
||||||
|
|
||||||
|
@ -221,8 +222,6 @@ void console::operator()()
|
||||||
|
|
||||||
bool running_flag = *get_running_flag();
|
bool running_flag = *get_running_flag();
|
||||||
|
|
||||||
// printf("%d %d\n", running_flag, c);
|
|
||||||
|
|
||||||
if (running_flag == false && c == 3) // ^c
|
if (running_flag == false && c == 3) // ^c
|
||||||
*stop_event = EVENT_TERMINATE;
|
*stop_event = EVENT_TERMINATE;
|
||||||
else if (running_flag == true && c == 5) // ^e
|
else if (running_flag == true && c == 5) // ^e
|
||||||
|
@ -236,5 +235,5 @@ void console::operator()()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
D(fprintf(stderr, "Console thread terminating\n");)
|
DOLOG(::debug, true, "Console thread terminating");
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@ void console_ncurses::panel_update_thread()
|
||||||
int run_mode = current_PSW >> 14;
|
int run_mode = current_PSW >> 14;
|
||||||
|
|
||||||
uint16_t current_PC = c->getPC();
|
uint16_t current_PC = c->getPC();
|
||||||
uint32_t full_addr = b->calculate_physical_address(run_mode, current_PC, false, false);
|
uint32_t full_addr = b->calculate_physical_address(run_mode, current_PC, false, false, true);
|
||||||
|
|
||||||
uint16_t current_instr = b->readWord(current_PC);
|
uint16_t current_instr = b->readWord(current_PC);
|
||||||
|
|
||||||
|
|
40
cpu.cpp
40
cpu.cpp
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "gen.h"
|
#include "gen.h"
|
||||||
|
#include "log.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#define SIGN(x, wm) ((wm) ? (x) & 0x80 : (x) & 0x8000)
|
#define SIGN(x, wm) ((wm) ? (x) & 0x80 : (x) & 0x8000)
|
||||||
|
@ -264,7 +265,7 @@ bool cpu::check_queued_interrupts()
|
||||||
|
|
||||||
interrupts->second.erase(vector);
|
interrupts->second.erase(vector);
|
||||||
|
|
||||||
D(fprintf(stderr, "Invoking interrupt vector %o (IPL %d, current: %d)\n", v, i, current_level);)
|
DOLOG(debug, true, "Invoking interrupt vector %o (IPL %d, current: %d)", v, i, current_level);
|
||||||
|
|
||||||
trap(v, i);
|
trap(v, i);
|
||||||
|
|
||||||
|
@ -283,7 +284,7 @@ void cpu::queue_interrupt(const uint8_t level, const uint8_t vector)
|
||||||
|
|
||||||
it->second.insert(vector);
|
it->second.insert(vector);
|
||||||
|
|
||||||
D(fprintf(stderr, "Queueing interrupt vector %o (IPL %d, current: %d), n: %zu\n", vector, level, getPSW_spl(), it->second.size());)
|
DOLOG(debug, true, "Queueing interrupt vector %o (IPL %d, current: %d), n: %zu", vector, level, getPSW_spl(), it->second.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu::addToMMR1(const uint8_t mode, const uint8_t reg, const bool word_mode)
|
void cpu::addToMMR1(const uint8_t mode, const uint8_t reg, const bool word_mode)
|
||||||
|
@ -480,8 +481,6 @@ bool cpu::double_operand_instructions(const uint16_t instr)
|
||||||
|
|
||||||
addToMMR1(dst_mode, dst_reg, word_mode);
|
addToMMR1(dst_mode, dst_reg, word_mode);
|
||||||
|
|
||||||
// D(fprintf(stderr, "CMP%s %o,%o: %o\n", word_mode?"B":"", src_value, dst_value, temp);)
|
|
||||||
|
|
||||||
setPSW_n(SIGN(temp, word_mode));
|
setPSW_n(SIGN(temp, word_mode));
|
||||||
setPSW_z(IS_0(temp, word_mode));
|
setPSW_z(IS_0(temp, word_mode));
|
||||||
setPSW_v(SIGN((src_value ^ dst_value) & (~dst_value ^ temp), word_mode));
|
setPSW_v(SIGN((src_value ^ dst_value) & (~dst_value ^ temp), word_mode));
|
||||||
|
@ -492,7 +491,6 @@ bool cpu::double_operand_instructions(const uint16_t instr)
|
||||||
|
|
||||||
case 0b011: { // BIT/BITB Bit Test Word/Byte
|
case 0b011: { // BIT/BITB Bit Test Word/Byte
|
||||||
uint16_t dst_value = getGAM(dst_mode, dst_reg, word_mode, false);
|
uint16_t dst_value = getGAM(dst_mode, dst_reg, word_mode, false);
|
||||||
//D(fprintf(stderr, "BIT%s: dst_value %o, src_val: %o\n", word_mode?"B":"", dst_value, src_value);)
|
|
||||||
uint16_t result = (dst_value & src_value) & (word_mode ? 0xff : 0xffff);
|
uint16_t result = (dst_value & src_value) & (word_mode ? 0xff : 0xffff);
|
||||||
|
|
||||||
setPSW_n(SIGN(result, word_mode));
|
setPSW_n(SIGN(result, word_mode));
|
||||||
|
@ -615,8 +613,6 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr)
|
||||||
|
|
||||||
int32_t quot = R0R1 / divider;
|
int32_t quot = R0R1 / divider;
|
||||||
uint16_t rem = R0R1 % divider;
|
uint16_t rem = R0R1 % divider;
|
||||||
D(fprintf(stderr, "value: %d, divider: %d, gives: %d / %d\n", R0R1, divider, quot, rem);)
|
|
||||||
D(fprintf(stderr, "value: %o, divider: %o, gives: %o / %o\n", R0R1, divider, quot, rem);)
|
|
||||||
|
|
||||||
// TODO: handle results out of range
|
// TODO: handle results out of range
|
||||||
|
|
||||||
|
@ -643,8 +639,6 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr)
|
||||||
uint16_t shift = getGAM(dst_mode, dst_reg, false, false) & 077;
|
uint16_t shift = getGAM(dst_mode, dst_reg, false, false) & 077;
|
||||||
bool sign = SIGN(R, false);
|
bool sign = SIGN(R, false);
|
||||||
|
|
||||||
// fprintf(stderr, "R: %06o, shift: %d, sign: %d, ", R, shift, sign);
|
|
||||||
|
|
||||||
// extend sign-bit
|
// extend sign-bit
|
||||||
if (sign)
|
if (sign)
|
||||||
R |= 0xffff0000;
|
R |= 0xffff0000;
|
||||||
|
@ -679,12 +673,6 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr)
|
||||||
|
|
||||||
setRegister(reg, R);
|
setRegister(reg, R);
|
||||||
|
|
||||||
// uint16_t psw = getPSW();
|
|
||||||
// std::string psw_str = format("%d%d|%d|%d|%c%c%c%c%c", psw >> 14, (psw >> 12) & 3, (psw >> 11) & 1, (psw >> 5) & 7,
|
|
||||||
// psw & 16?'t':'-', psw & 8?'n':'-', psw & 4?'z':'-', psw & 2 ? 'v':'-', psw & 1 ? 'c':'-');
|
|
||||||
// // printf("flags: %06o\r\n", getPSW());
|
|
||||||
// fprintf(stderr, "%s > %06o, R OUT: %06o\r\n", psw_str.c_str(), psw, R);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1481,8 +1469,6 @@ bool cpu::condition_code_operations(const uint16_t instr)
|
||||||
// // trap via vector 010 only(?) on an 11/60 and not(?) on an 11/70
|
// // trap via vector 010 only(?) on an 11/60 and not(?) on an 11/70
|
||||||
// trap(010);
|
// trap(010);
|
||||||
|
|
||||||
D(fprintf(stderr, "SPL%d, new pc: %06o\n", level, getPC());)
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1507,14 +1493,16 @@ bool cpu::condition_code_operations(const uint16_t instr)
|
||||||
void cpu::pushStack(const uint16_t v)
|
void cpu::pushStack(const uint16_t v)
|
||||||
{
|
{
|
||||||
if (getRegister(6) == stackLimitRegister) {
|
if (getRegister(6) == stackLimitRegister) {
|
||||||
printf("stackLimitRegister reached\n"); // TODO
|
DOLOG(debug, true, "stackLimitRegister reached");
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
trap(123, 7); // TODO
|
||||||
|
}
|
||||||
|
else {
|
||||||
uint16_t a = addRegister(6, false, -2);
|
uint16_t a = addRegister(6, false, -2);
|
||||||
|
|
||||||
b -> writeWord(a, v);
|
b -> writeWord(a, v);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t cpu::popStack()
|
uint16_t cpu::popStack()
|
||||||
{
|
{
|
||||||
|
@ -1646,7 +1634,6 @@ void cpu::trap(const uint16_t vector, const int new_ipl)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((b->getMMR1() & 0160000) == 0) {
|
if ((b->getMMR1() & 0160000) == 0) {
|
||||||
D(fprintf(stderr, "trap: register vector/2xregister-undo\n");)
|
|
||||||
b->setMMR2(vector);
|
b->setMMR2(vector);
|
||||||
b->addToMMR1(-2, 6);
|
b->addToMMR1(-2, 6);
|
||||||
b->addToMMR1(-2, 6);
|
b->addToMMR1(-2, 6);
|
||||||
|
@ -1663,8 +1650,6 @@ void cpu::trap(const uint16_t vector, const int new_ipl)
|
||||||
|
|
||||||
pushStack(before_psw);
|
pushStack(before_psw);
|
||||||
pushStack(before_pc);
|
pushStack(before_pc);
|
||||||
|
|
||||||
D(fprintf(stderr, "TRAP %o: PC is now %06o, PSW is now %06o\n", vector, getPC(), new_psw);)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu::operand_parameters cpu::addressing_to_string(const uint8_t mode_register, const uint16_t pc, const bool word_mode) const
|
cpu::operand_parameters cpu::addressing_to_string(const uint8_t mode_register, const uint16_t pc, const bool word_mode) const
|
||||||
|
@ -1728,9 +1713,6 @@ cpu::operand_parameters cpu::addressing_to_string(const uint8_t mode_register, c
|
||||||
|
|
||||||
std::map<std::string, std::vector<std::string> > cpu::disassemble(const uint16_t addr) const
|
std::map<std::string, std::vector<std::string> > cpu::disassemble(const uint16_t addr) const
|
||||||
{
|
{
|
||||||
bool old_trace_output = trace_output;
|
|
||||||
trace_output = false;
|
|
||||||
|
|
||||||
uint16_t instruction = b->peekWord(addr);
|
uint16_t instruction = b->peekWord(addr);
|
||||||
|
|
||||||
bool word_mode = !!(instruction & 0x8000);
|
bool word_mode = !!(instruction & 0x8000);
|
||||||
|
@ -2140,8 +2122,6 @@ std::map<std::string, std::vector<std::string> > cpu::disassemble(const uint16_t
|
||||||
work_values_str.push_back(format("%06o", v));
|
work_values_str.push_back(format("%06o", v));
|
||||||
out.insert({ "work-values", work_values_str });
|
out.insert({ "work-values", work_values_str });
|
||||||
|
|
||||||
trace_output = old_trace_output;
|
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2189,11 +2169,11 @@ void cpu::step_b()
|
||||||
if (misc_operations(instr))
|
if (misc_operations(instr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fprintf(stderr, "UNHANDLED instruction %o\n", instr);
|
DOLOG(warning, true, "UNHANDLED instruction %o", instr);
|
||||||
|
|
||||||
trap(010);
|
trap(010);
|
||||||
}
|
}
|
||||||
catch(const int exception) {
|
catch(const int exception) {
|
||||||
D(fprintf(stderr, "bus-trap during execution of command\n");)
|
DOLOG(debug, true, "bus-trap during execution of command");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
gen.h
12
gen.h
|
@ -2,16 +2,4 @@
|
||||||
// Released under Apache License v2.0
|
// Released under Apache License v2.0
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
extern bool trace_output;
|
|
||||||
|
|
||||||
typedef enum { EVENT_NONE = 0, EVENT_HALT, EVENT_INTERRUPT, EVENT_TERMINATE } stop_event_t;
|
typedef enum { EVENT_NONE = 0, EVENT_HALT, EVENT_INTERRUPT, EVENT_TERMINATE } stop_event_t;
|
||||||
|
|
||||||
#if defined(ESP32)
|
|
||||||
#define D(...) do { } while(0);
|
|
||||||
#else
|
|
||||||
#ifndef NDEBUG
|
|
||||||
#define D(x) do { if (trace_output) { x } } while(0);
|
|
||||||
#else
|
|
||||||
#define D(...) do { } while(0);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
11
loaders.cpp
11
loaders.cpp
|
@ -7,6 +7,7 @@
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "gen.h"
|
#include "gen.h"
|
||||||
#include "loaders.h"
|
#include "loaders.h"
|
||||||
|
#include "log.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,7 +108,7 @@ uint16_t loadTape(bus *const b, const char *const file)
|
||||||
{
|
{
|
||||||
FILE *fh = fopen(file, "rb");
|
FILE *fh = fopen(file, "rb");
|
||||||
if (!fh) {
|
if (!fh) {
|
||||||
fprintf(stderr, "Cannot open %s\n", file);
|
DOLOG(ll_error, true, "Cannot open %s", file);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,16 +129,16 @@ uint16_t loadTape(bus *const b, const char *const file)
|
||||||
|
|
||||||
if (count == 6) { // eg no data
|
if (count == 6) { // eg no data
|
||||||
if (p != 1) {
|
if (p != 1) {
|
||||||
D(fprintf(stderr, "Setting start address to %o\n", p);)
|
DOLOG(info, true, "Setting start address to %o", p);
|
||||||
start = p;
|
start = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
D(fprintf(stderr, "%ld] reading %d (dec) bytes to %o (oct)\n", ftell(fh), count - 6, p);)
|
DOLOG(debug, true, "%ld] reading %d (dec) bytes to %o (oct)", ftell(fh), count - 6, p);
|
||||||
|
|
||||||
for(int i=0; i<count - 6; i++) {
|
for(int i=0; i<count - 6; i++) {
|
||||||
if (feof(fh)) {
|
if (feof(fh)) {
|
||||||
fprintf(stderr, "short read\n");
|
DOLOG(warning, true, "short read");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
uint8_t c = fgetc(fh);
|
uint8_t c = fgetc(fh);
|
||||||
|
@ -153,7 +154,7 @@ uint16_t loadTape(bus *const b, const char *const file)
|
||||||
csum += fcs;
|
csum += fcs;
|
||||||
|
|
||||||
if (csum != 255)
|
if (csum != 255)
|
||||||
fprintf(stderr, "checksum error %d\n", csum);
|
DOLOG(warning, true, "checksum error %d", csum);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fh);
|
fclose(fh);
|
||||||
|
|
93
log.cpp
Normal file
93
log.cpp
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "error.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
static int lf_uid = -1;
|
||||||
|
static int lf_gid = -1;
|
||||||
|
|
||||||
|
void setlog(const char *lf, const log_level_t ll_file, const log_level_t ll_screen)
|
||||||
|
{
|
||||||
|
if (lfh)
|
||||||
|
fclose(lfh);
|
||||||
|
|
||||||
|
free((void *)logfile);
|
||||||
|
|
||||||
|
logfile = strdup(lf);
|
||||||
|
|
||||||
|
log_level_file = ll_file;
|
||||||
|
log_level_screen = ll_screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setloguid(const int uid, const int gid)
|
||||||
|
{
|
||||||
|
lf_uid = uid;
|
||||||
|
lf_gid = gid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void closelog()
|
||||||
|
{
|
||||||
|
fclose(lfh);
|
||||||
|
|
||||||
|
lfh = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dolog(const log_level_t ll, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
if (ll < log_level_file && ll < log_level_screen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!lfh) {
|
||||||
|
lfh = fopen(logfile, "a+");
|
||||||
|
if (!lfh)
|
||||||
|
error_exit(true, "Cannot access log-file %s", logfile);
|
||||||
|
|
||||||
|
if (lf_uid != -1 && fchown(fileno(lfh), lf_uid, lf_gid) == -1)
|
||||||
|
error_exit(true, "Cannot change logfile (%s) ownership", logfile);
|
||||||
|
|
||||||
|
if (fcntl(fileno(lfh), F_SETFD, FD_CLOEXEC) == -1)
|
||||||
|
error_exit(true, "fcntl(FD_CLOEXEC) failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t now = get_us();
|
||||||
|
time_t t_now = now / 1000000;
|
||||||
|
|
||||||
|
struct tm tm { 0 };
|
||||||
|
if (!localtime_r(&t_now, &tm))
|
||||||
|
error_exit(true, "localtime_r failed");
|
||||||
|
|
||||||
|
char *ts_str = nullptr;
|
||||||
|
|
||||||
|
const char *const ll_names[] = { "debug ", "info ", "warning", "error " };
|
||||||
|
|
||||||
|
asprintf(&ts_str, "%04d-%02d-%02d %02d:%02d:%02d.%06d %.6f|%d] %s ",
|
||||||
|
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, int(now % 1000000),
|
||||||
|
get_us() / 1000000.0, gettid(), ll_names[ll]);
|
||||||
|
|
||||||
|
char *str = nullptr;
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
(void)vasprintf(&str, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (ll >= log_level_file)
|
||||||
|
fprintf(lfh, "%s%s\n", ts_str, str);
|
||||||
|
|
||||||
|
if (ll >= log_level_screen)
|
||||||
|
printf("%s%s\r\n", ts_str, str);
|
||||||
|
|
||||||
|
free(str);
|
||||||
|
free(ts_str);
|
||||||
|
}
|
||||||
|
|
13
log.h
Normal file
13
log.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
typedef enum { debug, info, warning, ll_error } log_level_t; // TODO ll_ prefix
|
||||||
|
//
|
||||||
|
void setlog(const char *lf, const log_level_t ll_file, const log_level_t ll_screen);
|
||||||
|
void setloguid(const int uid, const int gid);
|
||||||
|
void closelog();
|
||||||
|
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)) \
|
||||||
|
dolog(ll, fmt, ##__VA_ARGS__); \
|
||||||
|
} while(0)
|
20
main.cpp
20
main.cpp
|
@ -15,6 +15,7 @@
|
||||||
#include "gen.h"
|
#include "gen.h"
|
||||||
#include "kw11-l.h"
|
#include "kw11-l.h"
|
||||||
#include "loaders.h"
|
#include "loaders.h"
|
||||||
|
#include "log.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
|
@ -25,7 +26,6 @@
|
||||||
bool withUI { false };
|
bool withUI { false };
|
||||||
std::atomic_uint32_t event { 0 };
|
std::atomic_uint32_t event { 0 };
|
||||||
std::atomic_bool *running { nullptr };
|
std::atomic_bool *running { nullptr };
|
||||||
bool trace_output { false };
|
|
||||||
|
|
||||||
std::atomic_bool sigw_event { false };
|
std::atomic_bool sigw_event { false };
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ void help()
|
||||||
printf("-n ncurses UI\n");
|
printf("-n ncurses UI\n");
|
||||||
printf("-d enable debugger\n");
|
printf("-d enable debugger\n");
|
||||||
printf("-t enable tracing (disassemble to stderr, requires -d as well)\n");
|
printf("-t enable tracing (disassemble to stderr, requires -d as well)\n");
|
||||||
|
printf("-l x log to file x\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
@ -76,8 +77,10 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
bootloader_t bootloader = BL_NONE;
|
bootloader_t bootloader = BL_NONE;
|
||||||
|
|
||||||
|
const char *logfile = nullptr;
|
||||||
|
|
||||||
int opt = -1;
|
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:l:")) != -1)
|
||||||
{
|
{
|
||||||
switch(opt) {
|
switch(opt) {
|
||||||
case 'h':
|
case 'h':
|
||||||
|
@ -100,7 +103,6 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
tracing = true;
|
tracing = true;
|
||||||
trace_output = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n':
|
case 'n':
|
||||||
|
@ -136,6 +138,10 @@ int main(int argc, char *argv[])
|
||||||
loadbin(b, c->getRegister(7), optarg);
|
loadbin(b, c->getRegister(7), optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
logfile = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "-%c is not understood\n", opt);
|
fprintf(stderr, "-%c is not understood\n", opt);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -144,14 +150,16 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
console *cnsl = nullptr;
|
console *cnsl = nullptr;
|
||||||
|
|
||||||
|
setlog(logfile, logfile ? ((tracing || run_debugger) ? debug : info) : ll_error, ll_error);
|
||||||
|
|
||||||
std::atomic_bool interrupt_emulation { false };
|
std::atomic_bool interrupt_emulation { false };
|
||||||
|
|
||||||
if (withUI)
|
if (withUI)
|
||||||
cnsl = new console_ncurses(&event, b);
|
cnsl = new console_ncurses(&event, b);
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "This PDP-11 emulator is called \"kek\" (reason for that is forgotten) and was written by Folkert van Heusden.\n");
|
DOLOG(info, true, "This PDP-11 emulator is called \"kek\" (reason for that is forgotten) and was written by Folkert van Heusden.");
|
||||||
|
|
||||||
fprintf(stderr, "Built on: " __DATE__ " " __TIME__ "\n");
|
DOLOG(info, true, "Built on: " __DATE__ " " __TIME__);
|
||||||
|
|
||||||
cnsl = new console_posix(&event, b);
|
cnsl = new console_posix(&event, b);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +182,7 @@ int main(int argc, char *argv[])
|
||||||
if (testCases)
|
if (testCases)
|
||||||
tests(c);
|
tests(c);
|
||||||
|
|
||||||
D(fprintf(stderr, "Start running at %o\n", c->getRegister(7));)
|
DOLOG(info, true, "Start running at %o", c->getRegister(7));
|
||||||
|
|
||||||
struct sigaction sa { };
|
struct sigaction sa { };
|
||||||
sa.sa_handler = sw_handler;
|
sa.sa_handler = sw_handler;
|
||||||
|
|
35
rk05.cpp
35
rk05.cpp
|
@ -7,6 +7,7 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "gen.h"
|
#include "gen.h"
|
||||||
|
#include "log.h"
|
||||||
#include "rk05.h"
|
#include "rk05.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
@ -93,7 +94,7 @@ uint16_t rk05::readWord(const uint16_t addr)
|
||||||
if (addr == RK05_CS)
|
if (addr == RK05_CS)
|
||||||
setBit(registers[reg], 0, false); // clear go
|
setBit(registers[reg], 0, false); // clear go
|
||||||
|
|
||||||
D(fprintf(stderr, "RK05 read %s/%o: %06o\n", reg[regnames], addr, vtemp);)
|
DOLOG(debug, true, "RK05 read %s/%o: %06o", reg[regnames], addr, vtemp);
|
||||||
|
|
||||||
return vtemp;
|
return vtemp;
|
||||||
}
|
}
|
||||||
|
@ -145,13 +146,13 @@ void rk05::writeWord(const uint16_t addr, uint16_t v)
|
||||||
registers[(RK05_CS - RK05_BASE) / 2] &= ~(1 << 13); // reset search complete
|
registers[(RK05_CS - RK05_BASE) / 2] &= ~(1 << 13); // reset search complete
|
||||||
|
|
||||||
if (func == 0) { // controller reset
|
if (func == 0) { // controller reset
|
||||||
D(fprintf(stderr, "RK05 invoke %d (controller reset)\n", func);)
|
DOLOG(debug, true, "RK05 invoke %d (controller reset)", func);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (func == 1) { // write
|
else if (func == 1) { // write
|
||||||
*disk_write_acitivity = true;
|
*disk_write_acitivity = true;
|
||||||
|
|
||||||
D(fprintf(stderr, "RK05 drive %d position sec %d surf %d cyl %d, reclen %zo, WRITE to %o, mem: %o\n", device, sector, surface, cylinder, reclen, diskoffb, memoff);)
|
DOLOG(debug, true, "RK05 drive %d position sec %d surf %d cyl %d, reclen %zo, WRITE to %o, mem: %o", device, sector, surface, cylinder, reclen, diskoffb, memoff);
|
||||||
|
|
||||||
uint32_t p = reclen;
|
uint32_t p = reclen;
|
||||||
for(size_t i=0; i<reclen; i++)
|
for(size_t i=0; i<reclen; i++)
|
||||||
|
@ -160,19 +161,19 @@ void rk05::writeWord(const uint16_t addr, uint16_t v)
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
File32 *fh = fhs.at(device);
|
File32 *fh = fhs.at(device);
|
||||||
if (!fh->seek(diskoffb))
|
if (!fh->seek(diskoffb))
|
||||||
fprintf(stderr, "RK05 seek error %s\n", strerror(errno));
|
DOLOG(ll_error, true, "RK05 seek error %s", strerror(errno));
|
||||||
if (fh->write(xfer_buffer, reclen) != reclen)
|
if (fh->write(xfer_buffer, reclen) != reclen)
|
||||||
fprintf(stderr, "RK05 fwrite error %s\n", strerror(errno));
|
DOLOG(ll_error, true, "RK05 fwrite error %s", strerror(errno));
|
||||||
#else
|
#else
|
||||||
FILE *fh = fhs.at(device);
|
FILE *fh = fhs.at(device);
|
||||||
if (fseek(fh, diskoffb, SEEK_SET) == -1)
|
if (fseek(fh, diskoffb, SEEK_SET) == -1)
|
||||||
fprintf(stderr, "RK05 seek error %s\n", strerror(errno));
|
DOLOG(ll_error, true, "RK05 seek error %s", strerror(errno));
|
||||||
if (fwrite(xfer_buffer, 1, reclen, fh) != reclen)
|
if (fwrite(xfer_buffer, 1, reclen, fh) != reclen)
|
||||||
fprintf(stderr, "RK05 fwrite error %s\n", strerror(errno));
|
DOLOG(ll_error, true, "RK05 fwrite error %s", strerror(errno));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (v & 2048)
|
if (v & 2048)
|
||||||
D(fprintf(stderr, "RK05 inhibit BA increase\n");)
|
DOLOG(debug, true, "RK05 inhibit BA increase");
|
||||||
else
|
else
|
||||||
registers[(RK05_BA - RK05_BASE) / 2] += p;
|
registers[(RK05_BA - RK05_BASE) / 2] += p;
|
||||||
|
|
||||||
|
@ -191,14 +192,14 @@ void rk05::writeWord(const uint16_t addr, uint16_t v)
|
||||||
else if (func == 2) { // read
|
else if (func == 2) { // read
|
||||||
*disk_read_acitivity = true;
|
*disk_read_acitivity = true;
|
||||||
|
|
||||||
D(fprintf(stderr, "RK05 drive %d position sec %d surf %d cyl %d, reclen %zo, READ from %o, mem: %o\n", device, sector, surface, cylinder, reclen, diskoffb, memoff);)
|
DOLOG(debug, true, "RK05 drive %d position sec %d surf %d cyl %d, reclen %zo, READ from %o, mem: %o", device, sector, surface, cylinder, reclen, diskoffb, memoff);
|
||||||
|
|
||||||
bool proceed = true;
|
bool proceed = true;
|
||||||
|
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
File32 *fh = fhs.at(device);
|
File32 *fh = fhs.at(device);
|
||||||
if (!fh->seek(diskoffb)) {
|
if (!fh->seek(diskoffb)) {
|
||||||
fprintf(stderr, "RK05 seek error %s\n", strerror(errno));
|
DOLOG(ll_error, true, "RK05 seek error %s", strerror(errno));
|
||||||
proceed = false;
|
proceed = false;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -210,7 +211,7 @@ void rk05::writeWord(const uint16_t addr, uint16_t v)
|
||||||
fh = fhs.at(device);
|
fh = fhs.at(device);
|
||||||
|
|
||||||
if (fseek(fh, diskoffb, SEEK_SET) == -1) {
|
if (fseek(fh, diskoffb, SEEK_SET) == -1) {
|
||||||
fprintf(stderr, "RK05 seek error %s\n", strerror(errno));
|
DOLOG(ll_error, true, "RK05 seek error %s", strerror(errno));
|
||||||
proceed = false;
|
proceed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,10 +226,10 @@ void rk05::writeWord(const uint16_t addr, uint16_t v)
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
if (fh->read(xfer_buffer, cur) != size_t(cur))
|
if (fh->read(xfer_buffer, cur) != size_t(cur))
|
||||||
D(fprintf(stderr, "RK05 fread error: %s\n", strerror(errno));)
|
DOLOG(debug, true, "RK05 fread error: %s", strerror(errno));
|
||||||
#else
|
#else
|
||||||
if (fread(xfer_buffer, 1, cur, fh) != size_t(cur))
|
if (fread(xfer_buffer, 1, cur, fh) != size_t(cur))
|
||||||
D(fprintf(stderr, "RK05 fread error: %s\n", strerror(errno));)
|
DOLOG(debug, true, "RK05 fread error: %s", strerror(errno));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(uint32_t i=0; i<cur; i++) {
|
for(uint32_t i=0; i<cur; i++) {
|
||||||
|
@ -241,7 +242,7 @@ void rk05::writeWord(const uint16_t addr, uint16_t v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v & 2048)
|
if (v & 2048)
|
||||||
D(fprintf(stderr, "RK05 inhibit BA increase\n");)
|
DOLOG(debug, true, "RK05 inhibit BA increase");
|
||||||
else
|
else
|
||||||
registers[(RK05_BA - RK05_BASE) / 2] += p;
|
registers[(RK05_BA - RK05_BASE) / 2] += p;
|
||||||
|
|
||||||
|
@ -258,15 +259,15 @@ void rk05::writeWord(const uint16_t addr, uint16_t v)
|
||||||
*disk_read_acitivity = false;
|
*disk_read_acitivity = false;
|
||||||
}
|
}
|
||||||
else if (func == 4) {
|
else if (func == 4) {
|
||||||
D(fprintf(stderr, "RK05 invoke %d (seek) to %o\n", func, diskoffb);)
|
DOLOG(debug, true, "RK05 invoke %d (seek) to %o", func, diskoffb);
|
||||||
|
|
||||||
registers[(RK05_CS - RK05_BASE) / 2] |= 1 << 13; // search complete
|
registers[(RK05_CS - RK05_BASE) / 2] |= 1 << 13; // search complete
|
||||||
}
|
}
|
||||||
else if (func == 7) {
|
else if (func == 7) {
|
||||||
D(fprintf(stderr, "RK05 invoke %d (write lock)\n", func);)
|
DOLOG(debug, true, "RK05 invoke %d (write lock)", func);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
D(fprintf(stderr, "RK05 command %d UNHANDLED\n", func);)
|
DOLOG(debug, true, "RK05 command %d UNHANDLED", func);
|
||||||
}
|
}
|
||||||
|
|
||||||
registers[(RK05_WC - RK05_BASE) / 2] = 0;
|
registers[(RK05_WC - RK05_BASE) / 2] = 0;
|
||||||
|
|
21
rl02.cpp
21
rl02.cpp
|
@ -7,6 +7,7 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "gen.h"
|
#include "gen.h"
|
||||||
|
#include "log.h"
|
||||||
#include "rl02.h"
|
#include "rl02.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
@ -82,7 +83,7 @@ uint16_t rl02::readWord(const uint16_t addr)
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
D(fprintf(stderr, "RL02 read %s/%o: %06o\n", regnames[reg], addr, value);)
|
DOLOG(debug, true, "RL02 read %s/%o: %06o", regnames[reg], addr, value);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -119,7 +120,7 @@ void rl02::writeWord(const uint16_t addr, uint16_t v)
|
||||||
digitalWrite(LED_BUILTIN, LOW);
|
digitalWrite(LED_BUILTIN, LOW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fprintf(stderr, "RL02 write %06o: %06o\n", addr, v);
|
DOLOG(debug, true, "RL02 write %06o: %06o", addr, v);
|
||||||
|
|
||||||
const int reg = (addr - RL02_BASE) / 2;
|
const int reg = (addr - RL02_BASE) / 2;
|
||||||
|
|
||||||
|
@ -130,7 +131,7 @@ void rl02::writeWord(const uint16_t addr, uint16_t v)
|
||||||
|
|
||||||
const bool do_exec = !(v & 128);
|
const bool do_exec = !(v & 128);
|
||||||
|
|
||||||
fprintf(stderr, "RL02 set command %d, exec: %d\n", command, do_exec);
|
DOLOG(debug, true, "RL02 set command %d, exec: %d", command, do_exec);
|
||||||
|
|
||||||
uint32_t disk_offset = calcOffset(registers[(RL02_DAR - RL02_BASE) / 2] & ~1);
|
uint32_t disk_offset = calcOffset(registers[(RL02_DAR - RL02_BASE) / 2] & ~1);
|
||||||
int device = 0; // TODO
|
int device = 0; // TODO
|
||||||
|
@ -144,7 +145,7 @@ void rl02::writeWord(const uint16_t addr, uint16_t v)
|
||||||
(1 << 7) | // this is an RL02
|
(1 << 7) | // this is an RL02
|
||||||
0;
|
0;
|
||||||
|
|
||||||
fprintf(stderr, "RL02 set MPR for status to %06o\n", registers[(RL02_MPR - RL02_BASE) / 2]);
|
DOLOG(debug, true, "RL02 set MPR for status to %06o", registers[(RL02_MPR - RL02_BASE) / 2]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -157,7 +158,7 @@ void rl02::writeWord(const uint16_t addr, uint16_t v)
|
||||||
File32 *fh = fhs.at(device);
|
File32 *fh = fhs.at(device);
|
||||||
|
|
||||||
if (!fh->seek(disk_offset)) {
|
if (!fh->seek(disk_offset)) {
|
||||||
fprintf(stderr, "RL02 seek to %d error %s\n", disk_offset, strerror(errno));
|
DOLOG(ll_error, true, "RL02 seek to %d error %s", disk_offset, strerror(errno));
|
||||||
|
|
||||||
proceed = false;
|
proceed = false;
|
||||||
}
|
}
|
||||||
|
@ -170,7 +171,7 @@ void rl02::writeWord(const uint16_t addr, uint16_t v)
|
||||||
fh = fhs.at(device);
|
fh = fhs.at(device);
|
||||||
|
|
||||||
if (fseek(fh, disk_offset, SEEK_SET) == -1) {
|
if (fseek(fh, disk_offset, SEEK_SET) == -1) {
|
||||||
fprintf(stderr, "RL02 seek error %s\n", strerror(errno));
|
DOLOG(ll_error, true, "RL02 seek error %s", strerror(errno));
|
||||||
proceed = false;
|
proceed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,7 +181,7 @@ void rl02::writeWord(const uint16_t addr, uint16_t v)
|
||||||
|
|
||||||
uint32_t count = (65536 - registers[(RL02_MPR - RL02_BASE) / 2]) * 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);
|
DOLOG(debug, true, "RL02 read %d bytes (dec) from %d (dec) to %06o (oct)", count, disk_offset, memory_address);
|
||||||
|
|
||||||
uint32_t p = memory_address;
|
uint32_t p = memory_address;
|
||||||
while(proceed && count > 0) {
|
while(proceed && count > 0) {
|
||||||
|
@ -190,10 +191,10 @@ void rl02::writeWord(const uint16_t addr, uint16_t v)
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
if (fh->read(xfer_buffer, cur) != size_t(cur))
|
if (fh->read(xfer_buffer, cur) != size_t(cur))
|
||||||
D(fprintf(stderr, "RL02 fread error: %s\n", strerror(errno));)
|
DOLOG(info, true, "RL02 fread error: %s", strerror(errno));
|
||||||
#else
|
#else
|
||||||
if (fread(xfer_buffer, 1, cur, fh) != size_t(cur))
|
if (fread(xfer_buffer, 1, cur, fh) != size_t(cur))
|
||||||
D(fprintf(stderr, "RL02 fread error: %s\n", strerror(errno));)
|
DOLOG(info, true, "RL02 fread error: %s", strerror(errno));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(uint32_t i=0; i<cur; i++, p++)
|
for(uint32_t i=0; i<cur; i++, p++)
|
||||||
|
@ -203,7 +204,7 @@ void rl02::writeWord(const uint16_t addr, uint16_t v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (registers[(RL02_CSR - RL02_BASE) / 2] & 64) { // interrupt enable?
|
if (registers[(RL02_CSR - RL02_BASE) / 2] & 64) { // interrupt enable?
|
||||||
fprintf(stderr, "RL02 triggering interrupt\n");
|
DOLOG(debug, true, "RL02 triggering interrupt");
|
||||||
|
|
||||||
b->getCpu()->queue_interrupt(5, 0254);
|
b->getCpu()->queue_interrupt(5, 0254);
|
||||||
}
|
}
|
||||||
|
|
17
tm-11.cpp
17
tm-11.cpp
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "tm-11.h"
|
#include "tm-11.h"
|
||||||
#include "gen.h"
|
#include "gen.h"
|
||||||
|
#include "log.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
@ -36,8 +37,6 @@ uint16_t tm_11::readWord(const uint16_t addr)
|
||||||
const int reg = (addr - TM_11_BASE) / 2;
|
const int reg = (addr - TM_11_BASE) / 2;
|
||||||
uint16_t vtemp = registers[reg];
|
uint16_t vtemp = registers[reg];
|
||||||
|
|
||||||
D(printf("TM-11 read addr %o: ", addr);)
|
|
||||||
|
|
||||||
if (addr == TM_11_MTS) {
|
if (addr == TM_11_MTS) {
|
||||||
setBit(vtemp, 15, false); // ILC
|
setBit(vtemp, 15, false); // ILC
|
||||||
setBit(vtemp, 14, false); // EOC
|
setBit(vtemp, 14, false); // EOC
|
||||||
|
@ -63,7 +62,7 @@ uint16_t tm_11::readWord(const uint16_t addr)
|
||||||
vtemp = 0;
|
vtemp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
D(printf("%o\n", vtemp);)
|
DOLOG(debug, true, "TM-11 read addr %o: %o", addr, vtemp);
|
||||||
|
|
||||||
return vtemp;
|
return vtemp;
|
||||||
}
|
}
|
||||||
|
@ -86,22 +85,22 @@ void tm_11::writeByte(const uint16_t addr, const uint8_t v)
|
||||||
|
|
||||||
void tm_11::writeWord(const uint16_t addr, uint16_t v)
|
void tm_11::writeWord(const uint16_t addr, uint16_t v)
|
||||||
{
|
{
|
||||||
D(printf("TM-11 write %o: %o\n", addr, v);)
|
DOLOG(debug, true, "TM-11 write %o: %o", addr, v);
|
||||||
|
|
||||||
if (addr == TM_11_MTC) {
|
if (addr == TM_11_MTC) {
|
||||||
if (v & 1) { // GO
|
if (v & 1) { // GO
|
||||||
const int func = (v >> 1) & 7; // FUNCTION
|
const int func = (v >> 1) & 7; // FUNCTION
|
||||||
const int reclen = 512;
|
const int reclen = 512;
|
||||||
|
|
||||||
D(printf("invoke %d\n", func);)
|
DOLOG(debug, true, "invoke %d", func);
|
||||||
|
|
||||||
if (func == 0) { // off-line
|
if (func == 0) { // off-line
|
||||||
v = 128; // TODO set error if error
|
v = 128; // TODO set error if error
|
||||||
}
|
}
|
||||||
else if (func == 1) { // read
|
else if (func == 1) { // read
|
||||||
D(printf("reading %d bytes from offset %d\n", reclen, offset);)
|
DOLOG(debug, true, "reading %d bytes from offset %d", reclen, offset);
|
||||||
if (fread(xfer_buffer, 1, reclen, fh) != reclen)
|
if (fread(xfer_buffer, 1, reclen, fh) != reclen)
|
||||||
D(printf("failed: %s\n", strerror(errno));)
|
DOLOG(info, true, "failed: %s", strerror(errno));
|
||||||
for(int i=0; i<reclen; i++)
|
for(int i=0; i<reclen; i++)
|
||||||
m -> writeByte(registers[(TM_11_MTCMA - TM_11_BASE) / 2] + i, xfer_buffer[i]);
|
m -> writeByte(registers[(TM_11_MTCMA - TM_11_BASE) / 2] + i, xfer_buffer[i]);
|
||||||
offset += reclen;
|
offset += reclen;
|
||||||
|
@ -132,9 +131,9 @@ void tm_11::writeWord(const uint16_t addr, uint16_t v)
|
||||||
}
|
}
|
||||||
else if (addr == TM_11_MTCMA) {
|
else if (addr == TM_11_MTCMA) {
|
||||||
v &= ~1;
|
v &= ~1;
|
||||||
D(printf("Set DMA address to %o\n", v);)
|
DOLOG(debug, true, "Set DMA address to %o", v);
|
||||||
}
|
}
|
||||||
|
|
||||||
D(printf("set register %o to %o\n", addr, v);)
|
DOLOG(debug, true, "set register %o to %o", addr, v);
|
||||||
registers[(addr - TM_11_BASE) / 2] = v;
|
registers[(addr - TM_11_BASE) / 2] = v;
|
||||||
}
|
}
|
||||||
|
|
9
tty.cpp
9
tty.cpp
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "tty.h"
|
#include "tty.h"
|
||||||
#include "gen.h"
|
#include "gen.h"
|
||||||
|
#include "log.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
@ -67,7 +68,7 @@ uint16_t tty::readWord(const uint16_t addr)
|
||||||
vtemp = 128;
|
vtemp = 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
D(fprintf(stderr, "PDP11TTY read addr %o (%s): %d, 7bit: %d\n", addr, regnames[reg], vtemp, vtemp & 127);)
|
DOLOG(debug, true, "PDP11TTY read addr %o (%s): %d, 7bit: %d", addr, regnames[reg], vtemp, vtemp & 127);
|
||||||
|
|
||||||
registers[reg] = vtemp;
|
registers[reg] = vtemp;
|
||||||
|
|
||||||
|
@ -94,16 +95,16 @@ void tty::writeWord(const uint16_t addr, uint16_t v)
|
||||||
{
|
{
|
||||||
const int reg = (addr - PDP11TTY_BASE) / 2;
|
const int reg = (addr - PDP11TTY_BASE) / 2;
|
||||||
|
|
||||||
D(fprintf(stderr, "PDP11TTY write %o (%s): %o\n", addr, regnames[reg], v);)
|
DOLOG(debug, true, "PDP11TTY write %o (%s): %o", addr, regnames[reg], v);
|
||||||
|
|
||||||
if (addr == PDP11TTY_TPB) {
|
if (addr == PDP11TTY_TPB) {
|
||||||
char ch = v & 127;
|
char ch = v & 127;
|
||||||
|
|
||||||
D(fprintf(stderr, "PDP11TTY print '%c'\n", ch);)
|
DOLOG(debug, true, "PDP11TTY print '%c'", ch);
|
||||||
|
|
||||||
c->put_char(ch);
|
c->put_char(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
D(fprintf(stderr, "set register %o to %o\n", addr, v);)
|
DOLOG(debug, true, "set register %o to %o", addr, v);
|
||||||
registers[(addr - PDP11TTY_BASE) / 2] = v;
|
registers[(addr - PDP11TTY_BASE) / 2] = v;
|
||||||
}
|
}
|
||||||
|
|
15
utils.cpp
15
utils.cpp
|
@ -43,12 +43,27 @@ unsigned long get_ms()
|
||||||
#else
|
#else
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
||||||
|
// TODO replace gettimeofday by clock_gettime
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t long get_us()
|
||||||
|
{
|
||||||
|
#if defined(ESP32)
|
||||||
|
return micros();
|
||||||
|
#else
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
// TODO replace gettimeofday by clock_gettime
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
|
return tv.tv_sec * 1000000l + tv.tv_usec;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int parity(int v)
|
int parity(int v)
|
||||||
{
|
{
|
||||||
return __builtin_parity(v); // FIXME
|
return __builtin_parity(v); // FIXME
|
||||||
|
|
1
utils.h
1
utils.h
|
@ -14,6 +14,7 @@ std::string format(const char *const fmt, ...);
|
||||||
std::vector<std::string> split(std::string in, std::string splitter);
|
std::vector<std::string> split(std::string in, std::string splitter);
|
||||||
|
|
||||||
unsigned long get_ms();
|
unsigned long get_ms();
|
||||||
|
uint64_t get_us();
|
||||||
void myusleep(uint64_t us);
|
void myusleep(uint64_t us);
|
||||||
|
|
||||||
void set_thread_name(std::string name);
|
void set_thread_name(std::string name);
|
||||||
|
|
Loading…
Add table
Reference in a new issue