PR 9814
authorNick Clifton <nickc@redhat.com>
Fri, 6 Feb 2009 12:51:52 +0000 (12:51 +0000)
committerNick Clifton <nickc@redhat.com>
Fri, 6 Feb 2009 12:51:52 +0000 (12:51 +0000)
        * config/tc-arm.c (MODE_RECORDED): New define.
        (output_inst): Record the thumb_mode in the current frag.
        (arm_handle_align): Ignore the MODE_RECORDED bit in tc_frag_data.
        (arm_init_frag): Only set the tc_frag_data field if it has not
        already been set.

gas/ChangeLog
gas/config/tc-arm.c

index da6cc39..94c615b 100644 (file)
@@ -1,3 +1,12 @@
+2009-02-06  Nick Clifton  <nickc@redhat.com>
+
+       PR 9814
+       * config/tc-arm.c (MODE_RECORDED): New define.
+       (output_inst): Record the thumb_mode in the current frag.
+       (arm_handle_align): Ignore the MODE_RECORDED bit in tc_frag_data.
+       (arm_init_frag): Only set the tc_frag_data field if it has not
+       already been set.
+
 2009-02-04  H.J. Lu  <hongjiu.lu@intel.com>
 
        AVX Programming Reference (January, 2009)
index 3b13c49..782d10b 100644 (file)
@@ -260,6 +260,10 @@ symbolS * GOT_symbol;
    2: assemble for Thumb even though target CPU does not support thumb
       instructions.  */
 static int thumb_mode = 0;
+/* A value distinct from the possible values for thumb_mode that we
+   can use to record whether thumb_mode has been copied into the
+   tc_frag_data field of a frag.  */
+#define MODE_RECORDED (1 << 4)
 
 /* If unified_syntax is true, we are processing the new unified
    ARM/Thumb syntax.  Important differences from the old ARM mode:
@@ -14387,6 +14391,11 @@ output_inst (const char * str)
     return;
 
   to = frag_more (inst.size);
+  /* PR 9814: Record the thumb mode into the current frag so that we know
+     what type of NOP padding to use, if necessary.  We override any previous
+     setting so that if the mode has changed then the NOPS that we use will
+     match the encoding of the last instruction in the frag.  */
+  frag_now->tc_frag_data = thumb_mode | MODE_RECORDED;
 
   if (thumb_mode && (inst.size > THUMB_SIZE))
     {
@@ -17569,7 +17578,9 @@ arm_handle_align (fragS * fragP)
   if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
     bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
 
-  if (fragP->tc_frag_data)
+  assert ((fragP->tc_frag_data & MODE_RECORDED) != 0);
+
+  if (fragP->tc_frag_data & (~ MODE_RECORDED))
     {
       if (target_big_endian)
        noop = thumb_bigend_noop;
@@ -17629,13 +17640,19 @@ arm_frag_align_code (int n, int max)
   *p = 0;
 }
 
-/* Perform target specific initialisation of a frag.  */
+/* Perform target specific initialisation of a frag.
+   Note - despite the name this initialisation is not done when the frag
+   is created, but only when its type is assigned.  A frag can be created
+   and used a long time before its type is set, so beware of assuming that
+   this initialisationis performed first.  */
 
 void
 arm_init_frag (fragS * fragP)
 {
-  /* Record whether this frag is in an ARM or a THUMB area.  */
-  fragP->tc_frag_data = thumb_mode;
+  /* If the current ARM vs THUMB mode has not already
+     been recorded into this frag then do so now.  */
+  if ((fragP->tc_frag_data & MODE_RECORDED) == 0)
+    fragP->tc_frag_data = thumb_mode | MODE_RECORDED;
 }
 
 #ifdef OBJ_ELF