dl-startup.h 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /* Any assmbly language/system dependent hacks needed to setup boot1.c so it
  2. * will work as expected and cope with whatever platform specific wierdness is
  3. * needed for this architecture.
  4. * Copyright (C) 2005 by Joakim Tjernlund
  5. */
  6. asm(
  7. " .text\n"
  8. " .globl _start\n"
  9. " .type _start,@function\n"
  10. "_start:\n"
  11. " mr 3,1\n" /* Pass SP to _dl_start in r3 */
  12. " li 0,0\n"
  13. " stwu 1,-16(1)\n" /* Make room on stack for _dl_start to store LR */
  14. " stw 0,0(1)\n" /* Clear Stack frame */
  15. " bl _dl_start@local\n" /* Perform relocation */
  16. /* Save the address of the apps entry point in CTR register */
  17. " mtctr 3\n" /* application entry point */
  18. " bl _GLOBAL_OFFSET_TABLE_-4@local\n" /* Put our GOT pointer in r31, */
  19. " mflr 31\n"
  20. " addi 1,1,16\n" /* Restore SP */
  21. " lwz 7,_dl_skip_args@got(31)\n" /* load EA of _dl_skip_args */
  22. " lwz 7,0(7)\n" /* Load word from _dl_skip_args */
  23. " lwz 8,0(1)\n" /* Load argc from stack */
  24. " subf 8,7,8\n" /* Subtract _dl_skip_args from argc. */
  25. " slwi 7,7,2\n" /* Multiply by 4 */
  26. " stwux 8,1,7\n" /* Adjust the stack pointer to skip _dl_skip_args words and store adjusted argc on stack. */
  27. #if 0
  28. /* Try beeing SVR4 ABI compliant?, even though it is not needed for uClibc on Linux */
  29. /* argc */
  30. " lwz 3,0(1)\n"
  31. /* find argv one word offset from the stack pointer */
  32. " addi 4,1,4\n"
  33. /* find environment pointer (argv+argc+1) */
  34. " lwz 5,0(1)\n"
  35. " addi 5,5,1\n"
  36. " rlwinm 5,5,2,0,29\n"
  37. " add 5,5,4\n"
  38. /* pass the auxilary vector in r6. This is passed to us just after _envp. */
  39. "2: lwzu 0,4(6)\n"
  40. " cmpwi 0,0\n"
  41. " bne 2b\n"
  42. " addi 6,6,4\n"
  43. #endif
  44. /* Pass a termination function pointer (in this case _dl_fini) in r7. */
  45. " lwz 7,_dl_fini@got(31)\n"
  46. " bctr\n" /* Jump to entry point */
  47. " .size _start,.-_start\n"
  48. " .previous\n"
  49. );
  50. /*
  51. * Get a pointer to the argv array. On many platforms this can be just
  52. * the address if the first argument, on other platforms we need to
  53. * do something a little more subtle here.
  54. */
  55. #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS)+1)
  56. /*
  57. * Here is a macro to perform a relocation. This is only used when
  58. * bootstrapping the dynamic loader. RELP is the relocation that we
  59. * are performing, REL is the pointer to the address we are relocating.
  60. * SYMBOL is the symbol involved in the relocation, and LOAD is the
  61. * load address.
  62. */
  63. #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
  64. {int type=ELF32_R_TYPE((RELP)->r_info); \
  65. Elf32_Addr finaladdr=(SYMBOL)+(RELP)->r_addend;\
  66. if (type==R_PPC_RELATIVE) { \
  67. *REL=(Elf32_Word)(LOAD)+(RELP)->r_addend;\
  68. } else if (type==R_PPC_ADDR32 || type==R_PPC_GLOB_DAT) {\
  69. *REL=finaladdr; \
  70. } else if (type==R_PPC_JMP_SLOT) { \
  71. Elf32_Sword delta=finaladdr-(Elf32_Word)(REL);\
  72. *REL=OPCODE_B(delta); \
  73. PPC_DCBST(REL); PPC_SYNC; PPC_ICBI(REL);\
  74. } else { \
  75. _dl_exit(100+ELF32_R_TYPE((RELP)->r_info));\
  76. } \
  77. }
  78. /*
  79. * Transfer control to the user's application, once the dynamic loader
  80. * is done. This routine has to exit the current function, then
  81. * call the _dl_elf_main function.
  82. */
  83. #define START() return _dl_elf_main