Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


We're also offering banner ads on our site from just $5! 1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


- - - - -

Angelscript on Raspberry Pi


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
131 replies to this topic

#1 Tzarls   Members   -  Reputation: 891

Like
1Likes
Like

Posted 09 November 2012 - 07:31 PM

Hi. I´ve been trying to build Angelscript on a Raspberry Pi computer (ARM processor). I made some modifications to the makefile and I´ve got mixed results.

First, after the

...
else ifeq($(TARGERPLATFORM), android)
	OBJ += $(OBJDIR)/as_callfunc_arm_gcc.o

I added:

else
	OBJ += $(OBJDIR)/as_callfunc_arm_gcc.o


Since the RPi is ARM based, and since I´m using gcc, this looked like the right thing to do.
I also had to add -DAS_NO_THREADS to avoid getting some "unreferences".

The Tutorial and Game examples build fine with this setup, but in the tutorial project I´ve found some problems. When running it, the program outputs this:

---
Received: 1000, 1000
System has been running for 1000 seconds.
---
The script function returned: 8.53973

So as you can see, the received values are wrong. (Interestingly enough, the value returned at the end is correct).

I have the same problem with an application I made. Everything seems to be working fine as long as I use ints or string within my scripts, but as soon as I use floats or doubles the values get corrupted. (I haven´t tested the game project enough, BTW).

If I build the library with -DAS_MAX_PORTABILITY then the tutorial project build ok and works as expected:

---
Received: 3.14159, 2.71828
System has been running for 3.89004e+06 seconds.
---
The script function returned: 8.53973



Any ideas on what could be the problem or what to look for in order to find a solution?

Thanks!

Edited by Tzarls, 09 November 2012 - 07:32 PM.


Sponsor:

#2 Andreas Jonsson   Moderators   -  Reputation: 3415

Like
0Likes
Like

Posted 10 November 2012 - 02:55 PM

I'd wager this is the same problem that has been reported for Linux with armel. It's quite possible that RPi uses the same ABI as armel Linux.

The thing is that the ABI is slightly different from that used by iOS, Android, and Windows Phone. It would be necessary to make changes to the as_callfunc_arm_gcc code to support this too.

Do you have any documentation that describes the ABI used by RPi? Or else try to disassemble a function that returns a float value and another that returns an int value so we can examine the difference.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

#3 Tzarls   Members   -  Reputation: 891

Like
0Likes
Like

Posted 10 November 2012 - 03:41 PM

The RPi is using the armhf ABI. I haven´t found the docs yet but I found some posts in soe other forum stating that when passing values around, ints are passed using int registers and floats are passed using float registers.Does it make any sense?

I´ll check if I can get the ABI documentation.

#4 Andreas Jonsson   Moderators   -  Reputation: 3415

Like
0Likes
Like

Posted 11 November 2012 - 06:15 AM

This is common for x86 ABIs, but I'm not sure the ARM has separate registers for int and floats.

Seeing the disassembly of the functions would be helpful. Something simple, for example:

int func1()
{
   return 42;
}

float func2()
{
   return 3.141592f;
}

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

#5 Tzarls   Members   -  Reputation: 891

Like
0Likes
Like

Posted 12 November 2012 - 12:29 AM

Ok. I made this little program:

#include <iostream>
void receivesFloat (float f)
{
	std::cout << "Received " << f <<".\n";
}
void receivesInt(int i)
{
	std::cout <<"Received " << i <<".\n";
}
float returnsFloat(void)
{
	return 17.65f;
}
int returnsInt(void)
{
	return 7;
}
int main()
{
	receivesFloat(3.14);
	receivesInt(1138);
	std::cout << "Funcion returned " << returnsFloat() <<".\n";
	std::cout << "Funcion returned " << returnsInt() <<".\n";
	return 0;
}

Placed some breakpoints in main() and in every one of the functions to get the disassembly - is that correct? I got this:

main:


0x8738 push {r3, r4, r11, lr}
0x873c add r11, sp, #12
0x8740 vldr s0, [pc, #132] ; 0x87cc <main()+148>
0x8744 bl 0x8658 <receivesFloat(float)>
0x8748 ldr r0, [pc, #128] ; 0x87d0 <main()+152>
0x874c bl 0x86a8 <receivesInt(int)>
0x8750 ldr r0, [pc, #124] ; 0x87d4 <main()+156>
0x8754 ldr r1, [pc, #124] ; 0x87d8 <main()+160>
0x8758 bl 0x8588 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x875c mov r3, r0
0x8760 mov r4, r3
0x8764 bl 0x86f8 <returnsFloat()>
0x8768 vmov.f32 s15, s0
0x876c mov r0, r4
0x8770 vmov.f32 s0, s15
0x8774 bl 0x85a0 <std::ostream::operator<<(float)>
0x8778 mov r3, r0
0x877c mov r0, r3
0x8780 ldr r1, [pc, #84] ; 0x87dc <main()+164>
0x8784 bl 0x8588 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8788 ldr r0, [pc, #68] ; 0x87d4 <main()+156>
0x878c ldr r1, [pc, #68] ; 0x87d8 <main()+160>
0x8790 bl 0x8588 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8794 mov r3, r0
0x8798 mov r4, r3
0x879c bl 0x871c <returnsInt()>
0x87a0 mov r3, r0
0x87a4 mov r0, r4
0x87a8 mov r1, r3
0x87ac bl 0x8540 <std::ostream::operator<<(int)>
0x87b0 mov r3, r0
0x87b4 mov r0, r3
0x87b8 ldr r1, [pc, #28] ; 0x87dc <main()+164>
0x87bc bl 0x8588 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x87c0 mov r3, #0
0x87c4 mov r0, r3
0x87c8 pop {r3, r4, r11, pc}
0x87cc submi pc, r8, r3, asr #11
0x87d0 andeq r0, r0, r2, ror r4
0x87d4 andeq r0, r1, r0, lsr #21
0x87d8 andeq r8, r0, r0, ror #17
0x87dc ldrdeq r8, [r0], -r12

receivesFloat:


0x8658 push {r11, lr}
0x865c add r11, sp, #4
0x8660 sub sp, sp, #8
0x8664 vstr s0, [r11, #-8]
0x8668 ldr r0, [pc, #44] ; 0x869c <receivesFloat(float)+68>
0x866c ldr r1, [pc, #44] ; 0x86a0 <receivesFloat(float)+72>
0x8670 bl 0x8588 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8674 mov r3, r0
0x8678 mov r0, r3
0x867c vldr s0, [r11, #-8]
0x8680 bl 0x85a0 <std::ostream::operator<<(float)>
0x8684 mov r3, r0
0x8688 mov r0, r3
0x868c ldr r1, [pc, #16] ; 0x86a4 <receivesFloat(float)+76>
0x8690 bl 0x8588 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8694 sub sp, r11, #4
0x8698 pop {r11, pc}
0x869c andeq r0, r1, r0, lsr #21
0x86a0 ldrdeq r8, [r0], -r0
0x86a4 ldrdeq r8, [r0], -r12

receivesInt:


0x86a8 push {r11, lr}
0x86ac add r11, sp, #4
0x86b0 sub sp, sp, #8
0x86b4 str r0, [r11, #-8]
0x86b8 ldr r0, [pc, #44] ; 0x86ec <receivesInt(int)+68>
0x86bc ldr r1, [pc, #44] ; 0x86f0 <receivesInt(int)+72>
0x86c0 bl 0x8588 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x86c4 mov r3, r0
0x86c8 mov r0, r3
0x86cc ldr r1, [r11, #-8]
0x86d0 bl 0x8540 <std::ostream::operator<<(int)>
0x86d4 mov r3, r0
0x86d8 mov r0, r3
0x86dc ldr r1, [pc, #16] ; 0x86f4 <receivesInt(int)+76>
0x86e0 bl 0x8588 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x86e4 sub sp, r11, #4
0x86e8 pop {r11, pc}
0x86ec andeq r0, r1, r0, lsr #21
0x86f0 ldrdeq r8, [r0], -r0
0x86f4 ldrdeq r8, [r0], -r12

returnsFloat:


0x86f8 push {r11}  ; (str r11, [sp, #-4]!)
0x86fc add r11, sp, #0
0x8700 ldr r3, [pc, #16] ; 0x8718 <returnsFloat()+32>
0x8704 vmov s15, r3
0x8708 vmov.f32 s0, s15
0x870c add sp, r11, #0
0x8710 pop {r11}
0x8714 bx lr
0x8718 orrmi r3, sp, r3, lsr r3

returnsInt:


0x871c push {r11}  ; (str r11, [sp, #-4]!)
0x8720 add r11, sp, #0
0x8724 mov r3, #7
0x8728 mov r0, r3
0x872c add sp, r11, #0
0x8730 pop {r11}
0x8734 bx lr

Let me know if this is right and if I can do anything else to help.

Edited by Tzarls, 12 November 2012 - 12:31 AM.


#6 Andreas Jonsson   Moderators   -  Reputation: 3415

Like
0Likes
Like

Posted 12 November 2012 - 08:12 AM

Well, it's clear from the disassemblies that the ABI does indeed pass the float type in different registers.

For the int type, the register r0 is used both for passing the value are argument and returning the value. For the float type, the register s0 is used instead.

Based on this knowledge the code in the as_callfunc_arm.cpp and as_callfunc_arm_gcc.S needs to be modified to properly handle the float and double types with this ABI.

The function CallSystemFunctionNative() needs to be updated to prepare the arguments before calling the assembler routines. Either the arguments needs to be separated in two separate arrays, one for integers and one for floats, or the arguments can be kept as is but another array is created that identifies which of the arguments are floats. Then the assembler routines needs to be updated to load the registers correctly based on the arrays.

Before deciding how to implement the management of the argument you should identify how mixed arguments are handled in the ABI. For example, let's say you have a function like this:

void func(int a, float b, int c, float d) {}

We already know a will be placed into r0. But where does the other arguments go? There are two options that I believe are the most probable.

a -> r0, b -> s0, c -> r1, d -> s1

or

a -> r0, b -> s1, c -> r2, d -> s3

It would also be good to know how doubles and int64s are handled. On some platforms they take up 2 registers, and always aligned to an even numbered register, which would mean that you may have to handle skipping some registers in order to align the 64bit arguments.


Unfortunately I will not be able to do the coding myself, as without having the capability to test the code it would be extremely difficult to get it right. If you have time to invest in this should be able to get it to work on your own with a few days of work. It will be a bit of an investigative work to understand how the ABI works, but it's not so difficult if you have the capability to debug and disassemble.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

#7 Tzarls   Members   -  Reputation: 891

Like
0Likes
Like

Posted 12 November 2012 - 10:54 AM

It will be a bit of an investigative work to understand how the ABI works, but it's not so difficult if you have the capability to debug and disassemble.


I can debug and disassemble. The poblem is that I can´t understand what I get after disassembling! But I guess it won´t hurt to give it a try... unless you agree to access my RPi online using VNC (which is the way I actually work . my RPi is sitting at home and I connect to it every time I get some spare time). Because with me doing it, it´s probable that by the time I get something barely usable, you would have already release Angelscript 5 with some clever routines that auto detect ABI and handles appropriately!Posted Image

#8 Tzarls   Members   -  Reputation: 891

Like
0Likes
Like

Posted 12 November 2012 - 11:43 AM

I think I´m getting to understand this a little better:

New code, to check mixed values and doubles (forgot int64, will check later):

#include <iostream>
void receivesDouble (double d)
{
	std::cout << "Received " << d <<".\n";
}
void receivesFloat (float f)
{
	std::cout << "Received " << f <<".\n";
}
void receivesInt(int i)
{
	std::cout << "Received " << i <<".\n";
}
void receivesMixed(int a, float b, int c, double d)
{
	std::cout << "Received " << a << ".\n";
	std::cout << "Received " << b << ".\n";
	std::cout << "Received " << c << ".\n";
	std::cout << "Received " << d << ".\n";
}
float returnsFloat(void)
{
	return 17.65f;
}
int returnsInt(void)
{
	return 7;
}
int main()
{
	receivesDouble(12.3456789);
	receivesFloat(3.14f);
	receivesInt(1138);
	receivesMixed(1, 2.2f, 3, 4.456789);
	std::cout << "Funcion returned " << returnsFloat() <<".\n";
	std::cout << "Funcion returned " << returnsInt() <<".\n";
	return 0;
}

DIsassembly for main():

0x88a8 push {r3, r4, r11, lr}
0x88ac add r11, sp, #12
0x88b0 vldr d0, [pc, #160] ; 0x8958 <main()+176>
0x88b4 bl 0x8698 <receivesDouble(double)>
0x88b8 vldr s0, [pc, #168] ; 0x8968 <main()+192>
0x88bc bl 0x86e8 <receivesFloat(float)>
0x88c0 ldr r0, [pc, #168] ; 0x8970 <main()+200>
0x88c4 bl 0x8738 <receivesInt(int)>
0x88c8 mov r0, #1
0x88cc vldr s0, [pc, #152] ; 0x896c <main()+196>
0x88d0 mov r1, #3
0x88d4 vldr d1, [pc, #132] ; 0x8960 <main()+184>
0x88d8 bl 0x8788 <receivesMixed(int, float, int, double)>
0x88dc ldr r0, [pc, #144] ; 0x8974 <main()+204>
0x88e0 ldr r1, [pc, #144] ; 0x8978 <main()+208>
0x88e4 bl 0x85c0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x88e8 mov r3, r0
0x88ec mov r4, r3
0x88f0 bl 0x8868 <returnsFloat()>
0x88f4 vmov.f32 s15, s0
0x88f8 mov r0, r4
0x88fc vmov.f32 s0, s15
0x8900 bl 0x85d8 <std::ostream::operator<<(float)>
0x8904 mov r3, r0
0x8908 mov r0, r3
0x890c ldr r1, [pc, #104] ; 0x897c <main()+212>
0x8910 bl 0x85c0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8914 ldr r0, [pc, #88] ; 0x8974 <main()+204>
0x8918 ldr r1, [pc, #88] ; 0x8978 <main()+208>
0x891c bl 0x85c0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8920 mov r3, r0
0x8924 mov r4, r3
0x8928 bl 0x888c <returnsInt()>
0x892c mov r3, r0
0x8930 mov r0, r4
0x8934 mov r1, r3
0x8938 bl 0x8578 <std::ostream::operator<<(int)>
0x893c mov r3, r0
0x8940 mov r0, r3
0x8944 ldr r1, [pc, #48] ; 0x897c <main()+212>
0x8948 bl 0x85c0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x894c mov r3, #0
0x8950 mov r0, r3
0x8954 pop {r3, r4, r11, pc}
0x8958 teqle r4, #679477248 ; 0x28800000
0x895c strdmi r11, [r8], -r12 ; <UNPREDICTABLE>
0x8960 cdpvc 0, 14, cr11, cr0, cr15, {5}
0x8964 andsmi sp, r1, r0, asr #7
0x8968 submi pc, r8, r3, asr #11
0x896c andmi r12, r12, sp, asr #25
0x8970 andeq r0, r0, r2, ror r4
0x8974 andeq r0, r1, r0, ror r12
0x8978 andeq r8, r0, r0, lsl #21
0x897c andeq r8, r0, r12, ror r10

Disassembly for receivesDouble(...):

0x8698 push {r11, lr}
0x869c add r11, sp, #4
0x86a0 sub sp, sp, #8
0x86a4 vstr d0, [r11, #-12]
0x86a8 ldr r0, [pc, #44] ; 0x86dc <receivesDouble(double)+68>
0x86ac ldr r1, [pc, #44] ; 0x86e0 <receivesDouble(double)+72>
0x86b0 bl 0x85c0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x86b4 mov r3, r0
0x86b8 mov r0, r3
0x86bc vldr d0, [r11, #-12]
0x86c0 bl 0x856c <std::ostream::operator<<(double)>
0x86c4 mov r3, r0
0x86c8 mov r0, r3
0x86cc ldr r1, [pc, #16] ; 0x86e4 <receivesDouble(double)+76>
0x86d0 bl 0x85c0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x86d4 sub sp, r11, #4
0x86d8 pop {r11, pc}
0x86dc andeq r0, r1, r0, ror r12
0x86e0 andeq r8, r0, r0, ror r10
0x86e4 andeq r8, r0, r12, ror r10

Disassembly for receivesMixed(...):

0x8788 push {r11, lr}
0x878c add r11, sp, #4
0x8790 sub sp, sp, #24
0x8794 str r0, [r11, #-8]
0x8798 vstr s0, [r11, #-12]
0x879c str r1, [r11, #-16]
0x87a0 vstr d1, [r11, #-28] ; 0xffffffe4
0x87a4 ldr r0, [pc, #176] ; 0x885c <receivesMixed(int, float, int, double)+212>
0x87a8 ldr r1, [pc, #176] ; 0x8860 <receivesMixed(int, float, int, double)+216>
0x87ac bl 0x85c0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x87b0 mov r3, r0
0x87b4 mov r0, r3
0x87b8 ldr r1, [r11, #-8]
0x87bc bl 0x8578 <std::ostream::operator<<(int)>
0x87c0 mov r3, r0
0x87c4 mov r0, r3
0x87c8 ldr r1, [pc, #148] ; 0x8864 <receivesMixed(int, float, int, double)+220>
0x87cc bl 0x85c0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x87d0 ldr r0, [pc, #132] ; 0x885c <receivesMixed(int, float, int, double)+212>
0x87d4 ldr r1, [pc, #132] ; 0x8860 <receivesMixed(int, float, int, double)+216>
0x87d8 bl 0x85c0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x87dc mov r3, r0
0x87e0 mov r0, r3
0x87e4 vldr s0, [r11, #-12]
0x87e8 bl 0x85d8 <std::ostream::operator<<(float)>
0x87ec mov r3, r0
0x87f0 mov r0, r3
0x87f4 ldr r1, [pc, #104] ; 0x8864 <receivesMixed(int, float, int, double)+220>
0x87f8 bl 0x85c0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x87fc ldr r0, [pc, #88] ; 0x885c <receivesMixed(int, float, int, double)+212>
0x8800 ldr r1, [pc, #88] ; 0x8860 <receivesMixed(int, float, int, double)+216>
0x8804 bl 0x85c0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8808 mov r3, r0
0x880c mov r0, r3
0x8810 ldr r1, [r11, #-16]
0x8814 bl 0x8578 <std::ostream::operator<<(int)>
0x8818 mov r3, r0
0x881c mov r0, r3
0x8820 ldr r1, [pc, #60] ; 0x8864 <receivesMixed(int, float, int, double)+220>
0x8824 bl 0x85c0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8828 ldr r0, [pc, #44] ; 0x885c <receivesMixed(int, float, int, double)+212>
0x882c ldr r1, [pc, #44] ; 0x8860 <receivesMixed(int, float, int, double)+216>
0x8830 bl 0x85c0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8834 mov r3, r0
0x8838 mov r0, r3
0x883c vldr d0, [r11, #-28] ; 0xffffffe4
0x8840 bl 0x856c <std::ostream::operator<<(double)>
0x8844 mov r3, r0
0x8848 mov r0, r3
0x884c ldr r1, [pc, #16] ; 0x8864 <receivesMixed(int, float, int, double)+220>
0x8850 bl 0x85c0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8854 sub sp, r11, #4
0x8858 pop {r11, pc}
0x885c andeq r0, r1, r0, ror r12
0x8860 andeq r8, r0, r0, ror r10
0x8864 andeq r8, r0, r12, ror r10

By looking at this, would it be correct to say that when passing a double, the value is stored in d0, and when passing mixed (int a, float b, int c, double d), a goes to r0, b to s0, c to r1 and d to d1? (And why d1 and not d0 like with receivesDouble(...) ?) - EDIT: Because according to some tech specs I´ve found, d0 is s0 + s1, and since s0 is already used, we can´t use d0...

Edited by Tzarls, 12 November 2012 - 12:24 PM.


#9 Andreas Jonsson   Moderators   -  Reputation: 3415

Like
0Likes
Like

Posted 12 November 2012 - 02:31 PM

Yes, it would seem that the ABI keeps two distinct arrays, one for floats and one for integers. Integers goes to r0, r1, r2, ..., and floats to s0, s1, s2, ...

If each d, register is in fact two s registers, then it is necessary to consider padding when mixing floats and doubles.

It would be interested to see a receivesMixed2(int a, double b, int c, float d). From what we've seen so far, these arguments should be passed as following: a -> r0, b -> d0, c -> r1, d -> s2. The last goes to s2 because d0 occupies both s0 and s1.

receivesMixed3(float a, double b, float c) should be as following: a -> s0, b -> d1, c -> s4. The last goes to s4, because d1 occupies both s2 and s3. In this case s1 is not used.

Another thing that needs to be checked before the best algorithm can be determined is how many registers that may be used for passing arguments. The iOS and Android ABI only uses 4 registers at most (r0 to r3), the arguments that don't fit into these 4 registers are pushed on the stack.

Edited by Andreas Jonsson, 12 November 2012 - 02:31 PM.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

#10 Tzarls   Members   -  Reputation: 891

Like
0Likes
Like

Posted 12 November 2012 - 05:10 PM

More info - this time I´ve used the examples you gave me and also tried with long long types and a function called receivesLots, which receives 10 doubles, 2 floats and 2 long long.

#include <iostream>
void receivesMixed(int a, double b, int c, float d)
{
    std::cout << "Received " << a << ".\n";
    std::cout << "Received " << b << ".\n";
    std::cout << "Received " << c << ".\n";
    std::cout << "Received " << d << ".\n";
}
void receivesMixed2(float a, double b, float c)
{
    std::cout << "Received " << a << ".\n";
    std::cout << "Received " << b << ".\n";
    std::cout << "Received " << c << ".\n";
}
void receivesLots(double a0, double a1, double a2, double a3, double a4,
				 double a5, double a6, double a7, double a8, double a9,
				 float f0, float f1, long long i0, long long i1)
{
    std::cout << "Received " << a1 << ".\n";
    std::cout << "Received " << a2 << ".\n";
    std::cout << "Received " << a3 << ".\n";
    std::cout << "Received " << a4 << ".\n";
    std::cout << "Received " << a5 << ".\n";
    std::cout << "Received " << a6 << ".\n";
    std::cout << "Received " << a7 << ".\n";
    std::cout << "Received " << a8 << ".\n";
    std::cout << "Received " << a9 << ".\n";
    std::cout << "Received " << f0 << ".\n";
    std::cout << "Received " << f1 << ".\n";
    std::cout << "Received " << i0 << ".\n";
    std::cout << "Received " << i1 << ".\n";
}
int main()
{
    receivesMixed(1, 2.2345678, 3, 4.4f);
    receivesMixed2(1.1f, 2.2345678, 4.4f);
    receivesLots(0.12345, 1.12345, 2.34567, 3.456789, 4.5678901, 5.6789012, 6.78901234, 7.890123456, 8.901234, 9.012345,
				 10.2f, 11.23f, 100, 200);
    return 0;
}

Disassembly for main:

0x8ae4 push {r11, lr}
0x8ae8 add r11, sp, #4
0x8aec sub sp, sp, #24
0x8af0 mov r0, #1
0x8af4 vldr d0, [pc, #132] ; 0x8b80 <main()+156>
0x8af8 mov r1, #3
0x8afc vldr s2, [pc, #212] ; 0x8bd8 <main()+244>
0x8b00 bl 0x86d0 <receivesMixed(int, double, int, float)>
0x8b04 vldr s0, [pc, #208] ; 0x8bdc <main()+248>
0x8b08 vldr d1, [pc, #112] ; 0x8b80 <main()+156>
0x8b0c vldr s1, [pc, #196] ; 0x8bd8 <main()+244>
0x8b10 bl 0x87b0 <receivesMixed2(float, double, float)>
0x8b14 add r3, pc, #108 ; 0x6c
0x8b18 ldrd r2, [r3]
0x8b1c strd r2, [sp]
0x8b20 add r3, pc, #104 ; 0x68
0x8b24 ldrd r2, [r3]
0x8b28 strd r2, [sp, #8]
0x8b2c ldr r3, [pc, #172] ; 0x8be0 <main()+252>
0x8b30 str r3, [sp, #16]
0x8b34 ldr r3, [pc, #168] ; 0x8be4 <main()+256>
0x8b38 str r3, [sp, #20]
0x8b3c vldr d0, [pc, #84] ; 0x8b98 <main()+180>
0x8b40 vldr d1, [pc, #88] ; 0x8ba0 <main()+188>
0x8b44 vldr d2, [pc, #92] ; 0x8ba8 <main()+196>
0x8b48 vldr d3, [pc, #96] ; 0x8bb0 <main()+204>
0x8b4c vldr d4, [pc, #100] ; 0x8bb8 <main()+212>
0x8b50 vldr d5, [pc, #104] ; 0x8bc0 <main()+220>
0x8b54 vldr d6, [pc, #108] ; 0x8bc8 <main()+228>
0x8b58 vldr d7, [pc, #112] ; 0x8bd0 <main()+236>
0x8b5c mov r0, #100 ; 0x64
0x8b60 mov r1, #0
0x8b64 mov r2, #200 ; 0xc8
0x8b68 mov r3, #0
0x8b6c bl 0x8860 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)>
0x8b70 mov r3, #0
0x8b74 mov r0, r3
0x8b78 sub sp, r11, #4
0x8b7c pop {r11, pc}
0x8b80 strne r8, [sp, #-3759]! ; 0xeaf
0x8b84 andmi lr, r1, r5, rrx
0x8b88 bhi 0xffe0e42c
0x8b8c eormi r12, r1, lr, ror #26
0x8b90 ldrbne r8, [r6, #-2506]! ; 0x9ca
0x8b94 eormi r0, r2, r2, asr r6
0x8b98 adcspl pc, r0, r12, ror r2 ; <UNPREDICTABLE>
0x8b9c svccc 0x00bf9a6b
0x8ba0 strlt r0, [r11, #-3880] ; 0xf28
0x8ba4 svccc 0x00f1f9a6
0x8ba8 andge r10, r9, #164, 20 ; 0xa4000
0x8bac andmi r12, r2, lr, ror #7
0x8bb0 stc2l 1, cr6, [r1, #380] ; 0x17c
0x8bb4 andmi r10, r11, r0, lsl #15
0x8bb8 blx 0x1f419c2
0x8bbc andsmi r4, r2, r4, lsl #11
0x8bc0 sub sp, r12, r2, asr r12
0x8bc4 andsmi r11, r6, r1, lsr r7
0x8bc8 ldmible r1, {r0, r8, r9, lr, pc}^
0x8bcc ; <UNDEFINED> instruction: 0x401b27f2
0x8bd0 ldrbhi r11, [r3, #163]! ; 0xa3
0x8bd4 andsmi r8, pc, r12, ror pc ; <UNPREDICTABLE>
0x8bd8 addmi r12, r12, sp, asr #25
0x8bdc svccc 0x008ccccd
0x8be0 teqmi r3, r3, lsr r3
0x8be4 teqmi r3, r4, lsl lr




Disassembly for receivesMixed:

0x86d0 push {r11, lr}
0x86d4 add r11, sp, #4
0x86d8 sub sp, sp, #24
0x86dc str r0, [r11, #-8]
0x86e0 vstr d0, [r11, #-20] ; 0xffffffec
0x86e4 str r1, [r11, #-12]
0x86e8 vstr s2, [r11, #-24] ; 0xffffffe8
0x86ec ldr r0, [pc, #176] ; 0x87a4 <receivesMixed(int, double, int, float)+212>
0x86f0 ldr r1, [pc, #176] ; 0x87a8 <receivesMixed(int, double, int, float)+216>
0x86f4 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x86f8 mov r3, r0
0x86fc mov r0, r3
0x8700 ldr r1, [r11, #-8]
0x8704 bl 0x85a4 <std::ostream::operator<<(int)>
0x8708 mov r3, r0
0x870c mov r0, r3
0x8710 ldr r1, [pc, #148] ; 0x87ac <receivesMixed(int, double, int, float)+220>
0x8714 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8718 ldr r0, [pc, #132] ; 0x87a4 <receivesMixed(int, double, int, float)+212>
0x871c ldr r1, [pc, #132] ; 0x87a8 <receivesMixed(int, double, int, float)+216>
0x8720 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8724 mov r3, r0
0x8728 mov r0, r3
0x872c vldr d0, [r11, #-20] ; 0xffffffec
0x8730 bl 0x8598 <std::ostream::operator<<(double)>
0x8734 mov r3, r0
0x8738 mov r0, r3
0x873c ldr r1, [pc, #104] ; 0x87ac <receivesMixed(int, double, int, float)+220>
0x8740 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8744 ldr r0, [pc, #88] ; 0x87a4 <receivesMixed(int, double, int, float)+212>
0x8748 ldr r1, [pc, #88] ; 0x87a8 <receivesMixed(int, double, int, float)+216>
0x874c bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8750 mov r3, r0
0x8754 mov r0, r3
0x8758 ldr r1, [r11, #-12]
0x875c bl 0x85a4 <std::ostream::operator<<(int)>
0x8760 mov r3, r0
0x8764 mov r0, r3
0x8768 ldr r1, [pc, #60] ; 0x87ac <receivesMixed(int, double, int, float)+220>
0x876c bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8770 ldr r0, [pc, #44] ; 0x87a4 <receivesMixed(int, double, int, float)+212>
0x8774 ldr r1, [pc, #44] ; 0x87a8 <receivesMixed(int, double, int, float)+216>
0x8778 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x877c mov r3, r0
0x8780 mov r0, r3
0x8784 vldr s0, [r11, #-24] ; 0xffffffe8
0x8788 bl 0x8604 <std::ostream::operator<<(float)>
0x878c mov r3, r0
0x8790 mov r0, r3
0x8794 ldr r1, [pc, #16] ; 0x87ac <receivesMixed(int, double, int, float)+220>
0x8798 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x879c sub sp, r11, #4
0x87a0 pop {r11, pc}
0x87a4 andeq r0, r1, r8, lsr #29
0x87a8 ldrdeq r8, [r0], -r8 ; <UNPREDICTABLE>
0x87ac andeq r8, r0, r4, ror #25




Disassembly for receivesMixed2:

0x87b0 push {r11, lr}
0x87b4 add r11, sp, #4
0x87b8 sub sp, sp, #16
0x87bc vstr s0, [r11, #-8]
0x87c0 vstr d1, [r11, #-20] ; 0xffffffec
0x87c4 vstr s1, [r11, #-12]
0x87c8 ldr r0, [pc, #132] ; 0x8854 <receivesMixed2(float, double, float)+164>
0x87cc ldr r1, [pc, #132] ; 0x8858 <receivesMixed2(float, double, float)+168>
0x87d0 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x87d4 mov r3, r0
0x87d8 mov r0, r3
0x87dc vldr s0, [r11, #-8]
0x87e0 bl 0x8604 <std::ostream::operator<<(float)>
0x87e4 mov r3, r0
0x87e8 mov r0, r3
0x87ec ldr r1, [pc, #104] ; 0x885c <receivesMixed2(float, double, float)+172>
0x87f0 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x87f4 ldr r0, [pc, #88] ; 0x8854 <receivesMixed2(float, double, float)+164>
0x87f8 ldr r1, [pc, #88] ; 0x8858 <receivesMixed2(float, double, float)+168>
0x87fc bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8800 mov r3, r0
0x8804 mov r0, r3
0x8808 vldr d0, [r11, #-20] ; 0xffffffec
0x880c bl 0x8598 <std::ostream::operator<<(double)>
0x8810 mov r3, r0
0x8814 mov r0, r3
0x8818 ldr r1, [pc, #60] ; 0x885c <receivesMixed2(float, double, float)+172>
0x881c bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8820 ldr r0, [pc, #44] ; 0x8854 <receivesMixed2(float, double, float)+164>
0x8824 ldr r1, [pc, #44] ; 0x8858 <receivesMixed2(float, double, float)+168>
0x8828 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x882c mov r3, r0
0x8830 mov r0, r3
0x8834 vldr s0, [r11, #-12]
0x8838 bl 0x8604 <std::ostream::operator<<(float)>
0x883c mov r3, r0
0x8840 mov r0, r3
0x8844 ldr r1, [pc, #16] ; 0x885c <receivesMixed2(float, double, float)+172>
0x8848 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x884c sub sp, r11, #4
0x8850 pop {r11, pc}
0x8854 andeq r0, r1, r8, lsr #29
0x8858 ldrdeq r8, [r0], -r8 ; <UNPREDICTABLE>
0x885c andeq r8, r0, r4, ror #25




Disassembly for receivesLots:

0x8860 push {r11, lr}
0x8864 add r11, sp, #4
0x8868 sub sp, sp, #80 ; 0x50
0x886c vstr d0, [r11, #-12]
0x8870 vstr d1, [r11, #-20] ; 0xffffffec
0x8874 vstr d2, [r11, #-28] ; 0xffffffe4
0x8878 vstr d3, [r11, #-36] ; 0xffffffdc
0x887c vstr d4, [r11, #-44] ; 0xffffffd4
0x8880 vstr d5, [r11, #-52] ; 0xffffffcc
0x8884 vstr d6, [r11, #-60] ; 0xffffffc4
0x8888 vstr d7, [r11, #-68] ; 0xffffffbc
0x888c strd r0, [r11, #-76] ; 0xffffffb4
0x8890 strd r2, [r11, #-84] ; 0xffffffac
0x8894 ldr r0, [pc, #572] ; 0x8ad8 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+632>
0x8898 ldr r1, [pc, #572] ; 0x8adc <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+636>
0x889c bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x88a0 mov r3, r0
0x88a4 mov r0, r3
0x88a8 vldr d0, [r11, #-20] ; 0xffffffec
0x88ac bl 0x8598 <std::ostream::operator<<(double)>
0x88b0 mov r3, r0
0x88b4 mov r0, r3
0x88b8 ldr r1, [pc, #544] ; 0x8ae0 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+640>
0x88bc bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x88c0 ldr r0, [pc, #528] ; 0x8ad8 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+632>
0x88c4 ldr r1, [pc, #528] ; 0x8adc <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+636>
0x88c8 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x88cc mov r3, r0
0x88d0 mov r0, r3
0x88d4 vldr d0, [r11, #-28] ; 0xffffffe4
0x88d8 bl 0x8598 <std::ostream::operator<<(double)>
0x88dc mov r3, r0
0x88e0 mov r0, r3
0x88e4 ldr r1, [pc, #500] ; 0x8ae0 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+640>
0x88e8 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x88ec ldr r0, [pc, #484] ; 0x8ad8 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+632>
0x88f0 ldr r1, [pc, #484] ; 0x8adc <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+636>
0x88f4 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x88f8 mov r3, r0
0x88fc mov r0, r3
0x8900 vldr d0, [r11, #-36] ; 0xffffffdc
0x8904 bl 0x8598 <std::ostream::operator<<(double)>
0x8908 mov r3, r0
0x890c mov r0, r3
0x8910 ldr r1, [pc, #456] ; 0x8ae0 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+640>
0x8914 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8918 ldr r0, [pc, #440] ; 0x8ad8 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+632>
0x891c ldr r1, [pc, #440] ; 0x8adc <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+636>
0x8920 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8924 mov r3, r0
0x8928 mov r0, r3
0x892c vldr d0, [r11, #-44] ; 0xffffffd4
0x8930 bl 0x8598 <std::ostream::operator<<(double)>
0x8934 mov r3, r0
0x8938 mov r0, r3
0x893c ldr r1, [pc, #412] ; 0x8ae0 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+640>
0x8940 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8944 ldr r0, [pc, #396] ; 0x8ad8 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+632>
0x8948 ldr r1, [pc, #396] ; 0x8adc <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+636>
0x894c bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8950 mov r3, r0
0x8954 mov r0, r3
0x8958 vldr d0, [r11, #-52] ; 0xffffffcc
0x895c bl 0x8598 <std::ostream::operator<<(double)>
0x8960 mov r3, r0
0x8964 mov r0, r3
0x8968 ldr r1, [pc, #368] ; 0x8ae0 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+640>
0x896c bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8970 ldr r0, [pc, #352] ; 0x8ad8 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+632>
0x8974 ldr r1, [pc, #352] ; 0x8adc <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+636>
0x8978 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x897c mov r3, r0
0x8980 mov r0, r3
0x8984 vldr d0, [r11, #-60] ; 0xffffffc4
0x8988 bl 0x8598 <std::ostream::operator<<(double)>
0x898c mov r3, r0
0x8990 mov r0, r3
0x8994 ldr r1, [pc, #324] ; 0x8ae0 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+640>
0x8998 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x899c ldr r0, [pc, #308] ; 0x8ad8 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+632>
0x89a0 ldr r1, [pc, #308] ; 0x8adc <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+636>
0x89a4 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x89a8 mov r3, r0
0x89ac mov r0, r3
0x89b0 vldr d0, [r11, #-68] ; 0xffffffbc
0x89b4 bl 0x8598 <std::ostream::operator<<(double)>
0x89b8 mov r3, r0
0x89bc mov r0, r3
0x89c0 ldr r1, [pc, #280] ; 0x8ae0 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+640>
0x89c4 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x89c8 ldr r0, [pc, #264] ; 0x8ad8 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+632>
0x89cc ldr r1, [pc, #264] ; 0x8adc <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+636>
0x89d0 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x89d4 mov r3, r0
0x89d8 mov r0, r3
0x89dc vldr d0, [r11, #4]
0x89e0 bl 0x8598 <std::ostream::operator<<(double)>
0x89e4 mov r3, r0
0x89e8 mov r0, r3
0x89ec ldr r1, [pc, #236] ; 0x8ae0 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+640>
0x89f0 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x89f4 ldr r0, [pc, #220] ; 0x8ad8 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+632>
0x89f8 ldr r1, [pc, #220] ; 0x8adc <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+636>
0x89fc bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8a00 mov r3, r0
0x8a04 mov r0, r3
0x8a08 vldr d0, [r11, #12]
0x8a0c bl 0x8598 <std::ostream::operator<<(double)>
0x8a10 mov r3, r0
0x8a14 mov r0, r3
0x8a18 ldr r1, [pc, #192] ; 0x8ae0 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+640>
0x8a1c bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8a20 ldr r0, [pc, #176] ; 0x8ad8 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+632>
0x8a24 ldr r1, [pc, #176] ; 0x8adc <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+636>
0x8a28 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8a2c mov r3, r0
0x8a30 mov r0, r3
0x8a34 vldr s0, [r11, #20]
0x8a38 bl 0x8604 <std::ostream::operator<<(float)>
0x8a3c mov r3, r0
0x8a40 mov r0, r3
0x8a44 ldr r1, [pc, #148] ; 0x8ae0 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+640>
0x8a48 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8a4c ldr r0, [pc, #132] ; 0x8ad8 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+632>
0x8a50 ldr r1, [pc, #132] ; 0x8adc <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+636>
0x8a54 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8a58 mov r3, r0
0x8a5c mov r0, r3
0x8a60 vldr s0, [r11, #24]
0x8a64 bl 0x8604 <std::ostream::operator<<(float)>
0x8a68 mov r3, r0
0x8a6c mov r0, r3
0x8a70 ldr r1, [pc, #104] ; 0x8ae0 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+640>
0x8a74 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8a78 ldr r0, [pc, #88] ; 0x8ad8 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+632>
0x8a7c ldr r1, [pc, #88] ; 0x8adc <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+636>
0x8a80 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8a84 mov r3, r0
0x8a88 mov r0, r3
0x8a8c ldrd r2, [r11, #-76] ; 0xffffffb4
0x8a90 bl 0x8610 <std::ostream::operator<<(long long)>
0x8a94 mov r3, r0
0x8a98 mov r0, r3
0x8a9c ldr r1, [pc, #60] ; 0x8ae0 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+640>
0x8aa0 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8aa4 ldr r0, [pc, #44] ; 0x8ad8 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+632>
0x8aa8 ldr r1, [pc, #44] ; 0x8adc <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+636>
0x8aac bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8ab0 mov r3, r0
0x8ab4 mov r0, r3
0x8ab8 ldrd r2, [r11, #-84] ; 0xffffffac
0x8abc bl 0x8610 <std::ostream::operator<<(long long)>
0x8ac0 mov r3, r0
0x8ac4 mov r0, r3
0x8ac8 ldr r1, [pc, #16] ; 0x8ae0 <receivesLots(double, double, double, double, double, double, double, double, double, double, float, float, long long, long long)+640>
0x8acc bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8ad0 sub sp, r11, #4
0x8ad4 pop {r11, pc}
0x8ad8 andeq r0, r1, r8, lsr #29
0x8adc ldrdeq r8, [r0], -r8 ; <UNPREDICTABLE>
0x8ae0 andeq r8, r0, r4, ror #25


I guess we can conclude that we have 8 "d" registers (or 16 "s"?) and long long are passed using 2 "r", right?

#11 Andreas Jonsson   Moderators   -  Reputation: 3415

Like
0Likes
Like

Posted 12 November 2012 - 06:26 PM

Yes, there are 8 "d" registers for use by double arguments.

It probably means that there are 16 "s" registers too, but that needs to be confirmed. It may be that the ABI only uses 8 "s" registers.

The same for the "r" registers. How many are used?

I saw something interesting with the receivesMixed2(float a,double b,float c). The order of the arguments was changed, probably to use the s1 register which would otherwise be empty could be used. With this the arguments was passed as: a -> s0, c -> s1, b -> d1.

I wonder if the same happens when the function is receiving 32bit integers and 64bit integers too, i.e. receivesMixed3(int a, long long b, int c).

Edited by Andreas Jonsson, 12 November 2012 - 06:27 PM.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

#12 Tzarls   Members   -  Reputation: 891

Like
0Likes
Like

Posted 12 November 2012 - 06:44 PM

Yes, I noticed the reordering of parameters. Ok, so next is: test if reordering happens with 32bit int and 64bit ints, and check the real limits for "r" and "s" registers. Funnily, the docs i´ve got state that the floating point unit in this processor has 16 "d" registers (which can be seen as 32 "s" registers).

I´ll be back with some more disassemblies.

#13 Tzarls   Members   -  Reputation: 891

Like
0Likes
Like

Posted 12 November 2012 - 07:22 PM

#include <iostream>
void receivesMixedInts(int a, long long b, int c)
{
    std::cout << "Received " << a << ".\n";
    std::cout << "Received " << b << ".\n";
    std::cout << "Received " << c << ".\n";
}
void receivesLots(double a0, double a1, double a2, double a3, double a4, double a5,
				 float f0, float f1, float f2, float f3, float f4, float f5, float f6, float f7)
{
    std::cout << "Received " << a0 << ".\n";
    std::cout << "Received " << a1 << ".\n";
    std::cout << "Received " << a2 << ".\n";
    std::cout << "Received " << a3 << ".\n";
    std::cout << "Received " << a4 << ".\n";
    std::cout << "Received " << a5 << ".\n";
    std::cout << "Received " << f0 << ".\n";
    std::cout << "Received " << f1 << ".\n";
    std::cout << "Received " << f2 << ".\n";
    std::cout << "Received " << f3 << ".\n";
    std::cout << "Received " << f4 << ".\n";
    std::cout << "Received " << f5 << ".\n";
    std::cout << "Received " << f6 << ".\n";
    std::cout << "Received " << f7 << ".\n";
}
void receivesLotsInts(long long a0, long long a1, long long a2,
					  int f0, int f1, int f2, int f3, int f4, int f5, int f6, int f7)
{
    std::cout << "Received " << a0 << ".\n";
    std::cout << "Received " << a1 << ".\n";
    std::cout << "Received " << a2 << ".\n";
    std::cout << "Received " << f0 << ".\n";
    std::cout << "Received " << f1 << ".\n";
    std::cout << "Received " << f2 << ".\n";
    std::cout << "Received " << f3 << ".\n";
    std::cout << "Received " << f4 << ".\n";
    std::cout << "Received " << f5 << ".\n";
    std::cout << "Received " << f6 << ".\n";
    std::cout << "Received " << f7 << ".\n";
}
int main()
{
    receivesMixedInts(1, 100, 3);
    receivesLots(0.12345, 1.12345, 2.34567, 3.456789, 4.5678901, 5.6789012,
				 0.7f, 1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, 7.7f);
    receivesLotsInts(1000000,2000000, 3000000,
					 1, 2, 3, 4, 5, 6, 7, 8);
    return 0;
}



main:


0x8c38 push {r11, lr}
0x8c3c add r11, sp, #4
0x8c40 sub sp, sp, #40 ; 0x28
0x8c44 mov r3, #3
0x8c48 str r3, [sp]
0x8c4c mov r0, #1
0x8c50 mov r2, #100 ; 0x64
0x8c54 mov r3, #0
0x8c58 bl 0x86d0 <receivesMixedInts(int, long long, int)>
0x8c5c ldr r3, [pc, #268] ; 0x8d70 <main()+312>
0x8c60 str r3, [sp]
0x8c64 ldr r3, [pc, #264] ; 0x8d74 <main()+316>
0x8c68 str r3, [sp, #4]
0x8c6c ldr r3, [pc, #260] ; 0x8d78 <main()+320>
0x8c70 str r3, [sp, #8]
0x8c74 ldr r3, [pc, #256] ; 0x8d7c <main()+324>
0x8c78 str r3, [sp, #12]
0x8c7c vldr d0, [pc, #148] ; 0x8d18 <main()+224>
0x8c80 vldr d1, [pc, #152] ; 0x8d20 <main()+232>
0x8c84 vldr d2, [pc, #156] ; 0x8d28 <main()+240>
0x8c88 vldr d3, [pc, #160] ; 0x8d30 <main()+248>
0x8c8c vldr d4, [pc, #164] ; 0x8d38 <main()+256>
0x8c90 vldr d5, [pc, #168] ; 0x8d40 <main()+264>
0x8c94 vldr s12, [pc, #196] ; 0x8d60 <main()+296>
0x8c98 vldr s13, [pc, #196] ; 0x8d64 <main()+300>
0x8c9c vldr s14, [pc, #196] ; 0x8d68 <main()+304>
0x8ca0 vldr s15, [pc, #196] ; 0x8d6c <main()+308>
0x8ca4 bl 0x877c <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)>
0x8ca8 add r3, pc, #152 ; 0x98
0x8cac ldrd r2, [r3]
0x8cb0 strd r2, [sp]
0x8cb4 mov r3, #1
0x8cb8 str r3, [sp, #8]
0x8cbc mov r3, #2
0x8cc0 str r3, [sp, #12]
0x8cc4 mov r3, #3
0x8cc8 str r3, [sp, #16]
0x8ccc mov r3, #4
0x8cd0 str r3, [sp, #20]
0x8cd4 mov r3, #5
0x8cd8 str r3, [sp, #24]
0x8cdc mov r3, #6
0x8ce0 str r3, [sp, #28]
0x8ce4 mov r3, #7
0x8ce8 str r3, [sp, #32]
0x8cec mov r3, #8
0x8cf0 str r3, [sp, #36] ; 0x24
0x8cf4 add r1, pc, #84 ; 0x54
0x8cf8 ldrd r0, [r1]
0x8cfc add r3, pc, #84 ; 0x54
0x8d00 ldrd r2, [r3]
0x8d04 bl 0x8a2c <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)>
0x8d08 mov r3, #0
0x8d0c mov r0, r3
0x8d10 sub sp, r11, #4
0x8d14 pop {r11, pc}
0x8d18 adcspl pc, r0, r12, ror r2 ; <UNPREDICTABLE>
0x8d1c svccc 0x00bf9a6b
0x8d20 strlt r0, [r11, #-3880] ; 0xf28
0x8d24 svccc 0x00f1f9a6
0x8d28 andge r10, r9, #164, 20 ; 0xa4000
0x8d2c andmi r12, r2, lr, ror #7
0x8d30 stc2l 1, cr6, [r1, #380] ; 0x17c
0x8d34 andmi r10, r11, r0, lsl #15
0x8d38 blx 0x1f41b42
0x8d3c andsmi r4, r2, r4, lsl #11
0x8d40 sub sp, r12, r2, asr r12
0x8d44 andsmi r11, r6, r1, lsr r7
0x8d48 eoreq r12, sp, r0, asr #13
0x8d4c andeq r0, r0, r0
0x8d50 andeq r4, pc, r0, asr #4
0x8d54 andeq r0, r0, r0
0x8d58 andseq r8, lr, r0, lsl #9
0x8d5c andeq r0, r0, r0
0x8d60 svccc 0x00333333
0x8d64 svccc 0x008ccccd
0x8d68 andmi r12, r12, sp, asr #25
0x8d6c subsmi r3, r3, r3, lsr r3
0x8d70 addmi r12, r12, sp, asr #25
0x8d74 adcsmi r0, r0, r0
0x8d78 sbcsmi r3, r3, r3, lsr r3
0x8d7c rscsmi r6, r6, r6, ror #12

receiveMixedInts:


0x86d0 push {r11, lr}
0x86d4 add r11, sp, #4
0x86d8 sub sp, sp, #16
0x86dc str r0, [r11, #-8]
0x86e0 strd r2, [r11, #-20] ; 0xffffffec
0x86e4 ldr r0, [pc, #132] ; 0x8770 <receivesMixedInts(int, long long, int)+160>
0x86e8 ldr r1, [pc, #132] ; 0x8774 <receivesMixedInts(int, long long, int)+164>
0x86ec bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x86f0 mov r3, r0
0x86f4 mov r0, r3
0x86f8 ldr r1, [r11, #-8]
0x86fc bl 0x85a4 <std::ostream::operator<<(int)>
0x8700 mov r3, r0
0x8704 mov r0, r3
0x8708 ldr r1, [pc, #104] ; 0x8778 <receivesMixedInts(int, long long, int)+168>
0x870c bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8710 ldr r0, [pc, #88] ; 0x8770 <receivesMixedInts(int, long long, int)+160>
0x8714 ldr r1, [pc, #88] ; 0x8774 <receivesMixedInts(int, long long, int)+164>
0x8718 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x871c mov r3, r0
0x8720 mov r0, r3
0x8724 ldrd r2, [r11, #-20] ; 0xffffffec
0x8728 bl 0x8610 <std::ostream::operator<<(long long)>
0x872c mov r3, r0
0x8730 mov r0, r3
0x8734 ldr r1, [pc, #60] ; 0x8778 <receivesMixedInts(int, long long, int)+168>
0x8738 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x873c ldr r0, [pc, #44] ; 0x8770 <receivesMixedInts(int, long long, int)+160>
0x8740 ldr r1, [pc, #44] ; 0x8774 <receivesMixedInts(int, long long, int)+164>
0x8744 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8748 mov r3, r0
0x874c mov r0, r3
0x8750 ldr r1, [r11, #4]
0x8754 bl 0x85a4 <std::ostream::operator<<(int)>
0x8758 mov r3, r0
0x875c mov r0, r3
0x8760 ldr r1, [pc, #16] ; 0x8778 <receivesMixedInts(int, long long, int)+168>
0x8764 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8768 sub sp, r11, #4
0x876c pop {r11, pc}
0x8770 andeq r1, r1, r0, ror #2
0x8774 andeq r8, r0, r0, ror lr
0x8778 andeq r8, r0, r12, ror lr

receivesLots:


0x877c push {r11, lr}
0x8780 add r11, sp, #4
0x8784 sub sp, sp, #64 ; 0x40
0x8788 vstr d0, [r11, #-12]
0x878c vstr d1, [r11, #-20] ; 0xffffffec
0x8790 vstr d2, [r11, #-28] ; 0xffffffe4
0x8794 vstr d3, [r11, #-36] ; 0xffffffdc
0x8798 vstr d4, [r11, #-44] ; 0xffffffd4
0x879c vstr d5, [r11, #-52] ; 0xffffffcc
0x87a0 vstr s12, [r11, #-56] ; 0xffffffc8
0x87a4 vstr s13, [r11, #-60] ; 0xffffffc4
0x87a8 vstr s14, [r11, #-64] ; 0xffffffc0
0x87ac vstr s15, [r11, #-68] ; 0xffffffbc
0x87b0 ldr r0, [pc, #616] ; 0x8a20 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+676>
0x87b4 ldr r1, [pc, #616] ; 0x8a24 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+680>
0x87b8 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x87bc mov r3, r0
0x87c0 mov r0, r3
0x87c4 vldr d0, [r11, #-12]
0x87c8 bl 0x8598 <std::ostream::operator<<(double)>
0x87cc mov r3, r0
0x87d0 mov r0, r3
0x87d4 ldr r1, [pc, #588] ; 0x8a28 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+684>
0x87d8 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x87dc ldr r0, [pc, #572] ; 0x8a20 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+676>
0x87e0 ldr r1, [pc, #572] ; 0x8a24 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+680>
0x87e4 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x87e8 mov r3, r0
0x87ec mov r0, r3
0x87f0 vldr d0, [r11, #-20] ; 0xffffffec
0x87f4 bl 0x8598 <std::ostream::operator<<(double)>
0x87f8 mov r3, r0
0x87fc mov r0, r3
0x8800 ldr r1, [pc, #544] ; 0x8a28 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+684>
0x8804 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8808 ldr r0, [pc, #528] ; 0x8a20 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+676>
0x880c ldr r1, [pc, #528] ; 0x8a24 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+680>
0x8810 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8814 mov r3, r0
0x8818 mov r0, r3
0x881c vldr d0, [r11, #-28] ; 0xffffffe4
0x8820 bl 0x8598 <std::ostream::operator<<(double)>
0x8824 mov r3, r0
0x8828 mov r0, r3
0x882c ldr r1, [pc, #500] ; 0x8a28 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+684>
0x8830 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8834 ldr r0, [pc, #484] ; 0x8a20 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+676>
0x8838 ldr r1, [pc, #484] ; 0x8a24 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+680>
0x883c bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8840 mov r3, r0
0x8844 mov r0, r3
0x8848 vldr d0, [r11, #-36] ; 0xffffffdc
0x884c bl 0x8598 <std::ostream::operator<<(double)>
0x8850 mov r3, r0
0x8854 mov r0, r3
0x8858 ldr r1, [pc, #456] ; 0x8a28 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+684>
0x885c bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8860 ldr r0, [pc, #440] ; 0x8a20 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+676>
0x8864 ldr r1, [pc, #440] ; 0x8a24 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+680>
0x8868 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x886c mov r3, r0
0x8870 mov r0, r3
0x8874 vldr d0, [r11, #-44] ; 0xffffffd4
0x8878 bl 0x8598 <std::ostream::operator<<(double)>
0x887c mov r3, r0
0x8880 mov r0, r3
0x8884 ldr r1, [pc, #412] ; 0x8a28 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+684>
0x8888 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x888c ldr r0, [pc, #396] ; 0x8a20 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+676>
0x8890 ldr r1, [pc, #396] ; 0x8a24 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+680>
0x8894 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8898 mov r3, r0
0x889c mov r0, r3
0x88a0 vldr d0, [r11, #-52] ; 0xffffffcc
0x88a4 bl 0x8598 <std::ostream::operator<<(double)>
0x88a8 mov r3, r0
0x88ac mov r0, r3
0x88b0 ldr r1, [pc, #368] ; 0x8a28 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+684>
0x88b4 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x88b8 ldr r0, [pc, #352] ; 0x8a20 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+676>
0x88bc ldr r1, [pc, #352] ; 0x8a24 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+680>
0x88c0 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x88c4 mov r3, r0
0x88c8 mov r0, r3
0x88cc vldr s0, [r11, #-56] ; 0xffffffc8
0x88d0 bl 0x8604 <std::ostream::operator<<(float)>
0x88d4 mov r3, r0
0x88d8 mov r0, r3
0x88dc ldr r1, [pc, #324] ; 0x8a28 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+684>
0x88e0 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x88e4 ldr r0, [pc, #308] ; 0x8a20 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+676>
0x88e8 ldr r1, [pc, #308] ; 0x8a24 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+680>
0x88ec bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x88f0 mov r3, r0
0x88f4 mov r0, r3
0x88f8 vldr s0, [r11, #-60] ; 0xffffffc4
0x88fc bl 0x8604 <std::ostream::operator<<(float)>
0x8900 mov r3, r0
0x8904 mov r0, r3
0x8908 ldr r1, [pc, #280] ; 0x8a28 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+684>
0x890c bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8910 ldr r0, [pc, #264] ; 0x8a20 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+676>
0x8914 ldr r1, [pc, #264] ; 0x8a24 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+680>
0x8918 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x891c mov r3, r0
0x8920 mov r0, r3
0x8924 vldr s0, [r11, #-64] ; 0xffffffc0
0x8928 bl 0x8604 <std::ostream::operator<<(float)>
0x892c mov r3, r0
0x8930 mov r0, r3
0x8934 ldr r1, [pc, #236] ; 0x8a28 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+684>
0x8938 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x893c ldr r0, [pc, #220] ; 0x8a20 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+676>
0x8940 ldr r1, [pc, #220] ; 0x8a24 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+680>
0x8944 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8948 mov r3, r0
0x894c mov r0, r3
0x8950 vldr s0, [r11, #-68] ; 0xffffffbc
0x8954 bl 0x8604 <std::ostream::operator<<(float)>
0x8958 mov r3, r0
0x895c mov r0, r3
0x8960 ldr r1, [pc, #192] ; 0x8a28 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+684>
0x8964 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8968 ldr r0, [pc, #176] ; 0x8a20 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+676>
0x896c ldr r1, [pc, #176] ; 0x8a24 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+680>
0x8970 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8974 mov r3, r0
0x8978 mov r0, r3
0x897c vldr s0, [r11, #4]
0x8980 bl 0x8604 <std::ostream::operator<<(float)>
0x8984 mov r3, r0
0x8988 mov r0, r3
0x898c ldr r1, [pc, #148] ; 0x8a28 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+684>
0x8990 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8994 ldr r0, [pc, #132] ; 0x8a20 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+676>
0x8998 ldr r1, [pc, #132] ; 0x8a24 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+680>
0x899c bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x89a0 mov r3, r0
0x89a4 mov r0, r3
0x89a8 vldr s0, [r11, #8]
0x89ac bl 0x8604 <std::ostream::operator<<(float)>
0x89b0 mov r3, r0
0x89b4 mov r0, r3
0x89b8 ldr r1, [pc, #104] ; 0x8a28 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+684>
0x89bc bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x89c0 ldr r0, [pc, #88] ; 0x8a20 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+676>
0x89c4 ldr r1, [pc, #88] ; 0x8a24 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+680>
0x89c8 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x89cc mov r3, r0
0x89d0 mov r0, r3
0x89d4 vldr s0, [r11, #12]
0x89d8 bl 0x8604 <std::ostream::operator<<(float)>
0x89dc mov r3, r0
0x89e0 mov r0, r3
0x89e4 ldr r1, [pc, #60] ; 0x8a28 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+684>
0x89e8 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x89ec ldr r0, [pc, #44] ; 0x8a20 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+676>
0x89f0 ldr r1, [pc, #44] ; 0x8a24 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+680>
0x89f4 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x89f8 mov r3, r0
0x89fc mov r0, r3
0x8a00 vldr s0, [r11, #16]
0x8a04 bl 0x8604 <std::ostream::operator<<(float)>
0x8a08 mov r3, r0
0x8a0c mov r0, r3
0x8a10 ldr r1, [pc, #16] ; 0x8a28 <receivesLots(double, double, double, double, double, double, float, float, float, float, float, float, float, float)+684>
0x8a14 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8a18 sub sp, r11, #4
0x8a1c pop {r11, pc}
0x8a20 andeq r1, r1, r0, ror #2
0x8a24 andeq r8, r0, r0, ror lr
0x8a28 andeq r8, r0, r12, ror lr

receivesLotsInts:


0x8a2c push {r11, lr}
0x8a30 add r11, sp, #4
0x8a34 sub sp, sp, #16
0x8a38 strd r0, [r11, #-12]
0x8a3c strd r2, [r11, #-20] ; 0xffffffec
0x8a40 ldr r0, [pc, #484] ; 0x8c2c <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+512>
0x8a44 ldr r1, [pc, #484] ; 0x8c30 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+516>
0x8a48 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8a4c mov r3, r0
0x8a50 mov r0, r3
0x8a54 ldrd r2, [r11, #-12]
0x8a58 bl 0x8610 <std::ostream::operator<<(long long)>
0x8a5c mov r3, r0
0x8a60 mov r0, r3
0x8a64 ldr r1, [pc, #456] ; 0x8c34 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+520>
0x8a68 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8a6c ldr r0, [pc, #440] ; 0x8c2c <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+512>
0x8a70 ldr r1, [pc, #440] ; 0x8c30 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+516>
0x8a74 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8a78 mov r3, r0
0x8a7c mov r0, r3
0x8a80 ldrd r2, [r11, #-20] ; 0xffffffec
0x8a84 bl 0x8610 <std::ostream::operator<<(long long)>
0x8a88 mov r3, r0
0x8a8c mov r0, r3
0x8a90 ldr r1, [pc, #412] ; 0x8c34 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+520>
0x8a94 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8a98 ldr r0, [pc, #396] ; 0x8c2c <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+512>
0x8a9c ldr r1, [pc, #396] ; 0x8c30 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+516>
0x8aa0 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8aa4 mov r3, r0
0x8aa8 mov r0, r3
0x8aac ldrd r2, [r11, #4]
0x8ab0 bl 0x8610 <std::ostream::operator<<(long long)>
0x8ab4 mov r3, r0
0x8ab8 mov r0, r3
0x8abc ldr r1, [pc, #368] ; 0x8c34 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+520>
0x8ac0 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8ac4 ldr r0, [pc, #352] ; 0x8c2c <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+512>
0x8ac8 ldr r1, [pc, #352] ; 0x8c30 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+516>
0x8acc bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8ad0 mov r3, r0
0x8ad4 mov r0, r3
0x8ad8 ldr r1, [r11, #12]
0x8adc bl 0x85a4 <std::ostream::operator<<(int)>
0x8ae0 mov r3, r0
0x8ae4 mov r0, r3
0x8ae8 ldr r1, [pc, #324] ; 0x8c34 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+520>
0x8aec bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8af0 ldr r0, [pc, #308] ; 0x8c2c <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+512>
0x8af4 ldr r1, [pc, #308] ; 0x8c30 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+516>
0x8af8 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8afc mov r3, r0
0x8b00 mov r0, r3
0x8b04 ldr r1, [r11, #16]
0x8b08 bl 0x85a4 <std::ostream::operator<<(int)>
0x8b0c mov r3, r0
0x8b10 mov r0, r3
0x8b14 ldr r1, [pc, #280] ; 0x8c34 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+520>
0x8b18 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8b1c ldr r0, [pc, #264] ; 0x8c2c <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+512>
0x8b20 ldr r1, [pc, #264] ; 0x8c30 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+516>
0x8b24 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8b28 mov r3, r0
0x8b2c mov r0, r3
0x8b30 ldr r1, [r11, #20]
0x8b34 bl 0x85a4 <std::ostream::operator<<(int)>
0x8b38 mov r3, r0
0x8b3c mov r0, r3
0x8b40 ldr r1, [pc, #236] ; 0x8c34 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+520>
0x8b44 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8b48 ldr r0, [pc, #220] ; 0x8c2c <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+512>
0x8b4c ldr r1, [pc, #220] ; 0x8c30 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+516>
0x8b50 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8b54 mov r3, r0
0x8b58 mov r0, r3
0x8b5c ldr r1, [r11, #24]
0x8b60 bl 0x85a4 <std::ostream::operator<<(int)>
0x8b64 mov r3, r0
0x8b68 mov r0, r3
0x8b6c ldr r1, [pc, #192] ; 0x8c34 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+520>
0x8b70 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8b74 ldr r0, [pc, #176] ; 0x8c2c <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+512>
0x8b78 ldr r1, [pc, #176] ; 0x8c30 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+516>
0x8b7c bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8b80 mov r3, r0
0x8b84 mov r0, r3
0x8b88 ldr r1, [r11, #28]
0x8b8c bl 0x85a4 <std::ostream::operator<<(int)>
0x8b90 mov r3, r0
0x8b94 mov r0, r3
0x8b98 ldr r1, [pc, #148] ; 0x8c34 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+520>
0x8b9c bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8ba0 ldr r0, [pc, #132] ; 0x8c2c <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+512>
0x8ba4 ldr r1, [pc, #132] ; 0x8c30 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+516>
0x8ba8 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8bac mov r3, r0
0x8bb0 mov r0, r3
0x8bb4 ldr r1, [r11, #32]
0x8bb8 bl 0x85a4 <std::ostream::operator<<(int)>
0x8bbc mov r3, r0
0x8bc0 mov r0, r3
0x8bc4 ldr r1, [pc, #104] ; 0x8c34 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+520>
0x8bc8 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8bcc ldr r0, [pc, #88] ; 0x8c2c <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+512>
0x8bd0 ldr r1, [pc, #88] ; 0x8c30 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+516>
0x8bd4 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8bd8 mov r3, r0
0x8bdc mov r0, r3
0x8be0 ldr r1, [r11, #36] ; 0x24
0x8be4 bl 0x85a4 <std::ostream::operator<<(int)>
0x8be8 mov r3, r0
0x8bec mov r0, r3
0x8bf0 ldr r1, [pc, #60] ; 0x8c34 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+520>
0x8bf4 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8bf8 ldr r0, [pc, #44] ; 0x8c2c <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+512>
0x8bfc ldr r1, [pc, #44] ; 0x8c30 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+516>
0x8c00 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8c04 mov r3, r0
0x8c08 mov r0, r3
0x8c0c ldr r1, [r11, #40] ; 0x28
0x8c10 bl 0x85a4 <std::ostream::operator<<(int)>
0x8c14 mov r3, r0
0x8c18 mov r0, r3
0x8c1c ldr r1, [pc, #16] ; 0x8c34 <receivesLotsInts(long long, long long, long long, int, int, int, int, int, int, int, int)+520>
0x8c20 bl 0x85ec <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8c24 sub sp, r11, #4
0x8c28 pop {r11, pc}
0x8c2c andeq r1, r1, r0, ror #2
0x8c30 andeq r8, r0, r0, ror lr
0x8c34 andeq r8, r0, r12, ror lr

From what I see: 16 "s" registers, but only 4 "r" registers?

#14 Andreas Jonsson   Moderators   -  Reputation: 3415

Like
0Likes
Like

Posted 13 November 2012 - 07:38 AM

Yes. 16 "s" registers and only 4 "r" registers.

The 64 bit integers are also aligned to even registers, but contrary to what is done for floats, the arguments are not reordered to use the otherwise empty registers. When calling the receiveMixedInts the first arg was put in r0, the second in r2 and r3, and the third was pushed on the stack, leaving r1 unused.

One last thing needs to be checked. And that is how the arguments that don't fit in the registers are pushed on the stack.

void funcArgsOnStack(int i0, int i1, int i2, int i3, int i4, double f0, double f1, double f2, int i5, double f3, double f4, double f5, double f6, double f7, double f8, int i6);

From what we've learned I suspect the result will be as following:

i6 on stack
f8 on stack
f7 in d7
f6 in d6
f5 in d5
f4 in d4
f3 in d3
i5 on stack
f2 in d2
f1 in d1
f0 in d0
i4 on stack
i3 in r3
i2 in r2
i1 in r1
i0 in r0

If I'm right, I have a pretty good idea on the algorithm that needs to be used to prepare the arguments for loading into the registers. The good part is that we can reuse most of what is already there for the Android ABI, we just need to treat floats and doubles differently.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

#15 Tzarls   Members   -  Reputation: 891

Like
0Likes
Like

Posted 13 November 2012 - 11:37 AM

Ok, here´s the new data.

#include <iostream>
void funcArgsOnStack(int i0, int i1, int i2, int i3, int i4,
					 double f0, double f1, double f2,
					 int i5,
					 double f3, double f4, double f5, double f6, double f7, double f8,
					 int i6)
{
    std::cout << "Received " << i0 <<".\n";
    std::cout << "Received " << i1 <<".\n";
    std::cout << "Received " << i2 <<".\n";
    std::cout << "Received " << i3 <<".\n";
    std::cout << "Received " << i4 <<".\n";
    std::cout << "Received " << f0 <<".\n";
    std::cout << "Received " << f1 <<".\n";
    std::cout << "Received " << f2 <<".\n";
    std::cout << "Received " << i5 <<".\n";
    std::cout << "Received " << f3 <<".\n";
    std::cout << "Received " << f4 <<".\n";
    std::cout << "Received " << f5 <<".\n";
    std::cout << "Received " << f6 <<".\n";
    std::cout << "Received " << f7 <<".\n";
    std::cout << "Received " << f8 <<".\n";
    std::cout << "Received " << i6 <<".\n";
}
int main()
{
    funcArgsOnStack(0,1,2,3,4, 0.123456, 1.234567, 2.345678, 5, 3.456789, 4.56789, 5.6789, 6.789012,
				    7.890123, 8.9012345, 6);
    return 0;
}





main:


0x8970 push {r11, lr}
0x8974 add r11, sp, #4
0x8978 sub sp, sp, #24
0x897c mov r3, #4
0x8980 str r3, [sp]
0x8984 mov r3, #5
0x8988 str r3, [sp, #4]
0x898c add r3, pc, #84 ; 0x54
0x8990 ldrd r2, [r3]
0x8994 strd r2, [sp, #8]
0x8998 mov r3, #6
0x899c str r3, [sp, #16]
0x89a0 mov r0, #0
0x89a4 mov r1, #1
0x89a8 mov r2, #2
0x89ac mov r3, #3
0x89b0 vldr d0, [pc, #56] ; 0x89f0 <main()+128>
0x89b4 vldr d1, [pc, #60] ; 0x89f8 <main()+136>
0x89b8 vldr d2, [pc, #64] ; 0x8a00 <main()+144>
0x89bc vldr d3, [pc, #68] ; 0x8a08 <main()+152>
0x89c0 vldr d4, [pc, #72] ; 0x8a10 <main()+160>
0x89c4 vldr d5, [pc, #76] ; 0x8a18 <main()+168>
0x89c8 vldr d6, [pc, #80] ; 0x8a20 <main()+176>
0x89cc vldr d7, [pc, #84] ; 0x8a28 <main()+184>
0x89d0 bl 0x8660 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)>
0x89d4 mov r3, #0
0x89d8 mov r0, r3
0x89dc sub sp, r11, #4
0x89e0 pop {r11, pc}
0x89e4 nop   ; (mov r0, r0)
0x89e8 blls 0xfefcc10c
0x89ec eormi r12, r1, lr, ror #26
0x89f0 blx 0x1fb64f4
0x89f4 svccc 0x00bf9acf
0x89f8 orrspl r8, r11, #8847360 ; 0x870000
0x89fc svccc 0x00f3c0c9
0x8a00 bicle r9, r7, #268435469 ; 0x1000000d
0x8a04 strdmi r12, [r2], -r2
0x8a08 stc2l 1, cr6, [r1, #380] ; 0x17c
0x8a0c andmi r10, r11, r0, lsl #15
0x8a10 vst3.16   ; <UNDEFINED> instruction: 0xf4c6e6da
0x8a14 andsmi r4, r2, r4, lsl #11
0x8a18 svchi 0x00c50481
0x8a1c andsmi r11, r6, r1, lsr r7
0x8a20 movwgt r9, #2864 ; 0xb30
0x8a24 ; <UNDEFINED> instruction: 0x401b27f2
0x8a28 ldrbvs r10, [r9, -sp, ror #22]
0x8a2c andsmi r8, pc, r12, ror pc ; <UNPREDICTABLE>

funcArgsOnStack:



0x8660 push {r11, lr}
0x8664 add r11, sp, #4
0x8668 sub sp, sp, #80 ; 0x50
0x866c str r0, [r11, #-8]
0x8670 str r1, [r11, #-12]
0x8674 str r2, [r11, #-16]
0x8678 str r3, [r11, #-20]
0x867c vstr d0, [r11, #-28] ; 0xffffffe4
0x8680 vstr d1, [r11, #-36] ; 0xffffffdc
0x8684 vstr d2, [r11, #-44] ; 0xffffffd4
0x8688 vstr d3, [r11, #-52] ; 0xffffffcc
0x868c vstr d4, [r11, #-60] ; 0xffffffc4
0x8690 vstr d5, [r11, #-68] ; 0xffffffbc
0x8694 vstr d6, [r11, #-76] ; 0xffffffb4
0x8698 vstr d7, [r11, #-84] ; 0xffffffac
0x869c ldr r0, [pc, #704] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x86a0 ldr r1, [pc, #704] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x86a4 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x86a8 mov r3, r0
0x86ac mov r0, r3
0x86b0 ldr r1, [r11, #-8]
0x86b4 bl 0x854c <std::ostream::operator<<(int)>
0x86b8 mov r3, r0
0x86bc mov r0, r3
0x86c0 ldr r1, [pc, #676] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x86c4 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x86c8 ldr r0, [pc, #660] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x86cc ldr r1, [pc, #660] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x86d0 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x86d4 mov r3, r0
0x86d8 mov r0, r3
0x86dc ldr r1, [r11, #-12]
0x86e0 bl 0x854c <std::ostream::operator<<(int)>
0x86e4 mov r3, r0
0x86e8 mov r0, r3
0x86ec ldr r1, [pc, #632] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x86f0 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x86f4 ldr r0, [pc, #616] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x86f8 ldr r1, [pc, #616] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x86fc bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8700 mov r3, r0
0x8704 mov r0, r3
0x8708 ldr r1, [r11, #-16]
0x870c bl 0x854c <std::ostream::operator<<(int)>
0x8710 mov r3, r0
0x8714 mov r0, r3
0x8718 ldr r1, [pc, #588] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x871c bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8720 ldr r0, [pc, #572] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x8724 ldr r1, [pc, #572] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x8728 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x872c mov r3, r0
0x8730 mov r0, r3
0x8734 ldr r1, [r11, #-20]
0x8738 bl 0x854c <std::ostream::operator<<(int)>
0x873c mov r3, r0
0x8740 mov r0, r3
0x8744 ldr r1, [pc, #544] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x8748 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x874c ldr r0, [pc, #528] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x8750 ldr r1, [pc, #528] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x8754 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8758 mov r3, r0
0x875c mov r0, r3
0x8760 ldr r1, [r11, #4]
0x8764 bl 0x854c <std::ostream::operator<<(int)>
0x8768 mov r3, r0
0x876c mov r0, r3
0x8770 ldr r1, [pc, #500] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x8774 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8778 ldr r0, [pc, #484] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x877c ldr r1, [pc, #484] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x8780 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8784 mov r3, r0
0x8788 mov r0, r3
0x878c vldr d0, [r11, #-28] ; 0xffffffe4
0x8790 bl 0x8540 <std::ostream::operator<<(double)>
0x8794 mov r3, r0
0x8798 mov r0, r3
0x879c ldr r1, [pc, #456] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x87a0 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x87a4 ldr r0, [pc, #440] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x87a8 ldr r1, [pc, #440] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x87ac bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x87b0 mov r3, r0
0x87b4 mov r0, r3
0x87b8 vldr d0, [r11, #-36] ; 0xffffffdc
0x87bc bl 0x8540 <std::ostream::operator<<(double)>
0x87c0 mov r3, r0
0x87c4 mov r0, r3
0x87c8 ldr r1, [pc, #412] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x87cc bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x87d0 ldr r0, [pc, #396] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x87d4 ldr r1, [pc, #396] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x87d8 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x87dc mov r3, r0
0x87e0 mov r0, r3
0x87e4 vldr d0, [r11, #-44] ; 0xffffffd4
0x87e8 bl 0x8540 <std::ostream::operator<<(double)>
0x87ec mov r3, r0
0x87f0 mov r0, r3
0x87f4 ldr r1, [pc, #368] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x87f8 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x87fc ldr r0, [pc, #352] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x8800 ldr r1, [pc, #352] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x8804 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8808 mov r3, r0
0x880c mov r0, r3
0x8810 ldr r1, [r11, #8]
0x8814 bl 0x854c <std::ostream::operator<<(int)>
0x8818 mov r3, r0
0x881c mov r0, r3
0x8820 ldr r1, [pc, #324] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x8824 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8828 ldr r0, [pc, #308] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x882c ldr r1, [pc, #308] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x8830 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8834 mov r3, r0
0x8838 mov r0, r3
0x883c vldr d0, [r11, #-52] ; 0xffffffcc
0x8840 bl 0x8540 <std::ostream::operator<<(double)>
0x8844 mov r3, r0
0x8848 mov r0, r3
0x884c ldr r1, [pc, #280] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x8850 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8854 ldr r0, [pc, #264] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x8858 ldr r1, [pc, #264] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x885c bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8860 mov r3, r0
0x8864 mov r0, r3
0x8868 vldr d0, [r11, #-60] ; 0xffffffc4
0x886c bl 0x8540 <std::ostream::operator<<(double)>
0x8870 mov r3, r0
0x8874 mov r0, r3
0x8878 ldr r1, [pc, #236] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x887c bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8880 ldr r0, [pc, #220] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x8884 ldr r1, [pc, #220] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x8888 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x888c mov r3, r0
0x8890 mov r0, r3
0x8894 vldr d0, [r11, #-68] ; 0xffffffbc
0x8898 bl 0x8540 <std::ostream::operator<<(double)>
0x889c mov r3, r0
0x88a0 mov r0, r3
0x88a4 ldr r1, [pc, #192] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x88a8 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x88ac ldr r0, [pc, #176] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x88b0 ldr r1, [pc, #176] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x88b4 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x88b8 mov r3, r0
0x88bc mov r0, r3
0x88c0 vldr d0, [r11, #-76] ; 0xffffffb4
0x88c4 bl 0x8540 <std::ostream::operator<<(double)>
0x88c8 mov r3, r0
0x88cc mov r0, r3
0x88d0 ldr r1, [pc, #148] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x88d4 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x88d8 ldr r0, [pc, #132] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x88dc ldr r1, [pc, #132] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x88e0 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x88e4 mov r3, r0
0x88e8 mov r0, r3
0x88ec vldr d0, [r11, #-84] ; 0xffffffac
0x88f0 bl 0x8540 <std::ostream::operator<<(double)>
0x88f4 mov r3, r0
0x88f8 mov r0, r3
0x88fc ldr r1, [pc, #104] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x8900 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8904 ldr r0, [pc, #88] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x8908 ldr r1, [pc, #88] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x890c bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8910 mov r3, r0
0x8914 mov r0, r3
0x8918 vldr d0, [r11, #12]
0x891c bl 0x8540 <std::ostream::operator<<(double)>
0x8920 mov r3, r0
0x8924 mov r0, r3
0x8928 ldr r1, [pc, #60] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x892c bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x8930 ldr r0, [pc, #44] ; 0x8964 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+772>
0x8934 ldr r1, [pc, #44] ; 0x8968 <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+776>
0x8938 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x893c mov r3, r0
0x8940 mov r0, r3
0x8944 ldr r1, [r11, #20]
0x8948 bl 0x854c <std::ostream::operator<<(int)>
0x894c mov r3, r0
0x8950 mov r0, r3
0x8954 ldr r1, [pc, #16] ; 0x896c <funcArgsOnStack(int, int, int, int, int, double, double, double, int, double, double, double, double, double, double, int)+780>
0x8958 bl 0x8594 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
0x895c sub sp, r11, #4
0x8960 pop {r11, pc}
0x8964 andeq r0, r1, r0, asr #25
0x8968 andeq r8, r0, r0, lsr #22
0x896c andeq r8, r0, r12, lsr #22

I think this came out as you predicted?

#16 Andreas Jonsson   Moderators   -  Reputation: 3415

Like
0Likes
Like

Posted 13 November 2012 - 03:20 PM

Yes, it did.

So, from what I see the arguments needs to be prepared as the following pseudo code:

asDWORD genericArgs[MAX_ARGS]; // 4 "r" registers + stack
asDWORD floatArgs[16];  // 8 "d" or 16 "s" registers
int countGeneric = 0;
int countFloat = 0;
int freeSingleFloat = -1;

int argPos = 0;
for( asUINT n = 0; n < countArgs; n++ )
{
   if( parameterTypes[n] is float )
   {
     if( freeSingleFloat != -1 )
     {
       floatArgs[freeSingleFloat] = args[argPos++];
       freeSingleFloat = -1;
       continue;
     }
     else if( countFloat < 15 )
     {
        floatArgs[countFloat++] = args[argPos++];
        continue;
     }
   }
   else if( parameterTypes[n] is double )
   {
     if( countFloat < 14 )
     {
       // Make sure the double is aligned on even registers
       if( countFloat & 1 )
          freeSingleFloat = countFloat++;

       // Copy two dwords for the double
       floatArgs[countFloat++] = args[argPos++];
       floatArgs[countFloat++] = args[argPos++];
       continue;
     }
   }

   // else do whatever is already done for ANDROID in as_callfunc_arm.cpp
}

Of course, it will be necessary to update the as_callfunc_arm_gcc.S too, so the functions take the floatArgs and copy those into the registers. With the algorithm I described above it will be as simple as writing the instructions to copy each pair of elements from the floatArgs array into the d0 to d7 registers. From what I understood the d registers aliases two s registers so loading the d register or the loading each s register will give the same result.

The return of float or double can be handled in a similar way to what is done in as_callfunc_x86.cpp, i.e. after the call to the assembler routine returns to CallSystemFunctionNative, the code can check if the called function returns a float with if( sysFunc->hostReturnFloat ) and if so call another assembler routine that simply unloads the d0 register into r0 and r1, in order to return the float/double as a 64bit integer instead.


I hope you can do the implementation. Don't worry about keeping maintainability with iOS and Android, just get it to work on RPi. Once that is working I can help merge the code so it will work for all targets with the use of preprocessor defines.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

#17 Tzarls   Members   -  Reputation: 891

Like
0Likes
Like

Posted 13 November 2012 - 03:37 PM

Ok. I´ll do my best to get this working. I´ll let you know.

#18 Martins Mozeiko   Crossbones+   -  Reputation: 1422

Like
0Likes
Like

Posted 13 November 2012 - 04:05 PM

The ABI that is used by iOS, Android and other ARM based Linux'es is described here: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf
Section 6 talks about floating point types - how they are stored in VFP registers.

Edited by Martins Mozeiko, 13 November 2012 - 04:06 PM.


#19 Andreas Jonsson   Moderators   -  Reputation: 3415

Like
0Likes
Like

Posted 13 November 2012 - 06:37 PM

Yes, I have that reference in as_callfunc_arm.cpp. It is the official ARM ABI. It is however not strictly followed on the various platforms, so it can not be directly used. iOS, Android, and Windows Phone all have slight differences, and none of them use the floating point registers to pass arguments.

Raspberry Pi is one platform that seems to come closest to follow it. Perhaps we'll find that it is 100% compliant.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

#20 Tzarls   Members   -  Reputation: 891

Like
0Likes
Like

Posted 14 November 2012 - 12:38 AM

Andreas, I need some help here.

In your pseudo code you check for floats and doubles, but never for ints or long longs, even though you declared an array for "r" registers + stack. Was that an error?

Then, in as_callfunc_arm.cpp you have:

#ifndef AS_ANDROID
if( sysFunc->takesObjByVal )
#endif

What does takesObjByVal tell us? Also, I have trouble deciding where to put the new algo in the existing implementation. Would it be something like this?

if (argType == float)
{....}
else if (argType == double)
{.....}
else 
#ifndef AS_ANDROID
if( sysFunc->takesObjByVal )
#endif
{
#ifdef AS_ANDROID....

Edited by Tzarls, 14 November 2012 - 12:41 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS