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 }