Created
September 12, 2026 08:36
-
-
Save clausecker/723ed29d7af4d6a79da1b9ced28e2350 to your computer and use it in GitHub Desktop.
Validate SHRN/FCMP check for all-zero boolean bitmap works in the presence of FZ/FIZ/AH
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* for FreeBSD, some patching required to run on Linux */ | |
| #include <arm_neon.h> | |
| #include <machine/armreg.h> | |
| #include <stdbool.h> | |
| #include <stdint.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| static void | |
| usage(char *argv0) | |
| { | |
| fprintf(stderr, "usage: %s [-afi]\n -a for AH mode\n -f for FZ mode\n -i for FIZ mode\n", argv0); | |
| exit(EXIT_FAILURE); | |
| } | |
| static int | |
| veq_zero(uint8x16_t v) | |
| { | |
| #ifdef __arm__ | |
| union { uint8x8_t v; double d; } narrowed; | |
| /* narrow each byte to a nibble */ | |
| narrowed.v = vshrnnarrowed.v = vshrn_n_u16(vreinterpretq_u16_u8(v), 4); | |
| return (narrowed.d == 0.0); | |
| #else /* AArch64 */ | |
| uint8x8_t narrowed; | |
| /* narrow each byte to a nibble */ | |
| narrowed = vshrn_n_u16(vreinterpretq_u16_u8(v), 4); | |
| /* check if that vector is all zero */ | |
| return (vdupd_lane_f64(vreinterpret_f64_u16(narrowed), 0) == 0.0); | |
| #endif | |
| } | |
| /* check if veq_zero works correctly for all possible combinations of input */ | |
| static void | |
| run_test(void) | |
| { | |
| size_t i, j; | |
| int out; | |
| unsigned char v[16]; | |
| for (i = 0; i <= 0xffff; i++) { | |
| for (j = 0; j < 16; j++) | |
| v[j] = i & 1 << j ? 0xff : 0x00; | |
| out = veq_zero(vld1q_u8(v)); | |
| if (veq_zero(vld1q_u8(v)) != (i == 0)) | |
| printf("%04zx: wanted %d got %d\n", i, i == 0, out); | |
| } | |
| } | |
| int main(int argc, char *argv[]) | |
| { | |
| uint64_t fpcr; | |
| int ch; | |
| bool ah = false, fz = false, fiz = false; | |
| while (ch = getopt(argc, argv, "afi"), ch != -1) | |
| switch (ch) { | |
| case 'a': | |
| ah = true; | |
| break; | |
| case 'f': | |
| fz = true; | |
| break; | |
| case 'i': | |
| fiz = true; | |
| break; | |
| default: | |
| usage(argv[0]); | |
| } | |
| fpcr = READ_SPECIALREG(FPCR); | |
| fpcr &= ~0x01000003ULL; | |
| if (fiz) | |
| fpcr |= 1; | |
| if (ah) | |
| fpcr |= 2; | |
| if (fz) | |
| fpcr |= 0x01000000; | |
| WRITE_SPECIALREG(FPCR, fpcr); | |
| run_test(); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment