C++ Inline ASM code to get clock frequency for ARM - c++

I was trying to compile ODE(Open Dynamics Engine) physics C++ library for Android Native application on Android Studio.
When i tried to build it, it gave me some error telling that some inline ASM code is not correct as they are written for INTEL processor syntax. This are mostly to get CPU clock frequency for physics simulation purpose.
(Editor's note: this x86 GNU C inline asm is inefficient and not even safe or portable. See How to get the CPU cycle count in x86_64 from C++? for correct ways to use i386 / x86-64 rdtsc.)
static inline void getClockCount (unsigned long cc[2])
{
#ifndef X86_64_SYSTEM
asm volatile (
"rdtsc\n"
"movl %%eax,(%%esi)\n"
"movl %%edx,4(%%esi)\n"
: : "S" (cc) : "%eax","%edx","cc","memory");
#else
asm volatile (
"rdtsc\n"
"movl %%eax,(%%rsi)\n"
"movl %%edx,4(%%rsi)\n"
: : "S" (cc) : "%eax","%edx","cc","memory");
#endif
}
static inline void serialize()
{
#ifndef X86_64_SYSTEM
asm volatile (
"mov $0,%%eax\n"
"push %%ebx\n"
"cpuid\n"
"pop %%ebx\n"
: : : "%eax","%ecx","%edx","cc","memory");
#else
asm volatile (
"mov $0,%%rax\n"
"push %%rbx\n"
"cpuid\n"
"pop %%rbx\n"
: : : "%rax","%rcx","%rdx","cc","memory");
#endif
}
static inline double loadClockCount (unsigned long a[2])
{
double ret;
#ifndef X86_64_SYSTEM
asm volatile ("fildll %1; fstpl %0" : "=m" (ret) : "m" (a[0]) :
"cc","memory");
#else
asm volatile ("fildll %1; fstpl %0" : "=m" (ret) : "m" (a[0]) :
"cc","memory");
#endif
return ret;
}
I don't know how to do same for ARM? Any help?

Related

Compiling sample cygload.cc on windows with Visual Studio

I am trying to compile a sample program from the cygwin repo that shows how to correctly load the cygwin1.dll.
I am getting stumped by macro definition and getting "Unknown architecture error"
#ifdef __GNUC__ /* GCC */
# ifdef __x86_64__
__asm__ (
"mov %%gs:8, %0"
:"=r"(stackbase)
);
# elif __X86__
__asm__ (
"movl %%fs:4, %0"
:"=r"(stackbase)
);
# else
# error Unknown architecture
# endif
#else /* !GCC assumed to be MSVC */
# ifdef __X86__
__asm
{
mov eax, fs:[4];
mov stackbase, eax;
}
#else
# error Unknown architecture
# endif
#endif
UPDATE: Don't try to compile this on a 64-bit windows machine in 2022. The compiler macros are not defined on and the _asm directive has not been supported since VS2005

C++ printing string works in bootloader but not in kernel

I'm working on a simple real-mode OS in c++. I can't figure out how to print strings, though. The following code works when it's in the bootloader, but not when it's in the kernel.
__asm__ __volatile__(".code16gcc \n");
__asm__ __volatile__ ("xor ax, ax\n");
__asm__ __volatile__ ("mov ds, ax\n");
__asm__ __volatile__("jmp main \n");
void printf(const char* str)
{
while(*str)
{
__asm__ __volatile__("int 0x10" : : "a"(0x0e00 | *str), "b"(0x0007));
++str;
}
}
void main(){
printf("Hi!");
}
I'm sure it's because the ds register it set to 0, but the code is actually at 0x7E00 (that's where the bootloader puts it). I've tried setting ds to 0x7E0, which should cause it to load data correctly because 0x7E0 * 16 = 0x7E00, but it still doesn't work. It's probably just some silly mistake, but I would appreciate some help. If it matters, here is my bootloader code:
__asm__(".code16gcc \n");
void main(){
__asm__ __volatile__("mov al, 0x02 \n");
__asm__ __volatile__("xor ah, ah \n");
__asm__ __volatile__("int 0x10 \n");
__asm__ __volatile__("xor ax, ax \n");
__asm__ __volatile__("mov es, ax \n");
__asm__ __volatile__("mov bx, 0x7E00 \n");
__asm__ __volatile__("mov al, 0x03 \n");
__asm__ __volatile__("mov ch, 0x00 \n");
__asm__ __volatile__("mov cl, 0x02 \n");
__asm__ __volatile__("mov dh, 0x00 \n");
__asm__ __volatile__("mov ah, 0x02 \n");
__asm__ __volatile__("int 0x13 \n");
__asm__ __volatile__("jmp 0:0x7E00 \n");
}

android ndk asm compile error: inconsistent operand constraints in an 'asm'

I am compiling a piece of asm code for android:
static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
{
__asm__ __volatile__ (
"cpuid"
: "=a" (*a) ,
"=b" (*b) ,
"=c" (*c) ,
"=d" (*d)
: "0" (function)) ;
}
The APP_ABI is set to 'all':
APP_ABI := all
The compiling failed when come to x86:
$ ndk-build
[armeabi-v7a] Gdbserver : [arm-linux-androideabi-4.6] libs/armeabi-v7a/gdbserver
[armeabi-v7a] Gdbsetup : libs/armeabi-v7a/gdb.setup
[armeabi] Gdbserver : [arm-linux-androideabi-4.6] libs/armeabi/gdbserver
[armeabi] Gdbsetup : libs/armeabi/gdb.setup
[x86] Gdbserver : [x86-4.6] libs/x86/gdbserver
[x86] Gdbsetup : libs/x86/gdb.setup
[mips] Gdbserver : [mipsel-linux-android-4.6] libs/mips/gdbserver
[mips] Gdbsetup : libs/mips/gdb.setup
[armeabi-v7a] Compile thumb : hello-jni <= CpuArch.c
[armeabi-v7a] SharedLibrary : libhello-jni.so
[armeabi-v7a] Install : libhello-jni.so => libs/armeabi-v7a/libhello-jni.so
[armeabi] Compile thumb : hello-jni <= CpuArch.c
[armeabi] SharedLibrary : libhello-jni.so
[armeabi] Install : libhello-jni.so => libs/armeabi/libhello-jni.so
[x86] Compile : hello-jni <= CpuArch.c
D:/adt/ndk/samples/hello-jni/jni/CpuArch.c: In function 'MyCPUID':
D:/adt/ndk/samples/hello-jni/jni/CpuArch.c:75:3: error: inconsistent operand constraints in an 'asm'
/cygdrive/d/adt/ndk/build/core/build-binary.mk:391: recipe for target '/cygdrive/d/adt/ndk/samples/hello-jni/obj/local/x86/objs-debug/hello-jni/CpuArch.o' failed
make: *** [/cygdrive/d/adt/ndk/samples/hello-jni/obj/local/x86/objs-debug/hello-jni/CpuArch.o] Error 1
I don't have much experience in asm. And the error msg seems not enough to find a solution. :(
BTW,the compiling is made in win7 using cygwin.
Full version:
static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
{
#ifdef USE_ASM
#ifdef _MSC_VER
UInt32 a2, b2, c2, d2;
__asm xor EBX, EBX;
__asm xor ECX, ECX;
__asm xor EDX, EDX;
__asm mov EAX, function;
__asm cpuid;
__asm mov a2, EAX;
__asm mov b2, EBX;
__asm mov c2, ECX;
__asm mov d2, EDX;
*a = a2;
*b = b2;
*c = c2;
*d = d2;
#else
__asm__ __volatile__ (
"cpuid"
: "=a" (*a) ,
"=b" (*b) ,
"=c" (*c) ,
"=d" (*d)
: "0" (function)) ;
#endif
#else
int CPUInfo[4];
__cpuid(CPUInfo, function);
*a = CPUInfo[0];
*b = CPUInfo[1];
*c = CPUInfo[2];
*d = CPUInfo[3];
#endif
}
This code is based up something I wrote in this Stackoverflow answer. One has to be careful to preserve %ebx register on some x86 based architectures/ABI. %ebx is used to relocate code (shared object etc) when position independent code (-fPIC gcc option) is being generated. The code below avoids using =b in the extended assembler output and uses a register the compiler knows is free and usable. %ebx is preserved by swapping it to the free register before and after the call to cpuid. I've also fixed a small gotchya bug related to the %ecx register. I clear it to 0 ("c"(0)) since on some architectures failure to do so will result in stale values being returned by cpuid.
static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
{
#if defined(__i386__)
__asm__ __volatile__ (
"xchgl\t%%ebx, %k1\n\t" \
"cpuid\n\t" \
"xchgl\t%%ebx, %k1\n\t"
: "=a"(*a), "=&r"(*b), "=c"(*c), "=d"(*d)
: "a"(function), "c"(0));
#elif defined(__x86_64__)
__asm__ __volatile__ (
"xchgq\t%%rbx, %q1\n\t" \
"cpuid\n\t" \
"xchgq\t%%rbx, %q1\n\t"
: "=a"(*a), "=&r"(*b), "=c"(*c), "=d"(*d)
: "a"(function), "c"(0));
#else
#error "Unknown architecture."
#endif
}

Error compiling in Assembly Code for cmpxchg16b

I am working on a project that requires a double-width-compare-and-swap operation (cmpxchg16b). I found the following code by luke h, however when I compile it with "g++-4.7 -g -DDEBUG=1 -std=c++0x dwcas2.c -o dwcas2.o" I get the following error:
Error:
g++-4.7 -g -DDEBUG=1 -m64 -std=c++0x dwcas2.c -o dwcas2.o
dwcas2.c: Assembler messages:
dwcas2.c:29: Error: junk `ptr ' after expression
Any ideas why?, I feel like it is something small and easy to fix, I just can not see it.
Computer Specs:
64-core ThinkMate RAX QS5-4410 server running Ubuntu 12.04 LTS. It is a NUMA system with four AMD Opteron 6272 CPUs (16 cores per chip #2.1 GHz) and 314 GB of shared memory.
Code:
#include <stdint.h>
namespace types
{
struct uint128_t
{
uint64_t lo;
uint64_t hi;
}
__attribute__ (( __aligned__( 16 ) ));
}
template< class T > inline bool cas( volatile T * src, T cmp, T with );
template<> inline bool cas( volatile types::uint128_t * src, types::uint128_t cmp, types::uint128_t with )
{
bool result;
__asm__ __volatile__
(
"lock cmpxchg16b oword ptr %1\n\t"
"setz %0"
: "=q" ( result )
, "+m" ( *src )
, "+d" ( cmp.hi )
, "+a" ( cmp.lo )
: "c" ( with.hi )
, "b" ( with.lo )
: "cc"
);
return result;
}
int main()
{
using namespace types;
uint128_t test = { 0xdecafbad, 0xfeedbeef };
uint128_t cmp = test;
uint128_t with = { 0x55555555, 0xaaaaaaaa };
return ! cas( & test, cmp, with );
}
On x86 GCC defaults to using AT&T syntax assembly, but your source is in Intel syntax. You probably also need "memory" in the clobber list.

VS C++ ASM to GCC ASM

Did I convert this correctly?
Original VS C++ version:
_TEB *pTeb = NULL;
_asm
{
mov eax, fs:[0x18];
mov pTeb, eax;
}
My attempt (GCC):
_TEB *pTeb = NULL;
asm ("movl %%fs:0x18, %%eax\n\t"
"movl %%eax, %0"
: "=rm" (pTeb) : : "%eax");
If you need GCC syntax for Windows-related code, a good source to check is ReactOS sources. Here's their implementation of NtCurrentTeb() (with irrelevant parts removed):
unsigned long __readfsdword(const unsigned long Offset)
{
unsigned long value;
__asm__ __volatile__("movl %%fs:%a[Offset], %k[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
return value;
}
struct _TEB * NtCurrentTeb(VOID)
{
return (PTEB)__readfsdword(0x18);
}