OSDN Git Service

e81285c9067d363d4c7fd57c0afc628bce6fc8c4
[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 = alloca (sizeof (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       // microblaze_select_flags &= ~(MICROBLAZE_MASK_NO_UNSAFE_DELAY);
1321       microblaze_no_unsafe_delay = 0;
1322       microblaze_pipe = MICROBLAZE_PIPE_3;
1323     }
1324   else if (ver == 0
1325            || (MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v4.00.b")
1326                == 0))
1327     {
1328       // microblaze_select_flags |= (MICROBLAZE_MASK_NO_UNSAFE_DELAY);
1329       microblaze_no_unsafe_delay = 1;
1330       microblaze_pipe = MICROBLAZE_PIPE_3;
1331     }
1332   else
1333     {
1334       /* We agree to use 5 pipe-stage model even on area optimized 3 
1335          pipe-stage variants.  */
1336       // microblaze_select_flags &= ~(MICROBLAZE_MASK_NO_UNSAFE_DELAY);
1337       microblaze_no_unsafe_delay = 0;
1338       microblaze_pipe = MICROBLAZE_PIPE_5;
1339       if (MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v5.00.a") == 0
1340           || MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu,
1341                                          "v5.00.b") == 0
1342           || MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu,
1343                                          "v5.00.c") == 0)
1344         {
1345           /* Pattern compares are to be turned on by default only when 
1346              compiling for MB v5.00.'z'.  */
1347           target_flags |= MASK_PATTERN_COMPARE;
1348         }
1349     }
1350
1351   ver = MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v6.00.a");
1352   if (ver < 0)
1353     {
1354       if (TARGET_MULTIPLY_HIGH)
1355         warning (0,
1356                  "-mxl-multiply-high can be used only with -mcpu=v6.00.a or greater");
1357     }
1358
1359   if (TARGET_MULTIPLY_HIGH && TARGET_SOFT_MUL)
1360     error ("-mxl-multiply-high requires -mno-xl-soft-mul");
1361
1362   /* Always use DFA scheduler.  */
1363   microblaze_sched_use_dfa = 1;
1364
1365   // microblaze_abicalls = MICROBLAZE_ABICALLS_NO;
1366
1367   /* Initialize the high, low values for legit floating point constants.  */
1368   real_maxval (&dfhigh, 0, DFmode);
1369   real_maxval (&dflow, 1, DFmode);
1370   real_maxval (&sfhigh, 0, SFmode);
1371   real_maxval (&sflow, 1, SFmode);
1372
1373   microblaze_print_operand_punct['?'] = 1;
1374   microblaze_print_operand_punct['#'] = 1;
1375   microblaze_print_operand_punct['&'] = 1;
1376   microblaze_print_operand_punct['!'] = 1;
1377   microblaze_print_operand_punct['*'] = 1;
1378   microblaze_print_operand_punct['@'] = 1;
1379   microblaze_print_operand_punct['.'] = 1;
1380   microblaze_print_operand_punct['('] = 1;
1381   microblaze_print_operand_punct[')'] = 1;
1382   microblaze_print_operand_punct['['] = 1;
1383   microblaze_print_operand_punct[']'] = 1;
1384   microblaze_print_operand_punct['<'] = 1;
1385   microblaze_print_operand_punct['>'] = 1;
1386   microblaze_print_operand_punct['{'] = 1;
1387   microblaze_print_operand_punct['}'] = 1;
1388   microblaze_print_operand_punct['^'] = 1;
1389   microblaze_print_operand_punct['$'] = 1;
1390   microblaze_print_operand_punct['+'] = 1;
1391
1392   /* Set up array to map GCC register number to debug register number.
1393      Ignore the special purpose register numbers.  */
1394
1395   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1396     microblaze_dbx_regno[i] = -1;
1397
1398   start = GP_DBX_FIRST - GP_REG_FIRST;
1399   for (i = GP_REG_FIRST; i <= GP_REG_LAST; i++)
1400     microblaze_dbx_regno[i] = i + start;
1401
1402   /* Set up array giving whether a given register can hold a given mode.   */
1403
1404   for (mode = VOIDmode;
1405        mode != MAX_MACHINE_MODE; mode = (enum machine_mode) ((int) mode + 1))
1406     {
1407       register int size = GET_MODE_SIZE (mode);
1408
1409       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1410         {
1411           register int ok;
1412
1413           if (mode == CCmode)
1414             {
1415               ok = (ST_REG_P (regno) || GP_REG_P (regno));
1416             }
1417           else if (GP_REG_P (regno))
1418             ok = ((regno & 1) == 0 || size <= UNITS_PER_WORD);
1419           else
1420             ok = 0;
1421
1422           microblaze_hard_regno_mode_ok[(int) mode][regno] = ok;
1423         }
1424     }
1425 }
1426
1427 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE.  */
1428 static const struct default_options microblaze_option_optimization_table[] =
1429   {
1430     { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
1431     { OPT_LEVELS_NONE, 0, NULL, 0 }
1432   };
1433
1434 /* Return true if FUNC is an interrupt function as specified
1435    by the "interrupt_handler" attribute.  */
1436
1437 static int
1438 microblaze_interrupt_function_p (tree func)
1439 {
1440   tree a;
1441
1442   if (TREE_CODE (func) != FUNCTION_DECL)
1443     return 0;
1444
1445   a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
1446   return a != NULL_TREE;
1447 }
1448
1449 /* Return true if FUNC is an interrupt function which uses
1450    normal return, indicated by the "save_volatiles" attribute.  */
1451
1452 static int
1453 microblaze_save_volatiles (tree func)
1454 {
1455   tree a;
1456
1457   if (TREE_CODE (func) != FUNCTION_DECL)
1458     return 0;
1459
1460   a = lookup_attribute ("save_volatiles", DECL_ATTRIBUTES (func));
1461   return a != NULL_TREE;
1462 }
1463
1464 /* Return whether function is tagged with 'interrupt_handler'
1465    attribute.  Return true if function should use return from
1466    interrupt rather than normal function return.  */
1467 int
1468 microblaze_is_interrupt_handler (void)
1469 {
1470   return interrupt_handler;
1471 }
1472
1473 /* Determine of register must be saved/restored in call.  */
1474 static int
1475 microblaze_must_save_register (int regno)
1476 {
1477   if (pic_offset_table_rtx &&
1478       (regno == MB_ABI_PIC_ADDR_REGNUM) && df_regs_ever_live_p (regno))
1479     return 1;
1480
1481   if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
1482     return 1;
1483
1484   if (frame_pointer_needed && (regno == HARD_FRAME_POINTER_REGNUM))
1485     return 1;
1486
1487   if (!current_function_is_leaf)
1488     {
1489       if (regno == MB_ABI_SUB_RETURN_ADDR_REGNUM)
1490         return 1;
1491       if ((interrupt_handler || save_volatiles) &&
1492           (regno >= 3 && regno <= 12))
1493         return 1;
1494     }
1495
1496   if (interrupt_handler)
1497     {
1498       if (df_regs_ever_live_p (regno) 
1499           || regno == MB_ABI_MSR_SAVE_REG
1500           || regno == MB_ABI_ASM_TEMP_REGNUM
1501           || regno == MB_ABI_EXCEPTION_RETURN_ADDR_REGNUM)
1502         return 1;
1503     }
1504
1505   if (save_volatiles)
1506     {
1507       if (df_regs_ever_live_p (regno)
1508           || regno == MB_ABI_ASM_TEMP_REGNUM
1509           || regno == MB_ABI_EXCEPTION_RETURN_ADDR_REGNUM)
1510         return 1;
1511     }
1512
1513   return 0;
1514 }
1515
1516 /* Return the bytes needed to compute the frame pointer from the current
1517    stack pointer.
1518
1519    MicroBlaze stack frames look like:
1520
1521
1522
1523              Before call                        After call
1524         +-----------------------+       +-----------------------+
1525    high |                       |       |                       |
1526    mem. |  local variables,     |       |  local variables,     |
1527         |  callee saved and     |       |  callee saved and     |
1528         |  temps                |       |  temps                |
1529         +-----------------------+       +-----------------------+
1530         |  arguments for called |       |  arguments for called |
1531         |  subroutines          |       |  subroutines          |
1532         |  (optional)           |       |  (optional)           |
1533         +-----------------------+       +-----------------------+
1534         |  Link register        |       |  Link register        |
1535     SP->|                       |       |                       |
1536         +-----------------------+       +-----------------------+
1537                                         |                       |
1538                                         |  local variables,     |
1539                                         |  callee saved and     |
1540                                         |  temps                |
1541                                         +-----------------------+
1542                                         |   MSR (optional if,   |
1543                                         |   interrupt handler)  |
1544                                         +-----------------------+
1545                                         |                       |
1546                                         |  alloca allocations   |
1547                                         |                       |
1548                                         +-----------------------+
1549                                         |                       |
1550                                         |  arguments for called |
1551                                         |  subroutines          |
1552                                         |  (optional)           |
1553                                         |                       |
1554                                         +-----------------------+
1555                                         |  Link register        |
1556    low                           FP,SP->|                       |
1557    memory                               +-----------------------+
1558
1559 */
1560
1561 static HOST_WIDE_INT
1562 compute_frame_size (HOST_WIDE_INT size) 
1563 {
1564   int regno;
1565   HOST_WIDE_INT total_size;     /* # bytes that the entire frame takes up.  */
1566   HOST_WIDE_INT var_size;       /* # bytes that local variables take up.  */
1567   HOST_WIDE_INT args_size;      /* # bytes that outgoing arguments take up.  */
1568   int link_debug_size;          /* # bytes for link register.  */
1569   HOST_WIDE_INT gp_reg_size;    /* # bytes needed to store calle-saved gp regs.  */
1570   long mask;                    /* mask of saved gp registers.  */
1571
1572   interrupt_handler =
1573     microblaze_interrupt_function_p (current_function_decl);
1574   save_volatiles = microblaze_save_volatiles (current_function_decl);
1575
1576   gp_reg_size = 0;
1577   mask = 0;
1578   var_size = size;
1579   args_size = crtl->outgoing_args_size;
1580
1581   if ((args_size == 0) && cfun->calls_alloca)
1582     args_size = NUM_OF_ARGS * UNITS_PER_WORD;
1583
1584   total_size = var_size + args_size;
1585
1586   if (flag_pic == 2)
1587     /* force setting GOT.  */
1588     df_set_regs_ever_live (MB_ABI_PIC_ADDR_REGNUM, true);
1589
1590   /* Calculate space needed for gp registers.  */
1591   for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
1592     {
1593       if (microblaze_must_save_register (regno))
1594         {
1595
1596           if (regno != MB_ABI_SUB_RETURN_ADDR_REGNUM)
1597             /* Don't account for link register. It is accounted specially below.  */
1598             gp_reg_size += GET_MODE_SIZE (SImode);
1599
1600           mask |= (1L << (regno - GP_REG_FIRST));
1601         }
1602     }
1603
1604   total_size += gp_reg_size;
1605
1606   /* Add 4 bytes for MSR.  */
1607   if (interrupt_handler)
1608     total_size += 4;
1609
1610   /* No space to be allocated for link register in leaf functions with no other
1611      stack requirements.  */
1612   if (total_size == 0 && current_function_is_leaf)
1613     link_debug_size = 0;
1614   else
1615     link_debug_size = UNITS_PER_WORD;
1616
1617   total_size += link_debug_size;
1618
1619   /* Save other computed information.  */
1620   current_frame_info.total_size = total_size;
1621   current_frame_info.var_size = var_size;
1622   current_frame_info.args_size = args_size;
1623   current_frame_info.gp_reg_size = gp_reg_size;
1624   current_frame_info.mask = mask;
1625   current_frame_info.initialized = reload_completed;
1626   current_frame_info.num_gp = gp_reg_size / UNITS_PER_WORD;
1627   current_frame_info.link_debug_size = link_debug_size;
1628
1629   if (mask)
1630     /* Offset from which to callee-save GP regs.  */
1631     current_frame_info.gp_offset = (total_size - gp_reg_size);
1632   else
1633     current_frame_info.gp_offset = 0;
1634
1635   /* Ok, we're done.  */
1636   return total_size;
1637 }
1638
1639 /* Make sure that we're not trying to eliminate to the wrong hard frame
1640    pointer.  */
1641
1642 static bool
1643 microblaze_can_eliminate (const int from, const int to)
1644 {
1645   return ((from == RETURN_ADDRESS_POINTER_REGNUM && !leaf_function_p())
1646           || (to == MB_ABI_SUB_RETURN_ADDR_REGNUM && leaf_function_p())
1647           || (from != RETURN_ADDRESS_POINTER_REGNUM
1648               && (to == HARD_FRAME_POINTER_REGNUM
1649                   || (to == STACK_POINTER_REGNUM && !frame_pointer_needed))));
1650 }
1651
1652 /* Implement INITIAL_ELIMINATION_OFFSET.  FROM is either the frame
1653    pointer or argument pointer or the return address pointer.  TO is either 
1654    the stack pointer or hard frame pointer.  */
1655
1656 HOST_WIDE_INT
1657 microblaze_initial_elimination_offset (int from, int to)
1658 {
1659   HOST_WIDE_INT offset;
1660
1661   switch (from)
1662     {
1663     case FRAME_POINTER_REGNUM:
1664       offset = 0;
1665       break;
1666     case ARG_POINTER_REGNUM:
1667       if (to == STACK_POINTER_REGNUM || to == HARD_FRAME_POINTER_REGNUM)
1668         offset = compute_frame_size (get_frame_size ());
1669       else
1670         gcc_unreachable ();
1671       break;
1672     case RETURN_ADDRESS_POINTER_REGNUM:
1673       if (current_function_is_leaf)
1674         offset = 0;
1675       else
1676         offset = current_frame_info.gp_offset +
1677           ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT)));
1678       break;
1679     default:
1680       gcc_unreachable ();
1681     }
1682   return offset;
1683 }
1684
1685 /* Print operands using format code.
1686  
1687    The MicroBlaze specific codes are:
1688
1689    'X'  X is CONST_INT, prints 32 bits in hexadecimal format = "0x%08x",
1690    'x'  X is CONST_INT, prints 16 bits in hexadecimal format = "0x%04x",
1691    'F'  op is CONST_DOUBLE, print 32 bits in hex,
1692    'd'  output integer constant in decimal,
1693    'z'  if the operand is 0, use $0 instead of normal operand.
1694    'D'  print second register of double-word register operand.
1695    'L'  print low-order register of double-word register operand.
1696    'M'  print high-order register of double-word register operand.
1697    'C'  print part of opcode for a branch condition.
1698    'N'  print part of opcode for a branch condition, inverted.
1699    'S'  X is CODE_LABEL, print with prefix of "LS" (for embedded switch).
1700    'B'  print 'z' for EQ, 'n' for NE
1701    'b'  print 'n' for EQ, 'z' for NE
1702    'T'  print 'f' for EQ, 't' for NE
1703    't'  print 't' for EQ, 'f' for NE
1704    'm'  Print 1<<operand.
1705    'i'  Print 'i' if MEM operand has immediate value
1706    'o'  Print operand address+4
1707    '?'  Print 'd' if we use a branch with delay slot instead of normal branch.
1708    'h'  Print high word of const_double (int or float) value as hex
1709    'j'  Print low word of const_double (int or float) value as hex
1710    's'  Print -1 if operand is negative, 0 if positive (sign extend)
1711    '@'  Print the name of the temporary register (rMB_ABI_ASM_TEMP_REGNUM).
1712    '#'  Print nop if the delay slot of a branch is not filled. 
1713 */
1714
1715 void
1716 print_operand (FILE * file, rtx op, int letter)
1717 {
1718   register enum rtx_code code;
1719
1720   if (PRINT_OPERAND_PUNCT_VALID_P (letter))
1721     {
1722       switch (letter)
1723         {
1724         case '?':
1725           /* Conditionally add a 'd' to indicate filled delay slot.  */
1726           if (final_sequence != NULL)
1727             fputs ("d", file);
1728           break;
1729
1730         case '#':
1731           /* Conditionally add a nop in unfilled delay slot.  */
1732           if (final_sequence == NULL)
1733             fputs ("nop\t\t# Unfilled delay slot\n", file);
1734           break;
1735
1736         case '@':
1737           fputs (reg_names[GP_REG_FIRST + MB_ABI_ASM_TEMP_REGNUM], file);
1738           break;
1739
1740         default:
1741           output_operand_lossage ("unknown punctuation '%c'", letter);
1742           break;
1743         }
1744
1745       return;
1746     }
1747
1748   if (!op)
1749     {
1750       output_operand_lossage ("null pointer");
1751       return;
1752     }
1753
1754   code = GET_CODE (op);
1755
1756   if (code == SIGN_EXTEND)
1757     op = XEXP (op, 0), code = GET_CODE (op);
1758
1759   if (letter == 'C')
1760     switch (code)
1761       {
1762       case EQ:
1763         fputs ("eq", file);
1764         break;
1765       case NE:
1766         fputs ("ne", file);
1767         break;
1768       case GT:
1769       case GTU:
1770         fputs ("gt", file);
1771         break;
1772       case GE:
1773       case GEU:
1774         fputs ("ge", file);
1775         break;
1776       case LT:
1777       case LTU:
1778         fputs ("lt", file);
1779         break;
1780       case LE:
1781       case LEU:
1782         fputs ("le", file);
1783         break;
1784       default:
1785         fatal_insn ("PRINT_OPERAND, invalid insn for %%C", op);
1786       }
1787
1788   else if (letter == 'N')
1789     switch (code)
1790       {
1791       case EQ:
1792         fputs ("ne", file);
1793         break;
1794       case NE:
1795         fputs ("eq", file);
1796         break;
1797       case GT:
1798       case GTU:
1799         fputs ("le", file);
1800         break;
1801       case GE:
1802       case GEU:
1803         fputs ("lt", file);
1804         break;
1805       case LT:
1806       case LTU:
1807         fputs ("ge", file);
1808         break;
1809       case LE:
1810       case LEU:
1811         fputs ("gt", file);
1812         break;
1813       default:
1814         fatal_insn ("PRINT_OPERAND, invalid insn for %%N", op);
1815       }
1816
1817   else if (letter == 'S')
1818     {
1819       char buffer[100];
1820
1821       ASM_GENERATE_INTERNAL_LABEL (buffer, "LS", CODE_LABEL_NUMBER (op));
1822       assemble_name (file, buffer);
1823     }
1824
1825   /* Print 'i' for memory operands which have immediate values.  */
1826   else if (letter == 'i')
1827     {
1828       if (code == MEM)
1829         {
1830           struct microblaze_address_info info;
1831
1832           if (!microblaze_classify_address
1833               (&info, XEXP (op, 0), GET_MODE (op), 1))
1834             fatal_insn ("insn contains an invalid address !", op);
1835
1836           switch (info.type)
1837             {
1838             case ADDRESS_REG:
1839             case ADDRESS_CONST_INT:
1840             case ADDRESS_SYMBOLIC:
1841             case ADDRESS_GOTOFF:
1842               fputs ("i", file);
1843               break;
1844             case ADDRESS_REG_INDEX:
1845               break;
1846             case ADDRESS_INVALID:
1847             case ADDRESS_PLT:
1848               fatal_insn ("invalid address", op);
1849             }
1850         }
1851     }
1852
1853   else if (code == REG || code == SUBREG)
1854     {
1855       register int regnum;
1856
1857       if (code == REG)
1858         regnum = REGNO (op);
1859       else
1860         regnum = true_regnum (op);
1861
1862       if ((letter == 'M' && !WORDS_BIG_ENDIAN)
1863           || (letter == 'L' && WORDS_BIG_ENDIAN) || letter == 'D')
1864         regnum++;
1865
1866       fprintf (file, "%s", reg_names[regnum]);
1867     }
1868
1869   else if (code == MEM)
1870     if (letter == 'o')
1871       {
1872         rtx op4 = adjust_address (op, GET_MODE (op), 4);
1873         output_address (XEXP (op4, 0));
1874       }
1875     else
1876       output_address (XEXP (op, 0));
1877
1878   else if (letter == 'h' || letter == 'j')
1879     {
1880       long val[2];
1881       if (code == CONST_DOUBLE)
1882         {
1883           if (GET_MODE (op) == DFmode)
1884             {
1885               REAL_VALUE_TYPE value;
1886               REAL_VALUE_FROM_CONST_DOUBLE (value, op);
1887               REAL_VALUE_TO_TARGET_DOUBLE (value, val);
1888             }
1889           else
1890             {
1891               val[0] = CONST_DOUBLE_HIGH (op);
1892               val[1] = CONST_DOUBLE_LOW (op);
1893             }
1894         }
1895       else if (code == CONST_INT)
1896         {
1897           val[0] = (INTVAL (op) & 0xffffffff00000000LL) >> 32;
1898           val[1] = INTVAL (op) & 0x00000000ffffffffLL;
1899           if (val[0] == 0 && val[1] < 0)
1900             val[0] = -1;
1901             
1902         }
1903       fprintf (file, "0x%8.8lx", (letter == 'h') ? val[0] : val[1]);
1904     }
1905   else if (code == CONST_DOUBLE)
1906     {
1907       if (letter == 'F')
1908         {
1909           unsigned long value_long;
1910           REAL_VALUE_TYPE value;
1911           REAL_VALUE_FROM_CONST_DOUBLE (value, op);
1912           REAL_VALUE_TO_TARGET_SINGLE (value, value_long);
1913           fprintf (file, HOST_WIDE_INT_PRINT_HEX, value_long);
1914         }
1915       else
1916         {
1917           char s[60];
1918           real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (op), sizeof (s), 0, 1);
1919           fputs (s, file);
1920         }
1921     }
1922
1923   else if (code == UNSPEC)
1924     {
1925       print_operand_address (file, op);
1926     }
1927
1928   else if (letter == 'x' && GET_CODE (op) == CONST_INT)
1929     fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & INTVAL (op));
1930
1931   else if (letter == 'X' && GET_CODE (op) == CONST_INT)
1932     fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op));
1933
1934   else if (letter == 'd' && GET_CODE (op) == CONST_INT)
1935     fprintf (file, HOST_WIDE_INT_PRINT_DEC, (INTVAL (op)));
1936
1937   else if (letter == 'z' && GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
1938     fputs (reg_names[GP_REG_FIRST], file);
1939
1940   else if (letter == 's' && GET_CODE (op) == CONST_INT)
1941     if (INTVAL (op) < 0)
1942       fputs ("-1", file);
1943     else
1944       fputs ("0", file);
1945
1946   else if (letter == 'd' || letter == 'x' || letter == 'X' || letter == 's')
1947     output_operand_lossage ("letter %c was found & insn was not CONST_INT", letter);
1948
1949   else if (letter == 'B')
1950     fputs (code == EQ ? "z" : "n", file);
1951   else if (letter == 'b')
1952     fputs (code == EQ ? "n" : "z", file);
1953   else if (letter == 'T')
1954     fputs (code == EQ ? "f" : "t", file);
1955   else if (letter == 't')
1956     fputs (code == EQ ? "t" : "f", file);
1957
1958   else if (code == CONST && GET_CODE (XEXP (op, 0)) == REG)
1959     {
1960       print_operand (file, XEXP (op, 0), letter);
1961     }
1962   else if (letter == 'm')
1963     fprintf (file, HOST_WIDE_INT_PRINT_DEC, (1L << INTVAL (op)));
1964   else
1965     output_addr_const (file, op);
1966 }
1967
1968 /* A C compound statement to output to stdio stream STREAM the
1969    assembler syntax for an instruction operand that is a memory
1970    reference whose address is ADDR.  ADDR is an RTL expression.
1971
1972    Possible address classifications and output formats are,
1973    
1974    ADDRESS_REG                  "%0, r0"
1975
1976    ADDRESS_REG with non-zero    "%0, <addr_const>"
1977    offset       
1978
1979    ADDRESS_REG_INDEX            "rA, RB"    
1980                                 (if rA is r0, rA and rB are swapped)
1981
1982    ADDRESS_CONST_INT            "r0, <addr_const>"
1983
1984    ADDRESS_SYMBOLIC             "rBase, <addr_const>"   
1985                                 (rBase is a base register suitable for the 
1986                                  symbol's type)
1987 */
1988
1989 void
1990 print_operand_address (FILE * file, rtx addr)
1991 {
1992   struct microblaze_address_info info;
1993   enum microblaze_address_type type;
1994   if (!microblaze_classify_address (&info, addr, GET_MODE (addr), 1))
1995     fatal_insn ("insn contains an invalid address !", addr);
1996
1997   type = info.type;
1998   switch (info.type)
1999     {
2000     case ADDRESS_REG:
2001       fprintf (file, "%s,", reg_names[REGNO (info.regA)]);
2002       output_addr_const (file, info.offset);
2003       break;
2004     case ADDRESS_REG_INDEX:
2005       if (REGNO (info.regA) == 0)
2006         /* Make rB == r0 instead of rA == r0. This helps reduce read port 
2007            congestion.  */
2008         fprintf (file, "%s,%s", reg_names[REGNO (info.regB)],
2009                  reg_names[REGNO (info.regA)]);
2010       else if (REGNO (info.regB) != 0)
2011         /* This is a silly swap to help Dhrystone.  */
2012         fprintf (file, "%s,%s", reg_names[REGNO (info.regB)],
2013                  reg_names[REGNO (info.regA)]);
2014       break;
2015     case ADDRESS_CONST_INT:
2016       fprintf (file, "%s,", reg_names[REGNO (info.regA)]);
2017       output_addr_const (file, info.offset);
2018       break;
2019     case ADDRESS_SYMBOLIC:
2020     case ADDRESS_GOTOFF:
2021     case ADDRESS_PLT:
2022       if (info.regA)
2023         fprintf (file, "%s,", reg_names[REGNO (info.regA)]);
2024       output_addr_const (file, info.symbol);
2025       if (type == ADDRESS_GOTOFF)
2026         {
2027           fputs ("@GOT", file);
2028         }
2029       else if (type == ADDRESS_PLT)
2030         {
2031           fputs ("@PLT", file);
2032         }
2033       break;
2034     case ADDRESS_INVALID:
2035       fatal_insn ("invalid address", addr);
2036       break;
2037     }
2038 }
2039
2040 /* Emit either a label, .comm, or .lcomm directive, and mark that the symbol
2041    is used, so that we don't emit an .extern for it in 
2042    microblaze_asm_file_end.  */
2043
2044 void
2045 microblaze_declare_object (FILE * stream, const char *name,
2046                            const char *section, const char *fmt, int size)
2047 {
2048
2049   fputs (section, stream);      
2050   assemble_name (stream, name);
2051   fprintf (stream, fmt, size);
2052 }
2053
2054 /* Common code to emit the insns (or to write the instructions to a file)
2055    to save/restore registers.
2056
2057    Other parts of the code assume that MICROBLAZE_TEMP1_REGNUM (aka large_reg)
2058    is not modified within save_restore_insns.  */
2059
2060 #define BITSET_P(VALUE,BIT) (((VALUE) & (1L << (BIT))) != 0)
2061
2062 /* Save or restore instructions based on whether this is the prologue or 
2063    epilogue.  prologue is 1 for the prologue.  */
2064 static void
2065 save_restore_insns (int prologue)
2066 {
2067   rtx base_reg_rtx, reg_rtx, mem_rtx, /* msr_rtx, */ isr_reg_rtx =
2068     0, isr_mem_rtx = 0;
2069   rtx isr_msr_rtx = 0, insn;
2070   long mask = current_frame_info.mask;
2071   HOST_WIDE_INT base_offset, gp_offset;
2072   int regno;
2073
2074   if (frame_pointer_needed
2075       && !BITSET_P (mask, HARD_FRAME_POINTER_REGNUM - GP_REG_FIRST))
2076     gcc_unreachable ();
2077
2078   if (mask == 0)
2079     return;
2080
2081   /* Save registers starting from high to low.  The debuggers prefer at least
2082      the return register be stored at func+4, and also it allows us not to
2083      need a nop in the epilog if at least one register is reloaded in
2084      addition to return address.  */
2085
2086   /* Pick which pointer to use as a base register.  For small frames, just
2087      use the stack pointer.  Otherwise, use a temporary register.  Save 2
2088      cycles if the save area is near the end of a large frame, by reusing
2089      the constant created in the prologue/epilogue to adjust the stack
2090      frame.  */
2091
2092   gp_offset = current_frame_info.gp_offset;
2093
2094   gcc_assert (gp_offset > 0);
2095
2096   base_reg_rtx = stack_pointer_rtx;
2097   base_offset = 0;
2098
2099   /* For interrupt_handlers, need to save/restore the MSR.  */
2100   if (interrupt_handler)
2101     {
2102       isr_mem_rtx = gen_rtx_MEM (SImode,
2103                                  gen_rtx_PLUS (Pmode, base_reg_rtx,
2104                                                GEN_INT (current_frame_info.
2105                                                         gp_offset -
2106                                                         UNITS_PER_WORD)));
2107
2108       /* Do not optimize in flow analysis.  */
2109       MEM_VOLATILE_P (isr_mem_rtx) = 1;
2110       isr_reg_rtx = gen_rtx_REG (SImode, MB_ABI_MSR_SAVE_REG);
2111       isr_msr_rtx = gen_rtx_REG (SImode, ST_REG);
2112     }
2113
2114   if (interrupt_handler && !prologue)
2115     {
2116       emit_move_insn (isr_reg_rtx, isr_mem_rtx);
2117       emit_move_insn (isr_msr_rtx, isr_reg_rtx);
2118       /* Do not optimize in flow analysis.  */
2119       emit_insn (gen_rtx_USE (SImode, isr_reg_rtx));
2120       emit_insn (gen_rtx_USE (SImode, isr_msr_rtx));
2121     }
2122
2123   for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
2124     {
2125       if (BITSET_P (mask, regno - GP_REG_FIRST))
2126         {
2127           if (regno == MB_ABI_SUB_RETURN_ADDR_REGNUM)
2128             /* Don't handle here. Already handled as the first register.  */
2129             continue;
2130
2131           reg_rtx = gen_rtx_REG (SImode, regno);
2132           insn = gen_rtx_PLUS (Pmode, base_reg_rtx, GEN_INT (gp_offset));
2133           mem_rtx = gen_rtx_MEM (SImode, insn);
2134           if (interrupt_handler || save_volatiles)
2135             /* Do not optimize in flow analysis.  */
2136             MEM_VOLATILE_P (mem_rtx) = 1;
2137
2138           if (prologue)
2139             {
2140               insn = emit_move_insn (mem_rtx, reg_rtx);
2141               RTX_FRAME_RELATED_P (insn) = 1;
2142             }
2143           else
2144             {
2145               insn = emit_move_insn (reg_rtx, mem_rtx);
2146             }
2147
2148           gp_offset += GET_MODE_SIZE (SImode);
2149         }
2150     }
2151
2152   if (interrupt_handler && prologue)
2153     {
2154       emit_move_insn (isr_reg_rtx, isr_msr_rtx);
2155       emit_move_insn (isr_mem_rtx, isr_reg_rtx);
2156
2157       /* Do not optimize in flow analysis.  */
2158       emit_insn (gen_rtx_USE (SImode, isr_reg_rtx));
2159       emit_insn (gen_rtx_USE (SImode, isr_msr_rtx));
2160     }
2161
2162   /* Done saving and restoring */
2163 }
2164
2165
2166 /* Set up the stack and frame (if desired) for the function.  */
2167 static void
2168 microblaze_function_prologue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
2169 {
2170   const char *fnname;
2171   long fsiz = current_frame_info.total_size;
2172
2173   /* Get the function name the same way that toplev.c does before calling
2174      assemble_start_function.  This is needed so that the name used here
2175      exactly matches the name used in ASM_DECLARE_FUNCTION_NAME.  */
2176   fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
2177   if (!flag_inhibit_size_directive)
2178     {
2179       fputs ("\t.ent\t", file);
2180       if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname))
2181         fputs ("_interrupt_handler", file);
2182       else
2183         assemble_name (file, fnname);
2184       fputs ("\n", file);
2185       if (!interrupt_handler)
2186         ASM_OUTPUT_TYPE_DIRECTIVE (file, fnname, "function");
2187     }
2188
2189   assemble_name (file, fnname);
2190   fputs (":\n", file);
2191
2192   if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname))
2193     fputs ("_interrupt_handler:\n", file);
2194
2195   if (!flag_inhibit_size_directive)
2196     {
2197       /* .frame FRAMEREG, FRAMESIZE, RETREG.  */
2198       fprintf (file,
2199                "\t.frame\t%s,%ld,%s\t\t# vars= %ld, regs= %d, args= %d\n",
2200                (reg_names[(frame_pointer_needed)
2201                           ? HARD_FRAME_POINTER_REGNUM :
2202                           STACK_POINTER_REGNUM]), fsiz,
2203                reg_names[MB_ABI_SUB_RETURN_ADDR_REGNUM + GP_REG_FIRST],
2204                current_frame_info.var_size, current_frame_info.num_gp,
2205                crtl->outgoing_args_size);
2206       fprintf (file, "\t.mask\t0x%08lx\n", current_frame_info.mask);
2207     }
2208 }
2209
2210 /* Output extra assembler code at the end of a prologue.  */
2211 static void
2212 microblaze_function_end_prologue (FILE * file)
2213 {
2214   if (TARGET_STACK_CHECK)
2215     {
2216       fprintf (file, "\t# Stack Check Stub -- Start.\n\t");
2217       fprintf (file, "ori\tr18,r0,_stack_end\n\t");
2218       fprintf (file, "cmpu\tr18,r1,r18\n\t");
2219       fprintf (file, "bgei\tr18,_stack_overflow_exit\n\t");
2220       fprintf (file, "# Stack Check Stub -- End.\n");
2221     }
2222 }
2223
2224 /* Expand the prologue into a bunch of separate insns.  */
2225
2226 void
2227 microblaze_expand_prologue (void)
2228 {
2229   int regno;
2230   HOST_WIDE_INT fsiz;
2231   const char *arg_name = 0;
2232   tree fndecl = current_function_decl;
2233   tree fntype = TREE_TYPE (fndecl);
2234   tree fnargs = DECL_ARGUMENTS (fndecl);
2235   rtx next_arg_reg;
2236   int i;
2237   tree next_arg;
2238   tree cur_arg;
2239   CUMULATIVE_ARGS args_so_far;
2240   rtx mem_rtx, reg_rtx;
2241
2242   /* If struct value address is treated as the first argument, make it so.  */
2243   if (aggregate_value_p (DECL_RESULT (fndecl), fntype)
2244       && !cfun->returns_pcc_struct)
2245     {
2246       tree type = build_pointer_type (fntype);
2247       tree function_result_decl = build_decl (BUILTINS_LOCATION, PARM_DECL, 
2248                                               NULL_TREE, type);
2249
2250       DECL_ARG_TYPE (function_result_decl) = type;
2251       TREE_CHAIN (function_result_decl) = fnargs;
2252       fnargs = function_result_decl;
2253     }
2254
2255   /* Determine the last argument, and get its name.  */
2256
2257   INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, 0, 0);
2258   regno = GP_ARG_FIRST;
2259
2260   for (cur_arg = fnargs; cur_arg != 0; cur_arg = next_arg)
2261     {
2262       tree passed_type = DECL_ARG_TYPE (cur_arg);
2263       enum machine_mode passed_mode = TYPE_MODE (passed_type);
2264       rtx entry_parm;
2265
2266       if (TREE_ADDRESSABLE (passed_type))
2267         {
2268           passed_type = build_pointer_type (passed_type);
2269           passed_mode = Pmode;
2270         }
2271
2272       entry_parm = targetm.calls.function_arg (&args_so_far, passed_mode,
2273                                                passed_type, true);
2274
2275       if (entry_parm)
2276         {
2277           int words;
2278
2279           /* passed in a register, so will get homed automatically.  */
2280           if (GET_MODE (entry_parm) == BLKmode)
2281             words = (int_size_in_bytes (passed_type) + 3) / 4;
2282           else
2283             words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4;
2284
2285           regno = REGNO (entry_parm) + words - 1;
2286         }
2287       else
2288         {
2289           regno = GP_ARG_LAST + 1;
2290           break;
2291         }
2292
2293       targetm.calls.function_arg_advance (&args_so_far, passed_mode,
2294                                           passed_type, true);
2295
2296       next_arg = TREE_CHAIN (cur_arg);
2297       if (next_arg == 0)
2298         {
2299           if (DECL_NAME (cur_arg))
2300             arg_name = IDENTIFIER_POINTER (DECL_NAME (cur_arg));
2301
2302           break;
2303         }
2304     }
2305
2306   /* Split parallel insn into a sequence of insns.  */
2307
2308   next_arg_reg = targetm.calls.function_arg (&args_so_far, VOIDmode,
2309                                              void_type_node, true);
2310   if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL)
2311     {
2312       rtvec adjust = XVEC (next_arg_reg, 0);
2313       int num = GET_NUM_ELEM (adjust);
2314
2315       for (i = 0; i < num; i++)
2316         {
2317           rtx pattern = RTVEC_ELT (adjust, i);
2318           emit_insn (pattern);
2319         }
2320     }
2321
2322   fsiz = compute_frame_size (get_frame_size ());
2323
2324   /* If this function is a varargs function, store any registers that
2325      would normally hold arguments ($5 - $10) on the stack.  */
2326   if (((TYPE_ARG_TYPES (fntype) != 0
2327         && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2328             != void_type_node))
2329        || (arg_name != 0
2330            && ((arg_name[0] == '_'
2331                 && strcmp (arg_name, "__builtin_va_alist") == 0)
2332                || (arg_name[0] == 'v'
2333                    && strcmp (arg_name, "va_alist") == 0)))))
2334     {
2335       int offset = (regno - GP_ARG_FIRST + 1) * UNITS_PER_WORD;
2336       rtx ptr = stack_pointer_rtx;
2337
2338       /* If we are doing svr4-abi, sp has already been decremented by fsiz. */
2339       for (; regno <= GP_ARG_LAST; regno++)
2340         {
2341           if (offset != 0)
2342             ptr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
2343           emit_move_insn (gen_rtx_MEM (SImode, ptr),
2344                           gen_rtx_REG (SImode, regno));
2345
2346           offset += GET_MODE_SIZE (SImode);
2347         }
2348
2349     }
2350
2351   if (fsiz > 0)
2352     {
2353       rtx fsiz_rtx = GEN_INT (fsiz);
2354
2355       rtx insn = NULL;
2356       insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
2357                                     fsiz_rtx));
2358       if (insn)
2359         RTX_FRAME_RELATED_P (insn) = 1;
2360
2361       /* Handle SUB_RETURN_ADDR_REGNUM specially at first.  */
2362       if (!current_function_is_leaf || interrupt_handler)
2363         {
2364           mem_rtx = gen_rtx_MEM (SImode,
2365                                  gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2366                                                const0_rtx));
2367
2368           if (interrupt_handler)
2369             /* Do not optimize in flow analysis.  */
2370             MEM_VOLATILE_P (mem_rtx) = 1;
2371
2372           reg_rtx = gen_rtx_REG (SImode, MB_ABI_SUB_RETURN_ADDR_REGNUM);
2373           insn = emit_move_insn (mem_rtx, reg_rtx);
2374           RTX_FRAME_RELATED_P (insn) = 1;
2375         }
2376
2377       /* _save_ registers for prologue.  */
2378       save_restore_insns (1);
2379
2380       if (frame_pointer_needed)
2381         {
2382           rtx insn = 0;
2383
2384           insn = emit_insn (gen_movsi (hard_frame_pointer_rtx,
2385                                        stack_pointer_rtx));
2386
2387           if (insn)
2388             RTX_FRAME_RELATED_P (insn) = 1;
2389         }
2390     }
2391
2392   if (flag_pic == 2 && df_regs_ever_live_p (MB_ABI_PIC_ADDR_REGNUM))
2393     {
2394       rtx insn;
2395       SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM);
2396       insn = emit_insn (gen_set_got (pic_offset_table_rtx));    /* setting GOT.  */
2397     }
2398
2399   /* If we are profiling, make sure no instructions are scheduled before
2400      the call to mcount.  */
2401
2402   if (profile_flag)
2403     emit_insn (gen_blockage ());
2404 }
2405
2406 /* Do necessary cleanup after a function to restore stack, frame, and regs.  */
2407
2408 #define RA_MASK ((long) 0x80000000)     /* 1 << 31 */
2409 #define PIC_OFFSET_TABLE_MASK (1 << (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
2410
2411 static void
2412 microblaze_function_epilogue (FILE * file ATTRIBUTE_UNUSED,
2413                               HOST_WIDE_INT size ATTRIBUTE_UNUSED)
2414 {
2415   const char *fnname;
2416
2417   /* Get the function name the same way that toplev.c does before calling
2418      assemble_start_function.  This is needed so that the name used here
2419      exactly matches the name used in ASM_DECLARE_FUNCTION_NAME.  */
2420   fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
2421
2422   if (!flag_inhibit_size_directive)
2423     {
2424       fputs ("\t.end\t", file);
2425       if (interrupt_handler)
2426         fputs ("_interrupt_handler", file);
2427       else
2428         assemble_name (file, fnname);
2429       fputs ("\n", file);
2430     }
2431
2432   /* Reset state info for each function.  */
2433   current_frame_info = zero_frame_info;
2434
2435   /* Restore the output file if optimizing the GP (optimizing the GP causes
2436      the text to be diverted to a tempfile, so that data decls come before
2437      references to the data).  */
2438 }
2439
2440 /* Expand the epilogue into a bunch of separate insns.  */
2441
2442 void
2443 microblaze_expand_epilogue (void)
2444 {
2445   HOST_WIDE_INT fsiz = current_frame_info.total_size;
2446   rtx fsiz_rtx = GEN_INT (fsiz);
2447   rtx reg_rtx;
2448   rtx mem_rtx;
2449
2450   /* In case of interrupt handlers use addki instead of addi for changing the 
2451      stack pointer value.  */
2452
2453   if (microblaze_can_use_return_insn ())
2454     {
2455       emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode,
2456                                                         GP_REG_FIRST +
2457                                                         MB_ABI_SUB_RETURN_ADDR_REGNUM)));
2458       return;
2459     }
2460
2461   if (fsiz > 0)
2462     {
2463       /* Restore SUB_RETURN_ADDR_REGNUM at first. This is to prevent the 
2464          sequence of load-followed by a use (in rtsd) in every prologue. Saves 
2465          a load-use stall cycle  :)   This is also important to handle alloca. 
2466          (See comments for if (frame_pointer_needed) below.  */
2467
2468       if (!current_function_is_leaf || interrupt_handler)
2469         {
2470           mem_rtx =
2471             gen_rtx_MEM (SImode,
2472                          gen_rtx_PLUS (Pmode, stack_pointer_rtx, const0_rtx));
2473           if (interrupt_handler)
2474             /* Do not optimize in flow analysis.  */
2475             MEM_VOLATILE_P (mem_rtx) = 1;
2476           reg_rtx = gen_rtx_REG (SImode, MB_ABI_SUB_RETURN_ADDR_REGNUM);
2477           emit_move_insn (reg_rtx, mem_rtx);
2478         }
2479
2480       /* It is important that this is done after we restore the return address 
2481          register (above).  When alloca is used, we want to restore the 
2482          sub-routine return address only from the current stack top and not 
2483          from the frame pointer (which we restore below). (frame_pointer + 0) 
2484          might have been over-written since alloca allocates memory on the 
2485          current stack.  */
2486       if (frame_pointer_needed)
2487         emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx));
2488
2489       /* _restore_ registers for epilogue.  */
2490       save_restore_insns (0);
2491       emit_insn (gen_blockage ());
2492       emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, fsiz_rtx));
2493     }
2494
2495   emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, GP_REG_FIRST +
2496                                                     MB_ABI_SUB_RETURN_ADDR_REGNUM)));
2497 }
2498
2499
2500 /* Return nonzero if this function is known to have a null epilogue.
2501    This allows the optimizer to omit jumps to jumps if no stack
2502    was created.  */
2503
2504 int
2505 microblaze_can_use_return_insn (void)
2506 {
2507   if (!reload_completed)
2508     return 0;
2509
2510   if (df_regs_ever_live_p (MB_ABI_SUB_RETURN_ADDR_REGNUM) || profile_flag)
2511     return 0;
2512
2513   if (current_frame_info.initialized)
2514     return current_frame_info.total_size == 0;
2515
2516   return compute_frame_size (get_frame_size ()) == 0;
2517 }
2518
2519 /* Implement TARGET_SECONDARY_RELOAD.  */
2520
2521 static enum reg_class
2522 microblaze_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED, 
2523                              enum reg_class rclass, enum machine_mode mode ATTRIBUTE_UNUSED, 
2524                              secondary_reload_info *sri ATTRIBUTE_UNUSED)
2525 {
2526   if (rclass == ST_REGS)
2527     return GR_REGS;
2528
2529   return NO_REGS;
2530 }
2531
2532 static void
2533 microblaze_globalize_label (FILE * stream, const char *name)
2534 {
2535   fputs ("\t.globl\t", stream);
2536   if (interrupt_handler && strcmp (name, INTERRUPT_HANDLER_NAME))
2537     {
2538       fputs (INTERRUPT_HANDLER_NAME, stream);
2539       fputs ("\n\t.globl\t", stream);
2540     }
2541   assemble_name (stream, name);
2542   fputs ("\n", stream);
2543 }
2544
2545 /* Returns true if decl should be placed into a "small data" section.  */
2546 static bool
2547 microblaze_elf_in_small_data_p (const_tree decl)
2548 {
2549   if (!TARGET_XLGPOPT)
2550     return false;
2551
2552   /* We want to merge strings, so we never consider them small data.  */
2553   if (TREE_CODE (decl) == STRING_CST)
2554     return false;
2555
2556   /* Functions are never in the small data area.  */
2557   if (TREE_CODE (decl) == FUNCTION_DECL)
2558     return false;
2559
2560   if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl))
2561     {
2562       const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
2563       if (strcmp (section, ".sdata") == 0
2564           || strcmp (section, ".sdata2") == 0
2565           || strcmp (section, ".sbss") == 0
2566           || strcmp (section, ".sbss2") == 0)
2567         return true;
2568     }
2569
2570   HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
2571
2572   return (size > 0 && size <= microblaze_section_threshold);
2573 }
2574
2575
2576 static section *
2577 microblaze_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
2578 {
2579   switch (categorize_decl_for_section (decl, reloc))
2580     {
2581     case SECCAT_RODATA_MERGE_STR:
2582     case SECCAT_RODATA_MERGE_STR_INIT:
2583       /* MB binutils have various issues with mergeable string sections and
2584          relaxation/relocation. Currently, turning mergeable sections 
2585          into regular readonly sections.  */
2586
2587       return readonly_data_section;
2588     default:
2589       return default_elf_select_section (decl, reloc, align);
2590     }
2591 }
2592
2593 /*
2594   Encode info about sections into the RTL based on a symbol's declaration.
2595   The default definition of this hook, default_encode_section_info in 
2596   `varasm.c', sets a number of commonly-useful bits in SYMBOL_REF_FLAGS. */
2597
2598 static void
2599 microblaze_encode_section_info (tree decl, rtx rtl, int first)
2600 {
2601   default_encode_section_info (decl, rtl, first);
2602 }
2603
2604 static rtx
2605 expand_pic_symbol_ref (enum machine_mode mode ATTRIBUTE_UNUSED, rtx op)
2606 {
2607   rtx result;
2608   result = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op), UNSPEC_GOTOFF);
2609   result = gen_rtx_CONST (Pmode, result);
2610   result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
2611   result = gen_const_mem (Pmode, result);
2612   return result;
2613 }
2614
2615 bool
2616 microblaze_expand_move (enum machine_mode mode, rtx operands[])
2617 {
2618   /* If operands[1] is a constant address invalid for pic, then we need to
2619      handle it just like LEGITIMIZE_ADDRESS does.  */
2620   if (flag_pic)
2621     {
2622       if (GET_CODE (operands[0]) == MEM)
2623         {
2624           rtx addr = XEXP (operands[0], 0);
2625           if (GET_CODE (addr) == SYMBOL_REF)
2626             {
2627               if (reload_in_progress)
2628                 df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2629
2630               rtx ptr_reg, result;
2631
2632               addr = expand_pic_symbol_ref (mode, addr);
2633               ptr_reg = gen_reg_rtx (Pmode);
2634               emit_move_insn (ptr_reg, addr);
2635               result = gen_rtx_MEM (mode, ptr_reg);
2636               operands[0] = result;
2637             }
2638         }
2639       if (GET_CODE (operands[1]) == SYMBOL_REF
2640           || GET_CODE (operands[1]) == LABEL_REF)
2641         {
2642           rtx result;
2643           if (reload_in_progress)
2644             df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2645           result = expand_pic_symbol_ref (mode, operands[1]);
2646           if (GET_CODE (operands[0]) != REG)
2647             {
2648               rtx ptr_reg = gen_reg_rtx (Pmode);
2649               emit_move_insn (ptr_reg, result);
2650               emit_move_insn (operands[0], ptr_reg);
2651             }
2652           else
2653             {
2654               emit_move_insn (operands[0], result);
2655             }
2656           return true;
2657         }
2658       else if (GET_CODE (operands[1]) == MEM &&
2659                GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
2660         {
2661           rtx result;
2662           rtx ptr_reg;
2663           if (reload_in_progress)
2664             df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2665           result = expand_pic_symbol_ref (mode, XEXP (operands[1], 0));
2666
2667           ptr_reg = gen_reg_rtx (Pmode);
2668
2669           emit_move_insn (ptr_reg, result);
2670           result = gen_rtx_MEM (mode, ptr_reg);
2671           emit_move_insn (operands[0], result);
2672           return true;
2673         }
2674       else if (pic_address_needs_scratch (operands[1]))
2675         {
2676           rtx temp = force_reg (SImode, XEXP (XEXP (operands[1], 0), 0));
2677           rtx temp2 = XEXP (XEXP (operands[1], 0), 1);
2678
2679           if (reload_in_progress)
2680             df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2681           emit_move_insn (operands[0], gen_rtx_PLUS (SImode, temp, temp2));
2682           return true;
2683         }
2684     }
2685
2686   if ((reload_in_progress | reload_completed) == 0
2687       && !register_operand (operands[0], SImode)
2688       && !register_operand (operands[1], SImode)
2689       && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0))
2690     {
2691       rtx temp = force_reg (SImode, operands[1]);
2692       emit_move_insn (operands[0], temp);
2693       return true;
2694     }
2695   return false;
2696 }
2697
2698 /* Expand shift operations.  */
2699 int
2700 microblaze_expand_shift (rtx operands[])
2701 {
2702   gcc_assert ((GET_CODE (operands[2]) == CONST_INT)
2703               || (GET_CODE (operands[2]) == REG)
2704               || (GET_CODE (operands[2]) == SUBREG));
2705
2706   /* Shift by one -- generate pattern.  */
2707   if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) == 1))
2708     return 0;
2709
2710   /* Have barrel shifter and shift > 1: use it.  */
2711   if (TARGET_BARREL_SHIFT)
2712     return 0;
2713
2714   gcc_assert ((GET_CODE (operands[0]) == REG)
2715               || (GET_CODE (operands[0]) == SUBREG)
2716               || (GET_CODE (operands[1]) == REG)
2717               || (GET_CODE (operands[1]) == SUBREG));
2718
2719   /* Shift by zero -- copy regs if necessary.  */
2720   if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) == 0))
2721     {
2722       if (REGNO (operands[0]) != REGNO (operands[1]))
2723         emit_insn (gen_movsi (operands[0], operands[1]));
2724       return 1;
2725     }
2726
2727   return 0;
2728 }
2729
2730 /* Return an RTX indicating where the return address to the
2731    calling function can be found.  */
2732 rtx
2733 microblaze_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
2734 {
2735   if (count != 0)
2736     return NULL_RTX;
2737
2738   return gen_rtx_PLUS (Pmode,
2739                        get_hard_reg_initial_val (Pmode,
2740                                                  MB_ABI_SUB_RETURN_ADDR_REGNUM),
2741                        GEN_INT (8));
2742 }
2743
2744 /* Put string into .sdata2 if below threashold.  */
2745 void 
2746 microblaze_asm_output_ident (FILE *file ATTRIBUTE_UNUSED, const char *string)
2747 {
2748   int size = strlen (string) + 1;
2749   if (size <= microblaze_section_threshold)
2750     switch_to_section (sdata2_section);
2751   else
2752     switch_to_section (readonly_data_section);
2753   assemble_string (string, size);
2754 }
2755
2756 static void
2757 microblaze_elf_asm_init_sections (void)
2758 {
2759   sdata2_section
2760     = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
2761                            SDATA2_SECTION_ASM_OP);
2762 }
2763
2764 /*  Generate assembler code for constant parts of a trampoline.  */
2765
2766 static void
2767 microblaze_asm_trampoline_template (FILE *f)
2768 {
2769   fprintf (f, "\t.word\t0x03e00821\t\t# move   $1,$31\n");
2770   fprintf (f, "\t.word\t0x04110001\t\t# bgezal $0,.+8\n");
2771   fprintf (f, "\t.word\t0x00000000\t\t# nop\n");
2772   fprintf (f, "\t.word\t0x8fe30014\t\t# lw     $3,20($31)\n");
2773   fprintf (f, "\t.word\t0x8fe20018\t\t# lw     $2,24($31)\n");
2774   fprintf (f, "\t.word\t0x0060c821\t\t# move   $25,$3 (abicalls)\n");
2775   fprintf (f, "\t.word\t0x00600008\t\t# jr     $3\n");
2776   fprintf (f, "\t.word\t0x0020f821\t\t# move   $31,$1\n");
2777   /* fprintf (f, "\t.word\t0x00000000\t\t# <function address>\n");  */
2778   /* fprintf (f, "\t.word\t0x00000000\t\t# <static chain value>\n");  */
2779 }
2780
2781 /* Implement TARGET_TRAMPOLINE_INIT.  */
2782
2783 static void
2784 microblaze_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
2785 {
2786   rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2787   rtx mem;
2788
2789   emit_block_move (m_tramp, assemble_trampoline_template (),
2790                    GEN_INT (8*UNITS_PER_WORD), BLOCK_OP_NORMAL);
2791
2792   mem = adjust_address (m_tramp, SImode, 8);
2793   emit_move_insn (mem, chain_value);
2794   mem = adjust_address (m_tramp, SImode, 12);
2795   emit_move_insn (mem, fnaddr);
2796 }
2797 \f
2798 /* Emit instruction to perform compare.  
2799    cmp is (compare_op op0 op1).  */
2800 static rtx
2801 microblaze_emit_compare (enum machine_mode mode, rtx cmp, enum rtx_code *cmp_code)
2802 {
2803   rtx cmp_op0 = XEXP (cmp, 0);
2804   rtx cmp_op1 = XEXP (cmp, 1);
2805   rtx comp_reg = gen_reg_rtx (SImode);
2806   enum rtx_code code = *cmp_code;
2807   
2808   gcc_assert ((GET_CODE (cmp_op0) == REG) || (GET_CODE (cmp_op0) == SUBREG));
2809
2810   /* If comparing against zero, just test source reg.  */
2811   if (cmp_op1 == const0_rtx) 
2812     return cmp_op0;
2813
2814   if (code == EQ || code == NE)
2815     {
2816       if (TARGET_PATTERN_COMPARE && GET_CODE(cmp_op1) == REG) 
2817         {
2818           if (code == EQ) 
2819             emit_insn (gen_seq_internal_pat (comp_reg, cmp_op0, cmp_op1));
2820           else
2821             {    
2822               emit_insn (gen_sne_internal_pat (comp_reg, cmp_op0, cmp_op1));
2823               *cmp_code = EQ;
2824             }
2825         }
2826       else
2827         /* Use xor for equal/not-equal comparison.  */
2828         emit_insn (gen_xorsi3 (comp_reg, cmp_op0, cmp_op1));
2829     }
2830   else if (code == GT || code == GTU || code == LE || code == LEU)
2831     {
2832       /* MicroBlaze compare is not symmetrical.  */
2833       /* Swap argument order.  */
2834       cmp_op1 = force_reg (mode, cmp_op1);
2835       if (code == GT || code == LE) 
2836         emit_insn (gen_signed_compare (comp_reg, cmp_op0, cmp_op1));
2837       else
2838         emit_insn (gen_unsigned_compare (comp_reg, cmp_op0, cmp_op1));
2839       /* Translate test condition.  */
2840       *cmp_code = swap_condition (code);
2841     }
2842   else /* if (code == GE || code == GEU || code == LT || code == LTU) */
2843     {
2844       cmp_op1 = force_reg (mode, cmp_op1);
2845       if (code == GE || code == LT) 
2846         emit_insn (gen_signed_compare (comp_reg, cmp_op1, cmp_op0));
2847       else
2848         emit_insn (gen_unsigned_compare (comp_reg, cmp_op1, cmp_op0));
2849     }
2850
2851   return comp_reg;
2852 }
2853
2854 /* Generate conditional branch -- first, generate test condition,
2855    second, generate correct branch instruction.  */
2856
2857 void
2858 microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[])
2859 {
2860   enum rtx_code code = GET_CODE (operands[0]);
2861   rtx comp;
2862   rtx condition;
2863
2864   comp = microblaze_emit_compare (mode, operands[0], &code);
2865   condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp, const0_rtx);
2866   emit_jump_insn (gen_condjump (condition, operands[3]));
2867 }
2868
2869 void
2870 microblaze_expand_conditional_branch_sf (rtx operands[])
2871 {
2872   rtx condition;
2873   rtx cmp_op0 = XEXP (operands[0], 0);
2874   rtx cmp_op1 = XEXP (operands[0], 1);
2875   rtx comp_reg = gen_reg_rtx (SImode);
2876
2877   emit_insn (gen_cstoresf4 (comp_reg, operands[0], cmp_op0, cmp_op1));
2878   condition = gen_rtx_NE (SImode, comp_reg, const0_rtx);
2879   emit_jump_insn (gen_condjump (condition, operands[3]));
2880 }
2881
2882 /* Implement TARGET_FRAME_POINTER_REQUIRED.  */
2883
2884 static bool
2885 microblaze_frame_pointer_required (void)
2886 {
2887   /* If the function contains dynamic stack allocations, we need to
2888      use the frame pointer to access the static parts of the frame.  */
2889   if (cfun->calls_alloca)
2890     return true;
2891   return false;
2892 }
2893
2894 void
2895 microblaze_expand_divide (rtx operands[])
2896 {
2897   /* Table lookup software divides. Works for all (nr/dr) where (0 <= nr,dr <= 15).  */
2898
2899   rtx regt1 = gen_reg_rtx (SImode); 
2900   rtx reg18 = gen_rtx_REG (SImode, R_TMP);
2901   rtx regqi = gen_reg_rtx (QImode);
2902   rtx div_label = gen_label_rtx ();
2903   rtx div_end_label = gen_label_rtx ();
2904   rtx div_table_rtx = gen_rtx_SYMBOL_REF (QImode,"_divsi3_table");
2905   rtx mem_rtx;
2906   rtx ret;
2907   rtx jump, cjump, insn;
2908
2909   insn = emit_insn (gen_iorsi3 (regt1, operands[1], operands[2]));
2910   cjump = emit_jump_insn_after (gen_cbranchsi4 (
2911                                         gen_rtx_GTU (SImode, regt1, GEN_INT (15)), 
2912                                         regt1, GEN_INT (15), div_label), insn);
2913   LABEL_NUSES (div_label) = 1; 
2914   JUMP_LABEL (cjump) = div_label;
2915   emit_insn (gen_rtx_CLOBBER (SImode, reg18));
2916
2917   emit_insn (gen_ashlsi3_bshift (regt1, operands[1], GEN_INT(4)));
2918   emit_insn (gen_addsi3 (regt1, regt1, operands[2]));
2919   mem_rtx = gen_rtx_MEM (QImode,
2920                             gen_rtx_PLUS (Pmode, regt1, div_table_rtx));
2921
2922   insn = emit_insn (gen_movqi (regqi, mem_rtx)); 
2923   insn = emit_insn (gen_movsi (operands[0], gen_rtx_SUBREG (SImode, regqi, 0)));
2924   jump = emit_jump_insn_after (gen_jump (div_end_label), insn); 
2925   JUMP_LABEL (jump) = div_end_label;
2926   LABEL_NUSES (div_end_label) = 1; 
2927   emit_barrier ();
2928
2929   emit_label (div_label);
2930   ret = emit_library_call_value (gen_rtx_SYMBOL_REF (Pmode, "__divsi3"), 
2931                                        operands[0], LCT_NORMAL, 
2932                                        GET_MODE (operands[0]), 2, operands[1], 
2933                                        GET_MODE (operands[1]), operands[2], 
2934                                        GET_MODE (operands[2]));
2935   if (ret != operands[0])
2936                 emit_move_insn (operands[0], ret);    
2937
2938   emit_label (div_end_label);
2939   emit_insn (gen_blockage ());
2940 }
2941
2942 /* Implement TARGET_FUNCTION_VALUE.  */
2943 static rtx
2944 microblaze_function_value (const_tree valtype,
2945                            const_tree func ATTRIBUTE_UNUSED,
2946                            bool outgoing ATTRIBUTE_UNUSED)
2947 {
2948   return LIBCALL_VALUE (TYPE_MODE (valtype));
2949 }
2950
2951 /* Implement TARGET_SCHED_ADJUST_COST.  */
2952 static int
2953 microblaze_adjust_cost (rtx insn ATTRIBUTE_UNUSED, rtx link,
2954                         rtx dep ATTRIBUTE_UNUSED, int cost)
2955 {
2956   if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
2957     return cost;
2958   if (REG_NOTE_KIND (link) != 0)
2959     return 0;
2960   return cost;
2961 }
2962 \f
2963 #undef TARGET_ENCODE_SECTION_INFO
2964 #define TARGET_ENCODE_SECTION_INFO      microblaze_encode_section_info
2965
2966 #undef TARGET_ASM_GLOBALIZE_LABEL
2967 #define TARGET_ASM_GLOBALIZE_LABEL      microblaze_globalize_label
2968
2969 #undef TARGET_ASM_FUNCTION_PROLOGUE
2970 #define TARGET_ASM_FUNCTION_PROLOGUE    microblaze_function_prologue
2971
2972 #undef TARGET_ASM_FUNCTION_EPILOGUE
2973 #define TARGET_ASM_FUNCTION_EPILOGUE    microblaze_function_epilogue
2974
2975 #undef TARGET_RTX_COSTS
2976 #define TARGET_RTX_COSTS                microblaze_rtx_costs
2977
2978 #undef TARGET_ADDRESS_COST
2979 #define TARGET_ADDRESS_COST             microblaze_address_cost
2980
2981 #undef TARGET_ATTRIBUTE_TABLE
2982 #define TARGET_ATTRIBUTE_TABLE          microblaze_attribute_table
2983
2984 #undef TARGET_IN_SMALL_DATA_P
2985 #define TARGET_IN_SMALL_DATA_P          microblaze_elf_in_small_data_p
2986
2987 #undef TARGET_ASM_SELECT_SECTION
2988 #define TARGET_ASM_SELECT_SECTION       microblaze_select_section
2989
2990 #undef TARGET_HAVE_SRODATA_SECTION
2991 #define TARGET_HAVE_SRODATA_SECTION     true
2992
2993 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
2994 #define TARGET_ASM_FUNCTION_END_PROLOGUE \
2995                                         microblaze_function_end_prologue
2996
2997 #undef TARGET_HANDLE_OPTION
2998 #define TARGET_HANDLE_OPTION            microblaze_handle_option
2999
3000 #undef TARGET_DEFAULT_TARGET_FLAGS
3001 #define TARGET_DEFAULT_TARGET_FLAGS     TARGET_DEFAULT
3002
3003 #undef TARGET_ARG_PARTIAL_BYTES
3004 #define TARGET_ARG_PARTIAL_BYTES        function_arg_partial_bytes
3005
3006 #undef TARGET_FUNCTION_ARG
3007 #define TARGET_FUNCTION_ARG             microblaze_function_arg
3008
3009 #undef TARGET_FUNCTION_ARG_ADVANCE
3010 #define TARGET_FUNCTION_ARG_ADVANCE     microblaze_function_arg_advance
3011
3012 #undef TARGET_CAN_ELIMINATE
3013 #define TARGET_CAN_ELIMINATE            microblaze_can_eliminate
3014
3015 #undef TARGET_LEGITIMIZE_ADDRESS
3016 #define TARGET_LEGITIMIZE_ADDRESS       microblaze_legitimize_address
3017
3018 #undef TARGET_LEGITIMATE_ADDRESS_P
3019 #define TARGET_LEGITIMATE_ADDRESS_P     microblaze_legitimate_address_p 
3020
3021 #undef TARGET_FRAME_POINTER_REQUIRED
3022 #define TARGET_FRAME_POINTER_REQUIRED   microblaze_frame_pointer_required
3023
3024 #undef  TARGET_ASM_TRAMPOLINE_TEMPLATE
3025 #define TARGET_ASM_TRAMPOLINE_TEMPLATE  microblaze_asm_trampoline_template
3026
3027 #undef  TARGET_TRAMPOLINE_INIT
3028 #define TARGET_TRAMPOLINE_INIT          microblaze_trampoline_init
3029
3030 #undef  TARGET_PROMOTE_FUNCTION_MODE
3031 #define TARGET_PROMOTE_FUNCTION_MODE    default_promote_function_mode_always_promote
3032
3033 #undef TARGET_FUNCTION_VALUE
3034 #define TARGET_FUNCTION_VALUE           microblaze_function_value 
3035
3036 #undef TARGET_SECONDARY_RELOAD
3037 #define TARGET_SECONDARY_RELOAD         microblaze_secondary_reload
3038
3039 #undef TARGET_SCHED_ADJUST_COST
3040 #define TARGET_SCHED_ADJUST_COST        microblaze_adjust_cost
3041
3042 #undef TARGET_ASM_INIT_SECTIONS
3043 #define TARGET_ASM_INIT_SECTIONS        microblaze_elf_asm_init_sections
3044
3045 #undef  TARGET_OPTION_OVERRIDE
3046 #define TARGET_OPTION_OVERRIDE          microblaze_option_override 
3047
3048 #undef  TARGET_OPTION_OPTIMIZATION_TABLE
3049 #define TARGET_OPTION_OPTIMIZATION_TABLE microblaze_option_optimization_table
3050
3051 #undef TARGET_EXCEPT_UNWIND_INFO
3052 #define TARGET_EXCEPT_UNWIND_INFO  sjlj_except_unwind_info
3053
3054 struct gcc_target targetm = TARGET_INITIALIZER;
3055 \f
3056 #include "gt-microblaze.h"