page written bit only when written
double trap: use stack from 000004
This commit is contained in:
parent
88933e303c
commit
42fc44b206
5 changed files with 48 additions and 37 deletions
20
bus.cpp
20
bus.cpp
|
@ -278,8 +278,6 @@ uint16_t bus::read(const uint16_t a, const bool word_mode, const bool use_prev,
|
||||||
|
|
||||||
DOLOG(debug, !peek_only, "UNHANDLED read %o(%c)", a, word_mode ? 'B' : ' ');
|
DOLOG(debug, !peek_only, "UNHANDLED read %o(%c)", a, word_mode ? 'B' : ' ');
|
||||||
|
|
||||||
// c -> busError();
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +295,6 @@ uint16_t bus::read(const uint16_t a, const bool word_mode, const bool use_prev,
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void bus::setMMR0(int value)
|
void bus::setMMR0(int value)
|
||||||
{
|
{
|
||||||
value &= ~(3 << 10); // bit 10 & 11 always read as 0
|
value &= ~(3 << 10); // bit 10 & 11 always read as 0
|
||||||
|
@ -345,10 +342,11 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c
|
||||||
if ((a & 1) && word_mode == 0 && peek_only == false) {
|
if ((a & 1) && word_mode == 0 && peek_only == false) {
|
||||||
DOLOG(debug, true, "TRAP(004) (throw 5) on address %06o, page %d, run mode %d, MMR0 %06o, MMR2 %06o", a, apf, run_mode, MMR0, MMR2);
|
DOLOG(debug, true, "TRAP(004) (throw 5) on address %06o, page %d, run mode %d, MMR0 %06o, MMR2 %06o", a, apf, run_mode, MMR0, MMR2);
|
||||||
|
|
||||||
|
if (is_write)
|
||||||
pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I
|
pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I
|
||||||
|
|
||||||
MMR0 &= ~14; // add current page
|
//MMR0 &= ~14; // add current page
|
||||||
MMR0 |= apf << 1;
|
//MMR0 |= apf << 1;
|
||||||
|
|
||||||
c->schedule_trap(004); // invalid access
|
c->schedule_trap(004); // invalid access
|
||||||
|
|
||||||
|
@ -375,6 +373,7 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c
|
||||||
|
|
||||||
c->schedule_trap(0250); // invalid address
|
c->schedule_trap(0250); // invalid address
|
||||||
|
|
||||||
|
if (is_write)
|
||||||
pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I
|
pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I
|
||||||
|
|
||||||
if ((MMR0 & 0160000) == 0) {
|
if ((MMR0 & 0160000) == 0) {
|
||||||
|
@ -398,6 +397,7 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c
|
||||||
|
|
||||||
c->schedule_trap(0250); // invalid address
|
c->schedule_trap(0250); // invalid address
|
||||||
|
|
||||||
|
if (is_write)
|
||||||
pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I
|
pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I
|
||||||
|
|
||||||
if ((MMR0 & 0160000) == 0) {
|
if ((MMR0 & 0160000) == 0) {
|
||||||
|
@ -435,6 +435,7 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c
|
||||||
MMR0 |= run_mode << 5;
|
MMR0 |= run_mode << 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_write)
|
||||||
pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I
|
pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I
|
||||||
|
|
||||||
c->schedule_trap(04);
|
c->schedule_trap(04);
|
||||||
|
@ -442,14 +443,16 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c
|
||||||
throw 3;
|
throw 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t pdr_len = ((pages[run_mode][0][apf].pdr >> 8) & 127) * 64; // TODO: D/I
|
// uint16_t pdr_len = ((pages[run_mode][0][apf].pdr >> 8) & 127) * 64; // TODO: D/I
|
||||||
|
uint16_t pdr_len = (pages[run_mode][0][apf].pdr >> 8) & 127;
|
||||||
|
uint16_t pdr_cmp = (a >> 6) & 127;
|
||||||
|
|
||||||
bool direction = pages[run_mode][0][apf].pdr & 8; // TODO: D/I
|
bool direction = pages[run_mode][0][apf].pdr & 8; // TODO: D/I
|
||||||
|
|
||||||
// DOLOG(debug, true, "p_offset %06o pdr_len %06o direction %d, run_mode %d, apf %d, pdr: %06o", p_offset, pdr_len, direction, run_mode, apf, pages[run_mode][0][apf].pdr);
|
// DOLOG(debug, true, "p_offset %06o pdr_len %06o direction %d, run_mode %d, apf %d, pdr: %06o", p_offset, pdr_len, direction, run_mode, apf, pages[run_mode][0][apf].pdr);
|
||||||
|
|
||||||
if ((p_offset > pdr_len && direction == false) || (p_offset < pdr_len && direction == true)) {
|
if ((pdr_cmp > pdr_len && direction == false) || (pdr_cmp < pdr_len && direction == true)) {
|
||||||
DOLOG(debug, !peek_only, "bus::calculate_physical_address::p_offset %o >= %o", p_offset, pdr_len);
|
DOLOG(debug, !peek_only, "bus::calculate_physical_address::p_offset %o versus %o direction %d", pdr_cmp, pdr_len, direction);
|
||||||
DOLOG(debug, true, "TRAP(0250) (throw 4) on address %06o", a);
|
DOLOG(debug, true, "TRAP(0250) (throw 4) on address %06o", a);
|
||||||
c->schedule_trap(0250); // invalid access
|
c->schedule_trap(0250); // invalid access
|
||||||
|
|
||||||
|
@ -464,6 +467,7 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c
|
||||||
MMR0 |= run_mode << 5;
|
MMR0 |= run_mode << 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_write)
|
||||||
pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I
|
pages[run_mode][0][apf].pdr |= 1 << 7; // TODO: D/I
|
||||||
|
|
||||||
throw 4;
|
throw 4;
|
||||||
|
|
28
cpu.cpp
28
cpu.cpp
|
@ -1645,11 +1645,6 @@ bool cpu::misc_operations(const uint16_t instr)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu::busError()
|
|
||||||
{
|
|
||||||
trap(4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cpu::schedule_trap(const uint16_t vector)
|
void cpu::schedule_trap(const uint16_t vector)
|
||||||
{
|
{
|
||||||
scheduled_trap = vector;
|
scheduled_trap = vector;
|
||||||
|
@ -1658,7 +1653,7 @@ void cpu::schedule_trap(const uint16_t vector)
|
||||||
// 'is_interrupt' is not correct naming; it is true for mmu faults and interrupts
|
// 'is_interrupt' is not correct naming; it is true for mmu faults and interrupts
|
||||||
void cpu::trap(uint16_t vector, const int new_ipl, const bool is_interrupt)
|
void cpu::trap(uint16_t vector, const int new_ipl, const bool is_interrupt)
|
||||||
{
|
{
|
||||||
DOLOG(debug, true, "*** CPU::TRAP ***");
|
DOLOG(debug, true, "*** CPU::TRAP, MMR0: %06o, MMR2: %06o ***", b->getMMR0(), b->getMMR2());
|
||||||
|
|
||||||
int processing_trap_depth = 0;
|
int processing_trap_depth = 0;
|
||||||
uint16_t before_psw = 0;
|
uint16_t before_psw = 0;
|
||||||
|
@ -1668,9 +1663,16 @@ void cpu::trap(uint16_t vector, const int new_ipl, const bool is_interrupt)
|
||||||
try {
|
try {
|
||||||
processing_trap_depth++;
|
processing_trap_depth++;
|
||||||
|
|
||||||
|
bool kernel_mode = psw >> 14;
|
||||||
|
|
||||||
if (processing_trap_depth >= 2) {
|
if (processing_trap_depth >= 2) {
|
||||||
|
DOLOG(debug, true, "Trap depth %d", processing_trap_depth);
|
||||||
|
|
||||||
|
if (kernel_mode)
|
||||||
vector = 4;
|
vector = 4;
|
||||||
|
|
||||||
|
setRegister(6, 04);
|
||||||
|
|
||||||
if (processing_trap_depth >= 3) {
|
if (processing_trap_depth >= 3) {
|
||||||
// TODO: halt?
|
// TODO: halt?
|
||||||
}
|
}
|
||||||
|
@ -1678,10 +1680,6 @@ void cpu::trap(uint16_t vector, const int new_ipl, const bool is_interrupt)
|
||||||
else {
|
else {
|
||||||
before_psw = getPSW();
|
before_psw = getPSW();
|
||||||
before_pc = getPC();
|
before_pc = getPC();
|
||||||
}
|
|
||||||
|
|
||||||
// make sure the trap vector is retrieved from kernel space
|
|
||||||
psw &= 037777; // mask off 14/15
|
|
||||||
|
|
||||||
if ((b->getMMR0() & 0160000) == 0 && vector != 4) {
|
if ((b->getMMR0() & 0160000) == 0 && vector != 4) {
|
||||||
b->setMMR2(vector);
|
b->setMMR2(vector);
|
||||||
|
@ -1693,6 +1691,10 @@ void cpu::trap(uint16_t vector, const int new_ipl, const bool is_interrupt)
|
||||||
b->clearMMR0Bit(12);
|
b->clearMMR0Bit(12);
|
||||||
else
|
else
|
||||||
b->setMMR0Bit(12); // it's a trap
|
b->setMMR0Bit(12); // it's a trap
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the trap vector is retrieved from kernel space
|
||||||
|
psw &= 037777; // mask off 14/15
|
||||||
|
|
||||||
setPC(b->readWord(vector + 0));
|
setPC(b->readWord(vector + 0));
|
||||||
|
|
||||||
|
@ -1704,6 +1706,9 @@ void cpu::trap(uint16_t vector, const int new_ipl, const bool is_interrupt)
|
||||||
setPSW(new_psw, false);
|
setPSW(new_psw, false);
|
||||||
|
|
||||||
// DOLOG(info, true, "R6: %06o, before PSW: %06o, new PSW: %06o", getRegister(6), before_psw, new_psw);
|
// DOLOG(info, true, "R6: %06o, before PSW: %06o, new PSW: %06o", getRegister(6), before_psw, new_psw);
|
||||||
|
//
|
||||||
|
if (processing_trap_depth >= 2 && kernel_mode)
|
||||||
|
setRegister(6, 04);
|
||||||
|
|
||||||
pushStack(before_psw);
|
pushStack(before_psw);
|
||||||
pushStack(before_pc);
|
pushStack(before_pc);
|
||||||
|
@ -2192,6 +2197,9 @@ 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 });
|
||||||
|
|
||||||
|
out.insert({ "MMR0", { format("%06o", b->getMMR0()) } });
|
||||||
|
out.insert({ "MMR2", { format("%06o", b->getMMR2()) } });
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
cpu.h
1
cpu.h
|
@ -95,7 +95,6 @@ public:
|
||||||
void init_interrupt_queue();
|
void init_interrupt_queue();
|
||||||
void queue_interrupt(const uint8_t level, const uint8_t vector);
|
void queue_interrupt(const uint8_t level, const uint8_t vector);
|
||||||
|
|
||||||
void busError();
|
|
||||||
void trap(uint16_t vector, const int new_ipl = -1, const bool is_interrupt = false);
|
void trap(uint16_t vector, const int new_ipl = -1, const bool is_interrupt = false);
|
||||||
void schedule_trap(const uint16_t vector);
|
void schedule_trap(const uint16_t vector);
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,9 @@ int disassemble(cpu *const c, console *const cnsl, const int pc, const bool inst
|
||||||
|
|
||||||
std::string instruction = data["instruction-text"].at(0);
|
std::string instruction = data["instruction-text"].at(0);
|
||||||
|
|
||||||
|
std::string MMR0 = data["MMR0"].at(0);
|
||||||
|
std::string MMR2 = data["MMR2"].at(0);
|
||||||
|
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
if (instruction_only)
|
if (instruction_only)
|
||||||
|
@ -38,13 +41,13 @@ int disassemble(cpu *const c, console *const cnsl, const int pc, const bool inst
|
||||||
work_values.c_str()
|
work_values.c_str()
|
||||||
);
|
);
|
||||||
else
|
else
|
||||||
result = format("R0: %s, R1: %s, R2: %s, R3: %s, R4: %s, R5: %s, SP: %s, PC: %06o, PSW: %s, instr: %s: %s - %s",
|
result = format("R0: %s, R1: %s, R2: %s, R3: %s, R4: %s, R5: %s, SP: %s, PC: %06o, PSW: %s, instr: %s: %s - MMR0/2: %s/%s",
|
||||||
registers[0].c_str(), registers[1].c_str(), registers[2].c_str(), registers[3].c_str(), registers[4].c_str(), registers[5].c_str(),
|
registers[0].c_str(), registers[1].c_str(), registers[2].c_str(), registers[3].c_str(), registers[4].c_str(), registers[5].c_str(),
|
||||||
registers[6].c_str(), pc,
|
registers[6].c_str(), pc,
|
||||||
psw.c_str(),
|
psw.c_str(),
|
||||||
instruction_values.c_str(),
|
instruction_values.c_str(),
|
||||||
instruction.c_str(),
|
instruction.c_str(),
|
||||||
work_values.c_str()
|
MMR0.c_str(), MMR2.c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (cnsl)
|
if (cnsl)
|
||||||
|
|
3
tests.h
3
tests.h
|
@ -1,3 +0,0 @@
|
||||||
// (C) 2018 by Folkert van Heusden
|
|
||||||
// Released under Apache License v2.0
|
|
||||||
void tests(cpu *const c);
|
|
Loading…
Add table
Reference in a new issue