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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [config/] [fr30/] [fr30.c] - Blame information for rev 282

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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