OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [mep/] [mep-pragma.c] - Blame information for rev 718

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 709 jeremybenn
/* Definitions of Toshiba Media Processor
2
   Copyright (C) 2001, 2002, 2003, 2005, 2006, 2007, 2009, 2010 Free
3
   Software Foundation, Inc.  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 "tree.h"
26
#include "diagnostic-core.h"
27
#include "c-family/c-pragma.h"
28
#include "cpplib.h"
29
#include "hard-reg-set.h"
30
#include "output.h"
31
#include "mep-protos.h"
32
#include "function.h"
33
#define MAX_RECOG_OPERANDS 10
34
#include "reload.h"
35
#include "target.h"
36
 
37
enum cw_which { CW_AVAILABLE, CW_CALL_SAVED };
38
 
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
 
47
static enum cpp_ttype
48
mep_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
 
56
static void
57
mep_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
 
88
static unsigned int
89
parse_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
 
103
static bool
104
parse_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
 
174
static void
175
mep_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.  */
209
  mep_save_register_info ();
210
  mep_reinit_regs ();
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
 
224
static void
225
mep_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:
235
      if (! host_integerp (val, 1))
236
        break;
237
      i = tree_low_cst (val, 1);
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
 
264
static void
265
mep_pragma_coprocessor_subclass (void)
266
{
267
  tree val;
268
  enum cpp_ttype type;
269
  HARD_REG_SET set;
270
  int class_letter;
271
  enum reg_class rclass;
272
 
273
  type = mep_pragma_lex (&val);
274
  if (type != CPP_CHAR)
275
    goto syntax_error;
276
  class_letter = tree_low_cst (val, 1);
277
  if (class_letter >= 'A' && class_letter <= 'D')
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
      }
293
  else
294
    {
295
      error ("#pragma GCC coprocessor subclass letter must be in [ABCD]");
296
      return;
297
    }
298
  if (reg_class_size[rclass] > 0)
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.  */
313
  COPY_HARD_REG_SET (reg_class_contents[rclass], set);
314
  mep_init_regs ();
315
  return;
316
 
317
 syntax_error:
318
  error ("malformed #pragma GCC coprocessor subclass");
319
}
320
 
321
static void
322
mep_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
 
345
static void
346
mep_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
 
373
static void
374
mep_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
 
397
void
398
mep_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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.