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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gcc/] [gcc-3.4.4/] [gcc/] [config/] [or32/] [or32.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1612 phoenix
/* Subroutines for insn-output.c for GNU compiler.  OpenRISC 1000 version.
2
   Copyright (C) 1987, 1992, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
3
   2005  Free Software Foundation, Inc
4
   Contributed by Damjan Lampret <damjanl@bsemi.com> in 1999.
5
   Major optimizations by Matjaz Breskvar <matjazb@bsemi.com> in 2005.
6
 
7
This file is part of GNU CC.
8
 
9
GNU CC is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 1, or (at your option)
12
any later version.
13
 
14
GNU CC is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
GNU General Public License for more details.
18
 
19
You should have received a copy of the GNU General Public License
20
along with GNU CC; see the file COPYING.  If not, write to
21
the Free Software Foundation, 59 Temple Place - Suite 330,
22
Boston, MA 02111-1307, USA.  */
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 "tree.h"
37
#include "expr.h"
38
#include "except.h"
39
#include "function.h"
40
#include "toplev.h"
41
#include "recog.h"
42
#include "tm_p.h"
43
#include "debug.h"
44
#include "output.h"
45
#include "target.h"
46
#include "target-def.h"
47
#include "ggc.h"
48
#include "optabs.h"
49
 
50
/* Set thist to nonzero if you want l.nop instruction in delay slot
51
   of l.jr instruction in epilogue. */
52
#define  NOP_DELAY_SLOT_FILL 0
53
 
54
/* This is the pseudo register number that holds the comparison flags */
55
 
56
#define FLAGS_REG 32
57
 
58
/* Save information from a "cmpxx" operation until the branch or scc is
59
   emitted.  */
60
rtx or32_compare_op0, or32_compare_op1;
61
 
62
/* used in function prologue/epilogue generation */
63
extern int leaf_function;
64
 
65
/* Local function prototypes */
66
static void or32_output_function_prologue (FILE * file, HOST_WIDE_INT vars);
67
static void or32_output_function_epilogue (FILE * file, HOST_WIDE_INT vars);
68
static bool or32_save_reg_p (int regno);
69
HOST_WIDE_INT or32_compute_frame_size (HOST_WIDE_INT size);
70
static rtx emit_frame_insn (rtx insn);
71
static rtx indexed_memory (rtx base, HOST_WIDE_INT disp);
72
void or32_expand_prologue (void);
73
void or32_expand_epilogue (int sibcall);
74
const char *or32_output_move_double (rtx * operands);
75
enum rtx_code or32_reverse_condition (enum machine_mode mode,
76
                                      enum rtx_code code);
77
enum machine_mode or32_cc_mode (enum rtx_code code, rtx op0, rtx op1);
78
rtx or32_expand_compare (enum rtx_code code, rtx op0, rtx op1);
79
void or32_expand_branch (enum rtx_code code, rtx label);
80
static int or32_emit_int_cmove (rtx dest, rtx op, rtx true_cond,
81
                                rtx false_cond);
82
int or32_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond);
83
const char *output_cmov (rtx * operands);
84
const char *output_bf (rtx * operands);
85
void or32_emit_set_const32 (rtx op0, rtx op1);
86
int or32_register_move_cost (enum machine_mode mode, enum reg_class from,
87
                             enum reg_class to);
88
int or32_memory_move_cost (enum machine_mode mode, enum reg_class class,
89
                           int in);
90
int or32_branch_cost ();
91
 
92
 
93
#undef TARGET_ASM_FUNCTION_PROLOGUE
94
#define TARGET_ASM_FUNCTION_PROLOGUE or32_output_function_prologue
95
#undef TARGET_ASM_FUNCTION_EPILOGUE
96
#define TARGET_ASM_FUNCTION_EPILOGUE or32_output_function_epilogue
97
 
98
static bool or32_function_ok_for_sibcall (tree decl, tree exp);
99
 
100
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
101
#define TARGET_FUNCTION_OK_FOR_SIBCALL or32_function_ok_for_sibcall
102
 
103
 
104
/* Initialize the GCC target structure.  */
105
struct gcc_target targetm = TARGET_INITIALIZER;
106
 
107
/* Stack layout we use for pushing and poping saved registers */
108
struct or32_frame_info
109
{
110
  bool save_lr_p;
111
  int lr_save_offset;
112
  bool save_fp_p;
113
  int fp_save_offset;
114
  int gpr_size;
115
  int gpr_offset;
116
  int total_size;
117
  int vars_size;
118
  int args_size;
119
  HOST_WIDE_INT mask;
120
};
121
 
122
static struct or32_frame_info frame_info;
123
 
124
/* Returns 1 if OP is either a pseudo-register or a register denoting a
125
   CR field.  */
126
 
127
int
128
cc_reg_operand (rtx op, enum machine_mode mode)
129
{
130
  register_operand (op, mode);
131
 
132
  if (GET_CODE (op) == REG && REGNO (op) == 32)
133
    return 1;
134
 
135
  return 0;
136
}
137
 
138
int
139
sym_ref_mem_operand (op, mode)
140
     register rtx op;
141
     enum machine_mode mode ATTRIBUTE_UNUSED;
142
{
143
  if (GET_CODE (op) == MEM)
144
    {
145
      rtx t1 = XEXP (op, 0);
146
      if (GET_CODE (t1) == SYMBOL_REF)
147
        return 1;
148
    }
149
  return 0;
150
}
151
 
152
/* Return 1 if OP is a valid operand for the source of a move insn.  */
153
 
154
int
155
input_operand (rtx op, enum machine_mode mode)
156
{
157
 
158
  /* If both modes are non-void they must be the same.  */
159
  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
160
    return 0;
161
 
162
  /* Accept CONSTANT_P_RTX, since it will be gone by CSE1 and result in 0/1.  */
163
  if (GET_CODE (op) == CONSTANT_P_RTX)
164
    return 1;
165
 
166
  /* Allow any one instruction integer constant, and all CONST_INT
167
     variants when we are working in DImode and !arch64.  */
168
  if (GET_MODE_CLASS (mode) == MODE_INT
169
      && ((GET_CODE (op) == CONST_INT)
170
          && (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K')
171
              || CONST_OK_FOR_LETTER_P (INTVAL (op), 'M')
172
              || CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'))))
173
    return 1;
174
 
175
  if (register_operand (op, mode))
176
    return 1;
177
 
178
  /* If this is a SUBREG, look inside so that we handle
179
     paradoxical ones.  */
180
  if (GET_CODE (op) == SUBREG)
181
    op = SUBREG_REG (op);
182
 
183
 
184
  /* Check for valid MEM forms.  */
185
  if (GET_CODE (op) == MEM)
186
    return memory_address_p (mode, XEXP (op, 0));
187
 
188
  return 0;
189
}
190
 
191
/* Test for a valid operand for a call instruction.  Don't allow the
192
   arg pointer register or virtual regs since they may decay into
193
   reg + const, which the patterns can't handle.  */
194
 
195
int
196
sibcall_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
197
{
198
 
199
 
200
  /* Disallow indirect through a virtual register.  This leads to
201
     compiler aborts when trying to eliminate them.  */
202
  if (GET_CODE (op) == REG
203
      && (op == arg_pointer_rtx
204
          || op == frame_pointer_rtx
205
          || (REGNO (op) >= FIRST_PSEUDO_REGISTER
206
              && REGNO (op) <= LAST_VIRTUAL_REGISTER)))
207
    {
208
 
209
      fprintf (stderr, "0\n");
210
      return 0;
211
    }
212
 
213
  /* Explicitly allow SYMBOL_REF even if pic.  */
214
  if (GET_CODE (op) == SYMBOL_REF)
215
    return 1;
216
 
217
  /* Otherwise we can only allow register operands.  */
218
  return register_operand (op, Pmode);
219
}
220
 
221
 
222
/* Add a REG_MAYBE_DEAD note to the insn.  */
223
static void
224
or32_maybe_dead (rtx insn)
225
{
226
  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
227
                                        const0_rtx, REG_NOTES (insn));
228
}
229
 
230
int
231
print_operand_punct_valid_p (code)
232
     int code;
233
{
234
  switch (code)
235
    {
236
    case '(':                   /* idea taken from sparc; output nop for %( if
237
                                   not optimizing or the slot is not filled. */
238
    case '%':
239
      return 1;
240
    }
241
  return 0;
242
}
243
 
244
void
245
print_operand_address (file, addr)
246
     FILE *file;
247
     register rtx addr;
248
{
249
  register rtx reg1, reg2, breg, ireg;
250
  rtx offset;
251
 
252
  switch (GET_CODE (addr))
253
    {
254
    case MEM:
255
      if (GET_CODE (XEXP (addr, 0)) == REG)
256
        fprintf (file, "%s", reg_names[REGNO (addr)]);
257
      else
258
        abort ();
259
      break;
260
 
261
    case REG:
262
      fprintf (file, "0(%s)", reg_names[REGNO (addr)]);
263
      break;
264
 
265
    case PLUS:
266
      reg1 = 0;
267
      reg2 = 0;
268
      ireg = 0;
269
      breg = 0;
270
      offset = 0;
271
      if (GET_CODE (XEXP (addr, 0)) == REG)
272
        {
273
          offset = XEXP (addr, 1);
274
          addr = XEXP (addr, 0);
275
        }
276
      else if (GET_CODE (XEXP (addr, 1)) == REG)
277
        {
278
          offset = XEXP (addr, 0);
279
          addr = XEXP (addr, 1);
280
        }
281
      output_address (offset);
282
      fprintf (file, "(%s)", reg_names[REGNO (addr)]);
283
      break;
284
 
285
    default:
286
      /* fprintf(file, "{%d}", GET_CODE (addr)); */
287
      output_addr_const (file, addr);
288
    }
289
}
290
 
291
/* Calulcate and return stack size for current function.  */
292
static int
293
calculate_stack_size (int vars, int *lr_save_area,
294
                      int *fp_save_area, int *gpr_save_area, int *save_area)
295
{
296
  int regno;
297
 
298
  *gpr_save_area = 0;
299
  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
300
    {
301
      if (regs_ever_live[regno] && !call_used_regs[regno])
302
        *gpr_save_area += 4;
303
    }
304
 
305
  *lr_save_area = (!current_function_is_leaf
306
                   || regs_ever_live[LINK_REGNUM]) ? 4 : 0;
307
  *fp_save_area = frame_pointer_needed ? 4 : 0;
308
 
309
  *save_area = (OR32_ALIGN (current_function_outgoing_args_size, 4)
310
                + *lr_save_area + *fp_save_area);
311
 
312
  return
313
    (OR32_ALIGN (current_function_outgoing_args_size, 4)
314
     + *lr_save_area + *fp_save_area + *gpr_save_area + OR32_ALIGN (vars, 4));
315
}
316
 
317
/* Set up the stack and frame pointer (if desired) for the
318
   function.  */
319
static void
320
or32_output_function_prologue (FILE * file, HOST_WIDE_INT vars)
321
{
322
  int save_area;
323
  int gpr_save_area;
324
  int lr_save_area;
325
  int fp_save_area;
326
  int stack_size;
327
  int regno;
328
 
329
  if (TARGET_SCHED_LOGUE)
330
    return;
331
 
332
#if 0
333
  save_area = 0;
334
 
335
  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
336
    {
337
      if (regs_ever_live[regno] && !call_used_regs[regno])
338
        {
339
          save_area += 1;
340
        }
341
    }
342
 
343
  if (save_area != 0)
344
    fprintf (file, "\tl.nop \t0x%x\n", 0x100 + save_area);
345
 
346
  return;
347
#endif
348
 
349
  if (vars < 0)
350
    abort ();
351
 
352
  stack_size = calculate_stack_size
353
    (vars, &lr_save_area, &fp_save_area, &gpr_save_area, &save_area);
354
 
355
  fprintf (file,
356
           "\n\t# gpr_save_area %d vars %ld current_function_outgoing_args_size %d\n",
357
           gpr_save_area, vars, current_function_outgoing_args_size);
358
 
359
  if (stack_size >= 0x8000)
360
    {
361
      fprintf (file, "\tl.movhi   \tr%d,hi(%d)\n", GP_ARG_RETURN, stack_size);
362
      fprintf (file, "\tl.ori   \tr%d,r%d,lo(%d)\n", GP_ARG_RETURN,
363
               GP_ARG_RETURN, stack_size);
364
      fprintf (file, "\tl.sub   \tr%d,r%d,r%d\n", STACK_POINTER_REGNUM,
365
               STACK_POINTER_REGNUM, GP_ARG_RETURN);
366
    }
367
  else if (stack_size > 0)
368
    {
369
      fprintf (file, "\tl.addi   \tr%d,r%d,%d\n", STACK_POINTER_REGNUM,
370
               STACK_POINTER_REGNUM, -stack_size);
371
    }
372
 
373
  if (fp_save_area)
374
    {
375
      fprintf (file, "\tl.sw     \t%d(r%d),r%d\n",
376
               OR32_ALIGN (current_function_outgoing_args_size, 4)
377
               + lr_save_area, STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM);
378
      if (stack_size >= 0x8000)
379
        fprintf (file, "\tl.add   \tr%d,r%d,r%d\n", FRAME_POINTER_REGNUM,
380
                 STACK_POINTER_REGNUM, GP_ARG_RETURN);
381
      else
382
        fprintf (file, "\tl.addi   \tr%d,r%d,%d\n", FRAME_POINTER_REGNUM,
383
                 STACK_POINTER_REGNUM, stack_size);
384
    }
385
 
386
  if (lr_save_area)
387
    {
388
      fprintf (file, "\tl.sw     \t%d(r%d),r%d\n",
389
               OR32_ALIGN (current_function_outgoing_args_size, 4),
390
               STACK_POINTER_REGNUM, LINK_REGNUM);
391
    }
392
 
393
  save_area = (OR32_ALIGN (current_function_outgoing_args_size, 4)
394
               + lr_save_area + fp_save_area);
395
 
396
  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
397
    {
398
      if (regs_ever_live[regno] && !call_used_regs[regno])
399
        {
400
          fprintf (file, "\tl.sw    \t%d(r%d),r%d\n", save_area,
401
                   STACK_POINTER_REGNUM, regno);
402
          save_area += 4;
403
        }
404
    }
405
}
406
 
407
/* Do any necessary cleanup after a function to restore stack, frame,
408
   and regs.  */
409
static void
410
or32_output_function_epilogue (FILE * file, HOST_WIDE_INT vars)
411
{
412
  int save_area;
413
  int gpr_save_area;
414
  int lr_save_area;
415
  int fp_save_area;
416
  int stack_size;
417
  int regno;
418
 
419
  if (TARGET_SCHED_LOGUE)
420
    return;
421
 
422
#if 0
423
  save_area = 0;
424
 
425
  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
426
    {
427
      if (regs_ever_live[regno] && !call_used_regs[regno])
428
        {
429
          save_area += 1;
430
        }
431
    }
432
 
433
  fprintf (file, "\tl.nop \t0x%x\n", 0x200 + save_area);
434
  return;
435
#endif
436
 
437
  stack_size = calculate_stack_size
438
    (vars, &lr_save_area, &fp_save_area, &gpr_save_area, &save_area);
439
 
440
  if (lr_save_area)
441
    {
442
      fprintf (file, "\tl.lwz    \tr%d,%d(r%d)\n", LINK_REGNUM,
443
               OR32_ALIGN (current_function_outgoing_args_size, 4),
444
               STACK_POINTER_REGNUM);
445
    }
446
  if (fp_save_area)
447
    {
448
      fprintf (file, "\tl.lwz    \tr%d,%d(r%d)\n", FRAME_POINTER_REGNUM,
449
               OR32_ALIGN (current_function_outgoing_args_size, 4)
450
               + lr_save_area, STACK_POINTER_REGNUM);
451
    }
452
  save_area = (OR32_ALIGN (current_function_outgoing_args_size, 4)
453
               + lr_save_area + fp_save_area);
454
 
455
  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
456
    {
457
      if (regs_ever_live[regno] && !call_used_regs[regno])
458
        {
459
          fprintf (file, "\tl.lwz    \tr%d,%d(r%d)\n", regno, save_area,
460
                   STACK_POINTER_REGNUM);
461
          save_area += 4;
462
        }
463
    }
464
 
465
  if (stack_size >= 0x8000)
466
    {
467
      fprintf (file, "\tl.movhi   \tr3,hi(%d)\n", stack_size);
468
      fprintf (file, "\tl.ori   \tr3,r3,lo(%d)\n", stack_size);
469
 
470
      if (!TARGET_ALIGNED_JUMPS)
471
        fprintf (file, "\tl.jr  \tr%d\n", LINK_REGNUM);
472
      else
473
        fprintf (file, "\t.balignl 0x8,0x15000015,0x4;l.jr  \tr%d\n",
474
                 LINK_REGNUM);
475
 
476
      fprintf (file, "\tl.add   \tr%d,r%d,r3\n", STACK_POINTER_REGNUM,
477
               STACK_POINTER_REGNUM);
478
    }
479
  else if (stack_size > 0)
480
    {
481
      if (!TARGET_ALIGNED_JUMPS)
482
        fprintf (file, "\tl.jr  \tr%d\n", LINK_REGNUM);
483
      else
484
        fprintf (file, "\t.balignl 0x8,0x15000015,0x4;l.jr  \tr%d\n",
485
                 LINK_REGNUM);
486
 
487
      fprintf (file, "\tl.addi   \tr%d,r%d,%d\n", STACK_POINTER_REGNUM,
488
               STACK_POINTER_REGNUM, stack_size);
489
    }
490
  else
491
    {
492
      if (!TARGET_ALIGNED_JUMPS)
493
        fprintf (file, "\tl.jr  \tr%d\n", LINK_REGNUM);
494
      else
495
        fprintf (file, "\t.balignl 0x8,0x15000015,0x4;l.jr  \tr%d\n",
496
                 LINK_REGNUM);
497
 
498
      fprintf (file, "\tl.nop\n");
499
    }
500
 
501
#if 0
502
  fprintf (file, ".endproc _%s\n", get_function_name ());
503
#endif
504
}
505
 
506
/* Compuate full frame size and layout.  SIZE is the size of the
507
   functions local variables.  Store information in FRAME_INFO and
508
   return total size of stack frame.  */
509
 
510
HOST_WIDE_INT
511
or32_compute_frame_size (HOST_WIDE_INT size)
512
{
513
  HOST_WIDE_INT args_size;
514
  HOST_WIDE_INT vars_size;
515
  HOST_WIDE_INT stack_offset;
516
  int regno;
517
 
518
  args_size = current_function_outgoing_args_size;
519
  vars_size = OR32_ALIGN (size, 4);
520
 
521
  frame_info.args_size = args_size;
522
  frame_info.vars_size = vars_size;
523
 
524
  /* If the function has local variables, we're committed to
525
     allocating it anyway.  Otherwise reclaim it here.  */
526
  /* FIXME: Verify this.  Got if from the MIPS port.  */
527
  if (vars_size == 0 && current_function_is_leaf)
528
    args_size = 0;
529
 
530
  stack_offset = args_size;
531
 
532
  /* Save link register right after possible outgoing arguments.  */
533
  if (or32_save_reg_p (LINK_REGNUM))
534
    {
535
      frame_info.lr_save_offset = stack_offset;
536
      frame_info.save_lr_p = true;
537
      stack_offset = stack_offset + UNITS_PER_WORD;
538
    }
539
  else
540
    frame_info.save_lr_p = false;
541
 
542
  /* Save frame pointer right after possible link register.  */
543
  if (or32_save_reg_p (FRAME_POINTER_REGNUM))
544
    {
545
      frame_info.fp_save_offset = stack_offset;
546
      frame_info.save_fp_p = true;
547
      stack_offset = stack_offset + UNITS_PER_WORD;
548
    }
549
  else
550
    frame_info.save_fp_p = false;
551
 
552
  frame_info.gpr_size = 0;
553
  frame_info.mask = 0;
554
  frame_info.gpr_offset = stack_offset;
555
 
556
  for (regno = 0; regno <= LAST_INT_REG; regno++)
557
    {
558
      if (regno == LINK_REGNUM || regno == FRAME_POINTER_REGNUM)
559
        /* These has already been saved if so needed.  */
560
        continue;
561
 
562
      if (or32_save_reg_p (regno))
563
        {
564
          frame_info.gpr_size += UNITS_PER_WORD;
565
          frame_info.mask |= (1 << regno);
566
        }
567
    }
568
 
569
  frame_info.total_size = ((frame_info.save_fp_p ? UNITS_PER_WORD : 0)
570
                           + (frame_info.save_lr_p ? UNITS_PER_WORD : 0)
571
                           + args_size + frame_info.gpr_size + vars_size);
572
 
573
  return frame_info.total_size;
574
}
575
 
576
 
577
/* Return true if current function must save REGNO.  */
578
static bool
579
or32_save_reg_p (int regno)
580
{
581
  /* No need to save the faked cc0 register.  */
582
  if (regno == FLAGS_REG)
583
    return false;
584
 
585
  /* Check call-saved registers.  */
586
  if (regs_ever_live[regno] && !call_used_regs[regno])
587
    return true;
588
 
589
  /* We need to save the old frame pointer before setting up a new
590
     one.  */
591
  if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
592
    return true;
593
 
594
  /* We need to save the incoming return address if it is ever clobbered
595
     within the function.  */
596
  if (regno == LINK_REGNUM && regs_ever_live[regno])
597
    return true;
598
 
599
  return false;
600
}
601
 
602
/* Emit a frame related insn.  Same as emit_insn, but sets
603
   RTX_FRAME_RELATED_P to one.  */
604
 
605
static rtx
606
emit_frame_insn (rtx insn)
607
{
608
  insn = emit_insn (insn);
609
  RTX_FRAME_RELATED_P (insn) = 1;
610
  return (insn);
611
}
612
 
613
static rtx
614
indexed_memory (rtx base, HOST_WIDE_INT disp)
615
{
616
  return gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, base, GEN_INT (disp)));
617
}
618
 
619
/* Called after register allocation to add any instructions needed for
620
   the prologue.  Using a prologue insn is favored compared to putting
621
   all of the instructions in output_function_prologue(), since it
622
   allows the scheduler to intermix instructions with the saves of the
623
   caller saved registers.  In some cases, it might be necessary to
624
   emit a barrier instruction as the last insn to prevent such
625
   scheduling.  */
626
 
627
void
628
or32_expand_prologue ()
629
{
630
  int total_size = or32_compute_frame_size (get_frame_size ());
631
  rtx sp_rtx;
632
  rtx value_rtx;
633
 
634
  if (!total_size)
635
    /* No frame needed.  */
636
    return;
637
 
638
  sp_rtx = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
639
 
640
  if (total_size > 32767)
641
    {
642
      value_rtx = gen_rtx_REG (Pmode, GP_ARG_RETURN);
643
      emit_frame_insn (gen_rtx_SET (Pmode, value_rtx, GEN_INT (total_size)));
644
    }
645
  else
646
    value_rtx = GEN_INT (total_size);
647
 
648
  /* Update the stack pointer to reflect frame size.  */
649
  emit_frame_insn
650
    (gen_rtx_SET (Pmode, stack_pointer_rtx,
651
                  gen_rtx_MINUS (Pmode, stack_pointer_rtx, value_rtx)));
652
 
653
  if (frame_info.save_fp_p)
654
    {
655
      emit_frame_insn
656
        (gen_rtx_SET (Pmode,
657
                      indexed_memory (stack_pointer_rtx,
658
                                      frame_info.fp_save_offset),
659
                      frame_pointer_rtx));
660
 
661
      emit_frame_insn
662
        (gen_rtx_SET (Pmode, frame_pointer_rtx,
663
                      gen_rtx_PLUS (Pmode, frame_pointer_rtx, value_rtx)));
664
    }
665
  if (frame_info.save_lr_p)
666
    {
667
 
668
      emit_frame_insn
669
        (gen_rtx_SET (Pmode,
670
                      indexed_memory (stack_pointer_rtx,
671
                                      frame_info.lr_save_offset),
672
                      gen_rtx_REG (Pmode, LINK_REGNUM)));
673
    }
674
  if (frame_info.gpr_size)
675
    {
676
      int offset = 0;
677
      int regno;
678
 
679
      for (regno = 0; regno <= LAST_INT_REG; regno++)
680
        {
681
          HOST_WIDE_INT disp = frame_info.gpr_offset + offset;
682
 
683
          if (!(frame_info.mask & (1 << regno)))
684
            continue;
685
 
686
          emit_frame_insn
687
            (gen_rtx_SET (Pmode,
688
                          indexed_memory (stack_pointer_rtx, disp),
689
                          gen_rtx_REG (Pmode, regno)));
690
          offset = offset + UNITS_PER_WORD;
691
        }
692
    }
693
}
694
 
695
/* Called after register allocation to add any instructions needed for
696
   the epilogue.  Using an epilogue insn is favored compared to
697
   putting all of the instructions in output_function_epilogue(),
698
   since it allows the scheduler to intermix instructions with the
699
   restores of the caller saved registers.  In some cases, it might be
700
   necessary to emit a barrier instruction as the first insn to
701
   prevent such scheduling.  */
702
 
703
void
704
or32_expand_epilogue (int sibcall)
705
{
706
  int total_size = or32_compute_frame_size (get_frame_size ());
707
  rtx value_rtx;
708
 
709
  if (total_size > 32767)
710
    {
711
      value_rtx = gen_rtx_REG (Pmode, 3);
712
 
713
      emit_insn (gen_rtx_SET (Pmode, value_rtx, GEN_INT (total_size)));
714
    }
715
  else
716
    value_rtx = GEN_INT (total_size);
717
 
718
  if (frame_info.save_lr_p)
719
    {
720
      or32_maybe_dead
721
        (emit_insn
722
         (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, LINK_REGNUM),
723
                       indexed_memory (stack_pointer_rtx,
724
                                       frame_info.lr_save_offset))));
725
    }
726
  if (frame_info.save_fp_p)
727
    {
728
      emit_insn
729
        (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM),
730
                      indexed_memory (stack_pointer_rtx,
731
                                      frame_info.fp_save_offset)));
732
    }
733
 
734
  if (frame_info.gpr_size)
735
    {
736
      int offset = 0;
737
      int regno;
738
 
739
      for (regno = 0; regno <= LAST_INT_REG; regno++)
740
        {
741
          HOST_WIDE_INT disp = frame_info.gpr_offset + offset;
742
 
743
          if (!(frame_info.mask & (1 << regno)))
744
            continue;
745
 
746
          emit_insn
747
            (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, regno),
748
                          indexed_memory (stack_pointer_rtx, disp)));
749
          offset = offset + UNITS_PER_WORD;
750
        }
751
    }
752
 
753
  if (total_size)
754
    {
755
      emit_insn (gen_rtx_SET (Pmode, stack_pointer_rtx,
756
                              gen_rtx_PLUS (Pmode,
757
                                            stack_pointer_rtx, value_rtx)));
758
    }
759
 
760
  if (!sibcall)
761
    emit_jump_insn (gen_return_internal (gen_rtx (REG, Pmode, 9)));
762
}
763
 
764
 
765
void
766
print_operand (FILE * file, rtx x, int code)
767
{
768
  if (code == 'r' && GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == REG)
769
    fprintf (file, "%s", reg_names[REGNO (XEXP (x, 0))]);
770
  else if (code == '(')
771
    {
772
      if (dbr_sequence_length ())
773
        fprintf (file, "\t# delay slot filled");
774
      else
775
        fprintf (file, "\n\tl.nop\t\t\t# nop delay slot");
776
    }
777
  else if (code == 'C')
778
    {
779
      switch (GET_CODE (x))
780
        {
781
        case EQ:
782
          fputs ("eq", file);
783
          break;
784
        case NE:
785
          fputs ("ne", file);
786
          break;
787
        case GT:
788
          fputs ("gts", file);
789
          break;
790
        case GE:
791
          fputs ("ges", file);
792
          break;
793
        case LT:
794
          fputs ("lts", file);
795
          break;
796
        case LE:
797
          fputs ("les", file);
798
          break;
799
        case GTU:
800
          fputs ("gtu", file);
801
          break;
802
        case GEU:
803
          fputs ("geu", file);
804
          break;
805
        case LTU:
806
          fputs ("ltu", file);
807
          break;
808
        case LEU:
809
          fputs ("leu", file);
810
          break;
811
        default:
812
          abort ();
813
        }
814
    }
815
  else if (code == 'H')
816
    {
817
      if (GET_CODE (x) == REG)
818
        fprintf (file, "%s", reg_names[REGNO (x) + 1]);
819
      else
820
        abort ();
821
    }
822
  else if (GET_CODE (x) == REG)
823
    fprintf (file, "%s", reg_names[REGNO (x)]);
824
  else if (GET_CODE (x) == MEM)
825
    output_address (XEXP (x, 0));
826
  else
827
    output_addr_const (file, x);
828
}
829
 
830
/* Generate assembler code for a movdi/movdf */
831
 
832
const char *
833
or32_output_move_double (rtx * operands)
834
{
835
  rtx xoperands[3];
836
 
837
  switch (GET_CODE (operands[0]))
838
    {
839
    case REG:
840
      if (GET_CODE (operands[1]) == REG)
841
        {
842
          if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
843
            {
844
              output_asm_insn ("\tl.or    \t%H0, %H1, r0", operands);
845
              output_asm_insn ("\tl.or    \t%0, %1, r0", operands);
846
              return "";
847
            }
848
          else
849
            {
850
              output_asm_insn ("\tl.or    \t%0, %1, r0", operands);
851
              output_asm_insn ("\tl.or    \t%H0, %H1, r0", operands);
852
              return "";
853
            }
854
        }
855
      else if (GET_CODE (operands[1]) == MEM)
856
        {
857
          xoperands[1] = XEXP (operands[1], 0);
858
          if (GET_CODE (xoperands[1]) == REG)
859
            {
860
              xoperands[0] = operands[0];
861
              if (REGNO (xoperands[0]) == REGNO (xoperands[1]))
862
                {
863
                  output_asm_insn ("\tl.lwz   \t%H0, 4(%1)", xoperands);
864
                  output_asm_insn ("\tl.lwz   \t%0, 0(%1)", xoperands);
865
                  return "";
866
                }
867
              else
868
                {
869
                  output_asm_insn ("\tl.lwz   \t%0, 0(%1)", xoperands);
870
                  output_asm_insn ("\tl.lwz   \t%H0, 4(%1)", xoperands);
871
                  return "";
872
                }
873
            }
874
          else if (GET_CODE (xoperands[1]) == PLUS)
875
            {
876
              if (GET_CODE (xoperands[2] = XEXP (xoperands[1], 1)) == REG)
877
                {
878
                  xoperands[0] = operands[0];
879
                  xoperands[1] = XEXP (xoperands[1], 0);
880
                  if (REGNO (xoperands[0]) == REGNO (xoperands[2]))
881
                    {
882
                      output_asm_insn ("\tl.lwz   \t%H0, %1+4(%2)",
883
                                       xoperands);
884
                      output_asm_insn ("\tl.lwz   \t%0, %1(%2)", xoperands);
885
                      return "";
886
                    }
887
                  else
888
                    {
889
                      output_asm_insn ("\tl.lwz   \t%0, %1(%2)", xoperands);
890
                      output_asm_insn ("\tl.lwz   \t%H0, %1+4(%2)",
891
                                       xoperands);
892
                      return "";
893
                    }
894
                }
895
              else if (GET_CODE (xoperands[2] = XEXP (xoperands[1], 0)) ==
896
                       REG)
897
                {
898
                  xoperands[0] = operands[0];
899
                  xoperands[1] = XEXP (xoperands[1], 1);
900
                  if (REGNO (xoperands[0]) == REGNO (xoperands[2]))
901
                    {
902
                      output_asm_insn ("\tl.lwz   \t%H0, %1+4(%2)",
903
                                       xoperands);
904
                      output_asm_insn ("\tl.lwz   \t%0, %1(%2)", xoperands);
905
                      return "";
906
                    }
907
                  else
908
                    {
909
                      output_asm_insn ("\tl.lwz   \t%0, %1(%2)", xoperands);
910
                      output_asm_insn ("\tl.lwz   \t%H0, %1+4(%2)",
911
                                       xoperands);
912
                      return "";
913
                    }
914
                }
915
              else
916
                abort ();
917
            }
918
          else
919
            abort ();
920
        }
921
      else if (GET_CODE (operands[1]) == CONST_INT)
922
        {
923
          if (INTVAL (operands[1]) < 0)
924
            output_asm_insn ("\tl.addi  \t%0, r0, -1", operands);
925
          else
926
            output_asm_insn ("\tl.or    \t%0, r0, r0", operands);
927
          output_asm_insn ("\tl.movhi \t%H0, hi(%1)", operands);
928
          output_asm_insn ("\tl.ori   \t%H0, %H0, lo(%1)", operands);
929
          return "";
930
        }
931
      else
932
        abort ();
933
    case MEM:
934
      xoperands[0] = XEXP (operands[0], 0);
935
      if (GET_CODE (xoperands[0]) == REG)
936
        {
937
          xoperands[1] = operands[1];
938
          output_asm_insn ("\tl.sw    \t0(%0), %1", xoperands);
939
          output_asm_insn ("\tl.sw    \t4(%0), %H1", xoperands);
940
          return "";
941
        }
942
      else if (GET_CODE (xoperands[0]) == PLUS)
943
        {
944
          if (GET_CODE (xoperands[1] = XEXP (xoperands[0], 1)) == REG)
945
            {
946
              xoperands[0] = XEXP (xoperands[0], 0);
947
              xoperands[2] = operands[1];
948
              output_asm_insn ("\tl.sw    \t%0(%1), %2", xoperands);
949
              output_asm_insn ("\tl.sw    \t%0+4(%1), %H2", xoperands);
950
              return "";
951
            }
952
          else if (GET_CODE (xoperands[1] = XEXP (xoperands[0], 0)) == REG)
953
            {
954
              xoperands[0] = XEXP (xoperands[0], 1);
955
              xoperands[2] = operands[1];
956
              output_asm_insn ("\tl.sw    \t%0(%1), %2", xoperands);
957
              output_asm_insn ("\tl.sw    \t%0+4(%1), %H2", xoperands);
958
              return "";
959
            }
960
          else
961
            abort ();
962
        }
963
      else
964
        abort ();
965
    default:
966
      abort ();
967
    }
968
}
969
 
970
enum rtx_code
971
or32_reverse_condition (enum machine_mode mode ATTRIBUTE_UNUSED,
972
                        enum rtx_code code)
973
{
974
  return reverse_condition (code);
975
}
976
 
977
enum machine_mode
978
or32_cc_mode (enum rtx_code code,
979
              rtx op0 ATTRIBUTE_UNUSED, rtx op1 ATTRIBUTE_UNUSED)
980
{
981
 
982
  switch (code)
983
    {
984
    case EQ:
985
      return CCEQmode;
986
    case NE:
987
      return CCNEmode;
988
    case GEU:
989
      return CCGEUmode;
990
    case GTU:
991
      return CCGTUmode;
992
    case LTU:
993
      return CCLTUmode;
994
    case LEU:
995
      return CCLEUmode;
996
    case GE:
997
      return CCGEmode;
998
    case LT:
999
      return CCLTmode;
1000
    case GT:
1001
      return CCGTmode;
1002
    case LE:
1003
      return CCLEmode;
1004
 
1005
    default:
1006
      abort ();
1007
    }
1008
}
1009
 
1010
/* Generate insn patterns to do an integer compare of OPERANDS.  */
1011
 
1012
static rtx
1013
or32_expand_int_compare (enum rtx_code code, rtx op0, rtx op1)
1014
{
1015
  enum machine_mode cmpmode;
1016
  rtx tmp, flags;
1017
 
1018
  cmpmode = SELECT_CC_MODE (code, op0, op1);
1019
  flags = gen_rtx_REG (cmpmode, FLAGS_REG);
1020
 
1021
  /* This is very simple, but making the interface the same as in the
1022
     FP case makes the rest of the code easier.  */
1023
  tmp = gen_rtx_COMPARE (cmpmode, op0, op1);
1024
  emit_insn (gen_rtx_SET (VOIDmode, flags, tmp));
1025
 
1026
  /* Return the test that should be put into the flags user, i.e.
1027
     the bcc, scc, or cmov instruction.  */
1028
  return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
1029
}
1030
 
1031
rtx
1032
or32_expand_compare (enum rtx_code code, rtx op0, rtx op1)
1033
{
1034
  return or32_expand_int_compare (code, op0, op1);
1035
}
1036
 
1037
void
1038
or32_expand_branch (enum rtx_code code, rtx label)
1039
{
1040
  rtx tmp;
1041
 
1042
  switch (GET_MODE (or32_compare_op0))
1043
    {
1044
    case SImode:
1045
      tmp = or32_expand_compare (code, or32_compare_op0, or32_compare_op1);
1046
      tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
1047
                                  tmp,
1048
                                  gen_rtx_LABEL_REF (VOIDmode, label),
1049
                                  pc_rtx);
1050
      emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
1051
      return;
1052
 
1053
 
1054
    default:
1055
      abort ();
1056
    }
1057
 
1058
}
1059
 
1060
static int
1061
or32_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
1062
{
1063
  rtx condition_rtx, cr;
1064
 
1065
  if ((GET_MODE (or32_compare_op0) != SImode) &&
1066
      (GET_MODE (or32_compare_op0) != HImode) &&
1067
      (GET_MODE (or32_compare_op0) != QImode))
1068
    return 0;
1069
 
1070
  /* We still have to do the compare, because cmov doesn't do a
1071
     compare, it just looks at the FLAG bit set by a previous compare
1072
     instruction.  */
1073
 
1074
  condition_rtx = or32_expand_compare (GET_CODE (op),
1075
                                       or32_compare_op0, or32_compare_op1);
1076
 
1077
  cr = XEXP (condition_rtx, 0);
1078
 
1079
  emit_insn (gen_cmov (dest, condition_rtx, true_cond, false_cond, cr));
1080
 
1081
  return 1;
1082
}
1083
 
1084
 
1085
/* Emit a conditional move: move TRUE_COND to DEST if OP of the
1086
   operands of the last comparison is nonzero/true, FALSE_COND if it
1087
   is zero/false.  Return 0 if the hardware has no such operation.  */
1088
 
1089
int
1090
or32_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
1091
{
1092
  enum machine_mode result_mode = GET_MODE (dest);
1093
 
1094
  if (GET_MODE (true_cond) != result_mode)
1095
    return 0;
1096
 
1097
  if (GET_MODE (false_cond) != result_mode)
1098
    return 0;
1099
 
1100
  /* First, work out if the hardware can do this at all */
1101
  return or32_emit_int_cmove (dest, op, true_cond, false_cond);
1102
}
1103
 
1104
const char *
1105
output_bf (rtx * operands)
1106
{
1107
  enum rtx_code code;
1108
  enum machine_mode mode_calc, mode_got;
1109
 
1110
  code = GET_CODE (operands[1]);
1111
  mode_calc = SELECT_CC_MODE (code, or32_compare_op0, or32_compare_op1);
1112
  mode_got = GET_MODE (operands[2]);
1113
 
1114
  if (!TARGET_ALIGNED_JUMPS)
1115
    {
1116
      if (mode_calc != mode_got)
1117
        return "l.bnf   \t%l0%(";
1118
      else
1119
        return "l.bf    \t%l0%(";
1120
    }
1121
  else
1122
    {
1123
      if (mode_calc != mode_got)
1124
        return "\t.balignl 0x8,0x15000015,0x4;l.bnf   \t%l0%(";
1125
      else
1126
        return "\t.balignl 0x8,0x15000015,0x4;l.bf    \t%l0%(";
1127
    }
1128
}
1129
 
1130
const char *
1131
output_cmov (rtx * operands)
1132
{
1133
  enum rtx_code code;
1134
  enum machine_mode mode_calc, mode_got;
1135
 
1136
  code = GET_CODE (operands[1]);
1137
  mode_calc = SELECT_CC_MODE (code, or32_compare_op0, or32_compare_op1);
1138
  mode_got = GET_MODE (operands[4]);
1139
 
1140
  if (mode_calc != mode_got)
1141
    return "l.cmov  \t%0,%3,%2";        /* reversed */
1142
  else
1143
    return "l.cmov  \t%0,%2,%3";
1144
}
1145
 
1146
/* Any function is ok for sibcall optimization if we allow this optimization
1147
 */
1148
static bool
1149
or32_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1150
                              tree exp ATTRIBUTE_UNUSED)
1151
{
1152
  return TARGET_SIBCALL;
1153
}
1154
 
1155
/* For now this is very simple way for sibcall support */
1156
 
1157
void
1158
or32_expand_sibcall (rtx result, rtx addr, rtx args_size)
1159
{
1160
  emit_call_insn (gen_sibcall_internal (addr, args_size));
1161
}
1162
 
1163
 
1164
/* We know it can't be done in one insn when we get here,
1165
   the movsi expander guarantees this.  */
1166
void
1167
or32_emit_set_const32 (rtx op0, rtx op1)
1168
{
1169
  enum machine_mode mode = GET_MODE (op0);
1170
  rtx temp;
1171
 
1172
 
1173
  if (GET_CODE (op1) == CONST_INT)
1174
    {
1175
      HOST_WIDE_INT value = INTVAL (op1);
1176
 
1177
      if (CONST_OK_FOR_LETTER_P (value & GET_MODE_MASK (mode), 'K')
1178
          || CONST_OK_FOR_LETTER_P (value, 'M')
1179
          || CONST_OK_FOR_LETTER_P (value, 'I'))
1180
        abort ();
1181
    }
1182
 
1183
 
1184
  /* Full 2-insn decomposition is needed.  */
1185
  if (reload_in_progress || reload_completed)
1186
    {
1187
      temp = op0;
1188
    }
1189
  else
1190
    temp = gen_reg_rtx (mode);
1191
 
1192
  if (GET_CODE (op1) == CONST_INT)
1193
    {
1194
      /* Emit them as real moves instead of a HIGH/LO_SUM,
1195
         this way CSE can see everything and reuse intermediate
1196
         values if it wants.  */
1197
      emit_insn (gen_rtx_SET (VOIDmode, temp,
1198
                              GEN_INT (INTVAL (op1)
1199
                                       & ~(HOST_WIDE_INT) 0xffff)));
1200
 
1201
      emit_insn (gen_rtx_SET (VOIDmode,
1202
                              op0,
1203
                              gen_rtx_IOR (mode, temp,
1204
                                           GEN_INT (INTVAL (op1) & 0xffff))));
1205
    }
1206
  else
1207
    {
1208
 
1209
#if 0
1210
      /* A symbol, emit in the traditional way.  */
1211
 
1212
      emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_HIGH (mode, op1)));
1213
      emit_insn (gen_rtx_SET (VOIDmode,
1214
                              op0, gen_rtx_LO_SUM (mode, temp, op1)));
1215
#else
1216
      /* since or32 bfd can not deal with relocs that are not of type
1217
         OR32_CONSTH_RELOC + OR32_CONST_RELOC (ie move high must be
1218
         followed by exactly one lo_sum)
1219
       */
1220
      emit_insn (gen_movsi_insn_big (op0, op1));
1221
#endif
1222
    }
1223
}
1224
 
1225
 
1226
/* Functions returning costs and making code size/performance tradeoffs */
1227
 
1228
int
1229
or32_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1230
                         enum reg_class from ATTRIBUTE_UNUSED,
1231
                         enum reg_class to ATTRIBUTE_UNUSED)
1232
{
1233
  return 2;
1234
}
1235
 
1236
/* A C expressions returning the cost of moving data of MODE from a register to
1237
   or from memory.  */
1238
 
1239
int
1240
or32_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1241
                       enum reg_class class ATTRIBUTE_UNUSED,
1242
                       int in ATTRIBUTE_UNUSED)
1243
{
1244
  return 2;
1245
}
1246
 
1247
/* Specify the cost of a branch insn; roughly the number of extra insns that
1248
   should be added to avoid a branch.
1249
 
1250
   Set this to 3 on the or32 since that is roughly the average cost of an
1251
   unscheduled conditional branch.
1252
 
1253
   Cost of 2 and 3 give equal and ~0.7% bigger binaries
1254
 
1255
*/
1256
int
1257
or32_branch_cost ()
1258
{
1259
  return 1;
1260
}

powered by: WebSVN 2.1.0

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