From ab9ddf2beb8a266dd31e31178c53616b79ce4428 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Fri, 15 Feb 2019 15:03:12 +0100 Subject: Core: move complex memory operation to own function and implement LWL, LWR, SWL, SWR. The move makes basic memory stage processing more readable. Signed-off-by: Pavel Pisa --- qtmips_machine/core.cpp | 91 ++++++++++++++++++++++++++++++++++-------- qtmips_machine/core.h | 5 +++ qtmips_machine/instruction.cpp | 16 ++++---- qtmips_machine/machinedefs.h | 5 +++ 4 files changed, 92 insertions(+), 25 deletions(-) diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp index a276b3b..b80e297 100644 --- a/qtmips_machine/core.cpp +++ b/qtmips_machine/core.cpp @@ -139,6 +139,67 @@ void Core::set_c0_userlocal(std::uint32_t address) { hwr_userlocal = address; } +enum ExceptionCause Core::memory_special(enum AccessControl memctl, + int mode, bool memread, bool memwrite, + std::uint32_t &towrite_val, + std::uint32_t rt_value, std::uint32_t mem_addr) { + std::uint32_t mask; + std::uint32_t shift; + std::uint32_t temp; + (void)mode; + + switch (memctl) { + case AC_CACHE_OP: + mem_data->sync(); + mem_program->sync(); + break; + case AC_STORE_CONDITIONAL: + if (!memwrite) + break; + mem_data->write_ctl(AC_WORD, mem_addr, rt_value); + towrite_val = 1; + break; + case AC_LOAD_LINKED: + if (!memread) + break; + towrite_val = mem_data->read_ctl(AC_WORD, mem_addr); + break; + case AC_WORD_RIGHT: + if (memwrite) { + shift = (3 - (mem_addr & 3)) << 3; + mask = 0xffffffff << shift; + temp = mem_data->read_ctl(AC_WORD, mem_addr & ~3); + temp = (temp & ~mask) | (rt_value << shift); + mem_data->write_ctl(AC_WORD, mem_addr & ~3, temp); + } else { + shift = (3 - (mem_addr & 3)) << 3; + mask = 0xffffffff >> shift; + towrite_val = mem_data->read_ctl(AC_WORD, mem_addr & ~3); + towrite_val = (towrite_val >> shift) | (rt_value & ~mask); + } + break; + case AC_WORD_LEFT: + if (memwrite) { + shift = (mem_addr & 3) << 3; + mask = 0xffffffff >> shift; + temp = mem_data->read_ctl(AC_WORD, mem_addr & ~3); + temp = (temp & ~mask) | (rt_value >> shift); + mem_data->write_ctl(AC_WORD, mem_addr & ~3, temp); + } else { + shift = (mem_addr & 3) << 3; + mask = 0xffffffff << shift; + towrite_val = mem_data->read_ctl(AC_WORD, mem_addr & ~3); + towrite_val = (towrite_val << shift) | (rt_value & ~mask); + } + break; + default: + break; + } + + return EXCAUSE_NONE; +} + + struct Core::dtFetch Core::fetch(bool skip_break) { enum ExceptionCause excause = EXCAUSE_NONE; std::uint32_t inst_addr = regs->read_pc(); @@ -321,31 +382,27 @@ struct Core::dtExecute Core::execute(const struct dtDecode &dt) { struct Core::dtMemory Core::memory(const struct dtExecute &dt) { std::uint32_t towrite_val = dt.alu_val; std::uint32_t mem_addr = dt.alu_val; + enum ExceptionCause excause = dt.excause; bool memread = dt.memread; bool memwrite = dt.memwrite; bool regwrite = dt.regwrite; + if (excause == EXCAUSE_NONE) { + if (dt.memctl > AC_LAST_REGULAR) { + excause = memory_special(dt.memctl, dt.inst.rt(), memread, memwrite, + towrite_val, dt.val_rt, mem_addr); + } else { + if (memwrite) + mem_data->write_ctl(dt.memctl, mem_addr, dt.val_rt); + if (memread) + towrite_val = mem_data->read_ctl(dt.memctl, mem_addr); + } + } + if (dt.excause != EXCAUSE_NONE) { memread = false; memwrite = false; regwrite = false; - } else { - if (dt.memctl == AC_CACHE_OP) { - mem_data->sync(); - mem_program->sync(); - } else if (memwrite) { - if (dt.memctl == AC_STORE_CONDITIONAL) { - mem_data->write_ctl(AC_WORD, mem_addr, dt.val_rt); - towrite_val = 1; - } else { - mem_data->write_ctl(dt.memctl, mem_addr, dt.val_rt); - } - } else if (memread) { - if (dt.memctl == AC_LOAD_LINKED) - towrite_val = mem_data->read_ctl(AC_WORD, mem_addr); - else - towrite_val = mem_data->read_ctl(dt.memctl, mem_addr); - } } emit memory_inst_addr_value(dt.inst_addr); diff --git a/qtmips_machine/core.h b/qtmips_machine/core.h index 889a30c..7784797 100644 --- a/qtmips_machine/core.h +++ b/qtmips_machine/core.h @@ -234,6 +234,11 @@ protected: void writeback(const struct dtMemory&); bool handle_pc(const struct dtDecode&); + enum ExceptionCause memory_special(enum AccessControl memctl, + int mode, bool memread, bool memwrite, + std::uint32_t &towrite_val, + std::uint32_t rt_value, std::uint32_t mem_addr); + // Initialize structures to NOPE instruction void dtFetchInit(struct dtFetch &dt); void dtDecodeInit(struct dtDecode &dt); diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp index 0788eac..417d940 100644 --- a/qtmips_machine/instruction.cpp +++ b/qtmips_machine/instruction.cpp @@ -432,29 +432,29 @@ static const struct InstructionMap instruction_map[] = { .flags = FLAGS_ALU_I_LOAD}, {"LH", IT_I, ALU_OP_ADDU, AC_HALFWORD, nullptr, // LH .flags = FLAGS_ALU_I_LOAD}, - {"LWL", IT_I, ALU_OP_ADDU, NOMEM, nullptr, // LWL - unsupported - .flags = IMF_MEM}, + {"LWL", IT_I, ALU_OP_ADDU, AC_WORD_LEFT, nullptr, // LWL - unsupported + .flags = FLAGS_ALU_I_LOAD | IMF_ALU_REQ_RT}, {"LW", IT_I, ALU_OP_ADDU, AC_WORD, nullptr, // LW .flags = FLAGS_ALU_I_LOAD}, {"LBU", IT_I, ALU_OP_ADDU, AC_BYTE_UNSIGNED, nullptr, // LBU .flags = FLAGS_ALU_I_LOAD}, {"LHU", IT_I, ALU_OP_ADDU, AC_HALFWORD_UNSIGNED, nullptr, // LHU .flags = FLAGS_ALU_I_LOAD}, - {"LWR", IT_I, ALU_OP_ADDU, NOMEM, nullptr, // LWR - unsupported - .flags = IMF_MEM}, + {"LWR", IT_I, ALU_OP_ADDU, AC_WORD_RIGHT, nullptr, // LWR - unsupported + .flags = FLAGS_ALU_I_LOAD | IMF_ALU_REQ_RT}, IM_UNKNOWN, // 39 {"SB", IT_I, ALU_OP_ADDU, AC_BYTE, nullptr, // SB .flags = FLAGS_ALU_I_STORE}, {"SH", IT_I, ALU_OP_ADDU, AC_HALFWORD, nullptr, // SH .flags = FLAGS_ALU_I_STORE}, - {"SWL", IT_I, ALU_OP_ADDU, NOMEM, nullptr, // SWL - .flags = IMF_MEM | IMF_MEMWRITE}, + {"SWL", IT_I, ALU_OP_ADDU, AC_WORD_LEFT, nullptr, // SWL + .flags = FLAGS_ALU_I_STORE}, {"SW", IT_I, ALU_OP_ADDU, AC_WORD, nullptr, // SW .flags = FLAGS_ALU_I_STORE}, IM_UNKNOWN, // 44 IM_UNKNOWN, // 45 - {"SWR", IT_I, ALU_OP_ADDU, NOMEM, nullptr, // SWR - .flags = IMF_MEM | IMF_MEMWRITE}, + {"SWR", IT_I, ALU_OP_ADDU, AC_WORD_RIGHT, nullptr, // SWR + .flags = FLAGS_ALU_I_STORE}, {"CACHE", IT_I, ALU_OP_ADDU, AC_CACHE_OP, nullptr, // CACHE .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_MEM}, {"LL", IT_I, ALU_OP_ADDU, AC_LOAD_LINKED, nullptr, // LL diff --git a/qtmips_machine/machinedefs.h b/qtmips_machine/machinedefs.h index ef9ec0d..362bda2 100644 --- a/qtmips_machine/machinedefs.h +++ b/qtmips_machine/machinedefs.h @@ -49,7 +49,12 @@ enum AccessControl { AC_HALFWORD_UNSIGNED, AC_LOAD_LINKED, AC_STORE_CONDITIONAL, + AC_WORD_RIGHT, + AC_WORD_LEFT, AC_CACHE_OP, + + AC_FIRST_REGULAR = AC_BYTE, + AC_LAST_REGULAR = AC_HALFWORD_UNSIGNED, }; enum ExceptionCause { -- cgit v1.2.3