summary refs log tree commit diff stats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rwxr-xr-xtests/guest-debug/run-test.py16
-rw-r--r--tests/tcg/hexagon/Makefile.target21
-rw-r--r--tests/tcg/hexagon/fpstuff.c54
-rw-r--r--tests/tcg/hexagon/hvx_misc.c66
-rw-r--r--tests/tcg/hexagon/invalid-slots.c29
-rw-r--r--tests/tcg/hexagon/misc.c47
-rw-r--r--tests/tcg/hexagon/read_write_overlap.c136
-rw-r--r--tests/tcg/hexagon/v68_hvx.c90
-rw-r--r--tests/tcg/hexagon/v68_scalar.c186
-rw-r--r--tests/tcg/hexagon/v69_hvx.c318
-rw-r--r--tests/tcg/hexagon/v6mpy_ref.c.inc161
-rw-r--r--tests/tcg/hexagon/v73_scalar.c96
-rw-r--r--tests/tcg/multiarch/system/Makefile.softmmu-target16
13 files changed, 1186 insertions, 50 deletions
diff --git a/tests/guest-debug/run-test.py b/tests/guest-debug/run-test.py
index d865e46ecd..de6106a5e5 100755
--- a/tests/guest-debug/run-test.py
+++ b/tests/guest-debug/run-test.py
@@ -26,11 +26,12 @@ def get_args():
     parser.add_argument("--qargs", help="Qemu arguments for test")
     parser.add_argument("--binary", help="Binary to debug",
                         required=True)
-    parser.add_argument("--test", help="GDB test script",
-                        required=True)
+    parser.add_argument("--test", help="GDB test script")
     parser.add_argument("--gdb", help="The gdb binary to use",
                         default=None)
+    parser.add_argument("--gdb-args", help="Additional gdb arguments")
     parser.add_argument("--output", help="A file to redirect output to")
+    parser.add_argument("--stderr", help="A file to redirect stderr to")
 
     return parser.parse_args()
 
@@ -58,6 +59,10 @@ if __name__ == '__main__':
         output = open(args.output, "w")
     else:
         output = None
+    if args.stderr:
+        stderr = open(args.stderr, "w")
+    else:
+        stderr = None
 
     socket_dir = TemporaryDirectory("qemu-gdbstub")
     socket_name = os.path.join(socket_dir.name, "gdbstub.socket")
@@ -77,6 +82,8 @@ if __name__ == '__main__':
 
     # Now launch gdb with our test and collect the result
     gdb_cmd = "%s %s" % (args.gdb, args.binary)
+    if args.gdb_args:
+        gdb_cmd += " %s" % (args.gdb_args)
     # run quietly and ignore .gdbinit
     gdb_cmd += " -q -n -batch"
     # disable prompts in case of crash
@@ -84,13 +91,14 @@ if __name__ == '__main__':
     # connect to remote
     gdb_cmd += " -ex 'target remote %s'" % (socket_name)
     # finally the test script itself
-    gdb_cmd += " -x %s" % (args.test)
+    if args.test:
+        gdb_cmd += " -x %s" % (args.test)
 
 
     sleep(1)
     log(output, "GDB CMD: %s" % (gdb_cmd))
 
-    result = subprocess.call(gdb_cmd, shell=True, stdout=output)
+    result = subprocess.call(gdb_cmd, shell=True, stdout=output, stderr=stderr)
 
     # A result of greater than 128 indicates a fatal signal (likely a
     # crash due to gdb internal failure). That's a problem for GDB and
diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target
index 7c94db4bc4..890cceed5d 100644
--- a/tests/tcg/hexagon/Makefile.target
+++ b/tests/tcg/hexagon/Makefile.target
@@ -45,10 +45,18 @@ HEX_TESTS += fpstuff
 HEX_TESTS += overflow
 HEX_TESTS += signal_context
 HEX_TESTS += reg_mut
+HEX_TESTS += read_write_overlap
 HEX_TESTS += vector_add_int
 HEX_TESTS += scatter_gather
 HEX_TESTS += hvx_misc
 HEX_TESTS += hvx_histogram
+HEX_TESTS += invalid-slots
+
+run-and-check-exception = $(call run-test,$2,$3 2>$2.stderr; \
+	test $$? -eq 1 && grep -q "exception $(strip $1)" $2.stderr)
+
+run-invalid-slots: invalid-slots
+	$(call run-and-check-exception, 0x15, $@, $(QEMU) $(QEMU_OPTS) $<)
 
 HEX_TESTS += test_abs
 HEX_TESTS += test_bitcnt
@@ -76,17 +84,30 @@ HEX_TESTS += test_vminh
 HEX_TESTS += test_vpmpyh
 HEX_TESTS += test_vspliceb
 
+HEX_TESTS += v68_scalar
+HEX_TESTS += v68_hvx
+HEX_TESTS += v69_hvx
+HEX_TESTS += v73_scalar
+
 TESTS += $(HEX_TESTS)
 
 # This test has to be compiled for the -mv67t target
 usr: usr.c
 	$(CC) $(CFLAGS) -mv67t -O2 -Wno-inline-asm -Wno-expansion-to-defined $< -o $@ $(LDFLAGS)
 
+# Build this test with -mv71 to exercise the CABAC instruction
+misc: misc.c
+	$(CC) $(CFLAGS) -mv71 -O2 $< -o $@ $(LDFLAGS)
 scatter_gather: CFLAGS += -mhvx
 vector_add_int: CFLAGS += -mhvx -fvectorize
 hvx_misc: hvx_misc.c hvx_misc.h
 hvx_misc: CFLAGS += -mhvx
 hvx_histogram: CFLAGS += -mhvx -Wno-gnu-folding-constant
+v68_hvx: v68_hvx.c hvx_misc.h v6mpy_ref.c.inc
+v68_hvx: CFLAGS += -mhvx -Wno-unused-function
+v69_hvx: v69_hvx.c hvx_misc.h
+v69_hvx: CFLAGS += -mhvx -Wno-unused-function
+v73_scalar: CFLAGS += -Wno-unused-function
 
 hvx_histogram: hvx_histogram.c hvx_histogram_row.S
 	$(CC) $(CFLAGS) $(CROSS_CC_GUEST_CFLAGS) $^ -o $@ $(LDFLAGS)
diff --git a/tests/tcg/hexagon/fpstuff.c b/tests/tcg/hexagon/fpstuff.c
index 90ce9a6ef3..28f9397155 100644
--- a/tests/tcg/hexagon/fpstuff.c
+++ b/tests/tcg/hexagon/fpstuff.c
@@ -20,6 +20,7 @@
  */
 
 #include <stdio.h>
+#include <float.h>
 
 const int FPINVF_BIT = 1;                 /* Invalid */
 const int FPINVF = 1 << FPINVF_BIT;
@@ -706,6 +707,57 @@ static void check_float2int_convs()
     check_fpstatus(usr, FPINVF);
 }
 
+static void check_float_consts(void)
+{
+    int res32;
+    unsigned long long res64;
+
+    asm("%0 = sfmake(#%1):neg\n\t" : "=r"(res32) : "i"(0xf));
+    check32(res32, 0xbc9e0000);
+
+    asm("%0 = sfmake(#%1):pos\n\t" : "=r"(res32) : "i"(0xf));
+    check32(res32, 0x3c9e0000);
+
+    asm("%0 = dfmake(#%1):neg\n\t" : "=r"(res64) : "i"(0xf));
+    check64(res64, 0xbf93c00000000000ULL);
+
+    asm("%0 = dfmake(#%1):pos\n\t" : "=r"(res64) : "i"(0xf));
+    check64(res64, 0x3f93c00000000000ULL);
+}
+
+static inline unsigned long long dfmpyll(double x, double y)
+{
+    unsigned long long res64;
+    asm("%0 = dfmpyll(%1, %2)" : "=r"(res64) : "r"(x), "r"(y));
+    return res64;
+}
+
+static inline unsigned long long dfmpylh(double acc, double x, double y)
+{
+    unsigned long long res64 = *(unsigned long long *)&acc;
+    asm("%0 += dfmpylh(%1, %2)" : "+r"(res64) : "r"(x), "r"(y));
+    return res64;
+}
+
+static void check_dfmpyxx(void)
+{
+    unsigned long long res64;
+
+    res64 = dfmpyll(DBL_MIN, DBL_MIN);
+    check64(res64, 0ULL);
+    res64 = dfmpyll(-1.0, DBL_MIN);
+    check64(res64, 0ULL);
+    res64 = dfmpyll(DBL_MAX, DBL_MAX);
+    check64(res64, 0x1fffffffdULL);
+
+    res64 = dfmpylh(DBL_MIN, DBL_MIN, DBL_MIN);
+    check64(res64, 0x10000000000000ULL);
+    res64 = dfmpylh(-1.0, DBL_MAX, DBL_MIN);
+    check64(res64, 0xc00fffffffe00000ULL);
+    res64 = dfmpylh(DBL_MAX, 0.0, -1.0);
+    check64(res64, 0x7fefffffffffffffULL);
+}
+
 int main()
 {
     check_compare_exception();
@@ -718,6 +770,8 @@ int main()
     check_sffixupd();
     check_sffms();
     check_float2int_convs();
+    check_float_consts();
+    check_dfmpyxx();
 
     puts(err ? "FAIL" : "PASS");
     return err ? 1 : 0;
diff --git a/tests/tcg/hexagon/hvx_misc.c b/tests/tcg/hexagon/hvx_misc.c
index d0e64e035f..09dec8d7a1 100644
--- a/tests/tcg/hexagon/hvx_misc.c
+++ b/tests/tcg/hexagon/hvx_misc.c
@@ -342,49 +342,6 @@ static void test_vsubuwsat_dv(void)
     check_output_w(__LINE__, 2);
 }
 
-static void test_vshuff(void)
-{
-    /* Test that vshuff works when the two operands are the same register */
-    const uint32_t splat = 0x089be55c;
-    const uint32_t shuff = 0x454fa926;
-    MMVector v0, v1;
-
-    memset(expect, 0x12, sizeof(MMVector));
-    memset(output, 0x34, sizeof(MMVector));
-
-    asm volatile("v25 = vsplat(%0)\n\t"
-                 "vshuff(v25, v25, %1)\n\t"
-                 "vmem(%2 + #0) = v25\n\t"
-                 : /* no outputs */
-                 : "r"(splat), "r"(shuff), "r"(output)
-                 : "v25", "memory");
-
-    /*
-     * The semantics of Hexagon are the operands are pass-by-value, so create
-     * two copies of the vsplat result.
-     */
-    for (int i = 0; i < MAX_VEC_SIZE_BYTES / 4; i++) {
-        v0.uw[i] = splat;
-        v1.uw[i] = splat;
-    }
-    /* Do the vshuff operation */
-    for (int offset = 1; offset < MAX_VEC_SIZE_BYTES; offset <<= 1) {
-        if (shuff & offset) {
-            for (int k = 0; k < MAX_VEC_SIZE_BYTES; k++) {
-                if (!(k & offset)) {
-                    uint8_t tmp = v0.ub[k];
-                    v0.ub[k] = v1.ub[k + offset];
-                    v1.ub[k + offset] = tmp;
-                }
-            }
-        }
-    }
-    /* Put the result in the expect buffer for verification */
-    expect[0] = v1;
-
-    check_output_b(__LINE__, 1);
-}
-
 static void test_load_tmp_predicated(void)
 {
     void *p0 = buffer0;
@@ -454,6 +411,25 @@ static void test_load_cur_predicated(void)
     check_output_w(__LINE__, BUFSIZE);
 }
 
+static void test_vcombine(void)
+{
+    for (int i = 0; i < BUFSIZE / 2; i++) {
+        asm volatile("v2 = vsplat(%0)\n\t"
+                     "v3 = vsplat(%1)\n\t"
+                     "v3:2 = vcombine(v2, v3)\n\t"
+                     "vmem(%2+#0) = v2\n\t"
+                     "vmem(%2+#1) = v3\n\t"
+                     :
+                     : "r"(2 * i), "r"(2 * i + 1), "r"(&output[2 * i])
+                     : "v2", "v3", "memory");
+        for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
+            expect[2 * i].w[j] = 2 * i + 1;
+            expect[2 * i + 1].w[j] = 2 * i;
+        }
+    }
+    check_output_w(__LINE__, BUFSIZE);
+}
+
 int main()
 {
     init_buffers();
@@ -489,11 +465,11 @@ int main()
     test_vadduwsat();
     test_vsubuwsat_dv();
 
-    test_vshuff();
-
     test_load_tmp_predicated();
     test_load_cur_predicated();
 
+    test_vcombine();
+
     puts(err ? "FAIL" : "PASS");
     return err ? 1 : 0;
 }
diff --git a/tests/tcg/hexagon/invalid-slots.c b/tests/tcg/hexagon/invalid-slots.c
new file mode 100644
index 0000000000..366ce4f42f
--- /dev/null
+++ b/tests/tcg/hexagon/invalid-slots.c
@@ -0,0 +1,29 @@
+/*
+ *  Copyright(c) 2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+char mem[8] __attribute__((aligned(8)));
+
+int main()
+{
+    asm volatile(
+        "r0 = #mem\n"
+        /* Invalid packet (2 instructions at slot 0): */
+        ".word 0xa1804100\n" /* { memw(r0) = r1;      */
+        ".word 0x28032804\n" /*   r3 = #0; r4 = #0 }  */
+        : : : "r0", "r3", "r4", "memory");
+    return 0;
+}
diff --git a/tests/tcg/hexagon/misc.c b/tests/tcg/hexagon/misc.c
index e126751e3a..cfdda3fd09 100644
--- a/tests/tcg/hexagon/misc.c
+++ b/tests/tcg/hexagon/misc.c
@@ -18,6 +18,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#define CORE_HAS_CABAC            (__HEXAGON_ARCH__ <= 71)
+
 typedef unsigned char uint8_t;
 typedef unsigned short uint16_t;
 typedef unsigned int uint32_t;
@@ -245,6 +247,7 @@ static void check(int val, int expect)
     }
 }
 
+#if CORE_HAS_CABAC
 static void check64(long long val, long long expect)
 {
     if (val != expect) {
@@ -252,6 +255,7 @@ static void check64(long long val, long long expect)
         err++;
     }
 }
+#endif
 
 uint32_t init[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 uint32_t array[10];
@@ -286,6 +290,7 @@ static long long creg_pair(int x, int y)
     return retval;
 }
 
+#if CORE_HAS_CABAC
 static long long decbin(long long x, long long y, int *pred)
 {
     long long retval;
@@ -295,6 +300,7 @@ static long long decbin(long long x, long long y, int *pred)
          : "r"(x), "r"(y));
     return retval;
 }
+#endif
 
 /* Check that predicates are auto-and'ed in a packet */
 static int auto_and(void)
@@ -385,11 +391,46 @@ void test_count_trailing_zeros_ones(void)
     check(ct1p(0xffffff0fffffffffULL), 36);
 }
 
+static inline int dpmpyss_rnd_s0(int x, int y)
+{
+    int res;
+    asm("%0 = mpy(%1, %2):rnd\n\t" : "=r"(res) : "r"(x), "r"(y));
+    return res;
+}
+
+void test_dpmpyss_rnd_s0(void)
+{
+    check(dpmpyss_rnd_s0(-1, 0x80000000), 1);
+    check(dpmpyss_rnd_s0(0, 0x80000000), 0);
+    check(dpmpyss_rnd_s0(1, 0x80000000), 0);
+    check(dpmpyss_rnd_s0(0x7fffffff, 0x80000000), 0xc0000001);
+    check(dpmpyss_rnd_s0(0x80000000, -1), 1);
+    check(dpmpyss_rnd_s0(-1, -1), 0);
+    check(dpmpyss_rnd_s0(0, -1), 0);
+    check(dpmpyss_rnd_s0(1, -1), 0);
+    check(dpmpyss_rnd_s0(0x7fffffff, -1), 0);
+    check(dpmpyss_rnd_s0(0x80000000, 0), 0);
+    check(dpmpyss_rnd_s0(-1, 0), 0);
+    check(dpmpyss_rnd_s0(0, 0), 0);
+    check(dpmpyss_rnd_s0(1, 0), 0);
+    check(dpmpyss_rnd_s0(-1, -1), 0);
+    check(dpmpyss_rnd_s0(0, -1), 0);
+    check(dpmpyss_rnd_s0(1, -1), 0);
+    check(dpmpyss_rnd_s0(0x7fffffff, 1), 0);
+    check(dpmpyss_rnd_s0(0x80000000, 0x7fffffff), 0xc0000001);
+    check(dpmpyss_rnd_s0(-1, 0x7fffffff), 0);
+    check(dpmpyss_rnd_s0(0, 0x7fffffff),  0);
+    check(dpmpyss_rnd_s0(1, 0x7fffffff),  0);
+    check(dpmpyss_rnd_s0(0x7fffffff, 0x7fffffff), 0x3fffffff);
+}
+
 int main()
 {
     int res;
+#if CORE_HAS_CABAC
     long long res64;
     int pred;
+#endif
 
     memcpy(array, init, sizeof(array));
     S4_storerhnew_rr(array, 4, 0xffff);
@@ -505,6 +546,7 @@ int main()
     res = test_clrtnew(2, 7);
     check(res, 7);
 
+#if CORE_HAS_CABAC
     res64 = decbin(0xf0f1f2f3f4f5f6f7LL, 0x7f6f5f4f3f2f1f0fLL, &pred);
     check64(res64, 0x357980003700010cLL);
     check(pred, 0);
@@ -512,6 +554,9 @@ int main()
     res64 = decbin(0xfLL, 0x1bLL, &pred);
     check64(res64, 0x78000100LL);
     check(pred, 1);
+#else
+    puts("Skipping cabac tests");
+#endif
 
     res = auto_and();
     check(res, 0);
@@ -522,6 +567,8 @@ int main()
 
     test_count_trailing_zeros_ones();
 
+    test_dpmpyss_rnd_s0();
+
     puts(err ? "FAIL" : "PASS");
     return err;
 }
diff --git a/tests/tcg/hexagon/read_write_overlap.c b/tests/tcg/hexagon/read_write_overlap.c
new file mode 100644
index 0000000000..a75fc11dc4
--- /dev/null
+++ b/tests/tcg/hexagon/read_write_overlap.c
@@ -0,0 +1,136 @@
+/*
+ *  Copyright(c) 2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Test instructions where the semantics write to the destination
+ * before all the operand reads have been completed.
+ *
+ * These instructions are problematic when we short-circuit the
+ * register writes because the destination and source operands could
+ * be the same TCGv.
+ *
+ * We test by forcing the read and write to be register r7.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int err;
+
+static void __check(const char *filename, int line, int x, int expect)
+{
+    if (x != expect) {
+        printf("ERROR %s:%d - 0x%08x != 0x%08x\n",
+               filename, line, x, expect);
+        err++;
+    }
+}
+
+#define check(x, expect) __check(__FILE__, __LINE__, (x), (expect))
+
+#define insert(RES, X, WIDTH, OFFSET) \
+    asm("r7 = %1\n\t" \
+        "r7 = insert(r7, #" #WIDTH ", #" #OFFSET ")\n\t" \
+        "%0 = r7\n\t" \
+        : "=r"(RES) : "r"(X) : "r7")
+
+static void test_insert(void)
+{
+    uint32_t res;
+
+    insert(res, 0x12345678, 8, 1);
+    check(res, 0x123456f0);
+    insert(res, 0x12345678, 0, 1);
+    check(res, 0x12345678);
+    insert(res, 0x12345678, 20, 16);
+    check(res, 0x56785678);
+}
+
+static inline uint32_t insert_rp(uint32_t x, uint32_t width, uint32_t offset)
+{
+    uint64_t width_offset = (uint64_t)width << 32 | offset;
+    uint32_t res;
+    asm("r7 = %1\n\t"
+        "r7 = insert(r7, %2)\n\t"
+        "%0 = r7\n\t"
+        : "=r"(res) : "r"(x), "r"(width_offset) : "r7");
+    return res;
+
+}
+
+static void test_insert_rp(void)
+{
+    check(insert_rp(0x12345678,   8,  1), 0x123456f0);
+    check(insert_rp(0x12345678,  63,  8), 0x34567878);
+    check(insert_rp(0x12345678, 127,  8), 0x34567878);
+    check(insert_rp(0x12345678,   8, 24), 0x78345678);
+    check(insert_rp(0x12345678,   8, 63), 0x12345678);
+    check(insert_rp(0x12345678,   8, 64), 0x00000000);
+}
+
+static inline uint32_t asr_r_svw_trun(uint64_t x, uint32_t y)
+{
+    uint32_t res;
+    asm("r7 = %2\n\t"
+        "r7 = vasrw(%1, r7)\n\t"
+        "%0 = r7\n\t"
+        : "=r"(res) : "r"(x), "r"(y) : "r7");
+    return res;
+}
+
+static void test_asr_r_svw_trun(void)
+{
+    check(asr_r_svw_trun(0x1111111122222222ULL, 5),
+          0x88881111);
+    check(asr_r_svw_trun(0x1111111122222222ULL, 63),
+          0x00000000);
+    check(asr_r_svw_trun(0x1111111122222222ULL, 64),
+          0x00000000);
+    check(asr_r_svw_trun(0x1111111122222222ULL, 127),
+          0x22224444);
+    check(asr_r_svw_trun(0x1111111122222222ULL, 128),
+          0x11112222);
+    check(asr_r_svw_trun(0xffffffff22222222ULL, 128),
+          0xffff2222);
+}
+
+static inline uint32_t swiz(uint32_t x)
+{
+    uint32_t res;
+    asm("r7 = %1\n\t"
+        "r7 = swiz(r7)\n\t"
+        "%0 = r7\n\t"
+        : "=r"(res) : "r"(x) : "r7");
+    return res;
+}
+
+static void test_swiz(void)
+{
+    check(swiz(0x11223344), 0x44332211);
+}
+
+int main()
+{
+    test_insert();
+    test_insert_rp();
+    test_asr_r_svw_trun();
+    test_swiz();
+
+    puts(err ? "FAIL" : "PASS");
+    return err ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/tests/tcg/hexagon/v68_hvx.c b/tests/tcg/hexagon/v68_hvx.c
new file mode 100644
index 0000000000..02718722a3
--- /dev/null
+++ b/tests/tcg/hexagon/v68_hvx.c
@@ -0,0 +1,90 @@
+/*
+ *  Copyright(c) 2022-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <limits.h>
+
+int err;
+
+#include "hvx_misc.h"
+
+MMVector v6mpy_buffer0[BUFSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES)));
+MMVector v6mpy_buffer1[BUFSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES)));
+
+static void init_v6mpy_buffers(void)
+{
+    int counter0 = 0;
+    int counter1 = 17;
+    for (int i = 0; i < BUFSIZE; i++) {
+        for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
+            v6mpy_buffer0[i].w[j] = counter0++;
+            v6mpy_buffer1[i].w[j] = counter1++;
+        }
+    }
+}
+
+int v6mpy_ref[BUFSIZE][MAX_VEC_SIZE_BYTES / 4] = {
+#include "v6mpy_ref.c.inc"
+};
+
+static void test_v6mpy(void)
+{
+    void *p00 = buffer0;
+    void *p01 = v6mpy_buffer0;
+    void *p10 = buffer1;
+    void *p11 = v6mpy_buffer1;
+    void *pout = output;
+
+    memset(expect, 0xff, sizeof(expect));
+    memset(output, 0xff, sizeof(expect));
+
+    for (int i = 0; i < BUFSIZE; i++) {
+        asm("v2 = vmem(%0 + #0)\n\t"
+            "v3 = vmem(%1 + #0)\n\t"
+            "v4 = vmem(%2 + #0)\n\t"
+            "v5 = vmem(%3 + #0)\n\t"
+            "v5:4.w = v6mpy(v5:4.ub, v3:2.b, #1):v\n\t"
+            "vmem(%4 + #0) = v4\n\t"
+            : : "r"(p00), "r"(p01), "r"(p10), "r"(p11), "r"(pout)
+            : "v2", "v3", "v4", "v5", "memory");
+        p00 += sizeof(MMVector);
+        p01 += sizeof(MMVector);
+        p10 += sizeof(MMVector);
+        p11 += sizeof(MMVector);
+        pout += sizeof(MMVector);
+
+        for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
+            expect[i].w[j] = v6mpy_ref[i][j];
+        }
+    }
+
+    check_output_w(__LINE__, BUFSIZE);
+}
+
+int main()
+{
+    init_buffers();
+    init_v6mpy_buffers();
+
+    test_v6mpy();
+
+    puts(err ? "FAIL" : "PASS");
+    return err ? 1 : 0;
+}
diff --git a/tests/tcg/hexagon/v68_scalar.c b/tests/tcg/hexagon/v68_scalar.c
new file mode 100644
index 0000000000..7a8adb1130
--- /dev/null
+++ b/tests/tcg/hexagon/v68_scalar.c
@@ -0,0 +1,186 @@
+/*
+ *  Copyright(c) 2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+/*
+ *  Test the scalar core instructions that are new in v68
+ */
+
+int err;
+
+static int buffer32[] = { 1, 2, 3, 4 };
+static long long buffer64[] = { 5, 6, 7, 8 };
+
+static void __check32(int line, uint32_t result, uint32_t expect)
+{
+    if (result != expect) {
+        printf("ERROR at line %d: 0x%08x != 0x%08x\n",
+               line, result, expect);
+        err++;
+    }
+}
+
+#define check32(RES, EXP) __check32(__LINE__, RES, EXP)
+
+static void __check64(int line, uint64_t result, uint64_t expect)
+{
+    if (result != expect) {
+        printf("ERROR at line %d: 0x%016llx != 0x%016llx\n",
+               line, result, expect);
+        err++;
+    }
+}
+
+#define check64(RES, EXP) __check64(__LINE__, RES, EXP)
+
+static inline int loadw_aq(int *p)
+{
+    int res;
+    asm volatile("%0 = memw_aq(%1)\n\t"
+                 : "=r"(res) : "r"(p));
+    return res;
+}
+
+static void test_loadw_aq(void)
+{
+    int res;
+
+    res = loadw_aq(&buffer32[0]);
+    check32(res, 1);
+    res = loadw_aq(&buffer32[1]);
+    check32(res, 2);
+}
+
+static inline long long loadd_aq(long long *p)
+{
+    long long res;
+    asm volatile("%0 = memd_aq(%1)\n\t"
+                 : "=r"(res) : "r"(p));
+    return res;
+}
+
+static void test_loadd_aq(void)
+{
+    long long res;
+
+    res = loadd_aq(&buffer64[2]);
+    check64(res, 7);
+    res = loadd_aq(&buffer64[3]);
+    check64(res, 8);
+}
+
+static inline void release_at(int *p)
+{
+    asm volatile("release(%0):at\n\t"
+                 : : "r"(p));
+}
+
+static void test_release_at(void)
+{
+    release_at(&buffer32[2]);
+    check64(buffer32[2], 3);
+    release_at(&buffer32[3]);
+    check64(buffer32[3], 4);
+}
+
+static inline void release_st(int *p)
+{
+    asm volatile("release(%0):st\n\t"
+                 : : "r"(p));
+}
+
+static void test_release_st(void)
+{
+    release_st(&buffer32[2]);
+    check64(buffer32[2], 3);
+    release_st(&buffer32[3]);
+    check64(buffer32[3], 4);
+}
+
+static inline void storew_rl_at(int *p, int val)
+{
+    asm volatile("memw_rl(%0):at = %1\n\t"
+                 : : "r"(p), "r"(val) : "memory");
+}
+
+static void test_storew_rl_at(void)
+{
+    storew_rl_at(&buffer32[2], 9);
+    check64(buffer32[2], 9);
+    storew_rl_at(&buffer32[3], 10);
+    check64(buffer32[3], 10);
+}
+
+static inline void stored_rl_at(long long *p, long long val)
+{
+    asm volatile("memd_rl(%0):at = %1\n\t"
+                 : : "r"(p), "r"(val) : "memory");
+}
+
+static void test_stored_rl_at(void)
+{
+    stored_rl_at(&buffer64[2], 11);
+    check64(buffer64[2], 11);
+    stored_rl_at(&buffer64[3], 12);
+    check64(buffer64[3], 12);
+}
+
+static inline void storew_rl_st(int *p, int val)
+{
+    asm volatile("memw_rl(%0):st = %1\n\t"
+                 : : "r"(p), "r"(val) : "memory");
+}
+
+static void test_storew_rl_st(void)
+{
+    storew_rl_st(&buffer32[0], 13);
+    check64(buffer32[0], 13);
+    storew_rl_st(&buffer32[1], 14);
+    check64(buffer32[1], 14);
+}
+
+static inline void stored_rl_st(long long *p, long long val)
+{
+    asm volatile("memd_rl(%0):st = %1\n\t"
+                 : : "r"(p), "r"(val) : "memory");
+}
+
+static void test_stored_rl_st(void)
+{
+    stored_rl_st(&buffer64[0], 15);
+    check64(buffer64[0], 15);
+    stored_rl_st(&buffer64[1], 15);
+    check64(buffer64[1], 15);
+}
+
+int main()
+{
+    test_loadw_aq();
+    test_loadd_aq();
+    test_release_at();
+    test_release_st();
+    test_storew_rl_at();
+    test_stored_rl_at();
+    test_storew_rl_st();
+    test_stored_rl_st();
+
+    puts(err ? "FAIL" : "PASS");
+    return err ? 1 : 0;
+}
diff --git a/tests/tcg/hexagon/v69_hvx.c b/tests/tcg/hexagon/v69_hvx.c
new file mode 100644
index 0000000000..a0d567d142
--- /dev/null
+++ b/tests/tcg/hexagon/v69_hvx.c
@@ -0,0 +1,318 @@
+/*
+ *  Copyright(c) 2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <limits.h>
+
+int err;
+
+#include "hvx_misc.h"
+
+#define fVROUND(VAL, SHAMT) \
+    ((VAL) + (((SHAMT) > 0) ? (1LL << ((SHAMT) - 1)) : 0))
+
+#define fVSATUB(VAL) \
+    ((((VAL) & 0xffLL) == (VAL)) ? \
+        (VAL) : \
+        ((((int32_t)(VAL)) < 0) ? 0 : 0xff))
+
+#define fVSATUH(VAL) \
+    ((((VAL) & 0xffffLL) == (VAL)) ? \
+        (VAL) : \
+        ((((int32_t)(VAL)) < 0) ? 0 : 0xffff))
+
+static void test_vasrvuhubrndsat(void)
+{
+    void *p0 = buffer0;
+    void *p1 = buffer1;
+    void *pout = output;
+
+    memset(expect, 0xaa, sizeof(expect));
+    memset(output, 0xbb, sizeof(output));
+
+    for (int i = 0; i < BUFSIZE / 2; i++) {
+        asm("v4 = vmem(%0 + #0)\n\t"
+            "v5 = vmem(%0 + #1)\n\t"
+            "v6 = vmem(%1 + #0)\n\t"
+            "v5.ub = vasr(v5:4.uh, v6.ub):rnd:sat\n\t"
+            "vmem(%2) = v5\n\t"
+            : : "r"(p0), "r"(p1), "r"(pout)
+            : "v4", "v5", "v6", "memory");
+        p0 += sizeof(MMVector) * 2;
+        p1 += sizeof(MMVector);
+        pout += sizeof(MMVector);
+
+        for (int j = 0; j < MAX_VEC_SIZE_BYTES / 2; j++) {
+            int shamt;
+            uint8_t byte0;
+            uint8_t byte1;
+
+            shamt = buffer1[i].ub[2 * j + 0] & 0x7;
+            byte0 = fVSATUB(fVROUND(buffer0[2 * i + 0].uh[j], shamt) >> shamt);
+            shamt = buffer1[i].ub[2 * j + 1] & 0x7;
+            byte1 = fVSATUB(fVROUND(buffer0[2 * i + 1].uh[j], shamt) >> shamt);
+            expect[i].uh[j] = (byte1 << 8) | (byte0 & 0xff);
+        }
+    }
+
+    check_output_h(__LINE__, BUFSIZE / 2);
+}
+
+static void test_vasrvuhubsat(void)
+{
+    void *p0 = buffer0;
+    void *p1 = buffer1;
+    void *pout = output;
+
+    memset(expect, 0xaa, sizeof(expect));
+    memset(output, 0xbb, sizeof(output));
+
+    for (int i = 0; i < BUFSIZE / 2; i++) {
+        asm("v4 = vmem(%0 + #0)\n\t"
+            "v5 = vmem(%0 + #1)\n\t"
+            "v6 = vmem(%1 + #0)\n\t"
+            "v5.ub = vasr(v5:4.uh, v6.ub):sat\n\t"
+            "vmem(%2) = v5\n\t"
+            : : "r"(p0), "r"(p1), "r"(pout)
+            : "v4", "v5", "v6", "memory");
+        p0 += sizeof(MMVector) * 2;
+        p1 += sizeof(MMVector);
+        pout += sizeof(MMVector);
+
+        for (int j = 0; j < MAX_VEC_SIZE_BYTES / 2; j++) {
+            int shamt;
+            uint8_t byte0;
+            uint8_t byte1;
+
+            shamt = buffer1[i].ub[2 * j + 0] & 0x7;
+            byte0 = fVSATUB(buffer0[2 * i + 0].uh[j] >> shamt);
+            shamt = buffer1[i].ub[2 * j + 1] & 0x7;
+            byte1 = fVSATUB(buffer0[2 * i + 1].uh[j] >> shamt);
+            expect[i].uh[j] = (byte1 << 8) | (byte0 & 0xff);
+        }
+    }
+
+    check_output_h(__LINE__, BUFSIZE / 2);
+}
+
+static void test_vasrvwuhrndsat(void)
+{
+    void *p0 = buffer0;
+    void *p1 = buffer1;
+    void *pout = output;
+
+    memset(expect, 0xaa, sizeof(expect));
+    memset(output, 0xbb, sizeof(output));
+
+    for (int i = 0; i < BUFSIZE / 2; i++) {
+        asm("v4 = vmem(%0 + #0)\n\t"
+            "v5 = vmem(%0 + #1)\n\t"
+            "v6 = vmem(%1 + #0)\n\t"
+            "v5.uh = vasr(v5:4.w, v6.uh):rnd:sat\n\t"
+            "vmem(%2) = v5\n\t"
+            : : "r"(p0), "r"(p1), "r"(pout)
+            : "v4", "v5", "v6", "memory");
+        p0 += sizeof(MMVector) * 2;
+        p1 += sizeof(MMVector);
+        pout += sizeof(MMVector);
+
+        for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
+            int shamt;
+            uint16_t half0;
+            uint16_t half1;
+
+            shamt = buffer1[i].uh[2 * j + 0] & 0xf;
+            half0 = fVSATUH(fVROUND(buffer0[2 * i + 0].w[j], shamt) >> shamt);
+            shamt = buffer1[i].uh[2 * j + 1] & 0xf;
+            half1 = fVSATUH(fVROUND(buffer0[2 * i + 1].w[j], shamt) >> shamt);
+            expect[i].w[j] = (half1 << 16) | (half0 & 0xffff);
+        }
+    }
+
+    check_output_w(__LINE__, BUFSIZE / 2);
+}
+
+static void test_vasrvwuhsat(void)
+{
+    void *p0 = buffer0;
+    void *p1 = buffer1;
+    void *pout = output;
+
+    memset(expect, 0xaa, sizeof(expect));
+    memset(output, 0xbb, sizeof(output));
+
+    for (int i = 0; i < BUFSIZE / 2; i++) {
+        asm("v4 = vmem(%0 + #0)\n\t"
+            "v5 = vmem(%0 + #1)\n\t"
+            "v6 = vmem(%1 + #0)\n\t"
+            "v5.uh = vasr(v5:4.w, v6.uh):sat\n\t"
+            "vmem(%2) = v5\n\t"
+            : : "r"(p0), "r"(p1), "r"(pout)
+            : "v4", "v5", "v6", "memory");
+        p0 += sizeof(MMVector) * 2;
+        p1 += sizeof(MMVector);
+        pout += sizeof(MMVector);
+
+        for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
+            int shamt;
+            uint16_t half0;
+            uint16_t half1;
+
+            shamt = buffer1[i].uh[2 * j + 0] & 0xf;
+            half0 = fVSATUH(buffer0[2 * i + 0].w[j] >> shamt);
+            shamt = buffer1[i].uh[2 * j + 1] & 0xf;
+            half1 = fVSATUH(buffer0[2 * i + 1].w[j] >> shamt);
+            expect[i].w[j] = (half1 << 16) | (half0 & 0xffff);
+        }
+    }
+
+    check_output_w(__LINE__, BUFSIZE / 2);
+}
+
+static void test_vassign_tmp(void)
+{
+    void *p0 = buffer0;
+    void *pout = output;
+
+    memset(expect, 0xaa, sizeof(expect));
+    memset(output, 0xbb, sizeof(output));
+
+    for (int i = 0; i < BUFSIZE; i++) {
+        /*
+         * Assign into v12 as .tmp, then use it in the next packet
+         * Should get the new value within the same packet and
+         * the old value in the next packet
+         */
+        asm("v3 = vmem(%0 + #0)\n\t"
+            "r1 = #1\n\t"
+            "v12 = vsplat(r1)\n\t"
+            "r1 = #2\n\t"
+            "v13 = vsplat(r1)\n\t"
+            "{\n\t"
+            "    v12.tmp = v13\n\t"
+            "    v4.w = vadd(v12.w, v3.w)\n\t"
+            "}\n\t"
+            "v4.w = vadd(v4.w, v12.w)\n\t"
+            "vmem(%1 + #0) = v4\n\t"
+            : : "r"(p0), "r"(pout)
+            : "r1", "v3", "v4", "v12", "v13", "memory");
+        p0 += sizeof(MMVector);
+        pout += sizeof(MMVector);
+
+        for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
+            expect[i].w[j] = buffer0[i].w[j] + 3;
+        }
+    }
+
+    check_output_w(__LINE__, BUFSIZE);
+}
+
+static void test_vcombine_tmp(void)
+{
+    void *p0 = buffer0;
+    void *p1 = buffer1;
+    void *pout = output;
+
+    memset(expect, 0xaa, sizeof(expect));
+    memset(output, 0xbb, sizeof(output));
+
+    for (int i = 0; i < BUFSIZE; i++) {
+        /*
+         * Combine into v13:12 as .tmp, then use it in the next packet
+         * Should get the new value within the same packet and
+         * the old value in the next packet
+         */
+        asm("v3 = vmem(%0 + #0)\n\t"
+            "r1 = #1\n\t"
+            "v12 = vsplat(r1)\n\t"
+            "r1 = #2\n\t"
+            "v13 = vsplat(r1)\n\t"
+            "r1 = #3\n\t"
+            "v14 = vsplat(r1)\n\t"
+            "r1 = #4\n\t"
+            "v15 = vsplat(r1)\n\t"
+            "{\n\t"
+            "    v13:12.tmp = vcombine(v15, v14)\n\t"
+            "    v4.w = vadd(v12.w, v3.w)\n\t"
+            "    v16 = v13\n\t"
+            "}\n\t"
+            "v4.w = vadd(v4.w, v12.w)\n\t"
+            "v4.w = vadd(v4.w, v13.w)\n\t"
+            "v4.w = vadd(v4.w, v16.w)\n\t"
+            "vmem(%2 + #0) = v4\n\t"
+            : : "r"(p0), "r"(p1), "r"(pout)
+            : "r1", "v3", "v4", "v12", "v13", "v14", "v15", "v16", "memory");
+        p0 += sizeof(MMVector);
+        p1 += sizeof(MMVector);
+        pout += sizeof(MMVector);
+
+        for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
+            expect[i].w[j] = buffer0[i].w[j] + 10;
+        }
+    }
+
+    check_output_w(__LINE__, BUFSIZE);
+}
+
+static void test_vmpyuhvs(void)
+{
+    void *p0 = buffer0;
+    void *p1 = buffer1;
+    void *pout = output;
+
+    memset(expect, 0xaa, sizeof(expect));
+    memset(output, 0xbb, sizeof(output));
+
+    for (int i = 0; i < BUFSIZE; i++) {
+        asm("v4 = vmem(%0 + #0)\n\t"
+            "v5 = vmem(%1 + #0)\n\t"
+            "v4.uh = vmpy(V4.uh, v5.uh):>>16\n\t"
+            "vmem(%2) = v4\n\t"
+            : : "r"(p0), "r"(p1), "r"(pout)
+            : "v4", "v5", "memory");
+        p0 += sizeof(MMVector);
+        p1 += sizeof(MMVector);
+        pout += sizeof(MMVector);
+
+        for (int j = 0; j < MAX_VEC_SIZE_BYTES / 2; j++) {
+            expect[i].uh[j] = (buffer0[i].uh[j] * buffer1[i].uh[j]) >> 16;
+        }
+    }
+
+    check_output_h(__LINE__, BUFSIZE);
+}
+
+int main()
+{
+    init_buffers();
+
+    test_vasrvuhubrndsat();
+    test_vasrvuhubsat();
+    test_vasrvwuhrndsat();
+    test_vasrvwuhsat();
+
+    test_vassign_tmp();
+    test_vcombine_tmp();
+
+    test_vmpyuhvs();
+
+    puts(err ? "FAIL" : "PASS");
+    return err ? 1 : 0;
+}
diff --git a/tests/tcg/hexagon/v6mpy_ref.c.inc b/tests/tcg/hexagon/v6mpy_ref.c.inc
new file mode 100644
index 0000000000..8258cddcb1
--- /dev/null
+++ b/tests/tcg/hexagon/v6mpy_ref.c.inc
@@ -0,0 +1,161 @@
+/*
+ *  Copyright(c) 2021-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+{ 0xffffee11, 0xfffffcca, 0xffffc1b3, 0xffffd0cc,
+  0xffffe215, 0xfffff58e, 0xffffaf37, 0xffffc310,
+  0xffffd919, 0xfffff152, 0xffff9fbb, 0xffffb854,
+  0xffffd31d, 0xfffff016, 0xffff933f, 0xffffb098,
+  0xffffd021, 0xfffff1da, 0xffff89c3, 0xffffabdc,
+  0xffffd025, 0xfffff69e, 0xffff8347, 0xffffaa20,
+  0xffffd329, 0xfffffe62, 0xffff7fcb, 0xffffab64,
+  0xffffd92d, 0x00000926, 0xffff7f4f, 0xffffafa8,
+  },
+{ 0xffffe231, 0x000016ea, 0xffff81d3, 0xffffb6ec,
+  0xffffee35, 0x000027ae, 0xffff8757, 0xffffc130,
+  0xfffffd39, 0x00003b72, 0xffff8fdb, 0xffffce74,
+  0x00000f3d, 0x00005236, 0xffff9b5f, 0xffffdeb8,
+  0x00002441, 0x00006bfa, 0xffffa9e3, 0xfffff1fc,
+  0x00003c45, 0x000088be, 0xffffbb67, 0x00000840,
+  0x00005749, 0x0000a882, 0xffffcfeb, 0xffffe684,
+  0x0000494d, 0x00009a46, 0xffffb16f, 0x000002c8,
+  },
+{ 0xfffff351, 0x0000440a, 0xffff4af3, 0xffff9c0c,
+  0xffffef55, 0x000044ce, 0xffff4077, 0xffff9650,
+  0xffffee59, 0x00004892, 0xffff38fb, 0xffff9394,
+  0xfffff05d, 0x00004f56, 0xffff347f, 0xffff93d8,
+  0xfffff561, 0x0000591a, 0xffff3303, 0xffff971c,
+  0xfffffd65, 0x000065de, 0xffff3487, 0xffff9d60,
+  0x00000869, 0x000075a2, 0xffff390b, 0xffffa6a4,
+  0x0000166d, 0x00008866, 0xffff408f, 0xffffb2e8,
+  },
+{ 0x00002771, 0x00009e2a, 0xffff4b13, 0xffffc22c,
+  0x00003b75, 0x0000b6ee, 0xffff5897, 0xffffd470,
+  0x00005279, 0x0000d2b2, 0xffff691b, 0xffffe9b4,
+  0x00006c7d, 0x0000f176, 0xffff7c9f, 0x000001f8,
+  0x00008981, 0x0001133a, 0xffff9323, 0x00001d3c,
+  0x0000a985, 0x000137fe, 0xffffaca7, 0x00003b80,
+  0x0000cc89, 0x00015fc2, 0xffffc92b, 0xffffe1c4,
+  0x0000868d, 0x00011986, 0xffff72af, 0x00000608,
+  },
+{ 0xfffff891, 0x00008b4a, 0xfffed433, 0xffff674c,
+  0xfffffc95, 0x0000940e, 0xfffed1b7, 0xffff6990,
+  0x00000399, 0x00009fd2, 0xfffed23b, 0xffff6ed4,
+  0x00000d9d, 0x0000ae96, 0xfffed5bf, 0xffff7718,
+  0x00001aa1, 0x0000c05a, 0xfffedc43, 0xffff825c,
+  0x00002aa5, 0x0000d51e, 0xfffee5c7, 0xffff90a0,
+  0x00003da9, 0x0000ece2, 0xfffef24b, 0xffffa1e4,
+  0x000053ad, 0x000107a6, 0xffff01cf, 0xffffb628,
+  },
+{ 0x00006cb1, 0x0001256a, 0xffff1453, 0xffffcd6c,
+  0x000088b5, 0x0001462e, 0xffff29d7, 0xffffe7b0,
+  0x0000a7b9, 0x000169f2, 0xffff425b, 0x000004f4,
+  0x0000c9bd, 0x000190b6, 0xffff5ddf, 0x00002538,
+  0x0000eec1, 0x0001ba7a, 0xffff7c63, 0x0000487c,
+  0x000116c5, 0x0001e73e, 0xffff9de7, 0x00006ec0,
+  0x000141c9, 0x00021702, 0xffffc26b, 0xffffdd04,
+  0x0000c3cd, 0x000198c6, 0xffff33ef, 0x00000948,
+  },
+{ 0xfffffdd1, 0x0000d28a, 0xfffe5d73, 0xffff328c,
+  0x000009d5, 0x0000e34e, 0xfffe62f7, 0xffff3cd0,
+  0x000018d9, 0x0000f712, 0xfffe6b7b, 0xffff4a14,
+  0x00002add, 0x00010dd6, 0xfffe76ff, 0xffff5a58,
+  0x00003fe1, 0x0001279a, 0xfffe8583, 0xffff6d9c,
+  0x000057e5, 0x0001445e, 0xfffe9707, 0xffff83e0,
+  0x000072e9, 0x00016422, 0xfffeab8b, 0xffff9d24,
+  0x000090ed, 0x000186e6, 0xfffec30f, 0xffffb968,
+  },
+{ 0x0000b1f1, 0x0001acaa, 0xfffedd93, 0xffffd8ac,
+  0x0000d5f5, 0x0001d56e, 0xfffefb17, 0xfffffaf0,
+  0x0000fcf9, 0x00020132, 0xffff1b9b, 0x00002034,
+  0x000126fd, 0x00022ff6, 0xffff3f1f, 0x00008b36,
+  0x000093c3, 0x00009d80, 0x00009d6d, 0x0000a78a,
+  0x0000b4d7, 0x0000c354, 0x0000b801, 0x0000c6de,
+  0x0000d4eb, 0x0000e828, 0x0000d195, 0xffffea32,
+  0x00000fff, 0x000022fc, 0xfffffc29, 0x00000f86,
+  },
+{ 0xffffee13, 0xfffffcd0, 0xffffc1bd, 0xffffd0da,
+  0xffffe327, 0xfffff6a4, 0xffffb051, 0xffffc42e,
+  0xffffd73b, 0xffffef78, 0xffff9de5, 0xffffb682,
+  0xffffd24f, 0xffffef4c, 0xffff9279, 0xffffafd6,
+  0xffffd063, 0xfffff220, 0xffff8a0d, 0xffffac2a,
+  0xffffd177, 0xfffff7f4, 0xffff84a1, 0xffffab7e,
+  0xffffd18b, 0xfffffcc8, 0xffff7e35, 0xffffa9d2,
+  0xffffd89f, 0x0000089c, 0xffff7ec9, 0xffffaf26,
+  },
+{ 0xffffe2b3, 0x00001770, 0xffff825d, 0xffffb77a,
+  0xffffefc7, 0x00002944, 0xffff88f1, 0xffffc2ce,
+  0xfffffbdb, 0x00003a18, 0xffff8e85, 0xffffcd22,
+  0x00000eef, 0x000051ec, 0xffff9b19, 0xffffde76,
+  0x00002503, 0x00006cc0, 0xffffaaad, 0xfffff2ca,
+  0x00003e17, 0x00008a94, 0xffffbd41, 0x00000a1e,
+  0x0000562b, 0x0000a768, 0xffffced5, 0xffffe572,
+  0x0000493f, 0x00009a3c, 0xffffb169, 0x000002c6,
+  },
+{ 0xfffff353, 0x00004410, 0xffff4afd, 0xffff9c1a,
+  0xfffff067, 0x000045e4, 0xffff4191, 0xffff976e,
+  0xffffec7b, 0x000046b8, 0xffff3725, 0xffff91c2,
+  0xffffef8f, 0x00004e8c, 0xffff33b9, 0xffff9316,
+  0xfffff5a3, 0x00005960, 0xffff334d, 0xffff976a,
+  0xfffffeb7, 0x00006734, 0xffff35e1, 0xffff9ebe,
+  0x000006cb, 0x00007408, 0xffff3775, 0xffffa512,
+  0x000015df, 0x000087dc, 0xffff4009, 0xffffb266,
+  },
+{ 0x000027f3, 0x00009eb0, 0xffff4b9d, 0xffffc2ba,
+  0x00003d07, 0x0000b884, 0xffff5a31, 0xffffd60e,
+  0x0000511b, 0x0000d158, 0xffff67c5, 0xffffe862,
+  0x00006c2f, 0x0000f12c, 0xffff7c59, 0x000001b6,
+  0x00008a43, 0x00011400, 0xffff93ed, 0x00001e0a,
+  0x0000ab57, 0x000139d4, 0xffffae81, 0x00003d5e,
+  0x0000cb6b, 0x00015ea8, 0xffffc815, 0xffffe0b2,
+  0x0000867f, 0x0001197c, 0xffff72a9, 0x00000606,
+  },
+{ 0xfffff893, 0x00008b50, 0xfffed43d, 0xffff675a,
+  0xfffffda7, 0x00009524, 0xfffed2d1, 0xffff6aae,
+  0x000001bb, 0x00009df8, 0xfffed065, 0xffff6d02,
+  0x00000ccf, 0x0000adcc, 0xfffed4f9, 0xffff7656,
+  0x00001ae3, 0x0000c0a0, 0xfffedc8d, 0xffff82aa,
+  0x00002bf7, 0x0000d674, 0xfffee721, 0xffff91fe,
+  0x00003c0b, 0x0000eb48, 0xfffef0b5, 0xffffa052,
+  0x0000531f, 0x0001071c, 0xffff0149, 0xffffb5a6,
+  },
+{ 0x00006d33, 0x000125f0, 0xffff14dd, 0xffffcdfa,
+  0x00008a47, 0x000147c4, 0xffff2b71, 0xffffe94e,
+  0x0000a65b, 0x00016898, 0xffff4105, 0x000003a2,
+  0x0000c96f, 0x0001906c, 0xffff5d99, 0x000024f6,
+  0x0000ef83, 0x0001bb40, 0xffff7d2d, 0x0000494a,
+  0x00011897, 0x0001e914, 0xffff9fc1, 0x0000709e,
+  0x000140ab, 0x000215e8, 0xffffc155, 0xffffdbf2,
+  0x0000c3bf, 0x000198bc, 0xffff33e9, 0x00000946,
+  },
+{ 0xfffffdd3, 0x0000d290, 0xfffe5d7d, 0xffff329a,
+  0x00000ae7, 0x0000e464, 0xfffe6411, 0xffff3dee,
+  0x000016fb, 0x0000f538, 0xfffe69a5, 0xffff4842,
+  0x00002a0f, 0x00010d0c, 0xfffe7639, 0xffff5996,
+  0x00004023, 0x000127e0, 0xfffe85cd, 0xffff6dea,
+  0x00005937, 0x000145b4, 0xfffe9861, 0xffff853e,
+  0x0000714b, 0x00016288, 0xfffea9f5, 0xffff9b92,
+  0x0000905f, 0x0001865c, 0xfffec289, 0xffffb8e6,
+  },
+{ 0x0000b273, 0x0001ad30, 0xfffede1d, 0xffffd93a,
+  0x0000d787, 0x0001d704, 0xfffefcb1, 0xfffffc8e,
+  0x0000fb9b, 0x0001ffd8, 0xffff1a45, 0x00001ee2,
+  0x000126af, 0x00022fac, 0xffff3ed9, 0x00008af4,
+  0x00009485, 0x00009e46, 0x00009e37, 0x0000a858,
+  0x0000b6a9, 0x0000c52a, 0x0000b9db, 0x0000c8bc,
+  0x0000d3cd, 0x0000e70e, 0x0000d07f, 0xffffe920,
+  0x00000ff1, 0x000022f2, 0xfffffc23, 0x00000f84,
+  },
diff --git a/tests/tcg/hexagon/v73_scalar.c b/tests/tcg/hexagon/v73_scalar.c
new file mode 100644
index 0000000000..fee67fc531
--- /dev/null
+++ b/tests/tcg/hexagon/v73_scalar.c
@@ -0,0 +1,96 @@
+/*
+ *  Copyright(c) 2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+/*
+ *  Test the scalar core instructions that are new in v73
+ */
+
+int err;
+
+static void __check32(int line, uint32_t result, uint32_t expect)
+{
+    if (result != expect) {
+        printf("ERROR at line %d: 0x%08x != 0x%08x\n",
+               line, result, expect);
+        err++;
+    }
+}
+
+#define check32(RES, EXP) __check32(__LINE__, RES, EXP)
+
+static void __check64(int line, uint64_t result, uint64_t expect)
+{
+    if (result != expect) {
+        printf("ERROR at line %d: 0x%016llx != 0x%016llx\n",
+               line, result, expect);
+        err++;
+    }
+}
+
+#define check64(RES, EXP) __check64(__LINE__, RES, EXP)
+
+static bool my_func_called;
+
+static void my_func(void)
+{
+    my_func_called = true;
+}
+
+static inline void callrh(void *func)
+{
+    asm volatile("callrh %0\n\t"
+                 : : "r"(func)
+                 /* Mark the caller-save registers as clobbered */
+                 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
+                   "r10", "r11", "r12", "r13", "r14", "r15", "r28",
+                   "p0", "p1", "p2", "p3");
+}
+
+static void test_callrh(void)
+{
+    my_func_called = false;
+    callrh(&my_func);
+    check32(my_func_called, true);
+}
+
+static void test_jumprh(void)
+{
+    uint32_t res;
+    asm ("%0 = #5\n\t"
+         "r0 = ##1f\n\t"
+         "jumprh r0\n\t"
+         "%0 = #3\n\t"
+         "jump 2f\n\t"
+         "1:\n\t"
+         "%0 = #1\n\t"
+         "2:\n\t"
+         : "=r"(res) : : "r0");
+    check32(res, 1);
+}
+
+int main()
+{
+    test_callrh();
+    test_jumprh();
+
+    puts(err ? "FAIL" : "PASS");
+    return err ? 1 : 0;
+}
diff --git a/tests/tcg/multiarch/system/Makefile.softmmu-target b/tests/tcg/multiarch/system/Makefile.softmmu-target
index 5f432c95f3..fe40195d39 100644
--- a/tests/tcg/multiarch/system/Makefile.softmmu-target
+++ b/tests/tcg/multiarch/system/Makefile.softmmu-target
@@ -27,6 +27,20 @@ run-gdbstub-memory: memory
 		"-monitor none -display none -chardev file$(COMMA)path=$<.out$(COMMA)id=output $(QEMU_OPTS)" \
 		--bin $< --test $(MULTIARCH_SRC)/gdbstub/memory.py, \
 	softmmu gdbstub support)
+
+run-gdbstub-untimely-packet: hello
+	$(call run-test, $@, $(GDB_SCRIPT) \
+		--gdb $(HAVE_GDB_BIN) \
+		--gdb-args "-ex 'set debug remote 1'" \
+		--output untimely-packet.gdb.out \
+		--stderr untimely-packet.gdb.err \
+		--qemu $(QEMU) \
+		--bin $< --qargs \
+		"-monitor none -display none -chardev file$(COMMA)path=untimely-packet.out$(COMMA)id=output $(QEMU_OPTS)", \
+	"softmmu gdbstub untimely packets")
+	$(call quiet-command, \
+		(! grep -Fq 'Packet instead of Ack, ignoring it' untimely-packet.gdb.err), \
+		"GREP", "file  untimely-packet.gdb.err")
 else
 run-gdbstub-%:
 	$(call skip-test, "gdbstub test $*", "no guest arch support")
@@ -36,4 +50,4 @@ run-gdbstub-%:
 	$(call skip-test, "gdbstub test $*", "need working gdb")
 endif
 
-MULTIARCH_RUNS += run-gdbstub-memory
+MULTIARCH_RUNS += run-gdbstub-memory run-gdbstub-untimely-packet