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,