]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/lm32/lm32.c
2015-06-04 Andrew MacLeod <amacleod@redhat.com>
[thirdparty/gcc.git] / gcc / config / lm32 / lm32.c
CommitLineData
f6fe91e8 1/* Subroutines used for code generation on the Lattice Mico32 architecture.
2 Contributed by Jon Beniston <jon@beniston.com>
3
d353bf18 4 Copyright (C) 2009-2015 Free Software Foundation, Inc.
f6fe91e8 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"
94ea8568 29#include "predict.h"
30#include "vec.h"
31#include "hashtab.h"
32#include "hash-set.h"
94ea8568 33#include "input.h"
34#include "function.h"
35#include "dominance.h"
36#include "cfg.h"
37#include "cfgrtl.h"
38#include "cfganal.h"
39#include "lcm.h"
40#include "cfgbuild.h"
41#include "cfgcleanup.h"
f6fe91e8 42#include "basic-block.h"
f6fe91e8 43#include "insn-config.h"
44#include "conditions.h"
45#include "insn-flags.h"
46#include "insn-attr.h"
47#include "insn-codes.h"
48#include "recog.h"
49#include "output.h"
b20a8bb4 50#include "symtab.h"
b20a8bb4 51#include "inchash.h"
f6fe91e8 52#include "tree.h"
b20a8bb4 53#include "fold-const.h"
9ed99284 54#include "calls.h"
f6fe91e8 55#include "flags.h"
d53441c8 56#include "statistics.h"
d53441c8 57#include "alias.h"
58#include "expmed.h"
59#include "dojump.h"
60#include "explow.h"
61#include "emit-rtl.h"
62#include "varasm.h"
63#include "stmt.h"
64#include "expr.h"
f6fe91e8 65#include "reload.h"
66#include "tm_p.h"
0b205f4c 67#include "diagnostic-core.h"
f6fe91e8 68#include "optabs.h"
69#include "libfuncs.h"
70#include "ggc.h"
71#include "target.h"
72#include "target-def.h"
73#include "langhooks.h"
74#include "tm-constrs.h"
75#include "df.h"
f7715905 76#include "builtins.h"
f6fe91e8 77
78struct lm32_frame_info
79{
80 HOST_WIDE_INT total_size; /* number of bytes of entire frame. */
81 HOST_WIDE_INT callee_size; /* number of bytes to save callee saves. */
82 HOST_WIDE_INT pretend_size; /* number of bytes we pretend caller did. */
83 HOST_WIDE_INT args_size; /* number of bytes for outgoing arguments. */
84 HOST_WIDE_INT locals_size; /* number of bytes for local variables. */
85 unsigned int reg_save_mask; /* mask of saved registers. */
86};
87
88/* Prototypes for static functions. */
89static rtx emit_add (rtx dest, rtx src0, rtx src1);
90static void expand_save_restore (struct lm32_frame_info *info, int op);
91static void stack_adjust (HOST_WIDE_INT amount);
92static bool lm32_in_small_data_p (const_tree);
39cba157 93static void lm32_setup_incoming_varargs (cumulative_args_t cum,
3754d046 94 machine_mode mode, tree type,
f6fe91e8 95 int *pretend_size, int no_rtl);
20d892d1 96static bool lm32_rtx_costs (rtx x, int code, int outer_code, int opno,
97 int *total, bool speed);
f6fe91e8 98static bool lm32_can_eliminate (const int, const int);
99static bool
3754d046 100lm32_legitimate_address_p (machine_mode mode, rtx x, bool strict);
f6fe91e8 101static HOST_WIDE_INT lm32_compute_frame_size (int size);
4c834714 102static void lm32_option_override (void);
39cba157 103static rtx lm32_function_arg (cumulative_args_t cum,
3754d046 104 machine_mode mode, const_tree type,
060dbf36 105 bool named);
39cba157 106static void lm32_function_arg_advance (cumulative_args_t cum,
3754d046 107 machine_mode mode,
060dbf36 108 const_tree type, bool named);
f6fe91e8 109
4c834714 110#undef TARGET_OPTION_OVERRIDE
111#define TARGET_OPTION_OVERRIDE lm32_option_override
f6fe91e8 112#undef TARGET_ADDRESS_COST
d9c5e5f4 113#define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
f6fe91e8 114#undef TARGET_RTX_COSTS
115#define TARGET_RTX_COSTS lm32_rtx_costs
116#undef TARGET_IN_SMALL_DATA_P
117#define TARGET_IN_SMALL_DATA_P lm32_in_small_data_p
118#undef TARGET_PROMOTE_FUNCTION_MODE
119#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
120#undef TARGET_SETUP_INCOMING_VARARGS
121#define TARGET_SETUP_INCOMING_VARARGS lm32_setup_incoming_varargs
060dbf36 122#undef TARGET_FUNCTION_ARG
123#define TARGET_FUNCTION_ARG lm32_function_arg
124#undef TARGET_FUNCTION_ARG_ADVANCE
125#define TARGET_FUNCTION_ARG_ADVANCE lm32_function_arg_advance
f6fe91e8 126#undef TARGET_PROMOTE_PROTOTYPES
127#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
128#undef TARGET_MIN_ANCHOR_OFFSET
129#define TARGET_MIN_ANCHOR_OFFSET -0x8000
130#undef TARGET_MAX_ANCHOR_OFFSET
131#define TARGET_MAX_ANCHOR_OFFSET 0x7fff
132#undef TARGET_CAN_ELIMINATE
133#define TARGET_CAN_ELIMINATE lm32_can_eliminate
134#undef TARGET_LEGITIMATE_ADDRESS_P
135#define TARGET_LEGITIMATE_ADDRESS_P lm32_legitimate_address_p
136
137struct gcc_target targetm = TARGET_INITIALIZER;
138
139/* Current frame information calculated by lm32_compute_frame_size. */
140static struct lm32_frame_info current_frame_info;
141
142/* Return non-zero if the given return type should be returned in memory. */
143
144int
145lm32_return_in_memory (tree type)
146{
147 HOST_WIDE_INT size;
148
149 if (!AGGREGATE_TYPE_P (type))
150 {
151 /* All simple types are returned in registers. */
152 return 0;
153 }
154
155 size = int_size_in_bytes (type);
156 if (size >= 0 && size <= UNITS_PER_WORD)
157 {
158 /* If it can fit in one register. */
159 return 0;
160 }
161
162 return 1;
163}
164
165/* Generate an emit a word sized add instruction. */
166
167static rtx
168emit_add (rtx dest, rtx src0, rtx src1)
169{
170 rtx insn;
171 insn = emit_insn (gen_addsi3 (dest, src0, src1));
172 return insn;
173}
174
175/* Generate the code to compare (and possibly branch) two integer values
176 TEST_CODE is the comparison code we are trying to emulate
177 (or implement directly)
178 RESULT is where to store the result of the comparison,
179 or null to emit a branch
180 CMP0 CMP1 are the two comparison operands
181 DESTINATION is the destination of the branch, or null to only compare
182 */
183
184static void
185gen_int_relational (enum rtx_code code,
186 rtx result,
187 rtx cmp0,
188 rtx cmp1,
189 rtx destination)
190{
3754d046 191 machine_mode mode;
f6fe91e8 192 int branch_p;
193
194 mode = GET_MODE (cmp0);
195 if (mode == VOIDmode)
196 mode = GET_MODE (cmp1);
197
198 /* Is this a branch or compare. */
199 branch_p = (destination != 0);
200
201 /* Instruction set doesn't support LE or LT, so swap operands and use
202 GE, GT. */
203 switch (code)
204 {
205 case LE:
206 case LT:
207 case LEU:
208 case LTU:
3376a2eb 209 {
210 rtx temp;
211
212 code = swap_condition (code);
213 temp = cmp0;
214 cmp0 = cmp1;
215 cmp1 = temp;
216 break;
217 }
f6fe91e8 218 default:
219 break;
220 }
221
222 if (branch_p)
223 {
3376a2eb 224 rtx insn, cond, label;
f6fe91e8 225
226 /* Operands must be in registers. */
227 if (!register_operand (cmp0, mode))
228 cmp0 = force_reg (mode, cmp0);
229 if (!register_operand (cmp1, mode))
230 cmp1 = force_reg (mode, cmp1);
231
232 /* Generate conditional branch instruction. */
3376a2eb 233 cond = gen_rtx_fmt_ee (code, mode, cmp0, cmp1);
234 label = gen_rtx_LABEL_REF (VOIDmode, destination);
d1f9b275 235 insn = gen_rtx_SET (pc_rtx, gen_rtx_IF_THEN_ELSE (VOIDmode,
236 cond, label, pc_rtx));
f6fe91e8 237 emit_jump_insn (insn);
238 }
239 else
240 {
241 /* We can't have const_ints in cmp0, other than 0. */
242 if ((GET_CODE (cmp0) == CONST_INT) && (INTVAL (cmp0) != 0))
243 cmp0 = force_reg (mode, cmp0);
244
245 /* If the comparison is against an int not in legal range
246 move it into a register. */
247 if (GET_CODE (cmp1) == CONST_INT)
248 {
249 switch (code)
250 {
251 case EQ:
252 case NE:
253 case LE:
254 case LT:
255 case GE:
256 case GT:
257 if (!satisfies_constraint_K (cmp1))
258 cmp1 = force_reg (mode, cmp1);
259 break;
260 case LEU:
261 case LTU:
262 case GEU:
263 case GTU:
264 if (!satisfies_constraint_L (cmp1))
265 cmp1 = force_reg (mode, cmp1);
266 break;
267 default:
268 gcc_unreachable ();
269 }
270 }
271
272 /* Generate compare instruction. */
273 emit_move_insn (result, gen_rtx_fmt_ee (code, mode, cmp0, cmp1));
274 }
275}
276
277/* Try performing the comparison in OPERANDS[1], whose arms are OPERANDS[2]
278 and OPERAND[3]. Store the result in OPERANDS[0]. */
279
280void
281lm32_expand_scc (rtx operands[])
282{
283 rtx target = operands[0];
284 enum rtx_code code = GET_CODE (operands[1]);
285 rtx op0 = operands[2];
286 rtx op1 = operands[3];
287
288 gen_int_relational (code, target, op0, op1, NULL_RTX);
289}
290
291/* Compare OPERANDS[1] with OPERANDS[2] using comparison code
292 CODE and jump to OPERANDS[3] if the condition holds. */
293
294void
295lm32_expand_conditional_branch (rtx operands[])
296{
297 enum rtx_code code = GET_CODE (operands[0]);
298 rtx op0 = operands[1];
299 rtx op1 = operands[2];
300 rtx destination = operands[3];
301
302 gen_int_relational (code, NULL_RTX, op0, op1, destination);
303}
304
305/* Generate and emit RTL to save or restore callee save registers. */
306static void
307expand_save_restore (struct lm32_frame_info *info, int op)
308{
309 unsigned int reg_save_mask = info->reg_save_mask;
310 int regno;
311 HOST_WIDE_INT offset;
312 rtx insn;
313
314 /* Callee saves are below locals and above outgoing arguments. */
315 offset = info->args_size + info->callee_size;
316 for (regno = 0; regno <= 31; regno++)
317 {
318 if ((reg_save_mask & (1 << regno)) != 0)
319 {
320 rtx offset_rtx;
321 rtx mem;
322
323 offset_rtx = GEN_INT (offset);
324 if (satisfies_constraint_K (offset_rtx))
325 {
326 mem = gen_rtx_MEM (word_mode,
327 gen_rtx_PLUS (Pmode,
328 stack_pointer_rtx,
329 offset_rtx));
330 }
331 else
332 {
333 /* r10 is caller saved so it can be used as a temp reg. */
334 rtx r10;
335
336 r10 = gen_rtx_REG (word_mode, 10);
337 insn = emit_move_insn (r10, offset_rtx);
338 if (op == 0)
339 RTX_FRAME_RELATED_P (insn) = 1;
340 insn = emit_add (r10, r10, stack_pointer_rtx);
341 if (op == 0)
342 RTX_FRAME_RELATED_P (insn) = 1;
343 mem = gen_rtx_MEM (word_mode, r10);
344 }
345
346 if (op == 0)
347 insn = emit_move_insn (mem, gen_rtx_REG (word_mode, regno));
348 else
349 insn = emit_move_insn (gen_rtx_REG (word_mode, regno), mem);
350
351 /* only prologue instructions which set the sp fp or save a
352 register should be marked as frame related. */
353 if (op == 0)
354 RTX_FRAME_RELATED_P (insn) = 1;
355 offset -= UNITS_PER_WORD;
356 }
357 }
358}
359
360static void
361stack_adjust (HOST_WIDE_INT amount)
362{
363 rtx insn;
364
365 if (!IN_RANGE (amount, -32776, 32768))
366 {
367 /* r10 is caller saved so it can be used as a temp reg. */
368 rtx r10;
369 r10 = gen_rtx_REG (word_mode, 10);
370 insn = emit_move_insn (r10, GEN_INT (amount));
371 if (amount < 0)
372 RTX_FRAME_RELATED_P (insn) = 1;
373 insn = emit_add (stack_pointer_rtx, stack_pointer_rtx, r10);
374 if (amount < 0)
375 RTX_FRAME_RELATED_P (insn) = 1;
376 }
377 else
378 {
379 insn = emit_add (stack_pointer_rtx,
380 stack_pointer_rtx, GEN_INT (amount));
381 if (amount < 0)
382 RTX_FRAME_RELATED_P (insn) = 1;
383 }
384}
385
386
387/* Create and emit instructions for a functions prologue. */
388void
389lm32_expand_prologue (void)
390{
391 rtx insn;
392
393 lm32_compute_frame_size (get_frame_size ());
394
395 if (current_frame_info.total_size > 0)
396 {
397 /* Add space on stack new frame. */
398 stack_adjust (-current_frame_info.total_size);
399
400 /* Save callee save registers. */
401 if (current_frame_info.reg_save_mask != 0)
402 expand_save_restore (&current_frame_info, 0);
403
404 /* Setup frame pointer if it's needed. */
405 if (frame_pointer_needed == 1)
406 {
a965af21 407 /* Move sp to fp. */
408 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
409 RTX_FRAME_RELATED_P (insn) = 1;
f6fe91e8 410
a965af21 411 /* Add offset - Don't use total_size, as that includes pretend_size,
412 which isn't part of this frame? */
413 insn = emit_add (frame_pointer_rtx,
414 frame_pointer_rtx,
415 GEN_INT (current_frame_info.args_size +
416 current_frame_info.callee_size +
417 current_frame_info.locals_size));
f6fe91e8 418 RTX_FRAME_RELATED_P (insn) = 1;
419 }
420
421 /* Prevent prologue from being scheduled into function body. */
422 emit_insn (gen_blockage ());
423 }
424}
425
426/* Create an emit instructions for a functions epilogue. */
427void
428lm32_expand_epilogue (void)
429{
430 rtx ra_rtx = gen_rtx_REG (Pmode, RA_REGNUM);
431
432 lm32_compute_frame_size (get_frame_size ());
433
434 if (current_frame_info.total_size > 0)
435 {
436 /* Prevent stack code from being reordered. */
437 emit_insn (gen_blockage ());
438
439 /* Restore callee save registers. */
440 if (current_frame_info.reg_save_mask != 0)
441 expand_save_restore (&current_frame_info, 1);
442
443 /* Deallocate stack. */
444 stack_adjust (current_frame_info.total_size);
445
446 /* Return to calling function. */
447 emit_jump_insn (gen_return_internal (ra_rtx));
448 }
449 else
450 {
451 /* Return to calling function. */
452 emit_jump_insn (gen_return_internal (ra_rtx));
453 }
454}
455
456/* Return the bytes needed to compute the frame pointer from the current
457 stack pointer. */
458static HOST_WIDE_INT
459lm32_compute_frame_size (int size)
460{
461 int regno;
462 HOST_WIDE_INT total_size, locals_size, args_size, pretend_size, callee_size;
463 unsigned int reg_save_mask;
464
465 locals_size = size;
466 args_size = crtl->outgoing_args_size;
467 pretend_size = crtl->args.pretend_args_size;
468 callee_size = 0;
469 reg_save_mask = 0;
470
471 /* Build mask that actually determines which regsiters we save
472 and calculate size required to store them in the stack. */
473 for (regno = 1; regno < SP_REGNUM; regno++)
474 {
475 if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
476 {
477 reg_save_mask |= 1 << regno;
478 callee_size += UNITS_PER_WORD;
479 }
480 }
98eea2ef 481 if (df_regs_ever_live_p (RA_REGNUM) || ! crtl->is_leaf
f6fe91e8 482 || !optimize)
483 {
484 reg_save_mask |= 1 << RA_REGNUM;
485 callee_size += UNITS_PER_WORD;
486 }
487 if (!(reg_save_mask & (1 << FP_REGNUM)) && frame_pointer_needed)
488 {
489 reg_save_mask |= 1 << FP_REGNUM;
490 callee_size += UNITS_PER_WORD;
491 }
492
493 /* Compute total frame size. */
494 total_size = pretend_size + args_size + locals_size + callee_size;
495
496 /* Align frame to appropriate boundary. */
497 total_size = (total_size + 3) & ~3;
498
499 /* Save computed information. */
500 current_frame_info.total_size = total_size;
501 current_frame_info.callee_size = callee_size;
502 current_frame_info.pretend_size = pretend_size;
503 current_frame_info.locals_size = locals_size;
504 current_frame_info.args_size = args_size;
505 current_frame_info.reg_save_mask = reg_save_mask;
506
507 return total_size;
508}
509
510void
511lm32_print_operand (FILE * file, rtx op, int letter)
512{
513 enum rtx_code code;
514
515 code = GET_CODE (op);
516
517 if (code == SIGN_EXTEND)
518 op = XEXP (op, 0), code = GET_CODE (op);
519 else if (code == REG || code == SUBREG)
520 {
521 int regnum;
522
523 if (code == REG)
524 regnum = REGNO (op);
525 else
526 regnum = true_regnum (op);
527
528 fprintf (file, "%s", reg_names[regnum]);
529 }
530 else if (code == HIGH)
531 output_addr_const (file, XEXP (op, 0));
532 else if (code == MEM)
533 output_address (XEXP (op, 0));
534 else if (letter == 'z' && GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
535 fprintf (file, "%s", reg_names[0]);
536 else if (GET_CODE (op) == CONST_DOUBLE)
537 {
538 if ((CONST_DOUBLE_LOW (op) != 0) || (CONST_DOUBLE_HIGH (op) != 0))
bf776685 539 output_operand_lossage ("only 0.0 can be loaded as an immediate");
f6fe91e8 540 else
541 fprintf (file, "0");
542 }
543 else if (code == EQ)
544 fprintf (file, "e ");
545 else if (code == NE)
546 fprintf (file, "ne ");
547 else if (code == GT)
548 fprintf (file, "g ");
549 else if (code == GTU)
550 fprintf (file, "gu ");
551 else if (code == LT)
552 fprintf (file, "l ");
553 else if (code == LTU)
554 fprintf (file, "lu ");
555 else if (code == GE)
556 fprintf (file, "ge ");
557 else if (code == GEU)
558 fprintf (file, "geu");
559 else if (code == LE)
560 fprintf (file, "le ");
561 else if (code == LEU)
562 fprintf (file, "leu");
563 else
564 output_addr_const (file, op);
565}
566
567/* A C compound statement to output to stdio stream STREAM the
568 assembler syntax for an instruction operand that is a memory
569 reference whose address is ADDR. ADDR is an RTL expression.
570
571 On some machines, the syntax for a symbolic address depends on
572 the section that the address refers to. On these machines,
573 define the macro `ENCODE_SECTION_INFO' to store the information
574 into the `symbol_ref', and then check for it here. */
575
576void
577lm32_print_operand_address (FILE * file, rtx addr)
578{
579 switch (GET_CODE (addr))
580 {
581 case REG:
582 fprintf (file, "(%s+0)", reg_names[REGNO (addr)]);
583 break;
584
585 case MEM:
586 output_address (XEXP (addr, 0));
587 break;
588
589 case PLUS:
590 {
591 rtx arg0 = XEXP (addr, 0);
592 rtx arg1 = XEXP (addr, 1);
593
594 if (GET_CODE (arg0) == REG && CONSTANT_P (arg1))
595 {
596 if (GET_CODE (arg1) == CONST_INT)
597 fprintf (file, "(%s+%ld)", reg_names[REGNO (arg0)],
598 INTVAL (arg1));
599 else
600 {
601 fprintf (file, "(%s+", reg_names[REGNO (arg0)]);
602 output_addr_const (file, arg1);
603 fprintf (file, ")");
604 }
605 }
606 else if (CONSTANT_P (arg0) && CONSTANT_P (arg1))
607 output_addr_const (file, addr);
608 else
609 fatal_insn ("bad operand", addr);
610 }
611 break;
612
613 case SYMBOL_REF:
614 if (SYMBOL_REF_SMALL_P (addr))
615 {
616 fprintf (file, "gp(");
617 output_addr_const (file, addr);
618 fprintf (file, ")");
619 }
620 else
621 fatal_insn ("can't use non gp relative absolute address", addr);
622 break;
623
624 default:
625 fatal_insn ("invalid addressing mode", addr);
626 break;
627 }
628}
629
630/* Determine where to put an argument to a function.
631 Value is zero to push the argument on the stack,
632 or a hard register in which to store the argument.
633
634 MODE is the argument's machine mode.
635 TYPE is the data type of the argument (as a tree).
636 This is null for libcalls where that information may
637 not be available.
638 CUM is a variable of type CUMULATIVE_ARGS which gives info about
639 the preceding args and about the function being called.
640 NAMED is nonzero if this argument is a named parameter
641 (otherwise it is an extra parameter matching an ellipsis). */
642
060dbf36 643static rtx
3754d046 644lm32_function_arg (cumulative_args_t cum_v, machine_mode mode,
060dbf36 645 const_tree type, bool named)
f6fe91e8 646{
39cba157 647 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
648
f6fe91e8 649 if (mode == VOIDmode)
650 /* Compute operand 2 of the call insn. */
651 return GEN_INT (0);
652
653 if (targetm.calls.must_pass_in_stack (mode, type))
654 return NULL_RTX;
655
060dbf36 656 if (!named || (*cum + LM32_NUM_REGS2 (mode, type) > LM32_NUM_ARG_REGS))
f6fe91e8 657 return NULL_RTX;
658
060dbf36 659 return gen_rtx_REG (mode, *cum + LM32_FIRST_ARG_REG);
660}
661
662static void
3754d046 663lm32_function_arg_advance (cumulative_args_t cum, machine_mode mode,
060dbf36 664 const_tree type, bool named ATTRIBUTE_UNUSED)
665{
39cba157 666 *get_cumulative_args (cum) += LM32_NUM_REGS2 (mode, type);
f6fe91e8 667}
668
669HOST_WIDE_INT
670lm32_compute_initial_elimination_offset (int from, int to)
671{
672 HOST_WIDE_INT offset = 0;
673
674 switch (from)
675 {
676 case ARG_POINTER_REGNUM:
677 switch (to)
678 {
679 case FRAME_POINTER_REGNUM:
680 offset = 0;
681 break;
682 case STACK_POINTER_REGNUM:
683 offset =
684 lm32_compute_frame_size (get_frame_size ()) -
685 current_frame_info.pretend_size;
686 break;
687 default:
688 gcc_unreachable ();
689 }
690 break;
691 default:
692 gcc_unreachable ();
693 }
694
695 return offset;
696}
697
698static void
3754d046 699lm32_setup_incoming_varargs (cumulative_args_t cum_v, machine_mode mode,
f6fe91e8 700 tree type, int *pretend_size, int no_rtl)
701{
39cba157 702 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
f6fe91e8 703 int first_anon_arg;
704 tree fntype;
f6fe91e8 705
706 fntype = TREE_TYPE (current_function_decl);
f6fe91e8 707
257d99c3 708 if (stdarg_p (fntype))
f6fe91e8 709 first_anon_arg = *cum + LM32_FIRST_ARG_REG;
710 else
711 {
712 /* this is the common case, we have been passed details setup
713 for the last named argument, we want to skip over the
714 registers, if any used in passing this named paramter in
715 order to determine which is the first registers used to pass
716 anonymous arguments. */
717 int size;
718
719 if (mode == BLKmode)
720 size = int_size_in_bytes (type);
721 else
722 size = GET_MODE_SIZE (mode);
723
724 first_anon_arg =
725 *cum + LM32_FIRST_ARG_REG +
726 ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
727 }
728
729 if ((first_anon_arg < (LM32_FIRST_ARG_REG + LM32_NUM_ARG_REGS)) && !no_rtl)
730 {
731 int first_reg_offset = first_anon_arg;
732 int size = LM32_FIRST_ARG_REG + LM32_NUM_ARG_REGS - first_anon_arg;
733 rtx regblock;
734
735 regblock = gen_rtx_MEM (BLKmode,
29c05e22 736 plus_constant (Pmode, arg_pointer_rtx,
f6fe91e8 737 FIRST_PARM_OFFSET (0)));
738 move_block_from_reg (first_reg_offset, regblock, size);
739
740 *pretend_size = size * UNITS_PER_WORD;
741 }
742}
743
744/* Override command line options. */
4c834714 745static void
746lm32_option_override (void)
f6fe91e8 747{
748 /* We must have sign-extend enabled if barrel-shift isn't. */
749 if (!TARGET_BARREL_SHIFT_ENABLED && !TARGET_SIGN_EXTEND_ENABLED)
750 target_flags |= MASK_SIGN_EXTEND_ENABLED;
751}
752
753/* Return nonzero if this function is known to have a null epilogue.
754 This allows the optimizer to omit jumps to jumps if no stack
755 was created. */
756int
757lm32_can_use_return (void)
758{
759 if (!reload_completed)
760 return 0;
761
762 if (df_regs_ever_live_p (RA_REGNUM) || crtl->profile)
763 return 0;
764
765 if (lm32_compute_frame_size (get_frame_size ()) != 0)
766 return 0;
767
768 return 1;
769}
770
771/* Support function to determine the return address of the function
772 'count' frames back up the stack. */
773rtx
774lm32_return_addr_rtx (int count, rtx frame)
775{
776 rtx r;
777 if (count == 0)
778 {
779 if (!df_regs_ever_live_p (RA_REGNUM))
780 r = gen_rtx_REG (Pmode, RA_REGNUM);
781 else
782 {
783 r = gen_rtx_MEM (Pmode,
784 gen_rtx_PLUS (Pmode, frame,
785 GEN_INT (-2 * UNITS_PER_WORD)));
786 set_mem_alias_set (r, get_frame_alias_set ());
787 }
788 }
789 else if (flag_omit_frame_pointer)
790 r = NULL_RTX;
791 else
792 {
793 r = gen_rtx_MEM (Pmode,
794 gen_rtx_PLUS (Pmode, frame,
795 GEN_INT (-2 * UNITS_PER_WORD)));
796 set_mem_alias_set (r, get_frame_alias_set ());
797 }
798 return r;
799}
800
801/* Return true if EXP should be placed in the small data section. */
802
803static bool
804lm32_in_small_data_p (const_tree exp)
805{
806 /* We want to merge strings, so we never consider them small data. */
807 if (TREE_CODE (exp) == STRING_CST)
808 return false;
809
810 /* Functions are never in the small data area. Duh. */
811 if (TREE_CODE (exp) == FUNCTION_DECL)
812 return false;
813
814 if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
815 {
738a6bda 816 const char *section = DECL_SECTION_NAME (exp);
f6fe91e8 817 if (strcmp (section, ".sdata") == 0 || strcmp (section, ".sbss") == 0)
818 return true;
819 }
820 else
821 {
822 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
823
824 /* If this is an incomplete type with size 0, then we can't put it
825 in sdata because it might be too big when completed. */
13a54dd9 826 if (size > 0 && size <= g_switch_value)
f6fe91e8 827 return true;
828 }
829
830 return false;
831}
832
833/* Emit straight-line code to move LENGTH bytes from SRC to DEST.
834 Assume that the areas do not overlap. */
835
836static void
837lm32_block_move_inline (rtx dest, rtx src, HOST_WIDE_INT length,
838 HOST_WIDE_INT alignment)
839{
840 HOST_WIDE_INT offset, delta;
841 unsigned HOST_WIDE_INT bits;
842 int i;
3754d046 843 machine_mode mode;
f6fe91e8 844 rtx *regs;
845
846 /* Work out how many bits to move at a time. */
847 switch (alignment)
848 {
849 case 1:
850 bits = 8;
851 break;
852 case 2:
853 bits = 16;
854 break;
855 default:
856 bits = 32;
857 break;
858 }
859
860 mode = mode_for_size (bits, MODE_INT, 0);
861 delta = bits / BITS_PER_UNIT;
862
863 /* Allocate a buffer for the temporary registers. */
3376a2eb 864 regs = XALLOCAVEC (rtx, length / delta);
f6fe91e8 865
866 /* Load as many BITS-sized chunks as possible. */
867 for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
868 {
869 regs[i] = gen_reg_rtx (mode);
870 emit_move_insn (regs[i], adjust_address (src, mode, offset));
871 }
872
873 /* Copy the chunks to the destination. */
874 for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
875 emit_move_insn (adjust_address (dest, mode, offset), regs[i]);
876
877 /* Mop up any left-over bytes. */
878 if (offset < length)
879 {
880 src = adjust_address (src, BLKmode, offset);
881 dest = adjust_address (dest, BLKmode, offset);
882 move_by_pieces (dest, src, length - offset,
883 MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), 0);
884 }
885}
886
887/* Expand string/block move operations.
888
889 operands[0] is the pointer to the destination.
890 operands[1] is the pointer to the source.
891 operands[2] is the number of bytes to move.
892 operands[3] is the alignment. */
893
894int
895lm32_expand_block_move (rtx * operands)
896{
897 if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) <= 32))
898 {
899 lm32_block_move_inline (operands[0], operands[1], INTVAL (operands[2]),
900 INTVAL (operands[3]));
901 return 1;
902 }
903 return 0;
904}
905
906/* Return TRUE if X references a SYMBOL_REF or LABEL_REF whose symbol
907 isn't protected by a PIC unspec. */
908int
909nonpic_symbol_mentioned_p (rtx x)
910{
911 const char *fmt;
912 int i;
913
914 if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF
915 || GET_CODE (x) == PC)
916 return 1;
917
918 /* We don't want to look into the possible MEM location of a
919 CONST_DOUBLE, since we're not going to use it, in general. */
920 if (GET_CODE (x) == CONST_DOUBLE)
921 return 0;
922
923 if (GET_CODE (x) == UNSPEC)
924 return 0;
925
926 fmt = GET_RTX_FORMAT (GET_CODE (x));
927 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
928 {
929 if (fmt[i] == 'E')
930 {
931 int j;
932
933 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
934 if (nonpic_symbol_mentioned_p (XVECEXP (x, i, j)))
935 return 1;
936 }
937 else if (fmt[i] == 'e' && nonpic_symbol_mentioned_p (XEXP (x, i)))
938 return 1;
939 }
940
941 return 0;
942}
943
944/* Compute a (partial) cost for rtx X. Return true if the complete
945 cost has been computed, and false if subexpressions should be
946 scanned. In either case, *TOTAL contains the cost result. */
947
948static bool
20d892d1 949lm32_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
950 int *total, bool speed)
f6fe91e8 951{
3754d046 952 machine_mode mode = GET_MODE (x);
f6fe91e8 953 bool small_mode;
954
955 const int arithmetic_latency = 1;
956 const int shift_latency = 1;
957 const int compare_latency = 2;
958 const int multiply_latency = 3;
959 const int load_latency = 3;
960 const int libcall_size_cost = 5;
961
962 /* Determine if we can handle the given mode size in a single instruction. */
963 small_mode = (mode == QImode) || (mode == HImode) || (mode == SImode);
964
965 switch (code)
966 {
967
968 case PLUS:
969 case MINUS:
970 case AND:
971 case IOR:
972 case XOR:
973 case NOT:
974 case NEG:
975 if (!speed)
976 *total = COSTS_N_INSNS (LM32_NUM_REGS (mode));
977 else
978 *total =
979 COSTS_N_INSNS (arithmetic_latency + (LM32_NUM_REGS (mode) - 1));
980 break;
981
982 case COMPARE:
983 if (small_mode)
984 {
985 if (!speed)
986 *total = COSTS_N_INSNS (1);
987 else
988 *total = COSTS_N_INSNS (compare_latency);
989 }
990 else
991 {
992 /* FIXME. Guessing here. */
993 *total = COSTS_N_INSNS (LM32_NUM_REGS (mode) * (2 + 3) / 2);
994 }
995 break;
996
997 case ASHIFT:
998 case ASHIFTRT:
999 case LSHIFTRT:
1000 if (TARGET_BARREL_SHIFT_ENABLED && small_mode)
1001 {
1002 if (!speed)
1003 *total = COSTS_N_INSNS (1);
1004 else
1005 *total = COSTS_N_INSNS (shift_latency);
1006 }
1007 else if (TARGET_BARREL_SHIFT_ENABLED)
1008 {
1009 /* FIXME: Guessing here. */
1010 *total = COSTS_N_INSNS (LM32_NUM_REGS (mode) * 4);
1011 }
1012 else if (small_mode && GET_CODE (XEXP (x, 1)) == CONST_INT)
1013 {
1014 *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1)));
1015 }
1016 else
1017 {
1018 /* Libcall. */
1019 if (!speed)
1020 *total = COSTS_N_INSNS (libcall_size_cost);
1021 else
1022 *total = COSTS_N_INSNS (100);
1023 }
1024 break;
1025
1026 case MULT:
1027 if (TARGET_MULTIPLY_ENABLED && small_mode)
1028 {
1029 if (!speed)
1030 *total = COSTS_N_INSNS (1);
1031 else
1032 *total = COSTS_N_INSNS (multiply_latency);
1033 }
1034 else
1035 {
1036 /* Libcall. */
1037 if (!speed)
1038 *total = COSTS_N_INSNS (libcall_size_cost);
1039 else
1040 *total = COSTS_N_INSNS (100);
1041 }
1042 break;
1043
1044 case DIV:
1045 case MOD:
1046 case UDIV:
1047 case UMOD:
1048 if (TARGET_DIVIDE_ENABLED && small_mode)
1049 {
1050 if (!speed)
1051 *total = COSTS_N_INSNS (1);
1052 else
1053 {
1054 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1055 {
1056 int cycles = 0;
1057 unsigned HOST_WIDE_INT i = INTVAL (XEXP (x, 1));
1058
1059 while (i)
1060 {
1061 i >>= 2;
1062 cycles++;
1063 }
1064 if (IN_RANGE (i, 0, 65536))
1065 *total = COSTS_N_INSNS (1 + 1 + cycles);
1066 else
1067 *total = COSTS_N_INSNS (2 + 1 + cycles);
1068 return true;
1069 }
1070 else if (GET_CODE (XEXP (x, 1)) == REG)
1071 {
1072 *total = COSTS_N_INSNS (1 + GET_MODE_SIZE (mode) / 2);
1073 return true;
1074 }
1075 else
1076 {
1077 *total = COSTS_N_INSNS (1 + GET_MODE_SIZE (mode) / 2);
1078 return false;
1079 }
1080 }
1081 }
1082 else
1083 {
1084 /* Libcall. */
1085 if (!speed)
1086 *total = COSTS_N_INSNS (libcall_size_cost);
1087 else
1088 *total = COSTS_N_INSNS (100);
1089 }
1090 break;
1091
1092 case HIGH:
1093 case LO_SUM:
1094 if (!speed)
1095 *total = COSTS_N_INSNS (1);
1096 else
1097 *total = COSTS_N_INSNS (arithmetic_latency);
1098 break;
1099
1100 case ZERO_EXTEND:
1101 if (MEM_P (XEXP (x, 0)))
1102 *total = COSTS_N_INSNS (0);
1103 else if (small_mode)
1104 {
1105 if (!speed)
1106 *total = COSTS_N_INSNS (1);
1107 else
1108 *total = COSTS_N_INSNS (arithmetic_latency);
1109 }
1110 else
1111 *total = COSTS_N_INSNS (LM32_NUM_REGS (mode) / 2);
1112 break;
1113
1114 case CONST_INT:
1115 {
1116 switch (outer_code)
1117 {
1118 case HIGH:
1119 case LO_SUM:
1120 *total = COSTS_N_INSNS (0);
1121 return true;
1122
1123 case AND:
1124 case XOR:
1125 case IOR:
1126 case ASHIFT:
1127 case ASHIFTRT:
1128 case LSHIFTRT:
1129 case ROTATE:
1130 case ROTATERT:
1131 if (satisfies_constraint_L (x))
1132 *total = COSTS_N_INSNS (0);
1133 else
1134 *total = COSTS_N_INSNS (2);
1135 return true;
1136
1137 case SET:
1138 case PLUS:
1139 case MINUS:
1140 case COMPARE:
1141 if (satisfies_constraint_K (x))
1142 *total = COSTS_N_INSNS (0);
1143 else
1144 *total = COSTS_N_INSNS (2);
1145 return true;
1146
1147 case MULT:
1148 if (TARGET_MULTIPLY_ENABLED)
1149 {
1150 if (satisfies_constraint_K (x))
1151 *total = COSTS_N_INSNS (0);
1152 else
1153 *total = COSTS_N_INSNS (2);
1154 return true;
1155 }
1156 /* Fall through. */
1157
1158 default:
1159 if (satisfies_constraint_K (x))
1160 *total = COSTS_N_INSNS (1);
1161 else
1162 *total = COSTS_N_INSNS (2);
1163 return true;
1164 }
1165 }
1166
1167 case SYMBOL_REF:
1168 case CONST:
1169 switch (outer_code)
1170 {
1171 case HIGH:
1172 case LO_SUM:
1173 *total = COSTS_N_INSNS (0);
1174 return true;
1175
1176 case MEM:
1177 case SET:
1178 if (g_switch_value)
1179 {
1180 *total = COSTS_N_INSNS (0);
1181 return true;
1182 }
1183 break;
1184 }
1185 /* Fall through. */
1186
1187 case LABEL_REF:
1188 case CONST_DOUBLE:
1189 *total = COSTS_N_INSNS (2);
1190 return true;
1191
1192 case SET:
1193 *total = COSTS_N_INSNS (1);
1194 break;
1195
1196 case MEM:
1197 if (!speed)
1198 *total = COSTS_N_INSNS (1);
1199 else
1200 *total = COSTS_N_INSNS (load_latency);
1201 break;
1202
1203 }
1204
1205 return false;
1206}
1207
1208/* Implemenent TARGET_CAN_ELIMINATE. */
1209
1210bool
1211lm32_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
1212{
1213 return (to == STACK_POINTER_REGNUM && frame_pointer_needed) ? false : true;
1214}
1215
1216/* Implement TARGET_LEGITIMATE_ADDRESS_P. */
1217
1218static bool
3754d046 1219lm32_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x, bool strict)
f6fe91e8 1220{
1221 /* (rM) */
1222 if (strict && REG_P (x) && STRICT_REG_OK_FOR_BASE_P (x))
1223 return true;
1224 if (!strict && REG_P (x) && NONSTRICT_REG_OK_FOR_BASE_P (x))
1225 return true;
1226
1227 /* (rM)+literal) */
1228 if (GET_CODE (x) == PLUS
1229 && REG_P (XEXP (x, 0))
1230 && ((strict && STRICT_REG_OK_FOR_BASE_P (XEXP (x, 0)))
1231 || (!strict && NONSTRICT_REG_OK_FOR_BASE_P (XEXP (x, 0))))
1232 && GET_CODE (XEXP (x, 1)) == CONST_INT
1233 && satisfies_constraint_K (XEXP ((x), 1)))
1234 return true;
1235
1236 /* gp(sym) */
1237 if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_SMALL_P (x))
1238 return true;
1239
1240 return false;
1241}
1242
1243/* Check a move is not memory to memory. */
1244
1245bool
3754d046 1246lm32_move_ok (machine_mode mode, rtx operands[2]) {
f6fe91e8 1247 if (memory_operand (operands[0], mode))
1248 return register_or_zero_operand (operands[1], mode);
1249 return true;
1250}