Shop OBEX P1 Docs P2 Docs Learn Events
[solved: not a bug] cog/crt0_cog.s bug? Feature? — Parallax Forums

[solved: not a bug] cog/crt0_cog.s bug? Feature?

jac_goudsmitjac_goudsmit Posts: 418
edited 2012-09-26 08:22 in Propeller 1
I'm working on a Wiki page about cog mode and mixed mode programming with SimpleIDE and PropGCC and I'm looking at the crt0.s startup code (http://code.google.com/p/propgcc/source/browse/lib/cog/crt0_cog.s) and I noticed something:
_start
  jmpret  lr,#_main
  jmp  #__exit

It looks like the code is intended to call main and when main returns, it stops the cog (that's what _exit does).

But because the jmpret instruction stores the return address in the lr pseudo-register, not _main_ret, it really means that main cannot be _NATIVE but must be _NAKED and cannot return, or must end with __asm__ "jmp lr".

If main is declared _NATIVE, it will return to to #0 because the RET instruction at _main_ret doesn't get modified by the jmpret instruction under _start. Jumping to 0 is not a good idea because r0 is stored there so execution might end up pretty much anywhere. Oops!

As far as I can tell, the lr register is used as storage for the return address for functions that are declared _NAKED. Am I right?

Does it make sense to even use JMPRET to jump to main( ) if it's not expected to return? Would it make sense to change the instruction to a JMP (and save one longword by eliminating the jmp #__exit instruction)?

Just wondering :-)

===Jac

Comments

  • ersmithersmith Posts: 6,094
    edited 2012-09-26 05:02
    I'm working on a Wiki page about cog mode and mixed mode programming with SimpleIDE and PropGCC and I'm looking at the crt0.s startup code (http://code.google.com/p/propgcc/source/browse/lib/cog/crt0_cog.s) and I noticed something:
    _start
      jmpret  lr,#_main
      jmp  #__exit
    

    It looks like the code is intended to call main and when main returns, it stops the cog (that's what _exit does).

    But because the jmpret instruction stores the return address in the lr pseudo-register, not _main_ret, it really means that main cannot be _NATIVE but must be _NAKED and cannot return, or must end with __asm__ "jmp lr".
    If you compile main as a "normal" function, for example:
    int main() { return 0; }
    
    it will automatically end with "jmp lr". That's the default way functions return in PropGCC. The normal calling convention is that the return address is placed in the "lr" register ("lr" stands for "link register"). This allows functions to be recursive. _NATIVE and _NAKED are exceptional cases.

    As you've noticed, main() cannot be _NATIVE. It can (and probably should) be declared _NAKED if it never returns.
  • jac_goudsmitjac_goudsmit Posts: 418
    edited 2012-09-26 08:22
    ersmith wrote: »
    The normal calling convention is that the return address is placed in the "lr" register ("lr" stands for "link register"). This allows functions to be recursive. _NATIVE and _NAKED are exceptional cases.

    As you've noticed, main() cannot be _NATIVE. It can (and probably should) be declared _NAKED if it never returns.

    That's great information! Thanks!

    ===Jac
Sign In or Register to comment.