summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/regfile.h1
-rw-r--r--frontend/decode.h15
-rw-r--r--inst.h1
-rw-r--r--tests/loop-indirect.hex1
4 files changed, 15 insertions, 3 deletions
diff --git a/backend/regfile.h b/backend/regfile.h
index 276504c..4cf328a 100644
--- a/backend/regfile.h
+++ b/backend/regfile.h
@@ -33,6 +33,7 @@ namespace backend {
33 auto i = writebackp.read(); 33 auto i = writebackp.read();
34 if (i.generation == generation_down) { 34 if (i.generation == generation_down) {
35 pte(i.transaction, "W", fmt::format("writeback gen={} pc={:x}", generation_down, pc)); 35 pte(i.transaction, "W", fmt::format("writeback gen={} pc={:x}", generation_down, pc));
36 assert(pc == i.init_pc);
36 auto old_pc = pc; 37 auto old_pc = pc;
37 pc = i.linear_next_pc; 38 pc = i.linear_next_pc;
38 switch (i.field[OPCODE]) { 39 switch (i.field[OPCODE]) {
diff --git a/frontend/decode.h b/frontend/decode.h
index 717d0f6..cb7bedd 100644
--- a/frontend/decode.h
+++ b/frontend/decode.h
@@ -24,15 +24,20 @@ namespace frontend {
24 unsigned int generation_down = 0; 24 unsigned int generation_down = 0;
25 std::uint64_t pc = 0; 25 std::uint64_t pc = 0;
26 26
27 std::uint64_t indirect_jump_origin = ~(std::uint64_t)0;
28 std::uint64_t indirect_jump_destination = ~(std::uint64_t)0;
29
27 static constexpr unsigned int MAX_INST_SIZE = 64; 30 static constexpr unsigned int MAX_INST_SIZE = 64;
28 static constexpr unsigned int BYTES_PER_CYCLE = 4; 31 static constexpr unsigned int BYTES_PER_CYCLE = 1;
29 32
30 void clock() { 33 void clock() {
31 if (restartp.can_read()) { 34 if (restartp.can_read()) {
32 auto r = restartp.read(); 35 auto r = restartp.read();
33 generation_down = r.new_generation; 36 generation_down = r.new_generation;
34 pc = r.new_pc; 37 next_inst.init_pc = pc = r.new_pc;
35 next_inst.size = 0; 38 next_inst.size = 0;
39 indirect_jump_origin = r.from_pc;
40 indirect_jump_destination = r.new_pc;
36 for (auto &f : next_inst.field) 41 for (auto &f : next_inst.field)
37 f = 0; 42 f = 0;
38 fetch::restart fr; 43 fetch::restart fr;
@@ -95,7 +100,10 @@ namespace frontend {
95 redirect = target; 100 redirect = target;
96 } 101 }
97 } else if (!taken.has_value() || taken.value()) { 102 } else if (!taken.has_value() || taken.value()) {
98 unpredictable = true; 103 if (next_inst.init_pc == indirect_jump_origin)
104 redirect = indirect_jump_destination;
105 else
106 unpredictable = true;
99 } 107 }
100 } 108 }
101 if (redirect.has_value()) { 109 if (redirect.has_value()) {
@@ -106,6 +114,7 @@ namespace frontend {
106 next_inst.predicted_next_pc.reset(); 114 next_inst.predicted_next_pc.reset();
107 } 115 }
108 instp->write(std::move(next_inst)); 116 instp->write(std::move(next_inst));
117 next_inst.init_pc = pc;
109 next_inst.size = unpredictable ? MAX_INST_SIZE : 0; 118 next_inst.size = unpredictable ? MAX_INST_SIZE : 0;
110 for (auto &f : next_inst.field) 119 for (auto &f : next_inst.field)
111 f = 0; 120 f = 0;
diff --git a/inst.h b/inst.h
index 15ae9d7..5f96fe3 100644
--- a/inst.h
+++ b/inst.h
@@ -8,6 +8,7 @@ struct inst {
8 infra::transaction transaction; 8 infra::transaction transaction;
9 unsigned int generation; 9 unsigned int generation;
10 unsigned int size = 0; 10 unsigned int size = 0;
11 std::uint64_t init_pc = 0;
11 std::uint64_t linear_next_pc; 12 std::uint64_t linear_next_pc;
12 std::optional<std::uint64_t> predicted_next_pc; 13 std::optional<std::uint64_t> predicted_next_pc;
13 std::uint64_t field[4] = {}; 14 std::uint64_t field[4] = {};
diff --git a/tests/loop-indirect.hex b/tests/loop-indirect.hex
new file mode 100644
index 0000000..c8b07f7
--- /dev/null
+++ b/tests/loop-indirect.hex
@@ -0,0 +1 @@
00 # 0: jmp r0 if r0 == 0