From ac189e7bf8865d61b4f5e89a530476f9e4c5c70b Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Sat, 25 Feb 2017 20:04:09 -0800 Subject: [PATCH] Add missing cnt (popcount) instruction support. sim/aarch64/ * simulator.c (popcount): New. (do_vec_CNT): New. (do_vec_op1): Add do_vec_CNT call. sim/testsuite/sim/aarch64/ * cnt.s: New. --- sim/aarch64/ChangeLog | 6 ++++ sim/aarch64/simulator.c | 51 +++++++++++++++++++++++++++++ sim/testsuite/sim/aarch64/ChangeLog | 4 +++ sim/testsuite/sim/aarch64/cnt.s | 33 +++++++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 sim/testsuite/sim/aarch64/cnt.s diff --git a/sim/aarch64/ChangeLog b/sim/aarch64/ChangeLog index dbe68ecb589..243ec0eff09 100644 --- a/sim/aarch64/ChangeLog +++ b/sim/aarch64/ChangeLog @@ -1,3 +1,9 @@ +2017-02-25 Jim Wilson + + * simulator.c (popcount): New. + (do_vec_CNT): New. + (do_vec_op1): Add do_vec_CNT call. + 2017-02-19 Jim Wilson * simulator.c (do_vec_ADDV): Mov val declaration inside each case, diff --git a/sim/aarch64/simulator.c b/sim/aarch64/simulator.c index d31cb106cdc..f4301595710 100644 --- a/sim/aarch64/simulator.c +++ b/sim/aarch64/simulator.c @@ -4197,6 +4197,56 @@ do_vec_XTN (sim_cpu *cpu) } } +/* Return the number of bits set in the input value. */ +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# define popcount __builtin_popcount +#else +static int +popcount (unsigned char x) +{ + static const unsigned char popcnt[16] = + { + 0, 1, 1, 2, + 1, 2, 2, 3, + 1, 2, 2, 3, + 2, 3, 3, 4 + }; + + /* Only counts the low 8 bits of the input as that is all we need. */ + return popcnt[x % 16] + popcnt[x / 16]; +} +#endif + +static void +do_vec_CNT (sim_cpu *cpu) +{ + /* instr[31] = 0 + instr[30] = half (0)/ full (1) + instr[29,24] = 00 1110 + instr[23,22] = size: byte(00) + instr[21,10] = 1000 0001 0110 + instr[9,5] = Vs + instr[4,0] = Vd. */ + + unsigned vs = INSTR (9, 5); + unsigned vd = INSTR (4, 0); + int full = INSTR (30, 30); + int size = INSTR (23, 22); + int i; + + NYI_assert (29, 24, 0x0E); + NYI_assert (21, 10, 0x816); + + if (size != 0) + HALT_UNALLOC; + + TRACE_DECODE (cpu, "emulated at line %d", __LINE__); + + for (i = 0; i < (full ? 16 : 8); i++) + aarch64_set_vec_u8 (cpu, vd, i, + popcount (aarch64_get_vec_u8 (cpu, vs, i))); +} + static void do_vec_maxv (sim_cpu *cpu) { @@ -5605,6 +5655,7 @@ do_vec_op1 (sim_cpu *cpu) case 0x08: do_vec_sub_long (cpu); return; case 0x0a: do_vec_XTN (cpu); return; case 0x11: do_vec_SSHL (cpu); return; + case 0x16: do_vec_CNT (cpu); return; case 0x19: do_vec_max (cpu); return; case 0x1B: do_vec_min (cpu); return; case 0x21: do_vec_add (cpu); return; diff --git a/sim/testsuite/sim/aarch64/ChangeLog b/sim/testsuite/sim/aarch64/ChangeLog index f737e9d239c..fcd5873fcaa 100644 --- a/sim/testsuite/sim/aarch64/ChangeLog +++ b/sim/testsuite/sim/aarch64/ChangeLog @@ -1,3 +1,7 @@ +2017-02-25 Jim Wilson + + * cnt.s: New. + 2017-02-19 Jim Wilson * bit.s: Change cmp immediates to account for addv bug fix. diff --git a/sim/testsuite/sim/aarch64/cnt.s b/sim/testsuite/sim/aarch64/cnt.s new file mode 100644 index 00000000000..b4be2e3b624 --- /dev/null +++ b/sim/testsuite/sim/aarch64/cnt.s @@ -0,0 +1,33 @@ +# mach: aarch64 + +# Check the popcount instruction: cnt. + +.include "testutils.inc" + + .data + .align 4 +input: + .word 0x04030201 + .word 0x0f070605 + .word 0x44332211 + .word 0xff776655 + + start + adrp x0, input + ldr q0, [x0, #:lo12:input] + + cnt v1.8b, v0.8b + addv b2, v1.8b + mov x1, v2.d[0] + cmp x1, #16 + bne .Lfailure + + cnt v1.16b, v0.16b + addv b2, v1.16b + mov x1, v2.d[0] + cmp x1, #48 + bne .Lfailure + + pass +.Lfailure: + fail -- 2.30.2