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