diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2022-12-18 17:02:11 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2022-12-18 17:02:11 +0000 |
commit | 4f9a4cd37eb2f0c4e6be83640fcc5c31d4bf99e3 (patch) | |
tree | ac39a1ff82a36f902476f9122375de95a5b7be24 /tests | |
parent | 562d4af32ec2213061f844b3838223fd7711b56a (diff) | |
parent | 585a86b1041a45c3b4074440c7f1b54944570867 (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')
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, |