* alpha-opc.c: Remove ARGSUSED.
[deliverable/binutils-gdb.git] / gas / config / tc-xstormy16.c
index 30b8bcf45969c9cce22457e0511a75e3bfcb7561..83ae94d382aa9b3f678fa444402f76fd96112098 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-xstormy16.c -- Assembler for the Sanyo XSTORMY16.
-   Copyright (C) 2000, 2001, 2002 Free Software Foundation.
+   Copyright 2000, 2001, 2002, 2003 Free Software Foundation.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -104,6 +104,8 @@ md_begin ()
   cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
 }
 
+static bfd_boolean skipping_fptr = FALSE;
+
 void
 md_assemble (str)
      char * str;
@@ -111,6 +113,10 @@ md_assemble (str)
   xstormy16_insn insn;
   char *    errmsg;
 
+  /* Make sure that if we had an erroneous input line which triggered
+     the skipping_fptr boolean that it does not affect following lines.  */
+  skipping_fptr = FALSE;
+
   /* Initialize GAS's cgen interface for a new instruction.  */
   gas_cgen_init_parse ();
 
@@ -135,7 +141,7 @@ md_operand (e)
   if (*input_line_pointer != '@')
     return;
 
-  if (strncmp (input_line_pointer+1, "fptr", 4) == 0)
+  if (strncmp (input_line_pointer + 1, "fptr", 4) == 0)
     {
       input_line_pointer += 5;
       SKIP_WHITESPACE ();
@@ -154,9 +160,28 @@ md_operand (e)
          goto err;
        }
       input_line_pointer++;
+      SKIP_WHITESPACE ();
 
       if (e->X_op != O_symbol)
        as_bad ("Not a symbolic expression");
+      else if (* input_line_pointer == '-')
+       /* We are computing the difference of two function pointers
+          like this:
+
+           .hword  @fptr (foo) - @fptr (bar)
+
+         In this situation we do not want to generate O_fptr_symbol
+         operands because the result is an absolute value, not a
+         function pointer.
+
+         We need to make the check here, rather than when the fixup
+         is generated as the function names (foo & bar in the above
+         example) might be local symbols and we want the expression
+         to be evaluated now.  This kind of thing can happen when
+         gcc is generating computed gotos.  */
+       skipping_fptr = TRUE;
+      else if (skipping_fptr)
+       skipping_fptr = FALSE;
       else
         e->X_op = O_fptr_symbol;
     }
@@ -305,12 +330,13 @@ md_pcrel_from_section (fixP, sec)
 {
   if (fixP->fx_addsy != (symbolS *) NULL
       && (! S_IS_DEFINED (fixP->fx_addsy)
-         || S_GET_SEGMENT (fixP->fx_addsy) != sec))
-    {
-      /* The symbol is undefined (or is defined but not in this section).
-        Let the linker figure it out.  */
-      return 0;
-    }
+         || S_GET_SEGMENT (fixP->fx_addsy) != sec)
+          || xstormy16_force_relocation (fixP))
+    /* The symbol is undefined,
+       or it is defined but not in this section,
+       or the relocation will be relative to this symbol not the section symbol.        
+       Let the linker figure it out.  */
+    return 0;
 
   return fixP->fx_frag->fr_address + fixP->fx_where;
 }
@@ -331,23 +357,31 @@ md_cgen_lookup_reloc (insn, operand, fixP)
     case XSTORMY16_OPERAND_IMM3:
     case XSTORMY16_OPERAND_IMM3B:
     case XSTORMY16_OPERAND_IMM4:
-    case XSTORMY16_OPERAND_IMM12:
     case XSTORMY16_OPERAND_HMEM8:
       return BFD_RELOC_NONE;
 
+    case XSTORMY16_OPERAND_IMM12:
+      fixP->fx_where += 2;
+      return BFD_RELOC_XSTORMY16_12;
+
     case XSTORMY16_OPERAND_IMM8:
     case XSTORMY16_OPERAND_LMEM8:
       return fixP->fx_pcrel ? BFD_RELOC_8_PCREL : BFD_RELOC_8;
 
     case XSTORMY16_OPERAND_IMM16:
+      /* This might have been processed at parse time.  */
       fixP->fx_where += 2;
+      if (fixP->fx_cgen.opinfo && fixP->fx_cgen.opinfo != BFD_RELOC_NONE)
+       return fixP->fx_cgen.opinfo;
       return fixP->fx_pcrel ? BFD_RELOC_16_PCREL : BFD_RELOC_16;
 
     case XSTORMY16_OPERAND_ABS24:
       return BFD_RELOC_XSTORMY16_24;
 
-    case XSTORMY16_OPERAND_REL8_2:
     case XSTORMY16_OPERAND_REL8_4:
+      fixP->fx_addnumber -= 2;
+    case XSTORMY16_OPERAND_REL8_2:
+      fixP->fx_addnumber -= 2;
       fixP->fx_pcrel = 1;
       return BFD_RELOC_8_PCREL;
 
@@ -355,6 +389,7 @@ md_cgen_lookup_reloc (insn, operand, fixP)
       fixP->fx_where += 2;
       /* Fall through...  */
     case XSTORMY16_OPERAND_REL12A:
+      fixP->fx_addnumber -= 2;
       fixP->fx_pcrel = 1;
       return BFD_RELOC_XSTORMY16_REL_12;
 
@@ -371,24 +406,16 @@ int
 xstormy16_force_relocation (fix)
      fixS * fix;
 {
-  switch (fix->fx_r_type)
-    {
-    case BFD_RELOC_XSTORMY16_FPTR16:
-    case BFD_RELOC_VTABLE_INHERIT:
-    case BFD_RELOC_VTABLE_ENTRY:
-      return 1;
+  if (fix->fx_r_type == BFD_RELOC_XSTORMY16_FPTR16)
+    return 1;
 
-    default:
-      break;
-    }
-
-  return S_FORCE_RELOC (fix->fx_addsy);
+  return generic_force_reloc (fix);
 }
 
 /* Return true if a relocation against a symbol may be replaced with
    a relocation against section+offset.  */
 
-boolean
+bfd_boolean
 xstormy16_fix_adjustable (fixP)
    fixS * fixP;
 {
@@ -417,6 +444,12 @@ xstormy16_md_apply_fix3 (fixP, valueP, seg)
   /* Canonical name, since used a lot.  */
   CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
 
+  /* md_cgen_lookup_reloc() will adjust this to compensate for where
+     in the opcode the relocation happens, for pcrel relocations.  We
+     have no other way of keeping track of what this offset needs to
+     be.  */
+  fixP->fx_addnumber = 0;
+
   /* This port has pc-relative relocs and DIFF_EXPR_OK defined, so
      it must deal with turning a BFD_RELOC_{8,16,32,64} into a
      BFD_RELOC_*_PCREL for the case of
@@ -491,7 +524,7 @@ xstormy16_md_apply_fix3 (fixP, valueP, seg)
       /* 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.  */
+        !partial_inplace.  */
 
       reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
       if (reloc_type != BFD_RELOC_NONE)
@@ -550,7 +583,7 @@ xstormy16_md_apply_fix3 (fixP, valueP, seg)
   /* 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;
+  fixP->fx_addnumber += value;
 }
 
 \f
This page took 0.025388 seconds and 4 git commands to generate.