* config/tc-cr16.h (GLOBAL_OFFSET_TABLE_NAME): Defined
authorM R Swami Reddy <MR.Swami.Reddy@nsc.com>
Thu, 27 Nov 2008 11:57:29 +0000 (11:57 +0000)
committerM R Swami Reddy <MR.Swami.Reddy@nsc.com>
Thu, 27 Nov 2008 11:57:29 +0000 (11:57 +0000)
        * config/tc-cr16.c (md_pseudo_table): Add "4byte" directive to
        md_pseudo_table and accept @c prefix, same as long directive.
        (cr16_cons_fix_new): Initialize rtype to BFD_RELOC_UNUSED.
        config/tc-cr16.c (tc_gen_reloc): Declare a variable of type
        bfd_reloc_code_real_type and set it for GOT related relocations.
        (md_undefined_symbol): Defined
        (process_label_constant): Added checks for GOT/got and cGOT/cGOT
        prefixes with constant label and set the appropriate relocation type.
        * doc/c-cr16.texi (cr16-operand specifiers): Add got/GOT and cgot/cGOT.

gas/ChangeLog
gas/config/tc-cr16.c
gas/config/tc-cr16.h

index 2e6aa35..81daee0 100644 (file)
@@ -1,3 +1,16 @@
+2008-11-27  M R Swami Reddy <MR.Swami.Reddy@nsc.com>
+
+       * config/tc-cr16.h (GLOBAL_OFFSET_TABLE_NAME): Defined
+       * config/tc-cr16.c (md_pseudo_table): Add "4byte" directive to
+       md_pseudo_table and accept @c prefix, same as long directive.
+       (cr16_cons_fix_new): Initialize rtype to BFD_RELOC_UNUSED.
+       (tc_gen_reloc): Declare a variable of type bfd_reloc_code_real_type
+       and set it for GOT related relocations.
+       (md_undefined_symbol): Defined
+       (process_label_constant): Added checks for GOT/got and cGOT/cGOT
+       prefixes with constant label and set the appropriate relocation type.
+       * doc/c-cr16.texi (cr16-operand specifiers): Add got/GOT and cgot/cGOT. 
+
 2008-11-26  DJ Delorie  <dj@redhat.com>
 
        * config/tc-m32c.c (md_pseudo_table): Add support for .loc et al.
index 7fec215..171e3f3 100644 (file)
@@ -99,6 +99,11 @@ const char EXP_CHARS[] = "eE";
 /* Chars that mean this number is a floating point constant as in 0f12.456  */
 const char FLT_CHARS[] = "f'";
 
+#ifdef OBJ_ELF
+/* Pre-defined "_GLOBAL_OFFSET_TABLE_"  */
+symbolS * GOT_symbol;
+#endif
+
 /* Target-specific multicharacter options, not const-declared at usage.  */
 const char *md_shortopts = "";
 struct option md_longopts[] =
@@ -236,7 +241,6 @@ l_cons (int nbytes)
   demand_empty_rest_of_line ();
 }
 
-
 /* This table describes all the machine specific pseudo-ops
    the assembler has to support.  The fields are:
    *** Pseudo-op name without dot.
@@ -248,6 +252,7 @@ const pseudo_typeS md_pseudo_table[] =
   /* In CR16 machine, align is in bytes (not a ptwo boundary).  */
   {"align", s_align_bytes, 0},
   {"long", l_cons,  4 },
+  {"4byte", l_cons, 4 },
   {0, 0, 0}
 };
 
@@ -489,7 +494,8 @@ cr16_force_relocation (fixS *fix)
 void
 cr16_cons_fix_new (fragS *frag, int offset, int len, expressionS *exp)
 {
-  int rtype;
+  int rtype = BFD_RELOC_UNUSED;
+
   switch (len)
     {
     default: rtype = BFD_RELOC_NONE; break;
@@ -515,6 +521,7 @@ arelent *
 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS * fixP)
 {
   arelent * reloc;
+  bfd_reloc_code_real_type code;
 
   reloc = xmalloc (sizeof (arelent));
   reloc->sym_ptr_ptr  = xmalloc (sizeof (asymbol *));
@@ -562,6 +569,22 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS * fixP)
                         segment_name (S_GET_SEGMENT (fixP->fx_addsy)));
         }
     }
+#ifdef OBJ_ELF
+      if ((fixP->fx_r_type == BFD_RELOC_CR16_GOT_REGREL20)
+           && GOT_symbol
+          && fixP->fx_addsy == GOT_symbol)
+       {
+           code = BFD_RELOC_CR16_GOT_REGREL20;
+           reloc->addend = fixP->fx_offset = reloc->address;
+       }
+      else if ((fixP->fx_r_type == BFD_RELOC_CR16_GOTC_REGREL20)
+           && GOT_symbol
+          && fixP->fx_addsy == GOT_symbol)
+       {
+           code = BFD_RELOC_CR16_GOTC_REGREL20;
+           reloc->addend = fixP->fx_offset = reloc->address;
+       }
+#endif
 
   assert ((int) fixP->fx_r_type > 0);
   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
@@ -653,6 +676,24 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, fragS *fragP)
   fragP->fr_fix += md_relax_table[fragP->fr_subtype].rlx_length;
 }
 
+symbolS *
+md_undefined_symbol (char *name)
+{
+  if (*name == '_' && *(name + 1) == 'G'
+      && strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
+   {
+     if (!GOT_symbol)
+       {
+         if (symbol_find (name))
+             as_bad (_("GOT already in symbol table"));
+          GOT_symbol = symbol_new (name, undefined_section,
+                                   (valueT) 0, &zero_address_frag);
+       }
+     return GOT_symbol;
+   }
+  return 0;
+}
+
 /* Process machine-dependent command line options.  Called once for
    each option on the command line that the machine-independent part of
    GAS does not understand.  */
@@ -813,6 +854,8 @@ process_label_constant (char *str, ins * cr16_ins)
   int symbol_with_s = 0;
   int symbol_with_m = 0;
   int symbol_with_l = 0;
+  int symbol_with_at_got = 0;
+  int symbol_with_at_gotc = 0;
   argument *cur_arg = cr16_ins->arg + cur_arg_num;  /* Current argument.  */
 
   saved_input_line_pointer = input_line_pointer;
@@ -842,6 +885,8 @@ process_label_constant (char *str, ins * cr16_ins)
     case O_subtract:
     case O_add:
       cur_arg->X_op = O_symbol;
+      cur_arg->constant = cr16_ins->exp.X_add_number;
+      cr16_ins->exp.X_add_number = 0;
       cr16_ins->rtype = BFD_RELOC_NONE;
       relocatable = 1;
 
@@ -860,12 +905,37 @@ process_label_constant (char *str, ins * cr16_ins)
           || strneq (input_line_pointer, ":s", 2))
         symbol_with_s = 1;
 
+      if (strneq (input_line_pointer, "@cGOT", 5)
+          || strneq (input_line_pointer, "@cgot", 5))
+       {
+         if (GOT_symbol == NULL)
+           GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
+
+          symbol_with_at_gotc = 1;
+       }
+      else if (strneq (input_line_pointer, "@GOT", 4)
+          || strneq (input_line_pointer, "@got", 4))
+       {
+          if ((strneq (input_line_pointer, "+", 1)) 
+              || (strneq (input_line_pointer, "-", 1)))
+           as_warn (_("GOT bad expression with %s."), input_line_pointer);
+
+         if (GOT_symbol == NULL)
+           GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
+
+          symbol_with_at_got = 1;
+       }
+
       switch (cur_arg->type)
         {
         case arg_cr:
           if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
             {
-              if (cur_arg->size == 20)
+             if (symbol_with_at_got)
+                 cr16_ins->rtype = BFD_RELOC_CR16_GOT_REGREL20;
+             else if (symbol_with_at_gotc)
+                 cr16_ins->rtype = BFD_RELOC_CR16_GOTC_REGREL20;
+             else if (cur_arg->size == 20)
                 cr16_ins->rtype = BFD_RELOC_CR16_REGREL20;
               else
                 cr16_ins->rtype = BFD_RELOC_CR16_REGREL20a;
@@ -874,6 +944,12 @@ process_label_constant (char *str, ins * cr16_ins)
 
         case arg_crp:
           if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
+          {
+           if (symbol_with_at_got)
+             cr16_ins->rtype = BFD_RELOC_CR16_GOT_REGREL20;
+           else if (symbol_with_at_gotc)
+             cr16_ins->rtype = BFD_RELOC_CR16_GOTC_REGREL20;
+          } else {
             switch (instruction->size)
               {
               case 1:
@@ -903,15 +979,29 @@ process_label_constant (char *str, ins * cr16_ins)
               default:
                 break;
               }
+           }
           break;
 
         case arg_idxr:
           if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
-            cr16_ins->rtype = BFD_RELOC_CR16_REGREL20;
+           {
+             if (symbol_with_at_got)
+               cr16_ins->rtype = BFD_RELOC_CR16_GOT_REGREL20;
+             else if (symbol_with_at_gotc)
+               cr16_ins->rtype = BFD_RELOC_CR16_GOTC_REGREL20;
+             else
+                cr16_ins->rtype = BFD_RELOC_CR16_REGREL20;
+           }
           break;
 
         case arg_idxrp:
           if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
+           {
+           if (symbol_with_at_got)
+             cr16_ins->rtype = BFD_RELOC_CR16_GOT_REGREL20;
+           else if (symbol_with_at_gotc)
+             cr16_ins->rtype = BFD_RELOC_CR16_GOTC_REGREL20;
+           else {
             switch (instruction->size)
               {
               case 1: cr16_ins->rtype = BFD_RELOC_CR16_REGREL0; break;
@@ -919,6 +1009,8 @@ process_label_constant (char *str, ins * cr16_ins)
               case 3: cr16_ins->rtype = BFD_RELOC_CR16_REGREL20; break;
               default: break;
               }
+           }
+          }
           break;
 
         case arg_c:
@@ -936,9 +1028,13 @@ process_label_constant (char *str, ins * cr16_ins)
           else if (IS_INSN_TYPE (STOR_IMM_INS) || IS_INSN_TYPE (LD_STOR_INS)
                    || IS_INSN_TYPE (CSTBIT_INS))
             {
-              if (symbol_with_s)
+             if (symbol_with_s)
                 as_bad (_("operand %d: illegal use expression: `%s`"), cur_arg_num + 1, str);
-              if (symbol_with_m)
+             if (symbol_with_at_got)
+               cr16_ins->rtype = BFD_RELOC_CR16_GOT_REGREL20;
+             else if (symbol_with_at_gotc)
+               cr16_ins->rtype = BFD_RELOC_CR16_GOTC_REGREL20;
+             else if (symbol_with_m)
                 cr16_ins->rtype = BFD_RELOC_CR16_ABS20;
               else /* Default to (symbol_with_l) */
                 cr16_ins->rtype = BFD_RELOC_CR16_ABS24;
@@ -950,7 +1046,11 @@ process_label_constant (char *str, ins * cr16_ins)
         case arg_ic:
           if (IS_INSN_TYPE (ARITH_INS))
             {
-              if (symbol_with_s)
+             if (symbol_with_at_got)
+               cr16_ins->rtype = BFD_RELOC_CR16_GOT_REGREL20;
+             else if (symbol_with_at_gotc)
+               cr16_ins->rtype = BFD_RELOC_CR16_GOTC_REGREL20;
+             else if (symbol_with_s)
                 cr16_ins->rtype = BFD_RELOC_CR16_IMM4;
               else if (symbol_with_m)
                 cr16_ins->rtype = BFD_RELOC_CR16_IMM20;
@@ -2330,7 +2430,7 @@ print_insn (ins *insn)
         this_frag = frag_var (rs_machine_dependent, insn_size *2,
                               4, relax_subtype,
                               insn->exp.X_add_symbol,
-                              insn->exp.X_add_number,
+                              0,
                               0);
       }
     else
index 4b43f21..9aab15d 100644 (file)
 
 #define TARGET_BYTES_BIG_ENDIAN 0
 
+#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
+
 #define TARGET_FORMAT "elf32-cr16"
 #define TARGET_ARCH   bfd_arch_cr16
 
 #define WORKING_DOT_WORD
 #define LOCAL_LABEL_PREFIX '.'
 
-#define md_undefined_symbol(s)  0
 #define md_number_to_chars      number_to_chars_littleendian
 
 /* We do relaxing in the assembler as well as the linker.  */