1 2 #include <stdio.h> 3 #include <string.h> 4 5 typedef unsigned long long int ULong; 6 typedef unsigned int UInt; 7 8 __attribute__((noinline)) float s32_to_f32_imm1(int x) 9 { 10 float y; 11 __asm__ ("vcvt.f32.s32 %0, %1, #1" : "=w"(y) : "0"(x)); 12 return y; 13 } 14 15 __attribute__((noinline)) float s32_to_f32_imm32(int x) 16 { 17 float y; 18 __asm__ ("vcvt.f32.s32 %0, %1, #32" : "=w"(y) : "0"(x)); 19 return y; 20 } 21 22 void try_s32_to_f32 ( int x ) 23 { 24 float f32 = s32_to_f32_imm32(x); 25 printf("s32_to_f32_imm32: %11d -> %18.14e\n", x, (double)f32); 26 f32 = s32_to_f32_imm1(x); 27 printf("s32_to_f32_imm1: %11d -> %18.14e\n", x, (double)f32); 28 } 29 30 31 32 __attribute__((noinline)) float u32_to_f32_imm1(int x) 33 { 34 float y; 35 __asm__ ("vcvt.f32.u32 %0, %1, #1" : "=w"(y) : "0"(x)); 36 return y; 37 } 38 39 __attribute__((noinline)) float u32_to_f32_imm32(int x) 40 { 41 float y; 42 __asm__ ("vcvt.f32.u32 %0, %1, #32" : "=w"(y) : "0"(x)); 43 return y; 44 } 45 46 void try_u32_to_f32 ( unsigned int x ) 47 { 48 float f32 = u32_to_f32_imm32(x); 49 printf("u32_to_f32_imm32: %11u -> %18.14e\n", x, (double)f32); 50 f32 = u32_to_f32_imm1(x); 51 printf("u32_to_f32_imm1: %11u -> %18.14e\n", x, (double)f32); 52 } 53 54 55 56 __attribute__((noinline)) double s32_to_f64_imm1(int x) 57 { 58 double block[2]; 59 memset(block, 0x55, sizeof(block)); 60 __asm__ __volatile__( 61 "mov r8, %1" "\n\t" 62 "vldr d14, [%0, #8]" "\n\t" // d14 <- junk 63 "vmov s1, r8" "\n\t" 64 "vcvt.f64.s32 d14,d14,#1" "\n\t" 65 "vstr d14, [%0]" "\n\t" 66 : : /*IN*/"r"(&block[0]), "r"(x) : /*TRASH*/"r8","s28","d14","memory" 67 ); 68 return block[0]; 69 } 70 71 __attribute__((noinline)) double s32_to_f64_imm32(int x) 72 { 73 double block[2]; 74 memset(block, 0x55, sizeof(block)); 75 __asm__ __volatile__( 76 "mov r8, %1" "\n\t" 77 "vldr d14, [%0, #8]" "\n\t" // d14 <- junk 78 "vmov s28, r8" "\n\t" 79 "vcvt.f64.s32 d14,d14,#32" "\n\t" 80 "vstr d14, [%0]" "\n\t" 81 : : /*IN*/"r"(&block[0]), "r"(x) : /*TRASH*/"r8","s28","d14","memory" 82 ); 83 return block[0]; 84 } 85 86 void try_s32_to_f64 ( int x ) 87 { 88 double f64 = s32_to_f64_imm32(x); 89 printf("s32_to_f64_imm32: %11d -> %18.14e\n", x, f64); 90 f64 = s32_to_f64_imm1(x); 91 printf("s32_to_f64_imm1: %11d -> %18.14e\n", x, f64); 92 } 93 94 95 96 __attribute__((noinline)) double u32_to_f64_imm1(int x) 97 { 98 double block[2]; 99 memset(block, 0x55, sizeof(block)); 100 __asm__ __volatile__( 101 "mov r8, %1" "\n\t" 102 "vldr d14, [%0, #8]" "\n\t" // d14 <- junk 103 "vmov s28, r8" "\n\t" 104 "vcvt.f64.u32 d14,d14,#1" "\n\t" 105 "vstr d14, [%0]" "\n\t" 106 : : /*IN*/"r"(&block[0]), "r"(x) : /*TRASH*/"r8","s28","d14","memory" 107 ); 108 return block[0]; 109 } 110 111 __attribute__((noinline)) double u32_to_f64_imm32(int x) 112 { 113 double block[2]; 114 memset(block, 0x55, sizeof(block)); 115 __asm__ __volatile__( 116 "mov r8, %1" "\n\t" 117 "vldr d14, [%0, #8]" "\n\t" // d14 <- junk 118 "vmov s28, r8" "\n\t" 119 "vcvt.f64.u32 d14,d14,#32" "\n\t" 120 "vstr d14, [%0]" "\n\t" 121 : : /*IN*/"r"(&block[0]), "r"(x) : /*TRASH*/"r8","s28","d14","memory" 122 ); 123 return block[0]; 124 } 125 126 void try_u32_to_f64 ( int x ) 127 { 128 double f64 = u32_to_f64_imm32(x); 129 printf("u32_to_f64_imm32: %11d -> %18.14e\n", x, f64); 130 f64 = u32_to_f64_imm1(x); 131 printf("u32_to_f64_imm1: %11d -> %18.14e\n", x, f64); 132 } 133 134 135 136 __attribute__((noinline)) ULong f64_to_s32_imm1 ( double d ) 137 { 138 double block[5]; 139 memset(block, 0x55, sizeof(block)); 140 block[1] = d; 141 __asm__ __volatile__( 142 "mov r8, %0" "\n\t" 143 "vldr d14, [r8, #8]" "\n\t" 144 "vcvt.s32.f64 d14,d14,#1" "\n\t" 145 "vstr d14, [r8,#24]" "\n\t" 146 : : /*IN*/"r"(&block[0]) : /*TRASH*/"d14","r8","memory" 147 ); 148 return *(ULong*)(&block[3]); 149 } 150 151 __attribute__((noinline)) ULong f64_to_s32_imm32 ( double d ) 152 { 153 double block[5]; 154 memset(block, 0x55, sizeof(block)); 155 block[1] = d; 156 __asm__ __volatile__( 157 "mov r8, %0" "\n\t" 158 "vldr d14, [r8, #8]" "\n\t" 159 "vcvt.s32.f64 d14,d14,#32" "\n\t" 160 "vstr d14, [r8,#24]" "\n\t" 161 : : /*IN*/"r"(&block[0]) : /*TRASH*/"d14","r8","memory" 162 ); 163 return *(ULong*)(&block[3]); 164 } 165 166 void try_f64_to_s32 ( double d ) 167 { 168 ULong res = f64_to_s32_imm32(d); 169 printf("f64_to_s32_imm32: %18.14e -> 0x%016llx\n", d, res); 170 res = f64_to_s32_imm1(d); 171 printf("f64_to_s32_imm1: %18.14e -> 0x%016llx\n", d, res); 172 } 173 174 175 176 __attribute__((noinline)) ULong f64_to_u32_imm1 ( double d ) 177 { 178 double block[5]; 179 memset(block, 0x55, sizeof(block)); 180 block[1] = d; 181 __asm__ __volatile__( 182 "mov r8, %0" "\n\t" 183 "vldr d14, [r8, #8]" "\n\t" 184 "vcvt.u32.f64 d14,d14,#1" "\n\t" 185 "vstr d14, [r8,#24]" "\n\t" 186 : : /*IN*/"r"(&block[0]) : /*TRASH*/"d14","r8","memory" 187 ); 188 return *(ULong*)(&block[3]); 189 } 190 191 __attribute__((noinline)) ULong f64_to_u32_imm32 ( double d ) 192 { 193 double block[5]; 194 memset(block, 0x55, sizeof(block)); 195 block[1] = d; 196 __asm__ __volatile__( 197 "mov r8, %0" "\n\t" 198 "vldr d14, [r8, #8]" "\n\t" 199 "vcvt.u32.f64 d14,d14,#32" "\n\t" 200 "vstr d14, [r8,#24]" "\n\t" 201 : : /*IN*/"r"(&block[0]) : /*TRASH*/"d14","r8","memory" 202 ); 203 return *(ULong*)(&block[3]); 204 } 205 206 void try_f64_to_u32 ( double d ) 207 { 208 ULong res = f64_to_u32_imm32(d); 209 printf("f64_to_u32_imm32: %18.14e -> 0x%016llx\n", d, res); 210 res = f64_to_u32_imm1(d); 211 printf("f64_to_u32_imm1: %18.14e -> 0x%016llx\n", d, res); 212 } 213 214 215 216 __attribute__((noinline)) UInt f32_to_s32_imm1 ( float f ) 217 { 218 float block[5]; 219 memset(block, 0x55, sizeof(block)); 220 block[1] = f; 221 __asm__ __volatile__( 222 "mov r8, %0" "\n\t" 223 "vldr s14, [r8, #4]" "\n\t" 224 "vcvt.s32.f32 s14,s14,#1" "\n\t" 225 "vstr s14, [r8,#12]" "\n\t" 226 : : /*IN*/"r"(&block[0]) : /*TRASH*/"s14","r8","memory" 227 ); 228 return *(UInt*)(&block[3]); 229 } 230 231 __attribute__((noinline)) UInt f32_to_s32_imm32 ( float f ) 232 { 233 float block[5]; 234 memset(block, 0x55, sizeof(block)); 235 block[1] = f; 236 __asm__ __volatile__( 237 "mov r8, %0" "\n\t" 238 "vldr s14, [r8, #4]" "\n\t" 239 "vcvt.s32.f32 s14,s14,#32" "\n\t" 240 "vstr s14, [r8,#12]" "\n\t" 241 : : /*IN*/"r"(&block[0]) : /*TRASH*/"s14","r8","memory" 242 ); 243 return *(UInt*)(&block[3]); 244 } 245 246 void try_f32_to_s32 ( float f ) 247 { 248 UInt res = f32_to_s32_imm32(f); 249 printf("f32_to_s32_imm32: %18.14e -> 0x%08x\n", (double)f, res); 250 res = f32_to_s32_imm1(f); 251 printf("f32_to_s32_imm1: %18.14e -> 0x%08x\n", (double)f, res); 252 } 253 254 255 256 __attribute__((noinline)) UInt f32_to_u32_imm1 ( float f ) 257 { 258 float block[5]; 259 memset(block, 0x55, sizeof(block)); 260 block[1] = f; 261 __asm__ __volatile__( 262 "mov r8, %0" "\n\t" 263 "vldr s14, [r8, #4]" "\n\t" 264 "vcvt.u32.f32 s14,s14,#1" "\n\t" 265 "vstr s14, [r8,#12]" "\n\t" 266 : : /*IN*/"r"(&block[0]) : /*TRASH*/"s14","r8","memory" 267 ); 268 return *(UInt*)(&block[3]); 269 } 270 271 __attribute__((noinline)) UInt f32_to_u32_imm32 ( float f ) 272 { 273 float block[5]; 274 memset(block, 0x55, sizeof(block)); 275 block[1] = f; 276 __asm__ __volatile__( 277 "mov r8, %0" "\n\t" 278 "vldr s14, [r8, #4]" "\n\t" 279 "vcvt.u32.f32 s14,s14,#32" "\n\t" 280 "vstr s14, [r8,#12]" "\n\t" 281 : : /*IN*/"r"(&block[0]) : /*TRASH*/"s14","r8","memory" 282 ); 283 return *(UInt*)(&block[3]); 284 } 285 286 void try_f32_to_u32 ( float f ) 287 { 288 UInt res = f32_to_u32_imm32(f); 289 printf("f32_to_u32_imm32: %18.14e -> 0x%08x\n", (double)f, res); 290 res = f32_to_u32_imm1(f); 291 printf("f32_to_u32_imm1: %18.14e -> 0x%08x\n", (double)f, res); 292 } 293 294 295 296 int main ( void ) 297 { 298 int i; 299 double d; 300 301 try_s32_to_f32(0); 302 try_s32_to_f32(1); 303 for (i = 100; i < 200; i++) { 304 try_s32_to_f32(i); 305 } 306 try_s32_to_f32(0x7FFFFFFE); 307 try_s32_to_f32(0x7FFFFFFF); 308 try_s32_to_f32(0x80000000); 309 try_s32_to_f32(0x80000001); 310 try_s32_to_f32(0xFFFFFFFE); 311 try_s32_to_f32(0xFFFFFFFF); 312 313 printf("\n"); 314 315 try_u32_to_f32(0); 316 try_u32_to_f32(1); 317 for (i = 100; i < 200; i++) { 318 try_u32_to_f32(i); 319 } 320 try_u32_to_f32(0x7FFFFFFE); 321 try_u32_to_f32(0x7FFFFFFF); 322 try_u32_to_f32(0x80000000); 323 try_u32_to_f32(0x80000001); 324 try_u32_to_f32(0xFFFFFFFE); 325 try_u32_to_f32(0xFFFFFFFF); 326 327 printf("\n"); 328 329 try_s32_to_f64(0); 330 try_s32_to_f64(1); 331 for (i = 100; i < 200; i++) { 332 try_s32_to_f64(i); 333 } 334 try_s32_to_f64(0x7FFFFFFE); 335 try_s32_to_f64(0x7FFFFFFF); 336 try_s32_to_f64(0x80000000); 337 try_s32_to_f64(0x80000001); 338 try_s32_to_f64(0xFFFFFFFE); 339 try_s32_to_f64(0xFFFFFFFF); 340 341 printf("\n"); 342 343 try_u32_to_f64(0); 344 try_u32_to_f64(1); 345 for (i = 100; i < 200; i++) { 346 try_u32_to_f64(i); 347 } 348 try_u32_to_f64(0x7FFFFFFE); 349 try_u32_to_f64(0x7FFFFFFF); 350 try_u32_to_f64(0x80000000); 351 try_u32_to_f64(0x80000001); 352 try_u32_to_f64(0xFFFFFFFE); 353 try_u32_to_f64(0xFFFFFFFF); 354 355 printf("\n"); 356 try_f64_to_s32(0.0); 357 try_f64_to_s32(1.0); 358 try_f64_to_s32(-1.0); 359 try_f64_to_s32(0.0 / 0.0); 360 for (d = -100000.01; d < 100000.0; d += 10000.0) { 361 try_f64_to_s32(d); 362 } 363 364 printf("\n"); 365 try_f64_to_u32(0.0); 366 try_f64_to_u32(1.0); 367 try_f64_to_u32(-1.0); 368 try_f64_to_u32(0.0 / 0.0); 369 for (d = -100000.01; d < 100000.0; d += 10000.0) { 370 try_f64_to_u32(d); 371 } 372 373 printf("\n"); 374 try_f32_to_s32(0.0); 375 try_f32_to_s32(1.0); 376 try_f32_to_s32(-1.0); 377 try_f32_to_s32(0.0 / 0.0); 378 for (d = -100000.01; d < 100000.0; d += 10000.0) { 379 try_f32_to_s32((float)d); 380 } 381 382 printf("\n"); 383 try_f32_to_u32(0.0); 384 try_f32_to_u32(1.0); 385 try_f32_to_u32(-1.0); 386 try_f32_to_u32(0.0 / 0.0); 387 for (d = -100000.01; d < 100000.0; d += 10000.0) { 388 try_f32_to_u32((float)d); 389 } 390 391 return 0; 392 } 393