OSDN Git Service

* config/m32c/m32c-protos.h (m32c_note_pragma_address): Declare.
authordj <dj@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 26 Jun 2010 03:30:19 +0000 (03:30 +0000)
committerdj <dj@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 26 Jun 2010 03:30:19 +0000 (03:30 +0000)
(m32c_output_aligned_common): Likewise.
* config/m32c/m32c.h (ASM_OUTPUT_ALIGNED_DECL_COMMON): New.
(ASM_OUTPUT_ALIGNED_DECL_LOCAL): New.
* config/m32c/m32c-pragma.c (m32c_pragma_address): New.
(m32c_register_pragmas): Register it.
* config/m32c/m32c.c (m32c_get_pragma_address): New.
(m32c_insert_attributes): Set #pragma address decls volatile.
(pragma_entry_eq): New.
(pragma_entry_hash): New.
(m32c_note_pragma_address): New.
(m32c_get_pragma_address): New.
(m32c_output_aligned_common): New.
* doc/extend.texi: Document the new pragma.

* config/m32c/m32c.c (m32c_illegal_subreg_p): Reject illegal MEMs
also.
* config/m32c/predicates.md (m32c_any_operand): Check the code
instead of memory_operand so as to allow matching volatile MEMs.
(m32c_nonimmediate_operand): Likewise.
(mra_operand): Allow volatiles.

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

gcc/ChangeLog
gcc/config/m32c/m32c-pragma.c
gcc/config/m32c/m32c-protos.h
gcc/config/m32c/m32c.c
gcc/config/m32c/m32c.h
gcc/config/m32c/predicates.md
gcc/doc/extend.texi

index 5b08e5d..797f74d 100644 (file)
@@ -1,3 +1,27 @@
+2010-06-25  DJ Delorie  <dj@redhat.com>
+
+       * config/m32c/m32c-protos.h (m32c_note_pragma_address): Declare.
+       (m32c_output_aligned_common): Likewise.
+       * config/m32c/m32c.h (ASM_OUTPUT_ALIGNED_DECL_COMMON): New.
+       (ASM_OUTPUT_ALIGNED_DECL_LOCAL): New.
+       * config/m32c/m32c-pragma.c (m32c_pragma_address): New.
+       (m32c_register_pragmas): Register it.
+       * config/m32c/m32c.c (m32c_get_pragma_address): New.
+       (m32c_insert_attributes): Set #pragma address decls volatile.
+       (pragma_entry_eq): New.
+       (pragma_entry_hash): New.
+       (m32c_note_pragma_address): New.
+       (m32c_get_pragma_address): New.
+       (m32c_output_aligned_common): New.
+       * doc/extend.texi: Document the new pragma.
+
+       * config/m32c/m32c.c (m32c_illegal_subreg_p): Reject illegal MEMs
+       also.
+       * config/m32c/predicates.md (m32c_any_operand): Check the code
+       instead of memory_operand so as to allow matching volatile MEMs.
+       (m32c_nonimmediate_operand): Likewise.
+       (mra_operand): Allow volatiles.
+
 2010-06-25  Alexandre Oliva  <aoliva@redhat.com>
 
        PR debug/44610
index 49fe023..b576152 100644 (file)
@@ -87,9 +87,47 @@ m32c_pragma_memregs (cpp_reader * reader ATTRIBUTE_UNUSED)
   error ("#pragma GCC memregs takes a number [0..16]");
 }
 
+/* Implements the "pragma ADDRESS" pragma.  This pragma takes a
+   variable name and an address, and arranges for that variable to be
+   "at" that address.  The variable is also made volatile.  */
+static void
+m32c_pragma_address (cpp_reader * reader ATTRIBUTE_UNUSED)
+{
+  /* on off */
+  tree var, addr;
+  enum cpp_ttype type;
+  const char *var_str;
+
+  type = pragma_lex (&var);
+  if (type == CPP_NAME)
+    {
+      var_str = IDENTIFIER_POINTER (var);
+
+      type = pragma_lex (&addr);
+      if (type == CPP_NUMBER)
+       {
+         if (var != error_mark_node)
+           {
+             unsigned uaddr = tree_low_cst (addr, 1);
+             m32c_note_pragma_address (IDENTIFIER_POINTER (var), uaddr);
+           }
+
+         type = pragma_lex (&var);
+         if (type != CPP_EOF)
+           {
+             error ("junk at end of #pragma ADDRESS");
+           }
+         return;
+       }
+    }
+  error ("malformed #pragma ADDRESS variable address");
+}
+
 /* Implements REGISTER_TARGET_PRAGMAS.  */
 void
 m32c_register_pragmas (void)
 {
   c_register_pragma ("GCC", "memregs", m32c_pragma_memregs);
+  c_register_pragma (NULL, "ADDRESS", m32c_pragma_address);
+  c_register_pragma (NULL, "address", m32c_pragma_address);
 }
index 42b92fe..89231fc 100644 (file)
@@ -42,6 +42,7 @@ int  m32c_print_operand_punct_valid_p (int);
 int  m32c_push_rounding (int);
 int  m32c_reg_class_from_constraint (char, const char *);
 void m32c_register_pragmas (void);
+void m32c_note_pragma_address (const char *, unsigned);
 int  m32c_regno_ok_for_base_p (int);
 int  m32c_trampoline_alignment (void);
 int  m32c_trampoline_size (void);
@@ -104,6 +105,8 @@ tree m32c_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *);
 void m32c_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
 bool m32c_promote_function_return (const_tree);
 int  m32c_special_page_vector_p (tree);
+void m32c_output_aligned_common (FILE *, tree, const char *,
+                                int, int, int);
 
 #endif
 
index 3280d14..443325f 100644 (file)
@@ -83,6 +83,9 @@ static int need_to_save (int);
 static rtx m32c_function_value (const_tree, const_tree, bool);
 static rtx m32c_libcall_value (enum machine_mode, const_rtx);
 
+/* Returns true if an address is specified, else false.  */
+static bool m32c_get_pragma_address (const char *varname, unsigned *addr);
+
 int current_function_special_page_vector (rtx);
 
 #define SYMBOL_FLAG_FUNCVEC_FUNCTION    (SYMBOL_FLAG_MACH_DEP << 0)
@@ -2929,7 +2932,107 @@ static void
 m32c_insert_attributes (tree node ATTRIBUTE_UNUSED,
                        tree * attr_ptr ATTRIBUTE_UNUSED)
 {
-  /* Nothing to do here.  */
+  unsigned addr;
+  /* See if we need to make #pragma address variables volatile.  */
+
+  if (TREE_CODE (node) == VAR_DECL)
+    {
+      char *name = IDENTIFIER_POINTER (DECL_NAME (node));
+      if (m32c_get_pragma_address  (name, &addr))
+       {
+         TREE_THIS_VOLATILE (node) = true;
+       }
+    }  
+}
+
+
+struct GTY(()) pragma_entry {
+  const char *varname;
+  unsigned address;
+};
+typedef struct pragma_entry pragma_entry;
+
+/* Hash table of pragma info.  */
+static GTY((param_is (pragma_entry))) htab_t pragma_htab;
+
+static int
+pragma_entry_eq (const void *p1, const void *p2)
+{
+  const pragma_entry *old = (const pragma_entry *) p1;
+  const char *new_name = (const char *) p2;
+
+  return strcmp (old->varname, new_name) == 0;
+}
+
+static hashval_t
+pragma_entry_hash (const void *p)
+{
+  const pragma_entry *old = (const pragma_entry *) p;
+  return htab_hash_string (old->varname);
+}
+
+void
+m32c_note_pragma_address (const char *varname, unsigned address)
+{
+  pragma_entry **slot;
+
+  if (!pragma_htab)
+    pragma_htab = htab_create_ggc (31, pragma_entry_hash,
+                                   pragma_entry_eq, NULL);
+
+  slot = (pragma_entry **)
+    htab_find_slot_with_hash (pragma_htab, varname,
+                             htab_hash_string (varname), INSERT);
+
+  if (!*slot)
+    {
+      *slot = ggc_alloc_pragma_entry ();
+      (*slot)->varname = ggc_strdup (varname);
+    }
+  (*slot)->address = address;
+}
+
+static bool
+m32c_get_pragma_address (const char *varname, unsigned *address)
+{
+  pragma_entry **slot;
+
+  if (!pragma_htab)
+    return false;
+
+  slot = (pragma_entry **)
+    htab_find_slot_with_hash (pragma_htab, varname,
+                             htab_hash_string (varname), NO_INSERT);
+  if (slot && *slot)
+    {
+      *address = (*slot)->address;
+      return true;
+    }
+  return false;
+}
+
+void
+m32c_output_aligned_common (FILE *stream, tree decl, const char *name,
+                           int size, int align, int global)
+{
+  unsigned address;
+
+  if (m32c_get_pragma_address (name, &address))
+    {
+      /* We never output these as global.  */
+      assemble_name (stream, name);
+      fprintf (stream, " = 0x%04x\n", address);
+      return;
+    }
+  if (!global)
+    {
+      fprintf (stream, "\t.local\t");
+      assemble_name (stream, name);
+      fprintf (stream, "\n");
+    }
+  fprintf (stream, "\t.comm\t");
+  assemble_name (stream, name);
+  fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT);
 }
 
 /* Predicates */
@@ -2960,7 +3063,7 @@ static const struct {
 };
 
 /* Returns TRUE if OP is a subreg of a hard reg which we don't
-   support.  */
+   support.  We also bail on MEMs with illegal addresses.  */
 bool
 m32c_illegal_subreg_p (rtx op)
 {
@@ -2968,6 +3071,12 @@ m32c_illegal_subreg_p (rtx op)
   unsigned int i;
   int src_mode, dest_mode;
 
+  if (GET_CODE (op) == MEM
+      && ! m32c_legitimate_address_p (Pmode, XEXP (op, 0), false))
+    {
+      return true;
+    }
+
   if (GET_CODE (op) != SUBREG)
     return false;
 
index 85dc2d1..a98005c 100644 (file)
@@ -644,6 +644,13 @@ typedef struct m32c_cumulative_args
 #define ASM_OUTPUT_REG_PUSH(S,R) m32c_output_reg_push (S, R)
 #define ASM_OUTPUT_REG_POP(S,R) m32c_output_reg_pop (S, R)
 
+#define ASM_OUTPUT_ALIGNED_DECL_COMMON(STREAM, DECL, NAME, SIZE, ALIGNMENT) \
+       m32c_output_aligned_common (STREAM, DECL, NAME, SIZE, ALIGNMENT, 1)
+
+#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGNMENT) \
+       m32c_output_aligned_common (STREAM, DECL, NAME, SIZE, ALIGNMENT, 0)
+
+
 /* Output of Dispatch Tables */
 
 #define ASM_OUTPUT_ADDR_VEC_ELT(S,V) \
index 321debf..98a1c16 100644 (file)
@@ -26,7 +26,7 @@
 
 (define_predicate "m32c_any_operand"
   (ior (match_operand 0 "general_operand")
-       (match_operand 1 "memory_operand"))
+       (match_code "mem,const_int,const_double"))
   {
     return ! m32c_illegal_subreg_p (op);
   }
 
 (define_predicate "m32c_nonimmediate_operand"
   (ior (match_operand 0 "nonimmediate_operand")
-       (match_operand 1 "memory_operand")))
+       (match_code "mem"))
+  {
+    return ! m32c_illegal_subreg_p (op);
+  }
+)
 
 ; TRUE if the operand is a pseudo-register.
 (define_predicate "m32c_pseudo"
 
 ; Likewise, plus TRUE for memory references.
 (define_predicate "mra_operand"
-  (and (and (match_operand 0 "nonimmediate_operand" "")
+  (and (and (match_operand 0 "m32c_nonimmediate_operand" "")
            (not (match_operand 1 "cr_operand" "")))
        (not (match_operand 2 "m32c_wide_subreg" ""))))
 
index 795b6bf..86de226 100644 (file)
@@ -12266,7 +12266,7 @@ subsequent functions.
 @subsection M32C Pragmas
 
 @table @code
-@item memregs @var{number}
+@item GCC memregs @var{number}
 @cindex pragma, memregs
 Overrides the command-line option @code{-memregs=} for the current
 file.  Use with care!  This pragma must be before any function in the
@@ -12275,6 +12275,21 @@ make them incompatible.  This pragma is useful when a
 performance-critical function uses a memreg for temporary values,
 as it may allow you to reduce the number of memregs used.
 
+@item ADDRESS @var{name} @var{address}
+@cindex pragma, address
+For any declared symbols matching @var{name}, this does three things
+to that symbol: it forces the symbol to be located at the given
+address (a number), it forces the symbol to be volatile, and it
+changes the symbol's scope to be static.  This pragma exists for
+compatibility with other compilers, but note that the common
+@code{1234H} numeric syntax is not supported (use @code{0x1234}
+instead).  Example:
+
+@example
+#pragma ADDRESS port3 0x103
+char port3;
+@end example
+
 @end table
 
 @node MeP Pragmas