Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/avr/avr.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | 855418dad1a3 |
children | b7f97abdc517 |
comparison
equal
deleted
inserted
replaced
52:c156f1bd5cd9 | 55:77e2b8dfacca |
---|---|
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, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, | 2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, |
3 2009 Free Software Foundation, Inc. | 3 2009 Free Software Foundation, Inc. |
4 Contributed by Denis Chertykov (denisc@overta.ru) | 4 Contributed by Denis Chertykov (chertykov@gmail.com) |
5 | 5 |
6 This file is part of GCC. | 6 This file is part of GCC. |
7 | 7 |
8 GCC is free software; you can redistribute it and/or modify | 8 GCC is free software; you can redistribute it and/or modify |
9 it under the terms of the GNU General Public License as published by | 9 it under the terms of the GNU General Public License as published by |
60 static const char *ptrreg_to_str (int); | 60 static const char *ptrreg_to_str (int); |
61 static const char *cond_string (enum rtx_code); | 61 static const char *cond_string (enum rtx_code); |
62 static int avr_num_arg_regs (enum machine_mode, tree); | 62 static int avr_num_arg_regs (enum machine_mode, tree); |
63 | 63 |
64 static RTX_CODE compare_condition (rtx insn); | 64 static RTX_CODE compare_condition (rtx insn); |
65 static rtx avr_legitimize_address (rtx, rtx, enum machine_mode); | |
65 static int compare_sign_p (rtx insn); | 66 static int compare_sign_p (rtx insn); |
66 static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *); | 67 static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *); |
67 static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *); | 68 static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *); |
68 static tree avr_handle_fntype_attribute (tree *, tree, tree, int, bool *); | 69 static tree avr_handle_fntype_attribute (tree *, tree, tree, int, bool *); |
69 const struct attribute_spec avr_attribute_table[]; | |
70 static bool avr_assemble_integer (rtx, unsigned int, int); | 70 static bool avr_assemble_integer (rtx, unsigned int, int); |
71 static void avr_file_start (void); | 71 static void avr_file_start (void); |
72 static void avr_file_end (void); | 72 static void avr_file_end (void); |
73 static bool avr_legitimate_address_p (enum machine_mode, rtx, bool); | |
73 static void avr_asm_function_end_prologue (FILE *); | 74 static void avr_asm_function_end_prologue (FILE *); |
74 static void avr_asm_function_begin_epilogue (FILE *); | 75 static void avr_asm_function_begin_epilogue (FILE *); |
75 static rtx avr_function_value (const_tree, const_tree, bool); | 76 static rtx avr_function_value (const_tree, const_tree, bool); |
76 static void avr_insert_attributes (tree, tree *); | 77 static void avr_insert_attributes (tree, tree *); |
77 static void avr_asm_init_sections (void); | 78 static void avr_asm_init_sections (void); |
85 static int avr_address_cost (rtx, bool); | 86 static int avr_address_cost (rtx, bool); |
86 static bool avr_return_in_memory (const_tree, const_tree); | 87 static bool avr_return_in_memory (const_tree, const_tree); |
87 static struct machine_function * avr_init_machine_status (void); | 88 static struct machine_function * avr_init_machine_status (void); |
88 static rtx avr_builtin_setjmp_frame_value (void); | 89 static rtx avr_builtin_setjmp_frame_value (void); |
89 static bool avr_hard_regno_scratch_ok (unsigned int); | 90 static bool avr_hard_regno_scratch_ok (unsigned int); |
91 static unsigned int avr_case_values_threshold (void); | |
92 static bool avr_frame_pointer_required_p (void); | |
93 static bool avr_can_eliminate (const int, const int); | |
90 | 94 |
91 /* Allocate registers from r25 to r8 for parameters for function calls. */ | 95 /* Allocate registers from r25 to r8 for parameters for function calls. */ |
92 #define FIRST_CUM_REG 26 | 96 #define FIRST_CUM_REG 26 |
93 | 97 |
94 /* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */ | 98 /* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */ |
98 static GTY(()) rtx zero_reg_rtx; | 102 static GTY(()) rtx zero_reg_rtx; |
99 | 103 |
100 /* AVR register names {"r0", "r1", ..., "r31"} */ | 104 /* AVR register names {"r0", "r1", ..., "r31"} */ |
101 static const char *const avr_regnames[] = REGISTER_NAMES; | 105 static const char *const avr_regnames[] = REGISTER_NAMES; |
102 | 106 |
103 /* This holds the last insn address. */ | |
104 static int last_insn_address = 0; | |
105 | |
106 /* Preprocessor macros to define depending on MCU type. */ | 107 /* Preprocessor macros to define depending on MCU type. */ |
107 const char *avr_extra_arch_macro; | 108 const char *avr_extra_arch_macro; |
108 | 109 |
109 /* Current architecture. */ | 110 /* Current architecture. */ |
110 const struct base_arch_s *avr_current_arch; | 111 const struct base_arch_s *avr_current_arch; |
111 | 112 |
113 /* Current device. */ | |
114 const struct mcu_type_s *avr_current_device; | |
115 | |
112 section *progmem_section; | 116 section *progmem_section; |
113 | 117 |
114 static const struct base_arch_s avr_arch_types[] = { | 118 /* AVR attributes. */ |
115 { 1, 0, 0, 0, 0, 0, 0, 0, NULL }, /* unknown device specified */ | 119 static const struct attribute_spec avr_attribute_table[] = |
116 { 1, 0, 0, 0, 0, 0, 0, 0, "__AVR_ARCH__=1" }, | 120 { |
117 { 0, 0, 0, 0, 0, 0, 0, 0, "__AVR_ARCH__=2" }, | 121 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ |
118 { 0, 0, 0, 1, 0, 0, 0, 0, "__AVR_ARCH__=25" }, | 122 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute }, |
119 { 0, 0, 1, 0, 0, 0, 0, 0, "__AVR_ARCH__=3" }, | 123 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute }, |
120 { 0, 0, 1, 0, 1, 0, 0, 0, "__AVR_ARCH__=31" }, | 124 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute }, |
121 { 0, 0, 1, 1, 0, 0, 0, 0, "__AVR_ARCH__=35" }, | 125 { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute }, |
122 { 0, 1, 0, 1, 0, 0, 0, 0, "__AVR_ARCH__=4" }, | 126 { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute }, |
123 { 0, 1, 1, 1, 0, 0, 0, 0, "__AVR_ARCH__=5" }, | 127 { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute }, |
124 { 0, 1, 1, 1, 1, 1, 0, 0, "__AVR_ARCH__=51" }, | 128 { NULL, 0, 0, false, false, false, NULL } |
125 { 0, 1, 1, 1, 1, 1, 1, 0, "__AVR_ARCH__=6" } | |
126 }; | 129 }; |
127 | |
128 /* These names are used as the index into the avr_arch_types[] table | |
129 above. */ | |
130 | |
131 enum avr_arch | |
132 { | |
133 ARCH_UNKNOWN, | |
134 ARCH_AVR1, | |
135 ARCH_AVR2, | |
136 ARCH_AVR25, | |
137 ARCH_AVR3, | |
138 ARCH_AVR31, | |
139 ARCH_AVR35, | |
140 ARCH_AVR4, | |
141 ARCH_AVR5, | |
142 ARCH_AVR51, | |
143 ARCH_AVR6 | |
144 }; | |
145 | |
146 struct mcu_type_s { | |
147 const char *const name; | |
148 int arch; /* index in avr_arch_types[] */ | |
149 /* Must lie outside user's namespace. NULL == no macro. */ | |
150 const char *const macro; | |
151 }; | |
152 | |
153 /* List of all known AVR MCU types - if updated, it has to be kept | |
154 in sync in several places (FIXME: is there a better way?): | |
155 - here | |
156 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS) | |
157 - t-avr (MULTILIB_MATCHES) | |
158 - gas/config/tc-avr.c | |
159 - avr-libc */ | |
160 | |
161 static const struct mcu_type_s avr_mcu_types[] = { | |
162 /* Classic, <= 8K. */ | |
163 { "avr2", ARCH_AVR2, NULL }, | |
164 { "at90s2313", ARCH_AVR2, "__AVR_AT90S2313__" }, | |
165 { "at90s2323", ARCH_AVR2, "__AVR_AT90S2323__" }, | |
166 { "at90s2333", ARCH_AVR2, "__AVR_AT90S2333__" }, | |
167 { "at90s2343", ARCH_AVR2, "__AVR_AT90S2343__" }, | |
168 { "attiny22", ARCH_AVR2, "__AVR_ATtiny22__" }, | |
169 { "attiny26", ARCH_AVR2, "__AVR_ATtiny26__" }, | |
170 { "at90s4414", ARCH_AVR2, "__AVR_AT90S4414__" }, | |
171 { "at90s4433", ARCH_AVR2, "__AVR_AT90S4433__" }, | |
172 { "at90s4434", ARCH_AVR2, "__AVR_AT90S4434__" }, | |
173 { "at90s8515", ARCH_AVR2, "__AVR_AT90S8515__" }, | |
174 { "at90c8534", ARCH_AVR2, "__AVR_AT90C8534__" }, | |
175 { "at90s8535", ARCH_AVR2, "__AVR_AT90S8535__" }, | |
176 /* Classic + MOVW, <= 8K. */ | |
177 { "avr25", ARCH_AVR25, NULL }, | |
178 { "ata6289", ARCH_AVR25, "__AVR_ATA6289__" }, | |
179 { "attiny13", ARCH_AVR25, "__AVR_ATtiny13__" }, | |
180 { "attiny13a", ARCH_AVR25, "__AVR_ATtiny13A__" }, | |
181 { "attiny2313", ARCH_AVR25, "__AVR_ATtiny2313__" }, | |
182 { "attiny24", ARCH_AVR25, "__AVR_ATtiny24__" }, | |
183 { "attiny44", ARCH_AVR25, "__AVR_ATtiny44__" }, | |
184 { "attiny84", ARCH_AVR25, "__AVR_ATtiny84__" }, | |
185 { "attiny25", ARCH_AVR25, "__AVR_ATtiny25__" }, | |
186 { "attiny45", ARCH_AVR25, "__AVR_ATtiny45__" }, | |
187 { "attiny85", ARCH_AVR25, "__AVR_ATtiny85__" }, | |
188 { "attiny261", ARCH_AVR25, "__AVR_ATtiny261__" }, | |
189 { "attiny461", ARCH_AVR25, "__AVR_ATtiny461__" }, | |
190 { "attiny861", ARCH_AVR25, "__AVR_ATtiny861__" }, | |
191 { "attiny43u", ARCH_AVR25, "__AVR_ATtiny43U__" }, | |
192 { "attiny87", ARCH_AVR25, "__AVR_ATtiny87__" }, | |
193 { "attiny48", ARCH_AVR25, "__AVR_ATtiny48__" }, | |
194 { "attiny88", ARCH_AVR25, "__AVR_ATtiny88__" }, | |
195 { "at86rf401", ARCH_AVR25, "__AVR_AT86RF401__" }, | |
196 /* Classic, > 8K, <= 64K. */ | |
197 { "avr3", ARCH_AVR3, NULL }, | |
198 { "at43usb355", ARCH_AVR3, "__AVR_AT43USB355__" }, | |
199 { "at76c711", ARCH_AVR3, "__AVR_AT76C711__" }, | |
200 /* Classic, == 128K. */ | |
201 { "avr31", ARCH_AVR31, NULL }, | |
202 { "atmega103", ARCH_AVR31, "__AVR_ATmega103__" }, | |
203 { "at43usb320", ARCH_AVR31, "__AVR_AT43USB320__" }, | |
204 /* Classic + MOVW + JMP/CALL. */ | |
205 { "avr35", ARCH_AVR35, NULL }, | |
206 { "at90usb82", ARCH_AVR35, "__AVR_AT90USB82__" }, | |
207 { "at90usb162", ARCH_AVR35, "__AVR_AT90USB162__" }, | |
208 { "attiny167", ARCH_AVR35, "__AVR_ATtiny167__" }, | |
209 { "attiny327", ARCH_AVR35, "__AVR_ATtiny327__" }, | |
210 /* Enhanced, <= 8K. */ | |
211 { "avr4", ARCH_AVR4, NULL }, | |
212 { "atmega8", ARCH_AVR4, "__AVR_ATmega8__" }, | |
213 { "atmega48", ARCH_AVR4, "__AVR_ATmega48__" }, | |
214 { "atmega48p", ARCH_AVR4, "__AVR_ATmega48P__" }, | |
215 { "atmega88", ARCH_AVR4, "__AVR_ATmega88__" }, | |
216 { "atmega88p", ARCH_AVR4, "__AVR_ATmega88P__" }, | |
217 { "atmega8515", ARCH_AVR4, "__AVR_ATmega8515__" }, | |
218 { "atmega8535", ARCH_AVR4, "__AVR_ATmega8535__" }, | |
219 { "atmega8hva", ARCH_AVR4, "__AVR_ATmega8HVA__" }, | |
220 { "atmega4hvd", ARCH_AVR4, "__AVR_ATmega4HVD__" }, | |
221 { "atmega8hvd", ARCH_AVR4, "__AVR_ATmega8HVD__" }, | |
222 { "atmega8c1", ARCH_AVR4, "__AVR_ATmega8C1__" }, | |
223 { "atmega8m1", ARCH_AVR4, "__AVR_ATmega8M1__" }, | |
224 { "at90pwm1", ARCH_AVR4, "__AVR_AT90PWM1__" }, | |
225 { "at90pwm2", ARCH_AVR4, "__AVR_AT90PWM2__" }, | |
226 { "at90pwm2b", ARCH_AVR4, "__AVR_AT90PWM2B__" }, | |
227 { "at90pwm3", ARCH_AVR4, "__AVR_AT90PWM3__" }, | |
228 { "at90pwm3b", ARCH_AVR4, "__AVR_AT90PWM3B__" }, | |
229 { "at90pwm81", ARCH_AVR4, "__AVR_AT90PWM81__" }, | |
230 /* Enhanced, > 8K, <= 64K. */ | |
231 { "avr5", ARCH_AVR5, NULL }, | |
232 { "atmega16", ARCH_AVR5, "__AVR_ATmega16__" }, | |
233 { "atmega161", ARCH_AVR5, "__AVR_ATmega161__" }, | |
234 { "atmega162", ARCH_AVR5, "__AVR_ATmega162__" }, | |
235 { "atmega163", ARCH_AVR5, "__AVR_ATmega163__" }, | |
236 { "atmega164p", ARCH_AVR5, "__AVR_ATmega164P__" }, | |
237 { "atmega165", ARCH_AVR5, "__AVR_ATmega165__" }, | |
238 { "atmega165p", ARCH_AVR5, "__AVR_ATmega165P__" }, | |
239 { "atmega168", ARCH_AVR5, "__AVR_ATmega168__" }, | |
240 { "atmega168p", ARCH_AVR5, "__AVR_ATmega168P__" }, | |
241 { "atmega169", ARCH_AVR5, "__AVR_ATmega169__" }, | |
242 { "atmega169p", ARCH_AVR5, "__AVR_ATmega169P__" }, | |
243 { "atmega32", ARCH_AVR5, "__AVR_ATmega32__" }, | |
244 { "atmega323", ARCH_AVR5, "__AVR_ATmega323__" }, | |
245 { "atmega324p", ARCH_AVR5, "__AVR_ATmega324P__" }, | |
246 { "atmega325", ARCH_AVR5, "__AVR_ATmega325__" }, | |
247 { "atmega325p", ARCH_AVR5, "__AVR_ATmega325P__" }, | |
248 { "atmega3250", ARCH_AVR5, "__AVR_ATmega3250__" }, | |
249 { "atmega3250p", ARCH_AVR5, "__AVR_ATmega3250P__" }, | |
250 { "atmega328p", ARCH_AVR5, "__AVR_ATmega328P__" }, | |
251 { "atmega329", ARCH_AVR5, "__AVR_ATmega329__" }, | |
252 { "atmega329p", ARCH_AVR5, "__AVR_ATmega329P__" }, | |
253 { "atmega3290", ARCH_AVR5, "__AVR_ATmega3290__" }, | |
254 { "atmega3290p", ARCH_AVR5, "__AVR_ATmega3290P__" }, | |
255 { "atmega406", ARCH_AVR5, "__AVR_ATmega406__" }, | |
256 { "atmega64", ARCH_AVR5, "__AVR_ATmega64__" }, | |
257 { "atmega640", ARCH_AVR5, "__AVR_ATmega640__" }, | |
258 { "atmega644", ARCH_AVR5, "__AVR_ATmega644__" }, | |
259 { "atmega644p", ARCH_AVR5, "__AVR_ATmega644P__" }, | |
260 { "atmega645", ARCH_AVR5, "__AVR_ATmega645__" }, | |
261 { "atmega6450", ARCH_AVR5, "__AVR_ATmega6450__" }, | |
262 { "atmega649", ARCH_AVR5, "__AVR_ATmega649__" }, | |
263 { "atmega6490", ARCH_AVR5, "__AVR_ATmega6490__" }, | |
264 { "atmega16hva", ARCH_AVR5, "__AVR_ATmega16HVA__" }, | |
265 { "atmega16hvb", ARCH_AVR5, "__AVR_ATmega16HVB__" }, | |
266 { "atmega32hvb", ARCH_AVR5, "__AVR_ATmega32HVB__" }, | |
267 { "at90can32", ARCH_AVR5, "__AVR_AT90CAN32__" }, | |
268 { "at90can64", ARCH_AVR5, "__AVR_AT90CAN64__" }, | |
269 { "at90pwm216", ARCH_AVR5, "__AVR_AT90PWM216__" }, | |
270 { "at90pwm316", ARCH_AVR5, "__AVR_AT90PWM316__" }, | |
271 { "atmega16c1", ARCH_AVR5, "__AVR_ATmega16C1__" }, | |
272 { "atmega32c1", ARCH_AVR5, "__AVR_ATmega32C1__" }, | |
273 { "atmega64c1", ARCH_AVR5, "__AVR_ATmega64C1__" }, | |
274 { "atmega16m1", ARCH_AVR5, "__AVR_ATmega16M1__" }, | |
275 { "atmega32m1", ARCH_AVR5, "__AVR_ATmega32M1__" }, | |
276 { "atmega64m1", ARCH_AVR5, "__AVR_ATmega64M1__" }, | |
277 { "atmega16u4", ARCH_AVR5, "__AVR_ATmega16U4__" }, | |
278 { "atmega32u4", ARCH_AVR5, "__AVR_ATmega32U4__" }, | |
279 { "atmega32u6", ARCH_AVR5, "__AVR_ATmega32U6__" }, | |
280 { "at90scr100", ARCH_AVR5, "__AVR_AT90SCR100__" }, | |
281 { "at90usb646", ARCH_AVR5, "__AVR_AT90USB646__" }, | |
282 { "at90usb647", ARCH_AVR5, "__AVR_AT90USB647__" }, | |
283 { "at94k", ARCH_AVR5, "__AVR_AT94K__" }, | |
284 /* Enhanced, == 128K. */ | |
285 { "avr51", ARCH_AVR51, NULL }, | |
286 { "atmega128", ARCH_AVR51, "__AVR_ATmega128__" }, | |
287 { "atmega1280", ARCH_AVR51, "__AVR_ATmega1280__" }, | |
288 { "atmega1281", ARCH_AVR51, "__AVR_ATmega1281__" }, | |
289 { "atmega1284p", ARCH_AVR51, "__AVR_ATmega1284P__" }, | |
290 { "atmega128rfa1", ARCH_AVR51, "__AVR_ATmega128RFA1__" }, | |
291 { "at90can128", ARCH_AVR51, "__AVR_AT90CAN128__" }, | |
292 { "at90usb1286", ARCH_AVR51, "__AVR_AT90USB1286__" }, | |
293 { "at90usb1287", ARCH_AVR51, "__AVR_AT90USB1287__" }, | |
294 { "m3000f", ARCH_AVR51, "__AVR_M3000F__" }, | |
295 { "m3000s", ARCH_AVR51, "__AVR_M3000S__" }, | |
296 { "m3001b", ARCH_AVR51, "__AVR_M3001B__" }, | |
297 /* 3-Byte PC. */ | |
298 { "avr6", ARCH_AVR6, NULL }, | |
299 { "atmega2560", ARCH_AVR6, "__AVR_ATmega2560__" }, | |
300 { "atmega2561", ARCH_AVR6, "__AVR_ATmega2561__" }, | |
301 /* Assembler only. */ | |
302 { "avr1", ARCH_AVR1, NULL }, | |
303 { "at90s1200", ARCH_AVR1, "__AVR_AT90S1200__" }, | |
304 { "attiny11", ARCH_AVR1, "__AVR_ATtiny11__" }, | |
305 { "attiny12", ARCH_AVR1, "__AVR_ATtiny12__" }, | |
306 { "attiny15", ARCH_AVR1, "__AVR_ATtiny15__" }, | |
307 { "attiny28", ARCH_AVR1, "__AVR_ATtiny28__" }, | |
308 { NULL, ARCH_UNKNOWN, NULL } | |
309 }; | |
310 | |
311 int avr_case_values_threshold = 30000; | |
312 | 130 |
313 /* Initialize the GCC target structure. */ | 131 /* Initialize the GCC target structure. */ |
314 #undef TARGET_ASM_ALIGNED_HI_OP | 132 #undef TARGET_ASM_ALIGNED_HI_OP |
315 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t" | 133 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t" |
316 #undef TARGET_ASM_ALIGNED_SI_OP | 134 #undef TARGET_ASM_ALIGNED_SI_OP |
347 #undef TARGET_ADDRESS_COST | 165 #undef TARGET_ADDRESS_COST |
348 #define TARGET_ADDRESS_COST avr_address_cost | 166 #define TARGET_ADDRESS_COST avr_address_cost |
349 #undef TARGET_MACHINE_DEPENDENT_REORG | 167 #undef TARGET_MACHINE_DEPENDENT_REORG |
350 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg | 168 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg |
351 | 169 |
170 #undef TARGET_LEGITIMIZE_ADDRESS | |
171 #define TARGET_LEGITIMIZE_ADDRESS avr_legitimize_address | |
172 | |
352 #undef TARGET_RETURN_IN_MEMORY | 173 #undef TARGET_RETURN_IN_MEMORY |
353 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory | 174 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory |
354 | 175 |
355 #undef TARGET_STRICT_ARGUMENT_NAMING | 176 #undef TARGET_STRICT_ARGUMENT_NAMING |
356 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true | 177 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true |
358 #undef TARGET_BUILTIN_SETJMP_FRAME_VALUE | 179 #undef TARGET_BUILTIN_SETJMP_FRAME_VALUE |
359 #define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value | 180 #define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value |
360 | 181 |
361 #undef TARGET_HARD_REGNO_SCRATCH_OK | 182 #undef TARGET_HARD_REGNO_SCRATCH_OK |
362 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok | 183 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok |
184 #undef TARGET_CASE_VALUES_THRESHOLD | |
185 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold | |
186 | |
187 #undef TARGET_LEGITIMATE_ADDRESS_P | |
188 #define TARGET_LEGITIMATE_ADDRESS_P avr_legitimate_address_p | |
189 | |
190 #undef TARGET_FRAME_POINTER_REQUIRED | |
191 #define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p | |
192 #undef TARGET_CAN_ELIMINATE | |
193 #define TARGET_CAN_ELIMINATE avr_can_eliminate | |
363 | 194 |
364 struct gcc_target targetm = TARGET_INITIALIZER; | 195 struct gcc_target targetm = TARGET_INITIALIZER; |
365 | 196 |
366 void | 197 void |
367 avr_override_options (void) | 198 avr_override_options (void) |
368 { | 199 { |
369 const struct mcu_type_s *t; | 200 const struct mcu_type_s *t; |
370 static bool warned_no_tablejump_deprecated = false; | |
371 | 201 |
372 flag_delete_null_pointer_checks = 0; | 202 flag_delete_null_pointer_checks = 0; |
373 | |
374 if (!PARAM_SET_P (PARAM_INLINE_CALL_COST)) | |
375 set_param_value ("inline-call-cost", 5); | |
376 | 203 |
377 for (t = avr_mcu_types; t->name; t++) | 204 for (t = avr_mcu_types; t->name; t++) |
378 if (strcmp (t->name, avr_mcu_name) == 0) | 205 if (strcmp (t->name, avr_mcu_name) == 0) |
379 break; | 206 break; |
380 | 207 |
384 avr_mcu_name); | 211 avr_mcu_name); |
385 for (t = avr_mcu_types; t->name; t++) | 212 for (t = avr_mcu_types; t->name; t++) |
386 fprintf (stderr," %s\n", t->name); | 213 fprintf (stderr," %s\n", t->name); |
387 } | 214 } |
388 | 215 |
389 avr_current_arch = &avr_arch_types[t->arch]; | 216 avr_current_device = t; |
390 avr_extra_arch_macro = t->macro; | 217 avr_current_arch = &avr_arch_types[avr_current_device->arch]; |
391 | 218 avr_extra_arch_macro = avr_current_device->macro; |
392 if (optimize && !TARGET_NO_TABLEJUMP) | |
393 avr_case_values_threshold = | |
394 (!AVR_HAVE_JMP_CALL || TARGET_CALL_PROLOGUES) ? 8 : 17; | |
395 | |
396 if (TARGET_NO_TABLEJUMP | |
397 && !warned_no_tablejump_deprecated) | |
398 { | |
399 inform (input_location, "the -mno-tablejump switch is deprecated"); | |
400 inform (input_location, "GCC 4.4 is the last release with this switch"); | |
401 inform (input_location, "use the -fno-jump-tables switch instead"); | |
402 warned_no_tablejump_deprecated = true; | |
403 } | |
404 | 219 |
405 tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO); | 220 tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO); |
406 zero_reg_rtx = gen_rtx_REG (QImode, ZERO_REGNO); | 221 zero_reg_rtx = gen_rtx_REG (QImode, ZERO_REGNO); |
407 | 222 |
408 init_machine_status = avr_init_machine_status; | 223 init_machine_status = avr_init_machine_status; |
409 } | 224 } |
410 | 225 |
411 /* return register class from register number. */ | 226 /* return register class from register number. */ |
412 | 227 |
413 static const int reg_class_tab[]={ | 228 static const enum reg_class reg_class_tab[]={ |
414 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS, | 229 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS, |
415 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS, | 230 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS, |
416 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS, | 231 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS, |
417 GENERAL_REGS, /* r0 - r15 */ | 232 GENERAL_REGS, /* r0 - r15 */ |
418 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS, | 233 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS, |
520 { | 335 { |
521 int reg, count; | 336 int reg, count; |
522 int int_or_sig_p = (interrupt_function_p (current_function_decl) | 337 int int_or_sig_p = (interrupt_function_p (current_function_decl) |
523 || signal_function_p (current_function_decl)); | 338 || signal_function_p (current_function_decl)); |
524 | 339 |
525 if (!reload_completed) | |
526 cfun->machine->is_leaf = leaf_function_p (); | |
527 | |
528 if (set) | 340 if (set) |
529 CLEAR_HARD_REG_SET (*set); | 341 CLEAR_HARD_REG_SET (*set); |
530 count = 0; | 342 count = 0; |
531 | 343 |
532 /* No need to save any registers if the function never returns or | 344 /* No need to save any registers if the function never returns or |
541 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as | 353 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as |
542 any global register variables. */ | 354 any global register variables. */ |
543 if (fixed_regs[reg]) | 355 if (fixed_regs[reg]) |
544 continue; | 356 continue; |
545 | 357 |
546 if ((int_or_sig_p && !cfun->machine->is_leaf && call_used_regs[reg]) | 358 if ((int_or_sig_p && !current_function_is_leaf && call_used_regs[reg]) |
547 || (df_regs_ever_live_p (reg) | 359 || (df_regs_ever_live_p (reg) |
548 && (int_or_sig_p || !call_used_regs[reg]) | 360 && (int_or_sig_p || !call_used_regs[reg]) |
549 && !(frame_pointer_needed | 361 && !(frame_pointer_needed |
550 && (reg == REG_Y || reg == (REG_Y+1))))) | 362 && (reg == REG_Y || reg == (REG_Y+1))))) |
551 { | 363 { |
555 } | 367 } |
556 } | 368 } |
557 return count; | 369 return count; |
558 } | 370 } |
559 | 371 |
372 /* Return true if register FROM can be eliminated via register TO. */ | |
373 | |
374 bool | |
375 avr_can_eliminate (const int from, const int to) | |
376 { | |
377 return ((from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) | |
378 || ((from == FRAME_POINTER_REGNUM | |
379 || from == FRAME_POINTER_REGNUM + 1) | |
380 && !frame_pointer_needed)); | |
381 } | |
382 | |
560 /* Compute offset between arg_pointer and frame_pointer. */ | 383 /* Compute offset between arg_pointer and frame_pointer. */ |
561 | 384 |
562 int | 385 int |
563 initial_elimination_offset (int from, int to) | 386 avr_initial_elimination_offset (int from, int to) |
564 { | 387 { |
565 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) | 388 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) |
566 return 0; | 389 return 0; |
567 else | 390 else |
568 { | 391 { |
581 | 404 |
582 rtx avr_builtin_setjmp_frame_value (void) | 405 rtx avr_builtin_setjmp_frame_value (void) |
583 { | 406 { |
584 return gen_rtx_MINUS (Pmode, virtual_stack_vars_rtx, | 407 return gen_rtx_MINUS (Pmode, virtual_stack_vars_rtx, |
585 gen_int_mode (STARTING_FRAME_OFFSET, Pmode)); | 408 gen_int_mode (STARTING_FRAME_OFFSET, Pmode)); |
409 } | |
410 | |
411 /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3 byte PC). | |
412 This is return address of function. */ | |
413 rtx | |
414 avr_return_addr_rtx (int count, const_rtx tem) | |
415 { | |
416 rtx r; | |
417 | |
418 /* Can only return this functions return address. Others not supported. */ | |
419 if (count) | |
420 return NULL; | |
421 | |
422 if (AVR_3_BYTE_PC) | |
423 { | |
424 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2"); | |
425 warning (0, "'builtin_return_address' contains only 2 bytes of address"); | |
426 } | |
427 else | |
428 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1"); | |
429 | |
430 r = gen_rtx_PLUS (Pmode, tem, r); | |
431 r = gen_frame_mem (Pmode, memory_address (Pmode, r)); | |
432 r = gen_rtx_ROTATE (HImode, r, GEN_INT (8)); | |
433 return r; | |
586 } | 434 } |
587 | 435 |
588 /* Return 1 if the function epilogue is just a single "ret". */ | 436 /* Return 1 if the function epilogue is just a single "ret". */ |
589 | 437 |
590 int | 438 int |
675 rtx pushbyte = gen_rtx_MEM (QImode, | 523 rtx pushbyte = gen_rtx_MEM (QImode, |
676 gen_rtx_POST_DEC (HImode, stack_pointer_rtx)); | 524 gen_rtx_POST_DEC (HImode, stack_pointer_rtx)); |
677 rtx pushword = gen_rtx_MEM (HImode, | 525 rtx pushword = gen_rtx_MEM (HImode, |
678 gen_rtx_POST_DEC (HImode, stack_pointer_rtx)); | 526 gen_rtx_POST_DEC (HImode, stack_pointer_rtx)); |
679 rtx insn; | 527 rtx insn; |
680 | |
681 last_insn_address = 0; | |
682 | 528 |
683 /* Init cfun->machine. */ | 529 /* Init cfun->machine. */ |
684 cfun->machine->is_naked = avr_naked_function_p (current_function_decl); | 530 cfun->machine->is_naked = avr_naked_function_p (current_function_decl); |
685 cfun->machine->is_interrupt = interrupt_function_p (current_function_decl); | 531 cfun->machine->is_interrupt = interrupt_function_p (current_function_decl); |
686 cfun->machine->is_signal = signal_function_p (current_function_decl); | 532 cfun->machine->is_signal = signal_function_p (current_function_decl); |
687 cfun->machine->is_OS_task = avr_OS_task_function_p (current_function_decl); | 533 cfun->machine->is_OS_task = avr_OS_task_function_p (current_function_decl); |
688 cfun->machine->is_OS_main = avr_OS_main_function_p (current_function_decl); | 534 cfun->machine->is_OS_main = avr_OS_main_function_p (current_function_decl); |
535 cfun->machine->stack_usage = 0; | |
689 | 536 |
690 /* Prologue: naked. */ | 537 /* Prologue: naked. */ |
691 if (cfun->machine->is_naked) | 538 if (cfun->machine->is_naked) |
692 { | 539 { |
693 return; | 540 return; |
712 } | 559 } |
713 | 560 |
714 /* Push zero reg. */ | 561 /* Push zero reg. */ |
715 insn = emit_move_insn (pushbyte, zero_reg_rtx); | 562 insn = emit_move_insn (pushbyte, zero_reg_rtx); |
716 RTX_FRAME_RELATED_P (insn) = 1; | 563 RTX_FRAME_RELATED_P (insn) = 1; |
564 cfun->machine->stack_usage++; | |
717 | 565 |
718 /* Push tmp reg. */ | 566 /* Push tmp reg. */ |
719 insn = emit_move_insn (pushbyte, tmp_reg_rtx); | 567 insn = emit_move_insn (pushbyte, tmp_reg_rtx); |
720 RTX_FRAME_RELATED_P (insn) = 1; | 568 RTX_FRAME_RELATED_P (insn) = 1; |
569 cfun->machine->stack_usage++; | |
721 | 570 |
722 /* Push SREG. */ | 571 /* Push SREG. */ |
723 insn = emit_move_insn (tmp_reg_rtx, | 572 insn = emit_move_insn (tmp_reg_rtx, |
724 gen_rtx_MEM (QImode, GEN_INT (SREG_ADDR))); | 573 gen_rtx_MEM (QImode, GEN_INT (SREG_ADDR))); |
725 RTX_FRAME_RELATED_P (insn) = 1; | 574 RTX_FRAME_RELATED_P (insn) = 1; |
726 insn = emit_move_insn (pushbyte, tmp_reg_rtx); | 575 insn = emit_move_insn (pushbyte, tmp_reg_rtx); |
727 RTX_FRAME_RELATED_P (insn) = 1; | 576 RTX_FRAME_RELATED_P (insn) = 1; |
577 cfun->machine->stack_usage++; | |
728 | 578 |
729 /* Push RAMPZ. */ | 579 /* Push RAMPZ. */ |
730 if(AVR_HAVE_RAMPZ | 580 if(AVR_HAVE_RAMPZ |
731 && (TEST_HARD_REG_BIT (set, REG_Z) && TEST_HARD_REG_BIT (set, REG_Z + 1))) | 581 && (TEST_HARD_REG_BIT (set, REG_Z) && TEST_HARD_REG_BIT (set, REG_Z + 1))) |
732 { | 582 { |
733 insn = emit_move_insn (tmp_reg_rtx, | 583 insn = emit_move_insn (tmp_reg_rtx, |
734 gen_rtx_MEM (QImode, GEN_INT (RAMPZ_ADDR))); | 584 gen_rtx_MEM (QImode, GEN_INT (RAMPZ_ADDR))); |
735 RTX_FRAME_RELATED_P (insn) = 1; | 585 RTX_FRAME_RELATED_P (insn) = 1; |
736 insn = emit_move_insn (pushbyte, tmp_reg_rtx); | 586 insn = emit_move_insn (pushbyte, tmp_reg_rtx); |
737 RTX_FRAME_RELATED_P (insn) = 1; | 587 RTX_FRAME_RELATED_P (insn) = 1; |
588 cfun->machine->stack_usage++; | |
738 } | 589 } |
739 | 590 |
740 /* Clear zero reg. */ | 591 /* Clear zero reg. */ |
741 insn = emit_move_insn (zero_reg_rtx, const0_rtx); | 592 insn = emit_move_insn (zero_reg_rtx, const0_rtx); |
742 RTX_FRAME_RELATED_P (insn) = 1; | 593 RTX_FRAME_RELATED_P (insn) = 1; |
754 | 605 |
755 insn = | 606 insn = |
756 emit_insn (gen_call_prologue_saves (gen_int_mode (live_seq, HImode), | 607 emit_insn (gen_call_prologue_saves (gen_int_mode (live_seq, HImode), |
757 gen_int_mode (size + live_seq, HImode))); | 608 gen_int_mode (size + live_seq, HImode))); |
758 RTX_FRAME_RELATED_P (insn) = 1; | 609 RTX_FRAME_RELATED_P (insn) = 1; |
610 cfun->machine->stack_usage += size + live_seq; | |
759 } | 611 } |
760 else | 612 else |
761 { | 613 { |
762 int reg; | 614 int reg; |
763 for (reg = 0; reg < 32; ++reg) | 615 for (reg = 0; reg < 32; ++reg) |
765 if (TEST_HARD_REG_BIT (set, reg)) | 617 if (TEST_HARD_REG_BIT (set, reg)) |
766 { | 618 { |
767 /* Emit push of register to save. */ | 619 /* Emit push of register to save. */ |
768 insn=emit_move_insn (pushbyte, gen_rtx_REG (QImode, reg)); | 620 insn=emit_move_insn (pushbyte, gen_rtx_REG (QImode, reg)); |
769 RTX_FRAME_RELATED_P (insn) = 1; | 621 RTX_FRAME_RELATED_P (insn) = 1; |
622 cfun->machine->stack_usage++; | |
770 } | 623 } |
771 } | 624 } |
772 if (frame_pointer_needed) | 625 if (frame_pointer_needed) |
773 { | 626 { |
774 if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)) | 627 if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)) |
775 { | 628 { |
776 /* Push frame pointer. */ | 629 /* Push frame pointer. */ |
777 insn = emit_move_insn (pushword, frame_pointer_rtx); | 630 insn = emit_move_insn (pushword, frame_pointer_rtx); |
778 RTX_FRAME_RELATED_P (insn) = 1; | 631 RTX_FRAME_RELATED_P (insn) = 1; |
632 cfun->machine->stack_usage += 2; | |
779 } | 633 } |
780 | 634 |
781 if (!size) | 635 if (!size) |
782 { | 636 { |
783 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); | 637 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); |
798 is selected. */ | 652 is selected. */ |
799 rtx myfp; | 653 rtx myfp; |
800 rtx fp_plus_insns; | 654 rtx fp_plus_insns; |
801 rtx sp_plus_insns = NULL_RTX; | 655 rtx sp_plus_insns = NULL_RTX; |
802 | 656 |
803 if (TARGET_TINY_STACK) | 657 if (AVR_HAVE_8BIT_SP) |
804 { | 658 { |
805 /* The high byte (r29) doesn't change - prefer 'subi' (1 cycle) | 659 /* The high byte (r29) doesn't change - prefer 'subi' (1 cycle) |
806 over 'sbiw' (2 cycles, same size). */ | 660 over 'sbiw' (2 cycles, same size). */ |
807 myfp = gen_rtx_REG (QImode, REGNO (frame_pointer_rtx)); | 661 myfp = gen_rtx_REG (QImode, REGNO (frame_pointer_rtx)); |
808 } | 662 } |
824 gen_int_mode (-size, | 678 gen_int_mode (-size, |
825 GET_MODE(myfp)))); | 679 GET_MODE(myfp)))); |
826 RTX_FRAME_RELATED_P (insn) = 1; | 680 RTX_FRAME_RELATED_P (insn) = 1; |
827 | 681 |
828 /* Copy to stack pointer. */ | 682 /* Copy to stack pointer. */ |
829 if (TARGET_TINY_STACK) | 683 if (AVR_HAVE_8BIT_SP) |
830 { | 684 { |
831 insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); | 685 insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); |
832 RTX_FRAME_RELATED_P (insn) = 1; | 686 RTX_FRAME_RELATED_P (insn) = 1; |
833 } | 687 } |
834 else if (TARGET_NO_INTERRUPTS | 688 else if (TARGET_NO_INTERRUPTS |
880 if (size <= 6 && (get_sequence_length (sp_plus_insns) | 734 if (size <= 6 && (get_sequence_length (sp_plus_insns) |
881 < get_sequence_length (fp_plus_insns))) | 735 < get_sequence_length (fp_plus_insns))) |
882 emit_insn (sp_plus_insns); | 736 emit_insn (sp_plus_insns); |
883 else | 737 else |
884 emit_insn (fp_plus_insns); | 738 emit_insn (fp_plus_insns); |
739 cfun->machine->stack_usage += size; | |
885 } | 740 } |
886 } | 741 } |
887 } | 742 } |
888 } | 743 } |
889 | 744 |
909 else | 764 else |
910 fputs ("/* prologue: function */\n", file); | 765 fputs ("/* prologue: function */\n", file); |
911 } | 766 } |
912 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n", | 767 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n", |
913 get_frame_size()); | 768 get_frame_size()); |
769 fprintf (file, "/* stack size = %d */\n", | |
770 cfun->machine->stack_usage); | |
771 /* Create symbol stack offset here so all functions have it. Add 1 to stack | |
772 usage for offset so that SP + .L__stack_offset = return address. */ | |
773 fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage); | |
914 } | 774 } |
915 | 775 |
916 | 776 |
917 /* Implement EPILOGUE_USES. */ | 777 /* Implement EPILOGUE_USES. */ |
918 | 778 |
978 /* Try two methods to adjust stack and select shortest. */ | 838 /* Try two methods to adjust stack and select shortest. */ |
979 rtx myfp; | 839 rtx myfp; |
980 rtx fp_plus_insns; | 840 rtx fp_plus_insns; |
981 rtx sp_plus_insns = NULL_RTX; | 841 rtx sp_plus_insns = NULL_RTX; |
982 | 842 |
983 if (TARGET_TINY_STACK) | 843 if (AVR_HAVE_8BIT_SP) |
984 { | 844 { |
985 /* The high byte (r29) doesn't change - prefer 'subi' | 845 /* The high byte (r29) doesn't change - prefer 'subi' |
986 (1 cycle) over 'sbiw' (2 cycles, same size). */ | 846 (1 cycle) over 'sbiw' (2 cycles, same size). */ |
987 myfp = gen_rtx_REG (QImode, REGNO (frame_pointer_rtx)); | 847 myfp = gen_rtx_REG (QImode, REGNO (frame_pointer_rtx)); |
988 } | 848 } |
999 gen_rtx_PLUS (GET_MODE (myfp), myfp, | 859 gen_rtx_PLUS (GET_MODE (myfp), myfp, |
1000 gen_int_mode (size, | 860 gen_int_mode (size, |
1001 GET_MODE(myfp)))); | 861 GET_MODE(myfp)))); |
1002 | 862 |
1003 /* Copy to stack pointer. */ | 863 /* Copy to stack pointer. */ |
1004 if (TARGET_TINY_STACK) | 864 if (AVR_HAVE_8BIT_SP) |
1005 { | 865 { |
1006 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); | 866 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); |
1007 } | 867 } |
1008 else if (TARGET_NO_INTERRUPTS | 868 else if (TARGET_NO_INTERRUPTS |
1009 || cfun->machine->is_signal) | 869 || cfun->machine->is_signal) |
1094 } | 954 } |
1095 | 955 |
1096 /* Return nonzero if X (an RTX) is a legitimate memory address on the target | 956 /* Return nonzero if X (an RTX) is a legitimate memory address on the target |
1097 machine for a memory operand of mode MODE. */ | 957 machine for a memory operand of mode MODE. */ |
1098 | 958 |
1099 int | 959 bool |
1100 legitimate_address_p (enum machine_mode mode, rtx x, int strict) | 960 avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) |
1101 { | 961 { |
1102 enum reg_class r = NO_REGS; | 962 enum reg_class r = NO_REGS; |
1103 | 963 |
1104 if (TARGET_ALL_DEBUG) | 964 if (TARGET_ALL_DEBUG) |
1105 { | 965 { |
1163 | 1023 |
1164 /* Attempts to replace X with a valid | 1024 /* Attempts to replace X with a valid |
1165 memory address for an operand of mode MODE */ | 1025 memory address for an operand of mode MODE */ |
1166 | 1026 |
1167 rtx | 1027 rtx |
1168 legitimize_address (rtx x, rtx oldx, enum machine_mode mode) | 1028 avr_legitimize_address (rtx x, rtx oldx, enum machine_mode mode) |
1169 { | 1029 { |
1170 x = oldx; | 1030 x = oldx; |
1171 if (TARGET_ALL_DEBUG) | 1031 if (TARGET_ALL_DEBUG) |
1172 { | 1032 { |
1173 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode)); | 1033 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode)); |
1261 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0)))); | 1121 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0)))); |
1262 break; | 1122 break; |
1263 | 1123 |
1264 default: | 1124 default: |
1265 if (CONSTANT_ADDRESS_P (addr) | 1125 if (CONSTANT_ADDRESS_P (addr) |
1266 && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr)) | 1126 && text_segment_operand (addr, VOIDmode)) |
1267 || GET_CODE (addr) == LABEL_REF)) | 1127 { |
1268 { | 1128 rtx x = XEXP (addr,0); |
1269 fprintf (file, "gs("); | 1129 if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x,1)) == CONST_INT) |
1270 output_addr_const (file,addr); | 1130 { |
1271 fprintf (file ,")"); | 1131 /* Assembler gs() will implant word address. Make offset |
1132 a byte offset inside gs() for assembler. This is | |
1133 needed because the more logical (constant+gs(sym)) is not | |
1134 accepted by gas. For 128K and lower devices this is ok. For | |
1135 large devices it will create a Trampoline to offset from symbol | |
1136 which may not be what the user really wanted. */ | |
1137 fprintf (file, "gs("); | |
1138 output_addr_const (file, XEXP (x,0)); | |
1139 fprintf (file,"+" HOST_WIDE_INT_PRINT_DEC ")", 2 * INTVAL (XEXP (x,1))); | |
1140 if (AVR_3_BYTE_PC) | |
1141 if (warning ( 0, "Pointer offset from symbol maybe incorrect.")) | |
1142 { | |
1143 output_addr_const (stderr, addr); | |
1144 fprintf(stderr,"\n"); | |
1145 } | |
1146 } | |
1147 else | |
1148 { | |
1149 fprintf (file, "gs("); | |
1150 output_addr_const (file, addr); | |
1151 fprintf (file, ")"); | |
1152 } | |
1272 } | 1153 } |
1273 else | 1154 else |
1274 output_addr_const (file, addr); | 1155 output_addr_const (file, addr); |
1275 } | 1156 } |
1276 } | 1157 } |
1306 else if (GET_CODE (x) == CONST_INT) | 1187 else if (GET_CODE (x) == CONST_INT) |
1307 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd); | 1188 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd); |
1308 else if (GET_CODE (x) == MEM) | 1189 else if (GET_CODE (x) == MEM) |
1309 { | 1190 { |
1310 rtx addr = XEXP (x,0); | 1191 rtx addr = XEXP (x,0); |
1311 | 1192 if (code == 'm') |
1312 if (CONSTANT_P (addr) && abcd) | 1193 { |
1313 { | 1194 if (!CONSTANT_P (addr)) |
1314 fputc ('(', file); | 1195 fatal_insn ("bad address, not a constant):", addr); |
1315 output_address (addr); | 1196 /* Assembler template with m-code is data - not progmem section */ |
1316 fprintf (file, ")+%d", abcd); | 1197 if (text_segment_operand (addr, VOIDmode)) |
1198 if (warning ( 0, "accessing data memory with program memory address")) | |
1199 { | |
1200 output_addr_const (stderr, addr); | |
1201 fprintf(stderr,"\n"); | |
1202 } | |
1203 output_addr_const (file, addr); | |
1317 } | 1204 } |
1318 else if (code == 'o') | 1205 else if (code == 'o') |
1319 { | 1206 { |
1320 if (GET_CODE (addr) != PLUS) | 1207 if (GET_CODE (addr) != PLUS) |
1321 fatal_insn ("bad address, not (reg+disp):", addr); | 1208 fatal_insn ("bad address, not (reg+disp):", addr); |
1342 print_operand (file, XEXP (addr,1), code); | 1229 print_operand (file, XEXP (addr,1), code); |
1343 } | 1230 } |
1344 else | 1231 else |
1345 print_operand_address (file, addr); | 1232 print_operand_address (file, addr); |
1346 } | 1233 } |
1234 else if (code == 'x') | |
1235 { | |
1236 /* Constant progmem address - like used in jmp or call */ | |
1237 if (0 == text_segment_operand (x, VOIDmode)) | |
1238 if (warning ( 0, "accessing program memory with data memory address")) | |
1239 { | |
1240 output_addr_const (stderr, x); | |
1241 fprintf(stderr,"\n"); | |
1242 } | |
1243 /* Use normal symbol for direct address no linker trampoline needed */ | |
1244 output_addr_const (file, x); | |
1245 } | |
1347 else if (GET_CODE (x) == CONST_DOUBLE) | 1246 else if (GET_CODE (x) == CONST_DOUBLE) |
1348 { | 1247 { |
1349 long val; | 1248 long val; |
1350 REAL_VALUE_TYPE rv; | 1249 REAL_VALUE_TYPE rv; |
1351 if (GET_MODE (x) != SFmode) | 1250 if (GET_MODE (x) != SFmode) |
1452 3 - absolute jump (only for ATmega[16]03). */ | 1351 3 - absolute jump (only for ATmega[16]03). */ |
1453 | 1352 |
1454 int | 1353 int |
1455 avr_jump_mode (rtx x, rtx insn) | 1354 avr_jump_mode (rtx x, rtx insn) |
1456 { | 1355 { |
1457 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF | 1356 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF |
1458 ? XEXP (x, 0) : x)); | 1357 ? XEXP (x, 0) : x)); |
1459 int cur_addr = INSN_ADDRESSES (INSN_UID (insn)); | 1358 int cur_addr = INSN_ADDRESSES (INSN_UID (insn)); |
1460 int jump_distance = cur_addr - dest_addr; | 1359 int jump_distance = cur_addr - dest_addr; |
1461 | 1360 |
1462 if (-63 <= jump_distance && jump_distance <= 62) | 1361 if (-63 <= jump_distance && jump_distance <= 62) |
1578 { | 1477 { |
1579 return (GET_CODE (op) == CONST_INT | 1478 return (GET_CODE (op) == CONST_INT |
1580 && INTVAL (op) <= 0xff && INTVAL (op) >= 0); | 1479 && INTVAL (op) <= 0xff && INTVAL (op) >= 0); |
1581 } | 1480 } |
1582 | 1481 |
1583 /* Output all insn addresses and their sizes into the assembly language | 1482 /* Output insn cost for next insn. */ |
1584 output file. This is helpful for debugging whether the length attributes | |
1585 in the md file are correct. | |
1586 Output insn cost for next insn. */ | |
1587 | 1483 |
1588 void | 1484 void |
1589 final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED, | 1485 final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED, |
1590 int num_operands ATTRIBUTE_UNUSED) | 1486 int num_operands ATTRIBUTE_UNUSED) |
1591 { | 1487 { |
1592 int uid = INSN_UID (insn); | 1488 if (TARGET_ALL_DEBUG) |
1593 | 1489 { |
1594 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG) | 1490 fprintf (asm_out_file, "/* DEBUG: cost = %d. */\n", |
1595 { | |
1596 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n", | |
1597 INSN_ADDRESSES (uid), | |
1598 INSN_ADDRESSES (uid) - last_insn_address, | |
1599 rtx_cost (PATTERN (insn), INSN, !optimize_size)); | 1491 rtx_cost (PATTERN (insn), INSN, !optimize_size)); |
1600 } | 1492 } |
1601 last_insn_address = INSN_ADDRESSES (uid); | |
1602 } | 1493 } |
1603 | 1494 |
1604 /* Return 0 if undefined, 1 if always true or always false. */ | 1495 /* Return 0 if undefined, 1 if always true or always false. */ |
1605 | 1496 |
1606 int | 1497 int |
1812 { | 1703 { |
1813 if (register_operand (src, HImode)) /* mov r,r */ | 1704 if (register_operand (src, HImode)) /* mov r,r */ |
1814 { | 1705 { |
1815 if (test_hard_reg_class (STACK_REG, dest)) | 1706 if (test_hard_reg_class (STACK_REG, dest)) |
1816 { | 1707 { |
1817 if (TARGET_TINY_STACK) | 1708 if (AVR_HAVE_8BIT_SP) |
1818 return *l = 1, AS2 (out,__SP_L__,%A1); | 1709 return *l = 1, AS2 (out,__SP_L__,%A1); |
1819 /* Use simple load of stack pointer if no interrupts are | 1710 /* Use simple load of stack pointer if no interrupts are |
1820 used. */ | 1711 used. */ |
1821 else if (TARGET_NO_INTERRUPTS) | 1712 else if (TARGET_NO_INTERRUPTS) |
1822 return *l = 2, (AS2 (out,__SP_H__,%B1) CR_TAB | 1713 return *l = 2, (AS2 (out,__SP_H__,%B1) CR_TAB |
1967 return AS2 (in,%0,__SREG__); | 1858 return AS2 (in,%0,__SREG__); |
1968 } | 1859 } |
1969 if (optimize > 0 && io_address_operand (x, QImode)) | 1860 if (optimize > 0 && io_address_operand (x, QImode)) |
1970 { | 1861 { |
1971 *l = 1; | 1862 *l = 1; |
1972 return AS2 (in,%0,%1-0x20); | 1863 return AS2 (in,%0,%m1-0x20); |
1973 } | 1864 } |
1974 *l = 2; | 1865 *l = 2; |
1975 return AS2 (lds,%0,%1); | 1866 return AS2 (lds,%0,%m1); |
1976 } | 1867 } |
1977 /* memory access by reg+disp */ | 1868 /* memory access by reg+disp */ |
1978 else if (GET_CODE (x) == PLUS | 1869 else if (GET_CODE (x) == PLUS |
1979 && REG_P (XEXP (x,0)) | 1870 && REG_P (XEXP (x,0)) |
1980 && GET_CODE (XEXP (x,1)) == CONST_INT) | 1871 && GET_CODE (XEXP (x,1)) == CONST_INT) |
2155 else if (CONSTANT_ADDRESS_P (base)) | 2046 else if (CONSTANT_ADDRESS_P (base)) |
2156 { | 2047 { |
2157 if (optimize > 0 && io_address_operand (base, HImode)) | 2048 if (optimize > 0 && io_address_operand (base, HImode)) |
2158 { | 2049 { |
2159 *l = 2; | 2050 *l = 2; |
2160 return (AS2 (in,%A0,%A1-0x20) CR_TAB | 2051 return (AS2 (in,%A0,%m1-0x20) CR_TAB |
2161 AS2 (in,%B0,%B1-0x20)); | 2052 AS2 (in,%B0,%m1+1-0x20)); |
2162 } | 2053 } |
2163 *l = 4; | 2054 *l = 4; |
2164 return (AS2 (lds,%A0,%A1) CR_TAB | 2055 return (AS2 (lds,%A0,%m1) CR_TAB |
2165 AS2 (lds,%B0,%B1)); | 2056 AS2 (lds,%B0,%m1+1)); |
2166 } | 2057 } |
2167 | 2058 |
2168 fatal_insn ("unknown move insn:",insn); | 2059 fatal_insn ("unknown move insn:",insn); |
2169 return ""; | 2060 return ""; |
2170 } | 2061 } |
2319 return *l=4, (AS2 (ld,%A0,%1) CR_TAB | 2210 return *l=4, (AS2 (ld,%A0,%1) CR_TAB |
2320 AS2 (ld,%B0,%1) CR_TAB | 2211 AS2 (ld,%B0,%1) CR_TAB |
2321 AS2 (ld,%C0,%1) CR_TAB | 2212 AS2 (ld,%C0,%1) CR_TAB |
2322 AS2 (ld,%D0,%1)); | 2213 AS2 (ld,%D0,%1)); |
2323 else if (CONSTANT_ADDRESS_P (base)) | 2214 else if (CONSTANT_ADDRESS_P (base)) |
2324 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB | 2215 return *l=8, (AS2 (lds,%A0,%m1) CR_TAB |
2325 AS2 (lds,%B0,%B1) CR_TAB | 2216 AS2 (lds,%B0,%m1+1) CR_TAB |
2326 AS2 (lds,%C0,%C1) CR_TAB | 2217 AS2 (lds,%C0,%m1+2) CR_TAB |
2327 AS2 (lds,%D0,%D1)); | 2218 AS2 (lds,%D0,%m1+3)); |
2328 | 2219 |
2329 fatal_insn ("unknown move insn:",insn); | 2220 fatal_insn ("unknown move insn:",insn); |
2330 return ""; | 2221 return ""; |
2331 } | 2222 } |
2332 | 2223 |
2342 | 2233 |
2343 if (!l) | 2234 if (!l) |
2344 l = &tmp; | 2235 l = &tmp; |
2345 | 2236 |
2346 if (CONSTANT_ADDRESS_P (base)) | 2237 if (CONSTANT_ADDRESS_P (base)) |
2347 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB | 2238 return *l=8,(AS2 (sts,%m0,%A1) CR_TAB |
2348 AS2 (sts,%B0,%B1) CR_TAB | 2239 AS2 (sts,%m0+1,%B1) CR_TAB |
2349 AS2 (sts,%C0,%C1) CR_TAB | 2240 AS2 (sts,%m0+2,%C1) CR_TAB |
2350 AS2 (sts,%D0,%D1)); | 2241 AS2 (sts,%m0+3,%D1)); |
2351 if (reg_base > 0) /* (r) */ | 2242 if (reg_base > 0) /* (r) */ |
2352 { | 2243 { |
2353 if (reg_base == REG_X) /* (R26) */ | 2244 if (reg_base == REG_X) /* (R26) */ |
2354 { | 2245 { |
2355 if (reg_src == REG_X) | 2246 if (reg_src == REG_X) |
2655 return AS2 (out,__SREG__,%1); | 2546 return AS2 (out,__SREG__,%1); |
2656 } | 2547 } |
2657 if (optimize > 0 && io_address_operand (x, QImode)) | 2548 if (optimize > 0 && io_address_operand (x, QImode)) |
2658 { | 2549 { |
2659 *l = 1; | 2550 *l = 1; |
2660 return AS2 (out,%0-0x20,%1); | 2551 return AS2 (out,%m0-0x20,%1); |
2661 } | 2552 } |
2662 *l = 2; | 2553 *l = 2; |
2663 return AS2 (sts,%0,%1); | 2554 return AS2 (sts,%m0,%1); |
2664 } | 2555 } |
2665 /* memory access by reg+disp */ | 2556 /* memory access by reg+disp */ |
2666 else if (GET_CODE (x) == PLUS | 2557 else if (GET_CODE (x) == PLUS |
2667 && REG_P (XEXP (x,0)) | 2558 && REG_P (XEXP (x,0)) |
2668 && GET_CODE (XEXP (x,1)) == CONST_INT) | 2559 && GET_CODE (XEXP (x,1)) == CONST_INT) |
2734 if (CONSTANT_ADDRESS_P (base)) | 2625 if (CONSTANT_ADDRESS_P (base)) |
2735 { | 2626 { |
2736 if (optimize > 0 && io_address_operand (base, HImode)) | 2627 if (optimize > 0 && io_address_operand (base, HImode)) |
2737 { | 2628 { |
2738 *l = 2; | 2629 *l = 2; |
2739 return (AS2 (out,%B0-0x20,%B1) CR_TAB | 2630 return (AS2 (out,%m0+1-0x20,%B1) CR_TAB |
2740 AS2 (out,%A0-0x20,%A1)); | 2631 AS2 (out,%m0-0x20,%A1)); |
2741 } | 2632 } |
2742 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB | 2633 return *l = 4, (AS2 (sts,%m0+1,%B1) CR_TAB |
2743 AS2 (sts,%A0,%A1)); | 2634 AS2 (sts,%m0,%A1)); |
2744 } | 2635 } |
2745 if (reg_base > 0) | 2636 if (reg_base > 0) |
2746 { | 2637 { |
2747 if (reg_base == REG_X) | 2638 if (reg_base == REG_X) |
2748 { | 2639 { |
2853 return ""; | 2744 return ""; |
2854 } | 2745 } |
2855 | 2746 |
2856 /* Return 1 if frame pointer for current function required. */ | 2747 /* Return 1 if frame pointer for current function required. */ |
2857 | 2748 |
2858 int | 2749 bool |
2859 frame_pointer_required_p (void) | 2750 avr_frame_pointer_required_p (void) |
2860 { | 2751 { |
2861 return (cfun->calls_alloca | 2752 return (cfun->calls_alloca |
2862 || crtl->args.info.nregs == 0 | 2753 || crtl->args.info.nregs == 0 |
2863 || get_frame_size () > 0); | 2754 || get_frame_size () > 0); |
2864 } | 2755 } |
2910 | 2801 |
2911 | 2802 |
2912 /* Output test instruction for HImode. */ | 2803 /* Output test instruction for HImode. */ |
2913 | 2804 |
2914 const char * | 2805 const char * |
2915 out_tsthi (rtx insn, int *l) | 2806 out_tsthi (rtx insn, rtx op, int *l) |
2916 { | 2807 { |
2917 if (compare_sign_p (insn)) | 2808 if (compare_sign_p (insn)) |
2918 { | 2809 { |
2919 if (l) *l = 1; | 2810 if (l) *l = 1; |
2920 return AS1 (tst,%B0); | 2811 return AS1 (tst,%B0); |
2921 } | 2812 } |
2922 if (reg_unused_after (insn, SET_SRC (PATTERN (insn))) | 2813 if (reg_unused_after (insn, op) |
2923 && compare_eq_p (insn)) | 2814 && compare_eq_p (insn)) |
2924 { | 2815 { |
2925 /* Faster than sbiw if we can clobber the operand. */ | 2816 /* Faster than sbiw if we can clobber the operand. */ |
2926 if (l) *l = 1; | 2817 if (l) *l = 1; |
2927 return AS2 (or,%A0,%B0); | 2818 return "or %A0,%B0"; |
2928 } | 2819 } |
2929 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn)))) | 2820 if (test_hard_reg_class (ADDW_REGS, op)) |
2930 { | 2821 { |
2931 if (l) *l = 1; | 2822 if (l) *l = 1; |
2932 return AS2 (sbiw,%0,0); | 2823 return AS2 (sbiw,%0,0); |
2933 } | 2824 } |
2934 if (l) *l = 2; | 2825 if (l) *l = 2; |
2938 | 2829 |
2939 | 2830 |
2940 /* Output test instruction for SImode. */ | 2831 /* Output test instruction for SImode. */ |
2941 | 2832 |
2942 const char * | 2833 const char * |
2943 out_tstsi (rtx insn, int *l) | 2834 out_tstsi (rtx insn, rtx op, int *l) |
2944 { | 2835 { |
2945 if (compare_sign_p (insn)) | 2836 if (compare_sign_p (insn)) |
2946 { | 2837 { |
2947 if (l) *l = 1; | 2838 if (l) *l = 1; |
2948 return AS1 (tst,%D0); | 2839 return AS1 (tst,%D0); |
2949 } | 2840 } |
2950 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn)))) | 2841 if (test_hard_reg_class (ADDW_REGS, op)) |
2951 { | 2842 { |
2952 if (l) *l = 3; | 2843 if (l) *l = 3; |
2953 return (AS2 (sbiw,%A0,0) CR_TAB | 2844 return (AS2 (sbiw,%A0,0) CR_TAB |
2954 AS2 (cpc,%C0,__zero_reg__) CR_TAB | 2845 AS2 (cpc,%C0,__zero_reg__) CR_TAB |
2955 AS2 (cpc,%D0,__zero_reg__)); | 2846 AS2 (cpc,%D0,__zero_reg__)); |
3245 { | 3136 { |
3246 *len = 7; | 3137 *len = 7; |
3247 return (AS1 (swap,%A0) CR_TAB | 3138 return (AS1 (swap,%A0) CR_TAB |
3248 AS1 (swap,%B0) CR_TAB | 3139 AS1 (swap,%B0) CR_TAB |
3249 AS2 (ldi,%3,0xf0) CR_TAB | 3140 AS2 (ldi,%3,0xf0) CR_TAB |
3250 AS2 (and,%B0,%3) CR_TAB | 3141 "and %B0,%3" CR_TAB |
3251 AS2 (eor,%B0,%A0) CR_TAB | 3142 AS2 (eor,%B0,%A0) CR_TAB |
3252 AS2 (and,%A0,%3) CR_TAB | 3143 "and %A0,%3" CR_TAB |
3253 AS2 (eor,%B0,%A0)); | 3144 AS2 (eor,%B0,%A0)); |
3254 } | 3145 } |
3255 break; /* optimize_size ? 6 : 8 */ | 3146 break; /* optimize_size ? 6 : 8 */ |
3256 | 3147 |
3257 case 5: | 3148 case 5: |
3275 return (AS1 (lsl,%A0) CR_TAB | 3166 return (AS1 (lsl,%A0) CR_TAB |
3276 AS1 (rol,%B0) CR_TAB | 3167 AS1 (rol,%B0) CR_TAB |
3277 AS1 (swap,%A0) CR_TAB | 3168 AS1 (swap,%A0) CR_TAB |
3278 AS1 (swap,%B0) CR_TAB | 3169 AS1 (swap,%B0) CR_TAB |
3279 AS2 (ldi,%3,0xf0) CR_TAB | 3170 AS2 (ldi,%3,0xf0) CR_TAB |
3280 AS2 (and,%B0,%3) CR_TAB | 3171 "and %B0,%3" CR_TAB |
3281 AS2 (eor,%B0,%A0) CR_TAB | 3172 AS2 (eor,%B0,%A0) CR_TAB |
3282 AS2 (and,%A0,%3) CR_TAB | 3173 "and %A0,%3" CR_TAB |
3283 AS2 (eor,%B0,%A0)); | 3174 AS2 (eor,%B0,%A0)); |
3284 } | 3175 } |
3285 break; /* 10 */ | 3176 break; /* 10 */ |
3286 | 3177 |
3287 case 6: | 3178 case 6: |
3345 *len = 5; | 3236 *len = 5; |
3346 return (AS2 (mov,%B0,%A0) CR_TAB | 3237 return (AS2 (mov,%B0,%A0) CR_TAB |
3347 AS1 (clr,%A0) CR_TAB | 3238 AS1 (clr,%A0) CR_TAB |
3348 AS1 (swap,%B0) CR_TAB | 3239 AS1 (swap,%B0) CR_TAB |
3349 AS2 (ldi,%3,0xf0) CR_TAB | 3240 AS2 (ldi,%3,0xf0) CR_TAB |
3350 AS2 (and,%B0,%3)); | 3241 "and %B0,%3"); |
3351 } | 3242 } |
3352 *len = 6; | 3243 *len = 6; |
3353 return (AS2 (mov,%B0,%A0) CR_TAB | 3244 return (AS2 (mov,%B0,%A0) CR_TAB |
3354 AS1 (clr,%A0) CR_TAB | 3245 AS1 (clr,%A0) CR_TAB |
3355 AS1 (lsl,%B0) CR_TAB | 3246 AS1 (lsl,%B0) CR_TAB |
3384 return (AS2 (mov,%B0,%A0) CR_TAB | 3275 return (AS2 (mov,%B0,%A0) CR_TAB |
3385 AS1 (clr,%A0) CR_TAB | 3276 AS1 (clr,%A0) CR_TAB |
3386 AS1 (swap,%B0) CR_TAB | 3277 AS1 (swap,%B0) CR_TAB |
3387 AS1 (lsl,%B0) CR_TAB | 3278 AS1 (lsl,%B0) CR_TAB |
3388 AS2 (ldi,%3,0xe0) CR_TAB | 3279 AS2 (ldi,%3,0xe0) CR_TAB |
3389 AS2 (and,%B0,%3)); | 3280 "and %B0,%3"); |
3390 } | 3281 } |
3391 if (AVR_HAVE_MUL) | 3282 if (AVR_HAVE_MUL) |
3392 { | 3283 { |
3393 *len = 6; | 3284 *len = 6; |
3394 return ("set" CR_TAB | 3285 return ("set" CR_TAB |
4022 { | 3913 { |
4023 *len = 7; | 3914 *len = 7; |
4024 return (AS1 (swap,%B0) CR_TAB | 3915 return (AS1 (swap,%B0) CR_TAB |
4025 AS1 (swap,%A0) CR_TAB | 3916 AS1 (swap,%A0) CR_TAB |
4026 AS2 (ldi,%3,0x0f) CR_TAB | 3917 AS2 (ldi,%3,0x0f) CR_TAB |
4027 AS2 (and,%A0,%3) CR_TAB | 3918 "and %A0,%3" CR_TAB |
4028 AS2 (eor,%A0,%B0) CR_TAB | 3919 AS2 (eor,%A0,%B0) CR_TAB |
4029 AS2 (and,%B0,%3) CR_TAB | 3920 "and %B0,%3" CR_TAB |
4030 AS2 (eor,%A0,%B0)); | 3921 AS2 (eor,%A0,%B0)); |
4031 } | 3922 } |
4032 break; /* optimize_size ? 6 : 8 */ | 3923 break; /* optimize_size ? 6 : 8 */ |
4033 | 3924 |
4034 case 5: | 3925 case 5: |
4052 return (AS1 (lsr,%B0) CR_TAB | 3943 return (AS1 (lsr,%B0) CR_TAB |
4053 AS1 (ror,%A0) CR_TAB | 3944 AS1 (ror,%A0) CR_TAB |
4054 AS1 (swap,%B0) CR_TAB | 3945 AS1 (swap,%B0) CR_TAB |
4055 AS1 (swap,%A0) CR_TAB | 3946 AS1 (swap,%A0) CR_TAB |
4056 AS2 (ldi,%3,0x0f) CR_TAB | 3947 AS2 (ldi,%3,0x0f) CR_TAB |
4057 AS2 (and,%A0,%3) CR_TAB | 3948 "and %A0,%3" CR_TAB |
4058 AS2 (eor,%A0,%B0) CR_TAB | 3949 AS2 (eor,%A0,%B0) CR_TAB |
4059 AS2 (and,%B0,%3) CR_TAB | 3950 "and %B0,%3" CR_TAB |
4060 AS2 (eor,%A0,%B0)); | 3951 AS2 (eor,%A0,%B0)); |
4061 } | 3952 } |
4062 break; /* 10 */ | 3953 break; /* 10 */ |
4063 | 3954 |
4064 case 6: | 3955 case 6: |
4122 *len = 5; | 4013 *len = 5; |
4123 return (AS2 (mov,%A0,%B0) CR_TAB | 4014 return (AS2 (mov,%A0,%B0) CR_TAB |
4124 AS1 (clr,%B0) CR_TAB | 4015 AS1 (clr,%B0) CR_TAB |
4125 AS1 (swap,%A0) CR_TAB | 4016 AS1 (swap,%A0) CR_TAB |
4126 AS2 (ldi,%3,0x0f) CR_TAB | 4017 AS2 (ldi,%3,0x0f) CR_TAB |
4127 AS2 (and,%A0,%3)); | 4018 "and %A0,%3"); |
4128 } | 4019 } |
4129 *len = 6; | 4020 *len = 6; |
4130 return (AS2 (mov,%A0,%B0) CR_TAB | 4021 return (AS2 (mov,%A0,%B0) CR_TAB |
4131 AS1 (clr,%B0) CR_TAB | 4022 AS1 (clr,%B0) CR_TAB |
4132 AS1 (lsr,%A0) CR_TAB | 4023 AS1 (lsr,%A0) CR_TAB |
4161 return (AS2 (mov,%A0,%B0) CR_TAB | 4052 return (AS2 (mov,%A0,%B0) CR_TAB |
4162 AS1 (clr,%B0) CR_TAB | 4053 AS1 (clr,%B0) CR_TAB |
4163 AS1 (swap,%A0) CR_TAB | 4054 AS1 (swap,%A0) CR_TAB |
4164 AS1 (lsr,%A0) CR_TAB | 4055 AS1 (lsr,%A0) CR_TAB |
4165 AS2 (ldi,%3,0x07) CR_TAB | 4056 AS2 (ldi,%3,0x07) CR_TAB |
4166 AS2 (and,%A0,%3)); | 4057 "and %A0,%3"); |
4167 } | 4058 } |
4168 if (AVR_HAVE_MUL) | 4059 if (AVR_HAVE_MUL) |
4169 { | 4060 { |
4170 *len = 6; | 4061 *len = 6; |
4171 return ("set" CR_TAB | 4062 return ("set" CR_TAB |
4362 } | 4253 } |
4363 else if (op[0] == cc0_rtx && REG_P (op[1])) | 4254 else if (op[0] == cc0_rtx && REG_P (op[1])) |
4364 { | 4255 { |
4365 switch (GET_MODE (op[1])) | 4256 switch (GET_MODE (op[1])) |
4366 { | 4257 { |
4367 case HImode: out_tsthi (insn,&len); break; | 4258 case HImode: out_tsthi (insn, op[1], &len); break; |
4368 case SImode: out_tstsi (insn,&len); break; | 4259 case SImode: out_tstsi (insn, op[1], &len); break; |
4369 default: break; | 4260 default: break; |
4370 } | 4261 } |
4371 } | 4262 } |
4372 else if (GET_CODE (op[1]) == AND) | 4263 else if (GET_CODE (op[1]) == AND) |
4373 { | 4264 { |
4595 | 4486 |
4596 static bool | 4487 static bool |
4597 avr_assemble_integer (rtx x, unsigned int size, int aligned_p) | 4488 avr_assemble_integer (rtx x, unsigned int size, int aligned_p) |
4598 { | 4489 { |
4599 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p | 4490 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p |
4600 && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x)) | 4491 && text_segment_operand (x, VOIDmode) ) |
4601 || GET_CODE (x) == LABEL_REF)) | |
4602 { | 4492 { |
4603 fputs ("\t.word\tgs(", asm_out_file); | 4493 fputs ("\t.word\tgs(", asm_out_file); |
4604 output_addr_const (asm_out_file, x); | 4494 output_addr_const (asm_out_file, x); |
4605 fputs (")\n", asm_out_file); | 4495 fputs (")\n", asm_out_file); |
4606 return true; | 4496 return true; |
4737 | 4627 |
4738 /* Return value is nonzero if pseudos that have been | 4628 /* Return value is nonzero if pseudos that have been |
4739 assigned to registers of class CLASS would likely be spilled | 4629 assigned to registers of class CLASS would likely be spilled |
4740 because registers of CLASS are needed for spill registers. */ | 4630 because registers of CLASS are needed for spill registers. */ |
4741 | 4631 |
4742 enum reg_class | 4632 bool |
4743 class_likely_spilled_p (int c) | 4633 class_likely_spilled_p (int c) |
4744 { | 4634 { |
4745 return (c != ALL_REGS && c != ADDW_REGS); | 4635 return (c != ALL_REGS && c != ADDW_REGS); |
4746 } | 4636 } |
4747 | 4637 |
4753 prologue interrupts are enabled; | 4643 prologue interrupts are enabled; |
4754 naked - don't generate function prologue/epilogue and `ret' command. | 4644 naked - don't generate function prologue/epilogue and `ret' command. |
4755 | 4645 |
4756 Only `progmem' attribute valid for type. */ | 4646 Only `progmem' attribute valid for type. */ |
4757 | 4647 |
4758 const struct attribute_spec avr_attribute_table[] = | |
4759 { | |
4760 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ | |
4761 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute }, | |
4762 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute }, | |
4763 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute }, | |
4764 { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute }, | |
4765 { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute }, | |
4766 { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute }, | |
4767 { NULL, 0, 0, false, false, false, NULL } | |
4768 }; | |
4769 | |
4770 /* Handle a "progmem" attribute; arguments as in | 4648 /* Handle a "progmem" attribute; arguments as in |
4771 struct attribute_spec.handler. */ | 4649 struct attribute_spec.handler. */ |
4772 static tree | 4650 static tree |
4773 avr_handle_progmem_attribute (tree *node, tree name, | 4651 avr_handle_progmem_attribute (tree *node, tree name, |
4774 tree args ATTRIBUTE_UNUSED, | 4652 tree args ATTRIBUTE_UNUSED, |
4799 *no_add_attrs = true; | 4677 *no_add_attrs = true; |
4800 } | 4678 } |
4801 } | 4679 } |
4802 else | 4680 else |
4803 { | 4681 { |
4804 warning (OPT_Wattributes, "%qs attribute ignored", | 4682 warning (OPT_Wattributes, "%qE attribute ignored", |
4805 IDENTIFIER_POINTER (name)); | 4683 name); |
4806 *no_add_attrs = true; | 4684 *no_add_attrs = true; |
4807 } | 4685 } |
4808 } | 4686 } |
4809 | 4687 |
4810 return NULL_TREE; | 4688 return NULL_TREE; |
4819 int flags ATTRIBUTE_UNUSED, | 4697 int flags ATTRIBUTE_UNUSED, |
4820 bool *no_add_attrs) | 4698 bool *no_add_attrs) |
4821 { | 4699 { |
4822 if (TREE_CODE (*node) != FUNCTION_DECL) | 4700 if (TREE_CODE (*node) != FUNCTION_DECL) |
4823 { | 4701 { |
4824 warning (OPT_Wattributes, "%qs attribute only applies to functions", | 4702 warning (OPT_Wattributes, "%qE attribute only applies to functions", |
4825 IDENTIFIER_POINTER (name)); | 4703 name); |
4826 *no_add_attrs = true; | 4704 *no_add_attrs = true; |
4827 } | 4705 } |
4828 | 4706 |
4829 return NULL_TREE; | 4707 return NULL_TREE; |
4830 } | 4708 } |
4835 int flags ATTRIBUTE_UNUSED, | 4713 int flags ATTRIBUTE_UNUSED, |
4836 bool *no_add_attrs) | 4714 bool *no_add_attrs) |
4837 { | 4715 { |
4838 if (TREE_CODE (*node) != FUNCTION_TYPE) | 4716 if (TREE_CODE (*node) != FUNCTION_TYPE) |
4839 { | 4717 { |
4840 warning (OPT_Wattributes, "%qs attribute only applies to functions", | 4718 warning (OPT_Wattributes, "%qE attribute only applies to functions", |
4841 IDENTIFIER_POINTER (name)); | 4719 name); |
4842 *no_add_attrs = true; | 4720 *no_add_attrs = true; |
4843 } | 4721 } |
4844 | 4722 |
4845 return NULL_TREE; | 4723 return NULL_TREE; |
4846 } | 4724 } |
5061 is to be calculated. Return true if the complete cost has been | 4939 is to be calculated. Return true if the complete cost has been |
5062 computed, and false if subexpressions should be scanned. In either | 4940 computed, and false if subexpressions should be scanned. In either |
5063 case, *TOTAL contains the cost result. */ | 4941 case, *TOTAL contains the cost result. */ |
5064 | 4942 |
5065 static bool | 4943 static bool |
5066 avr_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total, | 4944 avr_rtx_costs (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED, int *total, |
5067 bool speed) | 4945 bool speed) |
5068 { | 4946 { |
4947 enum rtx_code code = (enum rtx_code) codearg; | |
5069 enum machine_mode mode = GET_MODE (x); | 4948 enum machine_mode mode = GET_MODE (x); |
5070 HOST_WIDE_INT val; | 4949 HOST_WIDE_INT val; |
5071 | 4950 |
5072 switch (code) | 4951 switch (code) |
5073 { | 4952 { |
5729 PUT_CODE (t, swap_condition (GET_CODE (t))); | 5608 PUT_CODE (t, swap_condition (GET_CODE (t))); |
5730 XEXP (pattern,0) = XEXP (pattern,1); | 5609 XEXP (pattern,0) = XEXP (pattern,1); |
5731 XEXP (pattern,1) = x; | 5610 XEXP (pattern,1) = x; |
5732 INSN_CODE (next) = -1; | 5611 INSN_CODE (next) = -1; |
5733 } | 5612 } |
5613 else if (true_regnum (XEXP (pattern, 0)) >= 0 | |
5614 && XEXP (pattern, 1) == const0_rtx) | |
5615 { | |
5616 /* This is a tst insn, we can reverse it. */ | |
5617 rtx next = next_real_insn (insn); | |
5618 rtx pat = PATTERN (next); | |
5619 rtx src = SET_SRC (pat); | |
5620 rtx t = XEXP (src,0); | |
5621 | |
5622 PUT_CODE (t, swap_condition (GET_CODE (t))); | |
5623 XEXP (pattern, 1) = XEXP (pattern, 0); | |
5624 XEXP (pattern, 0) = const0_rtx; | |
5625 INSN_CODE (next) = -1; | |
5626 INSN_CODE (insn) = -1; | |
5627 } | |
5734 else if (true_regnum (XEXP (pattern,0)) >= 0 | 5628 else if (true_regnum (XEXP (pattern,0)) >= 0 |
5735 && GET_CODE (XEXP (pattern,1)) == CONST_INT) | 5629 && GET_CODE (XEXP (pattern,1)) == CONST_INT) |
5736 { | 5630 { |
5737 rtx x = XEXP (pattern,1); | 5631 rtx x = XEXP (pattern,1); |
5738 rtx next = next_real_insn (insn); | 5632 rtx next = next_real_insn (insn); |
5747 PUT_CODE (t, avr_normalize_condition (GET_CODE (t))); | 5641 PUT_CODE (t, avr_normalize_condition (GET_CODE (t))); |
5748 INSN_CODE (next) = -1; | 5642 INSN_CODE (next) = -1; |
5749 INSN_CODE (insn) = -1; | 5643 INSN_CODE (insn) = -1; |
5750 } | 5644 } |
5751 } | 5645 } |
5752 } | |
5753 else if (true_regnum (SET_SRC (pattern)) >= 0) | |
5754 { | |
5755 /* This is a tst insn */ | |
5756 rtx next = next_real_insn (insn); | |
5757 rtx pat = PATTERN (next); | |
5758 rtx src = SET_SRC (pat); | |
5759 rtx t = XEXP (src,0); | |
5760 | |
5761 PUT_CODE (t, swap_condition (GET_CODE (t))); | |
5762 SET_SRC (pattern) = gen_rtx_COMPARE (GET_MODE (SET_SRC (pattern)), const0_rtx, | |
5763 SET_SRC (pattern)); | |
5764 INSN_CODE (next) = -1; | |
5765 INSN_CODE (insn) = -1; | |
5766 } | 5646 } |
5767 } | 5647 } |
5768 } | 5648 } |
5769 } | 5649 } |
5770 | 5650 |
6019 return 0; | 5899 return 0; |
6020 | 5900 |
6021 return 1; | 5901 return 1; |
6022 } | 5902 } |
6023 | 5903 |
6024 /* Output a branch that tests a single bit of a register (QI, HI or SImode) | 5904 /* Output a branch that tests a single bit of a register (QI, HI, SI or DImode) |
6025 or memory location in the I/O space (QImode only). | 5905 or memory location in the I/O space (QImode only). |
6026 | 5906 |
6027 Operand 0: comparison operator (must be EQ or NE, compare bit to zero). | 5907 Operand 0: comparison operator (must be EQ or NE, compare bit to zero). |
6028 Operand 1: register operand to test, or CONST_INT memory address. | 5908 Operand 1: register operand to test, or CONST_INT memory address. |
6029 Operand 2: bit number (for QImode operand) or mask (HImode, SImode). | 5909 Operand 2: bit number. |
6030 Operand 3: label to jump to if the test is true. */ | 5910 Operand 3: label to jump to if the test is true. */ |
6031 | 5911 |
6032 const char * | 5912 const char * |
6033 avr_out_sbxx_branch (rtx insn, rtx operands[]) | 5913 avr_out_sbxx_branch (rtx insn, rtx operands[]) |
6034 { | 5914 { |
6047 if (GET_CODE (operands[1]) == CONST_INT) | 5927 if (GET_CODE (operands[1]) == CONST_INT) |
6048 { | 5928 { |
6049 if (INTVAL (operands[1]) < 0x40) | 5929 if (INTVAL (operands[1]) < 0x40) |
6050 { | 5930 { |
6051 if (comp == EQ) | 5931 if (comp == EQ) |
6052 output_asm_insn (AS2 (sbis,%1-0x20,%2), operands); | 5932 output_asm_insn (AS2 (sbis,%m1-0x20,%2), operands); |
6053 else | 5933 else |
6054 output_asm_insn (AS2 (sbic,%1-0x20,%2), operands); | 5934 output_asm_insn (AS2 (sbic,%m1-0x20,%2), operands); |
6055 } | 5935 } |
6056 else | 5936 else |
6057 { | 5937 { |
6058 output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands); | 5938 output_asm_insn (AS2 (in,__tmp_reg__,%m1-0x20), operands); |
6059 if (comp == EQ) | 5939 if (comp == EQ) |
6060 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands); | 5940 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands); |
6061 else | 5941 else |
6062 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands); | 5942 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands); |
6063 } | 5943 } |
6072 output_asm_insn (AS2 (sbrc,%1,%2), operands); | 5952 output_asm_insn (AS2 (sbrc,%1,%2), operands); |
6073 } | 5953 } |
6074 else /* HImode or SImode */ | 5954 else /* HImode or SImode */ |
6075 { | 5955 { |
6076 static char buf[] = "sbrc %A1,0"; | 5956 static char buf[] = "sbrc %A1,0"; |
6077 int bit_nr = exact_log2 (INTVAL (operands[2]) | 5957 int bit_nr = INTVAL (operands[2]); |
6078 & GET_MODE_MASK (GET_MODE (operands[1]))); | |
6079 | |
6080 buf[3] = (comp == EQ) ? 's' : 'c'; | 5958 buf[3] = (comp == EQ) ? 's' : 'c'; |
6081 buf[6] = 'A' + (bit_nr >> 3); | 5959 buf[6] = 'A' + (bit_nr >> 3); |
6082 buf[9] = '0' + (bit_nr & 7); | 5960 buf[9] = '0' + (bit_nr & 7); |
6083 output_asm_insn (buf, operands); | 5961 output_asm_insn (buf, operands); |
6084 } | 5962 } |
6085 } | 5963 } |
6086 | 5964 |
6087 if (long_jump) | 5965 if (long_jump) |
6088 return (AS1 (rjmp,.+4) CR_TAB | 5966 return (AS1 (rjmp,.+4) CR_TAB |
6089 AS1 (jmp,%3)); | 5967 AS1 (jmp,%x3)); |
6090 if (!reverse) | 5968 if (!reverse) |
6091 return AS1 (rjmp,%3); | 5969 return AS1 (rjmp,%x3); |
6092 return ""; | 5970 return ""; |
6093 } | 5971 } |
6094 | 5972 |
6095 /* Worker function for TARGET_ASM_CONSTRUCTOR. */ | 5973 /* Worker function for TARGET_ASM_CONSTRUCTOR. */ |
6096 | 5974 |
6122 } | 6000 } |
6123 else | 6001 else |
6124 return false; | 6002 return false; |
6125 } | 6003 } |
6126 | 6004 |
6005 /* Worker function for CASE_VALUES_THRESHOLD. */ | |
6006 | |
6007 unsigned int avr_case_values_threshold (void) | |
6008 { | |
6009 return (!AVR_HAVE_JMP_CALL || TARGET_CALL_PROLOGUES) ? 8 : 17; | |
6010 } | |
6011 | |
6127 #include "gt-avr.h" | 6012 #include "gt-avr.h" |