OSDN Git Service

288b86fc10f0aedbfed9a9357c38266b1af100a2
[pf3gnuchains/gcc-fork.git] / gcc / config / microblaze / microblaze.c
1 /* Subroutines used for code generation on Xilinx MicroBlaze.
2    Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
3
4    Contributed by Michael Eager <eager@eagercon.com>.
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 "real.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-flags.h"
33 #include "insn-attr.h"
34 #include "integrate.h"
35 #include "recog.h"
36 #include "tree.h"
37 #include "function.h"
38 #include "expr.h"
39 #include "flags.h"
40 #include "reload.h"
41 #include "output.h"
42 #include "ggc.h"
43 #include "hashtab.h"
44 #include "target.h"
45 #include "target-def.h"
46 #include "tm_p.h"
47 #include "gstab.h"
48 #include "df.h"
49 #include "optabs.h"
50 #include "diagnostic-core.h"
51
52 #define MICROBLAZE_VERSION_COMPARE(VA,VB) strcasecmp (VA, VB)
53
54 /* Classifies an address.
55
56 ADDRESS_INVALID
57 An invalid address.
58
59 ADDRESS_REG
60
61 A natural register or a register + const_int offset address.  
62 The register satisfies microblaze_valid_base_register_p and the 
63 offset is a const_arith_operand.
64
65 ADDRESS_REG_INDEX
66
67 A natural register offset by the index contained in an index register. The base
68 register satisfies microblaze_valid_base_register_p and the index register
69 satisfies microblaze_valid_index_register_p
70
71 ADDRESS_CONST_INT
72
73 A signed 16/32-bit constant address.
74
75 ADDRESS_SYMBOLIC:
76
77 A constant symbolic address or a (register + symbol).  */
78
79 enum microblaze_address_type
80 {
81   ADDRESS_INVALID,
82   ADDRESS_REG,
83   ADDRESS_REG_INDEX,
84   ADDRESS_CONST_INT,
85   ADDRESS_SYMBOLIC,
86   ADDRESS_GOTOFF,
87   ADDRESS_PLT
88 };
89
90 /* Classifies symbols
91
92 SYMBOL_TYPE_GENERAL
93         
94 A general symbol.  */
95 enum microblaze_symbol_type
96 {
97   SYMBOL_TYPE_INVALID,
98   SYMBOL_TYPE_GENERAL
99 };
100
101 /* Classification of a MicroBlaze address.  */
102 struct microblaze_address_info
103 {
104   enum microblaze_address_type type;
105   rtx regA;     /* Contains valid values on ADDRESS_REG, ADDRESS_REG_INDEX, 
106                    ADDRESS_SYMBOLIC.  */
107   rtx regB;     /* Contains valid values on ADDRESS_REG_INDEX.  */
108   rtx offset;   /* Contains valid values on ADDRESS_CONST_INT and ADDRESS_REG.  */
109   rtx symbol;   /* Contains valid values on ADDRESS_SYMBOLIC.  */
110   enum microblaze_symbol_type symbol_type;
111 };
112
113 /* Structure to be filled in by compute_frame_size with register
114    save masks, and offsets for the current function.  */
115
116 struct GTY(()) microblaze_frame_info {
117   long total_size;              /* # bytes that the entire frame takes up.  */
118   long var_size;                /* # bytes that variables take up.  */
119   long args_size;               /* # bytes that outgoing arguments take up.  */
120   int link_debug_size;          /* # bytes for the link reg and back pointer.  */
121   int gp_reg_size;              /* # bytes needed to store gp regs.  */
122   long gp_offset;               /* offset from new sp to store gp registers.  */
123   long mask;                    /* mask of saved gp registers.  */
124   int initialized;              /* != 0 if frame size already calculated.  */
125   int num_gp;                   /* number of gp registers saved.  */
126   long insns_len;               /* length of insns.  */
127   int alloc_stack;              /* Flag to indicate if the current function 
128                                    must not create stack space. (As an optimization).  */
129 };
130
131 /* Global variables for machine-dependent things.  */
132
133 /* Toggle which pipleline interface to use.  */
134 static GTY(()) int microblaze_sched_use_dfa = 0;
135
136 /* Threshold for data being put into the small data/bss area, instead
137    of the normal data area (references to the small data/bss area take
138    1 instruction, and use the global pointer, references to the normal
139    data area takes 2 instructions).  */
140 int microblaze_section_threshold = -1;
141
142 /* Prevent scheduling potentially exception causing instructions in 
143    delay slots.  -mcpu=v3.00.a or v4.00.a turns this on.  */
144 int microblaze_no_unsafe_delay;
145
146 /* Which CPU pipeline do we use. We haven't really standardized on a CPU 
147    version having only a particular type of pipeline. There can still be 
148    options on the CPU to scale pipeline features up or down. :( 
149    Bad Presentation (??), so we let the MD file rely on the value of 
150    this variable instead Making PIPE_5 the default. It should be backward 
151    optimal with PIPE_3 MicroBlazes.  */
152 enum pipeline_type microblaze_pipe = MICROBLAZE_PIPE_5;
153
154 /* High and low marks for floating point values which we will accept
155    as legitimate constants for TARGET_LEGITIMATE_CONSTANT_P.  These are
156    initialized in override_options.  */
157 REAL_VALUE_TYPE dfhigh, dflow, sfhigh, sflow;
158
159 /* Array giving truth value on whether or not a given hard register
160    can support a given mode.  */
161 char microblaze_hard_regno_mode_ok[(int)MAX_MACHINE_MODE]
162                                   [FIRST_PSEUDO_REGISTER];
163
164 /* Current frame information calculated by compute_frame_size.  */
165 struct microblaze_frame_info current_frame_info;
166
167 /* Zero structure to initialize current_frame_info.  */
168 struct microblaze_frame_info zero_frame_info;
169
170 /* List of all MICROBLAZE punctuation characters used by print_operand.  */
171 char microblaze_print_operand_punct[256];
172
173 /* Map GCC register number to debugger register number.  */
174 int microblaze_dbx_regno[FIRST_PSEUDO_REGISTER];
175
176 /* Map hard register number to register class.  */
177 enum reg_class microblaze_regno_to_class[] =
178 {
179   GR_REGS,      GR_REGS,        GR_REGS,        GR_REGS,
180   GR_REGS,      GR_REGS,        GR_REGS,        GR_REGS,
181   GR_REGS,      GR_REGS,        GR_REGS,        GR_REGS,
182   GR_REGS,      GR_REGS,        GR_REGS,        GR_REGS,
183   GR_REGS,      GR_REGS,        GR_REGS,        GR_REGS,
184   GR_REGS,      GR_REGS,        GR_REGS,        GR_REGS,
185   GR_REGS,      GR_REGS,        GR_REGS,        GR_REGS,
186   GR_REGS,      GR_REGS,        GR_REGS,        GR_REGS,
187   ST_REGS,      GR_REGS,        GR_REGS,        GR_REGS
188 };
189
190 /* MicroBlaze specific machine attributes.
191    interrupt_handler - Interrupt handler attribute to add interrupt prologue 
192                        and epilogue and use appropriate interrupt return.
193    save_volatiles    - Similiar to interrupt handler, but use normal return.  */
194 int interrupt_handler;
195 int save_volatiles;
196
197 const struct attribute_spec microblaze_attribute_table[] = {
198   /* name         min_len, max_len, decl_req, type_req, fn_type, req_handler,
199      affects_type_identity */
200   {"interrupt_handler", 0,       0,     true,    false,   false,        NULL,
201     false },
202   {"save_volatiles"   , 0,       0,     true,    false,   false,        NULL,
203     false },
204   { NULL,               0,       0,    false,    false,   false,        NULL,
205     false }
206 };
207
208 static int microblaze_interrupt_function_p (tree);
209
210 section *sdata2_section;
211
212 /* Return truth value if a CONST_DOUBLE is ok to be a legitimate constant.  */
213 static bool
214 microblaze_const_double_ok (rtx op, enum machine_mode mode)
215 {
216   REAL_VALUE_TYPE d;
217
218   if (GET_CODE (op) != CONST_DOUBLE)
219     return 0;
220
221   if (GET_MODE (op) == VOIDmode)
222     return 1;
223
224   if (mode != SFmode && mode != DFmode)
225     return 0;
226
227   if (op == CONST0_RTX (mode))
228     return 1;
229
230   REAL_VALUE_FROM_CONST_DOUBLE (d, op);
231
232   if (REAL_VALUE_ISNAN (d))
233     return FALSE;
234
235   if (REAL_VALUE_NEGATIVE (d))
236     d = real_value_negate (&d);
237
238   if (mode == DFmode)
239     {
240       if (REAL_VALUES_LESS (d, dfhigh) && REAL_VALUES_LESS (dflow, d))
241         return 1;
242     }
243   else
244     {
245       if (REAL_VALUES_LESS (d, sfhigh) && REAL_VALUES_LESS (sflow, d))
246         return 1;
247     }
248
249   return 0;
250 }
251
252 /* Return truth value if a memory operand fits in a single instruction
253    (ie, register + small offset) or (register + register).  */
254
255 int
256 simple_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
257 {
258   rtx addr, plus0, plus1;
259
260   /* Eliminate non-memory operations.  */
261   if (GET_CODE (op) != MEM)
262     return 0;
263
264   /* dword operations really put out 2 instructions, so eliminate them.  */
265   /* ??? This isn't strictly correct.  It is OK to accept multiword modes
266      here, since the length attributes are being set correctly, but only
267      if the address is offsettable.  */
268   if (GET_MODE_SIZE (GET_MODE (op)) > UNITS_PER_WORD)
269     return 0;
270
271
272   /* Decode the address now.  */
273   addr = XEXP (op, 0);
274   switch (GET_CODE (addr))
275
276     {
277     case REG:
278       return 1;
279
280     case PLUS:
281       plus0 = XEXP (addr, 0);
282       plus1 = XEXP (addr, 1);
283
284       if (GET_CODE (plus0) == REG && GET_CODE (plus1) == CONST_INT
285           && SMALL_INT (plus1))
286         {
287           return 1;
288         }
289       else if (GET_CODE (plus1) == REG && GET_CODE (plus0) == CONST_INT)
290         {
291           return 1;
292         }
293       else if (GET_CODE (plus0) == REG && GET_CODE (plus1) == REG)
294         {
295           return 1;
296         }
297       else
298         return 0;
299
300     case SYMBOL_REF:
301       return 0;
302
303     default:
304       break;
305     }
306
307   return 0;
308 }
309
310 /* Return nonzero for a memory address that can be used to load or store
311    a doubleword.  */
312
313 int
314 double_memory_operand (rtx op, enum machine_mode mode)
315 {
316   rtx addr;
317
318   if (GET_CODE (op) != MEM || !memory_operand (op, mode))
319     {
320       /* During reload, we accept a pseudo register if it has an
321          appropriate memory address.  If we don't do this, we will
322          wind up reloading into a register, and then reloading that
323          register from memory, when we could just reload directly from
324          memory.  */
325       if (reload_in_progress
326           && GET_CODE (op) == REG
327           && REGNO (op) >= FIRST_PSEUDO_REGISTER
328           && reg_renumber[REGNO (op)] < 0
329           && reg_equiv_mem (REGNO (op)) != 0
330           && double_memory_operand (reg_equiv_mem (REGNO (op)), mode))
331         return 1;
332       return 0;
333     }
334
335   /* Make sure that 4 added to the address is a valid memory address.
336      This essentially just checks for overflow in an added constant.  */
337
338   addr = XEXP (op, 0);
339
340   if (CONSTANT_ADDRESS_P (addr))
341     return 1;
342
343   return memory_address_p ((GET_MODE_CLASS (mode) == MODE_INT
344                             ? SImode : SFmode), plus_constant (addr, 4));
345 }
346
347 /* Implement REG_OK_FOR_BASE_P -and- REG_OK_FOR_INDEX_P.  */
348 int
349 microblaze_regno_ok_for_base_p (int regno, int strict)
350 {
351   if (regno >= FIRST_PSEUDO_REGISTER)
352     {
353       if (!strict)
354         return true;
355       regno = reg_renumber[regno];
356     }
357
358   /* These fake registers will be eliminated to either the stack or
359      hard frame pointer, both of which are usually valid base registers.
360      Reload deals with the cases where the eliminated form isn't valid.  */
361   if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM)
362     return true;
363
364   return GP_REG_P (regno);
365 }
366
367 /* Return true if X is a valid base register for the given mode.
368    Allow only hard registers if STRICT.  */
369
370 static bool
371 microblaze_valid_base_register_p (rtx x,
372                                   enum machine_mode mode ATTRIBUTE_UNUSED,
373                                   int strict)
374 {
375   if (!strict && GET_CODE (x) == SUBREG)
376     x = SUBREG_REG (x);
377
378   return (GET_CODE (x) == REG
379           && microblaze_regno_ok_for_base_p (REGNO (x), strict));
380 }
381
382 static bool
383 microblaze_classify_unspec (struct microblaze_address_info *info, rtx x)
384 {
385   info->symbol_type = SYMBOL_TYPE_GENERAL;
386   info->symbol = XVECEXP (x, 0, 0);
387
388   if (XINT (x, 1) == UNSPEC_GOTOFF)
389     {
390       info->regA = gen_rtx_REG (SImode, PIC_OFFSET_TABLE_REGNUM);
391       info->type = ADDRESS_GOTOFF;
392     }
393   else if (XINT (x, 1) == UNSPEC_PLT)
394     {
395       info->type = ADDRESS_PLT;
396     }
397   else
398     {
399       return false;
400     }
401   return true;
402 }
403
404
405 /* Return true if X is a valid index register for the given mode.
406    Allow only hard registers if STRICT.  */
407
408 static bool
409 microblaze_valid_index_register_p (rtx x,
410                                    enum machine_mode mode ATTRIBUTE_UNUSED,
411                                    int strict)
412 {
413   if (!strict && GET_CODE (x) == SUBREG)
414     x = SUBREG_REG (x);
415
416   return (GET_CODE (x) == REG
417           /* A base register is good enough to be an index register on MicroBlaze.  */
418           && microblaze_regno_ok_for_base_p (REGNO (x), strict));
419 }
420
421 /* Get the base register for accessing a value from the memory or
422    Symbol ref. Used for MicroBlaze Small Data Area Pointer Optimization.  */
423 static int
424 get_base_reg (rtx x)
425 {
426   tree decl;
427   int base_reg = (flag_pic ? MB_ABI_PIC_ADDR_REGNUM : MB_ABI_BASE_REGNUM);
428
429   if (TARGET_XLGPOPT
430       && GET_CODE (x) == SYMBOL_REF
431       && SYMBOL_REF_SMALL_P (x) && (decl = SYMBOL_REF_DECL (x)) != NULL)
432     {
433       if (TREE_READONLY (decl))
434         base_reg = MB_ABI_GPRO_REGNUM;
435       else
436         base_reg = MB_ABI_GPRW_REGNUM;
437     }
438
439   return base_reg;
440 }
441
442 /* Return true if X is a valid address for machine mode MODE.  If it is,
443    fill in INFO appropriately.  STRICT is true if we should only accept
444    hard base registers.  
445
446       type                     regA      regB    offset      symbol
447
448    ADDRESS_INVALID             NULL      NULL     NULL        NULL
449
450    ADDRESS_REG                 %0        NULL     const_0 /   NULL
451                                                   const_int
452    ADDRESS_REG_INDEX           %0        %1       NULL        NULL
453
454    ADDRESS_SYMBOLIC            r0 /      NULL     NULL        symbol    
455                            sda_base_reg 
456
457    ADDRESS_CONST_INT           r0       NULL      const       NULL
458
459    For modes spanning multiple registers (DFmode in 32-bit GPRs,
460    DImode, TImode), indexed addressing cannot be used because
461    adjacent memory cells are accessed by adding word-sized offsets
462    during assembly output.  */
463
464 static bool
465 microblaze_classify_address (struct microblaze_address_info *info, rtx x,
466                              enum machine_mode mode, int strict)
467 {
468   rtx xplus0;
469   rtx xplus1;
470
471   info->type = ADDRESS_INVALID;
472   info->regA = NULL;
473   info->regB = NULL;
474   info->offset = NULL;
475   info->symbol = NULL;
476   info->symbol_type = SYMBOL_TYPE_INVALID;
477
478   switch (GET_CODE (x))
479     {
480     case REG:
481     case SUBREG:
482       {
483         info->type = ADDRESS_REG;
484         info->regA = x;
485         info->offset = const0_rtx;
486         return microblaze_valid_base_register_p (info->regA, mode, strict);
487       }
488     case PLUS:
489       {
490         xplus0 = XEXP (x, 0);
491         xplus1 = XEXP (x, 1);
492
493         if (microblaze_valid_base_register_p (xplus0, mode, strict))
494           {
495             info->type = ADDRESS_REG;
496             info->regA = xplus0;
497
498             if (GET_CODE (xplus1) == CONST_INT)
499               {
500                 info->offset = xplus1;
501                 return true;
502               }
503             else if (GET_CODE (xplus1) == UNSPEC)
504               {
505                 return microblaze_classify_unspec (info, xplus1);
506               }
507             else if ((GET_CODE (xplus1) == SYMBOL_REF ||
508                       GET_CODE (xplus1) == LABEL_REF) && flag_pic == 2)
509               {
510                 return false;
511               }
512             else if (GET_CODE (xplus1) == SYMBOL_REF ||
513                      GET_CODE (xplus1) == LABEL_REF ||
514                      GET_CODE (xplus1) == CONST)
515               {
516                 if (GET_CODE (XEXP (xplus1, 0)) == UNSPEC)
517                   return microblaze_classify_unspec (info, XEXP (xplus1, 0));
518                 else if (flag_pic == 2)
519                   {
520                     return false;
521                   }
522                 info->type = ADDRESS_SYMBOLIC;
523                 info->symbol = xplus1;
524                 info->symbol_type = SYMBOL_TYPE_GENERAL;
525                 return true;
526               }
527             else if (GET_CODE (xplus1) == REG
528                      && microblaze_valid_index_register_p (xplus1, mode,
529                                                            strict)
530                      && (GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
531               {
532                 /* Restrict larger than word-width modes from using an index register.  */
533                 info->type = ADDRESS_REG_INDEX;
534                 info->regB = xplus1;
535                 return true;
536               }
537           }
538         break;
539       }
540     case CONST_INT:
541       {
542         info->regA = gen_rtx_raw_REG (mode, 0);
543         info->type = ADDRESS_CONST_INT;
544         info->offset = x;
545         return true;
546       }
547     case CONST:
548     case LABEL_REF:
549     case SYMBOL_REF:
550       {
551         info->type = ADDRESS_SYMBOLIC;
552         info->symbol_type = SYMBOL_TYPE_GENERAL;
553         info->symbol = x;
554         info->regA = gen_rtx_raw_REG (mode, get_base_reg (x));
555
556         if (GET_CODE (x) == CONST)
557           {
558             return !(flag_pic && pic_address_needs_scratch (x));
559           }
560         else if (flag_pic == 2)
561           {
562             return false;
563           }
564
565         return true;
566       }
567
568     case UNSPEC:
569       {
570         if (reload_in_progress)
571           df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
572         return microblaze_classify_unspec (info, x);
573       }
574
575     default:
576       return false;
577     }
578
579   return false;
580 }
581
582 /* This function is used to implement GO_IF_LEGITIMATE_ADDRESS.  It
583    returns a nonzero value if X is a legitimate address for a memory
584    operand of the indicated MODE.  STRICT is nonzero if this function
585    is called during reload.  */
586
587 bool
588 microblaze_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
589 {
590   struct microblaze_address_info addr;
591
592   return microblaze_classify_address (&addr, x, mode, strict);
593 }
594
595
596 /* Try machine-dependent ways of modifying an illegitimate address
597    to be legitimate.  If we find one, return the new, valid address.
598    This is used from only one place: `memory_address' in explow.c.
599
600    OLDX is the address as it was before break_out_memory_refs was
601    called.  In some cases it is useful to look at this to decide what
602    needs to be done.
603
604    It is always safe for this function to do nothing.  It exists to
605    recognize opportunities to optimize the output.
606
607    For the MicroBlaze, transform:
608
609    memory(X + <large int>)
610
611    into:
612
613    Y = <large int> & ~0x7fff;
614    Z = X + Y
615    memory (Z + (<large int> & 0x7fff));
616
617    This is for CSE to find several similar references, and only use one Z.
618
619    When PIC, convert addresses of the form memory (symbol+large int) to
620    memory (reg+large int).  */
621
622 static rtx
623 microblaze_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
624                                enum machine_mode mode ATTRIBUTE_UNUSED)
625 {
626   register rtx xinsn = x, result;
627
628   if (GET_CODE (xinsn) == CONST
629       && flag_pic && pic_address_needs_scratch (xinsn))
630     {
631       rtx ptr_reg = gen_reg_rtx (Pmode);
632       rtx constant = XEXP (XEXP (xinsn, 0), 1);
633
634       emit_move_insn (ptr_reg, XEXP (XEXP (xinsn, 0), 0));
635
636       result = gen_rtx_PLUS (Pmode, ptr_reg, constant);
637       if (SMALL_INT (constant))
638         return result;
639       /* Otherwise we fall through so the code below will fix the 
640          constant.  */
641       xinsn = result;
642     }
643
644   if (GET_CODE (xinsn) == PLUS)
645     {
646       register rtx xplus0 = XEXP (xinsn, 0);
647       register rtx xplus1 = XEXP (xinsn, 1);
648       register enum rtx_code code0 = GET_CODE (xplus0);
649       register enum rtx_code code1 = GET_CODE (xplus1);
650
651       if (code0 != REG && code1 == REG)
652         {
653           xplus0 = XEXP (xinsn, 1);
654           xplus1 = XEXP (xinsn, 0);
655           code0 = GET_CODE (xplus0);
656           code1 = GET_CODE (xplus1);
657         }
658
659       if (code0 == REG && REG_OK_FOR_BASE_P (xplus0)
660           && code1 == CONST_INT && !SMALL_INT (xplus1))
661         {
662           rtx int_reg = gen_reg_rtx (Pmode);
663           rtx ptr_reg = gen_reg_rtx (Pmode);
664
665           emit_move_insn (int_reg, GEN_INT (INTVAL (xplus1) & ~0x7fff));
666
667           emit_insn (gen_rtx_SET (VOIDmode,
668                                   ptr_reg,
669                                   gen_rtx_PLUS (Pmode, xplus0, int_reg)));
670
671           result = gen_rtx_PLUS (Pmode, ptr_reg,
672                                  GEN_INT (INTVAL (xplus1) & 0x7fff));
673           return result;
674         }
675
676       if (code0 == REG && REG_OK_FOR_BASE_P (xplus0) && flag_pic == 2)
677         {
678           if (reload_in_progress)
679             df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
680           if (code1 == CONST)
681             {
682               xplus1 = XEXP (xplus1, 0);
683               code1 = GET_CODE (xplus1);
684             }
685           if (code1 == SYMBOL_REF)
686             {
687               result =
688                 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xplus1), UNSPEC_GOTOFF);
689               result = gen_rtx_CONST (Pmode, result);
690               result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
691               result = gen_const_mem (Pmode, result);
692               result = gen_rtx_PLUS (Pmode, xplus0, result);
693               return result;
694             }
695         }
696     }
697
698   if (GET_CODE (xinsn) == SYMBOL_REF)
699     {
700       if (reload_in_progress)
701         df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
702       result = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_GOTOFF);
703       result = gen_rtx_CONST (Pmode, result);
704       result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
705       result = gen_const_mem (Pmode, result);
706       return result;
707     }
708
709   return x;
710 }
711
712 /* Block Moves.  */
713
714 #define MAX_MOVE_REGS 8
715 #define MAX_MOVE_BYTES (MAX_MOVE_REGS * UNITS_PER_WORD)
716
717 /* Emit straight-line code to move LENGTH bytes from SRC to DEST.
718    Assume that the areas do not overlap.  */
719
720 static void
721 microblaze_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length)
722 {
723   HOST_WIDE_INT offset, delta;
724   unsigned HOST_WIDE_INT bits;
725   int i;
726   enum machine_mode mode;
727   rtx *regs;
728
729   bits = BITS_PER_WORD;
730   mode = mode_for_size (bits, MODE_INT, 0);
731   delta = bits / BITS_PER_UNIT;
732
733   /* Allocate a buffer for the temporary registers.  */
734   regs = XALLOCAVEC (rtx, length / delta);
735
736   /* Load as many BITS-sized chunks as possible.  Use a normal load if
737      the source has enough alignment, otherwise use left/right pairs.  */
738   for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
739     {
740       regs[i] = gen_reg_rtx (mode);
741       emit_move_insn (regs[i], adjust_address (src, mode, offset));
742     }
743
744   /* Copy the chunks to the destination.  */
745   for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
746     emit_move_insn (adjust_address (dest, mode, offset), regs[i]);
747
748   /* Mop up any left-over bytes.  */
749   if (offset < length)
750     {
751       src = adjust_address (src, BLKmode, offset);
752       dest = adjust_address (dest, BLKmode, offset);
753       move_by_pieces (dest, src, length - offset,
754                       MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), 0);
755     }
756 }
757
758 /* Helper function for doing a loop-based block operation on memory
759    reference MEM.  Each iteration of the loop will operate on LENGTH
760    bytes of MEM.
761
762    Create a new base register for use within the loop and point it to
763    the start of MEM.  Create a new memory reference that uses this
764    register.  Store them in *LOOP_REG and *LOOP_MEM respectively.  */
765
766 static void
767 microblaze_adjust_block_mem (rtx mem, HOST_WIDE_INT length,
768                              rtx * loop_reg, rtx * loop_mem)
769 {
770   *loop_reg = copy_addr_to_reg (XEXP (mem, 0));
771
772   /* Although the new mem does not refer to a known location,
773      it does keep up to LENGTH bytes of alignment.  */
774   *loop_mem = change_address (mem, BLKmode, *loop_reg);
775   set_mem_align (*loop_mem,
776                  MIN ((HOST_WIDE_INT) MEM_ALIGN (mem),
777                       length * BITS_PER_UNIT));
778 }
779
780
781 /* Move LENGTH bytes from SRC to DEST using a loop that moves MAX_MOVE_BYTES
782    per iteration.  LENGTH must be at least MAX_MOVE_BYTES.  Assume that the
783    memory regions do not overlap.  */
784
785 static void
786 microblaze_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length)
787 {
788   rtx label, src_reg, dest_reg, final_src;
789   HOST_WIDE_INT leftover;
790
791   leftover = length % MAX_MOVE_BYTES;
792   length -= leftover;
793
794   /* Create registers and memory references for use within the loop.  */
795   microblaze_adjust_block_mem (src, MAX_MOVE_BYTES, &src_reg, &src);
796   microblaze_adjust_block_mem (dest, MAX_MOVE_BYTES, &dest_reg, &dest);
797
798   /* Calculate the value that SRC_REG should have after the last iteration
799      of the loop.  */
800   final_src = expand_simple_binop (Pmode, PLUS, src_reg, GEN_INT (length),
801                                    0, 0, OPTAB_WIDEN);
802
803   /* Emit the start of the loop.  */
804   label = gen_label_rtx ();
805   emit_label (label);
806
807   /* Emit the loop body.  */
808   microblaze_block_move_straight (dest, src, MAX_MOVE_BYTES);
809
810   /* Move on to the next block.  */
811   emit_move_insn (src_reg, plus_constant (src_reg, MAX_MOVE_BYTES));
812   emit_move_insn (dest_reg, plus_constant (dest_reg, MAX_MOVE_BYTES));
813
814   /* Emit the test & branch.  */
815   emit_insn (gen_cbranchsi4 (gen_rtx_NE (SImode, src_reg, final_src),
816                              src_reg, final_src, label));
817
818   /* Mop up any left-over bytes.  */
819   if (leftover)
820     microblaze_block_move_straight (dest, src, leftover);
821 }
822
823 /* Expand a movmemsi instruction.  */
824
825 bool
826 microblaze_expand_block_move (rtx dest, rtx src, rtx length, rtx align_rtx)
827 {
828
829   if (GET_CODE (length) == CONST_INT)
830     {
831       HOST_WIDE_INT bytes = INTVAL (length);
832       int align = INTVAL (align_rtx);
833
834       if (align > UNITS_PER_WORD)
835         {
836           align = UNITS_PER_WORD;       /* We can't do any better.  */
837         }
838       else if (align < UNITS_PER_WORD)
839         {
840           if (INTVAL (length) <= MAX_MOVE_BYTES)
841             {
842               move_by_pieces (dest, src, bytes, align, 0);
843               return true;
844             }
845           else
846             return false;
847         }
848
849       if (INTVAL (length) <= 2 * MAX_MOVE_BYTES)
850         {
851           microblaze_block_move_straight (dest, src, INTVAL (length));
852           return true;
853         }
854       else if (optimize)
855         {
856           microblaze_block_move_loop (dest, src, INTVAL (length));
857           return true;
858         }
859     }
860   return false;
861 }
862
863 static bool
864 microblaze_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total, 
865                       bool speed ATTRIBUTE_UNUSED)
866 {
867   enum machine_mode mode = GET_MODE (x);
868
869   switch (code)
870     {
871     case MEM:
872       {
873         int num_words = (GET_MODE_SIZE (mode) > UNITS_PER_WORD) ? 2 : 1;
874         if (simple_memory_operand (x, mode))
875           *total = COSTS_N_INSNS (2 * num_words);
876         else
877           *total = COSTS_N_INSNS (2 * (2 * num_words));
878
879         return true;
880       }
881     case NOT:
882       {
883         if (mode == DImode)
884           {
885             *total = COSTS_N_INSNS (2);
886           }
887         else
888           *total = COSTS_N_INSNS (1);
889         return false;
890       }
891     case AND:
892     case IOR:
893     case XOR:
894       {
895         if (mode == DImode)
896           {
897             *total = COSTS_N_INSNS (2);
898           }
899         else
900           *total = COSTS_N_INSNS (1);
901
902         return false;
903       }
904     case ASHIFT:
905     case ASHIFTRT:
906     case LSHIFTRT:
907       {
908         if (TARGET_BARREL_SHIFT)
909           {
910             if (MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v5.00.a")
911                 >= 0)
912               *total = COSTS_N_INSNS (1);
913             else
914               *total = COSTS_N_INSNS (2);
915           }
916         else if (!TARGET_SOFT_MUL)
917           *total = COSTS_N_INSNS (1);
918         else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
919           {
920             /* Add 1 to make shift slightly more expensive than add.  */
921             *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1))) + 1;
922             /* Reduce shift costs for special circumstances.  */
923             if (optimize_size && INTVAL (XEXP (x, 1)) > 5)
924               *total -= 2;
925             if (!optimize_size && INTVAL (XEXP (x, 1)) > 17)
926               *total -= 2;
927           }
928         else
929           /* Double the worst cost of shifts when there is no barrel shifter and 
930              the shift amount is in a reg.  */
931           *total = COSTS_N_INSNS (32 * 4);
932         return true;
933       }
934     case PLUS:
935     case MINUS:
936       {
937         if (mode == SFmode || mode == DFmode)
938           {
939             if (TARGET_HARD_FLOAT)
940               *total = COSTS_N_INSNS (6);
941             return true;
942           }
943         else if (mode == DImode)
944           {
945             *total = COSTS_N_INSNS (4);
946             return true;
947           }
948         else
949           {
950             *total = COSTS_N_INSNS (1);
951             return true;
952           }
953
954         return false;
955       }
956     case NEG:
957       {
958         if (mode == DImode)
959           *total = COSTS_N_INSNS (4);
960
961         return false;
962       }
963     case MULT:
964       {
965         if (mode == SFmode)
966           {
967             if (TARGET_HARD_FLOAT)
968               *total = COSTS_N_INSNS (6);
969           }
970         else if (!TARGET_SOFT_MUL)
971           {
972             if (MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v5.00.a")
973                 >= 0)
974               *total = COSTS_N_INSNS (1);
975             else
976               *total = COSTS_N_INSNS (3);
977           }
978         else
979           *total = COSTS_N_INSNS (10);
980         return true;
981       }
982     case DIV:
983     case UDIV:
984       {
985         if (mode == SFmode)
986           {
987             if (TARGET_HARD_FLOAT)
988               *total = COSTS_N_INSNS (23);
989           }
990         return false;
991       }
992     case SIGN_EXTEND:
993       {
994         *total = COSTS_N_INSNS (1);
995         return false;
996       }
997     case ZERO_EXTEND:
998       {
999         *total = COSTS_N_INSNS (1);
1000         return false;
1001       }
1002     }
1003
1004   return false;
1005 }
1006
1007 /* Return the number of instructions needed to load or store a value
1008    of mode MODE at X.  Return 0 if X isn't valid for MODE.  */
1009
1010 static int
1011 microblaze_address_insns (rtx x, enum machine_mode mode)
1012 {
1013   struct microblaze_address_info addr;
1014
1015   if (microblaze_classify_address (&addr, x, mode, false))
1016     {
1017       switch (addr.type)
1018         {
1019         case ADDRESS_REG:
1020           if (SMALL_INT (addr.offset))
1021             return 1;
1022           else
1023             return 2;
1024         case ADDRESS_CONST_INT:
1025           if (SMALL_INT (x))
1026             return 1;
1027           else
1028             return 2;
1029         case ADDRESS_REG_INDEX:
1030         case ADDRESS_SYMBOLIC:
1031           return 1;
1032         case ADDRESS_GOTOFF:
1033           return 2;
1034         default:
1035           break;
1036         }
1037     }
1038   return 0;
1039 }
1040
1041 /* Provide the costs of an addressing mode that contains ADDR.
1042    If ADDR is not a valid address, its cost is irrelevant.  */
1043 static int
1044 microblaze_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
1045 {
1046   return COSTS_N_INSNS (microblaze_address_insns (addr, GET_MODE (addr)));
1047 }
1048
1049 /* Return nonzero if X is an address which needs a temporary register when 
1050    reloaded while generating PIC code.  */
1051
1052 int
1053 pic_address_needs_scratch (rtx x)
1054 {
1055   /* An address which is a symbolic plus a non SMALL_INT needs a temp reg.  */
1056   if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
1057       && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
1058       && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
1059       && (flag_pic == 2 || !SMALL_INT (XEXP (XEXP (x, 0), 1))))
1060     return 1;
1061
1062   return 0;
1063 }
1064
1065 /* Argument support functions.  */
1066 /* Initialize CUMULATIVE_ARGS for a function.  */
1067
1068 void
1069 init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
1070                       rtx libname ATTRIBUTE_UNUSED)
1071 {
1072   static CUMULATIVE_ARGS zero_cum;
1073   tree param, next_param;
1074
1075   *cum = zero_cum;
1076
1077   /* Determine if this function has variable arguments.  This is
1078      indicated by the last argument being 'void_type_mode' if there
1079      are no variable arguments.  The standard MicroBlaze calling sequence
1080      passes all arguments in the general purpose registers in this case. */
1081
1082   for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0;
1083        param != 0; param = next_param)
1084     {
1085       next_param = TREE_CHAIN (param);
1086       if (next_param == 0 && TREE_VALUE (param) != void_type_node)
1087         cum->gp_reg_found = 1;
1088     }
1089 }
1090
1091 /* Advance the argument to the next argument position.  */
1092
1093 static void
1094 microblaze_function_arg_advance (cumulative_args_t cum_v,
1095                                  enum machine_mode mode,
1096                                  const_tree type, bool named ATTRIBUTE_UNUSED)
1097 {
1098   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1099
1100   cum->arg_number++;
1101   switch (mode)
1102     {
1103     case VOIDmode:
1104       break;
1105
1106     default:
1107       gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
1108           || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
1109
1110       cum->gp_reg_found = 1;
1111       cum->arg_words += ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
1112                          / UNITS_PER_WORD);
1113       break;
1114
1115     case BLKmode:
1116       cum->gp_reg_found = 1;
1117       cum->arg_words += ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
1118                          / UNITS_PER_WORD);
1119       break;
1120
1121     case SFmode:
1122       cum->arg_words++;
1123       if (!cum->gp_reg_found && cum->arg_number <= 2)
1124         cum->fp_code += 1 << ((cum->arg_number - 1) * 2);
1125       break;
1126
1127     case DFmode:
1128       cum->arg_words += 2;
1129       if (!cum->gp_reg_found && cum->arg_number <= 2)
1130         cum->fp_code += 2 << ((cum->arg_number - 1) * 2);
1131       break;
1132
1133     case DImode:
1134       cum->gp_reg_found = 1;
1135       cum->arg_words += 2;
1136       break;
1137
1138     case QImode:
1139     case HImode:
1140     case SImode:
1141     case TImode:
1142       cum->gp_reg_found = 1;
1143       cum->arg_words++;
1144       break;
1145     }
1146 }
1147
1148 /* Return an RTL expression containing the register for the given mode,
1149    or 0 if the argument is to be passed on the stack.  */
1150
1151 static rtx
1152 microblaze_function_arg (cumulative_args_t cum_v, enum machine_mode mode, 
1153                          const_tree type ATTRIBUTE_UNUSED,
1154                          bool named ATTRIBUTE_UNUSED)
1155 {
1156   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1157
1158   rtx ret;
1159   int regbase = -1;
1160   int *arg_words = &cum->arg_words;
1161
1162   cum->last_arg_fp = 0;
1163   switch (mode)
1164     {
1165     case SFmode:
1166     case DFmode:
1167     case VOIDmode:
1168     case QImode:
1169     case HImode:
1170     case SImode:
1171     case DImode:
1172     case TImode:
1173       regbase = GP_ARG_FIRST;
1174       break;
1175     default:
1176       gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
1177           || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
1178       /* Drops through.  */
1179     case BLKmode:
1180       regbase = GP_ARG_FIRST;
1181       break;
1182     }
1183
1184   if (*arg_words >= MAX_ARGS_IN_REGISTERS)
1185     ret = 0;
1186   else
1187     {
1188       gcc_assert (regbase != -1);
1189
1190       ret = gen_rtx_REG (mode, regbase + *arg_words);
1191     }
1192
1193   if (mode == VOIDmode)
1194     {
1195       if (cum->num_adjusts > 0)
1196         ret = gen_rtx_PARALLEL ((enum machine_mode) cum->fp_code,
1197                                 gen_rtvec_v (cum->num_adjusts, cum->adjust));
1198     }
1199
1200   return ret;
1201 }
1202
1203 /* Return number of bytes of argument to put in registers. */
1204 static int
1205 function_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode,    
1206                             tree type, bool named ATTRIBUTE_UNUSED)     
1207 {
1208   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1209
1210   if ((mode == BLKmode
1211        || GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
1212        || GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
1213       && cum->arg_words < MAX_ARGS_IN_REGISTERS)
1214     {
1215       int words;
1216       if (mode == BLKmode)
1217         words = ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
1218                  / UNITS_PER_WORD);
1219       else
1220         words = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1221
1222       if (words + cum->arg_words <= MAX_ARGS_IN_REGISTERS)
1223         return 0;               /* structure fits in registers */
1224
1225       return (MAX_ARGS_IN_REGISTERS - cum->arg_words) * UNITS_PER_WORD;
1226     }
1227
1228   else if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1)
1229     return UNITS_PER_WORD;
1230
1231   return 0;
1232 }
1233
1234 /*  Convert a version number of the form "vX.YY.Z" to an integer encoding 
1235     for easier range comparison.  */
1236 static int
1237 microblaze_version_to_int (const char *version)
1238 {
1239   const char *p, *v;
1240   const char *tmpl = "vX.YY.Z";
1241   int iver = 0;
1242
1243   p = version;
1244   v = tmpl;
1245
1246   while (*v)
1247     {
1248       if (*v == 'X')
1249         {                       /* Looking for major  */
1250           if (!(*p >= '0' && *p <= '9'))
1251             return -1;
1252           iver += (int) (*p - '0');
1253           iver *= 10;
1254         }
1255       else if (*v == 'Y')
1256         {                       /* Looking for minor  */
1257           if (!(*p >= '0' && *p <= '9'))
1258             return -1;
1259           iver += (int) (*p - '0');
1260           iver *= 10;
1261         }
1262       else if (*v == 'Z')
1263         {                       /* Looking for compat  */
1264           if (!(*p >= 'a' && *p <= 'z'))
1265             return -1;
1266           iver *= 10;
1267           iver += (int) (*p - 'a');
1268         }
1269       else
1270         {
1271           if (*p != *v)
1272             return -1;
1273         }
1274
1275       v++;
1276       p++;
1277     }
1278
1279   if (*p)
1280     return -1;
1281
1282   return iver;
1283 }
1284
1285
1286 static void
1287 microblaze_option_override (void)
1288 {
1289   register int i, start;
1290   register int regno;
1291   register enum machine_mode mode;
1292   int ver;
1293
1294   microblaze_section_threshold = (global_options_set.x_g_switch_value
1295                                   ? g_switch_value
1296                                   : MICROBLAZE_DEFAULT_GVALUE);
1297
1298   /* Check the MicroBlaze CPU version for any special action to be done.  */
1299   if (microblaze_select_cpu == NULL)
1300     microblaze_select_cpu = MICROBLAZE_DEFAULT_CPU;
1301   ver = microblaze_version_to_int (microblaze_select_cpu);
1302   if (ver == -1)
1303     {
1304       error ("%qs is an invalid argument to -mcpu=", microblaze_select_cpu);
1305     }
1306
1307   ver = MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v3.00.a");
1308   if (ver < 0)
1309     {
1310       /* No hardware exceptions in earlier versions. So no worries.  */
1311 #if 0
1312       microblaze_select_flags &= ~(MICROBLAZE_MASK_NO_UNSAFE_DELAY);
1313 #endif
1314       microblaze_no_unsafe_delay = 0;
1315       microblaze_pipe = MICROBLAZE_PIPE_3;
1316     }
1317   else if (ver == 0
1318            || (MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v4.00.b")
1319                == 0))
1320     {
1321 #if 0
1322       microblaze_select_flags |= (MICROBLAZE_MASK_NO_UNSAFE_DELAY);
1323 #endif
1324       microblaze_no_unsafe_delay = 1;
1325       microblaze_pipe = MICROBLAZE_PIPE_3;
1326     }
1327   else
1328     {
1329       /* We agree to use 5 pipe-stage model even on area optimized 3 
1330          pipe-stage variants.  */
1331 #if 0
1332       microblaze_select_flags &= ~(MICROBLAZE_MASK_NO_UNSAFE_DELAY);
1333 #endif
1334       microblaze_no_unsafe_delay = 0;
1335       microblaze_pipe = MICROBLAZE_PIPE_5;
1336       if (MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v5.00.a") == 0
1337           || MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu,
1338                                          "v5.00.b") == 0
1339           || MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu,
1340                                          "v5.00.c") == 0)
1341         {
1342           /* Pattern compares are to be turned on by default only when 
1343              compiling for MB v5.00.'z'.  */
1344           target_flags |= MASK_PATTERN_COMPARE;
1345         }
1346     }
1347
1348   ver = MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v6.00.a");
1349   if (ver < 0)
1350     {
1351       if (TARGET_MULTIPLY_HIGH)
1352         warning (0,
1353                  "-mxl-multiply-high can be used only with -mcpu=v6.00.a or greater");
1354     }
1355
1356   if (TARGET_MULTIPLY_HIGH && TARGET_SOFT_MUL)
1357     error ("-mxl-multiply-high requires -mno-xl-soft-mul");
1358
1359   /* Always use DFA scheduler.  */
1360   microblaze_sched_use_dfa = 1;
1361
1362 #if 0
1363   microblaze_abicalls = MICROBLAZE_ABICALLS_NO;
1364 #endif
1365
1366   /* Initialize the high, low values for legit floating point constants.  */
1367   real_maxval (&dfhigh, 0, DFmode);
1368   real_maxval (&dflow, 1, DFmode);
1369   real_maxval (&sfhigh, 0, SFmode);
1370   real_maxval (&sflow, 1, SFmode);
1371
1372   microblaze_print_operand_punct['?'] = 1;
1373   microblaze_print_operand_punct['#'] = 1;
1374   microblaze_print_operand_punct['&'] = 1;
1375   microblaze_print_operand_punct['!'] = 1;
1376   microblaze_print_operand_punct['*'] = 1;
1377   microblaze_print_operand_punct['@'] = 1;
1378   microblaze_print_operand_punct['.'] = 1;
1379   microblaze_print_operand_punct['('] = 1;
1380   microblaze_print_operand_punct[')'] = 1;
1381   microblaze_print_operand_punct['['] = 1;
1382   microblaze_print_operand_punct[']'] = 1;
1383   microblaze_print_operand_punct['<'] = 1;
1384   microblaze_print_operand_punct['>'] = 1;
1385   microblaze_print_operand_punct['{'] = 1;
1386   microblaze_print_operand_punct['}'] = 1;
1387   microblaze_print_operand_punct['^'] = 1;
1388   microblaze_print_operand_punct['$'] = 1;
1389   microblaze_print_operand_punct['+'] = 1;
1390
1391   /* Set up array to map GCC register number to debug register number.
1392      Ignore the special purpose register numbers.  */
1393
1394   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1395     microblaze_dbx_regno[i] = -1;
1396
1397   start = GP_DBX_FIRST - GP_REG_FIRST;
1398   for (i = GP_REG_FIRST; i <= GP_REG_LAST; i++)
1399     microblaze_dbx_regno[i] = i + start;
1400
1401   /* Set up array giving whether a given register can hold a given mode.   */
1402
1403   for (mode = VOIDmode;
1404        mode != MAX_MACHINE_MODE; mode = (enum machine_mode) ((int) mode + 1))
1405     {
1406       register int size = GET_MODE_SIZE (mode);
1407
1408       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1409         {
1410           register int ok;
1411
1412           if (mode == CCmode)
1413             {
1414               ok = (ST_REG_P (regno) || GP_REG_P (regno));
1415             }
1416           else if (GP_REG_P (regno))
1417             ok = ((regno & 1) == 0 || size <= UNITS_PER_WORD);
1418           else
1419             ok = 0;
1420
1421           microblaze_hard_regno_mode_ok[(int) mode][regno] = ok;
1422         }
1423     }
1424 }
1425
1426 /* Return true if FUNC is an interrupt function as specified
1427    by the "interrupt_handler" attribute.  */
1428
1429 static int
1430 microblaze_interrupt_function_p (tree func)
1431 {
1432   tree a;
1433
1434   if (TREE_CODE (func) != FUNCTION_DECL)
1435     return 0;
1436
1437   a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
1438   return a != NULL_TREE;
1439 }
1440
1441 /* Return true if FUNC is an interrupt function which uses
1442    normal return, indicated by the "save_volatiles" attribute.  */
1443
1444 static int
1445 microblaze_save_volatiles (tree func)
1446 {
1447   tree a;
1448
1449   if (TREE_CODE (func) != FUNCTION_DECL)
1450     return 0;
1451
1452   a = lookup_attribute ("save_volatiles", DECL_ATTRIBUTES (func));
1453   return a != NULL_TREE;
1454 }
1455
1456 /* Return whether function is tagged with 'interrupt_handler'
1457    attribute.  Return true if function should use return from
1458    interrupt rather than normal function return.  */
1459 int
1460 microblaze_is_interrupt_handler (void)
1461 {
1462   return interrupt_handler;
1463 }
1464
1465 /* Determine of register must be saved/restored in call.  */
1466 static int
1467 microblaze_must_save_register (int regno)
1468 {
1469   if (pic_offset_table_rtx &&
1470       (regno == MB_ABI_PIC_ADDR_REGNUM) && df_regs_ever_live_p (regno))
1471     return 1;
1472
1473   if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
1474     return 1;
1475
1476   if (frame_pointer_needed && (regno == HARD_FRAME_POINTER_REGNUM))
1477     return 1;
1478
1479   if (!current_function_is_leaf)
1480     {
1481       if (regno == MB_ABI_SUB_RETURN_ADDR_REGNUM)
1482         return 1;
1483       if ((interrupt_handler || save_volatiles) &&
1484           (regno >= 3 && regno <= 12))
1485         return 1;
1486     }
1487
1488   if (interrupt_handler)
1489     {
1490       if (df_regs_ever_live_p (regno) 
1491           || regno == MB_ABI_MSR_SAVE_REG
1492           || regno == MB_ABI_ASM_TEMP_REGNUM
1493           || regno == MB_ABI_EXCEPTION_RETURN_ADDR_REGNUM)
1494         return 1;
1495     }
1496
1497   if (save_volatiles)
1498     {
1499       if (df_regs_ever_live_p (regno)
1500           || regno == MB_ABI_ASM_TEMP_REGNUM
1501           || regno == MB_ABI_EXCEPTION_RETURN_ADDR_REGNUM)
1502         return 1;
1503     }
1504
1505   return 0;
1506 }
1507
1508 /* Return the bytes needed to compute the frame pointer from the current
1509    stack pointer.
1510
1511    MicroBlaze stack frames look like:
1512
1513
1514
1515              Before call                        After call
1516         +-----------------------+       +-----------------------+
1517    high |                       |       |                       |
1518    mem. |  local variables,     |       |  local variables,     |
1519         |  callee saved and     |       |  callee saved and     |
1520         |  temps                |       |  temps                |
1521         +-----------------------+       +-----------------------+
1522         |  arguments for called |       |  arguments for called |
1523         |  subroutines          |       |  subroutines          |
1524         |  (optional)           |       |  (optional)           |
1525         +-----------------------+       +-----------------------+
1526         |  Link register        |       |  Link register        |
1527     SP->|                       |       |                       |
1528         +-----------------------+       +-----------------------+
1529                                         |                       |
1530                                         |  local variables,     |
1531                                         |  callee saved and     |
1532                                         |  temps                |
1533                                         +-----------------------+
1534                                         |   MSR (optional if,   |
1535                                         |   interrupt handler)  |
1536                                         +-----------------------+
1537                                         |                       |
1538                                         |  alloca allocations   |
1539                                         |                       |
1540                                         +-----------------------+
1541                                         |                       |
1542                                         |  arguments for called |
1543                                         |  subroutines          |
1544                                         |  (optional)           |
1545                                         |                       |
1546                                         +-----------------------+
1547                                         |  Link register        |
1548    low                           FP,SP->|                       |
1549    memory                               +-----------------------+
1550
1551 */
1552
1553 static HOST_WIDE_INT
1554 compute_frame_size (HOST_WIDE_INT size) 
1555 {
1556   int regno;
1557   HOST_WIDE_INT total_size;     /* # bytes that the entire frame takes up.  */
1558   HOST_WIDE_INT var_size;       /* # bytes that local variables take up.  */
1559   HOST_WIDE_INT args_size;      /* # bytes that outgoing arguments take up.  */
1560   int link_debug_size;          /* # bytes for link register.  */
1561   HOST_WIDE_INT gp_reg_size;    /* # bytes needed to store calle-saved gp regs.  */
1562   long mask;                    /* mask of saved gp registers.  */
1563
1564   interrupt_handler =
1565     microblaze_interrupt_function_p (current_function_decl);
1566   save_volatiles = microblaze_save_volatiles (current_function_decl);
1567
1568   gp_reg_size = 0;
1569   mask = 0;
1570   var_size = size;
1571   args_size = crtl->outgoing_args_size;
1572
1573   if ((args_size == 0) && cfun->calls_alloca)
1574     args_size = NUM_OF_ARGS * UNITS_PER_WORD;
1575
1576   total_size = var_size + args_size;
1577
1578   if (flag_pic == 2)
1579     /* force setting GOT.  */
1580     df_set_regs_ever_live (MB_ABI_PIC_ADDR_REGNUM, true);
1581
1582   /* Calculate space needed for gp registers.  */
1583   for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
1584     {
1585       if (microblaze_must_save_register (regno))
1586         {
1587
1588           if (regno != MB_ABI_SUB_RETURN_ADDR_REGNUM)
1589             /* Don't account for link register. It is accounted specially below.  */
1590             gp_reg_size += GET_MODE_SIZE (SImode);
1591
1592           mask |= (1L << (regno - GP_REG_FIRST));
1593         }
1594     }
1595
1596   total_size += gp_reg_size;
1597
1598   /* Add 4 bytes for MSR.  */
1599   if (interrupt_handler)
1600     total_size += 4;
1601
1602   /* No space to be allocated for link register in leaf functions with no other
1603      stack requirements.  */
1604   if (total_size == 0 && current_function_is_leaf)
1605     link_debug_size = 0;
1606   else
1607     link_debug_size = UNITS_PER_WORD;
1608
1609   total_size += link_debug_size;
1610
1611   /* Save other computed information.  */
1612   current_frame_info.total_size = total_size;
1613   current_frame_info.var_size = var_size;
1614   current_frame_info.args_size = args_size;
1615   current_frame_info.gp_reg_size = gp_reg_size;
1616   current_frame_info.mask = mask;
1617   current_frame_info.initialized = reload_completed;
1618   current_frame_info.num_gp = gp_reg_size / UNITS_PER_WORD;
1619   current_frame_info.link_debug_size = link_debug_size;
1620
1621   if (mask)
1622     /* Offset from which to callee-save GP regs.  */
1623     current_frame_info.gp_offset = (total_size - gp_reg_size);
1624   else
1625     current_frame_info.gp_offset = 0;
1626
1627   /* Ok, we're done.  */
1628   return total_size;
1629 }
1630
1631 /* Make sure that we're not trying to eliminate to the wrong hard frame
1632    pointer.  */
1633
1634 static bool
1635 microblaze_can_eliminate (const int from, const int to)
1636 {
1637   return ((from == RETURN_ADDRESS_POINTER_REGNUM && !leaf_function_p())
1638           || (to == MB_ABI_SUB_RETURN_ADDR_REGNUM && leaf_function_p())
1639           || (from != RETURN_ADDRESS_POINTER_REGNUM
1640               && (to == HARD_FRAME_POINTER_REGNUM
1641                   || (to == STACK_POINTER_REGNUM && !frame_pointer_needed))));
1642 }
1643
1644 /* Implement INITIAL_ELIMINATION_OFFSET.  FROM is either the frame
1645    pointer or argument pointer or the return address pointer.  TO is either 
1646    the stack pointer or hard frame pointer.  */
1647
1648 HOST_WIDE_INT
1649 microblaze_initial_elimination_offset (int from, int to)
1650 {
1651   HOST_WIDE_INT offset;
1652
1653   switch (from)
1654     {
1655     case FRAME_POINTER_REGNUM:
1656       offset = 0;
1657       break;
1658     case ARG_POINTER_REGNUM:
1659       if (to == STACK_POINTER_REGNUM || to == HARD_FRAME_POINTER_REGNUM)
1660         offset = compute_frame_size (get_frame_size ());
1661       else
1662         gcc_unreachable ();
1663       break;
1664     case RETURN_ADDRESS_POINTER_REGNUM:
1665       if (current_function_is_leaf)
1666         offset = 0;
1667       else
1668         offset = current_frame_info.gp_offset +
1669           ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT)));
1670       break;
1671     default:
1672       gcc_unreachable ();
1673     }
1674   return offset;
1675 }
1676
1677 /* Print operands using format code.
1678  
1679    The MicroBlaze specific codes are:
1680
1681    'X'  X is CONST_INT, prints 32 bits in hexadecimal format = "0x%08x",
1682    'x'  X is CONST_INT, prints 16 bits in hexadecimal format = "0x%04x",
1683    'F'  op is CONST_DOUBLE, print 32 bits in hex,
1684    'd'  output integer constant in decimal,
1685    'z'  if the operand is 0, use $0 instead of normal operand.
1686    'D'  print second register of double-word register operand.
1687    'L'  print low-order register of double-word register operand.
1688    'M'  print high-order register of double-word register operand.
1689    'C'  print part of opcode for a branch condition.
1690    'N'  print part of opcode for a branch condition, inverted.
1691    'S'  X is CODE_LABEL, print with prefix of "LS" (for embedded switch).
1692    'B'  print 'z' for EQ, 'n' for NE
1693    'b'  print 'n' for EQ, 'z' for NE
1694    'T'  print 'f' for EQ, 't' for NE
1695    't'  print 't' for EQ, 'f' for NE
1696    'm'  Print 1<<operand.
1697    'i'  Print 'i' if MEM operand has immediate value
1698    'o'  Print operand address+4
1699    '?'  Print 'd' if we use a branch with delay slot instead of normal branch.
1700    'h'  Print high word of const_double (int or float) value as hex
1701    'j'  Print low word of const_double (int or float) value as hex
1702    's'  Print -1 if operand is negative, 0 if positive (sign extend)
1703    '@'  Print the name of the temporary register (rMB_ABI_ASM_TEMP_REGNUM).
1704    '#'  Print nop if the delay slot of a branch is not filled. 
1705 */
1706
1707 void
1708 print_operand (FILE * file, rtx op, int letter)
1709 {
1710   register enum rtx_code code;
1711
1712   if (PRINT_OPERAND_PUNCT_VALID_P (letter))
1713     {
1714       switch (letter)
1715         {
1716         case '?':
1717           /* Conditionally add a 'd' to indicate filled delay slot.  */
1718           if (final_sequence != NULL)
1719             fputs ("d", file);
1720           break;
1721
1722         case '#':
1723           /* Conditionally add a nop in unfilled delay slot.  */
1724           if (final_sequence == NULL)
1725             fputs ("nop\t\t# Unfilled delay slot\n", file);
1726           break;
1727
1728         case '@':
1729           fputs (reg_names[GP_REG_FIRST + MB_ABI_ASM_TEMP_REGNUM], file);
1730           break;
1731
1732         default:
1733           output_operand_lossage ("unknown punctuation '%c'", letter);
1734           break;
1735         }
1736
1737       return;
1738     }
1739
1740   if (!op)
1741     {
1742       output_operand_lossage ("null pointer");
1743       return;
1744     }
1745
1746   code = GET_CODE (op);
1747
1748   if (code == SIGN_EXTEND)
1749     op = XEXP (op, 0), code = GET_CODE (op);
1750
1751   if (letter == 'C')
1752     switch (code)
1753       {
1754       case EQ:
1755         fputs ("eq", file);
1756         break;
1757       case NE:
1758         fputs ("ne", file);
1759         break;
1760       case GT:
1761       case GTU:
1762         fputs ("gt", file);
1763         break;
1764       case GE:
1765       case GEU:
1766         fputs ("ge", file);
1767         break;
1768       case LT:
1769       case LTU:
1770         fputs ("lt", file);
1771         break;
1772       case LE:
1773       case LEU:
1774         fputs ("le", file);
1775         break;
1776       default:
1777         fatal_insn ("PRINT_OPERAND, invalid insn for %%C", op);
1778       }
1779
1780   else if (letter == 'N')
1781     switch (code)
1782       {
1783       case EQ:
1784         fputs ("ne", file);
1785         break;
1786       case NE:
1787         fputs ("eq", file);
1788         break;
1789       case GT:
1790       case GTU:
1791         fputs ("le", file);
1792         break;
1793       case GE:
1794       case GEU:
1795         fputs ("lt", file);
1796         break;
1797       case LT:
1798       case LTU:
1799         fputs ("ge", file);
1800         break;
1801       case LE:
1802       case LEU:
1803         fputs ("gt", file);
1804         break;
1805       default:
1806         fatal_insn ("PRINT_OPERAND, invalid insn for %%N", op);
1807       }
1808
1809   else if (letter == 'S')
1810     {
1811       char buffer[100];
1812
1813       ASM_GENERATE_INTERNAL_LABEL (buffer, "LS", CODE_LABEL_NUMBER (op));
1814       assemble_name (file, buffer);
1815     }
1816
1817   /* Print 'i' for memory operands which have immediate values.  */
1818   else if (letter == 'i')
1819     {
1820       if (code == MEM)
1821         {
1822           struct microblaze_address_info info;
1823
1824           if (!microblaze_classify_address
1825               (&info, XEXP (op, 0), GET_MODE (op), 1))
1826             fatal_insn ("insn contains an invalid address !", op);
1827
1828           switch (info.type)
1829             {
1830             case ADDRESS_REG:
1831             case ADDRESS_CONST_INT:
1832             case ADDRESS_SYMBOLIC:
1833             case ADDRESS_GOTOFF:
1834               fputs ("i", file);
1835               break;
1836             case ADDRESS_REG_INDEX:
1837               break;
1838             case ADDRESS_INVALID:
1839             case ADDRESS_PLT:
1840               fatal_insn ("invalid address", op);
1841             }
1842         }
1843     }
1844
1845   else if (code == REG || code == SUBREG)
1846     {
1847       register int regnum;
1848
1849       if (code == REG)
1850         regnum = REGNO (op);
1851       else
1852         regnum = true_regnum (op);
1853
1854       if ((letter == 'M' && !WORDS_BIG_ENDIAN)
1855           || (letter == 'L' && WORDS_BIG_ENDIAN) || letter == 'D')
1856         regnum++;
1857
1858       fprintf (file, "%s", reg_names[regnum]);
1859     }
1860
1861   else if (code == MEM)
1862     if (letter == 'o')
1863       {
1864         rtx op4 = adjust_address (op, GET_MODE (op), 4);
1865         output_address (XEXP (op4, 0));
1866       }
1867     else
1868       output_address (XEXP (op, 0));
1869
1870   else if (letter == 'h' || letter == 'j')
1871     {
1872       long val[2];
1873       if (code == CONST_DOUBLE)
1874         {
1875           if (GET_MODE (op) == DFmode)
1876             {
1877               REAL_VALUE_TYPE value;
1878               REAL_VALUE_FROM_CONST_DOUBLE (value, op);
1879               REAL_VALUE_TO_TARGET_DOUBLE (value, val);
1880             }
1881           else
1882             {
1883               val[0] = CONST_DOUBLE_HIGH (op);
1884               val[1] = CONST_DOUBLE_LOW (op);
1885             }
1886         }
1887       else if (code == CONST_INT)
1888         {
1889           val[0] = (INTVAL (op) & 0xffffffff00000000LL) >> 32;
1890           val[1] = INTVAL (op) & 0x00000000ffffffffLL;
1891           if (val[0] == 0 && val[1] < 0)
1892             val[0] = -1;
1893             
1894         }
1895       fprintf (file, "0x%8.8lx", (letter == 'h') ? val[0] : val[1]);
1896     }
1897   else if (code == CONST_DOUBLE)
1898     {
1899       if (letter == 'F')
1900         {
1901           unsigned long value_long;
1902           REAL_VALUE_TYPE value;
1903           REAL_VALUE_FROM_CONST_DOUBLE (value, op);
1904           REAL_VALUE_TO_TARGET_SINGLE (value, value_long);
1905           fprintf (file, HOST_WIDE_INT_PRINT_HEX, value_long);
1906         }
1907       else
1908         {
1909           char s[60];
1910           real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (op), sizeof (s), 0, 1);
1911           fputs (s, file);
1912         }
1913     }
1914
1915   else if (code == UNSPEC)
1916     {
1917       print_operand_address (file, op);
1918     }
1919
1920   else if (letter == 'x' && GET_CODE (op) == CONST_INT)
1921     fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & INTVAL (op));
1922
1923   else if (letter == 'X' && GET_CODE (op) == CONST_INT)
1924     fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op));
1925
1926   else if (letter == 'd' && GET_CODE (op) == CONST_INT)
1927     fprintf (file, HOST_WIDE_INT_PRINT_DEC, (INTVAL (op)));
1928
1929   else if (letter == 'z' && GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
1930     fputs (reg_names[GP_REG_FIRST], file);
1931
1932   else if (letter == 's' && GET_CODE (op) == CONST_INT)
1933     if (INTVAL (op) < 0)
1934       fputs ("-1", file);
1935     else
1936       fputs ("0", file);
1937
1938   else if (letter == 'd' || letter == 'x' || letter == 'X' || letter == 's')
1939     output_operand_lossage ("letter %c was found & insn was not CONST_INT", letter);
1940
1941   else if (letter == 'B')
1942     fputs (code == EQ ? "z" : "n", file);
1943   else if (letter == 'b')
1944     fputs (code == EQ ? "n" : "z", file);
1945   else if (letter == 'T')
1946     fputs (code == EQ ? "f" : "t", file);
1947   else if (letter == 't')
1948     fputs (code == EQ ? "t" : "f", file);
1949
1950   else if (code == CONST && GET_CODE (XEXP (op, 0)) == REG)
1951     {
1952       print_operand (file, XEXP (op, 0), letter);
1953     }
1954   else if (letter == 'm')
1955     fprintf (file, HOST_WIDE_INT_PRINT_DEC, (1L << INTVAL (op)));
1956   else
1957     output_addr_const (file, op);
1958 }
1959
1960 /* A C compound statement to output to stdio stream STREAM the
1961    assembler syntax for an instruction operand that is a memory
1962    reference whose address is ADDR.  ADDR is an RTL expression.
1963
1964    Possible address classifications and output formats are,
1965    
1966    ADDRESS_REG                  "%0, r0"
1967
1968    ADDRESS_REG with non-zero    "%0, <addr_const>"
1969    offset       
1970
1971    ADDRESS_REG_INDEX            "rA, RB"    
1972                                 (if rA is r0, rA and rB are swapped)
1973
1974    ADDRESS_CONST_INT            "r0, <addr_const>"
1975
1976    ADDRESS_SYMBOLIC             "rBase, <addr_const>"   
1977                                 (rBase is a base register suitable for the 
1978                                  symbol's type)
1979 */
1980
1981 void
1982 print_operand_address (FILE * file, rtx addr)
1983 {
1984   struct microblaze_address_info info;
1985   enum microblaze_address_type type;
1986   if (!microblaze_classify_address (&info, addr, GET_MODE (addr), 1))
1987     fatal_insn ("insn contains an invalid address !", addr);
1988
1989   type = info.type;
1990   switch (info.type)
1991     {
1992     case ADDRESS_REG:
1993       fprintf (file, "%s,", reg_names[REGNO (info.regA)]);
1994       output_addr_const (file, info.offset);
1995       break;
1996     case ADDRESS_REG_INDEX:
1997       if (REGNO (info.regA) == 0)
1998         /* Make rB == r0 instead of rA == r0. This helps reduce read port 
1999            congestion.  */
2000         fprintf (file, "%s,%s", reg_names[REGNO (info.regB)],
2001                  reg_names[REGNO (info.regA)]);
2002       else if (REGNO (info.regB) != 0)
2003         /* This is a silly swap to help Dhrystone.  */
2004         fprintf (file, "%s,%s", reg_names[REGNO (info.regB)],
2005                  reg_names[REGNO (info.regA)]);
2006       break;
2007     case ADDRESS_CONST_INT:
2008       fprintf (file, "%s,", reg_names[REGNO (info.regA)]);
2009       output_addr_const (file, info.offset);
2010       break;
2011     case ADDRESS_SYMBOLIC:
2012     case ADDRESS_GOTOFF:
2013     case ADDRESS_PLT:
2014       if (info.regA)
2015         fprintf (file, "%s,", reg_names[REGNO (info.regA)]);
2016       output_addr_const (file, info.symbol);
2017       if (type == ADDRESS_GOTOFF)
2018         {
2019           fputs ("@GOT", file);
2020         }
2021       else if (type == ADDRESS_PLT)
2022         {
2023           fputs ("@PLT", file);
2024         }
2025       break;
2026     case ADDRESS_INVALID:
2027       fatal_insn ("invalid address", addr);
2028       break;
2029     }
2030 }
2031
2032 /* Emit either a label, .comm, or .lcomm directive, and mark that the symbol
2033    is used, so that we don't emit an .extern for it in 
2034    microblaze_asm_file_end.  */
2035
2036 void
2037 microblaze_declare_object (FILE * stream, const char *name,
2038                            const char *section, const char *fmt, int size)
2039 {
2040
2041   fputs (section, stream);      
2042   assemble_name (stream, name);
2043   fprintf (stream, fmt, size);
2044 }
2045
2046 /* Common code to emit the insns (or to write the instructions to a file)
2047    to save/restore registers.
2048
2049    Other parts of the code assume that MICROBLAZE_TEMP1_REGNUM (aka large_reg)
2050    is not modified within save_restore_insns.  */
2051
2052 #define BITSET_P(VALUE,BIT) (((VALUE) & (1L << (BIT))) != 0)
2053
2054 /* Save or restore instructions based on whether this is the prologue or 
2055    epilogue.  prologue is 1 for the prologue.  */
2056 static void
2057 save_restore_insns (int prologue)
2058 {
2059   rtx base_reg_rtx, reg_rtx, mem_rtx, /* msr_rtx, */ isr_reg_rtx =
2060     0, isr_mem_rtx = 0;
2061   rtx isr_msr_rtx = 0, insn;
2062   long mask = current_frame_info.mask;
2063   HOST_WIDE_INT gp_offset;
2064   int regno;
2065
2066   if (frame_pointer_needed
2067       && !BITSET_P (mask, HARD_FRAME_POINTER_REGNUM - GP_REG_FIRST))
2068     gcc_unreachable ();
2069
2070   if (mask == 0)
2071     return;
2072
2073   /* Save registers starting from high to low.  The debuggers prefer at least
2074      the return register be stored at func+4, and also it allows us not to
2075      need a nop in the epilog if at least one register is reloaded in
2076      addition to return address.  */
2077
2078   /* Pick which pointer to use as a base register.  For small frames, just
2079      use the stack pointer.  Otherwise, use a temporary register.  Save 2
2080      cycles if the save area is near the end of a large frame, by reusing
2081      the constant created in the prologue/epilogue to adjust the stack
2082      frame.  */
2083
2084   gp_offset = current_frame_info.gp_offset;
2085
2086   gcc_assert (gp_offset > 0);
2087
2088   base_reg_rtx = stack_pointer_rtx;
2089
2090   /* For interrupt_handlers, need to save/restore the MSR.  */
2091   if (interrupt_handler)
2092     {
2093       isr_mem_rtx = gen_rtx_MEM (SImode,
2094                                  gen_rtx_PLUS (Pmode, base_reg_rtx,
2095                                                GEN_INT (current_frame_info.
2096                                                         gp_offset -
2097                                                         UNITS_PER_WORD)));
2098
2099       /* Do not optimize in flow analysis.  */
2100       MEM_VOLATILE_P (isr_mem_rtx) = 1;
2101       isr_reg_rtx = gen_rtx_REG (SImode, MB_ABI_MSR_SAVE_REG);
2102       isr_msr_rtx = gen_rtx_REG (SImode, ST_REG);
2103     }
2104
2105   if (interrupt_handler && !prologue)
2106     {
2107       emit_move_insn (isr_reg_rtx, isr_mem_rtx);
2108       emit_move_insn (isr_msr_rtx, isr_reg_rtx);
2109       /* Do not optimize in flow analysis.  */
2110       emit_insn (gen_rtx_USE (SImode, isr_reg_rtx));
2111       emit_insn (gen_rtx_USE (SImode, isr_msr_rtx));
2112     }
2113
2114   for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
2115     {
2116       if (BITSET_P (mask, regno - GP_REG_FIRST))
2117         {
2118           if (regno == MB_ABI_SUB_RETURN_ADDR_REGNUM)
2119             /* Don't handle here. Already handled as the first register.  */
2120             continue;
2121
2122           reg_rtx = gen_rtx_REG (SImode, regno);
2123           insn = gen_rtx_PLUS (Pmode, base_reg_rtx, GEN_INT (gp_offset));
2124           mem_rtx = gen_rtx_MEM (SImode, insn);
2125           if (interrupt_handler || save_volatiles)
2126             /* Do not optimize in flow analysis.  */
2127             MEM_VOLATILE_P (mem_rtx) = 1;
2128
2129           if (prologue)
2130             {
2131               insn = emit_move_insn (mem_rtx, reg_rtx);
2132               RTX_FRAME_RELATED_P (insn) = 1;
2133             }
2134           else
2135             {
2136               insn = emit_move_insn (reg_rtx, mem_rtx);
2137             }
2138
2139           gp_offset += GET_MODE_SIZE (SImode);
2140         }
2141     }
2142
2143   if (interrupt_handler && prologue)
2144     {
2145       emit_move_insn (isr_reg_rtx, isr_msr_rtx);
2146       emit_move_insn (isr_mem_rtx, isr_reg_rtx);
2147
2148       /* Do not optimize in flow analysis.  */
2149       emit_insn (gen_rtx_USE (SImode, isr_reg_rtx));
2150       emit_insn (gen_rtx_USE (SImode, isr_msr_rtx));
2151     }
2152
2153   /* Done saving and restoring */
2154 }
2155
2156
2157 /* Set up the stack and frame (if desired) for the function.  */
2158 static void
2159 microblaze_function_prologue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
2160 {
2161   const char *fnname;
2162   long fsiz = current_frame_info.total_size;
2163
2164   /* Get the function name the same way that toplev.c does before calling
2165      assemble_start_function.  This is needed so that the name used here
2166      exactly matches the name used in ASM_DECLARE_FUNCTION_NAME.  */
2167   fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
2168   if (!flag_inhibit_size_directive)
2169     {
2170       fputs ("\t.ent\t", file);
2171       if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname))
2172         fputs ("_interrupt_handler", file);
2173       else
2174         assemble_name (file, fnname);
2175       fputs ("\n", file);
2176       if (!interrupt_handler)
2177         ASM_OUTPUT_TYPE_DIRECTIVE (file, fnname, "function");
2178     }
2179
2180   assemble_name (file, fnname);
2181   fputs (":\n", file);
2182
2183   if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname))
2184     fputs ("_interrupt_handler:\n", file);
2185
2186   if (!flag_inhibit_size_directive)
2187     {
2188       /* .frame FRAMEREG, FRAMESIZE, RETREG.  */
2189       fprintf (file,
2190                "\t.frame\t%s,%ld,%s\t\t# vars= %ld, regs= %d, args= %d\n",
2191                (reg_names[(frame_pointer_needed)
2192                           ? HARD_FRAME_POINTER_REGNUM :
2193                           STACK_POINTER_REGNUM]), fsiz,
2194                reg_names[MB_ABI_SUB_RETURN_ADDR_REGNUM + GP_REG_FIRST],
2195                current_frame_info.var_size, current_frame_info.num_gp,
2196                crtl->outgoing_args_size);
2197       fprintf (file, "\t.mask\t0x%08lx\n", current_frame_info.mask);
2198     }
2199 }
2200
2201 /* Output extra assembler code at the end of a prologue.  */
2202 static void
2203 microblaze_function_end_prologue (FILE * file)
2204 {
2205   if (TARGET_STACK_CHECK)
2206     {
2207       fprintf (file, "\t# Stack Check Stub -- Start.\n\t");
2208       fprintf (file, "ori\tr18,r0,_stack_end\n\t");
2209       fprintf (file, "cmpu\tr18,r1,r18\n\t");
2210       fprintf (file, "bgei\tr18,_stack_overflow_exit\n\t");
2211       fprintf (file, "# Stack Check Stub -- End.\n");
2212     }
2213 }
2214
2215 /* Expand the prologue into a bunch of separate insns.  */
2216
2217 void
2218 microblaze_expand_prologue (void)
2219 {
2220   int regno;
2221   HOST_WIDE_INT fsiz;
2222   const char *arg_name = 0;
2223   tree fndecl = current_function_decl;
2224   tree fntype = TREE_TYPE (fndecl);
2225   tree fnargs = DECL_ARGUMENTS (fndecl);
2226   rtx next_arg_reg;
2227   int i;
2228   tree next_arg;
2229   tree cur_arg;
2230   CUMULATIVE_ARGS args_so_far_v;
2231   cumulative_args_t args_so_far;
2232   rtx mem_rtx, reg_rtx;
2233
2234   /* If struct value address is treated as the first argument, make it so.  */
2235   if (aggregate_value_p (DECL_RESULT (fndecl), fntype)
2236       && !cfun->returns_pcc_struct)
2237     {
2238       tree type = build_pointer_type (fntype);
2239       tree function_result_decl = build_decl (BUILTINS_LOCATION, PARM_DECL, 
2240                                               NULL_TREE, type);
2241
2242       DECL_ARG_TYPE (function_result_decl) = type;
2243       TREE_CHAIN (function_result_decl) = fnargs;
2244       fnargs = function_result_decl;
2245     }
2246
2247   /* Determine the last argument, and get its name.  */
2248
2249   INIT_CUMULATIVE_ARGS (args_so_far_v, fntype, NULL_RTX, 0, 0);
2250   args_so_far = pack_cumulative_args (&args_so_far_v);
2251   regno = GP_ARG_FIRST;
2252
2253   for (cur_arg = fnargs; cur_arg != 0; cur_arg = next_arg)
2254     {
2255       tree passed_type = DECL_ARG_TYPE (cur_arg);
2256       enum machine_mode passed_mode = TYPE_MODE (passed_type);
2257       rtx entry_parm;
2258
2259       if (TREE_ADDRESSABLE (passed_type))
2260         {
2261           passed_type = build_pointer_type (passed_type);
2262           passed_mode = Pmode;
2263         }
2264
2265       entry_parm = targetm.calls.function_arg (args_so_far, passed_mode,
2266                                                passed_type, true);
2267
2268       if (entry_parm)
2269         {
2270           int words;
2271
2272           /* passed in a register, so will get homed automatically.  */
2273           if (GET_MODE (entry_parm) == BLKmode)
2274             words = (int_size_in_bytes (passed_type) + 3) / 4;
2275           else
2276             words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4;
2277
2278           regno = REGNO (entry_parm) + words - 1;
2279         }
2280       else
2281         {
2282           regno = GP_ARG_LAST + 1;
2283           break;
2284         }
2285
2286       targetm.calls.function_arg_advance (args_so_far, passed_mode,
2287                                           passed_type, true);
2288
2289       next_arg = TREE_CHAIN (cur_arg);
2290       if (next_arg == 0)
2291         {
2292           if (DECL_NAME (cur_arg))
2293             arg_name = IDENTIFIER_POINTER (DECL_NAME (cur_arg));
2294
2295           break;
2296         }
2297     }
2298
2299   /* Split parallel insn into a sequence of insns.  */
2300
2301   next_arg_reg = targetm.calls.function_arg (args_so_far, VOIDmode,
2302                                              void_type_node, true);
2303   if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL)
2304     {
2305       rtvec adjust = XVEC (next_arg_reg, 0);
2306       int num = GET_NUM_ELEM (adjust);
2307
2308       for (i = 0; i < num; i++)
2309         {
2310           rtx pattern = RTVEC_ELT (adjust, i);
2311           emit_insn (pattern);
2312         }
2313     }
2314
2315   fsiz = compute_frame_size (get_frame_size ());
2316
2317   /* If this function is a varargs function, store any registers that
2318      would normally hold arguments ($5 - $10) on the stack.  */
2319   if (((TYPE_ARG_TYPES (fntype) != 0
2320         && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2321             != void_type_node))
2322        || (arg_name != 0
2323            && ((arg_name[0] == '_'
2324                 && strcmp (arg_name, "__builtin_va_alist") == 0)
2325                || (arg_name[0] == 'v'
2326                    && strcmp (arg_name, "va_alist") == 0)))))
2327     {
2328       int offset = (regno - GP_ARG_FIRST + 1) * UNITS_PER_WORD;
2329       rtx ptr = stack_pointer_rtx;
2330
2331       /* If we are doing svr4-abi, sp has already been decremented by fsiz. */
2332       for (; regno <= GP_ARG_LAST; regno++)
2333         {
2334           if (offset != 0)
2335             ptr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
2336           emit_move_insn (gen_rtx_MEM (SImode, ptr),
2337                           gen_rtx_REG (SImode, regno));
2338
2339           offset += GET_MODE_SIZE (SImode);
2340         }
2341
2342     }
2343
2344   if (fsiz > 0)
2345     {
2346       rtx fsiz_rtx = GEN_INT (fsiz);
2347
2348       rtx insn = NULL;
2349       insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
2350                                     fsiz_rtx));
2351       if (insn)
2352         RTX_FRAME_RELATED_P (insn) = 1;
2353
2354       /* Handle SUB_RETURN_ADDR_REGNUM specially at first.  */
2355       if (!current_function_is_leaf || interrupt_handler)
2356         {
2357           mem_rtx = gen_rtx_MEM (SImode,
2358                                  gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2359                                                const0_rtx));
2360
2361           if (interrupt_handler)
2362             /* Do not optimize in flow analysis.  */
2363             MEM_VOLATILE_P (mem_rtx) = 1;
2364
2365           reg_rtx = gen_rtx_REG (SImode, MB_ABI_SUB_RETURN_ADDR_REGNUM);
2366           insn = emit_move_insn (mem_rtx, reg_rtx);
2367           RTX_FRAME_RELATED_P (insn) = 1;
2368         }
2369
2370       /* _save_ registers for prologue.  */
2371       save_restore_insns (1);
2372
2373       if (frame_pointer_needed)
2374         {
2375           rtx insn = 0;
2376
2377           insn = emit_insn (gen_movsi (hard_frame_pointer_rtx,
2378                                        stack_pointer_rtx));
2379
2380           if (insn)
2381             RTX_FRAME_RELATED_P (insn) = 1;
2382         }
2383     }
2384
2385   if (flag_pic == 2 && df_regs_ever_live_p (MB_ABI_PIC_ADDR_REGNUM))
2386     {
2387       SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM);
2388       emit_insn (gen_set_got (pic_offset_table_rtx));   /* setting GOT.  */
2389     }
2390
2391   /* If we are profiling, make sure no instructions are scheduled before
2392      the call to mcount.  */
2393
2394   if (profile_flag)
2395     emit_insn (gen_blockage ());
2396 }
2397
2398 /* Do necessary cleanup after a function to restore stack, frame, and regs.  */
2399
2400 #define RA_MASK ((long) 0x80000000)     /* 1 << 31 */
2401 #define PIC_OFFSET_TABLE_MASK (1 << (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
2402
2403 static void
2404 microblaze_function_epilogue (FILE * file ATTRIBUTE_UNUSED,
2405                               HOST_WIDE_INT size ATTRIBUTE_UNUSED)
2406 {
2407   const char *fnname;
2408
2409   /* Get the function name the same way that toplev.c does before calling
2410      assemble_start_function.  This is needed so that the name used here
2411      exactly matches the name used in ASM_DECLARE_FUNCTION_NAME.  */
2412   fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
2413
2414   if (!flag_inhibit_size_directive)
2415     {
2416       fputs ("\t.end\t", file);
2417       if (interrupt_handler)
2418         fputs ("_interrupt_handler", file);
2419       else
2420         assemble_name (file, fnname);
2421       fputs ("\n", file);
2422     }
2423
2424   /* Reset state info for each function.  */
2425   current_frame_info = zero_frame_info;
2426
2427   /* Restore the output file if optimizing the GP (optimizing the GP causes
2428      the text to be diverted to a tempfile, so that data decls come before
2429      references to the data).  */
2430 }
2431
2432 /* Expand the epilogue into a bunch of separate insns.  */
2433
2434 void
2435 microblaze_expand_epilogue (void)
2436 {
2437   HOST_WIDE_INT fsiz = current_frame_info.total_size;
2438   rtx fsiz_rtx = GEN_INT (fsiz);
2439   rtx reg_rtx;
2440   rtx mem_rtx;
2441
2442   /* In case of interrupt handlers use addki instead of addi for changing the 
2443      stack pointer value.  */
2444
2445   if (microblaze_can_use_return_insn ())
2446     {
2447       emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode,
2448                                                         GP_REG_FIRST +
2449                                                         MB_ABI_SUB_RETURN_ADDR_REGNUM)));
2450       return;
2451     }
2452
2453   if (fsiz > 0)
2454     {
2455       /* Restore SUB_RETURN_ADDR_REGNUM at first. This is to prevent the 
2456          sequence of load-followed by a use (in rtsd) in every prologue. Saves 
2457          a load-use stall cycle  :)   This is also important to handle alloca. 
2458          (See comments for if (frame_pointer_needed) below.  */
2459
2460       if (!current_function_is_leaf || interrupt_handler)
2461         {
2462           mem_rtx =
2463             gen_rtx_MEM (SImode,
2464                          gen_rtx_PLUS (Pmode, stack_pointer_rtx, const0_rtx));
2465           if (interrupt_handler)
2466             /* Do not optimize in flow analysis.  */
2467             MEM_VOLATILE_P (mem_rtx) = 1;
2468           reg_rtx = gen_rtx_REG (SImode, MB_ABI_SUB_RETURN_ADDR_REGNUM);
2469           emit_move_insn (reg_rtx, mem_rtx);
2470         }
2471
2472       /* It is important that this is done after we restore the return address 
2473          register (above).  When alloca is used, we want to restore the 
2474          sub-routine return address only from the current stack top and not 
2475          from the frame pointer (which we restore below). (frame_pointer + 0) 
2476          might have been over-written since alloca allocates memory on the 
2477          current stack.  */
2478       if (frame_pointer_needed)
2479         emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx));
2480
2481       /* _restore_ registers for epilogue.  */
2482       save_restore_insns (0);
2483       emit_insn (gen_blockage ());
2484       emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, fsiz_rtx));
2485     }
2486
2487   emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, GP_REG_FIRST +
2488                                                     MB_ABI_SUB_RETURN_ADDR_REGNUM)));
2489 }
2490
2491
2492 /* Return nonzero if this function is known to have a null epilogue.
2493    This allows the optimizer to omit jumps to jumps if no stack
2494    was created.  */
2495
2496 int
2497 microblaze_can_use_return_insn (void)
2498 {
2499   if (!reload_completed)
2500     return 0;
2501
2502   if (df_regs_ever_live_p (MB_ABI_SUB_RETURN_ADDR_REGNUM) || profile_flag)
2503     return 0;
2504
2505   if (current_frame_info.initialized)
2506     return current_frame_info.total_size == 0;
2507
2508   return compute_frame_size (get_frame_size ()) == 0;
2509 }
2510
2511 /* Implement TARGET_SECONDARY_RELOAD.  */
2512
2513 static reg_class_t
2514 microblaze_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED, 
2515                              reg_class_t rclass, enum machine_mode mode ATTRIBUTE_UNUSED, 
2516                              secondary_reload_info *sri ATTRIBUTE_UNUSED)
2517 {
2518   if (rclass == ST_REGS)
2519     return GR_REGS;
2520
2521   return NO_REGS;
2522 }
2523
2524 static void
2525 microblaze_globalize_label (FILE * stream, const char *name)
2526 {
2527   fputs ("\t.globl\t", stream);
2528   if (interrupt_handler && strcmp (name, INTERRUPT_HANDLER_NAME))
2529     {
2530       fputs (INTERRUPT_HANDLER_NAME, stream);
2531       fputs ("\n\t.globl\t", stream);
2532     }
2533   assemble_name (stream, name);
2534   fputs ("\n", stream);
2535 }
2536
2537 /* Returns true if decl should be placed into a "small data" section.  */
2538 static bool
2539 microblaze_elf_in_small_data_p (const_tree decl)
2540 {
2541   HOST_WIDE_INT size;
2542
2543   if (!TARGET_XLGPOPT)
2544     return false;
2545
2546   /* We want to merge strings, so we never consider them small data.  */
2547   if (TREE_CODE (decl) == STRING_CST)
2548     return false;
2549
2550   /* Functions are never in the small data area.  */
2551   if (TREE_CODE (decl) == FUNCTION_DECL)
2552     return false;
2553
2554   if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl))
2555     {
2556       const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
2557       if (strcmp (section, ".sdata") == 0
2558           || strcmp (section, ".sdata2") == 0
2559           || strcmp (section, ".sbss") == 0
2560           || strcmp (section, ".sbss2") == 0)
2561         return true;
2562     }
2563
2564   size = int_size_in_bytes (TREE_TYPE (decl));
2565
2566   return (size > 0 && size <= microblaze_section_threshold);
2567 }
2568
2569
2570 static section *
2571 microblaze_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
2572 {
2573   switch (categorize_decl_for_section (decl, reloc))
2574     {
2575     case SECCAT_RODATA_MERGE_STR:
2576     case SECCAT_RODATA_MERGE_STR_INIT:
2577       /* MB binutils have various issues with mergeable string sections and
2578          relaxation/relocation. Currently, turning mergeable sections 
2579          into regular readonly sections.  */
2580
2581       return readonly_data_section;
2582     default:
2583       return default_elf_select_section (decl, reloc, align);
2584     }
2585 }
2586
2587 /*
2588   Encode info about sections into the RTL based on a symbol's declaration.
2589   The default definition of this hook, default_encode_section_info in 
2590   `varasm.c', sets a number of commonly-useful bits in SYMBOL_REF_FLAGS. */
2591
2592 static void
2593 microblaze_encode_section_info (tree decl, rtx rtl, int first)
2594 {
2595   default_encode_section_info (decl, rtl, first);
2596 }
2597
2598 static rtx
2599 expand_pic_symbol_ref (enum machine_mode mode ATTRIBUTE_UNUSED, rtx op)
2600 {
2601   rtx result;
2602   result = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op), UNSPEC_GOTOFF);
2603   result = gen_rtx_CONST (Pmode, result);
2604   result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
2605   result = gen_const_mem (Pmode, result);
2606   return result;
2607 }
2608
2609 bool
2610 microblaze_expand_move (enum machine_mode mode, rtx operands[])
2611 {
2612   /* If operands[1] is a constant address invalid for pic, then we need to
2613      handle it just like LEGITIMIZE_ADDRESS does.  */
2614   if (flag_pic)
2615     {
2616       if (GET_CODE (operands[0]) == MEM)
2617         {
2618           rtx addr = XEXP (operands[0], 0);
2619           if (GET_CODE (addr) == SYMBOL_REF)
2620             {
2621               rtx ptr_reg, result;
2622
2623               if (reload_in_progress)
2624                 df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2625
2626               addr = expand_pic_symbol_ref (mode, addr);
2627               ptr_reg = gen_reg_rtx (Pmode);
2628               emit_move_insn (ptr_reg, addr);
2629               result = gen_rtx_MEM (mode, ptr_reg);
2630               operands[0] = result;
2631             }
2632         }
2633       if (GET_CODE (operands[1]) == SYMBOL_REF
2634           || GET_CODE (operands[1]) == LABEL_REF)
2635         {
2636           rtx result;
2637           if (reload_in_progress)
2638             df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2639           result = expand_pic_symbol_ref (mode, operands[1]);
2640           if (GET_CODE (operands[0]) != REG)
2641             {
2642               rtx ptr_reg = gen_reg_rtx (Pmode);
2643               emit_move_insn (ptr_reg, result);
2644               emit_move_insn (operands[0], ptr_reg);
2645             }
2646           else
2647             {
2648               emit_move_insn (operands[0], result);
2649             }
2650           return true;
2651         }
2652       else if (GET_CODE (operands[1]) == MEM &&
2653                GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
2654         {
2655           rtx result;
2656           rtx ptr_reg;
2657           if (reload_in_progress)
2658             df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2659           result = expand_pic_symbol_ref (mode, XEXP (operands[1], 0));
2660
2661           ptr_reg = gen_reg_rtx (Pmode);
2662
2663           emit_move_insn (ptr_reg, result);
2664           result = gen_rtx_MEM (mode, ptr_reg);
2665           emit_move_insn (operands[0], result);
2666           return true;
2667         }
2668       else if (pic_address_needs_scratch (operands[1]))
2669         {
2670           rtx temp = force_reg (SImode, XEXP (XEXP (operands[1], 0), 0));
2671           rtx temp2 = XEXP (XEXP (operands[1], 0), 1);
2672
2673           if (reload_in_progress)
2674             df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2675           emit_move_insn (operands[0], gen_rtx_PLUS (SImode, temp, temp2));
2676           return true;
2677         }
2678     }
2679
2680   if ((reload_in_progress | reload_completed) == 0
2681       && !register_operand (operands[0], SImode)
2682       && !register_operand (operands[1], SImode)
2683       && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0))
2684     {
2685       rtx temp = force_reg (SImode, operands[1]);
2686       emit_move_insn (operands[0], temp);
2687       return true;
2688     }
2689   return false;
2690 }
2691
2692 /* Expand shift operations.  */
2693 int
2694 microblaze_expand_shift (rtx operands[])
2695 {
2696   gcc_assert ((GET_CODE (operands[2]) == CONST_INT)
2697               || (GET_CODE (operands[2]) == REG)
2698               || (GET_CODE (operands[2]) == SUBREG));
2699
2700   /* Shift by one -- generate pattern.  */
2701   if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) == 1))
2702     return 0;
2703
2704   /* Have barrel shifter and shift > 1: use it.  */
2705   if (TARGET_BARREL_SHIFT)
2706     return 0;
2707
2708   gcc_assert ((GET_CODE (operands[0]) == REG)
2709               || (GET_CODE (operands[0]) == SUBREG)
2710               || (GET_CODE (operands[1]) == REG)
2711               || (GET_CODE (operands[1]) == SUBREG));
2712
2713   /* Shift by zero -- copy regs if necessary.  */
2714   if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) == 0))
2715     {
2716       if (REGNO (operands[0]) != REGNO (operands[1]))
2717         emit_insn (gen_movsi (operands[0], operands[1]));
2718       return 1;
2719     }
2720
2721   return 0;
2722 }
2723
2724 /* Return an RTX indicating where the return address to the
2725    calling function can be found.  */
2726 rtx
2727 microblaze_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
2728 {
2729   if (count != 0)
2730     return NULL_RTX;
2731
2732   return gen_rtx_PLUS (Pmode,
2733                        get_hard_reg_initial_val (Pmode,
2734                                                  MB_ABI_SUB_RETURN_ADDR_REGNUM),
2735                        GEN_INT (8));
2736 }
2737
2738 /* Put string into .sdata2 if below threashold.  */
2739 void 
2740 microblaze_asm_output_ident (FILE *file ATTRIBUTE_UNUSED, const char *string)
2741 {
2742   int size = strlen (string) + 1;
2743   if (size <= microblaze_section_threshold)
2744     switch_to_section (sdata2_section);
2745   else
2746     switch_to_section (readonly_data_section);
2747   assemble_string (string, size);
2748 }
2749
2750 static void
2751 microblaze_elf_asm_init_sections (void)
2752 {
2753   sdata2_section
2754     = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
2755                            SDATA2_SECTION_ASM_OP);
2756 }
2757
2758 /*  Generate assembler code for constant parts of a trampoline.  */
2759
2760 static void
2761 microblaze_asm_trampoline_template (FILE *f)
2762 {
2763   fprintf (f, "\t.word\t0x03e00821\t\t# move   $1,$31\n");
2764   fprintf (f, "\t.word\t0x04110001\t\t# bgezal $0,.+8\n");
2765   fprintf (f, "\t.word\t0x00000000\t\t# nop\n");
2766   fprintf (f, "\t.word\t0x8fe30014\t\t# lw     $3,20($31)\n");
2767   fprintf (f, "\t.word\t0x8fe20018\t\t# lw     $2,24($31)\n");
2768   fprintf (f, "\t.word\t0x0060c821\t\t# move   $25,$3 (abicalls)\n");
2769   fprintf (f, "\t.word\t0x00600008\t\t# jr     $3\n");
2770   fprintf (f, "\t.word\t0x0020f821\t\t# move   $31,$1\n");
2771   /* fprintf (f, "\t.word\t0x00000000\t\t# <function address>\n");  */
2772   /* fprintf (f, "\t.word\t0x00000000\t\t# <static chain value>\n");  */
2773 }
2774
2775 /* Implement TARGET_TRAMPOLINE_INIT.  */
2776
2777 static void
2778 microblaze_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
2779 {
2780   rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2781   rtx mem;
2782
2783   emit_block_move (m_tramp, assemble_trampoline_template (),
2784                    GEN_INT (8*UNITS_PER_WORD), BLOCK_OP_NORMAL);
2785
2786   mem = adjust_address (m_tramp, SImode, 8);
2787   emit_move_insn (mem, chain_value);
2788   mem = adjust_address (m_tramp, SImode, 12);
2789   emit_move_insn (mem, fnaddr);
2790 }
2791 \f
2792 /* Emit instruction to perform compare.  
2793    cmp is (compare_op op0 op1).  */
2794 static rtx
2795 microblaze_emit_compare (enum machine_mode mode, rtx cmp, enum rtx_code *cmp_code)
2796 {
2797   rtx cmp_op0 = XEXP (cmp, 0);
2798   rtx cmp_op1 = XEXP (cmp, 1);
2799   rtx comp_reg = gen_reg_rtx (SImode);
2800   enum rtx_code code = *cmp_code;
2801   
2802   gcc_assert ((GET_CODE (cmp_op0) == REG) || (GET_CODE (cmp_op0) == SUBREG));
2803
2804   /* If comparing against zero, just test source reg.  */
2805   if (cmp_op1 == const0_rtx) 
2806     return cmp_op0;
2807
2808   if (code == EQ || code == NE)
2809     {
2810       if (TARGET_PATTERN_COMPARE && GET_CODE(cmp_op1) == REG) 
2811         {
2812           if (code == EQ) 
2813             emit_insn (gen_seq_internal_pat (comp_reg, cmp_op0, cmp_op1));
2814           else
2815             {    
2816               emit_insn (gen_sne_internal_pat (comp_reg, cmp_op0, cmp_op1));
2817               *cmp_code = EQ;
2818             }
2819         }
2820       else
2821         /* Use xor for equal/not-equal comparison.  */
2822         emit_insn (gen_xorsi3 (comp_reg, cmp_op0, cmp_op1));
2823     }
2824   else if (code == GT || code == GTU || code == LE || code == LEU)
2825     {
2826       /* MicroBlaze compare is not symmetrical.  */
2827       /* Swap argument order.  */
2828       cmp_op1 = force_reg (mode, cmp_op1);
2829       if (code == GT || code == LE) 
2830         emit_insn (gen_signed_compare (comp_reg, cmp_op0, cmp_op1));
2831       else
2832         emit_insn (gen_unsigned_compare (comp_reg, cmp_op0, cmp_op1));
2833       /* Translate test condition.  */
2834       *cmp_code = swap_condition (code);
2835     }
2836   else /* if (code == GE || code == GEU || code == LT || code == LTU) */
2837     {
2838       cmp_op1 = force_reg (mode, cmp_op1);
2839       if (code == GE || code == LT) 
2840         emit_insn (gen_signed_compare (comp_reg, cmp_op1, cmp_op0));
2841       else
2842         emit_insn (gen_unsigned_compare (comp_reg, cmp_op1, cmp_op0));
2843     }
2844
2845   return comp_reg;
2846 }
2847
2848 /* Generate conditional branch -- first, generate test condition,
2849    second, generate correct branch instruction.  */
2850
2851 void
2852 microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[])
2853 {
2854   enum rtx_code code = GET_CODE (operands[0]);
2855   rtx comp;
2856   rtx condition;
2857
2858   comp = microblaze_emit_compare (mode, operands[0], &code);
2859   condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp, const0_rtx);
2860   emit_jump_insn (gen_condjump (condition, operands[3]));
2861 }
2862
2863 void
2864 microblaze_expand_conditional_branch_sf (rtx operands[])
2865 {
2866   rtx condition;
2867   rtx cmp_op0 = XEXP (operands[0], 0);
2868   rtx cmp_op1 = XEXP (operands[0], 1);
2869   rtx comp_reg = gen_reg_rtx (SImode);
2870
2871   emit_insn (gen_cstoresf4 (comp_reg, operands[0], cmp_op0, cmp_op1));
2872   condition = gen_rtx_NE (SImode, comp_reg, const0_rtx);
2873   emit_jump_insn (gen_condjump (condition, operands[3]));
2874 }
2875
2876 /* Implement TARGET_FRAME_POINTER_REQUIRED.  */
2877
2878 static bool
2879 microblaze_frame_pointer_required (void)
2880 {
2881   /* If the function contains dynamic stack allocations, we need to
2882      use the frame pointer to access the static parts of the frame.  */
2883   if (cfun->calls_alloca)
2884     return true;
2885   return false;
2886 }
2887
2888 void
2889 microblaze_expand_divide (rtx operands[])
2890 {
2891   /* Table lookup software divides. Works for all (nr/dr) where (0 <= nr,dr <= 15).  */
2892
2893   rtx regt1 = gen_reg_rtx (SImode); 
2894   rtx reg18 = gen_rtx_REG (SImode, R_TMP);
2895   rtx regqi = gen_reg_rtx (QImode);
2896   rtx div_label = gen_label_rtx ();
2897   rtx div_end_label = gen_label_rtx ();
2898   rtx div_table_rtx = gen_rtx_SYMBOL_REF (QImode,"_divsi3_table");
2899   rtx mem_rtx;
2900   rtx ret;
2901   rtx jump, cjump, insn;
2902
2903   insn = emit_insn (gen_iorsi3 (regt1, operands[1], operands[2]));
2904   cjump = emit_jump_insn_after (gen_cbranchsi4 (
2905                                         gen_rtx_GTU (SImode, regt1, GEN_INT (15)), 
2906                                         regt1, GEN_INT (15), div_label), insn);
2907   LABEL_NUSES (div_label) = 1; 
2908   JUMP_LABEL (cjump) = div_label;
2909   emit_insn (gen_rtx_CLOBBER (SImode, reg18));
2910
2911   emit_insn (gen_ashlsi3_bshift (regt1, operands[1], GEN_INT(4)));
2912   emit_insn (gen_addsi3 (regt1, regt1, operands[2]));
2913   mem_rtx = gen_rtx_MEM (QImode,
2914                             gen_rtx_PLUS (Pmode, regt1, div_table_rtx));
2915
2916   insn = emit_insn (gen_movqi (regqi, mem_rtx)); 
2917   insn = emit_insn (gen_movsi (operands[0], gen_rtx_SUBREG (SImode, regqi, 0)));
2918   jump = emit_jump_insn_after (gen_jump (div_end_label), insn); 
2919   JUMP_LABEL (jump) = div_end_label;
2920   LABEL_NUSES (div_end_label) = 1; 
2921   emit_barrier ();
2922
2923   emit_label (div_label);
2924   ret = emit_library_call_value (gen_rtx_SYMBOL_REF (Pmode, "__divsi3"), 
2925                                        operands[0], LCT_NORMAL, 
2926                                        GET_MODE (operands[0]), 2, operands[1], 
2927                                        GET_MODE (operands[1]), operands[2], 
2928                                        GET_MODE (operands[2]));
2929   if (ret != operands[0])
2930                 emit_move_insn (operands[0], ret);    
2931
2932   emit_label (div_end_label);
2933   emit_insn (gen_blockage ());
2934 }
2935
2936 /* Implement TARGET_FUNCTION_VALUE.  */
2937 static rtx
2938 microblaze_function_value (const_tree valtype,
2939                            const_tree func ATTRIBUTE_UNUSED,
2940                            bool outgoing ATTRIBUTE_UNUSED)
2941 {
2942   return LIBCALL_VALUE (TYPE_MODE (valtype));
2943 }
2944
2945 /* Implement TARGET_SCHED_ADJUST_COST.  */
2946 static int
2947 microblaze_adjust_cost (rtx insn ATTRIBUTE_UNUSED, rtx link,
2948                         rtx dep ATTRIBUTE_UNUSED, int cost)
2949 {
2950   if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
2951     return cost;
2952   if (REG_NOTE_KIND (link) != 0)
2953     return 0;
2954   return cost;
2955 }
2956
2957 /* Implement TARGET_LEGITIMATE_CONSTANT_P.
2958
2959    At present, GAS doesn't understand li.[sd], so don't allow it
2960    to be generated at present.  */
2961 static bool
2962 microblaze_legitimate_constant_p (enum machine_mode mode, rtx x)
2963 {
2964   return GET_CODE (x) != CONST_DOUBLE || microblaze_const_double_ok (x, mode);
2965 }
2966 \f
2967 #undef TARGET_ENCODE_SECTION_INFO
2968 #define TARGET_ENCODE_SECTION_INFO      microblaze_encode_section_info
2969
2970 #undef TARGET_ASM_GLOBALIZE_LABEL
2971 #define TARGET_ASM_GLOBALIZE_LABEL      microblaze_globalize_label
2972
2973 #undef TARGET_ASM_FUNCTION_PROLOGUE
2974 #define TARGET_ASM_FUNCTION_PROLOGUE    microblaze_function_prologue
2975
2976 #undef TARGET_ASM_FUNCTION_EPILOGUE
2977 #define TARGET_ASM_FUNCTION_EPILOGUE    microblaze_function_epilogue
2978
2979 #undef TARGET_RTX_COSTS
2980 #define TARGET_RTX_COSTS                microblaze_rtx_costs
2981
2982 #undef TARGET_ADDRESS_COST
2983 #define TARGET_ADDRESS_COST             microblaze_address_cost
2984
2985 #undef TARGET_ATTRIBUTE_TABLE
2986 #define TARGET_ATTRIBUTE_TABLE          microblaze_attribute_table
2987
2988 #undef TARGET_IN_SMALL_DATA_P
2989 #define TARGET_IN_SMALL_DATA_P          microblaze_elf_in_small_data_p
2990
2991 #undef TARGET_ASM_SELECT_SECTION
2992 #define TARGET_ASM_SELECT_SECTION       microblaze_select_section
2993
2994 #undef TARGET_HAVE_SRODATA_SECTION
2995 #define TARGET_HAVE_SRODATA_SECTION     true
2996
2997 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
2998 #define TARGET_ASM_FUNCTION_END_PROLOGUE \
2999                                         microblaze_function_end_prologue
3000
3001 #undef TARGET_ARG_PARTIAL_BYTES
3002 #define TARGET_ARG_PARTIAL_BYTES        function_arg_partial_bytes
3003
3004 #undef TARGET_FUNCTION_ARG
3005 #define TARGET_FUNCTION_ARG             microblaze_function_arg
3006
3007 #undef TARGET_FUNCTION_ARG_ADVANCE
3008 #define TARGET_FUNCTION_ARG_ADVANCE     microblaze_function_arg_advance
3009
3010 #undef TARGET_CAN_ELIMINATE
3011 #define TARGET_CAN_ELIMINATE            microblaze_can_eliminate
3012
3013 #undef TARGET_LEGITIMIZE_ADDRESS
3014 #define TARGET_LEGITIMIZE_ADDRESS       microblaze_legitimize_address
3015
3016 #undef TARGET_LEGITIMATE_ADDRESS_P
3017 #define TARGET_LEGITIMATE_ADDRESS_P     microblaze_legitimate_address_p 
3018
3019 #undef TARGET_FRAME_POINTER_REQUIRED
3020 #define TARGET_FRAME_POINTER_REQUIRED   microblaze_frame_pointer_required
3021
3022 #undef  TARGET_ASM_TRAMPOLINE_TEMPLATE
3023 #define TARGET_ASM_TRAMPOLINE_TEMPLATE  microblaze_asm_trampoline_template
3024
3025 #undef  TARGET_TRAMPOLINE_INIT
3026 #define TARGET_TRAMPOLINE_INIT          microblaze_trampoline_init
3027
3028 #undef  TARGET_PROMOTE_FUNCTION_MODE
3029 #define TARGET_PROMOTE_FUNCTION_MODE    default_promote_function_mode_always_promote
3030
3031 #undef TARGET_FUNCTION_VALUE
3032 #define TARGET_FUNCTION_VALUE           microblaze_function_value 
3033
3034 #undef TARGET_SECONDARY_RELOAD
3035 #define TARGET_SECONDARY_RELOAD         microblaze_secondary_reload
3036
3037 #undef TARGET_SCHED_ADJUST_COST
3038 #define TARGET_SCHED_ADJUST_COST        microblaze_adjust_cost
3039
3040 #undef TARGET_ASM_INIT_SECTIONS
3041 #define TARGET_ASM_INIT_SECTIONS        microblaze_elf_asm_init_sections
3042
3043 #undef  TARGET_OPTION_OVERRIDE
3044 #define TARGET_OPTION_OVERRIDE          microblaze_option_override 
3045
3046 #undef TARGET_LEGITIMATE_CONSTANT_P
3047 #define TARGET_LEGITIMATE_CONSTANT_P microblaze_legitimate_constant_p
3048
3049 struct gcc_target targetm = TARGET_INITIALIZER;
3050 \f
3051 #include "gt-microblaze.h"