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 > Newbie question

#11852 - Ribe - Tue Oct 21, 2003 6:56 pm

I just started out with arm asm, and I instantly encountered a problem (surprise, surprise).
For some reason, i can't do an ADD or SUB using two registers and a number, ( ADD r1,r2, value) , or use CMP r,value ... It works just fine when I use registers ( ADD, r1, r2, r3), but I can't imagine it's supposed to be like this? I'm using the AS compiler.

#11853 - poslundc - Tue Oct 21, 2003 7:07 pm

Constants in assembly language can only have eight significant bits. That is to say, 245 (0xF5) would be valid, and so would 62,720 (0xF500), but 62,721 (0xF501) would be invalid, since it cannot be represented by a simple rotation of an eight-bit constant.

To get more than eight significant bits, you need to either manually form your constant in a register (such as by orr-ing the bits together), or load the constant from somewhere local to your code in memory using ldr.

I'm not sure (insofar as I've never had the occasion to try it), but I believe if you prefix your constant with an equal sign (eg. =62,721), then put the directive ".pool" at the end of your code, then the compiler will intelligently determine if it's quicker to just move your constant in or load it from memory (in which case it will be stored at the location .pool). Someone may have to correct me on this, though.

Dan.

#11860 - jd - Wed Oct 22, 2003 12:19 am

Another possible cause of the problem is that you've forgotten to put a "#" in front of the constant - e.g. "add r1,r2,#5"

To the best of my knowledge, you can't do "add r1,r2,=62721" - you'd have to do this instead:

Code:

ldr r3,=62721
add r1,r2,r3


I'm also pretty sure that the the compiler won't automatically do a mov instead in the cases where it's possible to do so. It's a good idea to get in the habit of only using "ldr reg,=value" when you absolutely have to.

(By the way, all of this assumes you're writing ARM code. Thumb has many extra restrictions.)

#11861 - torne - Wed Oct 22, 2003 12:41 am

jd wrote:
To the best of my knowledge, you can't do "add r1,r2,=62721" - you'd have to do this instead:


No, you can't. =)

jd wrote:
I'm also pretty sure that the the compiler won't automatically do a mov instead in the cases where it's possible to do so. It's a good idea to get in the habit of only using "ldr reg,=value" when you absolutely have to.


Yes, it will work out if it can use mov, for both ARM and Thumb. If you want a more scary macro which can work out when it's faster to do a combination of mov/shl/add instead of an ldr for Thumb (because the Thumb mov instruction is less powerful as it has no shifted) then try my very old thread http://forum.gbadev.org/viewtopic.php?t=154 which has said macro. If you have nondefault wait state settings you will want to modify it in ways which will be obvious if you are, uhm, me. No, actually, not obvious to me either. Damn.

It only applies to ROM; EWRAM access times are probably too low for shift-and-add to be useful in comparison.