1

It's my first time struggling with ARM processors (ARMv6), and I need a bit of help while I'm trying to "translate" a block of ASM code written in a C++ source code.

The original code shows:

#ifdef _WIN32
__asm
{
    mov eax, var1
    xor edx, edx
    div var2
    mov var1, eax
    mov var3, edx
}
#else
__asm__ __volatile__ ( “mov %2, %%eax;”
                “xor %%edx, %%edx;”
                “divl %3;”
                “mov %%eax, %0;”
                “mov %%edx, %1;”
                : “=m” (var1), “=m” (var3)
                : “m” (var1), “m”(var2)
                : “%eax”, “%edx”
               );
#endif

So, I can assume that I have to add a new line to "let the compiler 'identify' the ARM", doing something like:

#if defined _WIN32
    __asm
#elif defined __ARM_ARCH_6__
    //here my new code
#else
   __asm__ __volatile__
#endif

But, as I said, it's my first time using ARM processor, so I have some questions... By a link found here (stackoverflow) I found a manual of ARM ASM, in which says there're 16 registrers (r0 - r15), in which (I assume) r4 to r8 are avaliable for "free use". It's that right?

If this is right, I can "translate" [eax=r4, edx=r5] or something similar. But I really have no idea of how I must declare the block; I mean, is "__asm__ __volatile__" a correct "signature" in this case? Is another one correct?

How I have to put the block? Between brackets ({})? How can I refer "var1", "var2" and "var3"?

Any link will be ok, I don't want the "translation", because I want to know about this topic...

Thanks a lot in advance

__

Edit:I was looking deeper (I have to confess that in first instance I only look at the #ifdef and #else, which is too bad) the source code, and I found this:

unsigned int var1 = (unsigned int)var0;
for (; i >= 0; i--){
    #ifdef __powerpc__
        var4[i] = var5[var1 % m_var2];
        var1 /= m_var2;
    #else
        unsigned int var2 = m_var2;
        unsigned int var3;
    #ifdef _WIN32
            __asm
            {
                mov eax, var1
                xor edx, edx
                div var2
                mov var1, eax
                mov var3, edx
            }
    #else
            __asm__ __volatile__ (  "mov %2, %%eax;"
                                    "xor %%edx, %%edx;"
                                    "divl %3;"
                                    "mov %%eax, %0;"
                                    "mov %%edx, %1;"
                                    : "=m"(var1), "=m"(var3)
                                    : "m"(var1), "m"(var2)
                                    : "%eax", "%edx"
                                );
    #endif
            var4[i] = var5[var3];
    #endif
}

So, as I can see, the "#ifdef powerpc block will work fine in ARM since it's no using any ASM instruction, right? Taking that is true, I can rewrite

#if defined(__powerpc__) || defined(__ARM_ARC_6__)
    //stuff here...

It will works?

Thakns again


Edit again: Better test before asking... It works! But now I have new problems with the linker... :-(

David
  • 21
  • 1
  • 7
  • Best would be to translate to C instead of to ARM asm. Is the function that contains this code called divmod by chance? – Marc Glisse Feb 01 '14 at 12:24
  • 1
    `void f(unsigned int a,unsigned int b,unsigned int*q,unsigned int*r){ *q=a/b; *r=a%b; }` generates exactly your asm on a 32-bit PC. My advice is to remove the whole nonsense and write C(++) code. Now you can compile this C code for ARM and see what the compiler generates, if you are interested. – Marc Glisse Feb 01 '14 at 12:31
  • http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html for explanations on the syntax of inline asm for gcc-compatible compilers. – Marc Glisse Feb 01 '14 at 12:34
  • Bear in mind that even on an ARM system that _has_ hardware divide instructions (they're an optional part of the architecture) they don't work this way - `SDIV`/`UDIV` are 32-bit to 32-bit divides with no remainder, and there is no mod instruction. Just let the compiler do it. – Notlikethat Feb 01 '14 at 13:19
  • Thanks everyone to answer. I was looking deeply in the source, and I edit the first post. I think now can be easily solved :-) – David Feb 01 '14 at 14:18
  • If I were you I'd keep only the 2-line version at the beginning and use it on all platforms, not just powerpc+arm. Unless you have the worst compiler on earth, you may even see better performance. – Marc Glisse Feb 01 '14 at 18:20
  • Well, it's a matter of perfomance... The program takes hours to complete a task, so if the creator of that block of ASM thoughts is better that way, I think is for some reason. The better way (in my opinion) will be "translate" the whole ASM block... – David Feb 01 '14 at 19:32
  • Just use the C code, as Marc said. The inline asm is either a misguided false optimisation, or this code dates from when compilers were less clever. Either way, it's pointless now - I've just tested and, with optimisation turned on, both GCC 4.8 and MSVC 2010 generate that same asm for x86, whilst GCC generates the optimal equivalent for ARM. Also note that inline asm can disable certain other compiler optimisations, thus making the rest of the code worse. – Notlikethat Feb 01 '14 at 20:39

0 Answers0