Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Functions | Variables
cgen.c File Reference
#include <setjmp.h>
#include "as.h"
#include "symcat.h"
#include "cgen-desc.h"
#include "subsegs.h"
#include "cgen.h"
#include "dwarf2dbg.h"
#include "symbols.h"
#include "struc-symbol.h"

Go to the source code of this file.

Classes

struct  fixup
struct  saved_fixups

Defines

#define md_cgen_record_fixup_exp   gas_cgen_record_fixup_exp

Functions

static void queue_fixup (int, int, expressionS *)
void cgen_asm_record_register (char *name, int number)
void gas_cgen_init_parse ()
void gas_cgen_initialize_saved_fixups_array ()
void gas_cgen_save_fixups (int i)
void gas_cgen_restore_fixups (int i)
void gas_cgen_swap_fixups (int i)
fixS * gas_cgen_record_fixup (fragS *frag, int where, const CGEN_INSN *insn, int length, const CGEN_OPERAND *operand, int opinfo, symbolS *symbol, offsetT offset)
fixS * gas_cgen_record_fixup_exp (fragS *frag, int where, const CGEN_INSN *insn, int length, const CGEN_OPERAND *operand, int opinfo, expressionS *exp)
const char * gas_cgen_parse_operand (cd, enum cgen_parse_operand_type want, const char **strP, int opindex, int opinfo, enum cgen_parse_operand_result *resultP, bfd_vma *valueP)
void gas_cgen_md_operand (expressionP)
void gas_cgen_finish_insn (CGEN_INSN *insn, CGEN_INSN_BYTES_PTR buf, unsigned int length, int relax_p, finished_insnS *result) const
void gas_cgen_md_apply_fix (fixS *fixP, valueT *valP, seg)
arelentgas_cgen_tc_gen_reloc (section, fixS *fixP)
void gas_cgen_begin ()

Variables

CGEN_CPU_DESC gas_cgen_cpu_desc
static struct fixup [GAS_CGEN_MAX_FIXUPS]
static int num_fixups
static struct saved_fixups [MAX_SAVED_FIXUP_CHAINS]
static jmp_buf expr_jmp_buf
static int expr_jmp_buf_p

Class Documentation

struct fixup

Definition at line 133 of file i386linux.c.

Collaboration diagram for fixup:
Class Members
char builtin
expressionS exp
struct cgen_maybe_multi_ifield * field
struct linux_link_hash_entry * h
char jump
int msb_field_p
struct fixup * next
int opindex
int opinfo
bfd_vma value
struct saved_fixups

Definition at line 154 of file cgen.c.

Class Members
int num_fixups_in_chain

Define Documentation


Function Documentation

void cgen_asm_record_register ( char *  name,
int  number 
)

Definition at line 61 of file cgen.c.

{
  /* Use symbol_create here instead of symbol_new so we don't try to
     output registers into the object file's symbol table.  */
  symbol_table_insert (symbol_create (name, reg_section,
                                  number, &zero_address_frag));
}

Here is the call graph for this function:

void gas_cgen_begin ( void  )

Definition at line 1057 of file cgen.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void gas_cgen_finish_insn ( CGEN_INSN *  insn,
CGEN_INSN_BYTES_PTR  buf,
unsigned int  length,
int  relax_p,
finished_insnS result 
) const

Definition at line 543 of file cgen.c.

{
  int i;
  int relax_operand;
  char *f;
  unsigned int byte_len = length / 8;

  /* ??? Target foo issues various warnings here, so one might want to provide
     a hook here.  However, our caller is defined in tc-foo.c so there
     shouldn't be a need for a hook.  */

  /* Write out the instruction.
     It is important to fetch enough space in one call to `frag_more'.
     We use (f - frag_now->fr_literal) to compute where we are and we
     don't want frag_now to change between calls.

     Relaxable instructions: We need to ensure we allocate enough
     space for the largest insn.  */

  if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
    /* These currently shouldn't get here.  */
    abort ();

  /* Is there a relaxable insn with the relaxable operand needing a fixup?  */

  relax_operand = -1;
  if (relax_p && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXABLE))
    {
      /* Scan the fixups for the operand affected by relaxing
        (i.e. the branch address).  */

      for (i = 0; i < num_fixups; ++i)
       {
         if (CGEN_OPERAND_ATTR_VALUE (cgen_operand_lookup_by_num (gas_cgen_cpu_desc, fixups[i].opindex),
                                   CGEN_OPERAND_RELAX))
           {
             relax_operand = i;
             break;
           }
       }
    }

  if (relax_operand != -1)
    {
      int max_len;
      fragS *old_frag;
      expressionS *exp;
      symbolS *sym;
      offsetT off;

#ifdef TC_CGEN_MAX_RELAX
      max_len = TC_CGEN_MAX_RELAX (insn, byte_len);
#else
      max_len = CGEN_MAX_INSN_SIZE;
#endif
      /* Ensure variable part and fixed part are in same fragment.  */
      /* FIXME: Having to do this seems like a hack.  */
      frag_grow (max_len);

      /* Allocate space for the fixed part.  */
      f = frag_more (byte_len);

      /* Create a relaxable fragment for this instruction.  */
      old_frag = frag_now;

      exp = &fixups[relax_operand].exp;
      sym = exp->X_add_symbol;
      off = exp->X_add_number;
      if (exp->X_op != O_constant && exp->X_op != O_symbol)
       {
         /* Handle complex expressions.  */
         sym = make_expr_symbol (exp);
         off = 0;
       }

      frag_var (rs_machine_dependent,
              max_len - byte_len /* max chars */,
              0 /* variable part already allocated */,
              /* FIXME: When we machine generate the relax table,
                 machine generate a macro to compute subtype.  */
              1 /* subtype */,
              sym,
              off,
              f);

      /* Record the operand number with the fragment so md_convert_frag
        can use gas_cgen_md_record_fixup to record the appropriate reloc.  */
      old_frag->fr_cgen.insn    = insn;
      old_frag->fr_cgen.opindex = fixups[relax_operand].opindex;
      old_frag->fr_cgen.opinfo  = fixups[relax_operand].opinfo;
      if (result)
       result->frag = old_frag;
    }
  else
    {
      f = frag_more (byte_len);
      if (result)
       result->frag = frag_now;
    }

  /* If we're recording insns as numbers (rather than a string of bytes),
     target byte order handling is deferred until now.  */
#if CGEN_INT_INSN_P
  cgen_put_insn_value (gas_cgen_cpu_desc, (unsigned char *) f, length, *buf);
#else
  memcpy (f, buf, byte_len);
#endif

  /* Emit DWARF2 debugging information.  */
  dwarf2_emit_insn (byte_len);

  /* Create any fixups.  */
  for (i = 0; i < num_fixups; ++i)
    {
      fixS *fixP;
      const CGEN_OPERAND *operand =
       cgen_operand_lookup_by_num (gas_cgen_cpu_desc, fixups[i].opindex);

      /* Don't create fixups for these.  That's done during relaxation.
        We don't need to test for CGEN_INSN_RELAXED as they can't get here
        (see above).  */
      if (relax_p
         && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXABLE)
         && CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_RELAX))
       continue;

#ifndef md_cgen_record_fixup_exp
#define md_cgen_record_fixup_exp gas_cgen_record_fixup_exp
#endif

      fixP = md_cgen_record_fixup_exp (frag_now, f - frag_now->fr_literal,
                                   insn, length, operand,
                                   fixups[i].opinfo,
                                   &fixups[i].exp);
      fixP->fx_cgen.field = fixups[i].field;
      fixP->fx_cgen.msb_field_p = fixups[i].msb_field_p;
      if (result)
       result->fixups[i] = fixP;
    }

  if (result)
    {
      result->num_fixups = num_fixups;
      result->addr = f;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void gas_cgen_init_parse ( void  )

Definition at line 98 of file cgen.c.

{
  num_fixups = 0;
}

Here is the caller graph for this function:

Definition at line 163 of file cgen.c.

{
  int i = 0;

  while (i < MAX_SAVED_FIXUP_CHAINS)
    stored_fixups[i++].num_fixups_in_chain = 0;
}

Here is the caller graph for this function:

void gas_cgen_md_apply_fix ( fixS *  fixP,
valueT valP,
seg   
)

Definition at line 869 of file cgen.c.

{
  char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
  valueT value = * valP;
  /* Canonical name, since used a lot.  */
  CGEN_CPU_DESC cd = gas_cgen_cpu_desc;

  if (fixP->fx_addsy == (symbolS *) NULL)
    fixP->fx_done = 1;

  /* We don't actually support subtracting a symbol.  */
  if (fixP->fx_subsy != (symbolS *) NULL)
    as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));

  if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
    {
      int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
      const CGEN_OPERAND *operand = cgen_operand_lookup_by_num (cd, opindex);
      const char *errmsg;
      bfd_reloc_code_real_type reloc_type;
      CGEN_FIELDS *fields = alloca (CGEN_CPU_SIZEOF_FIELDS (cd));
      const CGEN_INSN *insn = fixP->fx_cgen.insn;
      int start;
      int length;
      int signed_p = 0;

      if (fixP->fx_cgen.field)
       {            
         /* Use the twisty little pointer path
            back to the ifield if it exists.  */
         start = fixP->fx_cgen.field->val.leaf->start;
         length = fixP->fx_cgen.field->val.leaf->length;
       }
      else
       {
         /* Or the far less useful operand-size guesstimate.  */
         start = operand->start;
         length = operand->length;
       }

      /* FIXME: this is not a perfect heuristic for figuring out
         whether an operand is signed: it only works when the operand
         is an immediate. it's not terribly likely that any other
         values will be signed relocs, but it's possible. */
      if (operand && (operand->hw_type == HW_H_SINT))
        signed_p = 1;

      /* If the reloc has been fully resolved finish the operand here.  */
      /* FIXME: This duplicates the capabilities of code in BFD.  */
      if (fixP->fx_done
         /* FIXME: If partial_inplace isn't set bfd_install_relocation won't
            finish the job.  Testing for pcrel is a temporary hack.  */
         || fixP->fx_pcrel)
       {
         CGEN_CPU_SET_FIELDS_BITSIZE (cd) (fields, CGEN_INSN_BITSIZE (insn));
         CGEN_CPU_SET_VMA_OPERAND (cd) (cd, opindex, fields, (bfd_vma) value);

#if CGEN_INT_INSN_P
         {
           CGEN_INSN_INT insn_value =
             cgen_get_insn_value (cd, (unsigned char *) where,
                               CGEN_INSN_BITSIZE (insn));

           /* ??? 0 is passed for `pc'.  */
           errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
                                             &insn_value, (bfd_vma) 0);
           cgen_put_insn_value (cd, (unsigned char *) where,
                             CGEN_INSN_BITSIZE (insn), insn_value);
         }
#else
         /* ??? 0 is passed for `pc'.  */
         errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
                                           (unsigned char *) where,
                                           (bfd_vma) 0);
#endif
         if (errmsg)
           as_bad_where (fixP->fx_file, fixP->fx_line, "%s", errmsg);
       }

      if (fixP->fx_done)
       return;

      /* The operand isn't fully resolved.  Determine a BFD reloc value
        based on the operand information and leave it to
        bfd_install_relocation.  Note that this doesn't work when
        partial_inplace == false.  */

      reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
#ifdef OBJ_COMPLEX_RELC
      if (reloc_type == BFD_RELOC_RELC)
       {
         /* Change addend to "self-describing" form,
            for BFD to handle in the linker.  */
         value = gas_cgen_encode_addend (start, operand->length,
                                     length, fixP->fx_size, 
                                     cd->insn_chunk_bitsize / 8, 
                                     signed_p, 
                                     ! (fixP->fx_cgen.msb_field_p));
       }
#endif

      if (reloc_type != BFD_RELOC_NONE)
       fixP->fx_r_type = reloc_type;
      else
       {
         as_bad_where (fixP->fx_file, fixP->fx_line,
                     _("unresolved expression that must be resolved"));
         fixP->fx_done = 1;
         return;
       }
    }
  else if (fixP->fx_done)
    {
      /* We're finished with this fixup.  Install it because
        bfd_install_relocation won't be called to do it.  */
      switch (fixP->fx_r_type)
       {
       case BFD_RELOC_8:
         md_number_to_chars (where, value, 1);
         break;
       case BFD_RELOC_16:
         md_number_to_chars (where, value, 2);
         break;
       case BFD_RELOC_32:
         md_number_to_chars (where, value, 4);
         break;
       case BFD_RELOC_64:
         md_number_to_chars (where, value, 8);
         break;
       default:
         as_bad_where (fixP->fx_file, fixP->fx_line,
                     _("internal error: can't install fix for reloc type %d (`%s')"),
                     fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
         break;
       }
    }
  /* else
     bfd_install_relocation will be called to finish things up.  */

  /* Tuck `value' away for use by tc_gen_reloc.
     See the comment describing fx_addnumber in write.h.
     This field is misnamed (or misused :-).  */
  fixP->fx_addnumber = value;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void gas_cgen_md_operand ( expressionP  )

Definition at line 527 of file cgen.c.

{
  /* Don't longjmp if we're not called from within cgen_parse_operand().  */
  if (expr_jmp_buf_p)
    longjmp (expr_jmp_buf, 1);
}

Here is the caller graph for this function:

const char* gas_cgen_parse_operand ( cd  ,
enum cgen_parse_operand_type  want,
const char **  strP,
int  opindex,
int  opinfo,
enum cgen_parse_operand_result resultP,
bfd_vma valueP 
)

Definition at line 348 of file cgen.c.

{
#ifdef __STDC__
  /* These are volatile to survive the setjmp.  */
  char * volatile hold;
  enum cgen_parse_operand_result * volatile resultP_1;
  volatile int opinfo_1;
#else
  static char *hold;
  static enum cgen_parse_operand_result *resultP_1;
  int opinfo_1;
#endif
  const char *errmsg;
  expressionS exp;

#ifdef OBJ_COMPLEX_RELC
  volatile int              signed_p = 0;
  symbolS *                 stmp = NULL;
  bfd_reloc_code_real_type  reloc_type;
  const CGEN_OPERAND *      operand;
  fixS                      dummy_fixup;
#endif
  if (want == CGEN_PARSE_OPERAND_INIT)
    {
      gas_cgen_init_parse ();
      return NULL;
    }

  resultP_1 = resultP;
  hold = input_line_pointer;
  input_line_pointer = (char *) *strP;
  opinfo_1 = opinfo;

  /* We rely on md_operand to longjmp back to us.
     This is done via gas_cgen_md_operand.  */
  if (setjmp (expr_jmp_buf) != 0)
    {
      expr_jmp_buf_p = 0;
      input_line_pointer = (char *) hold;
      *resultP_1 = CGEN_PARSE_OPERAND_RESULT_ERROR;
      return _("illegal operand");
    }

  expr_jmp_buf_p = 1;
  expression (&exp);
  expr_jmp_buf_p = 0;
  errmsg = NULL;

  *strP = input_line_pointer;
  input_line_pointer = hold;

#ifdef TC_CGEN_PARSE_FIX_EXP
  opinfo_1 = TC_CGEN_PARSE_FIX_EXP (opinfo_1, & exp);
#endif 

  /* FIXME: Need to check `want'.  */

  switch (exp.X_op)
    {
    case O_illegal:
      errmsg = _("illegal operand");
      *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
      break;
    case O_absent:
      errmsg = _("missing operand");
      *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
      break;
    case O_constant:
      if (want == CGEN_PARSE_OPERAND_SYMBOLIC)
       goto de_fault;
      *valueP = exp.X_add_number;
      *resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER;
      break;
    case O_register:
      *valueP = exp.X_add_number;
      *resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER;
      break;
    de_fault:
    default:
#ifdef OBJ_COMPLEX_RELC
      /* Look up operand, check to see if there's an obvious
        overflow (this helps disambiguate some insn parses).  */
      operand = cgen_operand_lookup_by_num (cd, opindex);
      errmsg = weak_operand_overflow_check (& exp, operand);

      if (! errmsg)
       {
         /* Fragment the expression as necessary, and queue a reloc.  */
         memset (& dummy_fixup, 0, sizeof (fixS));

         reloc_type = md_cgen_lookup_reloc (0, operand, & dummy_fixup);

         if (exp.X_op == O_symbol
             && reloc_type == BFD_RELOC_RELC
             && exp.X_add_symbol->sy_value.X_op == O_constant
             && exp.X_add_symbol->bsym->section != expr_section
             && exp.X_add_symbol->bsym->section != absolute_section
             && exp.X_add_symbol->bsym->section != undefined_section)
           {
             /* Local labels will have been (eagerly) turned into constants
               by now, due to the inappropriately deep insight of the
               expression parser.  Unfortunately make_expr_symbol
               prematurely dives into the symbol evaluator, and in this
               case it gets a bad answer, so we manually create the
               expression symbol we want here.  */
             stmp = symbol_create (FAKE_LABEL_NAME, expr_section, 0,
                                & zero_address_frag);
             symbol_set_value_expression (stmp, & exp);
           } 
         else 
           stmp = make_expr_symbol (& exp);

         /* If this is a pc-relative RELC operand, we
            need to subtract "." from the expression.  */        
         if (reloc_type == BFD_RELOC_RELC
             && CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR))
           stmp = expr_build_binary (O_subtract, stmp, expr_build_dot ()); 

         /* FIXME: this is not a perfect heuristic for figuring out
            whether an operand is signed: it only works when the operand
            is an immediate. it's not terribly likely that any other
            values will be signed relocs, but it's possible. */
         if (operand && (operand->hw_type == HW_H_SINT))
           signed_p = 1;
         
         if (stmp->bsym && (stmp->bsym->section == expr_section))
           {
             if (signed_p)
              stmp->bsym->flags |= BSF_SRELC;
             else
              stmp->bsym->flags |= BSF_RELC;
           }
         
         /* Now package it all up for the fixup emitter.  */
         exp.X_op = O_symbol;
         exp.X_op_symbol = 0;
         exp.X_add_symbol = stmp;
         exp.X_add_number = 0;
             
         /* Re-init rightshift quantity, just in case.  */
         rightshift = operand->length;
         queue_fixup_recursively (opindex, opinfo_1, & exp,  
                               (reloc_type == BFD_RELOC_RELC) ?
                               & (operand->index_fields) : 0,
                               signed_p, -1);
       }
      * resultP = errmsg
       ? CGEN_PARSE_OPERAND_RESULT_ERROR
       : CGEN_PARSE_OPERAND_RESULT_QUEUED;
      *valueP = 0;
#else
      queue_fixup (opindex, opinfo_1, &exp);
      *valueP = 0;
      *resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED;
#endif      
      break;
    }

  return errmsg;
}

Here is the call graph for this function:

Here is the caller graph for this function:

fixS* gas_cgen_record_fixup ( fragS *  frag,
int  where,
const CGEN_INSN *  insn,
int  length,
const CGEN_OPERAND operand,
int  opinfo,
symbolS *  symbol,
offsetT  offset 
)

Definition at line 251 of file cgen.c.

{
  fixS *fixP;

  /* It may seem strange to use operand->attrs and not insn->attrs here,
     but it is the operand that has a pc relative relocation.  */
  fixP = fix_new (frag, where, length / 8, symbol, offset,
                CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
                (bfd_reloc_code_real_type)
                  ((int) BFD_RELOC_UNUSED
                   + (int) operand->type));
  fixP->fx_cgen.insn = insn;
  fixP->fx_cgen.opinfo = opinfo;
  fixP->fx_cgen.field = NULL;
  fixP->fx_cgen.msb_field_p = 0;

  return fixP;
}

Here is the call graph for this function:

Here is the caller graph for this function:

fixS* gas_cgen_record_fixup_exp ( fragS *  frag,
int  where,
const CGEN_INSN *  insn,
int  length,
const CGEN_OPERAND operand,
int  opinfo,
expressionS exp 
)

Definition at line 292 of file cgen.c.

{
  fixS *fixP;

  /* It may seem strange to use operand->attrs and not insn->attrs here,
     but it is the operand that has a pc relative relocation.  */
  fixP = fix_new_exp (frag, where, length / 8, exp,
                    CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
                    (bfd_reloc_code_real_type)
                      ((int) BFD_RELOC_UNUSED
                      + (int) operand->type));
  fixP->fx_cgen.insn = insn;
  fixP->fx_cgen.opinfo = opinfo;
  fixP->fx_cgen.field = NULL;
  fixP->fx_cgen.msb_field_p = 0;

  return fixP;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 188 of file cgen.c.

{
  if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
    {
      as_fatal ("index into stored_fixups[] out of bounds");
      return;
    }

  num_fixups = stored_fixups[i].num_fixups_in_chain;
  memcpy (fixups, stored_fixups[i].fixup_chain,
         (sizeof (stored_fixups[i].fixup_chain[0])) * num_fixups);
  stored_fixups[i].num_fixups_in_chain = 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 172 of file cgen.c.

{
  if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
    {
      as_fatal ("index into stored_fixups[] out of bounds");
      return;
    }

  stored_fixups[i].num_fixups_in_chain = num_fixups;
  memcpy (stored_fixups[i].fixup_chain, fixups,
         sizeof (fixups[0]) * num_fixups);
  num_fixups = 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 204 of file cgen.c.

{
  if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
    {
      as_fatal ("index into stored_fixups[] out of bounds");
      return;
    }

  if (num_fixups == 0)
    gas_cgen_restore_fixups (i);

  else if (stored_fixups[i].num_fixups_in_chain == 0)
    gas_cgen_save_fixups (i);

  else
    {
      int tmp;
      struct fixup tmp_fixup;

      tmp = stored_fixups[i].num_fixups_in_chain;
      stored_fixups[i].num_fixups_in_chain = num_fixups;
      num_fixups = tmp;

      for (tmp = GAS_CGEN_MAX_FIXUPS; tmp--;)
       {
         tmp_fixup = stored_fixups[i].fixup_chain [tmp];
         stored_fixups[i].fixup_chain[tmp] = fixups [tmp];
         fixups [tmp] = tmp_fixup;
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

arelent* gas_cgen_tc_gen_reloc ( section  ,
fixS *  fixP 
)

Definition at line 1022 of file cgen.c.

{
  arelent *reloc;
  reloc = (arelent *) xmalloc (sizeof (arelent));

  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
  if (reloc->howto == (reloc_howto_type *) NULL)
    {
      as_bad_where (fixP->fx_file, fixP->fx_line,
                  _("relocation is not supported"));
      return NULL;
    }

  assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);

  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);

  /* Use fx_offset for these cases.  */
  if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
      || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT)
    reloc->addend = fixP->fx_offset;
  else
    reloc->addend = fixP->fx_addnumber;

  reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
  return reloc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void queue_fixup ( int  opindex,
int  opinfo,
expressionS expP 
) [static]

Definition at line 106 of file cgen.c.

{
  /* We need to generate a fixup for this expression.  */
  if (num_fixups >= GAS_CGEN_MAX_FIXUPS)
    as_fatal (_("too many fixups"));
  fixups[num_fixups].exp     = *expP;
  fixups[num_fixups].opindex = opindex;
  fixups[num_fixups].opinfo  = opinfo;
  ++ num_fixups;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

jmp_buf expr_jmp_buf [static]

Definition at line 333 of file cgen.c.

int expr_jmp_buf_p [static]

Definition at line 334 of file cgen.c.

Definition at line 91 of file cgen.c.

Definition at line 54 of file cgen.c.

int num_fixups [static]

Definition at line 92 of file cgen.c.

Definition at line 160 of file cgen.c.