Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/rl78/rl78.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
1 /* Subroutines used for code generation on Renesas RL78 processors. | 1 /* Subroutines used for code generation on Renesas RL78 processors. |
2 Copyright (C) 2011-2017 Free Software Foundation, Inc. | 2 Copyright (C) 2011-2018 Free Software Foundation, Inc. |
3 Contributed by Red Hat. | 3 Contributed by Red Hat. |
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 | 7 GCC is free software; you can redistribute it and/or modify |
15 GNU General Public License for more details. | 15 GNU General Public License for more details. |
16 | 16 |
17 You should have received a copy of the GNU General Public License | 17 You should have received a copy of the GNU General Public License |
18 along with GCC; see the file COPYING3. If not see | 18 along with GCC; see the file COPYING3. If not see |
19 <http://www.gnu.org/licenses/>. */ | 19 <http://www.gnu.org/licenses/>. */ |
20 | |
21 #define IN_TARGET_CODE 1 | |
20 | 22 |
21 #include "config.h" | 23 #include "config.h" |
22 #include "system.h" | 24 #include "system.h" |
23 #include "coretypes.h" | 25 #include "coretypes.h" |
24 #include "backend.h" | 26 #include "backend.h" |
76 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", | 78 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", |
77 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", | 79 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", |
78 "sp", "ap", "psw", "es", "cs" | 80 "sp", "ap", "psw", "es", "cs" |
79 }; | 81 }; |
80 | 82 |
83 /* used by rl78_addsi3_internal for formatting insns output */ | |
84 static char fmt_buffer[1024]; | |
85 | |
81 /* Structure for G13 MDUC registers. */ | 86 /* Structure for G13 MDUC registers. */ |
82 struct mduc_reg_type | 87 struct mduc_reg_type |
83 { | 88 { |
84 unsigned int address; | 89 unsigned int address; |
85 enum machine_mode mode; | 90 enum machine_mode mode; |
221 else | 226 else |
222 prev = set; | 227 prev = set; |
223 } | 228 } |
224 | 229 |
225 if (dump_file) | 230 if (dump_file) |
226 print_rtl_with_bb (dump_file, get_insns (), 0); | 231 print_rtl_with_bb (dump_file, get_insns (), TDF_NONE); |
227 | 232 |
228 return 0; | 233 return 0; |
229 } | 234 } |
230 | 235 |
231 namespace | 236 namespace |
358 } | 363 } |
359 | 364 |
360 if (TARGET_ES0 | 365 if (TARGET_ES0 |
361 && strcmp (lang_hooks.name, "GNU C") | 366 && strcmp (lang_hooks.name, "GNU C") |
362 && strcmp (lang_hooks.name, "GNU C11") | 367 && strcmp (lang_hooks.name, "GNU C11") |
368 && strcmp (lang_hooks.name, "GNU C17") | |
369 && strcmp (lang_hooks.name, "GNU C2X") | |
363 && strcmp (lang_hooks.name, "GNU C89") | 370 && strcmp (lang_hooks.name, "GNU C89") |
364 && strcmp (lang_hooks.name, "GNU C99") | 371 && strcmp (lang_hooks.name, "GNU C99") |
365 /* Compiling with -flto results in a language of GNU GIMPLE being used... */ | 372 /* Compiling with -flto results in a language of GNU GIMPLE being used... */ |
366 && strcmp (lang_hooks.name, "GNU GIMPLE")) | 373 && strcmp (lang_hooks.name, "GNU GIMPLE")) |
367 /* Address spaces are currently only supported by C. */ | 374 /* Address spaces are currently only supported by C. */ |
591 operands[2] = op00; | 598 operands[2] = op00; |
592 operands[4] = op10; | 599 operands[4] = op10; |
593 operands[3] = op02; | 600 operands[3] = op02; |
594 operands[5] = op12; | 601 operands[5] = op12; |
595 } | 602 } |
603 } | |
604 | |
605 void | |
606 rl78_split_movdi (rtx *operands, enum machine_mode omode) | |
607 { | |
608 rtx op00, op04, op10, op14; | |
609 op00 = rl78_subreg (SImode, operands[0], omode, 0); | |
610 op04 = rl78_subreg (SImode, operands[0], omode, 4); | |
611 op10 = rl78_subreg (SImode, operands[1], omode, 0); | |
612 op14 = rl78_subreg (SImode, operands[1], omode, 4); | |
613 emit_insn (gen_movsi (op00, op10)); | |
614 emit_insn (gen_movsi (op04, op14)); | |
596 } | 615 } |
597 | 616 |
598 /* Used by various two-operand expanders which cannot accept all | 617 /* Used by various two-operand expanders which cannot accept all |
599 operands in the "far" namespace. Force some such operands into | 618 operands in the "far" namespace. Force some such operands into |
600 registers so that each pattern has at most one far operand. */ | 619 registers so that each pattern has at most one far operand. */ |
784 | 803 |
785 /* Check "interrupt" attributes. */ | 804 /* Check "interrupt" attributes. */ |
786 static tree | 805 static tree |
787 rl78_handle_func_attribute (tree * node, | 806 rl78_handle_func_attribute (tree * node, |
788 tree name, | 807 tree name, |
789 tree args, | 808 tree args ATTRIBUTE_UNUSED, |
790 int flags ATTRIBUTE_UNUSED, | 809 int flags ATTRIBUTE_UNUSED, |
791 bool * no_add_attrs) | 810 bool * no_add_attrs) |
792 { | 811 { |
793 gcc_assert (DECL_P (* node)); | 812 gcc_assert (DECL_P (* node)); |
794 gcc_assert (args == NULL_TREE); | |
795 | 813 |
796 if (TREE_CODE (* node) != FUNCTION_DECL) | 814 if (TREE_CODE (* node) != FUNCTION_DECL) |
797 { | 815 { |
798 warning (OPT_Wattributes, "%qE attribute only applies to functions", | 816 warning (OPT_Wattributes, "%qE attribute only applies to functions", |
799 name); | 817 name); |
848 } | 866 } |
849 | 867 |
850 return NULL_TREE; | 868 return NULL_TREE; |
851 } | 869 } |
852 | 870 |
871 /* Check "vector" attribute. */ | |
872 | |
873 static tree | |
874 rl78_handle_vector_attribute (tree * node, | |
875 tree name, | |
876 tree args, | |
877 int flags ATTRIBUTE_UNUSED, | |
878 bool * no_add_attrs) | |
879 { | |
880 gcc_assert (DECL_P (* node)); | |
881 gcc_assert (args != NULL_TREE); | |
882 | |
883 if (TREE_CODE (* node) != FUNCTION_DECL) | |
884 { | |
885 warning (OPT_Wattributes, "%qE attribute only applies to functions", | |
886 name); | |
887 * no_add_attrs = true; | |
888 } | |
889 | |
890 return NULL_TREE; | |
891 } | |
892 | |
853 #undef TARGET_ATTRIBUTE_TABLE | 893 #undef TARGET_ATTRIBUTE_TABLE |
854 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table | 894 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table |
855 | 895 |
856 /* Table of RL78-specific attributes. */ | 896 /* Table of RL78-specific attributes. */ |
857 const struct attribute_spec rl78_attribute_table[] = | 897 const struct attribute_spec rl78_attribute_table[] = |
858 { | 898 { |
859 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler, | 899 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, |
860 affects_type_identity. */ | 900 affects_type_identity, handler, exclude. */ |
861 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute, | 901 { "interrupt", 0, -1, true, false, false, false, |
862 false }, | 902 rl78_handle_func_attribute, NULL }, |
863 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute, | 903 { "brk_interrupt", 0, 0, true, false, false, false, |
864 false }, | 904 rl78_handle_func_attribute, NULL }, |
865 { "naked", 0, 0, true, false, false, rl78_handle_naked_attribute, | 905 { "naked", 0, 0, true, false, false, false, |
866 false }, | 906 rl78_handle_naked_attribute, NULL }, |
867 { "saddr", 0, 0, true, false, false, rl78_handle_saddr_attribute, | 907 { "saddr", 0, 0, true, false, false, false, |
868 false }, | 908 rl78_handle_saddr_attribute, NULL }, |
869 { NULL, 0, 0, false, false, false, NULL, false } | 909 { "vector", 1, -1, true, false, false, false, |
910 rl78_handle_vector_attribute, NULL }, | |
911 { NULL, 0, 0, false, false, false, false, NULL, NULL } | |
870 }; | 912 }; |
871 | 913 |
872 | 914 |
873 | 915 |
874 /* Break down an address RTX into its component base/index/addend | 916 /* Break down an address RTX into its component base/index/addend |
1563 } | 1605 } |
1564 | 1606 |
1565 #undef TARGET_ASM_FUNCTION_PROLOGUE | 1607 #undef TARGET_ASM_FUNCTION_PROLOGUE |
1566 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function | 1608 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function |
1567 | 1609 |
1610 static void | |
1611 add_vector_labels (FILE *file, const char *aname) | |
1612 { | |
1613 tree vec_attr; | |
1614 tree val_attr; | |
1615 const char *vname = "vect"; | |
1616 const char *s; | |
1617 int vnum; | |
1618 | |
1619 /* This node is for the vector/interrupt tag itself */ | |
1620 vec_attr = lookup_attribute (aname, DECL_ATTRIBUTES (current_function_decl)); | |
1621 if (!vec_attr) | |
1622 return; | |
1623 | |
1624 /* Now point it at the first argument */ | |
1625 vec_attr = TREE_VALUE (vec_attr); | |
1626 | |
1627 /* Iterate through the arguments. */ | |
1628 while (vec_attr) | |
1629 { | |
1630 val_attr = TREE_VALUE (vec_attr); | |
1631 switch (TREE_CODE (val_attr)) | |
1632 { | |
1633 case STRING_CST: | |
1634 s = TREE_STRING_POINTER (val_attr); | |
1635 goto string_id_common; | |
1636 | |
1637 case IDENTIFIER_NODE: | |
1638 s = IDENTIFIER_POINTER (val_attr); | |
1639 | |
1640 string_id_common: | |
1641 if (strcmp (s, "$default") == 0) | |
1642 { | |
1643 fprintf (file, "\t.global\t$tableentry$default$%s\n", vname); | |
1644 fprintf (file, "$tableentry$default$%s:\n", vname); | |
1645 } | |
1646 else | |
1647 vname = s; | |
1648 break; | |
1649 | |
1650 case INTEGER_CST: | |
1651 vnum = TREE_INT_CST_LOW (val_attr); | |
1652 | |
1653 fprintf (file, "\t.global\t$tableentry$%d$%s\n", vnum, vname); | |
1654 fprintf (file, "$tableentry$%d$%s:\n", vnum, vname); | |
1655 break; | |
1656 | |
1657 default: | |
1658 ; | |
1659 } | |
1660 | |
1661 vec_attr = TREE_CHAIN (vec_attr); | |
1662 } | |
1663 | |
1664 } | |
1665 | |
1568 /* We don't use this to actually emit the function prologue. We use | 1666 /* We don't use this to actually emit the function prologue. We use |
1569 this to insert a comment in the asm file describing the | 1667 this to insert a comment in the asm file describing the |
1570 function. */ | 1668 function. */ |
1571 static void | 1669 static void |
1572 rl78_start_function (FILE *file) | 1670 rl78_start_function (FILE *file) |
1573 { | 1671 { |
1574 int i; | 1672 int i; |
1673 | |
1674 add_vector_labels (file, "interrupt"); | |
1675 add_vector_labels (file, "vector"); | |
1575 | 1676 |
1576 if (cfun->machine->framesize == 0) | 1677 if (cfun->machine->framesize == 0) |
1577 return; | 1678 return; |
1578 fprintf (file, "\t; start of function\n"); | 1679 fprintf (file, "\t; start of function\n"); |
1579 | 1680 |
3787 /* Like the previous function, but scan for SETs instead. */ | 3888 /* Like the previous function, but scan for SETs instead. */ |
3788 static void | 3889 static void |
3789 rl78_note_reg_set (char *dead, rtx d, rtx insn) | 3890 rl78_note_reg_set (char *dead, rtx d, rtx insn) |
3790 { | 3891 { |
3791 int r, i; | 3892 int r, i; |
3792 | 3893 bool is_dead; |
3793 if (GET_CODE (d) == MEM) | 3894 if (GET_CODE (d) == MEM) |
3794 rl78_note_reg_uses (dead, XEXP (d, 0), insn); | 3895 rl78_note_reg_uses (dead, XEXP (d, 0), insn); |
3795 | 3896 |
3796 if (GET_CODE (d) != REG) | 3897 if (GET_CODE (d) != REG) |
3797 return; | 3898 return; |
3798 | 3899 |
3900 /* Do not mark the reg unused unless all QImode parts of it are dead. */ | |
3799 r = REGNO (d); | 3901 r = REGNO (d); |
3800 if (dead [r]) | 3902 is_dead = true; |
3801 add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r)); | 3903 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++) |
3904 if (!dead [r + i]) | |
3905 is_dead = false; | |
3906 if(is_dead) | |
3907 add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r)); | |
3802 if (dump_file) | 3908 if (dump_file) |
3803 fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d))); | 3909 fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d))); |
3804 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++) | 3910 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++) |
3805 dead [r + i] = 1; | 3911 dead [r + i] = 1; |
3806 } | 3912 } |
4210 rl78_alloc_physical_registers (); | 4316 rl78_alloc_physical_registers (); |
4211 | 4317 |
4212 if (dump_file) | 4318 if (dump_file) |
4213 { | 4319 { |
4214 fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n"); | 4320 fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n"); |
4215 print_rtl_with_bb (dump_file, get_insns (), 0); | 4321 print_rtl_with_bb (dump_file, get_insns (), TDF_NONE); |
4216 } | 4322 } |
4217 | 4323 |
4218 rl78_propogate_register_origins (); | 4324 rl78_propogate_register_origins (); |
4219 rl78_calculate_death_notes (); | 4325 rl78_calculate_death_notes (); |
4220 | 4326 |
4221 if (dump_file) | 4327 if (dump_file) |
4222 { | 4328 { |
4223 fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n"); | 4329 fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n"); |
4224 print_rtl_with_bb (dump_file, get_insns (), 0); | 4330 print_rtl_with_bb (dump_file, get_insns (), TDF_NONE); |
4225 fprintf (dump_file, "\n======================================================================\n"); | 4331 fprintf (dump_file, "\n======================================================================\n"); |
4226 } | 4332 } |
4227 | 4333 |
4228 rl78_remove_unused_sets (); | 4334 rl78_remove_unused_sets (); |
4229 | 4335 |
4766 } | 4872 } |
4767 | 4873 |
4768 const char * | 4874 const char * |
4769 rl78_addsi3_internal (rtx * operands, unsigned int alternative) | 4875 rl78_addsi3_internal (rtx * operands, unsigned int alternative) |
4770 { | 4876 { |
4877 const char *addH2 = "addw ax, %H2\n\t"; | |
4878 | |
4771 /* If we are adding in a constant symbolic address when -mes0 | 4879 /* If we are adding in a constant symbolic address when -mes0 |
4772 is active then we know that the address must be <64K and | 4880 is active then we know that the address must be <64K and |
4773 that it is invalid to access anything above 64K relative to | 4881 that it is invalid to access anything above 64K relative to |
4774 this address. So we can skip adding in the high bytes. */ | 4882 this address. So we can skip adding in the high bytes. */ |
4775 if (TARGET_ES0 | 4883 if (TARGET_ES0 |
4777 && TREE_CODE (SYMBOL_REF_DECL (operands[2])) == VAR_DECL | 4885 && TREE_CODE (SYMBOL_REF_DECL (operands[2])) == VAR_DECL |
4778 && TREE_READONLY (SYMBOL_REF_DECL (operands[2])) | 4886 && TREE_READONLY (SYMBOL_REF_DECL (operands[2])) |
4779 && ! TREE_SIDE_EFFECTS (SYMBOL_REF_DECL (operands[2]))) | 4887 && ! TREE_SIDE_EFFECTS (SYMBOL_REF_DECL (operands[2]))) |
4780 return "movw ax, %h1\n\taddw ax, %h2\n\tmovw %h0, ax"; | 4888 return "movw ax, %h1\n\taddw ax, %h2\n\tmovw %h0, ax"; |
4781 | 4889 |
4890 if(CONST_INT_P(operands[2])) | |
4891 { | |
4892 if((INTVAL(operands[2]) & 0xFFFF0000) == 0) | |
4893 { | |
4894 addH2 = ""; | |
4895 } | |
4896 else if((INTVAL(operands[2]) & 0xFFFF0000) == 0x00010000) | |
4897 { | |
4898 addH2 = "incw ax\n\t"; | |
4899 } | |
4900 else if((INTVAL(operands[2]) & 0xFFFF0000) == 0xFFFF0000) | |
4901 { | |
4902 addH2 = "decw ax\n\t"; | |
4903 } | |
4904 } | |
4905 | |
4782 switch (alternative) | 4906 switch (alternative) |
4783 { | 4907 { |
4784 case 0: | 4908 case 0: |
4785 case 1: | 4909 case 1: |
4786 return "movw ax, %h1\n\taddw ax, %h2\n\tmovw %h0, ax\n\tmovw ax, %H1\n\tsknc\n\tincw ax\n\taddw ax, %H2\n\tmovw %H0, ax"; | 4910 snprintf(fmt_buffer, sizeof(fmt_buffer), |
4911 "movw ax, %%h1\n\taddw ax, %%h2\n\tmovw %%h0, ax\n\tmovw ax, %%H1\n\tsknc\n\tincw ax\n\t%smovw %%H0,ax", addH2); | |
4912 break; | |
4787 case 2: | 4913 case 2: |
4788 return "movw ax, %h1\n\taddw ax,%h2\n\tmovw bc, ax\n\tmovw ax, %H1\n\tsknc\n\tincw ax\n\taddw ax, %H2\n\tmovw %H0, ax\n\tmovw ax, bc\n\tmovw %h0, ax"; | 4914 snprintf(fmt_buffer, sizeof(fmt_buffer), |
4915 "movw ax, %%h1\n\taddw ax, %%h2\n\tmovw bc, ax\n\tmovw ax, %%H1\n\tsknc\n\tincw ax\n\t%smovw %%H0, ax\n\tmovw ax, bc\n\tmovw %%h0, ax", addH2); | |
4916 break; | |
4789 default: | 4917 default: |
4790 gcc_unreachable (); | 4918 gcc_unreachable (); |
4791 } | 4919 } |
4920 | |
4921 return fmt_buffer; | |
4792 } | 4922 } |
4793 | 4923 |
4794 rtx | 4924 rtx |
4795 rl78_emit_libcall (const char *name, enum rtx_code code, | 4925 rl78_emit_libcall (const char *name, enum rtx_code code, |
4796 enum machine_mode dmode, enum machine_mode smode, | 4926 enum machine_mode dmode, enum machine_mode smode, |