comparison gcc/config/h8300/h8300.c @ 55:77e2b8dfacca gcc-4.4.5

update it from 4.4.3 to 4.5.0
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Fri, 12 Feb 2010 23:39:51 +0900
parents a06113de4d67
children b7f97abdc517
comparison
equal deleted inserted replaced
52:c156f1bd5cd9 55:77e2b8dfacca
1 /* Subroutines for insn-output.c for Renesas H8/300. 1 /* Subroutines for insn-output.c for Renesas H8/300.
2 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 3 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
4 Free Software Foundation, Inc. 4 Free Software Foundation, Inc.
5 Contributed by Steve Chamberlain (sac@cygnus.com), 5 Contributed by Steve Chamberlain (sac@cygnus.com),
6 Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com). 6 Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com).
7 7
8 This file is part of GCC. 8 This file is part of GCC.
505 handlers. */ \ 505 handlers. */ \
506 || (h8300_current_function_interrupt_function_p () \ 506 || (h8300_current_function_interrupt_function_p () \
507 && call_used_regs[regno] \ 507 && call_used_regs[regno] \
508 && !current_function_is_leaf))) 508 && !current_function_is_leaf)))
509 509
510 /* We use this to wrap all emitted insns in the prologue. */
511 static rtx
512 F (rtx x)
513 {
514 RTX_FRAME_RELATED_P (x) = 1;
515 return x;
516 }
517
518 /* Mark all the subexpressions of the PARALLEL rtx PAR as
519 frame-related. Return PAR.
520
521 dwarf2out.c:dwarf2out_frame_debug_expr ignores sub-expressions of a
522 PARALLEL rtx other than the first if they do not have the
523 FRAME_RELATED flag set on them. */
524 static rtx
525 Fpa (rtx par)
526 {
527 int len = XVECLEN (par, 0);
528 int i;
529
530 for (i = 0; i < len; i++)
531 F (XVECEXP (par, 0, i));
532
533 return par;
534 }
535
510 /* Output assembly language to FILE for the operation OP with operand size 536 /* Output assembly language to FILE for the operation OP with operand size
511 SIZE to adjust the stack pointer. */ 537 SIZE to adjust the stack pointer. */
512 538
513 static void 539 static void
514 h8300_emit_stack_adjustment (int sign, HOST_WIDE_INT size) 540 h8300_emit_stack_adjustment (int sign, HOST_WIDE_INT size)
524 && size > 4 550 && size > 4
525 && !h8300_current_function_interrupt_function_p () 551 && !h8300_current_function_interrupt_function_p ()
526 && !(cfun->static_chain_decl != NULL && sign < 0)) 552 && !(cfun->static_chain_decl != NULL && sign < 0))
527 { 553 {
528 rtx r3 = gen_rtx_REG (Pmode, 3); 554 rtx r3 = gen_rtx_REG (Pmode, 3);
529 emit_insn (gen_movhi (r3, GEN_INT (sign * size))); 555 F (emit_insn (gen_movhi (r3, GEN_INT (sign * size))));
530 emit_insn (gen_addhi3 (stack_pointer_rtx, 556 F (emit_insn (gen_addhi3 (stack_pointer_rtx,
531 stack_pointer_rtx, r3)); 557 stack_pointer_rtx, r3)));
532 } 558 }
533 else 559 else
534 { 560 {
535 /* The stack adjustment made here is further optimized by the 561 /* The stack adjustment made here is further optimized by the
536 splitter. In case of H8/300, the splitter always splits the 562 splitter. In case of H8/300, the splitter always splits the
537 addition emitted here to make the adjustment 563 addition emitted here to make the adjustment interrupt-safe.
538 interrupt-safe. */ 564 FIXME: We don't always tag those, because we don't know what
565 the splitter will do. */
539 if (Pmode == HImode) 566 if (Pmode == HImode)
540 emit_insn (gen_addhi3 (stack_pointer_rtx, 567 {
541 stack_pointer_rtx, GEN_INT (sign * size))); 568 rtx x = emit_insn (gen_addhi3 (stack_pointer_rtx,
569 stack_pointer_rtx, GEN_INT (sign * size)));
570 if (size < 4)
571 F (x);
572 }
542 else 573 else
543 emit_insn (gen_addsi3 (stack_pointer_rtx, 574 F (emit_insn (gen_addsi3 (stack_pointer_rtx,
544 stack_pointer_rtx, GEN_INT (sign * size))); 575 stack_pointer_rtx, GEN_INT (sign * size))));
545 } 576 }
546 } 577 }
547 578
548 /* Round up frame size SIZE. */ 579 /* Round up frame size SIZE. */
549 580
589 x = gen_push_h8300 (reg); 620 x = gen_push_h8300 (reg);
590 else if (!TARGET_NORMAL_MODE) 621 else if (!TARGET_NORMAL_MODE)
591 x = gen_push_h8300hs_advanced (reg); 622 x = gen_push_h8300hs_advanced (reg);
592 else 623 else
593 x = gen_push_h8300hs_normal (reg); 624 x = gen_push_h8300hs_normal (reg);
594 x = emit_insn (x); 625 x = F (emit_insn (x));
595 REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, 0); 626 REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, 0);
596 } 627 }
597 628
598 /* Emit an insn to pop register RN. */ 629 /* Emit an insn to pop register RN. */
599 630
632 static void 663 static void
633 h8300_push_pop (int regno, int nregs, int pop_p, int return_p) 664 h8300_push_pop (int regno, int nregs, int pop_p, int return_p)
634 { 665 {
635 int i, j; 666 int i, j;
636 rtvec vec; 667 rtvec vec;
637 rtx sp, offset; 668 rtx sp, offset, x;
638 669
639 /* See whether we can use a simple push or pop. */ 670 /* See whether we can use a simple push or pop. */
640 if (!return_p && nregs == 1) 671 if (!return_p && nregs == 1)
641 { 672 {
642 if (pop_p) 673 if (pop_p)
683 /* Add the stack adjustment. */ 714 /* Add the stack adjustment. */
684 offset = GEN_INT ((pop_p ? nregs : -nregs) * 4); 715 offset = GEN_INT ((pop_p ? nregs : -nregs) * 4);
685 RTVEC_ELT (vec, i + j) = gen_rtx_SET (VOIDmode, sp, 716 RTVEC_ELT (vec, i + j) = gen_rtx_SET (VOIDmode, sp,
686 gen_rtx_PLUS (Pmode, sp, offset)); 717 gen_rtx_PLUS (Pmode, sp, offset));
687 718
688 emit_insn (gen_rtx_PARALLEL (VOIDmode, vec)); 719 x = gen_rtx_PARALLEL (VOIDmode, vec);
720 if (!pop_p)
721 x = Fpa (x);
722 emit_insn (x);
689 } 723 }
690 724
691 /* Return true if X has the value sp + OFFSET. */ 725 /* Return true if X has the value sp + OFFSET. */
692 726
693 static int 727 static int
818 852
819 if (frame_pointer_needed) 853 if (frame_pointer_needed)
820 { 854 {
821 /* Push fp. */ 855 /* Push fp. */
822 push (HARD_FRAME_POINTER_REGNUM); 856 push (HARD_FRAME_POINTER_REGNUM);
823 emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); 857 F (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
824 } 858 }
825 859
826 /* Push the rest of the registers in ascending order. */ 860 /* Push the rest of the registers in ascending order. */
827 saved_regs = compute_saved_regs (); 861 saved_regs = compute_saved_regs ();
828 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno += n_regs) 862 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno += n_regs)
1224 1258
1225 case CONST_DOUBLE: 1259 case CONST_DOUBLE:
1226 *total = 20; 1260 *total = 20;
1227 return true; 1261 return true;
1228 1262
1263 case COMPARE:
1264 if (XEXP (x, 1) == const0_rtx)
1265 *total = 0;
1266 return false;
1267
1229 case AND: 1268 case AND:
1230 if (!h8300_dst_operand (XEXP (x, 0), VOIDmode) 1269 if (!h8300_dst_operand (XEXP (x, 0), VOIDmode)
1231 || !h8300_src_operand (XEXP (x, 1), VOIDmode)) 1270 || !h8300_src_operand (XEXP (x, 1), VOIDmode))
1232 return false; 1271 return false;
1233 *total = COSTS_N_INSNS (h8300_and_costs (x)); 1272 *total = COSTS_N_INSNS (h8300_and_costs (x));
1816 emit_move_insn (tmp, src); 1855 emit_move_insn (tmp, src);
1817 operands[1] = tmp; 1856 operands[1] = tmp;
1818 } 1857 }
1819 } 1858 }
1820 return 0; 1859 return 0;
1860 }
1861
1862 /* Given FROM and TO register numbers, say whether this elimination is allowed.
1863 Frame pointer elimination is automatically handled.
1864
1865 For the h8300, if frame pointer elimination is being done, we would like to
1866 convert ap and rp into sp, not fp.
1867
1868 All other eliminations are valid. */
1869
1870 static bool
1871 h8300_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
1872 {
1873 return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
1821 } 1874 }
1822 1875
1823 /* Function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET). 1876 /* Function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET).
1824 Define the offset between two registers, one to be eliminated, and 1877 Define the offset between two registers, one to be eliminated, and
1825 the other its replacement, at the start of a routine. */ 1878 the other its replacement, at the start of a routine. */
3501 } 3554 }
3502 3555
3503 /* Expand a conditional branch. */ 3556 /* Expand a conditional branch. */
3504 3557
3505 void 3558 void
3506 h8300_expand_branch (enum rtx_code code, rtx label) 3559 h8300_expand_branch (rtx operands[])
3507 { 3560 {
3561 enum rtx_code code = GET_CODE (operands[0]);
3562 rtx op0 = operands[1];
3563 rtx op1 = operands[2];
3564 rtx label = operands[3];
3508 rtx tmp; 3565 rtx tmp;
3566
3567 tmp = gen_rtx_COMPARE (VOIDmode, op0, op1);
3568 emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, tmp));
3509 3569
3510 tmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx); 3570 tmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
3511 tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, 3571 tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
3512 gen_rtx_LABEL_REF (VOIDmode, label), 3572 gen_rtx_LABEL_REF (VOIDmode, label),
3513 pc_rtx); 3573 pc_rtx);
3514 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); 3574 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
3575 }
3576
3577
3578 /* Expand a conditional store. */
3579
3580 void
3581 h8300_expand_store (rtx operands[])
3582 {
3583 rtx dest = operands[0];
3584 enum rtx_code code = GET_CODE (operands[1]);
3585 rtx op0 = operands[2];
3586 rtx op1 = operands[3];
3587 rtx tmp;
3588
3589 tmp = gen_rtx_COMPARE (VOIDmode, op0, op1);
3590 emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, tmp));
3591
3592 tmp = gen_rtx_fmt_ee (code, GET_MODE (dest), cc0_rtx, const0_rtx);
3593 emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
3515 } 3594 }
3516 3595
3517 /* Shifts. 3596 /* Shifts.
3518 3597
3519 We devote a fair bit of code to getting efficient shifts since we 3598 We devote a fair bit of code to getting efficient shifts since we
5230 be referenced with 8-bit absolute memory addresses. 5309 be referenced with 8-bit absolute memory addresses.
5231 5310
5232 tiny_data: This variable lives in the tiny data area and can be 5311 tiny_data: This variable lives in the tiny data area and can be
5233 referenced with 16-bit absolute memory references. */ 5312 referenced with 16-bit absolute memory references. */
5234 5313
5235 const struct attribute_spec h8300_attribute_table[] = 5314 static const struct attribute_spec h8300_attribute_table[] =
5236 { 5315 {
5237 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ 5316 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
5238 { "interrupt_handler", 0, 0, true, false, false, h8300_handle_fndecl_attribute }, 5317 { "interrupt_handler", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
5239 { "saveall", 0, 0, true, false, false, h8300_handle_fndecl_attribute }, 5318 { "saveall", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
5240 { "OS_Task", 0, 0, true, false, false, h8300_handle_fndecl_attribute }, 5319 { "OS_Task", 0, 0, true, false, false, h8300_handle_fndecl_attribute },
5254 int flags ATTRIBUTE_UNUSED, 5333 int flags ATTRIBUTE_UNUSED,
5255 bool *no_add_attrs) 5334 bool *no_add_attrs)
5256 { 5335 {
5257 if (TREE_CODE (*node) != FUNCTION_DECL) 5336 if (TREE_CODE (*node) != FUNCTION_DECL)
5258 { 5337 {
5259 warning (OPT_Wattributes, "%qs attribute only applies to functions", 5338 warning (OPT_Wattributes, "%qE attribute only applies to functions",
5260 IDENTIFIER_POINTER (name)); 5339 name);
5261 *no_add_attrs = true; 5340 *no_add_attrs = true;
5262 } 5341 }
5263 5342
5264 return NULL_TREE; 5343 return NULL_TREE;
5265 } 5344 }
5278 { 5357 {
5279 DECL_SECTION_NAME (decl) = build_string (7, ".eight"); 5358 DECL_SECTION_NAME (decl) = build_string (7, ".eight");
5280 } 5359 }
5281 else 5360 else
5282 { 5361 {
5283 warning (OPT_Wattributes, "%qs attribute ignored", 5362 warning (OPT_Wattributes, "%qE attribute ignored",
5284 IDENTIFIER_POINTER (name)); 5363 name);
5285 *no_add_attrs = true; 5364 *no_add_attrs = true;
5286 } 5365 }
5287 5366
5288 return NULL_TREE; 5367 return NULL_TREE;
5289 } 5368 }
5302 { 5381 {
5303 DECL_SECTION_NAME (decl) = build_string (6, ".tiny"); 5382 DECL_SECTION_NAME (decl) = build_string (6, ".tiny");
5304 } 5383 }
5305 else 5384 else
5306 { 5385 {
5307 warning (OPT_Wattributes, "%qs attribute ignored", 5386 warning (OPT_Wattributes, "%qE attribute ignored",
5308 IDENTIFIER_POINTER (name)); 5387 name);
5309 *no_add_attrs = true; 5388 *no_add_attrs = true;
5310 } 5389 }
5311 5390
5312 return NULL_TREE; 5391 return NULL_TREE;
5313 } 5392 }
5653 5732
5654 /* Return nozero if X is a legitimate address. On the H8/300, a 5733 /* Return nozero if X is a legitimate address. On the H8/300, a
5655 legitimate address has the form REG, REG+CONSTANT_ADDRESS or 5734 legitimate address has the form REG, REG+CONSTANT_ADDRESS or
5656 CONSTANT_ADDRESS. */ 5735 CONSTANT_ADDRESS. */
5657 5736
5658 int 5737 static bool
5659 h8300_legitimate_address_p (enum machine_mode mode, rtx x, int strict) 5738 h8300_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
5660 { 5739 {
5661 /* The register indirect addresses like @er0 is always valid. */ 5740 /* The register indirect addresses like @er0 is always valid. */
5662 if (h8300_rtx_ok_for_base_p (x, strict)) 5741 if (h8300_rtx_ok_for_base_p (x, strict))
5663 return 1; 5742 return 1;
5664 5743
5726 { 5805 {
5727 return (TYPE_MODE (type) == BLKmode 5806 return (TYPE_MODE (type) == BLKmode
5728 || GET_MODE_SIZE (TYPE_MODE (type)) > (TARGET_H8300 ? 4 : 8)); 5807 || GET_MODE_SIZE (TYPE_MODE (type)) > (TARGET_H8300 ? 4 : 8));
5729 } 5808 }
5730 5809
5810 /* We emit the entire trampoline here. Depending on the pointer size,
5811 we use a different trampoline.
5812
5813 Pmode == HImode
5814 vvvv context
5815 1 0000 7903xxxx mov.w #0x1234,r3
5816 2 0004 5A00xxxx jmp @0x1234
5817 ^^^^ function
5818
5819 Pmode == SImode
5820 vvvvvvvv context
5821 2 0000 7A03xxxxxxxx mov.l #0x12345678,er3
5822 3 0006 5Axxxxxx jmp @0x123456
5823 ^^^^^^ function
5824 */
5825
5826 static void
5827 h8300_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
5828 {
5829 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
5830 rtx mem;
5831
5832 if (Pmode == HImode)
5833 {
5834 mem = adjust_address (m_tramp, HImode, 0);
5835 emit_move_insn (mem, GEN_INT (0x7903));
5836 mem = adjust_address (m_tramp, Pmode, 2);
5837 emit_move_insn (mem, cxt);
5838 mem = adjust_address (m_tramp, HImode, 4);
5839 emit_move_insn (mem, GEN_INT (0x5a00));
5840 mem = adjust_address (m_tramp, Pmode, 6);
5841 emit_move_insn (mem, fnaddr);
5842 }
5843 else
5844 {
5845 rtx tem;
5846
5847 mem = adjust_address (m_tramp, HImode, 0);
5848 emit_move_insn (mem, GEN_INT (0x7a03));
5849 mem = adjust_address (m_tramp, Pmode, 2);
5850 emit_move_insn (mem, cxt);
5851
5852 tem = copy_to_reg (fnaddr);
5853 emit_insn (gen_andsi3 (tem, tem, GEN_INT (0x00ffffff)));
5854 emit_insn (gen_iorsi3 (tem, tem, GEN_INT (0x5a000000)));
5855 mem = adjust_address (m_tramp, SImode, 6);
5856 emit_move_insn (mem, tem);
5857 }
5858 }
5859
5731 /* Initialize the GCC target structure. */ 5860 /* Initialize the GCC target structure. */
5732 #undef TARGET_ATTRIBUTE_TABLE 5861 #undef TARGET_ATTRIBUTE_TABLE
5733 #define TARGET_ATTRIBUTE_TABLE h8300_attribute_table 5862 #define TARGET_ATTRIBUTE_TABLE h8300_attribute_table
5734 5863
5735 #undef TARGET_ASM_ALIGNED_HI_OP 5864 #undef TARGET_ASM_ALIGNED_HI_OP
5762 #define TARGET_MACHINE_DEPENDENT_REORG h8300_reorg 5891 #define TARGET_MACHINE_DEPENDENT_REORG h8300_reorg
5763 5892
5764 #undef TARGET_HARD_REGNO_SCRATCH_OK 5893 #undef TARGET_HARD_REGNO_SCRATCH_OK
5765 #define TARGET_HARD_REGNO_SCRATCH_OK h8300_hard_regno_scratch_ok 5894 #define TARGET_HARD_REGNO_SCRATCH_OK h8300_hard_regno_scratch_ok
5766 5895
5896 #undef TARGET_LEGITIMATE_ADDRESS_P
5897 #define TARGET_LEGITIMATE_ADDRESS_P h8300_legitimate_address_p
5898
5767 #undef TARGET_DEFAULT_TARGET_FLAGS 5899 #undef TARGET_DEFAULT_TARGET_FLAGS
5768 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT 5900 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
5769 5901
5902 #undef TARGET_CAN_ELIMINATE
5903 #define TARGET_CAN_ELIMINATE h8300_can_eliminate
5904
5905 #undef TARGET_TRAMPOLINE_INIT
5906 #define TARGET_TRAMPOLINE_INIT h8300_trampoline_init
5907
5770 struct gcc_target targetm = TARGET_INITIALIZER; 5908 struct gcc_target targetm = TARGET_INITIALIZER;