OSDN Git Service

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