diff options
Diffstat (limited to 'drivers/staging/tidspbridge/dynload/reloc.c')
-rw-r--r-- | drivers/staging/tidspbridge/dynload/reloc.c | 486 |
1 files changed, 0 insertions, 486 deletions
diff --git a/drivers/staging/tidspbridge/dynload/reloc.c b/drivers/staging/tidspbridge/dynload/reloc.c deleted file mode 100644 index bb422b693290..000000000000 --- a/drivers/staging/tidspbridge/dynload/reloc.c +++ /dev/null @@ -1,486 +0,0 @@ -/* - * reloc.c - * - * DSP-BIOS Bridge driver support functions for TI OMAP processors. - * - * Copyright (C) 2005-2006 Texas Instruments, Inc. - * - * This package is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#include "header.h" - -#if TMS32060 -/* the magic symbol for the start of BSS */ -static const char bsssymbol[] = { ".bss" }; -#endif - -#if TMS32060 -#include "reloc_table_c6000.c" -#endif - -#if TMS32060 -/* From coff.h - ignore these relocation operations */ -#define R_C60ALIGN 0x76 /* C60: Alignment info for compressor */ -#define R_C60FPHEAD 0x77 /* C60: Explicit assembly directive */ -#define R_C60NOCMP 0x100 /* C60: Don't compress this code scn */ -#endif - -/************************************************************************** - * Procedure dload_unpack - * - * Parameters: - * data pointer to storage unit containing lowest host address of - * image data - * fieldsz Size of bit field, 0 < fieldsz <= sizeof(rvalue)*BITS_PER_AU - * offset Offset from LSB, 0 <= offset < BITS_PER_AU - * sgn Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY) - * - * Effect: - * Extracts the specified field and returns it. - ************************************************************************* */ -rvalue dload_unpack(struct dload_state *dlthis, tgt_au_t *data, int fieldsz, - int offset, unsigned sgn) -{ - register rvalue objval; - register int shift, direction; - register tgt_au_t *dp = data; - - fieldsz -= 1; /* avoid nastiness with 32-bit shift of 32-bit value */ - /* * collect up enough bits to contain the desired field */ - if (TARGET_BIG_ENDIAN) { - dp += (fieldsz + offset) >> LOG_TGTAU_BITS; - direction = -1; - } else - direction = 1; - objval = *dp >> offset; - shift = TGTAU_BITS - offset; - while (shift <= fieldsz) { - dp += direction; - objval += (rvalue) *dp << shift; - shift += TGTAU_BITS; - } - - /* * sign or zero extend the value appropriately */ - if (sgn == ROP_UNS) - objval &= (2 << fieldsz) - 1; - else { - shift = sizeof(rvalue) * BITS_PER_AU - 1 - fieldsz; - objval = (objval << shift) >> shift; - } - - return objval; - -} /* dload_unpack */ - -/************************************************************************** - * Procedure dload_repack - * - * Parameters: - * val Value to insert - * data Pointer to storage unit containing lowest host address of - * image data - * fieldsz Size of bit field, 0 < fieldsz <= sizeof(rvalue)*BITS_PER_AU - * offset Offset from LSB, 0 <= offset < BITS_PER_AU - * sgn Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY) - * - * Effect: - * Stuffs the specified value in the specified field. Returns 0 for - * success - * or 1 if the value will not fit in the specified field according to the - * specified signedness rule. - ************************************************************************* */ -static const unsigned char ovf_limit[] = { 1, 2, 2 }; - -int dload_repack(struct dload_state *dlthis, rvalue val, tgt_au_t *data, - int fieldsz, int offset, unsigned sgn) -{ - register urvalue objval, mask; - register int shift, direction; - register tgt_au_t *dp = data; - - fieldsz -= 1; /* avoid nastiness with 32-bit shift of 32-bit value */ - /* clip the bits */ - mask = (2UL << fieldsz) - 1; - objval = (val & mask); - /* * store the bits through the specified mask */ - if (TARGET_BIG_ENDIAN) { - dp += (fieldsz + offset) >> LOG_TGTAU_BITS; - direction = -1; - } else - direction = 1; - - /* insert LSBs */ - *dp = (*dp & ~(mask << offset)) + (objval << offset); - shift = TGTAU_BITS - offset; - /* align mask and objval with AU boundary */ - objval >>= shift; - mask >>= shift; - - while (mask) { - dp += direction; - *dp = (*dp & ~mask) + objval; - objval >>= TGTAU_BITS; - mask >>= TGTAU_BITS; - } - - /* - * check for overflow - */ - if (sgn) { - unsigned tmp = (val >> fieldsz) + (sgn & 0x1); - - if (tmp > ovf_limit[sgn - 1]) - return 1; - } - return 0; - -} /* dload_repack */ - -/* lookup table for the scaling amount in a C6x instruction */ -#if TMS32060 -#define SCALE_BITS 4 /* there are 4 bits in the scale field */ -#define SCALE_MASK 0x7 /* we really only use the bottom 3 bits */ -static const u8 c60_scale[SCALE_MASK + 1] = { - 1, 0, 0, 0, 1, 1, 2, 2 -}; -#endif - -/************************************************************************** - * Procedure dload_relocate - * - * Parameters: - * data Pointer to base of image data - * rp Pointer to relocation operation - * - * Effect: - * Performs the specified relocation operation - ************************************************************************* */ -void dload_relocate(struct dload_state *dlthis, tgt_au_t *data, - struct reloc_record_t *rp, bool *tramps_generated, - bool second_pass) -{ - rvalue val, reloc_amt, orig_val = 0; - unsigned int fieldsz = 0; - unsigned int offset = 0; - unsigned int reloc_info = 0; - unsigned int reloc_action = 0; - register int rx = 0; - rvalue *stackp = NULL; - int top; - struct local_symbol *svp = NULL; -#ifdef RFV_SCALE - unsigned int scale = 0; -#endif - struct image_packet_t *img_pkt = NULL; - - /* The image packet data struct is only used during first pass - * relocation in the event that a trampoline is needed. 2nd pass - * relocation doesn't guarantee that data is coming from an - * image_packet_t structure. See cload.c, dload_data for how img_data is - * set. If that changes this needs to be updated!!! */ - if (second_pass == false) - img_pkt = (struct image_packet_t *)((u8 *) data - - sizeof(struct - image_packet_t)); - - rx = HASH_FUNC(rp->TYPE); - while (rop_map1[rx] != rp->TYPE) { - rx = HASH_L(rop_map2[rx]); - if (rx < 0) { -#if TMS32060 - switch (rp->TYPE) { - case R_C60ALIGN: - case R_C60NOCMP: - case R_C60FPHEAD: - /* Ignore these reloc types and return */ - break; - default: - /* Unknown reloc type, print error and return */ - dload_error(dlthis, "Bad coff operator 0x%x", - rp->TYPE); - } -#else - dload_error(dlthis, "Bad coff operator 0x%x", rp->TYPE); -#endif - return; - } - } - rx = HASH_I(rop_map2[rx]); - if ((rx < (sizeof(rop_action) / sizeof(u16))) - && (rx < (sizeof(rop_info) / sizeof(u16))) && (rx > 0)) { - reloc_action = rop_action[rx]; - reloc_info = rop_info[rx]; - } else { - dload_error(dlthis, "Buffer Overflow - Array Index Out " - "of Bounds"); - } - - /* Compute the relocation amount for the referenced symbol, if any */ - reloc_amt = rp->UVAL; - if (RFV_SYM(reloc_info)) { /* relocation uses a symbol reference */ - /* If this is first pass, use the module local symbol table, - * else use the trampoline symbol table. */ - if (second_pass == false) { - if ((u32) rp->SYMNDX < dlthis->dfile_hdr.df_no_syms) { - /* real symbol reference */ - svp = &dlthis->local_symtab[rp->SYMNDX]; - reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ? - svp->delta : svp->value; - } - /* reloc references current section */ - else if (rp->SYMNDX == -1) { - reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ? - dlthis->delta_runaddr : - dlthis->image_secn->run_addr; - } - } - } - /* relocation uses a symbol reference */ - /* Handle stack adjustment */ - val = 0; - top = RFV_STK(reloc_info); - if (top) { - top += dlthis->relstkidx - RSTK_UOP; - if (top >= STATIC_EXPR_STK_SIZE) { - dload_error(dlthis, - "Expression stack overflow in %s at offset " - FMT_UI32, dlthis->image_secn->name, - rp->vaddr + dlthis->image_offset); - return; - } - val = dlthis->relstk[dlthis->relstkidx]; - dlthis->relstkidx = top; - stackp = &dlthis->relstk[top]; - } - /* Derive field position and size, if we need them */ - if (reloc_info & ROP_RW) { /* read or write action in our future */ - fieldsz = RFV_WIDTH(reloc_action); - if (fieldsz) { /* field info from table */ - offset = RFV_POSN(reloc_action); - if (TARGET_BIG_ENDIAN) - /* make sure vaddr is the lowest target - * address containing bits */ - rp->vaddr += RFV_BIGOFF(reloc_info); - } else { /* field info from relocation op */ - fieldsz = rp->FIELDSZ; - offset = rp->OFFSET; - if (TARGET_BIG_ENDIAN) - /* make sure vaddr is the lowest target - address containing bits */ - rp->vaddr += (rp->WORDSZ - offset - fieldsz) - >> LOG_TARGET_AU_BITS; - } - data = (tgt_au_t *) ((char *)data + TADDR_TO_HOST(rp->vaddr)); - /* compute lowest host location of referenced data */ -#if BITS_PER_AU > TARGET_AU_BITS - /* conversion from target address to host address may lose - address bits; add loss to offset */ - if (TARGET_BIG_ENDIAN) { - offset += -((rp->vaddr << LOG_TARGET_AU_BITS) + - offset + fieldsz) & - (BITS_PER_AU - TARGET_AU_BITS); - } else { - offset += (rp->vaddr << LOG_TARGET_AU_BITS) & - (BITS_PER_AU - 1); - } -#endif -#ifdef RFV_SCALE - scale = RFV_SCALE(reloc_info); -#endif - } - /* read the object value from the current image, if so ordered */ - if (reloc_info & ROP_R) { - /* relocation reads current image value */ - val = dload_unpack(dlthis, data, fieldsz, offset, - RFV_SIGN(reloc_info)); - /* Save off the original value in case the relo overflows and - * we can trampoline it. */ - orig_val = val; - -#ifdef RFV_SCALE - val <<= scale; -#endif - } - /* perform the necessary arithmetic */ - switch (RFV_ACTION(reloc_action)) { /* relocation actions */ - case RACT_VAL: - break; - case RACT_ASGN: - val = reloc_amt; - break; - case RACT_ADD: - val += reloc_amt; - break; - case RACT_PCR: - /*----------------------------------------------------------- - * Handle special cases of jumping from absolute sections - * (special reloc type) or to absolute destination - * (symndx == -1). In either case, set the appropriate - * relocation amount to 0. - *----------------------------------------------------------- */ - if (rp->SYMNDX == -1) - reloc_amt = 0; - val += reloc_amt - dlthis->delta_runaddr; - break; - case RACT_ADDISP: - val += rp->R_DISP + reloc_amt; - break; - case RACT_ASGPC: - val = dlthis->image_secn->run_addr + reloc_amt; - break; - case RACT_PLUS: - if (stackp != NULL) - val += *stackp; - break; - case RACT_SUB: - if (stackp != NULL) - val = *stackp - val; - break; - case RACT_NEG: - val = -val; - break; - case RACT_MPY: - if (stackp != NULL) - val *= *stackp; - break; - case RACT_DIV: - if (stackp != NULL) - val = *stackp / val; - break; - case RACT_MOD: - if (stackp != NULL) - val = *stackp % val; - break; - case RACT_SR: - if (val >= sizeof(rvalue) * BITS_PER_AU) - val = 0; - else if (stackp != NULL) - val = (urvalue) *stackp >> val; - break; - case RACT_ASR: - if (val >= sizeof(rvalue) * BITS_PER_AU) - val = sizeof(rvalue) * BITS_PER_AU - 1; - else if (stackp != NULL) - val = *stackp >> val; - break; - case RACT_SL: - if (val >= sizeof(rvalue) * BITS_PER_AU) - val = 0; - else if (stackp != NULL) - val = *stackp << val; - break; - case RACT_AND: - if (stackp != NULL) - val &= *stackp; - break; - case RACT_OR: - if (stackp != NULL) - val |= *stackp; - break; - case RACT_XOR: - if (stackp != NULL) - val ^= *stackp; - break; - case RACT_NOT: - val = ~val; - break; -#if TMS32060 - case RACT_C6SECT: - /* actually needed address of secn containing symbol */ - if (svp != NULL) { - if (rp->SYMNDX >= 0) - if (svp->secnn > 0) - reloc_amt = dlthis->ldr_sections - [svp->secnn - 1].run_addr; - } - /* !!! FALL THRU !!! */ - case RACT_C6BASE: - if (dlthis->bss_run_base == 0) { - struct dynload_symbol *symp; - - symp = dlthis->mysym->find_matching_symbol - (dlthis->mysym, bsssymbol); - /* lookup value of global BSS base */ - if (symp) - dlthis->bss_run_base = symp->value; - else - dload_error(dlthis, - "Global BSS base referenced in %s " - "offset" FMT_UI32 " but not " - "defined", - dlthis->image_secn->name, - rp->vaddr + dlthis->image_offset); - } - reloc_amt -= dlthis->bss_run_base; - /* !!! FALL THRU !!! */ - case RACT_C6DSPL: - /* scale factor determined by 3 LSBs of field */ - scale = c60_scale[val & SCALE_MASK]; - offset += SCALE_BITS; - fieldsz -= SCALE_BITS; - val >>= SCALE_BITS; /* ignore the scale field hereafter */ - val <<= scale; - val += reloc_amt; /* do the usual relocation */ - if (((1 << scale) - 1) & val) - dload_error(dlthis, - "Unaligned reference in %s offset " - FMT_UI32, dlthis->image_secn->name, - rp->vaddr + dlthis->image_offset); - break; -#endif - } /* relocation actions */ - /* * Put back result as required */ - if (reloc_info & ROP_W) { /* relocation writes image value */ -#ifdef RFV_SCALE - val >>= scale; -#endif - if (dload_repack(dlthis, val, data, fieldsz, offset, - RFV_SIGN(reloc_info))) { - /* Check to see if this relo can be trampolined, - * but only in first phase relocation. 2nd phase - * relocation cannot trampoline. */ - if ((second_pass == false) && - (dload_tramp_avail(dlthis, rp) == true)) { - - /* Before generating the trampoline, restore - * the value to its original so the 2nd pass - * relo will work. */ - dload_repack(dlthis, orig_val, data, fieldsz, - offset, RFV_SIGN(reloc_info)); - if (!dload_tramp_generate(dlthis, - (dlthis->image_secn - - dlthis->ldr_sections), - dlthis->image_offset, - img_pkt, rp)) { - dload_error(dlthis, - "Failed to " - "generate trampoline for " - "bit overflow"); - dload_error(dlthis, - "Relocation val " FMT_UI32 - " overflows %d bits in %s " - "offset " FMT_UI32, val, - fieldsz, - dlthis->image_secn->name, - dlthis->image_offset + - rp->vaddr); - } else - *tramps_generated = true; - } else { - dload_error(dlthis, "Relocation value " - FMT_UI32 " overflows %d bits in %s" - " offset " FMT_UI32, val, fieldsz, - dlthis->image_secn->name, - dlthis->image_offset + rp->vaddr); - } - } - } else if (top) - *stackp = val; -} /* reloc_value */ |