Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Functions | Variables
tc-ppc.c File Reference
#include "as.h"
#include "safe-ctype.h"
#include "subsegs.h"
#include "dw2gencfi.h"
#include "opcode/ppc.h"

Go to the source code of this file.

Classes

struct  pd_reg
struct  ppc_fixup

Defines

#define TARGET_REG_NAMES_P   FALSE
#define PPC_LO(v)   ((v) & 0xffff)
#define PPC_HI(v)   (((v) >> 16) & 0xffff)
#define PPC_HA(v)   PPC_HI ((v) + 0x8000)
#define PPC_HIGHER(v)   (((v) >> 16 >> 16) & 0xffff)
#define PPC_HIGHERA(v)   PPC_HIGHER ((v) + 0x8000)
#define PPC_HIGHEST(v)   (((v) >> 24 >> 24) & 0xffff)
#define PPC_HIGHESTA(v)   PPC_HIGHEST ((v) + 0x8000)
#define SEX16(val)   ((((val) & 0xffff) ^ 0x8000) - 0x8000)
#define REG_NAME_CNT   (sizeof (pre_defined_registers) / sizeof (struct pd_reg))
#define MAX_INSN_FIXUPS   (5)

Functions

static bfd_boolean register_name PARAMS ((expressionS *))
static void ppc_set_cpu PARAMS ((void))
static unsigned long
ppc_insert_operand 
PARAMS ((unsigned long insn, const struct powerpc_operand *operand, offsetT val, char *file, unsigned int line))
static void ppc_macro PARAMS ((char *str, const struct powerpc_macro *macro))
static void ppc_byte PARAMS ((int))
static int reg_name_search PARAMS ((const struct pd_reg *, int, const char *name))
static int reg_name_search (struct pd_reg *regs, int regcount, const char *name) const
static bfd_boolean register_name (expressionS *expressionP)
int ppc_parse_name (char *name, expressionS *expr) const
static int parse_cpu (const char *arg)
int md_parse_option (int c, char *arg)
void md_show_usage (FILE *stream)
static void ppc_set_cpu ()
enum bfd_architecture ppc_arch ()
unsigned long ppc_mach ()
char * ppc_target_format ()
static void ppc_setup_opcodes (void)
void md_begin ()
void ppc_cleanup ()
static unsigned long ppc_insert_operand (unsigned long insn, const struct powerpc_operand *operand, offsetT val, char *file, unsigned int line)
void md_assemble (char *str)
static void ppc_macro (char *str, const struct powerpc_macro *macro)
static void ppc_byte (ignore)
char * md_atof (int type, char *litp, int *sizep)
void md_number_to_chars (char *buf, valueT val, int n)
valueT md_section_align (asection *seg ATTRIBUTE_UNUSED, valueT addr)
int md_estimate_size_before_relax (fragp, seg)
void md_convert_frag (abfd, sec, fragp)
symbolS * md_undefined_symbol (name)
long md_pcrel_from_section (fixS *fixp, sec)
void ppc_handle_align (struct frag *fragP)
void md_apply_fix (fixS *fixP, valueT *valP, seg)
arelenttc_gen_reloc (seg, fixS *fixp)
void ppc_cfi_frame_initial_instructions ()
int tc_ppc_regname_to_dw2regnum (char *regname)

Variables

int target_big_endian
static int set_target_endian = 0
static bfd_boolean reg_names_p = TARGET_REG_NAMES_P
const char comment_chars [] = "#"
const char line_comment_chars [] = "#"
const char line_separator_chars [] = ";"
const char EXP_CHARS [] = "eE"
const char FLT_CHARS [] = "dD"
const char ppc_symbol_chars [] = "%["
int ppc_cie_data_alignment
const pseudo_typeS md_pseudo_table []
static struct pd_reg []
static bfd_boolean cr_operand
static unsigned long ppc_cpu = 0
static unsigned int ppc_obj64 = BFD_DEFAULT_TARGET_SIZE == 64
static struct hash_controlppc_hash
static struct hash_controlppc_macro_hash
const char *const md_shortopts = "um:"
const size_t md_longopts_size = sizeof (md_longopts)

Class Documentation

struct pd_reg

Definition at line 467 of file tc-hppa.c.

Class Members
char * name
char * pname
int value
struct ppc_fixup

Definition at line 2104 of file tc-ppc.c.

Collaboration diagram for ppc_fixup:
Class Members
expressionS exp
int opindex
bfd_reloc_code_real_type reloc

Define Documentation

#define MAX_INSN_FIXUPS   (5)

Definition at line 2111 of file tc-ppc.c.

#define PPC_HA (   v)    PPC_HI ((v) + 0x8000)

Definition at line 67 of file tc-ppc.c.

#define PPC_HI (   v)    (((v) >> 16) & 0xffff)

Definition at line 62 of file tc-ppc.c.

#define PPC_HIGHER (   v)    (((v) >> 16 >> 16) & 0xffff)

Definition at line 70 of file tc-ppc.c.

#define PPC_HIGHERA (   v)    PPC_HIGHER ((v) + 0x8000)

Definition at line 74 of file tc-ppc.c.

#define PPC_HIGHEST (   v)    (((v) >> 24 >> 24) & 0xffff)

Definition at line 77 of file tc-ppc.c.

#define PPC_HIGHESTA (   v)    PPC_HIGHEST ((v) + 0x8000)

Definition at line 81 of file tc-ppc.c.

#define PPC_LO (   v)    ((v) & 0xffff)

Definition at line 59 of file tc-ppc.c.

#define REG_NAME_CNT   (sizeof (pre_defined_registers) / sizeof (struct pd_reg))

Definition at line 562 of file tc-ppc.c.

#define SEX16 (   val)    ((((val) & 0xffff) ^ 0x8000) - 0x8000)

Definition at line 83 of file tc-ppc.c.

#define TARGET_REG_NAMES_P   FALSE

Definition at line 51 of file tc-ppc.c.


Function Documentation

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

Definition at line 5580 of file tc-ppc.c.

{
  valueT value = * valP;

#ifdef OBJ_ELF
  if (fixP->fx_addsy != NULL)
    {
      /* Hack around bfd_install_relocation brain damage.  */
      if (fixP->fx_pcrel)
       value += fixP->fx_frag->fr_address + fixP->fx_where;
    }
  else
    fixP->fx_done = 1;
#else
  /* FIXME FIXME FIXME: The value we are passed in *valP includes
     the symbol values.  If we are doing this relocation the code in
     write.c is going to call bfd_install_relocation, which is also
     going to use the symbol value.  That means that if the reloc is
     fully resolved we want to use *valP since bfd_install_relocation is
     not being used.
     However, if the reloc is not fully resolved we do not want to use
     *valP, and must use fx_offset instead.  However, if the reloc
     is PC relative, we do want to use *valP since it includes the
     result of md_pcrel_from.  This is confusing.  */
  if (fixP->fx_addsy == (symbolS *) NULL)
    fixP->fx_done = 1;

  else if (fixP->fx_pcrel)
    ;

  else
    value = fixP->fx_offset;
#endif

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

  if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
    {
      int opindex;
      const struct powerpc_operand *operand;
      char *where;
      unsigned long insn;

      opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;

      operand = &powerpc_operands[opindex];

#ifdef OBJ_XCOFF
      /* An instruction like `lwz 9,sym(30)' when `sym' is not a TOC symbol
        does not generate a reloc.  It uses the offset of `sym' within its
        csect.  Other usages, such as `.long sym', generate relocs.  This
        is the documented behaviour of non-TOC symbols.  */
      if ((operand->flags & PPC_OPERAND_PARENS) != 0
         && operand->bits == 16
         && operand->shift == 0
         && (operand->insert == NULL || ppc_obj64)
         && fixP->fx_addsy != NULL
         && symbol_get_tc (fixP->fx_addsy)->subseg != 0
         && symbol_get_tc (fixP->fx_addsy)->class != XMC_TC
         && symbol_get_tc (fixP->fx_addsy)->class != XMC_TC0
         && S_GET_SEGMENT (fixP->fx_addsy) != bss_section)
       {
         value = fixP->fx_offset;
         fixP->fx_done = 1;
       }
#endif

      /* Fetch the instruction, insert the fully resolved operand
        value, and stuff the instruction back again.  */
      where = fixP->fx_frag->fr_literal + fixP->fx_where;
      if (target_big_endian)
       insn = bfd_getb32 ((unsigned char *) where);
      else
       insn = bfd_getl32 ((unsigned char *) where);
      insn = ppc_insert_operand (insn, operand, (offsetT) value,
                             fixP->fx_file, fixP->fx_line);
      if (target_big_endian)
       bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
      else
       bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);

      if (fixP->fx_done)
       /* Nothing else to do here.  */
       return;

      assert (fixP->fx_addsy != NULL);

      /* Determine a BFD reloc value based on the operand information.
        We are only prepared to turn a few of the operands into
        relocs.  */
      if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
         && operand->bits == 26
         && operand->shift == 0)
       fixP->fx_r_type = BFD_RELOC_PPC_B26;
      else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
         && operand->bits == 16
         && operand->shift == 0)
       {
         fixP->fx_r_type = BFD_RELOC_PPC_B16;
#ifdef OBJ_XCOFF
         fixP->fx_size = 2;
         if (target_big_endian)
           fixP->fx_where += 2;
#endif
       }
      else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
              && operand->bits == 26
              && operand->shift == 0)
       fixP->fx_r_type = BFD_RELOC_PPC_BA26;
      else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
              && operand->bits == 16
              && operand->shift == 0)
       {
         fixP->fx_r_type = BFD_RELOC_PPC_BA16;
#ifdef OBJ_XCOFF
         fixP->fx_size = 2;
         if (target_big_endian)
           fixP->fx_where += 2;
#endif
       }
#if defined (OBJ_XCOFF) || defined (OBJ_ELF)
      else if ((operand->flags & PPC_OPERAND_PARENS) != 0
              && operand->bits == 16
              && operand->shift == 0)
       {
         if (ppc_is_toc_sym (fixP->fx_addsy))
           {
             fixP->fx_r_type = BFD_RELOC_PPC_TOC16;
#ifdef OBJ_ELF
             if (ppc_obj64
                && (operand->flags & PPC_OPERAND_DS) != 0)
              fixP->fx_r_type = BFD_RELOC_PPC64_TOC16_DS;
#endif
           }
         else
           {
             fixP->fx_r_type = BFD_RELOC_16;
#ifdef OBJ_ELF
             if (ppc_obj64
                && (operand->flags & PPC_OPERAND_DS) != 0)
              fixP->fx_r_type = BFD_RELOC_PPC64_ADDR16_DS;
#endif
           }
         fixP->fx_size = 2;
         if (target_big_endian)
           fixP->fx_where += 2;
       }
#endif /* defined (OBJ_XCOFF) || defined (OBJ_ELF) */
      else
       {
         char *sfile;
         unsigned int sline;

         /* Use expr_symbol_where to see if this is an expression
            symbol.  */
         if (expr_symbol_where (fixP->fx_addsy, &sfile, &sline))
           as_bad_where (fixP->fx_file, fixP->fx_line,
                       _("unresolved expression that must be resolved"));
         else
           as_bad_where (fixP->fx_file, fixP->fx_line,
                       _("unsupported relocation against %s"),
                       S_GET_NAME (fixP->fx_addsy));
         fixP->fx_done = 1;
         return;
       }
    }
  else
    {
#ifdef OBJ_ELF
      ppc_elf_validate_fix (fixP, seg);
#endif
      switch (fixP->fx_r_type)
       {
       case BFD_RELOC_CTOR:
         if (ppc_obj64)
           goto ctor64;
         /* fall through */

       case BFD_RELOC_32:
         if (fixP->fx_pcrel)
           fixP->fx_r_type = BFD_RELOC_32_PCREL;
         /* fall through */

       case BFD_RELOC_RVA:
       case BFD_RELOC_32_PCREL:
       case BFD_RELOC_PPC_EMB_NADDR32:
         md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           value, 4);
         break;

       case BFD_RELOC_64:
       ctor64:
         if (fixP->fx_pcrel)
           fixP->fx_r_type = BFD_RELOC_64_PCREL;
         /* fall through */

       case BFD_RELOC_64_PCREL:
         md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           value, 8);
         break;

       case BFD_RELOC_GPREL16:
       case BFD_RELOC_16_GOT_PCREL:
       case BFD_RELOC_16_GOTOFF:
       case BFD_RELOC_LO16_GOTOFF:
       case BFD_RELOC_HI16_GOTOFF:
       case BFD_RELOC_HI16_S_GOTOFF:
       case BFD_RELOC_16_BASEREL:
       case BFD_RELOC_LO16_BASEREL:
       case BFD_RELOC_HI16_BASEREL:
       case BFD_RELOC_HI16_S_BASEREL:
       case BFD_RELOC_PPC_EMB_NADDR16:
       case BFD_RELOC_PPC_EMB_NADDR16_LO:
       case BFD_RELOC_PPC_EMB_NADDR16_HI:
       case BFD_RELOC_PPC_EMB_NADDR16_HA:
       case BFD_RELOC_PPC_EMB_SDAI16:
       case BFD_RELOC_PPC_EMB_SDA2REL:
       case BFD_RELOC_PPC_EMB_SDA2I16:
       case BFD_RELOC_PPC_EMB_RELSEC16:
       case BFD_RELOC_PPC_EMB_RELST_LO:
       case BFD_RELOC_PPC_EMB_RELST_HI:
       case BFD_RELOC_PPC_EMB_RELST_HA:
       case BFD_RELOC_PPC_EMB_RELSDA:
       case BFD_RELOC_PPC_TOC16:
#ifdef OBJ_ELF
       case BFD_RELOC_PPC64_TOC16_LO:
       case BFD_RELOC_PPC64_TOC16_HI:
       case BFD_RELOC_PPC64_TOC16_HA:
#endif
         if (fixP->fx_pcrel)
           {
             if (fixP->fx_addsy != NULL)
              as_bad_where (fixP->fx_file, fixP->fx_line,
                           _("cannot emit PC relative %s relocation against %s"),
                           bfd_get_reloc_code_name (fixP->fx_r_type),
                           S_GET_NAME (fixP->fx_addsy));
             else
              as_bad_where (fixP->fx_file, fixP->fx_line,
                           _("cannot emit PC relative %s relocation"),
                           bfd_get_reloc_code_name (fixP->fx_r_type));
           }

         md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           value, 2);
         break;

       case BFD_RELOC_16:
         if (fixP->fx_pcrel)
           fixP->fx_r_type = BFD_RELOC_16_PCREL;
         /* fall through */

       case BFD_RELOC_16_PCREL:
         md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           value, 2);
         break;

       case BFD_RELOC_LO16:
         if (fixP->fx_pcrel)
           fixP->fx_r_type = BFD_RELOC_LO16_PCREL;
         /* fall through */

       case BFD_RELOC_LO16_PCREL:
         md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           value, 2);
         break;

         /* This case happens when you write, for example,
            lis %r3,(L1-L2)@ha
            where L1 and L2 are defined later.  */
       case BFD_RELOC_HI16:
         if (fixP->fx_pcrel)
           fixP->fx_r_type = BFD_RELOC_HI16_PCREL;
         /* fall through */

       case BFD_RELOC_HI16_PCREL:
         md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           PPC_HI (value), 2);
         break;

       case BFD_RELOC_HI16_S:
         if (fixP->fx_pcrel)
           fixP->fx_r_type = BFD_RELOC_HI16_S_PCREL;
         /* fall through */

       case BFD_RELOC_HI16_S_PCREL:
         md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           PPC_HA (value), 2);
         break;

#ifdef OBJ_ELF
       case BFD_RELOC_PPC64_HIGHER:
         if (fixP->fx_pcrel)
           abort ();
         md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           PPC_HIGHER (value), 2);
         break;

       case BFD_RELOC_PPC64_HIGHER_S:
         if (fixP->fx_pcrel)
           abort ();
         md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           PPC_HIGHERA (value), 2);
         break;

       case BFD_RELOC_PPC64_HIGHEST:
         if (fixP->fx_pcrel)
           abort ();
         md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           PPC_HIGHEST (value), 2);
         break;

       case BFD_RELOC_PPC64_HIGHEST_S:
         if (fixP->fx_pcrel)
           abort ();
         md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                           PPC_HIGHESTA (value), 2);
         break;

       case BFD_RELOC_PPC64_ADDR16_DS:
       case BFD_RELOC_PPC64_ADDR16_LO_DS:
       case BFD_RELOC_PPC64_GOT16_DS:
       case BFD_RELOC_PPC64_GOT16_LO_DS:
       case BFD_RELOC_PPC64_PLT16_LO_DS:
       case BFD_RELOC_PPC64_SECTOFF_DS:
       case BFD_RELOC_PPC64_SECTOFF_LO_DS:
       case BFD_RELOC_PPC64_TOC16_DS:
       case BFD_RELOC_PPC64_TOC16_LO_DS:
       case BFD_RELOC_PPC64_PLTGOT16_DS:
       case BFD_RELOC_PPC64_PLTGOT16_LO_DS:
         if (fixP->fx_pcrel)
           abort ();
         {
           char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
           unsigned long val, mask;

           if (target_big_endian)
             val = bfd_getb32 (where - 2);
           else
             val = bfd_getl32 (where);
           mask = 0xfffc;
           /* lq insns reserve the four lsbs.  */
           if ((ppc_cpu & PPC_OPCODE_POWER4) != 0
              && (val & (0x3f << 26)) == (56u << 26))
             mask = 0xfff0;
           val |= value & mask;
           if (target_big_endian)
             bfd_putb16 ((bfd_vma) val, where);
           else
             bfd_putl16 ((bfd_vma) val, where);
         }
         break;

       case BFD_RELOC_PPC_B16_BRTAKEN:
       case BFD_RELOC_PPC_B16_BRNTAKEN:
       case BFD_RELOC_PPC_BA16_BRTAKEN:
       case BFD_RELOC_PPC_BA16_BRNTAKEN:
         break;

       case BFD_RELOC_PPC_TLS:
         break;

       case BFD_RELOC_PPC_DTPMOD:
       case BFD_RELOC_PPC_TPREL16:
       case BFD_RELOC_PPC_TPREL16_LO:
       case BFD_RELOC_PPC_TPREL16_HI:
       case BFD_RELOC_PPC_TPREL16_HA:
       case BFD_RELOC_PPC_TPREL:
       case BFD_RELOC_PPC_DTPREL16:
       case BFD_RELOC_PPC_DTPREL16_LO:
       case BFD_RELOC_PPC_DTPREL16_HI:
       case BFD_RELOC_PPC_DTPREL16_HA:
       case BFD_RELOC_PPC_DTPREL:
       case BFD_RELOC_PPC_GOT_TLSGD16:
       case BFD_RELOC_PPC_GOT_TLSGD16_LO:
       case BFD_RELOC_PPC_GOT_TLSGD16_HI:
       case BFD_RELOC_PPC_GOT_TLSGD16_HA:
       case BFD_RELOC_PPC_GOT_TLSLD16:
       case BFD_RELOC_PPC_GOT_TLSLD16_LO:
       case BFD_RELOC_PPC_GOT_TLSLD16_HI:
       case BFD_RELOC_PPC_GOT_TLSLD16_HA:
       case BFD_RELOC_PPC_GOT_TPREL16:
       case BFD_RELOC_PPC_GOT_TPREL16_LO:
       case BFD_RELOC_PPC_GOT_TPREL16_HI:
       case BFD_RELOC_PPC_GOT_TPREL16_HA:
       case BFD_RELOC_PPC_GOT_DTPREL16:
       case BFD_RELOC_PPC_GOT_DTPREL16_LO:
       case BFD_RELOC_PPC_GOT_DTPREL16_HI:
       case BFD_RELOC_PPC_GOT_DTPREL16_HA:
       case BFD_RELOC_PPC64_TPREL16_DS:
       case BFD_RELOC_PPC64_TPREL16_LO_DS:
       case BFD_RELOC_PPC64_TPREL16_HIGHER:
       case BFD_RELOC_PPC64_TPREL16_HIGHERA:
       case BFD_RELOC_PPC64_TPREL16_HIGHEST:
       case BFD_RELOC_PPC64_TPREL16_HIGHESTA:
       case BFD_RELOC_PPC64_DTPREL16_DS:
       case BFD_RELOC_PPC64_DTPREL16_LO_DS:
       case BFD_RELOC_PPC64_DTPREL16_HIGHER:
       case BFD_RELOC_PPC64_DTPREL16_HIGHERA:
       case BFD_RELOC_PPC64_DTPREL16_HIGHEST:
       case BFD_RELOC_PPC64_DTPREL16_HIGHESTA:
         S_SET_THREAD_LOCAL (fixP->fx_addsy);
         break;
#endif
         /* Because SDA21 modifies the register field, the size is set to 4
            bytes, rather than 2, so offset it here appropriately.  */
       case BFD_RELOC_PPC_EMB_SDA21:
         if (fixP->fx_pcrel)
           abort ();

         md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where
                           + ((target_big_endian) ? 2 : 0),
                           value, 2);
         break;

       case BFD_RELOC_8:
         if (fixP->fx_pcrel)
           {
             /* This can occur if there is a bug in the input assembler, eg:
               ".byte <undefined_symbol> - ."  */
             if (fixP->fx_addsy)
              as_bad (_("Unable to handle reference to symbol %s"),
                     S_GET_NAME (fixP->fx_addsy));
             else
              as_bad (_("Unable to resolve expression"));
             fixP->fx_done = 1;
           }
         else
           md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
                            value, 1);
         break;

       case BFD_RELOC_24_PLT_PCREL:
       case BFD_RELOC_PPC_LOCAL24PC:
         if (!fixP->fx_pcrel && !fixP->fx_done)
           abort ();

         if (fixP->fx_done)
           {
             char *where;
             unsigned long insn;

             /* Fetch the instruction, insert the fully resolved operand
               value, and stuff the instruction back again.  */
             where = fixP->fx_frag->fr_literal + fixP->fx_where;
             if (target_big_endian)
              insn = bfd_getb32 ((unsigned char *) where);
             else
              insn = bfd_getl32 ((unsigned char *) where);
             if ((value & 3) != 0)
              as_bad_where (fixP->fx_file, fixP->fx_line,
                           _("must branch to an address a multiple of 4"));
             if ((offsetT) value < -0x40000000
                || (offsetT) value >= 0x40000000)
              as_bad_where (fixP->fx_file, fixP->fx_line,
                           _("@local or @plt branch destination is too far away, %ld bytes"),
                           (long) value);
             insn = insn | (value & 0x03fffffc);
             if (target_big_endian)
              bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
             else
              bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
           }
         break;

       case BFD_RELOC_VTABLE_INHERIT:
         fixP->fx_done = 0;
         if (fixP->fx_addsy
             && !S_IS_DEFINED (fixP->fx_addsy)
             && !S_IS_WEAK (fixP->fx_addsy))
           S_SET_WEAK (fixP->fx_addsy);
         break;

       case BFD_RELOC_VTABLE_ENTRY:
         fixP->fx_done = 0;
         break;

#ifdef OBJ_ELF
         /* Generated by reference to `sym@tocbase'.  The sym is
            ignored by the linker.  */
       case BFD_RELOC_PPC64_TOC:
         fixP->fx_done = 0;
         break;
#endif
       default:
         fprintf (stderr,
                 _("Gas failure, reloc value %d\n"), fixP->fx_r_type);
         fflush (stderr);
         abort ();
       }
    }

#ifdef OBJ_ELF
  fixP->fx_addnumber = value;

  /* PowerPC uses RELA relocs, ie. the reloc addend is stored separately
     from the section contents.  If we are going to be emitting a reloc
     then the section contents are immaterial, so don't warn if they
     happen to overflow.  Leave such warnings to ld.  */
  if (!fixP->fx_done)
    fixP->fx_no_overflow = 1;
#else
  if (fixP->fx_r_type != BFD_RELOC_PPC_TOC16)
    fixP->fx_addnumber = 0;
  else
    {
#ifdef TE_PE
      fixP->fx_addnumber = 0;
#else
      /* We want to use the offset within the data segment of the
        symbol, not the actual VMA of the symbol.  */
      fixP->fx_addnumber =
       - bfd_get_section_vma (stdoutput, S_GET_SEGMENT (fixP->fx_addsy));
#endif
    }
#endif
}

Here is the call graph for this function:

void md_assemble ( char *  str)

Definition at line 2116 of file tc-ppc.c.

{
  char *s;
  const struct powerpc_opcode *opcode;
  unsigned long insn;
  const unsigned char *opindex_ptr;
  int skip_optional;
  int need_paren;
  int next_opindex;
  struct ppc_fixup fixups[MAX_INSN_FIXUPS];
  int fc;
  char *f;
  int addr_mod;
  int i;
#ifdef OBJ_ELF
  bfd_reloc_code_real_type reloc;
#endif

  /* Get the opcode.  */
  for (s = str; *s != '\0' && ! ISSPACE (*s); s++)
    ;
  if (*s != '\0')
    *s++ = '\0';

  /* Look up the opcode in the hash table.  */
  opcode = (const struct powerpc_opcode *) hash_find (ppc_hash, str);
  if (opcode == (const struct powerpc_opcode *) NULL)
    {
      const struct powerpc_macro *macro;

      macro = (const struct powerpc_macro *) hash_find (ppc_macro_hash, str);
      if (macro == (const struct powerpc_macro *) NULL)
       as_bad (_("Unrecognized opcode: `%s'"), str);
      else
       ppc_macro (s, macro);

      return;
    }

  insn = opcode->opcode;

  str = s;
  while (ISSPACE (*str))
    ++str;

  /* PowerPC operands are just expressions.  The only real issue is
     that a few operand types are optional.  All cases which might use
     an optional operand separate the operands only with commas (in some
     cases parentheses are used, as in ``lwz 1,0(1)'' but such cases never
     have optional operands).  Most instructions with optional operands
     have only one.  Those that have more than one optional operand can
     take either all their operands or none.  So, before we start seriously
     parsing the operands, we check to see if we have optional operands,
     and if we do, we count the number of commas to see which operands
     have been omitted.  */
  skip_optional = 0;
  for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
    {
      const struct powerpc_operand *operand;

      operand = &powerpc_operands[*opindex_ptr];
      if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
       {
         unsigned int opcount;
         unsigned int num_operands_expected;
         unsigned int i;

         /* There is an optional operand.  Count the number of
            commas in the input line.  */
         if (*str == '\0')
           opcount = 0;
         else
           {
             opcount = 1;
             s = str;
             while ((s = strchr (s, ',')) != (char *) NULL)
              {
                ++opcount;
                ++s;
              }
           }

         /* Compute the number of expected operands.
            Do not count fake operands.  */
         for (num_operands_expected = 0, i = 0; opcode->operands[i]; i ++)
           if ((powerpc_operands [opcode->operands[i]].flags & PPC_OPERAND_FAKE) == 0)
             ++ num_operands_expected;

         /* If there are fewer operands in the line then are called
            for by the instruction, we want to skip the optional
            operands.  */
         if (opcount < num_operands_expected)
           skip_optional = 1;

         break;
       }
    }

  /* Gather the operands.  */
  need_paren = 0;
  next_opindex = 0;
  fc = 0;
  for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
    {
      const struct powerpc_operand *operand;
      const char *errmsg;
      char *hold;
      expressionS ex;
      char endc;

      if (next_opindex == 0)
       operand = &powerpc_operands[*opindex_ptr];
      else
       {
         operand = &powerpc_operands[next_opindex];
         next_opindex = 0;
       }
      errmsg = NULL;

      /* If this is a fake operand, then we do not expect anything
        from the input.  */
      if ((operand->flags & PPC_OPERAND_FAKE) != 0)
       {
         insn = (*operand->insert) (insn, 0L, ppc_cpu, &errmsg);
         if (errmsg != (const char *) NULL)
           as_bad (errmsg);
         continue;
       }

      /* If this is an optional operand, and we are skipping it, just
        insert a zero.  */
      if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
         && skip_optional)
       {
         if (operand->insert)
           {
             insn = (*operand->insert) (insn, 0L, ppc_cpu, &errmsg);
             if (errmsg != (const char *) NULL)
              as_bad (errmsg);
           }
         if ((operand->flags & PPC_OPERAND_NEXT) != 0)
           next_opindex = *opindex_ptr + 1;
         continue;
       }

      /* Gather the operand.  */
      hold = input_line_pointer;
      input_line_pointer = str;

#ifdef TE_PE
      if (*input_line_pointer == '[')
       {
         /* We are expecting something like the second argument here:
          *
          *    lwz r4,[toc].GS.0.static_int(rtoc)
          *           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
          * The argument following the `]' must be a symbol name, and the
          * register must be the toc register: 'rtoc' or '2'
          *
          * The effect is to 0 as the displacement field
          * in the instruction, and issue an IMAGE_REL_PPC_TOCREL16 (or
          * the appropriate variation) reloc against it based on the symbol.
          * The linker will build the toc, and insert the resolved toc offset.
          *
          * Note:
          * o The size of the toc entry is currently assumed to be
          *   32 bits. This should not be assumed to be a hard coded
          *   number.
          * o In an effort to cope with a change from 32 to 64 bits,
          *   there are also toc entries that are specified to be
          *   either 32 or 64 bits:
          *     lwz r4,[toc32].GS.0.static_int(rtoc)
          *     lwz r4,[toc64].GS.0.static_int(rtoc)
          *   These demand toc entries of the specified size, and the
          *   instruction probably requires it.
          */

         int valid_toc;
         enum toc_size_qualifier toc_kind;
         bfd_reloc_code_real_type toc_reloc;

         /* Go parse off the [tocXX] part.  */
         valid_toc = parse_toc_entry (&toc_kind);

         if (!valid_toc)
           {
             /* Note: message has already been issued.
               FIXME: what sort of recovery should we do?
               demand_rest_of_line (); return; ?  */
           }

         /* Now get the symbol following the ']'.  */
         expression (&ex);

         switch (toc_kind)
           {
           case default_toc:
             /* In this case, we may not have seen the symbol yet,
               since  it is allowed to appear on a .extern or .globl
               or just be a label in the .data section.  */
             toc_reloc = BFD_RELOC_PPC_TOC16;
             break;
           case data_in_toc:
             /* 1. The symbol must be defined and either in the toc
               section, or a global.
               2. The reloc generated must have the TOCDEFN flag set
               in upper bit mess of the reloc type.
               FIXME: It's a little confusing what the tocv
               qualifier can be used for.  At the very least, I've
               seen three uses, only one of which I'm sure I can
               explain.  */
             if (ex.X_op == O_symbol)
              {
                assert (ex.X_add_symbol != NULL);
                if (symbol_get_bfdsym (ex.X_add_symbol)->section
                    != tocdata_section)
                  {
                    as_bad (_("[tocv] symbol is not a toc symbol"));
                  }
              }

             toc_reloc = BFD_RELOC_PPC_TOC16;
             break;
           case must_be_32:
             /* FIXME: these next two specifically specify 32/64 bit
               toc entries.  We don't support them today.  Is this
               the right way to say that?  */
             toc_reloc = BFD_RELOC_UNUSED;
             as_bad (_("Unimplemented toc32 expression modifier"));
             break;
           case must_be_64:
             /* FIXME: see above.  */
             toc_reloc = BFD_RELOC_UNUSED;
             as_bad (_("Unimplemented toc64 expression modifier"));
             break;
           default:
             fprintf (stderr,
                     _("Unexpected return value [%d] from parse_toc_entry!\n"),
                     toc_kind);
             abort ();
             break;
           }

         /* We need to generate a fixup for this expression.  */
         if (fc >= MAX_INSN_FIXUPS)
           as_fatal (_("too many fixups"));

         fixups[fc].reloc = toc_reloc;
         fixups[fc].exp = ex;
         fixups[fc].opindex = *opindex_ptr;
         ++fc;

         /* Ok. We've set up the fixup for the instruction. Now make it
            look like the constant 0 was found here.  */
         ex.X_unsigned = 1;
         ex.X_op = O_constant;
         ex.X_add_number = 0;
         ex.X_add_symbol = NULL;
         ex.X_op_symbol = NULL;
       }

      else
#endif        /* TE_PE */
       {
         if (! register_name (&ex))
           {
             if ((operand->flags & PPC_OPERAND_CR) != 0)
              cr_operand = TRUE;
             expression (&ex);
             cr_operand = FALSE;
           }
       }

      str = input_line_pointer;
      input_line_pointer = hold;

      if (ex.X_op == O_illegal)
       as_bad (_("illegal operand"));
      else if (ex.X_op == O_absent)
       as_bad (_("missing operand"));
      else if (ex.X_op == O_register)
       {
         insn = ppc_insert_operand (insn, operand, ex.X_add_number,
                                 (char *) NULL, 0);
       }
      else if (ex.X_op == O_constant)
       {
#ifdef OBJ_ELF
         /* Allow @HA, @L, @H on constants.  */
         char *orig_str = str;

         if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
           switch (reloc)
             {
             default:
              str = orig_str;
              break;

             case BFD_RELOC_LO16:
              /* X_unsigned is the default, so if the user has done
                 something which cleared it, we always produce a
                 signed value.  */
              if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
                ex.X_add_number &= 0xffff;
              else
                ex.X_add_number = SEX16 (ex.X_add_number);
              break;

             case BFD_RELOC_HI16:
              if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
                ex.X_add_number = PPC_HI (ex.X_add_number);
              else
                ex.X_add_number = SEX16 (PPC_HI (ex.X_add_number));
              break;

             case BFD_RELOC_HI16_S:
              if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
                ex.X_add_number = PPC_HA (ex.X_add_number);
              else
                ex.X_add_number = SEX16 (PPC_HA (ex.X_add_number));
              break;

             case BFD_RELOC_PPC64_HIGHER:
              if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
                ex.X_add_number = PPC_HIGHER (ex.X_add_number);
              else
                ex.X_add_number = SEX16 (PPC_HIGHER (ex.X_add_number));
              break;

             case BFD_RELOC_PPC64_HIGHER_S:
              if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
                ex.X_add_number = PPC_HIGHERA (ex.X_add_number);
              else
                ex.X_add_number = SEX16 (PPC_HIGHERA (ex.X_add_number));
              break;

             case BFD_RELOC_PPC64_HIGHEST:
              if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
                ex.X_add_number = PPC_HIGHEST (ex.X_add_number);
              else
                ex.X_add_number = SEX16 (PPC_HIGHEST (ex.X_add_number));
              break;

             case BFD_RELOC_PPC64_HIGHEST_S:
              if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
                ex.X_add_number = PPC_HIGHESTA (ex.X_add_number);
              else
                ex.X_add_number = SEX16 (PPC_HIGHESTA (ex.X_add_number));
              break;
             }
#endif /* OBJ_ELF */
         insn = ppc_insert_operand (insn, operand, ex.X_add_number,
                                 (char *) NULL, 0);
       }
#ifdef OBJ_ELF
      else if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
       {
         /* Some TLS tweaks.  */
         switch (reloc)
           {
           default:
             break;
           case BFD_RELOC_PPC_TLS:
             insn = ppc_insert_operand (insn, operand, ppc_obj64 ? 13 : 2,
                                    (char *) NULL, 0);
             break;
         /* We'll only use the 32 (or 64) bit form of these relocations
            in constants.  Instructions get the 16 bit form.  */
           case BFD_RELOC_PPC_DTPREL:
             reloc = BFD_RELOC_PPC_DTPREL16;
             break;
           case BFD_RELOC_PPC_TPREL:
             reloc = BFD_RELOC_PPC_TPREL16;
             break;
           }

         /* For the absolute forms of branches, convert the PC
            relative form back into the absolute.  */
         if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
           {
             switch (reloc)
              {
              case BFD_RELOC_PPC_B26:
                reloc = BFD_RELOC_PPC_BA26;
                break;
              case BFD_RELOC_PPC_B16:
                reloc = BFD_RELOC_PPC_BA16;
                break;
              case BFD_RELOC_PPC_B16_BRTAKEN:
                reloc = BFD_RELOC_PPC_BA16_BRTAKEN;
                break;
              case BFD_RELOC_PPC_B16_BRNTAKEN:
                reloc = BFD_RELOC_PPC_BA16_BRNTAKEN;
                break;
              default:
                break;
              }
           }

         if (ppc_obj64
             && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
           {
             switch (reloc)
              {
              case BFD_RELOC_16:
                reloc = BFD_RELOC_PPC64_ADDR16_DS;
                break;
              case BFD_RELOC_LO16:
                reloc = BFD_RELOC_PPC64_ADDR16_LO_DS;
                break;
              case BFD_RELOC_16_GOTOFF:
                reloc = BFD_RELOC_PPC64_GOT16_DS;
                break;
              case BFD_RELOC_LO16_GOTOFF:
                reloc = BFD_RELOC_PPC64_GOT16_LO_DS;
                break;
              case BFD_RELOC_LO16_PLTOFF:
                reloc = BFD_RELOC_PPC64_PLT16_LO_DS;
                break;
              case BFD_RELOC_16_BASEREL:
                reloc = BFD_RELOC_PPC64_SECTOFF_DS;
                break;
              case BFD_RELOC_LO16_BASEREL:
                reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS;
                break;
              case BFD_RELOC_PPC_TOC16:
                reloc = BFD_RELOC_PPC64_TOC16_DS;
                break;
              case BFD_RELOC_PPC64_TOC16_LO:
                reloc = BFD_RELOC_PPC64_TOC16_LO_DS;
                break;
              case BFD_RELOC_PPC64_PLTGOT16:
                reloc = BFD_RELOC_PPC64_PLTGOT16_DS;
                break;
              case BFD_RELOC_PPC64_PLTGOT16_LO:
                reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS;
                break;
              case BFD_RELOC_PPC_DTPREL16:
                reloc = BFD_RELOC_PPC64_DTPREL16_DS;
                break;
              case BFD_RELOC_PPC_DTPREL16_LO:
                reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS;
                break;
              case BFD_RELOC_PPC_TPREL16:
                reloc = BFD_RELOC_PPC64_TPREL16_DS;
                break;
              case BFD_RELOC_PPC_TPREL16_LO:
                reloc = BFD_RELOC_PPC64_TPREL16_LO_DS;
                break;
              case BFD_RELOC_PPC_GOT_DTPREL16:
              case BFD_RELOC_PPC_GOT_DTPREL16_LO:
              case BFD_RELOC_PPC_GOT_TPREL16:
              case BFD_RELOC_PPC_GOT_TPREL16_LO:
                break;
              default:
                as_bad (_("unsupported relocation for DS offset field"));
                break;
              }
           }

         /* We need to generate a fixup for this expression.  */
         if (fc >= MAX_INSN_FIXUPS)
           as_fatal (_("too many fixups"));
         fixups[fc].exp = ex;
         fixups[fc].opindex = 0;
         fixups[fc].reloc = reloc;
         ++fc;
       }
#endif /* OBJ_ELF */

      else
       {
         /* We need to generate a fixup for this expression.  */
         if (fc >= MAX_INSN_FIXUPS)
           as_fatal (_("too many fixups"));
         fixups[fc].exp = ex;
         fixups[fc].opindex = *opindex_ptr;
         fixups[fc].reloc = BFD_RELOC_UNUSED;
         ++fc;
       }

      if (need_paren)
       {
         endc = ')';
         need_paren = 0;
       }
      else if ((operand->flags & PPC_OPERAND_PARENS) != 0)
       {
         endc = '(';
         need_paren = 1;
       }
      else
       endc = ',';

      /* The call to expression should have advanced str past any
        whitespace.  */
      if (*str != endc
         && (endc != ',' || *str != '\0'))
       {
         as_bad (_("syntax error; found `%c' but expected `%c'"), *str, endc);
         break;
       }

      if (*str != '\0')
       ++str;
    }

  while (ISSPACE (*str))
    ++str;

  if (*str != '\0')
    as_bad (_("junk at end of line: `%s'"), str);

#ifdef OBJ_ELF
  /* Do we need/want a APUinfo section? */
  if (ppc_cpu & (PPC_OPCODE_SPE
              | PPC_OPCODE_ISEL | PPC_OPCODE_EFS
              | PPC_OPCODE_BRLOCK | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
              | PPC_OPCODE_RFMCI))
    {
      /* These are all version "1".  */
      if (opcode->flags & PPC_OPCODE_SPE)
       ppc_apuinfo_section_add (PPC_APUINFO_SPE, 1);
      if (opcode->flags & PPC_OPCODE_ISEL)
       ppc_apuinfo_section_add (PPC_APUINFO_ISEL, 1);
      if (opcode->flags & PPC_OPCODE_EFS)
       ppc_apuinfo_section_add (PPC_APUINFO_EFS, 1);
      if (opcode->flags & PPC_OPCODE_BRLOCK)
       ppc_apuinfo_section_add (PPC_APUINFO_BRLOCK, 1);
      if (opcode->flags & PPC_OPCODE_PMR)
       ppc_apuinfo_section_add (PPC_APUINFO_PMR, 1);
      if (opcode->flags & PPC_OPCODE_CACHELCK)
       ppc_apuinfo_section_add (PPC_APUINFO_CACHELCK, 1);
      if (opcode->flags & PPC_OPCODE_RFMCI)
       ppc_apuinfo_section_add (PPC_APUINFO_RFMCI, 1);
    }
#endif

  /* Write out the instruction.  */
  f = frag_more (4);
  addr_mod = frag_now_fix () & 3;
  if (frag_now->has_code && frag_now->insn_addr != addr_mod)
    as_bad (_("instruction address is not a multiple of 4"));
  frag_now->insn_addr = addr_mod;
  frag_now->has_code = 1;
  md_number_to_chars (f, insn, 4);

#ifdef OBJ_ELF
  dwarf2_emit_insn (4);
#endif

  /* Create any fixups.  At this point we do not use a
     bfd_reloc_code_real_type, but instead just use the
     BFD_RELOC_UNUSED plus the operand index.  This lets us easily
     handle fixups for any operand type, although that is admittedly
     not a very exciting feature.  We pick a BFD reloc type in
     md_apply_fix.  */
  for (i = 0; i < fc; i++)
    {
      const struct powerpc_operand *operand;

      operand = &powerpc_operands[fixups[i].opindex];
      if (fixups[i].reloc != BFD_RELOC_UNUSED)
       {
         reloc_howto_type *reloc_howto;
         int size;
         int offset;
         fixS *fixP;

         reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
         if (!reloc_howto)
           abort ();

         size = bfd_get_reloc_size (reloc_howto);
         offset = target_big_endian ? (4 - size) : 0;

         if (size < 1 || size > 4)
           abort ();

         fixP = fix_new_exp (frag_now,
                           f - frag_now->fr_literal + offset,
                           size,
                           &fixups[i].exp,
                           reloc_howto->pc_relative,
                           fixups[i].reloc);

         /* Turn off complaints that the addend is too large for things like
            foo+100000@ha.  */
         switch (fixups[i].reloc)
           {
           case BFD_RELOC_16_GOTOFF:
           case BFD_RELOC_PPC_TOC16:
           case BFD_RELOC_LO16:
           case BFD_RELOC_HI16:
           case BFD_RELOC_HI16_S:
#ifdef OBJ_ELF
           case BFD_RELOC_PPC64_HIGHER:
           case BFD_RELOC_PPC64_HIGHER_S:
           case BFD_RELOC_PPC64_HIGHEST:
           case BFD_RELOC_PPC64_HIGHEST_S:
#endif
             fixP->fx_no_overflow = 1;
             break;
           default:
             break;
           }
       }
      else
       fix_new_exp (frag_now,
                   f - frag_now->fr_literal,
                   4,
                   &fixups[i].exp,
                   (operand->flags & PPC_OPERAND_RELATIVE) != 0,
                   ((bfd_reloc_code_real_type)
                    (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
    }
}

Here is the call graph for this function:

char* md_atof ( int type  ,
char *  litp,
int sizep 
)

Definition at line 5204 of file tc-ppc.c.

{
  int prec;
  LITTLENUM_TYPE words[4];
  char *t;
  int i;

  switch (type)
    {
    case 'f':
      prec = 2;
      break;

    case 'd':
      prec = 4;
      break;

    default:
      *sizep = 0;
      return _("bad call to md_atof");
    }

  t = atof_ieee (input_line_pointer, type, words);
  if (t)
    input_line_pointer = t;

  *sizep = prec * 2;

  if (target_big_endian)
    {
      for (i = 0; i < prec; i++)
       {
         md_number_to_chars (litp, (valueT) words[i], 2);
         litp += 2;
       }
    }
  else
    {
      for (i = prec - 1; i >= 0; i--)
       {
         md_number_to_chars (litp, (valueT) words[i], 2);
         litp += 2;
       }
    }

  return NULL;
}

Here is the call graph for this function:

void md_begin ( void  )

Definition at line 1338 of file tc-ppc.c.

{
  ppc_set_cpu ();

  ppc_cie_data_alignment = ppc_obj64 ? -8 : -4;

#ifdef OBJ_ELF
  /* Set the ELF flags if desired.  */
  if (ppc_flags && !msolaris)
    bfd_set_private_flags (stdoutput, ppc_flags);
#endif

  ppc_setup_opcodes ();

  /* Tell the main code what the endianness is if it is not overridden
     by the user.  */
  if (!set_target_endian)
    {
      set_target_endian = 1;
      target_big_endian = PPC_BIG_ENDIAN;
    }

#ifdef OBJ_XCOFF
  ppc_coff_debug_section = coff_section_from_bfd_index (stdoutput, N_DEBUG);

  /* Create dummy symbols to serve as initial csects.  This forces the
     text csects to precede the data csects.  These symbols will not
     be output.  */
  ppc_text_csects = symbol_make ("dummy\001");
  symbol_get_tc (ppc_text_csects)->within = ppc_text_csects;
  ppc_data_csects = symbol_make ("dummy\001");
  symbol_get_tc (ppc_data_csects)->within = ppc_data_csects;
#endif

#ifdef TE_PE

  ppc_current_section = text_section;
  ppc_previous_section = 0;

#endif
}

Here is the call graph for this function:

void md_convert_frag ( abfd  ,
sec  ,
fragp   
)

Definition at line 5298 of file tc-ppc.c.

{
  abort ();
}

Definition at line 5287 of file tc-ppc.c.

{
  abort ();
  return 0;
}
void md_number_to_chars ( char *  buf,
valueT  val,
int  n 
)

Definition at line 5259 of file tc-ppc.c.

Here is the call graph for this function:

int md_parse_option ( int c  ,
char *  arg 
)

Definition at line 944 of file tc-ppc.c.

{
  switch (c)
    {
    case 'u':
      /* -u means that any undefined symbols should be treated as
        external, which is the default for gas anyhow.  */
      break;

#ifdef OBJ_ELF
    case 'l':
      /* Solaris as takes -le (presumably for little endian).  For completeness
        sake, recognize -be also.  */
      if (strcmp (arg, "e") == 0)
       {
         target_big_endian = 0;
         set_target_endian = 1;
       }
      else
       return 0;

      break;

    case 'b':
      if (strcmp (arg, "e") == 0)
       {
         target_big_endian = 1;
         set_target_endian = 1;
       }
      else
       return 0;

      break;

    case 'K':
      /* Recognize -K PIC.  */
      if (strcmp (arg, "PIC") == 0 || strcmp (arg, "pic") == 0)
       {
         shlib = SHLIB_PIC;
         ppc_flags |= EF_PPC_RELOCATABLE_LIB;
       }
      else
       return 0;

      break;
#endif

      /* a64 and a32 determine whether to use XCOFF64 or XCOFF32.  */
    case 'a':
      if (strcmp (arg, "64") == 0)
       {
#ifdef BFD64
         ppc_obj64 = 1;
#else
         as_fatal (_("%s unsupported"), "-a64");
#endif
       }
      else if (strcmp (arg, "32") == 0)
       ppc_obj64 = 0;
      else
       return 0;
      break;

    case 'm':
      if (parse_cpu (arg))
       ;

      else if (strcmp (arg, "regnames") == 0)
       reg_names_p = TRUE;

      else if (strcmp (arg, "no-regnames") == 0)
       reg_names_p = FALSE;

#ifdef OBJ_ELF
      /* -mrelocatable/-mrelocatable-lib -- warn about initializations
        that require relocation.  */
      else if (strcmp (arg, "relocatable") == 0)
       {
         shlib = SHLIB_MRELOCATABLE;
         ppc_flags |= EF_PPC_RELOCATABLE;
       }

      else if (strcmp (arg, "relocatable-lib") == 0)
       {
         shlib = SHLIB_MRELOCATABLE;
         ppc_flags |= EF_PPC_RELOCATABLE_LIB;
       }

      /* -memb, set embedded bit.  */
      else if (strcmp (arg, "emb") == 0)
       ppc_flags |= EF_PPC_EMB;

      /* -mlittle/-mbig set the endianess.  */
      else if (strcmp (arg, "little") == 0
              || strcmp (arg, "little-endian") == 0)
       {
         target_big_endian = 0;
         set_target_endian = 1;
       }

      else if (strcmp (arg, "big") == 0 || strcmp (arg, "big-endian") == 0)
       {
         target_big_endian = 1;
         set_target_endian = 1;
       }

      else if (strcmp (arg, "solaris") == 0)
       {
         msolaris = TRUE;
         ppc_comment_chars = ppc_solaris_comment_chars;
       }

      else if (strcmp (arg, "no-solaris") == 0)
       {
         msolaris = FALSE;
         ppc_comment_chars = ppc_eabi_comment_chars;
       }
#endif
      else
       {
         as_bad (_("invalid switch -m%s"), arg);
         return 0;
       }
      break;

#ifdef OBJ_ELF
      /* -V: SVR4 argument to print version ID.  */
    case 'V':
      print_version_id ();
      break;

      /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
        should be emitted or not.  FIXME: Not implemented.  */
    case 'Q':
      break;

      /* Solaris takes -s to specify that .stabs go in a .stabs section,
        rather than .stabs.excl, which is ignored by the linker.
        FIXME: Not implemented.  */
    case 's':
      if (arg)
       return 0;

      break;
#endif

    default:
      return 0;
    }

  return 1;
}

Here is the call graph for this function:

long md_pcrel_from_section ( fixS *  fixp,
sec   
)

Definition at line 5321 of file tc-ppc.c.

{
  return fixp->fx_frag->fr_address + fixp->fx_where;
}
valueT md_section_align ( asection *seg  ATTRIBUTE_UNUSED,
valueT  addr 
)

Definition at line 5273 of file tc-ppc.c.

{
#ifdef OBJ_ELF
  return addr;
#else
  int align = bfd_get_section_alignment (stdoutput, seg);

  return ((addr + (1 << align) - 1) & (-1 << align));
#endif
}
void md_show_usage ( FILE *  stream)

Definition at line 1100 of file tc-ppc.c.

{
  fprintf (stream, _("\
PowerPC options:\n\
-a32                 generate ELF32/XCOFF32\n\
-a64                 generate ELF64/XCOFF64\n\
-u                   ignored\n\
-mpwrx, -mpwr2              generate code for POWER/2 (RIOS2)\n\
-mpwr                generate code for POWER (RIOS1)\n\
-m601                generate code for PowerPC 601\n\
-mppc, -mppc32, -m603, -m604\n\
                     generate code for PowerPC 603/604\n\
-m403, -m405         generate code for PowerPC 403/405\n\
-m440                generate code for PowerPC 440\n\
-m7400, -m7410, -m7450, -m7455\n\
                     generate code For PowerPC 7400/7410/7450/7455\n"));
  fprintf (stream, _("\
-mppc64, -m620              generate code for PowerPC 620/625/630\n\
-mppc64bridge        generate code for PowerPC 64, including bridge insns\n\
-mbooke64            generate code for 64-bit PowerPC BookE\n\
-mbooke, mbooke32    generate code for 32-bit PowerPC BookE\n\
-mpower4             generate code for Power4 architecture\n\
-mpower5             generate code for Power5 architecture\n\
-mpower6             generate code for Power6 architecture\n\
-mcell               generate code for Cell Broadband Engine architecture\n\
-mcom                generate code Power/PowerPC common instructions\n\
-many                generate code for any architecture (PWR/PWRX/PPC)\n"));
  fprintf (stream, _("\
-maltivec            generate code for AltiVec\n\
-me300               generate code for PowerPC e300 family\n\
-me500, -me500x2     generate code for Motorola e500 core complex\n\
-mspe                generate code for Motorola SPE instructions\n\
-mregnames           Allow symbolic names for registers\n\
-mno-regnames        Do not allow symbolic names for registers\n"));
#ifdef OBJ_ELF
  fprintf (stream, _("\
-mrelocatable        support for GCC's -mrelocatble option\n\
-mrelocatable-lib    support for GCC's -mrelocatble-lib option\n\
-memb                set PPC_EMB bit in ELF flags\n\
-mlittle, -mlittle-endian, -l, -le\n\
                     generate code for a little endian machine\n\
-mbig, -mbig-endian, -b, -be\n\
                     generate code for a big endian machine\n\
-msolaris            generate code for Solaris\n\
-mno-solaris         do not generate code for Solaris\n\
-V                   print assembler version number\n\
-Qy, -Qn             ignored\n"));
#endif
}

Here is the call graph for this function:

symbolS* md_undefined_symbol ( name  )

Definition at line 5309 of file tc-ppc.c.

{
  return 0;
}
static bfd_boolean register_name PARAMS ( (expressionS *)  ) [static]
static void ppc_set_cpu PARAMS ( (void)  ) [static]
static void ppc_macro PARAMS ( (char *str, const struct powerpc_macro *macro ) [static]
static void ppc_byte PARAMS ( (int ) [static]
static int reg_name_search PARAMS ( (const struct pd_reg *, int, const char *name ) [static]
static int parse_cpu ( const char *  arg) [static]

Definition at line 825 of file tc-ppc.c.

{
  /* -mpwrx and -mpwr2 mean to assemble for the IBM POWER/2
     (RIOS2).  */
  if (strcmp (arg, "pwrx") == 0 || strcmp (arg, "pwr2") == 0)
    ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_32;
  /* -mpwr means to assemble for the IBM POWER (RIOS1).  */
  else if (strcmp (arg, "pwr") == 0)
    ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
  /* -m601 means to assemble for the PowerPC 601, which includes
     instructions that are holdovers from the Power.  */
  else if (strcmp (arg, "601") == 0)
    ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
              | PPC_OPCODE_601 | PPC_OPCODE_32);
  /* -mppc, -mppc32, -m603, and -m604 mean to assemble for the
     PowerPC 603/604.  */
  else if (strcmp (arg, "ppc") == 0
          || strcmp (arg, "ppc32") == 0
          || strcmp (arg, "603") == 0
          || strcmp (arg, "604") == 0)
    ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
  /* -m403 and -m405 mean to assemble for the PowerPC 403/405.  */
  else if (strcmp (arg, "403") == 0
          || strcmp (arg, "405") == 0)
    ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
              | PPC_OPCODE_403 | PPC_OPCODE_32);
  else if (strcmp (arg, "440") == 0)
    ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32
              | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI);
  else if (strcmp (arg, "7400") == 0
          || strcmp (arg, "7410") == 0
          || strcmp (arg, "7450") == 0
          || strcmp (arg, "7455") == 0)
    ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
              | PPC_OPCODE_ALTIVEC | PPC_OPCODE_32);
  else if (strcmp (arg, "e300") == 0)
    ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32
              | PPC_OPCODE_E300);
  else if (strcmp (arg, "altivec") == 0)
    {
      if (ppc_cpu == 0)
       ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC;
      else
       ppc_cpu |= PPC_OPCODE_ALTIVEC;
    }
  else if (strcmp (arg, "e500") == 0 || strcmp (arg, "e500x2") == 0)
    {
      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
               | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
               | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
               | PPC_OPCODE_RFMCI);
    }
  else if (strcmp (arg, "spe") == 0)
    {
      if (ppc_cpu == 0)
       ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_SPE | PPC_OPCODE_EFS;
      else
       ppc_cpu |= PPC_OPCODE_SPE;
    }
  /* -mppc64 and -m620 mean to assemble for the 64-bit PowerPC
     620.  */
  else if (strcmp (arg, "ppc64") == 0 || strcmp (arg, "620") == 0)
    {
      ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
    }
  else if (strcmp (arg, "ppc64bridge") == 0)
    {
      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
               | PPC_OPCODE_64_BRIDGE | PPC_OPCODE_64);
    }
  /* -mbooke/-mbooke32 mean enable 32-bit BookE support.  */
  else if (strcmp (arg, "booke") == 0 || strcmp (arg, "booke32") == 0)
    {
      ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32;
    }
  /* -mbooke64 means enable 64-bit BookE support.  */
  else if (strcmp (arg, "booke64") == 0)
    {
      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE
               | PPC_OPCODE_BOOKE64 | PPC_OPCODE_64);
    }
  else if (strcmp (arg, "power4") == 0)
    {
      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
               | PPC_OPCODE_64 | PPC_OPCODE_POWER4);
    }
  else if (strcmp (arg, "power5") == 0)
    {
      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
               | PPC_OPCODE_64 | PPC_OPCODE_POWER4
               | PPC_OPCODE_POWER5);
    }
  else if (strcmp (arg, "power6") == 0)
    {
      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
               | PPC_OPCODE_64 | PPC_OPCODE_POWER4
               | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6);
    }
  else if (strcmp (arg, "cell") == 0)
    {
      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
               | PPC_OPCODE_64 | PPC_OPCODE_POWER4
               | PPC_OPCODE_CELL);
    }
  /* -mcom means assemble for the common intersection between Power
     and PowerPC.  At present, we just allow the union, rather
     than the intersection.  */
  else if (strcmp (arg, "com") == 0)
    ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32;
  /* -many means to assemble for any architecture (PWR/PWRX/PPC).  */
  else if (strcmp (arg, "any") == 0)
    ppc_cpu |= PPC_OPCODE_ANY;
  else
    return 0;

  return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1182 of file tc-ppc.c.

{
  const char *default_cpu = TARGET_CPU;
  ppc_set_cpu ();

  if ((ppc_cpu & PPC_OPCODE_PPC) != 0)
    return bfd_arch_powerpc;
  else if ((ppc_cpu & PPC_OPCODE_POWER) != 0)
    return bfd_arch_rs6000;
  else if ((ppc_cpu & (PPC_OPCODE_COMMON | PPC_OPCODE_ANY)) != 0)
    {
      if (strcmp (default_cpu, "rs6000") == 0)
       return bfd_arch_rs6000;
      else if (strncmp (default_cpu, "powerpc", 7) == 0)
       return bfd_arch_powerpc;
    }

  as_fatal (_("Neither Power nor PowerPC opcodes were selected."));
  return bfd_arch_unknown;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ppc_byte ( ignore  ) [static]

Definition at line 2875 of file tc-ppc.c.

{
  if (*input_line_pointer != '\"')
    {
      cons (1);
      return;
    }

  /* Gather characters.  A real double quote is doubled.  Unusual
     characters are not permitted.  */
  ++input_line_pointer;
  while (1)
    {
      char c;

      c = *input_line_pointer++;

      if (c == '\"')
       {
         if (*input_line_pointer != '\"')
           break;
         ++input_line_pointer;
       }

      FRAG_APPEND_1_CHAR (c);
    }

  demand_empty_rest_of_line ();
}

Here is the call graph for this function:

Definition at line 6132 of file tc-ppc.c.

{
  cfi_add_CFA_def_cfa (1, 0);
}

Here is the call graph for this function:

void ppc_cleanup ( )

Definition at line 1381 of file tc-ppc.c.

{
#ifdef OBJ_ELF
  if (ppc_apuinfo_list == NULL)
    return;

  /* Ok, so write the section info out.  We have this layout:

  byte data          what
  ---- ----          ----
  0    8             length of "APUinfo\0"
  4    (n*4)         number of APU's (4 bytes each)
  8    2             note type 2
  12   "APUinfo\0"   name
  20   APU#1         first APU's info
  24   APU#2         second APU's info
  ...  ...
  */
  {
    char *p;
    asection *seg = now_seg;
    subsegT subseg = now_subseg;
    asection *apuinfo_secp = (asection *) NULL;
    unsigned int i;

    /* Create the .PPC.EMB.apuinfo section.  */
    apuinfo_secp = subseg_new (".PPC.EMB.apuinfo", 0);
    bfd_set_section_flags (stdoutput,
                        apuinfo_secp,
                        SEC_HAS_CONTENTS | SEC_READONLY);

    p = frag_more (4);
    md_number_to_chars (p, (valueT) 8, 4);

    p = frag_more (4);
    md_number_to_chars (p, (valueT) ppc_apuinfo_num * 4, 4);

    p = frag_more (4);
    md_number_to_chars (p, (valueT) 2, 4);

    p = frag_more (8);
    strcpy (p, "APUinfo");

    for (i = 0; i < ppc_apuinfo_num; i++)
      {
       p = frag_more (4);
       md_number_to_chars (p, (valueT) ppc_apuinfo_list[i], 4);
      }

    frag_align (2, 0, 0);

    /* We probably can't restore the current segment, for there likely
       isn't one yet...  */
    if (seg && subseg)
      subseg_set (seg, subseg);
  }
#endif
}

Here is the call graph for this function:

void ppc_handle_align ( struct frag fragP)

Definition at line 5533 of file tc-ppc.c.

{
  valueT count = (fragP->fr_next->fr_address
                - (fragP->fr_address + fragP->fr_fix));

  if (count != 0 && (count & 3) == 0)
    {
      char *dest = fragP->fr_literal + fragP->fr_fix;

      fragP->fr_var = 4;
      md_number_to_chars (dest, 0x60000000, 4);

      if ((ppc_cpu & PPC_OPCODE_POWER6) != 0)
       {
         /* For power6, we want the last nop to be a group terminating
            one, "ori 1,1,0".  Do this by inserting an rs_fill frag
            immediately after this one, with its address set to the last
            nop location.  This will automatically reduce the number of
            nops in the current frag by one.  */
         if (count > 4)
           {
             struct frag *group_nop = xmalloc (SIZEOF_STRUCT_FRAG + 4);

             memcpy (group_nop, fragP, SIZEOF_STRUCT_FRAG);
             group_nop->fr_address = group_nop->fr_next->fr_address - 4;
             group_nop->fr_fix = 0;
             group_nop->fr_offset = 1;
             group_nop->fr_type = rs_fill;
             fragP->fr_next = group_nop;
             dest = group_nop->fr_literal;
           }

         md_number_to_chars (dest, 0x60210000, 4);
       }
    }
}

Here is the call graph for this function:

static unsigned long ppc_insert_operand ( unsigned long  insn,
const struct powerpc_operand operand,
offsetT  val,
char *  file,
unsigned int  line 
) [static]

Definition at line 1443 of file tc-ppc.c.

{
  if (operand->bits != 32)
    {
      long min, max;
      offsetT test;

      if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
       {
         if ((operand->flags & PPC_OPERAND_SIGNOPT) != 0)
           max = (1 << operand->bits) - 1;
         else
           max = (1 << (operand->bits - 1)) - 1;
         min = - (1 << (operand->bits - 1));

         if (!ppc_obj64)
           {
             /* Some people write 32 bit hex constants with the sign
               extension done by hand.  This shouldn't really be
               valid, but, to permit this code to assemble on a 64
               bit host, we sign extend the 32 bit value.  */
             if (val > 0
                && (val & (offsetT) 0x80000000) != 0
                && (val & (offsetT) 0xffffffff) == val)
              {
                val -= 0x80000000;
                val -= 0x80000000;
              }
           }
       }
      else
       {
         max = (1 << operand->bits) - 1;
         min = 0;
       }

      if ((operand->flags & PPC_OPERAND_NEGATIVE) != 0)
       test = - val;
      else
       test = val;

      if (test < (offsetT) min || test > (offsetT) max)
       as_bad_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line);
    }

  if (operand->insert)
    {
      const char *errmsg;

      errmsg = NULL;
      insn = (*operand->insert) (insn, (long) val, ppc_cpu, &errmsg);
      if (errmsg != (const char *) NULL)
       as_bad_where (file, line, errmsg);
    }
  else
    insn |= (((long) val & ((1 << operand->bits) - 1))
            << operand->shift);

  return insn;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1204 of file tc-ppc.c.

{
  if (ppc_obj64)
    return bfd_mach_ppc64;
  else if (ppc_arch () == bfd_arch_rs6000)
    return bfd_mach_rs6k;
  else
    return bfd_mach_ppc;
}

Here is the call graph for this function:

static void ppc_macro ( char *  str,
const struct powerpc_macro macro 
) [static]

Definition at line 2741 of file tc-ppc.c.

{
  char *operands[10];
  unsigned int count;
  char *s;
  unsigned int len;
  const char *format;
  int arg;
  char *send;
  char *complete;

  /* Gather the users operands into the operands array.  */
  count = 0;
  s = str;
  while (1)
    {
      if (count >= sizeof operands / sizeof operands[0])
       break;
      operands[count++] = s;
      s = strchr (s, ',');
      if (s == (char *) NULL)
       break;
      *s++ = '\0';
    }

  if (count != macro->operands)
    {
      as_bad (_("wrong number of operands"));
      return;
    }

  /* Work out how large the string must be (the size is unbounded
     because it includes user input).  */
  len = 0;
  format = macro->format;
  while (*format != '\0')
    {
      if (*format != '%')
       {
         ++len;
         ++format;
       }
      else
       {
         arg = strtol (format + 1, &send, 10);
         know (send != format && arg >= 0 && arg < count);
         len += strlen (operands[arg]);
         format = send;
       }
    }

  /* Put the string together.  */
  complete = s = (char *) alloca (len + 1);
  format = macro->format;
  while (*format != '\0')
    {
      if (*format != '%')
       *s++ = *format++;
      else
       {
         arg = strtol (format + 1, &send, 10);
         strcpy (s, operands[arg]);
         s += strlen (s);
         format = send;
       }
    }
  *s = '\0';

  /* Assemble the constructed instruction.  */
  md_assemble (complete);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ppc_parse_name ( char *  name,
expressionS expr 
) const

Definition at line 679 of file tc-ppc.c.

{
  int val;

  if (! cr_operand)
    return 0;

  val = reg_name_search (cr_names, sizeof cr_names / sizeof cr_names[0],
                      name);
  if (val < 0)
    return 0;

  expr->X_op = O_constant;
  expr->X_add_number = val;

  return 1;
}

Here is the call graph for this function:

static void ppc_set_cpu ( ) [static]

Definition at line 1154 of file tc-ppc.c.

{
  const char *default_os  = TARGET_OS;
  const char *default_cpu = TARGET_CPU;

  if ((ppc_cpu & ~PPC_OPCODE_ANY) == 0)
    {
      if (ppc_obj64)
       ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
      else if (strncmp (default_os, "aix", 3) == 0
              && default_os[3] >= '4' && default_os[3] <= '9')
       ppc_cpu |= PPC_OPCODE_COMMON | PPC_OPCODE_32;
      else if (strncmp (default_os, "aix3", 4) == 0)
       ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32;
      else if (strcmp (default_cpu, "rs6000") == 0)
       ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32;
      else if (strncmp (default_cpu, "powerpc", 7) == 0)
       ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
      else
       as_fatal (_("Unknown default cpu = %s, os = %s"),
                default_cpu, default_os);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ppc_setup_opcodes ( void  ) [static]

Definition at line 1245 of file tc-ppc.c.

{
  register const struct powerpc_opcode *op;
  const struct powerpc_opcode *op_end;
  const struct powerpc_macro *macro;
  const struct powerpc_macro *macro_end;
  bfd_boolean dup_insn = FALSE;

  if (ppc_hash != NULL)
    hash_die (ppc_hash);
  if (ppc_macro_hash != NULL)
    hash_die (ppc_macro_hash);

  /* Insert the opcodes into a hash table.  */
  ppc_hash = hash_new ();

  op_end = powerpc_opcodes + powerpc_num_opcodes;
  for (op = powerpc_opcodes; op < op_end; op++)
    {
      know ((op->opcode & op->mask) == op->opcode);

      if ((op->flags & ppc_cpu & ~(PPC_OPCODE_32 | PPC_OPCODE_64)) != 0
         && ((op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == 0
             || ((op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64))
                == (ppc_cpu & (PPC_OPCODE_32 | PPC_OPCODE_64)))
             || (ppc_cpu & PPC_OPCODE_64_BRIDGE) != 0)
         /* Certain instructions (eg: extsw) do not exist in the
            32-bit BookE instruction set, but they do exist in the
            64-bit BookE instruction set, and other PPC instruction
            sets.  Check to see if the opcode has the BOOKE64 flag set.
            If it does make sure that the target CPU is not the BookE32.  */
         && ((op->flags & PPC_OPCODE_BOOKE64) == 0
             || (ppc_cpu & PPC_OPCODE_BOOKE64) == PPC_OPCODE_BOOKE64
             || (ppc_cpu & PPC_OPCODE_BOOKE) == 0)
         && ((op->flags & (PPC_OPCODE_POWER4 | PPC_OPCODE_NOPOWER4)) == 0
             || ((op->flags & PPC_OPCODE_POWER4)
                == (ppc_cpu & PPC_OPCODE_POWER4)))
         && ((op->flags & PPC_OPCODE_POWER5) == 0
             || ((op->flags & PPC_OPCODE_POWER5)
                == (ppc_cpu & PPC_OPCODE_POWER5)))
         && ((op->flags & PPC_OPCODE_POWER6) == 0
             || ((op->flags & PPC_OPCODE_POWER6)
                == (ppc_cpu & PPC_OPCODE_POWER6))))
       {
         const char *retval;

         retval = hash_insert (ppc_hash, op->name, (PTR) op);
         if (retval != NULL)
           {
             /* Ignore Power duplicates for -m601.  */
             if ((ppc_cpu & PPC_OPCODE_601) != 0
                && (op->flags & PPC_OPCODE_POWER) != 0)
              continue;

             as_bad (_("Internal assembler error for instruction %s"),
                    op->name);
             dup_insn = TRUE;
           }
       }
    }

  if ((ppc_cpu & PPC_OPCODE_ANY) != 0)
    for (op = powerpc_opcodes; op < op_end; op++)
      hash_insert (ppc_hash, op->name, (PTR) op);

  /* Insert the macros into a hash table.  */
  ppc_macro_hash = hash_new ();

  macro_end = powerpc_macros + powerpc_num_macros;
  for (macro = powerpc_macros; macro < macro_end; macro++)
    {
      if ((macro->flags & ppc_cpu) != 0)
       {
         const char *retval;

         retval = hash_insert (ppc_macro_hash, macro->name, (PTR) macro);
         if (retval != (const char *) NULL)
           {
             as_bad (_("Internal assembler error for macro %s"), macro->name);
             dup_insn = TRUE;
           }
       }
    }

  if (dup_insn)
    abort ();
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* ppc_target_format ( )

Definition at line 1215 of file tc-ppc.c.

{
#ifdef OBJ_COFF
#ifdef TE_PE
  return target_big_endian ? "pe-powerpc" : "pe-powerpcle";
#elif TE_POWERMAC
  return "xcoff-powermac";
#else
#  ifdef TE_AIX5
    return (ppc_obj64 ? "aix5coff64-rs6000" : "aixcoff-rs6000");
#  else
    return (ppc_obj64 ? "aixcoff64-rs6000" : "aixcoff-rs6000");
#  endif
#endif
#endif
#ifdef OBJ_ELF
# ifdef TE_VXWORKS
  return "elf32-powerpc-vxworks";
# else
  return (target_big_endian
         ? (ppc_obj64 ? "elf64-powerpc" : "elf32-powerpc")
         : (ppc_obj64 ? "elf64-powerpcle" : "elf32-powerpcle"));
# endif
#endif
}
static int reg_name_search ( struct pd_reg regs,
int  regcount,
const char *  name 
) const [static]

Definition at line 571 of file tc-ppc.c.

{
  int middle, low, high;
  int cmp;

  low = 0;
  high = regcount - 1;

  do
    {
      middle = (low + high) / 2;
      cmp = strcasecmp (name, regs[middle].name);
      if (cmp < 0)
       high = middle - 1;
      else if (cmp > 0)
       low = middle + 1;
      else
       return regs[middle].value;
    }
  while (low <= high);

  return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean register_name ( expressionS expressionP) [static]

Definition at line 611 of file tc-ppc.c.

{
  int reg_number;
  char *name;
  char *start;
  char c;

  /* Find the spelling of the operand.  */
  start = name = input_line_pointer;
  if (name[0] == '%' && ISALPHA (name[1]))
    name = ++input_line_pointer;

  else if (!reg_names_p || !ISALPHA (name[0]))
    return FALSE;

  c = get_symbol_end ();
  reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);

  /* Put back the delimiting char.  */
  *input_line_pointer = c;

  /* Look to see if it's in the register table.  */
  if (reg_number >= 0)
    {
      expressionP->X_op = O_register;
      expressionP->X_add_number = reg_number;

      /* Make the rest nice.  */
      expressionP->X_add_symbol = NULL;
      expressionP->X_op_symbol = NULL;
      return TRUE;
    }

  /* Reset the line as if we had not done anything.  */
  input_line_pointer = start;
  return FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

arelent* tc_gen_reloc ( seg  ,
fixS *  fixp 
)

Definition at line 6107 of file tc-ppc.c.

{
  arelent *reloc;

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

  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
  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,
                  _("reloc %d not supported by object file format"),
                  (int) fixp->fx_r_type);
      return NULL;
    }
  reloc->addend = fixp->fx_addnumber;

  return reloc;
}

Here is the call graph for this function:

int tc_ppc_regname_to_dw2regnum ( char *  regname)

Definition at line 6138 of file tc-ppc.c.

{
  unsigned int regnum = -1;
  unsigned int i;
  const char *p;
  char *q;
  static struct { char *name; int dw2regnum; } regnames[] =
    {
      { "sp", 1 }, { "r.sp", 1 }, { "rtoc", 2 }, { "r.toc", 2 },
      { "mq", 64 }, { "lr", 65 }, { "ctr", 66 }, { "ap", 67 },
      { "cr", 70 }, { "xer", 76 }, { "vrsave", 109 }, { "vscr", 110 },
      { "spe_acc", 111 }, { "spefscr", 112 }
    };

  for (i = 0; i < ARRAY_SIZE (regnames); ++i)
    if (strcmp (regnames[i].name, regname) == 0)
      return regnames[i].dw2regnum;

  if (regname[0] == 'r' || regname[0] == 'f' || regname[0] == 'v')
    {
      p = regname + 1 + (regname[1] == '.');
      regnum = strtoul (p, &q, 10);
      if (p == q || *q || regnum >= 32)
       return -1;
      if (regname[0] == 'f')
       regnum += 32;
      else if (regname[0] == 'v')
       regnum += 77;
    }
  else if (regname[0] == 'c' && regname[1] == 'r')
    {
      p = regname + 2 + (regname[2] == '.');
      if (p[0] < '0' || p[0] > '7' || p[1])
       return -1;
      regnum = p[0] - '0' + 68;
    }
  return regnum;
}

Here is the call graph for this function:


Variable Documentation

const char comment_chars[] = "#"

Definition at line 167 of file tc-ppc.c.

Definition at line 655 of file tc-ppc.c.

const char EXP_CHARS[] = "eE"

Definition at line 179 of file tc-ppc.c.

const char FLT_CHARS[] = "dD"

Definition at line 183 of file tc-ppc.c.

const char line_comment_chars[] = "#"

Definition at line 171 of file tc-ppc.c.

Definition at line 175 of file tc-ppc.c.

const size_t md_longopts_size = sizeof (md_longopts)

Definition at line 819 of file tc-ppc.c.

const pseudo_typeS md_pseudo_table[]

Definition at line 194 of file tc-ppc.c.

const char* const md_shortopts = "um:"

Definition at line 814 of file tc-ppc.c.

static struct pd_reg [static]

Definition at line 315 of file tc-ppc.c.

Definition at line 190 of file tc-ppc.c.

unsigned long ppc_cpu = 0 [static]

Definition at line 703 of file tc-ppc.c.

Definition at line 709 of file tc-ppc.c.

Definition at line 712 of file tc-ppc.c.

Definition at line 706 of file tc-ppc.c.

const char ppc_symbol_chars[] = "%["

Definition at line 187 of file tc-ppc.c.

Definition at line 85 of file tc-ppc.c.

int set_target_endian = 0 [static]

Definition at line 44 of file tc-ppc.c.

Definition at line 164 of file read.c.