From 3fe0d92d41e20d02721652300f94afe56b2946fc Mon Sep 17 00:00:00 2001
From: Luke Wren <wren6991@gmail.com>
Date: Sat, 11 Dec 2021 12:53:37 +0000
Subject: [PATCH] Add load/store alignment testcases

---
 .../sim/sw_testcases/load_misalign_halfword.c | 45 +++++++++++++++++++
 .../load_misalign_halfword.expected_output    | 18 ++++++++
 test/sim/sw_testcases/load_misalign_word.c    | 31 +++++++++++++
 .../load_misalign_word.expected_output        | 11 +++++
 .../sw_testcases/store_misalign_halfword.c    | 31 +++++++++++++
 .../store_misalign_halfword.expected_output   |  9 ++++
 test/sim/sw_testcases/store_misalign_word.c   | 32 +++++++++++++
 .../store_misalign_word.expected_output       | 11 +++++
 8 files changed, 188 insertions(+)
 create mode 100644 test/sim/sw_testcases/load_misalign_halfword.c
 create mode 100644 test/sim/sw_testcases/load_misalign_halfword.expected_output
 create mode 100644 test/sim/sw_testcases/load_misalign_word.c
 create mode 100644 test/sim/sw_testcases/load_misalign_word.expected_output
 create mode 100644 test/sim/sw_testcases/store_misalign_halfword.c
 create mode 100644 test/sim/sw_testcases/store_misalign_halfword.expected_output
 create mode 100644 test/sim/sw_testcases/store_misalign_word.c
 create mode 100644 test/sim/sw_testcases/store_misalign_word.expected_output

diff --git a/test/sim/sw_testcases/load_misalign_halfword.c b/test/sim/sw_testcases/load_misalign_halfword.c
new file mode 100644
index 0000000..2cea954
--- /dev/null
+++ b/test/sim/sw_testcases/load_misalign_halfword.c
@@ -0,0 +1,45 @@
+#include "tb_cxxrtl_io.h"
+#include "hazard3_csr.h"
+
+int main() {
+	volatile uint32_t target_word = 0x1234cdefu;
+	volatile uint32_t result_word = 0;
+	tb_puts("Load halfword signed, 1 byte offset\n");
+	asm volatile("lh %0, 1(%1)" : "+r" (result_word) : "r" (&target_word));
+	tb_printf("Result: %08x\n", result_word);
+	tb_puts("Load halfword signed, 3 byte offset\n");
+	asm volatile("lh %0, 3(%1)" : "+r" (result_word) : "r" (&target_word));
+	tb_printf("Result: %08x\n", result_word);
+	tb_puts("Load halfword signed aligned (sanity check)\n");
+	asm volatile("lh %0, 0(%1)" : "+r" (result_word) : "r" (&target_word));
+	tb_printf("Result: %08x\n", result_word);
+	asm volatile("lh %0, 2(%1)" : "+r" (result_word) : "r" (&target_word));
+	tb_printf("Result: %08x\n", result_word);
+
+	result_word = 0;
+	tb_puts("Load halfword unsigned, 1 byte offset\n");
+	asm volatile("lhu %0, 1(%1)" : "+r" (result_word) : "r" (&target_word));
+	tb_printf("Result: %08x\n", result_word);
+	tb_puts("Load halfword unsigned, 3 byte offset\n");
+	asm volatile("lhu %0, 3(%1)" : "+r" (result_word) : "r" (&target_word));
+	tb_printf("Result: %08x\n", result_word);
+	tb_puts("Load halfword unsigned aligned (sanity check)\n");
+	asm volatile("lhu %0, 0(%1)" : "+r" (result_word) : "r" (&target_word));
+	tb_printf("Result: %08x\n", result_word);
+	asm volatile("lhu %0, 2(%1)" : "+r" (result_word) : "r" (&target_word));
+	tb_printf("Result: %08x\n", result_word);
+
+	return 0;
+}
+
+void __attribute__((interrupt)) handle_exception() {
+	tb_printf("-> exception, mcause = %u\n", read_csr(mcause));
+	write_csr(mcause, 0);
+	if (*(uint16_t*)read_csr(mepc) & 0x3 == 0x3) {
+		write_csr(mepc, read_csr(mepc) + 4);
+	}
+	else {
+		write_csr(mepc, read_csr(mepc) + 2);
+	}
+}
+
diff --git a/test/sim/sw_testcases/load_misalign_halfword.expected_output b/test/sim/sw_testcases/load_misalign_halfword.expected_output
new file mode 100644
index 0000000..d9a1a7a
--- /dev/null
+++ b/test/sim/sw_testcases/load_misalign_halfword.expected_output
@@ -0,0 +1,18 @@
+Load halfword signed, 1 byte offset
+-> exception, mcause = 4
+Result: 00000000
+Load halfword signed, 3 byte offset
+-> exception, mcause = 4
+Result: 00000000
+Load halfword signed aligned (sanity check)
+Result: ffffcdef
+Result: 00001234
+Load halfword unsigned, 1 byte offset
+-> exception, mcause = 4
+Result: 00000000
+Load halfword unsigned, 3 byte offset
+-> exception, mcause = 4
+Result: 00000000
+Load halfword unsigned aligned (sanity check)
+Result: 0000cdef
+Result: 00001234
diff --git a/test/sim/sw_testcases/load_misalign_word.c b/test/sim/sw_testcases/load_misalign_word.c
new file mode 100644
index 0000000..59039a2
--- /dev/null
+++ b/test/sim/sw_testcases/load_misalign_word.c
@@ -0,0 +1,31 @@
+#include "tb_cxxrtl_io.h"
+#include "hazard3_csr.h"
+
+int main() {
+	volatile uint32_t target_word = -1u;
+	volatile uint32_t result_word = 0;
+	tb_puts("Load word, 1 byte offset\n");
+	asm volatile("lw %0, 1(%1)" : "+r" (result_word) : "r" (&target_word));
+	tb_printf("Result: %08x\n", result_word);
+	tb_puts("Load word, 2 byte offset\n");
+	asm volatile("lw %0, 2(%1)" : "+r" (result_word) : "r" (&target_word));
+	tb_printf("Result: %08x\n", result_word);
+	tb_puts("Load word, 3 byte offset\n");
+	asm volatile("lw %0, 3(%1)" : "+r" (result_word) : "r" (&target_word));
+	tb_printf("Result: %08x\n", result_word);
+	tb_puts("Load word aligned (sanity check)\n");
+	asm volatile("lw %0, 0(%1)" : "+r" (result_word) : "r" (&target_word));
+	tb_printf("Result: %08x\n", result_word);
+}
+
+void __attribute__((interrupt)) handle_exception() {
+	tb_printf("-> exception, mcause = %u\n", read_csr(mcause));
+	write_csr(mcause, 0);
+	if (*(uint16_t*)read_csr(mepc) & 0x3 == 0x3) {
+		write_csr(mepc, read_csr(mepc) + 4);
+	}
+	else {
+		write_csr(mepc, read_csr(mepc) + 2);
+	}
+}
+
diff --git a/test/sim/sw_testcases/load_misalign_word.expected_output b/test/sim/sw_testcases/load_misalign_word.expected_output
new file mode 100644
index 0000000..4d652d3
--- /dev/null
+++ b/test/sim/sw_testcases/load_misalign_word.expected_output
@@ -0,0 +1,11 @@
+Load word, 1 byte offset
+-> exception, mcause = 4
+Result: 00000000
+Load word, 2 byte offset
+-> exception, mcause = 4
+Result: 00000000
+Load word, 3 byte offset
+-> exception, mcause = 4
+Result: 00000000
+Load word aligned (sanity check)
+Result: ffffffff
diff --git a/test/sim/sw_testcases/store_misalign_halfword.c b/test/sim/sw_testcases/store_misalign_halfword.c
new file mode 100644
index 0000000..e51029d
--- /dev/null
+++ b/test/sim/sw_testcases/store_misalign_halfword.c
@@ -0,0 +1,31 @@
+#include "tb_cxxrtl_io.h"
+#include "hazard3_csr.h"
+
+int main() {
+	volatile uint32_t target_word = -1u;
+	tb_puts("Store halfword, 1 byte offset\n");
+	asm volatile ("sh zero, 1(%0)" : : "r" (&target_word));
+	tb_printf("Target value: %08x\n", target_word);
+	tb_puts("Store halfword, 3 byte offset\n");
+	asm volatile ("sh zero, 3(%0)" : : "r" (&target_word));
+	tb_printf("Target value: %08x\n", target_word);
+	tb_puts("Aligned store halfword, sanity check\n");
+	asm volatile ("sh zero, 0(%0)" : : "r" (&target_word));
+	tb_printf("Target value: %08x\n", target_word);
+	asm volatile ("sh zero, 2(%0)" : : "r" (&target_word));
+	tb_printf("Target value: %08x\n", target_word);
+
+	return 0;
+}
+
+void __attribute__((interrupt)) handle_exception() {
+	tb_printf("-> exception, mcause = %u\n", read_csr(mcause));
+	write_csr(mcause, 0);
+	if (*(uint16_t*)read_csr(mepc) & 0x3 == 0x3) {
+		write_csr(mepc, read_csr(mepc) + 4);
+	}
+	else {
+		write_csr(mepc, read_csr(mepc) + 2);
+	}
+}
+
diff --git a/test/sim/sw_testcases/store_misalign_halfword.expected_output b/test/sim/sw_testcases/store_misalign_halfword.expected_output
new file mode 100644
index 0000000..dcbf772
--- /dev/null
+++ b/test/sim/sw_testcases/store_misalign_halfword.expected_output
@@ -0,0 +1,9 @@
+Store halfword, 1 byte offset
+-> exception, mcause = 6
+Target value: ffffffff
+Store halfword, 3 byte offset
+-> exception, mcause = 6
+Target value: ffffffff
+Aligned store halfword, sanity check
+Target value: ffff0000
+Target value: 00000000
diff --git a/test/sim/sw_testcases/store_misalign_word.c b/test/sim/sw_testcases/store_misalign_word.c
new file mode 100644
index 0000000..e23db15
--- /dev/null
+++ b/test/sim/sw_testcases/store_misalign_word.c
@@ -0,0 +1,32 @@
+#include "tb_cxxrtl_io.h"
+#include "hazard3_csr.h"
+
+int main() {
+	volatile uint32_t target_word = -1u;
+	tb_puts("Store word, 1 byte offset\n");
+	asm volatile ("sw zero, 1(%0)" : : "r" (&target_word));
+	tb_printf("Target value: %08x\n", target_word);
+	tb_puts("Store word, 2 byte offset\n");
+	asm volatile ("sw zero, 2(%0)" : : "r" (&target_word));
+	tb_printf("Target value: %08x\n", target_word);
+	tb_puts("Store word, 3 byte offset\n");
+	asm volatile ("sw zero, 3(%0)" : : "r" (&target_word));
+	tb_printf("Target value: %08x\n", target_word);
+	tb_puts("Aligned store word, sanity check\n");
+	asm volatile ("sw zero, 0(%0)" : : "r" (&target_word));
+	tb_printf("Target value: %08x\n", target_word);
+
+	return 0;
+}
+
+void __attribute__((interrupt)) handle_exception() {
+	tb_printf("-> exception, mcause = %u\n", read_csr(mcause));
+	write_csr(mcause, 0);
+	if (*(uint16_t*)read_csr(mepc) & 0x3 == 0x3) {
+		write_csr(mepc, read_csr(mepc) + 4);
+	}
+	else {
+		write_csr(mepc, read_csr(mepc) + 2);
+	}
+}
+
diff --git a/test/sim/sw_testcases/store_misalign_word.expected_output b/test/sim/sw_testcases/store_misalign_word.expected_output
new file mode 100644
index 0000000..7a11b68
--- /dev/null
+++ b/test/sim/sw_testcases/store_misalign_word.expected_output
@@ -0,0 +1,11 @@
+Store word, 1 byte offset
+-> exception, mcause = 6
+Target value: ffffffff
+Store word, 2 byte offset
+-> exception, mcause = 6
+Target value: ffffffff
+Store word, 3 byte offset
+-> exception, mcause = 6
+Target value: ffffffff
+Aligned store word, sanity check
+Target value: 00000000