Michal Simek | c6087fd | 2009-03-27 14:25:34 +0100 | [diff] [blame] | 1 | /* |
| 2 | * uClinux flat-format executables |
| 3 | * |
| 4 | * Copyright (C) 2005 John Williams <jwilliams@itee.uq.edu.au> |
| 5 | * |
| 6 | * This file is subject to the terms and conditions of the GNU General |
| 7 | * Public License. See the file COPYING in the main directory of this |
| 8 | * archive for more details. |
| 9 | */ |
| 10 | |
| 11 | #ifndef _ASM_MICROBLAZE_FLAT_H |
| 12 | #define _ASM_MICROBLAZE_FLAT_H |
| 13 | |
| 14 | #include <asm/unaligned.h> |
| 15 | |
Michal Simek | c6087fd | 2009-03-27 14:25:34 +0100 | [diff] [blame] | 16 | #define flat_argvp_envp_on_stack() 0 |
| 17 | #define flat_old_ram_flag(flags) (flags) |
| 18 | #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) |
| 19 | #define flat_set_persistent(relval, p) 0 |
| 20 | |
| 21 | /* |
| 22 | * Microblaze works a little differently from other arches, because |
| 23 | * of the MICROBLAZE_64 reloc type. Here, a 32 bit address is split |
| 24 | * over two instructions, an 'imm' instruction which provides the top |
| 25 | * 16 bits, then the instruction "proper" which provides the low 16 |
| 26 | * bits. |
| 27 | */ |
| 28 | |
| 29 | /* |
| 30 | * Crack open a symbol reference and extract the address to be |
| 31 | * relocated. rp is a potentially unaligned pointer to the |
| 32 | * reference |
| 33 | */ |
| 34 | |
| 35 | static inline unsigned long |
| 36 | flat_get_addr_from_rp(unsigned long *rp, unsigned long relval, |
| 37 | unsigned long flags, unsigned long *persistent) |
| 38 | { |
| 39 | unsigned long addr; |
| 40 | (void)flags; |
| 41 | |
| 42 | /* Is it a split 64/32 reference? */ |
| 43 | if (relval & 0x80000000) { |
| 44 | /* Grab the two halves of the reference */ |
| 45 | unsigned long val_hi, val_lo; |
| 46 | |
| 47 | val_hi = get_unaligned(rp); |
| 48 | val_lo = get_unaligned(rp+1); |
| 49 | |
| 50 | /* Crack the address out */ |
| 51 | addr = ((val_hi & 0xffff) << 16) + (val_lo & 0xffff); |
| 52 | } else { |
| 53 | /* Get the address straight out */ |
| 54 | addr = get_unaligned(rp); |
| 55 | } |
| 56 | |
| 57 | return addr; |
| 58 | } |
| 59 | |
| 60 | /* |
| 61 | * Insert an address into the symbol reference at rp. rp is potentially |
| 62 | * unaligned. |
| 63 | */ |
| 64 | |
| 65 | static inline void |
| 66 | flat_put_addr_at_rp(unsigned long *rp, unsigned long addr, unsigned long relval) |
| 67 | { |
| 68 | /* Is this a split 64/32 reloc? */ |
| 69 | if (relval & 0x80000000) { |
| 70 | /* Get the two "halves" */ |
| 71 | unsigned long val_hi = get_unaligned(rp); |
| 72 | unsigned long val_lo = get_unaligned(rp + 1); |
| 73 | |
| 74 | /* insert the address */ |
| 75 | val_hi = (val_hi & 0xffff0000) | addr >> 16; |
| 76 | val_lo = (val_lo & 0xffff0000) | (addr & 0xffff); |
| 77 | |
| 78 | /* store the two halves back into memory */ |
| 79 | put_unaligned(val_hi, rp); |
| 80 | put_unaligned(val_lo, rp+1); |
| 81 | } else { |
| 82 | /* Put it straight in, no messing around */ |
| 83 | put_unaligned(addr, rp); |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | #define flat_get_relocate_addr(rel) (rel & 0x7fffffff) |
| 88 | |
| 89 | #endif /* _ASM_MICROBLAZE_FLAT_H */ |