123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 |
- /* Definitions of Toshiba Media Processor
- Copyright (C) 2001-2015 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 "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include "tm.h"
- #include "hash-set.h"
- #include "machmode.h"
- #include "vec.h"
- #include "double-int.h"
- #include "input.h"
- #include "alias.h"
- #include "symtab.h"
- #include "wide-int.h"
- #include "inchash.h"
- #include "tree.h"
- #include "diagnostic-core.h"
- #include "c-family/c-pragma.h"
- #include "cpplib.h"
- #include "hard-reg-set.h"
- #include "output.h" /* for decode_reg_name */
- #include "mep-protos.h"
- #include "input.h"
- #include "function.h"
- #define MAX_RECOG_OPERANDS 10
- #include "reload.h"
- #include "target.h"
- enum cw_which { CW_AVAILABLE, CW_CALL_SAVED };
- /* This is normally provided by rtl.h but we can't include that file
- here. It's safe to copy the definition here because we're only
- using it internally; the value isn't passed to functions outside
- this file. */
- #ifndef INVALID_REGNUM
- #define INVALID_REGNUM (~(unsigned int) 0)
- #endif
- 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. */
- mep_save_register_info ();
- mep_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 (! tree_fits_uhwi_p (val))
- break;
- i = tree_to_uhwi (val);
- /* 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 rclass;
- type = mep_pragma_lex (&val);
- if (type != CPP_CHAR)
- goto syntax_error;
- class_letter = tree_to_uhwi (val);
- switch (class_letter)
- {
- case 'A':
- rclass = USER0_REGS;
- break;
- case 'B':
- rclass = USER1_REGS;
- break;
- case 'C':
- rclass = USER2_REGS;
- break;
- case 'D':
- rclass = USER3_REGS;
- break;
- default:
- error ("#pragma GCC coprocessor subclass letter must be in [ABCD]");
- return;
- }
- if (reg_class_size[rclass] > 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[rclass], set);
- mep_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);
- }
|