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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [config/] [fr30/] [fr30.c] - Blame information for rev 820

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

Line No. Rev Author Line
1 38 julius
/* FR30 specific functions.
2
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007
3
   Free Software Foundation, Inc.
4
   Contributed by Cygnus Solutions.
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
/*{{{  Includes */
23
 
24
#include "config.h"
25
#include "system.h"
26
#include "coretypes.h"
27
#include "tm.h"
28
#include "rtl.h"
29
#include "regs.h"
30
#include "hard-reg-set.h"
31
#include "real.h"
32
#include "insn-config.h"
33
#include "conditions.h"
34
#include "insn-attr.h"
35
#include "flags.h"
36
#include "recog.h"
37
#include "tree.h"
38
#include "output.h"
39
#include "expr.h"
40
#include "obstack.h"
41
#include "except.h"
42
#include "function.h"
43
#include "toplev.h"
44
#include "tm_p.h"
45
#include "target.h"
46
#include "target-def.h"
47
 
48
/*}}}*/
49
/*{{{  Function Prologues & Epilogues */
50
 
51
/* Define the information needed to generate branch and scc insns.  This is
52
   stored from the compare operation.  */
53
 
54
struct rtx_def * fr30_compare_op0;
55
struct rtx_def * fr30_compare_op1;
56
 
57
/* The FR30 stack looks like this:
58
 
59
             Before call                       After call
60
   FP ->|                       |       |                       |
61
        +-----------------------+       +-----------------------+       high
62
        |                       |       |                       |       memory
63
        |  local variables,     |       |  local variables,     |
64
        |  reg save area, etc.  |       |  reg save area, etc.  |
65
        |                       |       |                       |
66
        +-----------------------+       +-----------------------+
67
        |                       |       |                       |
68
        | args to the func that |       |  args to this func.   |
69
        | is being called that  |       |                       |
70
   SP ->| do not fit in regs    |       |                       |
71
        +-----------------------+       +-----------------------+
72
                                        |  args that used to be |  \
73
                                        | in regs; only created |   |  pretend_size
74
                                   AP-> |   for vararg funcs    |  /
75
                                        +-----------------------+
76
                                        |                       |  \
77
                                        |  register save area   |   |
78
                                        |                       |   |
79
                                        +-----------------------+   |  reg_size
80
                                        |    return address     |   |
81
                                        +-----------------------+   |
82
                                   FP ->|   previous frame ptr  |  /
83
                                        +-----------------------+
84
                                        |                       |  \
85
                                        |  local variables      |   |  var_size
86
                                        |                       |  /
87
                                        +-----------------------+
88
                                        |                       |  \
89
     low                                |  room for args to     |   |
90
     memory                             |  other funcs called   |   |  args_size
91
                                        |  from this one        |   |
92
                                   SP ->|                       |  /
93
                                        +-----------------------+
94
 
95
   Note, AP is a fake hard register.  It will be eliminated in favor of
96
   SP or FP as appropriate.
97
 
98
   Note, Some or all of the stack sections above may be omitted if they
99
   are not needed.  */
100
 
101
/* Structure to be filled in by fr30_compute_frame_size() with register
102
   save masks, and offsets for the current function.  */
103
struct fr30_frame_info
104
{
105
  unsigned int total_size;      /* # Bytes that the entire frame takes up.  */
106
  unsigned int pretend_size;    /* # Bytes we push and pretend caller did.  */
107
  unsigned int args_size;       /* # Bytes that outgoing arguments take up.  */
108
  unsigned int reg_size;        /* # Bytes needed to store regs.  */
109
  unsigned int var_size;        /* # Bytes that variables take up.  */
110
  unsigned int frame_size;      /* # Bytes in current frame.  */
111
  unsigned int gmask;           /* Mask of saved registers.  */
112
  unsigned int save_fp;         /* Nonzero if frame pointer must be saved.  */
113
  unsigned int save_rp;         /* Nonzero if return pointer must be saved.  */
114
  int          initialised;     /* Nonzero if frame size already calculated.  */
115
};
116
 
117
/* Current frame information calculated by fr30_compute_frame_size().  */
118
static struct fr30_frame_info   current_frame_info;
119
 
120
/* Zero structure to initialize current_frame_info.  */
121
static struct fr30_frame_info   zero_frame_info;
122
 
123
static void fr30_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
124
                                         tree, int *, int);
125
static bool fr30_must_pass_in_stack (enum machine_mode, tree);
126
static int fr30_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
127
                                   tree, bool);
128
 
129
 
130
#define FRAME_POINTER_MASK      (1 << (FRAME_POINTER_REGNUM))
131
#define RETURN_POINTER_MASK     (1 << (RETURN_POINTER_REGNUM))
132
 
133
/* Tell prologue and epilogue if register REGNO should be saved / restored.
134
   The return address and frame pointer are treated separately.
135
   Don't consider them here.  */
136
#define MUST_SAVE_REGISTER(regno)      \
137
  (   (regno) != RETURN_POINTER_REGNUM \
138
   && (regno) != FRAME_POINTER_REGNUM  \
139
   &&   regs_ever_live [regno]         \
140
   && ! call_used_regs [regno]         )
141
 
142
#define MUST_SAVE_FRAME_POINTER  (regs_ever_live [FRAME_POINTER_REGNUM]  || frame_pointer_needed)
143
#define MUST_SAVE_RETURN_POINTER (regs_ever_live [RETURN_POINTER_REGNUM] || current_function_profile)
144
 
145
#if UNITS_PER_WORD == 4
146
#define WORD_ALIGN(SIZE) (((SIZE) + 3) & ~3)
147
#endif
148
 
149
/* Initialize the GCC target structure.  */
150
#undef  TARGET_ASM_ALIGNED_HI_OP
151
#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
152
#undef  TARGET_ASM_ALIGNED_SI_OP
153
#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
154
 
155
#undef  TARGET_PROMOTE_PROTOTYPES
156
#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
157
#undef  TARGET_PASS_BY_REFERENCE
158
#define TARGET_PASS_BY_REFERENCE hook_pass_by_reference_must_pass_in_stack
159
#undef  TARGET_ARG_PARTIAL_BYTES
160
#define TARGET_ARG_PARTIAL_BYTES fr30_arg_partial_bytes
161
 
162
#undef  TARGET_SETUP_INCOMING_VARARGS
163
#define TARGET_SETUP_INCOMING_VARARGS fr30_setup_incoming_varargs
164
#undef  TARGET_MUST_PASS_IN_STACK
165
#define TARGET_MUST_PASS_IN_STACK fr30_must_pass_in_stack
166
 
167
struct gcc_target targetm = TARGET_INITIALIZER;
168
 
169
/* Returns the number of bytes offset between FROM_REG and TO_REG
170
   for the current function.  As a side effect it fills in the
171
   current_frame_info structure, if the data is available.  */
172
unsigned int
173
fr30_compute_frame_size (int from_reg, int to_reg)
174
{
175
  int           regno;
176
  unsigned int  return_value;
177
  unsigned int  var_size;
178
  unsigned int  args_size;
179
  unsigned int  pretend_size;
180
  unsigned int  reg_size;
181
  unsigned int  gmask;
182
 
183
  var_size      = WORD_ALIGN (get_frame_size ());
184
  args_size     = WORD_ALIGN (current_function_outgoing_args_size);
185
  pretend_size  = current_function_pretend_args_size;
186
 
187
  reg_size      = 0;
188
  gmask         = 0;
189
 
190
  /* Calculate space needed for registers.  */
191
  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++)
192
    {
193
      if (MUST_SAVE_REGISTER (regno))
194
        {
195
          reg_size += UNITS_PER_WORD;
196
          gmask |= 1 << regno;
197
        }
198
    }
199
 
200
  current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER;
201
  current_frame_info.save_rp = MUST_SAVE_RETURN_POINTER;
202
 
203
  reg_size += (current_frame_info.save_fp + current_frame_info.save_rp)
204
               * UNITS_PER_WORD;
205
 
206
  /* Save computed information.  */
207
  current_frame_info.pretend_size = pretend_size;
208
  current_frame_info.var_size     = var_size;
209
  current_frame_info.args_size    = args_size;
210
  current_frame_info.reg_size     = reg_size;
211
  current_frame_info.frame_size   = args_size + var_size;
212
  current_frame_info.total_size   = args_size + var_size + reg_size + pretend_size;
213
  current_frame_info.gmask        = gmask;
214
  current_frame_info.initialised  = reload_completed;
215
 
216
  /* Calculate the required distance.  */
217
  return_value = 0;
218
 
219
  if (to_reg == STACK_POINTER_REGNUM)
220
    return_value += args_size + var_size;
221
 
222
  if (from_reg == ARG_POINTER_REGNUM)
223
    return_value += reg_size;
224
 
225
  return return_value;
226
}
227
 
228
/* Called after register allocation to add any instructions needed for the
229
   prologue.  Using a prologue insn is favored compared to putting all of the
230
   instructions in output_function_prologue(), since it allows the scheduler
231
   to intermix instructions with the saves of the caller saved registers.  In
232
   some cases, it might be necessary to emit a barrier instruction as the last
233
   insn to prevent such scheduling.  */
234
 
235
void
236
fr30_expand_prologue (void)
237
{
238
  int regno;
239
  rtx insn;
240
 
241
  if (! current_frame_info.initialised)
242
    fr30_compute_frame_size (0, 0);
243
 
244
  /* This cases shouldn't happen.  Catch it now.  */
245
  gcc_assert (current_frame_info.total_size || !current_frame_info.gmask);
246
 
247
  /* Allocate space for register arguments if this is a variadic function.  */
248
  if (current_frame_info.pretend_size)
249
    {
250
      int regs_to_save = current_frame_info.pretend_size / UNITS_PER_WORD;
251
 
252
      /* Push argument registers into the pretend arg area.  */
253
      for (regno = FIRST_ARG_REGNUM + FR30_NUM_ARG_REGS; regno --, regs_to_save --;)
254
        {
255
          insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
256
          RTX_FRAME_RELATED_P (insn) = 1;
257
        }
258
    }
259
 
260
  if (current_frame_info.gmask)
261
    {
262
      /* Save any needed call-saved regs.  */
263
      for (regno = STACK_POINTER_REGNUM; regno--;)
264
        {
265
          if ((current_frame_info.gmask & (1 << regno)) != 0)
266
            {
267
              insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
268
              RTX_FRAME_RELATED_P (insn) = 1;
269
            }
270
        }
271
    }
272
 
273
  /* Save return address if necessary.  */
274
  if (current_frame_info.save_rp)
275
    {
276
      insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode,
277
                                                     RETURN_POINTER_REGNUM)));
278
      RTX_FRAME_RELATED_P (insn) = 1;
279
    }
280
 
281
  /* Save old frame pointer and create new one, if necessary.  */
282
  if (current_frame_info.save_fp)
283
    {
284
      if (current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
285
        {
286
          int enter_size = current_frame_info.frame_size + UNITS_PER_WORD;
287
          rtx pattern;
288
 
289
          insn = emit_insn (gen_enter_func (GEN_INT (enter_size)));
290
          RTX_FRAME_RELATED_P (insn) = 1;
291
 
292
          pattern = PATTERN (insn);
293
 
294
          /* Also mark all 3 subexpressions as RTX_FRAME_RELATED_P. */
295
          if (GET_CODE (pattern) == PARALLEL)
296
            {
297
              int x;
298
              for (x = XVECLEN (pattern, 0); x--;)
299
                {
300
                  rtx part = XVECEXP (pattern, 0, x);
301
 
302
                  /* One of the insns in the ENTER pattern updates the
303
                     frame pointer.  If we do not actually need the frame
304
                     pointer in this function then this is a side effect
305
                     rather than a desired effect, so we do not mark that
306
                     insn as being related to the frame set up.  Doing this
307
                     allows us to compile the crash66.C test file in the
308
                     G++ testsuite.  */
309
                  if (! frame_pointer_needed
310
                      && GET_CODE (part) == SET
311
                      && REGNO (SET_DEST (part)) == HARD_FRAME_POINTER_REGNUM)
312
                    RTX_FRAME_RELATED_P (part) = 0;
313
                  else
314
                    RTX_FRAME_RELATED_P (part) = 1;
315
                }
316
            }
317
        }
318
      else
319
        {
320
          insn = emit_insn (gen_movsi_push (frame_pointer_rtx));
321
          RTX_FRAME_RELATED_P (insn) = 1;
322
 
323
          if (frame_pointer_needed)
324
            {
325
              insn = emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
326
              RTX_FRAME_RELATED_P (insn) = 1;
327
            }
328
        }
329
    }
330
 
331
  /* Allocate the stack frame.  */
332
  if (current_frame_info.frame_size == 0)
333
    ; /* Nothing to do.  */
334
  else if (current_frame_info.save_fp
335
           && current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
336
    ; /* Nothing to do.  */
337
  else if (current_frame_info.frame_size <= 512)
338
    {
339
      insn = emit_insn (gen_add_to_stack (GEN_INT (- current_frame_info.frame_size)));
340
      RTX_FRAME_RELATED_P (insn) = 1;
341
    }
342
  else
343
    {
344
      rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
345
      insn = emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
346
      RTX_FRAME_RELATED_P (insn) = 1;
347
      insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
348
      RTX_FRAME_RELATED_P (insn) = 1;
349
    }
350
 
351
  if (current_function_profile)
352
    emit_insn (gen_blockage ());
353
}
354
 
355
/* Called after register allocation to add any instructions needed for the
356
   epilogue.  Using an epilogue insn is favored compared to putting all of the
357
   instructions in output_function_epilogue(), since it allows the scheduler
358
   to intermix instructions with the restores of the caller saved registers.
359
   In some cases, it might be necessary to emit a barrier instruction as the
360
   first insn to prevent such scheduling.  */
361
void
362
fr30_expand_epilogue (void)
363
{
364
  int regno;
365
 
366
  /* Perform the inversion operations of the prologue.  */
367
  gcc_assert (current_frame_info.initialised);
368
 
369
  /* Pop local variables and arguments off the stack.
370
     If frame_pointer_needed is TRUE then the frame pointer register
371
     has actually been used as a frame pointer, and we can recover
372
     the stack pointer from it, otherwise we must unwind the stack
373
     manually.  */
374
  if (current_frame_info.frame_size > 0)
375
    {
376
      if (current_frame_info.save_fp && frame_pointer_needed)
377
        {
378
          emit_insn (gen_leave_func ());
379
          current_frame_info.save_fp = 0;
380
        }
381
      else if (current_frame_info.frame_size <= 508)
382
        emit_insn (gen_add_to_stack
383
                   (GEN_INT (current_frame_info.frame_size)));
384
      else
385
        {
386
          rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
387
          emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
388
          emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
389
        }
390
    }
391
 
392
  if (current_frame_info.save_fp)
393
    emit_insn (gen_movsi_pop (frame_pointer_rtx));
394
 
395
  /* Pop all the registers that were pushed.  */
396
  if (current_frame_info.save_rp)
397
    emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, RETURN_POINTER_REGNUM)));
398
 
399
  for (regno = 0; regno < STACK_POINTER_REGNUM; regno ++)
400
    if (current_frame_info.gmask & (1 << regno))
401
      emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, regno)));
402
 
403
  if (current_frame_info.pretend_size)
404
    emit_insn (gen_add_to_stack (GEN_INT (current_frame_info.pretend_size)));
405
 
406
  /* Reset state info for each function.  */
407
  current_frame_info = zero_frame_info;
408
 
409
  emit_jump_insn (gen_return_from_func ());
410
}
411
 
412
/* Do any needed setup for a variadic function.  We must create a register
413
   parameter block, and then copy any anonymous arguments, plus the last
414
   named argument, from registers into memory.  * copying actually done in
415
   fr30_expand_prologue().
416
 
417
   ARG_REGS_USED_SO_FAR has *not* been updated for the last named argument
418
   which has type TYPE and mode MODE, and we rely on this fact.  */
419
void
420
fr30_setup_incoming_varargs (CUMULATIVE_ARGS *arg_regs_used_so_far,
421
                             enum machine_mode mode,
422
                             tree type ATTRIBUTE_UNUSED,
423
                             int *pretend_size,
424
                             int second_time ATTRIBUTE_UNUSED)
425
{
426
  int size;
427
 
428
  /* All BLKmode values are passed by reference.  */
429
  gcc_assert (mode != BLKmode);
430
 
431
  /* ??? This run-time test as well as the code inside the if
432
     statement is probably unnecessary.  */
433
  if (targetm.calls.strict_argument_naming (arg_regs_used_so_far))
434
    /* If TARGET_STRICT_ARGUMENT_NAMING returns true, then the last named
435
       arg must not be treated as an anonymous arg.  */
436
    arg_regs_used_so_far += fr30_num_arg_regs (mode, type);
437
 
438
  size = FR30_NUM_ARG_REGS - (* arg_regs_used_so_far);
439
 
440
  if (size <= 0)
441
    return;
442
 
443
  * pretend_size = (size * UNITS_PER_WORD);
444
}
445
 
446
/*}}}*/
447
/*{{{  Printing operands */
448
 
449
/* Print a memory address as an operand to reference that memory location.  */
450
 
451
void
452
fr30_print_operand_address (FILE *stream, rtx address)
453
{
454
  switch (GET_CODE (address))
455
    {
456
    case SYMBOL_REF:
457
      output_addr_const (stream, address);
458
      break;
459
 
460
    default:
461
      fprintf (stderr, "code = %x\n", GET_CODE (address));
462
      debug_rtx (address);
463
      output_operand_lossage ("fr30_print_operand_address: unhandled address");
464
      break;
465
    }
466
}
467
 
468
/* Print an operand.  */
469
 
470
void
471
fr30_print_operand (FILE *file, rtx x, int code)
472
{
473
  rtx x0;
474
 
475
  switch (code)
476
    {
477
    case '#':
478
      /* Output a :D if this instruction is delayed.  */
479
      if (dbr_sequence_length () != 0)
480
        fputs (":D", file);
481
      return;
482
 
483
    case 'p':
484
      /* Compute the register name of the second register in a hi/lo
485
         register pair.  */
486
      if (GET_CODE (x) != REG)
487
        output_operand_lossage ("fr30_print_operand: unrecognized %%p code");
488
      else
489
        fprintf (file, "r%d", REGNO (x) + 1);
490
      return;
491
 
492
    case 'b':
493
      /* Convert GCC's comparison operators into FR30 comparison codes.  */
494
      switch (GET_CODE (x))
495
        {
496
        case EQ:  fprintf (file, "eq"); break;
497
        case NE:  fprintf (file, "ne"); break;
498
        case LT:  fprintf (file, "lt"); break;
499
        case LE:  fprintf (file, "le"); break;
500
        case GT:  fprintf (file, "gt"); break;
501
        case GE:  fprintf (file, "ge"); break;
502
        case LTU: fprintf (file, "c"); break;
503
        case LEU: fprintf (file, "ls"); break;
504
        case GTU: fprintf (file, "hi"); break;
505
        case GEU: fprintf (file, "nc");  break;
506
        default:
507
          output_operand_lossage ("fr30_print_operand: unrecognized %%b code");
508
          break;
509
        }
510
      return;
511
 
512
    case 'B':
513
      /* Convert GCC's comparison operators into the complimentary FR30
514
         comparison codes.  */
515
      switch (GET_CODE (x))
516
        {
517
        case EQ:  fprintf (file, "ne"); break;
518
        case NE:  fprintf (file, "eq"); break;
519
        case LT:  fprintf (file, "ge"); break;
520
        case LE:  fprintf (file, "gt"); break;
521
        case GT:  fprintf (file, "le"); break;
522
        case GE:  fprintf (file, "lt"); break;
523
        case LTU: fprintf (file, "nc"); break;
524
        case LEU: fprintf (file, "hi"); break;
525
        case GTU: fprintf (file, "ls"); break;
526
        case GEU: fprintf (file, "c"); break;
527
        default:
528
          output_operand_lossage ("fr30_print_operand: unrecognized %%B code");
529
          break;
530
        }
531
      return;
532
 
533
    case 'A':
534
      /* Print a signed byte value as an unsigned value.  */
535
      if (GET_CODE (x) != CONST_INT)
536
        output_operand_lossage ("fr30_print_operand: invalid operand to %%A code");
537
      else
538
        {
539
          HOST_WIDE_INT val;
540
 
541
          val = INTVAL (x);
542
 
543
          val &= 0xff;
544
 
545
          fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
546
        }
547
      return;
548
 
549
    case 'x':
550
      if (GET_CODE (x) != CONST_INT
551
          || INTVAL (x) < 16
552
          || INTVAL (x) > 32)
553
        output_operand_lossage ("fr30_print_operand: invalid %%x code");
554
      else
555
        fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) - 16);
556
      return;
557
 
558
    case 'F':
559
      if (GET_CODE (x) != CONST_DOUBLE)
560
        output_operand_lossage ("fr30_print_operand: invalid %%F code");
561
      else
562
        {
563
          char str[30];
564
 
565
          real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x),
566
                           sizeof (str), 0, 1);
567
          fputs (str, file);
568
        }
569
      return;
570
 
571
    case 0:
572
      /* Handled below.  */
573
      break;
574
 
575
    default:
576
      fprintf (stderr, "unknown code = %x\n", code);
577
      output_operand_lossage ("fr30_print_operand: unknown code");
578
      return;
579
    }
580
 
581
  switch (GET_CODE (x))
582
    {
583
    case REG:
584
      fputs (reg_names [REGNO (x)], file);
585
      break;
586
 
587
    case MEM:
588
      x0 = XEXP (x,0);
589
 
590
      switch (GET_CODE (x0))
591
        {
592
        case REG:
593
          gcc_assert ((unsigned) REGNO (x0) < ARRAY_SIZE (reg_names));
594
          fprintf (file, "@%s", reg_names [REGNO (x0)]);
595
          break;
596
 
597
        case PLUS:
598
          if (GET_CODE (XEXP (x0, 0)) != REG
599
              || REGNO (XEXP (x0, 0)) < FRAME_POINTER_REGNUM
600
              || REGNO (XEXP (x0, 0)) > STACK_POINTER_REGNUM
601
              || GET_CODE (XEXP (x0, 1)) != CONST_INT)
602
            {
603
              fprintf (stderr, "bad INDEXed address:");
604
              debug_rtx (x);
605
              output_operand_lossage ("fr30_print_operand: unhandled MEM");
606
            }
607
          else if (REGNO (XEXP (x0, 0)) == FRAME_POINTER_REGNUM)
608
            {
609
              HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
610
              if (val < -(1 << 9) || val > ((1 << 9) - 4))
611
                {
612
                  fprintf (stderr, "frame INDEX out of range:");
613
                  debug_rtx (x);
614
                  output_operand_lossage ("fr30_print_operand: unhandled MEM");
615
                }
616
              fprintf (file, "@(r14, #" HOST_WIDE_INT_PRINT_DEC ")", val);
617
            }
618
          else
619
            {
620
              HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
621
              if (val < 0 || val > ((1 << 6) - 4))
622
                {
623
                  fprintf (stderr, "stack INDEX out of range:");
624
                  debug_rtx (x);
625
                  output_operand_lossage ("fr30_print_operand: unhandled MEM");
626
                }
627
              fprintf (file, "@(r15, #" HOST_WIDE_INT_PRINT_DEC ")", val);
628
            }
629
          break;
630
 
631
        case SYMBOL_REF:
632
          output_address (x0);
633
          break;
634
 
635
        default:
636
          fprintf (stderr, "bad MEM code = %x\n", GET_CODE (x0));
637
          debug_rtx (x);
638
          output_operand_lossage ("fr30_print_operand: unhandled MEM");
639
          break;
640
        }
641
      break;
642
 
643
    case CONST_DOUBLE :
644
      /* We handle SFmode constants here as output_addr_const doesn't.  */
645
      if (GET_MODE (x) == SFmode)
646
        {
647
          REAL_VALUE_TYPE d;
648
          long l;
649
 
650
          REAL_VALUE_FROM_CONST_DOUBLE (d, x);
651
          REAL_VALUE_TO_TARGET_SINGLE (d, l);
652
          fprintf (file, "0x%08lx", l);
653
          break;
654
        }
655
 
656
      /* Fall through.  Let output_addr_const deal with it.  */
657
    default:
658
      output_addr_const (file, x);
659
      break;
660
    }
661
 
662
  return;
663
}
664
 
665
/*}}}*/
666
/*{{{  Function arguments */
667
 
668
/* Return true if we should pass an argument on the stack rather than
669
   in registers.  */
670
 
671
static bool
672
fr30_must_pass_in_stack (enum machine_mode mode, tree type)
673
{
674
  if (mode == BLKmode)
675
    return true;
676
  if (type == NULL)
677
    return false;
678
  return AGGREGATE_TYPE_P (type);
679
}
680
 
681
/* Compute the number of word sized registers needed to hold a
682
   function argument of mode INT_MODE and tree type TYPE.  */
683
int
684
fr30_num_arg_regs (enum machine_mode mode, tree type)
685
{
686
  int size;
687
 
688
  if (targetm.calls.must_pass_in_stack (mode, type))
689
    return 0;
690
 
691
  if (type && mode == BLKmode)
692
    size = int_size_in_bytes (type);
693
  else
694
    size = GET_MODE_SIZE (mode);
695
 
696
  return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
697
}
698
 
699
/* Returns the number of bytes in which *part* of a parameter of machine
700
   mode MODE and tree type TYPE (which may be NULL if the type is not known).
701
   If the argument fits entirely in the argument registers, or entirely on
702
   the stack, then 0 is returned.
703
   CUM is the number of argument registers already used by earlier
704
   parameters to the function.  */
705
 
706
static int
707
fr30_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
708
                        tree type, bool named)
709
{
710
  /* Unnamed arguments, i.e. those that are prototyped as ...
711
     are always passed on the stack.
712
     Also check here to see if all the argument registers are full.  */
713
  if (named == 0 || *cum >= FR30_NUM_ARG_REGS)
714
    return 0;
715
 
716
  /* Work out how many argument registers would be needed if this
717
     parameter were to be passed entirely in registers.  If there
718
     are sufficient argument registers available (or if no registers
719
     are needed because the parameter must be passed on the stack)
720
     then return zero, as this parameter does not require partial
721
     register, partial stack stack space.  */
722
  if (*cum + fr30_num_arg_regs (mode, type) <= FR30_NUM_ARG_REGS)
723
    return 0;
724
 
725
  return (FR30_NUM_ARG_REGS - *cum) * UNITS_PER_WORD;
726
}
727
 
728
/*}}}*/
729
/*{{{  Operand predicates */
730
 
731
#ifndef Mmode
732
#define Mmode enum machine_mode
733
#endif
734
 
735
/* Returns true iff all the registers in the operands array
736
   are in descending or ascending order.  */
737
int
738
fr30_check_multiple_regs (rtx *operands, int num_operands, int descending)
739
{
740
  if (descending)
741
    {
742
      unsigned int prev_regno = 0;
743
 
744
      while (num_operands --)
745
        {
746
          if (GET_CODE (operands [num_operands]) != REG)
747
            return 0;
748
 
749
          if (REGNO (operands [num_operands]) < prev_regno)
750
            return 0;
751
 
752
          prev_regno = REGNO (operands [num_operands]);
753
        }
754
    }
755
  else
756
    {
757
      unsigned int prev_regno = CONDITION_CODE_REGNUM;
758
 
759
      while (num_operands --)
760
        {
761
          if (GET_CODE (operands [num_operands]) != REG)
762
            return 0;
763
 
764
          if (REGNO (operands [num_operands]) > prev_regno)
765
            return 0;
766
 
767
          prev_regno = REGNO (operands [num_operands]);
768
        }
769
    }
770
 
771
  return 1;
772
}
773
 
774
int
775
fr30_const_double_is_zero (rtx operand)
776
{
777
  REAL_VALUE_TYPE d;
778
 
779
  if (operand == NULL || GET_CODE (operand) != CONST_DOUBLE)
780
    return 0;
781
 
782
  REAL_VALUE_FROM_CONST_DOUBLE (d, operand);
783
 
784
  return REAL_VALUES_EQUAL (d, dconst0);
785
}
786
 
787
/*}}}*/
788
/*{{{  Instruction Output Routines  */
789
 
790
/* Output a double word move.
791
   It must be REG<-REG, REG<-MEM, MEM<-REG or REG<-CONST.
792
   On the FR30 we are constrained by the fact that it does not
793
   support offsetable addresses, and so we have to load the
794
   address of the secnd word into the second destination register
795
   before we can use it.  */
796
 
797
rtx
798
fr30_move_double (rtx * operands)
799
{
800
  rtx src  = operands[1];
801
  rtx dest = operands[0];
802
  enum rtx_code src_code = GET_CODE (src);
803
  enum rtx_code dest_code = GET_CODE (dest);
804
  enum machine_mode mode = GET_MODE (dest);
805
  rtx val;
806
 
807
  start_sequence ();
808
 
809
  if (dest_code == REG)
810
    {
811
      if (src_code == REG)
812
        {
813
          int reverse = (REGNO (dest) == REGNO (src) + 1);
814
 
815
          /* We normally copy the low-numbered register first.  However, if
816
             the first register of operand 0 is the same as the second register
817
             of operand 1, we must copy in the opposite order.  */
818
          emit_insn (gen_rtx_SET (VOIDmode,
819
                                  operand_subword (dest, reverse, TRUE, mode),
820
                                  operand_subword (src,  reverse, TRUE, mode)));
821
 
822
          emit_insn (gen_rtx_SET (VOIDmode,
823
                              operand_subword (dest, !reverse, TRUE, mode),
824
                              operand_subword (src,  !reverse, TRUE, mode)));
825
        }
826
      else if (src_code == MEM)
827
        {
828
          rtx addr = XEXP (src, 0);
829
          int dregno = REGNO (dest);
830
          rtx dest0;
831
          rtx dest1;
832
          rtx new_mem;
833
 
834
          /* If the high-address word is used in the address, we
835
             must load it last.  Otherwise, load it first.  */
836
          int reverse = (refers_to_regno_p (dregno, dregno + 1, addr, 0) != 0);
837
 
838
          gcc_assert (GET_CODE (addr) == REG);
839
 
840
          dest0 = operand_subword (dest, reverse, TRUE, mode);
841
          dest1 = operand_subword (dest, !reverse, TRUE, mode);
842
 
843
          if (reverse)
844
            {
845
              emit_insn (gen_rtx_SET (VOIDmode, dest1,
846
                                      adjust_address (src, SImode, 0)));
847
              emit_insn (gen_rtx_SET (SImode, dest0,
848
                                      gen_rtx_REG (SImode, REGNO (addr))));
849
              emit_insn (gen_rtx_SET (SImode, dest0,
850
                                      plus_constant (dest0, UNITS_PER_WORD)));
851
 
852
              new_mem = gen_rtx_MEM (SImode, dest0);
853
              MEM_COPY_ATTRIBUTES (new_mem, src);
854
 
855
              emit_insn (gen_rtx_SET (VOIDmode, dest0, new_mem));
856
            }
857
          else
858
            {
859
              emit_insn (gen_rtx_SET (VOIDmode, dest0,
860
                                      adjust_address (src, SImode, 0)));
861
              emit_insn (gen_rtx_SET (SImode, dest1,
862
                                      gen_rtx_REG (SImode, REGNO (addr))));
863
              emit_insn (gen_rtx_SET (SImode, dest1,
864
                                      plus_constant (dest1, UNITS_PER_WORD)));
865
 
866
              new_mem = gen_rtx_MEM (SImode, dest1);
867
              MEM_COPY_ATTRIBUTES (new_mem, src);
868
 
869
              emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem));
870
            }
871
        }
872
      else if (src_code == CONST_INT || src_code == CONST_DOUBLE)
873
        {
874
          rtx words[2];
875
          split_double (src, &words[0], &words[1]);
876
          emit_insn (gen_rtx_SET (VOIDmode,
877
                                  operand_subword (dest, 0, TRUE, mode),
878
                                  words[0]));
879
 
880
          emit_insn (gen_rtx_SET (VOIDmode,
881
                                  operand_subword (dest, 1, TRUE, mode),
882
                                  words[1]));
883
        }
884
    }
885
  else if (src_code == REG && dest_code == MEM)
886
    {
887
      rtx addr = XEXP (dest, 0);
888
      rtx src0;
889
      rtx src1;
890
 
891
      gcc_assert (GET_CODE (addr) == REG);
892
 
893
      src0 = operand_subword (src, 0, TRUE, mode);
894
      src1 = operand_subword (src, 1, TRUE, mode);
895
 
896
      emit_insn (gen_rtx_SET (VOIDmode, adjust_address (dest, SImode, 0),
897
                              src0));
898
 
899
      if (REGNO (addr) == STACK_POINTER_REGNUM
900
          || REGNO (addr) == FRAME_POINTER_REGNUM)
901
        emit_insn (gen_rtx_SET (VOIDmode,
902
                                adjust_address (dest, SImode, UNITS_PER_WORD),
903
                                src1));
904
      else
905
        {
906
          rtx new_mem;
907
 
908
          /* We need a scratch register to hold the value of 'address + 4'.
909
             We ought to allow gcc to find one for us, but for now, just
910
             push one of the source registers.  */
911
          emit_insn (gen_movsi_push (src0));
912
          emit_insn (gen_movsi_internal (src0, addr));
913
          emit_insn (gen_addsi_small_int (src0, src0, GEN_INT (UNITS_PER_WORD)));
914
 
915
          new_mem = gen_rtx_MEM (SImode, src0);
916
          MEM_COPY_ATTRIBUTES (new_mem, dest);
917
 
918
          emit_insn (gen_rtx_SET (VOIDmode, new_mem, src1));
919
          emit_insn (gen_movsi_pop (src0));
920
        }
921
    }
922
  else
923
    /* This should have been prevented by the constraints on movdi_insn.  */
924
    gcc_unreachable ();
925
 
926
  val = get_insns ();
927
  end_sequence ();
928
 
929
  return val;
930
}
931
/*}}}*/
932
/* Local Variables: */
933
/* folded-file: t   */
934
/* End:             */

powered by: WebSVN 2.1.0

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