2005-08-12 Dmitry Diky <diwil@spec.ru>
authorDmitry Diky <diwil@spec.ru>
Fri, 12 Aug 2005 11:54:23 +0000 (11:54 +0000)
committerDmitry Diky <diwil@spec.ru>
Fri, 12 Aug 2005 11:54:23 +0000 (11:54 +0000)
* config/tc-msp430.c (msp430_enable_relax): New flag.
(msp430_enable_polys): Likewise.
(OPTION_RELAX): New option.
(OPTION_POLYMORPHS): Likewise.
(md_longopts): New long options.
(md_show_usage): Updated.
(md_parse_option): Add new options handler.
(msp430_operands): Add check if polymorph insns are enabled.
(msp430_force_relocation_local): New function.
(md_apply_fix): Now delete relocs according to new flags combination.
(msp430_relax_frag): Convert long branches to short branches only if
flag msp430_enable_relax is set.
* config/tc-msp430.h (TC_FORCE_RELOCATION_LOCAL): Defined.
(msp430_force_relocation_local): Likewise.
* doc/c-msp430.texi: Describe new options.

gas/ChangeLog
gas/config/tc-msp430.c
gas/config/tc-msp430.h
gas/doc/c-msp430.texi

index 1f5d8a0e3f9412c59d5538464726cfbe92c6757f..bc98f76da43edf9a6d031b78738e499306068aa3 100644 (file)
@@ -1,3 +1,20 @@
+2005-08-12  Dmitry Diky <diwil@spec.ru>
+       * config/tc-msp430.c (msp430_enable_relax): New flag.
+       (msp430_enable_polys): Likewise.
+       (OPTION_RELAX): New option.
+       (OPTION_POLYMORPHS): Likewise.
+       (md_longopts): New long options.
+       (md_show_usage): Updated.
+       (md_parse_option): Add new options handler.
+       (msp430_operands): Add check if polymorph insns are enabled.
+       (msp430_force_relocation_local): New function.
+       (md_apply_fix): Now delete relocs according to new flags combination.
+       (msp430_relax_frag): Convert long branches to short branches only if
+       flag msp430_enable_relax is set.
+       * config/tc-msp430.h (TC_FORCE_RELOCATION_LOCAL): Defined.
+       (msp430_force_relocation_local): Likewise.
+       * doc/c-msp430.texi: Describe new options.
+       
 2005-08-11  Ian Lance Taylor  <ian@airs.com>
 
        * Makefile.am ($(srcdir)/make-gas.com): Remove target.
index 5b6e196eb35a62d63156d70ef178e24ceed4ee46..ed00c6978fbd2bc4d6e7396ba70e7f4c37b02d11 100644 (file)
 #include "opcode/msp430.h"
 #include "safe-ctype.h"
 
+/*
+   We will disable polymorphs by default because it is dangerous.
+   The potencial problem here is the following: assume we got the
+   following code:
+
+       jump .l1
+       nop
+       jump  subroutine        ; external symbol
+      .l1:
+       nop
+       ret
+   
+   In case of assembly time relaxation we'll get:
+       0: jmp .l1 <.text +0x08> (reloc deleted)
+       2: nop
+       4: br subroutine
+    .l1:
+       8: nop
+       10: ret
+
+   If the 'subroutine' wiys thin +-1024 bytes range then linker
+   will produce
+       0: jmp .text +0x08
+       2: nop
+       4: jmp subroutine
+       .l1:
+       6: nop
+       8: ret  ; 'jmp .text +0x08' will land here. WRONG!!!
+
+
+   The workaround is the following:
+   1. Declare global var enable_polymorphs which set to 1 via option -mP.
+   2. Declare global var enable_relax  which set to 1 via option -mQ.
+
+   If polymorphs are enabled, and relax isn't, treat all jumps as long jumps,
+   do not delete any relocs and leave them for linker.
+   
+   If relax is enabled, relax at assembly time and kill relocs as necessary.
+ */
+
+int msp430_enable_relax;
+int msp430_enable_polys;
+
 /* GCC uses the some condition codes which we'll
    implement as new polymorph instructions.
   
@@ -660,6 +703,8 @@ extract_word (char * from, char * to, int limit)
 }
 
 #define OPTION_MMCU 'm'
+#define OPTION_RELAX 'Q'
+#define OPTION_POLYMORPHS 'P'
 
 static void
 msp430_set_arch (int dummy ATTRIBUTE_UNUSED)
@@ -709,6 +754,17 @@ md_parse_option (int c, char * arg)
        as_fatal (_("redefinition of mcu type %s' to %s'"),
                  msp430_mcu->name, mcu_types[i].name);
       return 1;
+      break;
+      
+    case OPTION_RELAX:
+      msp430_enable_relax = 1; 
+      return 1;
+      break;
+      
+    case OPTION_POLYMORPHS:
+      msp430_enable_polys = 1;
+      return 1;
+      break;
     }
 
   return 0;
@@ -727,6 +783,8 @@ const char *md_shortopts = "m:";
 struct option md_longopts[] =
 {
   {"mmcu", required_argument, NULL, OPTION_MMCU},
+  {"mP", no_argument, NULL, OPTION_POLYMORPHS},
+  {"mQ", no_argument, NULL, OPTION_RELAX},
   {NULL, no_argument, NULL, 0}
 };
 
@@ -758,6 +816,9 @@ md_show_usage (FILE * stream)
             "                  msp430xG437 msp430xG438 msp430G439\n"
             "                  msp430x435  msp430x436  msp430x437\n"
             "                  msp430x447  msp430x448  msp430x449\n"));
+  fprintf (stream,
+          _("  -mQ - enable relaxation at assembly time. DANGEROUS!\n"
+            "  -mP - enable polymorph instructions\n"));
 
   show_mcu_list (stream);
 }
@@ -1683,6 +1744,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
       break;
 
     case 4:    /* Extended jumps.  */
+      if (!msp430_enable_polys)
+       {
+         as_bad(_("polymorphs are not enabled. Use -mP option to enable."));
+         break;
+       }
+       
       line = extract_operand (line, l1, sizeof (l1));
       if (l1[0])
        {
@@ -1714,6 +1781,11 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
       break;
 
     case 5:    /* Emulated extended branches.  */
+      if (!msp430_enable_polys)
+       {
+         as_bad(_("polymorphs are not enabled. Use -mP option to enable."));
+         break;
+       }
       line = extract_operand (line, l1, sizeof (l1));
       if (l1[0])
        {
@@ -1820,9 +1892,24 @@ md_pcrel_from_section (fixS * fixp, segT sec)
   return fixp->fx_frag->fr_address + fixp->fx_where;
 }
 
+/* Replaces standard TC_FORCE_RELOCATION_LOCAL.
+   Now it handles the situation when relocations
+   have to be passed to linker. */
+int
+msp430_force_relocation_local(fixS *fixp)
+{
+  if (msp430_enable_polys
+        && !msp430_enable_relax)
+    return 1;
+  else
+    return (!fixp->fx_pcrel
+           || fixp->fx_plt
+           || generic_force_reloc(fixp));
+}
+
+
 /* GAS will call this for each fixup.  It should store the correct
    value in the object file.  */
-
 void
 md_apply_fix (fixS * fixp, valueT * valuep, segT seg)
 {
@@ -1879,13 +1966,18 @@ md_apply_fix (fixS * fixp, valueT * valuep, segT seg)
        }
     }
 
-  switch (fixp->fx_r_type)
+  fixp->fx_no_overflow = 1;
+
+  /* if polymorphs are enabled and relax disabled. 
+     do not kill any relocs and pass them to linker. */
+  if (msp430_enable_polys 
+      && !msp430_enable_relax)
     {
-    default:
-      fixp->fx_no_overflow = 1;
-      break;
-    case BFD_RELOC_MSP430_10_PCREL:
-      break;
+      if (!fixp->fx_addsy || (fixp->fx_addsy 
+         && S_GET_SEGMENT (fixp->fx_addsy) == absolute_section))
+       fixp->fx_done = 1;      /* it is ok to kill 'abs' reloc */
+      else
+       fixp->fx_done = 0;
     }
 
   if (fixp->fx_done)
@@ -2185,6 +2277,13 @@ msp430_relax_frag (segT seg ATTRIBUTE_UNUSED, fragS * fragP,
       aim = S_GET_VALUE (symbolP) - fragP->fr_address - fragP->fr_fix;
     }
 
+  if (!msp430_enable_relax)
+    {
+      /* Relaxation is not enabled. So, make all jump as long ones
+         by setting 'aim' to quite high value. */
+      aim = 0x7fff;
+    }
+  
   this_state = fragP->fr_subtype;
   start_type = this_type = table + this_state;
 
index 632e2a923b5c6aec88aee9267577ff62b8ab0282..9fef126e5515ff36fe2da33f5c1c7e18244857db 100644 (file)
@@ -112,3 +112,11 @@ extern long md_pcrel_from_section (struct fix *, segT);
 #define md_relax_frag(SEG, FRAGP, STRETCH)             \
    msp430_relax_frag (SEG, FRAGP, STRETCH)
 extern long msp430_relax_frag (segT, fragS *, long);
+
+#define TC_FORCE_RELOCATION_LOCAL(FIX) \
+   msp430_force_relocation_local(FIX)
+extern int msp430_force_relocation_local(struct fix *);
+
+
+extern int msp430_enable_relax;
+extern int msp430_enable_polys;
index b398952280919560c2cff18bbe589e4130b30d29..33f3e83ffbc106ef0fea803e0a14ce28e88578c5 100644 (file)
 @section Options
 @cindex MSP 430 options (none)
 @cindex options for MSP430 (none)
-@code{@value{AS}} has only -m flag which selects the mpu arch. Currently has 
-no effect.
+@table @code
+
+@item -m
+select the mpu arch. Currently has no effect.
+@item -mP 
+enables polymorph instructions handler.
+
+@item -mQ 
+enables relaxation at assembly time. DANGEROUS!
+
+@end table
 
 @node MSP430 Syntax
 @section Syntax
@@ -214,7 +223,7 @@ This directive instructs assembler to add new profile entry to the object file.
 additional pseudo-instructions are needed on this family.
 
 For information on the 430 machine instruction set, see @cite{MSP430
-User's Manual, document slau049b}, Texas Instrument, Inc.
+User's Manual, document slau049d}, Texas Instrument, Inc.
 
 @node MSP430 Profiling Capability
 @section Profiling Capability