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