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

Subversion Repositories openrisc

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

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

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

powered by: WebSVN 2.1.0

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