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