Mercurial > hg > CbC > CbC_gcc
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; |