Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/score/score7.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children |
comparison
equal
deleted
inserted
replaced
65:65488c3d617d | 67:f6334be47118 |
---|---|
1 /* score7.c for Sunplus S+CORE processor | 1 /* score7.c for Sunplus S+CORE processor |
2 Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. | 2 Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. |
3 Contributed by Sunnorth | 3 Contributed by Sunnorth |
4 | 4 |
5 This file is part of GCC. | 5 This file is part of GCC. |
6 | 6 |
7 GCC is free software; you can redistribute it and/or modify it | 7 GCC is free software; you can redistribute it and/or modify it |
27 #include "hard-reg-set.h" | 27 #include "hard-reg-set.h" |
28 #include "insn-config.h" | 28 #include "insn-config.h" |
29 #include "conditions.h" | 29 #include "conditions.h" |
30 #include "insn-attr.h" | 30 #include "insn-attr.h" |
31 #include "recog.h" | 31 #include "recog.h" |
32 #include "toplev.h" | 32 #include "diagnostic-core.h" |
33 #include "output.h" | 33 #include "output.h" |
34 #include "tree.h" | 34 #include "tree.h" |
35 #include "function.h" | 35 #include "function.h" |
36 #include "expr.h" | 36 #include "expr.h" |
37 #include "optabs.h" | 37 #include "optabs.h" |
287 return 0; | 287 return 0; |
288 } | 288 } |
289 } | 289 } |
290 | 290 |
291 bool | 291 bool |
292 score7_return_in_memory (tree type, tree fndecl ATTRIBUTE_UNUSED) | 292 score7_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED) |
293 { | 293 { |
294 return ((TYPE_MODE (type) == BLKmode) | 294 return ((TYPE_MODE (type) == BLKmode) |
295 || (int_size_in_bytes (type) > 2 * UNITS_PER_WORD) | 295 || (int_size_in_bytes (type) > 2 * UNITS_PER_WORD) |
296 || (int_size_in_bytes (type) == -1)); | 296 || (int_size_in_bytes (type) == -1)); |
297 } | 297 } |
338 | 338 |
339 /* Add DELTA to THIS_RTX. */ | 339 /* Add DELTA to THIS_RTX. */ |
340 if (delta != 0) | 340 if (delta != 0) |
341 { | 341 { |
342 rtx offset = GEN_INT (delta); | 342 rtx offset = GEN_INT (delta); |
343 if (!CONST_OK_FOR_LETTER_P (delta, 'L')) | 343 if (!(delta >= -32768 && delta <= 32767)) |
344 { | 344 { |
345 emit_move_insn (temp1, offset); | 345 emit_move_insn (temp1, offset); |
346 offset = temp1; | 346 offset = temp1; |
347 } | 347 } |
348 emit_insn (gen_add3_insn (this_rtx, this_rtx, offset)); | 348 emit_insn (gen_add3_insn (this_rtx, this_rtx, offset)); |
436 cumulative state for earlier arguments. MODE is the mode of this | 436 cumulative state for earlier arguments. MODE is the mode of this |
437 argument and TYPE is its type (if known). NAMED is true if this | 437 argument and TYPE is its type (if known). NAMED is true if this |
438 is a named (fixed) argument rather than a variable one. */ | 438 is a named (fixed) argument rather than a variable one. */ |
439 static void | 439 static void |
440 score7_classify_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, | 440 score7_classify_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, |
441 tree type, int named, struct score7_arg_info *info) | 441 const_tree type, bool named, struct score7_arg_info *info) |
442 { | 442 { |
443 int even_reg_p; | 443 int even_reg_p; |
444 unsigned int num_words, max_regs; | 444 unsigned int num_words, max_regs; |
445 | 445 |
446 even_reg_p = 0; | 446 even_reg_p = 0; |
572 return mergeable_constant_section (mode, align, 0); | 572 return mergeable_constant_section (mode, align, 0); |
573 } | 573 } |
574 | 574 |
575 /* Implement TARGET_IN_SMALL_DATA_P. */ | 575 /* Implement TARGET_IN_SMALL_DATA_P. */ |
576 bool | 576 bool |
577 score7_in_small_data_p (tree decl) | 577 score7_in_small_data_p (const_tree decl) |
578 { | 578 { |
579 HOST_WIDE_INT size; | 579 HOST_WIDE_INT size; |
580 | 580 |
581 if (TREE_CODE (decl) == STRING_CST | 581 if (TREE_CODE (decl) == STRING_CST |
582 || TREE_CODE (decl) == FUNCTION_DECL) | 582 || TREE_CODE (decl) == FUNCTION_DECL) |
631 } | 631 } |
632 } | 632 } |
633 } | 633 } |
634 } | 634 } |
635 | 635 |
636 /* Implement OVERRIDE_OPTIONS macro. */ | 636 /* Implement TARGET_OPTION_OVERRIDE hook. */ |
637 void | 637 void |
638 score7_override_options (void) | 638 score7_option_override (void) |
639 { | 639 { |
640 flag_pic = false; | 640 flag_pic = false; |
641 if (!flag_pic) | 641 score7_sdata_max = SCORE7_DEFAULT_SDATA_MAX; |
642 score7_sdata_max = g_switch_set ? g_switch_value : SCORE7_DEFAULT_SDATA_MAX; | 642 |
643 else | |
644 { | |
645 score7_sdata_max = 0; | |
646 if (g_switch_set && (g_switch_value != 0)) | |
647 warning (0, "-fPIC and -G are incompatible"); | |
648 } | |
649 | |
650 score_char_to_class['d'] = G32_REGS; | |
651 score_char_to_class['e'] = G16_REGS; | |
652 score_char_to_class['t'] = T32_REGS; | |
653 | |
654 score_char_to_class['h'] = HI_REG; | |
655 score_char_to_class['l'] = LO_REG; | |
656 score_char_to_class['x'] = CE_REGS; | |
657 | |
658 score_char_to_class['q'] = CN_REG; | |
659 score_char_to_class['y'] = LC_REG; | |
660 score_char_to_class['z'] = SC_REG; | |
661 score_char_to_class['a'] = SP_REGS; | |
662 | |
663 score_char_to_class['c'] = CR_REGS; | |
664 } | 643 } |
665 | 644 |
666 /* Implement REGNO_REG_CLASS macro. */ | 645 /* Implement REGNO_REG_CLASS macro. */ |
667 int | 646 int |
668 score7_reg_class (int regno) | 647 score7_reg_class (int regno) |
706 if (!GR_REG_CLASS_P (rclass)) | 685 if (!GR_REG_CLASS_P (rclass)) |
707 return GP_REG_P (regno) ? NO_REGS : G32_REGS; | 686 return GP_REG_P (regno) ? NO_REGS : G32_REGS; |
708 return NO_REGS; | 687 return NO_REGS; |
709 } | 688 } |
710 | 689 |
711 /* Implement CONST_OK_FOR_LETTER_P macro. */ | |
712 /* imm constraints | |
713 I imm16 << 16 | |
714 J uimm5 | |
715 K uimm16 | |
716 L simm16 | |
717 M uimm14 | |
718 N simm14 */ | |
719 int | |
720 score7_const_ok_for_letter_p (HOST_WIDE_INT value, char c) | |
721 { | |
722 switch (c) | |
723 { | |
724 case 'I': return ((value & 0xffff) == 0); | |
725 case 'J': return IMM_IN_RANGE (value, 5, 0); | |
726 case 'K': return IMM_IN_RANGE (value, 16, 0); | |
727 case 'L': return IMM_IN_RANGE (value, 16, 1); | |
728 case 'M': return IMM_IN_RANGE (value, 14, 0); | |
729 case 'N': return IMM_IN_RANGE (value, 14, 1); | |
730 default : return 0; | |
731 } | |
732 } | |
733 | |
734 /* Implement EXTRA_CONSTRAINT macro. */ | |
735 /* Z symbol_ref */ | |
736 int | |
737 score7_extra_constraint (rtx op, char c) | |
738 { | |
739 switch (c) | |
740 { | |
741 case 'Z': | |
742 return GET_CODE (op) == SYMBOL_REF; | |
743 default: | |
744 gcc_unreachable (); | |
745 } | |
746 } | |
747 | 690 |
748 /* Return truth value on whether or not a given hard register | 691 /* Return truth value on whether or not a given hard register |
749 can support a given mode. */ | 692 can support a given mode. */ |
750 int | 693 int |
751 score7_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode) | 694 score7_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode) |
786 default: | 729 default: |
787 gcc_unreachable (); | 730 gcc_unreachable (); |
788 } | 731 } |
789 } | 732 } |
790 | 733 |
791 /* Implement FUNCTION_ARG_ADVANCE macro. */ | 734 /* Implement TARGET_FUNCTION_ARG_ADVANCE hook. */ |
792 void | 735 void |
793 score7_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, | 736 score7_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, |
794 tree type, int named) | 737 const_tree type, bool named) |
795 { | 738 { |
796 struct score7_arg_info info; | 739 struct score7_arg_info info; |
797 score7_classify_arg (cum, mode, type, named, &info); | 740 score7_classify_arg (cum, mode, type, named, &info); |
798 cum->num_gprs = info.reg_offset + info.reg_words; | 741 cum->num_gprs = info.reg_offset + info.reg_words; |
799 if (info.stack_words > 0) | 742 if (info.stack_words > 0) |
809 struct score7_arg_info info; | 752 struct score7_arg_info info; |
810 score7_classify_arg (cum, mode, type, named, &info); | 753 score7_classify_arg (cum, mode, type, named, &info); |
811 return info.stack_words > 0 ? info.reg_words * UNITS_PER_WORD : 0; | 754 return info.stack_words > 0 ? info.reg_words * UNITS_PER_WORD : 0; |
812 } | 755 } |
813 | 756 |
814 /* Implement FUNCTION_ARG macro. */ | 757 /* Implement TARGET_FUNCTION_ARG hook. */ |
815 rtx | 758 rtx |
816 score7_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, | 759 score7_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, |
817 tree type, int named) | 760 const_tree type, bool named) |
818 { | 761 { |
819 struct score7_arg_info info; | 762 struct score7_arg_info info; |
820 | 763 |
821 if (mode == VOIDmode || !named) | 764 if (mode == VOIDmode || !named) |
822 return 0; | 765 return 0; |
846 | 789 |
847 /* Implement FUNCTION_VALUE and LIBCALL_VALUE. For normal calls, | 790 /* Implement FUNCTION_VALUE and LIBCALL_VALUE. For normal calls, |
848 VALTYPE is the return type and MODE is VOIDmode. For libcalls, | 791 VALTYPE is the return type and MODE is VOIDmode. For libcalls, |
849 VALTYPE is null and MODE is the mode of the return value. */ | 792 VALTYPE is null and MODE is the mode of the return value. */ |
850 rtx | 793 rtx |
851 score7_function_value (tree valtype, tree func, enum machine_mode mode) | 794 score7_function_value (const_tree valtype, const_tree func, |
795 enum machine_mode mode) | |
852 { | 796 { |
853 if (valtype) | 797 if (valtype) |
854 { | 798 { |
855 int unsignedp; | 799 int unsignedp; |
856 mode = TYPE_MODE (valtype); | 800 mode = TYPE_MODE (valtype); |
879 | 823 |
880 /* Implement TARGET_TRAMPOLINE_INIT. */ | 824 /* Implement TARGET_TRAMPOLINE_INIT. */ |
881 void | 825 void |
882 score7_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) | 826 score7_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) |
883 { | 827 { |
884 #define FFCACHE "_flush_cache" | |
885 #define CODE_SIZE (TRAMPOLINE_INSNS * UNITS_PER_WORD) | 828 #define CODE_SIZE (TRAMPOLINE_INSNS * UNITS_PER_WORD) |
886 | 829 |
887 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0); | 830 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0); |
888 rtx addr = XEXP (m_tramp, 0); | 831 rtx addr = XEXP (m_tramp, 0); |
889 rtx mem; | 832 rtx mem; |
894 mem = adjust_address (m_tramp, SImode, CODE_SIZE); | 837 mem = adjust_address (m_tramp, SImode, CODE_SIZE); |
895 emit_move_insn (mem, fnaddr); | 838 emit_move_insn (mem, fnaddr); |
896 mem = adjust_address (m_tramp, SImode, CODE_SIZE + GET_MODE_SIZE (SImode)); | 839 mem = adjust_address (m_tramp, SImode, CODE_SIZE + GET_MODE_SIZE (SImode)); |
897 emit_move_insn (mem, chain_value); | 840 emit_move_insn (mem, chain_value); |
898 | 841 |
899 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, FFCACHE), | |
900 0, VOIDmode, 2, | |
901 addr, Pmode, | |
902 GEN_INT (TRAMPOLINE_SIZE), SImode); | |
903 #undef FFCACHE | |
904 #undef CODE_SIZE | 842 #undef CODE_SIZE |
905 } | 843 } |
906 | 844 |
907 /* This function is used to implement REG_MODE_OK_FOR_BASE_P macro. */ | 845 /* This function is used to implement REG_MODE_OK_FOR_BASE_P macro. */ |
908 int | 846 int |
1013 switch (code) | 951 switch (code) |
1014 { | 952 { |
1015 case CONST_INT: | 953 case CONST_INT: |
1016 if (outer_code == SET) | 954 if (outer_code == SET) |
1017 { | 955 { |
1018 if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I') | 956 if (((INTVAL (x) & 0xffff) == 0) |
1019 || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')) | 957 || (INTVAL (x) >= -32768 && INTVAL (x) <= 32767)) |
1020 *total = COSTS_N_INSNS (1); | 958 *total = COSTS_N_INSNS (1); |
1021 else | 959 else |
1022 *total = COSTS_N_INSNS (2); | 960 *total = COSTS_N_INSNS (2); |
1023 } | 961 } |
1024 else if (outer_code == PLUS || outer_code == MINUS) | 962 else if (outer_code == PLUS || outer_code == MINUS) |
1025 { | 963 { |
1026 if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'N')) | 964 if (INTVAL (x) >= -8192 && INTVAL (x) <= 8191) |
1027 *total = 0; | 965 *total = 0; |
1028 else if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I') | 966 else if (((INTVAL (x) & 0xffff) == 0) |
1029 || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')) | 967 || (INTVAL (x) >= -32768 && INTVAL (x) <= 32767)) |
1030 *total = 1; | 968 *total = 1; |
1031 else | 969 else |
1032 *total = COSTS_N_INSNS (2); | 970 *total = COSTS_N_INSNS (2); |
1033 } | 971 } |
1034 else if (outer_code == AND || outer_code == IOR) | 972 else if (outer_code == AND || outer_code == IOR) |
1035 { | 973 { |
1036 if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'M')) | 974 if (INTVAL (x) >= 0 && INTVAL (x) <= 16383) |
1037 *total = 0; | 975 *total = 0; |
1038 else if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I') | 976 else if (((INTVAL (x) & 0xffff) == 0) |
1039 || CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')) | 977 || (INTVAL (x) >= 0 && INTVAL (x) <= 65535)) |
1040 *total = 1; | 978 *total = 1; |
1041 else | 979 else |
1042 *total = COSTS_N_INSNS (2); | 980 *total = COSTS_N_INSNS (2); |
1043 } | 981 } |
1044 else | 982 else |
1172 { | 1110 { |
1173 register struct extern_list *p; | 1111 register struct extern_list *p; |
1174 | 1112 |
1175 if (score7_in_small_data_p (decl)) | 1113 if (score7_in_small_data_p (decl)) |
1176 { | 1114 { |
1177 p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list)); | 1115 p = ggc_alloc_extern_list (); |
1178 p->next = extern_head; | 1116 p->next = extern_head; |
1179 p->name = name; | 1117 p->name = name; |
1180 p->size = int_size_in_bytes (TREE_TYPE (decl)); | 1118 p->size = int_size_in_bytes (TREE_TYPE (decl)); |
1181 extern_head = p; | 1119 extern_head = p; |
1182 } | 1120 } |
1207 'H' high part of DImode reg operand | 1145 'H' high part of DImode reg operand |
1208 'C' print part of opcode for a branch condition. */ | 1146 'C' print part of opcode for a branch condition. */ |
1209 void | 1147 void |
1210 score7_print_operand (FILE *file, rtx op, int c) | 1148 score7_print_operand (FILE *file, rtx op, int c) |
1211 { | 1149 { |
1212 enum rtx_code code = -1; | 1150 enum rtx_code code = UNKNOWN; |
1213 if (!PRINT_OPERAND_PUNCT_VALID_P (c)) | 1151 if (!PRINT_OPERAND_PUNCT_VALID_P (c)) |
1214 code = GET_CODE (op); | 1152 code = GET_CODE (op); |
1215 | 1153 |
1216 if (c == '[') | 1154 if (c == '[') |
1217 { | 1155 { |
1451 | 1389 |
1452 if (size > 0) | 1390 if (size > 0) |
1453 { | 1391 { |
1454 rtx insn; | 1392 rtx insn; |
1455 | 1393 |
1456 if (CONST_OK_FOR_LETTER_P (-size, 'L')) | 1394 if (size >= -32768 && size <= 32767) |
1457 EMIT_PL (emit_insn (gen_add3_insn (stack_pointer_rtx, | 1395 EMIT_PL (emit_insn (gen_add3_insn (stack_pointer_rtx, |
1458 stack_pointer_rtx, | 1396 stack_pointer_rtx, |
1459 GEN_INT (-size)))); | 1397 GEN_INT (-size)))); |
1460 else | 1398 else |
1461 { | 1399 { |
1506 else | 1444 else |
1507 base = hard_frame_pointer_rtx; | 1445 base = hard_frame_pointer_rtx; |
1508 | 1446 |
1509 if (size) | 1447 if (size) |
1510 { | 1448 { |
1511 if (CONST_OK_FOR_LETTER_P (size, 'L')) | 1449 if (size >= -32768 && size <= 32767) |
1512 emit_insn (gen_add3_insn (base, base, GEN_INT (size))); | 1450 emit_insn (gen_add3_insn (base, base, GEN_INT (size))); |
1513 else | 1451 else |
1514 { | 1452 { |
1515 emit_move_insn (gen_rtx_REG (Pmode, SCORE7_EPILOGUE_TEMP_REGNUM), | 1453 emit_move_insn (gen_rtx_REG (Pmode, SCORE7_EPILOGUE_TEMP_REGNUM), |
1516 GEN_INT (size)); | 1454 GEN_INT (size)); |
1709 } | 1647 } |
1710 if (REGNO (ai.reg) == HARD_FRAME_POINTER_REGNUM) | 1648 if (REGNO (ai.reg) == HARD_FRAME_POINTER_REGNUM) |
1711 { | 1649 { |
1712 HOST_WIDE_INT offset = INTVAL (ai.offset); | 1650 HOST_WIDE_INT offset = INTVAL (ai.offset); |
1713 if (SCORE_ALIGN_UNIT (offset, unit) | 1651 if (SCORE_ALIGN_UNIT (offset, unit) |
1714 && CONST_OK_FOR_LETTER_P (offset >> unit, 'J')) | 1652 && (((offset >> unit) >= 0) && ((offset >> unit) <= 31))) |
1715 { | 1653 { |
1716 ops[iaddr] = ai.offset; | 1654 ops[iaddr] = ai.offset; |
1717 return snprintf (ip, INS_BUF_SZ, | 1655 return snprintf (ip, INS_BUF_SZ, |
1718 "p!\t%%%d, %%c%d", idata, iaddr); | 1656 "p!\t%%%d, %%c%d", idata, iaddr); |
1719 } | 1657 } |