#include #include typedef unsigned long long int ULong; typedef unsigned int UInt; __attribute__((noinline)) float s32_to_f32_imm1(int x) { float y; __asm__ ("vcvt.f32.s32 %0, %1, #1" : "=w"(y) : "0"(x)); return y; } __attribute__((noinline)) float s32_to_f32_imm32(int x) { float y; __asm__ ("vcvt.f32.s32 %0, %1, #32" : "=w"(y) : "0"(x)); return y; } void try_s32_to_f32 ( int x ) { float f32 = s32_to_f32_imm32(x); printf("s32_to_f32_imm32: %11d -> %18.14e\n", x, (double)f32); f32 = s32_to_f32_imm1(x); printf("s32_to_f32_imm1: %11d -> %18.14e\n", x, (double)f32); } __attribute__((noinline)) float u32_to_f32_imm1(int x) { float y; __asm__ ("vcvt.f32.u32 %0, %1, #1" : "=w"(y) : "0"(x)); return y; } __attribute__((noinline)) float u32_to_f32_imm32(int x) { float y; __asm__ ("vcvt.f32.u32 %0, %1, #32" : "=w"(y) : "0"(x)); return y; } void try_u32_to_f32 ( unsigned int x ) { float f32 = u32_to_f32_imm32(x); printf("u32_to_f32_imm32: %11u -> %18.14e\n", x, (double)f32); f32 = u32_to_f32_imm1(x); printf("u32_to_f32_imm1: %11u -> %18.14e\n", x, (double)f32); } __attribute__((noinline)) double s32_to_f64_imm1(int x) { double block[2]; memset(block, 0x55, sizeof(block)); __asm__ __volatile__( "mov r8, %1" "\n\t" "vldr d14, [%0, #8]" "\n\t" // d14 <- junk "vmov s1, r8" "\n\t" "vcvt.f64.s32 d14,d14,#1" "\n\t" "vstr d14, [%0]" "\n\t" : : /*IN*/"r"(&block[0]), "r"(x) : /*TRASH*/"r8","s28","d14","memory" ); return block[0]; } __attribute__((noinline)) double s32_to_f64_imm32(int x) { double block[2]; memset(block, 0x55, sizeof(block)); __asm__ __volatile__( "mov r8, %1" "\n\t" "vldr d14, [%0, #8]" "\n\t" // d14 <- junk "vmov s28, r8" "\n\t" "vcvt.f64.s32 d14,d14,#32" "\n\t" "vstr d14, [%0]" "\n\t" : : /*IN*/"r"(&block[0]), "r"(x) : /*TRASH*/"r8","s28","d14","memory" ); return block[0]; } void try_s32_to_f64 ( int x ) { double f64 = s32_to_f64_imm32(x); printf("s32_to_f64_imm32: %11d -> %18.14e\n", x, f64); f64 = s32_to_f64_imm1(x); printf("s32_to_f64_imm1: %11d -> %18.14e\n", x, f64); } __attribute__((noinline)) double u32_to_f64_imm1(int x) { double block[2]; memset(block, 0x55, sizeof(block)); __asm__ __volatile__( "mov r8, %1" "\n\t" "vldr d14, [%0, #8]" "\n\t" // d14 <- junk "vmov s28, r8" "\n\t" "vcvt.f64.u32 d14,d14,#1" "\n\t" "vstr d14, [%0]" "\n\t" : : /*IN*/"r"(&block[0]), "r"(x) : /*TRASH*/"r8","s28","d14","memory" ); return block[0]; } __attribute__((noinline)) double u32_to_f64_imm32(int x) { double block[2]; memset(block, 0x55, sizeof(block)); __asm__ __volatile__( "mov r8, %1" "\n\t" "vldr d14, [%0, #8]" "\n\t" // d14 <- junk "vmov s28, r8" "\n\t" "vcvt.f64.u32 d14,d14,#32" "\n\t" "vstr d14, [%0]" "\n\t" : : /*IN*/"r"(&block[0]), "r"(x) : /*TRASH*/"r8","s28","d14","memory" ); return block[0]; } void try_u32_to_f64 ( int x ) { double f64 = u32_to_f64_imm32(x); printf("u32_to_f64_imm32: %11d -> %18.14e\n", x, f64); f64 = u32_to_f64_imm1(x); printf("u32_to_f64_imm1: %11d -> %18.14e\n", x, f64); } __attribute__((noinline)) ULong f64_to_s32_imm1 ( double d ) { double block[5]; memset(block, 0x55, sizeof(block)); block[1] = d; __asm__ __volatile__( "mov r8, %0" "\n\t" "vldr d14, [r8, #8]" "\n\t" "vcvt.s32.f64 d14,d14,#1" "\n\t" "vstr d14, [r8,#24]" "\n\t" : : /*IN*/"r"(&block[0]) : /*TRASH*/"d14","r8","memory" ); return *(ULong*)(&block[3]); } __attribute__((noinline)) ULong f64_to_s32_imm32 ( double d ) { double block[5]; memset(block, 0x55, sizeof(block)); block[1] = d; __asm__ __volatile__( "mov r8, %0" "\n\t" "vldr d14, [r8, #8]" "\n\t" "vcvt.s32.f64 d14,d14,#32" "\n\t" "vstr d14, [r8,#24]" "\n\t" : : /*IN*/"r"(&block[0]) : /*TRASH*/"d14","r8","memory" ); return *(ULong*)(&block[3]); } void try_f64_to_s32 ( double d ) { ULong res = f64_to_s32_imm32(d); printf("f64_to_s32_imm32: %18.14e -> 0x%016llx\n", d, res); res = f64_to_s32_imm1(d); printf("f64_to_s32_imm1: %18.14e -> 0x%016llx\n", d, res); } __attribute__((noinline)) ULong f64_to_u32_imm1 ( double d ) { double block[5]; memset(block, 0x55, sizeof(block)); block[1] = d; __asm__ __volatile__( "mov r8, %0" "\n\t" "vldr d14, [r8, #8]" "\n\t" "vcvt.u32.f64 d14,d14,#1" "\n\t" "vstr d14, [r8,#24]" "\n\t" : : /*IN*/"r"(&block[0]) : /*TRASH*/"d14","r8","memory" ); return *(ULong*)(&block[3]); } __attribute__((noinline)) ULong f64_to_u32_imm32 ( double d ) { double block[5]; memset(block, 0x55, sizeof(block)); block[1] = d; __asm__ __volatile__( "mov r8, %0" "\n\t" "vldr d14, [r8, #8]" "\n\t" "vcvt.u32.f64 d14,d14,#32" "\n\t" "vstr d14, [r8,#24]" "\n\t" : : /*IN*/"r"(&block[0]) : /*TRASH*/"d14","r8","memory" ); return *(ULong*)(&block[3]); } void try_f64_to_u32 ( double d ) { ULong res = f64_to_u32_imm32(d); printf("f64_to_u32_imm32: %18.14e -> 0x%016llx\n", d, res); res = f64_to_u32_imm1(d); printf("f64_to_u32_imm1: %18.14e -> 0x%016llx\n", d, res); } __attribute__((noinline)) UInt f32_to_s32_imm1 ( float f ) { float block[5]; memset(block, 0x55, sizeof(block)); block[1] = f; __asm__ __volatile__( "mov r8, %0" "\n\t" "vldr s14, [r8, #4]" "\n\t" "vcvt.s32.f32 s14,s14,#1" "\n\t" "vstr s14, [r8,#12]" "\n\t" : : /*IN*/"r"(&block[0]) : /*TRASH*/"s14","r8","memory" ); return *(UInt*)(&block[3]); } __attribute__((noinline)) UInt f32_to_s32_imm32 ( float f ) { float block[5]; memset(block, 0x55, sizeof(block)); block[1] = f; __asm__ __volatile__( "mov r8, %0" "\n\t" "vldr s14, [r8, #4]" "\n\t" "vcvt.s32.f32 s14,s14,#32" "\n\t" "vstr s14, [r8,#12]" "\n\t" : : /*IN*/"r"(&block[0]) : /*TRASH*/"s14","r8","memory" ); return *(UInt*)(&block[3]); } void try_f32_to_s32 ( float f ) { UInt res = f32_to_s32_imm32(f); printf("f32_to_s32_imm32: %18.14e -> 0x%08x\n", (double)f, res); res = f32_to_s32_imm1(f); printf("f32_to_s32_imm1: %18.14e -> 0x%08x\n", (double)f, res); } __attribute__((noinline)) UInt f32_to_u32_imm1 ( float f ) { float block[5]; memset(block, 0x55, sizeof(block)); block[1] = f; __asm__ __volatile__( "mov r8, %0" "\n\t" "vldr s14, [r8, #4]" "\n\t" "vcvt.u32.f32 s14,s14,#1" "\n\t" "vstr s14, [r8,#12]" "\n\t" : : /*IN*/"r"(&block[0]) : /*TRASH*/"s14","r8","memory" ); return *(UInt*)(&block[3]); } __attribute__((noinline)) UInt f32_to_u32_imm32 ( float f ) { float block[5]; memset(block, 0x55, sizeof(block)); block[1] = f; __asm__ __volatile__( "mov r8, %0" "\n\t" "vldr s14, [r8, #4]" "\n\t" "vcvt.u32.f32 s14,s14,#32" "\n\t" "vstr s14, [r8,#12]" "\n\t" : : /*IN*/"r"(&block[0]) : /*TRASH*/"s14","r8","memory" ); return *(UInt*)(&block[3]); } void try_f32_to_u32 ( float f ) { UInt res = f32_to_u32_imm32(f); printf("f32_to_u32_imm32: %18.14e -> 0x%08x\n", (double)f, res); res = f32_to_u32_imm1(f); printf("f32_to_u32_imm1: %18.14e -> 0x%08x\n", (double)f, res); } int main ( void ) { int i; double d; try_s32_to_f32(0); try_s32_to_f32(1); for (i = 100; i < 200; i++) { try_s32_to_f32(i); } try_s32_to_f32(0x7FFFFFFE); try_s32_to_f32(0x7FFFFFFF); try_s32_to_f32(0x80000000); try_s32_to_f32(0x80000001); try_s32_to_f32(0xFFFFFFFE); try_s32_to_f32(0xFFFFFFFF); printf("\n"); try_u32_to_f32(0); try_u32_to_f32(1); for (i = 100; i < 200; i++) { try_u32_to_f32(i); } try_u32_to_f32(0x7FFFFFFE); try_u32_to_f32(0x7FFFFFFF); try_u32_to_f32(0x80000000); try_u32_to_f32(0x80000001); try_u32_to_f32(0xFFFFFFFE); try_u32_to_f32(0xFFFFFFFF); printf("\n"); try_s32_to_f64(0); try_s32_to_f64(1); for (i = 100; i < 200; i++) { try_s32_to_f64(i); } try_s32_to_f64(0x7FFFFFFE); try_s32_to_f64(0x7FFFFFFF); try_s32_to_f64(0x80000000); try_s32_to_f64(0x80000001); try_s32_to_f64(0xFFFFFFFE); try_s32_to_f64(0xFFFFFFFF); printf("\n"); try_u32_to_f64(0); try_u32_to_f64(1); for (i = 100; i < 200; i++) { try_u32_to_f64(i); } try_u32_to_f64(0x7FFFFFFE); try_u32_to_f64(0x7FFFFFFF); try_u32_to_f64(0x80000000); try_u32_to_f64(0x80000001); try_u32_to_f64(0xFFFFFFFE); try_u32_to_f64(0xFFFFFFFF); printf("\n"); try_f64_to_s32(0.0); try_f64_to_s32(1.0); try_f64_to_s32(-1.0); try_f64_to_s32(0.0 / 0.0); for (d = -100000.01; d < 100000.0; d += 10000.0) { try_f64_to_s32(d); } printf("\n"); try_f64_to_u32(0.0); try_f64_to_u32(1.0); try_f64_to_u32(-1.0); try_f64_to_u32(0.0 / 0.0); for (d = -100000.01; d < 100000.0; d += 10000.0) { try_f64_to_u32(d); } printf("\n"); try_f32_to_s32(0.0); try_f32_to_s32(1.0); try_f32_to_s32(-1.0); try_f32_to_s32(0.0 / 0.0); for (d = -100000.01; d < 100000.0; d += 10000.0) { try_f32_to_s32((float)d); } printf("\n"); try_f32_to_u32(0.0); try_f32_to_u32(1.0); try_f32_to_u32(-1.0); try_f32_to_u32(0.0 / 0.0); for (d = -100000.01; d < 100000.0; d += 10000.0) { try_f32_to_u32((float)d); } return 0; }