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