public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] lib_arm global data pointer
@ 2009-07-10 12:52 Drasko DRASKOVIC
  2009-07-13 13:38 ` Rabin Vincent
  0 siblings, 1 reply; 7+ messages in thread
From: Drasko DRASKOVIC @ 2009-07-10 12:52 UTC (permalink / raw)
  To: u-boot

Hi all,
in libarm/board.c, in function start_armboot(void) I found lines like these:

    /* Pointer is writable since we allocated a register for it */
    gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
    /* compiler optimization barrier needed for GCC >= 3.4 */
    __asm__ __volatile__("": : :"memory");

gd is defined as: register volatile gd_t *gd asm ("r8")

I have 3 questions:
1) Why is it necessary to allocate register? Don't we have stack at this
point (we already allocated stack in start.S).
2) One C question - are we sure that compiler will listen to our which and
really allocate register?
3) Why do we need this membar? To prevent compiler from touching our reg r8
or for some other reason?

Suppose that I allocated  one register in start.S and put in it some data I
want to have later on C side. From start.S we enter to start_armboot(void)
function.
Would this work :

void start_armboot (void)
{
    init_fnc_t **init_fnc_ptr;
    char *s;
#ifndef CFG_NO_FLASH
    ulong size;
#endif
#if defined(CONFIG_VFD) || defined(CONFIG_LCD)
    unsigned long addr;
#endif
*#ifdef DATA_FROM_ASM_IN_R10
    register volatile unsigned long tmp asm ("r10");
#endif*

    /* Pointer is writable since we allocated a register for it */
    gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
    /* compiler optimization barrier needed for GCC >= 3.4 */
    __asm__ __volatile__("": : :"memory");

    memset ((void*)gd, 0, sizeof (gd_t));
    gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
    memset (gd->bd, 0, sizeof (bd_t));

*#ifdef DATA_FROM_ASM_IN_R10
    /* data will be passed to C from assembly start-up in reg r10 */
    gd->bd->bi_my_data = tmp;
#endif*

    monitor_flash_len = _bss_start - _armboot_start;

    for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
        if ((*init_fnc_ptr)() != 0) {
            hang ();
        }
    }

...

}

Would I from this point on really have on C stack what I had in r10 in
start.S?

If not, does anybody have idea how I can do it?

Thanks and best regards,
Drasko DRASKOVIC

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] lib_arm global data pointer
  2009-07-10 12:52 [U-Boot] lib_arm global data pointer Drasko DRASKOVIC
@ 2009-07-13 13:38 ` Rabin Vincent
  2009-07-13 14:00   ` Drasko DRASKOVIC
  0 siblings, 1 reply; 7+ messages in thread
From: Rabin Vincent @ 2009-07-13 13:38 UTC (permalink / raw)
  To: u-boot

On Fri, Jul 10, 2009 at 02:52:32PM +0200, Drasko DRASKOVIC wrote:
[...]
> Suppose that I allocated  one register in start.S and put in it some data I
> want to have later on C side. From start.S we enter to start_armboot(void)
> function.
> Would this work :
> 
> void start_armboot (void)
> {
>     init_fnc_t **init_fnc_ptr;
>     char *s;
> #ifndef CFG_NO_FLASH
>     ulong size;
> #endif
> #if defined(CONFIG_VFD) || defined(CONFIG_LCD)
>     unsigned long addr;
> #endif
> *#ifdef DATA_FROM_ASM_IN_R10
>     register volatile unsigned long tmp asm ("r10");
> #endif*
> 
>     /* Pointer is writable since we allocated a register for it */
>     gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
>     /* compiler optimization barrier needed for GCC >= 3.4 */
>     __asm__ __volatile__("": : :"memory");
> 
>     memset ((void*)gd, 0, sizeof (gd_t));
>     gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
>     memset (gd->bd, 0, sizeof (bd_t));
> 
> *#ifdef DATA_FROM_ASM_IN_R10
>     /* data will be passed to C from assembly start-up in reg r10 */
>     gd->bd->bi_my_data = tmp;
> #endif*
> 
[...]
> 
> Would I from this point on really have on C stack what I had in r10 in
> start.S?
> 
> If not, does anybody have idea how I can do it?

While the above may work, why you don't just follow the procedure call
standard instead?  Place the value in r0 instead of r10, and you'll have
it as the first argument to the function.

Rabin

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] lib_arm global data pointer
  2009-07-13 13:38 ` Rabin Vincent
@ 2009-07-13 14:00   ` Drasko DRASKOVIC
  2009-07-13 15:35     ` Wolfgang Denk
  0 siblings, 1 reply; 7+ messages in thread
From: Drasko DRASKOVIC @ 2009-07-13 14:00 UTC (permalink / raw)
  To: u-boot

>
> While the above may work, why you don't just follow the procedure call
> standard instead?  Place the value in r0 instead of r10, and you'll have
> it as the first argument to the function.
>
there is a reason why I use r10 (and why somebody used r8,  I suppose) - I
search some address during start.S, and want to stock it in the place that
will not be corrupted during continuation of the code in start.S. As you can
see, start.S will heavily use r0, r1, probably other low-numbered regs.

Yes, I can put r10 to r0 just before the call of the function (and change
signature of start(void) to start(int my_var), is that rght?) but what would
this change. If the thisngs work with r10, even better...

And one thing I also noted that is strange a variable of "register
volatile". I played around with arm gcc compiler - does this volatile stuff
really have some effect? Compiler seems to produce asm code like it is not
volatile (optimize by deleting conditions, assign values by add and not mov,
etc...)

BR,
Drasko

On Mon, Jul 13, 2009 at 3:38 PM, Rabin Vincent <rabin@rab.in> wrote:

> On Fri, Jul 10, 2009 at 02:52:32PM +0200, Drasko DRASKOVIC wrote:
> [...]
> > Suppose that I allocated  one register in start.S and put in it some data
> I
> > want to have later on C side. From start.S we enter to
> start_armboot(void)
> > function.
> > Would this work :
> >
> > void start_armboot (void)
> > {
> >     init_fnc_t **init_fnc_ptr;
> >     char *s;
> > #ifndef CFG_NO_FLASH
> >     ulong size;
> > #endif
> > #if defined(CONFIG_VFD) || defined(CONFIG_LCD)
> >     unsigned long addr;
> > #endif
> > *#ifdef DATA_FROM_ASM_IN_R10
> >     register volatile unsigned long tmp asm ("r10");
> > #endif*
> >
> >     /* Pointer is writable since we allocated a register for it */
> >     gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
> >     /* compiler optimization barrier needed for GCC >= 3.4 */
> >     __asm__ __volatile__("": : :"memory");
> >
> >     memset ((void*)gd, 0, sizeof (gd_t));
> >     gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
> >     memset (gd->bd, 0, sizeof (bd_t));
> >
> > *#ifdef DATA_FROM_ASM_IN_R10
> >     /* data will be passed to C from assembly start-up in reg r10 */
> >     gd->bd->bi_my_data = tmp;
> > #endif*
> >
> [...]
> >
> > Would I from this point on really have on C stack what I had in r10 in
> > start.S?
> >
> > If not, does anybody have idea how I can do it?
>
> While the above may work, why you don't just follow the procedure call
> standard instead?  Place the value in r0 instead of r10, and you'll have
> it as the first argument to the function.
>
> Rabin
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] lib_arm global data pointer
  2009-07-13 14:00   ` Drasko DRASKOVIC
@ 2009-07-13 15:35     ` Wolfgang Denk
  2009-07-13 16:00       ` Drasko DRASKOVIC
  0 siblings, 1 reply; 7+ messages in thread
From: Wolfgang Denk @ 2009-07-13 15:35 UTC (permalink / raw)
  To: u-boot

Dear Drasko DRASKOVIC,

In message <5ec3d7930907130700h24ab20c3t258e2c31e21bb71f@mail.gmail.com> you wrote:
>
> there is a reason why I use r10 (and why somebody used r8,  I suppose) - I

Well, that's easy - as the code has to interface with  GCC  generated
code, you have to stick with GCC's register usage conventions.

> And one thing I also noted that is strange a variable of "register
> volatile". I played around with arm gcc compiler - does this volatile stuff
> really have some effect? Compiler seems to produce asm code like it is not
> volatile (optimize by deleting conditions, assign values by add and not mov,
> etc...)

"register volatile" makes sense only for the special case  of  global
or  local  register  variables. Whether or not it is implemented in a
specific version of GCC for a specific architecture is another story;
please ask this on the GCC mailing list.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
One of the advantages of being a captain is being able to ask for ad-
vice without necessarily having to take it.
	-- Kirk, "Dagger of the Mind", stardate 2715.2

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] lib_arm global data pointer
  2009-07-13 15:35     ` Wolfgang Denk
@ 2009-07-13 16:00       ` Drasko DRASKOVIC
  2009-07-13 19:34         ` Wolfgang Denk
  0 siblings, 1 reply; 7+ messages in thread
From: Drasko DRASKOVIC @ 2009-07-13 16:00 UTC (permalink / raw)
  To: u-boot

>
> Well, that's easy - as the code has to interface with  GCC  generated
> code, you have to stick with GCC's register usage conventions.
>
I think we were refering here to ATPCS (ARM-THUMB Procedure Call Standard,
i.e. ARM ABI), which tells that first 4 args of the calee are passed by the
caller via r0-r3, and if calee takes more args, the rest is passed via
stack. IMHO, GCC conventions has not much to do with this. I used r10
because there is small probability that it will be clobbered  in start.S.

"register volatile" makes sense only for the special case  of  global
> or  local  register  variables. Whether or not it is implemented in a
> specific version of GCC for a specific architecture is another story;
> please ask this on the GCC mailing list.
>
OK. But since it was implemented in U-Boot and for ARM, I thought that
anybody who wrote this will be so kind to shread some light on this (I am
guessing that that it has something to do with ISR, but in ISR we seem to
preserve r8), and also on the membar two lines below, and spare me from
subscribing to a huge volume gcc mailing lists for posting just one
question. This rests for me one of the most obscure corners of U-Boot.

Best regards,
Drasko DRASKOVIC

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] lib_arm global data pointer
  2009-07-13 16:00       ` Drasko DRASKOVIC
@ 2009-07-13 19:34         ` Wolfgang Denk
  2009-07-14 13:22           ` Drasko DRASKOVIC
  0 siblings, 1 reply; 7+ messages in thread
From: Wolfgang Denk @ 2009-07-13 19:34 UTC (permalink / raw)
  To: u-boot

Dear Drasko DRASKOVIC,

In message <5ec3d7930907130900l7e043b11lcf37a0d3e161f511@mail.gmail.com> you wrote:
> 
> > Well, that's easy - as the code has to interface with  GCC  generated
> > code, you have to stick with GCC's register usage conventions.
> >
> I think we were refering here to ATPCS (ARM-THUMB Procedure Call Standard,
> i.e. ARM ABI), which tells that first 4 args of the calee are passed by the
> caller via r0-r3, and if calee takes more args, the rest is passed via
> stack. IMHO, GCC conventions has not much to do with this. I used r10
> because there is small probability that it will be clobbered  in start.S.

When I wrote "GCC's register usage conventions" I usually mean exactly
that and not some completely different thing.

You also might want to read the README. Search for "On ARM, the
following registers are used"...

> "register volatile" makes sense only for the special case  of  global
> > or  local  register  variables. Whether or not it is implemented in a
> > specific version of GCC for a specific architecture is another story;
> > please ask this on the GCC mailing list.
> >
> OK. But since it was implemented in U-Boot and for ARM, I thought that
> anybody who wrote this will be so kind to shread some light on this (I am
> guessing that that it has something to do with ISR, but in ISR we seem to

This has nothing to do with ISRs at all. What makes you think so?

> preserve r8), and also on the membar two lines below, and spare me from
> subscribing to a huge volume gcc mailing lists for posting just one
> question. This rests for me one of the most obscure corners of U-Boot.

The GCC mailing list is where GCC experts can answer your  questions.
I'm not a GCC expert - just a happy user since version 1.35 or so...

> --00151748e7286f26c8046e986b49
> Content-Type: text/html; charset=ISO-8859-1
> Content-Transfer-Encoding: quoted-printable

And please don't post HTML.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
You are only young once, but you can stay immature indefinitely.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [U-Boot] lib_arm global data pointer
  2009-07-13 19:34         ` Wolfgang Denk
@ 2009-07-14 13:22           ` Drasko DRASKOVIC
  0 siblings, 0 replies; 7+ messages in thread
From: Drasko DRASKOVIC @ 2009-07-14 13:22 UTC (permalink / raw)
  To: u-boot

Dear  Wolfgang Denk.

>On Mon, Jul 13, 2009 at 9:34 PM, Wolfgang Denk <wd@denx.de> wrote:
> When I wrote "GCC's register usage conventions" I usually mean exactly
> that and not some completely different thing.
>
> You also might want to read the README. Search for "On ARM, the
> following registers are used"...
On a first glance README actually tells that U-Boot will respect ATCPS
(whith exception of r8, which it will reserve). So, actually, it can
be that we were talking about the same thing, just that I used term
ATPCS to underline that it is ARM (and not U-Boot or GCC) specific.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ihi0042c/index.html
(http://www.nabble.com/Register-Usage-td23279910.html)

In any case, my code is working fine with r10 choice, which comes from
the reasons I elaborated before (although maybe r10 would not be the
happiest choice, but some of the regs r4-r9, r8 excluded).

> This has nothing to do with ISRs at all. What makes you think so?
This, for example:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=64978&postdays=0&postorder=asc
And this:
http://www.nabble.com/bug-or-feature--CSE-optimizes-away-global,-fixed-register-td23909408.html

This gave me a hint that people using "volatile register" vars mostly
in these cases.
And I was thinking myself: why claiming our local reg as volatile? Who
can change it appart from us, if not some other thread (written in
assembly most probably, because if it was a C call then GCC would
introduce prologue and epilogue to preserve register that are
guaranteed to be non clobbered by ATCPS). So what other thread do we
have in non-multithreaded U-Boot?
So, I grepped to see who the hell is touching r8, and all I could find
was (in cpu/armXXX/start.S) :
       .macro	irq_save_user_regs
	sub	sp, sp, #S_FRAME_SIZE
	stmia	sp, {r0 - r12}			@ Calling r0-r12
	@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
	add	r8, sp, #S_PC
	stmdb	r8, {sp, lr}^		@ Calling SP, LR
	str	lr, [r8, #0]		@ Save calling PC
	mrs	r6, spsr
	str	r6, [r8, #4]		@ Save CPSR
	str	r0, [r8, #8]		@ Save OLD_R0
	mov	r0, sp
	.endm
chunk of code in ISR.

So, my suspicions comes from there.

> The GCC mailing list is where GCC experts can answer your  questions.
> I'm not a GCC expert - just a happy user since version 1.35 or so...
Thanks, I will investigate this interesting topic further and post on
this thread if I come with reasonable solution. As I mentioned, my gcc
was not working as I expected with "register volatile", as it was
doing some optimization exibitions rather than plain register
read/mov.

Some questions are also worth mentioning:

        /* Pointer is writable since we allocated a register for it */
	gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));

Would not it be writable even if we did not allocated reg for it? We
could have declared it as a global var without asm("r8") stuff and
compiler would have put it on the stack - but I guess it would be
writable.

And then:
	/* compiler optimization barrier needed for GCC >= 3.4 */
	__asm__ __volatile__("": : :"memory");

Why is order of ams instructions important here?
(I did not had time yet to recompile without this membar before
posting this question, so I will try to do it and reproduce the
problem).


Best regards,
Drasko DRASKOVIC

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2009-07-14 13:22 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-10 12:52 [U-Boot] lib_arm global data pointer Drasko DRASKOVIC
2009-07-13 13:38 ` Rabin Vincent
2009-07-13 14:00   ` Drasko DRASKOVIC
2009-07-13 15:35     ` Wolfgang Denk
2009-07-13 16:00       ` Drasko DRASKOVIC
2009-07-13 19:34         ` Wolfgang Denk
2009-07-14 13:22           ` Drasko DRASKOVIC

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox