OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

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

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

Line No. Rev Author Line
1 282 jeremybenn
/* Subroutines used for code generation on the Lattice Mico32 architecture.
2
   Contributed by Jon Beniston <jon@beniston.com>
3
 
4
   Copyright (C) 2009 Free Software Foundation, Inc.
5
 
6
   This file is part of GCC.
7
 
8
   GCC is free software; you can redistribute it and/or modify it
9
   under the terms of the GNU General Public License as published
10
   by the Free Software Foundation; either version 3, or (at your
11
   option) any later version.
12
 
13
   GCC is distributed in the hope that it will be useful, but WITHOUT
14
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16
   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
#include "config.h"
23
#include "system.h"
24
#include "coretypes.h"
25
#include "tm.h"
26
#include "rtl.h"
27
#include "regs.h"
28
#include "hard-reg-set.h"
29
#include "basic-block.h"
30
#include "real.h"
31
#include "insn-config.h"
32
#include "conditions.h"
33
#include "insn-flags.h"
34
#include "insn-attr.h"
35
#include "insn-codes.h"
36
#include "recog.h"
37
#include "output.h"
38
#include "tree.h"
39
#include "expr.h"
40
#include "flags.h"
41
#include "reload.h"
42
#include "tm_p.h"
43
#include "function.h"
44
#include "toplev.h"
45
#include "optabs.h"
46
#include "libfuncs.h"
47
#include "ggc.h"
48
#include "target.h"
49
#include "target-def.h"
50
#include "langhooks.h"
51
#include "tm-constrs.h"
52
#include "df.h"
53
 
54
struct lm32_frame_info
55
{
56
  HOST_WIDE_INT total_size;     /* number of bytes of entire frame.  */
57
  HOST_WIDE_INT callee_size;    /* number of bytes to save callee saves.  */
58
  HOST_WIDE_INT pretend_size;   /* number of bytes we pretend caller did.  */
59
  HOST_WIDE_INT args_size;      /* number of bytes for outgoing arguments.  */
60
  HOST_WIDE_INT locals_size;    /* number of bytes for local variables.  */
61
  unsigned int reg_save_mask;   /* mask of saved registers.  */
62
};
63
 
64
/* Prototypes for static functions.  */
65
static rtx emit_add (rtx dest, rtx src0, rtx src1);
66
static void expand_save_restore (struct lm32_frame_info *info, int op);
67
static void stack_adjust (HOST_WIDE_INT amount);
68
static bool lm32_in_small_data_p (const_tree);
69
static void lm32_setup_incoming_varargs (CUMULATIVE_ARGS * cum,
70
                                         enum machine_mode mode, tree type,
71
                                         int *pretend_size, int no_rtl);
72
static bool lm32_rtx_costs (rtx x, int code, int outer_code, int *total,
73
                            bool speed);
74
static bool lm32_can_eliminate (const int, const int);
75
static bool
76
lm32_legitimate_address_p (enum machine_mode mode, rtx x, bool strict);
77
static HOST_WIDE_INT lm32_compute_frame_size (int size);
78
 
79
#undef TARGET_ADDRESS_COST
80
#define TARGET_ADDRESS_COST hook_int_rtx_bool_0
81
#undef TARGET_RTX_COSTS
82
#define TARGET_RTX_COSTS lm32_rtx_costs
83
#undef TARGET_IN_SMALL_DATA_P
84
#define TARGET_IN_SMALL_DATA_P lm32_in_small_data_p
85
#undef TARGET_PROMOTE_FUNCTION_MODE
86
#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
87
#undef TARGET_SETUP_INCOMING_VARARGS
88
#define TARGET_SETUP_INCOMING_VARARGS lm32_setup_incoming_varargs
89
#undef TARGET_PROMOTE_PROTOTYPES
90
#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
91
#undef TARGET_MIN_ANCHOR_OFFSET
92
#define TARGET_MIN_ANCHOR_OFFSET -0x8000
93
#undef TARGET_MAX_ANCHOR_OFFSET
94
#define TARGET_MAX_ANCHOR_OFFSET 0x7fff
95
#undef TARGET_CAN_ELIMINATE
96
#define TARGET_CAN_ELIMINATE lm32_can_eliminate
97
#undef TARGET_LEGITIMATE_ADDRESS_P
98
#define TARGET_LEGITIMATE_ADDRESS_P lm32_legitimate_address_p
99
 
100
struct gcc_target targetm = TARGET_INITIALIZER;
101
 
102
/* Current frame information calculated by lm32_compute_frame_size.  */
103
static struct lm32_frame_info current_frame_info;
104
 
105
/* Return non-zero if the given return type should be returned in memory.  */
106
 
107
int
108
lm32_return_in_memory (tree type)
109
{
110
  HOST_WIDE_INT size;
111
 
112
  if (!AGGREGATE_TYPE_P (type))
113
    {
114
      /* All simple types are returned in registers.  */
115
      return 0;
116
    }
117
 
118
  size = int_size_in_bytes (type);
119
  if (size >= 0 && size <= UNITS_PER_WORD)
120
    {
121
      /* If it can fit in one register.  */
122
      return 0;
123
    }
124
 
125
  return 1;
126
}
127
 
128
/* Generate an emit a word sized add instruction.  */
129
 
130
static rtx
131
emit_add (rtx dest, rtx src0, rtx src1)
132
{
133
  rtx insn;
134
  insn = emit_insn (gen_addsi3 (dest, src0, src1));
135
  return insn;
136
}
137
 
138
/* Generate the code to compare (and possibly branch) two integer values
139
   TEST_CODE is the comparison code we are trying to emulate
140
     (or implement directly)
141
   RESULT is where to store the result of the comparison,
142
     or null to emit a branch
143
   CMP0 CMP1 are the two comparison operands
144
   DESTINATION is the destination of the branch, or null to only compare
145
   */
146
 
147
static void
148
gen_int_relational (enum rtx_code code,
149
                    rtx result,
150
                    rtx cmp0,
151
                    rtx cmp1,
152
                    rtx destination)
153
{
154
  enum machine_mode mode;
155
  int branch_p;
156
 
157
  mode = GET_MODE (cmp0);
158
  if (mode == VOIDmode)
159
    mode = GET_MODE (cmp1);
160
 
161
  /* Is this a branch or compare.  */
162
  branch_p = (destination != 0);
163
 
164
  /* Instruction set doesn't support LE or LT, so swap operands and use
165
     GE, GT.  */
166
  switch (code)
167
    {
168
    case LE:
169
    case LT:
170
    case LEU:
171
    case LTU:
172
      code = swap_condition (code);
173
      rtx temp = cmp0;
174
      cmp0 = cmp1;
175
      cmp1 = temp;
176
      break;
177
    default:
178
      break;
179
    }
180
 
181
  if (branch_p)
182
    {
183
      rtx insn;
184
 
185
      /* Operands must be in registers.  */
186
      if (!register_operand (cmp0, mode))
187
        cmp0 = force_reg (mode, cmp0);
188
      if (!register_operand (cmp1, mode))
189
        cmp1 = force_reg (mode, cmp1);
190
 
191
      /* Generate conditional branch instruction.  */
192
      rtx cond = gen_rtx_fmt_ee (code, mode, cmp0, cmp1);
193
      rtx label = gen_rtx_LABEL_REF (VOIDmode, destination);
194
      insn = gen_rtx_SET (VOIDmode, pc_rtx,
195
                          gen_rtx_IF_THEN_ELSE (VOIDmode,
196
                                                cond, label, pc_rtx));
197
      emit_jump_insn (insn);
198
    }
199
  else
200
    {
201
      /* We can't have const_ints in cmp0, other than 0.  */
202
      if ((GET_CODE (cmp0) == CONST_INT) && (INTVAL (cmp0) != 0))
203
        cmp0 = force_reg (mode, cmp0);
204
 
205
      /* If the comparison is against an int not in legal range
206
         move it into a register.  */
207
      if (GET_CODE (cmp1) == CONST_INT)
208
        {
209
          switch (code)
210
            {
211
            case EQ:
212
            case NE:
213
            case LE:
214
            case LT:
215
            case GE:
216
            case GT:
217
              if (!satisfies_constraint_K (cmp1))
218
                cmp1 = force_reg (mode, cmp1);
219
              break;
220
            case LEU:
221
            case LTU:
222
            case GEU:
223
            case GTU:
224
              if (!satisfies_constraint_L (cmp1))
225
                cmp1 = force_reg (mode, cmp1);
226
              break;
227
            default:
228
              gcc_unreachable ();
229
            }
230
        }
231
 
232
      /* Generate compare instruction.  */
233
      emit_move_insn (result, gen_rtx_fmt_ee (code, mode, cmp0, cmp1));
234
    }
235
}
236
 
237
/* Try performing the comparison in OPERANDS[1], whose arms are OPERANDS[2]
238
   and OPERAND[3].  Store the result in OPERANDS[0].  */
239
 
240
void
241
lm32_expand_scc (rtx operands[])
242
{
243
  rtx target = operands[0];
244
  enum rtx_code code = GET_CODE (operands[1]);
245
  rtx op0 = operands[2];
246
  rtx op1 = operands[3];
247
 
248
  gen_int_relational (code, target, op0, op1, NULL_RTX);
249
}
250
 
251
/* Compare OPERANDS[1] with OPERANDS[2] using comparison code
252
   CODE and jump to OPERANDS[3] if the condition holds.  */
253
 
254
void
255
lm32_expand_conditional_branch (rtx operands[])
256
{
257
  enum rtx_code code = GET_CODE (operands[0]);
258
  rtx op0 = operands[1];
259
  rtx op1 = operands[2];
260
  rtx destination = operands[3];
261
 
262
  gen_int_relational (code, NULL_RTX, op0, op1, destination);
263
}
264
 
265
/* Generate and emit RTL to save or restore callee save registers.  */
266
static void
267
expand_save_restore (struct lm32_frame_info *info, int op)
268
{
269
  unsigned int reg_save_mask = info->reg_save_mask;
270
  int regno;
271
  HOST_WIDE_INT offset;
272
  rtx insn;
273
 
274
  /* Callee saves are below locals and above outgoing arguments.  */
275
  offset = info->args_size + info->callee_size;
276
  for (regno = 0; regno <= 31; regno++)
277
    {
278
      if ((reg_save_mask & (1 << regno)) != 0)
279
        {
280
          rtx offset_rtx;
281
          rtx mem;
282
 
283
          offset_rtx = GEN_INT (offset);
284
          if (satisfies_constraint_K (offset_rtx))
285
            {
286
              mem = gen_rtx_MEM (word_mode,
287
                                 gen_rtx_PLUS (Pmode,
288
                                               stack_pointer_rtx,
289
                                               offset_rtx));
290
            }
291
          else
292
            {
293
              /* r10 is caller saved so it can be used as a temp reg.  */
294
              rtx r10;
295
 
296
              r10 = gen_rtx_REG (word_mode, 10);
297
              insn = emit_move_insn (r10, offset_rtx);
298
              if (op == 0)
299
                RTX_FRAME_RELATED_P (insn) = 1;
300
              insn = emit_add (r10, r10, stack_pointer_rtx);
301
              if (op == 0)
302
                RTX_FRAME_RELATED_P (insn) = 1;
303
              mem = gen_rtx_MEM (word_mode, r10);
304
            }
305
 
306
          if (op == 0)
307
            insn = emit_move_insn (mem, gen_rtx_REG (word_mode, regno));
308
          else
309
            insn = emit_move_insn (gen_rtx_REG (word_mode, regno), mem);
310
 
311
          /* only prologue instructions which set the sp fp or save a
312
             register should be marked as frame related.  */
313
          if (op == 0)
314
            RTX_FRAME_RELATED_P (insn) = 1;
315
          offset -= UNITS_PER_WORD;
316
        }
317
    }
318
}
319
 
320
static void
321
stack_adjust (HOST_WIDE_INT amount)
322
{
323
  rtx insn;
324
 
325
  if (!IN_RANGE (amount, -32776, 32768))
326
    {
327
      /* r10 is caller saved so it can be used as a temp reg.  */
328
      rtx r10;
329
      r10 = gen_rtx_REG (word_mode, 10);
330
      insn = emit_move_insn (r10, GEN_INT (amount));
331
      if (amount < 0)
332
        RTX_FRAME_RELATED_P (insn) = 1;
333
      insn = emit_add (stack_pointer_rtx, stack_pointer_rtx, r10);
334
      if (amount < 0)
335
        RTX_FRAME_RELATED_P (insn) = 1;
336
    }
337
  else
338
    {
339
      insn = emit_add (stack_pointer_rtx,
340
                       stack_pointer_rtx, GEN_INT (amount));
341
      if (amount < 0)
342
        RTX_FRAME_RELATED_P (insn) = 1;
343
    }
344
}
345
 
346
 
347
/* Create and emit instructions for a functions prologue.  */
348
void
349
lm32_expand_prologue (void)
350
{
351
  rtx insn;
352
 
353
  lm32_compute_frame_size (get_frame_size ());
354
 
355
  if (current_frame_info.total_size > 0)
356
    {
357
      /* Add space on stack new frame.  */
358
      stack_adjust (-current_frame_info.total_size);
359
 
360
      /* Save callee save registers.  */
361
      if (current_frame_info.reg_save_mask != 0)
362
        expand_save_restore (&current_frame_info, 0);
363
 
364
      /* Setup frame pointer if it's needed.  */
365
      if (frame_pointer_needed == 1)
366
        {
367
          /* Load offset - Don't use total_size, as that includes pretend_size,
368
             which isn't part of this frame?  */
369
          insn =
370
            emit_move_insn (frame_pointer_rtx,
371
                            GEN_INT (current_frame_info.args_size +
372
                                     current_frame_info.callee_size +
373
                                     current_frame_info.locals_size));
374
          RTX_FRAME_RELATED_P (insn) = 1;
375
 
376
          /* Add in sp.  */
377
          insn = emit_add (frame_pointer_rtx,
378
                           frame_pointer_rtx, stack_pointer_rtx);
379
          RTX_FRAME_RELATED_P (insn) = 1;
380
        }
381
 
382
      /* Prevent prologue from being scheduled into function body.  */
383
      emit_insn (gen_blockage ());
384
    }
385
}
386
 
387
/* Create an emit instructions for a functions epilogue.  */
388
void
389
lm32_expand_epilogue (void)
390
{
391
  rtx ra_rtx = gen_rtx_REG (Pmode, RA_REGNUM);
392
 
393
  lm32_compute_frame_size (get_frame_size ());
394
 
395
  if (current_frame_info.total_size > 0)
396
    {
397
      /* Prevent stack code from being reordered.  */
398
      emit_insn (gen_blockage ());
399
 
400
      /* Restore callee save registers.  */
401
      if (current_frame_info.reg_save_mask != 0)
402
        expand_save_restore (&current_frame_info, 1);
403
 
404
      /* Deallocate stack.  */
405
      stack_adjust (current_frame_info.total_size);
406
 
407
      /* Return to calling function.  */
408
      emit_jump_insn (gen_return_internal (ra_rtx));
409
    }
410
  else
411
    {
412
      /* Return to calling function.  */
413
      emit_jump_insn (gen_return_internal (ra_rtx));
414
    }
415
}
416
 
417
/* Return the bytes needed to compute the frame pointer from the current
418
   stack pointer.  */
419
static HOST_WIDE_INT
420
lm32_compute_frame_size (int size)
421
{
422
  int regno;
423
  HOST_WIDE_INT total_size, locals_size, args_size, pretend_size, callee_size;
424
  unsigned int reg_save_mask;
425
 
426
  locals_size = size;
427
  args_size = crtl->outgoing_args_size;
428
  pretend_size = crtl->args.pretend_args_size;
429
  callee_size = 0;
430
  reg_save_mask = 0;
431
 
432
  /* Build mask that actually determines which regsiters we save
433
     and calculate size required to store them in the stack.  */
434
  for (regno = 1; regno < SP_REGNUM; regno++)
435
    {
436
      if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
437
        {
438
          reg_save_mask |= 1 << regno;
439
          callee_size += UNITS_PER_WORD;
440
        }
441
    }
442
  if (df_regs_ever_live_p (RA_REGNUM) || !current_function_is_leaf
443
      || !optimize)
444
    {
445
      reg_save_mask |= 1 << RA_REGNUM;
446
      callee_size += UNITS_PER_WORD;
447
    }
448
  if (!(reg_save_mask & (1 << FP_REGNUM)) && frame_pointer_needed)
449
    {
450
      reg_save_mask |= 1 << FP_REGNUM;
451
      callee_size += UNITS_PER_WORD;
452
    }
453
 
454
  /* Compute total frame size.  */
455
  total_size = pretend_size + args_size + locals_size + callee_size;
456
 
457
  /* Align frame to appropriate boundary.  */
458
  total_size = (total_size + 3) & ~3;
459
 
460
  /* Save computed information.  */
461
  current_frame_info.total_size = total_size;
462
  current_frame_info.callee_size = callee_size;
463
  current_frame_info.pretend_size = pretend_size;
464
  current_frame_info.locals_size = locals_size;
465
  current_frame_info.args_size = args_size;
466
  current_frame_info.reg_save_mask = reg_save_mask;
467
 
468
  return total_size;
469
}
470
 
471
void
472
lm32_print_operand (FILE * file, rtx op, int letter)
473
{
474
  enum rtx_code code;
475
 
476
  code = GET_CODE (op);
477
 
478
  if (code == SIGN_EXTEND)
479
    op = XEXP (op, 0), code = GET_CODE (op);
480
  else if (code == REG || code == SUBREG)
481
    {
482
      int regnum;
483
 
484
      if (code == REG)
485
        regnum = REGNO (op);
486
      else
487
        regnum = true_regnum (op);
488
 
489
      fprintf (file, "%s", reg_names[regnum]);
490
    }
491
  else if (code == HIGH)
492
    output_addr_const (file, XEXP (op, 0));
493
  else if (code == MEM)
494
    output_address (XEXP (op, 0));
495
  else if (letter == 'z' && GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
496
    fprintf (file, "%s", reg_names[0]);
497
  else if (GET_CODE (op) == CONST_DOUBLE)
498
    {
499
      if ((CONST_DOUBLE_LOW (op) != 0) || (CONST_DOUBLE_HIGH (op) != 0))
500
        output_operand_lossage ("Only 0.0 can be loaded as an immediate");
501
      else
502
        fprintf (file, "0");
503
    }
504
  else if (code == EQ)
505
    fprintf (file, "e  ");
506
  else if (code == NE)
507
    fprintf (file, "ne ");
508
  else if (code == GT)
509
    fprintf (file, "g  ");
510
  else if (code == GTU)
511
    fprintf (file, "gu ");
512
  else if (code == LT)
513
    fprintf (file, "l  ");
514
  else if (code == LTU)
515
    fprintf (file, "lu ");
516
  else if (code == GE)
517
    fprintf (file, "ge ");
518
  else if (code == GEU)
519
    fprintf (file, "geu");
520
  else if (code == LE)
521
    fprintf (file, "le ");
522
  else if (code == LEU)
523
    fprintf (file, "leu");
524
  else
525
    output_addr_const (file, op);
526
}
527
 
528
/* A C compound statement to output to stdio stream STREAM the
529
   assembler syntax for an instruction operand that is a memory
530
   reference whose address is ADDR.  ADDR is an RTL expression.
531
 
532
   On some machines, the syntax for a symbolic address depends on
533
   the section that the address refers to.  On these machines,
534
   define the macro `ENCODE_SECTION_INFO' to store the information
535
   into the `symbol_ref', and then check for it here.  */
536
 
537
void
538
lm32_print_operand_address (FILE * file, rtx addr)
539
{
540
  switch (GET_CODE (addr))
541
    {
542
    case REG:
543
      fprintf (file, "(%s+0)", reg_names[REGNO (addr)]);
544
      break;
545
 
546
    case MEM:
547
      output_address (XEXP (addr, 0));
548
      break;
549
 
550
    case PLUS:
551
      {
552
        rtx arg0 = XEXP (addr, 0);
553
        rtx arg1 = XEXP (addr, 1);
554
 
555
        if (GET_CODE (arg0) == REG && CONSTANT_P (arg1))
556
          {
557
            if (GET_CODE (arg1) == CONST_INT)
558
              fprintf (file, "(%s+%ld)", reg_names[REGNO (arg0)],
559
                       INTVAL (arg1));
560
            else
561
              {
562
                fprintf (file, "(%s+", reg_names[REGNO (arg0)]);
563
                output_addr_const (file, arg1);
564
                fprintf (file, ")");
565
              }
566
          }
567
        else if (CONSTANT_P (arg0) && CONSTANT_P (arg1))
568
          output_addr_const (file, addr);
569
        else
570
          fatal_insn ("bad operand", addr);
571
      }
572
      break;
573
 
574
    case SYMBOL_REF:
575
      if (SYMBOL_REF_SMALL_P (addr))
576
        {
577
          fprintf (file, "gp(");
578
          output_addr_const (file, addr);
579
          fprintf (file, ")");
580
        }
581
      else
582
        fatal_insn ("can't use non gp relative absolute address", addr);
583
      break;
584
 
585
    default:
586
      fatal_insn ("invalid addressing mode", addr);
587
      break;
588
    }
589
}
590
 
591
/* Determine where to put an argument to a function.
592
   Value is zero to push the argument on the stack,
593
   or a hard register in which to store the argument.
594
 
595
   MODE is the argument's machine mode.
596
   TYPE is the data type of the argument (as a tree).
597
    This is null for libcalls where that information may
598
    not be available.
599
   CUM is a variable of type CUMULATIVE_ARGS which gives info about
600
    the preceding args and about the function being called.
601
   NAMED is nonzero if this argument is a named parameter
602
    (otherwise it is an extra parameter matching an ellipsis).  */
603
 
604
rtx
605
lm32_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
606
                   tree type, int named)
607
{
608
  if (mode == VOIDmode)
609
    /* Compute operand 2 of the call insn.  */
610
    return GEN_INT (0);
611
 
612
  if (targetm.calls.must_pass_in_stack (mode, type))
613
    return NULL_RTX;
614
 
615
  if (!named || (cum + LM32_NUM_REGS2 (mode, type) > LM32_NUM_ARG_REGS))
616
    return NULL_RTX;
617
 
618
  return gen_rtx_REG (mode, cum + LM32_FIRST_ARG_REG);
619
}
620
 
621
HOST_WIDE_INT
622
lm32_compute_initial_elimination_offset (int from, int to)
623
{
624
  HOST_WIDE_INT offset = 0;
625
 
626
  switch (from)
627
    {
628
    case ARG_POINTER_REGNUM:
629
      switch (to)
630
        {
631
        case FRAME_POINTER_REGNUM:
632
          offset = 0;
633
          break;
634
        case STACK_POINTER_REGNUM:
635
          offset =
636
            lm32_compute_frame_size (get_frame_size ()) -
637
            current_frame_info.pretend_size;
638
          break;
639
        default:
640
          gcc_unreachable ();
641
        }
642
      break;
643
    default:
644
      gcc_unreachable ();
645
    }
646
 
647
  return offset;
648
}
649
 
650
static void
651
lm32_setup_incoming_varargs (CUMULATIVE_ARGS * cum, enum machine_mode mode,
652
                             tree type, int *pretend_size, int no_rtl)
653
{
654
  int first_anon_arg;
655
  tree fntype;
656
  int stdarg_p;
657
 
658
  fntype = TREE_TYPE (current_function_decl);
659
  stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
660
              && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
661
                  != void_type_node));
662
 
663
  if (stdarg_p)
664
    first_anon_arg = *cum + LM32_FIRST_ARG_REG;
665
  else
666
    {
667
      /* this is the common case, we have been passed details setup
668
         for the last named argument, we want to skip over the
669
         registers, if any used in passing this named paramter in
670
         order to determine which is the first registers used to pass
671
         anonymous arguments.  */
672
      int size;
673
 
674
      if (mode == BLKmode)
675
        size = int_size_in_bytes (type);
676
      else
677
        size = GET_MODE_SIZE (mode);
678
 
679
      first_anon_arg =
680
        *cum + LM32_FIRST_ARG_REG +
681
        ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
682
    }
683
 
684
  if ((first_anon_arg < (LM32_FIRST_ARG_REG + LM32_NUM_ARG_REGS)) && !no_rtl)
685
    {
686
      int first_reg_offset = first_anon_arg;
687
      int size = LM32_FIRST_ARG_REG + LM32_NUM_ARG_REGS - first_anon_arg;
688
      rtx regblock;
689
 
690
      regblock = gen_rtx_MEM (BLKmode,
691
                              plus_constant (arg_pointer_rtx,
692
                                             FIRST_PARM_OFFSET (0)));
693
      move_block_from_reg (first_reg_offset, regblock, size);
694
 
695
      *pretend_size = size * UNITS_PER_WORD;
696
    }
697
}
698
 
699
/* Override command line options.  */
700
void
701
lm32_override_options (void)
702
{
703
  /* We must have sign-extend enabled if barrel-shift isn't.  */
704
  if (!TARGET_BARREL_SHIFT_ENABLED && !TARGET_SIGN_EXTEND_ENABLED)
705
    target_flags |= MASK_SIGN_EXTEND_ENABLED;
706
}
707
 
708
/* Return nonzero if this function is known to have a null epilogue.
709
   This allows the optimizer to omit jumps to jumps if no stack
710
   was created.  */
711
int
712
lm32_can_use_return (void)
713
{
714
  if (!reload_completed)
715
    return 0;
716
 
717
  if (df_regs_ever_live_p (RA_REGNUM) || crtl->profile)
718
    return 0;
719
 
720
  if (lm32_compute_frame_size (get_frame_size ()) != 0)
721
    return 0;
722
 
723
  return 1;
724
}
725
 
726
/* Support function to determine the return address of the function
727
   'count' frames back up the stack.  */
728
rtx
729
lm32_return_addr_rtx (int count, rtx frame)
730
{
731
  rtx r;
732
  if (count == 0)
733
    {
734
      if (!df_regs_ever_live_p (RA_REGNUM))
735
        r = gen_rtx_REG (Pmode, RA_REGNUM);
736
      else
737
        {
738
          r = gen_rtx_MEM (Pmode,
739
                           gen_rtx_PLUS (Pmode, frame,
740
                                         GEN_INT (-2 * UNITS_PER_WORD)));
741
          set_mem_alias_set (r, get_frame_alias_set ());
742
        }
743
    }
744
  else if (flag_omit_frame_pointer)
745
    r = NULL_RTX;
746
  else
747
    {
748
      r = gen_rtx_MEM (Pmode,
749
                       gen_rtx_PLUS (Pmode, frame,
750
                                     GEN_INT (-2 * UNITS_PER_WORD)));
751
      set_mem_alias_set (r, get_frame_alias_set ());
752
    }
753
  return r;
754
}
755
 
756
/* Return true if EXP should be placed in the small data section.  */
757
 
758
static bool
759
lm32_in_small_data_p (const_tree exp)
760
{
761
  /* We want to merge strings, so we never consider them small data.  */
762
  if (TREE_CODE (exp) == STRING_CST)
763
    return false;
764
 
765
  /* Functions are never in the small data area.  Duh.  */
766
  if (TREE_CODE (exp) == FUNCTION_DECL)
767
    return false;
768
 
769
  if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
770
    {
771
      const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
772
      if (strcmp (section, ".sdata") == 0 || strcmp (section, ".sbss") == 0)
773
        return true;
774
    }
775
  else
776
    {
777
      HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
778
 
779
      /* If this is an incomplete type with size 0, then we can't put it
780
         in sdata because it might be too big when completed.  */
781
      if (size > 0 && (unsigned HOST_WIDE_INT) size <= g_switch_value)
782
        return true;
783
    }
784
 
785
  return false;
786
}
787
 
788
/* Emit straight-line code to move LENGTH bytes from SRC to DEST.
789
   Assume that the areas do not overlap.  */
790
 
791
static void
792
lm32_block_move_inline (rtx dest, rtx src, HOST_WIDE_INT length,
793
                        HOST_WIDE_INT alignment)
794
{
795
  HOST_WIDE_INT offset, delta;
796
  unsigned HOST_WIDE_INT bits;
797
  int i;
798
  enum machine_mode mode;
799
  rtx *regs;
800
 
801
  /* Work out how many bits to move at a time.  */
802
  switch (alignment)
803
    {
804
    case 1:
805
      bits = 8;
806
      break;
807
    case 2:
808
      bits = 16;
809
      break;
810
    default:
811
      bits = 32;
812
      break;
813
    }
814
 
815
  mode = mode_for_size (bits, MODE_INT, 0);
816
  delta = bits / BITS_PER_UNIT;
817
 
818
  /* Allocate a buffer for the temporary registers.  */
819
  regs = alloca (sizeof (rtx) * length / delta);
820
 
821
  /* Load as many BITS-sized chunks as possible.  */
822
  for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
823
    {
824
      regs[i] = gen_reg_rtx (mode);
825
      emit_move_insn (regs[i], adjust_address (src, mode, offset));
826
    }
827
 
828
  /* Copy the chunks to the destination.  */
829
  for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
830
    emit_move_insn (adjust_address (dest, mode, offset), regs[i]);
831
 
832
  /* Mop up any left-over bytes.  */
833
  if (offset < length)
834
    {
835
      src = adjust_address (src, BLKmode, offset);
836
      dest = adjust_address (dest, BLKmode, offset);
837
      move_by_pieces (dest, src, length - offset,
838
                      MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), 0);
839
    }
840
}
841
 
842
/* Expand string/block move operations.
843
 
844
   operands[0] is the pointer to the destination.
845
   operands[1] is the pointer to the source.
846
   operands[2] is the number of bytes to move.
847
   operands[3] is the alignment.  */
848
 
849
int
850
lm32_expand_block_move (rtx * operands)
851
{
852
  if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) <= 32))
853
    {
854
      lm32_block_move_inline (operands[0], operands[1], INTVAL (operands[2]),
855
                              INTVAL (operands[3]));
856
      return 1;
857
    }
858
  return 0;
859
}
860
 
861
/* Return TRUE if X references a SYMBOL_REF or LABEL_REF whose symbol
862
   isn't protected by a PIC unspec.  */
863
int
864
nonpic_symbol_mentioned_p (rtx x)
865
{
866
  const char *fmt;
867
  int i;
868
 
869
  if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF
870
      || GET_CODE (x) == PC)
871
    return 1;
872
 
873
  /* We don't want to look into the possible MEM location of a
874
     CONST_DOUBLE, since we're not going to use it, in general.  */
875
  if (GET_CODE (x) == CONST_DOUBLE)
876
    return 0;
877
 
878
  if (GET_CODE (x) == UNSPEC)
879
    return 0;
880
 
881
  fmt = GET_RTX_FORMAT (GET_CODE (x));
882
  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
883
    {
884
      if (fmt[i] == 'E')
885
        {
886
          int j;
887
 
888
          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
889
            if (nonpic_symbol_mentioned_p (XVECEXP (x, i, j)))
890
              return 1;
891
        }
892
      else if (fmt[i] == 'e' && nonpic_symbol_mentioned_p (XEXP (x, i)))
893
        return 1;
894
    }
895
 
896
  return 0;
897
}
898
 
899
/* Compute a (partial) cost for rtx X.  Return true if the complete
900
   cost has been computed, and false if subexpressions should be
901
   scanned.  In either case, *TOTAL contains the cost result.  */
902
 
903
static bool
904
lm32_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed)
905
{
906
  enum machine_mode mode = GET_MODE (x);
907
  bool small_mode;
908
 
909
  const int arithmetic_latency = 1;
910
  const int shift_latency = 1;
911
  const int compare_latency = 2;
912
  const int multiply_latency = 3;
913
  const int load_latency = 3;
914
  const int libcall_size_cost = 5;
915
 
916
  /* Determine if we can handle the given mode size in a single instruction.  */
917
  small_mode = (mode == QImode) || (mode == HImode) || (mode == SImode);
918
 
919
  switch (code)
920
    {
921
 
922
    case PLUS:
923
    case MINUS:
924
    case AND:
925
    case IOR:
926
    case XOR:
927
    case NOT:
928
    case NEG:
929
      if (!speed)
930
        *total = COSTS_N_INSNS (LM32_NUM_REGS (mode));
931
      else
932
        *total =
933
          COSTS_N_INSNS (arithmetic_latency + (LM32_NUM_REGS (mode) - 1));
934
      break;
935
 
936
    case COMPARE:
937
      if (small_mode)
938
        {
939
          if (!speed)
940
            *total = COSTS_N_INSNS (1);
941
          else
942
            *total = COSTS_N_INSNS (compare_latency);
943
        }
944
      else
945
        {
946
          /* FIXME. Guessing here.  */
947
          *total = COSTS_N_INSNS (LM32_NUM_REGS (mode) * (2 + 3) / 2);
948
        }
949
      break;
950
 
951
    case ASHIFT:
952
    case ASHIFTRT:
953
    case LSHIFTRT:
954
      if (TARGET_BARREL_SHIFT_ENABLED && small_mode)
955
        {
956
          if (!speed)
957
            *total = COSTS_N_INSNS (1);
958
          else
959
            *total = COSTS_N_INSNS (shift_latency);
960
        }
961
      else if (TARGET_BARREL_SHIFT_ENABLED)
962
        {
963
          /* FIXME: Guessing here.  */
964
          *total = COSTS_N_INSNS (LM32_NUM_REGS (mode) * 4);
965
        }
966
      else if (small_mode && GET_CODE (XEXP (x, 1)) == CONST_INT)
967
        {
968
          *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1)));
969
        }
970
      else
971
        {
972
          /* Libcall.  */
973
          if (!speed)
974
            *total = COSTS_N_INSNS (libcall_size_cost);
975
          else
976
            *total = COSTS_N_INSNS (100);
977
        }
978
      break;
979
 
980
    case MULT:
981
      if (TARGET_MULTIPLY_ENABLED && small_mode)
982
        {
983
          if (!speed)
984
            *total = COSTS_N_INSNS (1);
985
          else
986
            *total = COSTS_N_INSNS (multiply_latency);
987
        }
988
      else
989
        {
990
          /* Libcall.  */
991
          if (!speed)
992
            *total = COSTS_N_INSNS (libcall_size_cost);
993
          else
994
            *total = COSTS_N_INSNS (100);
995
        }
996
      break;
997
 
998
    case DIV:
999
    case MOD:
1000
    case UDIV:
1001
    case UMOD:
1002
      if (TARGET_DIVIDE_ENABLED && small_mode)
1003
        {
1004
          if (!speed)
1005
            *total = COSTS_N_INSNS (1);
1006
          else
1007
            {
1008
              if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1009
                {
1010
                  int cycles = 0;
1011
                  unsigned HOST_WIDE_INT i = INTVAL (XEXP (x, 1));
1012
 
1013
                  while (i)
1014
                    {
1015
                      i >>= 2;
1016
                      cycles++;
1017
                    }
1018
                  if (IN_RANGE (i, 0, 65536))
1019
                    *total = COSTS_N_INSNS (1 + 1 + cycles);
1020
                  else
1021
                    *total = COSTS_N_INSNS (2 + 1 + cycles);
1022
                  return true;
1023
                }
1024
              else if (GET_CODE (XEXP (x, 1)) == REG)
1025
                {
1026
                  *total = COSTS_N_INSNS (1 + GET_MODE_SIZE (mode) / 2);
1027
                  return true;
1028
                }
1029
              else
1030
                {
1031
                  *total = COSTS_N_INSNS (1 + GET_MODE_SIZE (mode) / 2);
1032
                  return false;
1033
                }
1034
            }
1035
        }
1036
      else
1037
        {
1038
          /* Libcall.  */
1039
          if (!speed)
1040
            *total = COSTS_N_INSNS (libcall_size_cost);
1041
          else
1042
            *total = COSTS_N_INSNS (100);
1043
        }
1044
      break;
1045
 
1046
    case HIGH:
1047
    case LO_SUM:
1048
      if (!speed)
1049
        *total = COSTS_N_INSNS (1);
1050
      else
1051
        *total = COSTS_N_INSNS (arithmetic_latency);
1052
      break;
1053
 
1054
    case ZERO_EXTEND:
1055
      if (MEM_P (XEXP (x, 0)))
1056
        *total = COSTS_N_INSNS (0);
1057
      else if (small_mode)
1058
        {
1059
          if (!speed)
1060
            *total = COSTS_N_INSNS (1);
1061
          else
1062
            *total = COSTS_N_INSNS (arithmetic_latency);
1063
        }
1064
      else
1065
        *total = COSTS_N_INSNS (LM32_NUM_REGS (mode) / 2);
1066
      break;
1067
 
1068
    case CONST_INT:
1069
      {
1070
        switch (outer_code)
1071
          {
1072
          case HIGH:
1073
          case LO_SUM:
1074
            *total = COSTS_N_INSNS (0);
1075
            return true;
1076
 
1077
          case AND:
1078
          case XOR:
1079
          case IOR:
1080
          case ASHIFT:
1081
          case ASHIFTRT:
1082
          case LSHIFTRT:
1083
          case ROTATE:
1084
          case ROTATERT:
1085
            if (satisfies_constraint_L (x))
1086
              *total = COSTS_N_INSNS (0);
1087
            else
1088
              *total = COSTS_N_INSNS (2);
1089
            return true;
1090
 
1091
          case SET:
1092
          case PLUS:
1093
          case MINUS:
1094
          case COMPARE:
1095
            if (satisfies_constraint_K (x))
1096
              *total = COSTS_N_INSNS (0);
1097
            else
1098
              *total = COSTS_N_INSNS (2);
1099
            return true;
1100
 
1101
          case MULT:
1102
            if (TARGET_MULTIPLY_ENABLED)
1103
              {
1104
                if (satisfies_constraint_K (x))
1105
                 *total = COSTS_N_INSNS (0);
1106
                else
1107
                  *total = COSTS_N_INSNS (2);
1108
                return true;
1109
              }
1110
            /* Fall through.  */
1111
 
1112
          default:
1113
            if (satisfies_constraint_K (x))
1114
              *total = COSTS_N_INSNS (1);
1115
            else
1116
              *total = COSTS_N_INSNS (2);
1117
            return true;
1118
          }
1119
      }
1120
 
1121
    case SYMBOL_REF:
1122
    case CONST:
1123
      switch (outer_code)
1124
        {
1125
        case HIGH:
1126
        case LO_SUM:
1127
          *total = COSTS_N_INSNS (0);
1128
          return true;
1129
 
1130
        case MEM:
1131
        case SET:
1132
          if (g_switch_value)
1133
            {
1134
              *total = COSTS_N_INSNS (0);
1135
              return true;
1136
            }
1137
          break;
1138
        }
1139
      /* Fall through.  */
1140
 
1141
    case LABEL_REF:
1142
    case CONST_DOUBLE:
1143
      *total = COSTS_N_INSNS (2);
1144
      return true;
1145
 
1146
    case SET:
1147
      *total = COSTS_N_INSNS (1);
1148
      break;
1149
 
1150
    case MEM:
1151
      if (!speed)
1152
        *total = COSTS_N_INSNS (1);
1153
      else
1154
        *total = COSTS_N_INSNS (load_latency);
1155
      break;
1156
 
1157
    }
1158
 
1159
  return false;
1160
}
1161
 
1162
/* Implemenent TARGET_CAN_ELIMINATE.  */
1163
 
1164
bool
1165
lm32_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
1166
{
1167
  return (to == STACK_POINTER_REGNUM && frame_pointer_needed) ? false : true;
1168
}
1169
 
1170
/* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
1171
 
1172
static bool
1173
lm32_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x, bool strict)
1174
{
1175
   /* (rM) */
1176
  if (strict && REG_P (x) && STRICT_REG_OK_FOR_BASE_P (x))
1177
    return true;
1178
  if (!strict && REG_P (x) && NONSTRICT_REG_OK_FOR_BASE_P (x))
1179
    return true;
1180
 
1181
  /* (rM)+literal) */
1182
  if (GET_CODE (x) == PLUS
1183
     && REG_P (XEXP (x, 0))
1184
     && ((strict && STRICT_REG_OK_FOR_BASE_P (XEXP (x, 0)))
1185
         || (!strict && NONSTRICT_REG_OK_FOR_BASE_P (XEXP (x, 0))))
1186
     && GET_CODE (XEXP (x, 1)) == CONST_INT
1187
     && satisfies_constraint_K (XEXP ((x), 1)))
1188
    return true;
1189
 
1190
  /* gp(sym)  */
1191
  if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_SMALL_P (x))
1192
    return true;
1193
 
1194
  return false;
1195
}
1196
 
1197
/* Check a move is not memory to memory.  */
1198
 
1199
bool
1200
lm32_move_ok (enum machine_mode mode, rtx operands[2]) {
1201
  if (memory_operand (operands[0], mode))
1202
    return register_or_zero_operand (operands[1], mode);
1203
  return true;
1204
}
1205
 
1206
/* Implement LEGITIMATE_CONSTANT_P.  */
1207
 
1208
bool
1209
lm32_legitimate_constant_p (rtx x)
1210
{
1211
  /* 32-bit addresses require multiple instructions.  */
1212
  if (!flag_pic && reloc_operand (x, GET_MODE (x)))
1213
    return false;
1214
 
1215
  return true;
1216
}

powered by: WebSVN 2.1.0

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