summaryrefslogtreecommitdiff
path: root/gcc/config/mep/mep-pragma.c
diff options
context:
space:
mode:
authordj <dj@138bc75d-0d04-0410-961f-82ee72b054a4>2009-06-24 04:16:25 +0000
committerdj <dj@138bc75d-0d04-0410-961f-82ee72b054a4>2009-06-24 04:16:25 +0000
commit46222c1821f32a4b0e0840125a1f15e708e78376 (patch)
tree43f723d14b2b85261e109309ad7df778f073cc92 /gcc/config/mep/mep-pragma.c
parent7ab76cecd643d0d098fb7293340afa0e2b5f9f37 (diff)
downloadgcc-46222c1821f32a4b0e0840125a1f15e708e78376.tar.gz
[toplevel]
* MAINTAINERS: Add myself as mep maintainer. [gcc] Add MeP port. * config.gcc: Add mep support. * recog.c: Resurrect validate_replace_rtx_subexp(). * recog.h: Likewise. * config/mep/: Add new port: * config/mep/constraints.md: New file. * config/mep/default.h: New file. * config/mep/intrinsics.h: New file. * config/mep/intrinsics.md: New file. * config/mep/ivc2-template.h: New file. * config/mep/mep-c5.cpu: New file. * config/mep/mep-core.cpu: New file. * config/mep/mep-default.cpu: New file. * config/mep/mep-ext-cop.cpu: New file. * config/mep/mep-intrin.h: New file. * config/mep/mep-ivc2.cpu: New file. * config/mep/mep-lib1.asm: New file. * config/mep/mep-lib2.c: New file. * config/mep/mep-pragma.c: New file. * config/mep/mep-protos.h: New file. * config/mep/mep-tramp.c: New file. * config/mep/mep.c: New file. * config/mep/mep.cpu: New file. * config/mep/mep.h: New file. * config/mep/mep.md: New file. * config/mep/mep.opt: New file. * config/mep/predicates.md: New file. * config/mep/t-mep: New file. [gcc/testsuite] Add MeP port. * lib/target-supports.exp: Add mep support (no profiling). [libgcc] Add MeP port. * config.host: Add mep support. [libstdc++-v3] Add MeP port. * configure.host: Add mep support. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@148890 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/mep/mep-pragma.c')
-rw-r--r--gcc/config/mep/mep-pragma.c384
1 files changed, 384 insertions, 0 deletions
diff --git a/gcc/config/mep/mep-pragma.c b/gcc/config/mep/mep-pragma.c
new file mode 100644
index 00000000000..3f9fc5a7071
--- /dev/null
+++ b/gcc/config/mep/mep-pragma.c
@@ -0,0 +1,384 @@
+/* Definitions of Toshiba Media Processor
+ Copyright (C) 2001, 2002, 2003, 2005, 2006, 2007, 2009 Free
+ Software Foundation, Inc. Contributed by Red Hat, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "rtl.h"
+#include "toplev.h"
+#include "c-pragma.h"
+#include "cpplib.h"
+#include "hard-reg-set.h"
+#include "output.h"
+#include "mep-protos.h"
+#include "function.h"
+#define MAX_RECOG_OPERANDS 10
+#include "reload.h"
+#include "target.h"
+
+enum cw_which { CW_AVAILABLE, CW_CALL_SAVED };
+
+static enum cpp_ttype
+mep_pragma_lex (tree *valp)
+{
+ enum cpp_ttype t = pragma_lex (valp);
+ if (t == CPP_EOF)
+ t = CPP_PRAGMA_EOL;
+ return t;
+}
+
+static void
+mep_pragma_io_volatile (cpp_reader *reader ATTRIBUTE_UNUSED)
+{
+ /* On off. */
+ tree val;
+ enum cpp_ttype type;
+ const char * str;
+
+ type = mep_pragma_lex (&val);
+ if (type == CPP_NAME)
+ {
+ str = IDENTIFIER_POINTER (val);
+
+ type = mep_pragma_lex (&val);
+ if (type != CPP_PRAGMA_EOL)
+ warning (0, "junk at end of #pragma io_volatile");
+
+ if (strcmp (str, "on") == 0)
+ {
+ target_flags |= MASK_IO_VOLATILE;
+ return;
+ }
+ if (strcmp (str, "off") == 0)
+ {
+ target_flags &= ~ MASK_IO_VOLATILE;
+ return;
+ }
+ }
+
+ error ("#pragma io_volatile takes only on or off");
+}
+
+static unsigned int
+parse_cr_reg (const char * str)
+{
+ unsigned int regno;
+
+ regno = decode_reg_name (str);
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return INVALID_REGNUM;
+
+ /* Verify that the regno is in CR_REGS. */
+ if (! TEST_HARD_REG_BIT (reg_class_contents[CR_REGS], regno))
+ return INVALID_REGNUM;
+ return regno;
+}
+
+static bool
+parse_cr_set (HARD_REG_SET * set)
+{
+ tree val;
+ enum cpp_ttype type;
+ unsigned int last_regno = INVALID_REGNUM;
+ bool do_range = false;
+
+ CLEAR_HARD_REG_SET (*set);
+
+ while ((type = mep_pragma_lex (&val)) != CPP_PRAGMA_EOL)
+ {
+ if (type == CPP_COMMA)
+ {
+ last_regno = INVALID_REGNUM;
+ do_range = false;
+ }
+ else if (type == CPP_ELLIPSIS)
+ {
+ if (last_regno == INVALID_REGNUM)
+ {
+ error ("invalid coprocessor register range");
+ return false;
+ }
+ do_range = true;
+ }
+ else if (type == CPP_NAME || type == CPP_STRING)
+ {
+ const char *str;
+ unsigned int regno, i;
+
+ if (TREE_CODE (val) == IDENTIFIER_NODE)
+ str = IDENTIFIER_POINTER (val);
+ else if (TREE_CODE (val) == STRING_CST)
+ str = TREE_STRING_POINTER (val);
+ else
+ gcc_unreachable ();
+
+ regno = parse_cr_reg (str);
+ if (regno == INVALID_REGNUM)
+ {
+ error ("invalid coprocessor register %qE", val);
+ return false;
+ }
+
+ if (do_range)
+ {
+ if (last_regno > regno)
+ i = regno, regno = last_regno;
+ else
+ i = last_regno;
+ do_range = false;
+ }
+ else
+ last_regno = i = regno;
+
+ while (i <= regno)
+ {
+ SET_HARD_REG_BIT (*set, i);
+ i++;
+ }
+ }
+ else
+ {
+ error ("malformed coprocessor register");
+ return false;
+ }
+ }
+ return true;
+}
+
+static void
+mep_pragma_coprocessor_which (enum cw_which cw_which)
+{
+ HARD_REG_SET set;
+
+ /* Process the balance of the pragma and turn it into a hard reg set. */
+ if (! parse_cr_set (&set))
+ return;
+
+ /* Process the collected hard reg set. */
+ switch (cw_which)
+ {
+ case CW_AVAILABLE:
+ {
+ int i;
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ if (TEST_HARD_REG_BIT (set, i))
+ fixed_regs[i] = 0;
+ }
+ break;
+
+ case CW_CALL_SAVED:
+ {
+ int i;
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ if (TEST_HARD_REG_BIT (set, i))
+ fixed_regs[i] = call_used_regs[i] = 0;
+ }
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Fix up register class hierarchy. */
+ save_register_info ();
+ reinit_regs ();
+
+ if (cfun == 0)
+ {
+ init_dummy_function_start ();
+ init_caller_save ();
+ expand_dummy_function_end ();
+ }
+ else
+ {
+ init_caller_save ();
+ }
+}
+
+static void
+mep_pragma_coprocessor_width (void)
+{
+ tree val;
+ enum cpp_ttype type;
+ HOST_WIDE_INT i;
+
+ type = mep_pragma_lex (&val);
+ switch (type)
+ {
+ case CPP_NUMBER:
+ if (! host_integerp (val, 1))
+ break;
+ i = tree_low_cst (val, 1);
+ /* This pragma no longer has any effect. */
+#if 0
+ if (i == 32)
+ target_flags &= ~MASK_64BIT_CR_REGS;
+ else if (i == 64)
+ target_flags |= MASK_64BIT_CR_REGS;
+ else
+ break;
+ targetm.init_builtins ();
+#else
+ if (i != 32 && i != 64)
+ break;
+#endif
+
+ type = mep_pragma_lex (&val);
+ if (type != CPP_PRAGMA_EOL)
+ warning (0, "junk at end of #pragma GCC coprocessor width");
+ return;
+
+ default:
+ break;
+ }
+
+ error ("#pragma GCC coprocessor width takes only 32 or 64");
+}
+
+static void
+mep_pragma_coprocessor_subclass (void)
+{
+ tree val;
+ enum cpp_ttype type;
+ HARD_REG_SET set;
+ int class_letter;
+ enum reg_class class;
+
+ type = mep_pragma_lex (&val);
+ if (type != CPP_CHAR)
+ goto syntax_error;
+ class_letter = tree_low_cst (val, 1);
+ if (class_letter >= 'A' && class_letter <= 'D')
+ class = class_letter - 'A' + USER0_REGS;
+ else
+ {
+ error ("#pragma GCC coprocessor subclass letter must be in [ABCD]");
+ return;
+ }
+ if (reg_class_size[class] > 0)
+ {
+ error ("#pragma GCC coprocessor subclass '%c' already defined",
+ class_letter);
+ return;
+ }
+
+ type = mep_pragma_lex (&val);
+ if (type != CPP_EQ)
+ goto syntax_error;
+
+ if (! parse_cr_set (&set))
+ return;
+
+ /* Fix up register class hierarchy. */
+ COPY_HARD_REG_SET (reg_class_contents[class], set);
+ init_regs ();
+ return;
+
+ syntax_error:
+ error ("malformed #pragma GCC coprocessor subclass");
+}
+
+static void
+mep_pragma_disinterrupt (cpp_reader *reader ATTRIBUTE_UNUSED)
+{
+ tree val;
+ enum cpp_ttype type;
+ int saw_one = 0;
+
+ for (;;)
+ {
+ type = mep_pragma_lex (&val);
+ if (type == CPP_COMMA)
+ continue;
+ if (type != CPP_NAME)
+ break;
+ mep_note_pragma_disinterrupt (IDENTIFIER_POINTER (val));
+ saw_one = 1;
+ }
+ if (!saw_one || type != CPP_PRAGMA_EOL)
+ {
+ error ("malformed #pragma disinterrupt");
+ return;
+ }
+}
+
+static void
+mep_pragma_coprocessor (cpp_reader *reader ATTRIBUTE_UNUSED)
+{
+ tree val;
+ enum cpp_ttype type;
+
+ type = mep_pragma_lex (&val);
+ if (type != CPP_NAME)
+ {
+ error ("malformed #pragma GCC coprocessor");
+ return;
+ }
+
+ if (!TARGET_COP)
+ error ("coprocessor not enabled");
+
+ if (strcmp (IDENTIFIER_POINTER (val), "available") == 0)
+ mep_pragma_coprocessor_which (CW_AVAILABLE);
+ else if (strcmp (IDENTIFIER_POINTER (val), "call_saved") == 0)
+ mep_pragma_coprocessor_which (CW_CALL_SAVED);
+ else if (strcmp (IDENTIFIER_POINTER (val), "width") == 0)
+ mep_pragma_coprocessor_width ();
+ else if (strcmp (IDENTIFIER_POINTER (val), "subclass") == 0)
+ mep_pragma_coprocessor_subclass ();
+ else
+ error ("unknown #pragma GCC coprocessor %E", val);
+}
+
+static void
+mep_pragma_call (cpp_reader *reader ATTRIBUTE_UNUSED)
+{
+ tree val;
+ enum cpp_ttype type;
+ int saw_one = 0;
+
+ for (;;)
+ {
+ type = mep_pragma_lex (&val);
+ if (type == CPP_COMMA)
+ continue;
+ if (type != CPP_NAME)
+ break;
+ mep_note_pragma_call (IDENTIFIER_POINTER (val));
+ saw_one = 1;
+ }
+ if (!saw_one || type != CPP_PRAGMA_EOL)
+ {
+ error ("malformed #pragma call");
+ return;
+ }
+}
+
+void
+mep_register_pragmas (void)
+{
+ c_register_pragma ("custom", "io_volatile", mep_pragma_io_volatile);
+ c_register_pragma ("GCC", "coprocessor", mep_pragma_coprocessor);
+ c_register_pragma (0, "disinterrupt", mep_pragma_disinterrupt);
+ c_register_pragma (0, "call", mep_pragma_call);
+}