OSDN Git Service

5796bc7c166ced38df2da895c56997aa6093d6e9
[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 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 int
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 (mode == 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 * cum, enum machine_mode mode,
1095                                  const_tree type, bool named ATTRIBUTE_UNUSED)
1096 {
1097   cum->arg_number++;
1098   switch (mode)
1099     {
1100     case VOIDmode:
1101       break;
1102
1103     default:
1104       gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
1105           || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
1106
1107       cum->gp_reg_found = 1;
1108       cum->arg_words += ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
1109                          / UNITS_PER_WORD);
1110       break;
1111
1112     case BLKmode:
1113       cum->gp_reg_found = 1;
1114       cum->arg_words += ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
1115                          / UNITS_PER_WORD);
1116       break;
1117
1118     case SFmode:
1119       cum->arg_words++;
1120       if (!cum->gp_reg_found && cum->arg_number <= 2)
1121         cum->fp_code += 1 << ((cum->arg_number - 1) * 2);
1122       break;
1123
1124     case DFmode:
1125       cum->arg_words += 2;
1126       if (!cum->gp_reg_found && cum->arg_number <= 2)
1127         cum->fp_code += 2 << ((cum->arg_number - 1) * 2);
1128       break;
1129
1130     case DImode:
1131       cum->gp_reg_found = 1;
1132       cum->arg_words += 2;
1133       break;
1134
1135     case QImode:
1136     case HImode:
1137     case SImode:
1138     case TImode:
1139       cum->gp_reg_found = 1;
1140       cum->arg_words++;
1141       break;
1142     }
1143 }
1144
1145 /* Return an RTL expression containing the register for the given mode,
1146    or 0 if the argument is to be passed on the stack.  */
1147
1148 static rtx
1149 microblaze_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode, 
1150                          const_tree type ATTRIBUTE_UNUSED,
1151                          bool named ATTRIBUTE_UNUSED)
1152 {
1153   rtx ret;
1154   int regbase = -1;
1155   int *arg_words = &cum->arg_words;
1156
1157   cum->last_arg_fp = 0;
1158   switch (mode)
1159     {
1160     case SFmode:
1161     case DFmode:
1162     case VOIDmode:
1163     case QImode:
1164     case HImode:
1165     case SImode:
1166     case DImode:
1167     case TImode:
1168       regbase = GP_ARG_FIRST;
1169       break;
1170     default:
1171       gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
1172           || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
1173       /* Drops through.  */
1174     case BLKmode:
1175       regbase = GP_ARG_FIRST;
1176       break;
1177     }
1178
1179   if (*arg_words >= MAX_ARGS_IN_REGISTERS)
1180     ret = 0;
1181   else
1182     {
1183       gcc_assert (regbase != -1);
1184
1185       ret = gen_rtx_REG (mode, regbase + *arg_words);
1186     }
1187
1188   if (mode == VOIDmode)
1189     {
1190       if (cum->num_adjusts > 0)
1191         ret = gen_rtx_PARALLEL ((enum machine_mode) cum->fp_code,
1192                                 gen_rtvec_v (cum->num_adjusts, cum->adjust));
1193     }
1194
1195   return ret;
1196 }
1197
1198 /* Return number of bytes of argument to put in registers. */
1199 static int
1200 function_arg_partial_bytes (CUMULATIVE_ARGS * cum, enum machine_mode mode,      
1201                             tree type, bool named ATTRIBUTE_UNUSED)     
1202 {
1203   if ((mode == BLKmode
1204        || GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
1205        || GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
1206       && cum->arg_words < MAX_ARGS_IN_REGISTERS)
1207     {
1208       int words;
1209       if (mode == BLKmode)
1210         words = ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
1211                  / UNITS_PER_WORD);
1212       else
1213         words = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1214
1215       if (words + cum->arg_words <= MAX_ARGS_IN_REGISTERS)
1216         return 0;               /* structure fits in registers */
1217
1218       return (MAX_ARGS_IN_REGISTERS - cum->arg_words) * UNITS_PER_WORD;
1219     }
1220
1221   else if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1)
1222     return UNITS_PER_WORD;
1223
1224   return 0;
1225 }
1226
1227 /*  Convert a version number of the form "vX.YY.Z" to an integer encoding 
1228     for easier range comparison.  */
1229 static int
1230 microblaze_version_to_int (const char *version)
1231 {
1232   const char *p, *v;
1233   const char *tmpl = "vX.YY.Z";
1234   int iver = 0;
1235
1236   p = version;
1237   v = tmpl;
1238
1239   while (*v)
1240     {
1241       if (*v == 'X')
1242         {                       /* Looking for major  */
1243           if (!(*p >= '0' && *p <= '9'))
1244             return -1;
1245           iver += (int) (*p - '0');
1246           iver *= 10;
1247         }
1248       else if (*v == 'Y')
1249         {                       /* Looking for minor  */
1250           if (!(*p >= '0' && *p <= '9'))
1251             return -1;
1252           iver += (int) (*p - '0');
1253           iver *= 10;
1254         }
1255       else if (*v == 'Z')
1256         {                       /* Looking for compat  */
1257           if (!(*p >= 'a' && *p <= 'z'))
1258             return -1;
1259           iver *= 10;
1260           iver += (int) (*p - 'a');
1261         }
1262       else
1263         {
1264           if (*p != *v)
1265             return -1;
1266         }
1267
1268       v++;
1269       p++;
1270     }
1271
1272   if (*p)
1273     return -1;
1274
1275   return iver;
1276 }
1277
1278
1279 static void
1280 microblaze_option_override (void)
1281 {
1282   register int i, start;
1283   register int regno;
1284   register enum machine_mode mode;
1285   int ver;
1286
1287   microblaze_section_threshold = (global_options_set.x_g_switch_value
1288                                   ? g_switch_value
1289                                   : MICROBLAZE_DEFAULT_GVALUE);
1290
1291   /* Check the MicroBlaze CPU version for any special action to be done.  */
1292   if (microblaze_select_cpu == NULL)
1293     microblaze_select_cpu = MICROBLAZE_DEFAULT_CPU;
1294   ver = microblaze_version_to_int (microblaze_select_cpu);
1295   if (ver == -1)
1296     {
1297       error ("%qs is an invalid argument to -mcpu=", microblaze_select_cpu);
1298     }
1299
1300   ver = MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v3.00.a");
1301   if (ver < 0)
1302     {
1303       /* No hardware exceptions in earlier versions. So no worries.  */
1304 #if 0
1305       microblaze_select_flags &= ~(MICROBLAZE_MASK_NO_UNSAFE_DELAY);
1306 #endif
1307       microblaze_no_unsafe_delay = 0;
1308       microblaze_pipe = MICROBLAZE_PIPE_3;
1309     }
1310   else if (ver == 0
1311            || (MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v4.00.b")
1312                == 0))
1313     {
1314 #if 0
1315       microblaze_select_flags |= (MICROBLAZE_MASK_NO_UNSAFE_DELAY);
1316 #endif
1317       microblaze_no_unsafe_delay = 1;
1318       microblaze_pipe = MICROBLAZE_PIPE_3;
1319     }
1320   else
1321     {
1322       /* We agree to use 5 pipe-stage model even on area optimized 3 
1323          pipe-stage variants.  */
1324 #if 0
1325       microblaze_select_flags &= ~(MICROBLAZE_MASK_NO_UNSAFE_DELAY);
1326 #endif
1327       microblaze_no_unsafe_delay = 0;
1328       microblaze_pipe = MICROBLAZE_PIPE_5;
1329       if (MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v5.00.a") == 0
1330           || MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu,
1331                                          "v5.00.b") == 0
1332           || MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu,
1333                                          "v5.00.c") == 0)
1334         {
1335           /* Pattern compares are to be turned on by default only when 
1336              compiling for MB v5.00.'z'.  */
1337           target_flags |= MASK_PATTERN_COMPARE;
1338         }
1339     }
1340
1341   ver = MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v6.00.a");
1342   if (ver < 0)
1343     {
1344       if (TARGET_MULTIPLY_HIGH)
1345         warning (0,
1346                  "-mxl-multiply-high can be used only with -mcpu=v6.00.a or greater");
1347     }
1348
1349   if (TARGET_MULTIPLY_HIGH && TARGET_SOFT_MUL)
1350     error ("-mxl-multiply-high requires -mno-xl-soft-mul");
1351
1352   /* Always use DFA scheduler.  */
1353   microblaze_sched_use_dfa = 1;
1354
1355 #if 0
1356   microblaze_abicalls = MICROBLAZE_ABICALLS_NO;
1357 #endif
1358
1359   /* Initialize the high, low values for legit floating point constants.  */
1360   real_maxval (&dfhigh, 0, DFmode);
1361   real_maxval (&dflow, 1, DFmode);
1362   real_maxval (&sfhigh, 0, SFmode);
1363   real_maxval (&sflow, 1, SFmode);
1364
1365   microblaze_print_operand_punct['?'] = 1;
1366   microblaze_print_operand_punct['#'] = 1;
1367   microblaze_print_operand_punct['&'] = 1;
1368   microblaze_print_operand_punct['!'] = 1;
1369   microblaze_print_operand_punct['*'] = 1;
1370   microblaze_print_operand_punct['@'] = 1;
1371   microblaze_print_operand_punct['.'] = 1;
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
1384   /* Set up array to map GCC register number to debug register number.
1385      Ignore the special purpose register numbers.  */
1386
1387   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1388     microblaze_dbx_regno[i] = -1;
1389
1390   start = GP_DBX_FIRST - GP_REG_FIRST;
1391   for (i = GP_REG_FIRST; i <= GP_REG_LAST; i++)
1392     microblaze_dbx_regno[i] = i + start;
1393
1394   /* Set up array giving whether a given register can hold a given mode.   */
1395
1396   for (mode = VOIDmode;
1397        mode != MAX_MACHINE_MODE; mode = (enum machine_mode) ((int) mode + 1))
1398     {
1399       register int size = GET_MODE_SIZE (mode);
1400
1401       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1402         {
1403           register int ok;
1404
1405           if (mode == CCmode)
1406             {
1407               ok = (ST_REG_P (regno) || GP_REG_P (regno));
1408             }
1409           else if (GP_REG_P (regno))
1410             ok = ((regno & 1) == 0 || size <= UNITS_PER_WORD);
1411           else
1412             ok = 0;
1413
1414           microblaze_hard_regno_mode_ok[(int) mode][regno] = ok;
1415         }
1416     }
1417 }
1418
1419 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE.  */
1420 static const struct default_options microblaze_option_optimization_table[] =
1421   {
1422     { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
1423     { OPT_LEVELS_NONE, 0, NULL, 0 }
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;
2231   rtx mem_rtx, reg_rtx;
2232
2233   /* If struct value address is treated as the first argument, make it so.  */
2234   if (aggregate_value_p (DECL_RESULT (fndecl), fntype)
2235       && !cfun->returns_pcc_struct)
2236     {
2237       tree type = build_pointer_type (fntype);
2238       tree function_result_decl = build_decl (BUILTINS_LOCATION, PARM_DECL, 
2239                                               NULL_TREE, type);
2240
2241       DECL_ARG_TYPE (function_result_decl) = type;
2242       TREE_CHAIN (function_result_decl) = fnargs;
2243       fnargs = function_result_decl;
2244     }
2245
2246   /* Determine the last argument, and get its name.  */
2247
2248   INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, 0, 0);
2249   regno = GP_ARG_FIRST;
2250
2251   for (cur_arg = fnargs; cur_arg != 0; cur_arg = next_arg)
2252     {
2253       tree passed_type = DECL_ARG_TYPE (cur_arg);
2254       enum machine_mode passed_mode = TYPE_MODE (passed_type);
2255       rtx entry_parm;
2256
2257       if (TREE_ADDRESSABLE (passed_type))
2258         {
2259           passed_type = build_pointer_type (passed_type);
2260           passed_mode = Pmode;
2261         }
2262
2263       entry_parm = targetm.calls.function_arg (&args_so_far, passed_mode,
2264                                                passed_type, true);
2265
2266       if (entry_parm)
2267         {
2268           int words;
2269
2270           /* passed in a register, so will get homed automatically.  */
2271           if (GET_MODE (entry_parm) == BLKmode)
2272             words = (int_size_in_bytes (passed_type) + 3) / 4;
2273           else
2274             words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4;
2275
2276           regno = REGNO (entry_parm) + words - 1;
2277         }
2278       else
2279         {
2280           regno = GP_ARG_LAST + 1;
2281           break;
2282         }
2283
2284       targetm.calls.function_arg_advance (&args_so_far, passed_mode,
2285                                           passed_type, true);
2286
2287       next_arg = TREE_CHAIN (cur_arg);
2288       if (next_arg == 0)
2289         {
2290           if (DECL_NAME (cur_arg))
2291             arg_name = IDENTIFIER_POINTER (DECL_NAME (cur_arg));
2292
2293           break;
2294         }
2295     }
2296
2297   /* Split parallel insn into a sequence of insns.  */
2298
2299   next_arg_reg = targetm.calls.function_arg (&args_so_far, VOIDmode,
2300                                              void_type_node, true);
2301   if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL)
2302     {
2303       rtvec adjust = XVEC (next_arg_reg, 0);
2304       int num = GET_NUM_ELEM (adjust);
2305
2306       for (i = 0; i < num; i++)
2307         {
2308           rtx pattern = RTVEC_ELT (adjust, i);
2309           emit_insn (pattern);
2310         }
2311     }
2312
2313   fsiz = compute_frame_size (get_frame_size ());
2314
2315   /* If this function is a varargs function, store any registers that
2316      would normally hold arguments ($5 - $10) on the stack.  */
2317   if (((TYPE_ARG_TYPES (fntype) != 0
2318         && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2319             != void_type_node))
2320        || (arg_name != 0
2321            && ((arg_name[0] == '_'
2322                 && strcmp (arg_name, "__builtin_va_alist") == 0)
2323                || (arg_name[0] == 'v'
2324                    && strcmp (arg_name, "va_alist") == 0)))))
2325     {
2326       int offset = (regno - GP_ARG_FIRST + 1) * UNITS_PER_WORD;
2327       rtx ptr = stack_pointer_rtx;
2328
2329       /* If we are doing svr4-abi, sp has already been decremented by fsiz. */
2330       for (; regno <= GP_ARG_LAST; regno++)
2331         {
2332           if (offset != 0)
2333             ptr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
2334           emit_move_insn (gen_rtx_MEM (SImode, ptr),
2335                           gen_rtx_REG (SImode, regno));
2336
2337           offset += GET_MODE_SIZE (SImode);
2338         }
2339
2340     }
2341
2342   if (fsiz > 0)
2343     {
2344       rtx fsiz_rtx = GEN_INT (fsiz);
2345
2346       rtx insn = NULL;
2347       insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
2348                                     fsiz_rtx));
2349       if (insn)
2350         RTX_FRAME_RELATED_P (insn) = 1;
2351
2352       /* Handle SUB_RETURN_ADDR_REGNUM specially at first.  */
2353       if (!current_function_is_leaf || interrupt_handler)
2354         {
2355           mem_rtx = gen_rtx_MEM (SImode,
2356                                  gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2357                                                const0_rtx));
2358
2359           if (interrupt_handler)
2360             /* Do not optimize in flow analysis.  */
2361             MEM_VOLATILE_P (mem_rtx) = 1;
2362
2363           reg_rtx = gen_rtx_REG (SImode, MB_ABI_SUB_RETURN_ADDR_REGNUM);
2364           insn = emit_move_insn (mem_rtx, reg_rtx);
2365           RTX_FRAME_RELATED_P (insn) = 1;
2366         }
2367
2368       /* _save_ registers for prologue.  */
2369       save_restore_insns (1);
2370
2371       if (frame_pointer_needed)
2372         {
2373           rtx insn = 0;
2374
2375           insn = emit_insn (gen_movsi (hard_frame_pointer_rtx,
2376                                        stack_pointer_rtx));
2377
2378           if (insn)
2379             RTX_FRAME_RELATED_P (insn) = 1;
2380         }
2381     }
2382
2383   if (flag_pic == 2 && df_regs_ever_live_p (MB_ABI_PIC_ADDR_REGNUM))
2384     {
2385       SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM);
2386       emit_insn (gen_set_got (pic_offset_table_rtx));   /* setting GOT.  */
2387     }
2388
2389   /* If we are profiling, make sure no instructions are scheduled before
2390      the call to mcount.  */
2391
2392   if (profile_flag)
2393     emit_insn (gen_blockage ());
2394 }
2395
2396 /* Do necessary cleanup after a function to restore stack, frame, and regs.  */
2397
2398 #define RA_MASK ((long) 0x80000000)     /* 1 << 31 */
2399 #define PIC_OFFSET_TABLE_MASK (1 << (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
2400
2401 static void
2402 microblaze_function_epilogue (FILE * file ATTRIBUTE_UNUSED,
2403                               HOST_WIDE_INT size ATTRIBUTE_UNUSED)
2404 {
2405   const char *fnname;
2406
2407   /* Get the function name the same way that toplev.c does before calling
2408      assemble_start_function.  This is needed so that the name used here
2409      exactly matches the name used in ASM_DECLARE_FUNCTION_NAME.  */
2410   fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
2411
2412   if (!flag_inhibit_size_directive)
2413     {
2414       fputs ("\t.end\t", file);
2415       if (interrupt_handler)
2416         fputs ("_interrupt_handler", file);
2417       else
2418         assemble_name (file, fnname);
2419       fputs ("\n", file);
2420     }
2421
2422   /* Reset state info for each function.  */
2423   current_frame_info = zero_frame_info;
2424
2425   /* Restore the output file if optimizing the GP (optimizing the GP causes
2426      the text to be diverted to a tempfile, so that data decls come before
2427      references to the data).  */
2428 }
2429
2430 /* Expand the epilogue into a bunch of separate insns.  */
2431
2432 void
2433 microblaze_expand_epilogue (void)
2434 {
2435   HOST_WIDE_INT fsiz = current_frame_info.total_size;
2436   rtx fsiz_rtx = GEN_INT (fsiz);
2437   rtx reg_rtx;
2438   rtx mem_rtx;
2439
2440   /* In case of interrupt handlers use addki instead of addi for changing the 
2441      stack pointer value.  */
2442
2443   if (microblaze_can_use_return_insn ())
2444     {
2445       emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode,
2446                                                         GP_REG_FIRST +
2447                                                         MB_ABI_SUB_RETURN_ADDR_REGNUM)));
2448       return;
2449     }
2450
2451   if (fsiz > 0)
2452     {
2453       /* Restore SUB_RETURN_ADDR_REGNUM at first. This is to prevent the 
2454          sequence of load-followed by a use (in rtsd) in every prologue. Saves 
2455          a load-use stall cycle  :)   This is also important to handle alloca. 
2456          (See comments for if (frame_pointer_needed) below.  */
2457
2458       if (!current_function_is_leaf || interrupt_handler)
2459         {
2460           mem_rtx =
2461             gen_rtx_MEM (SImode,
2462                          gen_rtx_PLUS (Pmode, stack_pointer_rtx, const0_rtx));
2463           if (interrupt_handler)
2464             /* Do not optimize in flow analysis.  */
2465             MEM_VOLATILE_P (mem_rtx) = 1;
2466           reg_rtx = gen_rtx_REG (SImode, MB_ABI_SUB_RETURN_ADDR_REGNUM);
2467           emit_move_insn (reg_rtx, mem_rtx);
2468         }
2469
2470       /* It is important that this is done after we restore the return address 
2471          register (above).  When alloca is used, we want to restore the 
2472          sub-routine return address only from the current stack top and not 
2473          from the frame pointer (which we restore below). (frame_pointer + 0) 
2474          might have been over-written since alloca allocates memory on the 
2475          current stack.  */
2476       if (frame_pointer_needed)
2477         emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx));
2478
2479       /* _restore_ registers for epilogue.  */
2480       save_restore_insns (0);
2481       emit_insn (gen_blockage ());
2482       emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, fsiz_rtx));
2483     }
2484
2485   emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, GP_REG_FIRST +
2486                                                     MB_ABI_SUB_RETURN_ADDR_REGNUM)));
2487 }
2488
2489
2490 /* Return nonzero if this function is known to have a null epilogue.
2491    This allows the optimizer to omit jumps to jumps if no stack
2492    was created.  */
2493
2494 int
2495 microblaze_can_use_return_insn (void)
2496 {
2497   if (!reload_completed)
2498     return 0;
2499
2500   if (df_regs_ever_live_p (MB_ABI_SUB_RETURN_ADDR_REGNUM) || profile_flag)
2501     return 0;
2502
2503   if (current_frame_info.initialized)
2504     return current_frame_info.total_size == 0;
2505
2506   return compute_frame_size (get_frame_size ()) == 0;
2507 }
2508
2509 /* Implement TARGET_SECONDARY_RELOAD.  */
2510
2511 static reg_class_t
2512 microblaze_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED, 
2513                              reg_class_t rclass, enum machine_mode mode ATTRIBUTE_UNUSED, 
2514                              secondary_reload_info *sri ATTRIBUTE_UNUSED)
2515 {
2516   if (rclass == ST_REGS)
2517     return GR_REGS;
2518
2519   return NO_REGS;
2520 }
2521
2522 static void
2523 microblaze_globalize_label (FILE * stream, const char *name)
2524 {
2525   fputs ("\t.globl\t", stream);
2526   if (interrupt_handler && strcmp (name, INTERRUPT_HANDLER_NAME))
2527     {
2528       fputs (INTERRUPT_HANDLER_NAME, stream);
2529       fputs ("\n\t.globl\t", stream);
2530     }
2531   assemble_name (stream, name);
2532   fputs ("\n", stream);
2533 }
2534
2535 /* Returns true if decl should be placed into a "small data" section.  */
2536 static bool
2537 microblaze_elf_in_small_data_p (const_tree decl)
2538 {
2539   HOST_WIDE_INT size;
2540
2541   if (!TARGET_XLGPOPT)
2542     return false;
2543
2544   /* We want to merge strings, so we never consider them small data.  */
2545   if (TREE_CODE (decl) == STRING_CST)
2546     return false;
2547
2548   /* Functions are never in the small data area.  */
2549   if (TREE_CODE (decl) == FUNCTION_DECL)
2550     return false;
2551
2552   if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl))
2553     {
2554       const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
2555       if (strcmp (section, ".sdata") == 0
2556           || strcmp (section, ".sdata2") == 0
2557           || strcmp (section, ".sbss") == 0
2558           || strcmp (section, ".sbss2") == 0)
2559         return true;
2560     }
2561
2562   size = int_size_in_bytes (TREE_TYPE (decl));
2563
2564   return (size > 0 && size <= microblaze_section_threshold);
2565 }
2566
2567
2568 static section *
2569 microblaze_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
2570 {
2571   switch (categorize_decl_for_section (decl, reloc))
2572     {
2573     case SECCAT_RODATA_MERGE_STR:
2574     case SECCAT_RODATA_MERGE_STR_INIT:
2575       /* MB binutils have various issues with mergeable string sections and
2576          relaxation/relocation. Currently, turning mergeable sections 
2577          into regular readonly sections.  */
2578
2579       return readonly_data_section;
2580     default:
2581       return default_elf_select_section (decl, reloc, align);
2582     }
2583 }
2584
2585 /*
2586   Encode info about sections into the RTL based on a symbol's declaration.
2587   The default definition of this hook, default_encode_section_info in 
2588   `varasm.c', sets a number of commonly-useful bits in SYMBOL_REF_FLAGS. */
2589
2590 static void
2591 microblaze_encode_section_info (tree decl, rtx rtl, int first)
2592 {
2593   default_encode_section_info (decl, rtl, first);
2594 }
2595
2596 static rtx
2597 expand_pic_symbol_ref (enum machine_mode mode ATTRIBUTE_UNUSED, rtx op)
2598 {
2599   rtx result;
2600   result = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op), UNSPEC_GOTOFF);
2601   result = gen_rtx_CONST (Pmode, result);
2602   result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
2603   result = gen_const_mem (Pmode, result);
2604   return result;
2605 }
2606
2607 bool
2608 microblaze_expand_move (enum machine_mode mode, rtx operands[])
2609 {
2610   /* If operands[1] is a constant address invalid for pic, then we need to
2611      handle it just like LEGITIMIZE_ADDRESS does.  */
2612   if (flag_pic)
2613     {
2614       if (GET_CODE (operands[0]) == MEM)
2615         {
2616           rtx addr = XEXP (operands[0], 0);
2617           if (GET_CODE (addr) == SYMBOL_REF)
2618             {
2619               rtx ptr_reg, result;
2620
2621               if (reload_in_progress)
2622                 df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2623
2624               addr = expand_pic_symbol_ref (mode, addr);
2625               ptr_reg = gen_reg_rtx (Pmode);
2626               emit_move_insn (ptr_reg, addr);
2627               result = gen_rtx_MEM (mode, ptr_reg);
2628               operands[0] = result;
2629             }
2630         }
2631       if (GET_CODE (operands[1]) == SYMBOL_REF
2632           || GET_CODE (operands[1]) == LABEL_REF)
2633         {
2634           rtx result;
2635           if (reload_in_progress)
2636             df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2637           result = expand_pic_symbol_ref (mode, operands[1]);
2638           if (GET_CODE (operands[0]) != REG)
2639             {
2640               rtx ptr_reg = gen_reg_rtx (Pmode);
2641               emit_move_insn (ptr_reg, result);
2642               emit_move_insn (operands[0], ptr_reg);
2643             }
2644           else
2645             {
2646               emit_move_insn (operands[0], result);
2647             }
2648           return true;
2649         }
2650       else if (GET_CODE (operands[1]) == MEM &&
2651                GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
2652         {
2653           rtx result;
2654           rtx ptr_reg;
2655           if (reload_in_progress)
2656             df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2657           result = expand_pic_symbol_ref (mode, XEXP (operands[1], 0));
2658
2659           ptr_reg = gen_reg_rtx (Pmode);
2660
2661           emit_move_insn (ptr_reg, result);
2662           result = gen_rtx_MEM (mode, ptr_reg);
2663           emit_move_insn (operands[0], result);
2664           return true;
2665         }
2666       else if (pic_address_needs_scratch (operands[1]))
2667         {
2668           rtx temp = force_reg (SImode, XEXP (XEXP (operands[1], 0), 0));
2669           rtx temp2 = XEXP (XEXP (operands[1], 0), 1);
2670
2671           if (reload_in_progress)
2672             df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2673           emit_move_insn (operands[0], gen_rtx_PLUS (SImode, temp, temp2));
2674           return true;
2675         }
2676     }
2677
2678   if ((reload_in_progress | reload_completed) == 0
2679       && !register_operand (operands[0], SImode)
2680       && !register_operand (operands[1], SImode)
2681       && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0))
2682     {
2683       rtx temp = force_reg (SImode, operands[1]);
2684       emit_move_insn (operands[0], temp);
2685       return true;
2686     }
2687   return false;
2688 }
2689
2690 /* Expand shift operations.  */
2691 int
2692 microblaze_expand_shift (rtx operands[])
2693 {
2694   gcc_assert ((GET_CODE (operands[2]) == CONST_INT)
2695               || (GET_CODE (operands[2]) == REG)
2696               || (GET_CODE (operands[2]) == SUBREG));
2697
2698   /* Shift by one -- generate pattern.  */
2699   if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) == 1))
2700     return 0;
2701
2702   /* Have barrel shifter and shift > 1: use it.  */
2703   if (TARGET_BARREL_SHIFT)
2704     return 0;
2705
2706   gcc_assert ((GET_CODE (operands[0]) == REG)
2707               || (GET_CODE (operands[0]) == SUBREG)
2708               || (GET_CODE (operands[1]) == REG)
2709               || (GET_CODE (operands[1]) == SUBREG));
2710
2711   /* Shift by zero -- copy regs if necessary.  */
2712   if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) == 0))
2713     {
2714       if (REGNO (operands[0]) != REGNO (operands[1]))
2715         emit_insn (gen_movsi (operands[0], operands[1]));
2716       return 1;
2717     }
2718
2719   return 0;
2720 }
2721
2722 /* Return an RTX indicating where the return address to the
2723    calling function can be found.  */
2724 rtx
2725 microblaze_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
2726 {
2727   if (count != 0)
2728     return NULL_RTX;
2729
2730   return gen_rtx_PLUS (Pmode,
2731                        get_hard_reg_initial_val (Pmode,
2732                                                  MB_ABI_SUB_RETURN_ADDR_REGNUM),
2733                        GEN_INT (8));
2734 }
2735
2736 /* Put string into .sdata2 if below threashold.  */
2737 void 
2738 microblaze_asm_output_ident (FILE *file ATTRIBUTE_UNUSED, const char *string)
2739 {
2740   int size = strlen (string) + 1;
2741   if (size <= microblaze_section_threshold)
2742     switch_to_section (sdata2_section);
2743   else
2744     switch_to_section (readonly_data_section);
2745   assemble_string (string, size);
2746 }
2747
2748 static void
2749 microblaze_elf_asm_init_sections (void)
2750 {
2751   sdata2_section
2752     = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
2753                            SDATA2_SECTION_ASM_OP);
2754 }
2755
2756 /*  Generate assembler code for constant parts of a trampoline.  */
2757
2758 static void
2759 microblaze_asm_trampoline_template (FILE *f)
2760 {
2761   fprintf (f, "\t.word\t0x03e00821\t\t# move   $1,$31\n");
2762   fprintf (f, "\t.word\t0x04110001\t\t# bgezal $0,.+8\n");
2763   fprintf (f, "\t.word\t0x00000000\t\t# nop\n");
2764   fprintf (f, "\t.word\t0x8fe30014\t\t# lw     $3,20($31)\n");
2765   fprintf (f, "\t.word\t0x8fe20018\t\t# lw     $2,24($31)\n");
2766   fprintf (f, "\t.word\t0x0060c821\t\t# move   $25,$3 (abicalls)\n");
2767   fprintf (f, "\t.word\t0x00600008\t\t# jr     $3\n");
2768   fprintf (f, "\t.word\t0x0020f821\t\t# move   $31,$1\n");
2769   /* fprintf (f, "\t.word\t0x00000000\t\t# <function address>\n");  */
2770   /* fprintf (f, "\t.word\t0x00000000\t\t# <static chain value>\n");  */
2771 }
2772
2773 /* Implement TARGET_TRAMPOLINE_INIT.  */
2774
2775 static void
2776 microblaze_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
2777 {
2778   rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2779   rtx mem;
2780
2781   emit_block_move (m_tramp, assemble_trampoline_template (),
2782                    GEN_INT (8*UNITS_PER_WORD), BLOCK_OP_NORMAL);
2783
2784   mem = adjust_address (m_tramp, SImode, 8);
2785   emit_move_insn (mem, chain_value);
2786   mem = adjust_address (m_tramp, SImode, 12);
2787   emit_move_insn (mem, fnaddr);
2788 }
2789 \f
2790 /* Emit instruction to perform compare.  
2791    cmp is (compare_op op0 op1).  */
2792 static rtx
2793 microblaze_emit_compare (enum machine_mode mode, rtx cmp, enum rtx_code *cmp_code)
2794 {
2795   rtx cmp_op0 = XEXP (cmp, 0);
2796   rtx cmp_op1 = XEXP (cmp, 1);
2797   rtx comp_reg = gen_reg_rtx (SImode);
2798   enum rtx_code code = *cmp_code;
2799   
2800   gcc_assert ((GET_CODE (cmp_op0) == REG) || (GET_CODE (cmp_op0) == SUBREG));
2801
2802   /* If comparing against zero, just test source reg.  */
2803   if (cmp_op1 == const0_rtx) 
2804     return cmp_op0;
2805
2806   if (code == EQ || code == NE)
2807     {
2808       if (TARGET_PATTERN_COMPARE && GET_CODE(cmp_op1) == REG) 
2809         {
2810           if (code == EQ) 
2811             emit_insn (gen_seq_internal_pat (comp_reg, cmp_op0, cmp_op1));
2812           else
2813             {    
2814               emit_insn (gen_sne_internal_pat (comp_reg, cmp_op0, cmp_op1));
2815               *cmp_code = EQ;
2816             }
2817         }
2818       else
2819         /* Use xor for equal/not-equal comparison.  */
2820         emit_insn (gen_xorsi3 (comp_reg, cmp_op0, cmp_op1));
2821     }
2822   else if (code == GT || code == GTU || code == LE || code == LEU)
2823     {
2824       /* MicroBlaze compare is not symmetrical.  */
2825       /* Swap argument order.  */
2826       cmp_op1 = force_reg (mode, cmp_op1);
2827       if (code == GT || code == LE) 
2828         emit_insn (gen_signed_compare (comp_reg, cmp_op0, cmp_op1));
2829       else
2830         emit_insn (gen_unsigned_compare (comp_reg, cmp_op0, cmp_op1));
2831       /* Translate test condition.  */
2832       *cmp_code = swap_condition (code);
2833     }
2834   else /* if (code == GE || code == GEU || code == LT || code == LTU) */
2835     {
2836       cmp_op1 = force_reg (mode, cmp_op1);
2837       if (code == GE || code == LT) 
2838         emit_insn (gen_signed_compare (comp_reg, cmp_op1, cmp_op0));
2839       else
2840         emit_insn (gen_unsigned_compare (comp_reg, cmp_op1, cmp_op0));
2841     }
2842
2843   return comp_reg;
2844 }
2845
2846 /* Generate conditional branch -- first, generate test condition,
2847    second, generate correct branch instruction.  */
2848
2849 void
2850 microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[])
2851 {
2852   enum rtx_code code = GET_CODE (operands[0]);
2853   rtx comp;
2854   rtx condition;
2855
2856   comp = microblaze_emit_compare (mode, operands[0], &code);
2857   condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp, const0_rtx);
2858   emit_jump_insn (gen_condjump (condition, operands[3]));
2859 }
2860
2861 void
2862 microblaze_expand_conditional_branch_sf (rtx operands[])
2863 {
2864   rtx condition;
2865   rtx cmp_op0 = XEXP (operands[0], 0);
2866   rtx cmp_op1 = XEXP (operands[0], 1);
2867   rtx comp_reg = gen_reg_rtx (SImode);
2868
2869   emit_insn (gen_cstoresf4 (comp_reg, operands[0], cmp_op0, cmp_op1));
2870   condition = gen_rtx_NE (SImode, comp_reg, const0_rtx);
2871   emit_jump_insn (gen_condjump (condition, operands[3]));
2872 }
2873
2874 /* Implement TARGET_FRAME_POINTER_REQUIRED.  */
2875
2876 static bool
2877 microblaze_frame_pointer_required (void)
2878 {
2879   /* If the function contains dynamic stack allocations, we need to
2880      use the frame pointer to access the static parts of the frame.  */
2881   if (cfun->calls_alloca)
2882     return true;
2883   return false;
2884 }
2885
2886 void
2887 microblaze_expand_divide (rtx operands[])
2888 {
2889   /* Table lookup software divides. Works for all (nr/dr) where (0 <= nr,dr <= 15).  */
2890
2891   rtx regt1 = gen_reg_rtx (SImode); 
2892   rtx reg18 = gen_rtx_REG (SImode, R_TMP);
2893   rtx regqi = gen_reg_rtx (QImode);
2894   rtx div_label = gen_label_rtx ();
2895   rtx div_end_label = gen_label_rtx ();
2896   rtx div_table_rtx = gen_rtx_SYMBOL_REF (QImode,"_divsi3_table");
2897   rtx mem_rtx;
2898   rtx ret;
2899   rtx jump, cjump, insn;
2900
2901   insn = emit_insn (gen_iorsi3 (regt1, operands[1], operands[2]));
2902   cjump = emit_jump_insn_after (gen_cbranchsi4 (
2903                                         gen_rtx_GTU (SImode, regt1, GEN_INT (15)), 
2904                                         regt1, GEN_INT (15), div_label), insn);
2905   LABEL_NUSES (div_label) = 1; 
2906   JUMP_LABEL (cjump) = div_label;
2907   emit_insn (gen_rtx_CLOBBER (SImode, reg18));
2908
2909   emit_insn (gen_ashlsi3_bshift (regt1, operands[1], GEN_INT(4)));
2910   emit_insn (gen_addsi3 (regt1, regt1, operands[2]));
2911   mem_rtx = gen_rtx_MEM (QImode,
2912                             gen_rtx_PLUS (Pmode, regt1, div_table_rtx));
2913
2914   insn = emit_insn (gen_movqi (regqi, mem_rtx)); 
2915   insn = emit_insn (gen_movsi (operands[0], gen_rtx_SUBREG (SImode, regqi, 0)));
2916   jump = emit_jump_insn_after (gen_jump (div_end_label), insn); 
2917   JUMP_LABEL (jump) = div_end_label;
2918   LABEL_NUSES (div_end_label) = 1; 
2919   emit_barrier ();
2920
2921   emit_label (div_label);
2922   ret = emit_library_call_value (gen_rtx_SYMBOL_REF (Pmode, "__divsi3"), 
2923                                        operands[0], LCT_NORMAL, 
2924                                        GET_MODE (operands[0]), 2, operands[1], 
2925                                        GET_MODE (operands[1]), operands[2], 
2926                                        GET_MODE (operands[2]));
2927   if (ret != operands[0])
2928                 emit_move_insn (operands[0], ret);    
2929
2930   emit_label (div_end_label);
2931   emit_insn (gen_blockage ());
2932 }
2933
2934 /* Implement TARGET_FUNCTION_VALUE.  */
2935 static rtx
2936 microblaze_function_value (const_tree valtype,
2937                            const_tree func ATTRIBUTE_UNUSED,
2938                            bool outgoing ATTRIBUTE_UNUSED)
2939 {
2940   return LIBCALL_VALUE (TYPE_MODE (valtype));
2941 }
2942
2943 /* Implement TARGET_SCHED_ADJUST_COST.  */
2944 static int
2945 microblaze_adjust_cost (rtx insn ATTRIBUTE_UNUSED, rtx link,
2946                         rtx dep ATTRIBUTE_UNUSED, int cost)
2947 {
2948   if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
2949     return cost;
2950   if (REG_NOTE_KIND (link) != 0)
2951     return 0;
2952   return cost;
2953 }
2954 \f
2955 #undef TARGET_ENCODE_SECTION_INFO
2956 #define TARGET_ENCODE_SECTION_INFO      microblaze_encode_section_info
2957
2958 #undef TARGET_ASM_GLOBALIZE_LABEL
2959 #define TARGET_ASM_GLOBALIZE_LABEL      microblaze_globalize_label
2960
2961 #undef TARGET_ASM_FUNCTION_PROLOGUE
2962 #define TARGET_ASM_FUNCTION_PROLOGUE    microblaze_function_prologue
2963
2964 #undef TARGET_ASM_FUNCTION_EPILOGUE
2965 #define TARGET_ASM_FUNCTION_EPILOGUE    microblaze_function_epilogue
2966
2967 #undef TARGET_RTX_COSTS
2968 #define TARGET_RTX_COSTS                microblaze_rtx_costs
2969
2970 #undef TARGET_ADDRESS_COST
2971 #define TARGET_ADDRESS_COST             microblaze_address_cost
2972
2973 #undef TARGET_ATTRIBUTE_TABLE
2974 #define TARGET_ATTRIBUTE_TABLE          microblaze_attribute_table
2975
2976 #undef TARGET_IN_SMALL_DATA_P
2977 #define TARGET_IN_SMALL_DATA_P          microblaze_elf_in_small_data_p
2978
2979 #undef TARGET_ASM_SELECT_SECTION
2980 #define TARGET_ASM_SELECT_SECTION       microblaze_select_section
2981
2982 #undef TARGET_HAVE_SRODATA_SECTION
2983 #define TARGET_HAVE_SRODATA_SECTION     true
2984
2985 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
2986 #define TARGET_ASM_FUNCTION_END_PROLOGUE \
2987                                         microblaze_function_end_prologue
2988
2989 #undef TARGET_DEFAULT_TARGET_FLAGS
2990 #define TARGET_DEFAULT_TARGET_FLAGS     TARGET_DEFAULT
2991
2992 #undef TARGET_ARG_PARTIAL_BYTES
2993 #define TARGET_ARG_PARTIAL_BYTES        function_arg_partial_bytes
2994
2995 #undef TARGET_FUNCTION_ARG
2996 #define TARGET_FUNCTION_ARG             microblaze_function_arg
2997
2998 #undef TARGET_FUNCTION_ARG_ADVANCE
2999 #define TARGET_FUNCTION_ARG_ADVANCE     microblaze_function_arg_advance
3000
3001 #undef TARGET_CAN_ELIMINATE
3002 #define TARGET_CAN_ELIMINATE            microblaze_can_eliminate
3003
3004 #undef TARGET_LEGITIMIZE_ADDRESS
3005 #define TARGET_LEGITIMIZE_ADDRESS       microblaze_legitimize_address
3006
3007 #undef TARGET_LEGITIMATE_ADDRESS_P
3008 #define TARGET_LEGITIMATE_ADDRESS_P     microblaze_legitimate_address_p 
3009
3010 #undef TARGET_FRAME_POINTER_REQUIRED
3011 #define TARGET_FRAME_POINTER_REQUIRED   microblaze_frame_pointer_required
3012
3013 #undef  TARGET_ASM_TRAMPOLINE_TEMPLATE
3014 #define TARGET_ASM_TRAMPOLINE_TEMPLATE  microblaze_asm_trampoline_template
3015
3016 #undef  TARGET_TRAMPOLINE_INIT
3017 #define TARGET_TRAMPOLINE_INIT          microblaze_trampoline_init
3018
3019 #undef  TARGET_PROMOTE_FUNCTION_MODE
3020 #define TARGET_PROMOTE_FUNCTION_MODE    default_promote_function_mode_always_promote
3021
3022 #undef TARGET_FUNCTION_VALUE
3023 #define TARGET_FUNCTION_VALUE           microblaze_function_value 
3024
3025 #undef TARGET_SECONDARY_RELOAD
3026 #define TARGET_SECONDARY_RELOAD         microblaze_secondary_reload
3027
3028 #undef TARGET_SCHED_ADJUST_COST
3029 #define TARGET_SCHED_ADJUST_COST        microblaze_adjust_cost
3030
3031 #undef TARGET_ASM_INIT_SECTIONS
3032 #define TARGET_ASM_INIT_SECTIONS        microblaze_elf_asm_init_sections
3033
3034 #undef  TARGET_OPTION_OVERRIDE
3035 #define TARGET_OPTION_OVERRIDE          microblaze_option_override 
3036
3037 #undef  TARGET_OPTION_OPTIMIZATION_TABLE
3038 #define TARGET_OPTION_OPTIMIZATION_TABLE microblaze_option_optimization_table
3039
3040 #undef TARGET_EXCEPT_UNWIND_INFO
3041 #define TARGET_EXCEPT_UNWIND_INFO  sjlj_except_unwind_info
3042
3043 struct gcc_target targetm = TARGET_INITIALIZER;
3044 \f
3045 #include "gt-microblaze.h"