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