flat.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * include/asm-v850/flat.h -- uClinux flat-format executables
  3. *
  4. * Copyright (C) 2002,03 NEC Electronics Corporation
  5. * Copyright (C) 2002,03 Miles Bader <miles@gnu.org>
  6. *
  7. * This file is subject to the terms and conditions of the GNU General
  8. * Public License. See the file COPYING in the main directory of this
  9. * archive for more details.
  10. *
  11. * Written by Miles Bader <miles@gnu.org>
  12. */
  13. #ifndef __V850_FLAT_H__
  14. #define __V850_FLAT_H__
  15. /* The amount by which a relocation can exceed the program image limits
  16. without being regarded as an error. On the v850, the relocations of
  17. some base-pointers can be offset by 0x8000 (to allow better usage of the
  18. space offered by 16-bit signed offsets -- in most cases the offsets used
  19. with such a base-pointer will be negative). */
  20. #define flat_reloc_valid(reloc, size) ((reloc) <= (size + 0x8000))
  21. #define flat_stack_align(sp) /* nothing needed */
  22. #define flat_argvp_envp_on_stack() 0
  23. #define flat_old_ram_flag(flags) (flags)
  24. #define flat_set_persistent(relval, p) 0
  25. /* We store the type of relocation in the top 4 bits of the `relval.' */
  26. /* Convert a relocation entry into an address. */
  27. static inline unsigned long
  28. flat_get_relocate_addr (unsigned long relval)
  29. {
  30. return relval & 0x0fffffff; /* Mask out top 4-bits */
  31. }
  32. #define flat_v850_get_reloc_type(relval) ((relval) >> 28)
  33. #define FLAT_V850_R_32 0 /* Normal 32-bit reloc */
  34. #define FLAT_V850_R_HI16S_LO15 1 /* High 16-bits + signed 15-bit low field */
  35. #define FLAT_V850_R_HI16S_LO16 2 /* High 16-bits + signed 16-bit low field */
  36. /* Extract the address to be relocated from the symbol reference at RP;
  37. RELVAL is the raw relocation-table entry from which RP is derived.
  38. For the v850, RP should always be half-word aligned. */
  39. static inline unsigned long flat_get_addr_from_rp (unsigned long *rp,
  40. unsigned long relval,
  41. unsigned long flags,
  42. unsigned long *persistent)
  43. {
  44. short *srp = (short *)rp;
  45. switch (flat_v850_get_reloc_type (relval))
  46. {
  47. case FLAT_V850_R_32:
  48. /* Simple 32-bit address. */
  49. return srp[0] | (srp[1] << 16);
  50. case FLAT_V850_R_HI16S_LO16:
  51. /* The high and low halves of the address are in the 16
  52. bits at RP, and the 2nd word of the 32-bit instruction
  53. following that, respectively. The low half is _signed_
  54. so we have to sign-extend it and add it to the upper
  55. half instead of simply or-ing them together.
  56. Unlike most relocated address, this one is stored in
  57. native (little-endian) byte-order to avoid problems with
  58. trashing the low-order bit, so we have to convert to
  59. network-byte-order before returning, as that's what the
  60. caller expects. */
  61. return htonl ((srp[0] << 16) + srp[2]);
  62. case FLAT_V850_R_HI16S_LO15:
  63. /* The high and low halves of the address are in the 16
  64. bits at RP, and the upper 15 bits of the 2nd word of the
  65. 32-bit instruction following that, respectively. The
  66. low half is _signed_ so we have to sign-extend it and
  67. add it to the upper half instead of simply or-ing them
  68. together. The lowest bit is always zero.
  69. Unlike most relocated address, this one is stored in
  70. native (little-endian) byte-order to avoid problems with
  71. trashing the low-order bit, so we have to convert to
  72. network-byte-order before returning, as that's what the
  73. caller expects. */
  74. return htonl ((srp[0] << 16) + (srp[2] & ~0x1));
  75. default:
  76. return ~0; /* bogus value */
  77. }
  78. }
  79. /* Insert the address ADDR into the symbol reference at RP;
  80. RELVAL is the raw relocation-table entry from which RP is derived.
  81. For the v850, RP should always be half-word aligned. */
  82. static inline void flat_put_addr_at_rp (unsigned long *rp, unsigned long addr,
  83. unsigned long relval)
  84. {
  85. short *srp = (short *)rp;
  86. switch (flat_v850_get_reloc_type (relval)) {
  87. case FLAT_V850_R_32:
  88. /* Simple 32-bit address. */
  89. srp[0] = addr & 0xFFFF;
  90. srp[1] = (addr >> 16);
  91. break;
  92. case FLAT_V850_R_HI16S_LO16:
  93. /* The high and low halves of the address are in the 16
  94. bits at RP, and the 2nd word of the 32-bit instruction
  95. following that, respectively. The low half is _signed_
  96. so we must carry its sign bit to the upper half before
  97. writing the upper half. */
  98. srp[0] = (addr >> 16) + ((addr >> 15) & 0x1);
  99. srp[2] = addr & 0xFFFF;
  100. break;
  101. case FLAT_V850_R_HI16S_LO15:
  102. /* The high and low halves of the address are in the 16
  103. bits at RP, and the upper 15 bits of the 2nd word of the
  104. 32-bit instruction following that, respectively. The
  105. low half is _signed_ so we must carry its sign bit to
  106. the upper half before writing the upper half. The
  107. lowest bit we preserve from the existing instruction. */
  108. srp[0] = (addr >> 16) + ((addr >> 15) & 0x1);
  109. srp[2] = (addr & 0xFFFE) | (srp[2] & 0x1);
  110. break;
  111. }
  112. }
  113. #endif /* __V850_FLAT_H__ */