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