]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/avr/avr.c
* config/host-hpux.c: Change copyright header to refer to version 3 of the GNU
[thirdparty/gcc.git] / gcc / config / avr / avr.c
CommitLineData
a28e4651 1/* Subroutines for insn-output.c for ATMEL AVR micro controllers
d07b1e9e 2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007
934f2848 3 Free Software Foundation, Inc.
a28e4651 4 Contributed by Denis Chertykov (denisc@overta.ru)
5
187b36cf 6 This file is part of GCC.
a28e4651 7
187b36cf 8 GCC is free software; you can redistribute it and/or modify
a28e4651 9 it under the terms of the GNU General Public License as published by
038d1e19 10 the Free Software Foundation; either version 3, or (at your option)
a28e4651 11 any later version.
12
187b36cf 13 GCC is distributed in the hope that it will be useful,
a28e4651 14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
038d1e19 19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
a28e4651 21
22#include "config.h"
3337ec92 23#include "system.h"
805e22b2 24#include "coretypes.h"
25#include "tm.h"
a28e4651 26#include "rtl.h"
27#include "regs.h"
28#include "hard-reg-set.h"
29#include "real.h"
30#include "insn-config.h"
31#include "conditions.h"
a28e4651 32#include "insn-attr.h"
33#include "flags.h"
34#include "reload.h"
35#include "tree.h"
9bfdb494 36#include "output.h"
a28e4651 37#include "expr.h"
38#include "toplev.h"
39#include "obstack.h"
40#include "function.h"
41#include "recog.h"
c84f2269 42#include "ggc.h"
a28e4651 43#include "tm_p.h"
a767736d 44#include "target.h"
45#include "target-def.h"
a4c6e6a2 46#include "df.h"
a28e4651 47
1cb39658 48/* Maximal allowed offset for an address in the LD command */
49#define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
a28e4651 50
206a5129 51static int avr_naked_function_p (tree);
52static int interrupt_function_p (tree);
53static int signal_function_p (tree);
54static int avr_regs_to_save (HARD_REG_SET *);
55static int sequent_regs_live (void);
56static const char *ptrreg_to_str (int);
57static const char *cond_string (enum rtx_code);
58static int avr_num_arg_regs (enum machine_mode, tree);
df3d6232 59
206a5129 60static RTX_CODE compare_condition (rtx insn);
61static int compare_sign_p (rtx insn);
62static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *);
63static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
f86b386b 64static tree avr_handle_fntype_attribute (tree *, tree, tree, int, bool *);
e3c541f0 65const struct attribute_spec avr_attribute_table[];
206a5129 66static bool avr_assemble_integer (rtx, unsigned int, int);
67static void avr_file_start (void);
68static void avr_file_end (void);
df3d6232 69static void avr_asm_function_end_prologue (FILE *);
70static void avr_asm_function_begin_epilogue (FILE *);
206a5129 71static void avr_insert_attributes (tree, tree *);
2f14b1f9 72static void avr_asm_init_sections (void);
206a5129 73static unsigned int avr_section_type_flags (tree, const char *, int);
74
75static void avr_reorg (void);
76static void avr_asm_out_ctor (rtx, int);
77static void avr_asm_out_dtor (rtx, int);
433a5f02 78static int avr_operand_rtx_cost (rtx, enum machine_mode, enum rtx_code);
206a5129 79static bool avr_rtx_costs (rtx, int, int, int *);
80static int avr_address_cost (rtx);
cfd55026 81static bool avr_return_in_memory (tree, tree);
df3d6232 82static struct machine_function * avr_init_machine_status (void);
20c71901 83/* Allocate registers from r25 to r8 for parameters for function calls. */
a28e4651 84#define FIRST_CUM_REG 26
85
1a83b3ff 86/* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */
c84f2269 87static GTY(()) rtx tmp_reg_rtx;
a28e4651 88
1a83b3ff 89/* Zeroed register RTX (gen_rtx_REG (QImode, ZERO_REGNO)) */
c84f2269 90static GTY(()) rtx zero_reg_rtx;
e511e253 91
a28e4651 92/* AVR register names {"r0", "r1", ..., "r31"} */
35823b64 93static const char *const avr_regnames[] = REGISTER_NAMES;
a28e4651 94
95/* This holds the last insn address. */
96static int last_insn_address = 0;
97
98/* Commands count in the compiled file */
99static int commands_in_file;
100
101/* Commands in the functions prologues in the compiled file */
102static int commands_in_prologues;
103
104/* Commands in the functions epilogues in the compiled file */
105static int commands_in_epilogues;
106
c284a148 107/* Preprocessor macros to define depending on MCU type. */
108const char *avr_base_arch_macro;
109const char *avr_extra_arch_macro;
110
2f14b1f9 111section *progmem_section;
112
e511e253 113/* More than 8K of program memory: use "call" and "jmp". */
114int avr_mega_p = 0;
115
8cc5a1af 116/* Core have 'MUL*' instructions. */
117int avr_have_mul_p = 0;
e511e253 118
235d7594 119/* Assembler only. */
c284a148 120int avr_asm_only_p = 0;
121
0aab73c2 122/* Core have 'MOVW' and 'LPM Rx,Z' instructions. */
123int avr_have_movw_lpmx_p = 0;
124
c284a148 125struct base_arch_s {
126 int asm_only;
8cc5a1af 127 int have_mul;
c284a148 128 int mega;
0aab73c2 129 int have_movw_lpmx;
c284a148 130 const char *const macro;
131};
132
133static const struct base_arch_s avr_arch_types[] = {
0aab73c2 134 { 1, 0, 0, 0, NULL }, /* unknown device specified */
135 { 1, 0, 0, 0, "__AVR_ARCH__=1" },
136 { 0, 0, 0, 0, "__AVR_ARCH__=2" },
8c23ba29 137 { 0, 0, 0, 1, "__AVR_ARCH__=25"},
0aab73c2 138 { 0, 0, 1, 0, "__AVR_ARCH__=3" },
139 { 0, 1, 0, 1, "__AVR_ARCH__=4" },
8c23ba29 140 { 0, 1, 1, 1, "__AVR_ARCH__=5" }
141};
142
143/* These names are used as the index into the avr_arch_types[] table
144 above. */
145
146enum avr_arch
147{
148 ARCH_UNKNOWN,
149 ARCH_AVR1,
150 ARCH_AVR2,
151 ARCH_AVR25,
152 ARCH_AVR3,
153 ARCH_AVR4,
154 ARCH_AVR5
e511e253 155};
156
157struct mcu_type_s {
e99c3a1d 158 const char *const name;
c284a148 159 int arch; /* index in avr_arch_types[] */
160 /* Must lie outside user's namespace. NULL == no macro. */
161 const char *const macro;
e511e253 162};
163
164/* List of all known AVR MCU types - if updated, it has to be kept
165 in sync in several places (FIXME: is there a better way?):
166 - here
167 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
168 - t-avr (MULTILIB_MATCHES)
169 - gas/config/tc-avr.c
170 - avr-libc */
171
172static const struct mcu_type_s avr_mcu_types[] = {
173 /* Classic, <= 8K. */
8c23ba29 174 { "avr2", ARCH_AVR2, NULL },
175 { "at90s2313", ARCH_AVR2, "__AVR_AT90S2313__" },
176 { "at90s2323", ARCH_AVR2, "__AVR_AT90S2323__" },
177 { "at90s2333", ARCH_AVR2, "__AVR_AT90S2333__" },
178 { "at90s2343", ARCH_AVR2, "__AVR_AT90S2343__" },
179 { "attiny22", ARCH_AVR2, "__AVR_ATtiny22__" },
180 { "attiny26", ARCH_AVR2, "__AVR_ATtiny26__" },
181 { "at90s4414", ARCH_AVR2, "__AVR_AT90S4414__" },
182 { "at90s4433", ARCH_AVR2, "__AVR_AT90S4433__" },
183 { "at90s4434", ARCH_AVR2, "__AVR_AT90S4434__" },
184 { "at90s8515", ARCH_AVR2, "__AVR_AT90S8515__" },
185 { "at90c8534", ARCH_AVR2, "__AVR_AT90C8534__" },
186 { "at90s8535", ARCH_AVR2, "__AVR_AT90S8535__" },
285244f6 187 /* Classic + MOVW, <= 8K. */
8c23ba29 188 { "avr25", ARCH_AVR25, NULL },
189 { "attiny13", ARCH_AVR25, "__AVR_ATtiny13__" },
190 { "attiny2313", ARCH_AVR25, "__AVR_ATtiny2313__" },
191 { "attiny24", ARCH_AVR25, "__AVR_ATtiny24__" },
192 { "attiny44", ARCH_AVR25, "__AVR_ATtiny44__" },
193 { "attiny84", ARCH_AVR25, "__AVR_ATtiny84__" },
194 { "attiny25", ARCH_AVR25, "__AVR_ATtiny25__" },
195 { "attiny45", ARCH_AVR25, "__AVR_ATtiny45__" },
196 { "attiny85", ARCH_AVR25, "__AVR_ATtiny85__" },
197 { "attiny261", ARCH_AVR25, "__AVR_ATtiny261__" },
198 { "attiny461", ARCH_AVR25, "__AVR_ATtiny461__" },
199 { "attiny861", ARCH_AVR25, "__AVR_ATtiny861__" },
200 { "at86rf401", ARCH_AVR25, "__AVR_AT86RF401__" },
e511e253 201 /* Classic, > 8K. */
8c23ba29 202 { "avr3", ARCH_AVR3, NULL },
203 { "atmega103", ARCH_AVR3, "__AVR_ATmega103__" },
204 { "atmega603", ARCH_AVR3, "__AVR_ATmega603__" },
205 { "at43usb320", ARCH_AVR3, "__AVR_AT43USB320__" },
206 { "at43usb355", ARCH_AVR3, "__AVR_AT43USB355__" },
207 { "at76c711", ARCH_AVR3, "__AVR_AT76C711__" },
e511e253 208 /* Enhanced, <= 8K. */
8c23ba29 209 { "avr4", ARCH_AVR4, NULL },
210 { "atmega8", ARCH_AVR4, "__AVR_ATmega8__" },
211 { "atmega48", ARCH_AVR4, "__AVR_ATmega48__" },
212 { "atmega88", ARCH_AVR4, "__AVR_ATmega88__" },
213 { "atmega8515", ARCH_AVR4, "__AVR_ATmega8515__" },
214 { "atmega8535", ARCH_AVR4, "__AVR_ATmega8535__" },
98dac559 215 { "atmega8hva", ARCH_AVR4, "__AVR_ATmega8HVA__" },
8c23ba29 216 { "at90pwm1", ARCH_AVR4, "__AVR_AT90PWM1__" },
217 { "at90pwm2", ARCH_AVR4, "__AVR_AT90PWM2__" },
218 { "at90pwm3", ARCH_AVR4, "__AVR_AT90PWM3__" },
e511e253 219 /* Enhanced, > 8K. */
8c23ba29 220 { "avr5", ARCH_AVR5, NULL },
221 { "atmega16", ARCH_AVR5, "__AVR_ATmega16__" },
222 { "atmega161", ARCH_AVR5, "__AVR_ATmega161__" },
223 { "atmega162", ARCH_AVR5, "__AVR_ATmega162__" },
224 { "atmega163", ARCH_AVR5, "__AVR_ATmega163__" },
225 { "atmega164p", ARCH_AVR5, "__AVR_ATmega164P__" },
226 { "atmega165", ARCH_AVR5, "__AVR_ATmega165__" },
227 { "atmega165p", ARCH_AVR5, "__AVR_ATmega165P__" },
228 { "atmega168", ARCH_AVR5, "__AVR_ATmega168__" },
229 { "atmega169", ARCH_AVR5, "__AVR_ATmega169__" },
230 { "atmega169p", ARCH_AVR5, "__AVR_ATmega169P__" },
231 { "atmega32", ARCH_AVR5, "__AVR_ATmega32__" },
232 { "atmega323", ARCH_AVR5, "__AVR_ATmega323__" },
233 { "atmega324p", ARCH_AVR5, "__AVR_ATmega324P__" },
234 { "atmega325", ARCH_AVR5, "__AVR_ATmega325__" },
235 { "atmega325p", ARCH_AVR5, "__AVR_ATmega325P__" },
236 { "atmega3250", ARCH_AVR5, "__AVR_ATmega3250__" },
237 { "atmega3250p", ARCH_AVR5, "__AVR_ATmega3250P__" },
238 { "atmega329", ARCH_AVR5, "__AVR_ATmega329__" },
239 { "atmega329p", ARCH_AVR5, "__AVR_ATmega329P__" },
240 { "atmega3290", ARCH_AVR5, "__AVR_ATmega3290__" },
241 { "atmega3290p", ARCH_AVR5, "__AVR_ATmega3290P__" },
242 { "atmega406", ARCH_AVR5, "__AVR_ATmega406__" },
243 { "atmega64", ARCH_AVR5, "__AVR_ATmega64__" },
244 { "atmega640", ARCH_AVR5, "__AVR_ATmega640__" },
245 { "atmega644", ARCH_AVR5, "__AVR_ATmega644__" },
246 { "atmega644p", ARCH_AVR5, "__AVR_ATmega644P__" },
247 { "atmega645", ARCH_AVR5, "__AVR_ATmega645__" },
248 { "atmega6450", ARCH_AVR5, "__AVR_ATmega6450__" },
249 { "atmega649", ARCH_AVR5, "__AVR_ATmega649__" },
250 { "atmega6490", ARCH_AVR5, "__AVR_ATmega6490__" },
251 { "atmega128", ARCH_AVR5, "__AVR_ATmega128__" },
252 { "atmega1280", ARCH_AVR5, "__AVR_ATmega1280__" },
253 { "atmega1281", ARCH_AVR5, "__AVR_ATmega1281__" },
98dac559 254 { "atmega16hva", ARCH_AVR5, "__AVR_ATmega16HVA__" },
8c23ba29 255 { "at90can32", ARCH_AVR5, "__AVR_AT90CAN32__" },
256 { "at90can64", ARCH_AVR5, "__AVR_AT90CAN64__" },
257 { "at90can128", ARCH_AVR5, "__AVR_AT90CAN128__" },
98dac559 258 { "at90usb82", ARCH_AVR5, "__AVR_AT90USB82__" },
8c23ba29 259 { "at90usb162", ARCH_AVR5, "__AVR_AT90USB162__" },
260 { "at90usb646", ARCH_AVR5, "__AVR_AT90USB646__" },
261 { "at90usb647", ARCH_AVR5, "__AVR_AT90USB647__" },
262 { "at90usb1286", ARCH_AVR5, "__AVR_AT90USB1286__" },
263 { "at90usb1287", ARCH_AVR5, "__AVR_AT90USB1287__" },
264 { "at94k", ARCH_AVR5, "__AVR_AT94K__" },
e511e253 265 /* Assembler only. */
8c23ba29 266 { "avr1", ARCH_AVR1, NULL },
267 { "at90s1200", ARCH_AVR1, "__AVR_AT90S1200__" },
268 { "attiny11", ARCH_AVR1, "__AVR_ATtiny11__" },
269 { "attiny12", ARCH_AVR1, "__AVR_ATtiny12__" },
270 { "attiny15", ARCH_AVR1, "__AVR_ATtiny15__" },
271 { "attiny28", ARCH_AVR1, "__AVR_ATtiny28__" },
272 { NULL, ARCH_UNKNOWN, NULL }
e511e253 273};
a28e4651 274
21167a30 275int avr_case_values_threshold = 30000;
a767736d 276\f
277/* Initialize the GCC target structure. */
58356836 278#undef TARGET_ASM_ALIGNED_HI_OP
279#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
e076c197 280#undef TARGET_ASM_ALIGNED_SI_OP
281#define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
282#undef TARGET_ASM_UNALIGNED_HI_OP
283#define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
284#undef TARGET_ASM_UNALIGNED_SI_OP
285#define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
58356836 286#undef TARGET_ASM_INTEGER
287#define TARGET_ASM_INTEGER avr_assemble_integer
92c473b8 288#undef TARGET_ASM_FILE_START
289#define TARGET_ASM_FILE_START avr_file_start
290#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
291#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
f6940372 292#undef TARGET_ASM_FILE_END
293#define TARGET_ASM_FILE_END avr_file_end
58356836 294
df3d6232 295#undef TARGET_ASM_FUNCTION_END_PROLOGUE
296#define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
297#undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
298#define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
e3c541f0 299#undef TARGET_ATTRIBUTE_TABLE
300#define TARGET_ATTRIBUTE_TABLE avr_attribute_table
76aec42f 301#undef TARGET_ASM_FUNCTION_RODATA_SECTION
302#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
a179a371 303#undef TARGET_INSERT_ATTRIBUTES
304#define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
8a46ca38 305#undef TARGET_SECTION_TYPE_FLAGS
306#define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
fab7adbf 307#undef TARGET_RTX_COSTS
308#define TARGET_RTX_COSTS avr_rtx_costs
ec0457a8 309#undef TARGET_ADDRESS_COST
310#define TARGET_ADDRESS_COST avr_address_cost
2efea8c0 311#undef TARGET_MACHINE_DEPENDENT_REORG
312#define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
a767736d 313
cfd55026 314#undef TARGET_RETURN_IN_MEMORY
315#define TARGET_RETURN_IN_MEMORY avr_return_in_memory
316
317#undef TARGET_STRICT_ARGUMENT_NAMING
318#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
319
57e4bbfb 320struct gcc_target targetm = TARGET_INITIALIZER;
a767736d 321\f
a28e4651 322void
206a5129 323avr_override_options (void)
a28e4651 324{
e511e253 325 const struct mcu_type_s *t;
c284a148 326 const struct base_arch_s *base;
e511e253 327
6e9e3dbe 328 flag_delete_null_pointer_checks = 0;
329
e511e253 330 for (t = avr_mcu_types; t->name; t++)
331 if (strcmp (t->name, avr_mcu_name) == 0)
a28e4651 332 break;
e511e253 333
334 if (!t->name)
a28e4651 335 {
3284a242 336 fprintf (stderr, "unknown MCU '%s' specified\nKnown MCU names:\n",
e511e253 337 avr_mcu_name);
338 for (t = avr_mcu_types; t->name; t++)
339 fprintf (stderr," %s\n", t->name);
e511e253 340 }
341
c284a148 342 base = &avr_arch_types[t->arch];
343 avr_asm_only_p = base->asm_only;
8cc5a1af 344 avr_have_mul_p = base->have_mul;
c284a148 345 avr_mega_p = base->mega;
0aab73c2 346 avr_have_movw_lpmx_p = base->have_movw_lpmx;
c284a148 347 avr_base_arch_macro = base->macro;
348 avr_extra_arch_macro = t->macro;
21167a30 349
350 if (optimize && !TARGET_NO_TABLEJUMP)
351 avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
a28e4651 352
c84f2269 353 tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO);
354 zero_reg_rtx = gen_rtx_REG (QImode, ZERO_REGNO);
df3d6232 355
356 init_machine_status = avr_init_machine_status;
a28e4651 357}
358
20c71901 359/* return register class from register number. */
a28e4651 360
e99c3a1d 361static const int reg_class_tab[]={
a28e4651 362 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
363 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
364 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
365 GENERAL_REGS, /* r0 - r15 */
366 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
367 LD_REGS, /* r16 - 23 */
368 ADDW_REGS,ADDW_REGS, /* r24,r25 */
369 POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
370 POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
371 POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
372 STACK_REG,STACK_REG /* SPL,SPH */
373};
374
df3d6232 375/* Function to set up the backend function structure. */
376
377static struct machine_function *
378avr_init_machine_status (void)
379{
380 return ((struct machine_function *)
381 ggc_alloc_cleared (sizeof (struct machine_function)));
382}
383
20c71901 384/* Return register class for register R. */
a28e4651 385
386enum reg_class
206a5129 387avr_regno_reg_class (int r)
a28e4651 388{
389 if (r <= 33)
390 return reg_class_tab[r];
391 return ALL_REGS;
392}
393
e3e08e7f 394/* Return nonzero if FUNC is a naked function. */
a28e4651 395
396static int
206a5129 397avr_naked_function_p (tree func)
a28e4651 398{
399 tree a;
400
8ef66241 401 gcc_assert (TREE_CODE (func) == FUNCTION_DECL);
a28e4651 402
f86b386b 403 a = lookup_attribute ("naked", TYPE_ATTRIBUTES (TREE_TYPE (func)));
a28e4651 404 return a != NULL_TREE;
405}
406
407/* Return nonzero if FUNC is an interrupt function as specified
408 by the "interrupt" attribute. */
409
410static int
206a5129 411interrupt_function_p (tree func)
a28e4651 412{
413 tree a;
414
415 if (TREE_CODE (func) != FUNCTION_DECL)
416 return 0;
417
e3c541f0 418 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
a28e4651 419 return a != NULL_TREE;
420}
421
1cb39658 422/* Return nonzero if FUNC is a signal function as specified
a28e4651 423 by the "signal" attribute. */
424
425static int
206a5129 426signal_function_p (tree func)
a28e4651 427{
428 tree a;
429
430 if (TREE_CODE (func) != FUNCTION_DECL)
431 return 0;
432
e3c541f0 433 a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
a28e4651 434 return a != NULL_TREE;
435}
436
f0973368 437/* Return the number of hard registers to push/pop in the prologue/epilogue
438 of the current function, and optionally store these registers in SET. */
439
440static int
206a5129 441avr_regs_to_save (HARD_REG_SET *set)
f0973368 442{
443 int reg, count;
444 int int_or_sig_p = (interrupt_function_p (current_function_decl)
445 || signal_function_p (current_function_decl));
446 int leaf_func_p = leaf_function_p ();
447
448 if (set)
449 CLEAR_HARD_REG_SET (*set);
450 count = 0;
c3bcd5a9 451
452 /* No need to save any registers if the function never returns. */
453 if (TREE_THIS_VOLATILE (current_function_decl))
454 return 0;
455
f0973368 456 for (reg = 0; reg < 32; reg++)
457 {
458 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
459 any global register variables. */
460 if (fixed_regs[reg])
461 continue;
462
463 if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
3072d30e 464 || (df_regs_ever_live_p (reg)
f0973368 465 && (int_or_sig_p || !call_used_regs[reg])
466 && !(frame_pointer_needed
467 && (reg == REG_Y || reg == (REG_Y+1)))))
468 {
469 if (set)
470 SET_HARD_REG_BIT (*set, reg);
471 count++;
472 }
473 }
474 return count;
475}
476
20c71901 477/* Compute offset between arg_pointer and frame_pointer. */
a28e4651 478
479int
206a5129 480initial_elimination_offset (int from, int to)
a28e4651 481{
1cb39658 482 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
483 return 0;
484 else
485 {
f0973368 486 int offset = frame_pointer_needed ? 2 : 0;
1cb39658 487
f0973368 488 offset += avr_regs_to_save (NULL);
1cb39658 489 return get_frame_size () + 2 + 1 + offset;
a28e4651 490 }
a28e4651 491}
492
bf522d86 493/* Return 1 if the function epilogue is just a single "ret". */
494
495int
206a5129 496avr_simple_epilogue (void)
bf522d86 497{
498 return (! frame_pointer_needed
499 && get_frame_size () == 0
500 && avr_regs_to_save (NULL) == 0
501 && ! interrupt_function_p (current_function_decl)
502 && ! signal_function_p (current_function_decl)
503 && ! avr_naked_function_p (current_function_decl)
504 && ! MAIN_NAME_P (DECL_NAME (current_function_decl))
505 && ! TREE_THIS_VOLATILE (current_function_decl));
506}
507
20c71901 508/* This function checks sequence of live registers. */
a28e4651 509
510static int
206a5129 511sequent_regs_live (void)
a28e4651 512{
513 int reg;
514 int live_seq=0;
515 int cur_seq=0;
516
517 for (reg = 0; reg < 18; ++reg)
518 {
519 if (!call_used_regs[reg])
520 {
3072d30e 521 if (df_regs_ever_live_p (reg))
a28e4651 522 {
523 ++live_seq;
524 ++cur_seq;
525 }
526 else
527 cur_seq = 0;
528 }
529 }
530
531 if (!frame_pointer_needed)
532 {
3072d30e 533 if (df_regs_ever_live_p (REG_Y))
a28e4651 534 {
535 ++live_seq;
536 ++cur_seq;
537 }
538 else
539 cur_seq = 0;
540
3072d30e 541 if (df_regs_ever_live_p (REG_Y+1))
a28e4651 542 {
543 ++live_seq;
544 ++cur_seq;
545 }
546 else
547 cur_seq = 0;
548 }
549 else
550 {
551 cur_seq += 2;
552 live_seq += 2;
553 }
554 return (cur_seq == live_seq) ? live_seq : 0;
555}
556
df3d6232 557/* Output function prologue. */
a28e4651 558
df3d6232 559void
560expand_prologue (void)
a7690ba9 561{
df3d6232 562 int live_seq;
563 int minimize;
564 HOST_WIDE_INT size = get_frame_size();
565 /* Define templates for push instructions. */
566 rtx pushbyte = gen_rtx_MEM (QImode,
567 gen_rtx_POST_DEC (HImode, stack_pointer_rtx));
568 rtx pushword = gen_rtx_MEM (HImode,
569 gen_rtx_POST_DEC (HImode, stack_pointer_rtx));
570 rtx insn;
a7690ba9 571
df3d6232 572 last_insn_address = 0;
573
574 /* Init cfun->machine. */
575 cfun->machine->is_main = MAIN_NAME_P (DECL_NAME (current_function_decl));
576 cfun->machine->is_naked = avr_naked_function_p (current_function_decl);
577 cfun->machine->is_interrupt = interrupt_function_p (current_function_decl);
578 cfun->machine->is_signal = signal_function_p (current_function_decl);
579
580 /* Prologue: naked. */
581 if (cfun->machine->is_naked)
a7690ba9 582 {
df3d6232 583 return;
a7690ba9 584 }
a7690ba9 585
df3d6232 586 live_seq = sequent_regs_live ();
587 minimize = (TARGET_CALL_PROLOGUES
588 && !(cfun->machine->is_interrupt || cfun->machine->is_signal)
589 && live_seq);
a7690ba9 590
df3d6232 591 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
a7690ba9 592 {
df3d6232 593 if (cfun->machine->is_interrupt)
594 {
595 /* Enable interrupts. */
596 insn = emit_insn (gen_enable_interrupt ());
597 RTX_FRAME_RELATED_P (insn) = 1;
598 }
599
600 /* Push zero reg. */
601 insn = emit_move_insn (pushbyte, zero_reg_rtx);
602 RTX_FRAME_RELATED_P (insn) = 1;
603
604 /* Push tmp reg. */
605 insn = emit_move_insn (pushbyte, tmp_reg_rtx);
606 RTX_FRAME_RELATED_P (insn) = 1;
607
608 /* Push SREG. */
609 insn = emit_move_insn (tmp_reg_rtx,
610 gen_rtx_MEM (QImode, GEN_INT (SREG_ADDR)));
611 RTX_FRAME_RELATED_P (insn) = 1;
612 insn = emit_move_insn (pushbyte, tmp_reg_rtx);
613 RTX_FRAME_RELATED_P (insn) = 1;
614
615 /* Clear zero reg. */
616 insn = emit_move_insn (zero_reg_rtx, const0_rtx);
617 RTX_FRAME_RELATED_P (insn) = 1;
a7690ba9 618
df3d6232 619 /* Prevent any attempt to delete the setting of ZERO_REG! */
620 emit_insn (gen_rtx_USE (VOIDmode, zero_reg_rtx));
a7690ba9 621 }
df3d6232 622 if (cfun->machine->is_main)
a7690ba9 623 {
df3d6232 624 char buffer[40];
625 sprintf (buffer, "%s - %d", avr_init_stack, (int) size);
626 rtx sym = gen_rtx_SYMBOL_REF (HImode, ggc_strdup (buffer));
310d2511 627 /* Initialize stack pointer using frame pointer. */
df3d6232 628 insn = emit_move_insn (frame_pointer_rtx, sym);
629 RTX_FRAME_RELATED_P (insn) = 1;
630 insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
631 RTX_FRAME_RELATED_P (insn) = 1;
a7690ba9 632 }
df3d6232 633 else if (minimize && (frame_pointer_needed || live_seq > 6))
a7690ba9 634 {
a4c6e6a2 635 insn = emit_move_insn (gen_rtx_REG (HImode, REG_X),
636 gen_int_mode (size, HImode));
637 RTX_FRAME_RELATED_P (insn) = 1;
638
df3d6232 639 insn =
a4c6e6a2 640 emit_insn (gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
641 gen_int_mode (size + live_seq, HImode)));
df3d6232 642 RTX_FRAME_RELATED_P (insn) = 1;
a7690ba9 643 }
df3d6232 644 else
a7690ba9 645 {
df3d6232 646 HARD_REG_SET set;
647 avr_regs_to_save (&set);
648 int reg;
649 for (reg = 0; reg < 32; ++reg)
650 {
651 if (TEST_HARD_REG_BIT (set, reg))
652 {
653 /* Emit push of register to save. */
654 insn=emit_move_insn (pushbyte, gen_rtx_REG (QImode, reg));
655 RTX_FRAME_RELATED_P (insn) = 1;
656 }
657 }
658 if (frame_pointer_needed)
659 {
660 /* Push frame pointer. */
661 insn = emit_move_insn (pushword, frame_pointer_rtx);
662 RTX_FRAME_RELATED_P (insn) = 1;
663 if (!size)
664 {
665 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
666 RTX_FRAME_RELATED_P (insn) = 1;
667 }
668 else
669 {
670 /* Creating a frame can be done by direct manipulation of the
671 stack or via the frame pointer. These two methods are:
672 fp=sp
673 fp-=size
674 sp=fp
675 OR
676 sp-=size
677 fp=sp
678 the optimum method depends on function type, stack and frame size.
679 To avoid a complex logic, both methods are tested and shortest
680 is selected. */
681 rtx myfp;
682 /* First method. */
683 if (TARGET_TINY_STACK)
684 {
685 if (size < -63 || size > 63)
686 warning (0, "large frame pointer change (%d) with -mtiny-stack", size);
687
688 /* The high byte (r29) doesn't change - prefer 'subi' (1 cycle)
689 over 'sbiw' (2 cycles, same size). */
690 myfp = gen_rtx_REG (QImode, REGNO (frame_pointer_rtx));
691 }
692 else
693 {
694 /* Normal sized addition. */
695 myfp = frame_pointer_rtx;
696 }
697 /* Calculate length. */
698 int method1_length;
699 method1_length =
700 get_attr_length (gen_move_insn (frame_pointer_rtx, stack_pointer_rtx));
701 method1_length +=
702 get_attr_length (gen_move_insn (myfp,
703 gen_rtx_PLUS (GET_MODE(myfp), myfp,
704 gen_int_mode (-size,
705 GET_MODE(myfp)))));
706 method1_length +=
707 get_attr_length (gen_move_insn (stack_pointer_rtx, frame_pointer_rtx));
708
709 /* Method 2-Adjust Stack pointer. */
710 int sp_plus_length = 0;
711 if (size <= 6)
712 {
713 sp_plus_length =
714 get_attr_length (gen_move_insn (stack_pointer_rtx,
715 gen_rtx_PLUS (HImode, stack_pointer_rtx,
716 gen_int_mode (-size,
717 HImode))));
718 sp_plus_length +=
719 get_attr_length (gen_move_insn (frame_pointer_rtx, stack_pointer_rtx));
720 }
721 /* Use shortest method. */
722 if (size <= 6 && (sp_plus_length < method1_length))
723 {
724 insn = emit_move_insn (stack_pointer_rtx,
725 gen_rtx_PLUS (HImode, stack_pointer_rtx,
726 gen_int_mode (-size, HImode)));
727 RTX_FRAME_RELATED_P (insn) = 1;
728 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
729 RTX_FRAME_RELATED_P (insn) = 1;
730 }
731 else
732 {
733 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
734 RTX_FRAME_RELATED_P (insn) = 1;
735 insn = emit_move_insn (myfp,
736 gen_rtx_PLUS (GET_MODE(myfp), frame_pointer_rtx,
737 gen_int_mode (-size, GET_MODE(myfp))));
738 RTX_FRAME_RELATED_P (insn) = 1;
739 insn = emit_move_insn ( stack_pointer_rtx, frame_pointer_rtx);
740 RTX_FRAME_RELATED_P (insn) = 1;
741 }
742 }
743 }
a7690ba9 744 }
a7690ba9 745}
746
df3d6232 747/* Output summary at end of function prologue. */
a28e4651 748
17d9b0c3 749static void
df3d6232 750avr_asm_function_end_prologue (FILE *file)
a28e4651 751{
df3d6232 752 if (cfun->machine->is_naked)
a28e4651 753 {
c3bcd5a9 754 fputs ("/* prologue: naked */\n", file);
a28e4651 755 }
df3d6232 756 else
a28e4651 757 {
df3d6232 758 if (cfun->machine->is_interrupt)
759 {
760 fputs ("/* prologue: Interrupt */\n", file);
761 }
762 else if (cfun->machine->is_signal)
763 {
764 fputs ("/* prologue: Signal */\n", file);
765 }
766 else if (cfun->machine->is_main)
767 {
768 fputs ("/* prologue: main */\n", file);
769 }
a28e4651 770 else
df3d6232 771 fputs ("/* prologue: function */\n", file);
a28e4651 772 }
df3d6232 773 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
774 get_frame_size());
775}
f0973368 776
e067eab2 777
df3d6232 778/* Implement EPILOGUE_USES. */
c3bcd5a9 779
df3d6232 780int
781avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
782{
783 if (reload_completed
784 && cfun->machine
785 && (cfun->machine->is_interrupt || cfun->machine->is_signal))
786 return 1;
787 return 0;
a28e4651 788}
789
df3d6232 790/* Output RTL epilogue. */
a28e4651 791
df3d6232 792void
793expand_epilogue (void)
a28e4651 794{
795 int reg;
a28e4651 796 int live_seq;
797 int minimize;
df3d6232 798 HOST_WIDE_INT size = get_frame_size();
799 rtx insn;
800
801 /* epilogue: naked */
802 if (cfun->machine->is_naked)
c3bcd5a9 803 {
df3d6232 804 insn = emit_jump_insn (gen_return ());
805 RTX_FRAME_RELATED_P (insn) = 1;
806 return;
a28e4651 807 }
808
a28e4651 809 live_seq = sequent_regs_live ();
810 minimize = (TARGET_CALL_PROLOGUES
df3d6232 811 && !(cfun->machine->is_interrupt || cfun->machine->is_signal)
812 && live_seq);
a28e4651 813
df3d6232 814 if (cfun->machine->is_main)
a28e4651 815 {
9aa7484c 816 /* Return value from main() is already in the correct registers
df3d6232 817 (r25:r24) as the exit() argument. */
818 insn = emit_jump_insn (gen_return ());
819 RTX_FRAME_RELATED_P (insn) = 1;
a28e4651 820 }
821 else if (minimize && (frame_pointer_needed || live_seq > 4))
822 {
a28e4651 823 if (frame_pointer_needed)
824 {
df3d6232 825 /* Get rid of frame. */
826 insn =
827 emit_move_insn(frame_pointer_rtx,
828 gen_rtx_PLUS (HImode, frame_pointer_rtx,
829 gen_int_mode (size, HImode)));
830 RTX_FRAME_RELATED_P (insn) = 1;
a28e4651 831 }
832 else
833 {
df3d6232 834 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
835 RTX_FRAME_RELATED_P (insn) = 1;
a28e4651 836 }
df3d6232 837
838 insn =
839 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
840 RTX_FRAME_RELATED_P (insn) = 1;
a28e4651 841 }
842 else
843 {
844 if (frame_pointer_needed)
845 {
846 if (size)
847 {
df3d6232 848 /* Try two methods to adjust stack and select shortest. */
849 int fp_plus_length;
850 /* Method 1-Adjust frame pointer. */
851 fp_plus_length =
852 get_attr_length (gen_move_insn (frame_pointer_rtx,
853 gen_rtx_PLUS (HImode, frame_pointer_rtx,
854 gen_int_mode (size,
855 HImode))));
856 /* Copy to stack pointer. */
857 fp_plus_length +=
858 get_attr_length (gen_move_insn (stack_pointer_rtx, frame_pointer_rtx));
859
860 /* Method 2-Adjust Stack pointer. */
861 int sp_plus_length = 0;
862 if (size <= 5)
863 {
864 sp_plus_length =
865 get_attr_length (gen_move_insn (stack_pointer_rtx,
866 gen_rtx_PLUS (HImode, stack_pointer_rtx,
867 gen_int_mode (size,
868 HImode))));
869 }
870 /* Use shortest method. */
871 if (size <= 5 && (sp_plus_length < fp_plus_length))
872 {
873 insn = emit_move_insn (stack_pointer_rtx,
874 gen_rtx_PLUS (HImode, stack_pointer_rtx,
875 gen_int_mode (size, HImode)));
876 RTX_FRAME_RELATED_P (insn) = 1;
877 }
878 else
879 {
880 insn = emit_move_insn (frame_pointer_rtx,
881 gen_rtx_PLUS (HImode, frame_pointer_rtx,
882 gen_int_mode (size, HImode)));
883 RTX_FRAME_RELATED_P (insn) = 1;
884 /* Copy to stack pointer. */
885 insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
886 RTX_FRAME_RELATED_P (insn) = 1;
887 }
888 }
889
890 /* Restore previous frame_pointer. */
891 insn = emit_insn (gen_pophi (frame_pointer_rtx));
892 RTX_FRAME_RELATED_P (insn) = 1;
a28e4651 893 }
df3d6232 894 /* Restore used registers. */
895 HARD_REG_SET set;
896 avr_regs_to_save (&set);
a28e4651 897 for (reg = 31; reg >= 0; --reg)
df3d6232 898 {
899 if (TEST_HARD_REG_BIT (set, reg))
900 {
901 insn = emit_insn (gen_popqi (gen_rtx_REG (QImode, reg)));
902 RTX_FRAME_RELATED_P (insn) = 1;
903 }
904 }
905 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
906 {
f0973368 907
df3d6232 908 /* Restore SREG using tmp reg as scratch. */
909 insn = emit_insn (gen_popqi (tmp_reg_rtx));
910 RTX_FRAME_RELATED_P (insn) = 1;
911
912 insn = emit_move_insn (gen_rtx_MEM(QImode, GEN_INT(SREG_ADDR)),
913 tmp_reg_rtx);
914 RTX_FRAME_RELATED_P (insn) = 1;
915
916 /* Restore tmp REG. */
917 insn = emit_insn (gen_popqi (tmp_reg_rtx));
918 RTX_FRAME_RELATED_P (insn) = 1;
919
920 /* Restore zero REG. */
921 insn = emit_insn (gen_popqi (zero_reg_rtx));
922 RTX_FRAME_RELATED_P (insn) = 1;
923 }
c3bcd5a9 924
df3d6232 925 insn = emit_jump_insn (gen_return ());
926 RTX_FRAME_RELATED_P (insn) = 1;
927 }
a28e4651 928}
929
df3d6232 930/* Output summary messages at beginning of function epilogue. */
931
932static void
933avr_asm_function_begin_epilogue (FILE *file)
934{
935 fprintf (file, "/* epilogue start */\n");
936}
a28e4651 937
938/* Return nonzero if X (an RTX) is a legitimate memory address on the target
939 machine for a memory operand of mode MODE. */
940
941int
206a5129 942legitimate_address_p (enum machine_mode mode, rtx x, int strict)
a28e4651 943{
dd5cfeaf 944 enum reg_class r = NO_REGS;
945
a28e4651 946 if (TARGET_ALL_DEBUG)
947 {
948 fprintf (stderr, "mode: (%s) %s %s %s %s:",
949 GET_MODE_NAME(mode),
950 strict ? "(strict)": "",
951 reload_completed ? "(reload_completed)": "",
952 reload_in_progress ? "(reload_in_progress)": "",
953 reg_renumber ? "(reg_renumber)" : "");
954 if (GET_CODE (x) == PLUS
955 && REG_P (XEXP (x, 0))
956 && GET_CODE (XEXP (x, 1)) == CONST_INT
957 && INTVAL (XEXP (x, 1)) >= 0
1cb39658 958 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
a28e4651 959 && reg_renumber
960 )
961 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
962 true_regnum (XEXP (x, 0)));
963 debug_rtx (x);
964 }
965 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
966 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
dd5cfeaf 967 r = POINTER_REGS;
a28e4651 968 else if (CONSTANT_ADDRESS_P (x))
dd5cfeaf 969 r = ALL_REGS;
a28e4651 970 else if (GET_CODE (x) == PLUS
971 && REG_P (XEXP (x, 0))
972 && GET_CODE (XEXP (x, 1)) == CONST_INT
973 && INTVAL (XEXP (x, 1)) >= 0)
974 {
1cb39658 975 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
a28e4651 976 if (fit)
977 {
978 if (! strict
e511e253 979 || REGNO (XEXP (x,0)) == REG_Y
980 || REGNO (XEXP (x,0)) == REG_Z)
dd5cfeaf 981 r = BASE_POINTER_REGS;
a28e4651 982 if (XEXP (x,0) == frame_pointer_rtx
983 || XEXP (x,0) == arg_pointer_rtx)
dd5cfeaf 984 r = BASE_POINTER_REGS;
a28e4651 985 }
986 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
dd5cfeaf 987 r = POINTER_Y_REGS;
a28e4651 988 }
989 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
990 && REG_P (XEXP (x, 0))
991 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
992 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
993 {
dd5cfeaf 994 r = POINTER_REGS;
a28e4651 995 }
996 if (TARGET_ALL_DEBUG)
997 {
89c316e0 998 fprintf (stderr, " ret = %c\n", r + '0');
a28e4651 999 }
dd5cfeaf 1000 return r == NO_REGS ? 0 : (int)r;
a28e4651 1001}
1002
1003/* Attempts to replace X with a valid
1004 memory address for an operand of mode MODE */
1005
1006rtx
206a5129 1007legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
a28e4651 1008{
1009 x = oldx;
1010 if (TARGET_ALL_DEBUG)
1011 {
1012 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
1013 debug_rtx (oldx);
1014 }
1015
1016 if (GET_CODE (oldx) == PLUS
1017 && REG_P (XEXP (oldx,0)))
1018 {
1019 if (REG_P (XEXP (oldx,1)))
1020 x = force_reg (GET_MODE (oldx), oldx);
1021 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
1022 {
1023 int offs = INTVAL (XEXP (oldx,1));
1024 if (frame_pointer_rtx != XEXP (oldx,0))
1cb39658 1025 if (offs > MAX_LD_OFFSET (mode))
a28e4651 1026 {
1027 if (TARGET_ALL_DEBUG)
1028 fprintf (stderr, "force_reg (big offset)\n");
1029 x = force_reg (GET_MODE (oldx), oldx);
1030 }
1031 }
1032 }
1033 return x;
1034}
1035
1036
20c71901 1037/* Return a pointer register name as a string. */
a28e4651 1038
37ac04dc 1039static const char *
206a5129 1040ptrreg_to_str (int regno)
a28e4651 1041{
1042 switch (regno)
1043 {
1044 case REG_X: return "X";
1045 case REG_Y: return "Y";
1046 case REG_Z: return "Z";
1047 default:
5985f1ef 1048 output_operand_lossage ("address operand requires constraint for X, Y, or Z register");
a28e4651 1049 }
1050 return NULL;
1051}
1052
1053/* Return the condition name as a string.
1054 Used in conditional jump constructing */
1055
37ac04dc 1056static const char *
206a5129 1057cond_string (enum rtx_code code)
a28e4651 1058{
1059 switch (code)
1060 {
1061 case NE:
1062 return "ne";
1063 case EQ:
1064 return "eq";
1065 case GE:
1066 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1067 return "pl";
1068 else
1069 return "ge";
a28e4651 1070 case LT:
1071 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1072 return "mi";
1073 else
1074 return "lt";
1075 case GEU:
1076 return "sh";
a28e4651 1077 case LTU:
1078 return "lo";
1079 default:
8ef66241 1080 gcc_unreachable ();
a28e4651 1081 }
1082}
1083
20c71901 1084/* Output ADDR to FILE as address. */
a28e4651 1085
1086void
206a5129 1087print_operand_address (FILE *file, rtx addr)
a28e4651 1088{
1089 switch (GET_CODE (addr))
1090 {
1091 case REG:
1092 fprintf (file, ptrreg_to_str (REGNO (addr)));
1093 break;
1094
1095 case PRE_DEC:
1096 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1097 break;
1098
1099 case POST_INC:
1100 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1101 break;
1102
1103 default:
1104 if (CONSTANT_ADDRESS_P (addr)
a179a371 1105 && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
57463428 1106 || GET_CODE (addr) == LABEL_REF))
a28e4651 1107 {
1108 fprintf (file, "pm(");
1109 output_addr_const (file,addr);
1110 fprintf (file ,")");
1111 }
1112 else
1113 output_addr_const (file, addr);
1114 }
1115}
1116
1117
20c71901 1118/* Output X as assembler operand to file FILE. */
a28e4651 1119
1120void
206a5129 1121print_operand (FILE *file, rtx x, int code)
a28e4651 1122{
1123 int abcd = 0;
1124
1125 if (code >= 'A' && code <= 'D')
1126 abcd = code - 'A';
1127
3b351734 1128 if (code == '~')
1129 {
1130 if (!AVR_MEGA)
1131 fputc ('r', file);
1132 }
1133 else if (REG_P (x))
a28e4651 1134 {
1135 if (x == zero_reg_rtx)
3b351734 1136 fprintf (file, "__zero_reg__");
a28e4651 1137 else
1138 fprintf (file, reg_names[true_regnum (x) + abcd]);
1139 }
1140 else if (GET_CODE (x) == CONST_INT)
636eb6b4 1141 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd);
a28e4651 1142 else if (GET_CODE (x) == MEM)
1143 {
1144 rtx addr = XEXP (x,0);
e511e253 1145
1146 if (CONSTANT_P (addr) && abcd)
a28e4651 1147 {
1148 fputc ('(', file);
1149 output_address (addr);
1150 fprintf (file, ")+%d", abcd);
1151 }
3b351734 1152 else if (code == 'o')
1153 {
1154 if (GET_CODE (addr) != PLUS)
68435912 1155 fatal_insn ("bad address, not (reg+disp):", addr);
3b351734 1156
1157 print_operand (file, XEXP (addr, 1), 0);
1158 }
f43bae99 1159 else if (code == 'p' || code == 'r')
1160 {
1161 if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
1162 fatal_insn ("bad address, not post_inc or pre_dec:", addr);
1163
1164 if (code == 'p')
1165 print_operand_address (file, XEXP (addr, 0)); /* X, Y, Z */
1166 else
1167 print_operand (file, XEXP (addr, 0), 0); /* r26, r28, r30 */
1168 }
a28e4651 1169 else if (GET_CODE (addr) == PLUS)
1170 {
1171 print_operand_address (file, XEXP (addr,0));
1172 if (REGNO (XEXP (addr, 0)) == REG_X)
68435912 1173 fatal_insn ("internal compiler error. Bad address:"
a28e4651 1174 ,addr);
1175 fputc ('+', file);
1176 print_operand (file, XEXP (addr,1), code);
1177 }
1178 else
1179 print_operand_address (file, addr);
1180 }
1181 else if (GET_CODE (x) == CONST_DOUBLE)
1182 {
1183 long val;
1184 REAL_VALUE_TYPE rv;
1185 if (GET_MODE (x) != SFmode)
68435912 1186 fatal_insn ("internal compiler error. Unknown mode:", x);
a28e4651 1187 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1188 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
7fe1d31c 1189 fprintf (file, "0x%lx", val);
a28e4651 1190 }
1191 else if (code == 'j')
7fe1d31c 1192 fputs (cond_string (GET_CODE (x)), file);
a28e4651 1193 else if (code == 'k')
7fe1d31c 1194 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
a28e4651 1195 else
1ae5b968 1196 print_operand_address (file, x);
a28e4651 1197}
1198
a28e4651 1199/* Update the condition code in the INSN. */
1200
1201void
206a5129 1202notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
a28e4651 1203{
1cb39658 1204 rtx set;
1205
a28e4651 1206 switch (get_attr_cc (insn))
1207 {
1208 case CC_NONE:
1209 /* Insn does not affect CC at all. */
1210 break;
1211
1212 case CC_SET_N:
1213 CC_STATUS_INIT;
1214 break;
1215
1216 case CC_SET_ZN:
1cb39658 1217 set = single_set (insn);
1218 CC_STATUS_INIT;
1219 if (set)
1220 {
1221 cc_status.flags |= CC_NO_OVERFLOW;
1222 cc_status.value1 = SET_DEST (set);
1223 }
a28e4651 1224 break;
1225
1226 case CC_SET_CZN:
1227 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1228 The V flag may or may not be known but that's ok because
1229 alter_cond will change tests to use EQ/NE. */
1cb39658 1230 set = single_set (insn);
1231 CC_STATUS_INIT;
1232 if (set)
1233 {
1234 cc_status.value1 = SET_DEST (set);
1235 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1236 }
a28e4651 1237 break;
1238
1239 case CC_COMPARE:
1cb39658 1240 set = single_set (insn);
1241 CC_STATUS_INIT;
1242 if (set)
1243 cc_status.value1 = SET_SRC (set);
a28e4651 1244 break;
1cb39658 1245
a28e4651 1246 case CC_CLOBBER:
1247 /* Insn doesn't leave CC in a usable state. */
1248 CC_STATUS_INIT;
1cb39658 1249
1250 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1251 set = single_set (insn);
1252 if (set)
1253 {
1254 rtx src = SET_SRC (set);
1255
1256 if (GET_CODE (src) == ASHIFTRT
1257 && GET_MODE (src) == QImode)
1258 {
1259 rtx x = XEXP (src, 1);
1260
1261 if (GET_CODE (x) == CONST_INT
5667001b 1262 && INTVAL (x) > 0
1cb39658 1263 && INTVAL (x) != 6)
1264 {
1265 cc_status.value1 = SET_DEST (set);
1266 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1267 }
1268 }
1269 }
a28e4651 1270 break;
1271 }
1272}
1273
1274/* Return maximum number of consecutive registers of
1275 class CLASS needed to hold a value of mode MODE. */
1276
1277int
206a5129 1278class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED,enum machine_mode mode)
a28e4651 1279{
1280 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1281}
1282
1283/* Choose mode for jump insn:
1284 1 - relative jump in range -63 <= x <= 62 ;
1285 2 - relative jump in range -2046 <= x <= 2045 ;
1286 3 - absolute jump (only for ATmega[16]03). */
1287
1288int
206a5129 1289avr_jump_mode (rtx x, rtx insn)
a28e4651 1290{
47fc0706 1291 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1292 ? XEXP (x, 0) : x));
1293 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
a28e4651 1294 int jump_distance = cur_addr - dest_addr;
1295
1296 if (-63 <= jump_distance && jump_distance <= 62)
1297 return 1;
1298 else if (-2046 <= jump_distance && jump_distance <= 2045)
1299 return 2;
1300 else if (AVR_MEGA)
1301 return 3;
1302
1303 return 2;
1304}
1305
e7d17bf3 1306/* return an AVR condition jump commands.
1307 X is a comparison RTX.
1308 LEN is a number returned by avr_jump_mode function.
1309 if REVERSE nonzero then condition code in X must be reversed. */
a28e4651 1310
37ac04dc 1311const char *
206a5129 1312ret_cond_branch (rtx x, int len, int reverse)
a28e4651 1313{
e7d17bf3 1314 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1315
a28e4651 1316 switch (cond)
1317 {
1318 case GT:
1319 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
31bf8549 1320 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
a28e4651 1321 AS1 (brpl,%0)) :
31bf8549 1322 len == 2 ? (AS1 (breq,.+4) CR_TAB
1323 AS1 (brmi,.+2) CR_TAB
a28e4651 1324 AS1 (rjmp,%0)) :
31bf8549 1325 (AS1 (breq,.+6) CR_TAB
1326 AS1 (brmi,.+4) CR_TAB
a28e4651 1327 AS1 (jmp,%0)));
1328
1329 else
31bf8549 1330 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
a28e4651 1331 AS1 (brge,%0)) :
31bf8549 1332 len == 2 ? (AS1 (breq,.+4) CR_TAB
1333 AS1 (brlt,.+2) CR_TAB
a28e4651 1334 AS1 (rjmp,%0)) :
31bf8549 1335 (AS1 (breq,.+6) CR_TAB
1336 AS1 (brlt,.+4) CR_TAB
a28e4651 1337 AS1 (jmp,%0)));
1338 case GTU:
31bf8549 1339 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
a28e4651 1340 AS1 (brsh,%0)) :
31bf8549 1341 len == 2 ? (AS1 (breq,.+4) CR_TAB
1342 AS1 (brlo,.+2) CR_TAB
a28e4651 1343 AS1 (rjmp,%0)) :
31bf8549 1344 (AS1 (breq,.+6) CR_TAB
1345 AS1 (brlo,.+4) CR_TAB
a28e4651 1346 AS1 (jmp,%0)));
1347 case LE:
1348 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1349 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1350 AS1 (brmi,%0)) :
31bf8549 1351 len == 2 ? (AS1 (breq,.+2) CR_TAB
1352 AS1 (brpl,.+2) CR_TAB
a28e4651 1353 AS1 (rjmp,%0)) :
31bf8549 1354 (AS1 (breq,.+2) CR_TAB
1355 AS1 (brpl,.+4) CR_TAB
a28e4651 1356 AS1 (jmp,%0)));
1357 else
1358 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1359 AS1 (brlt,%0)) :
31bf8549 1360 len == 2 ? (AS1 (breq,.+2) CR_TAB
1361 AS1 (brge,.+2) CR_TAB
a28e4651 1362 AS1 (rjmp,%0)) :
31bf8549 1363 (AS1 (breq,.+2) CR_TAB
1364 AS1 (brge,.+4) CR_TAB
a28e4651 1365 AS1 (jmp,%0)));
1366 case LEU:
1367 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1368 AS1 (brlo,%0)) :
31bf8549 1369 len == 2 ? (AS1 (breq,.+2) CR_TAB
1370 AS1 (brsh,.+2) CR_TAB
a28e4651 1371 AS1 (rjmp,%0)) :
31bf8549 1372 (AS1 (breq,.+2) CR_TAB
1373 AS1 (brsh,.+4) CR_TAB
a28e4651 1374 AS1 (jmp,%0)));
1375 default:
e7d17bf3 1376 if (reverse)
1377 {
1378 switch (len)
1379 {
1380 case 1:
1381 return AS1 (br%k1,%0);
1382 case 2:
31bf8549 1383 return (AS1 (br%j1,.+2) CR_TAB
e7d17bf3 1384 AS1 (rjmp,%0));
1385 default:
31bf8549 1386 return (AS1 (br%j1,.+4) CR_TAB
e7d17bf3 1387 AS1 (jmp,%0));
1388 }
1389 }
1390 else
1391 {
1392 switch (len)
1393 {
1394 case 1:
1395 return AS1 (br%j1,%0);
1396 case 2:
31bf8549 1397 return (AS1 (br%k1,.+2) CR_TAB
e7d17bf3 1398 AS1 (rjmp,%0));
1399 default:
31bf8549 1400 return (AS1 (br%k1,.+4) CR_TAB
e7d17bf3 1401 AS1 (jmp,%0));
1402 }
1403 }
a28e4651 1404 }
1405 return "";
1406}
1407
1408/* Predicate function for immediate operand which fits to byte (8bit) */
1409
1410int
206a5129 1411byte_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
a28e4651 1412{
1413 return (GET_CODE (op) == CONST_INT
1414 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1415}
1416
1417/* Output all insn addresses and their sizes into the assembly language
1418 output file. This is helpful for debugging whether the length attributes
1419 in the md file are correct.
1420 Output insn cost for next insn. */
1421
1422void
206a5129 1423final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
1424 int num_operands ATTRIBUTE_UNUSED)
a28e4651 1425{
1426 int uid = INSN_UID (insn);
1427
1428 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1429 {
47fc0706 1430 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1431 INSN_ADDRESSES (uid),
1432 INSN_ADDRESSES (uid) - last_insn_address,
1433 rtx_cost (PATTERN (insn), INSN));
a28e4651 1434 }
47fc0706 1435 last_insn_address = INSN_ADDRESSES (uid);
a28e4651 1436}
1437
37ac04dc 1438/* Return 0 if undefined, 1 if always true or always false. */
a28e4651 1439
1440int
206a5129 1441avr_simplify_comparison_p (enum machine_mode mode, RTX_CODE operator, rtx x)
a28e4651 1442{
1443 unsigned int max = (mode == QImode ? 0xff :
1444 mode == HImode ? 0xffff :
30435bf8 1445 mode == SImode ? 0xffffffff : 0);
a28e4651 1446 if (max && operator && GET_CODE (x) == CONST_INT)
1447 {
1448 if (unsigned_condition (operator) != operator)
1449 max >>= 1;
1450
1451 if (max != (INTVAL (x) & max)
1452 && INTVAL (x) != 0xff)
1453 return 1;
1454 }
1455 return 0;
1456}
1457
1458
1459/* Returns nonzero if REGNO is the number of a hard
1460 register in which function arguments are sometimes passed. */
1461
1462int
206a5129 1463function_arg_regno_p(int r)
a28e4651 1464{
1465 return (r >= 8 && r <= 25);
1466}
1467
1468/* Initializing the variable cum for the state at the beginning
1469 of the argument list. */
1470
1471void
206a5129 1472init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
1473 tree fndecl ATTRIBUTE_UNUSED)
a28e4651 1474{
1475 cum->nregs = 18;
1476 cum->regno = FIRST_CUM_REG;
e9b473cd 1477 if (!libname && fntype)
a28e4651 1478 {
1479 int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1480 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1481 != void_type_node));
1482 if (stdarg)
1483 cum->nregs = 0;
1484 }
1485}
1486
0af74aa0 1487/* Returns the number of registers to allocate for a function argument. */
1488
1489static int
206a5129 1490avr_num_arg_regs (enum machine_mode mode, tree type)
0af74aa0 1491{
1492 int size;
1493
1494 if (mode == BLKmode)
1495 size = int_size_in_bytes (type);
1496 else
1497 size = GET_MODE_SIZE (mode);
1498
b681d971 1499 /* Align all function arguments to start in even-numbered registers.
1500 Odd-sized arguments leave holes above them. */
0af74aa0 1501
b681d971 1502 return (size + 1) & ~1;
0af74aa0 1503}
1504
a28e4651 1505/* Controls whether a function argument is passed
20c71901 1506 in a register, and which register. */
a28e4651 1507
1508rtx
206a5129 1509function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1510 int named ATTRIBUTE_UNUSED)
a28e4651 1511{
0af74aa0 1512 int bytes = avr_num_arg_regs (mode, type);
a28e4651 1513
1514 if (cum->nregs && bytes <= cum->nregs)
1a83b3ff 1515 return gen_rtx_REG (mode, cum->regno - bytes);
0af74aa0 1516
a28e4651 1517 return NULL_RTX;
1518}
1519
1520/* Update the summarizer variable CUM to advance past an argument
1521 in the argument list. */
1522
1523void
206a5129 1524function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1525 int named ATTRIBUTE_UNUSED)
a28e4651 1526{
0af74aa0 1527 int bytes = avr_num_arg_regs (mode, type);
a28e4651 1528
a28e4651 1529 cum->nregs -= bytes;
1530 cum->regno -= bytes;
1531
1532 if (cum->nregs <= 0)
1533 {
1534 cum->nregs = 0;
1535 cum->regno = FIRST_CUM_REG;
1536 }
a28e4651 1537}
1538
1539/***********************************************************************
1540 Functions for outputting various mov's for a various modes
1541************************************************************************/
37ac04dc 1542const char *
206a5129 1543output_movqi (rtx insn, rtx operands[], int *l)
a28e4651 1544{
e511e253 1545 int dummy;
1546 rtx dest = operands[0];
1547 rtx src = operands[1];
1548 int *real_l = l;
1549
1550 if (!l)
1551 l = &dummy;
1552
1553 *l = 1;
1554
1555 if (register_operand (dest, QImode))
a28e4651 1556 {
e511e253 1557 if (register_operand (src, QImode)) /* mov r,r */
a28e4651 1558 {
e511e253 1559 if (test_hard_reg_class (STACK_REG, dest))
1560 return AS2 (out,%0,%1);
1561 else if (test_hard_reg_class (STACK_REG, src))
1562 return AS2 (in,%0,%1);
1563
1564 return AS2 (mov,%0,%1);
1565 }
1566 else if (CONSTANT_P (src))
1567 {
1568 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1569 return AS2 (ldi,%0,lo8(%1));
1570
1571 if (GET_CODE (src) == CONST_INT)
a28e4651 1572 {
e511e253 1573 if (src == const0_rtx) /* mov r,L */
1574 return AS1 (clr,%0);
1575 else if (src == const1_rtx)
a28e4651 1576 {
e511e253 1577 *l = 2;
1578 return (AS1 (clr,%0) CR_TAB
1579 AS1 (inc,%0));
1580 }
e511e253 1581 else if (src == constm1_rtx)
a28e4651 1582 {
e511e253 1583 /* Immediate constants -1 to any register */
e511e253 1584 *l = 2;
1585 return (AS1 (clr,%0) CR_TAB
1586 AS1 (dec,%0));
a28e4651 1587 }
b681d971 1588 else
1589 {
1590 int bit_nr = exact_log2 (INTVAL (src));
1591
1592 if (bit_nr >= 0)
1593 {
8e999997 1594 *l = 3;
1595 if (!real_l)
1596 output_asm_insn ((AS1 (clr,%0) CR_TAB
1597 "set"), operands);
b681d971 1598 if (!real_l)
1599 avr_output_bld (operands, bit_nr);
1600
1601 return "";
1602 }
1603 }
a28e4651 1604 }
e511e253 1605
1606 /* Last resort, larger than loading from memory. */
1607 *l = 4;
1608 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1609 AS2 (ldi,r31,lo8(%1)) CR_TAB
1610 AS2 (mov,%0,r31) CR_TAB
1611 AS2 (mov,r31,__tmp_reg__));
1612 }
1613 else if (GET_CODE (src) == MEM)
1614 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1615 }
1616 else if (GET_CODE (dest) == MEM)
1617 {
37ac04dc 1618 const char *template;
1619
1620 if (src == const0_rtx)
1621 operands[1] = zero_reg_rtx;
1622
e511e253 1623 template = out_movqi_mr_r (insn, operands, real_l);
1624
1625 if (!real_l)
1626 output_asm_insn (template, operands);
37ac04dc 1627
1628 operands[1] = src;
e511e253 1629 }
1630 return "";
1631}
1632
1633
37ac04dc 1634const char *
206a5129 1635output_movhi (rtx insn, rtx operands[], int *l)
e511e253 1636{
1637 int dummy;
1638 rtx dest = operands[0];
1639 rtx src = operands[1];
1640 int *real_l = l;
1641
1642 if (!l)
1643 l = &dummy;
1644
1645 if (register_operand (dest, HImode))
1646 {
1647 if (register_operand (src, HImode)) /* mov r,r */
1648 {
1649 if (test_hard_reg_class (STACK_REG, dest))
a28e4651 1650 {
e511e253 1651 if (TARGET_TINY_STACK)
1652 {
1653 *l = 1;
1654 return AS2 (out,__SP_L__,%A1);
1655 }
df3d6232 1656 /* Use simple load of stack pointer if no interrupts are used
1657 or inside main or signal function prologue where they disabled. */
1658 else if (TARGET_NO_INTERRUPTS
1659 || (reload_completed
1660 && cfun->machine->is_main
1661 && prologue_epilogue_contains (insn))
1662 || (reload_completed
1663 && cfun->machine->is_signal
1664 && prologue_epilogue_contains (insn)))
1665 {
1666 *l = 2;
1667 return (AS2 (out,__SP_H__,%B1) CR_TAB
1668 AS2 (out,__SP_L__,%A1));
1669 }
1670 /* In interrupt prolog we know interrupts are enabled. */
1671 else if (reload_completed
1672 && cfun->machine->is_interrupt
1673 && prologue_epilogue_contains (insn))
1674 {
1675 *l = 4;
1676 return ("cli" CR_TAB
1677 AS2 (out,__SP_H__,%B1) CR_TAB
1678 "sei" CR_TAB
1679 AS2 (out,__SP_L__,%A1));
1680 }
e511e253 1681 *l = 5;
1682 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1683 "cli" CR_TAB
1684 AS2 (out,__SP_H__,%B1) CR_TAB
1685 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1686 AS2 (out,__SP_L__,%A1));
1687 }
1688 else if (test_hard_reg_class (STACK_REG, src))
1689 {
1690 *l = 2;
1691 return (AS2 (in,%A0,__SP_L__) CR_TAB
1692 AS2 (in,%B0,__SP_H__));
1693 }
1694
0aab73c2 1695 if (AVR_HAVE_MOVW)
e511e253 1696 {
1697 *l = 1;
1698 return (AS2 (movw,%0,%1));
1699 }
e511e253 1700 else
1701 {
1702 *l = 2;
1703 return (AS2 (mov,%A0,%A1) CR_TAB
1704 AS2 (mov,%B0,%B1));
1705 }
1706 }
1707 else if (CONSTANT_P (src))
1708 {
1709 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1710 {
1711 *l = 2;
1712 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1713 AS2 (ldi,%B0,hi8(%1)));
1714 }
1715
1716 if (GET_CODE (src) == CONST_INT)
1717 {
1718 if (src == const0_rtx) /* mov r,L */
1719 {
1720 *l = 2;
1721 return (AS1 (clr,%A0) CR_TAB
1722 AS1 (clr,%B0));
1723 }
1724 else if (src == const1_rtx)
1725 {
47f97894 1726 *l = 3;
1727 return (AS1 (clr,%A0) CR_TAB
1728 AS1 (clr,%B0) CR_TAB
1729 AS1 (inc,%A0));
e511e253 1730 }
e511e253 1731 else if (src == constm1_rtx)
1732 {
1733 /* Immediate constants -1 to any register */
e511e253 1734 *l = 3;
1735 return (AS1 (clr,%0) CR_TAB
1736 AS1 (dec,%A0) CR_TAB
1737 AS2 (mov,%B0,%A0));
1738 }
b681d971 1739 else
1740 {
1741 int bit_nr = exact_log2 (INTVAL (src));
1742
1743 if (bit_nr >= 0)
1744 {
8e999997 1745 *l = 4;
1746 if (!real_l)
1747 output_asm_insn ((AS1 (clr,%A0) CR_TAB
1748 AS1 (clr,%B0) CR_TAB
1749 "set"), operands);
b681d971 1750 if (!real_l)
1751 avr_output_bld (operands, bit_nr);
1752
1753 return "";
1754 }
1755 }
1756
e511e253 1757 if ((INTVAL (src) & 0xff) == 0)
1758 {
1759 *l = 5;
1760 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1761 AS1 (clr,%A0) CR_TAB
1762 AS2 (ldi,r31,hi8(%1)) CR_TAB
1763 AS2 (mov,%B0,r31) CR_TAB
1764 AS2 (mov,r31,__tmp_reg__));
1765 }
1766 else if ((INTVAL (src) & 0xff00) == 0)
1767 {
1768 *l = 5;
1769 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1770 AS2 (ldi,r31,lo8(%1)) CR_TAB
1771 AS2 (mov,%A0,r31) CR_TAB
1772 AS1 (clr,%B0) CR_TAB
1773 AS2 (mov,r31,__tmp_reg__));
a28e4651 1774 }
a28e4651 1775 }
e511e253 1776
1777 /* Last resort, equal to loading from memory. */
1778 *l = 6;
1779 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1780 AS2 (ldi,r31,lo8(%1)) CR_TAB
1781 AS2 (mov,%A0,r31) CR_TAB
1782 AS2 (ldi,r31,hi8(%1)) CR_TAB
1783 AS2 (mov,%B0,r31) CR_TAB
1784 AS2 (mov,r31,__tmp_reg__));
1785 }
1786 else if (GET_CODE (src) == MEM)
1787 return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1788 }
1789 else if (GET_CODE (dest) == MEM)
1790 {
37ac04dc 1791 const char *template;
1792
1793 if (src == const0_rtx)
1794 operands[1] = zero_reg_rtx;
1795
e511e253 1796 template = out_movhi_mr_r (insn, operands, real_l);
1797
1798 if (!real_l)
1799 output_asm_insn (template, operands);
37ac04dc 1800
1801 operands[1] = src;
e511e253 1802 return "";
a28e4651 1803 }
68435912 1804 fatal_insn ("invalid insn:", insn);
e511e253 1805 return "";
1806}
1807
37ac04dc 1808const char *
206a5129 1809out_movqi_r_mr (rtx insn, rtx op[], int *l)
e511e253 1810{
37ac04dc 1811 rtx dest = op[0];
1812 rtx src = op[1];
1813 rtx x = XEXP (src, 0);
e511e253 1814 int dummy;
1815
1816 if (!l)
1817 l = &dummy;
e511e253 1818
1819 if (CONSTANT_ADDRESS_P (x))
1820 {
df3d6232 1821 if (CONST_INT_P (x) && INTVAL (x) == SREG_ADDR)
1822 {
1823 *l = 1;
1824 return AS2 (in,%0,__SREG__);
1825 }
57463428 1826 if (avr_io_address_p (x, 1))
e511e253 1827 {
1828 *l = 1;
1829 return AS2 (in,%0,%1-0x20);
1830 }
1831 *l = 2;
1832 return AS2 (lds,%0,%1);
1833 }
1834 /* memory access by reg+disp */
1835 else if (GET_CODE (x) == PLUS
1836 && REG_P (XEXP (x,0))
1837 && GET_CODE (XEXP (x,1)) == CONST_INT)
1838 {
37ac04dc 1839 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
e511e253 1840 {
1841 int disp = INTVAL (XEXP (x,1));
1842 if (REGNO (XEXP (x,0)) != REG_Y)
68435912 1843 fatal_insn ("incorrect insn:",insn);
db45d3ed 1844
37ac04dc 1845 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
db45d3ed 1846 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1847 AS2 (ldd,%0,Y+63) CR_TAB
1848 AS2 (sbiw,r28,%o1-63));
1849
1850 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1851 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1852 AS2 (ld,%0,Y) CR_TAB
1853 AS2 (subi,r28,lo8(%o1)) CR_TAB
1854 AS2 (sbci,r29,hi8(%o1)));
e511e253 1855 }
1856 else if (REGNO (XEXP (x,0)) == REG_X)
1857 {
e511e253 1858 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1859 it but I have this situation with extremal optimizing options. */
37ac04dc 1860 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
e511e253 1861 || reg_unused_after (insn, XEXP (x,0)))
db45d3ed 1862 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1863 AS2 (ld,%0,X));
1864
1865 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1866 AS2 (ld,%0,X) CR_TAB
1867 AS2 (sbiw,r26,%o1));
e511e253 1868 }
1869 *l = 1;
1870 return AS2 (ldd,%0,%1);
1871 }
1872 *l = 1;
1873 return AS2 (ld,%0,%1);
a28e4651 1874}
1875
37ac04dc 1876const char *
206a5129 1877out_movhi_r_mr (rtx insn, rtx op[], int *l)
a28e4651 1878{
37ac04dc 1879 rtx dest = op[0];
1880 rtx src = op[1];
1881 rtx base = XEXP (src, 0);
1882 int reg_dest = true_regnum (dest);
1883 int reg_base = true_regnum (base);
f43bae99 1884 /* "volatile" forces reading low byte first, even if less efficient,
1885 for correct operation with 16-bit I/O registers. */
1886 int mem_volatile_p = MEM_VOLATILE_P (src);
e511e253 1887 int tmp;
a28e4651 1888
1889 if (!l)
e511e253 1890 l = &tmp;
a28e4651 1891
1892 if (reg_base > 0)
1893 {
1894 if (reg_dest == reg_base) /* R = (R) */
e511e253 1895 {
1896 *l = 3;
1897 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1898 AS2 (ld,%B0,%1) CR_TAB
1899 AS2 (mov,%A0,__tmp_reg__));
1900 }
a28e4651 1901 else if (reg_base == REG_X) /* (R26) */
1902 {
37ac04dc 1903 if (reg_unused_after (insn, base))
e511e253 1904 {
1905 *l = 2;
1906 return (AS2 (ld,%A0,X+) CR_TAB
1907 AS2 (ld,%B0,X));
1908 }
1909 *l = 3;
1910 return (AS2 (ld,%A0,X+) CR_TAB
1911 AS2 (ld,%B0,X) CR_TAB
1912 AS2 (sbiw,r26,1));
a28e4651 1913 }
1914 else /* (R) */
e511e253 1915 {
1916 *l = 2;
1917 return (AS2 (ld,%A0,%1) CR_TAB
1918 AS2 (ldd,%B0,%1+1));
1919 }
a28e4651 1920 }
37ac04dc 1921 else if (GET_CODE (base) == PLUS) /* (R + i) */
a28e4651 1922 {
37ac04dc 1923 int disp = INTVAL (XEXP (base, 1));
1924 int reg_base = true_regnum (XEXP (base, 0));
a28e4651 1925
37ac04dc 1926 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
a28e4651 1927 {
37ac04dc 1928 if (REGNO (XEXP (base, 0)) != REG_Y)
68435912 1929 fatal_insn ("incorrect insn:",insn);
e511e253 1930
37ac04dc 1931 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
db45d3ed 1932 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
1933 AS2 (ldd,%A0,Y+62) CR_TAB
1934 AS2 (ldd,%B0,Y+63) CR_TAB
1935 AS2 (sbiw,r28,%o1-62));
1936
1937 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1938 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1939 AS2 (ld,%A0,Y) CR_TAB
1940 AS2 (ldd,%B0,Y+1) CR_TAB
1941 AS2 (subi,r28,lo8(%o1)) CR_TAB
1942 AS2 (sbci,r29,hi8(%o1)));
a28e4651 1943 }
1944 if (reg_base == REG_X)
1945 {
1946 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
e511e253 1947 it but I have this situation with extremal
1948 optimization options. */
1949
db45d3ed 1950 *l = 4;
e511e253 1951 if (reg_base == reg_dest)
db45d3ed 1952 return (AS2 (adiw,r26,%o1) CR_TAB
1953 AS2 (ld,__tmp_reg__,X+) CR_TAB
1954 AS2 (ld,%B0,X) CR_TAB
1955 AS2 (mov,%A0,__tmp_reg__));
e511e253 1956
db45d3ed 1957 return (AS2 (adiw,r26,%o1) CR_TAB
1958 AS2 (ld,%A0,X+) CR_TAB
1959 AS2 (ld,%B0,X) CR_TAB
1960 AS2 (sbiw,r26,%o1+1));
e511e253 1961 }
1962
1963 if (reg_base == reg_dest)
1964 {
1965 *l = 3;
1966 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
1967 AS2 (ldd,%B0,%B1) CR_TAB
1968 AS2 (mov,%A0,__tmp_reg__));
a28e4651 1969 }
1970
e511e253 1971 *l = 2;
1972 return (AS2 (ldd,%A0,%A1) CR_TAB
1973 AS2 (ldd,%B0,%B1));
a28e4651 1974 }
37ac04dc 1975 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
a28e4651 1976 {
37ac04dc 1977 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
68435912 1978 fatal_insn ("incorrect insn:", insn);
e511e253 1979
f43bae99 1980 if (mem_volatile_p)
1981 {
1982 if (REGNO (XEXP (base, 0)) == REG_X)
1983 {
1984 *l = 4;
1985 return (AS2 (sbiw,r26,2) CR_TAB
1986 AS2 (ld,%A0,X+) CR_TAB
1987 AS2 (ld,%B0,X) CR_TAB
1988 AS2 (sbiw,r26,1));
1989 }
1990 else
1991 {
1992 *l = 3;
1993 return (AS2 (sbiw,%r1,2) CR_TAB
1994 AS2 (ld,%A0,%p1) CR_TAB
1995 AS2 (ldd,%B0,%p1+1));
1996 }
1997 }
1998
e511e253 1999 *l = 2;
2000 return (AS2 (ld,%B0,%1) CR_TAB
2001 AS2 (ld,%A0,%1));
a28e4651 2002 }
37ac04dc 2003 else if (GET_CODE (base) == POST_INC) /* (R++) */
a28e4651 2004 {
37ac04dc 2005 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
68435912 2006 fatal_insn ("incorrect insn:", insn);
e511e253 2007
2008 *l = 2;
2009 return (AS2 (ld,%A0,%1) CR_TAB
2010 AS2 (ld,%B0,%1));
a28e4651 2011 }
37ac04dc 2012 else if (CONSTANT_ADDRESS_P (base))
e511e253 2013 {
57463428 2014 if (avr_io_address_p (base, 2))
37ac04dc 2015 {
2016 *l = 2;
2017 return (AS2 (in,%A0,%A1-0x20) CR_TAB
2018 AS2 (in,%B0,%B1-0x20));
2019 }
e511e253 2020 *l = 4;
2021 return (AS2 (lds,%A0,%A1) CR_TAB
2022 AS2 (lds,%B0,%B1));
2023 }
2024
68435912 2025 fatal_insn ("unknown move insn:",insn);
a28e4651 2026 return "";
2027}
2028
37ac04dc 2029const char *
206a5129 2030out_movsi_r_mr (rtx insn, rtx op[], int *l)
a28e4651 2031{
37ac04dc 2032 rtx dest = op[0];
2033 rtx src = op[1];
2034 rtx base = XEXP (src, 0);
2035 int reg_dest = true_regnum (dest);
2036 int reg_base = true_regnum (base);
a28e4651 2037 int tmp;
e511e253 2038
a28e4651 2039 if (!l)
e511e253 2040 l = &tmp;
2041
a28e4651 2042 if (reg_base > 0)
2043 {
2044 if (reg_base == REG_X) /* (R26) */
2045 {
2046 if (reg_dest == REG_X)
66ad0834 2047 /* "ld r26,-X" is undefined */
2048 return *l=7, (AS2 (adiw,r26,3) CR_TAB
2049 AS2 (ld,r29,X) CR_TAB
2050 AS2 (ld,r28,-X) CR_TAB
2051 AS2 (ld,__tmp_reg__,-X) CR_TAB
2052 AS2 (sbiw,r26,1) CR_TAB
2053 AS2 (ld,r26,X) CR_TAB
2054 AS2 (mov,r27,__tmp_reg__));
a28e4651 2055 else if (reg_dest == REG_X - 2)
2056 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2057 AS2 (ld,%B0,X+) CR_TAB
2058 AS2 (ld,__tmp_reg__,X+) CR_TAB
2059 AS2 (ld,%D0,X) CR_TAB
2060 AS2 (mov,%C0,__tmp_reg__));
37ac04dc 2061 else if (reg_unused_after (insn, base))
a28e4651 2062 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
2063 AS2 (ld,%B0,X+) CR_TAB
2064 AS2 (ld,%C0,X+) CR_TAB
2065 AS2 (ld,%D0,X));
2066 else
2067 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2068 AS2 (ld,%B0,X+) CR_TAB
2069 AS2 (ld,%C0,X+) CR_TAB
2070 AS2 (ld,%D0,X) CR_TAB
2071 AS2 (sbiw,r26,3));
2072 }
2073 else
2074 {
2075 if (reg_dest == reg_base)
2076 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
2077 AS2 (ldd,%C0,%1+2) CR_TAB
2078 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
2079 AS2 (ld,%A0,%1) CR_TAB
2080 AS2 (mov,%B0,__tmp_reg__));
2081 else if (reg_base == reg_dest + 2)
2082 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
2083 AS2 (ldd,%B0,%1+1) CR_TAB
2084 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
2085 AS2 (ldd,%D0,%1+3) CR_TAB
2086 AS2 (mov,%C0,__tmp_reg__));
2087 else
2088 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
2089 AS2 (ldd,%B0,%1+1) CR_TAB
2090 AS2 (ldd,%C0,%1+2) CR_TAB
2091 AS2 (ldd,%D0,%1+3));
2092 }
2093 }
37ac04dc 2094 else if (GET_CODE (base) == PLUS) /* (R + i) */
a28e4651 2095 {
37ac04dc 2096 int disp = INTVAL (XEXP (base, 1));
a28e4651 2097
37ac04dc 2098 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
a28e4651 2099 {
37ac04dc 2100 if (REGNO (XEXP (base, 0)) != REG_Y)
68435912 2101 fatal_insn ("incorrect insn:",insn);
db45d3ed 2102
37ac04dc 2103 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
db45d3ed 2104 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2105 AS2 (ldd,%A0,Y+60) CR_TAB
2106 AS2 (ldd,%B0,Y+61) CR_TAB
2107 AS2 (ldd,%C0,Y+62) CR_TAB
2108 AS2 (ldd,%D0,Y+63) CR_TAB
2109 AS2 (sbiw,r28,%o1-60));
2110
2111 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2112 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2113 AS2 (ld,%A0,Y) CR_TAB
2114 AS2 (ldd,%B0,Y+1) CR_TAB
2115 AS2 (ldd,%C0,Y+2) CR_TAB
2116 AS2 (ldd,%D0,Y+3) CR_TAB
2117 AS2 (subi,r28,lo8(%o1)) CR_TAB
2118 AS2 (sbci,r29,hi8(%o1)));
a28e4651 2119 }
2120
37ac04dc 2121 reg_base = true_regnum (XEXP (base, 0));
66ad0834 2122 if (reg_base == REG_X)
2123 {
2124 /* R = (X + d) */
2125 if (reg_dest == REG_X)
2126 {
2127 *l = 7;
2128 /* "ld r26,-X" is undefined */
2129 return (AS2 (adiw,r26,%o1+3) CR_TAB
2130 AS2 (ld,r29,X) CR_TAB
2131 AS2 (ld,r28,-X) CR_TAB
2132 AS2 (ld,__tmp_reg__,-X) CR_TAB
2133 AS2 (sbiw,r26,1) CR_TAB
2134 AS2 (ld,r26,X) CR_TAB
2135 AS2 (mov,r27,__tmp_reg__));
2136 }
2137 *l = 6;
2138 if (reg_dest == REG_X - 2)
2139 return (AS2 (adiw,r26,%o1) CR_TAB
2140 AS2 (ld,r24,X+) CR_TAB
2141 AS2 (ld,r25,X+) CR_TAB
2142 AS2 (ld,__tmp_reg__,X+) CR_TAB
2143 AS2 (ld,r27,X) CR_TAB
2144 AS2 (mov,r26,__tmp_reg__));
2145
2146 return (AS2 (adiw,r26,%o1) CR_TAB
2147 AS2 (ld,%A0,X+) CR_TAB
2148 AS2 (ld,%B0,X+) CR_TAB
2149 AS2 (ld,%C0,X+) CR_TAB
2150 AS2 (ld,%D0,X) CR_TAB
2151 AS2 (sbiw,r26,%o1+3));
2152 }
a28e4651 2153 if (reg_dest == reg_base)
2154 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2155 AS2 (ldd,%C0,%C1) CR_TAB
2156 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
2157 AS2 (ldd,%A0,%A1) CR_TAB
2158 AS2 (mov,%B0,__tmp_reg__));
2159 else if (reg_dest == reg_base - 2)
2160 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2161 AS2 (ldd,%B0,%B1) CR_TAB
2162 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
2163 AS2 (ldd,%D0,%D1) CR_TAB
2164 AS2 (mov,%C0,__tmp_reg__));
2165 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2166 AS2 (ldd,%B0,%B1) CR_TAB
2167 AS2 (ldd,%C0,%C1) CR_TAB
2168 AS2 (ldd,%D0,%D1));
2169 }
37ac04dc 2170 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
a28e4651 2171 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2172 AS2 (ld,%C0,%1) CR_TAB
2173 AS2 (ld,%B0,%1) CR_TAB
2174 AS2 (ld,%A0,%1));
37ac04dc 2175 else if (GET_CODE (base) == POST_INC) /* (R++) */
a28e4651 2176 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2177 AS2 (ld,%B0,%1) CR_TAB
2178 AS2 (ld,%C0,%1) CR_TAB
2179 AS2 (ld,%D0,%1));
37ac04dc 2180 else if (CONSTANT_ADDRESS_P (base))
a28e4651 2181 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2182 AS2 (lds,%B0,%B1) CR_TAB
2183 AS2 (lds,%C0,%C1) CR_TAB
2184 AS2 (lds,%D0,%D1));
2185
68435912 2186 fatal_insn ("unknown move insn:",insn);
a28e4651 2187 return "";
2188}
2189
37ac04dc 2190const char *
206a5129 2191out_movsi_mr_r (rtx insn, rtx op[], int *l)
a28e4651 2192{
37ac04dc 2193 rtx dest = op[0];
2194 rtx src = op[1];
2195 rtx base = XEXP (dest, 0);
2196 int reg_base = true_regnum (base);
2197 int reg_src = true_regnum (src);
a28e4651 2198 int tmp;
e511e253 2199
a28e4651 2200 if (!l)
2201 l = &tmp;
e511e253 2202
37ac04dc 2203 if (CONSTANT_ADDRESS_P (base))
a28e4651 2204 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2205 AS2 (sts,%B0,%B1) CR_TAB
2206 AS2 (sts,%C0,%C1) CR_TAB
2207 AS2 (sts,%D0,%D1));
2208 if (reg_base > 0) /* (r) */
2209 {
2210 if (reg_base == REG_X) /* (R26) */
2211 {
37ac04dc 2212 if (reg_src == REG_X)
a28e4651 2213 {
66ad0834 2214 /* "st X+,r26" is undefined */
37ac04dc 2215 if (reg_unused_after (insn, base))
66ad0834 2216 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2217 AS2 (st,X,r26) CR_TAB
2218 AS2 (adiw,r26,1) CR_TAB
2219 AS2 (st,X+,__tmp_reg__) CR_TAB
2220 AS2 (st,X+,r28) CR_TAB
2221 AS2 (st,X,r29));
a28e4651 2222 else
66ad0834 2223 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2224 AS2 (st,X,r26) CR_TAB
2225 AS2 (adiw,r26,1) CR_TAB
2226 AS2 (st,X+,__tmp_reg__) CR_TAB
2227 AS2 (st,X+,r28) CR_TAB
2228 AS2 (st,X,r29) CR_TAB
2229 AS2 (sbiw,r26,3));
a28e4651 2230 }
37ac04dc 2231 else if (reg_base == reg_src + 2)
a28e4651 2232 {
37ac04dc 2233 if (reg_unused_after (insn, base))
a28e4651 2234 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2235 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2236 AS2 (st,%0+,%A1) CR_TAB
2237 AS2 (st,%0+,%B1) CR_TAB
2238 AS2 (st,%0+,__zero_reg__) CR_TAB
2239 AS2 (st,%0,__tmp_reg__) CR_TAB
2240 AS1 (clr,__zero_reg__));
2241 else
2242 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2243 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2244 AS2 (st,%0+,%A1) CR_TAB
2245 AS2 (st,%0+,%B1) CR_TAB
2246 AS2 (st,%0+,__zero_reg__) CR_TAB
2247 AS2 (st,%0,__tmp_reg__) CR_TAB
2248 AS1 (clr,__zero_reg__) CR_TAB
2249 AS2 (sbiw,r26,3));
2250 }
2251 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
2252 AS2 (st,%0+,%B1) CR_TAB
2253 AS2 (st,%0+,%C1) CR_TAB
2254 AS2 (st,%0,%D1) CR_TAB
2255 AS2 (sbiw,r26,3));
2256 }
2257 else
2258 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2259 AS2 (std,%0+1,%B1) CR_TAB
2260 AS2 (std,%0+2,%C1) CR_TAB
2261 AS2 (std,%0+3,%D1));
2262 }
37ac04dc 2263 else if (GET_CODE (base) == PLUS) /* (R + i) */
a28e4651 2264 {
37ac04dc 2265 int disp = INTVAL (XEXP (base, 1));
66ad0834 2266 reg_base = REGNO (XEXP (base, 0));
37ac04dc 2267 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
a28e4651 2268 {
66ad0834 2269 if (reg_base != REG_Y)
68435912 2270 fatal_insn ("incorrect insn:",insn);
db45d3ed 2271
37ac04dc 2272 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
db45d3ed 2273 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2274 AS2 (std,Y+60,%A1) CR_TAB
2275 AS2 (std,Y+61,%B1) CR_TAB
2276 AS2 (std,Y+62,%C1) CR_TAB
2277 AS2 (std,Y+63,%D1) CR_TAB
2278 AS2 (sbiw,r28,%o0-60));
2279
2280 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2281 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2282 AS2 (st,Y,%A1) CR_TAB
2283 AS2 (std,Y+1,%B1) CR_TAB
2284 AS2 (std,Y+2,%C1) CR_TAB
2285 AS2 (std,Y+3,%D1) CR_TAB
2286 AS2 (subi,r28,lo8(%o0)) CR_TAB
2287 AS2 (sbci,r29,hi8(%o0)));
a28e4651 2288 }
66ad0834 2289 if (reg_base == REG_X)
2290 {
2291 /* (X + d) = R */
2292 if (reg_src == REG_X)
2293 {
2294 *l = 9;
2295 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2296 AS2 (mov,__zero_reg__,r27) CR_TAB
2297 AS2 (adiw,r26,%o0) CR_TAB
2298 AS2 (st,X+,__tmp_reg__) CR_TAB
2299 AS2 (st,X+,__zero_reg__) CR_TAB
2300 AS2 (st,X+,r28) CR_TAB
2301 AS2 (st,X,r29) CR_TAB
2302 AS1 (clr,__zero_reg__) CR_TAB
2303 AS2 (sbiw,r26,%o0+3));
2304 }
2305 else if (reg_src == REG_X - 2)
2306 {
2307 *l = 9;
2308 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2309 AS2 (mov,__zero_reg__,r27) CR_TAB
2310 AS2 (adiw,r26,%o0) CR_TAB
2311 AS2 (st,X+,r24) CR_TAB
2312 AS2 (st,X+,r25) CR_TAB
2313 AS2 (st,X+,__tmp_reg__) CR_TAB
2314 AS2 (st,X,__zero_reg__) CR_TAB
2315 AS1 (clr,__zero_reg__) CR_TAB
2316 AS2 (sbiw,r26,%o0+3));
2317 }
2318 *l = 6;
2319 return (AS2 (adiw,r26,%o0) CR_TAB
2320 AS2 (st,X+,%A1) CR_TAB
2321 AS2 (st,X+,%B1) CR_TAB
2322 AS2 (st,X+,%C1) CR_TAB
2323 AS2 (st,X,%D1) CR_TAB
2324 AS2 (sbiw,r26,%o0+3));
2325 }
a28e4651 2326 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
2327 AS2 (std,%B0,%B1) CR_TAB
2328 AS2 (std,%C0,%C1) CR_TAB
2329 AS2 (std,%D0,%D1));
2330 }
37ac04dc 2331 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
a28e4651 2332 return *l=4, (AS2 (st,%0,%D1) CR_TAB
2333 AS2 (st,%0,%C1) CR_TAB
2334 AS2 (st,%0,%B1) CR_TAB
2335 AS2 (st,%0,%A1));
37ac04dc 2336 else if (GET_CODE (base) == POST_INC) /* (R++) */
a28e4651 2337 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2338 AS2 (st,%0,%B1) CR_TAB
2339 AS2 (st,%0,%C1) CR_TAB
2340 AS2 (st,%0,%D1));
68435912 2341 fatal_insn ("unknown move insn:",insn);
a28e4651 2342 return "";
2343}
2344
37ac04dc 2345const char *
206a5129 2346output_movsisf(rtx insn, rtx operands[], int *l)
a28e4651 2347{
e511e253 2348 int dummy;
2349 rtx dest = operands[0];
2350 rtx src = operands[1];
2351 int *real_l = l;
2352
2353 if (!l)
2354 l = &dummy;
2355
2356 if (register_operand (dest, VOIDmode))
a28e4651 2357 {
e511e253 2358 if (register_operand (src, VOIDmode)) /* mov r,r */
0af74aa0 2359 {
e511e253 2360 if (true_regnum (dest) > true_regnum (src))
2361 {
0aab73c2 2362 if (AVR_HAVE_MOVW)
e511e253 2363 {
2364 *l = 2;
2365 return (AS2 (movw,%C0,%C1) CR_TAB
2366 AS2 (movw,%A0,%A1));
2367 }
2368 *l = 4;
2369 return (AS2 (mov,%D0,%D1) CR_TAB
2370 AS2 (mov,%C0,%C1) CR_TAB
2371 AS2 (mov,%B0,%B1) CR_TAB
2372 AS2 (mov,%A0,%A1));
2373 }
0af74aa0 2374 else
e511e253 2375 {
0aab73c2 2376 if (AVR_HAVE_MOVW)
e511e253 2377 {
2378 *l = 2;
2379 return (AS2 (movw,%A0,%A1) CR_TAB
2380 AS2 (movw,%C0,%C1));
2381 }
2382 *l = 4;
2383 return (AS2 (mov,%A0,%A1) CR_TAB
2384 AS2 (mov,%B0,%B1) CR_TAB
2385 AS2 (mov,%C0,%C1) CR_TAB
2386 AS2 (mov,%D0,%D1));
2387 }
0af74aa0 2388 }
e511e253 2389 else if (CONSTANT_P (src))
0af74aa0 2390 {
e511e253 2391 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2392 {
2393 *l = 4;
2394 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
2395 AS2 (ldi,%B0,hi8(%1)) CR_TAB
2396 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2397 AS2 (ldi,%D0,hhi8(%1)));
2398 }
2399
2400 if (GET_CODE (src) == CONST_INT)
2401 {
0d95286f 2402 const char *const clr_op0 =
0aab73c2 2403 AVR_HAVE_MOVW ? (AS1 (clr,%A0) CR_TAB
b681d971 2404 AS1 (clr,%B0) CR_TAB
2405 AS2 (movw,%C0,%A0))
2406 : (AS1 (clr,%A0) CR_TAB
2407 AS1 (clr,%B0) CR_TAB
2408 AS1 (clr,%C0) CR_TAB
2409 AS1 (clr,%D0));
2410
e511e253 2411 if (src == const0_rtx) /* mov r,L */
2412 {
0aab73c2 2413 *l = AVR_HAVE_MOVW ? 3 : 4;
b681d971 2414 return clr_op0;
e511e253 2415 }
2416 else if (src == const1_rtx)
2417 {
b681d971 2418 if (!real_l)
2419 output_asm_insn (clr_op0, operands);
0aab73c2 2420 *l = AVR_HAVE_MOVW ? 4 : 5;
b681d971 2421 return AS1 (inc,%A0);
e511e253 2422 }
2423 else if (src == constm1_rtx)
2424 {
2425 /* Immediate constants -1 to any register */
0aab73c2 2426 if (AVR_HAVE_MOVW)
e511e253 2427 {
2428 *l = 4;
2429 return (AS1 (clr,%A0) CR_TAB
2430 AS1 (dec,%A0) CR_TAB
2431 AS2 (mov,%B0,%A0) CR_TAB
2432 AS2 (movw,%C0,%A0));
2433 }
2434 *l = 5;
2435 return (AS1 (clr,%A0) CR_TAB
2436 AS1 (dec,%A0) CR_TAB
2437 AS2 (mov,%B0,%A0) CR_TAB
2438 AS2 (mov,%C0,%A0) CR_TAB
2439 AS2 (mov,%D0,%A0));
2440 }
b681d971 2441 else
2442 {
2443 int bit_nr = exact_log2 (INTVAL (src));
2444
2445 if (bit_nr >= 0)
2446 {
0aab73c2 2447 *l = AVR_HAVE_MOVW ? 5 : 6;
8e999997 2448 if (!real_l)
b681d971 2449 {
8e999997 2450 output_asm_insn (clr_op0, operands);
2451 output_asm_insn ("set", operands);
b681d971 2452 }
2453 if (!real_l)
2454 avr_output_bld (operands, bit_nr);
2455
2456 return "";
2457 }
2458 }
e511e253 2459 }
2460
2461 /* Last resort, better than loading from memory. */
2462 *l = 10;
2463 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2464 AS2 (ldi,r31,lo8(%1)) CR_TAB
2465 AS2 (mov,%A0,r31) CR_TAB
2466 AS2 (ldi,r31,hi8(%1)) CR_TAB
2467 AS2 (mov,%B0,r31) CR_TAB
2468 AS2 (ldi,r31,hlo8(%1)) CR_TAB
2469 AS2 (mov,%C0,r31) CR_TAB
2470 AS2 (ldi,r31,hhi8(%1)) CR_TAB
2471 AS2 (mov,%D0,r31) CR_TAB
2472 AS2 (mov,r31,__tmp_reg__));
2473 }
2474 else if (GET_CODE (src) == MEM)
2475 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2476 }
2477 else if (GET_CODE (dest) == MEM)
2478 {
37ac04dc 2479 const char *template;
2480
2481 if (src == const0_rtx)
e511e253 2482 operands[1] = zero_reg_rtx;
37ac04dc 2483
e511e253 2484 template = out_movsi_mr_r (insn, operands, real_l);
2485
2486 if (!real_l)
2487 output_asm_insn (template, operands);
37ac04dc 2488
2489 operands[1] = src;
e511e253 2490 return "";
a28e4651 2491 }
68435912 2492 fatal_insn ("invalid insn:", insn);
a28e4651 2493 return "";
2494}
2495
37ac04dc 2496const char *
206a5129 2497out_movqi_mr_r (rtx insn, rtx op[], int *l)
a28e4651 2498{
37ac04dc 2499 rtx dest = op[0];
2500 rtx src = op[1];
2501 rtx x = XEXP (dest, 0);
e511e253 2502 int dummy;
a28e4651 2503
e511e253 2504 if (!l)
2505 l = &dummy;
e511e253 2506
2507 if (CONSTANT_ADDRESS_P (x))
a28e4651 2508 {
df3d6232 2509 if (CONST_INT_P (x) && INTVAL (x) == SREG_ADDR)
2510 {
2511 *l = 1;
2512 return AS2 (out,__SREG__,%1);
2513 }
57463428 2514 if (avr_io_address_p (x, 1))
e511e253 2515 {
2516 *l = 1;
2517 return AS2 (out,%0-0x20,%1);
2518 }
2519 *l = 2;
2520 return AS2 (sts,%0,%1);
2521 }
2522 /* memory access by reg+disp */
2523 else if (GET_CODE (x) == PLUS
2524 && REG_P (XEXP (x,0))
2525 && GET_CODE (XEXP (x,1)) == CONST_INT)
2526 {
37ac04dc 2527 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
a28e4651 2528 {
e511e253 2529 int disp = INTVAL (XEXP (x,1));
2530 if (REGNO (XEXP (x,0)) != REG_Y)
68435912 2531 fatal_insn ("incorrect insn:",insn);
db45d3ed 2532
37ac04dc 2533 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
db45d3ed 2534 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2535 AS2 (std,Y+63,%1) CR_TAB
2536 AS2 (sbiw,r28,%o0-63));
2537
2538 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2539 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2540 AS2 (st,Y,%1) CR_TAB
2541 AS2 (subi,r28,lo8(%o0)) CR_TAB
2542 AS2 (sbci,r29,hi8(%o0)));
e511e253 2543 }
2544 else if (REGNO (XEXP (x,0)) == REG_X)
2545 {
37ac04dc 2546 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
e511e253 2547 {
2548 if (reg_unused_after (insn, XEXP (x,0)))
db45d3ed 2549 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2550 AS2 (adiw,r26,%o0) CR_TAB
2551 AS2 (st,X,__tmp_reg__));
2552
2553 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2554 AS2 (adiw,r26,%o0) CR_TAB
2555 AS2 (st,X,__tmp_reg__) CR_TAB
2556 AS2 (sbiw,r26,%o0));
a28e4651 2557 }
e511e253 2558 else
a28e4651 2559 {
e511e253 2560 if (reg_unused_after (insn, XEXP (x,0)))
db45d3ed 2561 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2562 AS2 (st,X,%1));
2563
2564 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2565 AS2 (st,X,%1) CR_TAB
2566 AS2 (sbiw,r26,%o0));
a28e4651 2567 }
2568 }
e511e253 2569 *l = 1;
2570 return AS2 (std,%0,%1);
a28e4651 2571 }
e511e253 2572 *l = 1;
2573 return AS2 (st,%0,%1);
a28e4651 2574}
2575
37ac04dc 2576const char *
206a5129 2577out_movhi_mr_r (rtx insn, rtx op[], int *l)
a28e4651 2578{
37ac04dc 2579 rtx dest = op[0];
2580 rtx src = op[1];
2581 rtx base = XEXP (dest, 0);
2582 int reg_base = true_regnum (base);
2583 int reg_src = true_regnum (src);
f43bae99 2584 /* "volatile" forces writing high byte first, even if less efficient,
2585 for correct operation with 16-bit I/O registers. */
2586 int mem_volatile_p = MEM_VOLATILE_P (dest);
a28e4651 2587 int tmp;
f43bae99 2588
a28e4651 2589 if (!l)
2590 l = &tmp;
37ac04dc 2591 if (CONSTANT_ADDRESS_P (base))
2592 {
57463428 2593 if (avr_io_address_p (base, 2))
37ac04dc 2594 {
2595 *l = 2;
2596 return (AS2 (out,%B0-0x20,%B1) CR_TAB
2597 AS2 (out,%A0-0x20,%A1));
2598 }
2599 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2600 AS2 (sts,%A0,%A1));
2601 }
a28e4651 2602 if (reg_base > 0)
2603 {
2604 if (reg_base == REG_X)
2605 {
37ac04dc 2606 if (reg_src == REG_X)
a28e4651 2607 {
f43bae99 2608 /* "st X+,r26" and "st -X,r26" are undefined. */
2609 if (!mem_volatile_p && reg_unused_after (insn, src))
66ad0834 2610 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2611 AS2 (st,X,r26) CR_TAB
2612 AS2 (adiw,r26,1) CR_TAB
2613 AS2 (st,X,__tmp_reg__));
a28e4651 2614 else
66ad0834 2615 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
66ad0834 2616 AS2 (adiw,r26,1) CR_TAB
2617 AS2 (st,X,__tmp_reg__) CR_TAB
f43bae99 2618 AS2 (sbiw,r26,1) CR_TAB
2619 AS2 (st,X,r26));
a28e4651 2620 }
2621 else
2622 {
f43bae99 2623 if (!mem_volatile_p && reg_unused_after (insn, base))
a28e4651 2624 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2625 AS2 (st,X,%B1));
2626 else
f43bae99 2627 return *l=3, (AS2 (adiw,r26,1) CR_TAB
2628 AS2 (st,X,%B1) CR_TAB
2629 AS2 (st,-X,%A1));
a28e4651 2630 }
2631 }
2632 else
f43bae99 2633 return *l=2, (AS2 (std,%0+1,%B1) CR_TAB
2634 AS2 (st,%0,%A1));
a28e4651 2635 }
37ac04dc 2636 else if (GET_CODE (base) == PLUS)
a28e4651 2637 {
37ac04dc 2638 int disp = INTVAL (XEXP (base, 1));
66ad0834 2639 reg_base = REGNO (XEXP (base, 0));
37ac04dc 2640 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
a28e4651 2641 {
66ad0834 2642 if (reg_base != REG_Y)
68435912 2643 fatal_insn ("incorrect insn:",insn);
db45d3ed 2644
37ac04dc 2645 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
db45d3ed 2646 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
db45d3ed 2647 AS2 (std,Y+63,%B1) CR_TAB
f43bae99 2648 AS2 (std,Y+62,%A1) CR_TAB
db45d3ed 2649 AS2 (sbiw,r28,%o0-62));
2650
2651 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2652 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
db45d3ed 2653 AS2 (std,Y+1,%B1) CR_TAB
f43bae99 2654 AS2 (st,Y,%A1) CR_TAB
db45d3ed 2655 AS2 (subi,r28,lo8(%o0)) CR_TAB
2656 AS2 (sbci,r29,hi8(%o0)));
a28e4651 2657 }
66ad0834 2658 if (reg_base == REG_X)
2659 {
2660 /* (X + d) = R */
2661 if (reg_src == REG_X)
f43bae99 2662 {
66ad0834 2663 *l = 7;
2664 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2665 AS2 (mov,__zero_reg__,r27) CR_TAB
f43bae99 2666 AS2 (adiw,r26,%o0+1) CR_TAB
66ad0834 2667 AS2 (st,X,__zero_reg__) CR_TAB
f43bae99 2668 AS2 (st,-X,__tmp_reg__) CR_TAB
66ad0834 2669 AS1 (clr,__zero_reg__) CR_TAB
f43bae99 2670 AS2 (sbiw,r26,%o0));
66ad0834 2671 }
2672 *l = 4;
f43bae99 2673 return (AS2 (adiw,r26,%o0+1) CR_TAB
2674 AS2 (st,X,%B1) CR_TAB
2675 AS2 (st,-X,%A1) CR_TAB
2676 AS2 (sbiw,r26,%o0));
66ad0834 2677 }
f43bae99 2678 return *l=2, (AS2 (std,%B0,%B1) CR_TAB
2679 AS2 (std,%A0,%A1));
e511e253 2680 }
37ac04dc 2681 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
a28e4651 2682 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2683 AS2 (st,%0,%A1));
37ac04dc 2684 else if (GET_CODE (base) == POST_INC) /* (R++) */
f43bae99 2685 {
2686 if (mem_volatile_p)
2687 {
2688 if (REGNO (XEXP (base, 0)) == REG_X)
2689 {
2690 *l = 4;
2691 return (AS2 (adiw,r26,1) CR_TAB
2692 AS2 (st,X,%B1) CR_TAB
2693 AS2 (st,-X,%A1) CR_TAB
2694 AS2 (adiw,r26,2));
2695 }
2696 else
2697 {
2698 *l = 3;
2699 return (AS2 (std,%p0+1,%B1) CR_TAB
2700 AS2 (st,%p0,%A1) CR_TAB
2701 AS2 (adiw,%r0,2));
2702 }
2703 }
2704
2705 *l = 2;
2706 return (AS2 (st,%0,%A1) CR_TAB
2707 AS2 (st,%0,%B1));
2708 }
68435912 2709 fatal_insn ("unknown move insn:",insn);
a28e4651 2710 return "";
2711}
2712
20c71901 2713/* Return 1 if frame pointer for current function required. */
a28e4651 2714
2715int
206a5129 2716frame_pointer_required_p (void)
a28e4651 2717{
2718 return (current_function_calls_alloca
2719 || current_function_args_info.nregs == 0
a28e4651 2720 || get_frame_size () > 0);
2721}
2722
faf8f400 2723/* Returns the condition of compare insn INSN, or UNKNOWN. */
a28e4651 2724
faf8f400 2725static RTX_CODE
206a5129 2726compare_condition (rtx insn)
a28e4651 2727{
2728 rtx next = next_real_insn (insn);
2729 RTX_CODE cond = UNKNOWN;
faf8f400 2730 if (next && GET_CODE (next) == JUMP_INSN)
a28e4651 2731 {
2732 rtx pat = PATTERN (next);
2733 rtx src = SET_SRC (pat);
faf8f400 2734 rtx t = XEXP (src, 0);
a28e4651 2735 cond = GET_CODE (t);
2736 }
faf8f400 2737 return cond;
2738}
2739
2740/* Returns nonzero if INSN is a tst insn that only tests the sign. */
2741
2742static int
206a5129 2743compare_sign_p (rtx insn)
faf8f400 2744{
2745 RTX_CODE cond = compare_condition (insn);
2746 return (cond == GE || cond == LT);
2747}
2748
2749/* Returns nonzero if the next insn is a JUMP_INSN with a condition
2750 that needs to be swapped (GT, GTU, LE, LEU). */
2751
2752int
206a5129 2753compare_diff_p (rtx insn)
faf8f400 2754{
2755 RTX_CODE cond = compare_condition (insn);
a28e4651 2756 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2757}
2758
faf8f400 2759/* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
a28e4651 2760
2761int
206a5129 2762compare_eq_p (rtx insn)
a28e4651 2763{
faf8f400 2764 RTX_CODE cond = compare_condition (insn);
a28e4651 2765 return (cond == EQ || cond == NE);
2766}
2767
2768
20c71901 2769/* Output test instruction for HImode. */
a28e4651 2770
37ac04dc 2771const char *
206a5129 2772out_tsthi (rtx insn, int *l)
a28e4651 2773{
faf8f400 2774 if (compare_sign_p (insn))
a28e4651 2775 {
2776 if (l) *l = 1;
2777 return AS1 (tst,%B0);
2778 }
faf8f400 2779 if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
2780 && compare_eq_p (insn))
a28e4651 2781 {
20c71901 2782 /* Faster than sbiw if we can clobber the operand. */
a28e4651 2783 if (l) *l = 1;
37ac04dc 2784 return AS2 (or,%A0,%B0);
a28e4651 2785 }
37ac04dc 2786 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
a28e4651 2787 {
2788 if (l) *l = 1;
37ac04dc 2789 return AS2 (sbiw,%0,0);
a28e4651 2790 }
2791 if (l) *l = 2;
2792 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2793 AS2 (cpc,%B0,__zero_reg__));
2794}
2795
2796
20c71901 2797/* Output test instruction for SImode. */
a28e4651 2798
37ac04dc 2799const char *
206a5129 2800out_tstsi (rtx insn, int *l)
a28e4651 2801{
faf8f400 2802 if (compare_sign_p (insn))
a28e4651 2803 {
2804 if (l) *l = 1;
2805 return AS1 (tst,%D0);
2806 }
0af74aa0 2807 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
a28e4651 2808 {
2809 if (l) *l = 3;
2810 return (AS2 (sbiw,%A0,0) CR_TAB
2811 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2812 AS2 (cpc,%D0,__zero_reg__));
2813 }
2814 if (l) *l = 4;
2815 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2816 AS2 (cpc,%B0,__zero_reg__) CR_TAB
2817 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2818 AS2 (cpc,%D0,__zero_reg__));
2819}
2820
2821
b681d971 2822/* Generate asm equivalent for various shifts.
2823 Shift count is a CONST_INT, MEM or REG.
2824 This only handles cases that are not already
2825 carefully hand-optimized in ?sh??i3_out. */
a28e4651 2826
2827void
206a5129 2828out_shift_with_cnt (const char *template, rtx insn, rtx operands[],
2829 int *len, int t_len)
a28e4651 2830{
2831 rtx op[10];
b681d971 2832 char str[500];
361aa610 2833 int second_label = 1;
b681d971 2834 int saved_in_tmp = 0;
2835 int use_zero_reg = 0;
2836
a28e4651 2837 op[0] = operands[0];
2838 op[1] = operands[1];
2839 op[2] = operands[2];
2840 op[3] = operands[3];
2841 str[0] = 0;
b681d971 2842
2843 if (len)
2844 *len = 1;
2845
2846 if (GET_CODE (operands[2]) == CONST_INT)
a28e4651 2847 {
b681d971 2848 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2849 int count = INTVAL (operands[2]);
2850 int max_len = 10; /* If larger than this, always use a loop. */
2851
5667001b 2852 if (count <= 0)
2853 {
2854 if (len)
2855 *len = 0;
2856 return;
2857 }
2858
b681d971 2859 if (count < 8 && !scratch)
2860 use_zero_reg = 1;
2861
2862 if (optimize_size)
2863 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2864
2865 if (t_len * count <= max_len)
2866 {
2867 /* Output shifts inline with no loop - faster. */
2868 if (len)
2869 *len = t_len * count;
2870 else
2871 {
2872 while (count-- > 0)
2873 output_asm_insn (template, op);
2874 }
2875
2876 return;
2877 }
2878
2879 if (scratch)
2880 {
2881 if (!len)
2882 strcat (str, AS2 (ldi,%3,%2));
2883 }
2884 else if (use_zero_reg)
2885 {
2886 /* Hack to save one word: use __zero_reg__ as loop counter.
2887 Set one bit, then shift in a loop until it is 0 again. */
2888
2889 op[3] = zero_reg_rtx;
2890 if (len)
2891 *len = 2;
2892 else
2893 strcat (str, ("set" CR_TAB
2894 AS2 (bld,%3,%2-1)));
2895 }
a28e4651 2896 else
b681d971 2897 {
2898 /* No scratch register available, use one from LD_REGS (saved in
2899 __tmp_reg__) that doesn't overlap with registers to shift. */
2900
1a83b3ff 2901 op[3] = gen_rtx_REG (QImode,
b681d971 2902 ((true_regnum (operands[0]) - 1) & 15) + 16);
2903 op[4] = tmp_reg_rtx;
2904 saved_in_tmp = 1;
2905
2906 if (len)
2907 *len = 3; /* Includes "mov %3,%4" after the loop. */
2908 else
2909 strcat (str, (AS2 (mov,%4,%3) CR_TAB
2910 AS2 (ldi,%3,%2)));
2911 }
2912
361aa610 2913 second_label = 0;
a28e4651 2914 }
2915 else if (GET_CODE (operands[2]) == MEM)
2916 {
a28e4651 2917 rtx op_mov[10];
361aa610 2918
a28e4651 2919 op[3] = op_mov[0] = tmp_reg_rtx;
2920 op_mov[1] = op[2];
b681d971 2921
2922 if (len)
2923 out_movqi_r_mr (insn, op_mov, len);
a28e4651 2924 else
b681d971 2925 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
a28e4651 2926 }
0af74aa0 2927 else if (register_operand (operands[2], QImode))
a28e4651 2928 {
a28e4651 2929 if (reg_unused_after (insn, operands[2]))
361aa610 2930 op[3] = op[2];
a28e4651 2931 else
2932 {
2933 op[3] = tmp_reg_rtx;
b681d971 2934 if (!len)
2935 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
a28e4651 2936 }
b681d971 2937 }
2938 else
68435912 2939 fatal_insn ("bad shift insn:", insn);
b681d971 2940
2941 if (second_label)
2942 {
361aa610 2943 if (len)
2944 ++*len;
2945 else
2946 strcat (str, AS1 (rjmp,2f));
a28e4651 2947 }
b681d971 2948
2949 if (len)
2950 *len += t_len + 2; /* template + dec + brXX */
2951 else
a28e4651 2952 {
41c1bf43 2953 strcat (str, "\n1:\t");
a28e4651 2954 strcat (str, template);
361aa610 2955 strcat (str, second_label ? "\n2:\t" : "\n\t");
b681d971 2956 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
2957 strcat (str, CR_TAB);
2958 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
2959 if (saved_in_tmp)
2960 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
a28e4651 2961 output_asm_insn (str, op);
2962 }
2963}
2964
2965
2966/* 8bit shift left ((char)x << i) */
2967
37ac04dc 2968const char *
206a5129 2969ashlqi3_out (rtx insn, rtx operands[], int *len)
a28e4651 2970{
2971 if (GET_CODE (operands[2]) == CONST_INT)
2972 {
2973 int k;
1cb39658 2974
a28e4651 2975 if (!len)
2976 len = &k;
1cb39658 2977
a28e4651 2978 switch (INTVAL (operands[2]))
2979 {
1cb39658 2980 default:
5667001b 2981 if (INTVAL (operands[2]) < 8)
2982 break;
2983
1cb39658 2984 *len = 1;
2985 return AS1 (clr,%0);
2986
a28e4651 2987 case 1:
1cb39658 2988 *len = 1;
a28e4651 2989 return AS1 (lsl,%0);
1cb39658 2990
a28e4651 2991 case 2:
1cb39658 2992 *len = 2;
a28e4651 2993 return (AS1 (lsl,%0) CR_TAB
2994 AS1 (lsl,%0));
1cb39658 2995
a28e4651 2996 case 3:
1cb39658 2997 *len = 3;
a28e4651 2998 return (AS1 (lsl,%0) CR_TAB
2999 AS1 (lsl,%0) CR_TAB
3000 AS1 (lsl,%0));
1cb39658 3001
a28e4651 3002 case 4:
0af74aa0 3003 if (test_hard_reg_class (LD_REGS, operands[0]))
a28e4651 3004 {
1cb39658 3005 *len = 2;
a28e4651 3006 return (AS1 (swap,%0) CR_TAB
3007 AS2 (andi,%0,0xf0));
3008 }
1cb39658 3009 *len = 4;
a28e4651 3010 return (AS1 (lsl,%0) CR_TAB
3011 AS1 (lsl,%0) CR_TAB
3012 AS1 (lsl,%0) CR_TAB
3013 AS1 (lsl,%0));
1cb39658 3014
a28e4651 3015 case 5:
0af74aa0 3016 if (test_hard_reg_class (LD_REGS, operands[0]))
a28e4651 3017 {
1cb39658 3018 *len = 3;
a28e4651 3019 return (AS1 (swap,%0) CR_TAB
3020 AS1 (lsl,%0) CR_TAB
3021 AS2 (andi,%0,0xe0));
3022 }
1cb39658 3023 *len = 5;
a28e4651 3024 return (AS1 (lsl,%0) CR_TAB
3025 AS1 (lsl,%0) CR_TAB
3026 AS1 (lsl,%0) CR_TAB
3027 AS1 (lsl,%0) CR_TAB
3028 AS1 (lsl,%0));
1cb39658 3029
a28e4651 3030 case 6:
0af74aa0 3031 if (test_hard_reg_class (LD_REGS, operands[0]))
a28e4651 3032 {
1cb39658 3033 *len = 4;
a28e4651 3034 return (AS1 (swap,%0) CR_TAB
3035 AS1 (lsl,%0) CR_TAB
3036 AS1 (lsl,%0) CR_TAB
3037 AS2 (andi,%0,0xc0));
3038 }
1cb39658 3039 *len = 6;
a28e4651 3040 return (AS1 (lsl,%0) CR_TAB
3041 AS1 (lsl,%0) CR_TAB
3042 AS1 (lsl,%0) CR_TAB
3043 AS1 (lsl,%0) CR_TAB
3044 AS1 (lsl,%0) CR_TAB
3045 AS1 (lsl,%0));
1cb39658 3046
a28e4651 3047 case 7:
1cb39658 3048 *len = 3;
a28e4651 3049 return (AS1 (ror,%0) CR_TAB
3050 AS1 (clr,%0) CR_TAB
3051 AS1 (ror,%0));
3052 }
3053 }
1cb39658 3054 else if (CONSTANT_P (operands[2]))
68435912 3055 fatal_insn ("internal compiler error. Incorrect shift:", insn);
1cb39658 3056
361aa610 3057 out_shift_with_cnt (AS1 (lsl,%0),
b681d971 3058 insn, operands, len, 1);
a28e4651 3059 return "";
3060}
3061
3062
3063/* 16bit shift left ((short)x << i) */
3064
37ac04dc 3065const char *
206a5129 3066ashlhi3_out (rtx insn, rtx operands[], int *len)
a28e4651 3067{
3068 if (GET_CODE (operands[2]) == CONST_INT)
3069 {
b681d971 3070 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3071 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
a28e4651 3072 int k;
b681d971 3073 int *t = len;
1cb39658 3074
a28e4651 3075 if (!len)
3076 len = &k;
1cb39658 3077
a28e4651 3078 switch (INTVAL (operands[2]))
3079 {
5667001b 3080 default:
3081 if (INTVAL (operands[2]) < 16)
3082 break;
3083
3084 *len = 2;
3085 return (AS1 (clr,%B0) CR_TAB
3086 AS1 (clr,%A0));
3087
b681d971 3088 case 4:
3089 if (optimize_size && scratch)
3090 break; /* 5 */
3091 if (ldi_ok)
3092 {
3093 *len = 6;
3094 return (AS1 (swap,%A0) CR_TAB
3095 AS1 (swap,%B0) CR_TAB
3096 AS2 (andi,%B0,0xf0) CR_TAB
3097 AS2 (eor,%B0,%A0) CR_TAB
3098 AS2 (andi,%A0,0xf0) CR_TAB
3099 AS2 (eor,%B0,%A0));
3100 }
3101 if (scratch)
3102 {
3103 *len = 7;
3104 return (AS1 (swap,%A0) CR_TAB
3105 AS1 (swap,%B0) CR_TAB
3106 AS2 (ldi,%3,0xf0) CR_TAB
3107 AS2 (and,%B0,%3) CR_TAB
3108 AS2 (eor,%B0,%A0) CR_TAB
3109 AS2 (and,%A0,%3) CR_TAB
3110 AS2 (eor,%B0,%A0));
3111 }
3112 break; /* optimize_size ? 6 : 8 */
1cb39658 3113
b681d971 3114 case 5:
3115 if (optimize_size)
3116 break; /* scratch ? 5 : 6 */
3117 if (ldi_ok)
3118 {
3119 *len = 8;
3120 return (AS1 (lsl,%A0) CR_TAB
3121 AS1 (rol,%B0) CR_TAB
3122 AS1 (swap,%A0) CR_TAB
3123 AS1 (swap,%B0) CR_TAB
3124 AS2 (andi,%B0,0xf0) CR_TAB
3125 AS2 (eor,%B0,%A0) CR_TAB
3126 AS2 (andi,%A0,0xf0) CR_TAB
3127 AS2 (eor,%B0,%A0));
3128 }
3129 if (scratch)
3130 {
3131 *len = 9;
3132 return (AS1 (lsl,%A0) CR_TAB
3133 AS1 (rol,%B0) CR_TAB
3134 AS1 (swap,%A0) CR_TAB
3135 AS1 (swap,%B0) CR_TAB
3136 AS2 (ldi,%3,0xf0) CR_TAB
3137 AS2 (and,%B0,%3) CR_TAB
3138 AS2 (eor,%B0,%A0) CR_TAB
3139 AS2 (and,%A0,%3) CR_TAB
3140 AS2 (eor,%B0,%A0));
3141 }
3142 break; /* 10 */
3143
3144 case 6:
3145 if (optimize_size)
3146 break; /* scratch ? 5 : 6 */
3147 *len = 9;
3148 return (AS1 (clr,__tmp_reg__) CR_TAB
3149 AS1 (lsr,%B0) CR_TAB
3150 AS1 (ror,%A0) CR_TAB
3151 AS1 (ror,__tmp_reg__) CR_TAB
3152 AS1 (lsr,%B0) CR_TAB
3153 AS1 (ror,%A0) CR_TAB
3154 AS1 (ror,__tmp_reg__) CR_TAB
3155 AS2 (mov,%B0,%A0) CR_TAB
3156 AS2 (mov,%A0,__tmp_reg__));
1cb39658 3157
28f5cc4d 3158 case 7:
3159 *len = 5;
3160 return (AS1 (lsr,%B0) CR_TAB
3161 AS2 (mov,%B0,%A0) CR_TAB
3162 AS1 (clr,%A0) CR_TAB
3163 AS1 (ror,%B0) CR_TAB
3164 AS1 (ror,%A0));
3165
a28e4651 3166 case 8:
ab3a6ef8 3167 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3168 AS1 (clr,%A0));
28f5cc4d 3169
3170 case 9:
3171 *len = 3;
3172 return (AS2 (mov,%B0,%A0) CR_TAB
3173 AS1 (clr,%A0) CR_TAB
3174 AS1 (lsl,%B0));
3175
3176 case 10:
3177 *len = 4;
3178 return (AS2 (mov,%B0,%A0) CR_TAB
3179 AS1 (clr,%A0) CR_TAB
3180 AS1 (lsl,%B0) CR_TAB
3181 AS1 (lsl,%B0));
3182
3183 case 11:
3184 *len = 5;
3185 return (AS2 (mov,%B0,%A0) CR_TAB
3186 AS1 (clr,%A0) CR_TAB
3187 AS1 (lsl,%B0) CR_TAB
3188 AS1 (lsl,%B0) CR_TAB
3189 AS1 (lsl,%B0));
3190
3191 case 12:
b681d971 3192 if (ldi_ok)
28f5cc4d 3193 {
3194 *len = 4;
3195 return (AS2 (mov,%B0,%A0) CR_TAB
3196 AS1 (clr,%A0) CR_TAB
3197 AS1 (swap,%B0) CR_TAB
3198 AS2 (andi,%B0,0xf0));
3199 }
b681d971 3200 if (scratch)
3201 {
3202 *len = 5;
3203 return (AS2 (mov,%B0,%A0) CR_TAB
3204 AS1 (clr,%A0) CR_TAB
3205 AS1 (swap,%B0) CR_TAB
3206 AS2 (ldi,%3,0xf0) CR_TAB
3207 AS2 (and,%B0,%3));
3208 }
3209 *len = 6;
28f5cc4d 3210 return (AS2 (mov,%B0,%A0) CR_TAB
3211 AS1 (clr,%A0) CR_TAB
b681d971 3212 AS1 (lsl,%B0) CR_TAB
3213 AS1 (lsl,%B0) CR_TAB
3214 AS1 (lsl,%B0) CR_TAB
3215 AS1 (lsl,%B0));
28f5cc4d 3216
3217 case 13:
b681d971 3218 if (ldi_ok)
28f5cc4d 3219 {
3220 *len = 5;
3221 return (AS2 (mov,%B0,%A0) CR_TAB
3222 AS1 (clr,%A0) CR_TAB
3223 AS1 (swap,%B0) CR_TAB
3224 AS1 (lsl,%B0) CR_TAB
3225 AS2 (andi,%B0,0xe0));
3226 }
8cc5a1af 3227 if (AVR_HAVE_MUL && scratch)
28f5cc4d 3228 {
3229 *len = 5;
3230 return (AS2 (ldi,%3,0x20) CR_TAB
3231 AS2 (mul,%A0,%3) CR_TAB
3232 AS2 (mov,%B0,r0) CR_TAB
3233 AS1 (clr,%A0) CR_TAB
3234 AS1 (clr,__zero_reg__));
3235 }
b681d971 3236 if (optimize_size && scratch)
3237 break; /* 5 */
3238 if (scratch)
3239 {
3240 *len = 6;
3241 return (AS2 (mov,%B0,%A0) CR_TAB
3242 AS1 (clr,%A0) CR_TAB
3243 AS1 (swap,%B0) CR_TAB
3244 AS1 (lsl,%B0) CR_TAB
3245 AS2 (ldi,%3,0xe0) CR_TAB
3246 AS2 (and,%B0,%3));
3247 }
8cc5a1af 3248 if (AVR_HAVE_MUL)
b681d971 3249 {
3250 *len = 6;
3251 return ("set" CR_TAB
3252 AS2 (bld,r1,5) CR_TAB
3253 AS2 (mul,%A0,r1) CR_TAB
3254 AS2 (mov,%B0,r0) CR_TAB
3255 AS1 (clr,%A0) CR_TAB
3256 AS1 (clr,__zero_reg__));
3257 }
3258 *len = 7;
3259 return (AS2 (mov,%B0,%A0) CR_TAB
3260 AS1 (clr,%A0) CR_TAB
3261 AS1 (lsl,%B0) CR_TAB
3262 AS1 (lsl,%B0) CR_TAB
3263 AS1 (lsl,%B0) CR_TAB
3264 AS1 (lsl,%B0) CR_TAB
3265 AS1 (lsl,%B0));
28f5cc4d 3266
3267 case 14:
8cc5a1af 3268 if (AVR_HAVE_MUL && ldi_ok)
b681d971 3269 {
3270 *len = 5;
3271 return (AS2 (ldi,%B0,0x40) CR_TAB
3272 AS2 (mul,%A0,%B0) CR_TAB
3273 AS2 (mov,%B0,r0) CR_TAB
3274 AS1 (clr,%A0) CR_TAB
3275 AS1 (clr,__zero_reg__));
3276 }
8cc5a1af 3277 if (AVR_HAVE_MUL && scratch)
28f5cc4d 3278 {
3279 *len = 5;
3280 return (AS2 (ldi,%3,0x40) CR_TAB
3281 AS2 (mul,%A0,%3) CR_TAB
3282 AS2 (mov,%B0,r0) CR_TAB
3283 AS1 (clr,%A0) CR_TAB
3284 AS1 (clr,__zero_reg__));
3285 }
b681d971 3286 if (optimize_size && ldi_ok)
3287 {
3288 *len = 5;
3289 return (AS2 (mov,%B0,%A0) CR_TAB
3290 AS2 (ldi,%A0,6) "\n1:\t"
3291 AS1 (lsl,%B0) CR_TAB
3292 AS1 (dec,%A0) CR_TAB
3293 AS1 (brne,1b));
3294 }
3295 if (optimize_size && scratch)
3296 break; /* 5 */
3297 *len = 6;
3298 return (AS1 (clr,%B0) CR_TAB
3299 AS1 (lsr,%A0) CR_TAB
3300 AS1 (ror,%B0) CR_TAB
3301 AS1 (lsr,%A0) CR_TAB
3302 AS1 (ror,%B0) CR_TAB
3303 AS1 (clr,%A0));
28f5cc4d 3304
3305 case 15:
3306 *len = 4;
3307 return (AS1 (clr,%B0) CR_TAB
3308 AS1 (lsr,%A0) CR_TAB
3309 AS1 (ror,%B0) CR_TAB
3310 AS1 (clr,%A0));
a28e4651 3311 }
28f5cc4d 3312 len = t;
a28e4651 3313 }
b681d971 3314 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3315 AS1 (rol,%B0)),
3316 insn, operands, len, 2);
a28e4651 3317 return "";
3318}
3319
3320
3321/* 32bit shift left ((long)x << i) */
3322
37ac04dc 3323const char *
206a5129 3324ashlsi3_out (rtx insn, rtx operands[], int *len)
a28e4651 3325{
3326 if (GET_CODE (operands[2]) == CONST_INT)
3327 {
3328 int k;
b681d971 3329 int *t = len;
1cb39658 3330
a28e4651 3331 if (!len)
3332 len = &k;
1cb39658 3333
a28e4651 3334 switch (INTVAL (operands[2]))
3335 {
5667001b 3336 default:
3337 if (INTVAL (operands[2]) < 32)
3338 break;
3339
0aab73c2 3340 if (AVR_HAVE_MOVW)
5667001b 3341 return *len = 3, (AS1 (clr,%D0) CR_TAB
3342 AS1 (clr,%C0) CR_TAB
3343 AS2 (movw,%A0,%C0));
3344 *len = 4;
3345 return (AS1 (clr,%D0) CR_TAB
3346 AS1 (clr,%C0) CR_TAB
3347 AS1 (clr,%B0) CR_TAB
3348 AS1 (clr,%A0));
3349
a28e4651 3350 case 8:
3351 {
3352 int reg0 = true_regnum (operands[0]);
3353 int reg1 = true_regnum (operands[1]);
1cb39658 3354 *len = 4;
a28e4651 3355 if (reg0 >= reg1)
3356 return (AS2 (mov,%D0,%C1) CR_TAB
3357 AS2 (mov,%C0,%B1) CR_TAB
3358 AS2 (mov,%B0,%A1) CR_TAB
3359 AS1 (clr,%A0));
a28e4651 3360 else
3361 return (AS1 (clr,%A0) CR_TAB
3362 AS2 (mov,%B0,%A1) CR_TAB
3363 AS2 (mov,%C0,%B1) CR_TAB
3364 AS2 (mov,%D0,%C1));
3365 }
1cb39658 3366
a28e4651 3367 case 16:
3368 {
3369 int reg0 = true_regnum (operands[0]);
3370 int reg1 = true_regnum (operands[1]);
a28e4651 3371 if (reg0 + 2 == reg1)
ab3a6ef8 3372 return *len = 2, (AS1 (clr,%B0) CR_TAB
3373 AS1 (clr,%A0));
3374 if (AVR_HAVE_MOVW)
3375 return *len = 3, (AS2 (movw,%C0,%A1) CR_TAB
3376 AS1 (clr,%B0) CR_TAB
3377 AS1 (clr,%A0));
a28e4651 3378 else
ab3a6ef8 3379 return *len = 4, (AS2 (mov,%C0,%A1) CR_TAB
3380 AS2 (mov,%D0,%B1) CR_TAB
3381 AS1 (clr,%B0) CR_TAB
3382 AS1 (clr,%A0));
a28e4651 3383 }
1cb39658 3384
a28e4651 3385 case 24:
1cb39658 3386 *len = 4;
ab3a6ef8 3387 return (AS2 (mov,%D0,%A1) CR_TAB
3388 AS1 (clr,%C0) CR_TAB
3389 AS1 (clr,%B0) CR_TAB
3390 AS1 (clr,%A0));
28f5cc4d 3391
3392 case 31:
3393 *len = 6;
3394 return (AS1 (clr,%D0) CR_TAB
3395 AS1 (lsr,%A0) CR_TAB
3396 AS1 (ror,%D0) CR_TAB
3397 AS1 (clr,%C0) CR_TAB
3398 AS1 (clr,%B0) CR_TAB
3399 AS1 (clr,%A0));
a28e4651 3400 }
28f5cc4d 3401 len = t;
a28e4651 3402 }
b681d971 3403 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3404 AS1 (rol,%B0) CR_TAB
3405 AS1 (rol,%C0) CR_TAB
3406 AS1 (rol,%D0)),
3407 insn, operands, len, 4);
a28e4651 3408 return "";
3409}
3410
3411/* 8bit arithmetic shift right ((signed char)x >> i) */
3412
37ac04dc 3413const char *
206a5129 3414ashrqi3_out (rtx insn, rtx operands[], int *len)
a28e4651 3415{
3416 if (GET_CODE (operands[2]) == CONST_INT)
3417 {
a28e4651 3418 int k;
1cb39658 3419
a28e4651 3420 if (!len)
3421 len = &k;
1cb39658 3422
a28e4651 3423 switch (INTVAL (operands[2]))
3424 {
a28e4651 3425 case 1:
1cb39658 3426 *len = 1;
a28e4651 3427 return AS1 (asr,%0);
1cb39658 3428
a28e4651 3429 case 2:
1cb39658 3430 *len = 2;
a28e4651 3431 return (AS1 (asr,%0) CR_TAB
3432 AS1 (asr,%0));
1cb39658 3433
a28e4651 3434 case 3:
1cb39658 3435 *len = 3;
a28e4651 3436 return (AS1 (asr,%0) CR_TAB
3437 AS1 (asr,%0) CR_TAB
3438 AS1 (asr,%0));
1cb39658 3439
a28e4651 3440 case 4:
1cb39658 3441 *len = 4;
3442 return (AS1 (asr,%0) CR_TAB
3443 AS1 (asr,%0) CR_TAB
3444 AS1 (asr,%0) CR_TAB
3445 AS1 (asr,%0));
3446
3447 case 5:
3448 *len = 5;
a28e4651 3449 return (AS1 (asr,%0) CR_TAB
1cb39658 3450 AS1 (asr,%0) CR_TAB
a28e4651 3451 AS1 (asr,%0) CR_TAB
3452 AS1 (asr,%0) CR_TAB
3453 AS1 (asr,%0));
1cb39658 3454
3455 case 6:
3456 *len = 4;
3457 return (AS2 (bst,%0,6) CR_TAB
3458 AS1 (lsl,%0) CR_TAB
3459 AS2 (sbc,%0,%0) CR_TAB
3460 AS2 (bld,%0,0));
3461
3462 default:
5667001b 3463 if (INTVAL (operands[2]) < 8)
3464 break;
3465
3466 /* fall through */
3467
1cb39658 3468 case 7:
3469 *len = 2;
3470 return (AS1 (lsl,%0) CR_TAB
3471 AS2 (sbc,%0,%0));
a28e4651 3472 }
3473 }
1cb39658 3474 else if (CONSTANT_P (operands[2]))
68435912 3475 fatal_insn ("internal compiler error. Incorrect shift:", insn);
1cb39658 3476
361aa610 3477 out_shift_with_cnt (AS1 (asr,%0),
b681d971 3478 insn, operands, len, 1);
a28e4651 3479 return "";
3480}
3481
3482
3483/* 16bit arithmetic shift right ((signed short)x >> i) */
3484
37ac04dc 3485const char *
206a5129 3486ashrhi3_out (rtx insn, rtx operands[], int *len)
a28e4651 3487{
3488 if (GET_CODE (operands[2]) == CONST_INT)
3489 {
b681d971 3490 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3491 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
a28e4651 3492 int k;
1cb39658 3493 int *t = len;
3494
a28e4651 3495 if (!len)
3496 len = &k;
1cb39658 3497
a28e4651 3498 switch (INTVAL (operands[2]))
3499 {
b681d971 3500 case 4:
3501 case 5:
3502 /* XXX try to optimize this too? */
3503 break;
1cb39658 3504
b681d971 3505 case 6:
3506 if (optimize_size)
3507 break; /* scratch ? 5 : 6 */
3508 *len = 8;
3509 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3510 AS2 (mov,%A0,%B0) CR_TAB
3511 AS1 (lsl,__tmp_reg__) CR_TAB
3512 AS1 (rol,%A0) CR_TAB
3513 AS2 (sbc,%B0,%B0) CR_TAB
3514 AS1 (lsl,__tmp_reg__) CR_TAB
3515 AS1 (rol,%A0) CR_TAB
3516 AS1 (rol,%B0));
1cb39658 3517
28f5cc4d 3518 case 7:
3519 *len = 4;
3520 return (AS1 (lsl,%A0) CR_TAB
3521 AS2 (mov,%A0,%B0) CR_TAB
3522 AS1 (rol,%A0) CR_TAB
3523 AS2 (sbc,%B0,%B0));
3524
a28e4651 3525 case 8:
b681d971 3526 {
3527 int reg0 = true_regnum (operands[0]);
3528 int reg1 = true_regnum (operands[1]);
3529
3530 if (reg0 == reg1)
3531 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3532 AS1 (lsl,%B0) CR_TAB
3533 AS2 (sbc,%B0,%B0));
ab3a6ef8 3534 else
3535 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3536 AS1 (clr,%B0) CR_TAB
3537 AS2 (sbrc,%A0,7) CR_TAB
3538 AS1 (dec,%B0));
b681d971 3539 }
1cb39658 3540
28f5cc4d 3541 case 9:
3542 *len = 4;
3543 return (AS2 (mov,%A0,%B0) CR_TAB
3544 AS1 (lsl,%B0) CR_TAB
3545 AS2 (sbc,%B0,%B0) CR_TAB
3546 AS1 (asr,%A0));
3547
3548 case 10:
3549 *len = 5;
3550 return (AS2 (mov,%A0,%B0) CR_TAB
3551 AS1 (lsl,%B0) CR_TAB
3552 AS2 (sbc,%B0,%B0) CR_TAB
3553 AS1 (asr,%A0) CR_TAB
3554 AS1 (asr,%A0));
3555
3556 case 11:
8cc5a1af 3557 if (AVR_HAVE_MUL && ldi_ok)
28f5cc4d 3558 {
3559 *len = 5;
b681d971 3560 return (AS2 (ldi,%A0,0x20) CR_TAB
3561 AS2 (muls,%B0,%A0) CR_TAB
3562 AS2 (mov,%A0,r1) CR_TAB
3563 AS2 (sbc,%B0,%B0) CR_TAB
28f5cc4d 3564 AS1 (clr,__zero_reg__));
3565 }
b681d971 3566 if (optimize_size && scratch)
3567 break; /* 5 */
3568 *len = 6;
3569 return (AS2 (mov,%A0,%B0) CR_TAB
3570 AS1 (lsl,%B0) CR_TAB
3571 AS2 (sbc,%B0,%B0) CR_TAB
3572 AS1 (asr,%A0) CR_TAB
3573 AS1 (asr,%A0) CR_TAB
3574 AS1 (asr,%A0));
28f5cc4d 3575
3576 case 12:
8cc5a1af 3577 if (AVR_HAVE_MUL && ldi_ok)
28f5cc4d 3578 {
3579 *len = 5;
b681d971 3580 return (AS2 (ldi,%A0,0x10) CR_TAB
3581 AS2 (muls,%B0,%A0) CR_TAB
3582 AS2 (mov,%A0,r1) CR_TAB
3583 AS2 (sbc,%B0,%B0) CR_TAB
28f5cc4d 3584 AS1 (clr,__zero_reg__));
3585 }
b681d971 3586 if (optimize_size && scratch)
3587 break; /* 5 */
3588 *len = 7;
3589 return (AS2 (mov,%A0,%B0) CR_TAB
3590 AS1 (lsl,%B0) CR_TAB
3591 AS2 (sbc,%B0,%B0) CR_TAB
3592 AS1 (asr,%A0) CR_TAB
3593 AS1 (asr,%A0) CR_TAB
3594 AS1 (asr,%A0) CR_TAB
3595 AS1 (asr,%A0));
28f5cc4d 3596
3597 case 13:
8cc5a1af 3598 if (AVR_HAVE_MUL && ldi_ok)
28f5cc4d 3599 {
3600 *len = 5;
b681d971 3601 return (AS2 (ldi,%A0,0x08) CR_TAB
3602 AS2 (muls,%B0,%A0) CR_TAB
3603 AS2 (mov,%A0,r1) CR_TAB
3604 AS2 (sbc,%B0,%B0) CR_TAB
28f5cc4d 3605 AS1 (clr,__zero_reg__));
3606 }
b681d971 3607 if (optimize_size)
3608 break; /* scratch ? 5 : 7 */
3609 *len = 8;
3610 return (AS2 (mov,%A0,%B0) CR_TAB
3611 AS1 (lsl,%B0) CR_TAB
3612 AS2 (sbc,%B0,%B0) CR_TAB
3613 AS1 (asr,%A0) CR_TAB
3614 AS1 (asr,%A0) CR_TAB
3615 AS1 (asr,%A0) CR_TAB
3616 AS1 (asr,%A0) CR_TAB
3617 AS1 (asr,%A0));
28f5cc4d 3618
3619 case 14:
3620 *len = 5;
3621 return (AS1 (lsl,%B0) CR_TAB
3622 AS2 (sbc,%A0,%A0) CR_TAB
3623 AS1 (lsl,%B0) CR_TAB
3624 AS2 (mov,%B0,%A0) CR_TAB
3625 AS1 (rol,%A0));
3626
5667001b 3627 default:
3628 if (INTVAL (operands[2]) < 16)
3629 break;
3630
3631 /* fall through */
3632
8a2a7305 3633 case 15:
3634 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3635 AS2 (sbc,%A0,%A0) CR_TAB
3636 AS2 (mov,%B0,%A0));
a28e4651 3637 }
28f5cc4d 3638 len = t;
a28e4651 3639 }
b681d971 3640 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3641 AS1 (ror,%A0)),
3642 insn, operands, len, 2);
a28e4651 3643 return "";
3644}
3645
3646
3647/* 32bit arithmetic shift right ((signed long)x >> i) */
3648
37ac04dc 3649const char *
206a5129 3650ashrsi3_out (rtx insn, rtx operands[], int *len)
a28e4651 3651{
3652 if (GET_CODE (operands[2]) == CONST_INT)
3653 {
3654 int k;
3655 int *t = len;
1cb39658 3656
a28e4651 3657 if (!len)
3658 len = &k;
1cb39658 3659
a28e4651 3660 switch (INTVAL (operands[2]))
3661 {
a28e4651 3662 case 8:
3663 {
3664 int reg0 = true_regnum (operands[0]);
3665 int reg1 = true_regnum (operands[1]);
3666 *len=6;
3667 if (reg0 <= reg1)
3668 return (AS2 (mov,%A0,%B1) CR_TAB
3669 AS2 (mov,%B0,%C1) CR_TAB
3670 AS2 (mov,%C0,%D1) CR_TAB
3671 AS1 (clr,%D0) CR_TAB
3672 AS2 (sbrc,%C0,7) CR_TAB
3673 AS1 (dec,%D0));
a28e4651 3674 else
3675 return (AS1 (clr,%D0) CR_TAB
8a2a7305 3676 AS2 (sbrc,%D1,7) CR_TAB
a28e4651 3677 AS1 (dec,%D0) CR_TAB
3678 AS2 (mov,%C0,%D1) CR_TAB
3679 AS2 (mov,%B0,%C1) CR_TAB
3680 AS2 (mov,%A0,%B1));
3681 }
1cb39658 3682
a28e4651 3683 case 16:
3684 {
3685 int reg0 = true_regnum (operands[0]);
3686 int reg1 = true_regnum (operands[1]);
ab3a6ef8 3687
3688 if (reg0 == reg1 + 2)
a28e4651 3689 return *len = 4, (AS1 (clr,%D0) CR_TAB
3690 AS2 (sbrc,%B0,7) CR_TAB
3691 AS1 (com,%D0) CR_TAB
3692 AS2 (mov,%C0,%D0));
ab3a6ef8 3693 if (AVR_HAVE_MOVW)
3694 return *len = 5, (AS2 (movw,%A0,%C1) CR_TAB
3695 AS1 (clr,%D0) CR_TAB
3696 AS2 (sbrc,%B0,7) CR_TAB
3697 AS1 (com,%D0) CR_TAB
3698 AS2 (mov,%C0,%D0));
3699 else
3700 return *len = 6, (AS2 (mov,%B0,%D1) CR_TAB
3701 AS2 (mov,%A0,%C1) CR_TAB
3702 AS1 (clr,%D0) CR_TAB
3703 AS2 (sbrc,%B0,7) CR_TAB
3704 AS1 (com,%D0) CR_TAB
3705 AS2 (mov,%C0,%D0));
a28e4651 3706 }
1cb39658 3707
a28e4651 3708 case 24:
ab3a6ef8 3709 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3710 AS1 (clr,%D0) CR_TAB
3711 AS2 (sbrc,%A0,7) CR_TAB
3712 AS1 (com,%D0) CR_TAB
3713 AS2 (mov,%B0,%D0) CR_TAB
3714 AS2 (mov,%C0,%D0));
28f5cc4d 3715
5667001b 3716 default:
3717 if (INTVAL (operands[2]) < 32)
3718 break;
3719
3720 /* fall through */
3721
28f5cc4d 3722 case 31:
0aab73c2 3723 if (AVR_HAVE_MOVW)
28f5cc4d 3724 return *len = 4, (AS1 (lsl,%D0) CR_TAB
3725 AS2 (sbc,%A0,%A0) CR_TAB
3726 AS2 (mov,%B0,%A0) CR_TAB
3727 AS2 (movw,%C0,%A0));
3728 else
3729 return *len = 5, (AS1 (lsl,%D0) CR_TAB
3730 AS2 (sbc,%A0,%A0) CR_TAB
3731 AS2 (mov,%B0,%A0) CR_TAB
3732 AS2 (mov,%C0,%A0) CR_TAB
3733 AS2 (mov,%D0,%A0));
a28e4651 3734 }
28f5cc4d 3735 len = t;
a28e4651 3736 }
b681d971 3737 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3738 AS1 (ror,%C0) CR_TAB
3739 AS1 (ror,%B0) CR_TAB
3740 AS1 (ror,%A0)),
3741 insn, operands, len, 4);
a28e4651 3742 return "";
3743}
3744
3745/* 8bit logic shift right ((unsigned char)x >> i) */
3746
37ac04dc 3747const char *
206a5129 3748lshrqi3_out (rtx insn, rtx operands[], int *len)
a28e4651 3749{
3750 if (GET_CODE (operands[2]) == CONST_INT)
3751 {
3752 int k;
1cb39658 3753
a28e4651 3754 if (!len)
3755 len = &k;
1cb39658 3756
a28e4651 3757 switch (INTVAL (operands[2]))
3758 {
1cb39658 3759 default:
5667001b 3760 if (INTVAL (operands[2]) < 8)
3761 break;
3762
1cb39658 3763 *len = 1;
3764 return AS1 (clr,%0);
3765
a28e4651 3766 case 1:
1cb39658 3767 *len = 1;
a28e4651 3768 return AS1 (lsr,%0);
1cb39658 3769
a28e4651 3770 case 2:
1cb39658 3771 *len = 2;
a28e4651 3772 return (AS1 (lsr,%0) CR_TAB
3773 AS1 (lsr,%0));
3774 case 3:
1cb39658 3775 *len = 3;
a28e4651 3776 return (AS1 (lsr,%0) CR_TAB
3777 AS1 (lsr,%0) CR_TAB
3778 AS1 (lsr,%0));
1cb39658 3779
a28e4651 3780 case 4:
0af74aa0 3781 if (test_hard_reg_class (LD_REGS, operands[0]))
a28e4651 3782 {
3783 *len=2;
3784 return (AS1 (swap,%0) CR_TAB
3785 AS2 (andi,%0,0x0f));
3786 }
1cb39658 3787 *len = 4;
a28e4651 3788 return (AS1 (lsr,%0) CR_TAB
3789 AS1 (lsr,%0) CR_TAB
3790 AS1 (lsr,%0) CR_TAB
3791 AS1 (lsr,%0));
1cb39658 3792
a28e4651 3793 case 5:
0af74aa0 3794 if (test_hard_reg_class (LD_REGS, operands[0]))
a28e4651 3795 {
1cb39658 3796 *len = 3;
a28e4651 3797 return (AS1 (swap,%0) CR_TAB
3798 AS1 (lsr,%0) CR_TAB
3799 AS2 (andi,%0,0x7));
3800 }
1cb39658 3801 *len = 5;
a28e4651 3802 return (AS1 (lsr,%0) CR_TAB
3803 AS1 (lsr,%0) CR_TAB
3804 AS1 (lsr,%0) CR_TAB
3805 AS1 (lsr,%0) CR_TAB
3806 AS1 (lsr,%0));
1cb39658 3807
a28e4651 3808 case 6:
0af74aa0 3809 if (test_hard_reg_class (LD_REGS, operands[0]))
a28e4651 3810 {
1cb39658 3811 *len = 4;
a28e4651 3812 return (AS1 (swap,%0) CR_TAB
3813 AS1 (lsr,%0) CR_TAB
3814 AS1 (lsr,%0) CR_TAB
3815 AS2 (andi,%0,0x3));
3816 }
1cb39658 3817 *len = 6;
a28e4651 3818 return (AS1 (lsr,%0) CR_TAB
3819 AS1 (lsr,%0) CR_TAB
3820 AS1 (lsr,%0) CR_TAB
3821 AS1 (lsr,%0) CR_TAB
3822 AS1 (lsr,%0) CR_TAB
3823 AS1 (lsr,%0));
1cb39658 3824
a28e4651 3825 case 7:
1cb39658 3826 *len = 3;
a28e4651 3827 return (AS1 (rol,%0) CR_TAB
3828 AS1 (clr,%0) CR_TAB
3829 AS1 (rol,%0));
3830 }
3831 }
1cb39658 3832 else if (CONSTANT_P (operands[2]))
68435912 3833 fatal_insn ("internal compiler error. Incorrect shift:", insn);
1cb39658 3834
361aa610 3835 out_shift_with_cnt (AS1 (lsr,%0),
b681d971 3836 insn, operands, len, 1);
a28e4651 3837 return "";
3838}
3839
3840/* 16bit logic shift right ((unsigned short)x >> i) */
3841
37ac04dc 3842const char *
206a5129 3843lshrhi3_out (rtx insn, rtx operands[], int *len)
a28e4651 3844{
3845 if (GET_CODE (operands[2]) == CONST_INT)
3846 {
b681d971 3847 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3848 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
a28e4651 3849 int k;
1cb39658 3850 int *t = len;
b681d971 3851
a28e4651 3852 if (!len)
3853 len = &k;
1cb39658 3854
a28e4651 3855 switch (INTVAL (operands[2]))
3856 {
5667001b 3857 default:
3858 if (INTVAL (operands[2]) < 16)
3859 break;
3860
3861 *len = 2;
3862 return (AS1 (clr,%B0) CR_TAB
3863 AS1 (clr,%A0));
3864
b681d971 3865 case 4:
3866 if (optimize_size && scratch)
3867 break; /* 5 */
3868 if (ldi_ok)
3869 {
3870 *len = 6;
3871 return (AS1 (swap,%B0) CR_TAB
3872 AS1 (swap,%A0) CR_TAB
3873 AS2 (andi,%A0,0x0f) CR_TAB
3874 AS2 (eor,%A0,%B0) CR_TAB
3875 AS2 (andi,%B0,0x0f) CR_TAB
3876 AS2 (eor,%A0,%B0));
3877 }
3878 if (scratch)
3879 {
3880 *len = 7;
3881 return (AS1 (swap,%B0) CR_TAB
3882 AS1 (swap,%A0) CR_TAB
3883 AS2 (ldi,%3,0x0f) CR_TAB
3884 AS2 (and,%A0,%3) CR_TAB
3885 AS2 (eor,%A0,%B0) CR_TAB
3886 AS2 (and,%B0,%3) CR_TAB
3887 AS2 (eor,%A0,%B0));
3888 }
3889 break; /* optimize_size ? 6 : 8 */
3890
3891 case 5:
3892 if (optimize_size)
3893 break; /* scratch ? 5 : 6 */
3894 if (ldi_ok)
3895 {
3896 *len = 8;
3897 return (AS1 (lsr,%B0) CR_TAB
3898 AS1 (ror,%A0) CR_TAB
3899 AS1 (swap,%B0) CR_TAB
3900 AS1 (swap,%A0) CR_TAB
3901 AS2 (andi,%A0,0x0f) CR_TAB
3902 AS2 (eor,%A0,%B0) CR_TAB
3903 AS2 (andi,%B0,0x0f) CR_TAB
3904 AS2 (eor,%A0,%B0));
3905 }
3906 if (scratch)
3907 {
3908 *len = 9;
3909 return (AS1 (lsr,%B0) CR_TAB
3910 AS1 (ror,%A0) CR_TAB
3911 AS1 (swap,%B0) CR_TAB
3912 AS1 (swap,%A0) CR_TAB
3913 AS2 (ldi,%3,0x0f) CR_TAB
3914 AS2 (and,%A0,%3) CR_TAB
3915 AS2 (eor,%A0,%B0) CR_TAB
3916 AS2 (and,%B0,%3) CR_TAB
3917 AS2 (eor,%A0,%B0));
3918 }
3919 break; /* 10 */
3920
3921 case 6:
3922 if (optimize_size)
3923 break; /* scratch ? 5 : 6 */
3924 *len = 9;
3925 return (AS1 (clr,__tmp_reg__) CR_TAB
3926 AS1 (lsl,%A0) CR_TAB
3927 AS1 (rol,%B0) CR_TAB
3928 AS1 (rol,__tmp_reg__) CR_TAB
3929 AS1 (lsl,%A0) CR_TAB
3930 AS1 (rol,%B0) CR_TAB
3931 AS1 (rol,__tmp_reg__) CR_TAB
3932 AS2 (mov,%A0,%B0) CR_TAB
3933 AS2 (mov,%B0,__tmp_reg__));
28f5cc4d 3934
3935 case 7:
3936 *len = 5;
3937 return (AS1 (lsl,%A0) CR_TAB
3938 AS2 (mov,%A0,%B0) CR_TAB
3939 AS1 (rol,%A0) CR_TAB
3940 AS2 (sbc,%B0,%B0) CR_TAB
3941 AS1 (neg,%B0));
3942
a28e4651 3943 case 8:
ab3a6ef8 3944 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
3945 AS1 (clr,%B0));
28f5cc4d 3946
3947 case 9:
3948 *len = 3;
3949 return (AS2 (mov,%A0,%B0) CR_TAB
3950 AS1 (clr,%B0) CR_TAB
3951 AS1 (lsr,%A0));
3952
3953 case 10:
3954 *len = 4;
3955 return (AS2 (mov,%A0,%B0) CR_TAB
3956 AS1 (clr,%B0) CR_TAB
3957 AS1 (lsr,%A0) CR_TAB
3958 AS1 (lsr,%A0));
3959
3960 case 11:
3961 *len = 5;
3962 return (AS2 (mov,%A0,%B0) CR_TAB
3963 AS1 (clr,%B0) CR_TAB
3964 AS1 (lsr,%A0) CR_TAB
3965 AS1 (lsr,%A0) CR_TAB
3966 AS1 (lsr,%A0));
3967
3968 case 12:
b681d971 3969 if (ldi_ok)
28f5cc4d 3970 {
3971 *len = 4;
3972 return (AS2 (mov,%A0,%B0) CR_TAB
3973 AS1 (clr,%B0) CR_TAB
3974 AS1 (swap,%A0) CR_TAB
3975 AS2 (andi,%A0,0x0f));
3976 }
b681d971 3977 if (scratch)
3978 {
3979 *len = 5;
3980 return (AS2 (mov,%A0,%B0) CR_TAB
3981 AS1 (clr,%B0) CR_TAB
3982 AS1 (swap,%A0) CR_TAB
3983 AS2 (ldi,%3,0x0f) CR_TAB
3984 AS2 (and,%A0,%3));
3985 }
3986 *len = 6;
28f5cc4d 3987 return (AS2 (mov,%A0,%B0) CR_TAB
3988 AS1 (clr,%B0) CR_TAB
b681d971 3989 AS1 (lsr,%A0) CR_TAB
3990 AS1 (lsr,%A0) CR_TAB
3991 AS1 (lsr,%A0) CR_TAB
3992 AS1 (lsr,%A0));
28f5cc4d 3993
3994 case 13:
b681d971 3995 if (ldi_ok)
28f5cc4d 3996 {
3997 *len = 5;
3998 return (AS2 (mov,%A0,%B0) CR_TAB
3999 AS1 (clr,%B0) CR_TAB
4000 AS1 (swap,%A0) CR_TAB
4001 AS1 (lsr,%A0) CR_TAB
4002 AS2 (andi,%A0,0x07));
4003 }
8cc5a1af 4004 if (AVR_HAVE_MUL && scratch)
28f5cc4d 4005 {
4006 *len = 5;
4007 return (AS2 (ldi,%3,0x08) CR_TAB
4008 AS2 (mul,%B0,%3) CR_TAB
4009 AS2 (mov,%A0,r1) CR_TAB
4010 AS1 (clr,%B0) CR_TAB
4011 AS1 (clr,__zero_reg__));
4012 }
b681d971 4013 if (optimize_size && scratch)
4014 break; /* 5 */
4015 if (scratch)
4016 {
4017 *len = 6;
4018 return (AS2 (mov,%A0,%B0) CR_TAB
4019 AS1 (clr,%B0) CR_TAB
4020 AS1 (swap,%A0) CR_TAB
4021 AS1 (lsr,%A0) CR_TAB
4022 AS2 (ldi,%3,0x07) CR_TAB
4023 AS2 (and,%A0,%3));
4024 }
8cc5a1af 4025 if (AVR_HAVE_MUL)
b681d971 4026 {
4027 *len = 6;
4028 return ("set" CR_TAB
4029 AS2 (bld,r1,3) CR_TAB
4030 AS2 (mul,%B0,r1) CR_TAB
4031 AS2 (mov,%A0,r1) CR_TAB
4032 AS1 (clr,%B0) CR_TAB
4033 AS1 (clr,__zero_reg__));
4034 }
4035 *len = 7;
4036 return (AS2 (mov,%A0,%B0) CR_TAB
4037 AS1 (clr,%B0) CR_TAB
4038 AS1 (lsr,%A0) CR_TAB
4039 AS1 (lsr,%A0) CR_TAB
4040 AS1 (lsr,%A0) CR_TAB
4041 AS1 (lsr,%A0) CR_TAB
4042 AS1 (lsr,%A0));
28f5cc4d 4043
4044 case 14:
8cc5a1af 4045 if (AVR_HAVE_MUL && ldi_ok)
b681d971 4046 {
4047 *len = 5;
4048 return (AS2 (ldi,%A0,0x04) CR_TAB
4049 AS2 (mul,%B0,%A0) CR_TAB
4050 AS2 (mov,%A0,r1) CR_TAB
4051 AS1 (clr,%B0) CR_TAB
4052 AS1 (clr,__zero_reg__));
4053 }
8cc5a1af 4054 if (AVR_HAVE_MUL && scratch)
28f5cc4d 4055 {
4056 *len = 5;
4057 return (AS2 (ldi,%3,0x04) CR_TAB
4058 AS2 (mul,%B0,%3) CR_TAB
4059 AS2 (mov,%A0,r1) CR_TAB
4060 AS1 (clr,%B0) CR_TAB
4061 AS1 (clr,__zero_reg__));
4062 }
b681d971 4063 if (optimize_size && ldi_ok)
4064 {
4065 *len = 5;
4066 return (AS2 (mov,%A0,%B0) CR_TAB
4067 AS2 (ldi,%B0,6) "\n1:\t"
4068 AS1 (lsr,%A0) CR_TAB
4069 AS1 (dec,%B0) CR_TAB
4070 AS1 (brne,1b));
4071 }
4072 if (optimize_size && scratch)
4073 break; /* 5 */
4074 *len = 6;
4075 return (AS1 (clr,%A0) CR_TAB
4076 AS1 (lsl,%B0) CR_TAB
4077 AS1 (rol,%A0) CR_TAB
4078 AS1 (lsl,%B0) CR_TAB
4079 AS1 (rol,%A0) CR_TAB
4080 AS1 (clr,%B0));
28f5cc4d 4081
8a2a7305 4082 case 15:
1cb39658 4083 *len = 4;
b681d971 4084 return (AS1 (clr,%A0) CR_TAB
4085 AS1 (lsl,%B0) CR_TAB
4086 AS1 (rol,%A0) CR_TAB
1cb39658 4087 AS1 (clr,%B0));
a28e4651 4088 }
28f5cc4d 4089 len = t;
a28e4651 4090 }
b681d971 4091 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
4092 AS1 (ror,%A0)),
4093 insn, operands, len, 2);
a28e4651 4094 return "";
4095}
4096
4097/* 32bit logic shift right ((unsigned int)x >> i) */
4098
37ac04dc 4099const char *
206a5129 4100lshrsi3_out (rtx insn, rtx operands[], int *len)
a28e4651 4101{
4102 if (GET_CODE (operands[2]) == CONST_INT)
4103 {
4104 int k;
1cb39658 4105 int *t = len;
4106
a28e4651 4107 if (!len)
4108 len = &k;
1cb39658 4109
a28e4651 4110 switch (INTVAL (operands[2]))
4111 {
5667001b 4112 default:
4113 if (INTVAL (operands[2]) < 32)
4114 break;
4115
0aab73c2 4116 if (AVR_HAVE_MOVW)
5667001b 4117 return *len = 3, (AS1 (clr,%D0) CR_TAB
4118 AS1 (clr,%C0) CR_TAB
4119 AS2 (movw,%A0,%C0));
4120 *len = 4;
4121 return (AS1 (clr,%D0) CR_TAB
4122 AS1 (clr,%C0) CR_TAB
4123 AS1 (clr,%B0) CR_TAB
4124 AS1 (clr,%A0));
4125
a28e4651 4126 case 8:
4127 {
4128 int reg0 = true_regnum (operands[0]);
4129 int reg1 = true_regnum (operands[1]);
1cb39658 4130 *len = 4;
a28e4651 4131 if (reg0 <= reg1)
4132 return (AS2 (mov,%A0,%B1) CR_TAB
4133 AS2 (mov,%B0,%C1) CR_TAB
4134 AS2 (mov,%C0,%D1) CR_TAB
4135 AS1 (clr,%D0));
a28e4651 4136 else
4137 return (AS1 (clr,%D0) CR_TAB
4138 AS2 (mov,%C0,%D1) CR_TAB
4139 AS2 (mov,%B0,%C1) CR_TAB
4140 AS2 (mov,%A0,%B1));
4141 }
1cb39658 4142
a28e4651 4143 case 16:
4144 {
4145 int reg0 = true_regnum (operands[0]);
4146 int reg1 = true_regnum (operands[1]);
ab3a6ef8 4147
4148 if (reg0 == reg1 + 2)
a28e4651 4149 return *len = 2, (AS1 (clr,%C0) CR_TAB
4150 AS1 (clr,%D0));
ab3a6ef8 4151 if (AVR_HAVE_MOVW)
4152 return *len = 3, (AS2 (movw,%A0,%C1) CR_TAB
4153 AS1 (clr,%C0) CR_TAB
4154 AS1 (clr,%D0));
a28e4651 4155 else
ab3a6ef8 4156 return *len = 4, (AS2 (mov,%B0,%D1) CR_TAB
4157 AS2 (mov,%A0,%C1) CR_TAB
4158 AS1 (clr,%C0) CR_TAB
4159 AS1 (clr,%D0));
a28e4651 4160 }
1cb39658 4161
a28e4651 4162 case 24:
ab3a6ef8 4163 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4164 AS1 (clr,%B0) CR_TAB
4165 AS1 (clr,%C0) CR_TAB
4166 AS1 (clr,%D0));
28f5cc4d 4167
4168 case 31:
4169 *len = 6;
4170 return (AS1 (clr,%A0) CR_TAB
4171 AS2 (sbrc,%D0,7) CR_TAB
4172 AS1 (inc,%A0) CR_TAB
4173 AS1 (clr,%B0) CR_TAB
4174 AS1 (clr,%C0) CR_TAB
4175 AS1 (clr,%D0));
a28e4651 4176 }
28f5cc4d 4177 len = t;
a28e4651 4178 }
b681d971 4179 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4180 AS1 (ror,%C0) CR_TAB
4181 AS1 (ror,%B0) CR_TAB
4182 AS1 (ror,%A0)),
4183 insn, operands, len, 4);
a28e4651 4184 return "";
4185}
4186
4187/* Modifies the length assigned to instruction INSN
4188 LEN is the initially computed length of the insn. */
4189
4190int
206a5129 4191adjust_insn_length (rtx insn, int len)
a28e4651 4192{
4193 rtx patt = PATTERN (insn);
4194 rtx set;
9c501a04 4195
a28e4651 4196 if (GET_CODE (patt) == SET)
4197 {
4198 rtx op[10];
4199 op[1] = SET_SRC (patt);
4200 op[0] = SET_DEST (patt);
e511e253 4201 if (general_operand (op[1], VOIDmode)
4202 && general_operand (op[0], VOIDmode))
4203 {
4204 switch (GET_MODE (op[0]))
4205 {
4206 case QImode:
4207 output_movqi (insn, op, &len);
4208 break;
4209 case HImode:
4210 output_movhi (insn, op, &len);
4211 break;
4212 case SImode:
4213 case SFmode:
4214 output_movsisf (insn, op, &len);
4215 break;
4216 default:
4217 break;
4218 }
4219 }
a28e4651 4220 else if (op[0] == cc0_rtx && REG_P (op[1]))
4221 {
4222 switch (GET_MODE (op[1]))
4223 {
4224 case HImode: out_tsthi (insn,&len); break;
4225 case SImode: out_tstsi (insn,&len); break;
4226 default: break;
4227 }
4228 }
4229 else if (GET_CODE (op[1]) == AND)
4230 {
4231 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4232 {
4233 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4234 if (GET_MODE (op[1]) == SImode)
4235 len = (((mask & 0xff) != 0xff)
4236 + ((mask & 0xff00) != 0xff00)
30435bf8 4237 + ((mask & 0xff0000L) != 0xff0000L)
4238 + ((mask & 0xff000000L) != 0xff000000L));
a28e4651 4239 else if (GET_MODE (op[1]) == HImode)
4240 len = (((mask & 0xff) != 0xff)
4241 + ((mask & 0xff00) != 0xff00));
4242 }
4243 }
4244 else if (GET_CODE (op[1]) == IOR)
4245 {
4246 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4247 {
4248 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4249 if (GET_MODE (op[1]) == SImode)
37ac04dc 4250 len = (((mask & 0xff) != 0)
4251 + ((mask & 0xff00) != 0)
30435bf8 4252 + ((mask & 0xff0000L) != 0)
4253 + ((mask & 0xff000000L) != 0));
a28e4651 4254 else if (GET_MODE (op[1]) == HImode)
37ac04dc 4255 len = (((mask & 0xff) != 0)
4256 + ((mask & 0xff00) != 0));
a28e4651 4257 }
4258 }
4259 }
4260 set = single_set (insn);
4261 if (set)
4262 {
4263 rtx op[10];
9c501a04 4264
a28e4651 4265 op[1] = SET_SRC (set);
4266 op[0] = SET_DEST (set);
9c501a04 4267
4268 if (GET_CODE (patt) == PARALLEL
4269 && general_operand (op[1], VOIDmode)
4270 && general_operand (op[0], VOIDmode))
4271 {
4272 if (XVECLEN (patt, 0) == 2)
4273 op[2] = XVECEXP (patt, 0, 1);
4274
4275 switch (GET_MODE (op[0]))
4276 {
4277 case QImode:
4278 len = 2;
4279 break;
4280 case HImode:
4281 output_reload_inhi (insn, op, &len);
4282 break;
4283 case SImode:
4284 case SFmode:
4285 output_reload_insisf (insn, op, &len);
4286 break;
4287 default:
4288 break;
4289 }
4290 }
4291 else if (GET_CODE (op[1]) == ASHIFT
a28e4651 4292 || GET_CODE (op[1]) == ASHIFTRT
4293 || GET_CODE (op[1]) == LSHIFTRT)
4294 {
4295 rtx ops[10];
4296 ops[0] = op[0];
4297 ops[1] = XEXP (op[1],0);
4298 ops[2] = XEXP (op[1],1);
4299 switch (GET_CODE (op[1]))
4300 {
4301 case ASHIFT:
4302 switch (GET_MODE (op[0]))
4303 {
4304 case QImode: ashlqi3_out (insn,ops,&len); break;
4305 case HImode: ashlhi3_out (insn,ops,&len); break;
4306 case SImode: ashlsi3_out (insn,ops,&len); break;
4307 default: break;
4308 }
4309 break;
4310 case ASHIFTRT:
4311 switch (GET_MODE (op[0]))
4312 {
4313 case QImode: ashrqi3_out (insn,ops,&len); break;
4314 case HImode: ashrhi3_out (insn,ops,&len); break;
4315 case SImode: ashrsi3_out (insn,ops,&len); break;
4316 default: break;
4317 }
4318 break;
4319 case LSHIFTRT:
4320 switch (GET_MODE (op[0]))
4321 {
4322 case QImode: lshrqi3_out (insn,ops,&len); break;
4323 case HImode: lshrhi3_out (insn,ops,&len); break;
4324 case SImode: lshrsi3_out (insn,ops,&len); break;
4325 default: break;
4326 }
4327 break;
4328 default:
4329 break;
4330 }
4331 }
4332 }
4333 return len;
4334}
4335
674a8f0b 4336/* Return nonzero if register REG dead after INSN. */
a28e4651 4337
4338int
206a5129 4339reg_unused_after (rtx insn, rtx reg)
a28e4651 4340{
e511e253 4341 return (dead_or_set_p (insn, reg)
a28e4651 4342 || (REG_P(reg) && _reg_unused_after (insn, reg)));
4343}
4344
e3e08e7f 4345/* Return nonzero if REG is not used after INSN.
a28e4651 4346 We assume REG is a reload reg, and therefore does
4347 not live past labels. It may live past calls or jumps though. */
4348
4349int
206a5129 4350_reg_unused_after (rtx insn, rtx reg)
a28e4651 4351{
4352 enum rtx_code code;
4353 rtx set;
4354
4355 /* If the reg is set by this instruction, then it is safe for our
4356 case. Disregard the case where this is a store to memory, since
4357 we are checking a register used in the store address. */
4358 set = single_set (insn);
4359 if (set && GET_CODE (SET_DEST (set)) != MEM
4360 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4361 return 1;
4362
4363 while ((insn = NEXT_INSN (insn)))
4364 {
6720e96c 4365 rtx set;
a28e4651 4366 code = GET_CODE (insn);
4367
4368#if 0
4369 /* If this is a label that existed before reload, then the register
4370 if dead here. However, if this is a label added by reorg, then
4371 the register may still be live here. We can't tell the difference,
4372 so we just ignore labels completely. */
4373 if (code == CODE_LABEL)
4374 return 1;
4375 /* else */
4376#endif
4377
6720e96c 4378 if (!INSN_P (insn))
4379 continue;
4380
a28e4651 4381 if (code == JUMP_INSN)
4382 return 0;
4383
4384 /* If this is a sequence, we must handle them all at once.
4385 We could have for instance a call that sets the target register,
ebb11c7b 4386 and an insn in a delay slot that uses the register. In this case,
a28e4651 4387 we must return 0. */
4388 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4389 {
4390 int i;
4391 int retval = 0;
4392
4393 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4394 {
4395 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4396 rtx set = single_set (this_insn);
4397
4398 if (GET_CODE (this_insn) == CALL_INSN)
4399 code = CALL_INSN;
4400 else if (GET_CODE (this_insn) == JUMP_INSN)
4401 {
4402 if (INSN_ANNULLED_BRANCH_P (this_insn))
4403 return 0;
4404 code = JUMP_INSN;
4405 }
4406
4407 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4408 return 0;
4409 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4410 {
4411 if (GET_CODE (SET_DEST (set)) != MEM)
4412 retval = 1;
4413 else
4414 return 0;
4415 }
4416 if (set == 0
4417 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4418 return 0;
4419 }
4420 if (retval == 1)
4421 return 1;
4422 else if (code == JUMP_INSN)
4423 return 0;
4424 }
4425
4426 if (code == CALL_INSN)
4427 {
4428 rtx tem;
4429 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4430 if (GET_CODE (XEXP (tem, 0)) == USE
4431 && REG_P (XEXP (XEXP (tem, 0), 0))
4432 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4433 return 0;
4434 if (call_used_regs[REGNO (reg)])
4435 return 1;
4436 }
4437
6720e96c 4438 set = single_set (insn);
a28e4651 4439
6720e96c 4440 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4441 return 0;
4442 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4443 return GET_CODE (SET_DEST (set)) != MEM;
4444 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4445 return 0;
a28e4651 4446 }
4447 return 1;
4448}
4449
58356836 4450/* Target hook for assembling integer objects. The AVR version needs
4451 special handling for references to certain labels. */
a28e4651 4452
58356836 4453static bool
206a5129 4454avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
a28e4651 4455{
58356836 4456 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
a179a371 4457 && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
58356836 4458 || GET_CODE (x) == LABEL_REF))
a28e4651 4459 {
58356836 4460 fputs ("\t.word\tpm(", asm_out_file);
4461 output_addr_const (asm_out_file, x);
4462 fputs (")\n", asm_out_file);
4463 return true;
a28e4651 4464 }
58356836 4465 return default_assemble_integer (x, size, aligned_p);
a28e4651 4466}
4467
a28e4651 4468/* The routine used to output NUL terminated strings. We use a special
4469 version of this for most svr4 targets because doing so makes the
4470 generated assembly code more compact (and thus faster to assemble)
4471 as well as more readable, especially for targets like the i386
4472 (where the only alternative is to output character sequences as
674a8f0b 4473 comma separated lists of numbers). */
a28e4651 4474
4475void
206a5129 4476gas_output_limited_string(FILE *file, const char *str)
a28e4651 4477{
37ac04dc 4478 const unsigned char *_limited_str = (unsigned char *) str;
a28e4651 4479 unsigned ch;
95d655c3 4480 fprintf (file, "%s\"", STRING_ASM_OP);
a28e4651 4481 for (; (ch = *_limited_str); _limited_str++)
4482 {
4483 int escape;
4484 switch (escape = ESCAPES[ch])
4485 {
4486 case 0:
4487 putc (ch, file);
4488 break;
4489 case 1:
4490 fprintf (file, "\\%03o", ch);
4491 break;
4492 default:
4493 putc ('\\', file);
4494 putc (escape, file);
4495 break;
4496 }
4497 }
4498 fprintf (file, "\"\n");
4499}
4500
4501/* The routine used to output sequences of byte values. We use a special
4502 version of this for most svr4 targets because doing so makes the
4503 generated assembly code more compact (and thus faster to assemble)
4504 as well as more readable. Note that if we find subparts of the
4505 character sequence which end with NUL (and which are shorter than
4506 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4507
4508void
206a5129 4509gas_output_ascii(FILE *file, const char *str, size_t length)
a28e4651 4510{
37ac04dc 4511 const unsigned char *_ascii_bytes = (const unsigned char *) str;
4512 const unsigned char *limit = _ascii_bytes + length;
a28e4651 4513 unsigned bytes_in_chunk = 0;
4514 for (; _ascii_bytes < limit; _ascii_bytes++)
4515 {
37ac04dc 4516 const unsigned char *p;
a28e4651 4517 if (bytes_in_chunk >= 60)
4518 {
4519 fprintf (file, "\"\n");
4520 bytes_in_chunk = 0;
4521 }
4522 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4523 continue;
4524 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4525 {
4526 if (bytes_in_chunk > 0)
4527 {
4528 fprintf (file, "\"\n");
4529 bytes_in_chunk = 0;
4530 }
e511e253 4531 gas_output_limited_string (file, (char*)_ascii_bytes);
a28e4651 4532 _ascii_bytes = p;
4533 }
4534 else
4535 {
4536 int escape;
4537 unsigned ch;
4538 if (bytes_in_chunk == 0)
4539 fprintf (file, "\t.ascii\t\"");
4540 switch (escape = ESCAPES[ch = *_ascii_bytes])
4541 {
4542 case 0:
4543 putc (ch, file);
4544 bytes_in_chunk++;
4545 break;
4546 case 1:
4547 fprintf (file, "\\%03o", ch);
4548 bytes_in_chunk += 4;
4549 break;
4550 default:
4551 putc ('\\', file);
4552 putc (escape, file);
4553 bytes_in_chunk += 2;
4554 break;
4555 }
4556 }
4557 }
4558 if (bytes_in_chunk > 0)
4559 fprintf (file, "\"\n");
4560}
4561
4562/* Return value is nonzero if pseudos that have been
4563 assigned to registers of class CLASS would likely be spilled
4564 because registers of CLASS are needed for spill registers. */
4565
4566enum reg_class
206a5129 4567class_likely_spilled_p (int c)
a28e4651 4568{
4569 return (c != ALL_REGS && c != ADDW_REGS);
4570}
4571
e3c541f0 4572/* Valid attributes:
a28e4651 4573 progmem - put data to program memory;
4574 signal - make a function to be hardware interrupt. After function
0af74aa0 4575 prologue interrupts are disabled;
a28e4651 4576 interrupt - make a function to be hardware interrupt. After function
0af74aa0 4577 prologue interrupts are enabled;
e3c541f0 4578 naked - don't generate function prologue/epilogue and `ret' command.
a28e4651 4579
e3c541f0 4580 Only `progmem' attribute valid for type. */
4581
4582const struct attribute_spec avr_attribute_table[] =
a28e4651 4583{
e3c541f0 4584 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4585 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
4586 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4587 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
f86b386b 4588 { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute },
e3c541f0 4589 { NULL, 0, 0, false, false, false, NULL }
4590};
a28e4651 4591
e3c541f0 4592/* Handle a "progmem" attribute; arguments as in
4593 struct attribute_spec.handler. */
4594static tree
206a5129 4595avr_handle_progmem_attribute (tree *node, tree name,
4596 tree args ATTRIBUTE_UNUSED,
4597 int flags ATTRIBUTE_UNUSED,
4598 bool *no_add_attrs)
e3c541f0 4599{
4600 if (DECL_P (*node))
a28e4651 4601 {
68e7ca0a 4602 if (TREE_CODE (*node) == TYPE_DECL)
4603 {
4604 /* This is really a decl attribute, not a type attribute,
4605 but try to handle it for GCC 3.0 backwards compatibility. */
4606
4607 tree type = TREE_TYPE (*node);
4608 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
4609 tree newtype = build_type_attribute_variant (type, attr);
4610
4611 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
4612 TREE_TYPE (*node) = newtype;
4613 *no_add_attrs = true;
4614 }
4615 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
a28e4651 4616 {
e3c541f0 4617 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
4618 {
c3ceba8e 4619 warning (0, "only initialized variables can be placed into "
68435912 4620 "program memory area");
e3c541f0 4621 *no_add_attrs = true;
4622 }
4623 }
4624 else
4625 {
9b2d6d13 4626 warning (OPT_Wattributes, "%qs attribute ignored",
4627 IDENTIFIER_POINTER (name));
e3c541f0 4628 *no_add_attrs = true;
a28e4651 4629 }
a28e4651 4630 }
e3c541f0 4631
4632 return NULL_TREE;
a28e4651 4633}
4634
e3c541f0 4635/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4636 struct attribute_spec.handler. */
206a5129 4637
e3c541f0 4638static tree
206a5129 4639avr_handle_fndecl_attribute (tree *node, tree name,
4640 tree args ATTRIBUTE_UNUSED,
4641 int flags ATTRIBUTE_UNUSED,
4642 bool *no_add_attrs)
e3c541f0 4643{
4644 if (TREE_CODE (*node) != FUNCTION_DECL)
4645 {
9b2d6d13 4646 warning (OPT_Wattributes, "%qs attribute only applies to functions",
e3c541f0 4647 IDENTIFIER_POINTER (name));
4648 *no_add_attrs = true;
4649 }
7a238e40 4650 else
4651 {
0d528483 4652 const char *func_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (*node));
7a238e40 4653 const char *attr = IDENTIFIER_POINTER (name);
4654
4655 /* If the function has the 'signal' or 'interrupt' attribute, test to
4656 make sure that the name of the function is "__vector_NN" so as to
4657 catch when the user misspells the interrupt vector name. */
4658
4659 if (strncmp (attr, "interrupt", strlen ("interrupt")) == 0)
4660 {
4661 if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
4662 {
3284a242 4663 warning (0, "%qs appears to be a misspelled interrupt handler",
7a238e40 4664 func_name);
4665 }
4666 }
4667 else if (strncmp (attr, "signal", strlen ("signal")) == 0)
4668 {
4669 if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
4670 {
3284a242 4671 warning (0, "%qs appears to be a misspelled signal handler",
7a238e40 4672 func_name);
4673 }
4674 }
4675 }
e3c541f0 4676
4677 return NULL_TREE;
4678}
a28e4651 4679
f86b386b 4680static tree
4681avr_handle_fntype_attribute (tree *node, tree name,
4682 tree args ATTRIBUTE_UNUSED,
4683 int flags ATTRIBUTE_UNUSED,
4684 bool *no_add_attrs)
4685{
4686 if (TREE_CODE (*node) != FUNCTION_TYPE)
4687 {
4688 warning (OPT_Wattributes, "%qs attribute only applies to functions",
4689 IDENTIFIER_POINTER (name));
4690 *no_add_attrs = true;
4691 }
4692
4693 return NULL_TREE;
4694}
4695
a28e4651 4696/* Look for attribute `progmem' in DECL
0af74aa0 4697 if found return 1, otherwise 0. */
a28e4651 4698
4699int
148b2ce0 4700avr_progmem_p (tree decl, tree attributes)
a28e4651 4701{
4702 tree a;
4703
4704 if (TREE_CODE (decl) != VAR_DECL)
4705 return 0;
4706
4707 if (NULL_TREE
148b2ce0 4708 != lookup_attribute ("progmem", attributes))
a28e4651 4709 return 1;
4710
4711 a=decl;
4712 do
4713 a = TREE_TYPE(a);
4714 while (TREE_CODE (a) == ARRAY_TYPE);
4715
faf8f400 4716 if (a == error_mark_node)
4717 return 0;
4718
a28e4651 4719 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4720 return 1;
4721
4722 return 0;
4723}
4724
a179a371 4725/* Add the section attribute if the variable is in progmem. */
4726
7811991d 4727static void
206a5129 4728avr_insert_attributes (tree node, tree *attributes)
a28e4651 4729{
a179a371 4730 if (TREE_CODE (node) == VAR_DECL
4731 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
148b2ce0 4732 && avr_progmem_p (node, *attributes))
a28e4651 4733 {
a179a371 4734 static const char dsec[] = ".progmem.data";
4735 *attributes = tree_cons (get_identifier ("section"),
4736 build_tree_list (NULL, build_string (strlen (dsec), dsec)),
4737 *attributes);
4738
4739 /* ??? This seems sketchy. Why can't the user declare the
4740 thing const in the first place? */
4741 TREE_READONLY (node) = 1;
a28e4651 4742 }
7b4a38a6 4743}
a28e4651 4744
2f14b1f9 4745/* A get_unnamed_section callback for switching to progmem_section. */
4746
4747static void
4748avr_output_progmem_section_asm_op (const void *arg ATTRIBUTE_UNUSED)
4749{
4750 fprintf (asm_out_file,
4751 "\t.section .progmem.gcc_sw_table, \"%s\", @progbits\n",
4752 AVR_MEGA ? "a" : "ax");
4753 /* Should already be aligned, this is just to be safe if it isn't. */
4754 fprintf (asm_out_file, "\t.p2align 1\n");
4755}
4756
4757/* Implement TARGET_ASM_INIT_SECTIONS. */
4758
4759static void
4760avr_asm_init_sections (void)
4761{
4762 progmem_section = get_unnamed_section (AVR_MEGA ? 0 : SECTION_CODE,
4763 avr_output_progmem_section_asm_op,
4764 NULL);
4765 readonly_data_section = data_section;
4766}
4767
8a46ca38 4768static unsigned int
206a5129 4769avr_section_type_flags (tree decl, const char *name, int reloc)
8a46ca38 4770{
4771 unsigned int flags = default_section_type_flags (decl, name, reloc);
4772
4773 if (strncmp (name, ".noinit", 7) == 0)
4774 {
4775 if (decl && TREE_CODE (decl) == VAR_DECL
4776 && DECL_INITIAL (decl) == NULL_TREE)
4777 flags |= SECTION_BSS; /* @nobits */
4778 else
c3ceba8e 4779 warning (0, "only uninitialized variables can be placed in the "
8a46ca38 4780 ".noinit section");
4781 }
4782
4783 return flags;
4784}
4785
92c473b8 4786/* Outputs some appropriate text to go at the start of an assembler
4787 file. */
a28e4651 4788
92c473b8 4789static void
206a5129 4790avr_file_start (void)
a28e4651 4791{
235d7594 4792 if (avr_asm_only_p)
1e5fcbe2 4793 error ("MCU %qs supported for assembler only", avr_mcu_name);
235d7594 4794
92c473b8 4795 default_file_start ();
4796
0aab73c2 4797/* fprintf (asm_out_file, "\t.arch %s\n", avr_mcu_name);*/
a28e4651 4798 fputs ("__SREG__ = 0x3f\n"
4799 "__SP_H__ = 0x3e\n"
92c473b8 4800 "__SP_L__ = 0x3d\n", asm_out_file);
a28e4651 4801
91c3269b 4802 fputs ("__tmp_reg__ = 0\n"
92c473b8 4803 "__zero_reg__ = 1\n", asm_out_file);
9aa7484c 4804
4805 /* FIXME: output these only if there is anything in the .data / .bss
4806 sections - some code size could be saved by not linking in the
4807 initialization code from libgcc if one or both sections are empty. */
92c473b8 4808 fputs ("\t.global __do_copy_data\n", asm_out_file);
4809 fputs ("\t.global __do_clear_bss\n", asm_out_file);
9aa7484c 4810
a28e4651 4811 commands_in_file = 0;
4812 commands_in_prologues = 0;
4813 commands_in_epilogues = 0;
4814}
4815
4816/* Outputs to the stdio stream FILE some
4817 appropriate text to go at the end of an assembler file. */
4818
f6940372 4819static void
206a5129 4820avr_file_end (void)
a28e4651 4821{
f6940372 4822 fputs ("/* File ", asm_out_file);
4823 output_quoted_string (asm_out_file, main_input_filename);
4824 fprintf (asm_out_file,
6e957326 4825 ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
a28e4651 4826 commands_in_file,
1cb39658 4827 commands_in_file,
a28e4651 4828 commands_in_file - commands_in_prologues - commands_in_epilogues,
4829 commands_in_prologues, commands_in_epilogues);
4830}
4831
4832/* Choose the order in which to allocate hard registers for
4833 pseudo-registers local to a basic block.
4834
4835 Store the desired register order in the array `reg_alloc_order'.
4836 Element 0 should be the register to allocate first; element 1, the
4837 next register; and so on. */
4838
4839void
206a5129 4840order_regs_for_local_alloc (void)
a28e4651 4841{
4842 unsigned int i;
e99c3a1d 4843 static const int order_0[] = {
a28e4651 4844 24,25,
4845 18,19,
4846 20,21,
4847 22,23,
4848 30,31,
4849 26,27,
4850 28,29,
4851 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4852 0,1,
4853 32,33,34,35
4854 };
e99c3a1d 4855 static const int order_1[] = {
a28e4651 4856 18,19,
4857 20,21,
4858 22,23,
4859 24,25,
4860 30,31,
4861 26,27,
4862 28,29,
4863 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4864 0,1,
4865 32,33,34,35
4866 };
e99c3a1d 4867 static const int order_2[] = {
a28e4651 4868 25,24,
4869 23,22,
4870 21,20,
4871 19,18,
4872 30,31,
4873 26,27,
4874 28,29,
4875 17,16,
4876 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4877 1,0,
4878 32,33,34,35
4879 };
4880
e99c3a1d 4881 const int *order = (TARGET_ORDER_1 ? order_1 :
4882 TARGET_ORDER_2 ? order_2 :
4883 order_0);
5c62f199 4884 for (i=0; i < ARRAY_SIZE (order_0); ++i)
a28e4651 4885 reg_alloc_order[i] = order[i];
4886}
4887
433a5f02 4888
4889/* Mutually recursive subroutine of avr_rtx_cost for calculating the
4890 cost of an RTX operand given its context. X is the rtx of the
4891 operand, MODE is its mode, and OUTER is the rtx_code of this
4892 operand's parent operator. */
a28e4651 4893
fab7adbf 4894static int
433a5f02 4895avr_operand_rtx_cost (rtx x, enum machine_mode mode, enum rtx_code outer)
a28e4651 4896{
433a5f02 4897 enum rtx_code code = GET_CODE (x);
4898 int total;
4899
a28e4651 4900 switch (code)
4901 {
433a5f02 4902 case REG:
4903 case SUBREG:
4904 return 0;
4905
a28e4651 4906 case CONST_INT:
433a5f02 4907 case CONST_DOUBLE:
4908 return COSTS_N_INSNS (GET_MODE_SIZE (mode));
4909
a28e4651 4910 default:
4911 break;
4912 }
433a5f02 4913
4914 total = 0;
4915 avr_rtx_costs (x, code, outer, &total);
4916 return total;
a28e4651 4917}
4918
433a5f02 4919/* The AVR backend's rtx_cost function. X is rtx expression whose cost
4920 is to be calculated. Return true if the complete cost has been
4921 computed, and false if subexpressions should be scanned. In either
4922 case, *TOTAL contains the cost result. */
4923
fab7adbf 4924static bool
79fe0612 4925avr_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total)
fab7adbf 4926{
433a5f02 4927 enum machine_mode mode = GET_MODE (x);
4928 HOST_WIDE_INT val;
fab7adbf 4929
4930 switch (code)
4931 {
4932 case CONST_INT:
433a5f02 4933 case CONST_DOUBLE:
4934 /* Immediate constants are as cheap as registers. */
4935 *total = 0;
4936 return true;
4937
4938 case MEM:
4939 case CONST:
4940 case LABEL_REF:
4941 case SYMBOL_REF:
4942 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
4943 return true;
4944
4945 case NEG:
4946 switch (mode)
fab7adbf 4947 {
433a5f02 4948 case QImode:
4949 case SFmode:
4950 *total = COSTS_N_INSNS (1);
4951 break;
4952
4953 case HImode:
4954 *total = COSTS_N_INSNS (3);
4955 break;
4956
4957 case SImode:
4958 *total = COSTS_N_INSNS (7);
4959 break;
4960
4961 default:
4962 return false;
fab7adbf 4963 }
433a5f02 4964 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
4965 return true;
4966
4967 case ABS:
4968 switch (mode)
fab7adbf 4969 {
433a5f02 4970 case QImode:
4971 case SFmode:
4972 *total = COSTS_N_INSNS (1);
4973 break;
4974
4975 default:
4976 return false;
fab7adbf 4977 }
433a5f02 4978 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
4979 return true;
fab7adbf 4980
433a5f02 4981 case NOT:
4982 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
4983 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
fab7adbf 4984 return true;
4985
433a5f02 4986 case ZERO_EXTEND:
4987 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
4988 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
4989 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
4990 return true;
4991
4992 case SIGN_EXTEND:
4993 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
4994 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
4995 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
4996 return true;
4997
4998 case PLUS:
4999 switch (mode)
5000 {
5001 case QImode:
5002 *total = COSTS_N_INSNS (1);
5003 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5004 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5005 break;
5006
5007 case HImode:
5008 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5009 {
5010 *total = COSTS_N_INSNS (2);
5011 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5012 }
5013 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
5014 *total = COSTS_N_INSNS (1);
5015 else
5016 *total = COSTS_N_INSNS (2);
5017 break;
5018
5019 case SImode:
5020 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5021 {
5022 *total = COSTS_N_INSNS (4);
5023 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5024 }
5025 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
5026 *total = COSTS_N_INSNS (1);
5027 else
5028 *total = COSTS_N_INSNS (4);
5029 break;
5030
5031 default:
5032 return false;
5033 }
5034 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5035 return true;
5036
5037 case MINUS:
5038 case AND:
5039 case IOR:
5040 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
5041 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5042 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5043 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5044 return true;
5045
5046 case XOR:
5047 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
5048 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5049 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5050 return true;
5051
5052 case MULT:
5053 switch (mode)
5054 {
5055 case QImode:
8cc5a1af 5056 if (AVR_HAVE_MUL)
433a5f02 5057 *total = COSTS_N_INSNS (optimize_size ? 3 : 4);
5058 else if (optimize_size)
5059 *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
5060 else
5061 return false;
ba92127f 5062 break;
433a5f02 5063
5064 case HImode:
8cc5a1af 5065 if (AVR_HAVE_MUL)
433a5f02 5066 *total = COSTS_N_INSNS (optimize_size ? 7 : 10);
5067 else if (optimize_size)
5068 *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
5069 else
5070 return false;
ba92127f 5071 break;
433a5f02 5072
5073 default:
5074 return false;
5075 }
5076 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5077 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5078 return true;
5079
5080 case DIV:
5081 case MOD:
5082 case UDIV:
5083 case UMOD:
5084 if (optimize_size)
5085 *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
5086 else
5087 return false;
5088 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5089 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5090 return true;
5091
5092 case ASHIFT:
5093 switch (mode)
5094 {
5095 case QImode:
5096 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5097 {
5098 *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
5099 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5100 }
5101 else
5102 {
5103 val = INTVAL (XEXP (x, 1));
5104 if (val == 7)
5105 *total = COSTS_N_INSNS (3);
5106 else if (val >= 0 && val <= 7)
5107 *total = COSTS_N_INSNS (val);
5108 else
5109 *total = COSTS_N_INSNS (1);
5110 }
5111 break;
5112
5113 case HImode:
5114 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5115 {
5116 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5117 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5118 }
5119 else
5120 switch (INTVAL (XEXP (x, 1)))
5121 {
5122 case 0:
5123 *total = 0;
5124 break;
5125 case 1:
5126 case 8:
5127 *total = COSTS_N_INSNS (2);
5128 break;
5129 case 9:
5130 *total = COSTS_N_INSNS (3);
5131 break;
5132 case 2:
5133 case 3:
5134 case 10:
5135 case 15:
5136 *total = COSTS_N_INSNS (4);
5137 break;
5138 case 7:
5139 case 11:
5140 case 12:
5141 *total = COSTS_N_INSNS (5);
5142 break;
5143 case 4:
5144 *total = COSTS_N_INSNS (optimize_size ? 5 : 8);
5145 break;
5146 case 6:
5147 *total = COSTS_N_INSNS (optimize_size ? 5 : 9);
5148 break;
5149 case 5:
5150 *total = COSTS_N_INSNS (optimize_size ? 5 : 10);
5151 break;
5152 default:
5153 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5154 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5155 }
5156 break;
5157
5158 case SImode:
5159 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5160 {
5161 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5162 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5163 }
5164 else
5165 switch (INTVAL (XEXP (x, 1)))
5166 {
5167 case 0:
5168 *total = 0;
5169 break;
5170 case 24:
5171 *total = COSTS_N_INSNS (3);
5172 break;
5173 case 1:
5174 case 8:
5175 case 16:
5176 *total = COSTS_N_INSNS (4);
5177 break;
5178 case 31:
5179 *total = COSTS_N_INSNS (6);
5180 break;
5181 case 2:
5182 *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
5183 break;
5184 default:
5185 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5186 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5187 }
5188 break;
5189
5190 default:
5191 return false;
5192 }
5193 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5194 return true;
5195
5196 case ASHIFTRT:
5197 switch (mode)
5198 {
5199 case QImode:
5200 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5201 {
5202 *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
5203 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5204 }
5205 else
5206 {
5207 val = INTVAL (XEXP (x, 1));
5208 if (val == 6)
5209 *total = COSTS_N_INSNS (4);
5210 else if (val == 7)
5211 *total = COSTS_N_INSNS (2);
5212 else if (val >= 0 && val <= 7)
5213 *total = COSTS_N_INSNS (val);
5214 else
5215 *total = COSTS_N_INSNS (1);
5216 }
5217 break;
5218
5219 case HImode:
5220 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5221 {
5222 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5223 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5224 }
5225 else
5226 switch (INTVAL (XEXP (x, 1)))
5227 {
5228 case 0:
5229 *total = 0;
5230 break;
5231 case 1:
5232 *total = COSTS_N_INSNS (2);
5233 break;
5234 case 15:
5235 *total = COSTS_N_INSNS (3);
5236 break;
5237 case 2:
5238 case 7:
5239 case 8:
5240 case 9:
5241 *total = COSTS_N_INSNS (4);
5242 break;
5243 case 10:
5244 case 14:
5245 *total = COSTS_N_INSNS (5);
5246 break;
5247 case 11:
5248 *total = COSTS_N_INSNS (optimize_size ? 5 : 6);
5249 break;
5250 case 12:
5251 *total = COSTS_N_INSNS (optimize_size ? 5 : 7);
5252 break;
5253 case 6:
5254 case 13:
5255 *total = COSTS_N_INSNS (optimize_size ? 5 : 8);
5256 break;
5257 default:
5258 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5259 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5260 }
5261 break;
5262
5263 case SImode:
5264 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5265 {
5266 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5267 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5268 }
5269 else
5270 switch (INTVAL (XEXP (x, 1)))
5271 {
5272 case 0:
5273 *total = 0;
5274 break;
5275 case 1:
5276 *total = COSTS_N_INSNS (4);
5277 break;
5278 case 8:
5279 case 16:
5280 case 24:
5281 *total = COSTS_N_INSNS (6);
5282 break;
5283 case 2:
5284 *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
5285 break;
5286 case 31:
0aab73c2 5287 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
433a5f02 5288 break;
5289 default:
5290 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5291 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5292 }
5293 break;
5294
5295 default:
5296 return false;
5297 }
5298 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5299 return true;
5300
5301 case LSHIFTRT:
5302 switch (mode)
5303 {
5304 case QImode:
5305 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5306 {
5307 *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
5308 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5309 }
5310 else
5311 {
5312 val = INTVAL (XEXP (x, 1));
5313 if (val == 7)
5314 *total = COSTS_N_INSNS (3);
5315 else if (val >= 0 && val <= 7)
5316 *total = COSTS_N_INSNS (val);
5317 else
5318 *total = COSTS_N_INSNS (1);
5319 }
5320 break;
5321
5322 case HImode:
5323 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5324 {
5325 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5326 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5327 }
5328 else
5329 switch (INTVAL (XEXP (x, 1)))
5330 {
5331 case 0:
5332 *total = 0;
5333 break;
5334 case 1:
5335 case 8:
5336 *total = COSTS_N_INSNS (2);
5337 break;
5338 case 9:
5339 *total = COSTS_N_INSNS (3);
5340 break;
5341 case 2:
5342 case 10:
5343 case 15:
5344 *total = COSTS_N_INSNS (4);
5345 break;
5346 case 7:
5347 case 11:
5348 *total = COSTS_N_INSNS (5);
5349 break;
5350 case 3:
5351 case 12:
5352 case 13:
5353 case 14:
5354 *total = COSTS_N_INSNS (optimize_size ? 5 : 6);
5355 break;
5356 case 4:
5357 *total = COSTS_N_INSNS (optimize_size ? 5 : 7);
5358 break;
5359 case 5:
5360 case 6:
5361 *total = COSTS_N_INSNS (optimize_size ? 5 : 9);
5362 break;
5363 default:
5364 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5365 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5366 }
5367 break;
5368
5369 case SImode:
5370 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5371 {
5372 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5373 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5374 }
5375 else
5376 switch (INTVAL (XEXP (x, 1)))
5377 {
5378 case 0:
5379 *total = 0;
5380 break;
5381 case 1:
5382 *total = COSTS_N_INSNS (4);
5383 break;
5384 case 2:
5385 *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
5386 break;
5387 case 8:
5388 case 16:
5389 case 24:
5390 *total = COSTS_N_INSNS (4);
5391 break;
5392 case 31:
5393 *total = COSTS_N_INSNS (6);
5394 break;
5395 default:
5396 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5397 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5398 }
5399 break;
5400
5401 default:
5402 return false;
5403 }
5404 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5405 return true;
5406
5407 case COMPARE:
5408 switch (GET_MODE (XEXP (x, 0)))
fab7adbf 5409 {
433a5f02 5410 case QImode:
5411 *total = COSTS_N_INSNS (1);
5412 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5413 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5414 break;
5415
5416 case HImode:
5417 *total = COSTS_N_INSNS (2);
5418 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5419 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5420 else if (INTVAL (XEXP (x, 1)) != 0)
5421 *total += COSTS_N_INSNS (1);
5422 break;
5423
5424 case SImode:
5425 *total = COSTS_N_INSNS (4);
5426 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5427 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5428 else if (INTVAL (XEXP (x, 1)) != 0)
5429 *total += COSTS_N_INSNS (3);
5430 break;
5431
5432 default:
5433 return false;
fab7adbf 5434 }
433a5f02 5435 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5436 return true;
5437
5438 default:
5439 break;
fab7adbf 5440 }
433a5f02 5441 return false;
fab7adbf 5442}
5443
20c71901 5444/* Calculate the cost of a memory address. */
a28e4651 5445
ec0457a8 5446static int
206a5129 5447avr_address_cost (rtx x)
a28e4651 5448{
5449 if (GET_CODE (x) == PLUS
5450 && GET_CODE (XEXP (x,1)) == CONST_INT
5451 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
5452 && INTVAL (XEXP (x,1)) >= 61)
5453 return 18;
5454 if (CONSTANT_ADDRESS_P (x))
37ac04dc 5455 {
57463428 5456 if (avr_io_address_p (x, 1))
37ac04dc 5457 return 2;
5458 return 4;
5459 }
a28e4651 5460 return 4;
5461}
5462
164f5b34 5463/* Test for extra memory constraint 'Q'.
5464 It's a memory address based on Y or Z pointer with valid displacement. */
a28e4651 5465
5466int
164f5b34 5467extra_constraint_Q (rtx x)
a28e4651 5468{
164f5b34 5469 if (GET_CODE (XEXP (x,0)) == PLUS
5470 && REG_P (XEXP (XEXP (x,0), 0))
5471 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
5472 && (INTVAL (XEXP (XEXP (x,0), 1))
5473 <= MAX_LD_OFFSET (GET_MODE (x))))
a28e4651 5474 {
164f5b34 5475 rtx xx = XEXP (XEXP (x,0), 0);
5476 int regno = REGNO (xx);
5477 if (TARGET_ALL_DEBUG)
a28e4651 5478 {
164f5b34 5479 fprintf (stderr, ("extra_constraint:\n"
5480 "reload_completed: %d\n"
5481 "reload_in_progress: %d\n"),
5482 reload_completed, reload_in_progress);
5483 debug_rtx (x);
a28e4651 5484 }
164f5b34 5485 if (regno >= FIRST_PSEUDO_REGISTER)
5486 return 1; /* allocate pseudos */
5487 else if (regno == REG_Z || regno == REG_Y)
5488 return 1; /* strictly check */
5489 else if (xx == frame_pointer_rtx
5490 || xx == arg_pointer_rtx)
5491 return 1; /* XXX frame & arg pointer checks */
a28e4651 5492 }
5493 return 0;
5494}
5495
20c71901 5496/* Convert condition code CONDITION to the valid AVR condition code. */
a28e4651 5497
5498RTX_CODE
206a5129 5499avr_normalize_condition (RTX_CODE condition)
a28e4651 5500{
5501 switch (condition)
5502 {
5503 case GT:
5504 return GE;
5505 case GTU:
5506 return GEU;
5507 case LE:
5508 return LT;
5509 case LEU:
5510 return LTU;
5511 default:
8ef66241 5512 gcc_unreachable ();
a28e4651 5513 }
5514}
5515
ca692148 5516/* This function optimizes conditional jumps. */
a28e4651 5517
2efea8c0 5518static void
206a5129 5519avr_reorg (void)
a28e4651 5520{
5521 rtx insn, pattern;
a28e4651 5522
2efea8c0 5523 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
a28e4651 5524 {
e6ee4afa 5525 if (! (GET_CODE (insn) == INSN
5526 || GET_CODE (insn) == CALL_INSN
5527 || GET_CODE (insn) == JUMP_INSN)
a28e4651 5528 || !single_set (insn))
5529 continue;
5530
5531 pattern = PATTERN (insn);
5532
a28e4651 5533 if (GET_CODE (pattern) == PARALLEL)
5534 pattern = XVECEXP (pattern, 0, 0);
5535 if (GET_CODE (pattern) == SET
5536 && SET_DEST (pattern) == cc0_rtx
5537 && compare_diff_p (insn))
5538 {
5539 if (GET_CODE (SET_SRC (pattern)) == COMPARE)
5540 {
20c71901 5541 /* Now we work under compare insn. */
a28e4651 5542
5543 pattern = SET_SRC (pattern);
5544 if (true_regnum (XEXP (pattern,0)) >= 0
5545 && true_regnum (XEXP (pattern,1)) >= 0 )
5546 {
5547 rtx x = XEXP (pattern,0);
5548 rtx next = next_real_insn (insn);
5549 rtx pat = PATTERN (next);
5550 rtx src = SET_SRC (pat);
5551 rtx t = XEXP (src,0);
5552 PUT_CODE (t, swap_condition (GET_CODE (t)));
5553 XEXP (pattern,0) = XEXP (pattern,1);
5554 XEXP (pattern,1) = x;
5555 INSN_CODE (next) = -1;
5556 }
5557 else if (true_regnum (XEXP (pattern,0)) >= 0
5558 && GET_CODE (XEXP (pattern,1)) == CONST_INT)
5559 {
5560 rtx x = XEXP (pattern,1);
5561 rtx next = next_real_insn (insn);
5562 rtx pat = PATTERN (next);
5563 rtx src = SET_SRC (pat);
5564 rtx t = XEXP (src,0);
f4d3a3e0 5565 enum machine_mode mode = GET_MODE (XEXP (pattern, 0));
a28e4651 5566
0f10e357 5567 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
a28e4651 5568 {
f4d3a3e0 5569 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
a28e4651 5570 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
5571 INSN_CODE (next) = -1;
5572 INSN_CODE (insn) = -1;
5573 }
5574 }
5575 }
5576 else if (true_regnum (SET_SRC (pattern)) >= 0)
5577 {
5578 /* This is a tst insn */
5579 rtx next = next_real_insn (insn);
5580 rtx pat = PATTERN (next);
5581 rtx src = SET_SRC (pat);
5582 rtx t = XEXP (src,0);
5583
e6ee4afa 5584 PUT_CODE (t, swap_condition (GET_CODE (t)));
1a83b3ff 5585 SET_SRC (pattern) = gen_rtx_NEG (GET_MODE (SET_SRC (pattern)),
5586 SET_SRC (pattern));
e6ee4afa 5587 INSN_CODE (next) = -1;
5588 INSN_CODE (insn) = -1;
a28e4651 5589 }
5590 }
5591 }
5592}
5593
5594/* Returns register number for function return value.*/
5595
5596int
206a5129 5597avr_ret_register (void)
a28e4651 5598{
5599 return 24;
5600}
5601
f2b32076 5602/* Create an RTX representing the place where a
a28e4651 5603 library function returns a value of mode MODE. */
5604
5605rtx
206a5129 5606avr_libcall_value (enum machine_mode mode)
a28e4651 5607{
5608 int offs = GET_MODE_SIZE (mode);
5609 if (offs < 2)
5610 offs = 2;
1a83b3ff 5611 return gen_rtx_REG (mode, RET_REGISTER + 2 - offs);
a28e4651 5612}
5613
5614/* Create an RTX representing the place where a
5615 function returns a value of data type VALTYPE. */
5616
5617rtx
206a5129 5618avr_function_value (tree type, tree func ATTRIBUTE_UNUSED)
a28e4651 5619{
1cb39658 5620 unsigned int offs;
e7d17bf3 5621
a28e4651 5622 if (TYPE_MODE (type) != BLKmode)
5623 return avr_libcall_value (TYPE_MODE (type));
5624
5625 offs = int_size_in_bytes (type);
5626 if (offs < 2)
5627 offs = 2;
5628 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
5629 offs = GET_MODE_SIZE (SImode);
5630 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
5631 offs = GET_MODE_SIZE (DImode);
5632
1a83b3ff 5633 return gen_rtx_REG (BLKmode, RET_REGISTER + 2 - offs);
a28e4651 5634}
5635
a28e4651 5636/* Places additional restrictions on the register class to
5637 use when it is necessary to copy value X into a register
5638 in class CLASS. */
5639
5640enum reg_class
206a5129 5641preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class class)
a28e4651 5642{
a28e4651 5643 return class;
5644}
5645
8a2a7305 5646int
206a5129 5647test_hard_reg_class (enum reg_class class, rtx x)
8a2a7305 5648{
5649 int regno = true_regnum (x);
5650 if (regno < 0)
5651 return 0;
cb39cd35 5652
5653 if (TEST_HARD_REG_CLASS (class, regno))
5654 return 1;
5655
5656 return 0;
8a2a7305 5657}
5658
2ebcbfe8 5659
5660int
206a5129 5661jump_over_one_insn_p (rtx insn, rtx dest)
2ebcbfe8 5662{
5663 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5664 ? XEXP (dest, 0)
5665 : dest);
47fc0706 5666 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
5667 int dest_addr = INSN_ADDRESSES (uid);
4af90ac0 5668 return dest_addr - jump_addr == get_attr_length (insn) + 1;
2ebcbfe8 5669}
a7690ba9 5670
5671/* Returns 1 if a value of mode MODE can be stored starting with hard
0af74aa0 5672 register number REGNO. On the enhanced core, anything larger than
5673 1 byte must start in even numbered register for "movw" to work
5674 (this way we don't have to check for odd registers everywhere). */
a7690ba9 5675
5676int
206a5129 5677avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
a7690ba9 5678{
dc39da57 5679 /* Disallow QImode in stack pointer regs. */
5680 if ((regno == REG_SP || regno == (REG_SP + 1)) && mode == QImode)
5681 return 0;
5682
60d76236 5683 /* The only thing that can go into registers r28:r29 is a Pmode. */
5684 if (regno == REG_Y && mode == Pmode)
5685 return 1;
fdd6a205 5686
60d76236 5687 /* Otherwise disallow all regno/mode combinations that span r28:r29. */
5688 if (regno <= (REG_Y + 1) && (regno + GET_MODE_SIZE (mode)) >= (REG_Y + 1))
02b088c6 5689 return 0;
5690
a7690ba9 5691 if (mode == QImode)
5692 return 1;
60d76236 5693
5694 /* Modes larger than QImode occupy consecutive registers. */
5695 if (regno + GET_MODE_SIZE (mode) > FIRST_PSEUDO_REGISTER)
5696 return 0;
5697
5698 /* All modes larger than QImode should start in an even register. */
a7690ba9 5699 return !(regno & 1);
5700}
e511e253 5701
e511e253 5702/* Returns 1 if X is a valid address for an I/O register of size SIZE
57463428 5703 (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
5704 to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
e511e253 5705
57463428 5706int
206a5129 5707avr_io_address_p (rtx x, int size)
e511e253 5708{
5709 return (optimize > 0 && GET_CODE (x) == CONST_INT
5710 && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
5711}
5712
37ac04dc 5713const char *
206a5129 5714output_reload_inhi (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
e511e253 5715{
14da2a08 5716 int tmp;
5717 if (!len)
5718 len = &tmp;
5719
e511e253 5720 if (GET_CODE (operands[1]) == CONST_INT)
5721 {
5722 int val = INTVAL (operands[1]);
5723 if ((val & 0xff) == 0)
5724 {
5725 *len = 3;
5726 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
5727 AS2 (ldi,%2,hi8(%1)) CR_TAB
5728 AS2 (mov,%B0,%2));
5729 }
5730 else if ((val & 0xff00) == 0)
5731 {
5732 *len = 3;
5733 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5734 AS2 (mov,%A0,%2) CR_TAB
5735 AS2 (mov,%B0,__zero_reg__));
5736 }
5737 else if ((val & 0xff) == ((val & 0xff00) >> 8))
5738 {
5739 *len = 3;
5740 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5741 AS2 (mov,%A0,%2) CR_TAB
5742 AS2 (mov,%B0,%2));
5743 }
5744 }
5745 *len = 4;
5746 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5747 AS2 (mov,%A0,%2) CR_TAB
5748 AS2 (ldi,%2,hi8(%1)) CR_TAB
5749 AS2 (mov,%B0,%2));
5750}
5751
5752
37ac04dc 5753const char *
206a5129 5754output_reload_insisf (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
e511e253 5755{
37ac04dc 5756 rtx src = operands[1];
5757 int cnst = (GET_CODE (src) == CONST_INT);
5758
5759 if (len)
5760 {
5761 if (cnst)
5762 *len = 4 + ((INTVAL (src) & 0xff) != 0)
5763 + ((INTVAL (src) & 0xff00) != 0)
5764 + ((INTVAL (src) & 0xff0000) != 0)
30435bf8 5765 + ((INTVAL (src) & 0xff000000) != 0);
37ac04dc 5766 else
5767 *len = 8;
5768
5769 return "";
5770 }
e511e253 5771
37ac04dc 5772 if (cnst && ((INTVAL (src) & 0xff) == 0))
e511e253 5773 output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
5774 else
5775 {
5776 output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
5777 output_asm_insn (AS2 (mov, %A0, %2), operands);
5778 }
37ac04dc 5779 if (cnst && ((INTVAL (src) & 0xff00) == 0))
e511e253 5780 output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
5781 else
5782 {
5783 output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
5784 output_asm_insn (AS2 (mov, %B0, %2), operands);
5785 }
37ac04dc 5786 if (cnst && ((INTVAL (src) & 0xff0000) == 0))
e511e253 5787 output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
5788 else
5789 {
5790 output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
5791 output_asm_insn (AS2 (mov, %C0, %2), operands);
5792 }
30435bf8 5793 if (cnst && ((INTVAL (src) & 0xff000000) == 0))
e511e253 5794 output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
5795 else
5796 {
5797 output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
5798 output_asm_insn (AS2 (mov, %D0, %2), operands);
5799 }
5800 return "";
5801}
b681d971 5802
5803void
206a5129 5804avr_output_bld (rtx operands[], int bit_nr)
b681d971 5805{
5806 static char s[] = "bld %A0,0";
5807
5808 s[5] = 'A' + (bit_nr >> 3);
5809 s[8] = '0' + (bit_nr & 7);
5810 output_asm_insn (s, operands);
5811}
5812
91b18013 5813void
206a5129 5814avr_output_addr_vec_elt (FILE *stream, int value)
91b18013 5815{
2f14b1f9 5816 switch_to_section (progmem_section);
91b18013 5817 if (AVR_MEGA)
5818 fprintf (stream, "\t.word pm(.L%d)\n", value);
5819 else
5820 fprintf (stream, "\trjmp .L%d\n", value);
91b18013 5821}
5822
51fe7379 5823/* Returns 1 if SCRATCH are safe to be allocated as a scratch
5824 registers (for a define_peephole2) in the current function. */
5825
5826int
206a5129 5827avr_peep2_scratch_safe (rtx scratch)
51fe7379 5828{
5829 if ((interrupt_function_p (current_function_decl)
5830 || signal_function_p (current_function_decl))
5831 && leaf_function_p ())
5832 {
5833 int first_reg = true_regnum (scratch);
5834 int last_reg = first_reg + GET_MODE_SIZE (GET_MODE (scratch)) - 1;
5835 int reg;
5836
5837 for (reg = first_reg; reg <= last_reg; reg++)
5838 {
3072d30e 5839 if (!df_regs_ever_live_p (reg))
51fe7379 5840 return 0;
5841 }
5842 }
5843 return 1;
5844}
4af90ac0 5845
5846/* Output a branch that tests a single bit of a register (QI, HI or SImode)
5847 or memory location in the I/O space (QImode only).
5848
5849 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5850 Operand 1: register operand to test, or CONST_INT memory address.
5851 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5852 Operand 3: label to jump to if the test is true. */
5853
5854const char *
206a5129 5855avr_out_sbxx_branch (rtx insn, rtx operands[])
4af90ac0 5856{
5857 enum rtx_code comp = GET_CODE (operands[0]);
5858 int long_jump = (get_attr_length (insn) >= 4);
5859 int reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
5860
5861 if (comp == GE)
5862 comp = EQ;
5863 else if (comp == LT)
5864 comp = NE;
5865
5866 if (reverse)
5867 comp = reverse_condition (comp);
5868
5869 if (GET_CODE (operands[1]) == CONST_INT)
5870 {
5871 if (INTVAL (operands[1]) < 0x40)
5872 {
5873 if (comp == EQ)
5874 output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
5875 else
5876 output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
5877 }
5878 else
5879 {
5880 output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
5881 if (comp == EQ)
5882 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
5883 else
5884 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
5885 }
5886 }
5887 else /* GET_CODE (operands[1]) == REG */
5888 {
5889 if (GET_MODE (operands[1]) == QImode)
5890 {
5891 if (comp == EQ)
5892 output_asm_insn (AS2 (sbrs,%1,%2), operands);
5893 else
5894 output_asm_insn (AS2 (sbrc,%1,%2), operands);
5895 }
5896 else /* HImode or SImode */
5897 {
5898 static char buf[] = "sbrc %A1,0";
5899 int bit_nr = exact_log2 (INTVAL (operands[2])
5900 & GET_MODE_MASK (GET_MODE (operands[1])));
5901
5902 buf[3] = (comp == EQ) ? 's' : 'c';
5903 buf[6] = 'A' + (bit_nr >> 3);
5904 buf[9] = '0' + (bit_nr & 7);
5905 output_asm_insn (buf, operands);
5906 }
5907 }
5908
5909 if (long_jump)
31bf8549 5910 return (AS1 (rjmp,.+4) CR_TAB
4af90ac0 5911 AS1 (jmp,%3));
5912 if (!reverse)
5913 return AS1 (rjmp,%3);
5914 return "";
5915}
9aa7484c 5916
6644435d 5917/* Worker function for TARGET_ASM_CONSTRUCTOR. */
5918
9aa7484c 5919static void
206a5129 5920avr_asm_out_ctor (rtx symbol, int priority)
9aa7484c 5921{
5922 fputs ("\t.global __do_global_ctors\n", asm_out_file);
5923 default_ctor_section_asm_out_constructor (symbol, priority);
5924}
5925
6644435d 5926/* Worker function for TARGET_ASM_DESTRUCTOR. */
5927
9aa7484c 5928static void
206a5129 5929avr_asm_out_dtor (rtx symbol, int priority)
9aa7484c 5930{
5931 fputs ("\t.global __do_global_dtors\n", asm_out_file);
5932 default_dtor_section_asm_out_destructor (symbol, priority);
5933}
5934
6644435d 5935/* Worker function for TARGET_RETURN_IN_MEMORY. */
5936
cfd55026 5937static bool
5938avr_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
5939{
39cc9599 5940 if (TYPE_MODE (type) == BLKmode)
5941 {
5942 HOST_WIDE_INT size = int_size_in_bytes (type);
5943 return (size == -1 || size > 8);
5944 }
5945 else
5946 return false;
cfd55026 5947}
5948
c84f2269 5949#include "gt-avr.h"