MMR1/2
This commit is contained in:
parent
87e181a8e2
commit
1673548c37
4 changed files with 78 additions and 22 deletions
42
bus.cpp
42
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
|
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 &= ~(3 << 5);
|
||||||
MMR0 |= run_mode << 5; // TODO: kernel-mode or user-mode when a trap occurs in user-mode?
|
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
|
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 &= ~(3 << 5);
|
||||||
MMR0 |= run_mode << 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);)
|
D(fprintf(stderr, "bus::calculate_physical_address %o >= %o\n", m_offset, n_pages * 8192);)
|
||||||
c->schedule_trap(04); // invalid address
|
c->schedule_trap(04); // invalid address
|
||||||
|
|
||||||
|
MMR0 |= 1 << 15; // non-resident
|
||||||
|
|
||||||
pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I
|
pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I
|
||||||
|
|
||||||
throw 1;
|
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);)
|
D(fprintf(stderr, "bus::calculate_physical_address::p_offset %o >= %o\n", p_offset, pdr_len);)
|
||||||
c->schedule_trap(0250); // invalid access
|
c->schedule_trap(0250); // invalid access
|
||||||
|
|
||||||
|
MMR0 |= 1 << 14; // length
|
||||||
|
|
||||||
pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I
|
pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I
|
||||||
|
|
||||||
throw 1;
|
throw 1;
|
||||||
|
@ -396,6 +404,19 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c
|
||||||
return m_offset;
|
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)
|
uint16_t bus::write(const uint16_t a, const bool word_mode, uint16_t value, const bool use_prev)
|
||||||
{
|
{
|
||||||
if (a >= 0160000) {
|
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;
|
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
|
if (a == 0177572) { // MMR0
|
||||||
D(fprintf(stderr, "write set MMR0: %o\n", value);)
|
D(fprintf(stderr, "write set MMR0: %o\n", value);)
|
||||||
|
|
||||||
MMR0 = value & ~(3 << 10); // bit 10 & 11 always read as 0
|
MMR0 = value & ~(3 << 10); // bit 10 & 11 always read as 0
|
||||||
|
|
||||||
|
if (value & 1)
|
||||||
|
MMR0 = value & ~(7 << 13); // reset error bits
|
||||||
|
|
||||||
return MMR0;
|
return MMR0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
bus.h
6
bus.h
|
@ -72,8 +72,10 @@ public:
|
||||||
void writeUnibusByte(const uint16_t a, const uint8_t value);
|
void writeUnibusByte(const uint16_t a, const uint8_t value);
|
||||||
|
|
||||||
uint16_t getMMR0() { return MMR0; }
|
uint16_t getMMR0() { return MMR0; }
|
||||||
|
uint16_t getMMR1() { return MMR1; }
|
||||||
void setMMR2(const uint16_t value) { MMR2 = value; }
|
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; }
|
uint16_t get_switch_register() const { return switch_register; }
|
||||||
|
|
||||||
|
|
47
cpu.cpp
47
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());)
|
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
|
// GAM = general addressing modes
|
||||||
uint16_t cpu::getGAM(const uint8_t mode, const uint8_t reg, const bool word_mode, const bool prev_mode)
|
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) {
|
switch(operation) {
|
||||||
case 0b001: { // MOV/MOVB Move Word/Byte
|
case 0b001: { // MOV/MOVB Move Word/Byte
|
||||||
|
addToMMR1(src_mode, src_reg, word_mode);
|
||||||
|
|
||||||
if (word_mode && dst_mode == 0)
|
if (word_mode && dst_mode == 0)
|
||||||
setRegister(dst_reg, false, int8_t(src_value)); // int8_t: sign extension
|
setRegister(dst_reg, false, int8_t(src_value)); // int8_t: sign extension
|
||||||
else
|
else
|
||||||
putGAM(dst_mode, dst_reg, word_mode, src_value, false);
|
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_n(SIGN(src_value, word_mode));
|
||||||
setPSW_z(IS_0(src_value, word_mode));
|
setPSW_z(IS_0(src_value, word_mode));
|
||||||
setPSW_v(false);
|
setPSW_v(false);
|
||||||
|
@ -431,10 +448,14 @@ bool cpu::double_operand_instructions(const uint16_t instr)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0b010: { // CMP/CMPB Compare Word/Byte
|
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 dst_value = getGAM(dst_mode, dst_reg, word_mode, false);
|
||||||
|
|
||||||
uint16_t temp = (src_value - dst_value) & (word_mode ? 0xff : 0xffff);
|
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);)
|
// 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));
|
||||||
|
@ -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
|
// always words: word_mode-bit is to select between MFPI and MFPD
|
||||||
assert(!word_mode); // TODO
|
assert(!word_mode); // TODO
|
||||||
|
|
||||||
|
if ((b->getMMR1() & 0160000) == 0)
|
||||||
|
b->addToMMR1(-2, 6);
|
||||||
|
|
||||||
// calculate address in current address space
|
// calculate address in current address space
|
||||||
uint16_t a = getGAMAddress(dst_mode, dst_reg, false, false);
|
uint16_t a = getGAMAddress(dst_mode, dst_reg, false, false);
|
||||||
// reed from previous space
|
// 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
|
// always words: word_mode-bit is to select between MTPI and MTPD
|
||||||
assert(!word_mode); // TODO
|
assert(!word_mode); // TODO
|
||||||
|
|
||||||
|
if ((b->getMMR1() & 0160000) == 0)
|
||||||
|
b->addToMMR1(2, 6);
|
||||||
|
|
||||||
// retrieve word from '15/14'-stack
|
// retrieve word from '15/14'-stack
|
||||||
uint16_t v = popStack();
|
uint16_t v = popStack();
|
||||||
|
|
||||||
|
@ -1381,11 +1408,23 @@ bool cpu::misc_operations(const uint16_t instr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((instr >> 8) == 0b10001000) { // EMT
|
if ((instr >> 8) == 0b10001000) { // EMT
|
||||||
|
if ((b->getMMR1() & 0160000) == 0) {
|
||||||
|
b->setMMR2(030);
|
||||||
|
b->addToMMR1(-2, 6);
|
||||||
|
b->addToMMR1(-2, 6);
|
||||||
|
}
|
||||||
|
|
||||||
trap(030);
|
trap(030);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((instr >> 8) == 0b10001001) { // TRAP
|
if ((instr >> 8) == 0b10001001) { // TRAP
|
||||||
|
if ((b->getMMR1() & 0160000) == 0) {
|
||||||
|
b->setMMR2(034);
|
||||||
|
b->addToMMR1(-2, 6);
|
||||||
|
b->addToMMR1(-2, 6);
|
||||||
|
}
|
||||||
|
|
||||||
trap(034);
|
trap(034);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1955,6 +1994,9 @@ void cpu::step()
|
||||||
{
|
{
|
||||||
instruction_count++;
|
instruction_count++;
|
||||||
|
|
||||||
|
if ((b->getMMR1() & 0160000) == 0)
|
||||||
|
b->clearMMR1();
|
||||||
|
|
||||||
if (check_queued_interrupts())
|
if (check_queued_interrupts())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1967,6 +2009,7 @@ void cpu::step()
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t temp_pc = getPC();
|
uint16_t temp_pc = getPC();
|
||||||
|
b->setMMR2(temp_pc);
|
||||||
|
|
||||||
if (temp_pc & 1)
|
if (temp_pc & 1)
|
||||||
busError();
|
busError();
|
||||||
|
@ -1994,9 +2037,5 @@ void cpu::step()
|
||||||
}
|
}
|
||||||
catch(const int exception) {
|
catch(const int exception) {
|
||||||
D(fprintf(stderr, "bus-trap during execution of command\n");)
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1
cpu.h
1
cpu.h
|
@ -40,6 +40,7 @@ private:
|
||||||
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);
|
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 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);
|
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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue