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 > Strange compile bug using blgt?

#167525 - headspin - Tue Mar 17, 2009 1:22 pm

I've stumbled upon a strange bug that I can't figure out. I have a "C" file that contains a function that I call from an asm file.

I needed to jump to this function if a value is greater than another. So I use the blgt opcode but it jumps to the wrong address. If I change the blgt to a bl it wont crash. Very strange. So for a comparison I placed the two instructions next to each other like so.

Code:
blgt resetFileStream
bl resetFileStream


And when I compile it looks like this

Code:
CB00436E   blgt   20125A0h
FAFFFF7B   blx   20015D8h


WTF? Why the different addresses?
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game

#167536 - Miked0801 - Tue Mar 17, 2009 5:40 pm

blx allows swapping to arm/thumb. Are you trying to call an arm routine from thumb or visa versa?

<Pulls out ARM reference>

Interesting. BL doesn't exist as an ARM instruction, only BLX. Therefore the conversion. Also, there are 2 versions of BLX, one that takes a 24-bit signed immediate value, but doesn't allow conditional execution and a second version that allows condition execution but requires a register to hold the destination with the low bit of the address selecting arm or thumb swap.

There is also bx which allows acts like the 2nd version of blx (register holding address.)

Now in Thumb land, blgt and blxgt do exist and work like you think. Perhaps you are in ARM assembly and are forcing the compiler to make a thumb op-code?

Just some thoughts. Either way, load your destination into a register and it should work either way.

#167538 - headspin - Tue Mar 17, 2009 6:03 pm

Placing the blgt in thumb I get "Error: Thumb does not support conditional execution".

The .s file is arm but the c file is aparently thumb. Is this some sort of optimization the compiler does? Is there a compiler directive in c to force it to compile as arm?

Can you please give an example of "load your destination into a register and it should work either way."? Not sure what you mean by that.
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game

#167539 - Mighty Max - Tue Mar 17, 2009 6:05 pm

Miked0801 wrote:
BL doesn't exist as an ARM instruction


It does, it's B with bit l set.

The Quick Reference lists it as available on all versions.
http://www.simplemachines.it/doc/QRC0001H_rvct_v2.1_arm.pdf
_________________
GBAMP Multiboot

#167544 - Miked0801 - Tue Mar 17, 2009 9:40 pm

Yep, just found B,BL on the same page with each other instead of next to BLX where I would expect it. My bad.

But if you are calling thumb to arm and back, you need the blx versions of the opcode. Just load a register with the address and blxgt (or blgtx, not sure which) instead.

And yes, you can tell the compiler to compile ARM code with a command line switch. We also have a pragma/section command to do it within a source file. Yours probably does as well which would allow branching without exchange.

#167545 - Mighty Max - Tue Mar 17, 2009 10:41 pm

Miked0801 wrote:
blxgt (or blgtx, not sure which) instead.


This is the source of the problem. There is no condition code available to blx. (The condition part of the BLX is allways 0xF iirc)
It needs to BLcc to a BX
_________________
GBAMP Multiboot

#167552 - headspin - Wed Mar 18, 2009 4:51 am

Yep I get "Error: selected processor does not support `blxgt resetFileStream'"

So I still don't understand why bl from arm to thumb works but blgt doesn't. Really frusting the hell out of me.

Can someone please give an example of the pragma/section I need to place in the C file to make it arm?
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game

#167555 - Cearn - Wed Mar 18, 2009 10:55 am

headspin wrote:
So I still don't understand why bl from arm to thumb works but blgt doesn't. Really frusting the hell out of me.
Actually, BL doesn't work either. What you write in assembly isn't quite identical to the eventual binary. For example, a LDR R0,=255 is turned into a simple MOV because the assembler recognizes it's allowed and faster. And a cross-code BL is turned into a BLX by the linker because BL can't do a cross-code branch but BX and BLX can. This is how interworking is implemented.

A BL is converted into a BLX; but a BLGT can't be changed into a BLXGT because, as you've seen, BLX doesn't allow conditionals.

headspin wrote:
Can someone please give an example of the pragma/section I need to place in the C file to make it arm?
To compile as ARM, give it an .arm.c extension; the template makefiles will take care of the rest. The magic compiler option is -marm (instead of -mthumb), possibly augmented by -mlong-calls -mthumb-interworking .

#167565 - Miked0801 - Wed Mar 18, 2009 6:24 pm

Code:

    ldr     r0,functionAddressHere
    blxgt  r0


Compiles and runs in ARM. You need to add 1 to the address if it is a jump to thumb code.

#167569 - Mighty Max - Wed Mar 18, 2009 6:41 pm

Miked0801 wrote:
Code:

    ldr     r0,functionAddressHere
    blxgt  r0


Compiles and runs in ARM.


Can you check the actual produced opcodes?

Quote:

You need to add 1 to the address if it is a jump to thumb code.


functionAddresssHere will allready have that bit set (if retrieved from label). Manually adding 1 will produce severe problems. You can orr bit0 instead of increasing if you want it to work with both, the thumb corrected and pure address.
_________________
GBAMP Multiboot

#167570 - Miked0801 - Wed Mar 18, 2009 6:56 pm

C Code to test

Code:

#include <nitro/code32.h>
asm void foo()
{
   ldr   r0,=foo2
   blxgt r0
}
#include <nitro/code16.h>
int foo2()
{
   int i = 0;
   i++;

   return i;
}


Assembler output:
Code:

foo:
0xe59f0000    ldr r0,[pc]
0xc12fff30    blxgt r0
0x02066341    <DATA> 0x02066341

foo2:
opcodes...


And you are right, the label was already had the low bit set without need of manual intervention.

#167572 - Mighty Max - Wed Mar 18, 2009 7:12 pm

Ah yes ok, only that blx <address> was unconditioned, not the blx <reg>
Wrong thing remembered by me.
_________________
GBAMP Multiboot

#167596 - headspin - Thu Mar 19, 2009 4:18 pm

Miked0801 wrote:
Code:

    ldr     r0,functionAddressHere
    blxgt  r0


Compiles and runs in ARM. You need to add 1 to the address if it is a jump to thumb code.


I tried that and get "Error: selected processor does not support `blxgt r0'". At the top of the file I have defined .arm so it should be compiled as arm.

Also I tried adding .arm.c to the end of the "C" file but now I seem to have alignment issues. I tried adding "#pragma align 4" to the top of the file but I get "warning: ignoring #pragma align".

I can't seem to crack this one!
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game

#167598 - Mighty Max - Thu Mar 19, 2009 5:31 pm

its only available on v5 Architecture (and up), so not on the arm7 if you are trying it there (arm7 is v4)
_________________
GBAMP Multiboot

#167599 - headspin - Thu Mar 19, 2009 5:33 pm

Mighty Max wrote:
its only available on v5 Architecture (and up), so not on the arm7 if you are trying it there (arm7 is v4)


I'm compiling this on the arm9 (in my makefile I have "-march=armv5te -mtune=arm946e-s" CFLAGS)
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game

#167607 - Cearn - Thu Mar 19, 2009 8:03 pm

headspin wrote:

Also I tried adding .arm.c to the end of the "C" file but now I seem to have alignment issues. I tried adding "#pragma align 4" to the top of the file but I get "warning: ignoring #pragma align".

AFAIK, pragmas are rather compiler specific. For GCC, the compiler magic for alignment is done with attributes, specifically __attribute__((align(n) )). Or __attribute__((aligned(n) )), I always forget which. Fortunately there should be a macro for it as well: try adding ALIGN(4) after the definition.

What is causing the alignment error anyway?

headspin wrote:
Mighty Max wrote:

its only available on v5 Architecture (and up), so not on the arm7 if you are trying it there (arm7 is v4)


I'm compiling this on the arm9 (in my makefile I have "-march=armv5te -mtune=arm946e-s" CFLAGS)
What about ASFLAGS? Since this is assembly, that's where you should be looking.