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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [rx/] [rx.c] - Blame information for rev 709

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 709 jeremybenn
/* Subroutines used for code generation on Renesas RX processors.
2
   Copyright (C) 2008, 2009, 2010, 2011, 2012
3
   Free Software Foundation, Inc.
4
   Contributed by Red Hat.
5
 
6
   This file is part of GCC.
7
 
8
   GCC is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3, or (at your option)
11
   any later version.
12
 
13
   GCC is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with GCC; see the file COPYING3.  If not see
20
   <http://www.gnu.org/licenses/>.  */
21
 
22
/* To Do:
23
 
24
 * Re-enable memory-to-memory copies and fix up reload.  */
25
 
26
#include "config.h"
27
#include "system.h"
28
#include "coretypes.h"
29
#include "tm.h"
30
#include "tree.h"
31
#include "rtl.h"
32
#include "regs.h"
33
#include "hard-reg-set.h"
34
#include "insn-config.h"
35
#include "conditions.h"
36
#include "output.h"
37
#include "insn-attr.h"
38
#include "flags.h"
39
#include "function.h"
40
#include "expr.h"
41
#include "optabs.h"
42
#include "libfuncs.h"
43
#include "recog.h"
44
#include "diagnostic-core.h"
45
#include "toplev.h"
46
#include "reload.h"
47
#include "df.h"
48
#include "ggc.h"
49
#include "tm_p.h"
50
#include "debug.h"
51
#include "target.h"
52
#include "target-def.h"
53
#include "langhooks.h"
54
#include "opts.h"
55
 
56
static unsigned int rx_gp_base_regnum_val = INVALID_REGNUM;
57
static unsigned int rx_pid_base_regnum_val = INVALID_REGNUM;
58
static unsigned int rx_num_interrupt_regs;
59
 
60
static unsigned int
61
rx_gp_base_regnum (void)
62
{
63
  if (rx_gp_base_regnum_val == INVALID_REGNUM)
64
    gcc_unreachable ();
65
  return rx_gp_base_regnum_val;
66
}
67
 
68
static unsigned int
69
rx_pid_base_regnum (void)
70
{
71
  if (rx_pid_base_regnum_val == INVALID_REGNUM)
72
    gcc_unreachable ();
73
  return rx_pid_base_regnum_val;
74
}
75
 
76
/* Find a SYMBOL_REF in a "standard" MEM address and return its decl.  */
77
 
78
static tree
79
rx_decl_for_addr (rtx op)
80
{
81
  if (GET_CODE (op) == MEM)
82
    op = XEXP (op, 0);
83
  if (GET_CODE (op) == CONST)
84
    op = XEXP (op, 0);
85
  while (GET_CODE (op) == PLUS)
86
    op = XEXP (op, 0);
87
  if (GET_CODE (op) == SYMBOL_REF)
88
    return SYMBOL_REF_DECL (op);
89
  return NULL_TREE;
90
}
91
 
92
static void rx_print_operand (FILE *, rtx, int);
93
 
94
#define CC_FLAG_S       (1 << 0)
95
#define CC_FLAG_Z       (1 << 1)
96
#define CC_FLAG_O       (1 << 2)
97
#define CC_FLAG_C       (1 << 3)
98
#define CC_FLAG_FP      (1 << 4)        /* Fake, to differentiate CC_Fmode.  */
99
 
100
static unsigned int flags_from_mode (enum machine_mode mode);
101
static unsigned int flags_from_code (enum rtx_code code);
102
 
103
/* Return true if OP is a reference to an object in a PID data area.  */
104
 
105
enum pid_type
106
{
107
  PID_NOT_PID = 0,       /* The object is not in the PID data area.  */
108
  PID_ENCODED,          /* The object is in the PID data area.  */
109
  PID_UNENCODED         /* The object will be placed in the PID data area, but it has not been placed there yet.  */
110
};
111
 
112
static enum pid_type
113
rx_pid_data_operand (rtx op)
114
{
115
  tree op_decl;
116
 
117
  if (!TARGET_PID)
118
    return PID_NOT_PID;
119
 
120
  if (GET_CODE (op) == PLUS
121
      && GET_CODE (XEXP (op, 0)) == REG
122
      && GET_CODE (XEXP (op, 1)) == CONST
123
      && GET_CODE (XEXP (XEXP (op, 1), 0)) == UNSPEC)
124
    return PID_ENCODED;
125
 
126
  op_decl = rx_decl_for_addr (op);
127
 
128
  if (op_decl)
129
    {
130
      if (TREE_READONLY (op_decl))
131
        return PID_UNENCODED;
132
    }
133
  else
134
    {
135
      /* Sigh, some special cases.  */
136
      if (GET_CODE (op) == SYMBOL_REF
137
          || GET_CODE (op) == LABEL_REF)
138
        return PID_UNENCODED;
139
    }
140
 
141
  return PID_NOT_PID;
142
}
143
 
144
static rtx
145
rx_legitimize_address (rtx x,
146
                       rtx oldx ATTRIBUTE_UNUSED,
147
                       enum machine_mode mode ATTRIBUTE_UNUSED)
148
{
149
  if (rx_pid_data_operand (x) == PID_UNENCODED)
150
    {
151
      rtx rv = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), x);
152
      return rv;
153
    }
154
 
155
  if (GET_CODE (x) == PLUS
156
      && GET_CODE (XEXP (x, 0)) == PLUS
157
      && REG_P (XEXP (XEXP (x, 0), 0))
158
      && REG_P (XEXP (x, 1)))
159
    return force_reg (SImode, x);
160
 
161
  return x;
162
}
163
 
164
/* Return true if OP is a reference to an object in a small data area.  */
165
 
166
static bool
167
rx_small_data_operand (rtx op)
168
{
169
  if (rx_small_data_limit == 0)
170
    return false;
171
 
172
  if (GET_CODE (op) == SYMBOL_REF)
173
    return SYMBOL_REF_SMALL_P (op);
174
 
175
  return false;
176
}
177
 
178
static bool
179
rx_is_legitimate_address (enum machine_mode mode, rtx x,
180
                          bool strict ATTRIBUTE_UNUSED)
181
{
182
  if (RTX_OK_FOR_BASE (x, strict))
183
    /* Register Indirect.  */
184
    return true;
185
 
186
  if ((GET_MODE_SIZE (mode) == 4
187
       || GET_MODE_SIZE (mode) == 2
188
       || GET_MODE_SIZE (mode) == 1)
189
      && (GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC))
190
    /* Pre-decrement Register Indirect or
191
       Post-increment Register Indirect.  */
192
    return RTX_OK_FOR_BASE (XEXP (x, 0), strict);
193
 
194
  switch (rx_pid_data_operand (x))
195
    {
196
    case PID_UNENCODED:
197
      return false;
198
    case PID_ENCODED:
199
      return true;
200
    default:
201
      break;
202
    }
203
 
204
  if (GET_CODE (x) == PLUS)
205
    {
206
      rtx arg1 = XEXP (x, 0);
207
      rtx arg2 = XEXP (x, 1);
208
      rtx index = NULL_RTX;
209
 
210
      if (REG_P (arg1) && RTX_OK_FOR_BASE (arg1, strict))
211
        index = arg2;
212
      else if (REG_P (arg2) && RTX_OK_FOR_BASE (arg2, strict))
213
        index = arg1;
214
      else
215
        return false;
216
 
217
      switch (GET_CODE (index))
218
        {
219
        case CONST_INT:
220
          {
221
            /* Register Relative: REG + INT.
222
               Only positive, mode-aligned, mode-sized
223
               displacements are allowed.  */
224
            HOST_WIDE_INT val = INTVAL (index);
225
            int factor;
226
 
227
            if (val < 0)
228
              return false;
229
 
230
            switch (GET_MODE_SIZE (mode))
231
              {
232
              default:
233
              case 4: factor = 4; break;
234
              case 2: factor = 2; break;
235
              case 1: factor = 1; break;
236
              }
237
 
238
            if (val > (65535 * factor))
239
              return false;
240
            return (val % factor) == 0;
241
          }
242
 
243
        case REG:
244
          /* Unscaled Indexed Register Indirect: REG + REG
245
             Size has to be "QI", REG has to be valid.  */
246
          return GET_MODE_SIZE (mode) == 1 && RTX_OK_FOR_BASE (index, strict);
247
 
248
        case MULT:
249
          {
250
            /* Scaled Indexed Register Indirect: REG + (REG * FACTOR)
251
               Factor has to equal the mode size, REG has to be valid.  */
252
            rtx factor;
253
 
254
            factor = XEXP (index, 1);
255
            index = XEXP (index, 0);
256
 
257
            return REG_P (index)
258
              && RTX_OK_FOR_BASE (index, strict)
259
              && CONST_INT_P (factor)
260
              && GET_MODE_SIZE (mode) == INTVAL (factor);
261
          }
262
 
263
        default:
264
          return false;
265
        }
266
    }
267
 
268
  /* Small data area accesses turn into register relative offsets.  */
269
  return rx_small_data_operand (x);
270
}
271
 
272
/* Returns TRUE for simple memory addreses, ie ones
273
   that do not involve register indirect addressing
274
   or pre/post increment/decrement.  */
275
 
276
bool
277
rx_is_restricted_memory_address (rtx mem, enum machine_mode mode)
278
{
279
  if (! rx_is_legitimate_address
280
      (mode, mem, reload_in_progress || reload_completed))
281
    return false;
282
 
283
  switch (GET_CODE (mem))
284
    {
285
    case REG:
286
      /* Simple memory addresses are OK.  */
287
      return true;
288
 
289
    case PRE_DEC:
290
    case POST_INC:
291
      return false;
292
 
293
    case PLUS:
294
      {
295
        rtx base, index;
296
 
297
        /* Only allow REG+INT addressing.  */
298
        base = XEXP (mem, 0);
299
        index = XEXP (mem, 1);
300
 
301
        if (! RX_REG_P (base) || ! CONST_INT_P (index))
302
          return false;
303
 
304
        return IN_RANGE (INTVAL (index), 0, (0x10000 * GET_MODE_SIZE (mode)) - 1);
305
      }
306
 
307
    case SYMBOL_REF:
308
      /* Can happen when small data is being supported.
309
         Assume that it will be resolved into GP+INT.  */
310
      return true;
311
 
312
    default:
313
      gcc_unreachable ();
314
    }
315
}
316
 
317
/* Implement TARGET_MODE_DEPENDENT_ADDRESS_P.  */
318
 
319
static bool
320
rx_mode_dependent_address_p (const_rtx addr)
321
{
322
  if (GET_CODE (addr) == CONST)
323
    addr = XEXP (addr, 0);
324
 
325
  switch (GET_CODE (addr))
326
    {
327
      /* --REG and REG++ only work in SImode.  */
328
    case PRE_DEC:
329
    case POST_INC:
330
      return true;
331
 
332
    case MINUS:
333
    case PLUS:
334
      if (! REG_P (XEXP (addr, 0)))
335
        return true;
336
 
337
      addr = XEXP (addr, 1);
338
 
339
      switch (GET_CODE (addr))
340
        {
341
        case REG:
342
          /* REG+REG only works in SImode.  */
343
          return true;
344
 
345
        case CONST_INT:
346
          /* REG+INT is only mode independent if INT is a
347
             multiple of 4, positive and will fit into 8-bits.  */
348
          if (((INTVAL (addr) & 3) == 0)
349
              && IN_RANGE (INTVAL (addr), 4, 252))
350
            return false;
351
          return true;
352
 
353
        case SYMBOL_REF:
354
        case LABEL_REF:
355
          return true;
356
 
357
        case MULT:
358
          gcc_assert (REG_P (XEXP (addr, 0)));
359
          gcc_assert (CONST_INT_P (XEXP (addr, 1)));
360
          /* REG+REG*SCALE is always mode dependent.  */
361
          return true;
362
 
363
        default:
364
          /* Not recognized, so treat as mode dependent.  */
365
          return true;
366
        }
367
 
368
    case CONST_INT:
369
    case SYMBOL_REF:
370
    case LABEL_REF:
371
    case REG:
372
      /* These are all mode independent.  */
373
      return false;
374
 
375
    default:
376
      /* Everything else is unrecognized,
377
         so treat as mode dependent.  */
378
      return true;
379
    }
380
}
381
 
382
/* A C compound statement to output to stdio stream FILE the
383
   assembler syntax for an instruction operand that is a memory
384
   reference whose address is ADDR.  */
385
 
386
static void
387
rx_print_operand_address (FILE * file, rtx addr)
388
{
389
  switch (GET_CODE (addr))
390
    {
391
    case REG:
392
      fprintf (file, "[");
393
      rx_print_operand (file, addr, 0);
394
      fprintf (file, "]");
395
      break;
396
 
397
    case PRE_DEC:
398
      fprintf (file, "[-");
399
      rx_print_operand (file, XEXP (addr, 0), 0);
400
      fprintf (file, "]");
401
      break;
402
 
403
    case POST_INC:
404
      fprintf (file, "[");
405
      rx_print_operand (file, XEXP (addr, 0), 0);
406
      fprintf (file, "+]");
407
      break;
408
 
409
    case PLUS:
410
      {
411
        rtx arg1 = XEXP (addr, 0);
412
        rtx arg2 = XEXP (addr, 1);
413
        rtx base, index;
414
 
415
        if (REG_P (arg1) && RTX_OK_FOR_BASE (arg1, true))
416
          base = arg1, index = arg2;
417
        else if (REG_P (arg2) && RTX_OK_FOR_BASE (arg2, true))
418
          base = arg2, index = arg1;
419
        else
420
          {
421
            rx_print_operand (file, arg1, 0);
422
            fprintf (file, " + ");
423
            rx_print_operand (file, arg2, 0);
424
            break;
425
          }
426
 
427
        if (REG_P (index) || GET_CODE (index) == MULT)
428
          {
429
            fprintf (file, "[");
430
            rx_print_operand (file, index, 'A');
431
            fprintf (file, ",");
432
          }
433
        else /* GET_CODE (index) == CONST_INT  */
434
          {
435
            rx_print_operand (file, index, 'A');
436
            fprintf (file, "[");
437
          }
438
        rx_print_operand (file, base, 0);
439
        fprintf (file, "]");
440
        break;
441
      }
442
 
443
    case CONST:
444
      if (GET_CODE (XEXP (addr, 0)) == UNSPEC)
445
        {
446
          addr = XEXP (addr, 0);
447
          gcc_assert (XINT (addr, 1) == UNSPEC_CONST);
448
 
449
          /* FIXME: Putting this case label here is an appalling abuse of the C language.  */
450
        case UNSPEC:
451
          addr = XVECEXP (addr, 0, 0);
452
          gcc_assert (CONST_INT_P (addr));
453
        }
454
      /* Fall through.  */
455
    case LABEL_REF:
456
    case SYMBOL_REF:
457
      fprintf (file, "#");
458
      /* Fall through.  */
459
    default:
460
      output_addr_const (file, addr);
461
      break;
462
    }
463
}
464
 
465
static void
466
rx_print_integer (FILE * file, HOST_WIDE_INT val)
467
{
468
  if (IN_RANGE (val, -64, 64))
469
    fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
470
  else
471
    fprintf (file,
472
             TARGET_AS100_SYNTAX
473
             ? "0%" HOST_WIDE_INT_PRINT "xH" : HOST_WIDE_INT_PRINT_HEX,
474
             val);
475
}
476
 
477
static bool
478
rx_assemble_integer (rtx x, unsigned int size, int is_aligned)
479
{
480
  const char *  op = integer_asm_op (size, is_aligned);
481
 
482
  if (! CONST_INT_P (x))
483
    return default_assemble_integer (x, size, is_aligned);
484
 
485
  if (op == NULL)
486
    return false;
487
  fputs (op, asm_out_file);
488
 
489
  rx_print_integer (asm_out_file, INTVAL (x));
490
  fputc ('\n', asm_out_file);
491
  return true;
492
}
493
 
494
 
495
/* Handles the insertion of a single operand into the assembler output.
496
   The %<letter> directives supported are:
497
 
498
     %A  Print an operand without a leading # character.
499
     %B  Print an integer comparison name.
500
     %C  Print a control register name.
501
     %F  Print a condition code flag name.
502
     %G  Register used for small-data-area addressing
503
     %H  Print high part of a DImode register, integer or address.
504
     %L  Print low part of a DImode register, integer or address.
505
     %N  Print the negation of the immediate value.
506
     %P  Register used for PID addressing
507
     %Q  If the operand is a MEM, then correctly generate
508
         register indirect or register relative addressing.
509
     %R  Like %Q but for zero-extending loads.  */
510
 
511
static void
512
rx_print_operand (FILE * file, rtx op, int letter)
513
{
514
  bool unsigned_load = false;
515
  bool print_hash = true;
516
 
517
  if (letter == 'A'
518
      && ((GET_CODE (op) == CONST
519
           && GET_CODE (XEXP (op, 0)) == UNSPEC)
520
          || GET_CODE (op) == UNSPEC))
521
    {
522
      print_hash = false;
523
      letter = 0;
524
    }
525
 
526
  switch (letter)
527
    {
528
    case 'A':
529
      /* Print an operand without a leading #.  */
530
      if (MEM_P (op))
531
        op = XEXP (op, 0);
532
 
533
      switch (GET_CODE (op))
534
        {
535
        case LABEL_REF:
536
        case SYMBOL_REF:
537
          output_addr_const (file, op);
538
          break;
539
        case CONST_INT:
540
          fprintf (file, "%ld", (long) INTVAL (op));
541
          break;
542
        default:
543
          rx_print_operand (file, op, 0);
544
          break;
545
        }
546
      break;
547
 
548
    case 'B':
549
      {
550
        enum rtx_code code = GET_CODE (op);
551
        enum machine_mode mode = GET_MODE (XEXP (op, 0));
552
        const char *ret;
553
 
554
        if (mode == CC_Fmode)
555
          {
556
            /* C flag is undefined, and O flag carries unordered.  None of the
557
               branch combinations that include O use it helpfully.  */
558
            switch (code)
559
              {
560
              case ORDERED:
561
                ret = "no";
562
                break;
563
              case UNORDERED:
564
                ret = "o";
565
                break;
566
              case LT:
567
                ret = "n";
568
                break;
569
              case GE:
570
                ret = "pz";
571
                break;
572
              case EQ:
573
                ret = "eq";
574
                break;
575
              case NE:
576
                ret = "ne";
577
                break;
578
              default:
579
                gcc_unreachable ();
580
              }
581
          }
582
        else
583
          {
584
            unsigned int flags = flags_from_mode (mode);
585
 
586
            switch (code)
587
              {
588
              case LT:
589
                ret = (flags & CC_FLAG_O ? "lt" : "n");
590
                break;
591
              case GE:
592
                ret = (flags & CC_FLAG_O ? "ge" : "pz");
593
                break;
594
              case GT:
595
                ret = "gt";
596
                break;
597
              case LE:
598
                ret = "le";
599
                break;
600
              case GEU:
601
                ret = "geu";
602
                break;
603
              case LTU:
604
                ret = "ltu";
605
                break;
606
              case GTU:
607
                ret = "gtu";
608
                break;
609
              case LEU:
610
                ret = "leu";
611
                break;
612
              case EQ:
613
                ret = "eq";
614
                break;
615
              case NE:
616
                ret = "ne";
617
                break;
618
              default:
619
                gcc_unreachable ();
620
              }
621
            gcc_checking_assert ((flags_from_code (code) & ~flags) == 0);
622
          }
623
        fputs (ret, file);
624
        break;
625
      }
626
 
627
    case 'C':
628
      gcc_assert (CONST_INT_P (op));
629
      switch (INTVAL (op))
630
        {
631
        case 0:   fprintf (file, "psw"); break;
632
        case 2:   fprintf (file, "usp"); break;
633
        case 3:   fprintf (file, "fpsw"); break;
634
        case 4:   fprintf (file, "cpen"); break;
635
        case 8:   fprintf (file, "bpsw"); break;
636
        case 9:   fprintf (file, "bpc"); break;
637
        case 0xa: fprintf (file, "isp"); break;
638
        case 0xb: fprintf (file, "fintv"); break;
639
        case 0xc: fprintf (file, "intb"); break;
640
        default:
641
          warning (0, "unrecognized control register number: %d - using 'psw'",
642
                   (int) INTVAL (op));
643
          fprintf (file, "psw");
644
          break;
645
        }
646
      break;
647
 
648
    case 'F':
649
      gcc_assert (CONST_INT_P (op));
650
      switch (INTVAL (op))
651
        {
652
        case 0: case 'c': case 'C': fprintf (file, "C"); break;
653
        case 1: case 'z': case 'Z': fprintf (file, "Z"); break;
654
        case 2: case 's': case 'S': fprintf (file, "S"); break;
655
        case 3: case 'o': case 'O': fprintf (file, "O"); break;
656
        case 8: case 'i': case 'I': fprintf (file, "I"); break;
657
        case 9: case 'u': case 'U': fprintf (file, "U"); break;
658
        default:
659
          gcc_unreachable ();
660
        }
661
      break;
662
 
663
    case 'G':
664
      fprintf (file, "%s", reg_names [rx_gp_base_regnum ()]);
665
      break;
666
 
667
    case 'H':
668
      switch (GET_CODE (op))
669
        {
670
        case REG:
671
          fprintf (file, "%s", reg_names [REGNO (op) + (WORDS_BIG_ENDIAN ? 0 : 1)]);
672
          break;
673
        case CONST_INT:
674
          {
675
            HOST_WIDE_INT v = INTVAL (op);
676
 
677
            fprintf (file, "#");
678
            /* Trickery to avoid problems with shifting 32 bits at a time.  */
679
            v = v >> 16;
680
            v = v >> 16;
681
            rx_print_integer (file, v);
682
            break;
683
          }
684
        case CONST_DOUBLE:
685
          fprintf (file, "#");
686
          rx_print_integer (file, CONST_DOUBLE_HIGH (op));
687
          break;
688
        case MEM:
689
          if (! WORDS_BIG_ENDIAN)
690
            op = adjust_address (op, SImode, 4);
691
          output_address (XEXP (op, 0));
692
          break;
693
        default:
694
          gcc_unreachable ();
695
        }
696
      break;
697
 
698
    case 'L':
699
      switch (GET_CODE (op))
700
        {
701
        case REG:
702
          fprintf (file, "%s", reg_names [REGNO (op) + (WORDS_BIG_ENDIAN ? 1 : 0)]);
703
          break;
704
        case CONST_INT:
705
          fprintf (file, "#");
706
          rx_print_integer (file, INTVAL (op) & 0xffffffff);
707
          break;
708
        case CONST_DOUBLE:
709
          fprintf (file, "#");
710
          rx_print_integer (file, CONST_DOUBLE_LOW (op));
711
          break;
712
        case MEM:
713
          if (WORDS_BIG_ENDIAN)
714
            op = adjust_address (op, SImode, 4);
715
          output_address (XEXP (op, 0));
716
          break;
717
        default:
718
          gcc_unreachable ();
719
        }
720
      break;
721
 
722
    case 'N':
723
      gcc_assert (CONST_INT_P (op));
724
      fprintf (file, "#");
725
      rx_print_integer (file, - INTVAL (op));
726
      break;
727
 
728
    case 'P':
729
      fprintf (file, "%s", reg_names [rx_pid_base_regnum ()]);
730
      break;
731
 
732
    case 'R':
733
      gcc_assert (GET_MODE_SIZE (GET_MODE (op)) < 4);
734
      unsigned_load = true;
735
      /* Fall through.  */
736
    case 'Q':
737
      if (MEM_P (op))
738
        {
739
          HOST_WIDE_INT offset;
740
          rtx mem = op;
741
 
742
          op = XEXP (op, 0);
743
 
744
          if (REG_P (op))
745
            offset = 0;
746
          else if (GET_CODE (op) == PLUS)
747
            {
748
              rtx displacement;
749
 
750
              if (REG_P (XEXP (op, 0)))
751
                {
752
                  displacement = XEXP (op, 1);
753
                  op = XEXP (op, 0);
754
                }
755
              else
756
                {
757
                  displacement = XEXP (op, 0);
758
                  op = XEXP (op, 1);
759
                  gcc_assert (REG_P (op));
760
                }
761
 
762
              gcc_assert (CONST_INT_P (displacement));
763
              offset = INTVAL (displacement);
764
              gcc_assert (offset >= 0);
765
 
766
              fprintf (file, "%ld", offset);
767
            }
768
          else
769
            gcc_unreachable ();
770
 
771
          fprintf (file, "[");
772
          rx_print_operand (file, op, 0);
773
          fprintf (file, "].");
774
 
775
          switch (GET_MODE_SIZE (GET_MODE (mem)))
776
            {
777
            case 1:
778
              gcc_assert (offset <= 65535 * 1);
779
              fprintf (file, unsigned_load ? "UB" : "B");
780
              break;
781
            case 2:
782
              gcc_assert (offset % 2 == 0);
783
              gcc_assert (offset <= 65535 * 2);
784
              fprintf (file, unsigned_load ? "UW" : "W");
785
              break;
786
            case 4:
787
              gcc_assert (offset % 4 == 0);
788
              gcc_assert (offset <= 65535 * 4);
789
              fprintf (file, "L");
790
              break;
791
            default:
792
              gcc_unreachable ();
793
            }
794
          break;
795
        }
796
 
797
      /* Fall through.  */
798
 
799
    default:
800
      if (GET_CODE (op) == CONST
801
          && GET_CODE (XEXP (op, 0)) == UNSPEC)
802
        op = XEXP (op, 0);
803
      else if (GET_CODE (op) == CONST
804
               && GET_CODE (XEXP (op, 0)) == PLUS
805
               && GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC
806
               && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
807
        {
808
          if (print_hash)
809
            fprintf (file, "#");
810
          fprintf (file, "(");
811
          rx_print_operand (file, XEXP (XEXP (op, 0), 0), 'A');
812
          fprintf (file, " + ");
813
          output_addr_const (file, XEXP (XEXP (op, 0), 1));
814
          fprintf (file, ")");
815
          return;
816
        }
817
 
818
      switch (GET_CODE (op))
819
        {
820
        case MULT:
821
          /* Should be the scaled part of an
822
             indexed register indirect address.  */
823
          {
824
            rtx base = XEXP (op, 0);
825
            rtx index = XEXP (op, 1);
826
 
827
            /* Check for a swaped index register and scaling factor.
828
               Not sure if this can happen, but be prepared to handle it.  */
829
            if (CONST_INT_P (base) && REG_P (index))
830
              {
831
                rtx tmp = base;
832
                base = index;
833
                index = tmp;
834
              }
835
 
836
            gcc_assert (REG_P (base));
837
            gcc_assert (REGNO (base) < FIRST_PSEUDO_REGISTER);
838
            gcc_assert (CONST_INT_P (index));
839
            /* Do not try to verify the value of the scalar as it is based
840
               on the mode of the MEM not the mode of the MULT.  (Which
841
               will always be SImode).  */
842
            fprintf (file, "%s", reg_names [REGNO (base)]);
843
            break;
844
          }
845
 
846
        case MEM:
847
          output_address (XEXP (op, 0));
848
          break;
849
 
850
        case PLUS:
851
          output_address (op);
852
          break;
853
 
854
        case REG:
855
          gcc_assert (REGNO (op) < FIRST_PSEUDO_REGISTER);
856
          fprintf (file, "%s", reg_names [REGNO (op)]);
857
          break;
858
 
859
        case SUBREG:
860
          gcc_assert (subreg_regno (op) < FIRST_PSEUDO_REGISTER);
861
          fprintf (file, "%s", reg_names [subreg_regno (op)]);
862
          break;
863
 
864
          /* This will only be single precision....  */
865
        case CONST_DOUBLE:
866
          {
867
            unsigned long val;
868
            REAL_VALUE_TYPE rv;
869
 
870
            REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
871
            REAL_VALUE_TO_TARGET_SINGLE (rv, val);
872
            if (print_hash)
873
              fprintf (file, "#");
874
            fprintf (file, TARGET_AS100_SYNTAX ? "0%lxH" : "0x%lx", val);
875
            break;
876
          }
877
 
878
        case CONST_INT:
879
          if (print_hash)
880
            fprintf (file, "#");
881
          rx_print_integer (file, INTVAL (op));
882
          break;
883
 
884
        case UNSPEC:
885
          switch (XINT (op, 1))
886
            {
887
            case UNSPEC_PID_ADDR:
888
              {
889
                rtx sym, add;
890
 
891
                if (print_hash)
892
                  fprintf (file, "#");
893
                sym = XVECEXP (op, 0, 0);
894
                add = NULL_RTX;
895
                fprintf (file, "(");
896
                if (GET_CODE (sym) == PLUS)
897
                  {
898
                    add = XEXP (sym, 1);
899
                    sym = XEXP (sym, 0);
900
                  }
901
                output_addr_const (file, sym);
902
                if (add != NULL_RTX)
903
                  {
904
                    fprintf (file, "+");
905
                    output_addr_const (file, add);
906
                  }
907
                fprintf (file, "-__pid_base");
908
                fprintf (file, ")");
909
                return;
910
              }
911
            }
912
          /* Fall through */
913
 
914
        case CONST:
915
        case SYMBOL_REF:
916
        case LABEL_REF:
917
        case CODE_LABEL:
918
          rx_print_operand_address (file, op);
919
          break;
920
 
921
        default:
922
          gcc_unreachable ();
923
        }
924
      break;
925
    }
926
}
927
 
928
/* Maybe convert an operand into its PID format.  */
929
 
930
rtx
931
rx_maybe_pidify_operand (rtx op, int copy_to_reg)
932
{
933
  if (rx_pid_data_operand (op) == PID_UNENCODED)
934
    {
935
      if (GET_CODE (op) == MEM)
936
        {
937
          rtx a = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), XEXP (op, 0));
938
          op = replace_equiv_address (op, a);
939
        }
940
      else
941
        {
942
          op = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), op);
943
        }
944
 
945
      if (copy_to_reg)
946
        op = copy_to_mode_reg (GET_MODE (op), op);
947
    }
948
  return op;
949
}
950
 
951
/* Returns an assembler template for a move instruction.  */
952
 
953
char *
954
rx_gen_move_template (rtx * operands, bool is_movu)
955
{
956
  static char  out_template [64];
957
  const char * extension = TARGET_AS100_SYNTAX ? ".L" : "";
958
  const char * src_template;
959
  const char * dst_template;
960
  rtx          dest = operands[0];
961
  rtx          src  = operands[1];
962
 
963
  /* Decide which extension, if any, should be given to the move instruction.  */
964
  switch (CONST_INT_P (src) ? GET_MODE (dest) : GET_MODE (src))
965
    {
966
    case QImode:
967
      /* The .B extension is not valid when
968
         loading an immediate into a register.  */
969
      if (! REG_P (dest) || ! CONST_INT_P (src))
970
        extension = ".B";
971
      break;
972
    case HImode:
973
      if (! REG_P (dest) || ! CONST_INT_P (src))
974
        /* The .W extension is not valid when
975
           loading an immediate into a register.  */
976
        extension = ".W";
977
      break;
978
    case SFmode:
979
    case SImode:
980
      extension = ".L";
981
      break;
982
    case VOIDmode:
983
      /* This mode is used by constants.  */
984
      break;
985
    default:
986
      debug_rtx (src);
987
      gcc_unreachable ();
988
    }
989
 
990
  if (MEM_P (src) && rx_pid_data_operand (XEXP (src, 0)) == PID_UNENCODED)
991
    src_template = "(%A1-__pid_base)[%P1]";
992
  else if (MEM_P (src) && rx_small_data_operand (XEXP (src, 0)))
993
    src_template = "%%gp(%A1)[%G1]";
994
  else
995
    src_template = "%1";
996
 
997
  if (MEM_P (dest) && rx_small_data_operand (XEXP (dest, 0)))
998
    dst_template = "%%gp(%A0)[%G0]";
999
  else
1000
    dst_template = "%0";
1001
 
1002
  sprintf (out_template, "%s%s\t%s, %s", is_movu ? "movu" : "mov",
1003
           extension, src_template, dst_template);
1004
  return out_template;
1005
}
1006
 
1007
/* Return VALUE rounded up to the next ALIGNMENT boundary.  */
1008
 
1009
static inline unsigned int
1010
rx_round_up (unsigned int value, unsigned int alignment)
1011
{
1012
  alignment -= 1;
1013
  return (value + alignment) & (~ alignment);
1014
}
1015
 
1016
/* Return the number of bytes in the argument registers
1017
   occupied by an argument of type TYPE and mode MODE.  */
1018
 
1019
static unsigned int
1020
rx_function_arg_size (enum machine_mode mode, const_tree type)
1021
{
1022
  unsigned int num_bytes;
1023
 
1024
  num_bytes = (mode == BLKmode)
1025
    ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1026
  return rx_round_up (num_bytes, UNITS_PER_WORD);
1027
}
1028
 
1029
#define NUM_ARG_REGS            4
1030
#define MAX_NUM_ARG_BYTES       (NUM_ARG_REGS * UNITS_PER_WORD)
1031
 
1032
/* Return an RTL expression describing the register holding a function
1033
   parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1034
   be passed on the stack.  CUM describes the previous parameters to the
1035
   function and NAMED is false if the parameter is part of a variable
1036
   parameter list, or the last named parameter before the start of a
1037
   variable parameter list.  */
1038
 
1039
static rtx
1040
rx_function_arg (cumulative_args_t cum, enum machine_mode mode,
1041
                 const_tree type, bool named)
1042
{
1043
  unsigned int next_reg;
1044
  unsigned int bytes_so_far = *get_cumulative_args (cum);
1045
  unsigned int size;
1046
  unsigned int rounded_size;
1047
 
1048
  /* An exploded version of rx_function_arg_size.  */
1049
  size = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1050
  /* If the size is not known it cannot be passed in registers.  */
1051
  if (size < 1)
1052
    return NULL_RTX;
1053
 
1054
  rounded_size = rx_round_up (size, UNITS_PER_WORD);
1055
 
1056
  /* Don't pass this arg via registers if there
1057
     are insufficient registers to hold all of it.  */
1058
  if (rounded_size + bytes_so_far > MAX_NUM_ARG_BYTES)
1059
    return NULL_RTX;
1060
 
1061
  /* Unnamed arguments and the last named argument in a
1062
     variadic function are always passed on the stack.  */
1063
  if (!named)
1064
    return NULL_RTX;
1065
 
1066
  /* Structures must occupy an exact number of registers,
1067
     otherwise they are passed on the stack.  */
1068
  if ((type == NULL || AGGREGATE_TYPE_P (type))
1069
      && (size % UNITS_PER_WORD) != 0)
1070
    return NULL_RTX;
1071
 
1072
  next_reg = (bytes_so_far / UNITS_PER_WORD) + 1;
1073
 
1074
  return gen_rtx_REG (mode, next_reg);
1075
}
1076
 
1077
static void
1078
rx_function_arg_advance (cumulative_args_t cum, enum machine_mode mode,
1079
                         const_tree type, bool named ATTRIBUTE_UNUSED)
1080
{
1081
  *get_cumulative_args (cum) += rx_function_arg_size (mode, type);
1082
}
1083
 
1084
static unsigned int
1085
rx_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
1086
                          const_tree type ATTRIBUTE_UNUSED)
1087
{
1088
  return 32;
1089
}
1090
 
1091
/* Return an RTL describing where a function return value of type RET_TYPE
1092
   is held.  */
1093
 
1094
static rtx
1095
rx_function_value (const_tree ret_type,
1096
                   const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1097
                   bool       outgoing ATTRIBUTE_UNUSED)
1098
{
1099
  enum machine_mode mode = TYPE_MODE (ret_type);
1100
 
1101
  /* RX ABI specifies that small integer types are
1102
     promoted to int when returned by a function.  */
1103
  if (GET_MODE_SIZE (mode) > 0
1104
      && GET_MODE_SIZE (mode) < 4
1105
      && ! COMPLEX_MODE_P (mode)
1106
      )
1107
    return gen_rtx_REG (SImode, FUNC_RETURN_REGNUM);
1108
 
1109
  return gen_rtx_REG (mode, FUNC_RETURN_REGNUM);
1110
}
1111
 
1112
/* TARGET_PROMOTE_FUNCTION_MODE must behave in the same way with
1113
   regard to function returns as does TARGET_FUNCTION_VALUE.  */
1114
 
1115
static enum machine_mode
1116
rx_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
1117
                          enum machine_mode mode,
1118
                          int * punsignedp ATTRIBUTE_UNUSED,
1119
                          const_tree funtype ATTRIBUTE_UNUSED,
1120
                          int for_return)
1121
{
1122
  if (for_return != 1
1123
      || GET_MODE_SIZE (mode) >= 4
1124
      || COMPLEX_MODE_P (mode)
1125
      || GET_MODE_SIZE (mode) < 1)
1126
    return mode;
1127
 
1128
  return SImode;
1129
}
1130
 
1131
static bool
1132
rx_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1133
{
1134
  HOST_WIDE_INT size;
1135
 
1136
  if (TYPE_MODE (type) != BLKmode
1137
      && ! AGGREGATE_TYPE_P (type))
1138
    return false;
1139
 
1140
  size = int_size_in_bytes (type);
1141
  /* Large structs and those whose size is not an
1142
     exact multiple of 4 are returned in memory.  */
1143
  return size < 1
1144
    || size > 16
1145
    || (size % UNITS_PER_WORD) != 0;
1146
}
1147
 
1148
static rtx
1149
rx_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED,
1150
                     int incoming ATTRIBUTE_UNUSED)
1151
{
1152
  return gen_rtx_REG (Pmode, STRUCT_VAL_REGNUM);
1153
}
1154
 
1155
static bool
1156
rx_return_in_msb (const_tree valtype)
1157
{
1158
  return TARGET_BIG_ENDIAN_DATA
1159
    && (AGGREGATE_TYPE_P (valtype) || TREE_CODE (valtype) == COMPLEX_TYPE);
1160
}
1161
 
1162
/* Returns true if the provided function has the specified attribute.  */
1163
 
1164
static inline bool
1165
has_func_attr (const_tree decl, const char * func_attr)
1166
{
1167
  if (decl == NULL_TREE)
1168
    decl = current_function_decl;
1169
 
1170
  return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
1171
}
1172
 
1173
/* Returns true if the provided function has the "fast_interrupt" attribute.  */
1174
 
1175
static inline bool
1176
is_fast_interrupt_func (const_tree decl)
1177
{
1178
  return has_func_attr (decl, "fast_interrupt");
1179
}
1180
 
1181
/* Returns true if the provided function has the "interrupt" attribute.  */
1182
 
1183
static inline bool
1184
is_interrupt_func (const_tree decl)
1185
{
1186
  return has_func_attr (decl, "interrupt");
1187
}
1188
 
1189
/* Returns true if the provided function has the "naked" attribute.  */
1190
 
1191
static inline bool
1192
is_naked_func (const_tree decl)
1193
{
1194
  return has_func_attr (decl, "naked");
1195
}
1196
 
1197
static bool use_fixed_regs = false;
1198
 
1199
static void
1200
rx_conditional_register_usage (void)
1201
{
1202
  static bool using_fixed_regs = false;
1203
 
1204
  if (TARGET_PID)
1205
    {
1206
      rx_pid_base_regnum_val = GP_BASE_REGNUM - rx_num_interrupt_regs;
1207
      fixed_regs[rx_pid_base_regnum_val] = call_used_regs [rx_pid_base_regnum_val] = 1;
1208
    }
1209
 
1210
  if (rx_small_data_limit > 0)
1211
    {
1212
      if (TARGET_PID)
1213
        rx_gp_base_regnum_val = rx_pid_base_regnum_val - 1;
1214
      else
1215
        rx_gp_base_regnum_val = GP_BASE_REGNUM - rx_num_interrupt_regs;
1216
 
1217
      fixed_regs[rx_gp_base_regnum_val] = call_used_regs [rx_gp_base_regnum_val] = 1;
1218
    }
1219
 
1220
  if (use_fixed_regs != using_fixed_regs)
1221
    {
1222
      static char saved_fixed_regs[FIRST_PSEUDO_REGISTER];
1223
      static char saved_call_used_regs[FIRST_PSEUDO_REGISTER];
1224
 
1225
      if (use_fixed_regs)
1226
        {
1227
          unsigned int r;
1228
 
1229
          memcpy (saved_fixed_regs, fixed_regs, sizeof fixed_regs);
1230
          memcpy (saved_call_used_regs, call_used_regs, sizeof call_used_regs);
1231
 
1232
          /* This is for fast interrupt handlers.  Any register in
1233
             the range r10 to r13 (inclusive) that is currently
1234
             marked as fixed is now a viable, call-used register.  */
1235
          for (r = 10; r <= 13; r++)
1236
            if (fixed_regs[r])
1237
              {
1238
                fixed_regs[r] = 0;
1239
                call_used_regs[r] = 1;
1240
              }
1241
 
1242
          /* Mark r7 as fixed.  This is just a hack to avoid
1243
             altering the reg_alloc_order array so that the newly
1244
             freed r10-r13 registers are the preferred registers.  */
1245
          fixed_regs[7] = call_used_regs[7] = 1;
1246
        }
1247
      else
1248
        {
1249
          /* Restore the normal register masks.  */
1250
          memcpy (fixed_regs, saved_fixed_regs, sizeof fixed_regs);
1251
          memcpy (call_used_regs, saved_call_used_regs, sizeof call_used_regs);
1252
        }
1253
 
1254
      using_fixed_regs = use_fixed_regs;
1255
    }
1256
}
1257
 
1258
/* Perform any actions necessary before starting to compile FNDECL.
1259
   For the RX we use this to make sure that we have the correct
1260
   set of register masks selected.  If FNDECL is NULL then we are
1261
   compiling top level things.  */
1262
 
1263
static void
1264
rx_set_current_function (tree fndecl)
1265
{
1266
  /* Remember the last target of rx_set_current_function.  */
1267
  static tree rx_previous_fndecl;
1268
  bool prev_was_fast_interrupt;
1269
  bool current_is_fast_interrupt;
1270
 
1271
  /* Only change the context if the function changes.  This hook is called
1272
     several times in the course of compiling a function, and we don't want
1273
     to slow things down too much or call target_reinit when it isn't safe.  */
1274
  if (fndecl == rx_previous_fndecl)
1275
    return;
1276
 
1277
  prev_was_fast_interrupt
1278
    = rx_previous_fndecl
1279
    ? is_fast_interrupt_func (rx_previous_fndecl) : false;
1280
 
1281
  current_is_fast_interrupt
1282
    = fndecl ? is_fast_interrupt_func (fndecl) : false;
1283
 
1284
  if (prev_was_fast_interrupt != current_is_fast_interrupt)
1285
    {
1286
      use_fixed_regs = current_is_fast_interrupt;
1287
      target_reinit ();
1288
    }
1289
 
1290
  rx_previous_fndecl = fndecl;
1291
}
1292
 
1293
/* Typical stack layout should looks like this after the function's prologue:
1294
 
1295
                            |    |
1296
                              --                       ^
1297
                            |    | \                   |
1298
                            |    |   arguments saved   | Increasing
1299
                            |    |   on the stack      |  addresses
1300
    PARENT   arg pointer -> |    | /
1301
  -------------------------- ---- -------------------
1302
    CHILD                   |ret |   return address
1303
                              --
1304
                            |    | \
1305
                            |    |   call saved
1306
                            |    |   registers
1307
                            |    | /
1308
                              --
1309
                            |    | \
1310
                            |    |   local
1311
                            |    |   variables
1312
        frame pointer ->    |    | /
1313
                              --
1314
                            |    | \
1315
                            |    |   outgoing          | Decreasing
1316
                            |    |   arguments         |  addresses
1317
   current stack pointer -> |    | /                   |
1318
  -------------------------- ---- ------------------   V
1319
                            |    |                 */
1320
 
1321
static unsigned int
1322
bit_count (unsigned int x)
1323
{
1324
  const unsigned int m1 = 0x55555555;
1325
  const unsigned int m2 = 0x33333333;
1326
  const unsigned int m4 = 0x0f0f0f0f;
1327
 
1328
  x -= (x >> 1) & m1;
1329
  x = (x & m2) + ((x >> 2) & m2);
1330
  x = (x + (x >> 4)) & m4;
1331
  x += x >>  8;
1332
 
1333
  return (x + (x >> 16)) & 0x3f;
1334
}
1335
 
1336
#define MUST_SAVE_ACC_REGISTER                  \
1337
  (TARGET_SAVE_ACC_REGISTER                     \
1338
   && (is_interrupt_func (NULL_TREE)            \
1339
       || is_fast_interrupt_func (NULL_TREE)))
1340
 
1341
/* Returns either the lowest numbered and highest numbered registers that
1342
   occupy the call-saved area of the stack frame, if the registers are
1343
   stored as a contiguous block, or else a bitmask of the individual
1344
   registers if they are stored piecemeal.
1345
 
1346
   Also computes the size of the frame and the size of the outgoing
1347
   arguments block (in bytes).  */
1348
 
1349
static void
1350
rx_get_stack_layout (unsigned int * lowest,
1351
                     unsigned int * highest,
1352
                     unsigned int * register_mask,
1353
                     unsigned int * frame_size,
1354
                     unsigned int * stack_size)
1355
{
1356
  unsigned int reg;
1357
  unsigned int low;
1358
  unsigned int high;
1359
  unsigned int fixed_reg = 0;
1360
  unsigned int save_mask;
1361
  unsigned int pushed_mask;
1362
  unsigned int unneeded_pushes;
1363
 
1364
  if (is_naked_func (NULL_TREE))
1365
    {
1366
      /* Naked functions do not create their own stack frame.
1367
         Instead the programmer must do that for us.  */
1368
      * lowest = 0;
1369
      * highest = 0;
1370
      * register_mask = 0;
1371
      * frame_size = 0;
1372
      * stack_size = 0;
1373
      return;
1374
    }
1375
 
1376
  for (save_mask = high = low = 0, reg = 1; reg < CC_REGNUM; reg++)
1377
    {
1378
      if ((df_regs_ever_live_p (reg)
1379
           /* Always save all call clobbered registers inside non-leaf
1380
              interrupt handlers, even if they are not live - they may
1381
              be used in (non-interrupt aware) routines called from this one.  */
1382
           || (call_used_regs[reg]
1383
               && is_interrupt_func (NULL_TREE)
1384
               && ! current_function_is_leaf))
1385
          && (! call_used_regs[reg]
1386
              /* Even call clobbered registered must
1387
                 be pushed inside interrupt handlers.  */
1388
              || is_interrupt_func (NULL_TREE)
1389
              /* Likewise for fast interrupt handlers, except registers r10 -
1390
                 r13.  These are normally call-saved, but may have been set
1391
                 to call-used by rx_conditional_register_usage.  If so then
1392
                 they can be used in the fast interrupt handler without
1393
                 saving them on the stack.  */
1394
              || (is_fast_interrupt_func (NULL_TREE)
1395
                  && ! IN_RANGE (reg, 10, 13))))
1396
        {
1397
          if (low == 0)
1398
            low = reg;
1399
          high = reg;
1400
 
1401
          save_mask |= 1 << reg;
1402
        }
1403
 
1404
      /* Remember if we see a fixed register
1405
         after having found the low register.  */
1406
      if (low != 0 && fixed_reg == 0 && fixed_regs [reg])
1407
        fixed_reg = reg;
1408
    }
1409
 
1410
  /* If we have to save the accumulator register, make sure
1411
     that at least two registers are pushed into the frame.  */
1412
  if (MUST_SAVE_ACC_REGISTER
1413
      && bit_count (save_mask) < 2)
1414
    {
1415
      save_mask |= (1 << 13) | (1 << 14);
1416
      if (low == 0)
1417
        low = 13;
1418
      if (high == 0 || low == high)
1419
        high = low + 1;
1420
    }
1421
 
1422
  /* Decide if it would be faster fill in the call-saved area of the stack
1423
     frame using multiple PUSH instructions instead of a single PUSHM
1424
     instruction.
1425
 
1426
     SAVE_MASK is a bitmask of the registers that must be stored in the
1427
     call-save area.  PUSHED_MASK is a bitmask of the registers that would
1428
     be pushed into the area if we used a PUSHM instruction.  UNNEEDED_PUSHES
1429
     is a bitmask of those registers in pushed_mask that are not in
1430
     save_mask.
1431
 
1432
     We use a simple heuristic that says that it is better to use
1433
     multiple PUSH instructions if the number of unnecessary pushes is
1434
     greater than the number of necessary pushes.
1435
 
1436
     We also use multiple PUSH instructions if there are any fixed registers
1437
     between LOW and HIGH.  The only way that this can happen is if the user
1438
     has specified --fixed-<reg-name> on the command line and in such
1439
     circumstances we do not want to touch the fixed registers at all.
1440
 
1441
     FIXME: Is it worth improving this heuristic ?  */
1442
  pushed_mask = (-1 << low) & ~(-1 << (high + 1));
1443
  unneeded_pushes = (pushed_mask & (~ save_mask)) & pushed_mask;
1444
 
1445
  if ((fixed_reg && fixed_reg <= high)
1446
      || (optimize_function_for_speed_p (cfun)
1447
          && bit_count (save_mask) < bit_count (unneeded_pushes)))
1448
    {
1449
      /* Use multiple pushes.  */
1450
      * lowest = 0;
1451
      * highest = 0;
1452
      * register_mask = save_mask;
1453
    }
1454
  else
1455
    {
1456
      /* Use one push multiple instruction.  */
1457
      * lowest = low;
1458
      * highest = high;
1459
      * register_mask = 0;
1460
    }
1461
 
1462
  * frame_size = rx_round_up
1463
    (get_frame_size (), STACK_BOUNDARY / BITS_PER_UNIT);
1464
 
1465
  if (crtl->args.size > 0)
1466
    * frame_size += rx_round_up
1467
      (crtl->args.size, STACK_BOUNDARY / BITS_PER_UNIT);
1468
 
1469
  * stack_size = rx_round_up
1470
    (crtl->outgoing_args_size, STACK_BOUNDARY / BITS_PER_UNIT);
1471
}
1472
 
1473
/* Generate a PUSHM instruction that matches the given operands.  */
1474
 
1475
void
1476
rx_emit_stack_pushm (rtx * operands)
1477
{
1478
  HOST_WIDE_INT last_reg;
1479
  rtx first_push;
1480
 
1481
  gcc_assert (CONST_INT_P (operands[0]));
1482
  last_reg = (INTVAL (operands[0]) / UNITS_PER_WORD) - 1;
1483
 
1484
  gcc_assert (GET_CODE (operands[1]) == PARALLEL);
1485
  first_push = XVECEXP (operands[1], 0, 1);
1486
  gcc_assert (SET_P (first_push));
1487
  first_push = SET_SRC (first_push);
1488
  gcc_assert (REG_P (first_push));
1489
 
1490
  asm_fprintf (asm_out_file, "\tpushm\t%s-%s\n",
1491
               reg_names [REGNO (first_push) - last_reg],
1492
               reg_names [REGNO (first_push)]);
1493
}
1494
 
1495
/* Generate a PARALLEL that will pass the rx_store_multiple_vector predicate.  */
1496
 
1497
static rtx
1498
gen_rx_store_vector (unsigned int low, unsigned int high)
1499
{
1500
  unsigned int i;
1501
  unsigned int count = (high - low) + 2;
1502
  rtx vector;
1503
 
1504
  vector = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
1505
 
1506
  XVECEXP (vector, 0, 0) =
1507
    gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1508
                 gen_rtx_MINUS (SImode, stack_pointer_rtx,
1509
                                GEN_INT ((count - 1) * UNITS_PER_WORD)));
1510
 
1511
  for (i = 0; i < count - 1; i++)
1512
    XVECEXP (vector, 0, i + 1) =
1513
      gen_rtx_SET (VOIDmode,
1514
                   gen_rtx_MEM (SImode,
1515
                                gen_rtx_MINUS (SImode, stack_pointer_rtx,
1516
                                               GEN_INT ((i + 1) * UNITS_PER_WORD))),
1517
                   gen_rtx_REG (SImode, high - i));
1518
  return vector;
1519
}
1520
 
1521
/* Mark INSN as being frame related.  If it is a PARALLEL
1522
   then mark each element as being frame related as well.  */
1523
 
1524
static void
1525
mark_frame_related (rtx insn)
1526
{
1527
  RTX_FRAME_RELATED_P (insn) = 1;
1528
  insn = PATTERN (insn);
1529
 
1530
  if (GET_CODE (insn) == PARALLEL)
1531
    {
1532
      unsigned int i;
1533
 
1534
      for (i = 0; i < (unsigned) XVECLEN (insn, 0); i++)
1535
        RTX_FRAME_RELATED_P (XVECEXP (insn, 0, i)) = 1;
1536
    }
1537
}
1538
 
1539
static bool
1540
ok_for_max_constant (HOST_WIDE_INT val)
1541
{
1542
  if (rx_max_constant_size == 0  || rx_max_constant_size == 4)
1543
    /* If there is no constraint on the size of constants
1544
       used as operands, then any value is legitimate.  */
1545
    return true;
1546
 
1547
  /* rx_max_constant_size specifies the maximum number
1548
     of bytes that can be used to hold a signed value.  */
1549
  return IN_RANGE (val, (-1 << (rx_max_constant_size * 8)),
1550
                        ( 1 << (rx_max_constant_size * 8)));
1551
}
1552
 
1553
/* Generate an ADD of SRC plus VAL into DEST.
1554
   Handles the case where VAL is too big for max_constant_value.
1555
   Sets FRAME_RELATED_P on the insn if IS_FRAME_RELATED is true.  */
1556
 
1557
static void
1558
gen_safe_add (rtx dest, rtx src, rtx val, bool is_frame_related)
1559
{
1560
  rtx insn;
1561
 
1562
  if (val == NULL_RTX || INTVAL (val) == 0)
1563
    {
1564
      gcc_assert (dest != src);
1565
 
1566
      insn = emit_move_insn (dest, src);
1567
    }
1568
  else if (ok_for_max_constant (INTVAL (val)))
1569
    insn = emit_insn (gen_addsi3 (dest, src, val));
1570
  else
1571
    {
1572
      /* Wrap VAL in an UNSPEC so that rx_is_legitimate_constant
1573
         will not reject it.  */
1574
      val = gen_rtx_CONST (SImode, gen_rtx_UNSPEC (SImode, gen_rtvec (1, val), UNSPEC_CONST));
1575
      insn = emit_insn (gen_addsi3 (dest, src, val));
1576
 
1577
      if (is_frame_related)
1578
        /* We have to provide our own frame related note here
1579
           as the dwarf2out code cannot be expected to grok
1580
           our unspec.  */
1581
        add_reg_note (insn, REG_FRAME_RELATED_EXPR,
1582
                      gen_rtx_SET (SImode, dest,
1583
                                   gen_rtx_PLUS (SImode, src, val)));
1584
      return;
1585
    }
1586
 
1587
  if (is_frame_related)
1588
    RTX_FRAME_RELATED_P (insn) = 1;
1589
  return;
1590
}
1591
 
1592
void
1593
rx_expand_prologue (void)
1594
{
1595
  unsigned int stack_size;
1596
  unsigned int frame_size;
1597
  unsigned int mask;
1598
  unsigned int low;
1599
  unsigned int high;
1600
  unsigned int reg;
1601
  rtx insn;
1602
 
1603
  /* Naked functions use their own, programmer provided prologues.  */
1604
  if (is_naked_func (NULL_TREE))
1605
    return;
1606
 
1607
  rx_get_stack_layout (& low, & high, & mask, & frame_size, & stack_size);
1608
 
1609
  /* If we use any of the callee-saved registers, save them now.  */
1610
  if (mask)
1611
    {
1612
      /* Push registers in reverse order.  */
1613
      for (reg = CC_REGNUM; reg --;)
1614
        if (mask & (1 << reg))
1615
          {
1616
            insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, reg)));
1617
            mark_frame_related (insn);
1618
          }
1619
    }
1620
  else if (low)
1621
    {
1622
      if (high == low)
1623
        insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, low)));
1624
      else
1625
        insn = emit_insn (gen_stack_pushm (GEN_INT (((high - low) + 1)
1626
                                                    * UNITS_PER_WORD),
1627
                                           gen_rx_store_vector (low, high)));
1628
      mark_frame_related (insn);
1629
    }
1630
 
1631
  if (MUST_SAVE_ACC_REGISTER)
1632
    {
1633
      unsigned int acc_high, acc_low;
1634
 
1635
      /* Interrupt handlers have to preserve the accumulator
1636
         register if so requested by the user.  Use the first
1637
         two pushed registers as intermediaries.  */
1638
      if (mask)
1639
        {
1640
          acc_low = acc_high = 0;
1641
 
1642
          for (reg = 1; reg < CC_REGNUM; reg ++)
1643
            if (mask & (1 << reg))
1644
              {
1645
                if (acc_low == 0)
1646
                  acc_low = reg;
1647
                else
1648
                  {
1649
                    acc_high = reg;
1650
                    break;
1651
                  }
1652
              }
1653
 
1654
          /* We have assumed that there are at least two registers pushed... */
1655
          gcc_assert (acc_high != 0);
1656
 
1657
          /* Note - the bottom 16 bits of the accumulator are inaccessible.
1658
             We just assume that they are zero.  */
1659
          emit_insn (gen_mvfacmi (gen_rtx_REG (SImode, acc_low)));
1660
          emit_insn (gen_mvfachi (gen_rtx_REG (SImode, acc_high)));
1661
          emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_low)));
1662
          emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_high)));
1663
        }
1664
      else
1665
        {
1666
          acc_low = low;
1667
          acc_high = low + 1;
1668
 
1669
          /* We have assumed that there are at least two registers pushed... */
1670
          gcc_assert (acc_high <= high);
1671
 
1672
          emit_insn (gen_mvfacmi (gen_rtx_REG (SImode, acc_low)));
1673
          emit_insn (gen_mvfachi (gen_rtx_REG (SImode, acc_high)));
1674
          emit_insn (gen_stack_pushm (GEN_INT (2 * UNITS_PER_WORD),
1675
                                      gen_rx_store_vector (acc_low, acc_high)));
1676
        }
1677
    }
1678
 
1679
  /* If needed, set up the frame pointer.  */
1680
  if (frame_pointer_needed)
1681
    gen_safe_add (frame_pointer_rtx, stack_pointer_rtx,
1682
                  GEN_INT (- (HOST_WIDE_INT) frame_size), true);
1683
 
1684
  /* Allocate space for the outgoing args.
1685
     If the stack frame has not already been set up then handle this as well.  */
1686
  if (stack_size)
1687
    {
1688
      if (frame_size)
1689
        {
1690
          if (frame_pointer_needed)
1691
            gen_safe_add (stack_pointer_rtx, frame_pointer_rtx,
1692
                          GEN_INT (- (HOST_WIDE_INT) stack_size), true);
1693
          else
1694
            gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
1695
                          GEN_INT (- (HOST_WIDE_INT) (frame_size + stack_size)),
1696
                          true);
1697
        }
1698
      else
1699
        gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
1700
                      GEN_INT (- (HOST_WIDE_INT) stack_size), true);
1701
    }
1702
  else if (frame_size)
1703
    {
1704
      if (! frame_pointer_needed)
1705
        gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
1706
                      GEN_INT (- (HOST_WIDE_INT) frame_size), true);
1707
      else
1708
        gen_safe_add (stack_pointer_rtx, frame_pointer_rtx, NULL_RTX,
1709
                      true);
1710
    }
1711
}
1712
 
1713
static void
1714
rx_output_function_prologue (FILE * file,
1715
                             HOST_WIDE_INT frame_size ATTRIBUTE_UNUSED)
1716
{
1717
  if (is_fast_interrupt_func (NULL_TREE))
1718
    asm_fprintf (file, "\t; Note: Fast Interrupt Handler\n");
1719
 
1720
  if (is_interrupt_func (NULL_TREE))
1721
    asm_fprintf (file, "\t; Note: Interrupt Handler\n");
1722
 
1723
  if (is_naked_func (NULL_TREE))
1724
    asm_fprintf (file, "\t; Note: Naked Function\n");
1725
 
1726
  if (cfun->static_chain_decl != NULL)
1727
    asm_fprintf (file, "\t; Note: Nested function declared "
1728
                 "inside another function.\n");
1729
 
1730
  if (crtl->calls_eh_return)
1731
    asm_fprintf (file, "\t; Note: Calls __builtin_eh_return.\n");
1732
}
1733
 
1734
/* Generate a POPM or RTSD instruction that matches the given operands.  */
1735
 
1736
void
1737
rx_emit_stack_popm (rtx * operands, bool is_popm)
1738
{
1739
  HOST_WIDE_INT stack_adjust;
1740
  HOST_WIDE_INT last_reg;
1741
  rtx first_push;
1742
 
1743
  gcc_assert (CONST_INT_P (operands[0]));
1744
  stack_adjust = INTVAL (operands[0]);
1745
 
1746
  gcc_assert (GET_CODE (operands[1]) == PARALLEL);
1747
  last_reg = XVECLEN (operands[1], 0) - (is_popm ? 2 : 3);
1748
 
1749
  first_push = XVECEXP (operands[1], 0, 1);
1750
  gcc_assert (SET_P (first_push));
1751
  first_push = SET_DEST (first_push);
1752
  gcc_assert (REG_P (first_push));
1753
 
1754
  if (is_popm)
1755
    asm_fprintf (asm_out_file, "\tpopm\t%s-%s\n",
1756
                 reg_names [REGNO (first_push)],
1757
                 reg_names [REGNO (first_push) + last_reg]);
1758
  else
1759
    asm_fprintf (asm_out_file, "\trtsd\t#%d, %s-%s\n",
1760
                 (int) stack_adjust,
1761
                 reg_names [REGNO (first_push)],
1762
                 reg_names [REGNO (first_push) + last_reg]);
1763
}
1764
 
1765
/* Generate a PARALLEL which will satisfy the rx_rtsd_vector predicate.  */
1766
 
1767
static rtx
1768
gen_rx_rtsd_vector (unsigned int adjust, unsigned int low, unsigned int high)
1769
{
1770
  unsigned int i;
1771
  unsigned int bias = 3;
1772
  unsigned int count = (high - low) + bias;
1773
  rtx vector;
1774
 
1775
  vector = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
1776
 
1777
  XVECEXP (vector, 0, 0) =
1778
    gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1779
                 plus_constant (stack_pointer_rtx, adjust));
1780
 
1781
  for (i = 0; i < count - 2; i++)
1782
    XVECEXP (vector, 0, i + 1) =
1783
      gen_rtx_SET (VOIDmode,
1784
                   gen_rtx_REG (SImode, low + i),
1785
                   gen_rtx_MEM (SImode,
1786
                                i == 0 ? stack_pointer_rtx
1787
                                : plus_constant (stack_pointer_rtx,
1788
                                                 i * UNITS_PER_WORD)));
1789
 
1790
  XVECEXP (vector, 0, count - 1) = ret_rtx;
1791
 
1792
  return vector;
1793
}
1794
 
1795
/* Generate a PARALLEL which will satisfy the rx_load_multiple_vector predicate.  */
1796
 
1797
static rtx
1798
gen_rx_popm_vector (unsigned int low, unsigned int high)
1799
{
1800
  unsigned int i;
1801
  unsigned int count = (high - low) + 2;
1802
  rtx vector;
1803
 
1804
  vector = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
1805
 
1806
  XVECEXP (vector, 0, 0) =
1807
    gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1808
                 plus_constant (stack_pointer_rtx,
1809
                                (count - 1) * UNITS_PER_WORD));
1810
 
1811
  for (i = 0; i < count - 1; i++)
1812
    XVECEXP (vector, 0, i + 1) =
1813
      gen_rtx_SET (VOIDmode,
1814
                   gen_rtx_REG (SImode, low + i),
1815
                   gen_rtx_MEM (SImode,
1816
                                i == 0 ? stack_pointer_rtx
1817
                                : plus_constant (stack_pointer_rtx,
1818
                                                 i * UNITS_PER_WORD)));
1819
 
1820
  return vector;
1821
}
1822
 
1823
/* Returns true if a simple return insn can be used.  */
1824
 
1825
bool
1826
rx_can_use_simple_return (void)
1827
{
1828
  unsigned int low;
1829
  unsigned int high;
1830
  unsigned int frame_size;
1831
  unsigned int stack_size;
1832
  unsigned int register_mask;
1833
 
1834
  if (is_naked_func (NULL_TREE)
1835
      || is_fast_interrupt_func (NULL_TREE)
1836
      || is_interrupt_func (NULL_TREE))
1837
    return false;
1838
 
1839
  rx_get_stack_layout (& low, & high, & register_mask,
1840
                       & frame_size, & stack_size);
1841
 
1842
  return (register_mask == 0
1843
          && (frame_size + stack_size) == 0
1844
          && low == 0);
1845
}
1846
 
1847
void
1848
rx_expand_epilogue (bool is_sibcall)
1849
{
1850
  unsigned int low;
1851
  unsigned int high;
1852
  unsigned int frame_size;
1853
  unsigned int stack_size;
1854
  unsigned int register_mask;
1855
  unsigned int regs_size;
1856
  unsigned int reg;
1857
  unsigned HOST_WIDE_INT total_size;
1858
 
1859
  /* FIXME: We do not support indirect sibcalls at the moment becaause we
1860
     cannot guarantee that the register holding the function address is a
1861
     call-used register.  If it is a call-saved register then the stack
1862
     pop instructions generated in the epilogue will corrupt the address
1863
     before it is used.
1864
 
1865
     Creating a new call-used-only register class works but then the
1866
     reload pass gets stuck because it cannot always find a call-used
1867
     register for spilling sibcalls.
1868
 
1869
     The other possible solution is for this pass to scan forward for the
1870
     sibcall instruction (if it has been generated) and work out if it
1871
     is an indirect sibcall using a call-saved register.  If it is then
1872
     the address can copied into a call-used register in this epilogue
1873
     code and the sibcall instruction modified to use that register.  */
1874
 
1875
  if (is_naked_func (NULL_TREE))
1876
    {
1877
      gcc_assert (! is_sibcall);
1878
 
1879
      /* Naked functions use their own, programmer provided epilogues.
1880
         But, in order to keep gcc happy we have to generate some kind of
1881
         epilogue RTL.  */
1882
      emit_jump_insn (gen_naked_return ());
1883
      return;
1884
    }
1885
 
1886
  rx_get_stack_layout (& low, & high, & register_mask,
1887
                       & frame_size, & stack_size);
1888
 
1889
  total_size = frame_size + stack_size;
1890
  regs_size = ((high - low) + 1) * UNITS_PER_WORD;
1891
 
1892
  /* See if we are unable to use the special stack frame deconstruct and
1893
     return instructions.  In most cases we can use them, but the exceptions
1894
     are:
1895
 
1896
     - Sibling calling functions deconstruct the frame but do not return to
1897
       their caller.  Instead they branch to their sibling and allow their
1898
       return instruction to return to this function's parent.
1899
 
1900
     - Fast and normal interrupt handling functions have to use special
1901
       return instructions.
1902
 
1903
     - Functions where we have pushed a fragmented set of registers into the
1904
       call-save area must have the same set of registers popped.  */
1905
  if (is_sibcall
1906
      || is_fast_interrupt_func (NULL_TREE)
1907
      || is_interrupt_func (NULL_TREE)
1908
      || register_mask)
1909
    {
1910
      /* Cannot use the special instructions - deconstruct by hand.  */
1911
      if (total_size)
1912
        gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
1913
                      GEN_INT (total_size), false);
1914
 
1915
      if (MUST_SAVE_ACC_REGISTER)
1916
        {
1917
          unsigned int acc_low, acc_high;
1918
 
1919
          /* Reverse the saving of the accumulator register onto the stack.
1920
             Note we must adjust the saved "low" accumulator value as it
1921
             is really the middle 32-bits of the accumulator.  */
1922
          if (register_mask)
1923
            {
1924
              acc_low = acc_high = 0;
1925
 
1926
              for (reg = 1; reg < CC_REGNUM; reg ++)
1927
                if (register_mask & (1 << reg))
1928
                  {
1929
                    if (acc_low == 0)
1930
                      acc_low = reg;
1931
                    else
1932
                      {
1933
                        acc_high = reg;
1934
                        break;
1935
                      }
1936
                  }
1937
              emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_high)));
1938
              emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_low)));
1939
            }
1940
          else
1941
            {
1942
              acc_low = low;
1943
              acc_high = low + 1;
1944
              emit_insn (gen_stack_popm (GEN_INT (2 * UNITS_PER_WORD),
1945
                                         gen_rx_popm_vector (acc_low, acc_high)));
1946
            }
1947
 
1948
          emit_insn (gen_ashlsi3 (gen_rtx_REG (SImode, acc_low),
1949
                                  gen_rtx_REG (SImode, acc_low),
1950
                                  GEN_INT (16)));
1951
          emit_insn (gen_mvtaclo (gen_rtx_REG (SImode, acc_low)));
1952
          emit_insn (gen_mvtachi (gen_rtx_REG (SImode, acc_high)));
1953
        }
1954
 
1955
      if (register_mask)
1956
        {
1957
          for (reg = 0; reg < CC_REGNUM; reg ++)
1958
            if (register_mask & (1 << reg))
1959
              emit_insn (gen_stack_pop (gen_rtx_REG (SImode, reg)));
1960
        }
1961
      else if (low)
1962
        {
1963
          if (high == low)
1964
            emit_insn (gen_stack_pop (gen_rtx_REG (SImode, low)));
1965
          else
1966
            emit_insn (gen_stack_popm (GEN_INT (regs_size),
1967
                                       gen_rx_popm_vector (low, high)));
1968
        }
1969
 
1970
      if (is_fast_interrupt_func (NULL_TREE))
1971
        {
1972
          gcc_assert (! is_sibcall);
1973
          emit_jump_insn (gen_fast_interrupt_return ());
1974
        }
1975
      else if (is_interrupt_func (NULL_TREE))
1976
        {
1977
          gcc_assert (! is_sibcall);
1978
          emit_jump_insn (gen_exception_return ());
1979
        }
1980
      else if (! is_sibcall)
1981
        emit_jump_insn (gen_simple_return ());
1982
 
1983
      return;
1984
    }
1985
 
1986
  /* If we allocated space on the stack, free it now.  */
1987
  if (total_size)
1988
    {
1989
      unsigned HOST_WIDE_INT rtsd_size;
1990
 
1991
      /* See if we can use the RTSD instruction.  */
1992
      rtsd_size = total_size + regs_size;
1993
      if (rtsd_size < 1024 && (rtsd_size % 4) == 0)
1994
        {
1995
          if (low)
1996
            emit_jump_insn (gen_pop_and_return
1997
                            (GEN_INT (rtsd_size),
1998
                             gen_rx_rtsd_vector (rtsd_size, low, high)));
1999
          else
2000
            emit_jump_insn (gen_deallocate_and_return (GEN_INT (total_size)));
2001
 
2002
          return;
2003
        }
2004
 
2005
      gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
2006
                    GEN_INT (total_size), false);
2007
    }
2008
 
2009
  if (low)
2010
    emit_jump_insn (gen_pop_and_return (GEN_INT (regs_size),
2011
                                        gen_rx_rtsd_vector (regs_size,
2012
                                                            low, high)));
2013
  else
2014
    emit_jump_insn (gen_simple_return ());
2015
}
2016
 
2017
 
2018
/* Compute the offset (in words) between FROM (arg pointer
2019
   or frame pointer) and TO (frame pointer or stack pointer).
2020
   See ASCII art comment at the start of rx_expand_prologue
2021
   for more information.  */
2022
 
2023
int
2024
rx_initial_elimination_offset (int from, int to)
2025
{
2026
  unsigned int low;
2027
  unsigned int high;
2028
  unsigned int frame_size;
2029
  unsigned int stack_size;
2030
  unsigned int mask;
2031
 
2032
  rx_get_stack_layout (& low, & high, & mask, & frame_size, & stack_size);
2033
 
2034
  if (from == ARG_POINTER_REGNUM)
2035
    {
2036
      /* Extend the computed size of the stack frame to
2037
         include the registers pushed in the prologue.  */
2038
      if (low)
2039
        frame_size += ((high - low) + 1) * UNITS_PER_WORD;
2040
      else
2041
        frame_size += bit_count (mask) * UNITS_PER_WORD;
2042
 
2043
      /* Remember to include the return address.  */
2044
      frame_size += 1 * UNITS_PER_WORD;
2045
 
2046
      if (to == FRAME_POINTER_REGNUM)
2047
        return frame_size;
2048
 
2049
      gcc_assert (to == STACK_POINTER_REGNUM);
2050
      return frame_size + stack_size;
2051
    }
2052
 
2053
  gcc_assert (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM);
2054
  return stack_size;
2055
}
2056
 
2057
/* Decide if a variable should go into one of the small data sections.  */
2058
 
2059
static bool
2060
rx_in_small_data (const_tree decl)
2061
{
2062
  int size;
2063
  const_tree section;
2064
 
2065
  if (rx_small_data_limit == 0)
2066
    return false;
2067
 
2068
  if (TREE_CODE (decl) != VAR_DECL)
2069
    return false;
2070
 
2071
  /* We do not put read-only variables into a small data area because
2072
     they would be placed with the other read-only sections, far away
2073
     from the read-write data sections, and we only have one small
2074
     data area pointer.
2075
     Similarly commons are placed in the .bss section which might be
2076
     far away (and out of alignment with respect to) the .data section.  */
2077
  if (TREE_READONLY (decl) || DECL_COMMON (decl))
2078
    return false;
2079
 
2080
  section = DECL_SECTION_NAME (decl);
2081
  if (section)
2082
    {
2083
      const char * const name = TREE_STRING_POINTER (section);
2084
 
2085
      return (strcmp (name, "D_2") == 0) || (strcmp (name, "B_2") == 0);
2086
    }
2087
 
2088
  size = int_size_in_bytes (TREE_TYPE (decl));
2089
 
2090
  return (size > 0) && (size <= rx_small_data_limit);
2091
}
2092
 
2093
/* Return a section for X.
2094
   The only special thing we do here is to honor small data.  */
2095
 
2096
static section *
2097
rx_select_rtx_section (enum machine_mode mode,
2098
                       rtx x,
2099
                       unsigned HOST_WIDE_INT align)
2100
{
2101
  if (rx_small_data_limit > 0
2102
      && GET_MODE_SIZE (mode) <= rx_small_data_limit
2103
      && align <= (unsigned HOST_WIDE_INT) rx_small_data_limit * BITS_PER_UNIT)
2104
    return sdata_section;
2105
 
2106
  return default_elf_select_rtx_section (mode, x, align);
2107
}
2108
 
2109
static section *
2110
rx_select_section (tree decl,
2111
                   int reloc,
2112
                   unsigned HOST_WIDE_INT align)
2113
{
2114
  if (rx_small_data_limit > 0)
2115
    {
2116
      switch (categorize_decl_for_section (decl, reloc))
2117
        {
2118
        case SECCAT_SDATA:      return sdata_section;
2119
        case SECCAT_SBSS:       return sbss_section;
2120
        case SECCAT_SRODATA:
2121
          /* Fall through.  We do not put small, read only
2122
             data into the C_2 section because we are not
2123
             using the C_2 section.  We do not use the C_2
2124
             section because it is located with the other
2125
             read-only data sections, far away from the read-write
2126
             data sections and we only have one small data
2127
             pointer (r13).  */
2128
        default:
2129
          break;
2130
        }
2131
    }
2132
 
2133
  /* If we are supporting the Renesas assembler
2134
     we cannot use mergeable sections.  */
2135
  if (TARGET_AS100_SYNTAX)
2136
    switch (categorize_decl_for_section (decl, reloc))
2137
      {
2138
      case SECCAT_RODATA_MERGE_CONST:
2139
      case SECCAT_RODATA_MERGE_STR_INIT:
2140
      case SECCAT_RODATA_MERGE_STR:
2141
        return readonly_data_section;
2142
 
2143
      default:
2144
        break;
2145
      }
2146
 
2147
  return default_elf_select_section (decl, reloc, align);
2148
}
2149
 
2150
enum rx_builtin
2151
{
2152
  RX_BUILTIN_BRK,
2153
  RX_BUILTIN_CLRPSW,
2154
  RX_BUILTIN_INT,
2155
  RX_BUILTIN_MACHI,
2156
  RX_BUILTIN_MACLO,
2157
  RX_BUILTIN_MULHI,
2158
  RX_BUILTIN_MULLO,
2159
  RX_BUILTIN_MVFACHI,
2160
  RX_BUILTIN_MVFACMI,
2161
  RX_BUILTIN_MVFC,
2162
  RX_BUILTIN_MVTACHI,
2163
  RX_BUILTIN_MVTACLO,
2164
  RX_BUILTIN_MVTC,
2165
  RX_BUILTIN_MVTIPL,
2166
  RX_BUILTIN_RACW,
2167
  RX_BUILTIN_REVW,
2168
  RX_BUILTIN_RMPA,
2169
  RX_BUILTIN_ROUND,
2170
  RX_BUILTIN_SETPSW,
2171
  RX_BUILTIN_WAIT,
2172
  RX_BUILTIN_max
2173
};
2174
 
2175
static GTY(()) tree rx_builtins[(int) RX_BUILTIN_max];
2176
 
2177
static void
2178
rx_init_builtins (void)
2179
{
2180
#define ADD_RX_BUILTIN1(UC_NAME, LC_NAME, RET_TYPE, ARG_TYPE)           \
2181
   rx_builtins[RX_BUILTIN_##UC_NAME] =                                  \
2182
   add_builtin_function ("__builtin_rx_" LC_NAME,                       \
2183
                        build_function_type_list (RET_TYPE##_type_node, \
2184
                                                  ARG_TYPE##_type_node, \
2185
                                                  NULL_TREE),           \
2186
                        RX_BUILTIN_##UC_NAME,                           \
2187
                        BUILT_IN_MD, NULL, NULL_TREE)
2188
 
2189
#define ADD_RX_BUILTIN2(UC_NAME, LC_NAME, RET_TYPE, ARG_TYPE1, ARG_TYPE2) \
2190
  rx_builtins[RX_BUILTIN_##UC_NAME] =                                   \
2191
  add_builtin_function ("__builtin_rx_" LC_NAME,                        \
2192
                        build_function_type_list (RET_TYPE##_type_node, \
2193
                                                  ARG_TYPE1##_type_node,\
2194
                                                  ARG_TYPE2##_type_node,\
2195
                                                  NULL_TREE),           \
2196
                        RX_BUILTIN_##UC_NAME,                           \
2197
                        BUILT_IN_MD, NULL, NULL_TREE)
2198
 
2199
#define ADD_RX_BUILTIN3(UC_NAME,LC_NAME,RET_TYPE,ARG_TYPE1,ARG_TYPE2,ARG_TYPE3) \
2200
  rx_builtins[RX_BUILTIN_##UC_NAME] =                                   \
2201
  add_builtin_function ("__builtin_rx_" LC_NAME,                        \
2202
                        build_function_type_list (RET_TYPE##_type_node, \
2203
                                                  ARG_TYPE1##_type_node,\
2204
                                                  ARG_TYPE2##_type_node,\
2205
                                                  ARG_TYPE3##_type_node,\
2206
                                                  NULL_TREE),           \
2207
                        RX_BUILTIN_##UC_NAME,                           \
2208
                        BUILT_IN_MD, NULL, NULL_TREE)
2209
 
2210
  ADD_RX_BUILTIN1 (BRK,     "brk",     void,  void);
2211
  ADD_RX_BUILTIN1 (CLRPSW,  "clrpsw",  void,  integer);
2212
  ADD_RX_BUILTIN1 (SETPSW,  "setpsw",  void,  integer);
2213
  ADD_RX_BUILTIN1 (INT,     "int",     void,  integer);
2214
  ADD_RX_BUILTIN2 (MACHI,   "machi",   void,  intSI, intSI);
2215
  ADD_RX_BUILTIN2 (MACLO,   "maclo",   void,  intSI, intSI);
2216
  ADD_RX_BUILTIN2 (MULHI,   "mulhi",   void,  intSI, intSI);
2217
  ADD_RX_BUILTIN2 (MULLO,   "mullo",   void,  intSI, intSI);
2218
  ADD_RX_BUILTIN1 (MVFACHI, "mvfachi", intSI, void);
2219
  ADD_RX_BUILTIN1 (MVFACMI, "mvfacmi", intSI, void);
2220
  ADD_RX_BUILTIN1 (MVTACHI, "mvtachi", void,  intSI);
2221
  ADD_RX_BUILTIN1 (MVTACLO, "mvtaclo", void,  intSI);
2222
  ADD_RX_BUILTIN1 (RMPA,    "rmpa",    void,  void);
2223
  ADD_RX_BUILTIN1 (MVFC,    "mvfc",    intSI, integer);
2224
  ADD_RX_BUILTIN2 (MVTC,    "mvtc",    void,  integer, integer);
2225
  ADD_RX_BUILTIN1 (MVTIPL,  "mvtipl",  void,  integer);
2226
  ADD_RX_BUILTIN1 (RACW,    "racw",    void,  integer);
2227
  ADD_RX_BUILTIN1 (ROUND,   "round",   intSI, float);
2228
  ADD_RX_BUILTIN1 (REVW,    "revw",    intSI, intSI);
2229
  ADD_RX_BUILTIN1 (WAIT,    "wait",    void,  void);
2230
}
2231
 
2232
/* Return the RX builtin for CODE.  */
2233
 
2234
static tree
2235
rx_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
2236
{
2237
  if (code >= RX_BUILTIN_max)
2238
    return error_mark_node;
2239
 
2240
  return rx_builtins[code];
2241
}
2242
 
2243
static rtx
2244
rx_expand_void_builtin_1_arg (rtx arg, rtx (* gen_func)(rtx), bool reg)
2245
{
2246
  if (reg && ! REG_P (arg))
2247
    arg = force_reg (SImode, arg);
2248
 
2249
  emit_insn (gen_func (arg));
2250
 
2251
  return NULL_RTX;
2252
}
2253
 
2254
static rtx
2255
rx_expand_builtin_mvtc (tree exp)
2256
{
2257
  rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
2258
  rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
2259
 
2260
  if (! CONST_INT_P (arg1))
2261
    return NULL_RTX;
2262
 
2263
  if (! REG_P (arg2))
2264
    arg2 = force_reg (SImode, arg2);
2265
 
2266
  emit_insn (gen_mvtc (arg1, arg2));
2267
 
2268
  return NULL_RTX;
2269
}
2270
 
2271
static rtx
2272
rx_expand_builtin_mvfc (tree t_arg, rtx target)
2273
{
2274
  rtx arg = expand_normal (t_arg);
2275
 
2276
  if (! CONST_INT_P (arg))
2277
    return NULL_RTX;
2278
 
2279
  if (target == NULL_RTX)
2280
    return NULL_RTX;
2281
 
2282
  if (! REG_P (target))
2283
    target = force_reg (SImode, target);
2284
 
2285
  emit_insn (gen_mvfc (target, arg));
2286
 
2287
  return target;
2288
}
2289
 
2290
static rtx
2291
rx_expand_builtin_mvtipl (rtx arg)
2292
{
2293
  /* The RX610 does not support the MVTIPL instruction.  */
2294
  if (rx_cpu_type == RX610)
2295
    return NULL_RTX;
2296
 
2297
  if (! CONST_INT_P (arg) || ! IN_RANGE (INTVAL (arg), 0, (1 << 4) - 1))
2298
    return NULL_RTX;
2299
 
2300
  emit_insn (gen_mvtipl (arg));
2301
 
2302
  return NULL_RTX;
2303
}
2304
 
2305
static rtx
2306
rx_expand_builtin_mac (tree exp, rtx (* gen_func)(rtx, rtx))
2307
{
2308
  rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
2309
  rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
2310
 
2311
  if (! REG_P (arg1))
2312
    arg1 = force_reg (SImode, arg1);
2313
 
2314
  if (! REG_P (arg2))
2315
    arg2 = force_reg (SImode, arg2);
2316
 
2317
  emit_insn (gen_func (arg1, arg2));
2318
 
2319
  return NULL_RTX;
2320
}
2321
 
2322
static rtx
2323
rx_expand_int_builtin_1_arg (rtx arg,
2324
                             rtx target,
2325
                             rtx (* gen_func)(rtx, rtx),
2326
                             bool mem_ok)
2327
{
2328
  if (! REG_P (arg))
2329
    if (!mem_ok || ! MEM_P (arg))
2330
      arg = force_reg (SImode, arg);
2331
 
2332
  if (target == NULL_RTX || ! REG_P (target))
2333
    target = gen_reg_rtx (SImode);
2334
 
2335
  emit_insn (gen_func (target, arg));
2336
 
2337
  return target;
2338
}
2339
 
2340
static rtx
2341
rx_expand_int_builtin_0_arg (rtx target, rtx (* gen_func)(rtx))
2342
{
2343
  if (target == NULL_RTX || ! REG_P (target))
2344
    target = gen_reg_rtx (SImode);
2345
 
2346
  emit_insn (gen_func (target));
2347
 
2348
  return target;
2349
}
2350
 
2351
static rtx
2352
rx_expand_builtin_round (rtx arg, rtx target)
2353
{
2354
  if ((! REG_P (arg) && ! MEM_P (arg))
2355
      || GET_MODE (arg) != SFmode)
2356
    arg = force_reg (SFmode, arg);
2357
 
2358
  if (target == NULL_RTX || ! REG_P (target))
2359
    target = gen_reg_rtx (SImode);
2360
 
2361
  emit_insn (gen_lrintsf2 (target, arg));
2362
 
2363
  return target;
2364
}
2365
 
2366
static int
2367
valid_psw_flag (rtx op, const char *which)
2368
{
2369
  static int mvtc_inform_done = 0;
2370
 
2371
  if (GET_CODE (op) == CONST_INT)
2372
    switch (INTVAL (op))
2373
      {
2374
      case 0: case 'c': case 'C':
2375
      case 1: case 'z': case 'Z':
2376
      case 2: case 's': case 'S':
2377
      case 3: case 'o': case 'O':
2378
      case 8: case 'i': case 'I':
2379
      case 9: case 'u': case 'U':
2380
        return 1;
2381
      }
2382
 
2383
  error ("__builtin_rx_%s takes 'C', 'Z', 'S', 'O', 'I', or 'U'", which);
2384
  if (!mvtc_inform_done)
2385
    error ("use __builtin_rx_mvtc (0, ... ) to write arbitrary values to PSW");
2386
  mvtc_inform_done = 1;
2387
 
2388
  return 0;
2389
}
2390
 
2391
static rtx
2392
rx_expand_builtin (tree exp,
2393
                   rtx target,
2394
                   rtx subtarget ATTRIBUTE_UNUSED,
2395
                   enum machine_mode mode ATTRIBUTE_UNUSED,
2396
                   int ignore ATTRIBUTE_UNUSED)
2397
{
2398
  tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2399
  tree arg    = call_expr_nargs (exp) >= 1 ? CALL_EXPR_ARG (exp, 0) : NULL_TREE;
2400
  rtx  op     = arg ? expand_normal (arg) : NULL_RTX;
2401
  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2402
 
2403
  switch (fcode)
2404
    {
2405
    case RX_BUILTIN_BRK:     emit_insn (gen_brk ()); return NULL_RTX;
2406
    case RX_BUILTIN_CLRPSW:
2407
      if (!valid_psw_flag (op, "clrpsw"))
2408
        return NULL_RTX;
2409
      return rx_expand_void_builtin_1_arg (op, gen_clrpsw, false);
2410
    case RX_BUILTIN_SETPSW:
2411
      if (!valid_psw_flag (op, "setpsw"))
2412
        return NULL_RTX;
2413
      return rx_expand_void_builtin_1_arg (op, gen_setpsw, false);
2414
    case RX_BUILTIN_INT:     return rx_expand_void_builtin_1_arg
2415
        (op, gen_int, false);
2416
    case RX_BUILTIN_MACHI:   return rx_expand_builtin_mac (exp, gen_machi);
2417
    case RX_BUILTIN_MACLO:   return rx_expand_builtin_mac (exp, gen_maclo);
2418
    case RX_BUILTIN_MULHI:   return rx_expand_builtin_mac (exp, gen_mulhi);
2419
    case RX_BUILTIN_MULLO:   return rx_expand_builtin_mac (exp, gen_mullo);
2420
    case RX_BUILTIN_MVFACHI: return rx_expand_int_builtin_0_arg
2421
        (target, gen_mvfachi);
2422
    case RX_BUILTIN_MVFACMI: return rx_expand_int_builtin_0_arg
2423
        (target, gen_mvfacmi);
2424
    case RX_BUILTIN_MVTACHI: return rx_expand_void_builtin_1_arg
2425
        (op, gen_mvtachi, true);
2426
    case RX_BUILTIN_MVTACLO: return rx_expand_void_builtin_1_arg
2427
        (op, gen_mvtaclo, true);
2428
    case RX_BUILTIN_RMPA:    emit_insn (gen_rmpa ()); return NULL_RTX;
2429
    case RX_BUILTIN_MVFC:    return rx_expand_builtin_mvfc (arg, target);
2430
    case RX_BUILTIN_MVTC:    return rx_expand_builtin_mvtc (exp);
2431
    case RX_BUILTIN_MVTIPL:  return rx_expand_builtin_mvtipl (op);
2432
    case RX_BUILTIN_RACW:    return rx_expand_void_builtin_1_arg
2433
        (op, gen_racw, false);
2434
    case RX_BUILTIN_ROUND:   return rx_expand_builtin_round (op, target);
2435
    case RX_BUILTIN_REVW:    return rx_expand_int_builtin_1_arg
2436
        (op, target, gen_revw, false);
2437
    case RX_BUILTIN_WAIT:    emit_insn (gen_wait ()); return NULL_RTX;
2438
 
2439
    default:
2440
      internal_error ("bad builtin code");
2441
      break;
2442
    }
2443
 
2444
  return NULL_RTX;
2445
}
2446
 
2447
/* Place an element into a constructor or destructor section.
2448
   Like default_ctor_section_asm_out_constructor in varasm.c
2449
   except that it uses .init_array (or .fini_array) and it
2450
   handles constructor priorities.  */
2451
 
2452
static void
2453
rx_elf_asm_cdtor (rtx symbol, int priority, bool is_ctor)
2454
{
2455
  section * s;
2456
 
2457
  if (priority != DEFAULT_INIT_PRIORITY)
2458
    {
2459
      char buf[18];
2460
 
2461
      sprintf (buf, "%s.%.5u",
2462
               is_ctor ? ".init_array" : ".fini_array",
2463
               priority);
2464
      s = get_section (buf, SECTION_WRITE, NULL_TREE);
2465
    }
2466
  else if (is_ctor)
2467
    s = ctors_section;
2468
  else
2469
    s = dtors_section;
2470
 
2471
  switch_to_section (s);
2472
  assemble_align (POINTER_SIZE);
2473
  assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
2474
}
2475
 
2476
static void
2477
rx_elf_asm_constructor (rtx symbol, int priority)
2478
{
2479
  rx_elf_asm_cdtor (symbol, priority, /* is_ctor= */true);
2480
}
2481
 
2482
static void
2483
rx_elf_asm_destructor (rtx symbol, int priority)
2484
{
2485
  rx_elf_asm_cdtor (symbol, priority, /* is_ctor= */false);
2486
}
2487
 
2488
/* Check "fast_interrupt", "interrupt" and "naked" attributes.  */
2489
 
2490
static tree
2491
rx_handle_func_attribute (tree * node,
2492
                          tree   name,
2493
                          tree   args,
2494
                          int    flags ATTRIBUTE_UNUSED,
2495
                          bool * no_add_attrs)
2496
{
2497
  gcc_assert (DECL_P (* node));
2498
  gcc_assert (args == NULL_TREE);
2499
 
2500
  if (TREE_CODE (* node) != FUNCTION_DECL)
2501
    {
2502
      warning (OPT_Wattributes, "%qE attribute only applies to functions",
2503
               name);
2504
      * no_add_attrs = true;
2505
    }
2506
 
2507
  /* FIXME: We ought to check for conflicting attributes.  */
2508
 
2509
  /* FIXME: We ought to check that the interrupt and exception
2510
     handler attributes have been applied to void functions.  */
2511
  return NULL_TREE;
2512
}
2513
 
2514
/* Table of RX specific attributes.  */
2515
const struct attribute_spec rx_attribute_table[] =
2516
{
2517
  /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
2518
     affects_type_identity.  */
2519
  { "fast_interrupt", 0, 0, true, false, false, rx_handle_func_attribute,
2520
    false },
2521
  { "interrupt",      0, 0, true, false, false, rx_handle_func_attribute,
2522
    false },
2523
  { "naked",          0, 0, true, false, false, rx_handle_func_attribute,
2524
    false },
2525
  { NULL,             0, 0, false, false, false, NULL, false }
2526
};
2527
 
2528
/* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE.  */
2529
 
2530
static void
2531
rx_override_options_after_change (void)
2532
{
2533
  static bool first_time = TRUE;
2534
 
2535
  if (first_time)
2536
    {
2537
      /* If this is the first time through and the user has not disabled
2538
         the use of RX FPU hardware then enable -ffinite-math-only,
2539
         since the FPU instructions do not support NaNs and infinities.  */
2540
      if (TARGET_USE_FPU)
2541
        flag_finite_math_only = 1;
2542
 
2543
      first_time = FALSE;
2544
    }
2545
  else
2546
    {
2547
      /* Alert the user if they are changing the optimization options
2548
         to use IEEE compliant floating point arithmetic with RX FPU insns.  */
2549
      if (TARGET_USE_FPU
2550
          && !flag_finite_math_only)
2551
        warning (0, "RX FPU instructions do not support NaNs and infinities");
2552
    }
2553
}
2554
 
2555
static void
2556
rx_option_override (void)
2557
{
2558
  unsigned int i;
2559
  cl_deferred_option *opt;
2560
  VEC(cl_deferred_option,heap) *vec
2561
    = (VEC(cl_deferred_option,heap) *) rx_deferred_options;
2562
 
2563
  FOR_EACH_VEC_ELT (cl_deferred_option, vec, i, opt)
2564
    {
2565
      switch (opt->opt_index)
2566
        {
2567
        case OPT_mint_register_:
2568
          switch (opt->value)
2569
            {
2570
            case 4:
2571
              fixed_regs[10] = call_used_regs [10] = 1;
2572
              /* Fall through.  */
2573
            case 3:
2574
              fixed_regs[11] = call_used_regs [11] = 1;
2575
              /* Fall through.  */
2576
            case 2:
2577
              fixed_regs[12] = call_used_regs [12] = 1;
2578
              /* Fall through.  */
2579
            case 1:
2580
              fixed_regs[13] = call_used_regs [13] = 1;
2581
              /* Fall through.  */
2582
            case 0:
2583
              rx_num_interrupt_regs = opt->value;
2584
              break;
2585
            default:
2586
              rx_num_interrupt_regs = 0;
2587
              /* Error message already given because rx_handle_option
2588
                 returned false.  */
2589
              break;
2590
            }
2591
          break;
2592
 
2593
        default:
2594
          gcc_unreachable ();
2595
        }
2596
    }
2597
 
2598
  /* This target defaults to strict volatile bitfields.  */
2599
  if (flag_strict_volatile_bitfields < 0 && abi_version_at_least(2))
2600
    flag_strict_volatile_bitfields = 1;
2601
 
2602
  rx_override_options_after_change ();
2603
 
2604
  if (align_jumps == 0 && ! optimize_size)
2605
    align_jumps = 3;
2606
  if (align_loops == 0 && ! optimize_size)
2607
    align_loops = 3;
2608
  if (align_labels == 0 && ! optimize_size)
2609
    align_labels = 3;
2610
}
2611
 
2612
 
2613
static bool
2614
rx_allocate_stack_slots_for_args (void)
2615
{
2616
  /* Naked functions should not allocate stack slots for arguments.  */
2617
  return ! is_naked_func (NULL_TREE);
2618
}
2619
 
2620
static bool
2621
rx_func_attr_inlinable (const_tree decl)
2622
{
2623
  return ! is_fast_interrupt_func (decl)
2624
    &&   ! is_interrupt_func (decl)
2625
    &&   ! is_naked_func (decl);
2626
}
2627
 
2628
/* Return nonzero if it is ok to make a tail-call to DECL,
2629
   a function_decl or NULL if this is an indirect call, using EXP  */
2630
 
2631
static bool
2632
rx_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
2633
{
2634
  /* Do not allow indirect tailcalls.  The
2635
     sibcall patterns do not support them.  */
2636
  if (decl == NULL)
2637
    return false;
2638
 
2639
  /* Never tailcall from inside interrupt handlers or naked functions.  */
2640
  if (is_fast_interrupt_func (NULL_TREE)
2641
      || is_interrupt_func (NULL_TREE)
2642
      || is_naked_func (NULL_TREE))
2643
    return false;
2644
 
2645
  return true;
2646
}
2647
 
2648
static void
2649
rx_file_start (void)
2650
{
2651
  if (! TARGET_AS100_SYNTAX)
2652
    default_file_start ();
2653
}
2654
 
2655
static bool
2656
rx_is_ms_bitfield_layout (const_tree record_type ATTRIBUTE_UNUSED)
2657
{
2658
  /* The packed attribute overrides the MS behaviour.  */
2659
  return ! TYPE_PACKED (record_type);
2660
}
2661
 
2662
/* Returns true if X a legitimate constant for an immediate
2663
   operand on the RX.  X is already known to satisfy CONSTANT_P.  */
2664
 
2665
bool
2666
rx_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
2667
{
2668
  switch (GET_CODE (x))
2669
    {
2670
    case CONST:
2671
      x = XEXP (x, 0);
2672
 
2673
      if (GET_CODE (x) == PLUS)
2674
        {
2675
          if (! CONST_INT_P (XEXP (x, 1)))
2676
            return false;
2677
 
2678
          /* GCC would not pass us CONST_INT + CONST_INT so we
2679
             know that we have {SYMBOL|LABEL} + CONST_INT.  */
2680
          x = XEXP (x, 0);
2681
          gcc_assert (! CONST_INT_P (x));
2682
        }
2683
 
2684
      switch (GET_CODE (x))
2685
        {
2686
        case LABEL_REF:
2687
        case SYMBOL_REF:
2688
          return true;
2689
 
2690
        case UNSPEC:
2691
          return XINT (x, 1) == UNSPEC_CONST || XINT (x, 1) == UNSPEC_PID_ADDR;
2692
 
2693
        default:
2694
          /* FIXME: Can this ever happen ?  */
2695
          gcc_unreachable ();
2696
        }
2697
      break;
2698
 
2699
    case LABEL_REF:
2700
    case SYMBOL_REF:
2701
      return true;
2702
    case CONST_DOUBLE:
2703
      return (rx_max_constant_size == 0 || rx_max_constant_size == 4);
2704
    case CONST_VECTOR:
2705
      return false;
2706
    default:
2707
      gcc_assert (CONST_INT_P (x));
2708
      break;
2709
    }
2710
 
2711
  return ok_for_max_constant (INTVAL (x));
2712
}
2713
 
2714
static int
2715
rx_address_cost (rtx addr, bool speed)
2716
{
2717
  rtx a, b;
2718
 
2719
  if (GET_CODE (addr) != PLUS)
2720
    return COSTS_N_INSNS (1);
2721
 
2722
  a = XEXP (addr, 0);
2723
  b = XEXP (addr, 1);
2724
 
2725
  if (REG_P (a) && REG_P (b))
2726
    /* Try to discourage REG+REG addressing as it keeps two registers live.  */
2727
    return COSTS_N_INSNS (4);
2728
 
2729
  if (speed)
2730
    /* [REG+OFF] is just as fast as [REG].  */
2731
    return COSTS_N_INSNS (1);
2732
 
2733
  if (CONST_INT_P (b)
2734
      && ((INTVAL (b) > 128) || INTVAL (b) < -127))
2735
    /* Try to discourage REG + <large OFF> when optimizing for size.  */
2736
    return COSTS_N_INSNS (2);
2737
 
2738
  return COSTS_N_INSNS (1);
2739
}
2740
 
2741
static bool
2742
rx_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
2743
{
2744
  /* We can always eliminate to the frame pointer.
2745
     We can eliminate to the stack pointer unless a frame
2746
     pointer is needed.  */
2747
 
2748
  return to == FRAME_POINTER_REGNUM
2749
    || ( to == STACK_POINTER_REGNUM && ! frame_pointer_needed);
2750
}
2751
 
2752
 
2753
static void
2754
rx_trampoline_template (FILE * file)
2755
{
2756
  /* Output assembler code for a block containing the constant
2757
     part of a trampoline, leaving space for the variable parts.
2758
 
2759
     On the RX, (where r8 is the static chain regnum) the trampoline
2760
     looks like:
2761
 
2762
           mov          #<static chain value>, r8
2763
           mov          #<function's address>, r9
2764
           jmp          r9
2765
 
2766
     In big-endian-data-mode however instructions are read into the CPU
2767
     4 bytes at a time.  These bytes are then swapped around before being
2768
     passed to the decoder.  So...we must partition our trampoline into
2769
     4 byte packets and swap these packets around so that the instruction
2770
     reader will reverse the process.  But, in order to avoid splitting
2771
     the 32-bit constants across these packet boundaries, (making inserting
2772
     them into the constructed trampoline very difficult) we have to pad the
2773
     instruction sequence with NOP insns.  ie:
2774
 
2775
           nop
2776
           nop
2777
           mov.l        #<...>, r8
2778
           nop
2779
           nop
2780
           mov.l        #<...>, r9
2781
           jmp          r9
2782
           nop
2783
           nop             */
2784
 
2785
  if (! TARGET_BIG_ENDIAN_DATA)
2786
    {
2787
      asm_fprintf (file, "\tmov.L\t#0deadbeefH, r%d\n", STATIC_CHAIN_REGNUM);
2788
      asm_fprintf (file, "\tmov.L\t#0deadbeefH, r%d\n", TRAMPOLINE_TEMP_REGNUM);
2789
      asm_fprintf (file, "\tjmp\tr%d\n",                TRAMPOLINE_TEMP_REGNUM);
2790
    }
2791
  else
2792
    {
2793
      char r8 = '0' + STATIC_CHAIN_REGNUM;
2794
      char r9 = '0' + TRAMPOLINE_TEMP_REGNUM;
2795
 
2796
      if (TARGET_AS100_SYNTAX)
2797
        {
2798
          asm_fprintf (file, "\t.BYTE 0%c2H, 0fbH, 003H,  003H\n", r8);
2799
          asm_fprintf (file, "\t.BYTE 0deH,  0adH, 0beH,  0efH\n");
2800
          asm_fprintf (file, "\t.BYTE 0%c2H, 0fbH, 003H,  003H\n", r9);
2801
          asm_fprintf (file, "\t.BYTE 0deH,  0adH, 0beH,  0efH\n");
2802
          asm_fprintf (file, "\t.BYTE 003H,  003H, 00%cH, 07fH\n", r9);
2803
        }
2804
      else
2805
        {
2806
          asm_fprintf (file, "\t.byte 0x%c2, 0xfb, 0x03,  0x03\n", r8);
2807
          asm_fprintf (file, "\t.byte 0xde,  0xad, 0xbe,  0xef\n");
2808
          asm_fprintf (file, "\t.byte 0x%c2, 0xfb, 0x03,  0x03\n", r9);
2809
          asm_fprintf (file, "\t.byte 0xde,  0xad, 0xbe,  0xef\n");
2810
          asm_fprintf (file, "\t.byte 0x03,  0x03, 0x0%c, 0x7f\n", r9);
2811
        }
2812
    }
2813
}
2814
 
2815
static void
2816
rx_trampoline_init (rtx tramp, tree fndecl, rtx chain)
2817
{
2818
  rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2819
 
2820
  emit_block_move (tramp, assemble_trampoline_template (),
2821
                   GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
2822
 
2823
  if (TARGET_BIG_ENDIAN_DATA)
2824
    {
2825
      emit_move_insn (adjust_address (tramp, SImode, 4), chain);
2826
      emit_move_insn (adjust_address (tramp, SImode, 12), fnaddr);
2827
    }
2828
  else
2829
    {
2830
      emit_move_insn (adjust_address (tramp, SImode, 2), chain);
2831
      emit_move_insn (adjust_address (tramp, SImode, 6 + 2), fnaddr);
2832
    }
2833
}
2834
 
2835
static int
2836
rx_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
2837
                     reg_class_t regclass ATTRIBUTE_UNUSED,
2838
                     bool in)
2839
{
2840
  return (in ? 2 : 0) + REGISTER_MOVE_COST (mode, regclass, regclass);
2841
}
2842
 
2843
/* Convert a CC_MODE to the set of flags that it represents.  */
2844
 
2845
static unsigned int
2846
flags_from_mode (enum machine_mode mode)
2847
{
2848
  switch (mode)
2849
    {
2850
    case CC_ZSmode:
2851
      return CC_FLAG_S | CC_FLAG_Z;
2852
    case CC_ZSOmode:
2853
      return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O;
2854
    case CC_ZSCmode:
2855
      return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_C;
2856
    case CCmode:
2857
      return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O | CC_FLAG_C;
2858
    case CC_Fmode:
2859
      return CC_FLAG_FP;
2860
    default:
2861
      gcc_unreachable ();
2862
    }
2863
}
2864
 
2865
/* Convert a set of flags to a CC_MODE that can implement it.  */
2866
 
2867
static enum machine_mode
2868
mode_from_flags (unsigned int f)
2869
{
2870
  if (f & CC_FLAG_FP)
2871
    return CC_Fmode;
2872
  if (f & CC_FLAG_O)
2873
    {
2874
      if (f & CC_FLAG_C)
2875
        return CCmode;
2876
      else
2877
        return CC_ZSOmode;
2878
    }
2879
  else if (f & CC_FLAG_C)
2880
    return CC_ZSCmode;
2881
  else
2882
    return CC_ZSmode;
2883
}
2884
 
2885
/* Convert an RTX_CODE to the set of flags needed to implement it.
2886
   This assumes an integer comparison.  */
2887
 
2888
static unsigned int
2889
flags_from_code (enum rtx_code code)
2890
{
2891
  switch (code)
2892
    {
2893
    case LT:
2894
    case GE:
2895
      return CC_FLAG_S;
2896
    case GT:
2897
    case LE:
2898
      return CC_FLAG_S | CC_FLAG_O | CC_FLAG_Z;
2899
    case GEU:
2900
    case LTU:
2901
      return CC_FLAG_C;
2902
    case GTU:
2903
    case LEU:
2904
      return CC_FLAG_C | CC_FLAG_Z;
2905
    case EQ:
2906
    case NE:
2907
      return CC_FLAG_Z;
2908
    default:
2909
      gcc_unreachable ();
2910
    }
2911
}
2912
 
2913
/* Return a CC_MODE of which both M1 and M2 are subsets.  */
2914
 
2915
static enum machine_mode
2916
rx_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
2917
{
2918
  unsigned f;
2919
 
2920
  /* Early out for identical modes.  */
2921
  if (m1 == m2)
2922
    return m1;
2923
 
2924
  /* There's no valid combination for FP vs non-FP.  */
2925
  f = flags_from_mode (m1) | flags_from_mode (m2);
2926
  if (f & CC_FLAG_FP)
2927
    return VOIDmode;
2928
 
2929
  /* Otherwise, see what mode can implement all the flags.  */
2930
  return mode_from_flags (f);
2931
}
2932
 
2933
/* Return the minimal CC mode needed to implement (CMP_CODE X Y).  */
2934
 
2935
enum machine_mode
2936
rx_select_cc_mode (enum rtx_code cmp_code, rtx x, rtx y)
2937
{
2938
  if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
2939
    return CC_Fmode;
2940
 
2941
  if (y != const0_rtx)
2942
    return CCmode;
2943
 
2944
  return mode_from_flags (flags_from_code (cmp_code));
2945
}
2946
 
2947
/* Split the conditional branch.  Emit (COMPARE C1 C2) into CC_REG with
2948
   CC_MODE, and use that in branches based on that compare.  */
2949
 
2950
void
2951
rx_split_cbranch (enum machine_mode cc_mode, enum rtx_code cmp1,
2952
                  rtx c1, rtx c2, rtx label)
2953
{
2954
  rtx flags, x;
2955
 
2956
  flags = gen_rtx_REG (cc_mode, CC_REG);
2957
  x = gen_rtx_COMPARE (cc_mode, c1, c2);
2958
  x = gen_rtx_SET (VOIDmode, flags, x);
2959
  emit_insn (x);
2960
 
2961
  x = gen_rtx_fmt_ee (cmp1, VOIDmode, flags, const0_rtx);
2962
  x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label, pc_rtx);
2963
  x = gen_rtx_SET (VOIDmode, pc_rtx, x);
2964
  emit_jump_insn (x);
2965
}
2966
 
2967
/* A helper function for matching parallels that set the flags.  */
2968
 
2969
bool
2970
rx_match_ccmode (rtx insn, enum machine_mode cc_mode)
2971
{
2972
  rtx op1, flags;
2973
  enum machine_mode flags_mode;
2974
 
2975
  gcc_checking_assert (XVECLEN (PATTERN (insn), 0) == 2);
2976
 
2977
  op1 = XVECEXP (PATTERN (insn), 0, 1);
2978
  gcc_checking_assert (GET_CODE (SET_SRC (op1)) == COMPARE);
2979
 
2980
  flags = SET_DEST (op1);
2981
  flags_mode = GET_MODE (flags);
2982
 
2983
  if (GET_MODE (SET_SRC (op1)) != flags_mode)
2984
    return false;
2985
  if (GET_MODE_CLASS (flags_mode) != MODE_CC)
2986
    return false;
2987
 
2988
  /* Ensure that the mode of FLAGS is compatible with CC_MODE.  */
2989
  if (flags_from_mode (flags_mode) & ~flags_from_mode (cc_mode))
2990
    return false;
2991
 
2992
  return true;
2993
}
2994
 
2995
int
2996
rx_align_for_label (rtx lab, int uses_threshold)
2997
{
2998
  /* This is a simple heuristic to guess when an alignment would not be useful
2999
     because the delay due to the inserted NOPs would be greater than the delay
3000
     due to the misaligned branch.  If uses_threshold is zero then the alignment
3001
     is always useful.  */
3002
  if (LABEL_P (lab) && LABEL_NUSES (lab) < uses_threshold)
3003
    return 0;
3004
 
3005
  return optimize_size ? 1 : 3;
3006
}
3007
 
3008
static int
3009
rx_max_skip_for_label (rtx lab)
3010
{
3011
  int opsize;
3012
  rtx op;
3013
 
3014
  if (lab == NULL_RTX)
3015
    return 0;
3016
 
3017
  op = lab;
3018
  do
3019
    {
3020
      op = next_nonnote_nondebug_insn (op);
3021
    }
3022
  while (op && (LABEL_P (op)
3023
                || (INSN_P (op) && GET_CODE (PATTERN (op)) == USE)));
3024
  if (!op)
3025
    return 0;
3026
 
3027
  opsize = get_attr_length (op);
3028
  if (opsize >= 0 && opsize < 8)
3029
    return opsize - 1;
3030
  return 0;
3031
}
3032
 
3033
/* Compute the real length of the extending load-and-op instructions.  */
3034
 
3035
int
3036
rx_adjust_insn_length (rtx insn, int current_length)
3037
{
3038
  rtx extend, mem, offset;
3039
  bool zero;
3040
  int factor;
3041
 
3042
  switch (INSN_CODE (insn))
3043
    {
3044
    default:
3045
      return current_length;
3046
 
3047
    case CODE_FOR_plussi3_zero_extendhi:
3048
    case CODE_FOR_andsi3_zero_extendhi:
3049
    case CODE_FOR_iorsi3_zero_extendhi:
3050
    case CODE_FOR_xorsi3_zero_extendhi:
3051
    case CODE_FOR_divsi3_zero_extendhi:
3052
    case CODE_FOR_udivsi3_zero_extendhi:
3053
    case CODE_FOR_minussi3_zero_extendhi:
3054
    case CODE_FOR_smaxsi3_zero_extendhi:
3055
    case CODE_FOR_sminsi3_zero_extendhi:
3056
    case CODE_FOR_multsi3_zero_extendhi:
3057
    case CODE_FOR_comparesi3_zero_extendhi:
3058
      zero = true;
3059
      factor = 2;
3060
      break;
3061
 
3062
    case CODE_FOR_plussi3_sign_extendhi:
3063
    case CODE_FOR_andsi3_sign_extendhi:
3064
    case CODE_FOR_iorsi3_sign_extendhi:
3065
    case CODE_FOR_xorsi3_sign_extendhi:
3066
    case CODE_FOR_divsi3_sign_extendhi:
3067
    case CODE_FOR_udivsi3_sign_extendhi:
3068
    case CODE_FOR_minussi3_sign_extendhi:
3069
    case CODE_FOR_smaxsi3_sign_extendhi:
3070
    case CODE_FOR_sminsi3_sign_extendhi:
3071
    case CODE_FOR_multsi3_sign_extendhi:
3072
    case CODE_FOR_comparesi3_sign_extendhi:
3073
      zero = false;
3074
      factor = 2;
3075
      break;
3076
 
3077
    case CODE_FOR_plussi3_zero_extendqi:
3078
    case CODE_FOR_andsi3_zero_extendqi:
3079
    case CODE_FOR_iorsi3_zero_extendqi:
3080
    case CODE_FOR_xorsi3_zero_extendqi:
3081
    case CODE_FOR_divsi3_zero_extendqi:
3082
    case CODE_FOR_udivsi3_zero_extendqi:
3083
    case CODE_FOR_minussi3_zero_extendqi:
3084
    case CODE_FOR_smaxsi3_zero_extendqi:
3085
    case CODE_FOR_sminsi3_zero_extendqi:
3086
    case CODE_FOR_multsi3_zero_extendqi:
3087
    case CODE_FOR_comparesi3_zero_extendqi:
3088
      zero = true;
3089
      factor = 1;
3090
      break;
3091
 
3092
    case CODE_FOR_plussi3_sign_extendqi:
3093
    case CODE_FOR_andsi3_sign_extendqi:
3094
    case CODE_FOR_iorsi3_sign_extendqi:
3095
    case CODE_FOR_xorsi3_sign_extendqi:
3096
    case CODE_FOR_divsi3_sign_extendqi:
3097
    case CODE_FOR_udivsi3_sign_extendqi:
3098
    case CODE_FOR_minussi3_sign_extendqi:
3099
    case CODE_FOR_smaxsi3_sign_extendqi:
3100
    case CODE_FOR_sminsi3_sign_extendqi:
3101
    case CODE_FOR_multsi3_sign_extendqi:
3102
    case CODE_FOR_comparesi3_sign_extendqi:
3103
      zero = false;
3104
      factor = 1;
3105
      break;
3106
    }
3107
 
3108
  /* We are expecting: (SET (REG) (<OP> (REG) (<EXTEND> (MEM)))).  */
3109
  extend = single_set (insn);
3110
  gcc_assert (extend != NULL_RTX);
3111
 
3112
  extend = SET_SRC (extend);
3113
  if (GET_CODE (XEXP (extend, 0)) == ZERO_EXTEND
3114
      || GET_CODE (XEXP (extend, 0)) == SIGN_EXTEND)
3115
    extend = XEXP (extend, 0);
3116
  else
3117
    extend = XEXP (extend, 1);
3118
 
3119
  gcc_assert ((zero && (GET_CODE (extend) == ZERO_EXTEND))
3120
              || (! zero && (GET_CODE (extend) == SIGN_EXTEND)));
3121
 
3122
  mem = XEXP (extend, 0);
3123
  gcc_checking_assert (MEM_P (mem));
3124
  if (REG_P (XEXP (mem, 0)))
3125
    return (zero && factor == 1) ? 2 : 3;
3126
 
3127
  /* We are expecting: (MEM (PLUS (REG) (CONST_INT))).  */
3128
  gcc_checking_assert (GET_CODE (XEXP (mem, 0)) == PLUS);
3129
  gcc_checking_assert (REG_P (XEXP (XEXP (mem, 0), 0)));
3130
 
3131
  offset = XEXP (XEXP (mem, 0), 1);
3132
  gcc_checking_assert (GET_CODE (offset) == CONST_INT);
3133
 
3134
  if (IN_RANGE (INTVAL (offset), 0, 255 * factor))
3135
    return (zero && factor == 1) ? 3 : 4;
3136
 
3137
  return (zero && factor == 1) ? 4 : 5;
3138
}
3139
 
3140
#undef  TARGET_ASM_JUMP_ALIGN_MAX_SKIP
3141
#define TARGET_ASM_JUMP_ALIGN_MAX_SKIP                  rx_max_skip_for_label
3142
#undef  TARGET_ASM_LOOP_ALIGN_MAX_SKIP
3143
#define TARGET_ASM_LOOP_ALIGN_MAX_SKIP                  rx_max_skip_for_label
3144
#undef  TARGET_LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP
3145
#define TARGET_LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP       rx_max_skip_for_label
3146
#undef  TARGET_ASM_LABEL_ALIGN_MAX_SKIP
3147
#define TARGET_ASM_LABEL_ALIGN_MAX_SKIP                 rx_max_skip_for_label
3148
 
3149
#undef  TARGET_FUNCTION_VALUE
3150
#define TARGET_FUNCTION_VALUE           rx_function_value
3151
 
3152
#undef  TARGET_RETURN_IN_MSB
3153
#define TARGET_RETURN_IN_MSB            rx_return_in_msb
3154
 
3155
#undef  TARGET_IN_SMALL_DATA_P
3156
#define TARGET_IN_SMALL_DATA_P          rx_in_small_data
3157
 
3158
#undef  TARGET_RETURN_IN_MEMORY
3159
#define TARGET_RETURN_IN_MEMORY         rx_return_in_memory
3160
 
3161
#undef  TARGET_HAVE_SRODATA_SECTION
3162
#define TARGET_HAVE_SRODATA_SECTION     true
3163
 
3164
#undef  TARGET_ASM_SELECT_RTX_SECTION
3165
#define TARGET_ASM_SELECT_RTX_SECTION   rx_select_rtx_section
3166
 
3167
#undef  TARGET_ASM_SELECT_SECTION
3168
#define TARGET_ASM_SELECT_SECTION       rx_select_section
3169
 
3170
#undef  TARGET_INIT_BUILTINS
3171
#define TARGET_INIT_BUILTINS            rx_init_builtins
3172
 
3173
#undef  TARGET_BUILTIN_DECL
3174
#define TARGET_BUILTIN_DECL             rx_builtin_decl
3175
 
3176
#undef  TARGET_EXPAND_BUILTIN
3177
#define TARGET_EXPAND_BUILTIN           rx_expand_builtin
3178
 
3179
#undef  TARGET_ASM_CONSTRUCTOR
3180
#define TARGET_ASM_CONSTRUCTOR          rx_elf_asm_constructor
3181
 
3182
#undef  TARGET_ASM_DESTRUCTOR
3183
#define TARGET_ASM_DESTRUCTOR           rx_elf_asm_destructor
3184
 
3185
#undef  TARGET_STRUCT_VALUE_RTX
3186
#define TARGET_STRUCT_VALUE_RTX         rx_struct_value_rtx
3187
 
3188
#undef  TARGET_ATTRIBUTE_TABLE
3189
#define TARGET_ATTRIBUTE_TABLE          rx_attribute_table
3190
 
3191
#undef  TARGET_ASM_FILE_START
3192
#define TARGET_ASM_FILE_START                   rx_file_start
3193
 
3194
#undef  TARGET_MS_BITFIELD_LAYOUT_P
3195
#define TARGET_MS_BITFIELD_LAYOUT_P             rx_is_ms_bitfield_layout
3196
 
3197
#undef  TARGET_LEGITIMATE_ADDRESS_P
3198
#define TARGET_LEGITIMATE_ADDRESS_P             rx_is_legitimate_address
3199
 
3200
#undef  TARGET_MODE_DEPENDENT_ADDRESS_P
3201
#define TARGET_MODE_DEPENDENT_ADDRESS_P         rx_mode_dependent_address_p
3202
 
3203
#undef  TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
3204
#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS    rx_allocate_stack_slots_for_args
3205
 
3206
#undef  TARGET_ASM_FUNCTION_PROLOGUE
3207
#define TARGET_ASM_FUNCTION_PROLOGUE            rx_output_function_prologue
3208
 
3209
#undef  TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P
3210
#define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P   rx_func_attr_inlinable
3211
 
3212
#undef  TARGET_FUNCTION_OK_FOR_SIBCALL
3213
#define TARGET_FUNCTION_OK_FOR_SIBCALL          rx_function_ok_for_sibcall
3214
 
3215
#undef  TARGET_FUNCTION_ARG
3216
#define TARGET_FUNCTION_ARG                     rx_function_arg
3217
 
3218
#undef  TARGET_FUNCTION_ARG_ADVANCE
3219
#define TARGET_FUNCTION_ARG_ADVANCE             rx_function_arg_advance
3220
 
3221
#undef  TARGET_FUNCTION_ARG_BOUNDARY
3222
#define TARGET_FUNCTION_ARG_BOUNDARY            rx_function_arg_boundary
3223
 
3224
#undef  TARGET_SET_CURRENT_FUNCTION
3225
#define TARGET_SET_CURRENT_FUNCTION             rx_set_current_function
3226
 
3227
#undef  TARGET_ASM_INTEGER
3228
#define TARGET_ASM_INTEGER                      rx_assemble_integer
3229
 
3230
#undef  TARGET_USE_BLOCKS_FOR_CONSTANT_P
3231
#define TARGET_USE_BLOCKS_FOR_CONSTANT_P        hook_bool_mode_const_rtx_true
3232
 
3233
#undef  TARGET_MAX_ANCHOR_OFFSET
3234
#define TARGET_MAX_ANCHOR_OFFSET                32
3235
 
3236
#undef  TARGET_ADDRESS_COST
3237
#define TARGET_ADDRESS_COST                     rx_address_cost
3238
 
3239
#undef  TARGET_CAN_ELIMINATE
3240
#define TARGET_CAN_ELIMINATE                    rx_can_eliminate
3241
 
3242
#undef  TARGET_CONDITIONAL_REGISTER_USAGE
3243
#define TARGET_CONDITIONAL_REGISTER_USAGE       rx_conditional_register_usage
3244
 
3245
#undef  TARGET_ASM_TRAMPOLINE_TEMPLATE
3246
#define TARGET_ASM_TRAMPOLINE_TEMPLATE          rx_trampoline_template
3247
 
3248
#undef  TARGET_TRAMPOLINE_INIT
3249
#define TARGET_TRAMPOLINE_INIT                  rx_trampoline_init
3250
 
3251
#undef  TARGET_PRINT_OPERAND
3252
#define TARGET_PRINT_OPERAND                    rx_print_operand
3253
 
3254
#undef  TARGET_PRINT_OPERAND_ADDRESS
3255
#define TARGET_PRINT_OPERAND_ADDRESS            rx_print_operand_address
3256
 
3257
#undef  TARGET_CC_MODES_COMPATIBLE
3258
#define TARGET_CC_MODES_COMPATIBLE              rx_cc_modes_compatible
3259
 
3260
#undef  TARGET_MEMORY_MOVE_COST
3261
#define TARGET_MEMORY_MOVE_COST                 rx_memory_move_cost
3262
 
3263
#undef  TARGET_OPTION_OVERRIDE
3264
#define TARGET_OPTION_OVERRIDE                  rx_option_override
3265
 
3266
#undef  TARGET_PROMOTE_FUNCTION_MODE
3267
#define TARGET_PROMOTE_FUNCTION_MODE            rx_promote_function_mode
3268
 
3269
#undef  TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
3270
#define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE    rx_override_options_after_change
3271
 
3272
#undef  TARGET_FLAGS_REGNUM
3273
#define TARGET_FLAGS_REGNUM                     CC_REG
3274
 
3275
#undef  TARGET_LEGITIMATE_CONSTANT_P
3276
#define TARGET_LEGITIMATE_CONSTANT_P            rx_is_legitimate_constant
3277
 
3278
#undef  TARGET_LEGITIMIZE_ADDRESS
3279
#define TARGET_LEGITIMIZE_ADDRESS               rx_legitimize_address
3280
 
3281
struct gcc_target targetm = TARGET_INITIALIZER;
3282
 
3283
#include "gt-rx.h"

powered by: WebSVN 2.1.0

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