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