Implement using "base addresses" in insn operands as default.
authorhp <hp@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Feb 2002 05:13:12 +0000 (05:13 +0000)
committerhp <hp@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Feb 2002 05:13:12 +0000 (05:13 +0000)
* config/mmix/mmix.c (mmix_conditional_register_usage): if
-mabi=gnu, modify fixed_regs to fit the GNU ABI.
(mmix_extra_constraint): Use 'R' to indicate that GETA should be
used to read the rtx value.
(mmix_target_asm_function_epilogue): Fix spacing.
(mmix_constant_address_p): Handle TARGET_BASE_ADDRESSES.
(mmix_legitimate_address): Ditto.
(mmix_encode_section_info): Set SYMBOL_REF_FLAG on rtx:es that
should be loaded with a GETA insn.  Don't allocate needless extra
char for nul termination and fix misleading comment.
(mmix_print_operand_address): Handle constants if
TARGET_BASE_ADDRESSES.
(mmix_output_register_setting): Use base addressing if
TARGET_BASE_ADDRESSES and the number of insns is 3.
* config/mmix/t-mmix (MULTILIB_EXTRA_OPTS): New.
* config/mmix/mmix.md ("movdi"): Change the alternative with GETA
to use R as constraint, add LDA to match s.
* config/mmix/mmix.h (TARGET_BASE_ADDRESSES): New.
(TARGET_DEFAULT): Add TARGET_MASK_BASE_ADDRESSES.
(TARGET_SWITCHES): Add -mbase-addresses, -mno-base-addresses.
(FIXED_REGISTERS): Make registers $231..$246 fixed by default.
(MMIX_MMIXWARE_ABI_REG_ALLOC_ORDER): Move $231..$246 last, in
order with other fixed registers.
(MMIX_GNU_ABI_REG_ALLOC_ORDER): Put forward $231, in order with
other parameter/call-clobbered registers.
* doc/invoke.texi (Option Summary) <MMIX Options>: Add
-mbase-addresses, -mno-base-addresses.
(MMIX Options): Ditto.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@49536 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mmix/mmix.c
gcc/config/mmix/mmix.h
gcc/config/mmix/mmix.md
gcc/config/mmix/t-mmix
gcc/doc/invoke.texi

index 3a4eeaf..bdaa34a 100644 (file)
@@ -1,3 +1,35 @@
+2002-02-06  Hans-Peter Nilsson  <hp@bitrange.com>
+
+       Implement using "base addresses" in insn operands as default.
+       * config/mmix/mmix.c (mmix_conditional_register_usage): if
+       -mabi=gnu, modify fixed_regs to fit the GNU ABI.
+       (mmix_extra_constraint): Use 'R' to indicate that GETA should be
+       used to read the rtx value.
+       (mmix_target_asm_function_epilogue): Fix spacing.
+       (mmix_constant_address_p): Handle TARGET_BASE_ADDRESSES.
+       (mmix_legitimate_address): Ditto.
+       (mmix_encode_section_info): Set SYMBOL_REF_FLAG on rtx:es that
+       should be loaded with a GETA insn.  Don't allocate needless extra
+       char for nul termination and fix misleading comment.
+       (mmix_print_operand_address): Handle constants if
+       TARGET_BASE_ADDRESSES.
+       (mmix_output_register_setting): Use base addressing if
+       TARGET_BASE_ADDRESSES and the number of insns is 3.
+       * config/mmix/t-mmix (MULTILIB_EXTRA_OPTS): New.
+       * config/mmix/mmix.md ("movdi"): Change the alternative with GETA
+       to use R as constraint, add LDA to match s.
+       * config/mmix/mmix.h (TARGET_BASE_ADDRESSES): New.
+       (TARGET_DEFAULT): Add TARGET_MASK_BASE_ADDRESSES.
+       (TARGET_SWITCHES): Add -mbase-addresses, -mno-base-addresses.
+       (FIXED_REGISTERS): Make registers $231..$246 fixed by default.
+       (MMIX_MMIXWARE_ABI_REG_ALLOC_ORDER): Move $231..$246 last, in
+       order with other fixed registers.
+       (MMIX_GNU_ABI_REG_ALLOC_ORDER): Put forward $231, in order with
+       other parameter/call-clobbered registers.
+       * doc/invoke.texi (Option Summary) <MMIX Options>: Add
+       -mbase-addresses, -mno-base-addresses.
+       (MMIX Options): Ditto.
+
 2002-02-05  John David Anglin  <dave@hiauly1.hia.nrc.ca>
 
        * pa.h (PREDICATE_CODES): Add reg_before_reload_operand.
index bbe8313..8192d9b 100644 (file)
@@ -228,6 +228,12 @@ mmix_conditional_register_usage ()
         mmixware ABI.  */
       for (i = 15; i <= 30; i++)
        call_used_regs[i] = 0;
+
+      /* "Unfix" the parameter registers.  */
+      for (i = MMIX_RESERVED_GNU_ARG_0_REGNUM;
+          i < MMIX_RESERVED_GNU_ARG_0_REGNUM + MMIX_MAX_ARGS_IN_REGS;
+          i++)
+       fixed_regs[i] = 0;
     }
 
   /* Step over the ":" in special register names.  */
@@ -334,14 +340,34 @@ mmix_extra_constraint (x, c, strict)
       ? strict_memory_address_p (Pmode, x)
       : memory_address_p (Pmode, x);
 
+  /* R asks whether x is to be loaded with GETA or something else.  Right
+     now, only a SYMBOL_REF and LABEL_REF can fit for
+     TARGET_BASE_ADDRESSES.
+
+     Only constant symbolic addresses apply.  With TARGET_BASE_ADDRESSES,
+     we just allow straight LABEL_REF or SYMBOL_REFs with SYMBOL_REF_FLAG
+     set right now; only function addresses and code labels.  If we change
+     to let SYMBOL_REF_FLAG be set on other symbols, we have to check
+     inside CONST expressions.  When TARGET_BASE_ADDRESSES is not in
+     effect, a "raw" constant check together with mmix_constant_address_p
+     is all that's needed; we want all constant addresses to be loaded
+     with GETA then.  */
+  if (c == 'R')
+    return
+      GET_CODE (x) != CONST_INT && GET_CODE (x) != CONST_DOUBLE
+      && mmix_constant_address_p (x)
+      && (! TARGET_BASE_ADDRESSES
+         || (GET_CODE (x) == LABEL_REF
+             || (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (x))));
+
   if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != VOIDmode)
     return 0;
 
   value = mmix_intval (x);
 
   /* We used to map Q->J, R->K, S->L, T->N, U->O, but we don't have to any
-     more ('U' taken for address_operand).  Some letters map outside of
-     CONST_INT, though; we still use 'S' and 'T'.  */
+     more ('U' taken for address_operand, 'R' similarly).  Some letters map
+     outside of CONST_INT, though; we still use 'S' and 'T'.  */
   if (c == 'S')
     return mmix_shiftable_wyde_value (value);
   else if (c == 'T')
@@ -1017,7 +1043,7 @@ mmix_target_asm_function_epilogue (stream, locals_size)
   if (frame_pointer_needed)
     stack_space_to_deallocate += 8;
 
-  /* Make sure we don't get an unaligned stack. */
+  /* Make sure we don't get an unaligned stack.  */
   if ((stack_space_to_deallocate % 8) != 0)
     internal_error ("stack frame not a multiple of octabyte: %d",
                    stack_space_to_deallocate);
@@ -1354,7 +1380,7 @@ mmix_initialize_trampoline (trampaddr, fnaddr, static_chain)
 
 /* We must exclude constant addresses that have an increment that is not a
    multiple of four bytes because of restrictions of the GETA
-   instruction.  FIXME: No, I don't think so.  Just add a constraint.  */
+   instruction, unless TARGET_BASE_ADDRESSES.  */
 
 int
 mmix_constant_address_p (x)
@@ -1362,13 +1388,15 @@ mmix_constant_address_p (x)
 {
   RTX_CODE code = GET_CODE (x);
   int addend = 0;
+  /* When using "base addresses", anything constant goes.  */
+  int constant_ok = TARGET_BASE_ADDRESSES != 0;
 
   if (code == LABEL_REF || code == SYMBOL_REF)
     return 1;
 
   if (code == CONSTANT_P_RTX || code == HIGH)
     /* FIXME: Don't know how to dissect these.  Avoid them for now.  */
-    return 0;
+    return constant_ok;
 
   switch (code)
     {
@@ -1376,12 +1404,11 @@ mmix_constant_address_p (x)
     case SYMBOL_REF:
       return 1;
 
-    case PLUS:
-      /* Can we get a naked PLUS? */
     case CONSTANT_P_RTX:
     case HIGH:
-      /* FIXME: Don't know how to dissect these.  Avoid them for now.  */
-      return 0;
+      /* FIXME: Don't know how to dissect these.  Avoid them for now,
+        except we know they're constants.  */
+      return constant_ok;
 
     case CONST_INT:
       addend = INTVAL (x);
@@ -1390,7 +1417,7 @@ mmix_constant_address_p (x)
     case CONST_DOUBLE:
       if (GET_MODE (x) != VOIDmode)
        /* Strange that we got here.  FIXME: Check if we do.  */
-       return 0;
+       return constant_ok;
       addend = CONST_DOUBLE_LOW (x);
       break;
 
@@ -1410,17 +1437,17 @@ mmix_constant_address_p (x)
                      && GET_MODE (x1) == VOIDmode)))
            addend = mmix_intval (x1);
          else
-           return 0;
+           return constant_ok;
        }
       else
-       return 0;
+       return constant_ok;
       break;
 
     default:
       return 0;
     }
 
-  return (addend & 3) == 0;
+  return constant_ok || (addend & 3) == 0;
 }
 
 /* Return 1 if the address is OK, otherwise 0.
@@ -1445,7 +1472,9 @@ mmix_legitimate_address (mode, x, strict_checking)
   /* We only accept:
      (mem reg)
      (mem (plus reg reg))
-     (mem (plus reg 0..255)).  */
+     (mem (plus reg 0..255)).
+     unless TARGET_BASE_ADDRESSES, in which case we accept all
+     (mem constant_address) too.  */
 
 
     /* (mem reg) */
@@ -1465,21 +1494,23 @@ mmix_legitimate_address (mode, x, strict_checking)
          x2 = tem;
        }
 
-      /* (mem (plus (reg) (?))) */
+      /* (mem (plus (reg?) (?))) */
       if (!REG_P (x1) || !MMIX_REG_OK (x1))
-       return 0;
+       return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x);
 
-      /* (mem (plus (reg) (reg))) */
+      /* (mem (plus (reg) (reg?))) */
       if (REG_P (x2) && MMIX_REG_OK (x2))
        return 1;
 
-      /* (mem (plus (reg) (0..255))) */
+      /* (mem (plus (reg) (0..255?))) */
       if (GET_CODE (x2) == CONST_INT
          && CONST_OK_FOR_LETTER_P (INTVAL (x2), 'I'))
        return 1;
+
+      return 0;
     }
 
-  return 0;
+  return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x);
 }
 
 /* LEGITIMATE_CONSTANT_P.  */
@@ -1676,34 +1707,41 @@ mmix_encode_section_info (decl)
     {
       /* For non-visible declarations, add a "@" prefix, which we skip
         when the label is output.  If the label does not have this
-        prefix, a ":" is output.
+        prefix, a ":" is output if -mtoplevel-symbols.
 
         Note that this does not work for data that is declared extern and
         later defined as static.  If there's code in between, that code
-        will refer to the extern declaration.  And vice versa.  Until we
-        can get rid of mmixal, we have to assume that code is
-        well-behaved.  */
+        will refer to the extern declaration, and vice versa.  This just
+        means that when -mtoplevel-symbols is in use, we can just handle
+        well-behaved ISO-compliant code.  */
 
       const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
       int len = strlen (str);
       char *newstr;
 
-      /* Doing as rs6000 seems safe; always use ggc.  Except don't copy
-        the suspected off-by-one bug.
-        FIXME: Is it still there? yes 2001-08-23
-        Why is the return type of ggc_alloc_string const?  */
-      newstr = (char *) ggc_alloc_string ("", len + 2);
+      /* Why is the return type of ggc_alloc_string const?  */
+      newstr = (char *) ggc_alloc_string ("", len + 1);
 
       strcpy (newstr + 1, str);
       *newstr = '@';
       XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
     }
 
-  /* FIXME: Later on, add SYMBOL_REF_FLAG for things that we can reach
-     from here via GETA, to check in LEGITIMATE_CONSTANT_P.  Needs to have
-     different options for the cases where we want *all* to be assumed
-     reachable via GETA, or all constant symbols, or just text symbols in
-     this file, or perhaps just the constant pool.  */
+  /* Set SYMBOL_REF_FLAG for things that we want to access with GETA.  We
+     may need different options to reach for different things with GETA.
+     For now, functions and things we know or have been told are constant.  */
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      || TREE_CONSTANT (decl)
+      || (TREE_CODE (decl) == VAR_DECL
+         && TREE_READONLY (decl)
+         && !TREE_SIDE_EFFECTS (decl)
+         && (!DECL_INITIAL (decl)
+             || TREE_CONSTANT (DECL_INITIAL (decl)))))
+    {
+      rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
+                 ? TREE_CST_RTL (decl) : DECL_RTL (decl));
+      SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
+    }
 }
 
 /* STRIP_NAME_ENCODING.  */
@@ -2351,6 +2389,12 @@ mmix_print_operand_address (stream, x)
        }
     }
 
+  if (TARGET_BASE_ADDRESSES && mmix_legitimate_constant_p (x))
+    {
+      output_addr_const (stream, x);
+      return;
+    }
+
   fatal_insn ("MMIX Internal: This is not a recognized address", x);
 }
 
@@ -2514,25 +2558,52 @@ mmix_output_register_setting (stream, regno, value, do_begin_end)
       static const char *const higher_parts[] = {"L", "ML", "MH", "H"};
       const char *op = "SET";
       const char *line_begin = "";
+      int insns = 0;
       int i;
+      HOST_WIDEST_INT tmpvalue = value;
 
-      /* Output pertinent parts of the 4-wyde sequence.
-        Still more to do if we want this to be optimal, but hey...
-        Note that the zero case has been handled above.  */
-      for (i = 0; i < 4 && value != 0; i++)
+      /* Compute the number of insns needed to output this constant.  */
+      for (i = 0; i < 4 && tmpvalue != 0; i++)
+       {
+         if (tmpvalue & 65535)
+           insns++;
+         tmpvalue >>= 16;
+       }
+      if (TARGET_BASE_ADDRESSES && insns == 3)
+       {
+         /* The number three is based on a static observation on
+            ghostscript-6.52.  Two and four are excluded because there
+            are too many such constants, and each unique constant (maybe
+            offset by 1..255) were used few times compared to other uses,
+            e.g. addresses.
+
+            We use base-plus-offset addressing to force it into a global
+            register; we just use a "LDA reg,VALUE", which will cause the
+            assembler and linker to DTRT (for constants as well as
+            addresses).  */
+         fprintf (stream, "LDA %s,", reg_names[regno]);
+         mmix_output_octa (stream, value, 0);
+       }
+      else
        {
-         if (value & 65535)
+         /* Output pertinent parts of the 4-wyde sequence.
+            Still more to do if we want this to be optimal, but hey...
+            Note that the zero case has been handled above.  */
+         for (i = 0; i < 4 && value != 0; i++)
            {
-             fprintf (stream, "%s%s%s %s,#%x", line_begin, op,
-                      higher_parts[i], reg_names[regno],
-                      (int) (value & 65535));
-             /* The first one sets the rest of the bits to 0, the next
-                ones add set bits.  */
-             op = "INC";
-             line_begin = "\n\t";
-           }
+             if (value & 65535)
+               {
+                 fprintf (stream, "%s%s%s %s,#%x", line_begin, op,
+                          higher_parts[i], reg_names[regno],
+                          (int) (value & 65535));
+                 /* The first one sets the rest of the bits to 0, the next
+                    ones add set bits.  */
+                 op = "INC";
+                 line_begin = "\n\t";
+               }
 
-         value >>= 16;
+             value >>= 16;
+           }
        }
     }
 
index 9c1e2f1..74229ac 100644 (file)
@@ -157,6 +157,16 @@ extern int target_flags;
 #define TARGET_MASK_TOPLEVEL_SYMBOLS 32
 #define TARGET_MASK_BRANCH_PREDICT 64
 
+/* We use the term "base address" since that's what Knuth uses.  The base
+   address goes in a global register.  When addressing, it's more like
+   "base address plus offset", with the offset being 0..255 from the base,
+   which itself can be a symbol plus an offset.  The effect is like having
+   a constant pool in global registers, code offseting from those
+   registers (automatically causing a request for a suitable constant base
+   address register) without having to know the specific register or the
+   specific offset.  */
+#define TARGET_MASK_BASE_ADDRESSES 128
+
 /* FIXME: Get rid of this one.  */
 #define TARGET_LIBFUNC (target_flags & TARGET_MASK_LIBFUNCS)
 #define TARGET_ABI_GNU (target_flags & TARGET_MASK_ABI_GNU)
@@ -165,9 +175,10 @@ extern int target_flags;
 #define TARGET_KNUTH_DIVISION (target_flags & TARGET_MASK_KNUTH_DIVISION)
 #define TARGET_TOPLEVEL_SYMBOLS (target_flags & TARGET_MASK_TOPLEVEL_SYMBOLS)
 #define TARGET_BRANCH_PREDICT (target_flags & TARGET_MASK_BRANCH_PREDICT)
+#define TARGET_BASE_ADDRESSES (target_flags & TARGET_MASK_BASE_ADDRESSES)
 
 #define TARGET_DEFAULT \
- (TARGET_MASK_BRANCH_PREDICT)
+ (TARGET_MASK_BRANCH_PREDICT | TARGET_MASK_BASE_ADDRESSES)
 
 /* FIXME: Provide a way to *load* the epsilon register.  */
 #define TARGET_SWITCHES                                                        \
@@ -198,6 +209,10 @@ extern int target_flags;
    N_("Use P-mnemonics for branches statically predicted as taken")},  \
   {"no-branch-predict",        -TARGET_MASK_BRANCH_PREDICT,                    \
    N_("Don't use P-mnemonics for branches")},                          \
+  {"base-addresses",   TARGET_MASK_BASE_ADDRESSES,                     \
+   N_("Use addresses that allocate global registers")},                        \
+  {"no-base-addresses",        -TARGET_MASK_BASE_ADDRESSES,                    \
+   N_("Do not use addresses that allocate global registers")},         \
   {"",                 TARGET_DEFAULT, ""}}
 
 /* Unfortunately, this must not reference anything in "mmix.c".  */
@@ -366,8 +381,8 @@ extern int target_flags;
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
-   1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, \
+   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+   1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, \
    1, 1, 0, 0, 0, 1 \
  }
 
@@ -419,8 +434,6 @@ extern int target_flags;
    24, 25, 26, 27, 28, 29, 30, 31,             \
                                                \
    252, 251, 250, 249, 248, 247,               \
-   246, 245, 244, 243, 242, 241, 240, 239,     \
-   238, 237, 236, 235, 234, 233, 232, 231,     \
                                                \
    253,                                                \
                                                \
@@ -451,6 +464,9 @@ extern int target_flags;
    208, 209, 210, 211, 212, 213, 214, 215,     \
    216, 217, 218, 219, 220, 221, 222, 223,     \
    224, 225, 226, 227, 228, 229, 230, 231,     \
+   232, 233, 234, 235, 236, 237, 238, 239,     \
+   240, 241, 242, 243, 244, 245, 246,          \
+                                               \
    254, 255, 256, 257, 261                     \
  }
 
@@ -469,7 +485,7 @@ extern int target_flags;
 #define MMIX_GNU_ABI_REG_ALLOC_ORDER           \
 {  252, 251, 250, 249, 248, 247, 246,          \
    245, 244, 243, 242, 241, 240, 239, 238,     \
-   237, 236, 235, 234, 233, 232,               \
+   237, 236, 235, 234, 233, 232, 231,          \
                                                \
    0, 1, 2, 3, 4, 5, 6, 7,                     \
    8, 9, 10, 11, 12, 13, 14, 15,               \
@@ -504,7 +520,8 @@ extern int target_flags;
    200, 201, 202, 203, 204, 205, 206, 207,     \
    208, 209, 210, 211, 212, 213, 214, 215,     \
    216, 217, 218, 219, 220, 221, 222, 223,     \
-   224, 225, 226, 227, 228, 229, 230, 231,     \
+   224, 225, 226, 227, 228, 229, 230,          \
+                                               \
    254, 255, 256, 257, 261                     \
  }
 
index c8e0167..da555ff 100644 (file)
@@ -88,8 +88,8 @@
 
 ;; We assume all "s" are addresses.  Does that hold?
 (define_insn "movdi"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r ,r,x,r,m,r,m,r,??r")
-       (match_operand:DI 1 "general_operand"       "r,LS,K,r,x,I,m,r,s,n"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r ,r,x,r,m,r,m,r,r,??r")
+       (match_operand:DI 1 "general_operand"       "r,LS,K,r,x,I,m,r,R,s,n"))]
   ""
   "@
    SET %0,%1
    LDO %0,%1
    STOU %1,%0
    GETA %0,%1
+   LDA %0,%1
    %r0%I1")
 
 ;; Note that we move around the float as a collection of bits; no
index fbe1a10..fcfe7c7 100644 (file)
@@ -13,6 +13,9 @@ EXTRA_MULTILIB_PARTS = crti.o crtn.o crtbegin.o crtend.o
 MULTILIB_OPTIONS = mabi=gnu
 MULTILIB_DIRNAMES = gnuabi
 
+# Don't use global registers in libraries.
+MULTILIB_EXTRA_OPTS = mno-base-addresses
+
 $(T)crti.o: $(srcdir)/config/mmix/crti.asm $(GCC_PASSES)
        $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
        -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/mmix/crti.asm
index 51db49a..c5f88be 100644 (file)
@@ -593,7 +593,8 @@ in the following sections.
 @gccoptlist{
 -mlibfuncs -mno-libfuncs -mepsilon -mno-epsilon -mabi=gnu @gol
 -mabi=mmixware -mzero-extend -mknuthdiv -mtoplevel-symbols @gol
--melf -mbranch-predict -mno-branch-predict}
+-melf -mbranch-predict -mno-branch-predict -mbase-addresses @gol
+-mno-base-addresses}
 
 @emph{IA-64 Options}
 @gccoptlist{
@@ -9513,6 +9514,19 @@ Generate an executable in the ELF format, rather than the default
 @opindex mno-branch-predict
 Use (do not use) the probable-branch instructions, when static branch
 prediction indicates a probable branch.
+
+@item -mbase-addresses
+@itemx -mno-base-addresses
+@opindex mbase-addresses
+@opindex mno-base-addresses
+Generate (do not generate) code that uses @emph{base addresses}.  Using a
+base address automatically generates a request (handled by the assembler
+and the linker) for a constant to be set up in a global register.  The
+register is used for one or more base address requests within the range 0
+to 255 from the value held in the register.  The generally leads to short
+and fast code, but the number of different data items that can be
+addressed is limited.  This means that a program that uses lots of static
+data may require @option{-mno-base-addresses}.
 @end table
 
 @node PDP-11 Options