Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/h8300/h8300.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
comparison
equal
deleted
inserted
replaced
56:3c8a44c06a95 | 63:b7f97abdc517 |
---|---|
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, 2009 | 3 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 |
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. |
27 #include "tm.h" | 27 #include "tm.h" |
28 #include "rtl.h" | 28 #include "rtl.h" |
29 #include "tree.h" | 29 #include "tree.h" |
30 #include "regs.h" | 30 #include "regs.h" |
31 #include "hard-reg-set.h" | 31 #include "hard-reg-set.h" |
32 #include "real.h" | |
33 #include "insn-config.h" | 32 #include "insn-config.h" |
34 #include "conditions.h" | 33 #include "conditions.h" |
35 #include "output.h" | 34 #include "output.h" |
36 #include "insn-attr.h" | 35 #include "insn-attr.h" |
37 #include "flags.h" | 36 #include "flags.h" |
81 static const char *byte_reg (rtx, int); | 80 static const char *byte_reg (rtx, int); |
82 static int h8300_interrupt_function_p (tree); | 81 static int h8300_interrupt_function_p (tree); |
83 static int h8300_saveall_function_p (tree); | 82 static int h8300_saveall_function_p (tree); |
84 static int h8300_monitor_function_p (tree); | 83 static int h8300_monitor_function_p (tree); |
85 static int h8300_os_task_function_p (tree); | 84 static int h8300_os_task_function_p (tree); |
86 static void h8300_emit_stack_adjustment (int, HOST_WIDE_INT); | 85 static void h8300_emit_stack_adjustment (int, HOST_WIDE_INT, bool); |
87 static HOST_WIDE_INT round_frame_size (HOST_WIDE_INT); | 86 static HOST_WIDE_INT round_frame_size (HOST_WIDE_INT); |
88 static unsigned int compute_saved_regs (void); | 87 static unsigned int compute_saved_regs (void); |
89 static void push (int); | 88 static void push (int); |
90 static void pop (int); | 89 static void pop (int); |
91 static const char *cond_string (enum rtx_code); | 90 static const char *cond_string (enum rtx_code); |
96 #ifndef OBJECT_FORMAT_ELF | 95 #ifndef OBJECT_FORMAT_ELF |
97 static void h8300_asm_named_section (const char *, unsigned int, tree); | 96 static void h8300_asm_named_section (const char *, unsigned int, tree); |
98 #endif | 97 #endif |
99 static int h8300_and_costs (rtx); | 98 static int h8300_and_costs (rtx); |
100 static int h8300_shift_costs (rtx); | 99 static int h8300_shift_costs (rtx); |
101 static void h8300_push_pop (int, int, int, int); | 100 static void h8300_push_pop (int, int, bool, bool); |
102 static int h8300_stack_offset_p (rtx, int); | 101 static int h8300_stack_offset_p (rtx, int); |
103 static int h8300_ldm_stm_regno (rtx, int, int, int); | 102 static int h8300_ldm_stm_regno (rtx, int, int, int); |
104 static void h8300_reorg (void); | 103 static void h8300_reorg (void); |
105 static unsigned int h8300_constant_length (rtx); | 104 static unsigned int h8300_constant_length (rtx); |
106 static unsigned int h8300_displacement_length (rtx, int); | 105 static unsigned int h8300_displacement_length (rtx, int); |
507 && call_used_regs[regno] \ | 506 && call_used_regs[regno] \ |
508 && !current_function_is_leaf))) | 507 && !current_function_is_leaf))) |
509 | 508 |
510 /* We use this to wrap all emitted insns in the prologue. */ | 509 /* We use this to wrap all emitted insns in the prologue. */ |
511 static rtx | 510 static rtx |
512 F (rtx x) | 511 F (rtx x, bool set_it) |
513 { | 512 { |
514 RTX_FRAME_RELATED_P (x) = 1; | 513 if (set_it) |
514 RTX_FRAME_RELATED_P (x) = 1; | |
515 return x; | 515 return x; |
516 } | 516 } |
517 | 517 |
518 /* Mark all the subexpressions of the PARALLEL rtx PAR as | 518 /* Mark all the subexpressions of the PARALLEL rtx PAR as |
519 frame-related. Return PAR. | 519 frame-related. Return PAR. |
526 { | 526 { |
527 int len = XVECLEN (par, 0); | 527 int len = XVECLEN (par, 0); |
528 int i; | 528 int i; |
529 | 529 |
530 for (i = 0; i < len; i++) | 530 for (i = 0; i < len; i++) |
531 F (XVECEXP (par, 0, i)); | 531 F (XVECEXP (par, 0, i), true); |
532 | 532 |
533 return par; | 533 return par; |
534 } | 534 } |
535 | 535 |
536 /* 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 |
537 SIZE to adjust the stack pointer. */ | 537 SIZE to adjust the stack pointer. */ |
538 | 538 |
539 static void | 539 static void |
540 h8300_emit_stack_adjustment (int sign, HOST_WIDE_INT size) | 540 h8300_emit_stack_adjustment (int sign, HOST_WIDE_INT size, bool in_prologue) |
541 { | 541 { |
542 /* If the frame size is 0, we don't have anything to do. */ | 542 /* If the frame size is 0, we don't have anything to do. */ |
543 if (size == 0) | 543 if (size == 0) |
544 return; | 544 return; |
545 | 545 |
550 && size > 4 | 550 && size > 4 |
551 && !h8300_current_function_interrupt_function_p () | 551 && !h8300_current_function_interrupt_function_p () |
552 && !(cfun->static_chain_decl != NULL && sign < 0)) | 552 && !(cfun->static_chain_decl != NULL && sign < 0)) |
553 { | 553 { |
554 rtx r3 = gen_rtx_REG (Pmode, 3); | 554 rtx r3 = gen_rtx_REG (Pmode, 3); |
555 F (emit_insn (gen_movhi (r3, GEN_INT (sign * size)))); | 555 F (emit_insn (gen_movhi (r3, GEN_INT (sign * size))), in_prologue); |
556 F (emit_insn (gen_addhi3 (stack_pointer_rtx, | 556 F (emit_insn (gen_addhi3 (stack_pointer_rtx, |
557 stack_pointer_rtx, r3))); | 557 stack_pointer_rtx, r3)), in_prologue); |
558 } | 558 } |
559 else | 559 else |
560 { | 560 { |
561 /* The stack adjustment made here is further optimized by the | 561 /* The stack adjustment made here is further optimized by the |
562 splitter. In case of H8/300, the splitter always splits the | 562 splitter. In case of H8/300, the splitter always splits the |
566 if (Pmode == HImode) | 566 if (Pmode == HImode) |
567 { | 567 { |
568 rtx x = emit_insn (gen_addhi3 (stack_pointer_rtx, | 568 rtx x = emit_insn (gen_addhi3 (stack_pointer_rtx, |
569 stack_pointer_rtx, GEN_INT (sign * size))); | 569 stack_pointer_rtx, GEN_INT (sign * size))); |
570 if (size < 4) | 570 if (size < 4) |
571 F (x); | 571 F (x, in_prologue); |
572 } | 572 } |
573 else | 573 else |
574 F (emit_insn (gen_addsi3 (stack_pointer_rtx, | 574 F (emit_insn (gen_addsi3 (stack_pointer_rtx, |
575 stack_pointer_rtx, GEN_INT (sign * size)))); | 575 stack_pointer_rtx, GEN_INT (sign * size))), in_prologue); |
576 } | 576 } |
577 } | 577 } |
578 | 578 |
579 /* Round up frame size SIZE. */ | 579 /* Round up frame size SIZE. */ |
580 | 580 |
620 x = gen_push_h8300 (reg); | 620 x = gen_push_h8300 (reg); |
621 else if (!TARGET_NORMAL_MODE) | 621 else if (!TARGET_NORMAL_MODE) |
622 x = gen_push_h8300hs_advanced (reg); | 622 x = gen_push_h8300hs_advanced (reg); |
623 else | 623 else |
624 x = gen_push_h8300hs_normal (reg); | 624 x = gen_push_h8300hs_normal (reg); |
625 x = F (emit_insn (x)); | 625 x = F (emit_insn (x), true); |
626 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); |
627 } | 627 } |
628 | 628 |
629 /* Emit an insn to pop register RN. */ | 629 /* Emit an insn to pop register RN. */ |
630 | 630 |
659 ... | 659 ... |
660 (save or restore REGNO + NREGS - 1) | 660 (save or restore REGNO + NREGS - 1) |
661 (set sp (plus sp (const_int adjust)))] */ | 661 (set sp (plus sp (const_int adjust)))] */ |
662 | 662 |
663 static void | 663 static void |
664 h8300_push_pop (int regno, int nregs, int pop_p, int return_p) | 664 h8300_push_pop (int regno, int nregs, bool pop_p, bool return_p) |
665 { | 665 { |
666 int i, j; | 666 int i, j; |
667 rtvec vec; | 667 rtvec vec; |
668 rtx sp, offset, x; | 668 rtx sp, offset, x; |
669 | 669 |
677 return; | 677 return; |
678 } | 678 } |
679 | 679 |
680 /* We need one element for the return insn, if present, one for each | 680 /* We need one element for the return insn, if present, one for each |
681 register, and one for stack adjustment. */ | 681 register, and one for stack adjustment. */ |
682 vec = rtvec_alloc ((return_p != 0) + nregs + 1); | 682 vec = rtvec_alloc ((return_p ? 1 : 0) + nregs + 1); |
683 sp = stack_pointer_rtx; | 683 sp = stack_pointer_rtx; |
684 i = 0; | 684 i = 0; |
685 | 685 |
686 /* Add the return instruction. */ | 686 /* Add the return instruction. */ |
687 if (return_p) | 687 if (return_p) |
717 gen_rtx_PLUS (Pmode, sp, offset)); | 717 gen_rtx_PLUS (Pmode, sp, offset)); |
718 | 718 |
719 x = gen_rtx_PARALLEL (VOIDmode, vec); | 719 x = gen_rtx_PARALLEL (VOIDmode, vec); |
720 if (!pop_p) | 720 if (!pop_p) |
721 x = Fpa (x); | 721 x = Fpa (x); |
722 emit_insn (x); | 722 |
723 if (return_p) | |
724 emit_jump_insn (x); | |
725 else | |
726 emit_insn (x); | |
723 } | 727 } |
724 | 728 |
725 /* Return true if X has the value sp + OFFSET. */ | 729 /* Return true if X has the value sp + OFFSET. */ |
726 | 730 |
727 static int | 731 static int |
852 | 856 |
853 if (frame_pointer_needed) | 857 if (frame_pointer_needed) |
854 { | 858 { |
855 /* Push fp. */ | 859 /* Push fp. */ |
856 push (HARD_FRAME_POINTER_REGNUM); | 860 push (HARD_FRAME_POINTER_REGNUM); |
857 F (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx)); | 861 F (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx), true); |
858 } | 862 } |
859 | 863 |
860 /* Push the rest of the registers in ascending order. */ | 864 /* Push the rest of the registers in ascending order. */ |
861 saved_regs = compute_saved_regs (); | 865 saved_regs = compute_saved_regs (); |
862 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno += n_regs) | 866 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno += n_regs) |
878 else if ((!TARGET_H8300SX || (regno & 1) == 0) | 882 else if ((!TARGET_H8300SX || (regno & 1) == 0) |
879 && ((saved_regs >> regno) & 0x03) == 0x03) | 883 && ((saved_regs >> regno) & 0x03) == 0x03) |
880 n_regs = 2; | 884 n_regs = 2; |
881 } | 885 } |
882 | 886 |
883 h8300_push_pop (regno, n_regs, 0, 0); | 887 h8300_push_pop (regno, n_regs, false, false); |
884 } | 888 } |
885 } | 889 } |
886 | 890 |
887 /* Leave room for locals. */ | 891 /* Leave room for locals. */ |
888 h8300_emit_stack_adjustment (-1, round_frame_size (get_frame_size ())); | 892 h8300_emit_stack_adjustment (-1, round_frame_size (get_frame_size ()), true); |
889 } | 893 } |
890 | 894 |
891 /* Return nonzero if we can use "rts" for the function currently being | 895 /* Return nonzero if we can use "rts" for the function currently being |
892 compiled. */ | 896 compiled. */ |
893 | 897 |
918 | 922 |
919 frame_size = round_frame_size (get_frame_size ()); | 923 frame_size = round_frame_size (get_frame_size ()); |
920 returned_p = false; | 924 returned_p = false; |
921 | 925 |
922 /* Deallocate locals. */ | 926 /* Deallocate locals. */ |
923 h8300_emit_stack_adjustment (1, frame_size); | 927 h8300_emit_stack_adjustment (1, frame_size, false); |
924 | 928 |
925 /* Pop the saved registers in descending order. */ | 929 /* Pop the saved registers in descending order. */ |
926 saved_regs = compute_saved_regs (); | 930 saved_regs = compute_saved_regs (); |
927 for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno -= n_regs) | 931 for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno -= n_regs) |
928 { | 932 { |
951 && !frame_pointer_needed | 955 && !frame_pointer_needed |
952 && frame_size == 0 | 956 && frame_size == 0 |
953 && (saved_regs & ((1 << (regno - n_regs + 1)) - 1)) == 0) | 957 && (saved_regs & ((1 << (regno - n_regs + 1)) - 1)) == 0) |
954 returned_p = true; | 958 returned_p = true; |
955 | 959 |
956 h8300_push_pop (regno - n_regs + 1, n_regs, 1, returned_p); | 960 h8300_push_pop (regno - n_regs + 1, n_regs, true, returned_p); |
957 } | 961 } |
958 } | 962 } |
959 | 963 |
960 /* Pop frame pointer if we had one. */ | 964 /* Pop frame pointer if we had one. */ |
961 if (frame_pointer_needed) | 965 if (frame_pointer_needed) |
962 { | 966 { |
963 if (TARGET_H8300SX) | 967 if (TARGET_H8300SX) |
964 returned_p = true; | 968 returned_p = true; |
965 h8300_push_pop (HARD_FRAME_POINTER_REGNUM, 1, 1, returned_p); | 969 h8300_push_pop (HARD_FRAME_POINTER_REGNUM, 1, true, returned_p); |
966 } | 970 } |
967 | 971 |
968 if (!returned_p) | 972 if (!returned_p) |
969 emit_jump_insn (gen_rtx_RETURN (VOIDmode)); | 973 emit_jump_insn (gen_rtx_RETURN (VOIDmode)); |
970 } | 974 } |
1461 fprintf (file, "%s", names_big[REGNO (x)]); | 1465 fprintf (file, "%s", names_big[REGNO (x)]); |
1462 else | 1466 else |
1463 goto def; | 1467 goto def; |
1464 break; | 1468 break; |
1465 case 'V': | 1469 case 'V': |
1466 bitint = exact_log2 (INTVAL (x) & 0xff); | 1470 bitint = (INTVAL (x) & 0xffff); |
1471 if ((exact_log2 ((bitint >> 8) & 0xff)) == -1) | |
1472 bitint = exact_log2 (bitint & 0xff); | |
1473 else | |
1474 bitint = exact_log2 ((bitint >> 8) & 0xff); | |
1467 gcc_assert (bitint >= 0); | 1475 gcc_assert (bitint >= 0); |
1468 fprintf (file, "#%d", bitint); | 1476 fprintf (file, "#%d", bitint); |
1469 break; | 1477 break; |
1470 case 'W': | 1478 case 'W': |
1471 bitint = exact_log2 ((~INTVAL (x)) & 0xff); | 1479 bitint = ((~INTVAL (x)) & 0xffff); |
1480 if ((exact_log2 ((bitint >> 8) & 0xff)) == -1 ) | |
1481 bitint = exact_log2 (bitint & 0xff); | |
1482 else | |
1483 bitint = (exact_log2 ((bitint >> 8) & 0xff)); | |
1472 gcc_assert (bitint >= 0); | 1484 gcc_assert (bitint >= 0); |
1473 fprintf (file, "#%d", bitint); | 1485 fprintf (file, "#%d", bitint); |
1474 break; | 1486 break; |
1475 case 'R': | 1487 case 'R': |
1476 case 'X': | 1488 case 'X': |