gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

ASM > MULSHIFT32 aka smull error

#169332 - Tommmie - Sat Jul 04, 2009 7:16 pm

hey everyone,

i'm very new to assembly, but i have to decode a lib which is optimized for arm. in a header file they declare this function:

Code:
static __inline__ int MULSHIFT32(int x, int y)
{
    int zlow;
    __asm__ volatile ("smull %0,%1,%2,%3" : "=&r" (zlow), "=r" (y) : "r" (x), "1" (y) : "cc");
    return y;
}


but when i try to compile a c file with the function MULSHIFT32(to multiply two 32bit integers) it gives errors like this:
Quote:
775: Error: selected processor does not support `smull ip,r7,r6,r7'


can someone help me?[/code]

#169334 - Miked0801 - Sat Jul 04, 2009 7:46 pm

My guess is it is compiled in Thumb mode and that is an ARM only op.

#169335 - Tommmie - Sun Jul 05, 2009 7:36 am

thanks, didn't thought about it! will try it

edit: you're the best man, it works now!!! really thanks

#169338 - Tommmie - Sun Jul 05, 2009 12:28 pm

following error is this:

Code:
/home/tom/tmp/ccp00P8r.s:350: rdhi, rdlo and rm must all be different
/home/tom/tmp/ccp00P8r.s:826: rdhi, rdlo and rm must all be different
/home/tom/tmp/ccp00P8r.s:836: rdhi, rdlo and rm must all be different
/home/tom/tmp/ccp00P8r.s:1225: rdhi, rdlo and rm must all be different
/home/tom/tmp/ccp00P8r.s:1235: rdhi, rdlo and rm must all be different
/home/tom/tmp/ccp00P8r.s:1251: rdhi, rdlo and rm must all be different
/home/tom/tmp/ccp00P8r.s:1261: rdhi, rdlo and rm must all be different


i don't know where the problem lies. it uses some arm asm functions but not rdhi and so on
[/code]

#169340 - Dwedit - Sun Jul 05, 2009 2:23 pm

It's saying that "rdhi, rdlo and rm must all be different"

From the ARM reference, the format of the SMULL instruction is:
SMULL{cond}{S} RdLo,RdHi,Rm,Rs

So an instruction like "SMULL r0,r2,r0,r1" would cause an error.

First compile with the -S switch to get the ASM source so you can see what the compiler is doing wrong, and which registers it's duplicating.

Look at this nice page about ARM GCC inline assembly
Find out how to force it not to reuse registers inappropriately.

edit: I have no idea why the guy who wrote that inline asm claims it clobbers the condition codes, when it clearly doesn't (that's what the "CC" is for, but the instruction is not SMULLS, it's plain SMULL)

Another edit:
I just tested how the compiler compiles this C code:
Code:

typedef int s32;
typedef long long s64;

s32 test(s32 x, s32 y)
{
   return ((s64)x * (s64)y) >> 32;
}

It produces an SMULL instruction followed by a MOV instruction. Maybe that's what the inline ASM was there for, getting rid of the MOV.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."

#169342 - Tommmie - Sun Jul 05, 2009 2:53 pm

ok, sorry but i'm not good with makefiles, where to put that switch?

edit: sorry wasn't clear enough in the second post, the error about mulshift32 is gone. i try to compile another file of the lib. and then i got that error. and the fine is: it say's not in which instruction:(

#169344 - Ruben - Sun Jul 05, 2009 3:38 pm

I really don't think it's an error, but rather a warning: In my Midi player, I use UMULL to calculate the final frequency for a note, and get the same error, but it compiles. I suppose it's something like the warning that one shouldn't do "mul r0, r0, r1".

#169345 - Tommmie - Sun Jul 05, 2009 3:54 pm

i read something about a warning to, but it should work, or not?

#169346 - Dwedit - Sun Jul 05, 2009 4:38 pm

If it is duplicating registers that shouldn't be duplicated, it probably won't work on an ARM.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."

#169347 - Ruben - Sun Jul 05, 2009 5:12 pm

Dwedit:
I think the reason for the warnings is for compatibility for pure ARM processors, because in THUMB, MUL must overlap at least one register, so it would make sense that one could do that in ARM, so they allowed it on the ARM7TDMI. So I suppose it would work on an ARM processor that supports THUMB, but won't on a purely ARM processor.

#169348 - Tommmie - Sun Jul 05, 2009 5:21 pm

it compiled fine, now i have to make a test program with it and see if it works:) just read up some more asm for arm. is it really dofficult or not?

#169349 - Ruben - Sun Jul 05, 2009 6:28 pm

Well, at first it's like @__@ but once you get the hang of it, it's actually quite easy. You just have to remember the basic arithmetic functions (like add, sub, mul), the memory functions (ldr[b/h], str[b/h], the misc. functions (b, bl, bx) and once you get the hang of it, the conditionals (like -eq, -ne, -vc, -vs, etc). But yeah, it's hard at first, but it pays off nicely and actually turns into fun at times (like when coding tinting routines, or sound mixing routines, in my case).

#169350 - Tommmie - Sun Jul 05, 2009 7:01 pm

yes, i'm dutch, so sometimes the document is a bit hard to read. but i already know how to do defines:) and add
Code:

PI EQU 3.14

add r0, r1, #PI @ is this one right?

or did i misunderstood that?

how did you learned asm, do you know some good tutorials for beginners?

#169352 - Ruben - Mon Jul 06, 2009 5:12 am

Err, I'll just have to point something out there: As far as I'm concerned, one can't do floating-point arithmetic (that is, 3.14159 or whatever).

And about learning it...
Well, I've got Asperger's syndrome so I tend to pick up things I like a lot faster than "normal" people, but I suppose that if you are serious about learning ARM assembler, then you should check out Tonc's page on assembler. Another nice thing to have is Rejected's ARM/THUMB reference sheet.

But yeah, it would be better if you start small and then challenge yourself to re-write some small C programs in assembler.

#169354 - Tommmie - Mon Jul 06, 2009 7:10 am

thanks, i will do that. and because i'm a "nornal" person i will learn something slower but i don't care: i've summer holiday here!

#169373 - Cearn - Mon Jul 06, 2009 8:03 pm

Ruben wrote:
Well, at first it's like @__@ but once you get the hang of it, it's actually quite easy. You just have to remember the basic arithmetic functions (like add, sub, mul), the memory functions (ldr[b/h], str[b/h], the misc. functions (b, bl, bx) and once you get the hang of it, the conditionals (like -eq, -ne, -vc, -vs, etc). But yeah, it's hard at first, but it pays off nicely and actually turns into fun at times.
Also, ARM asm's purdy ^_^.

But yeah, it'll take a while to understand how it works. Reading assembly shouldn't be too hard, even if you're just starting, but writing assembly that works (and plays nice with C code; and is efficient) will require some effort. While you certainly need the reference documents and maybe tutorials, the best start is probably reading the code that the compiler generates. Add -save-temps to the CFLAGS in the makefile and you should get a number of .s files with the code of your C functions. Take a look at some of your own C functions and see if you can understand the assembly version of it. You'll probably want to do this in ARM code (use .arm.c files to compile to ARM) since thumb assembly can't be somewhat ugly.

#169384 - Tommmie - Tue Jul 07, 2009 8:39 pm

thanks, that is indeed a very good way to learn! i will start with some simple functions and look if understand them. thanks everyone, i'm going to learn asm:)

edit: ok did my first comment on an asm function.
in c the function was like this:

Code:
int substract(int first, int second){
return(first-second);
}


and in asm it was this, is the comment right?

Code:
rsb   r0, r1, r0 @ r0 is the destination for the answor, r1 contains the value of first and r0 contains the value of second

#169385 - Mighty Max - Tue Jul 07, 2009 11:09 pm

The parameters: r0 ist the first, r1 the second, r2 the third, r3 the forth, others go on stack on a function call.
On return r0 is the return value.

For the instruction here: RSB is a reverse sub
RSB Rd,Rn,Rm means Rd := Rm - Rn
while
SUB Rd,Rn,Rm would mean Rd := Rn - Rm
_________________
GBAMP Multiboot

#169390 - Tommmie - Wed Jul 08, 2009 7:27 am

but what's the advantage of a rsb?

#169391 - Ruben - Wed Jul 08, 2009 7:40 am

The advantage of RSB is that you can scale the other register, like this...

Code:
rsb r0, r0, r1, asr #16 @ r0 = (r1>>16) - r0
sub r0, r0, r1, asr #16 @ r0 = r0 - (r1>>16)


I think a SUB would've been better, but then again, compilers tend to do that a lot: muck up -- EDIT: Read as "show off" ;)

#169392 - Tommmie - Wed Jul 08, 2009 7:53 am

ok, i'm confused now: what do you mean with scale? and with sub you do rn-operand2 and with rsv operand2-rn. but why should you use rsb then? for imitating rsb with sub you could just exhange the values in the register. the value of r0 would go in r1 and the value of r1 in r0 and you could also do a rsb with sub. or am i compeltely wrong?

#169393 - Ruben - Wed Jul 08, 2009 8:26 am

No, you are correct: By scaling, I meant using the barrel shifter which allows you to shift or rotate a certain register by n bits.

For now, you shouldn't really worry about it, but when you'll need it, you'll know. For example, if I had to do something like this...
Code:
int foobar = (foo>>16) - bar;

The most obvious way would be to do this...
Code:
@ Assume r0 is foobar, r1 is foo and r2 is bar
mov r1, r1, asr #16 @ foo>>16
sub r0, r1, r2      @ (foo>>16) - bar

However, with the barrel shifter this turns into 1 instruction...
Code:
@ Assume the above
rsb r0, r2, r1, asr #16 @ (foo>>16) - bar

#169394 - Tommmie - Wed Jul 08, 2009 9:20 am

thanks got it! is it also more efficient or not?

#169396 - Ruben - Wed Jul 08, 2009 9:56 am

Well, sub/rsb both have the same execution time (that is, 1 cycle), so they have no advantage over each other, other than the shift position. It really depends on what you're doing, really. Personally, when I encounter something like "sub r0, r1, r0" I tend to make it "rsb r0, r0, r1" to make it cleaner and the opposite for "rsb r0, r1, r0", but that's just me.

#169397 - Tommmie - Wed Jul 08, 2009 11:20 am

ok, yes that's indeed cleaner. thanks, i've just coded another C function looked into the asm code and i got it!

btw. the compiler is fan of rsb instead of sub:)

#169398 - Ruben - Wed Jul 08, 2009 11:54 am

Cool. When you feel confident enough, try compiling some "stronger" functions, and once you get the hang of it, try reading other people's "hand-written" ASM. Cearn's ASM is a bit.. err.. advanced, even for me, to the point where it takes me a bit of time to get what the HELL it's doing, but when you feel confident enough, feel free to scan it. Another thing you may wanna look at it labels (that is, ".Lfoo"), other directives (such as ".section", ".thumb" ".thumb_func" ".align" etc) and eventually, macros of you have functions that repeat segments of code with only slightly different values/registers/whatever.