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