summaryrefslogtreecommitdiff
path: root/drivers/staging/tidspbridge/dynload/reloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/tidspbridge/dynload/reloc.c')
-rw-r--r--drivers/staging/tidspbridge/dynload/reloc.c486
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 */