Relocate I/O to upper page of virtual address space

This commit is contained in:
folkert van heusden 2023-03-26 00:22:12 +01:00
parent 017339a768
commit 0754aa692b
Signed by untrusted user who does not match committer: folkert
GPG key ID: 6B6455EDFEED3BD1

85
bus.cpp
View file

@ -114,11 +114,18 @@ void bus::trap_odd(const uint16_t a)
c->trap(004); // invalid access c->trap(004); // invalid access
} }
uint16_t bus::read(const uint16_t a, const word_mode_t word_mode, const rm_selection_t mode_selection, const bool peek_only, const d_i_space_t space) uint16_t bus::read(const uint16_t addr_in, const word_mode_t word_mode, const rm_selection_t mode_selection, const bool peek_only, const d_i_space_t space)
{ {
uint16_t temp = 0; int run_mode = mode_selection == rm_cur ? c->getPSW_runmode() : c->getPSW_prev_runmode();
uint32_t m_offset = calculate_physical_address(run_mode, addr_in, !peek_only, false, peek_only, space);
uint32_t io_base = MMR0 & 1 ? (MMR3 & 16 ? 017760000 : 0760000) : 0160000;
bool is_io = m_offset >= io_base;
if (is_io) {
uint16_t a = m_offset - io_base + 0160000; // TODO
if (a >= 0160000) {
//// REGISTERS //// //// REGISTERS ////
if (a >= ADDR_KERNEL_R && a <= ADDR_KERNEL_R + 5) { // kernel R0-R5 if (a >= ADDR_KERNEL_R && a <= ADDR_KERNEL_R + 5) { // kernel R0-R5
uint16_t temp = c->getRegister(a - ADDR_KERNEL_R) & (word_mode ? 0xff : 0xffff); uint16_t temp = c->getRegister(a - ADDR_KERNEL_R) & (word_mode ? 0xff : 0xffff);
@ -387,31 +394,21 @@ uint16_t bus::read(const uint16_t a, const word_mode_t word_mode, const rm_selec
return -1; return -1;
} }
if (peek_only == false && word_mode == false && (a & 1)) { if (peek_only == false && word_mode == false && (addr_in & 1)) {
if (!peek_only) DOLOG(debug, true, "READ from %06o - odd address!", a); if (!peek_only) DOLOG(debug, true, "READ from %06o - odd address!", addr_in);
trap_odd(a); trap_odd(addr_in);
throw 2; throw 2;
return 0; return 0;
} }
int run_mode = mode_selection == rm_cur ? c->getPSW_runmode() : c->getPSW_prev_runmode(); uint16_t temp = 0;
uint32_t m_offset = calculate_physical_address(run_mode, a, !peek_only, false, peek_only, space);
if (peek_only == false && m_offset >= n_pages * 8192) {
if (!peek_only) DOLOG(debug, true, "Read non existing mapped memory (%o >= %o)", m_offset, n_pages * 8192);
c->trap(004); // no such memory
throw 3;
}
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);
if (!peek_only) DOLOG(debug, false, "READ from %06o/%07o %c %c: %o", a, m_offset, space == d_space ? 'D' : 'I', word_mode ? 'B' : 'W', temp); if (!peek_only) DOLOG(debug, false, "READ from %06o/%07o %c %c: %o", addr_in, m_offset, space == d_space ? 'D' : 'I', word_mode ? 'B' : 'W', temp);
return temp; return temp;
} }
@ -498,18 +495,12 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c
{ {
uint32_t m_offset = a; uint32_t m_offset = a;
if (a == 0100000)
DOLOG(info, true, "0100000: MMR0=%d", MMR0);
if ((MMR0 & 1) || (is_write && (MMR0 & (1 << 8)))) { if ((MMR0 & 1) || (is_write && (MMR0 & (1 << 8)))) {
const uint8_t apf = a >> 13; // active page field const uint8_t apf = a >> 13; // active page field
bool d = space == d_space && get_use_data_space(run_mode) ? space == d_space : false; bool d = space == d_space && get_use_data_space(run_mode) ? space == d_space : false;
uint16_t p_offset = a & 8191; // page offset uint16_t p_offset = a & 8191; // page offset
//
if (a == 0100000)
DOLOG(info, true, "0100000: APF=%d, d=%d, MMR3=%06o, run_mode=%d, mask=%d, space=%d", apf, d, MMR3, run_mode, get_use_data_space(run_mode), space);
m_offset = pages[run_mode][d][apf].par * 64; // memory offset TODO: handle 16b int-s m_offset = pages[run_mode][d][apf].par * 64; // memory offset TODO: handle 16b int-s
@ -518,6 +509,9 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c
if ((MMR3 & 16) == 0) // off is 18bit if ((MMR3 & 16) == 0) // off is 18bit
m_offset &= 0x3ffff; m_offset &= 0x3ffff;
uint32_t io_base = MMR3 & 16 ? 017760000 : 0760000;
bool is_io = m_offset >= io_base;
if (trap_on_failure) { if (trap_on_failure) {
{ {
const int access_control = pages[run_mode][d][apf].pdr & 7; const int access_control = pages[run_mode][d][apf].pdr & 7;
@ -530,9 +524,6 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c
do_trap = true; do_trap = true;
} }
if (a == 0100000)
DOLOG(info, true, "0100000: access_control=%d, do_trap=%d", access_control, do_trap);
if (do_trap) { if (do_trap) {
bool do_trap_250 = false; bool do_trap_250 = false;
@ -576,7 +567,7 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c
} }
} }
if (m_offset >= n_pages * 8192) { if (m_offset >= n_pages * 8192 && !is_io) {
DOLOG(debug, !peek_only, "bus::calculate_physical_address %o >= %o", m_offset, n_pages * 8192); DOLOG(debug, !peek_only, "bus::calculate_physical_address %o >= %o", m_offset, n_pages * 8192);
DOLOG(debug, true, "TRAP(04) (throw 6) on address %06o", a); DOLOG(debug, true, "TRAP(04) (throw 6) on address %06o", a);
@ -696,21 +687,27 @@ void bus::write_par(const uint32_t a, const int run_mode, const uint16_t value,
DOLOG(debug, true, "WRITE-I/O PAR run-mode %d: %c for %d: %o (%07o)", run_mode, is_d ? 'D' : 'I', page, word_mode ? value & 0xff : value, pages[run_mode][is_d][page].par * 64); DOLOG(debug, true, "WRITE-I/O PAR run-mode %d: %c for %d: %o (%07o)", run_mode, is_d ? 'D' : 'I', page, word_mode ? value & 0xff : value, pages[run_mode][is_d][page].par * 64);
} }
void bus::write(const uint16_t a, const word_mode_t word_mode, uint16_t value, const rm_selection_t mode_selection, const d_i_space_t space) void bus::write(const uint16_t addr_in, const word_mode_t word_mode, uint16_t value, const rm_selection_t mode_selection, const d_i_space_t space)
{ {
int run_mode = mode_selection == rm_cur ? c->getPSW_runmode() : c->getPSW_prev_runmode(); int run_mode = mode_selection == rm_cur ? c->getPSW_runmode() : c->getPSW_prev_runmode();
if ((MMR0 & 1) == 1 && (a & 1) == 0 && a != ADDR_MMR0) { const uint8_t apf = addr_in >> 13; // active page field
const uint8_t apf = a >> 13; // active page field
bool is_data = space == d_space; bool is_data = space == d_space;
bool d = is_data && get_use_data_space(run_mode) ? is_data : false; bool d = is_data && get_use_data_space(run_mode) ? is_data : false;
if ((MMR0 & 1) == 1 && (addr_in & 1) == 0 && addr_in != ADDR_MMR0)
pages[run_mode][d][apf].pdr |= 64; // set 'W' (written to) bit pages[run_mode][d][apf].pdr |= 64; // set 'W' (written to) bit
}
if (a >= 0160000) { uint32_t m_offset = calculate_physical_address(run_mode, addr_in, true, true, false, space);
uint32_t io_base = MMR0 & 1 ? (MMR3 & 16 ? 017760000 : 0760000) : 0160000;
bool is_io = m_offset >= io_base;
if (is_io) {
uint16_t a = m_offset - io_base + 0160000; // TODO
if (word_mode) { if (word_mode) {
if (a == ADDR_PSW || a == ADDR_PSW + 1) { // PSW if (a == ADDR_PSW || a == ADDR_PSW + 1) { // PSW
DOLOG(debug, true, "WRITE-I/O PSW %s: %03o", a & 1 ? "MSB" : "LSB", value); DOLOG(debug, true, "WRITE-I/O PSW %s: %03o", a & 1 ? "MSB" : "LSB", value);
@ -952,22 +949,14 @@ void bus::write(const uint16_t a, const word_mode_t word_mode, uint16_t value, c
throw 9; throw 9;
} }
if (word_mode == false && (a & 1)) { if (word_mode == false && (addr_in & 1)) {
DOLOG(debug, true, "WRITE to %06o (value: %06o) - odd address!", a, value); DOLOG(debug, true, "WRITE to %06o (value: %06o) - odd address!", addr_in, value);
trap_odd(a); trap_odd(addr_in);
throw 10; throw 10;
} }
uint32_t m_offset = calculate_physical_address(run_mode, a, true, true, false, space); DOLOG(debug, true, "WRITE to %06o/%07o %c %c: %06o", addr_in, m_offset, space == d_space ? 'D' : 'I', word_mode ? 'B' : 'W', value);
if (m_offset >= n_pages * 8192) {
DOLOG(debug, false, "Write non existing mapped memory (%06o, value: %06o)", m_offset, value);
c->trap(004); // no such memory
throw 11;
}
DOLOG(debug, true, "WRITE to %06o/%07o %c %c: %06o", a, m_offset, space == d_space ? 'D' : 'I', word_mode ? 'B' : 'W', value);
if (word_mode) if (word_mode)
m->writeByte(m_offset, value); m->writeByte(m_offset, value);