@@ -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
@@ -42,4 +42,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_clobber
+HEX_TESTS += test_cmp
+HEX_TESTS += test_cmpy
+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_overflow
+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_vcmpy
+HEX_TESTS += test_vlsrw
+HEX_TESTS += test_vmaxh
+HEX_TESTS += test_vminh
+HEX_TESTS += test_vpmpyh
+HEX_TESTS += test_vspliceb
+
TESTS += $(HEX_TESTS)
new file mode 100644
@@ -0,0 +1,26 @@
+#define SYS_exit_group 94
+
+ .text
+ .globl init
+init:
+ {
+ allocframe(r29,#0):raw
+ }
+ {
+ r0=#256
+ }
+ {
+ dealloc_return
+ }
+
+ .globl pass
+pass:
+ r0 = #0
+ r6 = #SYS_exit_group
+ trap0(#1)
+
+ .globl fail
+fail:
+ r0 = #1
+ r6 = #SYS_exit_group
+ trap0(#1)
new file mode 100644
@@ -0,0 +1,20 @@
+/* Purpose: test example, verify the soundness of the abs operation */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ r1=#-2
+ r2=#2
+ }
+ {
+ r3=abs(r1)
+ }
+ {
+ p0 = cmp.eq(r3, r2); if (p0.new) jump:t pass
+ jump fail
+ }
new file mode 100644
@@ -0,0 +1,42 @@
+/* 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:
+ {
+ call init
+ }
+ {
+ 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
+ }
new file mode 100644
@@ -0,0 +1,25 @@
+/* Purpose: test example, verify the soundness of the bitsplit operation */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ 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
+ }
new file mode 100644
@@ -0,0 +1,60 @@
+/* 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.
+ */
+
+ .text
+ .globl test
+test:
+ {
+ jumpr r31
+ memb(r0+#0)=#76
+ }
+.Lfunc_end0:
+.Ltmp0:
+ .size test, .Ltmp0-test
+
+ .globl _start
+_start:
+ {
+ call init
+ }
+ {
+ call test
+ r0=##dummy_buffer
+ allocframe(#0)
+ }
+ {
+ call write
+ }
+ {
+ jump pass
+ }
+ {
+ r31:30=deallocframe(r30):raw
+ }
+.Lfunc_end1:
+.Ltmp1:
+ .size _start, .Ltmp1-_start
+write:
+ {
+ r0=##dummy_buffer
+ }
+ {
+ r1=#256
+ }
+ {
+ 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
new file mode 100644
@@ -0,0 +1,35 @@
+/* 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:
+ {
+ call init
+ }
+ {
+ r16=#47
+ r17=#155
+ }
+ {
+ memd(r29+#-16)=r17:16; allocframe(#8)
+ }
+ {
+ r16=#255
+ r17=#42
+ }
+ {
+ r17:16=memd(r29+#0); deallocframe
+ }
+ {
+ r3=add(r16,r17)
+ }
+ {
+ p0 = cmp.eq(r3, #202); if (p0.new) jump:t pass
+ }
+ {
+ jump fail
+ }
new file mode 100644
@@ -0,0 +1,34 @@
+/* Purpose: test a signed and unsigned comparison */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ 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
+ }
new file mode 100644
@@ -0,0 +1,31 @@
+/* Purpose: test example, verify the soundness of the cmpy operation
+ *
+ * 3j+5 * 2j+4 = 22j+14
+ *
+ * the complex multiply between 0x00030005 and 0x00020004 is 0x000000160000000e
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ r0=#196613
+ r1=#131076
+ }
+ {
+ r3:2=cmpy(r0, r1):sat
+ }
+ {
+ p0 = cmp.eq(r2, #14); if (p0.new) jump:t test2
+ jump fail
+ }
+
+test2:
+ {
+ p0 = cmp.eq(r3, #22); if (p0.new) jump:t pass
+ jump fail
+ }
new file mode 100644
@@ -0,0 +1,36 @@
+/* Purpose: test the .new operator while performing memory stores. */
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ 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)
+ }
+ {
+ p0 = cmp.eq(r3, #2); if (p0.new) jump:t pass
+ jump fail
+ }
new file mode 100644
@@ -0,0 +1,16 @@
+/* Purpose: test immediate extender instructions. */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ r2=##-559038737
+ }
+ {
+ p0 = cmp.eq(r2, ##-559038737); if (p0.new) jump:t pass
+ jump fail
+ }
new file mode 100644
@@ -0,0 +1,33 @@
+/* Purpose: computes the Fibonacci series up to a constant number. */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ 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
+ }
new file mode 100644
@@ -0,0 +1,19 @@
+/* Purpose: test example, verify the soundness of the high/low assignment */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ r0.H=#42
+ }
+ {
+ r0.L=#69
+ }
+ {
+ p0 = cmp.eq(r0, #2752581); if (p0.new) jump:t pass
+ jump fail
+ }
new file mode 100644
@@ -0,0 +1,22 @@
+/* Purpose: simple C Program to test hardware loops. */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ 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
+ }
new file mode 100644
@@ -0,0 +1,25 @@
+/* Purpose: test example, verify the soundness of the add operation */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ r1=#0
+ r2=#0
+ }
+ {
+ r3=add(r1,r2)
+ }
+ {
+ p0 = cmp.eq(r3, #0)
+ }
+ {
+ if (p0) jump:t pass
+ }
+ {
+ jump fail
+ }
new file mode 100644
@@ -0,0 +1,39 @@
+/* Purpose: test the soundness of the lsr operation */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ 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
+ }
new file mode 100644
@@ -0,0 +1,20 @@
+/* Purpose: test a simple multiplication operation */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ r1=#4
+ r2=#6
+ }
+ {
+ r3=mpyi(r1,r2)
+ }
+ {
+ p0 = cmp.eq(r3, #24); if (p0.new) jump:t pass
+ jump fail
+ }
new file mode 100644
@@ -0,0 +1,63 @@
+// Purpose: test example, verify the soundness of the overflow bit
+//
+// a right shift with negative amount should make r0 saturate, setting the
+// overflow bit
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ r0=#0x10000000
+ r1=#-2
+ }
+ {
+ r2=asr(r0, r1):sat
+ }
+ {
+ r4=USR
+ }
+ {
+ r5=and(r4,#1)
+ }
+ {
+ p0 = cmp.eq(r5, #0); if (p0.new) jump:t check_ovfl
+ jump fail
+ }
+check_ovfl:
+ {
+ r1=#-3
+ }
+ {
+ r2=asr(r0, r1):sat
+ }
+ {
+ r4=USR
+ }
+ {
+ r5=and(r4,#1)
+ }
+ {
+ p0 = cmp.eq(r5, #1); if (p0.new) jump:t check_sticky
+ jump fail
+ }
+check_sticky:
+ {
+ r1=#-2
+ }
+ {
+ r2=asr(r0, r1):sat
+ }
+ {
+ r4=USR
+ }
+ {
+ r5=and(r4,#1)
+ }
+ {
+ p0 = cmp.eq(r5, #1); if (p0.new) jump:t pass
+ jump fail
+ }
new file mode 100644
@@ -0,0 +1,26 @@
+/* Purpose: test that writes of a register in a packet are performed only after
+ * that packet has finished its execution.
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ r2=#4
+ r3=#6
+ }
+ {
+ memw(sp+#0)=r2
+ }
+ {
+ r3=memw(sp+#0)
+ r0=add(r2,r3)
+ }
+ {
+ p0 = cmp.eq(r0, #10); if (p0.new) jump:t pass
+ jump fail
+ }
new file mode 100644
@@ -0,0 +1,29 @@
+/* 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:
+ {
+ call init
+ }
+ { 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
+ }
new file mode 100644
@@ -0,0 +1,31 @@
+/* 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:
+ {
+ call init
+ }
+ {
+ 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
+ }
new file mode 100644
@@ -0,0 +1,33 @@
+/* Purpose: test example, verify the soundness of the vavgw operation
+ *
+ * 0x00030001 averaged with 0x00010003 results 0x00020002
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ 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
+ }
new file mode 100644
@@ -0,0 +1,32 @@
+/* Purpose: test example, verify the soundness of the vector compare bytes
+ * operation
+ *
+ * Vector word comparison between 0x1234567887654321 and 0x1234567800000000
+ * should result in 0x11110000
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ r0=#305419896
+ r1=#-2023406815
+ }
+ {
+ r2=#305419896
+ r3=#0
+ }
+ {
+ p2=vcmpb.eq(r1:0, r3:2)
+ }
+ {
+ r4=p2
+ }
+ {
+ p0 = cmp.eq(r4, #15); if (p0.new) jump:t pass
+ jump fail
+ }
new file mode 100644
@@ -0,0 +1,29 @@
+/* Purpose: test example, verify the soundness of the vector compare words
+ * operation
+ *
+ * Vector word comparison between 0x1234567887654321 and 0x1234567800000000
+ * should result in 0x11110000
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ r0=#305419896
+ r1=#-2023406815
+ }
+ {
+ r2=#305419896
+ r3=#0
+ }
+ {
+ p2=vcmpw.eq(r1:0, r3:2)
+ }
+ {
+ if (p2) jump:t pass
+ jump fail
+ }
new file mode 100644
@@ -0,0 +1,50 @@
+/* Purpose: test example, verify the soundness of the vcmpy operation
+ * this operation is a complex multiply and accumulate on vectors of two values
+ *
+ * (3j+5 * 2j+4) + (4j+6 * 5j+2) = 22j+14
+ *
+ * the complex multiply between 0x00030005 and 0x00020004 is 0x000000160000000e
+ * the complex multiply between 0x00040006 and 0x00050002 is 0x000000160000000e
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ r0=#196613
+ r1=#131076
+ }
+ {
+ r2=#262150
+ r3=#327682
+ }
+ {
+ r5:4=vcmpyr(r1:0, r3:2):sat
+ r7:6=vcmpyi(r1:0, r3:2):sat
+ }
+ {
+ p0 = cmp.eq(r4, #18); if (p0.new) jump:t test2
+ jump fail
+ }
+
+test2:
+ {
+ p0 = cmp.eq(r5, #-2); if (p0.new) jump:t test3
+ jump fail
+ }
+
+test3:
+ {
+ p0 = cmp.eq(r6, #38); if (p0.new) jump:t test4
+ jump fail
+ }
+
+test4:
+ {
+ p0 = cmp.eq(r7, #24); if (p0.new) jump:t pass
+ jump fail
+ }
new file mode 100644
@@ -0,0 +1,23 @@
+/* Purpose: test the soundness of the vlsrw operation */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ 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
+ }
new file mode 100644
@@ -0,0 +1,37 @@
+/* Purpose: test example, verify the soundness of the vrmaxh operation
+ *
+ * the maximum between 0x0002000300010005 and 0x0003000200020007 is
+ * 0x0003000300020007.
+ *
+ * r1=0x00010003 r0=0x00010005 r3=0x00030002 r2=0x00020007
+ * result: r1=0x00030003 r0=0x00020007
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ 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
+ }
new file mode 100644
@@ -0,0 +1,37 @@
+/* Purpose: test example, verify the soundness of the vrmaxh operation
+ *
+ * the minimum between 0x0002000300010005 and 0x0003000200020007 is
+ * 0x0003000300020007
+ *
+ * r1=0x00010003 r0=0x00010005 r3=0x00030002 r2=0x00020007
+ * result: r1=0x00010002 r0=0x00010005
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ 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
+ }
new file mode 100644
@@ -0,0 +1,30 @@
+/* Purpose: test example, verify the soundness of the vpmpyh operator
+ *
+ * 0x01020304 vector polynomial multiplied with 0x04030201 results
+ * 0x000400060b060b04
+ */
+
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ 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
+ }
new file mode 100644
@@ -0,0 +1,33 @@
+/* Purpose: test example, verify the soundness of the vspliceb operation
+ * the operation is a binary splice of two 64bit operators
+ *
+ * vspliceb(0xffffffffffffffff,0x0000000000000000,5) = 0x000000000000001f
+ */
+ .text
+ .globl _start
+
+_start:
+ {
+ call init
+ }
+ {
+ 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
+ }