0

For my project I must use inline assembly instructions such as rdtsc to calculate the execution time of an Android 4.3 C++ instruction in the stack. I found similar problem in stackoverflow such as 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 but non of them solve the problem that I have.

I used the following code:

{unsigned a, d;asm volatile("rdtsc" : "=a" (a), "=d" (d)); t0 = ((unsigned long)a) | (((unsigned long)d) << 32);}
//The C++ statement to measure its execution time
{unsigned a, d;asm volatile("rdtsc" : "=a" (a), "=d" (d)); t1 = ((unsigned long)a) | (((unsigned long)d) << 32);}
time = (t1-t0)/2-20;

But I'm getting the error message:

error: impossible constraint in 'asm'

My build environment are:

  • Ubuntu 14.04.5 LTS
  • Android 4.3
  • GCC 4.8.5
  • G++ 4.8.5
  • Target: x86_64-linux-gnu

I have tried the above code in a standalone C program (in the same environment) and it is working fine with no problem but once I embed the above code in the Android source code, I get the error message.

My target:

I'm building an image for Android emulator qemu on x86_64-linux-gnu platform.

Community
  • 1
  • 1
Curious
  • 373
  • 1
  • 2
  • 8
  • 3
    If you're building for an ARM Android target (as most Androids are), this cannot be fixed - `rdtsc` does not exist in ARM assembly, it's an `x86` or `x86_64` instruction. – DUman Nov 05 '16 at 22:53
  • And there are even other platforms that runs Android which are even more remote from x86. – Surt Nov 05 '16 at 23:12
  • I'm building for Android emulator qemu on x86_64-linux-gnu platform. – Curious Nov 05 '16 at 23:37
  • How about linux [`clock_gettime`](https://linux.die.net/man/3/clock_gettime)? (on x86_64 it should use `rdtsc` internally). Here is Android related mention: http://stackoverflow.com/a/17216789/4271923 – Ped7g Nov 06 '16 at 00:46
  • 2
    The reason this works in the host OS is that `rdtsc` is a valid instruction for that hw. The compiler/assembler will be able to recognize this code, and emit the appropriate machine code instructions. But it simply isn't a valid ARM instruction, and the fact that you are running an emulator on an i386 host doesn't allow you to 'cheat' and still use it. Also, strictly speaking, the "constraints" error comes from using `"=a"` and `"=d"`, which are i386-only [machine constraints](https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html), not available on ARM. Not like that changes anything. – David Wohlferd Nov 06 '16 at 01:05
  • How to write the code above for ARM? – Curious Nov 06 '16 at 02:03
  • @DavidWohlferd Running the x86_64 android ROM in the emulator would allow him to use `rdtsc`, but it means to set up the project compilation only to x86_64 ABI and no else. (I though this is so obvious, that the OP already did that). I still don't see what it will be good for, as there's minimum (none I'm aware of, but I don't follow new devices much) of x86_64 Android devices. – Ped7g Nov 06 '16 at 12:52
  • @Ped7g: how to compile Android source code to only x86_64 ABI if that fixes the problem because I tried the rdtsc equivalent in ARM (which is mrc p15, 0, %0, c9, c13, 0) but I get the compiler error message "no such instruction". – Curious Nov 07 '16 at 04:38
  • 1
    I don't know what your project build method is. I build my C++ sources for android with `ndk-build` script from NDK, so I set up some things in `jni/Application.mk`, but recently I think there's push to switch to CMake and/or gradle, I'm didn't use those yet. By the "constraint" error I think it may be you already do have correct target, and the inline asm is wrong, I don't know, sorry, I never mix C with asm, I write asm in asm files and C++ in cpp files. I see zero reasons a) why you don't use the `clock_gettime` instead, it's the same thing. b) why to clock something in emulator -> useless. – Ped7g Nov 07 '16 at 05:11
  • 1
    @Ped7g: **I’m building/compiling the Android source code (with some added inline assembly code) itself (not an app) for x86_64 and ARM Android ROM images**. I must build/compile these ROM images on my Ubuntu PC (my build environment) first before I can test the images on an emulator or a real phone, however,**I’m getting error messages as explained before during the compiling process and I could not pass the compilation phase yet.** – Curious Nov 07 '16 at 22:21
  • @Ped7g: To answer your questions, 1) `clock_gettime` is very slow and did not give me the correct result when measuring the execution time of a single Android source code C++ statement but `RDTSC` did. Also in my project I cannot use for-loops or any type of iteration; 2) I’m not clocking something in the emulator but I’m clocking something in the Android source code itself. However, I need to test the build on the QEMU emulator to make sure these ROM images are working before I flash them to the real phones (Intel and ARM). – Curious Nov 07 '16 at 22:24
  • @Ped7g: I'm using the standard Android source code build process outlined [here](https://source.android.com/source/building.html) in the Android Open Source Project web site. – Curious Nov 07 '16 at 22:28
  • @Ped7g: as I said before I tested the inline assembly code in a standalone C/C++ in the same build environment and it's working fine with no problems. – Curious Nov 07 '16 at 22:32
  • Now I understand it, thanks. Does anything from here work for you (it should)? http://stackoverflow.com/a/9887899/4271923 (also by the look of it, you should cast to `unsigned long long` in the shift, but that's not causing you compilation error) – Ped7g Nov 08 '16 at 08:07
  • Maybe put around also some #ifdef to verify you are really in x86_64 platform target, #else #error ... And I think you should rather stick to clock_monotonic of clock_gettime to get more reliable timing results, it should execute within 200 cycles or something like that. Or at least add `cpuid` ahead of `rdtsc` to not read tsc way too much out of order (depends if you are micro benchmarking few instructions, or some complex call, then few cycles off shouldn't matter that much) – Ped7g Nov 08 '16 at 08:21
  • clock_monotonic of clock_gettime and similar functions did not work for me because I'm measuring in some cases the execution time of a single Android source code C/C++, only `rdtsc` works for me. – Curious Nov 09 '16 at 01:32
  • I added the following code for Android source code and for a standalone C/C++ code `#if defined(__x86_64__) printf("__x86_64__"); #elif defined(__aarch64__) printf("__aarch64__"); #elif defined(__ARM_ARCH) printf("__ARM_ARCH"); #else printf("Not Intel and Not ARM arch!"); #endif` – Curious Nov 09 '16 at 01:33
  • For the Android source code, the above added code displays the message "Not Intel and Not ARM arch!" but for the standalone C/C++ code, the above added code displays the message "__x86_64__" – Curious Nov 09 '16 at 01:36
  • Maybe it was in x86 32b mode? Or MIPS? :D ... Get full g++ line executed to compile that file, so you can examine all the switches, plus some of the configuration may be in some option file read by g++, if not everything is provided through CLI. Maybe `make SHELL='sh -x'` to see what is executed? Also maybe you have multi-arch configuration compiling both 32 and 64b? https://source.android.com/source/64-bit-builds.html (I never built android ROM, so this is the point where I'm just doing you the [rubber duck](https://en.wikipedia.org/wiki/Rubber_duck_debugging) ... and I can't help further). – Ped7g Nov 09 '16 at 10:33
  • I confirmed that my CPU is ARM7A, however, when I try to use the instruction asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr));, the compiler gives the error message: Error “no such instruction” asm volatile("mrc p15, 0, %eax, c9, c13, 0" : "=r"(pmccntr)); – Curious Nov 11 '16 at 03:53
  • My Build Environment= PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=4.3 TARGET_PRODUCT=full_manta TARGET_BUILD_VARIANT=eng TARGET_BUILD_TYPE=release TARGET_BUILD_APPS= TARGET_ARCH=arm TARGET_ARCH_VARIANT=armv7-a-neon TARGET_CPU_VARIANT=cortex-a15 HOST_ARCH=x86 HOST_OS=linux HOST_OS_EXTRA=Linux-3.16.0-70-generic-x86_64-with-Ubuntu-14.‌​04-trusty HOST_BUILD_TYPE=release BUILD_ID=JWR66V OUT_DIR=out – – Curious Nov 11 '16 at 03:54
  • This is the code that I used but it gives the above error. {uint32_t pmccntr;asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr));t0=static_cast(pmccntr) * 64;} //The C++ statement to measure its execution time {uint32_t pmccntr;asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr));t1=static_cast(pmccntr) * 64;} time = t1-t0; – Curious Nov 11 '16 at 03:54

0 Answers0