aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2022-12-18 17:02:11 +0000
committerPeter Maydell <peter.maydell@linaro.org>2022-12-18 17:02:11 +0000
commit4f9a4cd37eb2f0c4e6be83640fcc5c31d4bf99e3 (patch)
treeac39a1ff82a36f902476f9122375de95a5b7be24 /tests
parent562d4af32ec2213061f844b3838223fd7711b56a (diff)
parent585a86b1041a45c3b4074440c7f1b54944570867 (diff)
Merge tag 'pull-hex-20221216-1' of https://github.com/quic/qemu into staging
1) Performance improvement Add pkt and insn to DisasContext Many functions need information from all 3 structures, so merge them together. 2) Bug fix Fix predicated assignment to .tmp and .cur 3) Performance improvement Add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat These functions will not be handled by idef-parser 4-11) The final 8 patches improve change-of-flow handling. Currently, we set the PC to a new address before exiting a TB. The ultimate goal is to use direct block chaining. However, several steps are needed along the way. 4) When a packet has more than one change-of-flow (COF) instruction, only the first one taken is considered. The runtime bookkeeping is only needed when there is more than one COF instruction in a packet. 5, 6) Remove PC and next_PC from the runtime state and always use a translation-time constant. Note that next_PC is used by call instructions to set LR and by conditional COF instructions to set the fall-through address. 7, 8, 9) Add helper overrides for COF instructions. In particular, we must distinguish those that use a PC-relative address for the destination. These are candidates for direct block chaining later. 10) Use direct block chaining for packets that have a single PC-relative COF instruction. Instead of generating the code while processing the instruction, we record the effect in DisasContext and generate the code during gen_end_tb. 11) Use direct block chaining for tight loops. We look for TBs that end with an endloop0 that will branch back to the TB start address. 12-21) Instruction definition parser (idef-parser) from rev.ng Parses the instruction semantics and generates TCG # gpg: Signature made Fri 16 Dec 2022 20:41:53 GMT # gpg: using RSA key 3635C788CE62B91FD4C59AB47B0244FB12DE4422 # gpg: Good signature from "Taylor Simpson (Rock on) <tsimpson@quicinc.com>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 3635 C788 CE62 B91F D4C5 9AB4 7B02 44FB 12DE 4422 * tag 'pull-hex-20221216-1' of https://github.com/quic/qemu: (21 commits) target/hexagon: import additional tests target/hexagon: call idef-parser functions target/hexagon: import parser for idef-parser target/hexagon: import lexer for idef-parser target/hexagon: prepare input for the idef-parser target/hexagon: introduce new helper functions target/hexagon: make helper functions non-static target/hexagon: make slot number an unsigned target/hexagon: import README for idef-parser target/hexagon: update MAINTAINERS for idef-parser Hexagon (target/hexagon) Use direct block chaining for tight loops Hexagon (target/hexagon) Use direct block chaining for direct jump/branch Hexagon (target/hexagon) Add overrides for various forms of jump Hexagon (target/hexagon) Add overrides for compound compare and jump Hexagon (target/hexagon) Add overrides for direct call instructions Hexagon (target/hexagon) Remove next_PC from runtime state Hexagon (target/hexagon) Remove PC from the runtime state Hexagon (target/hexagon) Only use branch_taken when packet has multi cof Hexagon (target/hexagon) Add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat Hexagon (target/hexagon) Fix predicated assignment to .tmp and .cur ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/tcg/hexagon/Makefile.target28
-rw-r--r--tests/tcg/hexagon/crt.S14
-rw-r--r--tests/tcg/hexagon/hvx_misc.c72
-rw-r--r--tests/tcg/hexagon/test_abs.S17
-rw-r--r--tests/tcg/hexagon/test_bitcnt.S40
-rw-r--r--tests/tcg/hexagon/test_bitsplit.S22
-rw-r--r--tests/tcg/hexagon/test_call.S64
-rw-r--r--tests/tcg/hexagon/test_clobber.S29
-rw-r--r--tests/tcg/hexagon/test_cmp.S31
-rw-r--r--tests/tcg/hexagon/test_dotnew.S38
-rw-r--r--tests/tcg/hexagon/test_ext.S13
-rw-r--r--tests/tcg/hexagon/test_fibonacci.S30
-rw-r--r--tests/tcg/hexagon/test_hl.S16
-rw-r--r--tests/tcg/hexagon/test_hwloops.S19
-rw-r--r--tests/tcg/hexagon/test_jmp.S22
-rw-r--r--tests/tcg/hexagon/test_lsr.S36
-rw-r--r--tests/tcg/hexagon/test_mpyi.S17
-rw-r--r--tests/tcg/hexagon/test_packet.S29
-rw-r--r--tests/tcg/hexagon/test_reorder.S33
-rw-r--r--tests/tcg/hexagon/test_round.S29
-rw-r--r--tests/tcg/hexagon/test_vavgw.S31
-rw-r--r--tests/tcg/hexagon/test_vcmpb.S30
-rw-r--r--tests/tcg/hexagon/test_vcmpw.S30
-rw-r--r--tests/tcg/hexagon/test_vlsrw.S20
-rw-r--r--tests/tcg/hexagon/test_vmaxh.S35
-rw-r--r--tests/tcg/hexagon/test_vminh.S35
-rw-r--r--tests/tcg/hexagon/test_vpmpyh.S28
-rw-r--r--tests/tcg/hexagon/test_vspliceb.S31
-rw-r--r--tests/tcg/hexagon/usr.c34
29 files changed, 866 insertions, 7 deletions
diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target
index 96a4d7a614..9ee1faa1e1 100644
--- a/tests/tcg/hexagon/Makefile.target
+++ b/tests/tcg/hexagon/Makefile.target
@@ -24,7 +24,7 @@ CFLAGS += -fno-unroll-loops
HEX_SRC=$(SRC_PATH)/tests/tcg/hexagon
VPATH += $(HEX_SRC)
-first: $(HEX_SRC)/first.S
+%: $(HEX_SRC)/%.S $(HEX_SRC)/crt.S
$(CC) -static -mv67 -nostdlib $^ -o $@
HEX_TESTS = first
@@ -44,6 +44,32 @@ HEX_TESTS += atomics
HEX_TESTS += fpstuff
HEX_TESTS += overflow
+HEX_TESTS += test_abs
+HEX_TESTS += test_bitcnt
+HEX_TESTS += test_bitsplit
+HEX_TESTS += test_call
+HEX_TESTS += test_clobber
+HEX_TESTS += test_cmp
+HEX_TESTS += test_dotnew
+HEX_TESTS += test_ext
+HEX_TESTS += test_fibonacci
+HEX_TESTS += test_hl
+HEX_TESTS += test_hwloops
+HEX_TESTS += test_jmp
+HEX_TESTS += test_lsr
+HEX_TESTS += test_mpyi
+HEX_TESTS += test_packet
+HEX_TESTS += test_reorder
+HEX_TESTS += test_round
+HEX_TESTS += test_vavgw
+HEX_TESTS += test_vcmpb
+HEX_TESTS += test_vcmpw
+HEX_TESTS += test_vlsrw
+HEX_TESTS += test_vmaxh
+HEX_TESTS += test_vminh
+HEX_TESTS += test_vpmpyh
+HEX_TESTS += test_vspliceb
+
TESTS += $(HEX_TESTS)
# This test has to be compiled for the -mv67t target
diff --git a/tests/tcg/hexagon/crt.S b/tests/tcg/hexagon/crt.S
new file mode 100644
index 0000000000..f9e6bc80f7
--- /dev/null
+++ b/tests/tcg/hexagon/crt.S
@@ -0,0 +1,14 @@
+#define SYS_exit_group 94
+
+ .text
+ .globl pass
+pass:
+ r0 = #0
+ r6 = #SYS_exit_group
+ trap0(#1)
+
+ .globl fail
+fail:
+ r0 = #1
+ r6 = #SYS_exit_group
+ trap0(#1)
diff --git a/tests/tcg/hexagon/hvx_misc.c b/tests/tcg/hexagon/hvx_misc.c
index 6e2c9ab3cd..53d5c9b44f 100644
--- a/tests/tcg/hexagon/hvx_misc.c
+++ b/tests/tcg/hexagon/hvx_misc.c
@@ -541,6 +541,75 @@ static void test_vshuff(void)
check_output_b(__LINE__, 1);
}
+static void test_load_tmp_predicated(void)
+{
+ void *p0 = buffer0;
+ void *p1 = buffer1;
+ void *pout = output;
+ bool pred = true;
+
+ for (int i = 0; i < BUFSIZE; i++) {
+ /*
+ * Load into v12 as .tmp with a predicate
+ * When the predicate is true, we get the vector from buffer1[i]
+ * When the predicate is false, we get a vector of all 1's
+ * Regardless of the predicate, the next packet should have
+ * a vector of all 1's
+ */
+ asm("v3 = vmem(%0 + #0)\n\t"
+ "r1 = #1\n\t"
+ "v12 = vsplat(r1)\n\t"
+ "p1 = !cmp.eq(%3, #0)\n\t"
+ "{\n\t"
+ " if (p1) v12.tmp = vmem(%1 + #0)\n\t"
+ " v4.w = vadd(v12.w, v3.w)\n\t"
+ "}\n\t"
+ "v4.w = vadd(v4.w, v12.w)\n\t"
+ "vmem(%2 + #0) = v4\n\t"
+ : : "r"(p0), "r"(p1), "r"(pout), "r"(pred)
+ : "r1", "p1", "v12", "v3", "v4", "v6", "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] =
+ pred ? buffer0[i].w[j] + buffer1[i].w[j] + 1
+ : buffer0[i].w[j] + 2;
+ }
+ pred = !pred;
+ }
+
+ check_output_w(__LINE__, BUFSIZE);
+}
+
+static void test_load_cur_predicated(void)
+{
+ bool pred = true;
+ for (int i = 0; i < BUFSIZE; i++) {
+ asm volatile("p0 = !cmp.eq(%3, #0)\n\t"
+ "v3 = vmem(%0+#0)\n\t"
+ /*
+ * Preload v4 to make sure that the assignment from the
+ * packet below is not being ignored when pred is false.
+ */
+ "r0 = #0x01237654\n\t"
+ "v4 = vsplat(r0)\n\t"
+ "{\n\t"
+ " if (p0) v3.cur = vmem(%1+#0)\n\t"
+ " v4 = v3\n\t"
+ "}\n\t"
+ "vmem(%2+#0) = v4\n\t"
+ :
+ : "r"(&buffer0[i]), "r"(&buffer1[i]),
+ "r"(&output[i]), "r"(pred)
+ : "r0", "p0", "v3", "v4", "memory");
+ expect[i] = pred ? buffer1[i] : buffer0[i];
+ pred = !pred;
+ }
+ check_output_w(__LINE__, BUFSIZE);
+}
+
int main()
{
init_buffers();
@@ -578,6 +647,9 @@ int main()
test_vshuff();
+ test_load_tmp_predicated();
+ test_load_cur_predicated();
+
puts(err ? "FAIL" : "PASS");
return err ? 1 : 0;
}
diff --git a/tests/tcg/hexagon/test_abs.S b/tests/tcg/hexagon/test_abs.S
new file mode 100644
index 0000000000..d68aea6f64
--- /dev/null
+++ b/tests/tcg/hexagon/test_abs.S
@@ -0,0 +1,17 @@
+/* Purpose: test example, verify the soundness of the abs operation */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r1 = #-2
+ r2 = #2
+ }
+ {
+ r3 = abs(r1)
+ }
+ {
+ p0 = cmp.eq(r3, r2); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_bitcnt.S b/tests/tcg/hexagon/test_bitcnt.S
new file mode 100644
index 0000000000..624460488e
--- /dev/null
+++ b/tests/tcg/hexagon/test_bitcnt.S
@@ -0,0 +1,40 @@
+/*
+ * Purpose: test example, verify the soundness of the cl[01] operations.
+ *
+ * The number 0x000001aa has 23 leading zeroes
+ * they become 55 when considered as 64 bit register
+ * and it has 1 trailing zero.
+ */
+ .text
+ .globl _start
+
+_start:
+ {
+ r0 = #426
+ r1 = #0
+ }
+ {
+ r2 = cl0(r0)
+ }
+ {
+ p0 = cmp.eq(r2, #23); if (p0.new) jump:t test2
+ jump fail
+ }
+
+test2:
+ {
+ r2 = cl0(r1:0)
+ }
+ {
+ p0 = cmp.eq(r2, #55); if (p0.new) jump:t test3
+ jump fail
+ }
+
+test3:
+ {
+ r2 = ct0(r0)
+ }
+ {
+ p0 = cmp.eq(r2, #1); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_bitsplit.S b/tests/tcg/hexagon/test_bitsplit.S
new file mode 100644
index 0000000000..275658e613
--- /dev/null
+++ b/tests/tcg/hexagon/test_bitsplit.S
@@ -0,0 +1,22 @@
+/* Purpose: test example, verify the soundness of the bitsplit operation */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r1 = #187
+ }
+ {
+ r3:2 = bitsplit(r1, #3)
+ }
+ {
+ p0 = cmp.eq(r2, #3); if (p0.new) jump:t test2
+ jump fail
+ }
+
+test2:
+ {
+ p0 = cmp.eq(r3, #23); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_call.S b/tests/tcg/hexagon/test_call.S
new file mode 100644
index 0000000000..338cd04e40
--- /dev/null
+++ b/tests/tcg/hexagon/test_call.S
@@ -0,0 +1,64 @@
+/*
+ * Purpose: test function calls and duplex instructions.
+ * The string "Hello there, I'm a test string!" with the first letter replaced
+ * with a capital L should be printed out.
+ */
+
+#define SYS_write 64
+#define FD_STDOUT 1
+
+ .text
+ .globl test
+test:
+ {
+ jumpr r31
+ memb(r0+#0) = #76
+ }
+.Lfunc_end0:
+.Ltmp0:
+ .size test, .Ltmp0-test
+
+ .globl _start
+_start:
+ {
+ r0 = ##dummy_buffer
+ allocframe(#0)
+ call test
+ }
+ {
+ call write
+ }
+ {
+ deallocframe
+ jump pass
+ }
+.Lfunc_end1:
+.Ltmp1:
+ .size _start, .Ltmp1-_start
+
+write:
+ {
+ r6 = #SYS_write
+ r0 = #FD_STDOUT
+ r1 = ##dummy_buffer
+ r2 = #33
+ }
+ {
+ trap0(#1)
+ }
+ {
+ jumpr r31
+ }
+
+.Lfunc_end2:
+.Ltmp2:
+ .size write, .Ltmp2-write
+
+ .type dummy_buffer,@object
+ .data
+ .globl dummy_buffer
+ .p2align 3
+dummy_buffer:
+ .string "Hello there, I'm a test string!\n"
+ .space 223
+ .size dummy_buffer, 256
diff --git a/tests/tcg/hexagon/test_clobber.S b/tests/tcg/hexagon/test_clobber.S
new file mode 100644
index 0000000000..a7aeb2b60c
--- /dev/null
+++ b/tests/tcg/hexagon/test_clobber.S
@@ -0,0 +1,29 @@
+/*
+ * Purpose: demonstrate the succesful operation of the register save mechanism,
+ * in which the caller saves the registers that will be clobbered, and restores
+ * them after the call.
+ */
+
+ .text
+ .globl _start
+
+_start:
+ allocframe(#8)
+ {
+ r16 = #47
+ r17 = #155
+ }
+ memd(sp+#0) = r17:16
+ {
+ r16 = #255
+ r17 = #42
+ }
+ {
+ deallocframe
+ r17:16 = memd(sp+#0)
+ }
+ {
+ p0 = cmp.eq(r16, #47)
+ p0 = cmp.eq(r17, #155); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_cmp.S b/tests/tcg/hexagon/test_cmp.S
new file mode 100644
index 0000000000..1db87d3db5
--- /dev/null
+++ b/tests/tcg/hexagon/test_cmp.S
@@ -0,0 +1,31 @@
+/* Purpose: test a signed and unsigned comparison */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ jump signed
+ }
+
+ .globl signed
+signed:
+ {
+ r0 = #-2
+ r1 = #0
+ }
+ {
+ p0 = cmp.lt(r0, r1); if (p0.new) jump:t unsigned
+ jump fail
+ }
+
+ .globl unsigned
+unsigned:
+ {
+ r0 = #-2
+ r1 = #0
+ }
+ {
+ p0 = cmp.gtu(r0, r1); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_dotnew.S b/tests/tcg/hexagon/test_dotnew.S
new file mode 100644
index 0000000000..b18b6a72e2
--- /dev/null
+++ b/tests/tcg/hexagon/test_dotnew.S
@@ -0,0 +1,38 @@
+/* Purpose: test the .new operator while performing memory stores. */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ allocframe(#16)
+ }
+ {
+ r0 = #1
+ memw(sp+#0) = r0.new
+ }
+ {
+ r1 = #2
+ memw(sp+#4) = r1.new
+ }
+ {
+ r2 = #3
+ memw(sp+#8) = r2.new
+ }
+ {
+ r0 = memw(sp+#8)
+ }
+ {
+ r1 = memw(sp+#4)
+ }
+ {
+ r2 = memw(sp+#0)
+ }
+ {
+ r3 = mpyi(r1, r2)
+ }
+ {
+ deallocframe
+ p0 = cmp.eq(r3, #2); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_ext.S b/tests/tcg/hexagon/test_ext.S
new file mode 100644
index 0000000000..03e7bce2a7
--- /dev/null
+++ b/tests/tcg/hexagon/test_ext.S
@@ -0,0 +1,13 @@
+/* Purpose: test immediate extender instructions. */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r2 = ##-559038737
+ }
+ {
+ p0 = cmp.eq(r2, ##-559038737); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_fibonacci.S b/tests/tcg/hexagon/test_fibonacci.S
new file mode 100644
index 0000000000..4ef2c3896e
--- /dev/null
+++ b/tests/tcg/hexagon/test_fibonacci.S
@@ -0,0 +1,30 @@
+/* Purpose: computes the Fibonacci series up to a constant number. */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r2 = #100
+ }
+ {
+ p0 = cmp.gt(r2, #0); if (!p0.new) jump:nt .LBB0_3
+ }
+ {
+ r3 = #0
+ r4 = #1
+ }
+.LBB0_2:
+ {
+ r5 = r4
+ }
+ {
+ p0 = cmp.gt(r2, r5); if (p0.new) jump:nt .LBB0_2
+ r4 = add(r3, r4)
+ r3 = r5
+ }
+.LBB0_3:
+ {
+ p0 = cmp.eq(r3, #144); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_hl.S b/tests/tcg/hexagon/test_hl.S
new file mode 100644
index 0000000000..93ace46aeb
--- /dev/null
+++ b/tests/tcg/hexagon/test_hl.S
@@ -0,0 +1,16 @@
+/* Purpose: test example, verify the soundness of the high/low assignment */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r0.H = #42
+ }
+ {
+ r0.L = #69
+ }
+ {
+ p0 = cmp.eq(r0, #2752581); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_hwloops.S b/tests/tcg/hexagon/test_hwloops.S
new file mode 100644
index 0000000000..42785e6f25
--- /dev/null
+++ b/tests/tcg/hexagon/test_hwloops.S
@@ -0,0 +1,19 @@
+/* Purpose: simple C Program to test hardware loops. */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ loop0(.LBB0_1, #10)
+ r2 = #0
+ }
+.LBB0_1:
+ {
+ r2 = add(r2, #1)
+ nop
+ }:endloop0
+ {
+ p0 = cmp.eq(r2, #10); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_jmp.S b/tests/tcg/hexagon/test_jmp.S
new file mode 100644
index 0000000000..5be25c52b2
--- /dev/null
+++ b/tests/tcg/hexagon/test_jmp.S
@@ -0,0 +1,22 @@
+/* Purpose: test example, verify the soundness of the jump operation */
+
+#define SYS_exit_group 94
+
+ .text
+ .globl _start
+
+_start:
+ {
+ jump pass
+ }
+ /*
+ * Inlined fail label in crt.S so we can fail without
+ * having a functioning jump
+ */
+ {
+ r0 = #1
+ r6 = #SYS_exit_group
+ }
+ {
+ trap0(#1)
+ }
diff --git a/tests/tcg/hexagon/test_lsr.S b/tests/tcg/hexagon/test_lsr.S
new file mode 100644
index 0000000000..b30aa64673
--- /dev/null
+++ b/tests/tcg/hexagon/test_lsr.S
@@ -0,0 +1,36 @@
+/* Purpose: test the soundness of the lsr operation */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r0 = #-56984
+ r1 = #2147483647
+ }
+ {
+ r2 = #0x19
+ }
+ {
+ r0 &= lsr(r1, r2)
+ }
+ {
+ p0 = cmp.eq(r0, #0x28); if (p0.new) jump:t test2
+ jump fail
+ }
+
+test2:
+ {
+ r0 = #0x0000000a
+ r1 = #0x00000000
+ }
+ {
+ r2 = #-1
+ }
+ {
+ r1:0 = lsl(r1:0, r2)
+ }
+ {
+ p0 = cmp.eq(r0, #0x5); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_mpyi.S b/tests/tcg/hexagon/test_mpyi.S
new file mode 100644
index 0000000000..953b46e57e
--- /dev/null
+++ b/tests/tcg/hexagon/test_mpyi.S
@@ -0,0 +1,17 @@
+/* Purpose: test a simple multiplication operation */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r1 = #4
+ r2 = #6
+ }
+ {
+ r3 = mpyi(r1, r2)
+ }
+ {
+ p0 = cmp.eq(r3, #24); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_packet.S b/tests/tcg/hexagon/test_packet.S
new file mode 100644
index 0000000000..9ec9d8d6fb
--- /dev/null
+++ b/tests/tcg/hexagon/test_packet.S
@@ -0,0 +1,29 @@
+/*
+ * Purpose: test that writes of a register in a packet are performed only after
+ * that packet has finished its execution.
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ allocframe(#8)
+ }
+ {
+ r2 = #4
+ r3 = #6
+ }
+ {
+ memw(sp+#0) = r2
+ }
+ {
+ r3 = memw(sp+#0)
+ r0 = add(r2, r3)
+ }
+ {
+ deallocframe
+ p0 = cmp.eq(r3, #4)
+ p0 = cmp.eq(r0, #10); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_reorder.S b/tests/tcg/hexagon/test_reorder.S
new file mode 100644
index 0000000000..5ee0539836
--- /dev/null
+++ b/tests/tcg/hexagon/test_reorder.S
@@ -0,0 +1,33 @@
+/*
+ * Purpose: demonstrate handling of .new uses appearing before the associated
+ * definition.
+ * Here we perform a jump that skips the code resetting R2 from 0xDEADBEEF to 0,
+ * only if P0.new is true, but P0 is assigned to 1 (R4) in the next instruction
+ * in the packet.
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r2 = #-559038737
+ }
+ {
+ r4 = #1
+ }
+ {
+ if (p0.new) jump:nt skip
+ p0 = r4;
+ }
+
+fallthrough:
+ {
+ r2 = #0
+ }
+
+skip:
+ {
+ p0 = cmp.eq(r2, #-559038737); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_round.S b/tests/tcg/hexagon/test_round.S
new file mode 100644
index 0000000000..3c83812fe8
--- /dev/null
+++ b/tests/tcg/hexagon/test_round.S
@@ -0,0 +1,29 @@
+/*
+ * Purpose: test example, verify the soundness of the cround operation
+ * 106 = 0b1101010 with the comma at third digit is 12.5 which is crounded to 12
+ * but rounded to 13.
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r1 = #200
+ }
+ {
+ r2 = round(r1, #4)
+ }
+ {
+ p0 = cmp.eq(r2, #13); if (p0.new) jump:t test2
+ jump fail
+ }
+
+test2:
+ {
+ r2 = cround(r1, #4)
+ }
+ {
+ p0 = cmp.eq(r2, #12); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_vavgw.S b/tests/tcg/hexagon/test_vavgw.S
new file mode 100644
index 0000000000..53c9df706a
--- /dev/null
+++ b/tests/tcg/hexagon/test_vavgw.S
@@ -0,0 +1,31 @@
+/*
+ * Purpose: test example, verify the soundness of the vavgw operation.
+ *
+ * 0x00030001 averaged with 0x00010003 results 0x00020002.
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r0 = #3
+ r1 = #1
+ }
+ {
+ r2 = #1
+ r3 = #3
+ }
+ {
+ r1:0 = vavgw(r1:0, r3:2):crnd
+ }
+ {
+ p0 = cmp.eq(r0, #2); if (p0.new) jump:t test2
+ jump fail
+ }
+
+test2:
+ {
+ p0 = cmp.eq(r1, #2); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_vcmpb.S b/tests/tcg/hexagon/test_vcmpb.S
new file mode 100644
index 0000000000..66d253eb48
--- /dev/null
+++ b/tests/tcg/hexagon/test_vcmpb.S
@@ -0,0 +1,30 @@
+/*
+ * Purpose: test example, verify the soundness of the vector compare bytes
+ * operation.
+ *
+ * Vector byte comparison between 0x1234567887654321 and 0x1234567800000000
+ * should result in 0b11110000 in binary, or 0xf0 in hex.
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r0 = #0x87654321
+ r1 = #0x12345678
+ }
+ {
+ r2 = #0x00000000
+ r3 = #0x12345678
+ }
+ {
+ p2 = vcmpb.eq(r1:0, r3:2)
+ }
+ {
+ r4 = p2
+ }
+ {
+ p0 = cmp.eq(r4, #0xf0); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_vcmpw.S b/tests/tcg/hexagon/test_vcmpw.S
new file mode 100644
index 0000000000..5be88d1e2e
--- /dev/null
+++ b/tests/tcg/hexagon/test_vcmpw.S
@@ -0,0 +1,30 @@
+/*
+ * Purpose: test example, verify the soundness of the vector compare words
+ * operation.
+ *
+ * Vector word comparison between 0x1234567887654321 and 0x1234567800000000
+ * should result in 0b11110000 in binary, or 0xf0 in hex.
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r0 = #0x87654321
+ r1 = #0x12345678
+ }
+ {
+ r2 = #0x00000000
+ r3 = #0x12345678
+ }
+ {
+ p2 = vcmpw.eq(r1:0, r3:2)
+ }
+ {
+ r4 = p2
+ }
+ {
+ p0 = cmp.eq(r4, #0xf0); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_vlsrw.S b/tests/tcg/hexagon/test_vlsrw.S
new file mode 100644
index 0000000000..912e49aa0b
--- /dev/null
+++ b/tests/tcg/hexagon/test_vlsrw.S
@@ -0,0 +1,20 @@
+/* Purpose: test the soundness of the vlsrw operation */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r0 = #0x00000001
+ r1 = #0x00000001
+ }
+ {
+ r1:0 = vlsrw(r1:0, #1)
+ }
+ {
+ r0 = add(r0, r1)
+ }
+ {
+ p0 = cmp.eq(r0, #0); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_vmaxh.S b/tests/tcg/hexagon/test_vmaxh.S
new file mode 100644
index 0000000000..4ea6bd9d96
--- /dev/null
+++ b/tests/tcg/hexagon/test_vmaxh.S
@@ -0,0 +1,35 @@
+/*
+ * Purpose: test example, verify the soundness of the vrmaxh operation.
+ *
+ * The maximum between 0x0002000300010005 and 0x0003000200020007 is
+ * 0x0003000300020007.
+ *
+ * input: r1 = 0x00010003 r0 = 0x00010005 r3 = 0x00030002 r2 = 0x00020007
+ * output: r1 = 0x00030003 r0 = 0x00020007
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r0 = #65541
+ r1 = #65539
+ }
+ {
+ r2 = #131079
+ r3 = #196610
+ }
+ {
+ r1:0 = vmaxh(r1:0, r3:2)
+ }
+ {
+ p0 = cmp.eq(r0, #131079); if (p0.new) jump:t test2
+ jump fail
+ }
+
+test2:
+ {
+ p0 = cmp.eq(r1, #196611); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_vminh.S b/tests/tcg/hexagon/test_vminh.S
new file mode 100644
index 0000000000..e5fcf2eb94
--- /dev/null
+++ b/tests/tcg/hexagon/test_vminh.S
@@ -0,0 +1,35 @@
+/*
+ * Purpose: test example, verify the soundness of the vrmaxh operation.
+ *
+ * The minimum between 0x0002000300010005 and 0x0003000200020007 is
+ * 0x0003000300020007.
+ *
+ * input: r1 = 0x00010003 r0 = 0x00010005 r3 = 0x00030002 r2 = 0x00020007
+ * output: r1 = 0x00010002 r0 = 0x00010005
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r0 = #65541
+ r1 = #65539
+ }
+ {
+ r2 = #131079
+ r3 = #196610
+ }
+ {
+ r1:0 = vminh(r1:0, r3:2)
+ }
+ {
+ p0 = cmp.eq(r0, #65541); if (p0.new) jump:t test2
+ jump fail
+ }
+
+test2:
+ {
+ p0 = cmp.eq(r1, #65538); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_vpmpyh.S b/tests/tcg/hexagon/test_vpmpyh.S
new file mode 100644
index 0000000000..f02758e449
--- /dev/null
+++ b/tests/tcg/hexagon/test_vpmpyh.S
@@ -0,0 +1,28 @@
+/*
+ * Purpose: test example, verify the soundness of the vpmpyh operator.
+ *
+ * 0x01020304 vector polynomial multiplied with 0x04030201 results
+ * 0x000400060b060b04.
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ r0 = #16909060
+ r1 = #67305985
+ }
+ {
+ r1:0 = vpmpyh(r0, r1)
+ }
+ {
+ p0 = cmp.eq(r0, #184945412); if (p0.new) jump:t test2
+ jump fail
+ }
+
+test2:
+ {
+ p0 = cmp.eq(r1, #262150); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/test_vspliceb.S b/tests/tcg/hexagon/test_vspliceb.S
new file mode 100644
index 0000000000..53c4a91c51
--- /dev/null
+++ b/tests/tcg/hexagon/test_vspliceb.S
@@ -0,0 +1,31 @@
+/*
+ * Purpose: test example, verify the soundness of the vspliceb operation
+ * the operation is a binary splice of two 64bit operators.
+ *
+ * vspliceb(0xffffffffffffffff,0x0000000000000000,5) = 0x000000ffffffffff.
+ */
+ .text
+ .globl _start
+
+_start:
+ {
+ r0 = #-1
+ r1 = #-1
+ }
+ {
+ r2 = #0
+ r3 = #0
+ }
+ {
+ r5:4 = vspliceb(r1:0, r3:2, #5)
+ }
+ {
+ p0 = cmp.eq(r4, #-1); if (p0.new) jump:t test2
+ jump fail
+ }
+
+test2:
+ {
+ p0 = cmp.eq(r5, #255); if (p0.new) jump:t pass
+ jump fail
+ }
diff --git a/tests/tcg/hexagon/usr.c b/tests/tcg/hexagon/usr.c
index fb4514989c..5f68c539dd 100644
--- a/tests/tcg/hexagon/usr.c
+++ b/tests/tcg/hexagon/usr.c
@@ -429,6 +429,7 @@ FUNC_P_OP_P(vabshsat, "%0 = vabsh(%2):sat")
FUNC_P_OP_PP(vnavgwr, "%0 = vnavgw(%2, %3):rnd:sat")
FUNC_R_OP_RI(round_ri_sat, "%0 = round(%2, #%3):sat")
FUNC_R_OP_RR(asr_r_r_sat, "%0 = asr(%2, %3):sat")
+FUNC_R_OP_RR(asl_r_r_sat, "%0 = asl(%2, %3):sat")
FUNC_XPp_OP_PP(ACS, "%0, p2 = vacsh(%3, %4)")
@@ -907,12 +908,33 @@ int main()
TEST_R_OP_RI(round_ri_sat, 0x0000ffff, 2, 0x00004000, USR_CLEAR);
TEST_R_OP_RI(round_ri_sat, 0x7fffffff, 2, 0x1fffffff, USR_OVF);
- TEST_R_OP_RR(asr_r_r_sat, 0x0000ffff, 0x00000002, 0x00003fff,
- USR_CLEAR);
- TEST_R_OP_RR(asr_r_r_sat, 0x00ffffff, 0xfffffff5, 0x7fffffff,
- USR_OVF);
- TEST_R_OP_RR(asr_r_r_sat, 0x80000000, 0xfffffff5, 0x80000000,
- USR_OVF);
+ TEST_R_OP_RR(asr_r_r_sat, 0x0000ffff, 0x02, 0x00003fff, USR_CLEAR);
+ TEST_R_OP_RR(asr_r_r_sat, 0x80000000, 0x01, 0xc0000000, USR_CLEAR);
+ TEST_R_OP_RR(asr_r_r_sat, 0xffffffff, 0x01, 0xffffffff, USR_CLEAR);
+ TEST_R_OP_RR(asr_r_r_sat, 0x00ffffff, 0xf5, 0x7fffffff, USR_OVF);
+ TEST_R_OP_RR(asr_r_r_sat, 0x80000000, 0xf5, 0x80000000, USR_OVF);
+ TEST_R_OP_RR(asr_r_r_sat, 0x7fff0000, 0x42, 0x7fffffff, USR_OVF);
+ TEST_R_OP_RR(asr_r_r_sat, 0xff000000, 0x42, 0x80000000, USR_OVF);
+ TEST_R_OP_RR(asr_r_r_sat, 4096, 32, 0x00000000, USR_CLEAR);
+ TEST_R_OP_RR(asr_r_r_sat, 4096, -32, 0x7fffffff, USR_OVF);
+ TEST_R_OP_RR(asr_r_r_sat, -4096, 32, 0xffffffff, USR_CLEAR);
+ TEST_R_OP_RR(asr_r_r_sat, -4096, -32, 0x80000000, USR_OVF);
+ TEST_R_OP_RR(asr_r_r_sat, 0, -32, 0x00000000, USR_CLEAR);
+ TEST_R_OP_RR(asr_r_r_sat, 1, -32, 0x7fffffff, USR_OVF);
+
+ TEST_R_OP_RR(asl_r_r_sat, 0x00000000, 0x40, 0x00000000, USR_CLEAR);
+ TEST_R_OP_RR(asl_r_r_sat, 0x80000000, 0xff, 0xc0000000, USR_CLEAR);
+ TEST_R_OP_RR(asl_r_r_sat, 0xffffffff, 0xff, 0xffffffff, USR_CLEAR);
+ TEST_R_OP_RR(asl_r_r_sat, 0x00ffffff, 0x0b, 0x7fffffff, USR_OVF);
+ TEST_R_OP_RR(asl_r_r_sat, 0x80000000, 0x0b, 0x80000000, USR_OVF);
+ TEST_R_OP_RR(asl_r_r_sat, 0x7fff0000, 0xbe, 0x7fffffff, USR_OVF);
+ TEST_R_OP_RR(asl_r_r_sat, 0xff000000, 0xbe, 0x80000000, USR_OVF);
+ TEST_R_OP_RR(asl_r_r_sat, 4096, 32, 0x7fffffff, USR_OVF);
+ TEST_R_OP_RR(asl_r_r_sat, 4096, -32, 0x00000000, USR_CLEAR);
+ TEST_R_OP_RR(asl_r_r_sat, -4096, 32, 0x80000000, USR_OVF);
+ TEST_R_OP_RR(asl_r_r_sat, -4096, -32, 0xffffffff, USR_CLEAR);
+ TEST_R_OP_RR(asl_r_r_sat, 0, 32, 0x00000000, USR_CLEAR);
+ TEST_R_OP_RR(asl_r_r_sat, 1, 32, 0x7fffffff, USR_OVF);
TEST_XPp_OP_PP(ACS, 0x0004000300020001ULL, 0x0001000200030004ULL,
0x0000000000000000ULL, 0x0004000300030004ULL, 0xf0,