* config/tc-v850,h (TC_FIX_TYPE): Define. (TC_INIT_FIX_TYPE): Define.
authorNick Clifton <nickc@redhat.com>
Tue, 17 May 2005 11:56:13 +0000 (11:56 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 17 May 2005 11:56:13 +0000 (11:56 +0000)
* config/tc-v850.c (md_assemble): When creating a fix record the operand in the
    tc_fix_data field.
    (md_apply_fix3): When applying a resolved fix use the operand's insertion
    procedure to store the value, if the operand has been recorded.
* gas/v850/split-lo16.s: Add test for a lo() pseudo reloc corrupting an ld.w
    instruction.
* gas/v850/split-lo16.d: Add expected, correct (ie not corrupt) output.

gas/ChangeLog
gas/config/tc-v850.c
gas/config/tc-v850.h
gas/symbols.c
gas/testsuite/ChangeLog
gas/testsuite/gas/v850/split-lo16.d
gas/testsuite/gas/v850/split-lo16.s

index 67a4a1e796cfcb9567fe5dab3fce09b904264240..df1def0aa91ba545b3b44609aaa556468733e630 100644 (file)
@@ -1,3 +1,13 @@
+2005-05-17  Nick Clifton  <nickc@redhat.com>
+
+       * config/tc-v850,h (TC_FIX_TYPE): Define.
+       (TC_INIT_FIX_TYPE): Define.
+       * config/tc-v850.c (md_assemble): When creating a fix record the
+       operand in the tc_fix_data field.
+       (md_apply_fix3): When applying a resolved fix use the operand's
+       insertion procedure to store the value, if the operand has been
+       recorded.
+
 2005-05-15  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * Makefile.am (m68k-parse.c, itbl-parse.c): Update ylwrap
index 33eef58399a8b8396863a1800d4dd9a0281898af..1828396c0d5fe17c5ccd94f46453c6f2b5ecb514 100644 (file)
@@ -2125,6 +2125,8 @@ md_assemble (char *str)
                              reloc_howto->pc_relative,
                              reloc);
 
+         fixP->tc_fix_data = (void *) operand;
+
          switch (reloc)
            {
            case BFD_RELOC_LO16:
@@ -2319,16 +2321,42 @@ md_apply_fix3 (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
       /* We still have to insert the value into memory!  */
       where = fixP->fx_frag->fr_literal + fixP->fx_where;
 
-      if (fixP->fx_r_type == BFD_RELOC_V850_LO16_SPLIT_OFFSET)
-       bfd_putl32 (((value << 16) & 0xfffe0000)
-                   | ((value << 5) & 0x20)
-                   | (bfd_getl32 (where) & ~0xfffe0020), where);
-      else if (fixP->fx_size == 1)
-       *where = value & 0xff;
-      else if (fixP->fx_size == 2)
-       bfd_putl16 (value & 0xffff, (unsigned char *) where);
-      else if (fixP->fx_size == 4)
-       bfd_putl32 (value, (unsigned char *) where);
+      if (fixP->tc_fix_data != NULL)
+       {
+         struct v850_operand * operand = (struct v850_operand *) fixP->tc_fix_data;
+         unsigned long insn;
+
+         /* The variable "where" currently points at the exact point inside
+            the insn where we need to insert the value.  But we need to
+            extract the entire insn so we probably need to move "where"
+            back a few bytes.  */
+         if (fixP->fx_size == 2)
+           where -= 2;
+         else if (fixP->fx_size == 1)
+           where -= 3;
+
+         insn = bfd_getl32 ((unsigned char *) where);
+
+         /* Use the operand's insertion procedure, if present, in order to
+            make sure that the value is correctly stored in the insn.  */
+         insn = v850_insert_operand (insn, operand, (offsetT) value,
+                                     fixP->fx_file, fixP->fx_line, NULL);
+
+         bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
+       }
+      else
+       {
+         if (fixP->fx_r_type == BFD_RELOC_V850_LO16_SPLIT_OFFSET)
+           bfd_putl32 (((value << 16) & 0xfffe0000)
+                       | ((value << 5) & 0x20)
+                       | (bfd_getl32 (where) & ~0xfffe0020), where);
+         else if (fixP->fx_size == 1)
+           *where = value & 0xff;
+         else if (fixP->fx_size == 2)
+           bfd_putl16 (value & 0xffff, (unsigned char *) where);
+         else if (fixP->fx_size == 4)
+           bfd_putl32 (value, (unsigned char *) where);
+       }
     }
 }
 \f
index 5db11414277d4cd9805e844fb2a36d853e4d1d50..4dd3c7e26360a575eb5c2fa6a1e4e0c0c3b45106 100644 (file)
@@ -78,3 +78,8 @@ extern void v850_handle_align (fragS *);
 extern long v850_pcrel_from_section (struct fix *, asection *);
 
 #define DWARF2_LINE_MIN_INSN_LENGTH 2
+
+/* We need to record the operand involved when a pseudo-reloc is
+   processed so that the resulting value can be inserted correctly.  */
+#define TC_FIX_TYPE             void *
+#define TC_INIT_FIX_DATA(fixP)  (fixP)->tc_fix_data = NULL
index 5341c6a2efe53fa8324dc692f0f7f1dc8c09a72d..ebcad5bf21b564a4d837879f555c45813fa3a392 100644 (file)
@@ -906,6 +906,7 @@ resolve_symbol_value (symbolS *symp)
       offsetT left, right;
       segT seg_left, seg_right;
       operatorT op;
+      int move_seg_ok;
 
       symp->sy_resolving = 1;
 
@@ -1091,18 +1092,15 @@ resolve_symbol_value (symbolS *symp)
                }
            }
 
+         move_seg_ok = 1;
          /* Equality and non-equality tests are permitted on anything.
             Subtraction, and other comparison operators are permitted if
             both operands are in the same section.  Otherwise, both
             operands must be absolute.  We already handled the case of
             addition or subtraction of a constant above.  This will
             probably need to be changed for an object file format which
-            supports arbitrary expressions, such as IEEE-695.
-
-            Don't emit messages unless we're finalizing the symbol value,
-            otherwise we may get the same message multiple times.  */
-         if (finalize_syms
-             && !(seg_left == absolute_section
+            supports arbitrary expressions, such as IEEE-695.  */
+         if (!(seg_left == absolute_section
                   && seg_right == absolute_section)
              && !(op == O_eq || op == O_ne)
              && !((op == O_subtract
@@ -1110,9 +1108,21 @@ resolve_symbol_value (symbolS *symp)
                   && seg_left == seg_right
                   && (seg_left != undefined_section
                       || add_symbol == op_symbol)))
-           report_op_error (symp, add_symbol, op_symbol);
+           {
+             /* Don't emit messages unless we're finalizing the symbol value,
+                otherwise we may get the same message multiple times.  */
+             if (finalize_syms)
+               report_op_error (symp, add_symbol, op_symbol);
+             /* However do not move the symbol into the absolute section
+                if it cannot currently be resolved - this would confuse
+                other parts of the assembler into believing that the
+                expression had been evaluated to zero.  */
+             else
+               move_seg_ok = 0;
+           }
 
-         if (final_seg == expr_section || final_seg == undefined_section)
+         if (move_seg_ok
+             && (final_seg == expr_section || final_seg == undefined_section))
            final_seg = absolute_section;
 
          /* Check for division by zero.  */
index d2210458f0ef8c7ea702283902c0bec3cdca9d17..4322c2698e1990fcee470703fd42d799f0218647 100644 (file)
@@ -1,3 +1,10 @@
+2005-05-17  Nick Clifton  <nickc@redhat.com>
+
+       * gas/v850/split-lo16.s: Add test for a lo() pseudo reloc
+       corrupting an ld.w instruction.
+       * gas/v850/split-lo16.d: Add expected, correct (ie not corrupt)
+       output.
+
 2005-05-10  Michael Matz  <matz@suse.de>
 
        * gas/hppa/parse/block1.s: Use official limit (0x3fffffff) for
index 9503ac9d8d0879138a8008dea199ab3f9142cbab..5ed195cb087ed94b2a9b34544d122630e45d562c 100644 (file)
@@ -13,4 +13,6 @@
                        c: R_V850_LO16_SPLIT_OFFSET     foo
   10:  a1 17 45 23     ld\.bu  9029\[r1\],r2
   14:  81 17 57 34     ld\.bu  13398\[r1\],r2
+  18:  20 57 01 00     ld.w    0\[r0\],r10
+  1c:  20 57 79 56     ld.w    22136\[r0\],r10
 #pass
index fc3afd14e6ebe93747124dd6efd9cc76ad009e46..bb6fb666c07d68d7bd6c2d8aeabbc0aa1431569a 100644 (file)
@@ -5,3 +5,6 @@
 
        ld.bu   lo(0x12345),r1,r2
        ld.bu   lo(0x123456),r1,r2
+
+       ld.w lo(0)[r0], r10
+       ld.w lo(0x12345678)[r0], r10