NO$GBA hates the "push sp" instruction, libgcc uses it

Posts that don't fit in the other forums
Post Reply
Dwedit
Posts: 43
Joined: Sun Jan 06, 2008 4:06 am

NO$GBA hates the "push sp" instruction, libgcc uses it

Post by Dwedit » Fri Jul 29, 2011 7:46 am

It appears that NO$GBA does not emulate the push (stmfd) instruction correctly when SP is one of the registers which is pushed onto the stack.

Unfortunately, libgcc uses this instruction a few times:
_aeabi_ldivmod
_aeabi_uldivmod
_arm_cmpdf2
_arm_cmpsf2
libunwind

For example, in _aeabi_ldivmod:

Code: Select all

  2c:	e92d6000 	push	{sp, lr}
  30:	ebfffffe 	bl	0 <__gnu_ldivmod_helper>
On this line, when NO$GBA attempts to push the stack pointer onto the stack, it instead pushes a value which is 8 less than it should be.

In the ldivmod helper:

Code: Select all

  20:	9a08      	ldr	r2, [sp, #32]
  22:	1a1b      	subs	r3, r3, r0
  24:	418c      	sbcs	r4, r1
  26:	6013      	str	r3, [r2, #0]
  28:	6054      	str	r4, [r2, #4]
It reads the old stack pointer from the stack, then writes two values into memory.
In NO$GBA, this overwrites the return address and it jumps to something invalid (I saw it return to address 00000000).

So is it possible to get rid of the "Store the stack pointer onto the stack" thing that libgcc is using, so code that divides 64-bit integers will work correctly on NO$GBA?

Dwedit
Posts: 43
Joined: Sun Jan 06, 2008 4:06 am

Re: NO$GBA hates the "push sp" instruction, LibGCC uses it

Post by Dwedit » Fri Jul 29, 2011 8:02 am

To clarify, this post concerns the libgcc THUMB library that is included in devkitARM, specifically the file "C:\devkitpro\devkitARM\lib\gcc\arm-eabi\4.5.1\thumb\libgcc.a".
edit: I have just confirmed that the problem also happens in version 4.6.1 as well.

WinterMute
Site Admin
Posts: 1986
Joined: Tue Aug 09, 2005 3:21 am
Location: UK
Contact:

Re: NO$GBA hates the "push sp" instruction, LibGCC uses it

Post by WinterMute » Fri Jul 29, 2011 11:53 am

Why are you reporting no$gba bugs here?

There are absolutely no circumstances under which I will ever be convinced to modify the toolchain to work around bugs in emulators. If it works on the target hardware there is no issue.
Help keep devkitPro toolchains free, Donate today

Personal Blog

HeavyDude
Posts: 14
Joined: Sun Oct 31, 2010 12:55 pm

Re: NO$GBA hates the "push sp" instruction, LibGCC uses it

Post by HeavyDude » Sat Jul 30, 2011 1:00 pm

Surely you should be reporting this to the authors of NO$GBA. If development has stopped then thats tough luck.

Use another emulator (or use a DS... just a thought).

Dwedit
Posts: 43
Joined: Sun Jan 06, 2008 4:06 am

Re: NO$GBA hates the "push sp" instruction, LibGCC uses it

Post by Dwedit » Sat Jul 30, 2011 5:48 pm

Development stopped in Feb 2008, he even stopped shipping the product to people who wanted to pay for it, and disappeared from the face of the internet. Rumor has it that Nintendo bought it out and turned it into their debugger, but that's just a rumor.
And if I wanted to hack the EXE to try to fix bugs, there's copy protection in the way.
It's a very nice debugger because it just works well, has data breakpoints, shows symbols, etc.
Whereas Insight + VisualBoyAdvance just doesn't work at all. Insight refuses to show code that isn't in C files, can't connect to VBA, etc.

I was also looking at why __aeabi_ldivmod and __gnu_ldivmod_helper are two separate functions in the first place. Normally, since __gnu_ldivmod_helper is only called by __aeabi_ldivmod, I'd expect it to be inlined. But it was not inlined, and it appears that the reason is just to have it return early when dividing by zero to avoid a bunch of stack pushes.

Dwedit
Posts: 43
Joined: Sun Jan 06, 2008 4:06 am

Re: NO$GBA hates the "push sp" instruction, libgcc uses it

Post by Dwedit » Sat Oct 01, 2011 10:32 pm

I have confirmed that including this ASM code makes 64-bit division compatible with NO$GBA:

Code: Select all

 .text
 .align
 .pool
 
 .global __aeabi_ldivmod
 .global __aeabi_uldivmod

__aeabi_ldivmod:
	cmp	r3, #0
	cmpeq	r2, #0
	bne	0f
	cmp	r1, #0
	cmpeq	r0, #0
	movlt	r1, #-2147483648	@ 0x80000000
	movlt	r0, #0
	mvngt	r1, #-2147483648	@ 0x80000000
	mvngt	r0, #0
	b	__aeabi_ldiv0
0:
	sub	sp, sp, #8
	mov r12,sp
	push	{r12, lr}
	bl	__gnu_ldivmod_helper
	ldr	lr, [sp, #4]
	add	sp, sp, #8
	pop	{r2, r3}
	bx	lr

__aeabi_uldivmod:
	cmp	r3, #0
	cmpeq	r2, #0
	bne	0f
	cmp	r1, #0
	cmpeq	r0, #0
	mvnne	r1, #0
	mvnne	r0, #0
	b	__aeabi_ldiv0
0:
	sub	sp, sp, #8
	mov r12,sp
	push	{r12, lr}
	bl	__gnu_uldivmod_helper
	ldr	lr, [sp, #4]
	add	sp, sp, #8
	pop	{r2, r3}
	bx	lr

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest