aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2019-02-15 15:23:56 +0100
committerPavel Pisa <pisa@cmp.felk.cvut.cz>2019-02-15 15:23:56 +0100
commiteb217996098ffb5706cfe0ca8ffa4478b73ceb8e (patch)
treeb968a4edf276d5f2cf9db422f455774bf7a7061d
parentab9ddf2beb8a266dd31e31178c53616b79ce4428 (diff)
downloadqtmips-eb217996098ffb5706cfe0ca8ffa4478b73ceb8e.tar.gz
qtmips-eb217996098ffb5706cfe0ca8ffa4478b73ceb8e.tar.bz2
qtmips-eb217996098ffb5706cfe0ca8ffa4478b73ceb8e.zip
Implement EXT instruction used in GLIBC startup.
It requires one more field to pass to ALU. Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
-rw-r--r--qtmips_machine/alu.cpp6
-rw-r--r--qtmips_machine/alu.h4
-rw-r--r--qtmips_machine/core.cpp3
-rw-r--r--qtmips_machine/instruction.cpp3
-rw-r--r--qtmips_machine/machinedefs.h1
-rw-r--r--qtmips_machine/tests/testalu.cpp4
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, &regs_init, discard), res);
+ QCOMPARE(alu_operate(op, s , t, sa, 0, &regs_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, &regs, discard), QtMipsExceptionRuntime);
+ QVERIFY_EXCEPTION_THROWN(alu_operate((enum AluOp)op, s , t, 0, 0, &regs, discard), QtMipsExceptionRuntime);
}