If I understand correctly, if one specifies -mfpu=neon with -funsafe-math-optimizations (as in Code:Blocks by default) then NEON code is automatically generated by GCC, and one doesn't have to fiddle around with ARM's intrinsics, right ?-mfpu=name
This specifies what floating-point hardware (or hardware emulation) is available on the target. Permissible names are: ‘vfp’, ‘vfpv3’, ‘vfpv3-fp16’, ‘vfpv3-d16’, ‘vfpv3-d16-fp16’, ‘vfpv3xd’, ‘vfpv3xd-fp16’, ‘neon’, ‘neon-fp16’, ‘vfpv4’, ‘vfpv4-d16’, ‘fpv4-sp-d16’, ‘neon-vfpv4’, ‘fpv5-d16’, ‘fpv5-sp-d16’, ‘fp-armv8’, ‘neon-fp-armv8’ and ‘crypto-neon-fp-armv8’.
If -msoft-float is specified this specifies the format of floating-point values.
If the selected floating-point hardware includes the NEON extension (e.g. -mfpu=‘neon’), note that floating-point operations are not generated by GCC's auto-vectorization pass unless -funsafe-math-optimizations is also specified. This is because NEON hardware does not fully implement the IEEE 754 standard for floating-point arithmetic (in particular denormal values are treated as zero), so the use of NEON instructions may lead to a loss of precision.
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define NEON
void *copy_gl_pointer_color_bgra(void *ptr, size_t width, size_t skip, size_t count) {
// this one only convert from BGRA (unsigned byte) to RGBA FLOAT
unsigned char* src = (unsigned char*)ptr;
int stride = 0;
if (! src || !(count-skip))
return NULL;
if (! stride)
stride = 4;
void* out = malloc(4*sizeof(float)*(count-skip));
float* dst = (float*)out;
src += skip*(stride);
static const float d = 1.0f/255.0f;
for (int i=skip; i<count; i++) {
#if defined(NEON) && defined(__ARM_NEON__)
int lsrc = *(int*)src;
lsrc = (lsrc&0xff00ff00) | ((lsrc&0x00ff0000)>>16) | ((lsrc&0x000000ff)<<16);
asm volatile (
"vmov s12, %1 \n\t" // because you cannot vmovl.u8 d6, s11
"vmovl.u8 q3, d6 \n\t" // Expand to 16-bit (so unsetuped s13 is expanded in d7)
"vmovl.u16 q3, d6 \n\t" // Expand to 32-bit, ignoring expanded d7
"vcvt.f32.u32 q3, q3 \n\t" // Convert to float
"vmul.f32 q3, q3, %y2 \n\t" // Normlize
"vst1.f32 {q3}, [%0]! \n\t" // Store, next
:"+r"(dst) :"w"(lsrc), "w"(d)
: "q3", "memory"
);
#else
const unsigned char b = src[0], g = src[1], r = src[2], a = src[3];
*dst++ = r*d;
*dst++ = g*d;
*dst++ = b*d;
*dst++ = a*d;
#endif
src+=stride;
}
return out;
}
