]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/avr/avr.c
tm.texi.in (TARGET_RTX_COSTS): Add an opno paramter.
[thirdparty/gcc.git] / gcc / config / avr / avr.c
CommitLineData
90e7678c 1/* Subroutines for insn-output.c for ATMEL AVR micro controllers
5a7e237c 2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008,
68fd7765 3 2009, 2010, 2011 Free Software Foundation, Inc.
92bffc14 4 Contributed by Denis Chertykov (chertykov@gmail.com)
90e7678c 5
7ec022b2 6 This file is part of GCC.
90e7678c 7
7ec022b2 8 GCC is free software; you can redistribute it and/or modify
90e7678c 9 it under the terms of the GNU General Public License as published by
2f83c7d6 10 the Free Software Foundation; either version 3, or (at your option)
90e7678c
DC
11 any later version.
12
7ec022b2 13 GCC is distributed in the hope that it will be useful,
90e7678c
DC
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
2f83c7d6
NC
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
90e7678c
DC
21
22#include "config.h"
b8fa3ed6 23#include "system.h"
4977bab6
ZW
24#include "coretypes.h"
25#include "tm.h"
90e7678c
DC
26#include "rtl.h"
27#include "regs.h"
28#include "hard-reg-set.h"
90e7678c
DC
29#include "insn-config.h"
30#include "conditions.h"
90e7678c 31#include "insn-attr.h"
43ea6502 32#include "insn-codes.h"
90e7678c
DC
33#include "flags.h"
34#include "reload.h"
35#include "tree.h"
3eaf7a3c 36#include "output.h"
90e7678c 37#include "expr.h"
718f9c0f 38#include "diagnostic-core.h"
90e7678c
DC
39#include "obstack.h"
40#include "function.h"
41#include "recog.h"
43ea6502 42#include "optabs.h"
baac771a 43#include "ggc.h"
43ea6502 44#include "langhooks.h"
90e7678c 45#include "tm_p.h"
672a6f42
NB
46#include "target.h"
47#include "target-def.h"
3898bf50 48#include "params.h"
4e63b362 49#include "df.h"
90e7678c 50
3454eb73
DC
51/* Maximal allowed offset for an address in the LD command */
52#define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
90e7678c 53
c5387660 54static void avr_option_override (void);
269e3795
SB
55static int avr_naked_function_p (tree);
56static int interrupt_function_p (tree);
57static int signal_function_p (tree);
96ac4c9b 58static int avr_OS_task_function_p (tree);
9b678d96 59static int avr_OS_main_function_p (tree);
269e3795 60static int avr_regs_to_save (HARD_REG_SET *);
97822902 61static int get_sequence_length (rtx insns);
269e3795
SB
62static int sequent_regs_live (void);
63static const char *ptrreg_to_str (int);
64static const char *cond_string (enum rtx_code);
3f02a5f3 65static int avr_num_arg_regs (enum machine_mode, const_tree);
4fc2b4ff 66
269e3795 67static RTX_CODE compare_condition (rtx insn);
506d7b68 68static rtx avr_legitimize_address (rtx, rtx, enum machine_mode);
269e3795
SB
69static int compare_sign_p (rtx insn);
70static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *);
71static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
44190aed 72static tree avr_handle_fntype_attribute (tree *, tree, tree, int, bool *);
269e3795
SB
73static bool avr_assemble_integer (rtx, unsigned int, int);
74static void avr_file_start (void);
75static void avr_file_end (void);
c6c3dba9 76static bool avr_legitimate_address_p (enum machine_mode, rtx, bool);
4fc2b4ff
AH
77static void avr_asm_function_end_prologue (FILE *);
78static void avr_asm_function_begin_epilogue (FILE *);
6609216e 79static bool avr_cannot_modify_jumps_p (void);
f9f6caf5 80static rtx avr_function_value (const_tree, const_tree, bool);
68fd7765
AS
81static rtx avr_libcall_value (enum machine_mode, const_rtx);
82static bool avr_function_value_regno_p (const unsigned int);
269e3795 83static void avr_insert_attributes (tree, tree *);
d6b5193b 84static void avr_asm_init_sections (void);
269e3795
SB
85static unsigned int avr_section_type_flags (tree, const char *, int);
86
87static void avr_reorg (void);
88static void avr_asm_out_ctor (rtx, int);
89static void avr_asm_out_dtor (rtx, int);
5f892aa0
GJL
90static int avr_register_move_cost (enum machine_mode, reg_class_t, reg_class_t);
91static int avr_memory_move_cost (enum machine_mode, reg_class_t, bool);
68f932c4
RS
92static int avr_operand_rtx_cost (rtx, enum machine_mode, enum rtx_code,
93 int, bool);
94static bool avr_rtx_costs (rtx, int, int, int, int *, bool);
f40751dd 95static int avr_address_cost (rtx, bool);
586de218 96static bool avr_return_in_memory (const_tree, const_tree);
4fc2b4ff 97static struct machine_function * avr_init_machine_status (void);
43ea6502
AS
98static void avr_init_builtins (void);
99static rtx avr_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
1bf29643 100static rtx avr_builtin_setjmp_frame_value (void);
1cf0a7f1 101static bool avr_hard_regno_scratch_ok (unsigned int);
e6ff3083 102static unsigned int avr_case_values_threshold (void);
b52b1749 103static bool avr_frame_pointer_required_p (void);
7b5cbb57 104static bool avr_can_eliminate (const int, const int);
c21136ee 105static bool avr_class_likely_spilled_p (reg_class_t c);
d5cc9181 106static rtx avr_function_arg (cumulative_args_t , enum machine_mode,
733bdfbd 107 const_tree, bool);
d5cc9181 108static void avr_function_arg_advance (cumulative_args_t, enum machine_mode,
733bdfbd 109 const_tree, bool);
980a0ff4 110static bool avr_function_ok_for_sibcall (tree, tree);
516edfdd 111static void avr_asm_named_section (const char *name, unsigned int flags, tree decl);
946c8b23 112static void avr_encode_section_info (tree, rtx, int);
1bf29643 113
2c338472 114/* Allocate registers from r25 to r8 for parameters for function calls. */
90e7678c
DC
115#define FIRST_CUM_REG 26
116
f1c25d3b 117/* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */
baac771a 118static GTY(()) rtx tmp_reg_rtx;
90e7678c 119
f1c25d3b 120/* Zeroed register RTX (gen_rtx_REG (QImode, ZERO_REGNO)) */
baac771a 121static GTY(()) rtx zero_reg_rtx;
6bec29c9 122
90e7678c 123/* AVR register names {"r0", "r1", ..., "r31"} */
27c38fbe 124static const char *const avr_regnames[] = REGISTER_NAMES;
90e7678c 125
92c392e6 126/* Preprocessor macros to define depending on MCU type. */
17fad361 127const char *avr_extra_arch_macro;
92c392e6 128
19298da4
AS
129/* Current architecture. */
130const struct base_arch_s *avr_current_arch;
131
59ab92d2
AS
132/* Current device. */
133const struct mcu_type_s *avr_current_device;
6bec29c9 134
59ab92d2 135section *progmem_section;
90e7678c 136
516edfdd
GJL
137/* To track if code will use .bss and/or .data. */
138bool avr_need_clear_bss_p = false;
139bool avr_need_copy_data_p = false;
140
5a82ecd9
ILT
141/* AVR attributes. */
142static const struct attribute_spec avr_attribute_table[] =
143{
62d784f7
KT
144 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
145 affects_type_identity } */
146 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute,
147 false },
148 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute,
149 false },
150 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute,
151 false },
152 { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute,
153 false },
154 { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute,
155 false },
156 { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute,
157 false },
158 { NULL, 0, 0, false, false, false, NULL, false }
5a82ecd9 159};
672a6f42
NB
160\f
161/* Initialize the GCC target structure. */
301d03af
RS
162#undef TARGET_ASM_ALIGNED_HI_OP
163#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
10252a62
BH
164#undef TARGET_ASM_ALIGNED_SI_OP
165#define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
166#undef TARGET_ASM_UNALIGNED_HI_OP
167#define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
168#undef TARGET_ASM_UNALIGNED_SI_OP
169#define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
301d03af
RS
170#undef TARGET_ASM_INTEGER
171#define TARGET_ASM_INTEGER avr_assemble_integer
1bc7c5b6
ZW
172#undef TARGET_ASM_FILE_START
173#define TARGET_ASM_FILE_START avr_file_start
a5fe455b
ZW
174#undef TARGET_ASM_FILE_END
175#define TARGET_ASM_FILE_END avr_file_end
301d03af 176
4fc2b4ff
AH
177#undef TARGET_ASM_FUNCTION_END_PROLOGUE
178#define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
179#undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
180#define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
68fd7765 181
f9f6caf5
AS
182#undef TARGET_FUNCTION_VALUE
183#define TARGET_FUNCTION_VALUE avr_function_value
68fd7765
AS
184#undef TARGET_LIBCALL_VALUE
185#define TARGET_LIBCALL_VALUE avr_libcall_value
186#undef TARGET_FUNCTION_VALUE_REGNO_P
187#define TARGET_FUNCTION_VALUE_REGNO_P avr_function_value_regno_p
188
91d231cb
JM
189#undef TARGET_ATTRIBUTE_TABLE
190#define TARGET_ATTRIBUTE_TABLE avr_attribute_table
ab5c8549
JJ
191#undef TARGET_ASM_FUNCTION_RODATA_SECTION
192#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
74b66b3c
RH
193#undef TARGET_INSERT_ATTRIBUTES
194#define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
c16e5a35
MM
195#undef TARGET_SECTION_TYPE_FLAGS
196#define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
516edfdd 197
eb1dcdff
GJL
198#undef TARGET_ASM_NAMED_SECTION
199#define TARGET_ASM_NAMED_SECTION avr_asm_named_section
516edfdd
GJL
200#undef TARGET_ASM_INIT_SECTIONS
201#define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
946c8b23
GJL
202#undef TARGET_ENCODE_SECTION_INFO
203#define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
516edfdd 204
5f892aa0
GJL
205#undef TARGET_REGISTER_MOVE_COST
206#define TARGET_REGISTER_MOVE_COST avr_register_move_cost
207#undef TARGET_MEMORY_MOVE_COST
208#define TARGET_MEMORY_MOVE_COST avr_memory_move_cost
3c50106f
RH
209#undef TARGET_RTX_COSTS
210#define TARGET_RTX_COSTS avr_rtx_costs
dcefdf67
RH
211#undef TARGET_ADDRESS_COST
212#define TARGET_ADDRESS_COST avr_address_cost
18dbd950
RS
213#undef TARGET_MACHINE_DEPENDENT_REORG
214#define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
733bdfbd
NF
215#undef TARGET_FUNCTION_ARG
216#define TARGET_FUNCTION_ARG avr_function_arg
217#undef TARGET_FUNCTION_ARG_ADVANCE
218#define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
672a6f42 219
506d7b68
PB
220#undef TARGET_LEGITIMIZE_ADDRESS
221#define TARGET_LEGITIMIZE_ADDRESS avr_legitimize_address
222
b069302c
KH
223#undef TARGET_RETURN_IN_MEMORY
224#define TARGET_RETURN_IN_MEMORY avr_return_in_memory
225
226#undef TARGET_STRICT_ARGUMENT_NAMING
227#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
228
1bf29643
AH
229#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
230#define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value
231
1cf0a7f1
AS
232#undef TARGET_HARD_REGNO_SCRATCH_OK
233#define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
e6ff3083
AS
234#undef TARGET_CASE_VALUES_THRESHOLD
235#define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
1cf0a7f1 236
c6c3dba9
PB
237#undef TARGET_LEGITIMATE_ADDRESS_P
238#define TARGET_LEGITIMATE_ADDRESS_P avr_legitimate_address_p
239
b52b1749
AS
240#undef TARGET_FRAME_POINTER_REQUIRED
241#define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
7b5cbb57
AS
242#undef TARGET_CAN_ELIMINATE
243#define TARGET_CAN_ELIMINATE avr_can_eliminate
b52b1749 244
c21136ee
AS
245#undef TARGET_CLASS_LIKELY_SPILLED_P
246#define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
247
c5387660
JM
248#undef TARGET_OPTION_OVERRIDE
249#define TARGET_OPTION_OVERRIDE avr_option_override
250
6609216e
GJL
251#undef TARGET_CANNOT_MODIFY_JUMPS_P
252#define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p
253
980a0ff4
GJL
254#undef TARGET_FUNCTION_OK_FOR_SIBCALL
255#define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
256
43ea6502
AS
257#undef TARGET_INIT_BUILTINS
258#define TARGET_INIT_BUILTINS avr_init_builtins
259
260#undef TARGET_EXPAND_BUILTIN
261#define TARGET_EXPAND_BUILTIN avr_expand_builtin
262
263
f6897b10 264struct gcc_target targetm = TARGET_INITIALIZER;
672a6f42 265\f
c5387660
JM
266static void
267avr_option_override (void)
90e7678c 268{
6c7ac15d
AS
269 flag_delete_null_pointer_checks = 0;
270
1b916ca6 271 avr_current_device = &avr_mcu_types[avr_mcu_index];
164709cf
AS
272 avr_current_arch = &avr_arch_types[avr_current_device->arch];
273 avr_extra_arch_macro = avr_current_device->macro;
1268b05f 274
baac771a
KH
275 tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO);
276 zero_reg_rtx = gen_rtx_REG (QImode, ZERO_REGNO);
4fc2b4ff
AH
277
278 init_machine_status = avr_init_machine_status;
90e7678c
DC
279}
280
2c338472 281/* return register class from register number. */
90e7678c 282
5a82ecd9 283static const enum reg_class reg_class_tab[]={
90e7678c
DC
284 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
285 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
286 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
287 GENERAL_REGS, /* r0 - r15 */
288 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
289 LD_REGS, /* r16 - 23 */
290 ADDW_REGS,ADDW_REGS, /* r24,r25 */
291 POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
292 POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
293 POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
294 STACK_REG,STACK_REG /* SPL,SPH */
295};
296
4fc2b4ff
AH
297/* Function to set up the backend function structure. */
298
299static struct machine_function *
300avr_init_machine_status (void)
301{
a9429e29 302 return ggc_alloc_cleared_machine_function ();
4fc2b4ff
AH
303}
304
2c338472 305/* Return register class for register R. */
90e7678c
DC
306
307enum reg_class
269e3795 308avr_regno_reg_class (int r)
90e7678c
DC
309{
310 if (r <= 33)
311 return reg_class_tab[r];
312 return ALL_REGS;
313}
314
980a0ff4
GJL
315/* A helper for the subsequent function attribute used to dig for
316 attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
317
318static inline int
319avr_lookup_function_attribute1 (const_tree func, const char *name)
320{
321 if (FUNCTION_DECL == TREE_CODE (func))
322 {
323 if (NULL_TREE != lookup_attribute (name, DECL_ATTRIBUTES (func)))
324 {
325 return true;
326 }
327
328 func = TREE_TYPE (func);
329 }
330
331 gcc_assert (TREE_CODE (func) == FUNCTION_TYPE
332 || TREE_CODE (func) == METHOD_TYPE);
333
334 return NULL_TREE != lookup_attribute (name, TYPE_ATTRIBUTES (func));
335}
336
825dda42 337/* Return nonzero if FUNC is a naked function. */
90e7678c
DC
338
339static int
269e3795 340avr_naked_function_p (tree func)
90e7678c 341{
980a0ff4 342 return avr_lookup_function_attribute1 (func, "naked");
90e7678c
DC
343}
344
345/* Return nonzero if FUNC is an interrupt function as specified
346 by the "interrupt" attribute. */
347
348static int
269e3795 349interrupt_function_p (tree func)
90e7678c 350{
980a0ff4 351 return avr_lookup_function_attribute1 (func, "interrupt");
90e7678c
DC
352}
353
3454eb73 354/* Return nonzero if FUNC is a signal function as specified
90e7678c
DC
355 by the "signal" attribute. */
356
357static int
269e3795 358signal_function_p (tree func)
90e7678c 359{
980a0ff4 360 return avr_lookup_function_attribute1 (func, "signal");
90e7678c
DC
361}
362
96ac4c9b
AS
363/* Return nonzero if FUNC is a OS_task function. */
364
365static int
366avr_OS_task_function_p (tree func)
367{
980a0ff4 368 return avr_lookup_function_attribute1 (func, "OS_task");
96ac4c9b
AS
369}
370
9b678d96
AS
371/* Return nonzero if FUNC is a OS_main function. */
372
373static int
374avr_OS_main_function_p (tree func)
375{
980a0ff4 376 return avr_lookup_function_attribute1 (func, "OS_main");
9b678d96
AS
377}
378
93febe68
MM
379/* Return the number of hard registers to push/pop in the prologue/epilogue
380 of the current function, and optionally store these registers in SET. */
381
382static int
269e3795 383avr_regs_to_save (HARD_REG_SET *set)
93febe68
MM
384{
385 int reg, count;
386 int int_or_sig_p = (interrupt_function_p (current_function_decl)
387 || signal_function_p (current_function_decl));
4c75f709 388
93febe68
MM
389 if (set)
390 CLEAR_HARD_REG_SET (*set);
391 count = 0;
e52b6b63 392
96ac4c9b 393 /* No need to save any registers if the function never returns or
9b678d96 394 is have "OS_task" or "OS_main" attribute. */
96ac4c9b 395 if (TREE_THIS_VOLATILE (current_function_decl)
9b678d96
AS
396 || cfun->machine->is_OS_task
397 || cfun->machine->is_OS_main)
e52b6b63
MM
398 return 0;
399
93febe68
MM
400 for (reg = 0; reg < 32; reg++)
401 {
402 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
403 any global register variables. */
404 if (fixed_regs[reg])
405 continue;
406
9ed74235 407 if ((int_or_sig_p && !current_function_is_leaf && call_used_regs[reg])
6fb5fa3c 408 || (df_regs_ever_live_p (reg)
93febe68
MM
409 && (int_or_sig_p || !call_used_regs[reg])
410 && !(frame_pointer_needed
411 && (reg == REG_Y || reg == (REG_Y+1)))))
412 {
413 if (set)
414 SET_HARD_REG_BIT (*set, reg);
415 count++;
416 }
417 }
418 return count;
419}
420
c21ca196
AS
421/* Return true if register FROM can be eliminated via register TO. */
422
423bool
7b5cbb57 424avr_can_eliminate (const int from, const int to)
c21ca196
AS
425{
426 return ((from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
427 || ((from == FRAME_POINTER_REGNUM
428 || from == FRAME_POINTER_REGNUM + 1)
429 && !frame_pointer_needed));
430}
431
2c338472 432/* Compute offset between arg_pointer and frame_pointer. */
90e7678c
DC
433
434int
c21ca196 435avr_initial_elimination_offset (int from, int to)
90e7678c 436{
3454eb73
DC
437 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
438 return 0;
439 else
440 {
93febe68 441 int offset = frame_pointer_needed ? 2 : 0;
693092fb 442 int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
3454eb73 443
93febe68 444 offset += avr_regs_to_save (NULL);
693092fb 445 return get_frame_size () + (avr_pc_size) + 1 + offset;
90e7678c 446 }
90e7678c
DC
447}
448
1bf29643
AH
449/* Actual start of frame is virtual_stack_vars_rtx this is offset from
450 frame pointer by +STARTING_FRAME_OFFSET.
451 Using saved frame = virtual_stack_vars_rtx - STARTING_FRAME_OFFSET
452 avoids creating add/sub of offset in nonlocal goto and setjmp. */
453
454rtx avr_builtin_setjmp_frame_value (void)
455{
456 return gen_rtx_MINUS (Pmode, virtual_stack_vars_rtx,
457 gen_int_mode (STARTING_FRAME_OFFSET, Pmode));
458}
459
a212a5d4
AH
460/* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3 byte PC).
461 This is return address of function. */
462rtx
3f02a5f3 463avr_return_addr_rtx (int count, rtx tem)
a212a5d4
AH
464{
465 rtx r;
466
467 /* Can only return this functions return address. Others not supported. */
468 if (count)
469 return NULL;
470
471 if (AVR_3_BYTE_PC)
472 {
473 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
474 warning (0, "'builtin_return_address' contains only 2 bytes of address");
475 }
476 else
477 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
478
479 r = gen_rtx_PLUS (Pmode, tem, r);
480 r = gen_frame_mem (Pmode, memory_address (Pmode, r));
481 r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
482 return r;
483}
484
126dbce0
MM
485/* Return 1 if the function epilogue is just a single "ret". */
486
487int
269e3795 488avr_simple_epilogue (void)
126dbce0
MM
489{
490 return (! frame_pointer_needed
491 && get_frame_size () == 0
492 && avr_regs_to_save (NULL) == 0
493 && ! interrupt_function_p (current_function_decl)
494 && ! signal_function_p (current_function_decl)
495 && ! avr_naked_function_p (current_function_decl)
126dbce0
MM
496 && ! TREE_THIS_VOLATILE (current_function_decl));
497}
498
2c338472 499/* This function checks sequence of live registers. */
90e7678c
DC
500
501static int
269e3795 502sequent_regs_live (void)
90e7678c
DC
503{
504 int reg;
505 int live_seq=0;
506 int cur_seq=0;
507
508 for (reg = 0; reg < 18; ++reg)
509 {
510 if (!call_used_regs[reg])
511 {
6fb5fa3c 512 if (df_regs_ever_live_p (reg))
90e7678c
DC
513 {
514 ++live_seq;
515 ++cur_seq;
516 }
517 else
518 cur_seq = 0;
519 }
520 }
521
522 if (!frame_pointer_needed)
523 {
6fb5fa3c 524 if (df_regs_ever_live_p (REG_Y))
90e7678c
DC
525 {
526 ++live_seq;
527 ++cur_seq;
528 }
529 else
530 cur_seq = 0;
531
6fb5fa3c 532 if (df_regs_ever_live_p (REG_Y+1))
90e7678c
DC
533 {
534 ++live_seq;
535 ++cur_seq;
536 }
537 else
538 cur_seq = 0;
539 }
540 else
541 {
542 cur_seq += 2;
543 live_seq += 2;
544 }
545 return (cur_seq == live_seq) ? live_seq : 0;
546}
547
97822902
AS
548/* Obtain the length sequence of insns. */
549
550int
551get_sequence_length (rtx insns)
552{
553 rtx insn;
554 int length;
555
556 for (insn = insns, length = 0; insn; insn = NEXT_INSN (insn))
557 length += get_attr_length (insn);
558
559 return length;
560}
561
bdfe906f
RH
562/* Implement INCOMING_RETURN_ADDR_RTX. */
563
564rtx
565avr_incoming_return_addr_rtx (void)
566{
567 /* The return address is at the top of the stack. Note that the push
568 was via post-decrement, which means the actual address is off by one. */
569 return gen_frame_mem (HImode, plus_constant (stack_pointer_rtx, 1));
570}
571
572/* Helper for expand_prologue. Emit a push of a byte register. */
573
574static void
575emit_push_byte (unsigned regno, bool frame_related_p)
576{
577 rtx mem, reg, insn;
578
579 mem = gen_rtx_POST_DEC (HImode, stack_pointer_rtx);
580 mem = gen_frame_mem (QImode, mem);
581 reg = gen_rtx_REG (QImode, regno);
582
583 insn = emit_insn (gen_rtx_SET (VOIDmode, mem, reg));
584 if (frame_related_p)
585 RTX_FRAME_RELATED_P (insn) = 1;
586
587 cfun->machine->stack_usage++;
588}
589
590
4fc2b4ff 591/* Output function prologue. */
90e7678c 592
4fc2b4ff
AH
593void
594expand_prologue (void)
78cf8279 595{
4fc2b4ff 596 int live_seq;
d6f77715 597 HARD_REG_SET set;
4fc2b4ff
AH
598 int minimize;
599 HOST_WIDE_INT size = get_frame_size();
4fc2b4ff 600 rtx insn;
4fc2b4ff
AH
601
602 /* Init cfun->machine. */
4fc2b4ff
AH
603 cfun->machine->is_naked = avr_naked_function_p (current_function_decl);
604 cfun->machine->is_interrupt = interrupt_function_p (current_function_decl);
605 cfun->machine->is_signal = signal_function_p (current_function_decl);
96ac4c9b 606 cfun->machine->is_OS_task = avr_OS_task_function_p (current_function_decl);
9b678d96 607 cfun->machine->is_OS_main = avr_OS_main_function_p (current_function_decl);
a212a5d4 608 cfun->machine->stack_usage = 0;
4fc2b4ff
AH
609
610 /* Prologue: naked. */
611 if (cfun->machine->is_naked)
78cf8279 612 {
4fc2b4ff 613 return;
78cf8279 614 }
78cf8279 615
d6f77715 616 avr_regs_to_save (&set);
4fc2b4ff
AH
617 live_seq = sequent_regs_live ();
618 minimize = (TARGET_CALL_PROLOGUES
0d40cc60
AS
619 && !cfun->machine->is_interrupt
620 && !cfun->machine->is_signal
621 && !cfun->machine->is_OS_task
9b678d96 622 && !cfun->machine->is_OS_main
4fc2b4ff 623 && live_seq);
78cf8279 624
4fc2b4ff 625 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
78cf8279 626 {
bdfe906f 627 /* Enable interrupts. */
4fc2b4ff 628 if (cfun->machine->is_interrupt)
bdfe906f 629 emit_insn (gen_enable_interrupt ());
4fc2b4ff
AH
630
631 /* Push zero reg. */
bdfe906f 632 emit_push_byte (ZERO_REGNO, true);
4fc2b4ff
AH
633
634 /* Push tmp reg. */
bdfe906f 635 emit_push_byte (TMP_REGNO, true);
4fc2b4ff
AH
636
637 /* Push SREG. */
bdfe906f
RH
638 /* ??? There's no dwarf2 column reserved for SREG. */
639 emit_move_insn (tmp_reg_rtx, gen_rtx_MEM (QImode, GEN_INT (SREG_ADDR)));
640 emit_push_byte (TMP_REGNO, false);
d6f77715
AS
641
642 /* Push RAMPZ. */
bdfe906f
RH
643 /* ??? There's no dwarf2 column reserved for RAMPZ. */
644 if (AVR_HAVE_RAMPZ
645 && TEST_HARD_REG_BIT (set, REG_Z)
646 && TEST_HARD_REG_BIT (set, REG_Z + 1))
d6f77715 647 {
bdfe906f
RH
648 emit_move_insn (tmp_reg_rtx,
649 gen_rtx_MEM (QImode, GEN_INT (RAMPZ_ADDR)));
650 emit_push_byte (TMP_REGNO, false);
d6f77715
AS
651 }
652
4fc2b4ff 653 /* Clear zero reg. */
bdfe906f 654 emit_move_insn (zero_reg_rtx, const0_rtx);
78cf8279 655
4fc2b4ff 656 /* Prevent any attempt to delete the setting of ZERO_REG! */
c41c1387 657 emit_use (zero_reg_rtx);
78cf8279 658 }
4d492420
TG
659 if (minimize && (frame_pointer_needed
660 || (AVR_2_BYTE_PC && live_seq > 6)
661 || live_seq > 7))
78cf8279 662 {
bdfe906f
RH
663 int first_reg, reg, offset;
664
665 emit_move_insn (gen_rtx_REG (HImode, REG_X),
666 gen_int_mode (size, HImode));
4e63b362 667
bdfe906f
RH
668 insn = emit_insn (gen_call_prologue_saves
669 (gen_int_mode (live_seq, HImode),
670 gen_int_mode (size + live_seq, HImode)));
4fc2b4ff 671 RTX_FRAME_RELATED_P (insn) = 1;
bdfe906f
RH
672
673 /* Describe the effect of the unspec_volatile call to prologue_saves.
674 Note that this formulation assumes that add_reg_note pushes the
675 notes to the front. Thus we build them in the reverse order of
676 how we want dwarf2out to process them. */
677
678 /* The function does always set frame_pointer_rtx, but whether that
679 is going to be permanent in the function is frame_pointer_needed. */
680 add_reg_note (insn, REG_CFA_ADJUST_CFA,
681 gen_rtx_SET (VOIDmode,
682 (frame_pointer_needed
683 ? frame_pointer_rtx : stack_pointer_rtx),
684 plus_constant (stack_pointer_rtx,
685 -(size + live_seq))));
686
687 /* Note that live_seq always contains r28+r29, but the other
688 registers to be saved are all below 18. */
689 first_reg = 18 - (live_seq - 2);
690
691 for (reg = 29, offset = -live_seq + 1;
692 reg >= first_reg;
693 reg = (reg == 28 ? 17 : reg - 1), ++offset)
694 {
695 rtx m, r;
696
697 m = gen_rtx_MEM (QImode, plus_constant (stack_pointer_rtx, offset));
698 r = gen_rtx_REG (QImode, reg);
699 add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (VOIDmode, m, r));
700 }
701
a212a5d4 702 cfun->machine->stack_usage += size + live_seq;
78cf8279 703 }
4fc2b4ff 704 else
78cf8279 705 {
4fc2b4ff
AH
706 int reg;
707 for (reg = 0; reg < 32; ++reg)
bdfe906f
RH
708 if (TEST_HARD_REG_BIT (set, reg))
709 emit_push_byte (reg, true);
710
4fc2b4ff
AH
711 if (frame_pointer_needed)
712 {
9b678d96 713 if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
0d40cc60 714 {
bdfe906f
RH
715 /* Push frame pointer. Always be consistent about the
716 ordering of pushes -- epilogue_restores expects the
717 register pair to be pushed low byte first. */
718 emit_push_byte (REG_Y, true);
719 emit_push_byte (REG_Y + 1, true);
0d40cc60
AS
720 }
721
4fc2b4ff
AH
722 if (!size)
723 {
724 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
725 RTX_FRAME_RELATED_P (insn) = 1;
726 }
727 else
728 {
729 /* Creating a frame can be done by direct manipulation of the
730 stack or via the frame pointer. These two methods are:
731 fp=sp
732 fp-=size
733 sp=fp
734 OR
735 sp-=size
736 fp=sp
737 the optimum method depends on function type, stack and frame size.
738 To avoid a complex logic, both methods are tested and shortest
739 is selected. */
740 rtx myfp;
97822902 741 rtx fp_plus_insns;
97822902 742
164709cf 743 if (AVR_HAVE_8BIT_SP)
4fc2b4ff 744 {
bdfe906f
RH
745 /* The high byte (r29) doesn't change. Prefer 'subi'
746 (1 cycle) over 'sbiw' (2 cycles, same size). */
747 myfp = gen_rtx_REG (QImode, FRAME_POINTER_REGNUM);
4fc2b4ff
AH
748 }
749 else
750 {
751 /* Normal sized addition. */
752 myfp = frame_pointer_rtx;
753 }
97822902
AS
754
755 /* Method 1-Adjust frame pointer. */
756 start_sequence ();
757
bdfe906f
RH
758 /* Normally the dwarf2out frame-related-expr interpreter does
759 not expect to have the CFA change once the frame pointer is
760 set up. Thus we avoid marking the move insn below and
761 instead indicate that the entire operation is complete after
762 the frame pointer subtraction is done. */
97822902 763
bdfe906f 764 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
97822902 765
bdfe906f
RH
766 insn = emit_move_insn (myfp, plus_constant (myfp, -size));
767 RTX_FRAME_RELATED_P (insn) = 1;
768 add_reg_note (insn, REG_CFA_ADJUST_CFA,
769 gen_rtx_SET (VOIDmode, frame_pointer_rtx,
770 plus_constant (stack_pointer_rtx,
771 -size)));
772
773 /* Copy to stack pointer. Note that since we've already
774 changed the CFA to the frame pointer this operation
775 need not be annotated at all. */
164709cf 776 if (AVR_HAVE_8BIT_SP)
794cb45e 777 {
bdfe906f 778 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
794cb45e
AS
779 }
780 else if (TARGET_NO_INTERRUPTS
781 || cfun->machine->is_signal
782 || cfun->machine->is_OS_main)
783 {
bdfe906f
RH
784 emit_insn (gen_movhi_sp_r_irq_off (stack_pointer_rtx,
785 frame_pointer_rtx));
794cb45e
AS
786 }
787 else if (cfun->machine->is_interrupt)
788 {
bdfe906f
RH
789 emit_insn (gen_movhi_sp_r_irq_on (stack_pointer_rtx,
790 frame_pointer_rtx));
794cb45e
AS
791 }
792 else
793 {
bdfe906f 794 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
794cb45e 795 }
97822902
AS
796
797 fp_plus_insns = get_insns ();
798 end_sequence ();
799
4fc2b4ff 800 /* Method 2-Adjust Stack pointer. */
4fc2b4ff
AH
801 if (size <= 6)
802 {
bdfe906f
RH
803 rtx sp_plus_insns;
804
97822902
AS
805 start_sequence ();
806
bdfe906f
RH
807 insn = plus_constant (stack_pointer_rtx, -size);
808 insn = emit_move_insn (stack_pointer_rtx, insn);
97822902
AS
809 RTX_FRAME_RELATED_P (insn) = 1;
810
bdfe906f 811 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
97822902
AS
812 RTX_FRAME_RELATED_P (insn) = 1;
813
814 sp_plus_insns = get_insns ();
815 end_sequence ();
97822902 816
bdfe906f
RH
817 /* Use shortest method. */
818 if (get_sequence_length (sp_plus_insns)
819 < get_sequence_length (fp_plus_insns))
820 emit_insn (sp_plus_insns);
821 else
822 emit_insn (fp_plus_insns);
823 }
824 else
97822902 825 emit_insn (fp_plus_insns);
bdfe906f 826
a212a5d4 827 cfun->machine->stack_usage += size;
4fc2b4ff
AH
828 }
829 }
78cf8279 830 }
247df3b6 831
a11e0df4 832 if (flag_stack_usage_info)
247df3b6 833 current_function_static_stack_size = cfun->machine->stack_usage;
78cf8279
MM
834}
835
4fc2b4ff 836/* Output summary at end of function prologue. */
90e7678c 837
08c148a8 838static void
4fc2b4ff 839avr_asm_function_end_prologue (FILE *file)
90e7678c 840{
4fc2b4ff 841 if (cfun->machine->is_naked)
90e7678c 842 {
e52b6b63 843 fputs ("/* prologue: naked */\n", file);
90e7678c 844 }
4fc2b4ff 845 else
90e7678c 846 {
4fc2b4ff
AH
847 if (cfun->machine->is_interrupt)
848 {
849 fputs ("/* prologue: Interrupt */\n", file);
850 }
851 else if (cfun->machine->is_signal)
852 {
853 fputs ("/* prologue: Signal */\n", file);
854 }
90e7678c 855 else
4fc2b4ff 856 fputs ("/* prologue: function */\n", file);
90e7678c 857 }
4fc2b4ff
AH
858 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
859 get_frame_size());
a212a5d4
AH
860 fprintf (file, "/* stack size = %d */\n",
861 cfun->machine->stack_usage);
862 /* Create symbol stack offset here so all functions have it. Add 1 to stack
863 usage for offset so that SP + .L__stack_offset = return address. */
864 fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
4fc2b4ff 865}
93febe68 866
908c8c7e 867
4fc2b4ff 868/* Implement EPILOGUE_USES. */
e52b6b63 869
4fc2b4ff
AH
870int
871avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
872{
873 if (reload_completed
874 && cfun->machine
875 && (cfun->machine->is_interrupt || cfun->machine->is_signal))
876 return 1;
877 return 0;
90e7678c
DC
878}
879
bdfe906f
RH
880/* Helper for expand_epilogue. Emit a pop of a byte register. */
881
882static void
883emit_pop_byte (unsigned regno)
884{
885 rtx mem, reg;
886
887 mem = gen_rtx_PRE_INC (HImode, stack_pointer_rtx);
888 mem = gen_frame_mem (QImode, mem);
889 reg = gen_rtx_REG (QImode, regno);
890
891 emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
892}
893
4fc2b4ff 894/* Output RTL epilogue. */
90e7678c 895
4fc2b4ff 896void
980a0ff4 897expand_epilogue (bool sibcall_p)
90e7678c
DC
898{
899 int reg;
90e7678c 900 int live_seq;
d6f77715 901 HARD_REG_SET set;
90e7678c 902 int minimize;
4fc2b4ff 903 HOST_WIDE_INT size = get_frame_size();
4fc2b4ff
AH
904
905 /* epilogue: naked */
906 if (cfun->machine->is_naked)
e52b6b63 907 {
980a0ff4
GJL
908 gcc_assert (!sibcall_p);
909
8819eb78 910 emit_jump_insn (gen_return ());
4fc2b4ff 911 return;
90e7678c
DC
912 }
913
d6f77715 914 avr_regs_to_save (&set);
90e7678c
DC
915 live_seq = sequent_regs_live ();
916 minimize = (TARGET_CALL_PROLOGUES
0d40cc60
AS
917 && !cfun->machine->is_interrupt
918 && !cfun->machine->is_signal
919 && !cfun->machine->is_OS_task
9b678d96 920 && !cfun->machine->is_OS_main
4fc2b4ff 921 && live_seq);
90e7678c 922
96ac4c9b 923 if (minimize && (frame_pointer_needed || live_seq > 4))
90e7678c 924 {
90e7678c
DC
925 if (frame_pointer_needed)
926 {
4fc2b4ff 927 /* Get rid of frame. */
8819eb78
AS
928 emit_move_insn(frame_pointer_rtx,
929 gen_rtx_PLUS (HImode, frame_pointer_rtx,
930 gen_int_mode (size, HImode)));
90e7678c
DC
931 }
932 else
933 {
8819eb78 934 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
90e7678c 935 }
4fc2b4ff 936
8819eb78 937 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
90e7678c
DC
938 }
939 else
940 {
941 if (frame_pointer_needed)
942 {
943 if (size)
944 {
4fc2b4ff 945 /* Try two methods to adjust stack and select shortest. */
97822902
AS
946 rtx myfp;
947 rtx fp_plus_insns;
bdfe906f 948
164709cf 949 if (AVR_HAVE_8BIT_SP)
97822902
AS
950 {
951 /* The high byte (r29) doesn't change - prefer 'subi'
952 (1 cycle) over 'sbiw' (2 cycles, same size). */
bdfe906f 953 myfp = gen_rtx_REG (QImode, FRAME_POINTER_REGNUM);
97822902
AS
954 }
955 else
956 {
957 /* Normal sized addition. */
958 myfp = frame_pointer_rtx;
959 }
960
4fc2b4ff 961 /* Method 1-Adjust frame pointer. */
97822902
AS
962 start_sequence ();
963
bdfe906f 964 emit_move_insn (myfp, plus_constant (myfp, size));
97822902
AS
965
966 /* Copy to stack pointer. */
164709cf 967 if (AVR_HAVE_8BIT_SP)
794cb45e
AS
968 {
969 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
970 }
971 else if (TARGET_NO_INTERRUPTS
972 || cfun->machine->is_signal)
973 {
974 emit_insn (gen_movhi_sp_r_irq_off (stack_pointer_rtx,
975 frame_pointer_rtx));
976 }
977 else if (cfun->machine->is_interrupt)
978 {
979 emit_insn (gen_movhi_sp_r_irq_on (stack_pointer_rtx,
980 frame_pointer_rtx));
981 }
982 else
983 {
984 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
985 }
97822902
AS
986
987 fp_plus_insns = get_insns ();
988 end_sequence ();
989
4fc2b4ff 990 /* Method 2-Adjust Stack pointer. */
4fc2b4ff
AH
991 if (size <= 5)
992 {
bdfe906f
RH
993 rtx sp_plus_insns;
994
97822902
AS
995 start_sequence ();
996
997 emit_move_insn (stack_pointer_rtx,
bdfe906f 998 plus_constant (stack_pointer_rtx, size));
97822902
AS
999
1000 sp_plus_insns = get_insns ();
1001 end_sequence ();
97822902 1002
bdfe906f
RH
1003 /* Use shortest method. */
1004 if (get_sequence_length (sp_plus_insns)
1005 < get_sequence_length (fp_plus_insns))
1006 emit_insn (sp_plus_insns);
1007 else
1008 emit_insn (fp_plus_insns);
1009 }
1010 else
97822902 1011 emit_insn (fp_plus_insns);
4fc2b4ff 1012 }
9b678d96 1013 if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
0d40cc60 1014 {
bdfe906f
RH
1015 /* Restore previous frame_pointer. See expand_prologue for
1016 rationale for not using pophi. */
1017 emit_pop_byte (REG_Y + 1);
1018 emit_pop_byte (REG_Y);
0d40cc60 1019 }
90e7678c 1020 }
bdfe906f 1021
4fc2b4ff 1022 /* Restore used registers. */
90e7678c 1023 for (reg = 31; reg >= 0; --reg)
bdfe906f
RH
1024 if (TEST_HARD_REG_BIT (set, reg))
1025 emit_pop_byte (reg);
1026
4fc2b4ff
AH
1027 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1028 {
d6f77715 1029 /* Restore RAMPZ using tmp reg as scratch. */
bdfe906f
RH
1030 if (AVR_HAVE_RAMPZ
1031 && TEST_HARD_REG_BIT (set, REG_Z)
1032 && TEST_HARD_REG_BIT (set, REG_Z + 1))
d6f77715 1033 {
bdfe906f
RH
1034 emit_pop_byte (TMP_REGNO);
1035 emit_move_insn (gen_rtx_MEM (QImode, GEN_INT (RAMPZ_ADDR)),
d6f77715
AS
1036 tmp_reg_rtx);
1037 }
93febe68 1038
4fc2b4ff 1039 /* Restore SREG using tmp reg as scratch. */
bdfe906f 1040 emit_pop_byte (TMP_REGNO);
4fc2b4ff 1041
bdfe906f 1042 emit_move_insn (gen_rtx_MEM (QImode, GEN_INT (SREG_ADDR)),
8819eb78 1043 tmp_reg_rtx);
4fc2b4ff
AH
1044
1045 /* Restore tmp REG. */
bdfe906f 1046 emit_pop_byte (TMP_REGNO);
4fc2b4ff
AH
1047
1048 /* Restore zero REG. */
bdfe906f 1049 emit_pop_byte (ZERO_REGNO);
4fc2b4ff 1050 }
e52b6b63 1051
980a0ff4
GJL
1052 if (!sibcall_p)
1053 emit_jump_insn (gen_return ());
4fc2b4ff 1054 }
90e7678c
DC
1055}
1056
4fc2b4ff
AH
1057/* Output summary messages at beginning of function epilogue. */
1058
1059static void
1060avr_asm_function_begin_epilogue (FILE *file)
1061{
1062 fprintf (file, "/* epilogue start */\n");
1063}
90e7678c 1064
6609216e
GJL
1065
1066/* Implement TARGET_CANNOT_MODITY_JUMPS_P */
1067
1068static bool
1069avr_cannot_modify_jumps_p (void)
1070{
1071
1072 /* Naked Functions must not have any instructions after
1073 their epilogue, see PR42240 */
1074
1075 if (reload_completed
1076 && cfun->machine
1077 && cfun->machine->is_naked)
1078 {
1079 return true;
1080 }
1081
1082 return false;
1083}
1084
1085
90e7678c
DC
1086/* Return nonzero if X (an RTX) is a legitimate memory address on the target
1087 machine for a memory operand of mode MODE. */
1088
c6c3dba9
PB
1089bool
1090avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
90e7678c 1091{
48ccfb40
DC
1092 enum reg_class r = NO_REGS;
1093
90e7678c
DC
1094 if (TARGET_ALL_DEBUG)
1095 {
1096 fprintf (stderr, "mode: (%s) %s %s %s %s:",
1097 GET_MODE_NAME(mode),
1098 strict ? "(strict)": "",
1099 reload_completed ? "(reload_completed)": "",
1100 reload_in_progress ? "(reload_in_progress)": "",
1101 reg_renumber ? "(reg_renumber)" : "");
1102 if (GET_CODE (x) == PLUS
1103 && REG_P (XEXP (x, 0))
1104 && GET_CODE (XEXP (x, 1)) == CONST_INT
1105 && INTVAL (XEXP (x, 1)) >= 0
3454eb73 1106 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
90e7678c
DC
1107 && reg_renumber
1108 )
1109 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
1110 true_regnum (XEXP (x, 0)));
1111 debug_rtx (x);
1112 }
3e4f8484 1113
90e7678c
DC
1114 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
1115 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
48ccfb40 1116 r = POINTER_REGS;
90e7678c 1117 else if (CONSTANT_ADDRESS_P (x))
48ccfb40 1118 r = ALL_REGS;
90e7678c
DC
1119 else if (GET_CODE (x) == PLUS
1120 && REG_P (XEXP (x, 0))
1121 && GET_CODE (XEXP (x, 1)) == CONST_INT
1122 && INTVAL (XEXP (x, 1)) >= 0)
1123 {
3454eb73 1124 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
90e7678c
DC
1125 if (fit)
1126 {
1127 if (! strict
9215065f 1128 || REGNO (XEXP (x,0)) == REG_X
6bec29c9
DC
1129 || REGNO (XEXP (x,0)) == REG_Y
1130 || REGNO (XEXP (x,0)) == REG_Z)
48ccfb40 1131 r = BASE_POINTER_REGS;
90e7678c
DC
1132 if (XEXP (x,0) == frame_pointer_rtx
1133 || XEXP (x,0) == arg_pointer_rtx)
48ccfb40 1134 r = BASE_POINTER_REGS;
90e7678c
DC
1135 }
1136 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
48ccfb40 1137 r = POINTER_Y_REGS;
90e7678c
DC
1138 }
1139 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
1140 && REG_P (XEXP (x, 0))
1141 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
1142 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
1143 {
48ccfb40 1144 r = POINTER_REGS;
90e7678c
DC
1145 }
1146 if (TARGET_ALL_DEBUG)
1147 {
89a0b917 1148 fprintf (stderr, " ret = %c\n", r + '0');
90e7678c 1149 }
48ccfb40 1150 return r == NO_REGS ? 0 : (int)r;
90e7678c
DC
1151}
1152
1153/* Attempts to replace X with a valid
1154 memory address for an operand of mode MODE */
1155
1156rtx
506d7b68 1157avr_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
90e7678c
DC
1158{
1159 x = oldx;
1160 if (TARGET_ALL_DEBUG)
1161 {
1162 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
1163 debug_rtx (oldx);
1164 }
1165
1166 if (GET_CODE (oldx) == PLUS
1167 && REG_P (XEXP (oldx,0)))
1168 {
1169 if (REG_P (XEXP (oldx,1)))
1170 x = force_reg (GET_MODE (oldx), oldx);
1171 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
1172 {
1173 int offs = INTVAL (XEXP (oldx,1));
1174 if (frame_pointer_rtx != XEXP (oldx,0))
3454eb73 1175 if (offs > MAX_LD_OFFSET (mode))
90e7678c
DC
1176 {
1177 if (TARGET_ALL_DEBUG)
1178 fprintf (stderr, "force_reg (big offset)\n");
1179 x = force_reg (GET_MODE (oldx), oldx);
1180 }
1181 }
1182 }
1183 return x;
1184}
1185
1186
1e6a67d1
GJL
1187/* Helper function to print assembler resp. track instruction
1188 sequence lengths.
1189
1190 If PLEN == NULL:
1191 Output assembler code from template TPL with operands supplied
1192 by OPERANDS. This is just forwarding to output_asm_insn.
1193
1194 If PLEN != NULL:
1195 Add N_WORDS to *PLEN.
1196 Don't output anything.
1197*/
1198
1199static void
1200avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
1201{
1202 if (NULL == plen)
1203 {
1204 output_asm_insn (tpl, operands);
1205 }
1206 else
1207 {
1208 *plen += n_words;
1209 }
1210}
1211
1212
2c338472 1213/* Return a pointer register name as a string. */
90e7678c 1214
5fecfd8d 1215static const char *
269e3795 1216ptrreg_to_str (int regno)
90e7678c
DC
1217{
1218 switch (regno)
1219 {
1220 case REG_X: return "X";
1221 case REG_Y: return "Y";
1222 case REG_Z: return "Z";
1223 default:
3639b3fa 1224 output_operand_lossage ("address operand requires constraint for X, Y, or Z register");
90e7678c
DC
1225 }
1226 return NULL;
1227}
1228
1229/* Return the condition name as a string.
1230 Used in conditional jump constructing */
1231
5fecfd8d 1232static const char *
269e3795 1233cond_string (enum rtx_code code)
90e7678c
DC
1234{
1235 switch (code)
1236 {
1237 case NE:
1238 return "ne";
1239 case EQ:
1240 return "eq";
1241 case GE:
1242 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1243 return "pl";
1244 else
1245 return "ge";
90e7678c
DC
1246 case LT:
1247 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1248 return "mi";
1249 else
1250 return "lt";
1251 case GEU:
1252 return "sh";
90e7678c
DC
1253 case LTU:
1254 return "lo";
1255 default:
25b9575b 1256 gcc_unreachable ();
90e7678c
DC
1257 }
1258}
1259
2c338472 1260/* Output ADDR to FILE as address. */
90e7678c
DC
1261
1262void
269e3795 1263print_operand_address (FILE *file, rtx addr)
90e7678c
DC
1264{
1265 switch (GET_CODE (addr))
1266 {
1267 case REG:
1268 fprintf (file, ptrreg_to_str (REGNO (addr)));
1269 break;
1270
1271 case PRE_DEC:
1272 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1273 break;
1274
1275 case POST_INC:
1276 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1277 break;
1278
1279 default:
1280 if (CONSTANT_ADDRESS_P (addr)
846428f1 1281 && text_segment_operand (addr, VOIDmode))
90e7678c 1282 {
f64c36ba
EB
1283 rtx x = addr;
1284 if (GET_CODE (x) == CONST)
1285 x = XEXP (x, 0);
846428f1
AH
1286 if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x,1)) == CONST_INT)
1287 {
1288 /* Assembler gs() will implant word address. Make offset
1289 a byte offset inside gs() for assembler. This is
1290 needed because the more logical (constant+gs(sym)) is not
1291 accepted by gas. For 128K and lower devices this is ok. For
1292 large devices it will create a Trampoline to offset from symbol
1293 which may not be what the user really wanted. */
1294 fprintf (file, "gs(");
1295 output_addr_const (file, XEXP (x,0));
1296 fprintf (file,"+" HOST_WIDE_INT_PRINT_DEC ")", 2 * INTVAL (XEXP (x,1)));
1297 if (AVR_3_BYTE_PC)
d8a07487 1298 if (warning (0, "pointer offset from symbol maybe incorrect"))
846428f1
AH
1299 {
1300 output_addr_const (stderr, addr);
1301 fprintf(stderr,"\n");
1302 }
1303 }
1304 else
1305 {
1306 fprintf (file, "gs(");
1307 output_addr_const (file, addr);
1308 fprintf (file, ")");
1309 }
90e7678c
DC
1310 }
1311 else
1312 output_addr_const (file, addr);
1313 }
1314}
1315
1316
2c338472 1317/* Output X as assembler operand to file FILE. */
90e7678c
DC
1318
1319void
269e3795 1320print_operand (FILE *file, rtx x, int code)
90e7678c
DC
1321{
1322 int abcd = 0;
1323
1324 if (code >= 'A' && code <= 'D')
1325 abcd = code - 'A';
1326
cf14485b
MM
1327 if (code == '~')
1328 {
5dc77808 1329 if (!AVR_HAVE_JMP_CALL)
cf14485b
MM
1330 fputc ('r', file);
1331 }
693092fb
BH
1332 else if (code == '!')
1333 {
1334 if (AVR_HAVE_EIJMP_EICALL)
1335 fputc ('e', file);
1336 }
cf14485b 1337 else if (REG_P (x))
90e7678c
DC
1338 {
1339 if (x == zero_reg_rtx)
cf14485b 1340 fprintf (file, "__zero_reg__");
90e7678c
DC
1341 else
1342 fprintf (file, reg_names[true_regnum (x) + abcd]);
1343 }
1344 else if (GET_CODE (x) == CONST_INT)
7e53359d 1345 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd);
90e7678c
DC
1346 else if (GET_CODE (x) == MEM)
1347 {
1348 rtx addr = XEXP (x,0);
846428f1 1349 if (code == 'm')
90e7678c 1350 {
846428f1
AH
1351 if (!CONSTANT_P (addr))
1352 fatal_insn ("bad address, not a constant):", addr);
1353 /* Assembler template with m-code is data - not progmem section */
1354 if (text_segment_operand (addr, VOIDmode))
1355 if (warning ( 0, "accessing data memory with program memory address"))
1356 {
1357 output_addr_const (stderr, addr);
1358 fprintf(stderr,"\n");
1359 }
1360 output_addr_const (file, addr);
90e7678c 1361 }
cf14485b
MM
1362 else if (code == 'o')
1363 {
1364 if (GET_CODE (addr) != PLUS)
c725bd79 1365 fatal_insn ("bad address, not (reg+disp):", addr);
cf14485b
MM
1366
1367 print_operand (file, XEXP (addr, 1), 0);
1368 }
a6990185
MM
1369 else if (code == 'p' || code == 'r')
1370 {
1371 if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
1372 fatal_insn ("bad address, not post_inc or pre_dec:", addr);
1373
1374 if (code == 'p')
1375 print_operand_address (file, XEXP (addr, 0)); /* X, Y, Z */
1376 else
1377 print_operand (file, XEXP (addr, 0), 0); /* r26, r28, r30 */
1378 }
90e7678c
DC
1379 else if (GET_CODE (addr) == PLUS)
1380 {
1381 print_operand_address (file, XEXP (addr,0));
1382 if (REGNO (XEXP (addr, 0)) == REG_X)
c725bd79 1383 fatal_insn ("internal compiler error. Bad address:"
90e7678c
DC
1384 ,addr);
1385 fputc ('+', file);
1386 print_operand (file, XEXP (addr,1), code);
1387 }
1388 else
1389 print_operand_address (file, addr);
1390 }
846428f1
AH
1391 else if (code == 'x')
1392 {
1393 /* Constant progmem address - like used in jmp or call */
1394 if (0 == text_segment_operand (x, VOIDmode))
1395 if (warning ( 0, "accessing program memory with data memory address"))
1396 {
1397 output_addr_const (stderr, x);
1398 fprintf(stderr,"\n");
1399 }
1400 /* Use normal symbol for direct address no linker trampoline needed */
1401 output_addr_const (file, x);
1402 }
90e7678c
DC
1403 else if (GET_CODE (x) == CONST_DOUBLE)
1404 {
1405 long val;
1406 REAL_VALUE_TYPE rv;
1407 if (GET_MODE (x) != SFmode)
c725bd79 1408 fatal_insn ("internal compiler error. Unknown mode:", x);
90e7678c
DC
1409 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1410 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
761c70aa 1411 fprintf (file, "0x%lx", val);
90e7678c
DC
1412 }
1413 else if (code == 'j')
761c70aa 1414 fputs (cond_string (GET_CODE (x)), file);
90e7678c 1415 else if (code == 'k')
761c70aa 1416 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
90e7678c 1417 else
cdd9eb8f 1418 print_operand_address (file, x);
90e7678c
DC
1419}
1420
90e7678c
DC
1421/* Update the condition code in the INSN. */
1422
1423void
269e3795 1424notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
90e7678c 1425{
3454eb73
DC
1426 rtx set;
1427
90e7678c
DC
1428 switch (get_attr_cc (insn))
1429 {
1430 case CC_NONE:
1431 /* Insn does not affect CC at all. */
1432 break;
1433
1434 case CC_SET_N:
1435 CC_STATUS_INIT;
1436 break;
1437
1438 case CC_SET_ZN:
3454eb73
DC
1439 set = single_set (insn);
1440 CC_STATUS_INIT;
1441 if (set)
1442 {
1443 cc_status.flags |= CC_NO_OVERFLOW;
1444 cc_status.value1 = SET_DEST (set);
1445 }
90e7678c
DC
1446 break;
1447
1448 case CC_SET_CZN:
1449 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1450 The V flag may or may not be known but that's ok because
1451 alter_cond will change tests to use EQ/NE. */
3454eb73
DC
1452 set = single_set (insn);
1453 CC_STATUS_INIT;
1454 if (set)
1455 {
1456 cc_status.value1 = SET_DEST (set);
1457 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1458 }
90e7678c
DC
1459 break;
1460
1461 case CC_COMPARE:
3454eb73
DC
1462 set = single_set (insn);
1463 CC_STATUS_INIT;
1464 if (set)
1465 cc_status.value1 = SET_SRC (set);
90e7678c 1466 break;
3454eb73 1467
90e7678c
DC
1468 case CC_CLOBBER:
1469 /* Insn doesn't leave CC in a usable state. */
1470 CC_STATUS_INIT;
3454eb73
DC
1471
1472 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1473 set = single_set (insn);
1474 if (set)
1475 {
1476 rtx src = SET_SRC (set);
1477
1478 if (GET_CODE (src) == ASHIFTRT
1479 && GET_MODE (src) == QImode)
1480 {
1481 rtx x = XEXP (src, 1);
1482
7e4ec472
GJL
1483 if (CONST_INT_P (x)
1484 && IN_RANGE (INTVAL (x), 1, 5))
3454eb73
DC
1485 {
1486 cc_status.value1 = SET_DEST (set);
1487 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1488 }
1489 }
1490 }
90e7678c
DC
1491 break;
1492 }
1493}
1494
90e7678c
DC
1495/* Choose mode for jump insn:
1496 1 - relative jump in range -63 <= x <= 62 ;
1497 2 - relative jump in range -2046 <= x <= 2045 ;
1498 3 - absolute jump (only for ATmega[16]03). */
1499
1500int
269e3795 1501avr_jump_mode (rtx x, rtx insn)
90e7678c 1502{
5a82ecd9 1503 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
9d98a694
AO
1504 ? XEXP (x, 0) : x));
1505 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
90e7678c
DC
1506 int jump_distance = cur_addr - dest_addr;
1507
1508 if (-63 <= jump_distance && jump_distance <= 62)
1509 return 1;
1510 else if (-2046 <= jump_distance && jump_distance <= 2045)
1511 return 2;
5dc77808 1512 else if (AVR_HAVE_JMP_CALL)
90e7678c
DC
1513 return 3;
1514
1515 return 2;
1516}
1517
56b871c1
DC
1518/* return an AVR condition jump commands.
1519 X is a comparison RTX.
1520 LEN is a number returned by avr_jump_mode function.
1521 if REVERSE nonzero then condition code in X must be reversed. */
90e7678c 1522
5fecfd8d 1523const char *
269e3795 1524ret_cond_branch (rtx x, int len, int reverse)
90e7678c 1525{
56b871c1
DC
1526 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1527
90e7678c
DC
1528 switch (cond)
1529 {
1530 case GT:
1531 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
13e8651c 1532 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
90e7678c 1533 AS1 (brpl,%0)) :
13e8651c
TR
1534 len == 2 ? (AS1 (breq,.+4) CR_TAB
1535 AS1 (brmi,.+2) CR_TAB
90e7678c 1536 AS1 (rjmp,%0)) :
13e8651c
TR
1537 (AS1 (breq,.+6) CR_TAB
1538 AS1 (brmi,.+4) CR_TAB
90e7678c
DC
1539 AS1 (jmp,%0)));
1540
1541 else
13e8651c 1542 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
90e7678c 1543 AS1 (brge,%0)) :
13e8651c
TR
1544 len == 2 ? (AS1 (breq,.+4) CR_TAB
1545 AS1 (brlt,.+2) CR_TAB
90e7678c 1546 AS1 (rjmp,%0)) :
13e8651c
TR
1547 (AS1 (breq,.+6) CR_TAB
1548 AS1 (brlt,.+4) CR_TAB
90e7678c
DC
1549 AS1 (jmp,%0)));
1550 case GTU:
13e8651c 1551 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
90e7678c 1552 AS1 (brsh,%0)) :
13e8651c
TR
1553 len == 2 ? (AS1 (breq,.+4) CR_TAB
1554 AS1 (brlo,.+2) CR_TAB
90e7678c 1555 AS1 (rjmp,%0)) :
13e8651c
TR
1556 (AS1 (breq,.+6) CR_TAB
1557 AS1 (brlo,.+4) CR_TAB
90e7678c
DC
1558 AS1 (jmp,%0)));
1559 case LE:
1560 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1561 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1562 AS1 (brmi,%0)) :
13e8651c
TR
1563 len == 2 ? (AS1 (breq,.+2) CR_TAB
1564 AS1 (brpl,.+2) CR_TAB
90e7678c 1565 AS1 (rjmp,%0)) :
13e8651c
TR
1566 (AS1 (breq,.+2) CR_TAB
1567 AS1 (brpl,.+4) CR_TAB
90e7678c
DC
1568 AS1 (jmp,%0)));
1569 else
1570 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1571 AS1 (brlt,%0)) :
13e8651c
TR
1572 len == 2 ? (AS1 (breq,.+2) CR_TAB
1573 AS1 (brge,.+2) CR_TAB
90e7678c 1574 AS1 (rjmp,%0)) :
13e8651c
TR
1575 (AS1 (breq,.+2) CR_TAB
1576 AS1 (brge,.+4) CR_TAB
90e7678c
DC
1577 AS1 (jmp,%0)));
1578 case LEU:
1579 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1580 AS1 (brlo,%0)) :
13e8651c
TR
1581 len == 2 ? (AS1 (breq,.+2) CR_TAB
1582 AS1 (brsh,.+2) CR_TAB
90e7678c 1583 AS1 (rjmp,%0)) :
13e8651c
TR
1584 (AS1 (breq,.+2) CR_TAB
1585 AS1 (brsh,.+4) CR_TAB
90e7678c
DC
1586 AS1 (jmp,%0)));
1587 default:
56b871c1
DC
1588 if (reverse)
1589 {
1590 switch (len)
1591 {
1592 case 1:
1593 return AS1 (br%k1,%0);
1594 case 2:
13e8651c 1595 return (AS1 (br%j1,.+2) CR_TAB
56b871c1
DC
1596 AS1 (rjmp,%0));
1597 default:
13e8651c 1598 return (AS1 (br%j1,.+4) CR_TAB
56b871c1
DC
1599 AS1 (jmp,%0));
1600 }
1601 }
1602 else
1603 {
1604 switch (len)
1605 {
1606 case 1:
1607 return AS1 (br%j1,%0);
1608 case 2:
13e8651c 1609 return (AS1 (br%k1,.+2) CR_TAB
56b871c1
DC
1610 AS1 (rjmp,%0));
1611 default:
13e8651c 1612 return (AS1 (br%k1,.+4) CR_TAB
56b871c1
DC
1613 AS1 (jmp,%0));
1614 }
1615 }
90e7678c
DC
1616 }
1617 return "";
1618}
1619
1620/* Predicate function for immediate operand which fits to byte (8bit) */
1621
1622int
269e3795 1623byte_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
90e7678c
DC
1624{
1625 return (GET_CODE (op) == CONST_INT
1626 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1627}
1628
007a178c 1629/* Output insn cost for next insn. */
90e7678c
DC
1630
1631void
269e3795 1632final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
e9514725 1633 int num_operands ATTRIBUTE_UNUSED)
90e7678c 1634{
007a178c 1635 if (TARGET_ALL_DEBUG)
90e7678c 1636 {
e9514725
GJL
1637 rtx set = single_set (insn);
1638
1639 if (set)
1640 fprintf (asm_out_file, "/* DEBUG: cost = %d. */\n",
5e8f01f4 1641 set_src_cost (SET_SRC (set), optimize_insn_for_speed_p ()));
e9514725
GJL
1642 else
1643 fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d. */\n",
68f932c4
RS
1644 rtx_cost (PATTERN (insn), INSN, 0,
1645 optimize_insn_for_speed_p()));
90e7678c 1646 }
90e7678c
DC
1647}
1648
5fecfd8d 1649/* Return 0 if undefined, 1 if always true or always false. */
90e7678c
DC
1650
1651int
0a2aaacc 1652avr_simplify_comparison_p (enum machine_mode mode, RTX_CODE op, rtx x)
90e7678c
DC
1653{
1654 unsigned int max = (mode == QImode ? 0xff :
1655 mode == HImode ? 0xffff :
11f9ed1a 1656 mode == SImode ? 0xffffffff : 0);
0a2aaacc 1657 if (max && op && GET_CODE (x) == CONST_INT)
90e7678c 1658 {
0a2aaacc 1659 if (unsigned_condition (op) != op)
90e7678c
DC
1660 max >>= 1;
1661
1662 if (max != (INTVAL (x) & max)
1663 && INTVAL (x) != 0xff)
1664 return 1;
1665 }
1666 return 0;
1667}
1668
1669
1670/* Returns nonzero if REGNO is the number of a hard
1671 register in which function arguments are sometimes passed. */
1672
1673int
269e3795 1674function_arg_regno_p(int r)
90e7678c
DC
1675{
1676 return (r >= 8 && r <= 25);
1677}
1678
1679/* Initializing the variable cum for the state at the beginning
1680 of the argument list. */
1681
1682void
269e3795
SB
1683init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
1684 tree fndecl ATTRIBUTE_UNUSED)
90e7678c
DC
1685{
1686 cum->nregs = 18;
1687 cum->regno = FIRST_CUM_REG;
f38958e8
NF
1688 if (!libname && stdarg_p (fntype))
1689 cum->nregs = 0;
980a0ff4
GJL
1690
1691 /* Assume the calle may be tail called */
1692
1693 cfun->machine->sibcall_fails = 0;
90e7678c
DC
1694}
1695
c4984bad
MM
1696/* Returns the number of registers to allocate for a function argument. */
1697
1698static int
3f02a5f3 1699avr_num_arg_regs (enum machine_mode mode, const_tree type)
c4984bad
MM
1700{
1701 int size;
1702
1703 if (mode == BLKmode)
1704 size = int_size_in_bytes (type);
1705 else
1706 size = GET_MODE_SIZE (mode);
1707
afee2a52
MM
1708 /* Align all function arguments to start in even-numbered registers.
1709 Odd-sized arguments leave holes above them. */
c4984bad 1710
afee2a52 1711 return (size + 1) & ~1;
c4984bad
MM
1712}
1713
90e7678c 1714/* Controls whether a function argument is passed
2c338472 1715 in a register, and which register. */
90e7678c 1716
733bdfbd 1717static rtx
d5cc9181 1718avr_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
733bdfbd 1719 const_tree type, bool named ATTRIBUTE_UNUSED)
90e7678c 1720{
d5cc9181 1721 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
c4984bad 1722 int bytes = avr_num_arg_regs (mode, type);
90e7678c
DC
1723
1724 if (cum->nregs && bytes <= cum->nregs)
f1c25d3b 1725 return gen_rtx_REG (mode, cum->regno - bytes);
c4984bad 1726
90e7678c
DC
1727 return NULL_RTX;
1728}
1729
1730/* Update the summarizer variable CUM to advance past an argument
1731 in the argument list. */
1732
733bdfbd 1733static void
d5cc9181 1734avr_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
733bdfbd 1735 const_tree type, bool named ATTRIBUTE_UNUSED)
90e7678c 1736{
d5cc9181 1737 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
c4984bad 1738 int bytes = avr_num_arg_regs (mode, type);
90e7678c 1739
90e7678c
DC
1740 cum->nregs -= bytes;
1741 cum->regno -= bytes;
1742
980a0ff4
GJL
1743 /* A parameter is being passed in a call-saved register. As the original
1744 contents of these regs has to be restored before leaving the function,
1745 a function must not pass arguments in call-saved regs in order to get
1746 tail-called. */
1747
3f5ea9dc
GJL
1748 if (cum->regno >= 8
1749 && cum->nregs >= 0
980a0ff4
GJL
1750 && !call_used_regs[cum->regno])
1751 {
1752 /* FIXME: We ship info on failing tail-call in struct machine_function.
1753 This uses internals of calls.c:expand_call() and the way args_so_far
1754 is used. targetm.function_ok_for_sibcall() needs to be extended to
1755 pass &args_so_far, too. At present, CUMULATIVE_ARGS is target
1756 dependent so that such an extension is not wanted. */
1757
1758 cfun->machine->sibcall_fails = 1;
1759 }
1760
f24a5190
GJL
1761 /* Test if all registers needed by the ABI are actually available. If the
1762 user has fixed a GPR needed to pass an argument, an (implicit) function
1763 call would clobber that fixed register. See PR45099 for an example. */
1764
3f5ea9dc
GJL
1765 if (cum->regno >= 8
1766 && cum->nregs >= 0)
f24a5190
GJL
1767 {
1768 int regno;
1769
1770 for (regno = cum->regno; regno < cum->regno + bytes; regno++)
1771 if (fixed_regs[regno])
1772 error ("Register %s is needed to pass a parameter but is fixed",
1773 reg_names[regno]);
1774 }
1775
90e7678c
DC
1776 if (cum->nregs <= 0)
1777 {
1778 cum->nregs = 0;
1779 cum->regno = FIRST_CUM_REG;
1780 }
90e7678c
DC
1781}
1782
980a0ff4
GJL
1783/* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
1784/* Decide whether we can make a sibling call to a function. DECL is the
1785 declaration of the function being targeted by the call and EXP is the
1786 CALL_EXPR representing the call. */
1787
1788static bool
1789avr_function_ok_for_sibcall (tree decl_callee, tree exp_callee)
1790{
1791 tree fntype_callee;
1792
1793 /* Tail-calling must fail if callee-saved regs are used to pass
1794 function args. We must not tail-call when `epilogue_restores'
1795 is used. Unfortunately, we cannot tell at this point if that
1796 actually will happen or not, and we cannot step back from
1797 tail-calling. Thus, we inhibit tail-calling with -mcall-prologues. */
1798
1799 if (cfun->machine->sibcall_fails
1800 || TARGET_CALL_PROLOGUES)
1801 {
1802 return false;
1803 }
1804
1805 fntype_callee = TREE_TYPE (CALL_EXPR_FN (exp_callee));
1806
1807 if (decl_callee)
1808 {
1809 decl_callee = TREE_TYPE (decl_callee);
1810 }
1811 else
1812 {
1813 decl_callee = fntype_callee;
1814
1815 while (FUNCTION_TYPE != TREE_CODE (decl_callee)
1816 && METHOD_TYPE != TREE_CODE (decl_callee))
1817 {
1818 decl_callee = TREE_TYPE (decl_callee);
1819 }
1820 }
1821
1822 /* Ensure that caller and callee have compatible epilogues */
1823
1824 if (interrupt_function_p (current_function_decl)
1825 || signal_function_p (current_function_decl)
1826 || avr_naked_function_p (decl_callee)
1827 || avr_naked_function_p (current_function_decl)
1828 /* FIXME: For OS_task and OS_main, we are over-conservative.
1829 This is due to missing documentation of these attributes
1830 and what they actually should do and should not do. */
1831 || (avr_OS_task_function_p (decl_callee)
1832 != avr_OS_task_function_p (current_function_decl))
1833 || (avr_OS_main_function_p (decl_callee)
1834 != avr_OS_main_function_p (current_function_decl)))
1835 {
1836 return false;
1837 }
1838
1839 return true;
1840}
1841
90e7678c
DC
1842/***********************************************************************
1843 Functions for outputting various mov's for a various modes
1844************************************************************************/
5fecfd8d 1845const char *
269e3795 1846output_movqi (rtx insn, rtx operands[], int *l)
90e7678c 1847{
6bec29c9
DC
1848 int dummy;
1849 rtx dest = operands[0];
1850 rtx src = operands[1];
1851 int *real_l = l;
1852
1853 if (!l)
1854 l = &dummy;
1855
1856 *l = 1;
1857
1858 if (register_operand (dest, QImode))
90e7678c 1859 {
6bec29c9 1860 if (register_operand (src, QImode)) /* mov r,r */
90e7678c 1861 {
6bec29c9
DC
1862 if (test_hard_reg_class (STACK_REG, dest))
1863 return AS2 (out,%0,%1);
1864 else if (test_hard_reg_class (STACK_REG, src))
1865 return AS2 (in,%0,%1);
1866
1867 return AS2 (mov,%0,%1);
1868 }
1869 else if (CONSTANT_P (src))
1870 {
1871 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1872 return AS2 (ldi,%0,lo8(%1));
1873
1874 if (GET_CODE (src) == CONST_INT)
90e7678c 1875 {
6bec29c9
DC
1876 if (src == const0_rtx) /* mov r,L */
1877 return AS1 (clr,%0);
1878 else if (src == const1_rtx)
90e7678c 1879 {
6bec29c9
DC
1880 *l = 2;
1881 return (AS1 (clr,%0) CR_TAB
1882 AS1 (inc,%0));
1883 }
6bec29c9 1884 else if (src == constm1_rtx)
90e7678c 1885 {
6bec29c9 1886 /* Immediate constants -1 to any register */
6bec29c9
DC
1887 *l = 2;
1888 return (AS1 (clr,%0) CR_TAB
1889 AS1 (dec,%0));
90e7678c 1890 }
afee2a52
MM
1891 else
1892 {
1893 int bit_nr = exact_log2 (INTVAL (src));
1894
1895 if (bit_nr >= 0)
1896 {
6001794d
KH
1897 *l = 3;
1898 if (!real_l)
1899 output_asm_insn ((AS1 (clr,%0) CR_TAB
1900 "set"), operands);
afee2a52
MM
1901 if (!real_l)
1902 avr_output_bld (operands, bit_nr);
1903
1904 return "";
1905 }
1906 }
90e7678c 1907 }
6bec29c9
DC
1908
1909 /* Last resort, larger than loading from memory. */
1910 *l = 4;
1911 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1912 AS2 (ldi,r31,lo8(%1)) CR_TAB
1913 AS2 (mov,%0,r31) CR_TAB
1914 AS2 (mov,r31,__tmp_reg__));
1915 }
1916 else if (GET_CODE (src) == MEM)
1917 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1918 }
1919 else if (GET_CODE (dest) == MEM)
1920 {
0a2aaacc 1921 const char *templ;
5fecfd8d
MM
1922
1923 if (src == const0_rtx)
1924 operands[1] = zero_reg_rtx;
1925
0a2aaacc 1926 templ = out_movqi_mr_r (insn, operands, real_l);
6bec29c9
DC
1927
1928 if (!real_l)
0a2aaacc 1929 output_asm_insn (templ, operands);
5fecfd8d
MM
1930
1931 operands[1] = src;
6bec29c9
DC
1932 }
1933 return "";
1934}
1935
1936
5fecfd8d 1937const char *
269e3795 1938output_movhi (rtx insn, rtx operands[], int *l)
6bec29c9
DC
1939{
1940 int dummy;
1941 rtx dest = operands[0];
1942 rtx src = operands[1];
1943 int *real_l = l;
1944
1945 if (!l)
1946 l = &dummy;
1947
1948 if (register_operand (dest, HImode))
1949 {
1950 if (register_operand (src, HImode)) /* mov r,r */
1951 {
1952 if (test_hard_reg_class (STACK_REG, dest))
90e7678c 1953 {
164709cf 1954 if (AVR_HAVE_8BIT_SP)
794cb45e
AS
1955 return *l = 1, AS2 (out,__SP_L__,%A1);
1956 /* Use simple load of stack pointer if no interrupts are
1957 used. */
1958 else if (TARGET_NO_INTERRUPTS)
1959 return *l = 2, (AS2 (out,__SP_H__,%B1) CR_TAB
1960 AS2 (out,__SP_L__,%A1));
6bec29c9
DC
1961 *l = 5;
1962 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1963 "cli" CR_TAB
1964 AS2 (out,__SP_H__,%B1) CR_TAB
1965 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1966 AS2 (out,__SP_L__,%A1));
1967 }
1968 else if (test_hard_reg_class (STACK_REG, src))
1969 {
1970 *l = 2;
1971 return (AS2 (in,%A0,__SP_L__) CR_TAB
1972 AS2 (in,%B0,__SP_H__));
1973 }
1974
4301ec4f 1975 if (AVR_HAVE_MOVW)
6bec29c9
DC
1976 {
1977 *l = 1;
1978 return (AS2 (movw,%0,%1));
1979 }
6bec29c9
DC
1980 else
1981 {
1982 *l = 2;
1983 return (AS2 (mov,%A0,%A1) CR_TAB
1984 AS2 (mov,%B0,%B1));
1985 }
1986 }
1987 else if (CONSTANT_P (src))
1988 {
1989 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1990 {
1991 *l = 2;
1992 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1993 AS2 (ldi,%B0,hi8(%1)));
1994 }
1995
1996 if (GET_CODE (src) == CONST_INT)
1997 {
1998 if (src == const0_rtx) /* mov r,L */
1999 {
2000 *l = 2;
2001 return (AS1 (clr,%A0) CR_TAB
2002 AS1 (clr,%B0));
2003 }
2004 else if (src == const1_rtx)
2005 {
08f81276
MM
2006 *l = 3;
2007 return (AS1 (clr,%A0) CR_TAB
2008 AS1 (clr,%B0) CR_TAB
2009 AS1 (inc,%A0));
6bec29c9 2010 }
6bec29c9
DC
2011 else if (src == constm1_rtx)
2012 {
2013 /* Immediate constants -1 to any register */
6bec29c9
DC
2014 *l = 3;
2015 return (AS1 (clr,%0) CR_TAB
2016 AS1 (dec,%A0) CR_TAB
2017 AS2 (mov,%B0,%A0));
2018 }
afee2a52
MM
2019 else
2020 {
2021 int bit_nr = exact_log2 (INTVAL (src));
2022
2023 if (bit_nr >= 0)
2024 {
6001794d
KH
2025 *l = 4;
2026 if (!real_l)
2027 output_asm_insn ((AS1 (clr,%A0) CR_TAB
2028 AS1 (clr,%B0) CR_TAB
2029 "set"), operands);
afee2a52
MM
2030 if (!real_l)
2031 avr_output_bld (operands, bit_nr);
2032
2033 return "";
2034 }
2035 }
2036
6bec29c9
DC
2037 if ((INTVAL (src) & 0xff) == 0)
2038 {
2039 *l = 5;
2040 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2041 AS1 (clr,%A0) CR_TAB
2042 AS2 (ldi,r31,hi8(%1)) CR_TAB
2043 AS2 (mov,%B0,r31) CR_TAB
2044 AS2 (mov,r31,__tmp_reg__));
2045 }
2046 else if ((INTVAL (src) & 0xff00) == 0)
2047 {
2048 *l = 5;
2049 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2050 AS2 (ldi,r31,lo8(%1)) CR_TAB
2051 AS2 (mov,%A0,r31) CR_TAB
2052 AS1 (clr,%B0) CR_TAB
2053 AS2 (mov,r31,__tmp_reg__));
90e7678c 2054 }
90e7678c 2055 }
6bec29c9
DC
2056
2057 /* Last resort, equal to loading from memory. */
2058 *l = 6;
2059 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2060 AS2 (ldi,r31,lo8(%1)) CR_TAB
2061 AS2 (mov,%A0,r31) CR_TAB
2062 AS2 (ldi,r31,hi8(%1)) CR_TAB
2063 AS2 (mov,%B0,r31) CR_TAB
2064 AS2 (mov,r31,__tmp_reg__));
2065 }
2066 else if (GET_CODE (src) == MEM)
2067 return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
2068 }
2069 else if (GET_CODE (dest) == MEM)
2070 {
0a2aaacc 2071 const char *templ;
5fecfd8d
MM
2072
2073 if (src == const0_rtx)
2074 operands[1] = zero_reg_rtx;
2075
0a2aaacc 2076 templ = out_movhi_mr_r (insn, operands, real_l);
6bec29c9
DC
2077
2078 if (!real_l)
0a2aaacc 2079 output_asm_insn (templ, operands);
5fecfd8d
MM
2080
2081 operands[1] = src;
6bec29c9 2082 return "";
90e7678c 2083 }
c725bd79 2084 fatal_insn ("invalid insn:", insn);
6bec29c9
DC
2085 return "";
2086}
2087
5fecfd8d 2088const char *
269e3795 2089out_movqi_r_mr (rtx insn, rtx op[], int *l)
6bec29c9 2090{
5fecfd8d
MM
2091 rtx dest = op[0];
2092 rtx src = op[1];
2093 rtx x = XEXP (src, 0);
6bec29c9
DC
2094 int dummy;
2095
2096 if (!l)
2097 l = &dummy;
6bec29c9
DC
2098
2099 if (CONSTANT_ADDRESS_P (x))
2100 {
4fc2b4ff
AH
2101 if (CONST_INT_P (x) && INTVAL (x) == SREG_ADDR)
2102 {
2103 *l = 1;
2104 return AS2 (in,%0,__SREG__);
2105 }
e6b69d0e 2106 if (optimize > 0 && io_address_operand (x, QImode))
6bec29c9
DC
2107 {
2108 *l = 1;
846428f1 2109 return AS2 (in,%0,%m1-0x20);
6bec29c9
DC
2110 }
2111 *l = 2;
846428f1 2112 return AS2 (lds,%0,%m1);
6bec29c9
DC
2113 }
2114 /* memory access by reg+disp */
2115 else if (GET_CODE (x) == PLUS
2116 && REG_P (XEXP (x,0))
2117 && GET_CODE (XEXP (x,1)) == CONST_INT)
2118 {
5fecfd8d 2119 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
6bec29c9
DC
2120 {
2121 int disp = INTVAL (XEXP (x,1));
2122 if (REGNO (XEXP (x,0)) != REG_Y)
c725bd79 2123 fatal_insn ("incorrect insn:",insn);
33d5e2dc 2124
5fecfd8d 2125 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
33d5e2dc
MM
2126 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
2127 AS2 (ldd,%0,Y+63) CR_TAB
2128 AS2 (sbiw,r28,%o1-63));
2129
2130 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2131 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2132 AS2 (ld,%0,Y) CR_TAB
2133 AS2 (subi,r28,lo8(%o1)) CR_TAB
2134 AS2 (sbci,r29,hi8(%o1)));
6bec29c9
DC
2135 }
2136 else if (REGNO (XEXP (x,0)) == REG_X)
2137 {
6bec29c9
DC
2138 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
2139 it but I have this situation with extremal optimizing options. */
5fecfd8d 2140 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
6bec29c9 2141 || reg_unused_after (insn, XEXP (x,0)))
33d5e2dc
MM
2142 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
2143 AS2 (ld,%0,X));
2144
2145 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
2146 AS2 (ld,%0,X) CR_TAB
2147 AS2 (sbiw,r26,%o1));
6bec29c9
DC
2148 }
2149 *l = 1;
2150 return AS2 (ldd,%0,%1);
2151 }
2152 *l = 1;
2153 return AS2 (ld,%0,%1);
90e7678c
DC
2154}
2155
5fecfd8d 2156const char *
269e3795 2157out_movhi_r_mr (rtx insn, rtx op[], int *l)
90e7678c 2158{
5fecfd8d
MM
2159 rtx dest = op[0];
2160 rtx src = op[1];
2161 rtx base = XEXP (src, 0);
2162 int reg_dest = true_regnum (dest);
2163 int reg_base = true_regnum (base);
a6990185
MM
2164 /* "volatile" forces reading low byte first, even if less efficient,
2165 for correct operation with 16-bit I/O registers. */
2166 int mem_volatile_p = MEM_VOLATILE_P (src);
6bec29c9 2167 int tmp;
90e7678c
DC
2168
2169 if (!l)
6bec29c9 2170 l = &tmp;
90e7678c
DC
2171
2172 if (reg_base > 0)
2173 {
2174 if (reg_dest == reg_base) /* R = (R) */
6bec29c9
DC
2175 {
2176 *l = 3;
2177 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
2178 AS2 (ld,%B0,%1) CR_TAB
2179 AS2 (mov,%A0,__tmp_reg__));
2180 }
90e7678c
DC
2181 else if (reg_base == REG_X) /* (R26) */
2182 {
5fecfd8d 2183 if (reg_unused_after (insn, base))
6bec29c9
DC
2184 {
2185 *l = 2;
2186 return (AS2 (ld,%A0,X+) CR_TAB
2187 AS2 (ld,%B0,X));
2188 }
2189 *l = 3;
2190 return (AS2 (ld,%A0,X+) CR_TAB
2191 AS2 (ld,%B0,X) CR_TAB
2192 AS2 (sbiw,r26,1));
90e7678c
DC
2193 }
2194 else /* (R) */
6bec29c9
DC
2195 {
2196 *l = 2;
2197 return (AS2 (ld,%A0,%1) CR_TAB
2198 AS2 (ldd,%B0,%1+1));
2199 }
90e7678c 2200 }
5fecfd8d 2201 else if (GET_CODE (base) == PLUS) /* (R + i) */
90e7678c 2202 {
5fecfd8d
MM
2203 int disp = INTVAL (XEXP (base, 1));
2204 int reg_base = true_regnum (XEXP (base, 0));
90e7678c 2205
5fecfd8d 2206 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
90e7678c 2207 {
5fecfd8d 2208 if (REGNO (XEXP (base, 0)) != REG_Y)
c725bd79 2209 fatal_insn ("incorrect insn:",insn);
6bec29c9 2210
5fecfd8d 2211 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
33d5e2dc
MM
2212 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
2213 AS2 (ldd,%A0,Y+62) CR_TAB
2214 AS2 (ldd,%B0,Y+63) CR_TAB
2215 AS2 (sbiw,r28,%o1-62));
2216
2217 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2218 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2219 AS2 (ld,%A0,Y) CR_TAB
2220 AS2 (ldd,%B0,Y+1) CR_TAB
2221 AS2 (subi,r28,lo8(%o1)) CR_TAB
2222 AS2 (sbci,r29,hi8(%o1)));
90e7678c
DC
2223 }
2224 if (reg_base == REG_X)
2225 {
2226 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
6bec29c9
DC
2227 it but I have this situation with extremal
2228 optimization options. */
2229
33d5e2dc 2230 *l = 4;
6bec29c9 2231 if (reg_base == reg_dest)
33d5e2dc
MM
2232 return (AS2 (adiw,r26,%o1) CR_TAB
2233 AS2 (ld,__tmp_reg__,X+) CR_TAB
2234 AS2 (ld,%B0,X) CR_TAB
2235 AS2 (mov,%A0,__tmp_reg__));
6bec29c9 2236
33d5e2dc
MM
2237 return (AS2 (adiw,r26,%o1) CR_TAB
2238 AS2 (ld,%A0,X+) CR_TAB
2239 AS2 (ld,%B0,X) CR_TAB
2240 AS2 (sbiw,r26,%o1+1));
6bec29c9
DC
2241 }
2242
2243 if (reg_base == reg_dest)
2244 {
2245 *l = 3;
2246 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
2247 AS2 (ldd,%B0,%B1) CR_TAB
2248 AS2 (mov,%A0,__tmp_reg__));
90e7678c
DC
2249 }
2250
6bec29c9
DC
2251 *l = 2;
2252 return (AS2 (ldd,%A0,%A1) CR_TAB
2253 AS2 (ldd,%B0,%B1));
90e7678c 2254 }
5fecfd8d 2255 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
90e7678c 2256 {
5fecfd8d 2257 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
c725bd79 2258 fatal_insn ("incorrect insn:", insn);
6bec29c9 2259
a6990185
MM
2260 if (mem_volatile_p)
2261 {
2262 if (REGNO (XEXP (base, 0)) == REG_X)
2263 {
2264 *l = 4;
2265 return (AS2 (sbiw,r26,2) CR_TAB
2266 AS2 (ld,%A0,X+) CR_TAB
2267 AS2 (ld,%B0,X) CR_TAB
2268 AS2 (sbiw,r26,1));
2269 }
2270 else
2271 {
2272 *l = 3;
2273 return (AS2 (sbiw,%r1,2) CR_TAB
2274 AS2 (ld,%A0,%p1) CR_TAB
2275 AS2 (ldd,%B0,%p1+1));
2276 }
2277 }
2278
6bec29c9
DC
2279 *l = 2;
2280 return (AS2 (ld,%B0,%1) CR_TAB
2281 AS2 (ld,%A0,%1));
90e7678c 2282 }
5fecfd8d 2283 else if (GET_CODE (base) == POST_INC) /* (R++) */
90e7678c 2284 {
5fecfd8d 2285 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
c725bd79 2286 fatal_insn ("incorrect insn:", insn);
6bec29c9
DC
2287
2288 *l = 2;
2289 return (AS2 (ld,%A0,%1) CR_TAB
2290 AS2 (ld,%B0,%1));
90e7678c 2291 }
5fecfd8d 2292 else if (CONSTANT_ADDRESS_P (base))
6bec29c9 2293 {
e6b69d0e 2294 if (optimize > 0 && io_address_operand (base, HImode))
5fecfd8d
MM
2295 {
2296 *l = 2;
846428f1
AH
2297 return (AS2 (in,%A0,%m1-0x20) CR_TAB
2298 AS2 (in,%B0,%m1+1-0x20));
5fecfd8d 2299 }
6bec29c9 2300 *l = 4;
846428f1
AH
2301 return (AS2 (lds,%A0,%m1) CR_TAB
2302 AS2 (lds,%B0,%m1+1));
6bec29c9
DC
2303 }
2304
c725bd79 2305 fatal_insn ("unknown move insn:",insn);
90e7678c
DC
2306 return "";
2307}
2308
5fecfd8d 2309const char *
269e3795 2310out_movsi_r_mr (rtx insn, rtx op[], int *l)
90e7678c 2311{
5fecfd8d
MM
2312 rtx dest = op[0];
2313 rtx src = op[1];
2314 rtx base = XEXP (src, 0);
2315 int reg_dest = true_regnum (dest);
2316 int reg_base = true_regnum (base);
90e7678c 2317 int tmp;
6bec29c9 2318
90e7678c 2319 if (!l)
6bec29c9
DC
2320 l = &tmp;
2321
90e7678c
DC
2322 if (reg_base > 0)
2323 {
2324 if (reg_base == REG_X) /* (R26) */
2325 {
2326 if (reg_dest == REG_X)
dfaf5abf
MM
2327 /* "ld r26,-X" is undefined */
2328 return *l=7, (AS2 (adiw,r26,3) CR_TAB
2329 AS2 (ld,r29,X) CR_TAB
2330 AS2 (ld,r28,-X) CR_TAB
2331 AS2 (ld,__tmp_reg__,-X) CR_TAB
2332 AS2 (sbiw,r26,1) CR_TAB
2333 AS2 (ld,r26,X) CR_TAB
2334 AS2 (mov,r27,__tmp_reg__));
90e7678c
DC
2335 else if (reg_dest == REG_X - 2)
2336 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2337 AS2 (ld,%B0,X+) CR_TAB
2338 AS2 (ld,__tmp_reg__,X+) CR_TAB
2339 AS2 (ld,%D0,X) CR_TAB
2340 AS2 (mov,%C0,__tmp_reg__));
5fecfd8d 2341 else if (reg_unused_after (insn, base))
90e7678c
DC
2342 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
2343 AS2 (ld,%B0,X+) CR_TAB
2344 AS2 (ld,%C0,X+) CR_TAB
2345 AS2 (ld,%D0,X));
2346 else
2347 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2348 AS2 (ld,%B0,X+) CR_TAB
2349 AS2 (ld,%C0,X+) CR_TAB
2350 AS2 (ld,%D0,X) CR_TAB
2351 AS2 (sbiw,r26,3));
2352 }
2353 else
2354 {
2355 if (reg_dest == reg_base)
2356 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
2357 AS2 (ldd,%C0,%1+2) CR_TAB
2358 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
2359 AS2 (ld,%A0,%1) CR_TAB
2360 AS2 (mov,%B0,__tmp_reg__));
2361 else if (reg_base == reg_dest + 2)
2362 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
2363 AS2 (ldd,%B0,%1+1) CR_TAB
2364 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
2365 AS2 (ldd,%D0,%1+3) CR_TAB
2366 AS2 (mov,%C0,__tmp_reg__));
2367 else
2368 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
2369 AS2 (ldd,%B0,%1+1) CR_TAB
2370 AS2 (ldd,%C0,%1+2) CR_TAB
2371 AS2 (ldd,%D0,%1+3));
2372 }
2373 }
5fecfd8d 2374 else if (GET_CODE (base) == PLUS) /* (R + i) */
90e7678c 2375 {
5fecfd8d 2376 int disp = INTVAL (XEXP (base, 1));
90e7678c 2377
5fecfd8d 2378 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
90e7678c 2379 {
5fecfd8d 2380 if (REGNO (XEXP (base, 0)) != REG_Y)
c725bd79 2381 fatal_insn ("incorrect insn:",insn);
33d5e2dc 2382
5fecfd8d 2383 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
33d5e2dc
MM
2384 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2385 AS2 (ldd,%A0,Y+60) CR_TAB
2386 AS2 (ldd,%B0,Y+61) CR_TAB
2387 AS2 (ldd,%C0,Y+62) CR_TAB
2388 AS2 (ldd,%D0,Y+63) CR_TAB
2389 AS2 (sbiw,r28,%o1-60));
2390
2391 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2392 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2393 AS2 (ld,%A0,Y) CR_TAB
2394 AS2 (ldd,%B0,Y+1) CR_TAB
2395 AS2 (ldd,%C0,Y+2) CR_TAB
2396 AS2 (ldd,%D0,Y+3) CR_TAB
2397 AS2 (subi,r28,lo8(%o1)) CR_TAB
2398 AS2 (sbci,r29,hi8(%o1)));
90e7678c
DC
2399 }
2400
5fecfd8d 2401 reg_base = true_regnum (XEXP (base, 0));
dfaf5abf
MM
2402 if (reg_base == REG_X)
2403 {
2404 /* R = (X + d) */
2405 if (reg_dest == REG_X)
2406 {
2407 *l = 7;
2408 /* "ld r26,-X" is undefined */
2409 return (AS2 (adiw,r26,%o1+3) CR_TAB
2410 AS2 (ld,r29,X) CR_TAB
2411 AS2 (ld,r28,-X) CR_TAB
2412 AS2 (ld,__tmp_reg__,-X) CR_TAB
2413 AS2 (sbiw,r26,1) CR_TAB
2414 AS2 (ld,r26,X) CR_TAB
2415 AS2 (mov,r27,__tmp_reg__));
2416 }
2417 *l = 6;
2418 if (reg_dest == REG_X - 2)
2419 return (AS2 (adiw,r26,%o1) CR_TAB
2420 AS2 (ld,r24,X+) CR_TAB
2421 AS2 (ld,r25,X+) CR_TAB
2422 AS2 (ld,__tmp_reg__,X+) CR_TAB
2423 AS2 (ld,r27,X) CR_TAB
2424 AS2 (mov,r26,__tmp_reg__));
2425
2426 return (AS2 (adiw,r26,%o1) CR_TAB
2427 AS2 (ld,%A0,X+) CR_TAB
2428 AS2 (ld,%B0,X+) CR_TAB
2429 AS2 (ld,%C0,X+) CR_TAB
2430 AS2 (ld,%D0,X) CR_TAB
2431 AS2 (sbiw,r26,%o1+3));
2432 }
90e7678c
DC
2433 if (reg_dest == reg_base)
2434 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2435 AS2 (ldd,%C0,%C1) CR_TAB
2436 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
2437 AS2 (ldd,%A0,%A1) CR_TAB
2438 AS2 (mov,%B0,__tmp_reg__));
2439 else if (reg_dest == reg_base - 2)
2440 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2441 AS2 (ldd,%B0,%B1) CR_TAB
2442 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
2443 AS2 (ldd,%D0,%D1) CR_TAB
2444 AS2 (mov,%C0,__tmp_reg__));
2445 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2446 AS2 (ldd,%B0,%B1) CR_TAB
2447 AS2 (ldd,%C0,%C1) CR_TAB
2448 AS2 (ldd,%D0,%D1));
2449 }
5fecfd8d 2450 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
90e7678c
DC
2451 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2452 AS2 (ld,%C0,%1) CR_TAB
2453 AS2 (ld,%B0,%1) CR_TAB
2454 AS2 (ld,%A0,%1));
5fecfd8d 2455 else if (GET_CODE (base) == POST_INC) /* (R++) */
90e7678c
DC
2456 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2457 AS2 (ld,%B0,%1) CR_TAB
2458 AS2 (ld,%C0,%1) CR_TAB
2459 AS2 (ld,%D0,%1));
5fecfd8d 2460 else if (CONSTANT_ADDRESS_P (base))
846428f1
AH
2461 return *l=8, (AS2 (lds,%A0,%m1) CR_TAB
2462 AS2 (lds,%B0,%m1+1) CR_TAB
2463 AS2 (lds,%C0,%m1+2) CR_TAB
2464 AS2 (lds,%D0,%m1+3));
90e7678c 2465
c725bd79 2466 fatal_insn ("unknown move insn:",insn);
90e7678c
DC
2467 return "";
2468}
2469
5fecfd8d 2470const char *
269e3795 2471out_movsi_mr_r (rtx insn, rtx op[], int *l)
90e7678c 2472{
5fecfd8d
MM
2473 rtx dest = op[0];
2474 rtx src = op[1];
2475 rtx base = XEXP (dest, 0);
2476 int reg_base = true_regnum (base);
2477 int reg_src = true_regnum (src);
90e7678c 2478 int tmp;
6bec29c9 2479
90e7678c
DC
2480 if (!l)
2481 l = &tmp;
6bec29c9 2482
5fecfd8d 2483 if (CONSTANT_ADDRESS_P (base))
846428f1
AH
2484 return *l=8,(AS2 (sts,%m0,%A1) CR_TAB
2485 AS2 (sts,%m0+1,%B1) CR_TAB
2486 AS2 (sts,%m0+2,%C1) CR_TAB
2487 AS2 (sts,%m0+3,%D1));
90e7678c
DC
2488 if (reg_base > 0) /* (r) */
2489 {
2490 if (reg_base == REG_X) /* (R26) */
2491 {
5fecfd8d 2492 if (reg_src == REG_X)
90e7678c 2493 {
dfaf5abf 2494 /* "st X+,r26" is undefined */
5fecfd8d 2495 if (reg_unused_after (insn, base))
dfaf5abf
MM
2496 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2497 AS2 (st,X,r26) CR_TAB
2498 AS2 (adiw,r26,1) CR_TAB
2499 AS2 (st,X+,__tmp_reg__) CR_TAB
2500 AS2 (st,X+,r28) CR_TAB
2501 AS2 (st,X,r29));
90e7678c 2502 else
dfaf5abf
MM
2503 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2504 AS2 (st,X,r26) CR_TAB
2505 AS2 (adiw,r26,1) CR_TAB
2506 AS2 (st,X+,__tmp_reg__) CR_TAB
2507 AS2 (st,X+,r28) CR_TAB
2508 AS2 (st,X,r29) CR_TAB
2509 AS2 (sbiw,r26,3));
90e7678c 2510 }
5fecfd8d 2511 else if (reg_base == reg_src + 2)
90e7678c 2512 {
5fecfd8d 2513 if (reg_unused_after (insn, base))
90e7678c
DC
2514 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2515 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2516 AS2 (st,%0+,%A1) CR_TAB
2517 AS2 (st,%0+,%B1) CR_TAB
2518 AS2 (st,%0+,__zero_reg__) CR_TAB
2519 AS2 (st,%0,__tmp_reg__) CR_TAB
2520 AS1 (clr,__zero_reg__));
2521 else
2522 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2523 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2524 AS2 (st,%0+,%A1) CR_TAB
2525 AS2 (st,%0+,%B1) CR_TAB
2526 AS2 (st,%0+,__zero_reg__) CR_TAB
2527 AS2 (st,%0,__tmp_reg__) CR_TAB
2528 AS1 (clr,__zero_reg__) CR_TAB
2529 AS2 (sbiw,r26,3));
2530 }
2531 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
2532 AS2 (st,%0+,%B1) CR_TAB
2533 AS2 (st,%0+,%C1) CR_TAB
2534 AS2 (st,%0,%D1) CR_TAB
2535 AS2 (sbiw,r26,3));
2536 }
2537 else
2538 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2539 AS2 (std,%0+1,%B1) CR_TAB
2540 AS2 (std,%0+2,%C1) CR_TAB
2541 AS2 (std,%0+3,%D1));
2542 }
5fecfd8d 2543 else if (GET_CODE (base) == PLUS) /* (R + i) */
90e7678c 2544 {
5fecfd8d 2545 int disp = INTVAL (XEXP (base, 1));
dfaf5abf 2546 reg_base = REGNO (XEXP (base, 0));
5fecfd8d 2547 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
90e7678c 2548 {
dfaf5abf 2549 if (reg_base != REG_Y)
c725bd79 2550 fatal_insn ("incorrect insn:",insn);
33d5e2dc 2551
5fecfd8d 2552 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
33d5e2dc
MM
2553 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2554 AS2 (std,Y+60,%A1) CR_TAB
2555 AS2 (std,Y+61,%B1) CR_TAB
2556 AS2 (std,Y+62,%C1) CR_TAB
2557 AS2 (std,Y+63,%D1) CR_TAB
2558 AS2 (sbiw,r28,%o0-60));
2559
2560 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2561 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2562 AS2 (st,Y,%A1) CR_TAB
2563 AS2 (std,Y+1,%B1) CR_TAB
2564 AS2 (std,Y+2,%C1) CR_TAB
2565 AS2 (std,Y+3,%D1) CR_TAB
2566 AS2 (subi,r28,lo8(%o0)) CR_TAB
2567 AS2 (sbci,r29,hi8(%o0)));
90e7678c 2568 }
dfaf5abf
MM
2569 if (reg_base == REG_X)
2570 {
2571 /* (X + d) = R */
2572 if (reg_src == REG_X)
2573 {
2574 *l = 9;
2575 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2576 AS2 (mov,__zero_reg__,r27) CR_TAB
2577 AS2 (adiw,r26,%o0) CR_TAB
2578 AS2 (st,X+,__tmp_reg__) CR_TAB
2579 AS2 (st,X+,__zero_reg__) CR_TAB
2580 AS2 (st,X+,r28) CR_TAB
2581 AS2 (st,X,r29) CR_TAB
2582 AS1 (clr,__zero_reg__) CR_TAB
2583 AS2 (sbiw,r26,%o0+3));
2584 }
2585 else if (reg_src == REG_X - 2)
2586 {
2587 *l = 9;
2588 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2589 AS2 (mov,__zero_reg__,r27) CR_TAB
2590 AS2 (adiw,r26,%o0) CR_TAB
2591 AS2 (st,X+,r24) CR_TAB
2592 AS2 (st,X+,r25) CR_TAB
2593 AS2 (st,X+,__tmp_reg__) CR_TAB
2594 AS2 (st,X,__zero_reg__) CR_TAB
2595 AS1 (clr,__zero_reg__) CR_TAB
2596 AS2 (sbiw,r26,%o0+3));
2597 }
2598 *l = 6;
2599 return (AS2 (adiw,r26,%o0) CR_TAB
2600 AS2 (st,X+,%A1) CR_TAB
2601 AS2 (st,X+,%B1) CR_TAB
2602 AS2 (st,X+,%C1) CR_TAB
2603 AS2 (st,X,%D1) CR_TAB
2604 AS2 (sbiw,r26,%o0+3));
2605 }
90e7678c
DC
2606 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
2607 AS2 (std,%B0,%B1) CR_TAB
2608 AS2 (std,%C0,%C1) CR_TAB
2609 AS2 (std,%D0,%D1));
2610 }
5fecfd8d 2611 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
90e7678c
DC
2612 return *l=4, (AS2 (st,%0,%D1) CR_TAB
2613 AS2 (st,%0,%C1) CR_TAB
2614 AS2 (st,%0,%B1) CR_TAB
2615 AS2 (st,%0,%A1));
5fecfd8d 2616 else if (GET_CODE (base) == POST_INC) /* (R++) */
90e7678c
DC
2617 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2618 AS2 (st,%0,%B1) CR_TAB
2619 AS2 (st,%0,%C1) CR_TAB
2620 AS2 (st,%0,%D1));
c725bd79 2621 fatal_insn ("unknown move insn:",insn);
90e7678c
DC
2622 return "";
2623}
2624
5fecfd8d 2625const char *
1e6a67d1 2626output_movsisf (rtx insn, rtx operands[], rtx clobber_reg, int *l)
90e7678c 2627{
6bec29c9
DC
2628 int dummy;
2629 rtx dest = operands[0];
2630 rtx src = operands[1];
2631 int *real_l = l;
2632
2633 if (!l)
2634 l = &dummy;
2635
2636 if (register_operand (dest, VOIDmode))
90e7678c 2637 {
6bec29c9 2638 if (register_operand (src, VOIDmode)) /* mov r,r */
c4984bad 2639 {
6bec29c9
DC
2640 if (true_regnum (dest) > true_regnum (src))
2641 {
4301ec4f 2642 if (AVR_HAVE_MOVW)
6bec29c9
DC
2643 {
2644 *l = 2;
2645 return (AS2 (movw,%C0,%C1) CR_TAB
2646 AS2 (movw,%A0,%A1));
2647 }
2648 *l = 4;
2649 return (AS2 (mov,%D0,%D1) CR_TAB
2650 AS2 (mov,%C0,%C1) CR_TAB
2651 AS2 (mov,%B0,%B1) CR_TAB
2652 AS2 (mov,%A0,%A1));
2653 }
c4984bad 2654 else
6bec29c9 2655 {
4301ec4f 2656 if (AVR_HAVE_MOVW)
6bec29c9
DC
2657 {
2658 *l = 2;
2659 return (AS2 (movw,%A0,%A1) CR_TAB
2660 AS2 (movw,%C0,%C1));
2661 }
2662 *l = 4;
2663 return (AS2 (mov,%A0,%A1) CR_TAB
2664 AS2 (mov,%B0,%B1) CR_TAB
2665 AS2 (mov,%C0,%C1) CR_TAB
2666 AS2 (mov,%D0,%D1));
2667 }
c4984bad 2668 }
1e6a67d1
GJL
2669 else if (CONST_INT_P (src)
2670 || CONST_DOUBLE_P (src))
2671 {
2672 return output_reload_insisf (insn, operands, clobber_reg, real_l);
2673 }
6bec29c9 2674 else if (CONSTANT_P (src))
c4984bad 2675 {
6bec29c9
DC
2676 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2677 {
2678 *l = 4;
2679 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
2680 AS2 (ldi,%B0,hi8(%1)) CR_TAB
2681 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2682 AS2 (ldi,%D0,hhi8(%1)));
2683 }
6bec29c9
DC
2684 /* Last resort, better than loading from memory. */
2685 *l = 10;
2686 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2687 AS2 (ldi,r31,lo8(%1)) CR_TAB
2688 AS2 (mov,%A0,r31) CR_TAB
2689 AS2 (ldi,r31,hi8(%1)) CR_TAB
2690 AS2 (mov,%B0,r31) CR_TAB
2691 AS2 (ldi,r31,hlo8(%1)) CR_TAB
2692 AS2 (mov,%C0,r31) CR_TAB
2693 AS2 (ldi,r31,hhi8(%1)) CR_TAB
2694 AS2 (mov,%D0,r31) CR_TAB
2695 AS2 (mov,r31,__tmp_reg__));
2696 }
2697 else if (GET_CODE (src) == MEM)
2698 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2699 }
2700 else if (GET_CODE (dest) == MEM)
2701 {
0a2aaacc 2702 const char *templ;
5fecfd8d 2703
1e6a67d1 2704 if (src == CONST0_RTX (GET_MODE (dest)))
6bec29c9 2705 operands[1] = zero_reg_rtx;
5fecfd8d 2706
0a2aaacc 2707 templ = out_movsi_mr_r (insn, operands, real_l);
6bec29c9
DC
2708
2709 if (!real_l)
0a2aaacc 2710 output_asm_insn (templ, operands);
5fecfd8d
MM
2711
2712 operands[1] = src;
6bec29c9 2713 return "";
90e7678c 2714 }
c725bd79 2715 fatal_insn ("invalid insn:", insn);
90e7678c
DC
2716 return "";
2717}
2718
5fecfd8d 2719const char *
269e3795 2720out_movqi_mr_r (rtx insn, rtx op[], int *l)
90e7678c 2721{
5fecfd8d
MM
2722 rtx dest = op[0];
2723 rtx src = op[1];
2724 rtx x = XEXP (dest, 0);
6bec29c9 2725 int dummy;
90e7678c 2726
6bec29c9
DC
2727 if (!l)
2728 l = &dummy;
6bec29c9
DC
2729
2730 if (CONSTANT_ADDRESS_P (x))
90e7678c 2731 {
4fc2b4ff
AH
2732 if (CONST_INT_P (x) && INTVAL (x) == SREG_ADDR)
2733 {
2734 *l = 1;
2735 return AS2 (out,__SREG__,%1);
2736 }
e6b69d0e 2737 if (optimize > 0 && io_address_operand (x, QImode))
6bec29c9
DC
2738 {
2739 *l = 1;
846428f1 2740 return AS2 (out,%m0-0x20,%1);
6bec29c9
DC
2741 }
2742 *l = 2;
846428f1 2743 return AS2 (sts,%m0,%1);
6bec29c9
DC
2744 }
2745 /* memory access by reg+disp */
2746 else if (GET_CODE (x) == PLUS
2747 && REG_P (XEXP (x,0))
2748 && GET_CODE (XEXP (x,1)) == CONST_INT)
2749 {
5fecfd8d 2750 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
90e7678c 2751 {
6bec29c9
DC
2752 int disp = INTVAL (XEXP (x,1));
2753 if (REGNO (XEXP (x,0)) != REG_Y)
c725bd79 2754 fatal_insn ("incorrect insn:",insn);
33d5e2dc 2755
5fecfd8d 2756 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
33d5e2dc
MM
2757 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2758 AS2 (std,Y+63,%1) CR_TAB
2759 AS2 (sbiw,r28,%o0-63));
2760
2761 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2762 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2763 AS2 (st,Y,%1) CR_TAB
2764 AS2 (subi,r28,lo8(%o0)) CR_TAB
2765 AS2 (sbci,r29,hi8(%o0)));
6bec29c9
DC
2766 }
2767 else if (REGNO (XEXP (x,0)) == REG_X)
2768 {
5fecfd8d 2769 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
6bec29c9
DC
2770 {
2771 if (reg_unused_after (insn, XEXP (x,0)))
33d5e2dc
MM
2772 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2773 AS2 (adiw,r26,%o0) CR_TAB
2774 AS2 (st,X,__tmp_reg__));
2775
2776 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2777 AS2 (adiw,r26,%o0) CR_TAB
2778 AS2 (st,X,__tmp_reg__) CR_TAB
2779 AS2 (sbiw,r26,%o0));
90e7678c 2780 }
6bec29c9 2781 else
90e7678c 2782 {
6bec29c9 2783 if (reg_unused_after (insn, XEXP (x,0)))
33d5e2dc
MM
2784 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2785 AS2 (st,X,%1));
2786
2787 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2788 AS2 (st,X,%1) CR_TAB
2789 AS2 (sbiw,r26,%o0));
90e7678c
DC
2790 }
2791 }
6bec29c9
DC
2792 *l = 1;
2793 return AS2 (std,%0,%1);
90e7678c 2794 }
6bec29c9
DC
2795 *l = 1;
2796 return AS2 (st,%0,%1);
90e7678c
DC
2797}
2798
5fecfd8d 2799const char *
269e3795 2800out_movhi_mr_r (rtx insn, rtx op[], int *l)
90e7678c 2801{
5fecfd8d
MM
2802 rtx dest = op[0];
2803 rtx src = op[1];
2804 rtx base = XEXP (dest, 0);
2805 int reg_base = true_regnum (base);
2806 int reg_src = true_regnum (src);
a6990185
MM
2807 /* "volatile" forces writing high byte first, even if less efficient,
2808 for correct operation with 16-bit I/O registers. */
2809 int mem_volatile_p = MEM_VOLATILE_P (dest);
90e7678c 2810 int tmp;
a6990185 2811
90e7678c
DC
2812 if (!l)
2813 l = &tmp;
5fecfd8d
MM
2814 if (CONSTANT_ADDRESS_P (base))
2815 {
e6b69d0e 2816 if (optimize > 0 && io_address_operand (base, HImode))
5fecfd8d
MM
2817 {
2818 *l = 2;
846428f1
AH
2819 return (AS2 (out,%m0+1-0x20,%B1) CR_TAB
2820 AS2 (out,%m0-0x20,%A1));
5fecfd8d 2821 }
846428f1
AH
2822 return *l = 4, (AS2 (sts,%m0+1,%B1) CR_TAB
2823 AS2 (sts,%m0,%A1));
5fecfd8d 2824 }
90e7678c
DC
2825 if (reg_base > 0)
2826 {
2827 if (reg_base == REG_X)
2828 {
5fecfd8d 2829 if (reg_src == REG_X)
90e7678c 2830 {
a6990185
MM
2831 /* "st X+,r26" and "st -X,r26" are undefined. */
2832 if (!mem_volatile_p && reg_unused_after (insn, src))
dfaf5abf
MM
2833 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2834 AS2 (st,X,r26) CR_TAB
2835 AS2 (adiw,r26,1) CR_TAB
2836 AS2 (st,X,__tmp_reg__));
90e7678c 2837 else
dfaf5abf 2838 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
dfaf5abf
MM
2839 AS2 (adiw,r26,1) CR_TAB
2840 AS2 (st,X,__tmp_reg__) CR_TAB
a6990185
MM
2841 AS2 (sbiw,r26,1) CR_TAB
2842 AS2 (st,X,r26));
90e7678c
DC
2843 }
2844 else
2845 {
a6990185 2846 if (!mem_volatile_p && reg_unused_after (insn, base))
90e7678c
DC
2847 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2848 AS2 (st,X,%B1));
2849 else
a6990185
MM
2850 return *l=3, (AS2 (adiw,r26,1) CR_TAB
2851 AS2 (st,X,%B1) CR_TAB
2852 AS2 (st,-X,%A1));
90e7678c
DC
2853 }
2854 }
2855 else
a6990185
MM
2856 return *l=2, (AS2 (std,%0+1,%B1) CR_TAB
2857 AS2 (st,%0,%A1));
90e7678c 2858 }
5fecfd8d 2859 else if (GET_CODE (base) == PLUS)
90e7678c 2860 {
5fecfd8d 2861 int disp = INTVAL (XEXP (base, 1));
dfaf5abf 2862 reg_base = REGNO (XEXP (base, 0));
5fecfd8d 2863 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
90e7678c 2864 {
dfaf5abf 2865 if (reg_base != REG_Y)
c725bd79 2866 fatal_insn ("incorrect insn:",insn);
33d5e2dc 2867
5fecfd8d 2868 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
33d5e2dc 2869 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
33d5e2dc 2870 AS2 (std,Y+63,%B1) CR_TAB
a6990185 2871 AS2 (std,Y+62,%A1) CR_TAB
33d5e2dc
MM
2872 AS2 (sbiw,r28,%o0-62));
2873
2874 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2875 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
33d5e2dc 2876 AS2 (std,Y+1,%B1) CR_TAB
a6990185 2877 AS2 (st,Y,%A1) CR_TAB
33d5e2dc
MM
2878 AS2 (subi,r28,lo8(%o0)) CR_TAB
2879 AS2 (sbci,r29,hi8(%o0)));
90e7678c 2880 }
dfaf5abf
MM
2881 if (reg_base == REG_X)
2882 {
2883 /* (X + d) = R */
2884 if (reg_src == REG_X)
a6990185 2885 {
dfaf5abf
MM
2886 *l = 7;
2887 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2888 AS2 (mov,__zero_reg__,r27) CR_TAB
a6990185 2889 AS2 (adiw,r26,%o0+1) CR_TAB
dfaf5abf 2890 AS2 (st,X,__zero_reg__) CR_TAB
a6990185 2891 AS2 (st,-X,__tmp_reg__) CR_TAB
dfaf5abf 2892 AS1 (clr,__zero_reg__) CR_TAB
a6990185 2893 AS2 (sbiw,r26,%o0));
dfaf5abf
MM
2894 }
2895 *l = 4;
a6990185
MM
2896 return (AS2 (adiw,r26,%o0+1) CR_TAB
2897 AS2 (st,X,%B1) CR_TAB
2898 AS2 (st,-X,%A1) CR_TAB
2899 AS2 (sbiw,r26,%o0));
dfaf5abf 2900 }
a6990185
MM
2901 return *l=2, (AS2 (std,%B0,%B1) CR_TAB
2902 AS2 (std,%A0,%A1));
6bec29c9 2903 }
5fecfd8d 2904 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
90e7678c
DC
2905 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2906 AS2 (st,%0,%A1));
5fecfd8d 2907 else if (GET_CODE (base) == POST_INC) /* (R++) */
a6990185
MM
2908 {
2909 if (mem_volatile_p)
2910 {
2911 if (REGNO (XEXP (base, 0)) == REG_X)
2912 {
2913 *l = 4;
2914 return (AS2 (adiw,r26,1) CR_TAB
2915 AS2 (st,X,%B1) CR_TAB
2916 AS2 (st,-X,%A1) CR_TAB
2917 AS2 (adiw,r26,2));
2918 }
2919 else
2920 {
2921 *l = 3;
2922 return (AS2 (std,%p0+1,%B1) CR_TAB
2923 AS2 (st,%p0,%A1) CR_TAB
2924 AS2 (adiw,%r0,2));
2925 }
2926 }
2927
2928 *l = 2;
2929 return (AS2 (st,%0,%A1) CR_TAB
2930 AS2 (st,%0,%B1));
2931 }
c725bd79 2932 fatal_insn ("unknown move insn:",insn);
90e7678c
DC
2933 return "";
2934}
2935
2c338472 2936/* Return 1 if frame pointer for current function required. */
90e7678c 2937
c21ca196
AS
2938bool
2939avr_frame_pointer_required_p (void)
90e7678c 2940{
e3b5732b 2941 return (cfun->calls_alloca
38173d38 2942 || crtl->args.info.nregs == 0
90e7678c
DC
2943 || get_frame_size () > 0);
2944}
2945
89741abb 2946/* Returns the condition of compare insn INSN, or UNKNOWN. */
90e7678c 2947
89741abb 2948static RTX_CODE
269e3795 2949compare_condition (rtx insn)
90e7678c
DC
2950{
2951 rtx next = next_real_insn (insn);
f3713778
GJL
2952
2953 if (next && JUMP_P (next))
90e7678c
DC
2954 {
2955 rtx pat = PATTERN (next);
2956 rtx src = SET_SRC (pat);
f3713778
GJL
2957
2958 if (IF_THEN_ELSE == GET_CODE (src))
2959 return GET_CODE (XEXP (src, 0));
90e7678c 2960 }
f3713778
GJL
2961
2962 return UNKNOWN;
89741abb
MM
2963}
2964
2965/* Returns nonzero if INSN is a tst insn that only tests the sign. */
2966
2967static int
269e3795 2968compare_sign_p (rtx insn)
89741abb
MM
2969{
2970 RTX_CODE cond = compare_condition (insn);
2971 return (cond == GE || cond == LT);
2972}
2973
2974/* Returns nonzero if the next insn is a JUMP_INSN with a condition
2975 that needs to be swapped (GT, GTU, LE, LEU). */
2976
2977int
269e3795 2978compare_diff_p (rtx insn)
89741abb
MM
2979{
2980 RTX_CODE cond = compare_condition (insn);
90e7678c
DC
2981 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2982}
2983
89741abb 2984/* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
90e7678c
DC
2985
2986int
269e3795 2987compare_eq_p (rtx insn)
90e7678c 2988{
89741abb 2989 RTX_CODE cond = compare_condition (insn);
90e7678c
DC
2990 return (cond == EQ || cond == NE);
2991}
2992
2993
2c338472 2994/* Output test instruction for HImode. */
90e7678c 2995
5fecfd8d 2996const char *
f90b7a5a 2997out_tsthi (rtx insn, rtx op, int *l)
90e7678c 2998{
89741abb 2999 if (compare_sign_p (insn))
90e7678c
DC
3000 {
3001 if (l) *l = 1;
3002 return AS1 (tst,%B0);
3003 }
f90b7a5a 3004 if (reg_unused_after (insn, op)
89741abb 3005 && compare_eq_p (insn))
90e7678c 3006 {
2c338472 3007 /* Faster than sbiw if we can clobber the operand. */
90e7678c 3008 if (l) *l = 1;
5a82ecd9 3009 return "or %A0,%B0";
90e7678c 3010 }
f90b7a5a 3011 if (test_hard_reg_class (ADDW_REGS, op))
90e7678c
DC
3012 {
3013 if (l) *l = 1;
5fecfd8d 3014 return AS2 (sbiw,%0,0);
90e7678c
DC
3015 }
3016 if (l) *l = 2;
3017 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
3018 AS2 (cpc,%B0,__zero_reg__));
3019}
3020
3021
2c338472 3022/* Output test instruction for SImode. */
90e7678c 3023
5fecfd8d 3024const char *
f90b7a5a 3025out_tstsi (rtx insn, rtx op, int *l)
90e7678c 3026{
89741abb 3027 if (compare_sign_p (insn))
90e7678c
DC
3028 {
3029 if (l) *l = 1;
3030 return AS1 (tst,%D0);
3031 }
f90b7a5a 3032 if (test_hard_reg_class (ADDW_REGS, op))
90e7678c
DC
3033 {
3034 if (l) *l = 3;
3035 return (AS2 (sbiw,%A0,0) CR_TAB
3036 AS2 (cpc,%C0,__zero_reg__) CR_TAB
3037 AS2 (cpc,%D0,__zero_reg__));
3038 }
3039 if (l) *l = 4;
3040 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
3041 AS2 (cpc,%B0,__zero_reg__) CR_TAB
3042 AS2 (cpc,%C0,__zero_reg__) CR_TAB
3043 AS2 (cpc,%D0,__zero_reg__));
3044}
3045
3046
afee2a52
MM
3047/* Generate asm equivalent for various shifts.
3048 Shift count is a CONST_INT, MEM or REG.
3049 This only handles cases that are not already
3050 carefully hand-optimized in ?sh??i3_out. */
90e7678c
DC
3051
3052void
0a2aaacc 3053out_shift_with_cnt (const char *templ, rtx insn, rtx operands[],
269e3795 3054 int *len, int t_len)
90e7678c
DC
3055{
3056 rtx op[10];
afee2a52 3057 char str[500];
0db7ad3a 3058 int second_label = 1;
afee2a52
MM
3059 int saved_in_tmp = 0;
3060 int use_zero_reg = 0;
3061
90e7678c
DC
3062 op[0] = operands[0];
3063 op[1] = operands[1];
3064 op[2] = operands[2];
3065 op[3] = operands[3];
3066 str[0] = 0;
afee2a52
MM
3067
3068 if (len)
3069 *len = 1;
3070
3071 if (GET_CODE (operands[2]) == CONST_INT)
90e7678c 3072 {
afee2a52
MM
3073 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3074 int count = INTVAL (operands[2]);
3075 int max_len = 10; /* If larger than this, always use a loop. */
3076
a3cf5992
MM
3077 if (count <= 0)
3078 {
3079 if (len)
3080 *len = 0;
3081 return;
3082 }
3083
afee2a52
MM
3084 if (count < 8 && !scratch)
3085 use_zero_reg = 1;
3086
3087 if (optimize_size)
3088 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
3089
3090 if (t_len * count <= max_len)
3091 {
3092 /* Output shifts inline with no loop - faster. */
3093 if (len)
3094 *len = t_len * count;
3095 else
3096 {
3097 while (count-- > 0)
0a2aaacc 3098 output_asm_insn (templ, op);
afee2a52
MM
3099 }
3100
3101 return;
3102 }
3103
3104 if (scratch)
3105 {
3106 if (!len)
3107 strcat (str, AS2 (ldi,%3,%2));
3108 }
3109 else if (use_zero_reg)
3110 {
3111 /* Hack to save one word: use __zero_reg__ as loop counter.
3112 Set one bit, then shift in a loop until it is 0 again. */
3113
3114 op[3] = zero_reg_rtx;
3115 if (len)
3116 *len = 2;
3117 else
3118 strcat (str, ("set" CR_TAB
3119 AS2 (bld,%3,%2-1)));
3120 }
90e7678c 3121 else
afee2a52
MM
3122 {
3123 /* No scratch register available, use one from LD_REGS (saved in
3124 __tmp_reg__) that doesn't overlap with registers to shift. */
3125
f1c25d3b 3126 op[3] = gen_rtx_REG (QImode,
afee2a52
MM
3127 ((true_regnum (operands[0]) - 1) & 15) + 16);
3128 op[4] = tmp_reg_rtx;
3129 saved_in_tmp = 1;
3130
3131 if (len)
3132 *len = 3; /* Includes "mov %3,%4" after the loop. */
3133 else
3134 strcat (str, (AS2 (mov,%4,%3) CR_TAB
3135 AS2 (ldi,%3,%2)));
3136 }
3137
0db7ad3a 3138 second_label = 0;
90e7678c
DC
3139 }
3140 else if (GET_CODE (operands[2]) == MEM)
3141 {
90e7678c 3142 rtx op_mov[10];
0db7ad3a 3143
90e7678c
DC
3144 op[3] = op_mov[0] = tmp_reg_rtx;
3145 op_mov[1] = op[2];
afee2a52
MM
3146
3147 if (len)
3148 out_movqi_r_mr (insn, op_mov, len);
90e7678c 3149 else
afee2a52 3150 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
90e7678c 3151 }
c4984bad 3152 else if (register_operand (operands[2], QImode))
90e7678c 3153 {
f4da258f
GJL
3154 if (reg_unused_after (insn, operands[2])
3155 && !reg_overlap_mentioned_p (operands[0], operands[2]))
3156 {
3157 op[3] = op[2];
3158 }
90e7678c
DC
3159 else
3160 {
3161 op[3] = tmp_reg_rtx;
afee2a52
MM
3162 if (!len)
3163 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
90e7678c 3164 }
afee2a52
MM
3165 }
3166 else
c725bd79 3167 fatal_insn ("bad shift insn:", insn);
afee2a52
MM
3168
3169 if (second_label)
3170 {
0db7ad3a
DC
3171 if (len)
3172 ++*len;
3173 else
3174 strcat (str, AS1 (rjmp,2f));
90e7678c 3175 }
afee2a52
MM
3176
3177 if (len)
3178 *len += t_len + 2; /* template + dec + brXX */
3179 else
90e7678c 3180 {
80b8585d 3181 strcat (str, "\n1:\t");
0a2aaacc 3182 strcat (str, templ);
0db7ad3a 3183 strcat (str, second_label ? "\n2:\t" : "\n\t");
afee2a52
MM
3184 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
3185 strcat (str, CR_TAB);
3186 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
3187 if (saved_in_tmp)
3188 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
90e7678c
DC
3189 output_asm_insn (str, op);
3190 }
3191}
3192
3193
3194/* 8bit shift left ((char)x << i) */
3195
5fecfd8d 3196const char *
269e3795 3197ashlqi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
3198{
3199 if (GET_CODE (operands[2]) == CONST_INT)
3200 {
3201 int k;
3454eb73 3202
90e7678c
DC
3203 if (!len)
3204 len = &k;
3454eb73 3205
90e7678c
DC
3206 switch (INTVAL (operands[2]))
3207 {
3454eb73 3208 default:
a3cf5992
MM
3209 if (INTVAL (operands[2]) < 8)
3210 break;
3211
3454eb73
DC
3212 *len = 1;
3213 return AS1 (clr,%0);
3214
90e7678c 3215 case 1:
3454eb73 3216 *len = 1;
90e7678c 3217 return AS1 (lsl,%0);
3454eb73 3218
90e7678c 3219 case 2:
3454eb73 3220 *len = 2;
90e7678c
DC
3221 return (AS1 (lsl,%0) CR_TAB
3222 AS1 (lsl,%0));
3454eb73 3223
90e7678c 3224 case 3:
3454eb73 3225 *len = 3;
90e7678c
DC
3226 return (AS1 (lsl,%0) CR_TAB
3227 AS1 (lsl,%0) CR_TAB
3228 AS1 (lsl,%0));
3454eb73 3229
90e7678c 3230 case 4:
c4984bad 3231 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c 3232 {
3454eb73 3233 *len = 2;
90e7678c
DC
3234 return (AS1 (swap,%0) CR_TAB
3235 AS2 (andi,%0,0xf0));
3236 }
3454eb73 3237 *len = 4;
90e7678c
DC
3238 return (AS1 (lsl,%0) CR_TAB
3239 AS1 (lsl,%0) CR_TAB
3240 AS1 (lsl,%0) CR_TAB
3241 AS1 (lsl,%0));
3454eb73 3242
90e7678c 3243 case 5:
c4984bad 3244 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c 3245 {
3454eb73 3246 *len = 3;
90e7678c
DC
3247 return (AS1 (swap,%0) CR_TAB
3248 AS1 (lsl,%0) CR_TAB
3249 AS2 (andi,%0,0xe0));
3250 }
3454eb73 3251 *len = 5;
90e7678c
DC
3252 return (AS1 (lsl,%0) CR_TAB
3253 AS1 (lsl,%0) CR_TAB
3254 AS1 (lsl,%0) CR_TAB
3255 AS1 (lsl,%0) CR_TAB
3256 AS1 (lsl,%0));
3454eb73 3257
90e7678c 3258 case 6:
c4984bad 3259 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c 3260 {
3454eb73 3261 *len = 4;
90e7678c
DC
3262 return (AS1 (swap,%0) CR_TAB
3263 AS1 (lsl,%0) CR_TAB
3264 AS1 (lsl,%0) CR_TAB
3265 AS2 (andi,%0,0xc0));
3266 }
3454eb73 3267 *len = 6;
90e7678c
DC
3268 return (AS1 (lsl,%0) CR_TAB
3269 AS1 (lsl,%0) CR_TAB
3270 AS1 (lsl,%0) CR_TAB
3271 AS1 (lsl,%0) CR_TAB
3272 AS1 (lsl,%0) CR_TAB
3273 AS1 (lsl,%0));
3454eb73 3274
90e7678c 3275 case 7:
3454eb73 3276 *len = 3;
90e7678c
DC
3277 return (AS1 (ror,%0) CR_TAB
3278 AS1 (clr,%0) CR_TAB
3279 AS1 (ror,%0));
3280 }
3281 }
3454eb73 3282 else if (CONSTANT_P (operands[2]))
c725bd79 3283 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3454eb73 3284
0db7ad3a 3285 out_shift_with_cnt (AS1 (lsl,%0),
afee2a52 3286 insn, operands, len, 1);
90e7678c
DC
3287 return "";
3288}
3289
3290
3291/* 16bit shift left ((short)x << i) */
3292
5fecfd8d 3293const char *
269e3795 3294ashlhi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
3295{
3296 if (GET_CODE (operands[2]) == CONST_INT)
3297 {
afee2a52
MM
3298 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3299 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
90e7678c 3300 int k;
afee2a52 3301 int *t = len;
3454eb73 3302
90e7678c
DC
3303 if (!len)
3304 len = &k;
3454eb73 3305
90e7678c
DC
3306 switch (INTVAL (operands[2]))
3307 {
a3cf5992
MM
3308 default:
3309 if (INTVAL (operands[2]) < 16)
3310 break;
3311
3312 *len = 2;
3313 return (AS1 (clr,%B0) CR_TAB
3314 AS1 (clr,%A0));
3315
afee2a52
MM
3316 case 4:
3317 if (optimize_size && scratch)
3318 break; /* 5 */
3319 if (ldi_ok)
3320 {
3321 *len = 6;
3322 return (AS1 (swap,%A0) CR_TAB
3323 AS1 (swap,%B0) CR_TAB
3324 AS2 (andi,%B0,0xf0) CR_TAB
3325 AS2 (eor,%B0,%A0) CR_TAB
3326 AS2 (andi,%A0,0xf0) CR_TAB
3327 AS2 (eor,%B0,%A0));
3328 }
3329 if (scratch)
3330 {
3331 *len = 7;
3332 return (AS1 (swap,%A0) CR_TAB
3333 AS1 (swap,%B0) CR_TAB
3334 AS2 (ldi,%3,0xf0) CR_TAB
5a82ecd9 3335 "and %B0,%3" CR_TAB
afee2a52 3336 AS2 (eor,%B0,%A0) CR_TAB
5a82ecd9 3337 "and %A0,%3" CR_TAB
afee2a52
MM
3338 AS2 (eor,%B0,%A0));
3339 }
3340 break; /* optimize_size ? 6 : 8 */
3454eb73 3341
afee2a52
MM
3342 case 5:
3343 if (optimize_size)
3344 break; /* scratch ? 5 : 6 */
3345 if (ldi_ok)
3346 {
3347 *len = 8;
3348 return (AS1 (lsl,%A0) CR_TAB
3349 AS1 (rol,%B0) CR_TAB
3350 AS1 (swap,%A0) CR_TAB
3351 AS1 (swap,%B0) CR_TAB
3352 AS2 (andi,%B0,0xf0) CR_TAB
3353 AS2 (eor,%B0,%A0) CR_TAB
3354 AS2 (andi,%A0,0xf0) CR_TAB
3355 AS2 (eor,%B0,%A0));
3356 }
3357 if (scratch)
3358 {
3359 *len = 9;
3360 return (AS1 (lsl,%A0) CR_TAB
3361 AS1 (rol,%B0) CR_TAB
3362 AS1 (swap,%A0) CR_TAB
3363 AS1 (swap,%B0) CR_TAB
3364 AS2 (ldi,%3,0xf0) CR_TAB
5a82ecd9 3365 "and %B0,%3" CR_TAB
afee2a52 3366 AS2 (eor,%B0,%A0) CR_TAB
5a82ecd9 3367 "and %A0,%3" CR_TAB
afee2a52
MM
3368 AS2 (eor,%B0,%A0));
3369 }
3370 break; /* 10 */
3371
3372 case 6:
3373 if (optimize_size)
3374 break; /* scratch ? 5 : 6 */
3375 *len = 9;
3376 return (AS1 (clr,__tmp_reg__) CR_TAB
3377 AS1 (lsr,%B0) CR_TAB
3378 AS1 (ror,%A0) CR_TAB
3379 AS1 (ror,__tmp_reg__) CR_TAB
3380 AS1 (lsr,%B0) CR_TAB
3381 AS1 (ror,%A0) CR_TAB
3382 AS1 (ror,__tmp_reg__) CR_TAB
3383 AS2 (mov,%B0,%A0) CR_TAB
3384 AS2 (mov,%A0,__tmp_reg__));
3454eb73 3385
adcd8f77
MM
3386 case 7:
3387 *len = 5;
3388 return (AS1 (lsr,%B0) CR_TAB
3389 AS2 (mov,%B0,%A0) CR_TAB
3390 AS1 (clr,%A0) CR_TAB
3391 AS1 (ror,%B0) CR_TAB
3392 AS1 (ror,%A0));
3393
90e7678c 3394 case 8:
120b24f7
AS
3395 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3396 AS1 (clr,%A0));
adcd8f77
MM
3397
3398 case 9:
3399 *len = 3;
3400 return (AS2 (mov,%B0,%A0) CR_TAB
3401 AS1 (clr,%A0) CR_TAB
3402 AS1 (lsl,%B0));
3403
3404 case 10:
3405 *len = 4;
3406 return (AS2 (mov,%B0,%A0) CR_TAB
3407 AS1 (clr,%A0) CR_TAB
3408 AS1 (lsl,%B0) CR_TAB
3409 AS1 (lsl,%B0));
3410
3411 case 11:
3412 *len = 5;
3413 return (AS2 (mov,%B0,%A0) CR_TAB
3414 AS1 (clr,%A0) CR_TAB
3415 AS1 (lsl,%B0) CR_TAB
3416 AS1 (lsl,%B0) CR_TAB
3417 AS1 (lsl,%B0));
3418
3419 case 12:
afee2a52 3420 if (ldi_ok)
adcd8f77
MM
3421 {
3422 *len = 4;
3423 return (AS2 (mov,%B0,%A0) CR_TAB
3424 AS1 (clr,%A0) CR_TAB
3425 AS1 (swap,%B0) CR_TAB
3426 AS2 (andi,%B0,0xf0));
3427 }
afee2a52
MM
3428 if (scratch)
3429 {
3430 *len = 5;
3431 return (AS2 (mov,%B0,%A0) CR_TAB
3432 AS1 (clr,%A0) CR_TAB
3433 AS1 (swap,%B0) CR_TAB
3434 AS2 (ldi,%3,0xf0) CR_TAB
5a82ecd9 3435 "and %B0,%3");
afee2a52
MM
3436 }
3437 *len = 6;
adcd8f77
MM
3438 return (AS2 (mov,%B0,%A0) CR_TAB
3439 AS1 (clr,%A0) CR_TAB
afee2a52
MM
3440 AS1 (lsl,%B0) CR_TAB
3441 AS1 (lsl,%B0) CR_TAB
3442 AS1 (lsl,%B0) CR_TAB
3443 AS1 (lsl,%B0));
adcd8f77
MM
3444
3445 case 13:
afee2a52 3446 if (ldi_ok)
adcd8f77
MM
3447 {
3448 *len = 5;
3449 return (AS2 (mov,%B0,%A0) CR_TAB
3450 AS1 (clr,%A0) CR_TAB
3451 AS1 (swap,%B0) CR_TAB
3452 AS1 (lsl,%B0) CR_TAB
3453 AS2 (andi,%B0,0xe0));
3454 }
dd6d1f8c 3455 if (AVR_HAVE_MUL && scratch)
adcd8f77
MM
3456 {
3457 *len = 5;
3458 return (AS2 (ldi,%3,0x20) CR_TAB
3459 AS2 (mul,%A0,%3) CR_TAB
3460 AS2 (mov,%B0,r0) CR_TAB
3461 AS1 (clr,%A0) CR_TAB
3462 AS1 (clr,__zero_reg__));
3463 }
afee2a52
MM
3464 if (optimize_size && scratch)
3465 break; /* 5 */
3466 if (scratch)
3467 {
3468 *len = 6;
3469 return (AS2 (mov,%B0,%A0) CR_TAB
3470 AS1 (clr,%A0) CR_TAB
3471 AS1 (swap,%B0) CR_TAB
3472 AS1 (lsl,%B0) CR_TAB
3473 AS2 (ldi,%3,0xe0) CR_TAB
5a82ecd9 3474 "and %B0,%3");
afee2a52 3475 }
dd6d1f8c 3476 if (AVR_HAVE_MUL)
afee2a52
MM
3477 {
3478 *len = 6;
3479 return ("set" CR_TAB
3480 AS2 (bld,r1,5) CR_TAB
3481 AS2 (mul,%A0,r1) CR_TAB
3482 AS2 (mov,%B0,r0) CR_TAB
3483 AS1 (clr,%A0) CR_TAB
3484 AS1 (clr,__zero_reg__));
3485 }
3486 *len = 7;
3487 return (AS2 (mov,%B0,%A0) CR_TAB
3488 AS1 (clr,%A0) CR_TAB
3489 AS1 (lsl,%B0) CR_TAB
3490 AS1 (lsl,%B0) CR_TAB
3491 AS1 (lsl,%B0) CR_TAB
3492 AS1 (lsl,%B0) CR_TAB
3493 AS1 (lsl,%B0));
adcd8f77
MM
3494
3495 case 14:
dd6d1f8c 3496 if (AVR_HAVE_MUL && ldi_ok)
afee2a52
MM
3497 {
3498 *len = 5;
3499 return (AS2 (ldi,%B0,0x40) CR_TAB
3500 AS2 (mul,%A0,%B0) CR_TAB
3501 AS2 (mov,%B0,r0) CR_TAB
3502 AS1 (clr,%A0) CR_TAB
3503 AS1 (clr,__zero_reg__));
3504 }
dd6d1f8c 3505 if (AVR_HAVE_MUL && scratch)
adcd8f77
MM
3506 {
3507 *len = 5;
3508 return (AS2 (ldi,%3,0x40) CR_TAB
3509 AS2 (mul,%A0,%3) CR_TAB
3510 AS2 (mov,%B0,r0) CR_TAB
3511 AS1 (clr,%A0) CR_TAB
3512 AS1 (clr,__zero_reg__));
3513 }
afee2a52
MM
3514 if (optimize_size && ldi_ok)
3515 {
3516 *len = 5;
3517 return (AS2 (mov,%B0,%A0) CR_TAB
3518 AS2 (ldi,%A0,6) "\n1:\t"
3519 AS1 (lsl,%B0) CR_TAB
3520 AS1 (dec,%A0) CR_TAB
3521 AS1 (brne,1b));
3522 }
3523 if (optimize_size && scratch)
3524 break; /* 5 */
3525 *len = 6;
3526 return (AS1 (clr,%B0) CR_TAB
3527 AS1 (lsr,%A0) CR_TAB
3528 AS1 (ror,%B0) CR_TAB
3529 AS1 (lsr,%A0) CR_TAB
3530 AS1 (ror,%B0) CR_TAB
3531 AS1 (clr,%A0));
adcd8f77
MM
3532
3533 case 15:
3534 *len = 4;
3535 return (AS1 (clr,%B0) CR_TAB
3536 AS1 (lsr,%A0) CR_TAB
3537 AS1 (ror,%B0) CR_TAB
3538 AS1 (clr,%A0));
90e7678c 3539 }
adcd8f77 3540 len = t;
90e7678c 3541 }
afee2a52
MM
3542 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3543 AS1 (rol,%B0)),
3544 insn, operands, len, 2);
90e7678c
DC
3545 return "";
3546}
3547
3548
3549/* 32bit shift left ((long)x << i) */
3550
5fecfd8d 3551const char *
269e3795 3552ashlsi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
3553{
3554 if (GET_CODE (operands[2]) == CONST_INT)
3555 {
3556 int k;
afee2a52 3557 int *t = len;
3454eb73 3558
90e7678c
DC
3559 if (!len)
3560 len = &k;
3454eb73 3561
90e7678c
DC
3562 switch (INTVAL (operands[2]))
3563 {
a3cf5992
MM
3564 default:
3565 if (INTVAL (operands[2]) < 32)
3566 break;
3567
4301ec4f 3568 if (AVR_HAVE_MOVW)
a3cf5992
MM
3569 return *len = 3, (AS1 (clr,%D0) CR_TAB
3570 AS1 (clr,%C0) CR_TAB
3571 AS2 (movw,%A0,%C0));
3572 *len = 4;
3573 return (AS1 (clr,%D0) CR_TAB
3574 AS1 (clr,%C0) CR_TAB
3575 AS1 (clr,%B0) CR_TAB
3576 AS1 (clr,%A0));
3577
90e7678c
DC
3578 case 8:
3579 {
3580 int reg0 = true_regnum (operands[0]);
3581 int reg1 = true_regnum (operands[1]);
3454eb73 3582 *len = 4;
90e7678c
DC
3583 if (reg0 >= reg1)
3584 return (AS2 (mov,%D0,%C1) CR_TAB
3585 AS2 (mov,%C0,%B1) CR_TAB
3586 AS2 (mov,%B0,%A1) CR_TAB
3587 AS1 (clr,%A0));
90e7678c
DC
3588 else
3589 return (AS1 (clr,%A0) CR_TAB
3590 AS2 (mov,%B0,%A1) CR_TAB
3591 AS2 (mov,%C0,%B1) CR_TAB
3592 AS2 (mov,%D0,%C1));
3593 }
3454eb73 3594
90e7678c
DC
3595 case 16:
3596 {
3597 int reg0 = true_regnum (operands[0]);
3598 int reg1 = true_regnum (operands[1]);
90e7678c 3599 if (reg0 + 2 == reg1)
120b24f7
AS
3600 return *len = 2, (AS1 (clr,%B0) CR_TAB
3601 AS1 (clr,%A0));
3602 if (AVR_HAVE_MOVW)
3603 return *len = 3, (AS2 (movw,%C0,%A1) CR_TAB
3604 AS1 (clr,%B0) CR_TAB
3605 AS1 (clr,%A0));
90e7678c 3606 else
120b24f7
AS
3607 return *len = 4, (AS2 (mov,%C0,%A1) CR_TAB
3608 AS2 (mov,%D0,%B1) CR_TAB
3609 AS1 (clr,%B0) CR_TAB
3610 AS1 (clr,%A0));
90e7678c 3611 }
3454eb73 3612
90e7678c 3613 case 24:
3454eb73 3614 *len = 4;
120b24f7
AS
3615 return (AS2 (mov,%D0,%A1) CR_TAB
3616 AS1 (clr,%C0) CR_TAB
3617 AS1 (clr,%B0) CR_TAB
3618 AS1 (clr,%A0));
adcd8f77
MM
3619
3620 case 31:
3621 *len = 6;
3622 return (AS1 (clr,%D0) CR_TAB
3623 AS1 (lsr,%A0) CR_TAB
3624 AS1 (ror,%D0) CR_TAB
3625 AS1 (clr,%C0) CR_TAB
3626 AS1 (clr,%B0) CR_TAB
3627 AS1 (clr,%A0));
90e7678c 3628 }
adcd8f77 3629 len = t;
90e7678c 3630 }
afee2a52
MM
3631 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3632 AS1 (rol,%B0) CR_TAB
3633 AS1 (rol,%C0) CR_TAB
3634 AS1 (rol,%D0)),
3635 insn, operands, len, 4);
90e7678c
DC
3636 return "";
3637}
3638
3639/* 8bit arithmetic shift right ((signed char)x >> i) */
3640
5fecfd8d 3641const char *
269e3795 3642ashrqi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
3643{
3644 if (GET_CODE (operands[2]) == CONST_INT)
3645 {
90e7678c 3646 int k;
3454eb73 3647
90e7678c
DC
3648 if (!len)
3649 len = &k;
3454eb73 3650
90e7678c
DC
3651 switch (INTVAL (operands[2]))
3652 {
90e7678c 3653 case 1:
3454eb73 3654 *len = 1;
90e7678c 3655 return AS1 (asr,%0);
3454eb73 3656
90e7678c 3657 case 2:
3454eb73 3658 *len = 2;
90e7678c
DC
3659 return (AS1 (asr,%0) CR_TAB
3660 AS1 (asr,%0));
3454eb73 3661
90e7678c 3662 case 3:
3454eb73 3663 *len = 3;
90e7678c
DC
3664 return (AS1 (asr,%0) CR_TAB
3665 AS1 (asr,%0) CR_TAB
3666 AS1 (asr,%0));
3454eb73 3667
90e7678c 3668 case 4:
3454eb73
DC
3669 *len = 4;
3670 return (AS1 (asr,%0) CR_TAB
3671 AS1 (asr,%0) CR_TAB
3672 AS1 (asr,%0) CR_TAB
3673 AS1 (asr,%0));
3674
3675 case 5:
3676 *len = 5;
90e7678c 3677 return (AS1 (asr,%0) CR_TAB
3454eb73 3678 AS1 (asr,%0) CR_TAB
90e7678c
DC
3679 AS1 (asr,%0) CR_TAB
3680 AS1 (asr,%0) CR_TAB
3681 AS1 (asr,%0));
3454eb73
DC
3682
3683 case 6:
3684 *len = 4;
3685 return (AS2 (bst,%0,6) CR_TAB
3686 AS1 (lsl,%0) CR_TAB
3687 AS2 (sbc,%0,%0) CR_TAB
3688 AS2 (bld,%0,0));
3689
3690 default:
a3cf5992
MM
3691 if (INTVAL (operands[2]) < 8)
3692 break;
3693
3694 /* fall through */
3695
3454eb73
DC
3696 case 7:
3697 *len = 2;
3698 return (AS1 (lsl,%0) CR_TAB
3699 AS2 (sbc,%0,%0));
90e7678c
DC
3700 }
3701 }
3454eb73 3702 else if (CONSTANT_P (operands[2]))
c725bd79 3703 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3454eb73 3704
0db7ad3a 3705 out_shift_with_cnt (AS1 (asr,%0),
afee2a52 3706 insn, operands, len, 1);
90e7678c
DC
3707 return "";
3708}
3709
3710
3711/* 16bit arithmetic shift right ((signed short)x >> i) */
3712
5fecfd8d 3713const char *
269e3795 3714ashrhi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
3715{
3716 if (GET_CODE (operands[2]) == CONST_INT)
3717 {
afee2a52
MM
3718 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3719 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
90e7678c 3720 int k;
3454eb73
DC
3721 int *t = len;
3722
90e7678c
DC
3723 if (!len)
3724 len = &k;
3454eb73 3725
90e7678c
DC
3726 switch (INTVAL (operands[2]))
3727 {
afee2a52
MM
3728 case 4:
3729 case 5:
3730 /* XXX try to optimize this too? */
3731 break;
3454eb73 3732
afee2a52
MM
3733 case 6:
3734 if (optimize_size)
3735 break; /* scratch ? 5 : 6 */
3736 *len = 8;
3737 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3738 AS2 (mov,%A0,%B0) CR_TAB
3739 AS1 (lsl,__tmp_reg__) CR_TAB
3740 AS1 (rol,%A0) CR_TAB
3741 AS2 (sbc,%B0,%B0) CR_TAB
3742 AS1 (lsl,__tmp_reg__) CR_TAB
3743 AS1 (rol,%A0) CR_TAB
3744 AS1 (rol,%B0));
3454eb73 3745
adcd8f77
MM
3746 case 7:
3747 *len = 4;
3748 return (AS1 (lsl,%A0) CR_TAB
3749 AS2 (mov,%A0,%B0) CR_TAB
3750 AS1 (rol,%A0) CR_TAB
3751 AS2 (sbc,%B0,%B0));
3752
90e7678c 3753 case 8:
afee2a52
MM
3754 {
3755 int reg0 = true_regnum (operands[0]);
3756 int reg1 = true_regnum (operands[1]);
3757
3758 if (reg0 == reg1)
3759 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3760 AS1 (lsl,%B0) CR_TAB
3761 AS2 (sbc,%B0,%B0));
120b24f7
AS
3762 else
3763 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3764 AS1 (clr,%B0) CR_TAB
3765 AS2 (sbrc,%A0,7) CR_TAB
3766 AS1 (dec,%B0));
afee2a52 3767 }
3454eb73 3768
adcd8f77
MM
3769 case 9:
3770 *len = 4;
3771 return (AS2 (mov,%A0,%B0) CR_TAB
3772 AS1 (lsl,%B0) CR_TAB
3773 AS2 (sbc,%B0,%B0) CR_TAB
3774 AS1 (asr,%A0));
3775
3776 case 10:
3777 *len = 5;
3778 return (AS2 (mov,%A0,%B0) CR_TAB
3779 AS1 (lsl,%B0) CR_TAB
3780 AS2 (sbc,%B0,%B0) CR_TAB
3781 AS1 (asr,%A0) CR_TAB
3782 AS1 (asr,%A0));
3783
3784 case 11:
dd6d1f8c 3785 if (AVR_HAVE_MUL && ldi_ok)
adcd8f77
MM
3786 {
3787 *len = 5;
afee2a52
MM
3788 return (AS2 (ldi,%A0,0x20) CR_TAB
3789 AS2 (muls,%B0,%A0) CR_TAB
3790 AS2 (mov,%A0,r1) CR_TAB
3791 AS2 (sbc,%B0,%B0) CR_TAB
adcd8f77
MM
3792 AS1 (clr,__zero_reg__));
3793 }
afee2a52
MM
3794 if (optimize_size && scratch)
3795 break; /* 5 */
3796 *len = 6;
3797 return (AS2 (mov,%A0,%B0) CR_TAB
3798 AS1 (lsl,%B0) CR_TAB
3799 AS2 (sbc,%B0,%B0) CR_TAB
3800 AS1 (asr,%A0) CR_TAB
3801 AS1 (asr,%A0) CR_TAB
3802 AS1 (asr,%A0));
adcd8f77
MM
3803
3804 case 12:
dd6d1f8c 3805 if (AVR_HAVE_MUL && ldi_ok)
adcd8f77
MM
3806 {
3807 *len = 5;
afee2a52
MM
3808 return (AS2 (ldi,%A0,0x10) CR_TAB
3809 AS2 (muls,%B0,%A0) CR_TAB
3810 AS2 (mov,%A0,r1) CR_TAB
3811 AS2 (sbc,%B0,%B0) CR_TAB
adcd8f77
MM
3812 AS1 (clr,__zero_reg__));
3813 }
afee2a52
MM
3814 if (optimize_size && scratch)
3815 break; /* 5 */
3816 *len = 7;
3817 return (AS2 (mov,%A0,%B0) CR_TAB
3818 AS1 (lsl,%B0) CR_TAB
3819 AS2 (sbc,%B0,%B0) CR_TAB
3820 AS1 (asr,%A0) CR_TAB
3821 AS1 (asr,%A0) CR_TAB
3822 AS1 (asr,%A0) CR_TAB
3823 AS1 (asr,%A0));
adcd8f77
MM
3824
3825 case 13:
dd6d1f8c 3826 if (AVR_HAVE_MUL && ldi_ok)
adcd8f77
MM
3827 {
3828 *len = 5;
afee2a52
MM
3829 return (AS2 (ldi,%A0,0x08) CR_TAB
3830 AS2 (muls,%B0,%A0) CR_TAB
3831 AS2 (mov,%A0,r1) CR_TAB
3832 AS2 (sbc,%B0,%B0) CR_TAB
adcd8f77
MM
3833 AS1 (clr,__zero_reg__));
3834 }
afee2a52
MM
3835 if (optimize_size)
3836 break; /* scratch ? 5 : 7 */
3837 *len = 8;
3838 return (AS2 (mov,%A0,%B0) CR_TAB
3839 AS1 (lsl,%B0) CR_TAB
3840 AS2 (sbc,%B0,%B0) CR_TAB
3841 AS1 (asr,%A0) CR_TAB
3842 AS1 (asr,%A0) CR_TAB
3843 AS1 (asr,%A0) CR_TAB
3844 AS1 (asr,%A0) CR_TAB
3845 AS1 (asr,%A0));
adcd8f77
MM
3846
3847 case 14:
3848 *len = 5;
3849 return (AS1 (lsl,%B0) CR_TAB
3850 AS2 (sbc,%A0,%A0) CR_TAB
3851 AS1 (lsl,%B0) CR_TAB
3852 AS2 (mov,%B0,%A0) CR_TAB
3853 AS1 (rol,%A0));
3854
a3cf5992
MM
3855 default:
3856 if (INTVAL (operands[2]) < 16)
3857 break;
3858
3859 /* fall through */
3860
28e801e2
DC
3861 case 15:
3862 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3863 AS2 (sbc,%A0,%A0) CR_TAB
3864 AS2 (mov,%B0,%A0));
90e7678c 3865 }
adcd8f77 3866 len = t;
90e7678c 3867 }
afee2a52
MM
3868 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3869 AS1 (ror,%A0)),
3870 insn, operands, len, 2);
90e7678c
DC
3871 return "";
3872}
3873
3874
3875/* 32bit arithmetic shift right ((signed long)x >> i) */
3876
5fecfd8d 3877const char *
269e3795 3878ashrsi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
3879{
3880 if (GET_CODE (operands[2]) == CONST_INT)
3881 {
3882 int k;
3883 int *t = len;
3454eb73 3884
90e7678c
DC
3885 if (!len)
3886 len = &k;
3454eb73 3887
90e7678c
DC
3888 switch (INTVAL (operands[2]))
3889 {
90e7678c
DC
3890 case 8:
3891 {
3892 int reg0 = true_regnum (operands[0]);
3893 int reg1 = true_regnum (operands[1]);
3894 *len=6;
3895 if (reg0 <= reg1)
3896 return (AS2 (mov,%A0,%B1) CR_TAB
3897 AS2 (mov,%B0,%C1) CR_TAB
3898 AS2 (mov,%C0,%D1) CR_TAB
3899 AS1 (clr,%D0) CR_TAB
3900 AS2 (sbrc,%C0,7) CR_TAB
3901 AS1 (dec,%D0));
90e7678c
DC
3902 else
3903 return (AS1 (clr,%D0) CR_TAB
28e801e2 3904 AS2 (sbrc,%D1,7) CR_TAB
90e7678c
DC
3905 AS1 (dec,%D0) CR_TAB
3906 AS2 (mov,%C0,%D1) CR_TAB
3907 AS2 (mov,%B0,%C1) CR_TAB
3908 AS2 (mov,%A0,%B1));
3909 }
3454eb73 3910
90e7678c
DC
3911 case 16:
3912 {
3913 int reg0 = true_regnum (operands[0]);
3914 int reg1 = true_regnum (operands[1]);
120b24f7
AS
3915
3916 if (reg0 == reg1 + 2)
90e7678c
DC
3917 return *len = 4, (AS1 (clr,%D0) CR_TAB
3918 AS2 (sbrc,%B0,7) CR_TAB
3919 AS1 (com,%D0) CR_TAB
3920 AS2 (mov,%C0,%D0));
120b24f7
AS
3921 if (AVR_HAVE_MOVW)
3922 return *len = 5, (AS2 (movw,%A0,%C1) CR_TAB
3923 AS1 (clr,%D0) CR_TAB
3924 AS2 (sbrc,%B0,7) CR_TAB
3925 AS1 (com,%D0) CR_TAB
3926 AS2 (mov,%C0,%D0));
3927 else
3928 return *len = 6, (AS2 (mov,%B0,%D1) CR_TAB
3929 AS2 (mov,%A0,%C1) CR_TAB
3930 AS1 (clr,%D0) CR_TAB
3931 AS2 (sbrc,%B0,7) CR_TAB
3932 AS1 (com,%D0) CR_TAB
3933 AS2 (mov,%C0,%D0));
90e7678c 3934 }
3454eb73 3935
90e7678c 3936 case 24:
120b24f7
AS
3937 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3938 AS1 (clr,%D0) CR_TAB
3939 AS2 (sbrc,%A0,7) CR_TAB
3940 AS1 (com,%D0) CR_TAB
3941 AS2 (mov,%B0,%D0) CR_TAB
3942 AS2 (mov,%C0,%D0));
adcd8f77 3943
a3cf5992
MM
3944 default:
3945 if (INTVAL (operands[2]) < 32)
3946 break;
3947
3948 /* fall through */
3949
adcd8f77 3950 case 31:
4301ec4f 3951 if (AVR_HAVE_MOVW)
adcd8f77
MM
3952 return *len = 4, (AS1 (lsl,%D0) CR_TAB
3953 AS2 (sbc,%A0,%A0) CR_TAB
3954 AS2 (mov,%B0,%A0) CR_TAB
3955 AS2 (movw,%C0,%A0));
3956 else
3957 return *len = 5, (AS1 (lsl,%D0) CR_TAB
3958 AS2 (sbc,%A0,%A0) CR_TAB
3959 AS2 (mov,%B0,%A0) CR_TAB
3960 AS2 (mov,%C0,%A0) CR_TAB
3961 AS2 (mov,%D0,%A0));
90e7678c 3962 }
adcd8f77 3963 len = t;
90e7678c 3964 }
afee2a52
MM
3965 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3966 AS1 (ror,%C0) CR_TAB
3967 AS1 (ror,%B0) CR_TAB
3968 AS1 (ror,%A0)),
3969 insn, operands, len, 4);
90e7678c
DC
3970 return "";
3971}
3972
3973/* 8bit logic shift right ((unsigned char)x >> i) */
3974
5fecfd8d 3975const char *
269e3795 3976lshrqi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
3977{
3978 if (GET_CODE (operands[2]) == CONST_INT)
3979 {
3980 int k;
3454eb73 3981
90e7678c
DC
3982 if (!len)
3983 len = &k;
3454eb73 3984
90e7678c
DC
3985 switch (INTVAL (operands[2]))
3986 {
3454eb73 3987 default:
a3cf5992
MM
3988 if (INTVAL (operands[2]) < 8)
3989 break;
3990
3454eb73
DC
3991 *len = 1;
3992 return AS1 (clr,%0);
3993
90e7678c 3994 case 1:
3454eb73 3995 *len = 1;
90e7678c 3996 return AS1 (lsr,%0);
3454eb73 3997
90e7678c 3998 case 2:
3454eb73 3999 *len = 2;
90e7678c
DC
4000 return (AS1 (lsr,%0) CR_TAB
4001 AS1 (lsr,%0));
4002 case 3:
3454eb73 4003 *len = 3;
90e7678c
DC
4004 return (AS1 (lsr,%0) CR_TAB
4005 AS1 (lsr,%0) CR_TAB
4006 AS1 (lsr,%0));
3454eb73 4007
90e7678c 4008 case 4:
c4984bad 4009 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c
DC
4010 {
4011 *len=2;
4012 return (AS1 (swap,%0) CR_TAB
4013 AS2 (andi,%0,0x0f));
4014 }
3454eb73 4015 *len = 4;
90e7678c
DC
4016 return (AS1 (lsr,%0) CR_TAB
4017 AS1 (lsr,%0) CR_TAB
4018 AS1 (lsr,%0) CR_TAB
4019 AS1 (lsr,%0));
3454eb73 4020
90e7678c 4021 case 5:
c4984bad 4022 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c 4023 {
3454eb73 4024 *len = 3;
90e7678c
DC
4025 return (AS1 (swap,%0) CR_TAB
4026 AS1 (lsr,%0) CR_TAB
4027 AS2 (andi,%0,0x7));
4028 }
3454eb73 4029 *len = 5;
90e7678c
DC
4030 return (AS1 (lsr,%0) CR_TAB
4031 AS1 (lsr,%0) CR_TAB
4032 AS1 (lsr,%0) CR_TAB
4033 AS1 (lsr,%0) CR_TAB
4034 AS1 (lsr,%0));
3454eb73 4035
90e7678c 4036 case 6:
c4984bad 4037 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c 4038 {
3454eb73 4039 *len = 4;
90e7678c
DC
4040 return (AS1 (swap,%0) CR_TAB
4041 AS1 (lsr,%0) CR_TAB
4042 AS1 (lsr,%0) CR_TAB
4043 AS2 (andi,%0,0x3));
4044 }
3454eb73 4045 *len = 6;
90e7678c
DC
4046 return (AS1 (lsr,%0) CR_TAB
4047 AS1 (lsr,%0) CR_TAB
4048 AS1 (lsr,%0) CR_TAB
4049 AS1 (lsr,%0) CR_TAB
4050 AS1 (lsr,%0) CR_TAB
4051 AS1 (lsr,%0));
3454eb73 4052
90e7678c 4053 case 7:
3454eb73 4054 *len = 3;
90e7678c
DC
4055 return (AS1 (rol,%0) CR_TAB
4056 AS1 (clr,%0) CR_TAB
4057 AS1 (rol,%0));
4058 }
4059 }
3454eb73 4060 else if (CONSTANT_P (operands[2]))
c725bd79 4061 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3454eb73 4062
0db7ad3a 4063 out_shift_with_cnt (AS1 (lsr,%0),
afee2a52 4064 insn, operands, len, 1);
90e7678c
DC
4065 return "";
4066}
4067
4068/* 16bit logic shift right ((unsigned short)x >> i) */
4069
5fecfd8d 4070const char *
269e3795 4071lshrhi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
4072{
4073 if (GET_CODE (operands[2]) == CONST_INT)
4074 {
afee2a52
MM
4075 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
4076 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
90e7678c 4077 int k;
3454eb73 4078 int *t = len;
afee2a52 4079
90e7678c
DC
4080 if (!len)
4081 len = &k;
3454eb73 4082
90e7678c
DC
4083 switch (INTVAL (operands[2]))
4084 {
a3cf5992
MM
4085 default:
4086 if (INTVAL (operands[2]) < 16)
4087 break;
4088
4089 *len = 2;
4090 return (AS1 (clr,%B0) CR_TAB
4091 AS1 (clr,%A0));
4092
afee2a52
MM
4093 case 4:
4094 if (optimize_size && scratch)
4095 break; /* 5 */
4096 if (ldi_ok)
4097 {
4098 *len = 6;
4099 return (AS1 (swap,%B0) CR_TAB
4100 AS1 (swap,%A0) CR_TAB
4101 AS2 (andi,%A0,0x0f) CR_TAB
4102 AS2 (eor,%A0,%B0) CR_TAB
4103 AS2 (andi,%B0,0x0f) CR_TAB
4104 AS2 (eor,%A0,%B0));
4105 }
4106 if (scratch)
4107 {
4108 *len = 7;
4109 return (AS1 (swap,%B0) CR_TAB
4110 AS1 (swap,%A0) CR_TAB
4111 AS2 (ldi,%3,0x0f) CR_TAB
5a82ecd9 4112 "and %A0,%3" CR_TAB
afee2a52 4113 AS2 (eor,%A0,%B0) CR_TAB
5a82ecd9 4114 "and %B0,%3" CR_TAB
afee2a52
MM
4115 AS2 (eor,%A0,%B0));
4116 }
4117 break; /* optimize_size ? 6 : 8 */
4118
4119 case 5:
4120 if (optimize_size)
4121 break; /* scratch ? 5 : 6 */
4122 if (ldi_ok)
4123 {
4124 *len = 8;
4125 return (AS1 (lsr,%B0) CR_TAB
4126 AS1 (ror,%A0) CR_TAB
4127 AS1 (swap,%B0) CR_TAB
4128 AS1 (swap,%A0) CR_TAB
4129 AS2 (andi,%A0,0x0f) CR_TAB
4130 AS2 (eor,%A0,%B0) CR_TAB
4131 AS2 (andi,%B0,0x0f) CR_TAB
4132 AS2 (eor,%A0,%B0));
4133 }
4134 if (scratch)
4135 {
4136 *len = 9;
4137 return (AS1 (lsr,%B0) CR_TAB
4138 AS1 (ror,%A0) CR_TAB
4139 AS1 (swap,%B0) CR_TAB
4140 AS1 (swap,%A0) CR_TAB
4141 AS2 (ldi,%3,0x0f) CR_TAB
5a82ecd9 4142 "and %A0,%3" CR_TAB
afee2a52 4143 AS2 (eor,%A0,%B0) CR_TAB
5a82ecd9 4144 "and %B0,%3" CR_TAB
afee2a52
MM
4145 AS2 (eor,%A0,%B0));
4146 }
4147 break; /* 10 */
4148
4149 case 6:
4150 if (optimize_size)
4151 break; /* scratch ? 5 : 6 */
4152 *len = 9;
4153 return (AS1 (clr,__tmp_reg__) CR_TAB
4154 AS1 (lsl,%A0) CR_TAB
4155 AS1 (rol,%B0) CR_TAB
4156 AS1 (rol,__tmp_reg__) CR_TAB
4157 AS1 (lsl,%A0) CR_TAB
4158 AS1 (rol,%B0) CR_TAB
4159 AS1 (rol,__tmp_reg__) CR_TAB
4160 AS2 (mov,%A0,%B0) CR_TAB
4161 AS2 (mov,%B0,__tmp_reg__));
adcd8f77
MM
4162
4163 case 7:
4164 *len = 5;
4165 return (AS1 (lsl,%A0) CR_TAB
4166 AS2 (mov,%A0,%B0) CR_TAB
4167 AS1 (rol,%A0) CR_TAB
4168 AS2 (sbc,%B0,%B0) CR_TAB
4169 AS1 (neg,%B0));
4170
90e7678c 4171 case 8:
120b24f7
AS
4172 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
4173 AS1 (clr,%B0));
adcd8f77
MM
4174
4175 case 9:
4176 *len = 3;
4177 return (AS2 (mov,%A0,%B0) CR_TAB
4178 AS1 (clr,%B0) CR_TAB
4179 AS1 (lsr,%A0));
4180
4181 case 10:
4182 *len = 4;
4183 return (AS2 (mov,%A0,%B0) CR_TAB
4184 AS1 (clr,%B0) CR_TAB
4185 AS1 (lsr,%A0) CR_TAB
4186 AS1 (lsr,%A0));
4187
4188 case 11:
4189 *len = 5;
4190 return (AS2 (mov,%A0,%B0) CR_TAB
4191 AS1 (clr,%B0) CR_TAB
4192 AS1 (lsr,%A0) CR_TAB
4193 AS1 (lsr,%A0) CR_TAB
4194 AS1 (lsr,%A0));
4195
4196 case 12:
afee2a52 4197 if (ldi_ok)
adcd8f77
MM
4198 {
4199 *len = 4;
4200 return (AS2 (mov,%A0,%B0) CR_TAB
4201 AS1 (clr,%B0) CR_TAB
4202 AS1 (swap,%A0) CR_TAB
4203 AS2 (andi,%A0,0x0f));
4204 }
afee2a52
MM
4205 if (scratch)
4206 {
4207 *len = 5;
4208 return (AS2 (mov,%A0,%B0) CR_TAB
4209 AS1 (clr,%B0) CR_TAB
4210 AS1 (swap,%A0) CR_TAB
4211 AS2 (ldi,%3,0x0f) CR_TAB
5a82ecd9 4212 "and %A0,%3");
afee2a52
MM
4213 }
4214 *len = 6;
adcd8f77
MM
4215 return (AS2 (mov,%A0,%B0) CR_TAB
4216 AS1 (clr,%B0) CR_TAB
afee2a52
MM
4217 AS1 (lsr,%A0) CR_TAB
4218 AS1 (lsr,%A0) CR_TAB
4219 AS1 (lsr,%A0) CR_TAB
4220 AS1 (lsr,%A0));
adcd8f77
MM
4221
4222 case 13:
afee2a52 4223 if (ldi_ok)
adcd8f77
MM
4224 {
4225 *len = 5;
4226 return (AS2 (mov,%A0,%B0) CR_TAB
4227 AS1 (clr,%B0) CR_TAB
4228 AS1 (swap,%A0) CR_TAB
4229 AS1 (lsr,%A0) CR_TAB
4230 AS2 (andi,%A0,0x07));
4231 }
dd6d1f8c 4232 if (AVR_HAVE_MUL && scratch)
adcd8f77
MM
4233 {
4234 *len = 5;
4235 return (AS2 (ldi,%3,0x08) CR_TAB
4236 AS2 (mul,%B0,%3) CR_TAB
4237 AS2 (mov,%A0,r1) CR_TAB
4238 AS1 (clr,%B0) CR_TAB
4239 AS1 (clr,__zero_reg__));
4240 }
afee2a52
MM
4241 if (optimize_size && scratch)
4242 break; /* 5 */
4243 if (scratch)
4244 {
4245 *len = 6;
4246 return (AS2 (mov,%A0,%B0) CR_TAB
4247 AS1 (clr,%B0) CR_TAB
4248 AS1 (swap,%A0) CR_TAB
4249 AS1 (lsr,%A0) CR_TAB
4250 AS2 (ldi,%3,0x07) CR_TAB
5a82ecd9 4251 "and %A0,%3");
afee2a52 4252 }
dd6d1f8c 4253 if (AVR_HAVE_MUL)
afee2a52
MM
4254 {
4255 *len = 6;
4256 return ("set" CR_TAB
4257 AS2 (bld,r1,3) CR_TAB
4258 AS2 (mul,%B0,r1) CR_TAB
4259 AS2 (mov,%A0,r1) CR_TAB
4260 AS1 (clr,%B0) CR_TAB
4261 AS1 (clr,__zero_reg__));
4262 }
4263 *len = 7;
4264 return (AS2 (mov,%A0,%B0) CR_TAB
4265 AS1 (clr,%B0) CR_TAB
4266 AS1 (lsr,%A0) CR_TAB
4267 AS1 (lsr,%A0) CR_TAB
4268 AS1 (lsr,%A0) CR_TAB
4269 AS1 (lsr,%A0) CR_TAB
4270 AS1 (lsr,%A0));
adcd8f77
MM
4271
4272 case 14:
dd6d1f8c 4273 if (AVR_HAVE_MUL && ldi_ok)
afee2a52
MM
4274 {
4275 *len = 5;
4276 return (AS2 (ldi,%A0,0x04) CR_TAB
4277 AS2 (mul,%B0,%A0) CR_TAB
4278 AS2 (mov,%A0,r1) CR_TAB
4279 AS1 (clr,%B0) CR_TAB
4280 AS1 (clr,__zero_reg__));
4281 }
dd6d1f8c 4282 if (AVR_HAVE_MUL && scratch)
adcd8f77
MM
4283 {
4284 *len = 5;
4285 return (AS2 (ldi,%3,0x04) CR_TAB
4286 AS2 (mul,%B0,%3) CR_TAB
4287 AS2 (mov,%A0,r1) CR_TAB
4288 AS1 (clr,%B0) CR_TAB
4289 AS1 (clr,__zero_reg__));
4290 }
afee2a52
MM
4291 if (optimize_size && ldi_ok)
4292 {
4293 *len = 5;
4294 return (AS2 (mov,%A0,%B0) CR_TAB
4295 AS2 (ldi,%B0,6) "\n1:\t"
4296 AS1 (lsr,%A0) CR_TAB
4297 AS1 (dec,%B0) CR_TAB
4298 AS1 (brne,1b));
4299 }
4300 if (optimize_size && scratch)
4301 break; /* 5 */
4302 *len = 6;
4303 return (AS1 (clr,%A0) CR_TAB
4304 AS1 (lsl,%B0) CR_TAB
4305 AS1 (rol,%A0) CR_TAB
4306 AS1 (lsl,%B0) CR_TAB
4307 AS1 (rol,%A0) CR_TAB
4308 AS1 (clr,%B0));
adcd8f77 4309
28e801e2 4310 case 15:
3454eb73 4311 *len = 4;
afee2a52
MM
4312 return (AS1 (clr,%A0) CR_TAB
4313 AS1 (lsl,%B0) CR_TAB
4314 AS1 (rol,%A0) CR_TAB
3454eb73 4315 AS1 (clr,%B0));
90e7678c 4316 }
adcd8f77 4317 len = t;
90e7678c 4318 }
afee2a52
MM
4319 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
4320 AS1 (ror,%A0)),
4321 insn, operands, len, 2);
90e7678c
DC
4322 return "";
4323}
4324
4325/* 32bit logic shift right ((unsigned int)x >> i) */
4326
5fecfd8d 4327const char *
269e3795 4328lshrsi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
4329{
4330 if (GET_CODE (operands[2]) == CONST_INT)
4331 {
4332 int k;
3454eb73
DC
4333 int *t = len;
4334
90e7678c
DC
4335 if (!len)
4336 len = &k;
3454eb73 4337
90e7678c
DC
4338 switch (INTVAL (operands[2]))
4339 {
a3cf5992
MM
4340 default:
4341 if (INTVAL (operands[2]) < 32)
4342 break;
4343
4301ec4f 4344 if (AVR_HAVE_MOVW)
a3cf5992
MM
4345 return *len = 3, (AS1 (clr,%D0) CR_TAB
4346 AS1 (clr,%C0) CR_TAB
4347 AS2 (movw,%A0,%C0));
4348 *len = 4;
4349 return (AS1 (clr,%D0) CR_TAB
4350 AS1 (clr,%C0) CR_TAB
4351 AS1 (clr,%B0) CR_TAB
4352 AS1 (clr,%A0));
4353
90e7678c
DC
4354 case 8:
4355 {
4356 int reg0 = true_regnum (operands[0]);
4357 int reg1 = true_regnum (operands[1]);
3454eb73 4358 *len = 4;
90e7678c
DC
4359 if (reg0 <= reg1)
4360 return (AS2 (mov,%A0,%B1) CR_TAB
4361 AS2 (mov,%B0,%C1) CR_TAB
4362 AS2 (mov,%C0,%D1) CR_TAB
4363 AS1 (clr,%D0));
90e7678c
DC
4364 else
4365 return (AS1 (clr,%D0) CR_TAB
4366 AS2 (mov,%C0,%D1) CR_TAB
4367 AS2 (mov,%B0,%C1) CR_TAB
4368 AS2 (mov,%A0,%B1));
4369 }
3454eb73 4370
90e7678c
DC
4371 case 16:
4372 {
4373 int reg0 = true_regnum (operands[0]);
4374 int reg1 = true_regnum (operands[1]);
120b24f7
AS
4375
4376 if (reg0 == reg1 + 2)
90e7678c
DC
4377 return *len = 2, (AS1 (clr,%C0) CR_TAB
4378 AS1 (clr,%D0));
120b24f7
AS
4379 if (AVR_HAVE_MOVW)
4380 return *len = 3, (AS2 (movw,%A0,%C1) CR_TAB
4381 AS1 (clr,%C0) CR_TAB
4382 AS1 (clr,%D0));
90e7678c 4383 else
120b24f7
AS
4384 return *len = 4, (AS2 (mov,%B0,%D1) CR_TAB
4385 AS2 (mov,%A0,%C1) CR_TAB
4386 AS1 (clr,%C0) CR_TAB
4387 AS1 (clr,%D0));
90e7678c 4388 }
3454eb73 4389
90e7678c 4390 case 24:
120b24f7
AS
4391 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4392 AS1 (clr,%B0) CR_TAB
4393 AS1 (clr,%C0) CR_TAB
4394 AS1 (clr,%D0));
adcd8f77
MM
4395
4396 case 31:
4397 *len = 6;
4398 return (AS1 (clr,%A0) CR_TAB
4399 AS2 (sbrc,%D0,7) CR_TAB
4400 AS1 (inc,%A0) CR_TAB
4401 AS1 (clr,%B0) CR_TAB
4402 AS1 (clr,%C0) CR_TAB
4403 AS1 (clr,%D0));
90e7678c 4404 }
adcd8f77 4405 len = t;
90e7678c 4406 }
afee2a52
MM
4407 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4408 AS1 (ror,%C0) CR_TAB
4409 AS1 (ror,%B0) CR_TAB
4410 AS1 (ror,%A0)),
4411 insn, operands, len, 4);
90e7678c
DC
4412 return "";
4413}
4414
58f0ea2f
AH
4415/* Create RTL split patterns for byte sized rotate expressions. This
4416 produces a series of move instructions and considers overlap situations.
4417 Overlapping non-HImode operands need a scratch register. */
4418
4419bool
4420avr_rotate_bytes (rtx operands[])
4421{
4422 int i, j;
4423 enum machine_mode mode = GET_MODE (operands[0]);
4424 bool overlapped = reg_overlap_mentioned_p (operands[0], operands[1]);
4425 bool same_reg = rtx_equal_p (operands[0], operands[1]);
4426 int num = INTVAL (operands[2]);
4427 rtx scratch = operands[3];
4428 /* Work out if byte or word move is needed. Odd byte rotates need QImode.
4429 Word move if no scratch is needed, otherwise use size of scratch. */
4430 enum machine_mode move_mode = QImode;
3f02a5f3
JR
4431 int move_size, offset, size;
4432
58f0ea2f
AH
4433 if (num & 0xf)
4434 move_mode = QImode;
4435 else if ((mode == SImode && !same_reg) || !overlapped)
4436 move_mode = HImode;
4437 else
4438 move_mode = GET_MODE (scratch);
4439
4440 /* Force DI rotate to use QI moves since other DI moves are currently split
4441 into QI moves so forward propagation works better. */
4442 if (mode == DImode)
4443 move_mode = QImode;
4444 /* Make scratch smaller if needed. */
d772f97c
GJL
4445 if (SCRATCH != GET_CODE (scratch)
4446 && HImode == GET_MODE (scratch)
4447 && QImode == move_mode)
58f0ea2f
AH
4448 scratch = simplify_gen_subreg (move_mode, scratch, HImode, 0);
4449
3f02a5f3 4450 move_size = GET_MODE_SIZE (move_mode);
58f0ea2f 4451 /* Number of bytes/words to rotate. */
3f02a5f3 4452 offset = (num >> 3) / move_size;
58f0ea2f 4453 /* Number of moves needed. */
3f02a5f3 4454 size = GET_MODE_SIZE (mode) / move_size;
58f0ea2f
AH
4455 /* Himode byte swap is special case to avoid a scratch register. */
4456 if (mode == HImode && same_reg)
4457 {
4458 /* HImode byte swap, using xor. This is as quick as using scratch. */
4459 rtx src, dst;
4460 src = simplify_gen_subreg (move_mode, operands[1], mode, 0);
4461 dst = simplify_gen_subreg (move_mode, operands[0], mode, 1);
4462 if (!rtx_equal_p (dst, src))
4463 {
4464 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
4465 emit_move_insn (src, gen_rtx_XOR (QImode, src, dst));
4466 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
4467 }
4468 }
4469 else
4470 {
3f02a5f3 4471#define MAX_SIZE 8 /* GET_MODE_SIZE (DImode) / GET_MODE_SIZE (QImode) */
58f0ea2f
AH
4472 /* Create linked list of moves to determine move order. */
4473 struct {
4474 rtx src, dst;
4475 int links;
3f02a5f3
JR
4476 } move[MAX_SIZE + 8];
4477 int blocked, moves;
58f0ea2f 4478
3f02a5f3 4479 gcc_assert (size <= MAX_SIZE);
58f0ea2f
AH
4480 /* Generate list of subreg moves. */
4481 for (i = 0; i < size; i++)
4482 {
4483 int from = i;
4484 int to = (from + offset) % size;
4485 move[i].src = simplify_gen_subreg (move_mode, operands[1],
4486 mode, from * move_size);
4487 move[i].dst = simplify_gen_subreg (move_mode, operands[0],
4488 mode, to * move_size);
4489 move[i].links = -1;
4490 }
4491 /* Mark dependence where a dst of one move is the src of another move.
4492 The first move is a conflict as it must wait until second is
4493 performed. We ignore moves to self - we catch this later. */
4494 if (overlapped)
4495 for (i = 0; i < size; i++)
4496 if (reg_overlap_mentioned_p (move[i].dst, operands[1]))
4497 for (j = 0; j < size; j++)
4498 if (j != i && rtx_equal_p (move[j].src, move[i].dst))
4499 {
4500 /* The dst of move i is the src of move j. */
4501 move[i].links = j;
4502 break;
4503 }
4504
3f02a5f3
JR
4505 blocked = -1;
4506 moves = 0;
58f0ea2f
AH
4507 /* Go through move list and perform non-conflicting moves. As each
4508 non-overlapping move is made, it may remove other conflicts
4509 so the process is repeated until no conflicts remain. */
4510 do
4511 {
4512 blocked = -1;
4513 moves = 0;
4514 /* Emit move where dst is not also a src or we have used that
4515 src already. */
4516 for (i = 0; i < size; i++)
4517 if (move[i].src != NULL_RTX)
3f02a5f3
JR
4518 {
4519 if (move[i].links == -1
4520 || move[move[i].links].src == NULL_RTX)
4521 {
4522 moves++;
4523 /* Ignore NOP moves to self. */
4524 if (!rtx_equal_p (move[i].dst, move[i].src))
4525 emit_move_insn (move[i].dst, move[i].src);
58f0ea2f 4526
3f02a5f3
JR
4527 /* Remove conflict from list. */
4528 move[i].src = NULL_RTX;
4529 }
4530 else
4531 blocked = i;
4532 }
58f0ea2f
AH
4533
4534 /* Check for deadlock. This is when no moves occurred and we have
4535 at least one blocked move. */
4536 if (moves == 0 && blocked != -1)
4537 {
4538 /* Need to use scratch register to break deadlock.
4539 Add move to put dst of blocked move into scratch.
4540 When this move occurs, it will break chain deadlock.
4541 The scratch register is substituted for real move. */
4542
d772f97c
GJL
4543 gcc_assert (SCRATCH != GET_CODE (scratch));
4544
58f0ea2f
AH
4545 move[size].src = move[blocked].dst;
4546 move[size].dst = scratch;
4547 /* Scratch move is never blocked. */
4548 move[size].links = -1;
4549 /* Make sure we have valid link. */
4550 gcc_assert (move[blocked].links != -1);
4551 /* Replace src of blocking move with scratch reg. */
4552 move[move[blocked].links].src = scratch;
4553 /* Make dependent on scratch move occuring. */
4554 move[blocked].links = size;
4555 size=size+1;
4556 }
4557 }
4558 while (blocked != -1);
4559 }
4560 return true;
4561}
4562
90e7678c
DC
4563/* Modifies the length assigned to instruction INSN
4564 LEN is the initially computed length of the insn. */
4565
4566int
269e3795 4567adjust_insn_length (rtx insn, int len)
90e7678c
DC
4568{
4569 rtx patt = PATTERN (insn);
4570 rtx set;
155b14a8 4571
90e7678c
DC
4572 if (GET_CODE (patt) == SET)
4573 {
4574 rtx op[10];
4575 op[1] = SET_SRC (patt);
4576 op[0] = SET_DEST (patt);
6bec29c9
DC
4577 if (general_operand (op[1], VOIDmode)
4578 && general_operand (op[0], VOIDmode))
4579 {
4580 switch (GET_MODE (op[0]))
4581 {
4582 case QImode:
4583 output_movqi (insn, op, &len);
4584 break;
4585 case HImode:
4586 output_movhi (insn, op, &len);
4587 break;
4588 case SImode:
4589 case SFmode:
1e6a67d1 4590 output_movsisf (insn, op, NULL_RTX, &len);
6bec29c9
DC
4591 break;
4592 default:
4593 break;
4594 }
4595 }
90e7678c
DC
4596 else if (op[0] == cc0_rtx && REG_P (op[1]))
4597 {
4598 switch (GET_MODE (op[1]))
4599 {
f90b7a5a
PB
4600 case HImode: out_tsthi (insn, op[1], &len); break;
4601 case SImode: out_tstsi (insn, op[1], &len); break;
90e7678c
DC
4602 default: break;
4603 }
4604 }
4605 else if (GET_CODE (op[1]) == AND)
4606 {
4607 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4608 {
4609 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4610 if (GET_MODE (op[1]) == SImode)
4611 len = (((mask & 0xff) != 0xff)
4612 + ((mask & 0xff00) != 0xff00)
11f9ed1a
KG
4613 + ((mask & 0xff0000L) != 0xff0000L)
4614 + ((mask & 0xff000000L) != 0xff000000L));
90e7678c
DC
4615 else if (GET_MODE (op[1]) == HImode)
4616 len = (((mask & 0xff) != 0xff)
4617 + ((mask & 0xff00) != 0xff00));
4618 }
4619 }
4620 else if (GET_CODE (op[1]) == IOR)
4621 {
4622 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4623 {
4624 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4625 if (GET_MODE (op[1]) == SImode)
5fecfd8d
MM
4626 len = (((mask & 0xff) != 0)
4627 + ((mask & 0xff00) != 0)
11f9ed1a
KG
4628 + ((mask & 0xff0000L) != 0)
4629 + ((mask & 0xff000000L) != 0));
90e7678c 4630 else if (GET_MODE (op[1]) == HImode)
5fecfd8d
MM
4631 len = (((mask & 0xff) != 0)
4632 + ((mask & 0xff00) != 0));
90e7678c
DC
4633 }
4634 }
4635 }
4636 set = single_set (insn);
4637 if (set)
4638 {
4639 rtx op[10];
155b14a8 4640
90e7678c
DC
4641 op[1] = SET_SRC (set);
4642 op[0] = SET_DEST (set);
155b14a8
DC
4643
4644 if (GET_CODE (patt) == PARALLEL
4645 && general_operand (op[1], VOIDmode)
4646 && general_operand (op[0], VOIDmode))
4647 {
4648 if (XVECLEN (patt, 0) == 2)
4649 op[2] = XVECEXP (patt, 0, 1);
4650
4651 switch (GET_MODE (op[0]))
4652 {
4653 case QImode:
4654 len = 2;
4655 break;
4656 case HImode:
4657 output_reload_inhi (insn, op, &len);
4658 break;
4659 case SImode:
4660 case SFmode:
1e6a67d1 4661 output_reload_insisf (insn, op, XEXP (op[2], 0), &len);
155b14a8
DC
4662 break;
4663 default:
4664 break;
4665 }
4666 }
4667 else if (GET_CODE (op[1]) == ASHIFT
90e7678c
DC
4668 || GET_CODE (op[1]) == ASHIFTRT
4669 || GET_CODE (op[1]) == LSHIFTRT)
4670 {
4671 rtx ops[10];
4672 ops[0] = op[0];
4673 ops[1] = XEXP (op[1],0);
4674 ops[2] = XEXP (op[1],1);
4675 switch (GET_CODE (op[1]))
4676 {
4677 case ASHIFT:
4678 switch (GET_MODE (op[0]))
4679 {
4680 case QImode: ashlqi3_out (insn,ops,&len); break;
4681 case HImode: ashlhi3_out (insn,ops,&len); break;
4682 case SImode: ashlsi3_out (insn,ops,&len); break;
4683 default: break;
4684 }
4685 break;
4686 case ASHIFTRT:
4687 switch (GET_MODE (op[0]))
4688 {
4689 case QImode: ashrqi3_out (insn,ops,&len); break;
4690 case HImode: ashrhi3_out (insn,ops,&len); break;
4691 case SImode: ashrsi3_out (insn,ops,&len); break;
4692 default: break;
4693 }
4694 break;
4695 case LSHIFTRT:
4696 switch (GET_MODE (op[0]))
4697 {
4698 case QImode: lshrqi3_out (insn,ops,&len); break;
4699 case HImode: lshrhi3_out (insn,ops,&len); break;
4700 case SImode: lshrsi3_out (insn,ops,&len); break;
4701 default: break;
4702 }
4703 break;
4704 default:
4705 break;
4706 }
4707 }
4708 }
4709 return len;
4710}
4711
d6b4baa4 4712/* Return nonzero if register REG dead after INSN. */
90e7678c
DC
4713
4714int
269e3795 4715reg_unused_after (rtx insn, rtx reg)
90e7678c 4716{
6bec29c9 4717 return (dead_or_set_p (insn, reg)
90e7678c
DC
4718 || (REG_P(reg) && _reg_unused_after (insn, reg)));
4719}
4720
825dda42 4721/* Return nonzero if REG is not used after INSN.
90e7678c
DC
4722 We assume REG is a reload reg, and therefore does
4723 not live past labels. It may live past calls or jumps though. */
4724
4725int
269e3795 4726_reg_unused_after (rtx insn, rtx reg)
90e7678c
DC
4727{
4728 enum rtx_code code;
4729 rtx set;
4730
4731 /* If the reg is set by this instruction, then it is safe for our
4732 case. Disregard the case where this is a store to memory, since
4733 we are checking a register used in the store address. */
4734 set = single_set (insn);
4735 if (set && GET_CODE (SET_DEST (set)) != MEM
4736 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4737 return 1;
4738
4739 while ((insn = NEXT_INSN (insn)))
4740 {
ec8e098d 4741 rtx set;
90e7678c
DC
4742 code = GET_CODE (insn);
4743
4744#if 0
4745 /* If this is a label that existed before reload, then the register
4746 if dead here. However, if this is a label added by reorg, then
4747 the register may still be live here. We can't tell the difference,
4748 so we just ignore labels completely. */
4749 if (code == CODE_LABEL)
4750 return 1;
4751 /* else */
4752#endif
4753
ec8e098d
PB
4754 if (!INSN_P (insn))
4755 continue;
4756
90e7678c
DC
4757 if (code == JUMP_INSN)
4758 return 0;
4759
4760 /* If this is a sequence, we must handle them all at once.
4761 We could have for instance a call that sets the target register,
e03f5d43 4762 and an insn in a delay slot that uses the register. In this case,
90e7678c
DC
4763 we must return 0. */
4764 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4765 {
4766 int i;
4767 int retval = 0;
4768
4769 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4770 {
4771 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4772 rtx set = single_set (this_insn);
4773
4774 if (GET_CODE (this_insn) == CALL_INSN)
4775 code = CALL_INSN;
4776 else if (GET_CODE (this_insn) == JUMP_INSN)
4777 {
4778 if (INSN_ANNULLED_BRANCH_P (this_insn))
4779 return 0;
4780 code = JUMP_INSN;
4781 }
4782
4783 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4784 return 0;
4785 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4786 {
4787 if (GET_CODE (SET_DEST (set)) != MEM)
4788 retval = 1;
4789 else
4790 return 0;
4791 }
4792 if (set == 0
4793 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4794 return 0;
4795 }
4796 if (retval == 1)
4797 return 1;
4798 else if (code == JUMP_INSN)
4799 return 0;
4800 }
4801
4802 if (code == CALL_INSN)
4803 {
4804 rtx tem;
4805 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4806 if (GET_CODE (XEXP (tem, 0)) == USE
4807 && REG_P (XEXP (XEXP (tem, 0), 0))
4808 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4809 return 0;
4810 if (call_used_regs[REGNO (reg)])
4811 return 1;
4812 }
4813
ec8e098d 4814 set = single_set (insn);
90e7678c 4815
ec8e098d
PB
4816 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4817 return 0;
4818 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4819 return GET_CODE (SET_DEST (set)) != MEM;
4820 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4821 return 0;
90e7678c
DC
4822 }
4823 return 1;
4824}
4825
301d03af
RS
4826/* Target hook for assembling integer objects. The AVR version needs
4827 special handling for references to certain labels. */
90e7678c 4828
301d03af 4829static bool
269e3795 4830avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
90e7678c 4831{
301d03af 4832 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
846428f1 4833 && text_segment_operand (x, VOIDmode) )
90e7678c 4834 {
693092fb 4835 fputs ("\t.word\tgs(", asm_out_file);
301d03af
RS
4836 output_addr_const (asm_out_file, x);
4837 fputs (")\n", asm_out_file);
4838 return true;
90e7678c 4839 }
301d03af 4840 return default_assemble_integer (x, size, aligned_p);
90e7678c
DC
4841}
4842
2cb4817b
AS
4843/* Worker function for ASM_DECLARE_FUNCTION_NAME. */
4844
4845void
4846avr_asm_declare_function_name (FILE *file, const char *name, tree decl)
4847{
4848
4849 /* If the function has the 'signal' or 'interrupt' attribute, test to
4850 make sure that the name of the function is "__vector_NN" so as to
4851 catch when the user misspells the interrupt vector name. */
4852
4853 if (cfun->machine->is_interrupt)
4854 {
4855 if (strncmp (name, "__vector", strlen ("__vector")) != 0)
4856 {
4857 warning_at (DECL_SOURCE_LOCATION (decl), 0,
4858 "%qs appears to be a misspelled interrupt handler",
4859 name);
4860 }
4861 }
4862 else if (cfun->machine->is_signal)
4863 {
4864 if (strncmp (name, "__vector", strlen ("__vector")) != 0)
4865 {
4866 warning_at (DECL_SOURCE_LOCATION (decl), 0,
4867 "%qs appears to be a misspelled signal handler",
4868 name);
4869 }
4870 }
4871
4872 ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
4873 ASM_OUTPUT_LABEL (file, name);
4874}
4875
90e7678c
DC
4876
4877/* Return value is nonzero if pseudos that have been
4878 assigned to registers of class CLASS would likely be spilled
4879 because registers of CLASS are needed for spill registers. */
4880
c21136ee
AS
4881static bool
4882avr_class_likely_spilled_p (reg_class_t c)
90e7678c
DC
4883{
4884 return (c != ALL_REGS && c != ADDW_REGS);
4885}
4886
91d231cb 4887/* Valid attributes:
90e7678c
DC
4888 progmem - put data to program memory;
4889 signal - make a function to be hardware interrupt. After function
c4984bad 4890 prologue interrupts are disabled;
90e7678c 4891 interrupt - make a function to be hardware interrupt. After function
c4984bad 4892 prologue interrupts are enabled;
91d231cb 4893 naked - don't generate function prologue/epilogue and `ret' command.
90e7678c 4894
91d231cb
JM
4895 Only `progmem' attribute valid for type. */
4896
91d231cb
JM
4897/* Handle a "progmem" attribute; arguments as in
4898 struct attribute_spec.handler. */
4899static tree
269e3795
SB
4900avr_handle_progmem_attribute (tree *node, tree name,
4901 tree args ATTRIBUTE_UNUSED,
4902 int flags ATTRIBUTE_UNUSED,
4903 bool *no_add_attrs)
91d231cb
JM
4904{
4905 if (DECL_P (*node))
90e7678c 4906 {
b47cae3d
MM
4907 if (TREE_CODE (*node) == TYPE_DECL)
4908 {
4909 /* This is really a decl attribute, not a type attribute,
4910 but try to handle it for GCC 3.0 backwards compatibility. */
4911
4912 tree type = TREE_TYPE (*node);
4913 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
4914 tree newtype = build_type_attribute_variant (type, attr);
4915
4916 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
4917 TREE_TYPE (*node) = newtype;
4918 *no_add_attrs = true;
4919 }
4920 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
90e7678c 4921 {
946c8b23 4922 *no_add_attrs = false;
91d231cb
JM
4923 }
4924 else
4925 {
29d08eba
JM
4926 warning (OPT_Wattributes, "%qE attribute ignored",
4927 name);
91d231cb 4928 *no_add_attrs = true;
90e7678c 4929 }
90e7678c 4930 }
91d231cb
JM
4931
4932 return NULL_TREE;
90e7678c
DC
4933}
4934
91d231cb
JM
4935/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4936 struct attribute_spec.handler. */
269e3795 4937
91d231cb 4938static tree
269e3795
SB
4939avr_handle_fndecl_attribute (tree *node, tree name,
4940 tree args ATTRIBUTE_UNUSED,
4941 int flags ATTRIBUTE_UNUSED,
4942 bool *no_add_attrs)
91d231cb
JM
4943{
4944 if (TREE_CODE (*node) != FUNCTION_DECL)
4945 {
29d08eba
JM
4946 warning (OPT_Wattributes, "%qE attribute only applies to functions",
4947 name);
91d231cb
JM
4948 *no_add_attrs = true;
4949 }
4950
4951 return NULL_TREE;
4952}
90e7678c 4953
44190aed
AS
4954static tree
4955avr_handle_fntype_attribute (tree *node, tree name,
4956 tree args ATTRIBUTE_UNUSED,
4957 int flags ATTRIBUTE_UNUSED,
4958 bool *no_add_attrs)
4959{
4960 if (TREE_CODE (*node) != FUNCTION_TYPE)
4961 {
29d08eba
JM
4962 warning (OPT_Wattributes, "%qE attribute only applies to functions",
4963 name);
44190aed
AS
4964 *no_add_attrs = true;
4965 }
4966
4967 return NULL_TREE;
4968}
4969
90e7678c 4970/* Look for attribute `progmem' in DECL
c4984bad 4971 if found return 1, otherwise 0. */
90e7678c
DC
4972
4973int
427ee360 4974avr_progmem_p (tree decl, tree attributes)
90e7678c
DC
4975{
4976 tree a;
4977
4978 if (TREE_CODE (decl) != VAR_DECL)
4979 return 0;
4980
4981 if (NULL_TREE
427ee360 4982 != lookup_attribute ("progmem", attributes))
90e7678c
DC
4983 return 1;
4984
4985 a=decl;
4986 do
4987 a = TREE_TYPE(a);
4988 while (TREE_CODE (a) == ARRAY_TYPE);
4989
89741abb
MM
4990 if (a == error_mark_node)
4991 return 0;
4992
90e7678c
DC
4993 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4994 return 1;
4995
4996 return 0;
4997}
4998
74b66b3c
RH
4999/* Add the section attribute if the variable is in progmem. */
5000
fb49053f 5001static void
269e3795 5002avr_insert_attributes (tree node, tree *attributes)
90e7678c 5003{
74b66b3c
RH
5004 if (TREE_CODE (node) == VAR_DECL
5005 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
427ee360 5006 && avr_progmem_p (node, *attributes))
90e7678c 5007 {
db297e20
GJL
5008 tree node0 = node;
5009
5010 /* For C++, we have to peel arrays in order to get correct
5011 determination of readonlyness. */
5012
5013 do
5014 node0 = TREE_TYPE (node0);
5015 while (TREE_CODE (node0) == ARRAY_TYPE);
5016
5017 if (error_mark_node == node0)
5018 return;
5019
5020 if (TYPE_READONLY (node0))
8a9b55f3
GJL
5021 {
5022 static const char dsec[] = ".progmem.data";
5023
5024 *attributes = tree_cons (get_identifier ("section"),
5025 build_tree_list (NULL, build_string (strlen (dsec), dsec)),
5026 *attributes);
5027 }
5028 else
5029 {
5030 error ("variable %q+D must be const in order to be put into"
5031 " read-only section by means of %<__attribute__((progmem))%>",
5032 node);
5033 }
90e7678c 5034 }
772c5265 5035}
90e7678c 5036
d6b5193b
RS
5037/* A get_unnamed_section callback for switching to progmem_section. */
5038
5039static void
5040avr_output_progmem_section_asm_op (const void *arg ATTRIBUTE_UNUSED)
5041{
5042 fprintf (asm_out_file,
5043 "\t.section .progmem.gcc_sw_table, \"%s\", @progbits\n",
5dc77808 5044 AVR_HAVE_JMP_CALL ? "a" : "ax");
d6b5193b
RS
5045 /* Should already be aligned, this is just to be safe if it isn't. */
5046 fprintf (asm_out_file, "\t.p2align 1\n");
5047}
5048
516edfdd
GJL
5049
5050/* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'. */
5051/* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'. */
5052/* Track need of __do_clear_bss. */
5053
5054void
5055avr_asm_output_aligned_decl_common (FILE * stream, const_tree decl ATTRIBUTE_UNUSED,
5056 const char *name, unsigned HOST_WIDE_INT size,
5057 unsigned int align, bool local_p)
5058{
5059 avr_need_clear_bss_p = true;
5060
5061 if (local_p)
880962ac
GJL
5062 ASM_OUTPUT_ALIGNED_LOCAL (stream, name, size, align);
5063 else
5064 ASM_OUTPUT_ALIGNED_COMMON (stream, name, size, align);
516edfdd
GJL
5065}
5066
5067
5068/* Unnamed section callback for data_section
5069 to track need of __do_copy_data. */
5070
5071static void
5072avr_output_data_section_asm_op (const void *data)
5073{
5074 avr_need_copy_data_p = true;
5075
5076 /* Dispatch to default. */
5077 output_section_asm_op (data);
5078}
5079
5080
5081/* Unnamed section callback for bss_section
5082 to track need of __do_clear_bss. */
5083
5084static void
5085avr_output_bss_section_asm_op (const void *data)
5086{
5087 avr_need_clear_bss_p = true;
5088
5089 /* Dispatch to default. */
5090 output_section_asm_op (data);
5091}
5092
5093
5094/* Implement `TARGET_ASM_INIT_SECTIONS'. */
d6b5193b
RS
5095
5096static void
5097avr_asm_init_sections (void)
5098{
5dc77808 5099 progmem_section = get_unnamed_section (AVR_HAVE_JMP_CALL ? 0 : SECTION_CODE,
d6b5193b
RS
5100 avr_output_progmem_section_asm_op,
5101 NULL);
516edfdd 5102
eb1dcdff
GJL
5103 /* Override section callbacks to keep track of `avr_need_clear_bss_p'
5104 resp. `avr_need_copy_data_p'. */
5105
5106 readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
516edfdd
GJL
5107 data_section->unnamed.callback = avr_output_data_section_asm_op;
5108 bss_section->unnamed.callback = avr_output_bss_section_asm_op;
5109}
5110
5111
5112/* Implement `TARGET_ASM_NAMED_SECTION'. */
5113/* Track need of __do_clear_bss, __do_copy_data for named sections. */
5114
eb1dcdff 5115static void
516edfdd
GJL
5116avr_asm_named_section (const char *name, unsigned int flags, tree decl)
5117{
5118 if (!avr_need_copy_data_p)
5119 avr_need_copy_data_p = (0 == strncmp (name, ".data", 5)
5120 || 0 == strncmp (name, ".rodata", 7)
5121 || 0 == strncmp (name, ".gnu.linkonce.d", 15));
5122
5123 if (!avr_need_clear_bss_p)
5124 avr_need_clear_bss_p = (0 == strncmp (name, ".bss", 4));
5125
5126 default_elf_asm_named_section (name, flags, decl);
d6b5193b
RS
5127}
5128
c16e5a35 5129static unsigned int
269e3795 5130avr_section_type_flags (tree decl, const char *name, int reloc)
c16e5a35
MM
5131{
5132 unsigned int flags = default_section_type_flags (decl, name, reloc);
5133
5134 if (strncmp (name, ".noinit", 7) == 0)
5135 {
5136 if (decl && TREE_CODE (decl) == VAR_DECL
5137 && DECL_INITIAL (decl) == NULL_TREE)
5138 flags |= SECTION_BSS; /* @nobits */
5139 else
d4ee4d25 5140 warning (0, "only uninitialized variables can be placed in the "
c16e5a35
MM
5141 ".noinit section");
5142 }
5143
946c8b23
GJL
5144 if (0 == strncmp (name, ".progmem.data", strlen (".progmem.data")))
5145 flags &= ~SECTION_WRITE;
5146
c16e5a35
MM
5147 return flags;
5148}
5149
516edfdd 5150
946c8b23
GJL
5151/* Implement `TARGET_ENCODE_SECTION_INFO'. */
5152
5153static void
d17fc175 5154avr_encode_section_info (tree decl, rtx rtl,
946c8b23
GJL
5155 int new_decl_p)
5156{
5157 /* In avr_handle_progmem_attribute, DECL_INITIAL is not yet
5158 readily available, see PR34734. So we postpone the warning
5159 about uninitialized data in program memory section until here. */
5160
5161 if (new_decl_p
5162 && decl && DECL_P (decl)
5163 && NULL_TREE == DECL_INITIAL (decl)
5164 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
5165 {
5166 warning (OPT_Wuninitialized,
5167 "uninitialized variable %q+D put into "
5168 "program memory area", decl);
5169 }
d17fc175
GJL
5170
5171 default_encode_section_info (decl, rtl, new_decl_p);
946c8b23
GJL
5172}
5173
5174
516edfdd 5175/* Implement `TARGET_ASM_FILE_START'. */
1bc7c5b6
ZW
5176/* Outputs some appropriate text to go at the start of an assembler
5177 file. */
90e7678c 5178
1bc7c5b6 5179static void
269e3795 5180avr_file_start (void)
90e7678c 5181{
470a4c97 5182 if (avr_current_arch->asm_only)
1b916ca6 5183 error ("MCU %qs supported for assembler only", avr_current_device->name);
bcb6a2be 5184
1bc7c5b6
ZW
5185 default_file_start ();
5186
1b916ca6 5187/* fprintf (asm_out_file, "\t.arch %s\n", avr_current_device->name);*/
90e7678c
DC
5188 fputs ("__SREG__ = 0x3f\n"
5189 "__SP_H__ = 0x3e\n"
1bc7c5b6 5190 "__SP_L__ = 0x3d\n", asm_out_file);
90e7678c 5191
368256d8 5192 fputs ("__tmp_reg__ = 0\n"
1bc7c5b6 5193 "__zero_reg__ = 1\n", asm_out_file);
90e7678c
DC
5194}
5195
516edfdd
GJL
5196
5197/* Implement `TARGET_ASM_FILE_END'. */
90e7678c
DC
5198/* Outputs to the stdio stream FILE some
5199 appropriate text to go at the end of an assembler file. */
5200
a5fe455b 5201static void
269e3795 5202avr_file_end (void)
90e7678c 5203{
516edfdd
GJL
5204 /* Output these only if there is anything in the
5205 .data* / .rodata* / .gnu.linkonce.* resp. .bss*
5206 input section(s) - some code size can be saved by not
5207 linking in the initialization code from libgcc if resp.
5208 sections are empty. */
5209
5210 if (avr_need_copy_data_p)
5211 fputs (".global __do_copy_data\n", asm_out_file);
5212
5213 if (avr_need_clear_bss_p)
5214 fputs (".global __do_clear_bss\n", asm_out_file);
90e7678c
DC
5215}
5216
5217/* Choose the order in which to allocate hard registers for
5218 pseudo-registers local to a basic block.
5219
5220 Store the desired register order in the array `reg_alloc_order'.
5221 Element 0 should be the register to allocate first; element 1, the
5222 next register; and so on. */
5223
5224void
269e3795 5225order_regs_for_local_alloc (void)
90e7678c
DC
5226{
5227 unsigned int i;
8b60264b 5228 static const int order_0[] = {
90e7678c
DC
5229 24,25,
5230 18,19,
5231 20,21,
5232 22,23,
5233 30,31,
5234 26,27,
5235 28,29,
5236 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
5237 0,1,
5238 32,33,34,35
5239 };
8b60264b 5240 static const int order_1[] = {
90e7678c
DC
5241 18,19,
5242 20,21,
5243 22,23,
5244 24,25,
5245 30,31,
5246 26,27,
5247 28,29,
5248 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
5249 0,1,
5250 32,33,34,35
5251 };
8b60264b 5252 static const int order_2[] = {
90e7678c
DC
5253 25,24,
5254 23,22,
5255 21,20,
5256 19,18,
5257 30,31,
5258 26,27,
5259 28,29,
5260 17,16,
5261 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
5262 1,0,
5263 32,33,34,35
5264 };
5265
8b60264b
KG
5266 const int *order = (TARGET_ORDER_1 ? order_1 :
5267 TARGET_ORDER_2 ? order_2 :
5268 order_0);
5b47282c 5269 for (i=0; i < ARRAY_SIZE (order_0); ++i)
90e7678c
DC
5270 reg_alloc_order[i] = order[i];
5271}
5272
8f2bf9f1 5273
5f892aa0
GJL
5274/* Implement `TARGET_REGISTER_MOVE_COST' */
5275
5276static int
5277avr_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
5278 reg_class_t from, reg_class_t to)
5279{
5280 return (from == STACK_REG ? 6
5281 : to == STACK_REG ? 12
5282 : 2);
5283}
5284
5285
5286/* Implement `TARGET_MEMORY_MOVE_COST' */
5287
5288static int
5289avr_memory_move_cost (enum machine_mode mode, reg_class_t rclass ATTRIBUTE_UNUSED,
5290 bool in ATTRIBUTE_UNUSED)
5291{
5292 return (mode == QImode ? 2
5293 : mode == HImode ? 4
5294 : mode == SImode ? 8
5295 : mode == SFmode ? 8
5296 : 16);
5297}
5298
5299
8f2bf9f1
RS
5300/* Mutually recursive subroutine of avr_rtx_cost for calculating the
5301 cost of an RTX operand given its context. X is the rtx of the
5302 operand, MODE is its mode, and OUTER is the rtx_code of this
5303 operand's parent operator. */
90e7678c 5304
3c50106f 5305static int
f40751dd 5306avr_operand_rtx_cost (rtx x, enum machine_mode mode, enum rtx_code outer,
68f932c4 5307 int opno, bool speed)
90e7678c 5308{
8f2bf9f1
RS
5309 enum rtx_code code = GET_CODE (x);
5310 int total;
5311
90e7678c
DC
5312 switch (code)
5313 {
8f2bf9f1
RS
5314 case REG:
5315 case SUBREG:
5316 return 0;
5317
90e7678c 5318 case CONST_INT:
8f2bf9f1
RS
5319 case CONST_DOUBLE:
5320 return COSTS_N_INSNS (GET_MODE_SIZE (mode));
5321
90e7678c
DC
5322 default:
5323 break;
5324 }
8f2bf9f1
RS
5325
5326 total = 0;
68f932c4 5327 avr_rtx_costs (x, code, outer, opno, &total, speed);
8f2bf9f1 5328 return total;
90e7678c
DC
5329}
5330
8f2bf9f1
RS
5331/* The AVR backend's rtx_cost function. X is rtx expression whose cost
5332 is to be calculated. Return true if the complete cost has been
5333 computed, and false if subexpressions should be scanned. In either
5334 case, *TOTAL contains the cost result. */
5335
3c50106f 5336static bool
68f932c4
RS
5337avr_rtx_costs (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
5338 int opno ATTRIBUTE_UNUSED, int *total, bool speed)
3c50106f 5339{
5a82ecd9 5340 enum rtx_code code = (enum rtx_code) codearg;
8f2bf9f1
RS
5341 enum machine_mode mode = GET_MODE (x);
5342 HOST_WIDE_INT val;
3c50106f
RH
5343
5344 switch (code)
5345 {
5346 case CONST_INT:
8f2bf9f1 5347 case CONST_DOUBLE:
73451ae7 5348 case SYMBOL_REF:
21f3ae2f
GJL
5349 case CONST:
5350 case LABEL_REF:
8f2bf9f1
RS
5351 /* Immediate constants are as cheap as registers. */
5352 *total = 0;
5353 return true;
5354
5355 case MEM:
8f2bf9f1
RS
5356 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
5357 return true;
5358
5359 case NEG:
5360 switch (mode)
3c50106f 5361 {
8f2bf9f1
RS
5362 case QImode:
5363 case SFmode:
5364 *total = COSTS_N_INSNS (1);
5365 break;
5366
5367 case HImode:
5368 *total = COSTS_N_INSNS (3);
5369 break;
5370
5371 case SImode:
5372 *total = COSTS_N_INSNS (7);
5373 break;
5374
5375 default:
5376 return false;
3c50106f 5377 }
68f932c4 5378 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1
RS
5379 return true;
5380
5381 case ABS:
5382 switch (mode)
3c50106f 5383 {
8f2bf9f1
RS
5384 case QImode:
5385 case SFmode:
5386 *total = COSTS_N_INSNS (1);
5387 break;
5388
5389 default:
5390 return false;
3c50106f 5391 }
68f932c4 5392 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1 5393 return true;
3c50106f 5394
8f2bf9f1
RS
5395 case NOT:
5396 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
68f932c4 5397 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
3c50106f
RH
5398 return true;
5399
8f2bf9f1
RS
5400 case ZERO_EXTEND:
5401 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
5402 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
68f932c4 5403 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1
RS
5404 return true;
5405
5406 case SIGN_EXTEND:
5407 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
5408 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
68f932c4 5409 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1
RS
5410 return true;
5411
5412 case PLUS:
5413 switch (mode)
5414 {
5415 case QImode:
5416 *total = COSTS_N_INSNS (1);
5417 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
68f932c4 5418 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
8f2bf9f1
RS
5419 break;
5420
5421 case HImode:
5422 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5423 {
5424 *total = COSTS_N_INSNS (2);
68f932c4
RS
5425 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5426 speed);
8f2bf9f1
RS
5427 }
5428 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
5429 *total = COSTS_N_INSNS (1);
5430 else
5431 *total = COSTS_N_INSNS (2);
5432 break;
5433
5434 case SImode:
5435 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5436 {
5437 *total = COSTS_N_INSNS (4);
68f932c4
RS
5438 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5439 speed);
8f2bf9f1
RS
5440 }
5441 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
5442 *total = COSTS_N_INSNS (1);
5443 else
5444 *total = COSTS_N_INSNS (4);
5445 break;
5446
5447 default:
5448 return false;
5449 }
68f932c4 5450 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1
RS
5451 return true;
5452
5453 case MINUS:
5454 case AND:
5455 case IOR:
5456 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
68f932c4 5457 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1 5458 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
68f932c4 5459 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
8f2bf9f1
RS
5460 return true;
5461
5462 case XOR:
5463 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
68f932c4
RS
5464 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
5465 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
8f2bf9f1
RS
5466 return true;
5467
5468 case MULT:
5469 switch (mode)
5470 {
5471 case QImode:
dd6d1f8c 5472 if (AVR_HAVE_MUL)
f40751dd
JH
5473 *total = COSTS_N_INSNS (!speed ? 3 : 4);
5474 else if (!speed)
5dc77808 5475 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
8f2bf9f1
RS
5476 else
5477 return false;
c8bbabf2 5478 break;
8f2bf9f1
RS
5479
5480 case HImode:
dd6d1f8c 5481 if (AVR_HAVE_MUL)
8c352fa8
GJL
5482 {
5483 rtx op0 = XEXP (x, 0);
5484 rtx op1 = XEXP (x, 1);
5485 enum rtx_code code0 = GET_CODE (op0);
5486 enum rtx_code code1 = GET_CODE (op1);
5487 bool ex0 = SIGN_EXTEND == code0 || ZERO_EXTEND == code0;
5488 bool ex1 = SIGN_EXTEND == code1 || ZERO_EXTEND == code1;
5489
5490 if (ex0
5491 && (u8_operand (op1, HImode)
5492 || s8_operand (op1, HImode)))
5493 {
5494 *total = COSTS_N_INSNS (!speed ? 4 : 6);
5495 return true;
5496 }
5497 if (ex0
5498 && register_operand (op1, HImode))
5499 {
5500 *total = COSTS_N_INSNS (!speed ? 5 : 8);
5501 return true;
5502 }
5503 else if (ex0 || ex1)
5504 {
5505 *total = COSTS_N_INSNS (!speed ? 3 : 5);
5506 return true;
5507 }
5508 else if (register_operand (op0, HImode)
5509 && (u8_operand (op1, HImode)
5510 || s8_operand (op1, HImode)))
5511 {
5512 *total = COSTS_N_INSNS (!speed ? 6 : 9);
5513 return true;
5514 }
5515 else
5516 *total = COSTS_N_INSNS (!speed ? 7 : 10);
5517 }
f40751dd 5518 else if (!speed)
5dc77808 5519 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
8f2bf9f1
RS
5520 else
5521 return false;
c8bbabf2 5522 break;
8f2bf9f1 5523
296799ba
GJL
5524 case SImode:
5525 if (AVR_HAVE_MUL)
5526 {
5527 if (!speed)
5528 {
5529 /* Add some additional costs besides CALL like moves etc. */
5530
5531 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
5532 }
5533 else
5534 {
5535 /* Just a rough estimate. Even with -O2 we don't want bulky
5536 code expanded inline. */
5537
5538 *total = COSTS_N_INSNS (25);
5539 }
5540 }
5541 else
5542 {
5543 if (speed)
5544 *total = COSTS_N_INSNS (300);
5545 else
5546 /* Add some additional costs besides CALL like moves etc. */
5547 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
5548 }
5549
5550 return true;
5551
8f2bf9f1
RS
5552 default:
5553 return false;
5554 }
68f932c4
RS
5555 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
5556 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
8f2bf9f1
RS
5557 return true;
5558
5559 case DIV:
5560 case MOD:
5561 case UDIV:
5562 case UMOD:
f40751dd 5563 if (!speed)
5dc77808 5564 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
8f2bf9f1
RS
5565 else
5566 return false;
68f932c4
RS
5567 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
5568 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
8f2bf9f1
RS
5569 return true;
5570
15fe850f
AS
5571 case ROTATE:
5572 switch (mode)
5573 {
5574 case QImode:
5575 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
5576 *total = COSTS_N_INSNS (1);
5577
5578 break;
5579
5580 case HImode:
5581 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
5582 *total = COSTS_N_INSNS (3);
5583
5584 break;
5585
5586 case SImode:
5587 if (CONST_INT_P (XEXP (x, 1)))
5588 switch (INTVAL (XEXP (x, 1)))
5589 {
5590 case 8:
5591 case 24:
5592 *total = COSTS_N_INSNS (5);
5593 break;
5594 case 16:
5595 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 6);
5596 break;
5597 }
5598 break;
5599
5600 default:
5601 return false;
5602 }
68f932c4 5603 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
15fe850f
AS
5604 return true;
5605
8f2bf9f1
RS
5606 case ASHIFT:
5607 switch (mode)
5608 {
5609 case QImode:
5610 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5611 {
f40751dd 5612 *total = COSTS_N_INSNS (!speed ? 4 : 17);
68f932c4
RS
5613 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5614 speed);
8f2bf9f1
RS
5615 }
5616 else
5617 {
5618 val = INTVAL (XEXP (x, 1));
5619 if (val == 7)
5620 *total = COSTS_N_INSNS (3);
5621 else if (val >= 0 && val <= 7)
5622 *total = COSTS_N_INSNS (val);
5623 else
5624 *total = COSTS_N_INSNS (1);
5625 }
5626 break;
5627
5628 case HImode:
8c352fa8
GJL
5629 if (AVR_HAVE_MUL)
5630 {
5631 if (const_2_to_7_operand (XEXP (x, 1), HImode)
5632 && (SIGN_EXTEND == GET_CODE (XEXP (x, 0))
5633 || ZERO_EXTEND == GET_CODE (XEXP (x, 0))))
5634 {
5635 *total = COSTS_N_INSNS (!speed ? 4 : 6);
5636 return true;
5637 }
5638 }
5639
8f2bf9f1
RS
5640 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5641 {
f40751dd 5642 *total = COSTS_N_INSNS (!speed ? 5 : 41);
68f932c4
RS
5643 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5644 speed);
8f2bf9f1
RS
5645 }
5646 else
5647 switch (INTVAL (XEXP (x, 1)))
5648 {
5649 case 0:
5650 *total = 0;
5651 break;
5652 case 1:
5653 case 8:
5654 *total = COSTS_N_INSNS (2);
5655 break;
5656 case 9:
5657 *total = COSTS_N_INSNS (3);
5658 break;
5659 case 2:
5660 case 3:
5661 case 10:
5662 case 15:
5663 *total = COSTS_N_INSNS (4);
5664 break;
5665 case 7:
5666 case 11:
5667 case 12:
5668 *total = COSTS_N_INSNS (5);
5669 break;
5670 case 4:
f40751dd 5671 *total = COSTS_N_INSNS (!speed ? 5 : 8);
8f2bf9f1
RS
5672 break;
5673 case 6:
1f494b6d 5674 *total = COSTS_N_INSNS (!speed ? 5 : 9);
8f2bf9f1
RS
5675 break;
5676 case 5:
f40751dd 5677 *total = COSTS_N_INSNS (!speed ? 5 : 10);
8f2bf9f1
RS
5678 break;
5679 default:
f40751dd 5680 *total = COSTS_N_INSNS (!speed ? 5 : 41);
68f932c4
RS
5681 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5682 speed);
8f2bf9f1
RS
5683 }
5684 break;
5685
5686 case SImode:
5687 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5688 {
f40751dd 5689 *total = COSTS_N_INSNS (!speed ? 7 : 113);
68f932c4
RS
5690 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5691 speed);
8f2bf9f1
RS
5692 }
5693 else
5694 switch (INTVAL (XEXP (x, 1)))
5695 {
5696 case 0:
5697 *total = 0;
5698 break;
5699 case 24:
5700 *total = COSTS_N_INSNS (3);
5701 break;
5702 case 1:
5703 case 8:
5704 case 16:
5705 *total = COSTS_N_INSNS (4);
5706 break;
5707 case 31:
5708 *total = COSTS_N_INSNS (6);
5709 break;
5710 case 2:
f40751dd 5711 *total = COSTS_N_INSNS (!speed ? 7 : 8);
8f2bf9f1
RS
5712 break;
5713 default:
f40751dd 5714 *total = COSTS_N_INSNS (!speed ? 7 : 113);
68f932c4
RS
5715 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5716 speed);
8f2bf9f1
RS
5717 }
5718 break;
5719
5720 default:
5721 return false;
5722 }
68f932c4 5723 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1
RS
5724 return true;
5725
5726 case ASHIFTRT:
5727 switch (mode)
5728 {
5729 case QImode:
5730 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5731 {
f40751dd 5732 *total = COSTS_N_INSNS (!speed ? 4 : 17);
68f932c4
RS
5733 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5734 speed);
8f2bf9f1
RS
5735 }
5736 else
5737 {
5738 val = INTVAL (XEXP (x, 1));
5739 if (val == 6)
5740 *total = COSTS_N_INSNS (4);
5741 else if (val == 7)
5742 *total = COSTS_N_INSNS (2);
5743 else if (val >= 0 && val <= 7)
5744 *total = COSTS_N_INSNS (val);
5745 else
5746 *total = COSTS_N_INSNS (1);
5747 }
5748 break;
5749
5750 case HImode:
5751 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5752 {
f40751dd 5753 *total = COSTS_N_INSNS (!speed ? 5 : 41);
68f932c4
RS
5754 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5755 speed);
8f2bf9f1
RS
5756 }
5757 else
5758 switch (INTVAL (XEXP (x, 1)))
5759 {
5760 case 0:
5761 *total = 0;
5762 break;
5763 case 1:
5764 *total = COSTS_N_INSNS (2);
5765 break;
5766 case 15:
5767 *total = COSTS_N_INSNS (3);
5768 break;
5769 case 2:
5770 case 7:
5771 case 8:
5772 case 9:
5773 *total = COSTS_N_INSNS (4);
5774 break;
5775 case 10:
5776 case 14:
5777 *total = COSTS_N_INSNS (5);
5778 break;
5779 case 11:
f40751dd 5780 *total = COSTS_N_INSNS (!speed ? 5 : 6);
8f2bf9f1
RS
5781 break;
5782 case 12:
f40751dd 5783 *total = COSTS_N_INSNS (!speed ? 5 : 7);
8f2bf9f1
RS
5784 break;
5785 case 6:
5786 case 13:
f40751dd 5787 *total = COSTS_N_INSNS (!speed ? 5 : 8);
8f2bf9f1
RS
5788 break;
5789 default:
f40751dd 5790 *total = COSTS_N_INSNS (!speed ? 5 : 41);
68f932c4
RS
5791 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5792 speed);
8f2bf9f1
RS
5793 }
5794 break;
5795
5796 case SImode:
5797 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5798 {
f40751dd 5799 *total = COSTS_N_INSNS (!speed ? 7 : 113);
68f932c4
RS
5800 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5801 speed);
8f2bf9f1
RS
5802 }
5803 else
5804 switch (INTVAL (XEXP (x, 1)))
5805 {
5806 case 0:
5807 *total = 0;
5808 break;
5809 case 1:
5810 *total = COSTS_N_INSNS (4);
5811 break;
5812 case 8:
5813 case 16:
5814 case 24:
5815 *total = COSTS_N_INSNS (6);
5816 break;
5817 case 2:
f40751dd 5818 *total = COSTS_N_INSNS (!speed ? 7 : 8);
8f2bf9f1
RS
5819 break;
5820 case 31:
4301ec4f 5821 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
8f2bf9f1
RS
5822 break;
5823 default:
f40751dd 5824 *total = COSTS_N_INSNS (!speed ? 7 : 113);
68f932c4
RS
5825 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5826 speed);
8f2bf9f1
RS
5827 }
5828 break;
5829
5830 default:
5831 return false;
5832 }
68f932c4 5833 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1
RS
5834 return true;
5835
5836 case LSHIFTRT:
5837 switch (mode)
5838 {
5839 case QImode:
5840 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5841 {
f40751dd 5842 *total = COSTS_N_INSNS (!speed ? 4 : 17);
68f932c4
RS
5843 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5844 speed);
8f2bf9f1
RS
5845 }
5846 else
5847 {
5848 val = INTVAL (XEXP (x, 1));
5849 if (val == 7)
5850 *total = COSTS_N_INSNS (3);
5851 else if (val >= 0 && val <= 7)
5852 *total = COSTS_N_INSNS (val);
5853 else
5854 *total = COSTS_N_INSNS (1);
5855 }
5856 break;
5857
5858 case HImode:
5859 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5860 {
f40751dd 5861 *total = COSTS_N_INSNS (!speed ? 5 : 41);
68f932c4
RS
5862 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5863 speed);
8f2bf9f1
RS
5864 }
5865 else
5866 switch (INTVAL (XEXP (x, 1)))
5867 {
5868 case 0:
5869 *total = 0;
5870 break;
5871 case 1:
5872 case 8:
5873 *total = COSTS_N_INSNS (2);
5874 break;
5875 case 9:
5876 *total = COSTS_N_INSNS (3);
5877 break;
5878 case 2:
5879 case 10:
5880 case 15:
5881 *total = COSTS_N_INSNS (4);
5882 break;
5883 case 7:
5884 case 11:
5885 *total = COSTS_N_INSNS (5);
5886 break;
5887 case 3:
5888 case 12:
5889 case 13:
5890 case 14:
f40751dd 5891 *total = COSTS_N_INSNS (!speed ? 5 : 6);
8f2bf9f1
RS
5892 break;
5893 case 4:
f40751dd 5894 *total = COSTS_N_INSNS (!speed ? 5 : 7);
8f2bf9f1
RS
5895 break;
5896 case 5:
5897 case 6:
f40751dd 5898 *total = COSTS_N_INSNS (!speed ? 5 : 9);
8f2bf9f1
RS
5899 break;
5900 default:
f40751dd 5901 *total = COSTS_N_INSNS (!speed ? 5 : 41);
68f932c4
RS
5902 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5903 speed);
8f2bf9f1
RS
5904 }
5905 break;
5906
5907 case SImode:
5908 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5909 {
f40751dd 5910 *total = COSTS_N_INSNS (!speed ? 7 : 113);
68f932c4
RS
5911 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5912 speed);
8f2bf9f1
RS
5913 }
5914 else
5915 switch (INTVAL (XEXP (x, 1)))
5916 {
5917 case 0:
5918 *total = 0;
5919 break;
5920 case 1:
5921 *total = COSTS_N_INSNS (4);
5922 break;
5923 case 2:
f40751dd 5924 *total = COSTS_N_INSNS (!speed ? 7 : 8);
8f2bf9f1
RS
5925 break;
5926 case 8:
5927 case 16:
5928 case 24:
5929 *total = COSTS_N_INSNS (4);
5930 break;
5931 case 31:
5932 *total = COSTS_N_INSNS (6);
5933 break;
5934 default:
f40751dd 5935 *total = COSTS_N_INSNS (!speed ? 7 : 113);
68f932c4
RS
5936 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
5937 speed);
8f2bf9f1
RS
5938 }
5939 break;
5940
5941 default:
5942 return false;
5943 }
68f932c4 5944 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1
RS
5945 return true;
5946
5947 case COMPARE:
5948 switch (GET_MODE (XEXP (x, 0)))
3c50106f 5949 {
8f2bf9f1
RS
5950 case QImode:
5951 *total = COSTS_N_INSNS (1);
5952 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
68f932c4 5953 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
8f2bf9f1
RS
5954 break;
5955
5956 case HImode:
5957 *total = COSTS_N_INSNS (2);
5958 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
68f932c4 5959 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
8f2bf9f1
RS
5960 else if (INTVAL (XEXP (x, 1)) != 0)
5961 *total += COSTS_N_INSNS (1);
5962 break;
5963
5964 case SImode:
5965 *total = COSTS_N_INSNS (4);
5966 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
68f932c4 5967 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
8f2bf9f1
RS
5968 else if (INTVAL (XEXP (x, 1)) != 0)
5969 *total += COSTS_N_INSNS (3);
5970 break;
5971
5972 default:
5973 return false;
3c50106f 5974 }
68f932c4 5975 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1
RS
5976 return true;
5977
7ece3881
GJL
5978 case TRUNCATE:
5979 if (AVR_HAVE_MUL
5980 && LSHIFTRT == GET_CODE (XEXP (x, 0))
5981 && MULT == GET_CODE (XEXP (XEXP (x, 0), 0))
5982 && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
5983 {
5984 if (QImode == mode || HImode == mode)
5985 {
5986 *total = COSTS_N_INSNS (2);
5987 return true;
5988 }
5989 }
5990 break;
5991
8f2bf9f1
RS
5992 default:
5993 break;
3c50106f 5994 }
8f2bf9f1 5995 return false;
3c50106f
RH
5996}
5997
2c338472 5998/* Calculate the cost of a memory address. */
90e7678c 5999
dcefdf67 6000static int
f40751dd 6001avr_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED)
90e7678c
DC
6002{
6003 if (GET_CODE (x) == PLUS
6004 && GET_CODE (XEXP (x,1)) == CONST_INT
6005 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
6006 && INTVAL (XEXP (x,1)) >= 61)
6007 return 18;
6008 if (CONSTANT_ADDRESS_P (x))
5fecfd8d 6009 {
e6b69d0e 6010 if (optimize > 0 && io_address_operand (x, QImode))
5fecfd8d
MM
6011 return 2;
6012 return 4;
6013 }
90e7678c
DC
6014 return 4;
6015}
6016
2d67effa
DC
6017/* Test for extra memory constraint 'Q'.
6018 It's a memory address based on Y or Z pointer with valid displacement. */
90e7678c
DC
6019
6020int
2d67effa 6021extra_constraint_Q (rtx x)
90e7678c 6022{
2d67effa
DC
6023 if (GET_CODE (XEXP (x,0)) == PLUS
6024 && REG_P (XEXP (XEXP (x,0), 0))
6025 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
6026 && (INTVAL (XEXP (XEXP (x,0), 1))
6027 <= MAX_LD_OFFSET (GET_MODE (x))))
90e7678c 6028 {
2d67effa
DC
6029 rtx xx = XEXP (XEXP (x,0), 0);
6030 int regno = REGNO (xx);
6031 if (TARGET_ALL_DEBUG)
90e7678c 6032 {
2d67effa
DC
6033 fprintf (stderr, ("extra_constraint:\n"
6034 "reload_completed: %d\n"
6035 "reload_in_progress: %d\n"),
6036 reload_completed, reload_in_progress);
6037 debug_rtx (x);
90e7678c 6038 }
2d67effa
DC
6039 if (regno >= FIRST_PSEUDO_REGISTER)
6040 return 1; /* allocate pseudos */
6041 else if (regno == REG_Z || regno == REG_Y)
6042 return 1; /* strictly check */
6043 else if (xx == frame_pointer_rtx
6044 || xx == arg_pointer_rtx)
6045 return 1; /* XXX frame & arg pointer checks */
90e7678c
DC
6046 }
6047 return 0;
6048}
6049
2c338472 6050/* Convert condition code CONDITION to the valid AVR condition code. */
90e7678c
DC
6051
6052RTX_CODE
269e3795 6053avr_normalize_condition (RTX_CODE condition)
90e7678c
DC
6054{
6055 switch (condition)
6056 {
6057 case GT:
6058 return GE;
6059 case GTU:
6060 return GEU;
6061 case LE:
6062 return LT;
6063 case LEU:
6064 return LTU;
6065 default:
25b9575b 6066 gcc_unreachable ();
90e7678c
DC
6067 }
6068}
6069
f3713778
GJL
6070/* Helper function for `avr_reorg'. */
6071
6072static rtx
6073avr_compare_pattern (rtx insn)
6074{
6075 rtx pattern = single_set (insn);
6076
6077 if (pattern
6078 && NONJUMP_INSN_P (insn)
6079 && SET_DEST (pattern) == cc0_rtx
6080 && GET_CODE (SET_SRC (pattern)) == COMPARE)
6081 {
6082 return pattern;
6083 }
6084
6085 return NULL_RTX;
6086}
6087
6088/* Helper function for `avr_reorg'. */
6089
6090/* Expansion of switch/case decision trees leads to code like
6091
6092 cc0 = compare (Reg, Num)
6093 if (cc0 == 0)
6094 goto L1
6095
6096 cc0 = compare (Reg, Num)
6097 if (cc0 > 0)
6098 goto L2
6099
6100 The second comparison is superfluous and can be deleted.
6101 The second jump condition can be transformed from a
6102 "difficult" one to a "simple" one because "cc0 > 0" and
6103 "cc0 >= 0" will have the same effect here.
6104
6105 This function relies on the way switch/case is being expaned
6106 as binary decision tree. For example code see PR 49903.
6107
6108 Return TRUE if optimization performed.
6109 Return FALSE if nothing changed.
6110
6111 INSN1 is a comparison, i.e. avr_compare_pattern != 0.
6112
6113 We don't want to do this in text peephole because it is
6114 tedious to work out jump offsets there and the second comparison
6115 might have been transormed by `avr_reorg'.
6116
6117 RTL peephole won't do because peephole2 does not scan across
6118 basic blocks. */
6119
6120static bool
6121avr_reorg_remove_redundant_compare (rtx insn1)
6122{
6123 rtx comp1, ifelse1, xcond1, branch1;
6124 rtx comp2, ifelse2, xcond2, branch2, insn2;
6125 enum rtx_code code;
6126 rtx jump, target, cond;
6127
6128 /* Look out for: compare1 - branch1 - compare2 - branch2 */
6129
6130 branch1 = next_nonnote_nondebug_insn (insn1);
6131 if (!branch1 || !JUMP_P (branch1))
6132 return false;
6133
6134 insn2 = next_nonnote_nondebug_insn (branch1);
6135 if (!insn2 || !avr_compare_pattern (insn2))
6136 return false;
6137
6138 branch2 = next_nonnote_nondebug_insn (insn2);
6139 if (!branch2 || !JUMP_P (branch2))
6140 return false;
6141
6142 comp1 = avr_compare_pattern (insn1);
6143 comp2 = avr_compare_pattern (insn2);
6144 xcond1 = single_set (branch1);
6145 xcond2 = single_set (branch2);
6146
6147 if (!comp1 || !comp2
6148 || !rtx_equal_p (comp1, comp2)
6149 || !xcond1 || SET_DEST (xcond1) != pc_rtx
6150 || !xcond2 || SET_DEST (xcond2) != pc_rtx
6151 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond1))
6152 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond2)))
6153 {
6154 return false;
6155 }
6156
6157 comp1 = SET_SRC (comp1);
6158 ifelse1 = SET_SRC (xcond1);
6159 ifelse2 = SET_SRC (xcond2);
6160
6161 /* comp<n> is COMPARE now and ifelse<n> is IF_THEN_ELSE. */
6162
6163 if (EQ != GET_CODE (XEXP (ifelse1, 0))
6164 || !REG_P (XEXP (comp1, 0))
6165 || !CONST_INT_P (XEXP (comp1, 1))
6166 || XEXP (ifelse1, 2) != pc_rtx
6167 || XEXP (ifelse2, 2) != pc_rtx
6168 || LABEL_REF != GET_CODE (XEXP (ifelse1, 1))
6169 || LABEL_REF != GET_CODE (XEXP (ifelse2, 1))
6170 || !COMPARISON_P (XEXP (ifelse2, 0))
6171 || cc0_rtx != XEXP (XEXP (ifelse1, 0), 0)
6172 || cc0_rtx != XEXP (XEXP (ifelse2, 0), 0)
6173 || const0_rtx != XEXP (XEXP (ifelse1, 0), 1)
6174 || const0_rtx != XEXP (XEXP (ifelse2, 0), 1))
6175 {
6176 return false;
6177 }
6178
6179 /* We filtered the insn sequence to look like
6180
6181 (set (cc0)
6182 (compare (reg:M N)
6183 (const_int VAL)))
6184 (set (pc)
6185 (if_then_else (eq (cc0)
6186 (const_int 0))
6187 (label_ref L1)
6188 (pc)))
6189
6190 (set (cc0)
6191 (compare (reg:M N)
6192 (const_int VAL)))
6193 (set (pc)
6194 (if_then_else (CODE (cc0)
6195 (const_int 0))
6196 (label_ref L2)
6197 (pc)))
6198 */
6199
6200 code = GET_CODE (XEXP (ifelse2, 0));
6201
6202 /* Map GT/GTU to GE/GEU which is easier for AVR.
6203 The first two instructions compare/branch on EQ
6204 so we may replace the difficult
6205
6206 if (x == VAL) goto L1;
6207 if (x > VAL) goto L2;
6208
6209 with easy
6210
6211 if (x == VAL) goto L1;
6212 if (x >= VAL) goto L2;
6213
6214 Similarly, replace LE/LEU by LT/LTU. */
6215
6216 switch (code)
6217 {
6218 case EQ:
6219 case LT: case LTU:
6220 case GE: case GEU:
6221 break;
6222
6223 case LE: case LEU:
6224 case GT: case GTU:
6225 code = avr_normalize_condition (code);
6226 break;
6227
6228 default:
6229 return false;
6230 }
6231
6232 /* Wrap the branches into UNSPECs so they won't be changed or
6233 optimized in the remainder. */
6234
6235 target = XEXP (XEXP (ifelse1, 1), 0);
6236 cond = XEXP (ifelse1, 0);
6237 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn1);
6238
6239 JUMP_LABEL (jump) = JUMP_LABEL (branch1);
6240
6241 target = XEXP (XEXP (ifelse2, 1), 0);
6242 cond = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
6243 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn2);
6244
6245 JUMP_LABEL (jump) = JUMP_LABEL (branch2);
6246
6247 /* The comparisons in insn1 and insn2 are exactly the same;
6248 insn2 is superfluous so delete it. */
6249
6250 delete_insn (insn2);
6251 delete_insn (branch1);
6252 delete_insn (branch2);
6253
6254 return true;
6255}
6256
6257
6258/* Implement `TARGET_MACHINE_DEPENDENT_REORG'. */
6259/* Optimize conditional jumps. */
90e7678c 6260
18dbd950 6261static void
269e3795 6262avr_reorg (void)
90e7678c 6263{
f3713778 6264 rtx insn = get_insns();
90e7678c 6265
f3713778 6266 for (insn = next_real_insn (insn); insn; insn = next_real_insn (insn))
90e7678c 6267 {
f3713778
GJL
6268 rtx pattern = avr_compare_pattern (insn);
6269
6270 if (!pattern)
6271 continue;
90e7678c 6272
f3713778
GJL
6273 if (optimize
6274 && avr_reorg_remove_redundant_compare (insn))
6275 {
6276 continue;
6277 }
90e7678c 6278
f3713778 6279 if (compare_diff_p (insn))
90e7678c 6280 {
f3713778
GJL
6281 /* Now we work under compare insn with difficult branch. */
6282
6283 rtx next = next_real_insn (insn);
6284 rtx pat = PATTERN (next);
6285
6286 pattern = SET_SRC (pattern);
6287
6288 if (true_regnum (XEXP (pattern, 0)) >= 0
6289 && true_regnum (XEXP (pattern, 1)) >= 0)
6290 {
6291 rtx x = XEXP (pattern, 0);
6292 rtx src = SET_SRC (pat);
6293 rtx t = XEXP (src,0);
6294 PUT_CODE (t, swap_condition (GET_CODE (t)));
6295 XEXP (pattern, 0) = XEXP (pattern, 1);
6296 XEXP (pattern, 1) = x;
6297 INSN_CODE (next) = -1;
6298 }
6299 else if (true_regnum (XEXP (pattern, 0)) >= 0
6300 && XEXP (pattern, 1) == const0_rtx)
6301 {
6302 /* This is a tst insn, we can reverse it. */
6303 rtx src = SET_SRC (pat);
6304 rtx t = XEXP (src,0);
f90b7a5a 6305
f3713778
GJL
6306 PUT_CODE (t, swap_condition (GET_CODE (t)));
6307 XEXP (pattern, 1) = XEXP (pattern, 0);
6308 XEXP (pattern, 0) = const0_rtx;
6309 INSN_CODE (next) = -1;
6310 INSN_CODE (insn) = -1;
6311 }
6312 else if (true_regnum (XEXP (pattern, 0)) >= 0
6313 && CONST_INT_P (XEXP (pattern, 1)))
6314 {
6315 rtx x = XEXP (pattern, 1);
6316 rtx src = SET_SRC (pat);
6317 rtx t = XEXP (src,0);
6318 enum machine_mode mode = GET_MODE (XEXP (pattern, 0));
6319
6320 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
6321 {
6322 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
6323 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
6324 INSN_CODE (next) = -1;
6325 INSN_CODE (insn) = -1;
6326 }
6327 }
6328 }
90e7678c
DC
6329 }
6330}
6331
6332/* Returns register number for function return value.*/
6333
fd01a351 6334static inline unsigned int
269e3795 6335avr_ret_register (void)
90e7678c
DC
6336{
6337 return 24;
6338}
6339
68fd7765
AS
6340/* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */
6341
6342static bool
6343avr_function_value_regno_p (const unsigned int regno)
6344{
6345 return (regno == avr_ret_register ());
6346}
6347
9f5ed61a 6348/* Create an RTX representing the place where a
90e7678c
DC
6349 library function returns a value of mode MODE. */
6350
68fd7765
AS
6351static rtx
6352avr_libcall_value (enum machine_mode mode,
6353 const_rtx func ATTRIBUTE_UNUSED)
90e7678c
DC
6354{
6355 int offs = GET_MODE_SIZE (mode);
6356 if (offs < 2)
6357 offs = 2;
68fd7765 6358 return gen_rtx_REG (mode, avr_ret_register () + 2 - offs);
90e7678c
DC
6359}
6360
6361/* Create an RTX representing the place where a
6362 function returns a value of data type VALTYPE. */
6363
68fd7765 6364static rtx
fd01a351
GJL
6365avr_function_value (const_tree type,
6366 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
6367 bool outgoing ATTRIBUTE_UNUSED)
90e7678c 6368{
3454eb73 6369 unsigned int offs;
68fd7765 6370
90e7678c 6371 if (TYPE_MODE (type) != BLKmode)
fd01a351 6372 return avr_libcall_value (TYPE_MODE (type), NULL_RTX);
90e7678c
DC
6373
6374 offs = int_size_in_bytes (type);
6375 if (offs < 2)
6376 offs = 2;
6377 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
6378 offs = GET_MODE_SIZE (SImode);
6379 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
6380 offs = GET_MODE_SIZE (DImode);
6381
68fd7765 6382 return gen_rtx_REG (BLKmode, avr_ret_register () + 2 - offs);
90e7678c
DC
6383}
6384
28e801e2 6385int
0a2aaacc 6386test_hard_reg_class (enum reg_class rclass, rtx x)
28e801e2
DC
6387{
6388 int regno = true_regnum (x);
6389 if (regno < 0)
6390 return 0;
26af4041 6391
0a2aaacc 6392 if (TEST_HARD_REG_CLASS (rclass, regno))
26af4041
MM
6393 return 1;
6394
6395 return 0;
28e801e2
DC
6396}
6397
b58c068a
DC
6398
6399int
269e3795 6400jump_over_one_insn_p (rtx insn, rtx dest)
b58c068a
DC
6401{
6402 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
6403 ? XEXP (dest, 0)
6404 : dest);
9d98a694
AO
6405 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
6406 int dest_addr = INSN_ADDRESSES (uid);
331ca350 6407 return dest_addr - jump_addr == get_attr_length (insn) + 1;
b58c068a 6408}
78cf8279
MM
6409
6410/* Returns 1 if a value of mode MODE can be stored starting with hard
c4984bad
MM
6411 register number REGNO. On the enhanced core, anything larger than
6412 1 byte must start in even numbered register for "movw" to work
6413 (this way we don't have to check for odd registers everywhere). */
78cf8279
MM
6414
6415int
269e3795 6416avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
78cf8279 6417{
3e4f8484
GJL
6418 /* NOTE: 8-bit values must not be disallowed for R28 or R29.
6419 Disallowing QI et al. in these regs might lead to code like
6420 (set (subreg:QI (reg:HI 28) n) ...)
6421 which will result in wrong code because reload does not
6422 handle SUBREGs of hard regsisters like this.
6423 This could be fixed in reload. However, it appears
6424 that fixing reload is not wanted by reload people. */
6425
6426 /* Any GENERAL_REGS register can hold 8-bit values. */
6427
6428 if (GET_MODE_SIZE (mode) == 1)
78cf8279 6429 return 1;
d2ebe27c 6430
3e4f8484
GJL
6431 /* FIXME: Ideally, the following test is not needed.
6432 However, it turned out that it can reduce the number
6433 of spill fails. AVR and it's poor endowment with
6434 address registers is extreme stress test for reload. */
6435
6436 if (GET_MODE_SIZE (mode) >= 4
6437 && regno >= REG_X)
d2ebe27c
RS
6438 return 0;
6439
3e4f8484
GJL
6440 /* All modes larger than 8 bits should start in an even register. */
6441
78cf8279
MM
6442 return !(regno & 1);
6443}
6bec29c9 6444
5fecfd8d 6445const char *
269e3795 6446output_reload_inhi (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
6bec29c9 6447{
612105a6
DC
6448 int tmp;
6449 if (!len)
6450 len = &tmp;
6451
6bec29c9
DC
6452 if (GET_CODE (operands[1]) == CONST_INT)
6453 {
6454 int val = INTVAL (operands[1]);
6455 if ((val & 0xff) == 0)
6456 {
6457 *len = 3;
6458 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
6459 AS2 (ldi,%2,hi8(%1)) CR_TAB
6460 AS2 (mov,%B0,%2));
6461 }
6462 else if ((val & 0xff00) == 0)
6463 {
6464 *len = 3;
6465 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
6466 AS2 (mov,%A0,%2) CR_TAB
6467 AS2 (mov,%B0,__zero_reg__));
6468 }
6469 else if ((val & 0xff) == ((val & 0xff00) >> 8))
6470 {
6471 *len = 3;
6472 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
6473 AS2 (mov,%A0,%2) CR_TAB
6474 AS2 (mov,%B0,%2));
6475 }
6476 }
6477 *len = 4;
6478 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
6479 AS2 (mov,%A0,%2) CR_TAB
6480 AS2 (ldi,%2,hi8(%1)) CR_TAB
6481 AS2 (mov,%B0,%2));
6482}
6483
6484
1e6a67d1
GJL
6485/* Reload a SI or SF compile time constant (OP[1]) into a GPR (OP[0]).
6486 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
6487 into a NO_LD_REGS. If CLOBBER_REG is NULL_RTX we either don't need a
6488 clobber reg or have to cook one up.
6489
6490 LEN == NULL: Output instructions.
6491
6492 LEN != NULL: Output nothing. Increment *LEN by number of words occupied
6493 by the insns printed.
6494
6495 Return "". */
6496
5fecfd8d 6497const char *
1e6a67d1
GJL
6498output_reload_insisf (rtx insn ATTRIBUTE_UNUSED,
6499 rtx *op, rtx clobber_reg, int *len)
6bec29c9 6500{
1e6a67d1
GJL
6501 rtx src = op[1];
6502 rtx dest = op[0];
6503 rtx xval, xdest[4];
6504 int ival[4];
6505 int clobber_val = 1234;
6506 bool cooked_clobber_p = false;
6507 bool set_p = false;
6508 unsigned int n;
6509 enum machine_mode mode = GET_MODE (dest);
6510
6511 gcc_assert (REG_P (dest));
5fecfd8d
MM
6512
6513 if (len)
1e6a67d1
GJL
6514 *len = 0;
6515
6516 /* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
6517 but has some subregs that are in LD_REGS. Use the MSB (REG:QI 17). */
6518
6519 if (14 == REGNO (dest))
5fecfd8d 6520 {
1e6a67d1 6521 clobber_reg = gen_rtx_REG (QImode, 17);
5fecfd8d 6522 }
6bec29c9 6523
1e6a67d1
GJL
6524 /* We might need a clobber reg but don't have one. Look at the value
6525 to be loaded more closely. A clobber is only needed if it contains
6526 a byte that is neither 0, -1 or a power of 2. */
6527
6528 if (NULL_RTX == clobber_reg
6529 && !test_hard_reg_class (LD_REGS, dest))
6bec29c9 6530 {
1e6a67d1
GJL
6531 for (n = 0; n < GET_MODE_SIZE (mode); n++)
6532 {
6533 xval = simplify_gen_subreg (QImode, src, mode, n);
6534
6535 if (!(const0_rtx == xval
6536 || constm1_rtx == xval
6537 || single_one_operand (xval, QImode)))
6538 {
6539 /* We have no clobber reg but need one. Cook one up.
6540 That's cheaper than loading from constant pool. */
6541
6542 cooked_clobber_p = true;
7d8d6d73 6543 clobber_reg = gen_rtx_REG (QImode, REG_Z + 1);
1e6a67d1
GJL
6544 avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg, len, 1);
6545 break;
6546 }
6547 }
6bec29c9 6548 }
1e6a67d1
GJL
6549
6550 /* Now start filling DEST from LSB to MSB. */
6551
6552 for (n = 0; n < GET_MODE_SIZE (mode); n++)
6bec29c9 6553 {
1e6a67d1
GJL
6554 bool done_byte = false;
6555 unsigned int j;
6556 rtx xop[3];
6557
6558 /* Crop the n-th sub-byte. */
6559
6560 xval = simplify_gen_subreg (QImode, src, mode, n);
6561 xdest[n] = simplify_gen_subreg (QImode, dest, mode, n);
6562 ival[n] = INTVAL (xval);
6563
6564 /* Look if we can reuse the low word by means of MOVW. */
6565
6566 if (n == 2
6567 && AVR_HAVE_MOVW)
6568 {
6569 rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0);
6570 rtx hi16 = simplify_gen_subreg (HImode, src, mode, 2);
6571
6572 if (INTVAL (lo16) == INTVAL (hi16))
6573 {
6574 avr_asm_len ("movw %C0,%A0", &op[0], len, 1);
6575 break;
6576 }
6577 }
6578
6579 /* Use CLR to zero a value so that cc0 is set as expected
6580 for zero. */
6581
6582 if (ival[n] == 0)
6583 {
6584 avr_asm_len ("clr %0", &xdest[n], len, 1);
6585 continue;
6586 }
6587
6588 if (clobber_val == ival[n]
6589 && REGNO (clobber_reg) == REGNO (xdest[n]))
6590 {
6591 continue;
6592 }
6593
6594 /* LD_REGS can use LDI to move a constant value */
6595
6596 if (test_hard_reg_class (LD_REGS, xdest[n]))
6597 {
6598 xop[0] = xdest[n];
6599 xop[1] = xval;
6600 avr_asm_len ("ldi %0,lo8(%1)", xop, len, 1);
6601 continue;
6602 }
6603
6604 /* Try to reuse value already loaded in some lower byte. */
6605
6606 for (j = 0; j < n; j++)
6607 if (ival[j] == ival[n])
6608 {
6609 xop[0] = xdest[n];
6610 xop[1] = xdest[j];
6611
6612 avr_asm_len ("mov %0,%1", xop, len, 1);
6613 done_byte = true;
6614 break;
6615 }
6616
6617 if (done_byte)
6618 continue;
6619
6620 /* Need no clobber reg for -1: Use CLR/DEC */
6621
6622 if (-1 == ival[n])
6623 {
6624 avr_asm_len ("clr %0" CR_TAB
6625 "dec %0", &xdest[n], len, 2);
6626 continue;
6627 }
6628
6629 /* Use T flag or INC to manage powers of 2 if we have
6630 no clobber reg. */
6631
6632 if (NULL_RTX == clobber_reg
6633 && single_one_operand (xval, QImode))
6634 {
6635 if (1 == ival[n])
6636 {
6637 avr_asm_len ("clr %0" CR_TAB
6638 "inc %0", &xdest[n], len, 2);
6639 continue;
6640 }
6641
6642 xop[0] = xdest[n];
6643 xop[1] = GEN_INT (exact_log2 (ival[n] & GET_MODE_MASK (QImode)));
6644
6645 gcc_assert (constm1_rtx != xop[1]);
6646
6647 if (!set_p)
6648 {
6649 set_p = true;
6650 avr_asm_len ("set", xop, len, 1);
6651 }
6652
6653 avr_asm_len ("clr %0" CR_TAB
6654 "bld %0,%1", xop, len, 2);
6655 continue;
6656 }
6657
6658 /* We actually need the LD_REGS clobber reg. */
6659
6660 gcc_assert (NULL_RTX != clobber_reg);
6661
6662 xop[0] = xdest[n];
6663 xop[1] = xval;
6664 xop[2] = clobber_reg;
6665 clobber_val = ival[n];
6666
6667 avr_asm_len ("ldi %2,lo8(%1)" CR_TAB
6668 "mov %0,%2", xop, len, 2);
6bec29c9 6669 }
1e6a67d1
GJL
6670
6671 /* If we cooked up a clobber reg above, restore it. */
6672
6673 if (cooked_clobber_p)
6bec29c9 6674 {
1e6a67d1 6675 avr_asm_len ("mov %0,__tmp_reg__", &clobber_reg, len, 1);
6bec29c9 6676 }
1e6a67d1 6677
6bec29c9
DC
6678 return "";
6679}
afee2a52
MM
6680
6681void
269e3795 6682avr_output_bld (rtx operands[], int bit_nr)
afee2a52
MM
6683{
6684 static char s[] = "bld %A0,0";
6685
6686 s[5] = 'A' + (bit_nr >> 3);
6687 s[8] = '0' + (bit_nr & 7);
6688 output_asm_insn (s, operands);
6689}
6690
e9284adf 6691void
269e3795 6692avr_output_addr_vec_elt (FILE *stream, int value)
e9284adf 6693{
d6b5193b 6694 switch_to_section (progmem_section);
693092fb
BH
6695 if (AVR_HAVE_JMP_CALL)
6696 fprintf (stream, "\t.word gs(.L%d)\n", value);
e9284adf
MM
6697 else
6698 fprintf (stream, "\trjmp .L%d\n", value);
e9284adf
MM
6699}
6700
1cf0a7f1 6701/* Returns true if SCRATCH are safe to be allocated as a scratch
dcfb1a36
MM
6702 registers (for a define_peephole2) in the current function. */
6703
1cf0a7f1
AS
6704bool
6705avr_hard_regno_scratch_ok (unsigned int regno)
dcfb1a36 6706{
1cf0a7f1
AS
6707 /* Interrupt functions can only use registers that have already been saved
6708 by the prologue, even if they would normally be call-clobbered. */
dcfb1a36 6709
1cf0a7f1
AS
6710 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
6711 && !df_regs_ever_live_p (regno))
6712 return false;
6713
3e4f8484
GJL
6714 /* Don't allow hard registers that might be part of the frame pointer.
6715 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
6716 and don't care for a frame pointer that spans more than one register. */
6717
6718 if ((!reload_completed || frame_pointer_needed)
6719 && (regno == REG_Y || regno == REG_Y + 1))
6720 {
6721 return false;
6722 }
6723
1cf0a7f1 6724 return true;
dcfb1a36 6725}
331ca350 6726
91635d08
AS
6727/* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
6728
6729int
3e4f8484 6730avr_hard_regno_rename_ok (unsigned int old_reg,
91635d08
AS
6731 unsigned int new_reg)
6732{
6733 /* Interrupt functions can only use registers that have already been
6734 saved by the prologue, even if they would normally be
6735 call-clobbered. */
6736
6737 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
6738 && !df_regs_ever_live_p (new_reg))
6739 return 0;
6740
3e4f8484
GJL
6741 /* Don't allow hard registers that might be part of the frame pointer.
6742 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
6743 and don't care for a frame pointer that spans more than one register. */
6744
6745 if ((!reload_completed || frame_pointer_needed)
6746 && (old_reg == REG_Y || old_reg == REG_Y + 1
6747 || new_reg == REG_Y || new_reg == REG_Y + 1))
6748 {
6749 return 0;
6750 }
6751
91635d08
AS
6752 return 1;
6753}
6754
ed1f5d71 6755/* Output a branch that tests a single bit of a register (QI, HI, SI or DImode)
331ca350
MM
6756 or memory location in the I/O space (QImode only).
6757
6758 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
6759 Operand 1: register operand to test, or CONST_INT memory address.
ed1f5d71 6760 Operand 2: bit number.
331ca350
MM
6761 Operand 3: label to jump to if the test is true. */
6762
6763const char *
269e3795 6764avr_out_sbxx_branch (rtx insn, rtx operands[])
331ca350
MM
6765{
6766 enum rtx_code comp = GET_CODE (operands[0]);
6767 int long_jump = (get_attr_length (insn) >= 4);
6768 int reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
6769
6770 if (comp == GE)
6771 comp = EQ;
6772 else if (comp == LT)
6773 comp = NE;
6774
6775 if (reverse)
6776 comp = reverse_condition (comp);
6777
6778 if (GET_CODE (operands[1]) == CONST_INT)
6779 {
6780 if (INTVAL (operands[1]) < 0x40)
6781 {
6782 if (comp == EQ)
846428f1 6783 output_asm_insn (AS2 (sbis,%m1-0x20,%2), operands);
331ca350 6784 else
846428f1 6785 output_asm_insn (AS2 (sbic,%m1-0x20,%2), operands);
331ca350
MM
6786 }
6787 else
6788 {
846428f1 6789 output_asm_insn (AS2 (in,__tmp_reg__,%m1-0x20), operands);
331ca350
MM
6790 if (comp == EQ)
6791 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
6792 else
6793 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
6794 }
6795 }
6796 else /* GET_CODE (operands[1]) == REG */
6797 {
6798 if (GET_MODE (operands[1]) == QImode)
6799 {
6800 if (comp == EQ)
6801 output_asm_insn (AS2 (sbrs,%1,%2), operands);
6802 else
6803 output_asm_insn (AS2 (sbrc,%1,%2), operands);
6804 }
6805 else /* HImode or SImode */
6806 {
6807 static char buf[] = "sbrc %A1,0";
ed1f5d71 6808 int bit_nr = INTVAL (operands[2]);
331ca350
MM
6809 buf[3] = (comp == EQ) ? 's' : 'c';
6810 buf[6] = 'A' + (bit_nr >> 3);
6811 buf[9] = '0' + (bit_nr & 7);
6812 output_asm_insn (buf, operands);
6813 }
6814 }
6815
6816 if (long_jump)
13e8651c 6817 return (AS1 (rjmp,.+4) CR_TAB
846428f1 6818 AS1 (jmp,%x3));
331ca350 6819 if (!reverse)
846428f1 6820 return AS1 (rjmp,%x3);
331ca350
MM
6821 return "";
6822}
9af145ae 6823
bd5bd7ac
KH
6824/* Worker function for TARGET_ASM_CONSTRUCTOR. */
6825
9af145ae 6826static void
269e3795 6827avr_asm_out_ctor (rtx symbol, int priority)
9af145ae
MM
6828{
6829 fputs ("\t.global __do_global_ctors\n", asm_out_file);
6830 default_ctor_section_asm_out_constructor (symbol, priority);
6831}
6832
bd5bd7ac
KH
6833/* Worker function for TARGET_ASM_DESTRUCTOR. */
6834
9af145ae 6835static void
269e3795 6836avr_asm_out_dtor (rtx symbol, int priority)
9af145ae
MM
6837{
6838 fputs ("\t.global __do_global_dtors\n", asm_out_file);
6839 default_dtor_section_asm_out_destructor (symbol, priority);
6840}
6841
bd5bd7ac
KH
6842/* Worker function for TARGET_RETURN_IN_MEMORY. */
6843
b069302c 6844static bool
586de218 6845avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
b069302c 6846{
78bc94a2
KH
6847 if (TYPE_MODE (type) == BLKmode)
6848 {
6849 HOST_WIDE_INT size = int_size_in_bytes (type);
6850 return (size == -1 || size > 8);
6851 }
6852 else
6853 return false;
b069302c
KH
6854}
6855
4223ff5f
AS
6856/* Worker function for CASE_VALUES_THRESHOLD. */
6857
6858unsigned int avr_case_values_threshold (void)
6859{
6860 return (!AVR_HAVE_JMP_CALL || TARGET_CALL_PROLOGUES) ? 8 : 17;
6861}
6862
43ea6502
AS
6863/* Helper for __builtin_avr_delay_cycles */
6864
6865static void
6866avr_expand_delay_cycles (rtx operands0)
6867{
6868 unsigned HOST_WIDE_INT cycles = UINTVAL (operands0);
6869 unsigned HOST_WIDE_INT cycles_used;
6870 unsigned HOST_WIDE_INT loop_count;
6871
6872 if (IN_RANGE (cycles, 83886082, 0xFFFFFFFF))
6873 {
6874 loop_count = ((cycles - 9) / 6) + 1;
6875 cycles_used = ((loop_count - 1) * 6) + 9;
6876 emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode)));
6877 cycles -= cycles_used;
6878 }
6879
6880 if (IN_RANGE (cycles, 262145, 83886081))
6881 {
6882 loop_count = ((cycles - 7) / 5) + 1;
6883 if (loop_count > 0xFFFFFF)
6884 loop_count = 0xFFFFFF;
6885 cycles_used = ((loop_count - 1) * 5) + 7;
6886 emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode)));
6887 cycles -= cycles_used;
6888 }
6889
6890 if (IN_RANGE (cycles, 768, 262144))
6891 {
6892 loop_count = ((cycles - 5) / 4) + 1;
6893 if (loop_count > 0xFFFF)
6894 loop_count = 0xFFFF;
6895 cycles_used = ((loop_count - 1) * 4) + 5;
6896 emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode)));
6897 cycles -= cycles_used;
6898 }
6899
6900 if (IN_RANGE (cycles, 6, 767))
6901 {
6902 loop_count = cycles / 3;
6903 if (loop_count > 255)
6904 loop_count = 255;
6905 cycles_used = loop_count * 3;
6906 emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode)));
6907 cycles -= cycles_used;
6908 }
6909
6910 while (cycles >= 2)
6911 {
6912 emit_insn (gen_nopv (GEN_INT(2)));
6913 cycles -= 2;
6914 }
6915
6916 if (cycles == 1)
6917 {
6918 emit_insn (gen_nopv (GEN_INT(1)));
6919 cycles--;
6920 }
6921}
6922
6923/* IDs for all the AVR builtins. */
6924
6925enum avr_builtin_id
6926 {
6927 AVR_BUILTIN_NOP,
6928 AVR_BUILTIN_SEI,
6929 AVR_BUILTIN_CLI,
6930 AVR_BUILTIN_WDR,
6931 AVR_BUILTIN_SLEEP,
6932 AVR_BUILTIN_SWAP,
6933 AVR_BUILTIN_FMUL,
6934 AVR_BUILTIN_FMULS,
6935 AVR_BUILTIN_FMULSU,
6936 AVR_BUILTIN_DELAY_CYCLES
6937 };
6938
6939#define DEF_BUILTIN(NAME, TYPE, CODE) \
6940 do \
6941 { \
6942 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
6943 NULL, NULL_TREE); \
6944 } while (0)
6945
6946
6947/* Implement `TARGET_INIT_BUILTINS' */
6948/* Set up all builtin functions for this target. */
6949
6950static void
6951avr_init_builtins (void)
6952{
6953 tree void_ftype_void
c19afe52 6954 = build_function_type_list (void_type_node, NULL_TREE);
43ea6502
AS
6955 tree uchar_ftype_uchar
6956 = build_function_type_list (unsigned_char_type_node,
6957 unsigned_char_type_node,
6958 NULL_TREE);
6959 tree uint_ftype_uchar_uchar
6960 = build_function_type_list (unsigned_type_node,
6961 unsigned_char_type_node,
6962 unsigned_char_type_node,
6963 NULL_TREE);
6964 tree int_ftype_char_char
6965 = build_function_type_list (integer_type_node,
6966 char_type_node,
6967 char_type_node,
6968 NULL_TREE);
6969 tree int_ftype_char_uchar
6970 = build_function_type_list (integer_type_node,
6971 char_type_node,
6972 unsigned_char_type_node,
6973 NULL_TREE);
6974 tree void_ftype_ulong
6975 = build_function_type_list (void_type_node,
6976 long_unsigned_type_node,
6977 NULL_TREE);
6978
6979 DEF_BUILTIN ("__builtin_avr_nop", void_ftype_void, AVR_BUILTIN_NOP);
6980 DEF_BUILTIN ("__builtin_avr_sei", void_ftype_void, AVR_BUILTIN_SEI);
6981 DEF_BUILTIN ("__builtin_avr_cli", void_ftype_void, AVR_BUILTIN_CLI);
6982 DEF_BUILTIN ("__builtin_avr_wdr", void_ftype_void, AVR_BUILTIN_WDR);
6983 DEF_BUILTIN ("__builtin_avr_sleep", void_ftype_void, AVR_BUILTIN_SLEEP);
6984 DEF_BUILTIN ("__builtin_avr_swap", uchar_ftype_uchar, AVR_BUILTIN_SWAP);
6985 DEF_BUILTIN ("__builtin_avr_delay_cycles", void_ftype_ulong,
6986 AVR_BUILTIN_DELAY_CYCLES);
6987
f451d14d
GJL
6988 DEF_BUILTIN ("__builtin_avr_fmul", uint_ftype_uchar_uchar,
6989 AVR_BUILTIN_FMUL);
6990 DEF_BUILTIN ("__builtin_avr_fmuls", int_ftype_char_char,
6991 AVR_BUILTIN_FMULS);
6992 DEF_BUILTIN ("__builtin_avr_fmulsu", int_ftype_char_uchar,
6993 AVR_BUILTIN_FMULSU);
43ea6502
AS
6994}
6995
6996#undef DEF_BUILTIN
6997
6998struct avr_builtin_description
6999{
7000 const enum insn_code icode;
7001 const char *const name;
7002 const enum avr_builtin_id id;
7003};
7004
7005static const struct avr_builtin_description
7006bdesc_1arg[] =
7007 {
7008 { CODE_FOR_rotlqi3_4, "__builtin_avr_swap", AVR_BUILTIN_SWAP }
7009 };
7010
7011static const struct avr_builtin_description
7012bdesc_2arg[] =
7013 {
7014 { CODE_FOR_fmul, "__builtin_avr_fmul", AVR_BUILTIN_FMUL },
7015 { CODE_FOR_fmuls, "__builtin_avr_fmuls", AVR_BUILTIN_FMULS },
7016 { CODE_FOR_fmulsu, "__builtin_avr_fmulsu", AVR_BUILTIN_FMULSU }
7017 };
7018
7019/* Subroutine of avr_expand_builtin to take care of unop insns. */
7020
7021static rtx
7022avr_expand_unop_builtin (enum insn_code icode, tree exp,
7023 rtx target)
7024{
7025 rtx pat;
7026 tree arg0 = CALL_EXPR_ARG (exp, 0);
fd01a351 7027 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
43ea6502
AS
7028 enum machine_mode op0mode = GET_MODE (op0);
7029 enum machine_mode tmode = insn_data[icode].operand[0].mode;
7030 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
7031
7032 if (! target
7033 || GET_MODE (target) != tmode
7034 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
7035 {
7036 target = gen_reg_rtx (tmode);
7037 }
7038
7039 if (op0mode == SImode && mode0 == HImode)
7040 {
7041 op0mode = HImode;
7042 op0 = gen_lowpart (HImode, op0);
7043 }
7044
7045 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
7046
7047 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
7048 op0 = copy_to_mode_reg (mode0, op0);
7049
7050 pat = GEN_FCN (icode) (target, op0);
7051 if (! pat)
7052 return 0;
7053
7054 emit_insn (pat);
7055
7056 return target;
7057}
7058
7059
7060/* Subroutine of avr_expand_builtin to take care of binop insns. */
7061
7062static rtx
7063avr_expand_binop_builtin (enum insn_code icode, tree exp, rtx target)
7064{
7065 rtx pat;
7066 tree arg0 = CALL_EXPR_ARG (exp, 0);
7067 tree arg1 = CALL_EXPR_ARG (exp, 1);
fd01a351
GJL
7068 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
7069 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
43ea6502
AS
7070 enum machine_mode op0mode = GET_MODE (op0);
7071 enum machine_mode op1mode = GET_MODE (op1);
7072 enum machine_mode tmode = insn_data[icode].operand[0].mode;
7073 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
7074 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
7075
7076 if (! target
7077 || GET_MODE (target) != tmode
7078 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
7079 {
7080 target = gen_reg_rtx (tmode);
7081 }
7082
7083 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
7084 {
7085 op0mode = HImode;
7086 op0 = gen_lowpart (HImode, op0);
7087 }
7088
7089 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
7090 {
7091 op1mode = HImode;
7092 op1 = gen_lowpart (HImode, op1);
7093 }
7094
7095 /* In case the insn wants input operands in modes different from
7096 the result, abort. */
7097
7098 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
7099 && (op1mode == mode1 || op1mode == VOIDmode));
7100
7101 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
7102 op0 = copy_to_mode_reg (mode0, op0);
7103
7104 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
7105 op1 = copy_to_mode_reg (mode1, op1);
7106
7107 pat = GEN_FCN (icode) (target, op0, op1);
7108
7109 if (! pat)
7110 return 0;
7111
7112 emit_insn (pat);
7113 return target;
7114}
7115
7116
7117/* Expand an expression EXP that calls a built-in function,
7118 with result going to TARGET if that's convenient
7119 (and in mode MODE if that's convenient).
7120 SUBTARGET may be used as the target for computing one of EXP's operands.
7121 IGNORE is nonzero if the value is to be ignored. */
7122
7123static rtx
7124avr_expand_builtin (tree exp, rtx target,
7125 rtx subtarget ATTRIBUTE_UNUSED,
7126 enum machine_mode mode ATTRIBUTE_UNUSED,
7127 int ignore ATTRIBUTE_UNUSED)
7128{
7129 size_t i;
7130 const struct avr_builtin_description *d;
7131 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
7132 unsigned int id = DECL_FUNCTION_CODE (fndecl);
7133 tree arg0;
7134 rtx op0;
7135
7136 switch (id)
7137 {
7138 case AVR_BUILTIN_NOP:
7139 emit_insn (gen_nopv (GEN_INT(1)));
7140 return 0;
7141
7142 case AVR_BUILTIN_SEI:
7143 emit_insn (gen_enable_interrupt ());
7144 return 0;
7145
7146 case AVR_BUILTIN_CLI:
7147 emit_insn (gen_disable_interrupt ());
7148 return 0;
7149
7150 case AVR_BUILTIN_WDR:
7151 emit_insn (gen_wdr ());
7152 return 0;
7153
7154 case AVR_BUILTIN_SLEEP:
7155 emit_insn (gen_sleep ());
7156 return 0;
7157
7158 case AVR_BUILTIN_DELAY_CYCLES:
7159 {
7160 arg0 = CALL_EXPR_ARG (exp, 0);
fd01a351 7161 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
43ea6502
AS
7162
7163 if (! CONST_INT_P (op0))
7164 error ("__builtin_avr_delay_cycles expects a compile time integer constant.");
7165
7166 avr_expand_delay_cycles (op0);
7167 return 0;
7168 }
7169 }
7170
7171 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
7172 if (d->id == id)
7173 return avr_expand_unop_builtin (d->icode, exp, target);
7174
7175 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
7176 if (d->id == id)
7177 return avr_expand_binop_builtin (d->icode, exp, target);
7178
7179 gcc_unreachable ();
7180}
7181
7182
baac771a 7183#include "gt-avr.h"