dl-startup.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /* Startup code for the OpenRISC 1000 platform,
  2. based on microblaze implementation */
  3. /*
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; see the file COPYING.LIB. If
  14. not, see <http://www.gnu.org/licenses/>.  */
  15. __asm__ ("\
  16. .text\n\
  17. .globl _start\n\
  18. .type _start,@function\n\
  19. .hidden _start\n\
  20. _start:\n\
  21. l.ori r3, r9, 0\n\
  22. l.ori r3, r1, 0\n\
  23. l.movhi r11, 0\n\
  24. 1:\n\
  25. l.addi r3, r3, 4\n\
  26. l.lwz r12, 0(r3)\n\
  27. l.sfnei r12, 0\n\
  28. l.addi r11, r11, 1\n\
  29. l.bf 1b\n\
  30. l.nop\n\
  31. l.ori r3, r11, 0\n\
  32. l.ori r3, r1, 0\n\
  33. l.addi r11, r11, -1\n\
  34. /* store argument counter to stack */\n\
  35. l.sw 0(r3), r11\n\
  36. l.addi r1, r1, -24\n\
  37. l.sw 0(r1), r9\n\
  38. \n\
  39. l.jal .LPC0\n\
  40. #ifndef __OR1K_NODELAY__\n\
  41. l.nop\n\
  42. #endif\n\
  43. /* Load the PIC register */\n\
  44. .LPC0:\n\
  45. l.movhi r16, gotpchi(_GLOBAL_OFFSET_TABLE_+(.-.LPC0))\n\
  46. l.ori r16, r16, gotpclo(_GLOBAL_OFFSET_TABLE_+(.-.LPC0))\n\
  47. l.add r16, r16, r9\n\
  48. \n\
  49. l.jal _dl_start\n\
  50. l.nop\n\
  51. /* FALLTHRU */\n\
  52. \n\
  53. .globl _dl_start_user\n\
  54. .type _dl_start_user,@function\n\
  55. _dl_start_user:\n\
  56. l.movhi r12, gotoffhi(_dl_skip_args)\n\
  57. l.ori r12, r12, gotofflo(_dl_skip_args)\n\
  58. l.add r12, r12, r16\n\
  59. l.lwz r12, 0(r12)\n\
  60. l.lwz r3, 24(r1)\n\
  61. \n\
  62. l.movhi r9, gotoffhi(_dl_fini)\n\
  63. l.ori r9, r9, gotofflo(_dl_fini)\n\
  64. l.add r9, r9, r16\n\
  65. \n\
  66. l.addi r9, r9, -8\n\
  67. l.addi r1, r1, 24\n\
  68. l.jr r11\n\
  69. l.nop\n\
  70. .size _dl_start_user, . - _dl_start_user\n\
  71. .previous\n\
  72. ");
  73. /*
  74. * Get a pointer to the argv array. On many platforms this can be just
  75. * the address of the first argument, on other platforms we need to
  76. * do something a little more subtle here.
  77. */
  78. #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS)+1)
  79. /* The ld.so library requires relocations */
  80. #define ARCH_NEEDS_BOOTSTRAP_RELOCS
  81. static __always_inline
  82. void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
  83. unsigned long symbol_addr, unsigned long load_addr,
  84. attribute_unused Elf32_Sym *symtab)
  85. {
  86. switch (ELF_R_TYPE(rpnt->r_info))
  87. {
  88. case R_OR1K_RELATIVE:
  89. *reloc_addr = load_addr + rpnt->r_addend;
  90. break;
  91. default:
  92. _dl_exit(1);
  93. break;
  94. }
  95. }