resources: Added the SPARC insttest.

The SPARC tests were re-added in this commit:
https://gem5-review.googlesource.com/c/public/gem5/+/33138

Change-Id: Idd2eeda678cab8abcac3eed4974d152efc22a5ad
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5-resources/+/33396
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu>
Tested-by: Bobby R. Bruce <bbruce@ucdavis.edu>
diff --git a/README.md b/README.md
index 3d9bae1..b2070d3 100755
--- a/README.md
+++ b/README.md
@@ -448,6 +448,36 @@
 
 The instructions to build the boot-tests disk image (`boot-exit`), the Linux binaries, and how to use gem5 run scripts to run boot-tests are available in this [README](src/boot-tests/README.md) file.
 
+# Resource: Insttest
+
+The Insttests test SPARC instructions.
+
+Creating the SPARC Insttest binary requires a SPARC cross compile. Instructions
+on creating a cross compiler can be found [here](
+https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler).
+
+## Compilation
+
+To compile:
+
+```
+cd src/insttest
+make
+```
+
+We provide a docker image with a pre-loaded SPARC cross compiler. To use:
+
+```
+cd src/insttest
+docker run --volume $(pwd):$(pwd) -w $(pwd) --rm gcr.io/gem5-test/sparc64-gnu-cross:latest make
+```
+
+The compiled binary can be found in `src/insttest/bin`.
+
+## Prebuild Binary
+
+<http://dist.gem5.org/dist/v20/test-progs/insttest/bin/sparc/linux/insttest>
+
 # Licensing
 
 Each project under the `src` is under a different license. Before using
@@ -475,4 +505,5 @@
 `src/npb`. The NAS Parallel Benchmarks utilize a permissive BSD-style license.
 * **boot-tests**: Consult individual copyright notices of source files in
 `src/boot-tests`.
-
+* **insttest**: Consult individual copyright notices of source files in
+`src/insttest`.
diff --git a/src/insttest/.gitignore b/src/insttest/.gitignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/src/insttest/.gitignore
@@ -0,0 +1 @@
+bin
diff --git a/src/insttest/Makefile b/src/insttest/Makefile
new file mode 100644
index 0000000..786f7aa
--- /dev/null
+++ b/src/insttest/Makefile
@@ -0,0 +1,44 @@
+# Copyright (c) 2020 The Regents of the University of California
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+CC := sparc64-linux-gcc
+CCFLAGS = -O3 -static
+
+BIN_DIR = ./bin
+
+TESTS = insttest
+
+all: $(addprefix $(BIN_DIR)/,$(TESTS))
+
+$(BIN_DIR)/%: %.c
+	@mkdir -p $(BIN_DIR)
+	$(CC) -o $@ $(CCFLAGS) $^
+
+clean:
+	$(RM) -r $(BIN_DIR)
+
+.PHONY: all clean
+
diff --git a/src/insttest/insttest.c b/src/insttest/insttest.c
new file mode 100644
index 0000000..eef1c1c
--- /dev/null
+++ b/src/insttest/insttest.c
@@ -0,0 +1,205 @@
+#include <stdio.h>
+#include <stdint.h>
+
+void check(int pass) { printf(pass ? "Passed\n" : "Failed\n"); }
+
+void
+ldstubTest()
+{
+    printf("LDSTUB:\t\t");
+
+    uint8_t volatile mem = 0x11;
+    uint8_t rd = 0;
+    uint8_t mem_o = mem, rd_o = rd;
+
+    // Load one byte of memory into rd, zero extended, and set that byte in
+    // memory to all ones.
+    asm volatile ("ldstub [%[address]], %[rd]"
+            : [rd] "=r" (rd)
+            : [address] "r" (&mem));
+
+    check(mem == 0xff && rd == mem_o);
+}
+
+void
+swapTest()
+{
+    printf("SWAP:\t\t");
+
+    uint32_t volatile mem = 0x01234567;
+    uint32_t rd = 0x89ABCDEF;
+    uint32_t mem_o = mem, rd_o = rd;
+
+    // Swap the lower 32 bits of rd with a word of memory. Zero the upper
+    // 32 bits of rd.
+    asm volatile ("swap [%[address]], %[rd]"
+            : [rd] "+r" (rd)
+            : [address] "r" (&mem));
+
+    check(mem == rd_o && rd == mem_o);
+}
+
+void
+casFailTest()
+{
+    printf("CAS FAIL:\t");
+
+    uint32_t rd = 0x00112233;
+    uint32_t volatile mem = 0xffeeddcc;
+    uint32_t rs2 = 0;
+    uint32_t rd_o = rd, mem_o = mem, rs2_o = rs2;
+
+    // Compare the lower 32 bits of rs2 with a word of memory. Since they are
+    // different, leave memory unchanged and put the contents of memory in
+    // rd, zero extended.
+    asm volatile ("cas [%[address]], %[rs2], %[rd]"
+            : [rd] "+r" (rd)
+            : [address] "r" (&mem), [rs2] "r" (rs2));
+
+    check(mem == mem_o && rd == mem_o);
+}
+
+void
+casWorkTest()
+{
+    printf("CAS WORK:\t");
+
+    uint32_t rd = 0x00112233;
+    uint32_t volatile mem = 0xffeeddcc;
+    uint32_t rs2 = 0xffeeddcc;
+    uint32_t rd_o = rd, mem_o = mem, rs2_o = rs2;
+
+    // Compare the lower 32 bits of rs2 with a word of memory. Since they are
+    // equal, swap the value in lower 32 bits of rd with that word of memory.
+    // Zero the upper 32 bits of rd.
+    asm volatile ("cas [%[address]], %[rs2], %[rd]"
+            : [rd] "+r" (rd)
+            : [address] "r" (&mem), [rs2] "r" (rs2));
+
+    check(mem == rd_o && rd == mem_o);
+}
+
+void
+casxFailTest()
+{
+    printf("CASX FAIL:\t");
+
+    uint64_t rd = 0x0011223344556677;
+    uint64_t volatile mem = 0xffeeddccbbaa9988;
+    uint64_t rs2 = 0;
+    uint64_t rd_o = rd, mem_o = mem, rs2_o = rs2;
+
+    // Compare rs2 with a doubleword of memory. Since they are different, leave
+    // memory unchanged and put the contets of memory in rd.
+    asm volatile ("casx [%[address]], %[rs2], %[rd]"
+            : [rd] "+r" (rd)
+            : [address] "r" (&mem), [rs2] "r" (rs2));
+
+    check(mem == mem_o && rd == mem_o);
+}
+
+void
+casxWorkTest()
+{
+    printf("CASX WORK:\t");
+
+    uint64_t rd = 0x0011223344556677;
+    uint64_t volatile mem = 0xffeeddccbbaa9988;
+    uint64_t rs2 = 0xffeeddccbbaa9988;
+    uint64_t rd_o = rd, mem_o = mem, rs2_o = rs2;
+
+    // Compare rs2 with a doubleword of memory. Since they are equal, swap rd
+    // with that doubleword of memory.
+    asm volatile ("casx [%[address]], %[rs2], %[rd]"
+            : [rd] "+r" (rd)
+            : [address] "r" (&mem), [rs2] "r" (rs2));
+
+    check(mem == rd_o && rd == mem_o);
+}
+
+void
+ldtxTest()
+{
+    printf("LDTX:\t\t");
+
+    uint64_t volatile mem[2] __attribute__((aligned(16))) = {
+        0xffeeddccbbaa9988, 0x0011223344556677 };
+    uint64_t rd1 = 0, rd2 = 0;
+    uint64_t mem_o[2] = { mem[0], mem[1] };
+
+    // LDDA will normally load a doubleword of memory into a register pair,
+    // but when told to use ASI e2 (ASI_TWINX_PRIMARY) it will load two
+    // doublewords which it will put into the register pair.
+    asm volatile (
+            "ldda [%[address]]0xe2, %%g2\n"
+            "mov %%g2, %[rd1]\n"
+            "mov %%g3, %[rd2]\n"
+            : [rd1] "=r" (rd1), [rd2] "=r" (rd2)
+            : [address] "r" (&mem[0])
+            : "%g2", "%g3");
+
+    check(rd1 == mem_o[0] && rd2 == mem_o[1]);
+}
+
+void
+ldtwTest()
+{
+    printf("LDTW:\t\t");
+
+    uint32_t volatile mem[2] __attribute__((aligned(8))) = {
+        0x89abcdef, 0x01234567 };
+    uint32_t rd1 = 0, rd2 = 0;
+    uint64_t mem_o[2] = { mem[0], mem[1] };
+
+    // Load two adjacent words from memory into the lower 32 bits of a pair
+    // of registers, and zero their upper 32 bits.
+    asm volatile (
+            "ldd [%[address]], %%g2\n"
+            "mov %%g2, %[rd1]\n"
+            "mov %%g3, %[rd2]\n"
+            : [rd1] "=r" (rd1), [rd2] "=r" (rd2)
+            : [address] "r" (&mem[0])
+            : "%g2", "%g3");
+    check(rd1 == mem_o[0] && rd2 == mem_o[1]);
+}
+
+void
+sttwTest()
+{
+    printf("STTW:\t\t");
+
+    uint32_t volatile mem[2] __attribute__((aligned(8))) = { 0, 0 };
+    uint64_t rd1 = 0x89abcdef, rd2 = 0x1234567;
+    uint64_t rd1_o = rd1, rd2_o = rd2;
+
+    // Store the lower 32 bits of a pair of registers into a single doubleword
+    // of memory.
+    asm volatile (
+            "mov %[rd1], %%g2\n"
+            "mov %[rd2], %%g3\n"
+            "std %%g2, [%[address]]"
+            :
+            : [rd1] "r" (rd1), [rd2] "r" (rd2), [address] "r" (&mem[0])
+            : "%g2", "%g3");
+
+    check(mem[0] == rd1_o && mem[1] == rd2_o);
+}
+
+int
+main()
+{
+    printf("Begining test of difficult SPARC instructions...\n");
+
+    ldstubTest();
+    swapTest();
+    casFailTest();
+    casWorkTest();
+    casxFailTest();
+    casxWorkTest();
+    ldtxTest();
+    ldtwTest();
+    sttwTest();
+
+    printf("Done\n");
+    return 0;
+}