From eb217996098ffb5706cfe0ca8ffa4478b73ceb8e Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Fri, 15 Feb 2019 15:23:56 +0100 Subject: Implement EXT instruction used in GLIBC startup. It requires one more field to pass to ALU. Signed-off-by: Pavel Pisa --- qtmips_machine/alu.cpp | 6 +++++- qtmips_machine/alu.h | 4 +++- qtmips_machine/core.cpp | 3 ++- qtmips_machine/instruction.cpp | 3 ++- qtmips_machine/machinedefs.h | 1 + qtmips_machine/tests/testalu.cpp | 4 ++-- 6 files changed, 15 insertions(+), 6 deletions(-) diff --git a/qtmips_machine/alu.cpp b/qtmips_machine/alu.cpp index f0e45a5..79194c9 100644 --- a/qtmips_machine/alu.cpp +++ b/qtmips_machine/alu.cpp @@ -39,7 +39,9 @@ using namespace machine; -std::uint32_t machine::alu_operate(enum AluOp operation, std::uint32_t s, std::uint32_t t, std::uint8_t sa, Registers *regs, bool &discard) { +std::uint32_t machine::alu_operate(enum AluOp operation, std::uint32_t s, std::uint32_t t, + std::uint8_t sa, std::uint8_t sz, Registers *regs, + bool &discard) { std::int64_t s64_val; std::uint64_t u64_val; discard = false; @@ -132,6 +134,8 @@ std::uint32_t machine::alu_operate(enum AluOp operation, std::uint32_t s, std::u return t << 16; case ALU_OP_BSHFL: return (uint32_t)(int32_t)(int8_t)t; + case ALU_OP_EXT: + return (s >> sa) & ((1 << sz) - 1); case ALU_OP_PASS_T: // Pass s argument without change for JAL return t; case ALU_OP_BREAK: diff --git a/qtmips_machine/alu.h b/qtmips_machine/alu.h index 372e4e6..e14a903 100644 --- a/qtmips_machine/alu.h +++ b/qtmips_machine/alu.h @@ -50,9 +50,11 @@ namespace machine { // s: Loaded from rs. Also calles as source. // t: Loaded from rt or immediate field from instruction it self. Also called as target. // sa: This is value directly from instruction it self (sa section) used for shift operations +// sz: This is value directly from instruction it self used in filed extract instructions // regs: Registers used. We need direct access to lo and hi registers (those are not accessed from core it self but from alu directly // Returned value is commonly saved to rt/rd or any other way passed trough core -std::uint32_t alu_operate(enum AluOp operation, std::uint32_t s, std::uint32_t t, std::uint8_t sa, Registers *regs, bool &discard); +std::uint32_t alu_operate(enum AluOp operation, std::uint32_t s, std::uint32_t t, + std::uint8_t sa, std::uint8_t sz, Registers *regs, bool &discard); } diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp index b80e297..dccc20b 100644 --- a/qtmips_machine/core.cpp +++ b/qtmips_machine/core.cpp @@ -322,7 +322,8 @@ struct Core::dtExecute Core::execute(const struct dtDecode &dt) { if (dt.alusrc) alu_sec = dt.immediate_val; // Sign or zero extend immediate value - std::uint32_t alu_val = alu_operate(dt.aluop, dt.val_rs, alu_sec, dt.inst.shamt(), regs, discard); + std::uint32_t alu_val = alu_operate(dt.aluop, dt.val_rs, alu_sec, + dt.inst.shamt(), dt.inst.rd(), regs, discard); if (discard) regwrite = false; diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp index 417d940..b26cc9b 100644 --- a/qtmips_machine/instruction.cpp +++ b/qtmips_machine/instruction.cpp @@ -252,7 +252,8 @@ static const struct InstructionMap special2_instruction_map[] = { }; static const struct InstructionMap special3_instruction_map[] = { - IM_UNKNOWN, // 0 + {"EXT", IT_I, ALU_OP_EXT, NOMEM, nullptr, + .flags = IMF_SUPPORTED | IMF_REGWRITE | IMF_ALU_REQ_RS}, IM_UNKNOWN, // 1 IM_UNKNOWN, // 2 IM_UNKNOWN, // 3 diff --git a/qtmips_machine/machinedefs.h b/qtmips_machine/machinedefs.h index 362bda2..a44aa75 100644 --- a/qtmips_machine/machinedefs.h +++ b/qtmips_machine/machinedefs.h @@ -95,6 +95,7 @@ enum AluOp : std::uint8_t { ALU_OP_MUL, ALU_OP_LUI, ALU_OP_BSHFL, + ALU_OP_EXT, ALU_OP_PASS_T, // Pass t argument without change for JAL ALU_OP_BREAK, ALU_OP_SYSCALL, diff --git a/qtmips_machine/tests/testalu.cpp b/qtmips_machine/tests/testalu.cpp index d3d27ec..b0e7073 100644 --- a/qtmips_machine/tests/testalu.cpp +++ b/qtmips_machine/tests/testalu.cpp @@ -224,7 +224,7 @@ void MachineTests::alu() { QFETCH(Registers, regs_res); QFETCH(std::uint32_t, res); - QCOMPARE(alu_operate(op, s , t, sa, ®s_init, discard), res); + QCOMPARE(alu_operate(op, s , t, sa, 0, ®s_init, discard), res); QCOMPARE(regs_res, regs_init); } @@ -254,5 +254,5 @@ void MachineTests::alu_except() { Registers regs; // Only runtime exception is expected as any other exception is a bug - QVERIFY_EXCEPTION_THROWN(alu_operate((enum AluOp)op, s , t, 0, ®s, discard), QtMipsExceptionRuntime); + QVERIFY_EXCEPTION_THROWN(alu_operate((enum AluOp)op, s , t, 0, 0, ®s, discard), QtMipsExceptionRuntime); } -- cgit v1.2.3