PSW addressing tweak

This commit is contained in:
folkert van heusden 2024-04-08 16:03:52 +02:00
parent a80d3b711d
commit c7f8d83c2b
Signed by untrusted user who does not match committer: folkert
GPG key ID: 6B6455EDFEED3BD1
3 changed files with 57 additions and 70 deletions

70
bus.cpp
View file

@ -758,7 +758,7 @@ void bus::write_par(const uint32_t a, const int run_mode, const uint16_t value,
DOLOG(debug, false, "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 addr_in, const word_mode_t word_mode, uint16_t value, const rm_selection_t mode_selection, const d_i_space_t space)
write_rc_t 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();
@ -794,7 +794,7 @@ void bus::write(const uint16_t addr_in, const word_mode_t word_mode, uint16_t va
c->setPSW(vtemp, false);
return;
return { true };
}
if (a == ADDR_STACKLIM || a == ADDR_STACKLIM + 1) { // stack limit register
@ -811,7 +811,7 @@ void bus::write(const uint16_t addr_in, const word_mode_t word_mode, uint16_t va
c->setStackLimitRegister(v);
return;
return { false };
}
if (a == ADDR_MICROPROG_BREAK_REG || a == ADDR_MICROPROG_BREAK_REG + 1) { // microprogram break register
@ -822,7 +822,7 @@ void bus::write(const uint16_t addr_in, const word_mode_t word_mode, uint16_t va
else
microprogram_break_register = (microprogram_break_register & 0x00ff) | (value << 8);
return;
return { false };
}
if (a == ADDR_MMR0 || a == ADDR_MMR0 + 1) { // MMR0
@ -833,78 +833,78 @@ void bus::write(const uint16_t addr_in, const word_mode_t word_mode, uint16_t va
else
MMR0 = (MMR0 & 0x00ff) | (value << 8);
return;
return { false };
}
}
else {
if (a == ADDR_PSW) { // PSW
DOLOG(debug, false, "WRITE-I/O PSW: %06o", value);
c->setPSW(value & ~16, false);
return;
return { true };
}
if (a == ADDR_STACKLIM) { // stack limit register
DOLOG(debug, false, "WRITE-I/O stack limit register: %06o", value);
c->setStackLimitRegister(value & 0xff00);
return;
return { false };
}
if (a >= ADDR_KERNEL_R && a <= ADDR_KERNEL_R + 5) { // kernel R0-R5
int reg = a - ADDR_KERNEL_R;
DOLOG(debug, false, "WRITE-I/O kernel R%d: %06o", reg, value);
c->setRegister(reg, value);
return;
return { false };
}
if (a >= ADDR_USER_R && a <= ADDR_USER_R + 5) { // user R0-R5
int reg = a - ADDR_USER_R;
DOLOG(debug, false, "WRITE-I/O user R%d: %06o", reg, value);
c->setRegister(reg, value);
return;
return { false };
}
if (a == ADDR_KERNEL_SP) { // kernel SP
DOLOG(debug, false, "WRITE-I/O kernel SP: %06o", value);
c->setStackPointer(0, value);
return;
return { false };
}
if (a == ADDR_PC) { // PC
DOLOG(debug, false, "WRITE-I/O PC: %06o", value);
c->setPC(value);
return;
return { false };
}
if (a == ADDR_SV_SP) { // supervisor SP
DOLOG(debug, false, "WRITE-I/O supervisor sp: %06o", value);
c->setStackPointer(1, value);
return;
return { false };
}
if (a == ADDR_USER_SP) { // user SP
DOLOG(debug, false, "WRITE-I/O user sp: %06o", value);
c->setStackPointer(3, value);
return;
return { false };
}
if (a == ADDR_MICROPROG_BREAK_REG) { // microprogram break register
DOLOG(debug, false, "WRITE-I/O microprogram break register: %06o", value);
microprogram_break_register = value & 0xff; // only 8b on 11/70?
return;
return { false };
}
}
if (a == ADDR_CPU_ERR) { // cpu error register
DOLOG(debug, false, "WRITE-I/O CPUERR: %06o", value);
CPUERR = 0;
return;
return { false };
}
if (a == ADDR_MMR3) { // MMR3
DOLOG(debug, false, "WRITE-I/O set MMR3: %06o", value);
MMR3 = value;
return;
return { false };
}
if (a == ADDR_MMR0) { // MMR0
DOLOG(debug, false, "WRITE-I/O set MMR0: %06o", value);
setMMR0(value);
return;
return { false };
}
if (a == ADDR_PIR) { // PIR
@ -920,7 +920,7 @@ void bus::write(const uint16_t addr_in, const word_mode_t word_mode, uint16_t va
}
PIR = value;
return;
return { false };
}
if (a == ADDR_LFC) { // line frequency clock and status register
@ -935,86 +935,86 @@ void bus::write(const uint16_t addr_in, const word_mode_t word_mode, uint16_t va
#if defined(BUILD_FOR_RP2040)
xSemaphoreGive(lf_csr_lock);
#endif
return;
return { false };
}
if (tm11 && a >= TM_11_BASE && a < TM_11_END) {
DOLOG(debug, false, "WRITE-I/O TM11 register %d: %06o", (a - TM_11_BASE) / 2, value);
word_mode ? tm11->writeByte(a, value) : tm11->writeWord(a, value);
return;
return { false };
}
if (rk05_ && a >= RK05_BASE && a < RK05_END) {
DOLOG(debug, false, "WRITE-I/O RK05 register %d: %06o", (a - RK05_BASE) / 2, value);
word_mode ? rk05_->writeByte(a, value) : rk05_->writeWord(a, value);
return;
return { false };
}
if (rl02_ && a >= RL02_BASE && a < RL02_END) {
DOLOG(debug, false, "WRITE-I/O RL02 register %d: %06o", (a - RL02_BASE) / 2, value);
word_mode ? rl02_->writeByte(a, value) : rl02_->writeWord(a, value);
return;
return { false };
}
if (tty_ && a >= PDP11TTY_BASE && a < PDP11TTY_END) {
DOLOG(debug, false, "WRITE-I/O TTY register %d: %06o", (a - PDP11TTY_BASE) / 2, value);
word_mode ? tty_->writeByte(a, value) : tty_->writeWord(a, value);
return;
return { false };
}
/// MMU ///
// supervisor
if (a >= ADDR_PDR_SV_START && a < ADDR_PDR_SV_END) {
write_pdr(a, 1, value, word_mode);
return;
return { false };
}
if (a >= ADDR_PAR_SV_START && a < ADDR_PAR_SV_END) {
write_par(a, 1, value, word_mode);
return;
return { false };
}
// kernel
if (a >= ADDR_PDR_K_START && a < ADDR_PDR_K_END) {
write_pdr(a, 0, value, word_mode);
return;
return { false };
}
if (a >= ADDR_PAR_K_START && a < ADDR_PAR_K_END) {
write_par(a, 0, value, word_mode);
return;
return { false };
}
// user
if (a >= ADDR_PDR_U_START && a < ADDR_PDR_U_END) {
write_pdr(a, 3, value, word_mode);
return;
return { false };
}
if (a >= ADDR_PAR_U_START && a < ADDR_PAR_U_END) {
write_par(a, 3, value, word_mode);
return;
return { false };
}
////
if (a >= 0177740 && a <= 0177753) { // cache control register and others
// TODO
return;
return { false };
}
if (a >= 0170200 && a <= 0170377) { // unibus map
DOLOG(debug, false, "writing %06o to unibus map (%06o)", value, a);
// TODO
return;
return { false };
}
if (a == ADDR_CONSW) { // switch register
console_leds = value;
return;
return { false };
}
if (a == ADDR_SYSSIZE || a == ADDR_SYSSIZE + 2) // system size (is read-only)
return;
return { false };
if (a == ADDR_SYSTEM_ID) // is r/o
return;
return { false };
///////////
@ -1050,6 +1050,8 @@ void bus::write(const uint16_t addr_in, const word_mode_t word_mode, uint16_t va
m->writeByte(m_offset, value);
else
m->writeWord(m_offset, value);
return { false };
}
void bus::writePhysical(const uint32_t a, const uint16_t value)

12
bus.h
View file

@ -82,6 +82,10 @@ typedef struct {
uint16_t par, pdr;
} page_t;
typedef struct {
bool is_psw;
} write_rc_t;
class bus
{
private:
@ -145,16 +149,16 @@ public:
void set_lf_crs_b7();
uint8_t get_lf_crs();
uint16_t read(const uint16_t a, const word_mode_t word_mode, const rm_selection_t mode_selection, const bool peek_only=false, const d_i_space_t s = i_space);
uint16_t read (const uint16_t a, const word_mode_t word_mode, const rm_selection_t mode_selection, const bool peek_only=false, const d_i_space_t s = i_space);
uint16_t readByte(const uint16_t a) { return read(a, wm_byte, rm_cur); }
uint16_t readWord(const uint16_t a, const d_i_space_t s = i_space);
uint16_t peekWord(const uint16_t a);
uint16_t readUnibusByte(const uint16_t a);
void 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 s = i_space);
void writeByte(const uint16_t a, const uint8_t value) { return write(a, wm_byte, value, rm_cur); }
void writeWord(const uint16_t a, const uint16_t value, const d_i_space_t s = i_space);
write_rc_t 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 s = i_space);
void writeByte(const uint16_t a, const uint8_t value) { write(a, wm_byte, value, rm_cur); }
void writeWord(const uint16_t a, const uint16_t value, const d_i_space_t s = i_space);
uint16_t readPhysical(const uint32_t a);
void writePhysical(const uint32_t a, const uint16_t value);

45
cpu.cpp
View file

@ -160,9 +160,7 @@ bool cpu::put_result(const gam_rc_t & g, const uint16_t value)
return true;
}
b->write(g.addr.value(), g.word_mode, value, g.mode_selection, g.space);
return !b->is_psw(g.addr.value(), g.mode_selection, g.space);
return b->write(g.addr.value(), g.word_mode, value, g.mode_selection, g.space).is_psw == false;
}
uint16_t cpu::addRegister(const int nr, const rm_selection_t mode_selection, const uint16_t value)
@ -453,9 +451,9 @@ gam_rc_t cpu::getGAM(const uint8_t mode, const uint8_t reg, const word_mode_t wo
bool cpu::putGAM(const gam_rc_t & g, const uint16_t value)
{
if (g.addr.has_value()) {
b->write(g.addr.value(), g.word_mode, value, g.mode_selection, g.space);
auto rc = b->write(g.addr.value(), g.word_mode, value, g.mode_selection, g.space);
return !b->is_psw(g.addr.value(), g.mode_selection, g.space);
return rc.is_psw == false;
}
setRegister(g.reg.value(), value, g.mode_selection);
@ -926,15 +924,14 @@ bool cpu::single_operand_instructions(const uint16_t instr)
else {
auto a = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
int32_t vl = (a.value.value() + 1) & (word_mode == wm_byte ? 0xff : 0xffff);
bool set_flags = !b->is_psw(a.addr.value(), a.mode_selection, a.space);
bool set_flags = b->write(a.addr.value(), a.word_mode, vl, a.mode_selection, a.space).is_psw == false;
if (set_flags) {
setPSW_n(SIGN(vl, word_mode));
setPSW_z(IS_0(vl, word_mode));
setPSW_v(word_mode == wm_byte ? vl == 0x80 : vl == 0x8000);
}
b->write(a.addr.value(), a.word_mode, vl, a.mode_selection, a.space);
}
break;
@ -959,15 +956,13 @@ bool cpu::single_operand_instructions(const uint16_t instr)
auto a = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
int32_t vl = (a.value.value() - 1) & (word_mode == wm_byte ? 0xff : 0xffff);
bool set_flags = !b->is_psw(a.addr.value(), a.mode_selection, a.space);
bool set_flags = b->write(a.addr.value(), a.word_mode, vl, a.mode_selection, a.space).is_psw == false;
if (set_flags) {
setPSW_n(SIGN(vl, word_mode));
setPSW_z(IS_0(vl, word_mode));
setPSW_v(word_mode == wm_byte ? vl == 0x7f : vl == 0x7fff);
}
b->write(a.addr.value(), a.word_mode, vl, a.mode_selection, a.space);
}
break;
@ -992,9 +987,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
auto a = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
uint16_t v = -a.value.value();
b->write(a.addr.value(), a.word_mode, v, a.mode_selection, a.space);
bool set_flags = !b->is_psw(a.addr.value(), a.mode_selection, a.space);
bool set_flags = b->write(a.addr.value(), a.word_mode, v, a.mode_selection, a.space).is_psw == false;
if (set_flags) {
setPSW_n(SIGN(v, word_mode));
@ -1030,9 +1023,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
bool org_c = getPSW_c();
uint16_t v = (vo + org_c) & (word_mode == wm_byte ? 0x00ff : 0xffff);
b->write(a.addr.value(), a.word_mode, v, a.mode_selection, a.space);
bool set_flags = !b->is_psw(a.addr.value(), a.mode_selection, a.space);
bool set_flags = b->write(a.addr.value(), a.word_mode, v, a.mode_selection, a.space).is_psw == false;
if (set_flags) {
setPSW_n(SIGN(v, word_mode));
@ -1068,9 +1059,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
bool org_c = getPSW_c();
uint16_t v = (vo - org_c) & (word_mode == wm_byte ? 0xff : 0xffff);
b->write(a.addr.value(), a.word_mode, v, a.mode_selection, a.space);
bool set_flags = !b->is_psw(a.addr.value(), a.mode_selection, a.space);
bool set_flags = b->write(a.addr.value(), a.word_mode, v, a.mode_selection, a.space).is_psw == false;
if (set_flags) {
setPSW_n(SIGN(v, word_mode));
@ -1120,9 +1109,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
else
temp = (t >> 1) | (getPSW_c() << 15);
b->write(a.addr.value(), a.word_mode, temp, a.mode_selection, a.space);
bool set_flags = !b->is_psw(a.addr.value(), a.mode_selection, a.space);
bool set_flags = b->write(a.addr.value(), a.word_mode, temp, a.mode_selection, a.space).is_psw == false;
if (set_flags) {
setPSW_c(new_carry);
@ -1171,9 +1158,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
temp = (t << 1) | getPSW_c();
}
b->write(a.addr.value(), a.word_mode, temp, a.mode_selection, a.space);
bool set_flags = !b->is_psw(a.addr.value(), a.mode_selection, a.space);
bool set_flags = b->write(a.addr.value(), a.word_mode, temp, a.mode_selection, a.space).is_psw == false;
if (set_flags) {
setPSW_c(new_carry);
@ -1218,9 +1203,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
v >>= 1;
v |= hb;
b->write(a.addr.value(), a.word_mode, v, a.mode_selection, a.space);
bool set_flags = !b->is_psw(a.addr.value(), a.mode_selection, a.space);
bool set_flags = b->write(a.addr.value(), a.word_mode, v, a.mode_selection, a.space).is_psw == false;
if (set_flags) {
setPSW_n(SIGN(v, word_mode));
@ -1251,7 +1234,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
uint16_t vl = a.value.value();
uint16_t v = (vl << 1) & (word_mode == wm_byte ? 0xff : 0xffff);
bool set_flags = !b->is_psw(a.addr.value(), a.mode_selection, a.space);
bool set_flags = b->write(a.addr.value(), a.word_mode, v, a.mode_selection, a.space).is_psw == false;
if (set_flags) {
setPSW_n(SIGN(v, word_mode));
@ -1259,8 +1242,6 @@ bool cpu::single_operand_instructions(const uint16_t instr)
setPSW_c(SIGN(vl, word_mode));
setPSW_v(getPSW_n() ^ getPSW_c());
}
b->write(a.addr.value(), a.word_mode, v, a.mode_selection, a.space);
}
break;
}