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