diff --git a/bus.cpp b/bus.cpp index a883566..06e8570 100644 --- a/bus.cpp +++ b/bus.cpp @@ -340,7 +340,9 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I - MMR0 |= 1 << 12; + MMR0 |= 1 << 13; // read-only + + MMR0 |= 1 << 12; // trap MMR0 &= ~(3 << 5); MMR0 |= run_mode << 5; // TODO: kernel-mode or user-mode when a trap occurs in user-mode? @@ -353,7 +355,9 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I - MMR0 |= 1 << 12; + MMR0 |= 1 << 13; // read-only + + MMR0 |= 1 << 12; // trap MMR0 &= ~(3 << 5); MMR0 |= run_mode << 5; @@ -371,6 +375,8 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c D(fprintf(stderr, "bus::calculate_physical_address %o >= %o\n", m_offset, n_pages * 8192);) c->schedule_trap(04); // invalid address + MMR0 |= 1 << 15; // non-resident + pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I throw 1; @@ -380,6 +386,8 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c D(fprintf(stderr, "bus::calculate_physical_address::p_offset %o >= %o\n", p_offset, pdr_len);) c->schedule_trap(0250); // invalid access + MMR0 |= 1 << 14; // length + pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I throw 1; @@ -396,6 +404,19 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c return m_offset; } +void bus::clearMMR1() +{ + MMR1 = 0; +} + +void bus::addToMMR1(const int8_t delta, const uint8_t reg) +{ + MMR1 <<= 8; + + MMR1 |= (delta & 5) << 3; + MMR1 |= reg; +} + uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, const bool use_prev) { if (a >= 0160000) { @@ -493,21 +514,14 @@ uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, cons return MMR3; } - if (a == 0177576) { // MMR2 - D(fprintf(stderr, "write set MMR2: %o\n", value);) - MMR2 = value; - return MMR2; - } - - if (a == 0177574) { // MMR1 - D(fprintf(stderr, "write set MMR1: %o\n", value);) - MMR1 = value; - return MMR1; - } - if (a == 0177572) { // MMR0 D(fprintf(stderr, "write set MMR0: %o\n", value);) + MMR0 = value & ~(3 << 10); // bit 10 & 11 always read as 0 + + if (value & 1) + MMR0 = value & ~(7 << 13); // reset error bits + return MMR0; } diff --git a/bus.h b/bus.h index 4ba3ac9..ad593f7 100644 --- a/bus.h +++ b/bus.h @@ -72,8 +72,10 @@ public: void writeUnibusByte(const uint16_t a, const uint8_t value); uint16_t getMMR0() { return MMR0; } - - void setMMR2(const uint16_t value) { MMR2 = value; } + uint16_t getMMR1() { return MMR1; } + void clearMMR1(); + void addToMMR1(const int8_t delta, const uint8_t reg); + void setMMR2(const uint16_t value) { MMR2 = value; } // address uint16_t get_switch_register() const { return switch_register; } diff --git a/cpu.cpp b/cpu.cpp index 9b70def..083bd05 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -275,6 +275,19 @@ void cpu::queue_interrupt(const uint8_t level, const uint8_t vector) D(fprintf(stderr, "Queueing interrupt vector %o (IPL %d, current: %d), n: %zu\n", vector, level, getPSW_spl(), it->second.size());) } +void cpu::addToMMR1(const uint8_t mode, const uint8_t reg, const bool word_mode) +{ + if (mode == 0 || mode == 1 || (b->getMMR1() & 0160000 /* bits frozen? */)) + return; + + bool neg = mode == 4 || mode == 5; + + if (!word_mode || reg >= 6 || mode == 6 || mode == 7) + b->addToMMR1(neg ? -2 : 2, reg); + else + b->addToMMR1(neg ? -1 : 1, reg); +} + // GAM = general addressing modes uint16_t cpu::getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode, const bool prev_mode) { @@ -418,11 +431,15 @@ bool cpu::double_operand_instructions(const uint16_t instr) switch(operation) { case 0b001: { // MOV/MOVB Move Word/Byte + addToMMR1(src_mode, src_reg, word_mode); + if (word_mode && dst_mode == 0) setRegister(dst_reg, false, int8_t(src_value)); // int8_t: sign extension else putGAM(dst_mode, dst_reg, word_mode, src_value, false); + addToMMR1(dst_mode, dst_reg, word_mode); + setPSW_n(SIGN(src_value, word_mode)); setPSW_z(IS_0(src_value, word_mode)); setPSW_v(false); @@ -431,10 +448,14 @@ bool cpu::double_operand_instructions(const uint16_t instr) } case 0b010: { // CMP/CMPB Compare Word/Byte + addToMMR1(src_mode, src_reg, word_mode); + uint16_t dst_value = getGAM(dst_mode, dst_reg, word_mode, false); uint16_t temp = (src_value - dst_value) & (word_mode ? 0xff : 0xffff); + 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)); @@ -1130,6 +1151,9 @@ bool cpu::single_operand_instructions(const uint16_t instr) // always words: word_mode-bit is to select between MFPI and MFPD assert(!word_mode); // TODO + if ((b->getMMR1() & 0160000) == 0) + b->addToMMR1(-2, 6); + // calculate address in current address space uint16_t a = getGAMAddress(dst_mode, dst_reg, false, false); // reed from previous space @@ -1149,6 +1173,9 @@ bool cpu::single_operand_instructions(const uint16_t instr) // always words: word_mode-bit is to select between MTPI and MTPD assert(!word_mode); // TODO + if ((b->getMMR1() & 0160000) == 0) + b->addToMMR1(2, 6); + // retrieve word from '15/14'-stack uint16_t v = popStack(); @@ -1381,11 +1408,23 @@ bool cpu::misc_operations(const uint16_t instr) } if ((instr >> 8) == 0b10001000) { // EMT + if ((b->getMMR1() & 0160000) == 0) { + b->setMMR2(030); + b->addToMMR1(-2, 6); + b->addToMMR1(-2, 6); + } + trap(030); return true; } if ((instr >> 8) == 0b10001001) { // TRAP + if ((b->getMMR1() & 0160000) == 0) { + b->setMMR2(034); + b->addToMMR1(-2, 6); + b->addToMMR1(-2, 6); + } + trap(034); return true; } @@ -1955,6 +1994,9 @@ void cpu::step() { instruction_count++; + if ((b->getMMR1() & 0160000) == 0) + b->clearMMR1(); + if (check_queued_interrupts()) return; @@ -1967,6 +2009,7 @@ void cpu::step() } uint16_t temp_pc = getPC(); + b->setMMR2(temp_pc); if (temp_pc & 1) busError(); @@ -1994,9 +2037,5 @@ void cpu::step() } catch(const int exception) { D(fprintf(stderr, "bus-trap during execution of command\n");) - - // error half way instruction; make sure it is not fully executed - - b->setMMR2(temp_pc); } } diff --git a/cpu.h b/cpu.h index f21df77..7793d07 100644 --- a/cpu.h +++ b/cpu.h @@ -37,12 +37,13 @@ private: bool check_queued_interrupts(); uint16_t getRegister(const int nr, const bool MF_MT) const; - void setRegister(const int nr, const bool MF_MT, const uint16_t value); + void setRegister(const int nr, const bool MF_MT, const uint16_t value); uint16_t addRegister(const int nr, const bool MF_MT, const uint16_t value); + void addToMMR1(const uint8_t mode, const uint8_t reg, const bool word_mode); uint16_t getGAMAddress(const uint8_t mode, const int reg, const bool word_mode, const bool MF_MT); uint16_t getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode, const bool MF_MT); - void putGAM(const uint8_t mode, const int reg, const bool word_mode, const uint16_t value, const bool MF_FT); + void putGAM(const uint8_t mode, const int reg, const bool word_mode, const uint16_t value, const bool MF_FT); bool double_operand_instructions(const uint16_t instr); bool additional_double_operand_instructions(const uint16_t instr);