diff --git a/bus.cpp b/bus.cpp index a081aed..fa741fd 100644 --- a/bus.cpp +++ b/bus.cpp @@ -563,6 +563,38 @@ bool bus::get_use_data_space(const int run_mode) const return !!(MMR3 & di_ena_mask[run_mode]); } +std::pair bus::get_trap_action(const int run_mode, const bool d, const int apf, const bool is_write) +{ + const int access_control = pages[run_mode][d][apf].pdr & 7; + + trap_action_t trap_action = T_PROCEED; + + if (access_control == 0) + trap_action = T_ABORT_4; + else if (access_control == 1) + trap_action = is_write ? T_ABORT_4 : T_TRAP_250; + else if (access_control == 2) { + if (is_write) + trap_action = T_ABORT_4; + } + else if (access_control == 3) + trap_action = T_ABORT_4; + else if (access_control == 4) + trap_action = T_TRAP_250; + else if (access_control == 5) { + if (is_write) + trap_action = T_TRAP_250; + } + else if (access_control == 6) { + // proceed + } + else if (access_control == 7) { + trap_action = T_ABORT_4; + } + + return { trap_action, access_control }; +} + uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, const bool trap_on_failure, const bool is_write, const bool peek_only, const d_i_space_t space) { uint32_t m_offset = a; @@ -586,32 +618,9 @@ uint32_t bus::calculate_physical_address(const int run_mode, const uint16_t a, c if (trap_on_failure) { { - const int access_control = pages[run_mode][d][apf].pdr & 7; - - enum { T_PROCEED, T_ABORT_4, T_TRAP_250 } trap_action { T_PROCEED }; - - if (access_control == 0) - trap_action = T_ABORT_4; - else if (access_control == 1) - trap_action = is_write ? T_ABORT_4 : T_TRAP_250; - else if (access_control == 2) { - if (is_write) - trap_action = T_ABORT_4; - } - else if (access_control == 3) - trap_action = T_ABORT_4; - else if (access_control == 4) - trap_action = T_TRAP_250; - else if (access_control == 5) { - if (is_write) - trap_action = T_TRAP_250; - } - else if (access_control == 6) { - // proceed - } - else if (access_control == 7) { - trap_action = T_ABORT_4; - } + auto rc = get_trap_action(run_mode, d, apf, is_write); + auto trap_action = rc.first; + int access_control = rc.second; if (trap_action != T_PROCEED) { if (is_write) diff --git a/bus.h b/bus.h index d3042b0..b56e453 100644 --- a/bus.h +++ b/bus.h @@ -69,6 +69,8 @@ typedef enum { wm_word = 0, wm_byte = 1 } word_mode_t; typedef enum { rm_prev, rm_cur } rm_selection_t; +typedef enum { T_PROCEED, T_ABORT_4, T_TRAP_250 } trap_action_t; + typedef struct { uint16_t virtual_address; uint8_t apf; // active page field @@ -184,6 +186,7 @@ public: uint32_t get_io_base() const { return MMR0 & 1 ? (MMR3 & 16 ? 017760000 : 0760000) : 0160000; } bool is_psw(const uint16_t addr, const int run_mode, const d_i_space_t space) const; + std::pair get_trap_action(const int run_mode, const bool d, const int apf, const bool is_write); uint32_t calculate_physical_address(const int run_mode, const uint16_t a, const bool trap_on_failure, const bool is_write, const bool peek_only, const d_i_space_t space); bool get_use_data_space(const int run_mode) const; diff --git a/debugger.cpp b/debugger.cpp index fccf694..7fb1be9 100644 --- a/debugger.cpp +++ b/debugger.cpp @@ -621,6 +621,18 @@ void mmu_dump(console *const cnsl, bus *const b, const bool verbose) } } +const char *trap_action_to_str(const trap_action_t ta) +{ + if (ta == T_PROCEED) + return "proceed"; + if (ta == T_ABORT_4) + return "abort (trap 4)"; + if (ta == T_TRAP_250) + return "trap 250"; + + return "?"; +} + void mmu_resolve(console *const cnsl, bus *const b, const uint16_t va) { int run_mode = b->getCpu()->getPSW_runmode(); @@ -647,6 +659,14 @@ void mmu_resolve(console *const cnsl, bus *const b, const uint16_t va) dump_par_pdr(cnsl, b, ADDR_PDR_U_START, ADDR_PAR_U_START, "user i-space", 0, data.apf); dump_par_pdr(cnsl, b, ADDR_PDR_U_START + 020, ADDR_PAR_U_START + 020, "user d-space", 1 + (!!(mmr3 & 4)), data.apf); } + + for(int i=0; i<2; i++) { + auto ta_i = b->get_trap_action(run_mode, false, data.apf, i); + auto ta_d = b->get_trap_action(run_mode, true, data.apf, i); + + cnsl->put_string_lf(format("Instruction action: %s (%s)", trap_action_to_str(ta_i.first), i ? "write" : "read")); + cnsl->put_string_lf(format("Data action : %s (%s)", trap_action_to_str(ta_d.first), i ? "write" : "read")); + } } void reg_dump(console *const cnsl, cpu *const c)