]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/mep/mep-pragma.c
2014-10-16 Andrew MacLeod <amacleod@redhat.com>
[thirdparty/gcc.git] / gcc / config / mep / mep-pragma.c
CommitLineData
46222c18 1/* Definitions of Toshiba Media Processor
3aea1f79 2 Copyright (C) 2001-2014 Free Software Foundation, Inc.
71e45bc2 3 Contributed by Red Hat, Inc.
46222c18 4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
46222c18 21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "tm.h"
25#include "tree.h"
0b205f4c 26#include "diagnostic-core.h"
7bedc3a0 27#include "c-family/c-pragma.h"
46222c18 28#include "cpplib.h"
29#include "hard-reg-set.h"
d5bf7b64 30#include "output.h" /* for decode_reg_name */
46222c18 31#include "mep-protos.h"
a3020f2f 32#include "hashtab.h"
33#include "hash-set.h"
34#include "vec.h"
35#include "machmode.h"
36#include "input.h"
46222c18 37#include "function.h"
38#define MAX_RECOG_OPERANDS 10
39#include "reload.h"
40#include "target.h"
41
42enum cw_which { CW_AVAILABLE, CW_CALL_SAVED };
43
7d86c715 44/* This is normally provided by rtl.h but we can't include that file
45 here. It's safe to copy the definition here because we're only
46 using it internally; the value isn't passed to functions outside
47 this file. */
48#ifndef INVALID_REGNUM
49#define INVALID_REGNUM (~(unsigned int) 0)
50#endif
51
46222c18 52static enum cpp_ttype
53mep_pragma_lex (tree *valp)
54{
55 enum cpp_ttype t = pragma_lex (valp);
56 if (t == CPP_EOF)
57 t = CPP_PRAGMA_EOL;
58 return t;
59}
60
61static void
62mep_pragma_io_volatile (cpp_reader *reader ATTRIBUTE_UNUSED)
63{
64 /* On off. */
65 tree val;
66 enum cpp_ttype type;
67 const char * str;
68
69 type = mep_pragma_lex (&val);
70 if (type == CPP_NAME)
71 {
72 str = IDENTIFIER_POINTER (val);
73
74 type = mep_pragma_lex (&val);
75 if (type != CPP_PRAGMA_EOL)
76 warning (0, "junk at end of #pragma io_volatile");
77
78 if (strcmp (str, "on") == 0)
79 {
80 target_flags |= MASK_IO_VOLATILE;
81 return;
82 }
83 if (strcmp (str, "off") == 0)
84 {
85 target_flags &= ~ MASK_IO_VOLATILE;
86 return;
87 }
88 }
89
90 error ("#pragma io_volatile takes only on or off");
91}
92
93static unsigned int
94parse_cr_reg (const char * str)
95{
96 unsigned int regno;
97
98 regno = decode_reg_name (str);
99 if (regno >= FIRST_PSEUDO_REGISTER)
100 return INVALID_REGNUM;
101
102 /* Verify that the regno is in CR_REGS. */
103 if (! TEST_HARD_REG_BIT (reg_class_contents[CR_REGS], regno))
104 return INVALID_REGNUM;
105 return regno;
106}
107
108static bool
109parse_cr_set (HARD_REG_SET * set)
110{
111 tree val;
112 enum cpp_ttype type;
113 unsigned int last_regno = INVALID_REGNUM;
114 bool do_range = false;
115
116 CLEAR_HARD_REG_SET (*set);
117
118 while ((type = mep_pragma_lex (&val)) != CPP_PRAGMA_EOL)
119 {
120 if (type == CPP_COMMA)
121 {
122 last_regno = INVALID_REGNUM;
123 do_range = false;
124 }
125 else if (type == CPP_ELLIPSIS)
126 {
127 if (last_regno == INVALID_REGNUM)
128 {
129 error ("invalid coprocessor register range");
130 return false;
131 }
132 do_range = true;
133 }
134 else if (type == CPP_NAME || type == CPP_STRING)
135 {
136 const char *str;
137 unsigned int regno, i;
138
139 if (TREE_CODE (val) == IDENTIFIER_NODE)
140 str = IDENTIFIER_POINTER (val);
141 else if (TREE_CODE (val) == STRING_CST)
142 str = TREE_STRING_POINTER (val);
143 else
144 gcc_unreachable ();
145
146 regno = parse_cr_reg (str);
147 if (regno == INVALID_REGNUM)
148 {
149 error ("invalid coprocessor register %qE", val);
150 return false;
151 }
152
153 if (do_range)
154 {
155 if (last_regno > regno)
156 i = regno, regno = last_regno;
157 else
158 i = last_regno;
159 do_range = false;
160 }
161 else
162 last_regno = i = regno;
163
164 while (i <= regno)
165 {
166 SET_HARD_REG_BIT (*set, i);
167 i++;
168 }
169 }
170 else
171 {
172 error ("malformed coprocessor register");
173 return false;
174 }
175 }
176 return true;
177}
178
179static void
180mep_pragma_coprocessor_which (enum cw_which cw_which)
181{
182 HARD_REG_SET set;
183
184 /* Process the balance of the pragma and turn it into a hard reg set. */
185 if (! parse_cr_set (&set))
186 return;
187
188 /* Process the collected hard reg set. */
189 switch (cw_which)
190 {
191 case CW_AVAILABLE:
192 {
193 int i;
194 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
195 if (TEST_HARD_REG_BIT (set, i))
196 fixed_regs[i] = 0;
197 }
198 break;
199
200 case CW_CALL_SAVED:
201 {
202 int i;
203 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
204 if (TEST_HARD_REG_BIT (set, i))
205 fixed_regs[i] = call_used_regs[i] = 0;
206 }
207 break;
208
209 default:
210 gcc_unreachable ();
211 }
212
213 /* Fix up register class hierarchy. */
7d86c715 214 mep_save_register_info ();
215 mep_reinit_regs ();
46222c18 216
217 if (cfun == 0)
218 {
219 init_dummy_function_start ();
220 init_caller_save ();
221 expand_dummy_function_end ();
222 }
223 else
224 {
225 init_caller_save ();
226 }
227}
228
229static void
230mep_pragma_coprocessor_width (void)
231{
232 tree val;
233 enum cpp_ttype type;
234 HOST_WIDE_INT i;
235
236 type = mep_pragma_lex (&val);
237 switch (type)
238 {
239 case CPP_NUMBER:
cd4547bf 240 if (! tree_fits_uhwi_p (val))
46222c18 241 break;
6a0712d4 242 i = tree_to_uhwi (val);
46222c18 243 /* This pragma no longer has any effect. */
244#if 0
245 if (i == 32)
246 target_flags &= ~MASK_64BIT_CR_REGS;
247 else if (i == 64)
248 target_flags |= MASK_64BIT_CR_REGS;
249 else
250 break;
251 targetm.init_builtins ();
252#else
253 if (i != 32 && i != 64)
254 break;
255#endif
256
257 type = mep_pragma_lex (&val);
258 if (type != CPP_PRAGMA_EOL)
259 warning (0, "junk at end of #pragma GCC coprocessor width");
260 return;
261
262 default:
263 break;
264 }
265
266 error ("#pragma GCC coprocessor width takes only 32 or 64");
267}
268
269static void
270mep_pragma_coprocessor_subclass (void)
271{
272 tree val;
273 enum cpp_ttype type;
274 HARD_REG_SET set;
275 int class_letter;
7d86c715 276 enum reg_class rclass;
46222c18 277
278 type = mep_pragma_lex (&val);
279 if (type != CPP_CHAR)
280 goto syntax_error;
6a0712d4 281 class_letter = tree_to_uhwi (val);
c7b51f7d 282 switch (class_letter)
46222c18 283 {
c7b51f7d 284 case 'A':
285 rclass = USER0_REGS;
286 break;
287 case 'B':
288 rclass = USER1_REGS;
289 break;
290 case 'C':
291 rclass = USER2_REGS;
292 break;
293 case 'D':
294 rclass = USER3_REGS;
295 break;
296 default:
46222c18 297 error ("#pragma GCC coprocessor subclass letter must be in [ABCD]");
298 return;
299 }
7d86c715 300 if (reg_class_size[rclass] > 0)
46222c18 301 {
302 error ("#pragma GCC coprocessor subclass '%c' already defined",
303 class_letter);
304 return;
305 }
306
307 type = mep_pragma_lex (&val);
308 if (type != CPP_EQ)
309 goto syntax_error;
310
311 if (! parse_cr_set (&set))
312 return;
313
314 /* Fix up register class hierarchy. */
7d86c715 315 COPY_HARD_REG_SET (reg_class_contents[rclass], set);
316 mep_init_regs ();
46222c18 317 return;
318
319 syntax_error:
320 error ("malformed #pragma GCC coprocessor subclass");
321}
322
323static void
324mep_pragma_disinterrupt (cpp_reader *reader ATTRIBUTE_UNUSED)
325{
326 tree val;
327 enum cpp_ttype type;
328 int saw_one = 0;
329
330 for (;;)
331 {
332 type = mep_pragma_lex (&val);
333 if (type == CPP_COMMA)
334 continue;
335 if (type != CPP_NAME)
336 break;
337 mep_note_pragma_disinterrupt (IDENTIFIER_POINTER (val));
338 saw_one = 1;
339 }
340 if (!saw_one || type != CPP_PRAGMA_EOL)
341 {
342 error ("malformed #pragma disinterrupt");
343 return;
344 }
345}
346
347static void
348mep_pragma_coprocessor (cpp_reader *reader ATTRIBUTE_UNUSED)
349{
350 tree val;
351 enum cpp_ttype type;
352
353 type = mep_pragma_lex (&val);
354 if (type != CPP_NAME)
355 {
356 error ("malformed #pragma GCC coprocessor");
357 return;
358 }
359
360 if (!TARGET_COP)
361 error ("coprocessor not enabled");
362
363 if (strcmp (IDENTIFIER_POINTER (val), "available") == 0)
364 mep_pragma_coprocessor_which (CW_AVAILABLE);
365 else if (strcmp (IDENTIFIER_POINTER (val), "call_saved") == 0)
366 mep_pragma_coprocessor_which (CW_CALL_SAVED);
367 else if (strcmp (IDENTIFIER_POINTER (val), "width") == 0)
368 mep_pragma_coprocessor_width ();
369 else if (strcmp (IDENTIFIER_POINTER (val), "subclass") == 0)
370 mep_pragma_coprocessor_subclass ();
371 else
372 error ("unknown #pragma GCC coprocessor %E", val);
373}
374
375static void
376mep_pragma_call (cpp_reader *reader ATTRIBUTE_UNUSED)
377{
378 tree val;
379 enum cpp_ttype type;
380 int saw_one = 0;
381
382 for (;;)
383 {
384 type = mep_pragma_lex (&val);
385 if (type == CPP_COMMA)
386 continue;
387 if (type != CPP_NAME)
388 break;
389 mep_note_pragma_call (IDENTIFIER_POINTER (val));
390 saw_one = 1;
391 }
392 if (!saw_one || type != CPP_PRAGMA_EOL)
393 {
394 error ("malformed #pragma call");
395 return;
396 }
397}
398
399void
400mep_register_pragmas (void)
401{
402 c_register_pragma ("custom", "io_volatile", mep_pragma_io_volatile);
403 c_register_pragma ("GCC", "coprocessor", mep_pragma_coprocessor);
404 c_register_pragma (0, "disinterrupt", mep_pragma_disinterrupt);
405 c_register_pragma (0, "call", mep_pragma_call);
406}