Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/avr/avr.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 for insn-output.c for ATMEL AVR micro controllers | 1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers |
2 Copyright (C) 1998-2017 Free Software Foundation, Inc. | 2 Copyright (C) 1998-2018 Free Software Foundation, Inc. |
3 Contributed by Denis Chertykov (chertykov@gmail.com) | 3 Contributed by Denis Chertykov (chertykov@gmail.com) |
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 "intl.h" | 25 #include "intl.h" |
24 #include "coretypes.h" | 26 #include "coretypes.h" |
61 | 63 |
62 /* Maximal allowed offset for an address in the LD command */ | 64 /* Maximal allowed offset for an address in the LD command */ |
63 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE)) | 65 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE)) |
64 | 66 |
65 /* Return true if STR starts with PREFIX and false, otherwise. */ | 67 /* Return true if STR starts with PREFIX and false, otherwise. */ |
66 #define STR_PREFIX_P(STR,PREFIX) (0 == strncmp (STR, PREFIX, strlen (PREFIX))) | 68 #define STR_PREFIX_P(STR,PREFIX) (strncmp (STR, PREFIX, strlen (PREFIX)) == 0) |
67 | 69 |
68 /* The 4 bits starting at SECTION_MACH_DEP are reserved to store the | 70 /* The 4 bits starting at SECTION_MACH_DEP are reserved to store the |
69 address space where data is to be located. | 71 address space where data is to be located. |
70 As the only non-generic address spaces are all located in flash, | 72 As the only non-generic address spaces are all located in flash, |
71 this can be used to test if data shall go into some .progmem* section. | 73 this can be used to test if data shall go into some .progmem* section. |
265 for (int i = 0; i < n_bytes; i++) | 267 for (int i = 0; i < n_bytes; i++) |
266 { | 268 { |
267 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i); | 269 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i); |
268 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode); | 270 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode); |
269 | 271 |
270 if (0 == (pop_mask & (1 << popcount_hwi (val8)))) | 272 if ((pop_mask & (1 << popcount_hwi (val8))) == 0) |
271 return false; | 273 return false; |
272 } | 274 } |
273 | 275 |
274 return true; | 276 return true; |
275 } | 277 } |
457 | 459 |
458 extract_insn (xinsn); | 460 extract_insn (xinsn); |
459 | 461 |
460 // Assert on the anatomy of xinsn's operands we are going to work with. | 462 // Assert on the anatomy of xinsn's operands we are going to work with. |
461 | 463 |
462 gcc_assert (11 == recog_data.n_operands); | 464 gcc_assert (recog_data.n_operands == 11); |
463 gcc_assert (4 == recog_data.n_dups); | 465 gcc_assert (recog_data.n_dups == 4); |
464 | 466 |
465 if (dump_file) | 467 if (dump_file) |
466 { | 468 { |
467 fprintf (dump_file, ";; Operands extracted:\n"); | 469 fprintf (dump_file, ";; Operands extracted:\n"); |
468 for (int i = 0; i < recog_data.n_operands; i++) | 470 for (int i = 0; i < recog_data.n_operands; i++) |
505 sub_5 = XEXP (xop[6], 0); | 507 sub_5 = XEXP (xop[6], 0); |
506 } | 508 } |
507 | 509 |
508 if (sub_5 | 510 if (sub_5 |
509 && SUBREG_P (sub_5) | 511 && SUBREG_P (sub_5) |
510 && 0 == SUBREG_BYTE (sub_5) | 512 && SUBREG_BYTE (sub_5) == 0 |
511 && rtx_equal_p (xop[5], SUBREG_REG (sub_5))) | 513 && rtx_equal_p (xop[5], SUBREG_REG (sub_5))) |
512 return true; | 514 return true; |
513 | 515 |
514 if (dump_file) | 516 if (dump_file) |
515 fprintf (dump_file, "\n;; Failed condition for casesi_<mode>_sequence\n\n"); | 517 fprintf (dump_file, "\n;; Failed condition for casesi_<mode>_sequence\n\n"); |
693 | 695 |
694 avr_arch = &avr_arch_types[0]; | 696 avr_arch = &avr_arch_types[0]; |
695 | 697 |
696 for (const avr_mcu_t *mcu = avr_mcu_types; ; mcu++) | 698 for (const avr_mcu_t *mcu = avr_mcu_types; ; mcu++) |
697 { | 699 { |
698 if (NULL == mcu->name) | 700 if (mcu->name == NULL) |
699 { | 701 { |
700 /* Reached the end of `avr_mcu_types'. This should actually never | 702 /* Reached the end of `avr_mcu_types'. This should actually never |
701 happen as options are provided by device-specs. It could be a | 703 happen as options are provided by device-specs. It could be a |
702 typo in a device-specs or calling the compiler proper directly | 704 typo in a device-specs or calling the compiler proper directly |
703 with -mmcu=<device>. */ | 705 with -mmcu=<device>. */ |
705 error ("unknown core architecture %qs specified with %qs", | 707 error ("unknown core architecture %qs specified with %qs", |
706 avr_mmcu, "-mmcu="); | 708 avr_mmcu, "-mmcu="); |
707 avr_inform_core_architectures (); | 709 avr_inform_core_architectures (); |
708 break; | 710 break; |
709 } | 711 } |
710 else if (0 == strcmp (mcu->name, avr_mmcu) | 712 else if (strcmp (mcu->name, avr_mmcu) == 0 |
711 // Is this a proper architecture ? | 713 // Is this a proper architecture ? |
712 && NULL == mcu->macro) | 714 && mcu->macro == NULL) |
713 { | 715 { |
714 avr_arch = &avr_arch_types[mcu->arch_id]; | 716 avr_arch = &avr_arch_types[mcu->arch_id]; |
715 if (avr_n_flash < 0) | 717 if (avr_n_flash < 0) |
716 avr_n_flash = 1 + (mcu->flash_size - 1) / 0x10000; | 718 avr_n_flash = 1 + (mcu->flash_size - 1) / 0x10000; |
717 | 719 |
726 /* Implement `TARGET_OPTION_OVERRIDE'. */ | 728 /* Implement `TARGET_OPTION_OVERRIDE'. */ |
727 | 729 |
728 static void | 730 static void |
729 avr_option_override (void) | 731 avr_option_override (void) |
730 { | 732 { |
731 /* Disable -fdelete-null-pointer-checks option for AVR target. | |
732 This option compiler assumes that dereferencing of a null pointer | |
733 would halt the program. For AVR this assumption is not true and | |
734 programs can safely dereference null pointers. Changes made by this | |
735 option may not work properly for AVR. So disable this option. */ | |
736 | |
737 flag_delete_null_pointer_checks = 0; | |
738 | |
739 /* caller-save.c looks for call-clobbered hard registers that are assigned | 733 /* caller-save.c looks for call-clobbered hard registers that are assigned |
740 to pseudos that cross calls and tries so save-restore them around calls | 734 to pseudos that cross calls and tries so save-restore them around calls |
741 in order to reduce the number of stack slots needed. | 735 in order to reduce the number of stack slots needed. |
742 | 736 |
743 This might lead to situations where reload is no more able to cope | 737 This might lead to situations where reload is no more able to cope |
1026 /* Sanity cheching for above function attributes. */ | 1020 /* Sanity cheching for above function attributes. */ |
1027 | 1021 |
1028 static void | 1022 static void |
1029 avr_set_current_function (tree decl) | 1023 avr_set_current_function (tree decl) |
1030 { | 1024 { |
1031 location_t loc; | |
1032 const char *isr; | |
1033 | |
1034 if (decl == NULL_TREE | 1025 if (decl == NULL_TREE |
1035 || current_function_decl == NULL_TREE | 1026 || current_function_decl == NULL_TREE |
1036 || current_function_decl == error_mark_node | 1027 || current_function_decl == error_mark_node |
1037 || ! cfun->machine | 1028 || ! cfun->machine |
1038 || cfun->machine->attributes_checked_p) | 1029 || cfun->machine->attributes_checked_p) |
1039 return; | 1030 return; |
1040 | 1031 |
1041 loc = DECL_SOURCE_LOCATION (decl); | 1032 location_t loc = DECL_SOURCE_LOCATION (decl); |
1042 | 1033 |
1043 cfun->machine->is_naked = avr_naked_function_p (decl); | 1034 cfun->machine->is_naked = avr_naked_function_p (decl); |
1044 cfun->machine->is_signal = avr_signal_function_p (decl); | 1035 cfun->machine->is_signal = avr_signal_function_p (decl); |
1045 cfun->machine->is_interrupt = avr_interrupt_function_p (decl); | 1036 cfun->machine->is_interrupt = avr_interrupt_function_p (decl); |
1046 cfun->machine->is_OS_task = avr_OS_task_function_p (decl); | 1037 cfun->machine->is_OS_task = avr_OS_task_function_p (decl); |
1047 cfun->machine->is_OS_main = avr_OS_main_function_p (decl); | 1038 cfun->machine->is_OS_main = avr_OS_main_function_p (decl); |
1048 cfun->machine->is_no_gccisr = avr_no_gccisr_function_p (decl); | 1039 cfun->machine->is_no_gccisr = avr_no_gccisr_function_p (decl); |
1049 | 1040 |
1050 isr = cfun->machine->is_interrupt ? "interrupt" : "signal"; | 1041 const char *isr = cfun->machine->is_interrupt ? "interrupt" : "signal"; |
1051 | 1042 |
1052 /* Too much attributes make no sense as they request conflicting features. */ | 1043 /* Too much attributes make no sense as they request conflicting features. */ |
1053 | 1044 |
1054 if (cfun->machine->is_OS_task + cfun->machine->is_OS_main | 1045 if (cfun->machine->is_OS_task |
1055 + (cfun->machine->is_signal || cfun->machine->is_interrupt) > 1) | 1046 && (cfun->machine->is_signal || cfun->machine->is_interrupt)) |
1056 error_at (loc, "function attributes %qs, %qs and %qs are mutually" | 1047 error_at (loc, "function attributes %qs and %qs are mutually exclusive", |
1057 " exclusive", "OS_task", "OS_main", isr); | 1048 "OS_task", isr); |
1058 | 1049 |
1059 /* 'naked' will hide effects of 'OS_task' and 'OS_main'. */ | 1050 if (cfun->machine->is_OS_main |
1060 | 1051 && (cfun->machine->is_signal || cfun->machine->is_interrupt)) |
1061 if (cfun->machine->is_naked | 1052 error_at (loc, "function attributes %qs and %qs are mutually exclusive", |
1062 && (cfun->machine->is_OS_task || cfun->machine->is_OS_main)) | 1053 "OS_main", isr); |
1063 warning_at (loc, OPT_Wattributes, "function attributes %qs and %qs have" | |
1064 " no effect on %qs function", "OS_task", "OS_main", "naked"); | |
1065 | 1054 |
1066 if (cfun->machine->is_interrupt || cfun->machine->is_signal) | 1055 if (cfun->machine->is_interrupt || cfun->machine->is_signal) |
1067 { | 1056 { |
1068 tree args = TYPE_ARG_TYPES (TREE_TYPE (decl)); | 1057 tree args = TYPE_ARG_TYPES (TREE_TYPE (decl)); |
1069 tree ret = TREE_TYPE (TREE_TYPE (decl)); | 1058 tree ret = TREE_TYPE (TREE_TYPE (decl)); |
1105 | 1094 |
1106 #if defined WITH_AVRLIBC | 1095 #if defined WITH_AVRLIBC |
1107 // Common problem is using "ISR" without first including avr/interrupt.h. | 1096 // Common problem is using "ISR" without first including avr/interrupt.h. |
1108 const char *name = IDENTIFIER_POINTER (DECL_NAME (decl)); | 1097 const char *name = IDENTIFIER_POINTER (DECL_NAME (decl)); |
1109 name = default_strip_name_encoding (name); | 1098 name = default_strip_name_encoding (name); |
1110 if (0 == strcmp ("ISR", name) | 1099 if (strcmp ("ISR", name) == 0 |
1111 || 0 == strcmp ("INTERRUPT", name) | 1100 || strcmp ("INTERRUPT", name) == 0 |
1112 || 0 == strcmp ("SIGNAL", name)) | 1101 || strcmp ("SIGNAL", name) == 0) |
1113 { | 1102 { |
1114 warning_at (loc, OPT_Wmisspelled_isr, "%qs is a reserved identifier" | 1103 warning_at (loc, OPT_Wmisspelled_isr, "%qs is a reserved identifier" |
1115 " in AVR-LibC. Consider %<#include <avr/interrupt.h>%>" | 1104 " in AVR-LibC. Consider %<#include <avr/interrupt.h>%>" |
1116 " before using the %qs macro", name, name); | 1105 " before using the %qs macro", name, name); |
1117 } | 1106 } |
1147 /* Report contribution of accumulated outgoing arguments to stack size. */ | 1136 /* Report contribution of accumulated outgoing arguments to stack size. */ |
1148 | 1137 |
1149 static inline int | 1138 static inline int |
1150 avr_outgoing_args_size (void) | 1139 avr_outgoing_args_size (void) |
1151 { | 1140 { |
1152 return ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0; | 1141 return (ACCUMULATE_OUTGOING_ARGS |
1142 ? (HOST_WIDE_INT) crtl->outgoing_args_size : 0); | |
1153 } | 1143 } |
1154 | 1144 |
1155 | 1145 |
1156 /* Implement TARGET_STARTING_FRAME_OFFSET. */ | 1146 /* Implement TARGET_STARTING_FRAME_OFFSET. */ |
1157 /* This is the offset from the frame pointer register to the first stack slot | 1147 /* This is the offset from the frame pointer register to the first stack slot |
2040 if (ACCUMULATE_OUTGOING_ARGS) | 2030 if (ACCUMULATE_OUTGOING_ARGS) |
2041 fprintf (file, "/* outgoing args size = %d */\n", | 2031 fprintf (file, "/* outgoing args size = %d */\n", |
2042 avr_outgoing_args_size()); | 2032 avr_outgoing_args_size()); |
2043 | 2033 |
2044 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n", | 2034 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n", |
2045 get_frame_size()); | 2035 (HOST_WIDE_INT) get_frame_size()); |
2046 | 2036 |
2047 if (!cfun->machine->gasisr.yes) | 2037 if (!cfun->machine->gasisr.yes) |
2048 { | 2038 { |
2049 fprintf (file, "/* stack size = %d */\n", cfun->machine->stack_usage); | 2039 fprintf (file, "/* stack size = %d */\n", cfun->machine->stack_usage); |
2050 // Create symbol stack offset so all functions have it. Add 1 to stack | 2040 // Create symbol stack offset so all functions have it. Add 1 to stack |
2568 return x; | 2558 return x; |
2569 } | 2559 } |
2570 | 2560 |
2571 if (GET_CODE (x) == PLUS | 2561 if (GET_CODE (x) == PLUS |
2572 && REG_P (XEXP (x, 0)) | 2562 && REG_P (XEXP (x, 0)) |
2573 && 0 == reg_equiv_constant (REGNO (XEXP (x, 0))) | 2563 && reg_equiv_constant (REGNO (XEXP (x, 0))) == 0 |
2574 && CONST_INT_P (XEXP (x, 1)) | 2564 && CONST_INT_P (XEXP (x, 1)) |
2575 && INTVAL (XEXP (x, 1)) >= 1) | 2565 && INTVAL (XEXP (x, 1)) >= 1) |
2576 { | 2566 { |
2577 bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode); | 2567 bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode); |
2578 | 2568 |
2635 */ | 2625 */ |
2636 | 2626 |
2637 static const char* | 2627 static const char* |
2638 avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words) | 2628 avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words) |
2639 { | 2629 { |
2640 if (NULL == plen) | 2630 if (plen == NULL) |
2641 { | 2631 output_asm_insn (tpl, operands); |
2642 output_asm_insn (tpl, operands); | |
2643 } | |
2644 else | 2632 else |
2645 { | 2633 { |
2646 if (n_words < 0) | 2634 if (n_words < 0) |
2647 *plen = -n_words; | 2635 *plen = -n_words; |
2648 else | 2636 else |
2965 fatal_insn ("bad address, not an I/O address:", x); | 2953 fatal_insn ("bad address, not an I/O address:", x); |
2966 } | 2954 } |
2967 else if (code == 'x') | 2955 else if (code == 'x') |
2968 { | 2956 { |
2969 /* Constant progmem address - like used in jmp or call */ | 2957 /* Constant progmem address - like used in jmp or call */ |
2970 if (0 == text_segment_operand (x, VOIDmode)) | 2958 if (text_segment_operand (x, VOIDmode) == 0) |
2971 if (warning (0, "accessing program memory" | 2959 if (warning (0, "accessing program memory" |
2972 " with data memory address")) | 2960 " with data memory address")) |
2973 { | 2961 { |
2974 output_addr_const (stderr, x); | 2962 output_addr_const (stderr, x); |
2975 fprintf(stderr,"\n"); | 2963 fprintf(stderr,"\n"); |
3523 /* Ensure that caller and callee have compatible epilogues */ | 3511 /* Ensure that caller and callee have compatible epilogues */ |
3524 | 3512 |
3525 if (cfun->machine->is_interrupt | 3513 if (cfun->machine->is_interrupt |
3526 || cfun->machine->is_signal | 3514 || cfun->machine->is_signal |
3527 || cfun->machine->is_naked | 3515 || cfun->machine->is_naked |
3528 || avr_naked_function_p (decl_callee) | 3516 || avr_naked_function_p (decl_callee)) |
3529 /* FIXME: For OS_task and OS_main, this might be over-conservative. */ | |
3530 || (avr_OS_task_function_p (decl_callee) | |
3531 != cfun->machine->is_OS_task) | |
3532 || (avr_OS_main_function_p (decl_callee) | |
3533 != cfun->machine->is_OS_main)) | |
3534 { | 3517 { |
3535 return false; | 3518 return false; |
3536 } | 3519 } |
3537 | 3520 |
3538 return true; | 3521 return true; |
3926 || avr_mem_flash_p (dest)) | 3909 || avr_mem_flash_p (dest)) |
3927 { | 3910 { |
3928 return avr_out_lpm (insn, operands, plen); | 3911 return avr_out_lpm (insn, operands, plen); |
3929 } | 3912 } |
3930 | 3913 |
3931 gcc_assert (1 == GET_MODE_SIZE (GET_MODE (dest))); | 3914 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 1); |
3932 | 3915 |
3933 if (REG_P (dest)) | 3916 if (REG_P (dest)) |
3934 { | 3917 { |
3935 if (REG_P (src)) /* mov r,r */ | 3918 if (REG_P (src)) /* mov r,r */ |
3936 { | 3919 { |
4921 } | 4904 } |
4922 | 4905 |
4923 if (!l) | 4906 if (!l) |
4924 l = &dummy; | 4907 l = &dummy; |
4925 | 4908 |
4926 gcc_assert (4 == GET_MODE_SIZE (GET_MODE (dest))); | 4909 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 4); |
4927 | 4910 |
4928 if (REG_P (dest)) | 4911 if (REG_P (dest)) |
4929 { | 4912 { |
4930 if (REG_P (src)) /* mov r,r */ | 4913 if (REG_P (src)) /* mov r,r */ |
4931 { | 4914 { |
8261 { | 8244 { |
8262 avr_out_plus_1 (xop, plen, code, pcc, code_sat, 0, out_label); | 8245 avr_out_plus_1 (xop, plen, code, pcc, code_sat, 0, out_label); |
8263 return ""; | 8246 return ""; |
8264 } | 8247 } |
8265 | 8248 |
8266 if (8 == n_bytes) | 8249 if (n_bytes == 8) |
8267 { | 8250 { |
8268 op[0] = gen_rtx_REG (DImode, ACC_A); | 8251 op[0] = gen_rtx_REG (DImode, ACC_A); |
8269 op[1] = gen_rtx_REG (DImode, ACC_A); | 8252 op[1] = gen_rtx_REG (DImode, ACC_A); |
8270 op[2] = avr_to_int_mode (xop[0]); | 8253 op[2] = avr_to_int_mode (xop[0]); |
8271 } | 8254 } |
8379 | 8362 |
8380 switch (code) | 8363 switch (code) |
8381 { | 8364 { |
8382 case IOR: | 8365 case IOR: |
8383 | 8366 |
8384 if (0 == pop8) | 8367 if (pop8 == 0) |
8385 continue; | 8368 continue; |
8386 else if (ld_reg_p) | 8369 else if (ld_reg_p) |
8387 avr_asm_len ("ori %0,%1", op, plen, 1); | 8370 avr_asm_len ("ori %0,%1", op, plen, 1); |
8388 else if (1 == pop8) | 8371 else if (pop8 == 1) |
8389 { | 8372 { |
8390 if (set_t != 1) | 8373 if (set_t != 1) |
8391 avr_asm_len ("set", op, plen, 1); | 8374 avr_asm_len ("set", op, plen, 1); |
8392 set_t = 1; | 8375 set_t = 1; |
8393 | 8376 |
8394 op[1] = GEN_INT (exact_log2 (val8)); | 8377 op[1] = GEN_INT (exact_log2 (val8)); |
8395 avr_asm_len ("bld %0,%1", op, plen, 1); | 8378 avr_asm_len ("bld %0,%1", op, plen, 1); |
8396 } | 8379 } |
8397 else if (8 == pop8) | 8380 else if (pop8 == 8) |
8398 { | 8381 { |
8399 if (op[3] != NULL_RTX) | 8382 if (op[3] != NULL_RTX) |
8400 avr_asm_len ("mov %0,%3", op, plen, 1); | 8383 avr_asm_len ("mov %0,%3", op, plen, 1); |
8401 else | 8384 else |
8402 avr_asm_len ("clr %0" CR_TAB | 8385 avr_asm_len ("clr %0" CR_TAB |
8415 | 8398 |
8416 continue; /* IOR */ | 8399 continue; /* IOR */ |
8417 | 8400 |
8418 case AND: | 8401 case AND: |
8419 | 8402 |
8420 if (8 == pop8) | 8403 if (pop8 == 8) |
8421 continue; | 8404 continue; |
8422 else if (0 == pop8) | 8405 else if (pop8 == 0) |
8423 avr_asm_len ("clr %0", op, plen, 1); | 8406 avr_asm_len ("clr %0", op, plen, 1); |
8424 else if (ld_reg_p) | 8407 else if (ld_reg_p) |
8425 avr_asm_len ("andi %0,%1", op, plen, 1); | 8408 avr_asm_len ("andi %0,%1", op, plen, 1); |
8426 else if (7 == pop8) | 8409 else if (pop8 == 7) |
8427 { | 8410 { |
8428 if (set_t != 0) | 8411 if (set_t != 0) |
8429 avr_asm_len ("clt", op, plen, 1); | 8412 avr_asm_len ("clt", op, plen, 1); |
8430 set_t = 0; | 8413 set_t = 0; |
8431 | 8414 |
8443 | 8426 |
8444 continue; /* AND */ | 8427 continue; /* AND */ |
8445 | 8428 |
8446 case XOR: | 8429 case XOR: |
8447 | 8430 |
8448 if (0 == pop8) | 8431 if (pop8 == 0) |
8449 continue; | 8432 continue; |
8450 else if (8 == pop8) | 8433 else if (pop8 == 8) |
8451 avr_asm_len ("com %0", op, plen, 1); | 8434 avr_asm_len ("com %0", op, plen, 1); |
8452 else if (ld_reg_p && val8 == (1 << 7)) | 8435 else if (ld_reg_p && val8 == (1 << 7)) |
8453 avr_asm_len ("subi %0,%1", op, plen, 1); | 8436 avr_asm_len ("subi %0,%1", op, plen, 1); |
8454 else | 8437 else |
8455 { | 8438 { |
8723 // Do we have a 16-Bit register that is cleared? | 8706 // Do we have a 16-Bit register that is cleared? |
8724 rtx clrw = NULL_RTX; | 8707 rtx clrw = NULL_RTX; |
8725 | 8708 |
8726 bool sign_extend = src.sbit && sign_bytes; | 8709 bool sign_extend = src.sbit && sign_bytes; |
8727 | 8710 |
8728 if (0 == dest.fbit % 8 && 7 == src.fbit % 8) | 8711 if (dest.fbit % 8 == 0 && src.fbit % 8 == 7) |
8729 shift = ASHIFT; | 8712 shift = ASHIFT; |
8730 else if (7 == dest.fbit % 8 && 0 == src.fbit % 8) | 8713 else if (dest.fbit % 8 == 7 && src.fbit % 8 == 0) |
8731 shift = ASHIFTRT; | 8714 shift = ASHIFTRT; |
8732 else if (dest.fbit % 8 == src.fbit % 8) | 8715 else if (dest.fbit % 8 == src.fbit % 8) |
8733 shift = UNKNOWN; | 8716 shift = UNKNOWN; |
8734 else | 8717 else |
8735 gcc_unreachable(); | 8718 gcc_unreachable(); |
9397 /* Some complex insns don't need length adjustment and therefore | 9380 /* Some complex insns don't need length adjustment and therefore |
9398 the length need not/must not be adjusted for these insns. | 9381 the length need not/must not be adjusted for these insns. |
9399 It is easier to state this in an insn attribute "adjust_len" than | 9382 It is easier to state this in an insn attribute "adjust_len" than |
9400 to clutter up code here... */ | 9383 to clutter up code here... */ |
9401 | 9384 |
9402 if (!NONDEBUG_INSN_P (insn) | 9385 if (!NONDEBUG_INSN_P (insn) || recog_memoized (insn) == -1) |
9403 || -1 == recog_memoized (insn)) | |
9404 { | 9386 { |
9405 return len; | 9387 return len; |
9406 } | 9388 } |
9407 | 9389 |
9408 /* Read from insn attribute "adjust_len" if/how length is to be adjusted. */ | 9390 /* Read from insn attribute "adjust_len" if/how length is to be adjusted. */ |
9869 return x; | 9851 return x; |
9870 } | 9852 } |
9871 | 9853 |
9872 | 9854 |
9873 /* AVR attributes. */ | 9855 /* AVR attributes. */ |
9874 static const struct attribute_spec | 9856 static const struct attribute_spec avr_attribute_table[] = |
9875 avr_attribute_table[] = | 9857 { |
9876 { | 9858 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, |
9877 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, | 9859 affects_type_identity, handler, exclude } */ |
9878 affects_type_identity } */ | 9860 { "progmem", 0, 0, false, false, false, false, |
9879 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute, | 9861 avr_handle_progmem_attribute, NULL }, |
9880 false }, | 9862 { "signal", 0, 0, true, false, false, false, |
9881 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute, | 9863 avr_handle_fndecl_attribute, NULL }, |
9882 false }, | 9864 { "interrupt", 0, 0, true, false, false, false, |
9883 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute, | 9865 avr_handle_fndecl_attribute, NULL }, |
9884 false }, | 9866 { "no_gccisr", 0, 0, true, false, false, false, |
9885 { "no_gccisr", 0, 0, true, false, false, avr_handle_fndecl_attribute, | 9867 avr_handle_fndecl_attribute, NULL }, |
9886 false }, | 9868 { "naked", 0, 0, false, true, true, false, |
9887 { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute, | 9869 avr_handle_fntype_attribute, NULL }, |
9888 false }, | 9870 { "OS_task", 0, 0, false, true, true, false, |
9889 { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute, | 9871 avr_handle_fntype_attribute, NULL }, |
9890 false }, | 9872 { "OS_main", 0, 0, false, true, true, false, |
9891 { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute, | 9873 avr_handle_fntype_attribute, NULL }, |
9892 false }, | 9874 { "io", 0, 1, true, false, false, false, |
9893 { "io", 0, 1, true, false, false, avr_handle_addr_attribute, | 9875 avr_handle_addr_attribute, NULL }, |
9894 false }, | 9876 { "io_low", 0, 1, true, false, false, false, |
9895 { "io_low", 0, 1, true, false, false, avr_handle_addr_attribute, | 9877 avr_handle_addr_attribute, NULL }, |
9896 false }, | 9878 { "address", 1, 1, true, false, false, false, |
9897 { "address", 1, 1, true, false, false, avr_handle_addr_attribute, | 9879 avr_handle_addr_attribute, NULL }, |
9898 false }, | 9880 { "absdata", 0, 0, true, false, false, false, |
9899 { "absdata", 0, 0, true, false, false, avr_handle_absdata_attribute, | 9881 avr_handle_absdata_attribute, NULL }, |
9900 false }, | 9882 { NULL, 0, 0, false, false, false, false, NULL, NULL } |
9901 { NULL, 0, 0, false, false, false, NULL, false } | |
9902 }; | 9883 }; |
9903 | 9884 |
9904 | 9885 |
9905 /* Return true if we support address space AS for the architecture in effect | 9886 /* Return true if we support address space AS for the architecture in effect |
9906 and false, otherwise. If LOC is not UNKNOWN_LOCATION then also issue | 9887 and false, otherwise. If LOC is not UNKNOWN_LOCATION then also issue |
10100 | 10081 |
10101 return reason == NULL; | 10082 return reason == NULL; |
10102 } | 10083 } |
10103 | 10084 |
10104 | 10085 |
10105 /* Add the section attribute if the variable is in progmem. */ | 10086 /* Implement `TARGET_INSERT_ATTRIBUTES'. */ |
10106 | 10087 |
10107 static void | 10088 static void |
10108 avr_insert_attributes (tree node, tree *attributes) | 10089 avr_insert_attributes (tree node, tree *attributes) |
10109 { | 10090 { |
10110 avr_pgm_check_var_decl (node); | 10091 avr_pgm_check_var_decl (node); |
10092 | |
10093 if (TARGET_MAIN_IS_OS_TASK | |
10094 && TREE_CODE (node) == FUNCTION_DECL | |
10095 && MAIN_NAME_P (DECL_NAME (node)) | |
10096 // FIXME: We'd like to also test `flag_hosted' which is only | |
10097 // available in the C-ish fronts, hence no such test for now. | |
10098 // Instead, we test the return type of "main" which is not exactly | |
10099 // the same but good enough. | |
10100 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (node))) | |
10101 && NULL == lookup_attribute ("OS_task", *attributes)) | |
10102 { | |
10103 *attributes = tree_cons (get_identifier ("OS_task"), | |
10104 NULL, *attributes); | |
10105 } | |
10106 | |
10107 /* Add the section attribute if the variable is in progmem. */ | |
10111 | 10108 |
10112 if (TREE_CODE (node) == VAR_DECL | 10109 if (TREE_CODE (node) == VAR_DECL |
10113 && (TREE_STATIC (node) || DECL_EXTERNAL (node)) | 10110 && (TREE_STATIC (node) || DECL_EXTERNAL (node)) |
10114 && avr_progmem_p (node, *attributes)) | 10111 && avr_progmem_p (node, *attributes)) |
10115 { | 10112 { |
10262 /* Override section callbacks to keep track of `avr_need_clear_bss_p' | 10259 /* Override section callbacks to keep track of `avr_need_clear_bss_p' |
10263 resp. `avr_need_copy_data_p'. If flash is not mapped to RAM then | 10260 resp. `avr_need_copy_data_p'. If flash is not mapped to RAM then |
10264 we have also to track .rodata because it is located in RAM then. */ | 10261 we have also to track .rodata because it is located in RAM then. */ |
10265 | 10262 |
10266 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH | 10263 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH |
10267 if (0 == avr_arch->flash_pm_offset) | 10264 if (avr_arch->flash_pm_offset == 0) |
10268 #endif | 10265 #endif |
10269 readonly_data_section->unnamed.callback = avr_output_data_section_asm_op; | 10266 readonly_data_section->unnamed.callback = avr_output_data_section_asm_op; |
10270 data_section->unnamed.callback = avr_output_data_section_asm_op; | 10267 data_section->unnamed.callback = avr_output_data_section_asm_op; |
10271 bss_section->unnamed.callback = avr_output_bss_section_asm_op; | 10268 bss_section->unnamed.callback = avr_output_bss_section_asm_op; |
10272 } | 10269 } |
10300 avr_need_copy_data_p = (STR_PREFIX_P (name, ".data") | 10297 avr_need_copy_data_p = (STR_PREFIX_P (name, ".data") |
10301 || STR_PREFIX_P (name, ".gnu.linkonce.d")); | 10298 || STR_PREFIX_P (name, ".gnu.linkonce.d")); |
10302 | 10299 |
10303 if (!avr_need_copy_data_p | 10300 if (!avr_need_copy_data_p |
10304 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH | 10301 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH |
10305 && 0 == avr_arch->flash_pm_offset | 10302 && avr_arch->flash_pm_offset == 0 |
10306 #endif | 10303 #endif |
10307 ) | 10304 ) |
10308 avr_need_copy_data_p = (STR_PREFIX_P (name, ".rodata") | 10305 avr_need_copy_data_p = (STR_PREFIX_P (name, ".rodata") |
10309 || STR_PREFIX_P (name, ".gnu.linkonce.r")); | 10306 || STR_PREFIX_P (name, ".gnu.linkonce.r")); |
10310 | 10307 |
10436 addr_space_t as = TYPE_ADDR_SPACE (type); | 10433 addr_space_t as = TYPE_ADDR_SPACE (type); |
10437 | 10434 |
10438 /* PSTR strings are in generic space but located in flash: | 10435 /* PSTR strings are in generic space but located in flash: |
10439 patch address space. */ | 10436 patch address space. */ |
10440 | 10437 |
10441 if (!AVR_TINY | 10438 if (!AVR_TINY && avr_progmem_p (decl, attr) == -1) |
10442 && -1 == avr_progmem_p (decl, attr)) | |
10443 as = ADDR_SPACE_FLASH; | 10439 as = ADDR_SPACE_FLASH; |
10444 | 10440 |
10445 AVR_SYMBOL_SET_ADDR_SPACE (sym, as); | 10441 AVR_SYMBOL_SET_ADDR_SPACE (sym, as); |
10446 | 10442 |
10447 tree io_low_attr = lookup_attribute ("io_low", attr); | 10443 tree io_low_attr = lookup_attribute ("io_low", attr); |
10476 && VAR_DECL == TREE_CODE (decl) | 10472 && VAR_DECL == TREE_CODE (decl) |
10477 && MEM_P (rtl) | 10473 && MEM_P (rtl) |
10478 && SYMBOL_REF_P (XEXP (rtl, 0))) | 10474 && SYMBOL_REF_P (XEXP (rtl, 0))) |
10479 { | 10475 { |
10480 rtx sym = XEXP (rtl, 0); | 10476 rtx sym = XEXP (rtl, 0); |
10481 bool progmem_p = -1 == avr_progmem_p (decl, DECL_ATTRIBUTES (decl)); | 10477 bool progmem_p = avr_progmem_p (decl, DECL_ATTRIBUTES (decl)) == -1; |
10482 | 10478 |
10483 if (progmem_p) | 10479 if (progmem_p) |
10484 { | 10480 { |
10485 // Tag symbols for addition of 0x4000 (avr_arch->flash_pm_offset). | 10481 // Tag symbols for addition of 0x4000 (avr_arch->flash_pm_offset). |
10486 SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_PM; | 10482 SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_PM; |
12088 and thus is suitable to be skipped by CPSE, SBRC, etc. */ | 12084 and thus is suitable to be skipped by CPSE, SBRC, etc. */ |
12089 | 12085 |
12090 static bool | 12086 static bool |
12091 avr_2word_insn_p (rtx_insn *insn) | 12087 avr_2word_insn_p (rtx_insn *insn) |
12092 { | 12088 { |
12093 if (TARGET_SKIP_BUG | 12089 if (TARGET_SKIP_BUG || !insn || get_attr_length (insn) != 2) |
12094 || !insn | |
12095 || 2 != get_attr_length (insn)) | |
12096 { | 12090 { |
12097 return false; | 12091 return false; |
12098 } | 12092 } |
12099 | 12093 |
12100 switch (INSN_CODE (insn)) | 12094 switch (INSN_CODE (insn)) |
12399 rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0); | 12393 rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0); |
12400 rtx hi16 = simplify_gen_subreg (HImode, src, mode, 2); | 12394 rtx hi16 = simplify_gen_subreg (HImode, src, mode, 2); |
12401 | 12395 |
12402 if (INTVAL (lo16) == INTVAL (hi16)) | 12396 if (INTVAL (lo16) == INTVAL (hi16)) |
12403 { | 12397 { |
12404 if (0 != INTVAL (lo16) | 12398 if (INTVAL (lo16) != 0 || !clear_p) |
12405 || !clear_p) | 12399 avr_asm_len ("movw %C0,%A0", &op[0], len, 1); |
12406 { | |
12407 avr_asm_len ("movw %C0,%A0", &op[0], len, 1); | |
12408 } | |
12409 | 12400 |
12410 break; | 12401 break; |
12411 } | 12402 } |
12412 } | 12403 } |
12413 | 12404 |
12455 if (done_byte) | 12446 if (done_byte) |
12456 continue; | 12447 continue; |
12457 | 12448 |
12458 /* Need no clobber reg for -1: Use CLR/DEC */ | 12449 /* Need no clobber reg for -1: Use CLR/DEC */ |
12459 | 12450 |
12460 if (-1 == ival[n]) | 12451 if (ival[n] == -1) |
12461 { | 12452 { |
12462 if (!clear_p) | 12453 if (!clear_p) |
12463 avr_asm_len ("clr %0", &xdest[n], len, 1); | 12454 avr_asm_len ("clr %0", &xdest[n], len, 1); |
12464 | 12455 |
12465 avr_asm_len ("dec %0", &xdest[n], len, 1); | 12456 avr_asm_len ("dec %0", &xdest[n], len, 1); |
12466 continue; | 12457 continue; |
12467 } | 12458 } |
12468 else if (1 == ival[n]) | 12459 else if (ival[n] == 1) |
12469 { | 12460 { |
12470 if (!clear_p) | 12461 if (!clear_p) |
12471 avr_asm_len ("clr %0", &xdest[n], len, 1); | 12462 avr_asm_len ("clr %0", &xdest[n], len, 1); |
12472 | 12463 |
12473 avr_asm_len ("inc %0", &xdest[n], len, 1); | 12464 avr_asm_len ("inc %0", &xdest[n], len, 1); |
13687 | 13678 |
13688 bool | 13679 bool |
13689 avr_has_nibble_0xf (rtx ival) | 13680 avr_has_nibble_0xf (rtx ival) |
13690 { | 13681 { |
13691 unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode); | 13682 unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode); |
13692 return 0 != avr_map_metric (map, MAP_MASK_PREIMAGE_F); | 13683 return avr_map_metric (map, MAP_MASK_PREIMAGE_F) != 0; |
13693 } | 13684 } |
13694 | 13685 |
13695 | 13686 |
13696 /* We have a set of bits that are mapped by a function F. | 13687 /* We have a set of bits that are mapped by a function F. |
13697 Try to decompose F by means of a second function G so that | 13688 Try to decompose F by means of a second function G so that |
13754 If result.cost < 0 then such a decomposition does not exist. */ | 13745 If result.cost < 0 then such a decomposition does not exist. */ |
13755 | 13746 |
13756 static avr_map_op_t | 13747 static avr_map_op_t |
13757 avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p) | 13748 avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p) |
13758 { | 13749 { |
13759 bool val_used_p = 0 != avr_map_metric (f, MAP_MASK_PREIMAGE_F); | 13750 bool val_used_p = avr_map_metric (f, MAP_MASK_PREIMAGE_F) != 0; |
13760 avr_map_op_t f_ginv = *g; | 13751 avr_map_op_t f_ginv = *g; |
13761 unsigned int ginv = g->ginv; | 13752 unsigned int ginv = g->ginv; |
13762 | 13753 |
13763 f_ginv.cost = -1; | 13754 f_ginv.cost = -1; |
13764 | 13755 |
13785 The overall cost of doing an operation prior to the insertion is | 13776 The overall cost of doing an operation prior to the insertion is |
13786 the cost of the insertion plus the cost of the operation. */ | 13777 the cost of the insertion plus the cost of the operation. */ |
13787 | 13778 |
13788 /* Step 2a: Compute cost of F o G^-1 */ | 13779 /* Step 2a: Compute cost of F o G^-1 */ |
13789 | 13780 |
13790 if (0 == avr_map_metric (f_ginv.map, MAP_NONFIXED_0_7)) | 13781 if (avr_map_metric (f_ginv.map, MAP_NONFIXED_0_7) == 0) |
13791 { | 13782 /* The mapping consists only of fixed points and can be folded |
13792 /* The mapping consists only of fixed points and can be folded | 13783 to AND/OR logic in the remainder. Reasonable cost is 3. */ |
13793 to AND/OR logic in the remainder. Reasonable cost is 3. */ | 13784 f_ginv.cost = 2 + (val_used_p && !val_const_p); |
13794 | |
13795 f_ginv.cost = 2 + (val_used_p && !val_const_p); | |
13796 } | |
13797 else | 13785 else |
13798 { | 13786 { |
13799 rtx xop[4]; | 13787 rtx xop[4]; |
13800 | 13788 |
13801 /* Get the cost of the insn by calling the output worker with some | 13789 /* Get the cost of the insn by calling the output worker with some |
14497 | 14485 |
14498 tmap = wide_int_to_tree (map_type, wi::to_wide (arg[0])); | 14486 tmap = wide_int_to_tree (map_type, wi::to_wide (arg[0])); |
14499 map = TREE_INT_CST_LOW (tmap); | 14487 map = TREE_INT_CST_LOW (tmap); |
14500 | 14488 |
14501 if (TREE_CODE (tval) != INTEGER_CST | 14489 if (TREE_CODE (tval) != INTEGER_CST |
14502 && 0 == avr_map_metric (map, MAP_MASK_PREIMAGE_F)) | 14490 && avr_map_metric (map, MAP_MASK_PREIMAGE_F) == 0) |
14503 { | 14491 { |
14504 /* There are no F in the map, i.e. 3rd operand is unused. | 14492 /* There are no F in the map, i.e. 3rd operand is unused. |
14505 Replace that argument with some constant to render | 14493 Replace that argument with some constant to render |
14506 respective input unused. */ | 14494 respective input unused. */ |
14507 | 14495 |
14508 tval = build_int_cst (val_type, 0); | 14496 tval = build_int_cst (val_type, 0); |
14509 changed = true; | 14497 changed = true; |
14510 } | 14498 } |
14511 | 14499 |
14512 if (TREE_CODE (tbits) != INTEGER_CST | 14500 if (TREE_CODE (tbits) != INTEGER_CST |
14513 && 0 == avr_map_metric (map, MAP_PREIMAGE_0_7)) | 14501 && avr_map_metric (map, MAP_PREIMAGE_0_7) == 0) |
14514 { | 14502 { |
14515 /* Similar for the bits to be inserted. If they are unused, | 14503 /* Similar for the bits to be inserted. If they are unused, |
14516 we can just as well pass 0. */ | 14504 we can just as well pass 0. */ |
14517 | 14505 |
14518 tbits = build_int_cst (val_type, 0); | 14506 tbits = build_int_cst (val_type, 0); |
14547 return build_call_expr (fndecl, 3, tmap, tbits, tval); | 14535 return build_call_expr (fndecl, 3, tmap, tbits, tval); |
14548 | 14536 |
14549 /* If bits don't change their position we can use vanilla logic | 14537 /* If bits don't change their position we can use vanilla logic |
14550 to merge the two arguments. */ | 14538 to merge the two arguments. */ |
14551 | 14539 |
14552 if (0 == avr_map_metric (map, MAP_NONFIXED_0_7)) | 14540 if (avr_map_metric (map, MAP_NONFIXED_0_7) == 0) |
14553 { | 14541 { |
14554 int mask_f = avr_map_metric (map, MAP_MASK_PREIMAGE_F); | 14542 int mask_f = avr_map_metric (map, MAP_MASK_PREIMAGE_F); |
14555 tree tres, tmask = build_int_cst (val_type, mask_f ^ 0xff); | 14543 tree tres, tmask = build_int_cst (val_type, mask_f ^ 0xff); |
14556 | 14544 |
14557 tres = fold_build2 (BIT_XOR_EXPR, val_type, tbits, tval); | 14545 tres = fold_build2 (BIT_XOR_EXPR, val_type, tbits, tval); |