* config/arc/arc.c: Include "df.h".
[official-gcc.git] / gcc / config / avr / avr.c
blob0ed978812166b63610ed0caa2e36dccfbe4fb453
1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008,
3 2009 Free Software Foundation, Inc.
4 Contributed by Denis Chertykov (chertykov@gmail.com)
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 GCC is distributed in the hope that it will be useful,
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.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "real.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-attr.h"
33 #include "flags.h"
34 #include "reload.h"
35 #include "tree.h"
36 #include "output.h"
37 #include "expr.h"
38 #include "toplev.h"
39 #include "obstack.h"
40 #include "function.h"
41 #include "recog.h"
42 #include "ggc.h"
43 #include "tm_p.h"
44 #include "target.h"
45 #include "target-def.h"
46 #include "params.h"
47 #include "df.h"
49 /* Maximal allowed offset for an address in the LD command */
50 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
52 static int avr_naked_function_p (tree);
53 static int interrupt_function_p (tree);
54 static int signal_function_p (tree);
55 static int avr_OS_task_function_p (tree);
56 static int avr_OS_main_function_p (tree);
57 static int avr_regs_to_save (HARD_REG_SET *);
58 static int get_sequence_length (rtx insns);
59 static int sequent_regs_live (void);
60 static const char *ptrreg_to_str (int);
61 static const char *cond_string (enum rtx_code);
62 static int avr_num_arg_regs (enum machine_mode, tree);
64 static RTX_CODE compare_condition (rtx insn);
65 static rtx avr_legitimize_address (rtx, rtx, enum machine_mode);
66 static int compare_sign_p (rtx insn);
67 static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *);
68 static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
69 static tree avr_handle_fntype_attribute (tree *, tree, tree, int, bool *);
70 static bool avr_assemble_integer (rtx, unsigned int, int);
71 static void avr_file_start (void);
72 static void avr_file_end (void);
73 static bool avr_legitimate_address_p (enum machine_mode, rtx, bool);
74 static void avr_asm_function_end_prologue (FILE *);
75 static void avr_asm_function_begin_epilogue (FILE *);
76 static rtx avr_function_value (const_tree, const_tree, bool);
77 static void avr_insert_attributes (tree, tree *);
78 static void avr_asm_init_sections (void);
79 static unsigned int avr_section_type_flags (tree, const char *, int);
81 static void avr_reorg (void);
82 static void avr_asm_out_ctor (rtx, int);
83 static void avr_asm_out_dtor (rtx, int);
84 static int avr_operand_rtx_cost (rtx, enum machine_mode, enum rtx_code, bool);
85 static bool avr_rtx_costs (rtx, int, int, int *, bool);
86 static int avr_address_cost (rtx, bool);
87 static bool avr_return_in_memory (const_tree, const_tree);
88 static struct machine_function * avr_init_machine_status (void);
89 static rtx avr_builtin_setjmp_frame_value (void);
90 static bool avr_hard_regno_scratch_ok (unsigned int);
91 static unsigned int avr_case_values_threshold (void);
93 /* Allocate registers from r25 to r8 for parameters for function calls. */
94 #define FIRST_CUM_REG 26
96 /* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */
97 static GTY(()) rtx tmp_reg_rtx;
99 /* Zeroed register RTX (gen_rtx_REG (QImode, ZERO_REGNO)) */
100 static GTY(()) rtx zero_reg_rtx;
102 /* AVR register names {"r0", "r1", ..., "r31"} */
103 static const char *const avr_regnames[] = REGISTER_NAMES;
105 /* This holds the last insn address. */
106 static int last_insn_address = 0;
108 /* Preprocessor macros to define depending on MCU type. */
109 const char *avr_extra_arch_macro;
111 /* Current architecture. */
112 const struct base_arch_s *avr_current_arch;
114 /* Current device. */
115 const struct mcu_type_s *avr_current_device;
117 section *progmem_section;
119 /* AVR attributes. */
120 static const struct attribute_spec avr_attribute_table[] =
122 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
123 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
124 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
125 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
126 { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute },
127 { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute },
128 { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute },
129 { NULL, 0, 0, false, false, false, NULL }
132 /* Initialize the GCC target structure. */
133 #undef TARGET_ASM_ALIGNED_HI_OP
134 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
135 #undef TARGET_ASM_ALIGNED_SI_OP
136 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
137 #undef TARGET_ASM_UNALIGNED_HI_OP
138 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
139 #undef TARGET_ASM_UNALIGNED_SI_OP
140 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
141 #undef TARGET_ASM_INTEGER
142 #define TARGET_ASM_INTEGER avr_assemble_integer
143 #undef TARGET_ASM_FILE_START
144 #define TARGET_ASM_FILE_START avr_file_start
145 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
146 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
147 #undef TARGET_ASM_FILE_END
148 #define TARGET_ASM_FILE_END avr_file_end
150 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
151 #define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
152 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
153 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
154 #undef TARGET_FUNCTION_VALUE
155 #define TARGET_FUNCTION_VALUE avr_function_value
156 #undef TARGET_ATTRIBUTE_TABLE
157 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
158 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
159 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
160 #undef TARGET_INSERT_ATTRIBUTES
161 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
162 #undef TARGET_SECTION_TYPE_FLAGS
163 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
164 #undef TARGET_RTX_COSTS
165 #define TARGET_RTX_COSTS avr_rtx_costs
166 #undef TARGET_ADDRESS_COST
167 #define TARGET_ADDRESS_COST avr_address_cost
168 #undef TARGET_MACHINE_DEPENDENT_REORG
169 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
171 #undef TARGET_LEGITIMIZE_ADDRESS
172 #define TARGET_LEGITIMIZE_ADDRESS avr_legitimize_address
174 #undef TARGET_RETURN_IN_MEMORY
175 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
177 #undef TARGET_STRICT_ARGUMENT_NAMING
178 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
180 #undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
181 #define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value
183 #undef TARGET_HARD_REGNO_SCRATCH_OK
184 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
185 #undef TARGET_CASE_VALUES_THRESHOLD
186 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
188 #undef TARGET_LEGITIMATE_ADDRESS_P
189 #define TARGET_LEGITIMATE_ADDRESS_P avr_legitimate_address_p
191 struct gcc_target targetm = TARGET_INITIALIZER;
193 void
194 avr_override_options (void)
196 const struct mcu_type_s *t;
198 flag_delete_null_pointer_checks = 0;
200 for (t = avr_mcu_types; t->name; t++)
201 if (strcmp (t->name, avr_mcu_name) == 0)
202 break;
204 if (!t->name)
206 fprintf (stderr, "unknown MCU '%s' specified\nKnown MCU names:\n",
207 avr_mcu_name);
208 for (t = avr_mcu_types; t->name; t++)
209 fprintf (stderr," %s\n", t->name);
212 avr_current_arch = &avr_arch_types[t->arch];
213 avr_extra_arch_macro = t->macro;
215 tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO);
216 zero_reg_rtx = gen_rtx_REG (QImode, ZERO_REGNO);
218 init_machine_status = avr_init_machine_status;
221 /* return register class from register number. */
223 static const enum reg_class reg_class_tab[]={
224 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
225 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
226 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
227 GENERAL_REGS, /* r0 - r15 */
228 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
229 LD_REGS, /* r16 - 23 */
230 ADDW_REGS,ADDW_REGS, /* r24,r25 */
231 POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
232 POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
233 POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
234 STACK_REG,STACK_REG /* SPL,SPH */
237 /* Function to set up the backend function structure. */
239 static struct machine_function *
240 avr_init_machine_status (void)
242 return ((struct machine_function *)
243 ggc_alloc_cleared (sizeof (struct machine_function)));
246 /* Return register class for register R. */
248 enum reg_class
249 avr_regno_reg_class (int r)
251 if (r <= 33)
252 return reg_class_tab[r];
253 return ALL_REGS;
256 /* Return nonzero if FUNC is a naked function. */
258 static int
259 avr_naked_function_p (tree func)
261 tree a;
263 gcc_assert (TREE_CODE (func) == FUNCTION_DECL);
265 a = lookup_attribute ("naked", TYPE_ATTRIBUTES (TREE_TYPE (func)));
266 return a != NULL_TREE;
269 /* Return nonzero if FUNC is an interrupt function as specified
270 by the "interrupt" attribute. */
272 static int
273 interrupt_function_p (tree func)
275 tree a;
277 if (TREE_CODE (func) != FUNCTION_DECL)
278 return 0;
280 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
281 return a != NULL_TREE;
284 /* Return nonzero if FUNC is a signal function as specified
285 by the "signal" attribute. */
287 static int
288 signal_function_p (tree func)
290 tree a;
292 if (TREE_CODE (func) != FUNCTION_DECL)
293 return 0;
295 a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
296 return a != NULL_TREE;
299 /* Return nonzero if FUNC is a OS_task function. */
301 static int
302 avr_OS_task_function_p (tree func)
304 tree a;
306 gcc_assert (TREE_CODE (func) == FUNCTION_DECL);
308 a = lookup_attribute ("OS_task", TYPE_ATTRIBUTES (TREE_TYPE (func)));
309 return a != NULL_TREE;
312 /* Return nonzero if FUNC is a OS_main function. */
314 static int
315 avr_OS_main_function_p (tree func)
317 tree a;
319 gcc_assert (TREE_CODE (func) == FUNCTION_DECL);
321 a = lookup_attribute ("OS_main", TYPE_ATTRIBUTES (TREE_TYPE (func)));
322 return a != NULL_TREE;
325 /* Return the number of hard registers to push/pop in the prologue/epilogue
326 of the current function, and optionally store these registers in SET. */
328 static int
329 avr_regs_to_save (HARD_REG_SET *set)
331 int reg, count;
332 int int_or_sig_p = (interrupt_function_p (current_function_decl)
333 || signal_function_p (current_function_decl));
335 if (!reload_completed)
336 cfun->machine->is_leaf = leaf_function_p ();
338 if (set)
339 CLEAR_HARD_REG_SET (*set);
340 count = 0;
342 /* No need to save any registers if the function never returns or
343 is have "OS_task" or "OS_main" attribute. */
344 if (TREE_THIS_VOLATILE (current_function_decl)
345 || cfun->machine->is_OS_task
346 || cfun->machine->is_OS_main)
347 return 0;
349 for (reg = 0; reg < 32; reg++)
351 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
352 any global register variables. */
353 if (fixed_regs[reg])
354 continue;
356 if ((int_or_sig_p && !cfun->machine->is_leaf && call_used_regs[reg])
357 || (df_regs_ever_live_p (reg)
358 && (int_or_sig_p || !call_used_regs[reg])
359 && !(frame_pointer_needed
360 && (reg == REG_Y || reg == (REG_Y+1)))))
362 if (set)
363 SET_HARD_REG_BIT (*set, reg);
364 count++;
367 return count;
370 /* Return true if register FROM can be eliminated via register TO. */
372 bool
373 avr_can_eliminate (int from, int to)
375 return ((from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
376 || ((from == FRAME_POINTER_REGNUM
377 || from == FRAME_POINTER_REGNUM + 1)
378 && !frame_pointer_needed));
381 /* Compute offset between arg_pointer and frame_pointer. */
384 avr_initial_elimination_offset (int from, int to)
386 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
387 return 0;
388 else
390 int offset = frame_pointer_needed ? 2 : 0;
391 int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
393 offset += avr_regs_to_save (NULL);
394 return get_frame_size () + (avr_pc_size) + 1 + offset;
398 /* Actual start of frame is virtual_stack_vars_rtx this is offset from
399 frame pointer by +STARTING_FRAME_OFFSET.
400 Using saved frame = virtual_stack_vars_rtx - STARTING_FRAME_OFFSET
401 avoids creating add/sub of offset in nonlocal goto and setjmp. */
403 rtx avr_builtin_setjmp_frame_value (void)
405 return gen_rtx_MINUS (Pmode, virtual_stack_vars_rtx,
406 gen_int_mode (STARTING_FRAME_OFFSET, Pmode));
409 /* Return 1 if the function epilogue is just a single "ret". */
412 avr_simple_epilogue (void)
414 return (! frame_pointer_needed
415 && get_frame_size () == 0
416 && avr_regs_to_save (NULL) == 0
417 && ! interrupt_function_p (current_function_decl)
418 && ! signal_function_p (current_function_decl)
419 && ! avr_naked_function_p (current_function_decl)
420 && ! TREE_THIS_VOLATILE (current_function_decl));
423 /* This function checks sequence of live registers. */
425 static int
426 sequent_regs_live (void)
428 int reg;
429 int live_seq=0;
430 int cur_seq=0;
432 for (reg = 0; reg < 18; ++reg)
434 if (!call_used_regs[reg])
436 if (df_regs_ever_live_p (reg))
438 ++live_seq;
439 ++cur_seq;
441 else
442 cur_seq = 0;
446 if (!frame_pointer_needed)
448 if (df_regs_ever_live_p (REG_Y))
450 ++live_seq;
451 ++cur_seq;
453 else
454 cur_seq = 0;
456 if (df_regs_ever_live_p (REG_Y+1))
458 ++live_seq;
459 ++cur_seq;
461 else
462 cur_seq = 0;
464 else
466 cur_seq += 2;
467 live_seq += 2;
469 return (cur_seq == live_seq) ? live_seq : 0;
472 /* Obtain the length sequence of insns. */
475 get_sequence_length (rtx insns)
477 rtx insn;
478 int length;
480 for (insn = insns, length = 0; insn; insn = NEXT_INSN (insn))
481 length += get_attr_length (insn);
483 return length;
486 /* Output function prologue. */
488 void
489 expand_prologue (void)
491 int live_seq;
492 HARD_REG_SET set;
493 int minimize;
494 HOST_WIDE_INT size = get_frame_size();
495 /* Define templates for push instructions. */
496 rtx pushbyte = gen_rtx_MEM (QImode,
497 gen_rtx_POST_DEC (HImode, stack_pointer_rtx));
498 rtx pushword = gen_rtx_MEM (HImode,
499 gen_rtx_POST_DEC (HImode, stack_pointer_rtx));
500 rtx insn;
502 last_insn_address = 0;
504 /* Init cfun->machine. */
505 cfun->machine->is_naked = avr_naked_function_p (current_function_decl);
506 cfun->machine->is_interrupt = interrupt_function_p (current_function_decl);
507 cfun->machine->is_signal = signal_function_p (current_function_decl);
508 cfun->machine->is_OS_task = avr_OS_task_function_p (current_function_decl);
509 cfun->machine->is_OS_main = avr_OS_main_function_p (current_function_decl);
511 /* Prologue: naked. */
512 if (cfun->machine->is_naked)
514 return;
517 avr_regs_to_save (&set);
518 live_seq = sequent_regs_live ();
519 minimize = (TARGET_CALL_PROLOGUES
520 && !cfun->machine->is_interrupt
521 && !cfun->machine->is_signal
522 && !cfun->machine->is_OS_task
523 && !cfun->machine->is_OS_main
524 && live_seq);
526 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
528 if (cfun->machine->is_interrupt)
530 /* Enable interrupts. */
531 insn = emit_insn (gen_enable_interrupt ());
532 RTX_FRAME_RELATED_P (insn) = 1;
535 /* Push zero reg. */
536 insn = emit_move_insn (pushbyte, zero_reg_rtx);
537 RTX_FRAME_RELATED_P (insn) = 1;
539 /* Push tmp reg. */
540 insn = emit_move_insn (pushbyte, tmp_reg_rtx);
541 RTX_FRAME_RELATED_P (insn) = 1;
543 /* Push SREG. */
544 insn = emit_move_insn (tmp_reg_rtx,
545 gen_rtx_MEM (QImode, GEN_INT (SREG_ADDR)));
546 RTX_FRAME_RELATED_P (insn) = 1;
547 insn = emit_move_insn (pushbyte, tmp_reg_rtx);
548 RTX_FRAME_RELATED_P (insn) = 1;
550 /* Push RAMPZ. */
551 if(AVR_HAVE_RAMPZ
552 && (TEST_HARD_REG_BIT (set, REG_Z) && TEST_HARD_REG_BIT (set, REG_Z + 1)))
554 insn = emit_move_insn (tmp_reg_rtx,
555 gen_rtx_MEM (QImode, GEN_INT (RAMPZ_ADDR)));
556 RTX_FRAME_RELATED_P (insn) = 1;
557 insn = emit_move_insn (pushbyte, tmp_reg_rtx);
558 RTX_FRAME_RELATED_P (insn) = 1;
561 /* Clear zero reg. */
562 insn = emit_move_insn (zero_reg_rtx, const0_rtx);
563 RTX_FRAME_RELATED_P (insn) = 1;
565 /* Prevent any attempt to delete the setting of ZERO_REG! */
566 emit_use (zero_reg_rtx);
568 if (minimize && (frame_pointer_needed
569 || (AVR_2_BYTE_PC && live_seq > 6)
570 || live_seq > 7))
572 insn = emit_move_insn (gen_rtx_REG (HImode, REG_X),
573 gen_int_mode (size, HImode));
574 RTX_FRAME_RELATED_P (insn) = 1;
576 insn =
577 emit_insn (gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
578 gen_int_mode (size + live_seq, HImode)));
579 RTX_FRAME_RELATED_P (insn) = 1;
581 else
583 int reg;
584 for (reg = 0; reg < 32; ++reg)
586 if (TEST_HARD_REG_BIT (set, reg))
588 /* Emit push of register to save. */
589 insn=emit_move_insn (pushbyte, gen_rtx_REG (QImode, reg));
590 RTX_FRAME_RELATED_P (insn) = 1;
593 if (frame_pointer_needed)
595 if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
597 /* Push frame pointer. */
598 insn = emit_move_insn (pushword, frame_pointer_rtx);
599 RTX_FRAME_RELATED_P (insn) = 1;
602 if (!size)
604 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
605 RTX_FRAME_RELATED_P (insn) = 1;
607 else
609 /* Creating a frame can be done by direct manipulation of the
610 stack or via the frame pointer. These two methods are:
611 fp=sp
612 fp-=size
613 sp=fp
615 sp-=size
616 fp=sp
617 the optimum method depends on function type, stack and frame size.
618 To avoid a complex logic, both methods are tested and shortest
619 is selected. */
620 rtx myfp;
621 rtx fp_plus_insns;
622 rtx sp_plus_insns = NULL_RTX;
624 if (TARGET_TINY_STACK)
626 /* The high byte (r29) doesn't change - prefer 'subi' (1 cycle)
627 over 'sbiw' (2 cycles, same size). */
628 myfp = gen_rtx_REG (QImode, REGNO (frame_pointer_rtx));
630 else
632 /* Normal sized addition. */
633 myfp = frame_pointer_rtx;
636 /* Method 1-Adjust frame pointer. */
637 start_sequence ();
639 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
640 RTX_FRAME_RELATED_P (insn) = 1;
642 insn =
643 emit_move_insn (myfp,
644 gen_rtx_PLUS (GET_MODE(myfp), myfp,
645 gen_int_mode (-size,
646 GET_MODE(myfp))));
647 RTX_FRAME_RELATED_P (insn) = 1;
649 /* Copy to stack pointer. */
650 if (TARGET_TINY_STACK)
652 insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
653 RTX_FRAME_RELATED_P (insn) = 1;
655 else if (TARGET_NO_INTERRUPTS
656 || cfun->machine->is_signal
657 || cfun->machine->is_OS_main)
659 insn =
660 emit_insn (gen_movhi_sp_r_irq_off (stack_pointer_rtx,
661 frame_pointer_rtx));
662 RTX_FRAME_RELATED_P (insn) = 1;
664 else if (cfun->machine->is_interrupt)
666 insn = emit_insn (gen_movhi_sp_r_irq_on (stack_pointer_rtx,
667 frame_pointer_rtx));
668 RTX_FRAME_RELATED_P (insn) = 1;
670 else
672 insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
673 RTX_FRAME_RELATED_P (insn) = 1;
676 fp_plus_insns = get_insns ();
677 end_sequence ();
679 /* Method 2-Adjust Stack pointer. */
680 if (size <= 6)
682 start_sequence ();
684 insn =
685 emit_move_insn (stack_pointer_rtx,
686 gen_rtx_PLUS (HImode,
687 stack_pointer_rtx,
688 gen_int_mode (-size,
689 HImode)));
690 RTX_FRAME_RELATED_P (insn) = 1;
692 insn =
693 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
694 RTX_FRAME_RELATED_P (insn) = 1;
696 sp_plus_insns = get_insns ();
697 end_sequence ();
700 /* Use shortest method. */
701 if (size <= 6 && (get_sequence_length (sp_plus_insns)
702 < get_sequence_length (fp_plus_insns)))
703 emit_insn (sp_plus_insns);
704 else
705 emit_insn (fp_plus_insns);
711 /* Output summary at end of function prologue. */
713 static void
714 avr_asm_function_end_prologue (FILE *file)
716 if (cfun->machine->is_naked)
718 fputs ("/* prologue: naked */\n", file);
720 else
722 if (cfun->machine->is_interrupt)
724 fputs ("/* prologue: Interrupt */\n", file);
726 else if (cfun->machine->is_signal)
728 fputs ("/* prologue: Signal */\n", file);
730 else
731 fputs ("/* prologue: function */\n", file);
733 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
734 get_frame_size());
738 /* Implement EPILOGUE_USES. */
741 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
743 if (reload_completed
744 && cfun->machine
745 && (cfun->machine->is_interrupt || cfun->machine->is_signal))
746 return 1;
747 return 0;
750 /* Output RTL epilogue. */
752 void
753 expand_epilogue (void)
755 int reg;
756 int live_seq;
757 HARD_REG_SET set;
758 int minimize;
759 HOST_WIDE_INT size = get_frame_size();
761 /* epilogue: naked */
762 if (cfun->machine->is_naked)
764 emit_jump_insn (gen_return ());
765 return;
768 avr_regs_to_save (&set);
769 live_seq = sequent_regs_live ();
770 minimize = (TARGET_CALL_PROLOGUES
771 && !cfun->machine->is_interrupt
772 && !cfun->machine->is_signal
773 && !cfun->machine->is_OS_task
774 && !cfun->machine->is_OS_main
775 && live_seq);
777 if (minimize && (frame_pointer_needed || live_seq > 4))
779 if (frame_pointer_needed)
781 /* Get rid of frame. */
782 emit_move_insn(frame_pointer_rtx,
783 gen_rtx_PLUS (HImode, frame_pointer_rtx,
784 gen_int_mode (size, HImode)));
786 else
788 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
791 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
793 else
795 if (frame_pointer_needed)
797 if (size)
799 /* Try two methods to adjust stack and select shortest. */
800 rtx myfp;
801 rtx fp_plus_insns;
802 rtx sp_plus_insns = NULL_RTX;
804 if (TARGET_TINY_STACK)
806 /* The high byte (r29) doesn't change - prefer 'subi'
807 (1 cycle) over 'sbiw' (2 cycles, same size). */
808 myfp = gen_rtx_REG (QImode, REGNO (frame_pointer_rtx));
810 else
812 /* Normal sized addition. */
813 myfp = frame_pointer_rtx;
816 /* Method 1-Adjust frame pointer. */
817 start_sequence ();
819 emit_move_insn (myfp,
820 gen_rtx_PLUS (HImode, myfp,
821 gen_int_mode (size,
822 GET_MODE(myfp))));
824 /* Copy to stack pointer. */
825 if (TARGET_TINY_STACK)
827 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
829 else if (TARGET_NO_INTERRUPTS
830 || cfun->machine->is_signal)
832 emit_insn (gen_movhi_sp_r_irq_off (stack_pointer_rtx,
833 frame_pointer_rtx));
835 else if (cfun->machine->is_interrupt)
837 emit_insn (gen_movhi_sp_r_irq_on (stack_pointer_rtx,
838 frame_pointer_rtx));
840 else
842 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
845 fp_plus_insns = get_insns ();
846 end_sequence ();
848 /* Method 2-Adjust Stack pointer. */
849 if (size <= 5)
851 start_sequence ();
853 emit_move_insn (stack_pointer_rtx,
854 gen_rtx_PLUS (HImode, stack_pointer_rtx,
855 gen_int_mode (size,
856 HImode)));
858 sp_plus_insns = get_insns ();
859 end_sequence ();
862 /* Use shortest method. */
863 if (size <= 5 && (get_sequence_length (sp_plus_insns)
864 < get_sequence_length (fp_plus_insns)))
865 emit_insn (sp_plus_insns);
866 else
867 emit_insn (fp_plus_insns);
869 if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
871 /* Restore previous frame_pointer. */
872 emit_insn (gen_pophi (frame_pointer_rtx));
875 /* Restore used registers. */
876 for (reg = 31; reg >= 0; --reg)
878 if (TEST_HARD_REG_BIT (set, reg))
879 emit_insn (gen_popqi (gen_rtx_REG (QImode, reg)));
881 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
883 /* Restore RAMPZ using tmp reg as scratch. */
884 if(AVR_HAVE_RAMPZ
885 && (TEST_HARD_REG_BIT (set, REG_Z) && TEST_HARD_REG_BIT (set, REG_Z + 1)))
887 emit_insn (gen_popqi (tmp_reg_rtx));
888 emit_move_insn (gen_rtx_MEM(QImode, GEN_INT(RAMPZ_ADDR)),
889 tmp_reg_rtx);
892 /* Restore SREG using tmp reg as scratch. */
893 emit_insn (gen_popqi (tmp_reg_rtx));
895 emit_move_insn (gen_rtx_MEM(QImode, GEN_INT(SREG_ADDR)),
896 tmp_reg_rtx);
898 /* Restore tmp REG. */
899 emit_insn (gen_popqi (tmp_reg_rtx));
901 /* Restore zero REG. */
902 emit_insn (gen_popqi (zero_reg_rtx));
905 emit_jump_insn (gen_return ());
909 /* Output summary messages at beginning of function epilogue. */
911 static void
912 avr_asm_function_begin_epilogue (FILE *file)
914 fprintf (file, "/* epilogue start */\n");
917 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
918 machine for a memory operand of mode MODE. */
920 bool
921 avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
923 enum reg_class r = NO_REGS;
925 if (TARGET_ALL_DEBUG)
927 fprintf (stderr, "mode: (%s) %s %s %s %s:",
928 GET_MODE_NAME(mode),
929 strict ? "(strict)": "",
930 reload_completed ? "(reload_completed)": "",
931 reload_in_progress ? "(reload_in_progress)": "",
932 reg_renumber ? "(reg_renumber)" : "");
933 if (GET_CODE (x) == PLUS
934 && REG_P (XEXP (x, 0))
935 && GET_CODE (XEXP (x, 1)) == CONST_INT
936 && INTVAL (XEXP (x, 1)) >= 0
937 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
938 && reg_renumber
940 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
941 true_regnum (XEXP (x, 0)));
942 debug_rtx (x);
944 if (!strict && GET_CODE (x) == SUBREG)
945 x = SUBREG_REG (x);
946 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
947 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
948 r = POINTER_REGS;
949 else if (CONSTANT_ADDRESS_P (x))
950 r = ALL_REGS;
951 else if (GET_CODE (x) == PLUS
952 && REG_P (XEXP (x, 0))
953 && GET_CODE (XEXP (x, 1)) == CONST_INT
954 && INTVAL (XEXP (x, 1)) >= 0)
956 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
957 if (fit)
959 if (! strict
960 || REGNO (XEXP (x,0)) == REG_X
961 || REGNO (XEXP (x,0)) == REG_Y
962 || REGNO (XEXP (x,0)) == REG_Z)
963 r = BASE_POINTER_REGS;
964 if (XEXP (x,0) == frame_pointer_rtx
965 || XEXP (x,0) == arg_pointer_rtx)
966 r = BASE_POINTER_REGS;
968 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
969 r = POINTER_Y_REGS;
971 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
972 && REG_P (XEXP (x, 0))
973 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
974 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
976 r = POINTER_REGS;
978 if (TARGET_ALL_DEBUG)
980 fprintf (stderr, " ret = %c\n", r + '0');
982 return r == NO_REGS ? 0 : (int)r;
985 /* Attempts to replace X with a valid
986 memory address for an operand of mode MODE */
989 avr_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
991 x = oldx;
992 if (TARGET_ALL_DEBUG)
994 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
995 debug_rtx (oldx);
998 if (GET_CODE (oldx) == PLUS
999 && REG_P (XEXP (oldx,0)))
1001 if (REG_P (XEXP (oldx,1)))
1002 x = force_reg (GET_MODE (oldx), oldx);
1003 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
1005 int offs = INTVAL (XEXP (oldx,1));
1006 if (frame_pointer_rtx != XEXP (oldx,0))
1007 if (offs > MAX_LD_OFFSET (mode))
1009 if (TARGET_ALL_DEBUG)
1010 fprintf (stderr, "force_reg (big offset)\n");
1011 x = force_reg (GET_MODE (oldx), oldx);
1015 return x;
1019 /* Return a pointer register name as a string. */
1021 static const char *
1022 ptrreg_to_str (int regno)
1024 switch (regno)
1026 case REG_X: return "X";
1027 case REG_Y: return "Y";
1028 case REG_Z: return "Z";
1029 default:
1030 output_operand_lossage ("address operand requires constraint for X, Y, or Z register");
1032 return NULL;
1035 /* Return the condition name as a string.
1036 Used in conditional jump constructing */
1038 static const char *
1039 cond_string (enum rtx_code code)
1041 switch (code)
1043 case NE:
1044 return "ne";
1045 case EQ:
1046 return "eq";
1047 case GE:
1048 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1049 return "pl";
1050 else
1051 return "ge";
1052 case LT:
1053 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1054 return "mi";
1055 else
1056 return "lt";
1057 case GEU:
1058 return "sh";
1059 case LTU:
1060 return "lo";
1061 default:
1062 gcc_unreachable ();
1066 /* Output ADDR to FILE as address. */
1068 void
1069 print_operand_address (FILE *file, rtx addr)
1071 switch (GET_CODE (addr))
1073 case REG:
1074 fprintf (file, ptrreg_to_str (REGNO (addr)));
1075 break;
1077 case PRE_DEC:
1078 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1079 break;
1081 case POST_INC:
1082 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1083 break;
1085 default:
1086 if (CONSTANT_ADDRESS_P (addr)
1087 && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
1088 || GET_CODE (addr) == LABEL_REF))
1090 fprintf (file, "gs(");
1091 output_addr_const (file,addr);
1092 fprintf (file ,")");
1094 else
1095 output_addr_const (file, addr);
1100 /* Output X as assembler operand to file FILE. */
1102 void
1103 print_operand (FILE *file, rtx x, int code)
1105 int abcd = 0;
1107 if (code >= 'A' && code <= 'D')
1108 abcd = code - 'A';
1110 if (code == '~')
1112 if (!AVR_HAVE_JMP_CALL)
1113 fputc ('r', file);
1115 else if (code == '!')
1117 if (AVR_HAVE_EIJMP_EICALL)
1118 fputc ('e', file);
1120 else if (REG_P (x))
1122 if (x == zero_reg_rtx)
1123 fprintf (file, "__zero_reg__");
1124 else
1125 fprintf (file, reg_names[true_regnum (x) + abcd]);
1127 else if (GET_CODE (x) == CONST_INT)
1128 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd);
1129 else if (GET_CODE (x) == MEM)
1131 rtx addr = XEXP (x,0);
1133 if (CONSTANT_P (addr) && abcd)
1135 fputc ('(', file);
1136 output_address (addr);
1137 fprintf (file, ")+%d", abcd);
1139 else if (code == 'o')
1141 if (GET_CODE (addr) != PLUS)
1142 fatal_insn ("bad address, not (reg+disp):", addr);
1144 print_operand (file, XEXP (addr, 1), 0);
1146 else if (code == 'p' || code == 'r')
1148 if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
1149 fatal_insn ("bad address, not post_inc or pre_dec:", addr);
1151 if (code == 'p')
1152 print_operand_address (file, XEXP (addr, 0)); /* X, Y, Z */
1153 else
1154 print_operand (file, XEXP (addr, 0), 0); /* r26, r28, r30 */
1156 else if (GET_CODE (addr) == PLUS)
1158 print_operand_address (file, XEXP (addr,0));
1159 if (REGNO (XEXP (addr, 0)) == REG_X)
1160 fatal_insn ("internal compiler error. Bad address:"
1161 ,addr);
1162 fputc ('+', file);
1163 print_operand (file, XEXP (addr,1), code);
1165 else
1166 print_operand_address (file, addr);
1168 else if (GET_CODE (x) == CONST_DOUBLE)
1170 long val;
1171 REAL_VALUE_TYPE rv;
1172 if (GET_MODE (x) != SFmode)
1173 fatal_insn ("internal compiler error. Unknown mode:", x);
1174 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1175 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1176 fprintf (file, "0x%lx", val);
1178 else if (code == 'j')
1179 fputs (cond_string (GET_CODE (x)), file);
1180 else if (code == 'k')
1181 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
1182 else
1183 print_operand_address (file, x);
1186 /* Update the condition code in the INSN. */
1188 void
1189 notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
1191 rtx set;
1193 switch (get_attr_cc (insn))
1195 case CC_NONE:
1196 /* Insn does not affect CC at all. */
1197 break;
1199 case CC_SET_N:
1200 CC_STATUS_INIT;
1201 break;
1203 case CC_SET_ZN:
1204 set = single_set (insn);
1205 CC_STATUS_INIT;
1206 if (set)
1208 cc_status.flags |= CC_NO_OVERFLOW;
1209 cc_status.value1 = SET_DEST (set);
1211 break;
1213 case CC_SET_CZN:
1214 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1215 The V flag may or may not be known but that's ok because
1216 alter_cond will change tests to use EQ/NE. */
1217 set = single_set (insn);
1218 CC_STATUS_INIT;
1219 if (set)
1221 cc_status.value1 = SET_DEST (set);
1222 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1224 break;
1226 case CC_COMPARE:
1227 set = single_set (insn);
1228 CC_STATUS_INIT;
1229 if (set)
1230 cc_status.value1 = SET_SRC (set);
1231 break;
1233 case CC_CLOBBER:
1234 /* Insn doesn't leave CC in a usable state. */
1235 CC_STATUS_INIT;
1237 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1238 set = single_set (insn);
1239 if (set)
1241 rtx src = SET_SRC (set);
1243 if (GET_CODE (src) == ASHIFTRT
1244 && GET_MODE (src) == QImode)
1246 rtx x = XEXP (src, 1);
1248 if (GET_CODE (x) == CONST_INT
1249 && INTVAL (x) > 0
1250 && INTVAL (x) != 6)
1252 cc_status.value1 = SET_DEST (set);
1253 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1257 break;
1261 /* Return maximum number of consecutive registers of
1262 class CLASS needed to hold a value of mode MODE. */
1265 class_max_nregs (enum reg_class rclass ATTRIBUTE_UNUSED,enum machine_mode mode)
1267 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1270 /* Choose mode for jump insn:
1271 1 - relative jump in range -63 <= x <= 62 ;
1272 2 - relative jump in range -2046 <= x <= 2045 ;
1273 3 - absolute jump (only for ATmega[16]03). */
1276 avr_jump_mode (rtx x, rtx insn)
1278 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
1279 ? XEXP (x, 0) : x));
1280 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
1281 int jump_distance = cur_addr - dest_addr;
1283 if (-63 <= jump_distance && jump_distance <= 62)
1284 return 1;
1285 else if (-2046 <= jump_distance && jump_distance <= 2045)
1286 return 2;
1287 else if (AVR_HAVE_JMP_CALL)
1288 return 3;
1290 return 2;
1293 /* return an AVR condition jump commands.
1294 X is a comparison RTX.
1295 LEN is a number returned by avr_jump_mode function.
1296 if REVERSE nonzero then condition code in X must be reversed. */
1298 const char *
1299 ret_cond_branch (rtx x, int len, int reverse)
1301 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1303 switch (cond)
1305 case GT:
1306 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1307 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1308 AS1 (brpl,%0)) :
1309 len == 2 ? (AS1 (breq,.+4) CR_TAB
1310 AS1 (brmi,.+2) CR_TAB
1311 AS1 (rjmp,%0)) :
1312 (AS1 (breq,.+6) CR_TAB
1313 AS1 (brmi,.+4) CR_TAB
1314 AS1 (jmp,%0)));
1316 else
1317 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1318 AS1 (brge,%0)) :
1319 len == 2 ? (AS1 (breq,.+4) CR_TAB
1320 AS1 (brlt,.+2) CR_TAB
1321 AS1 (rjmp,%0)) :
1322 (AS1 (breq,.+6) CR_TAB
1323 AS1 (brlt,.+4) CR_TAB
1324 AS1 (jmp,%0)));
1325 case GTU:
1326 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1327 AS1 (brsh,%0)) :
1328 len == 2 ? (AS1 (breq,.+4) CR_TAB
1329 AS1 (brlo,.+2) CR_TAB
1330 AS1 (rjmp,%0)) :
1331 (AS1 (breq,.+6) CR_TAB
1332 AS1 (brlo,.+4) CR_TAB
1333 AS1 (jmp,%0)));
1334 case LE:
1335 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1336 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1337 AS1 (brmi,%0)) :
1338 len == 2 ? (AS1 (breq,.+2) CR_TAB
1339 AS1 (brpl,.+2) CR_TAB
1340 AS1 (rjmp,%0)) :
1341 (AS1 (breq,.+2) CR_TAB
1342 AS1 (brpl,.+4) CR_TAB
1343 AS1 (jmp,%0)));
1344 else
1345 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1346 AS1 (brlt,%0)) :
1347 len == 2 ? (AS1 (breq,.+2) CR_TAB
1348 AS1 (brge,.+2) CR_TAB
1349 AS1 (rjmp,%0)) :
1350 (AS1 (breq,.+2) CR_TAB
1351 AS1 (brge,.+4) CR_TAB
1352 AS1 (jmp,%0)));
1353 case LEU:
1354 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1355 AS1 (brlo,%0)) :
1356 len == 2 ? (AS1 (breq,.+2) CR_TAB
1357 AS1 (brsh,.+2) CR_TAB
1358 AS1 (rjmp,%0)) :
1359 (AS1 (breq,.+2) CR_TAB
1360 AS1 (brsh,.+4) CR_TAB
1361 AS1 (jmp,%0)));
1362 default:
1363 if (reverse)
1365 switch (len)
1367 case 1:
1368 return AS1 (br%k1,%0);
1369 case 2:
1370 return (AS1 (br%j1,.+2) CR_TAB
1371 AS1 (rjmp,%0));
1372 default:
1373 return (AS1 (br%j1,.+4) CR_TAB
1374 AS1 (jmp,%0));
1377 else
1379 switch (len)
1381 case 1:
1382 return AS1 (br%j1,%0);
1383 case 2:
1384 return (AS1 (br%k1,.+2) CR_TAB
1385 AS1 (rjmp,%0));
1386 default:
1387 return (AS1 (br%k1,.+4) CR_TAB
1388 AS1 (jmp,%0));
1392 return "";
1395 /* Predicate function for immediate operand which fits to byte (8bit) */
1398 byte_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1400 return (GET_CODE (op) == CONST_INT
1401 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1404 /* Output all insn addresses and their sizes into the assembly language
1405 output file. This is helpful for debugging whether the length attributes
1406 in the md file are correct.
1407 Output insn cost for next insn. */
1409 void
1410 final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
1411 int num_operands ATTRIBUTE_UNUSED)
1413 int uid = INSN_UID (insn);
1415 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1417 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1418 INSN_ADDRESSES (uid),
1419 INSN_ADDRESSES (uid) - last_insn_address,
1420 rtx_cost (PATTERN (insn), INSN, !optimize_size));
1422 last_insn_address = INSN_ADDRESSES (uid);
1425 /* Return 0 if undefined, 1 if always true or always false. */
1428 avr_simplify_comparison_p (enum machine_mode mode, RTX_CODE op, rtx x)
1430 unsigned int max = (mode == QImode ? 0xff :
1431 mode == HImode ? 0xffff :
1432 mode == SImode ? 0xffffffff : 0);
1433 if (max && op && GET_CODE (x) == CONST_INT)
1435 if (unsigned_condition (op) != op)
1436 max >>= 1;
1438 if (max != (INTVAL (x) & max)
1439 && INTVAL (x) != 0xff)
1440 return 1;
1442 return 0;
1446 /* Returns nonzero if REGNO is the number of a hard
1447 register in which function arguments are sometimes passed. */
1450 function_arg_regno_p(int r)
1452 return (r >= 8 && r <= 25);
1455 /* Initializing the variable cum for the state at the beginning
1456 of the argument list. */
1458 void
1459 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
1460 tree fndecl ATTRIBUTE_UNUSED)
1462 cum->nregs = 18;
1463 cum->regno = FIRST_CUM_REG;
1464 if (!libname && fntype)
1466 int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1467 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1468 != void_type_node));
1469 if (stdarg)
1470 cum->nregs = 0;
1474 /* Returns the number of registers to allocate for a function argument. */
1476 static int
1477 avr_num_arg_regs (enum machine_mode mode, tree type)
1479 int size;
1481 if (mode == BLKmode)
1482 size = int_size_in_bytes (type);
1483 else
1484 size = GET_MODE_SIZE (mode);
1486 /* Align all function arguments to start in even-numbered registers.
1487 Odd-sized arguments leave holes above them. */
1489 return (size + 1) & ~1;
1492 /* Controls whether a function argument is passed
1493 in a register, and which register. */
1496 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1497 int named ATTRIBUTE_UNUSED)
1499 int bytes = avr_num_arg_regs (mode, type);
1501 if (cum->nregs && bytes <= cum->nregs)
1502 return gen_rtx_REG (mode, cum->regno - bytes);
1504 return NULL_RTX;
1507 /* Update the summarizer variable CUM to advance past an argument
1508 in the argument list. */
1510 void
1511 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1512 int named ATTRIBUTE_UNUSED)
1514 int bytes = avr_num_arg_regs (mode, type);
1516 cum->nregs -= bytes;
1517 cum->regno -= bytes;
1519 if (cum->nregs <= 0)
1521 cum->nregs = 0;
1522 cum->regno = FIRST_CUM_REG;
1526 /***********************************************************************
1527 Functions for outputting various mov's for a various modes
1528 ************************************************************************/
1529 const char *
1530 output_movqi (rtx insn, rtx operands[], int *l)
1532 int dummy;
1533 rtx dest = operands[0];
1534 rtx src = operands[1];
1535 int *real_l = l;
1537 if (!l)
1538 l = &dummy;
1540 *l = 1;
1542 if (register_operand (dest, QImode))
1544 if (register_operand (src, QImode)) /* mov r,r */
1546 if (test_hard_reg_class (STACK_REG, dest))
1547 return AS2 (out,%0,%1);
1548 else if (test_hard_reg_class (STACK_REG, src))
1549 return AS2 (in,%0,%1);
1551 return AS2 (mov,%0,%1);
1553 else if (CONSTANT_P (src))
1555 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1556 return AS2 (ldi,%0,lo8(%1));
1558 if (GET_CODE (src) == CONST_INT)
1560 if (src == const0_rtx) /* mov r,L */
1561 return AS1 (clr,%0);
1562 else if (src == const1_rtx)
1564 *l = 2;
1565 return (AS1 (clr,%0) CR_TAB
1566 AS1 (inc,%0));
1568 else if (src == constm1_rtx)
1570 /* Immediate constants -1 to any register */
1571 *l = 2;
1572 return (AS1 (clr,%0) CR_TAB
1573 AS1 (dec,%0));
1575 else
1577 int bit_nr = exact_log2 (INTVAL (src));
1579 if (bit_nr >= 0)
1581 *l = 3;
1582 if (!real_l)
1583 output_asm_insn ((AS1 (clr,%0) CR_TAB
1584 "set"), operands);
1585 if (!real_l)
1586 avr_output_bld (operands, bit_nr);
1588 return "";
1593 /* Last resort, larger than loading from memory. */
1594 *l = 4;
1595 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1596 AS2 (ldi,r31,lo8(%1)) CR_TAB
1597 AS2 (mov,%0,r31) CR_TAB
1598 AS2 (mov,r31,__tmp_reg__));
1600 else if (GET_CODE (src) == MEM)
1601 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1603 else if (GET_CODE (dest) == MEM)
1605 const char *templ;
1607 if (src == const0_rtx)
1608 operands[1] = zero_reg_rtx;
1610 templ = out_movqi_mr_r (insn, operands, real_l);
1612 if (!real_l)
1613 output_asm_insn (templ, operands);
1615 operands[1] = src;
1617 return "";
1621 const char *
1622 output_movhi (rtx insn, rtx operands[], int *l)
1624 int dummy;
1625 rtx dest = operands[0];
1626 rtx src = operands[1];
1627 int *real_l = l;
1629 if (!l)
1630 l = &dummy;
1632 if (register_operand (dest, HImode))
1634 if (register_operand (src, HImode)) /* mov r,r */
1636 if (test_hard_reg_class (STACK_REG, dest))
1638 if (TARGET_TINY_STACK)
1639 return *l = 1, AS2 (out,__SP_L__,%A1);
1640 /* Use simple load of stack pointer if no interrupts are
1641 used. */
1642 else if (TARGET_NO_INTERRUPTS)
1643 return *l = 2, (AS2 (out,__SP_H__,%B1) CR_TAB
1644 AS2 (out,__SP_L__,%A1));
1645 *l = 5;
1646 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1647 "cli" CR_TAB
1648 AS2 (out,__SP_H__,%B1) CR_TAB
1649 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1650 AS2 (out,__SP_L__,%A1));
1652 else if (test_hard_reg_class (STACK_REG, src))
1654 *l = 2;
1655 return (AS2 (in,%A0,__SP_L__) CR_TAB
1656 AS2 (in,%B0,__SP_H__));
1659 if (AVR_HAVE_MOVW)
1661 *l = 1;
1662 return (AS2 (movw,%0,%1));
1664 else
1666 *l = 2;
1667 return (AS2 (mov,%A0,%A1) CR_TAB
1668 AS2 (mov,%B0,%B1));
1671 else if (CONSTANT_P (src))
1673 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1675 *l = 2;
1676 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1677 AS2 (ldi,%B0,hi8(%1)));
1680 if (GET_CODE (src) == CONST_INT)
1682 if (src == const0_rtx) /* mov r,L */
1684 *l = 2;
1685 return (AS1 (clr,%A0) CR_TAB
1686 AS1 (clr,%B0));
1688 else if (src == const1_rtx)
1690 *l = 3;
1691 return (AS1 (clr,%A0) CR_TAB
1692 AS1 (clr,%B0) CR_TAB
1693 AS1 (inc,%A0));
1695 else if (src == constm1_rtx)
1697 /* Immediate constants -1 to any register */
1698 *l = 3;
1699 return (AS1 (clr,%0) CR_TAB
1700 AS1 (dec,%A0) CR_TAB
1701 AS2 (mov,%B0,%A0));
1703 else
1705 int bit_nr = exact_log2 (INTVAL (src));
1707 if (bit_nr >= 0)
1709 *l = 4;
1710 if (!real_l)
1711 output_asm_insn ((AS1 (clr,%A0) CR_TAB
1712 AS1 (clr,%B0) CR_TAB
1713 "set"), operands);
1714 if (!real_l)
1715 avr_output_bld (operands, bit_nr);
1717 return "";
1721 if ((INTVAL (src) & 0xff) == 0)
1723 *l = 5;
1724 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1725 AS1 (clr,%A0) CR_TAB
1726 AS2 (ldi,r31,hi8(%1)) CR_TAB
1727 AS2 (mov,%B0,r31) CR_TAB
1728 AS2 (mov,r31,__tmp_reg__));
1730 else if ((INTVAL (src) & 0xff00) == 0)
1732 *l = 5;
1733 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1734 AS2 (ldi,r31,lo8(%1)) CR_TAB
1735 AS2 (mov,%A0,r31) CR_TAB
1736 AS1 (clr,%B0) CR_TAB
1737 AS2 (mov,r31,__tmp_reg__));
1741 /* Last resort, equal to loading from memory. */
1742 *l = 6;
1743 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1744 AS2 (ldi,r31,lo8(%1)) CR_TAB
1745 AS2 (mov,%A0,r31) CR_TAB
1746 AS2 (ldi,r31,hi8(%1)) CR_TAB
1747 AS2 (mov,%B0,r31) CR_TAB
1748 AS2 (mov,r31,__tmp_reg__));
1750 else if (GET_CODE (src) == MEM)
1751 return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1753 else if (GET_CODE (dest) == MEM)
1755 const char *templ;
1757 if (src == const0_rtx)
1758 operands[1] = zero_reg_rtx;
1760 templ = out_movhi_mr_r (insn, operands, real_l);
1762 if (!real_l)
1763 output_asm_insn (templ, operands);
1765 operands[1] = src;
1766 return "";
1768 fatal_insn ("invalid insn:", insn);
1769 return "";
1772 const char *
1773 out_movqi_r_mr (rtx insn, rtx op[], int *l)
1775 rtx dest = op[0];
1776 rtx src = op[1];
1777 rtx x = XEXP (src, 0);
1778 int dummy;
1780 if (!l)
1781 l = &dummy;
1783 if (CONSTANT_ADDRESS_P (x))
1785 if (CONST_INT_P (x) && INTVAL (x) == SREG_ADDR)
1787 *l = 1;
1788 return AS2 (in,%0,__SREG__);
1790 if (optimize > 0 && io_address_operand (x, QImode))
1792 *l = 1;
1793 return AS2 (in,%0,%1-0x20);
1795 *l = 2;
1796 return AS2 (lds,%0,%1);
1798 /* memory access by reg+disp */
1799 else if (GET_CODE (x) == PLUS
1800 && REG_P (XEXP (x,0))
1801 && GET_CODE (XEXP (x,1)) == CONST_INT)
1803 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
1805 int disp = INTVAL (XEXP (x,1));
1806 if (REGNO (XEXP (x,0)) != REG_Y)
1807 fatal_insn ("incorrect insn:",insn);
1809 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1810 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1811 AS2 (ldd,%0,Y+63) CR_TAB
1812 AS2 (sbiw,r28,%o1-63));
1814 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1815 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1816 AS2 (ld,%0,Y) CR_TAB
1817 AS2 (subi,r28,lo8(%o1)) CR_TAB
1818 AS2 (sbci,r29,hi8(%o1)));
1820 else if (REGNO (XEXP (x,0)) == REG_X)
1822 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1823 it but I have this situation with extremal optimizing options. */
1824 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
1825 || reg_unused_after (insn, XEXP (x,0)))
1826 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1827 AS2 (ld,%0,X));
1829 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1830 AS2 (ld,%0,X) CR_TAB
1831 AS2 (sbiw,r26,%o1));
1833 *l = 1;
1834 return AS2 (ldd,%0,%1);
1836 *l = 1;
1837 return AS2 (ld,%0,%1);
1840 const char *
1841 out_movhi_r_mr (rtx insn, rtx op[], int *l)
1843 rtx dest = op[0];
1844 rtx src = op[1];
1845 rtx base = XEXP (src, 0);
1846 int reg_dest = true_regnum (dest);
1847 int reg_base = true_regnum (base);
1848 /* "volatile" forces reading low byte first, even if less efficient,
1849 for correct operation with 16-bit I/O registers. */
1850 int mem_volatile_p = MEM_VOLATILE_P (src);
1851 int tmp;
1853 if (!l)
1854 l = &tmp;
1856 if (reg_base > 0)
1858 if (reg_dest == reg_base) /* R = (R) */
1860 *l = 3;
1861 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1862 AS2 (ld,%B0,%1) CR_TAB
1863 AS2 (mov,%A0,__tmp_reg__));
1865 else if (reg_base == REG_X) /* (R26) */
1867 if (reg_unused_after (insn, base))
1869 *l = 2;
1870 return (AS2 (ld,%A0,X+) CR_TAB
1871 AS2 (ld,%B0,X));
1873 *l = 3;
1874 return (AS2 (ld,%A0,X+) CR_TAB
1875 AS2 (ld,%B0,X) CR_TAB
1876 AS2 (sbiw,r26,1));
1878 else /* (R) */
1880 *l = 2;
1881 return (AS2 (ld,%A0,%1) CR_TAB
1882 AS2 (ldd,%B0,%1+1));
1885 else if (GET_CODE (base) == PLUS) /* (R + i) */
1887 int disp = INTVAL (XEXP (base, 1));
1888 int reg_base = true_regnum (XEXP (base, 0));
1890 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
1892 if (REGNO (XEXP (base, 0)) != REG_Y)
1893 fatal_insn ("incorrect insn:",insn);
1895 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1896 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
1897 AS2 (ldd,%A0,Y+62) CR_TAB
1898 AS2 (ldd,%B0,Y+63) CR_TAB
1899 AS2 (sbiw,r28,%o1-62));
1901 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1902 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1903 AS2 (ld,%A0,Y) CR_TAB
1904 AS2 (ldd,%B0,Y+1) CR_TAB
1905 AS2 (subi,r28,lo8(%o1)) CR_TAB
1906 AS2 (sbci,r29,hi8(%o1)));
1908 if (reg_base == REG_X)
1910 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1911 it but I have this situation with extremal
1912 optimization options. */
1914 *l = 4;
1915 if (reg_base == reg_dest)
1916 return (AS2 (adiw,r26,%o1) CR_TAB
1917 AS2 (ld,__tmp_reg__,X+) CR_TAB
1918 AS2 (ld,%B0,X) CR_TAB
1919 AS2 (mov,%A0,__tmp_reg__));
1921 return (AS2 (adiw,r26,%o1) CR_TAB
1922 AS2 (ld,%A0,X+) CR_TAB
1923 AS2 (ld,%B0,X) CR_TAB
1924 AS2 (sbiw,r26,%o1+1));
1927 if (reg_base == reg_dest)
1929 *l = 3;
1930 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
1931 AS2 (ldd,%B0,%B1) CR_TAB
1932 AS2 (mov,%A0,__tmp_reg__));
1935 *l = 2;
1936 return (AS2 (ldd,%A0,%A1) CR_TAB
1937 AS2 (ldd,%B0,%B1));
1939 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
1941 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1942 fatal_insn ("incorrect insn:", insn);
1944 if (mem_volatile_p)
1946 if (REGNO (XEXP (base, 0)) == REG_X)
1948 *l = 4;
1949 return (AS2 (sbiw,r26,2) CR_TAB
1950 AS2 (ld,%A0,X+) CR_TAB
1951 AS2 (ld,%B0,X) CR_TAB
1952 AS2 (sbiw,r26,1));
1954 else
1956 *l = 3;
1957 return (AS2 (sbiw,%r1,2) CR_TAB
1958 AS2 (ld,%A0,%p1) CR_TAB
1959 AS2 (ldd,%B0,%p1+1));
1963 *l = 2;
1964 return (AS2 (ld,%B0,%1) CR_TAB
1965 AS2 (ld,%A0,%1));
1967 else if (GET_CODE (base) == POST_INC) /* (R++) */
1969 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1970 fatal_insn ("incorrect insn:", insn);
1972 *l = 2;
1973 return (AS2 (ld,%A0,%1) CR_TAB
1974 AS2 (ld,%B0,%1));
1976 else if (CONSTANT_ADDRESS_P (base))
1978 if (optimize > 0 && io_address_operand (base, HImode))
1980 *l = 2;
1981 return (AS2 (in,%A0,%A1-0x20) CR_TAB
1982 AS2 (in,%B0,%B1-0x20));
1984 *l = 4;
1985 return (AS2 (lds,%A0,%A1) CR_TAB
1986 AS2 (lds,%B0,%B1));
1989 fatal_insn ("unknown move insn:",insn);
1990 return "";
1993 const char *
1994 out_movsi_r_mr (rtx insn, rtx op[], int *l)
1996 rtx dest = op[0];
1997 rtx src = op[1];
1998 rtx base = XEXP (src, 0);
1999 int reg_dest = true_regnum (dest);
2000 int reg_base = true_regnum (base);
2001 int tmp;
2003 if (!l)
2004 l = &tmp;
2006 if (reg_base > 0)
2008 if (reg_base == REG_X) /* (R26) */
2010 if (reg_dest == REG_X)
2011 /* "ld r26,-X" is undefined */
2012 return *l=7, (AS2 (adiw,r26,3) CR_TAB
2013 AS2 (ld,r29,X) CR_TAB
2014 AS2 (ld,r28,-X) CR_TAB
2015 AS2 (ld,__tmp_reg__,-X) CR_TAB
2016 AS2 (sbiw,r26,1) CR_TAB
2017 AS2 (ld,r26,X) CR_TAB
2018 AS2 (mov,r27,__tmp_reg__));
2019 else if (reg_dest == REG_X - 2)
2020 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2021 AS2 (ld,%B0,X+) CR_TAB
2022 AS2 (ld,__tmp_reg__,X+) CR_TAB
2023 AS2 (ld,%D0,X) CR_TAB
2024 AS2 (mov,%C0,__tmp_reg__));
2025 else if (reg_unused_after (insn, base))
2026 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
2027 AS2 (ld,%B0,X+) CR_TAB
2028 AS2 (ld,%C0,X+) CR_TAB
2029 AS2 (ld,%D0,X));
2030 else
2031 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2032 AS2 (ld,%B0,X+) CR_TAB
2033 AS2 (ld,%C0,X+) CR_TAB
2034 AS2 (ld,%D0,X) CR_TAB
2035 AS2 (sbiw,r26,3));
2037 else
2039 if (reg_dest == reg_base)
2040 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
2041 AS2 (ldd,%C0,%1+2) CR_TAB
2042 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
2043 AS2 (ld,%A0,%1) CR_TAB
2044 AS2 (mov,%B0,__tmp_reg__));
2045 else if (reg_base == reg_dest + 2)
2046 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
2047 AS2 (ldd,%B0,%1+1) CR_TAB
2048 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
2049 AS2 (ldd,%D0,%1+3) CR_TAB
2050 AS2 (mov,%C0,__tmp_reg__));
2051 else
2052 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
2053 AS2 (ldd,%B0,%1+1) CR_TAB
2054 AS2 (ldd,%C0,%1+2) CR_TAB
2055 AS2 (ldd,%D0,%1+3));
2058 else if (GET_CODE (base) == PLUS) /* (R + i) */
2060 int disp = INTVAL (XEXP (base, 1));
2062 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2064 if (REGNO (XEXP (base, 0)) != REG_Y)
2065 fatal_insn ("incorrect insn:",insn);
2067 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2068 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2069 AS2 (ldd,%A0,Y+60) CR_TAB
2070 AS2 (ldd,%B0,Y+61) CR_TAB
2071 AS2 (ldd,%C0,Y+62) CR_TAB
2072 AS2 (ldd,%D0,Y+63) CR_TAB
2073 AS2 (sbiw,r28,%o1-60));
2075 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2076 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2077 AS2 (ld,%A0,Y) CR_TAB
2078 AS2 (ldd,%B0,Y+1) CR_TAB
2079 AS2 (ldd,%C0,Y+2) CR_TAB
2080 AS2 (ldd,%D0,Y+3) CR_TAB
2081 AS2 (subi,r28,lo8(%o1)) CR_TAB
2082 AS2 (sbci,r29,hi8(%o1)));
2085 reg_base = true_regnum (XEXP (base, 0));
2086 if (reg_base == REG_X)
2088 /* R = (X + d) */
2089 if (reg_dest == REG_X)
2091 *l = 7;
2092 /* "ld r26,-X" is undefined */
2093 return (AS2 (adiw,r26,%o1+3) CR_TAB
2094 AS2 (ld,r29,X) CR_TAB
2095 AS2 (ld,r28,-X) CR_TAB
2096 AS2 (ld,__tmp_reg__,-X) CR_TAB
2097 AS2 (sbiw,r26,1) CR_TAB
2098 AS2 (ld,r26,X) CR_TAB
2099 AS2 (mov,r27,__tmp_reg__));
2101 *l = 6;
2102 if (reg_dest == REG_X - 2)
2103 return (AS2 (adiw,r26,%o1) CR_TAB
2104 AS2 (ld,r24,X+) CR_TAB
2105 AS2 (ld,r25,X+) CR_TAB
2106 AS2 (ld,__tmp_reg__,X+) CR_TAB
2107 AS2 (ld,r27,X) CR_TAB
2108 AS2 (mov,r26,__tmp_reg__));
2110 return (AS2 (adiw,r26,%o1) CR_TAB
2111 AS2 (ld,%A0,X+) CR_TAB
2112 AS2 (ld,%B0,X+) CR_TAB
2113 AS2 (ld,%C0,X+) CR_TAB
2114 AS2 (ld,%D0,X) CR_TAB
2115 AS2 (sbiw,r26,%o1+3));
2117 if (reg_dest == reg_base)
2118 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2119 AS2 (ldd,%C0,%C1) CR_TAB
2120 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
2121 AS2 (ldd,%A0,%A1) CR_TAB
2122 AS2 (mov,%B0,__tmp_reg__));
2123 else if (reg_dest == reg_base - 2)
2124 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2125 AS2 (ldd,%B0,%B1) CR_TAB
2126 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
2127 AS2 (ldd,%D0,%D1) CR_TAB
2128 AS2 (mov,%C0,__tmp_reg__));
2129 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2130 AS2 (ldd,%B0,%B1) CR_TAB
2131 AS2 (ldd,%C0,%C1) CR_TAB
2132 AS2 (ldd,%D0,%D1));
2134 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2135 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2136 AS2 (ld,%C0,%1) CR_TAB
2137 AS2 (ld,%B0,%1) CR_TAB
2138 AS2 (ld,%A0,%1));
2139 else if (GET_CODE (base) == POST_INC) /* (R++) */
2140 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2141 AS2 (ld,%B0,%1) CR_TAB
2142 AS2 (ld,%C0,%1) CR_TAB
2143 AS2 (ld,%D0,%1));
2144 else if (CONSTANT_ADDRESS_P (base))
2145 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2146 AS2 (lds,%B0,%B1) CR_TAB
2147 AS2 (lds,%C0,%C1) CR_TAB
2148 AS2 (lds,%D0,%D1));
2150 fatal_insn ("unknown move insn:",insn);
2151 return "";
2154 const char *
2155 out_movsi_mr_r (rtx insn, rtx op[], int *l)
2157 rtx dest = op[0];
2158 rtx src = op[1];
2159 rtx base = XEXP (dest, 0);
2160 int reg_base = true_regnum (base);
2161 int reg_src = true_regnum (src);
2162 int tmp;
2164 if (!l)
2165 l = &tmp;
2167 if (CONSTANT_ADDRESS_P (base))
2168 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2169 AS2 (sts,%B0,%B1) CR_TAB
2170 AS2 (sts,%C0,%C1) CR_TAB
2171 AS2 (sts,%D0,%D1));
2172 if (reg_base > 0) /* (r) */
2174 if (reg_base == REG_X) /* (R26) */
2176 if (reg_src == REG_X)
2178 /* "st X+,r26" is undefined */
2179 if (reg_unused_after (insn, base))
2180 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2181 AS2 (st,X,r26) CR_TAB
2182 AS2 (adiw,r26,1) CR_TAB
2183 AS2 (st,X+,__tmp_reg__) CR_TAB
2184 AS2 (st,X+,r28) CR_TAB
2185 AS2 (st,X,r29));
2186 else
2187 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2188 AS2 (st,X,r26) CR_TAB
2189 AS2 (adiw,r26,1) CR_TAB
2190 AS2 (st,X+,__tmp_reg__) CR_TAB
2191 AS2 (st,X+,r28) CR_TAB
2192 AS2 (st,X,r29) CR_TAB
2193 AS2 (sbiw,r26,3));
2195 else if (reg_base == reg_src + 2)
2197 if (reg_unused_after (insn, base))
2198 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2199 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2200 AS2 (st,%0+,%A1) CR_TAB
2201 AS2 (st,%0+,%B1) CR_TAB
2202 AS2 (st,%0+,__zero_reg__) CR_TAB
2203 AS2 (st,%0,__tmp_reg__) CR_TAB
2204 AS1 (clr,__zero_reg__));
2205 else
2206 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2207 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2208 AS2 (st,%0+,%A1) CR_TAB
2209 AS2 (st,%0+,%B1) CR_TAB
2210 AS2 (st,%0+,__zero_reg__) CR_TAB
2211 AS2 (st,%0,__tmp_reg__) CR_TAB
2212 AS1 (clr,__zero_reg__) CR_TAB
2213 AS2 (sbiw,r26,3));
2215 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
2216 AS2 (st,%0+,%B1) CR_TAB
2217 AS2 (st,%0+,%C1) CR_TAB
2218 AS2 (st,%0,%D1) CR_TAB
2219 AS2 (sbiw,r26,3));
2221 else
2222 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2223 AS2 (std,%0+1,%B1) CR_TAB
2224 AS2 (std,%0+2,%C1) CR_TAB
2225 AS2 (std,%0+3,%D1));
2227 else if (GET_CODE (base) == PLUS) /* (R + i) */
2229 int disp = INTVAL (XEXP (base, 1));
2230 reg_base = REGNO (XEXP (base, 0));
2231 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2233 if (reg_base != REG_Y)
2234 fatal_insn ("incorrect insn:",insn);
2236 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2237 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2238 AS2 (std,Y+60,%A1) CR_TAB
2239 AS2 (std,Y+61,%B1) CR_TAB
2240 AS2 (std,Y+62,%C1) CR_TAB
2241 AS2 (std,Y+63,%D1) CR_TAB
2242 AS2 (sbiw,r28,%o0-60));
2244 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2245 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2246 AS2 (st,Y,%A1) CR_TAB
2247 AS2 (std,Y+1,%B1) CR_TAB
2248 AS2 (std,Y+2,%C1) CR_TAB
2249 AS2 (std,Y+3,%D1) CR_TAB
2250 AS2 (subi,r28,lo8(%o0)) CR_TAB
2251 AS2 (sbci,r29,hi8(%o0)));
2253 if (reg_base == REG_X)
2255 /* (X + d) = R */
2256 if (reg_src == REG_X)
2258 *l = 9;
2259 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2260 AS2 (mov,__zero_reg__,r27) CR_TAB
2261 AS2 (adiw,r26,%o0) CR_TAB
2262 AS2 (st,X+,__tmp_reg__) CR_TAB
2263 AS2 (st,X+,__zero_reg__) CR_TAB
2264 AS2 (st,X+,r28) CR_TAB
2265 AS2 (st,X,r29) CR_TAB
2266 AS1 (clr,__zero_reg__) CR_TAB
2267 AS2 (sbiw,r26,%o0+3));
2269 else if (reg_src == REG_X - 2)
2271 *l = 9;
2272 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2273 AS2 (mov,__zero_reg__,r27) CR_TAB
2274 AS2 (adiw,r26,%o0) CR_TAB
2275 AS2 (st,X+,r24) CR_TAB
2276 AS2 (st,X+,r25) CR_TAB
2277 AS2 (st,X+,__tmp_reg__) CR_TAB
2278 AS2 (st,X,__zero_reg__) CR_TAB
2279 AS1 (clr,__zero_reg__) CR_TAB
2280 AS2 (sbiw,r26,%o0+3));
2282 *l = 6;
2283 return (AS2 (adiw,r26,%o0) CR_TAB
2284 AS2 (st,X+,%A1) CR_TAB
2285 AS2 (st,X+,%B1) CR_TAB
2286 AS2 (st,X+,%C1) CR_TAB
2287 AS2 (st,X,%D1) CR_TAB
2288 AS2 (sbiw,r26,%o0+3));
2290 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
2291 AS2 (std,%B0,%B1) CR_TAB
2292 AS2 (std,%C0,%C1) CR_TAB
2293 AS2 (std,%D0,%D1));
2295 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2296 return *l=4, (AS2 (st,%0,%D1) CR_TAB
2297 AS2 (st,%0,%C1) CR_TAB
2298 AS2 (st,%0,%B1) CR_TAB
2299 AS2 (st,%0,%A1));
2300 else if (GET_CODE (base) == POST_INC) /* (R++) */
2301 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2302 AS2 (st,%0,%B1) CR_TAB
2303 AS2 (st,%0,%C1) CR_TAB
2304 AS2 (st,%0,%D1));
2305 fatal_insn ("unknown move insn:",insn);
2306 return "";
2309 const char *
2310 output_movsisf(rtx insn, rtx operands[], int *l)
2312 int dummy;
2313 rtx dest = operands[0];
2314 rtx src = operands[1];
2315 int *real_l = l;
2317 if (!l)
2318 l = &dummy;
2320 if (register_operand (dest, VOIDmode))
2322 if (register_operand (src, VOIDmode)) /* mov r,r */
2324 if (true_regnum (dest) > true_regnum (src))
2326 if (AVR_HAVE_MOVW)
2328 *l = 2;
2329 return (AS2 (movw,%C0,%C1) CR_TAB
2330 AS2 (movw,%A0,%A1));
2332 *l = 4;
2333 return (AS2 (mov,%D0,%D1) CR_TAB
2334 AS2 (mov,%C0,%C1) CR_TAB
2335 AS2 (mov,%B0,%B1) CR_TAB
2336 AS2 (mov,%A0,%A1));
2338 else
2340 if (AVR_HAVE_MOVW)
2342 *l = 2;
2343 return (AS2 (movw,%A0,%A1) CR_TAB
2344 AS2 (movw,%C0,%C1));
2346 *l = 4;
2347 return (AS2 (mov,%A0,%A1) CR_TAB
2348 AS2 (mov,%B0,%B1) CR_TAB
2349 AS2 (mov,%C0,%C1) CR_TAB
2350 AS2 (mov,%D0,%D1));
2353 else if (CONSTANT_P (src))
2355 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2357 *l = 4;
2358 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
2359 AS2 (ldi,%B0,hi8(%1)) CR_TAB
2360 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2361 AS2 (ldi,%D0,hhi8(%1)));
2364 if (GET_CODE (src) == CONST_INT)
2366 const char *const clr_op0 =
2367 AVR_HAVE_MOVW ? (AS1 (clr,%A0) CR_TAB
2368 AS1 (clr,%B0) CR_TAB
2369 AS2 (movw,%C0,%A0))
2370 : (AS1 (clr,%A0) CR_TAB
2371 AS1 (clr,%B0) CR_TAB
2372 AS1 (clr,%C0) CR_TAB
2373 AS1 (clr,%D0));
2375 if (src == const0_rtx) /* mov r,L */
2377 *l = AVR_HAVE_MOVW ? 3 : 4;
2378 return clr_op0;
2380 else if (src == const1_rtx)
2382 if (!real_l)
2383 output_asm_insn (clr_op0, operands);
2384 *l = AVR_HAVE_MOVW ? 4 : 5;
2385 return AS1 (inc,%A0);
2387 else if (src == constm1_rtx)
2389 /* Immediate constants -1 to any register */
2390 if (AVR_HAVE_MOVW)
2392 *l = 4;
2393 return (AS1 (clr,%A0) CR_TAB
2394 AS1 (dec,%A0) CR_TAB
2395 AS2 (mov,%B0,%A0) CR_TAB
2396 AS2 (movw,%C0,%A0));
2398 *l = 5;
2399 return (AS1 (clr,%A0) CR_TAB
2400 AS1 (dec,%A0) CR_TAB
2401 AS2 (mov,%B0,%A0) CR_TAB
2402 AS2 (mov,%C0,%A0) CR_TAB
2403 AS2 (mov,%D0,%A0));
2405 else
2407 int bit_nr = exact_log2 (INTVAL (src));
2409 if (bit_nr >= 0)
2411 *l = AVR_HAVE_MOVW ? 5 : 6;
2412 if (!real_l)
2414 output_asm_insn (clr_op0, operands);
2415 output_asm_insn ("set", operands);
2417 if (!real_l)
2418 avr_output_bld (operands, bit_nr);
2420 return "";
2425 /* Last resort, better than loading from memory. */
2426 *l = 10;
2427 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2428 AS2 (ldi,r31,lo8(%1)) CR_TAB
2429 AS2 (mov,%A0,r31) CR_TAB
2430 AS2 (ldi,r31,hi8(%1)) CR_TAB
2431 AS2 (mov,%B0,r31) CR_TAB
2432 AS2 (ldi,r31,hlo8(%1)) CR_TAB
2433 AS2 (mov,%C0,r31) CR_TAB
2434 AS2 (ldi,r31,hhi8(%1)) CR_TAB
2435 AS2 (mov,%D0,r31) CR_TAB
2436 AS2 (mov,r31,__tmp_reg__));
2438 else if (GET_CODE (src) == MEM)
2439 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2441 else if (GET_CODE (dest) == MEM)
2443 const char *templ;
2445 if (src == const0_rtx)
2446 operands[1] = zero_reg_rtx;
2448 templ = out_movsi_mr_r (insn, operands, real_l);
2450 if (!real_l)
2451 output_asm_insn (templ, operands);
2453 operands[1] = src;
2454 return "";
2456 fatal_insn ("invalid insn:", insn);
2457 return "";
2460 const char *
2461 out_movqi_mr_r (rtx insn, rtx op[], int *l)
2463 rtx dest = op[0];
2464 rtx src = op[1];
2465 rtx x = XEXP (dest, 0);
2466 int dummy;
2468 if (!l)
2469 l = &dummy;
2471 if (CONSTANT_ADDRESS_P (x))
2473 if (CONST_INT_P (x) && INTVAL (x) == SREG_ADDR)
2475 *l = 1;
2476 return AS2 (out,__SREG__,%1);
2478 if (optimize > 0 && io_address_operand (x, QImode))
2480 *l = 1;
2481 return AS2 (out,%0-0x20,%1);
2483 *l = 2;
2484 return AS2 (sts,%0,%1);
2486 /* memory access by reg+disp */
2487 else if (GET_CODE (x) == PLUS
2488 && REG_P (XEXP (x,0))
2489 && GET_CODE (XEXP (x,1)) == CONST_INT)
2491 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
2493 int disp = INTVAL (XEXP (x,1));
2494 if (REGNO (XEXP (x,0)) != REG_Y)
2495 fatal_insn ("incorrect insn:",insn);
2497 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2498 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2499 AS2 (std,Y+63,%1) CR_TAB
2500 AS2 (sbiw,r28,%o0-63));
2502 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2503 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2504 AS2 (st,Y,%1) CR_TAB
2505 AS2 (subi,r28,lo8(%o0)) CR_TAB
2506 AS2 (sbci,r29,hi8(%o0)));
2508 else if (REGNO (XEXP (x,0)) == REG_X)
2510 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
2512 if (reg_unused_after (insn, XEXP (x,0)))
2513 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2514 AS2 (adiw,r26,%o0) CR_TAB
2515 AS2 (st,X,__tmp_reg__));
2517 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2518 AS2 (adiw,r26,%o0) CR_TAB
2519 AS2 (st,X,__tmp_reg__) CR_TAB
2520 AS2 (sbiw,r26,%o0));
2522 else
2524 if (reg_unused_after (insn, XEXP (x,0)))
2525 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2526 AS2 (st,X,%1));
2528 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2529 AS2 (st,X,%1) CR_TAB
2530 AS2 (sbiw,r26,%o0));
2533 *l = 1;
2534 return AS2 (std,%0,%1);
2536 *l = 1;
2537 return AS2 (st,%0,%1);
2540 const char *
2541 out_movhi_mr_r (rtx insn, rtx op[], int *l)
2543 rtx dest = op[0];
2544 rtx src = op[1];
2545 rtx base = XEXP (dest, 0);
2546 int reg_base = true_regnum (base);
2547 int reg_src = true_regnum (src);
2548 /* "volatile" forces writing high byte first, even if less efficient,
2549 for correct operation with 16-bit I/O registers. */
2550 int mem_volatile_p = MEM_VOLATILE_P (dest);
2551 int tmp;
2553 if (!l)
2554 l = &tmp;
2555 if (CONSTANT_ADDRESS_P (base))
2557 if (optimize > 0 && io_address_operand (base, HImode))
2559 *l = 2;
2560 return (AS2 (out,%B0-0x20,%B1) CR_TAB
2561 AS2 (out,%A0-0x20,%A1));
2563 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2564 AS2 (sts,%A0,%A1));
2566 if (reg_base > 0)
2568 if (reg_base == REG_X)
2570 if (reg_src == REG_X)
2572 /* "st X+,r26" and "st -X,r26" are undefined. */
2573 if (!mem_volatile_p && reg_unused_after (insn, src))
2574 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2575 AS2 (st,X,r26) CR_TAB
2576 AS2 (adiw,r26,1) CR_TAB
2577 AS2 (st,X,__tmp_reg__));
2578 else
2579 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2580 AS2 (adiw,r26,1) CR_TAB
2581 AS2 (st,X,__tmp_reg__) CR_TAB
2582 AS2 (sbiw,r26,1) CR_TAB
2583 AS2 (st,X,r26));
2585 else
2587 if (!mem_volatile_p && reg_unused_after (insn, base))
2588 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2589 AS2 (st,X,%B1));
2590 else
2591 return *l=3, (AS2 (adiw,r26,1) CR_TAB
2592 AS2 (st,X,%B1) CR_TAB
2593 AS2 (st,-X,%A1));
2596 else
2597 return *l=2, (AS2 (std,%0+1,%B1) CR_TAB
2598 AS2 (st,%0,%A1));
2600 else if (GET_CODE (base) == PLUS)
2602 int disp = INTVAL (XEXP (base, 1));
2603 reg_base = REGNO (XEXP (base, 0));
2604 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2606 if (reg_base != REG_Y)
2607 fatal_insn ("incorrect insn:",insn);
2609 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2610 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
2611 AS2 (std,Y+63,%B1) CR_TAB
2612 AS2 (std,Y+62,%A1) CR_TAB
2613 AS2 (sbiw,r28,%o0-62));
2615 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2616 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2617 AS2 (std,Y+1,%B1) CR_TAB
2618 AS2 (st,Y,%A1) CR_TAB
2619 AS2 (subi,r28,lo8(%o0)) CR_TAB
2620 AS2 (sbci,r29,hi8(%o0)));
2622 if (reg_base == REG_X)
2624 /* (X + d) = R */
2625 if (reg_src == REG_X)
2627 *l = 7;
2628 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2629 AS2 (mov,__zero_reg__,r27) CR_TAB
2630 AS2 (adiw,r26,%o0+1) CR_TAB
2631 AS2 (st,X,__zero_reg__) CR_TAB
2632 AS2 (st,-X,__tmp_reg__) CR_TAB
2633 AS1 (clr,__zero_reg__) CR_TAB
2634 AS2 (sbiw,r26,%o0));
2636 *l = 4;
2637 return (AS2 (adiw,r26,%o0+1) CR_TAB
2638 AS2 (st,X,%B1) CR_TAB
2639 AS2 (st,-X,%A1) CR_TAB
2640 AS2 (sbiw,r26,%o0));
2642 return *l=2, (AS2 (std,%B0,%B1) CR_TAB
2643 AS2 (std,%A0,%A1));
2645 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2646 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2647 AS2 (st,%0,%A1));
2648 else if (GET_CODE (base) == POST_INC) /* (R++) */
2650 if (mem_volatile_p)
2652 if (REGNO (XEXP (base, 0)) == REG_X)
2654 *l = 4;
2655 return (AS2 (adiw,r26,1) CR_TAB
2656 AS2 (st,X,%B1) CR_TAB
2657 AS2 (st,-X,%A1) CR_TAB
2658 AS2 (adiw,r26,2));
2660 else
2662 *l = 3;
2663 return (AS2 (std,%p0+1,%B1) CR_TAB
2664 AS2 (st,%p0,%A1) CR_TAB
2665 AS2 (adiw,%r0,2));
2669 *l = 2;
2670 return (AS2 (st,%0,%A1) CR_TAB
2671 AS2 (st,%0,%B1));
2673 fatal_insn ("unknown move insn:",insn);
2674 return "";
2677 /* Return 1 if frame pointer for current function required. */
2679 bool
2680 avr_frame_pointer_required_p (void)
2682 return (cfun->calls_alloca
2683 || crtl->args.info.nregs == 0
2684 || get_frame_size () > 0);
2687 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2689 static RTX_CODE
2690 compare_condition (rtx insn)
2692 rtx next = next_real_insn (insn);
2693 RTX_CODE cond = UNKNOWN;
2694 if (next && GET_CODE (next) == JUMP_INSN)
2696 rtx pat = PATTERN (next);
2697 rtx src = SET_SRC (pat);
2698 rtx t = XEXP (src, 0);
2699 cond = GET_CODE (t);
2701 return cond;
2704 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2706 static int
2707 compare_sign_p (rtx insn)
2709 RTX_CODE cond = compare_condition (insn);
2710 return (cond == GE || cond == LT);
2713 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2714 that needs to be swapped (GT, GTU, LE, LEU). */
2717 compare_diff_p (rtx insn)
2719 RTX_CODE cond = compare_condition (insn);
2720 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2723 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2726 compare_eq_p (rtx insn)
2728 RTX_CODE cond = compare_condition (insn);
2729 return (cond == EQ || cond == NE);
2733 /* Output test instruction for HImode. */
2735 const char *
2736 out_tsthi (rtx insn, rtx op, int *l)
2738 if (compare_sign_p (insn))
2740 if (l) *l = 1;
2741 return AS1 (tst,%B0);
2743 if (reg_unused_after (insn, op)
2744 && compare_eq_p (insn))
2746 /* Faster than sbiw if we can clobber the operand. */
2747 if (l) *l = 1;
2748 return "or %A0,%B0";
2750 if (test_hard_reg_class (ADDW_REGS, op))
2752 if (l) *l = 1;
2753 return AS2 (sbiw,%0,0);
2755 if (l) *l = 2;
2756 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2757 AS2 (cpc,%B0,__zero_reg__));
2761 /* Output test instruction for SImode. */
2763 const char *
2764 out_tstsi (rtx insn, rtx op, int *l)
2766 if (compare_sign_p (insn))
2768 if (l) *l = 1;
2769 return AS1 (tst,%D0);
2771 if (test_hard_reg_class (ADDW_REGS, op))
2773 if (l) *l = 3;
2774 return (AS2 (sbiw,%A0,0) CR_TAB
2775 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2776 AS2 (cpc,%D0,__zero_reg__));
2778 if (l) *l = 4;
2779 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2780 AS2 (cpc,%B0,__zero_reg__) CR_TAB
2781 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2782 AS2 (cpc,%D0,__zero_reg__));
2786 /* Generate asm equivalent for various shifts.
2787 Shift count is a CONST_INT, MEM or REG.
2788 This only handles cases that are not already
2789 carefully hand-optimized in ?sh??i3_out. */
2791 void
2792 out_shift_with_cnt (const char *templ, rtx insn, rtx operands[],
2793 int *len, int t_len)
2795 rtx op[10];
2796 char str[500];
2797 int second_label = 1;
2798 int saved_in_tmp = 0;
2799 int use_zero_reg = 0;
2801 op[0] = operands[0];
2802 op[1] = operands[1];
2803 op[2] = operands[2];
2804 op[3] = operands[3];
2805 str[0] = 0;
2807 if (len)
2808 *len = 1;
2810 if (GET_CODE (operands[2]) == CONST_INT)
2812 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2813 int count = INTVAL (operands[2]);
2814 int max_len = 10; /* If larger than this, always use a loop. */
2816 if (count <= 0)
2818 if (len)
2819 *len = 0;
2820 return;
2823 if (count < 8 && !scratch)
2824 use_zero_reg = 1;
2826 if (optimize_size)
2827 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2829 if (t_len * count <= max_len)
2831 /* Output shifts inline with no loop - faster. */
2832 if (len)
2833 *len = t_len * count;
2834 else
2836 while (count-- > 0)
2837 output_asm_insn (templ, op);
2840 return;
2843 if (scratch)
2845 if (!len)
2846 strcat (str, AS2 (ldi,%3,%2));
2848 else if (use_zero_reg)
2850 /* Hack to save one word: use __zero_reg__ as loop counter.
2851 Set one bit, then shift in a loop until it is 0 again. */
2853 op[3] = zero_reg_rtx;
2854 if (len)
2855 *len = 2;
2856 else
2857 strcat (str, ("set" CR_TAB
2858 AS2 (bld,%3,%2-1)));
2860 else
2862 /* No scratch register available, use one from LD_REGS (saved in
2863 __tmp_reg__) that doesn't overlap with registers to shift. */
2865 op[3] = gen_rtx_REG (QImode,
2866 ((true_regnum (operands[0]) - 1) & 15) + 16);
2867 op[4] = tmp_reg_rtx;
2868 saved_in_tmp = 1;
2870 if (len)
2871 *len = 3; /* Includes "mov %3,%4" after the loop. */
2872 else
2873 strcat (str, (AS2 (mov,%4,%3) CR_TAB
2874 AS2 (ldi,%3,%2)));
2877 second_label = 0;
2879 else if (GET_CODE (operands[2]) == MEM)
2881 rtx op_mov[10];
2883 op[3] = op_mov[0] = tmp_reg_rtx;
2884 op_mov[1] = op[2];
2886 if (len)
2887 out_movqi_r_mr (insn, op_mov, len);
2888 else
2889 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
2891 else if (register_operand (operands[2], QImode))
2893 if (reg_unused_after (insn, operands[2]))
2894 op[3] = op[2];
2895 else
2897 op[3] = tmp_reg_rtx;
2898 if (!len)
2899 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
2902 else
2903 fatal_insn ("bad shift insn:", insn);
2905 if (second_label)
2907 if (len)
2908 ++*len;
2909 else
2910 strcat (str, AS1 (rjmp,2f));
2913 if (len)
2914 *len += t_len + 2; /* template + dec + brXX */
2915 else
2917 strcat (str, "\n1:\t");
2918 strcat (str, templ);
2919 strcat (str, second_label ? "\n2:\t" : "\n\t");
2920 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
2921 strcat (str, CR_TAB);
2922 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
2923 if (saved_in_tmp)
2924 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
2925 output_asm_insn (str, op);
2930 /* 8bit shift left ((char)x << i) */
2932 const char *
2933 ashlqi3_out (rtx insn, rtx operands[], int *len)
2935 if (GET_CODE (operands[2]) == CONST_INT)
2937 int k;
2939 if (!len)
2940 len = &k;
2942 switch (INTVAL (operands[2]))
2944 default:
2945 if (INTVAL (operands[2]) < 8)
2946 break;
2948 *len = 1;
2949 return AS1 (clr,%0);
2951 case 1:
2952 *len = 1;
2953 return AS1 (lsl,%0);
2955 case 2:
2956 *len = 2;
2957 return (AS1 (lsl,%0) CR_TAB
2958 AS1 (lsl,%0));
2960 case 3:
2961 *len = 3;
2962 return (AS1 (lsl,%0) CR_TAB
2963 AS1 (lsl,%0) CR_TAB
2964 AS1 (lsl,%0));
2966 case 4:
2967 if (test_hard_reg_class (LD_REGS, operands[0]))
2969 *len = 2;
2970 return (AS1 (swap,%0) CR_TAB
2971 AS2 (andi,%0,0xf0));
2973 *len = 4;
2974 return (AS1 (lsl,%0) CR_TAB
2975 AS1 (lsl,%0) CR_TAB
2976 AS1 (lsl,%0) CR_TAB
2977 AS1 (lsl,%0));
2979 case 5:
2980 if (test_hard_reg_class (LD_REGS, operands[0]))
2982 *len = 3;
2983 return (AS1 (swap,%0) CR_TAB
2984 AS1 (lsl,%0) CR_TAB
2985 AS2 (andi,%0,0xe0));
2987 *len = 5;
2988 return (AS1 (lsl,%0) CR_TAB
2989 AS1 (lsl,%0) CR_TAB
2990 AS1 (lsl,%0) CR_TAB
2991 AS1 (lsl,%0) CR_TAB
2992 AS1 (lsl,%0));
2994 case 6:
2995 if (test_hard_reg_class (LD_REGS, operands[0]))
2997 *len = 4;
2998 return (AS1 (swap,%0) CR_TAB
2999 AS1 (lsl,%0) CR_TAB
3000 AS1 (lsl,%0) CR_TAB
3001 AS2 (andi,%0,0xc0));
3003 *len = 6;
3004 return (AS1 (lsl,%0) CR_TAB
3005 AS1 (lsl,%0) CR_TAB
3006 AS1 (lsl,%0) CR_TAB
3007 AS1 (lsl,%0) CR_TAB
3008 AS1 (lsl,%0) CR_TAB
3009 AS1 (lsl,%0));
3011 case 7:
3012 *len = 3;
3013 return (AS1 (ror,%0) CR_TAB
3014 AS1 (clr,%0) CR_TAB
3015 AS1 (ror,%0));
3018 else if (CONSTANT_P (operands[2]))
3019 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3021 out_shift_with_cnt (AS1 (lsl,%0),
3022 insn, operands, len, 1);
3023 return "";
3027 /* 16bit shift left ((short)x << i) */
3029 const char *
3030 ashlhi3_out (rtx insn, rtx operands[], int *len)
3032 if (GET_CODE (operands[2]) == CONST_INT)
3034 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3035 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3036 int k;
3037 int *t = len;
3039 if (!len)
3040 len = &k;
3042 switch (INTVAL (operands[2]))
3044 default:
3045 if (INTVAL (operands[2]) < 16)
3046 break;
3048 *len = 2;
3049 return (AS1 (clr,%B0) CR_TAB
3050 AS1 (clr,%A0));
3052 case 4:
3053 if (optimize_size && scratch)
3054 break; /* 5 */
3055 if (ldi_ok)
3057 *len = 6;
3058 return (AS1 (swap,%A0) CR_TAB
3059 AS1 (swap,%B0) CR_TAB
3060 AS2 (andi,%B0,0xf0) CR_TAB
3061 AS2 (eor,%B0,%A0) CR_TAB
3062 AS2 (andi,%A0,0xf0) CR_TAB
3063 AS2 (eor,%B0,%A0));
3065 if (scratch)
3067 *len = 7;
3068 return (AS1 (swap,%A0) CR_TAB
3069 AS1 (swap,%B0) CR_TAB
3070 AS2 (ldi,%3,0xf0) CR_TAB
3071 "and %B0,%3" CR_TAB
3072 AS2 (eor,%B0,%A0) CR_TAB
3073 "and %A0,%3" CR_TAB
3074 AS2 (eor,%B0,%A0));
3076 break; /* optimize_size ? 6 : 8 */
3078 case 5:
3079 if (optimize_size)
3080 break; /* scratch ? 5 : 6 */
3081 if (ldi_ok)
3083 *len = 8;
3084 return (AS1 (lsl,%A0) CR_TAB
3085 AS1 (rol,%B0) CR_TAB
3086 AS1 (swap,%A0) CR_TAB
3087 AS1 (swap,%B0) CR_TAB
3088 AS2 (andi,%B0,0xf0) CR_TAB
3089 AS2 (eor,%B0,%A0) CR_TAB
3090 AS2 (andi,%A0,0xf0) CR_TAB
3091 AS2 (eor,%B0,%A0));
3093 if (scratch)
3095 *len = 9;
3096 return (AS1 (lsl,%A0) CR_TAB
3097 AS1 (rol,%B0) CR_TAB
3098 AS1 (swap,%A0) CR_TAB
3099 AS1 (swap,%B0) CR_TAB
3100 AS2 (ldi,%3,0xf0) CR_TAB
3101 "and %B0,%3" CR_TAB
3102 AS2 (eor,%B0,%A0) CR_TAB
3103 "and %A0,%3" CR_TAB
3104 AS2 (eor,%B0,%A0));
3106 break; /* 10 */
3108 case 6:
3109 if (optimize_size)
3110 break; /* scratch ? 5 : 6 */
3111 *len = 9;
3112 return (AS1 (clr,__tmp_reg__) CR_TAB
3113 AS1 (lsr,%B0) CR_TAB
3114 AS1 (ror,%A0) CR_TAB
3115 AS1 (ror,__tmp_reg__) CR_TAB
3116 AS1 (lsr,%B0) CR_TAB
3117 AS1 (ror,%A0) CR_TAB
3118 AS1 (ror,__tmp_reg__) CR_TAB
3119 AS2 (mov,%B0,%A0) CR_TAB
3120 AS2 (mov,%A0,__tmp_reg__));
3122 case 7:
3123 *len = 5;
3124 return (AS1 (lsr,%B0) CR_TAB
3125 AS2 (mov,%B0,%A0) CR_TAB
3126 AS1 (clr,%A0) CR_TAB
3127 AS1 (ror,%B0) CR_TAB
3128 AS1 (ror,%A0));
3130 case 8:
3131 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3132 AS1 (clr,%A0));
3134 case 9:
3135 *len = 3;
3136 return (AS2 (mov,%B0,%A0) CR_TAB
3137 AS1 (clr,%A0) CR_TAB
3138 AS1 (lsl,%B0));
3140 case 10:
3141 *len = 4;
3142 return (AS2 (mov,%B0,%A0) CR_TAB
3143 AS1 (clr,%A0) CR_TAB
3144 AS1 (lsl,%B0) CR_TAB
3145 AS1 (lsl,%B0));
3147 case 11:
3148 *len = 5;
3149 return (AS2 (mov,%B0,%A0) CR_TAB
3150 AS1 (clr,%A0) CR_TAB
3151 AS1 (lsl,%B0) CR_TAB
3152 AS1 (lsl,%B0) CR_TAB
3153 AS1 (lsl,%B0));
3155 case 12:
3156 if (ldi_ok)
3158 *len = 4;
3159 return (AS2 (mov,%B0,%A0) CR_TAB
3160 AS1 (clr,%A0) CR_TAB
3161 AS1 (swap,%B0) CR_TAB
3162 AS2 (andi,%B0,0xf0));
3164 if (scratch)
3166 *len = 5;
3167 return (AS2 (mov,%B0,%A0) CR_TAB
3168 AS1 (clr,%A0) CR_TAB
3169 AS1 (swap,%B0) CR_TAB
3170 AS2 (ldi,%3,0xf0) CR_TAB
3171 "and %B0,%3");
3173 *len = 6;
3174 return (AS2 (mov,%B0,%A0) CR_TAB
3175 AS1 (clr,%A0) CR_TAB
3176 AS1 (lsl,%B0) CR_TAB
3177 AS1 (lsl,%B0) CR_TAB
3178 AS1 (lsl,%B0) CR_TAB
3179 AS1 (lsl,%B0));
3181 case 13:
3182 if (ldi_ok)
3184 *len = 5;
3185 return (AS2 (mov,%B0,%A0) CR_TAB
3186 AS1 (clr,%A0) CR_TAB
3187 AS1 (swap,%B0) CR_TAB
3188 AS1 (lsl,%B0) CR_TAB
3189 AS2 (andi,%B0,0xe0));
3191 if (AVR_HAVE_MUL && scratch)
3193 *len = 5;
3194 return (AS2 (ldi,%3,0x20) CR_TAB
3195 AS2 (mul,%A0,%3) CR_TAB
3196 AS2 (mov,%B0,r0) CR_TAB
3197 AS1 (clr,%A0) CR_TAB
3198 AS1 (clr,__zero_reg__));
3200 if (optimize_size && scratch)
3201 break; /* 5 */
3202 if (scratch)
3204 *len = 6;
3205 return (AS2 (mov,%B0,%A0) CR_TAB
3206 AS1 (clr,%A0) CR_TAB
3207 AS1 (swap,%B0) CR_TAB
3208 AS1 (lsl,%B0) CR_TAB
3209 AS2 (ldi,%3,0xe0) CR_TAB
3210 "and %B0,%3");
3212 if (AVR_HAVE_MUL)
3214 *len = 6;
3215 return ("set" CR_TAB
3216 AS2 (bld,r1,5) CR_TAB
3217 AS2 (mul,%A0,r1) CR_TAB
3218 AS2 (mov,%B0,r0) CR_TAB
3219 AS1 (clr,%A0) CR_TAB
3220 AS1 (clr,__zero_reg__));
3222 *len = 7;
3223 return (AS2 (mov,%B0,%A0) CR_TAB
3224 AS1 (clr,%A0) CR_TAB
3225 AS1 (lsl,%B0) CR_TAB
3226 AS1 (lsl,%B0) CR_TAB
3227 AS1 (lsl,%B0) CR_TAB
3228 AS1 (lsl,%B0) CR_TAB
3229 AS1 (lsl,%B0));
3231 case 14:
3232 if (AVR_HAVE_MUL && ldi_ok)
3234 *len = 5;
3235 return (AS2 (ldi,%B0,0x40) CR_TAB
3236 AS2 (mul,%A0,%B0) CR_TAB
3237 AS2 (mov,%B0,r0) CR_TAB
3238 AS1 (clr,%A0) CR_TAB
3239 AS1 (clr,__zero_reg__));
3241 if (AVR_HAVE_MUL && scratch)
3243 *len = 5;
3244 return (AS2 (ldi,%3,0x40) CR_TAB
3245 AS2 (mul,%A0,%3) CR_TAB
3246 AS2 (mov,%B0,r0) CR_TAB
3247 AS1 (clr,%A0) CR_TAB
3248 AS1 (clr,__zero_reg__));
3250 if (optimize_size && ldi_ok)
3252 *len = 5;
3253 return (AS2 (mov,%B0,%A0) CR_TAB
3254 AS2 (ldi,%A0,6) "\n1:\t"
3255 AS1 (lsl,%B0) CR_TAB
3256 AS1 (dec,%A0) CR_TAB
3257 AS1 (brne,1b));
3259 if (optimize_size && scratch)
3260 break; /* 5 */
3261 *len = 6;
3262 return (AS1 (clr,%B0) CR_TAB
3263 AS1 (lsr,%A0) CR_TAB
3264 AS1 (ror,%B0) CR_TAB
3265 AS1 (lsr,%A0) CR_TAB
3266 AS1 (ror,%B0) CR_TAB
3267 AS1 (clr,%A0));
3269 case 15:
3270 *len = 4;
3271 return (AS1 (clr,%B0) CR_TAB
3272 AS1 (lsr,%A0) CR_TAB
3273 AS1 (ror,%B0) CR_TAB
3274 AS1 (clr,%A0));
3276 len = t;
3278 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3279 AS1 (rol,%B0)),
3280 insn, operands, len, 2);
3281 return "";
3285 /* 32bit shift left ((long)x << i) */
3287 const char *
3288 ashlsi3_out (rtx insn, rtx operands[], int *len)
3290 if (GET_CODE (operands[2]) == CONST_INT)
3292 int k;
3293 int *t = len;
3295 if (!len)
3296 len = &k;
3298 switch (INTVAL (operands[2]))
3300 default:
3301 if (INTVAL (operands[2]) < 32)
3302 break;
3304 if (AVR_HAVE_MOVW)
3305 return *len = 3, (AS1 (clr,%D0) CR_TAB
3306 AS1 (clr,%C0) CR_TAB
3307 AS2 (movw,%A0,%C0));
3308 *len = 4;
3309 return (AS1 (clr,%D0) CR_TAB
3310 AS1 (clr,%C0) CR_TAB
3311 AS1 (clr,%B0) CR_TAB
3312 AS1 (clr,%A0));
3314 case 8:
3316 int reg0 = true_regnum (operands[0]);
3317 int reg1 = true_regnum (operands[1]);
3318 *len = 4;
3319 if (reg0 >= reg1)
3320 return (AS2 (mov,%D0,%C1) CR_TAB
3321 AS2 (mov,%C0,%B1) CR_TAB
3322 AS2 (mov,%B0,%A1) CR_TAB
3323 AS1 (clr,%A0));
3324 else
3325 return (AS1 (clr,%A0) CR_TAB
3326 AS2 (mov,%B0,%A1) CR_TAB
3327 AS2 (mov,%C0,%B1) CR_TAB
3328 AS2 (mov,%D0,%C1));
3331 case 16:
3333 int reg0 = true_regnum (operands[0]);
3334 int reg1 = true_regnum (operands[1]);
3335 if (reg0 + 2 == reg1)
3336 return *len = 2, (AS1 (clr,%B0) CR_TAB
3337 AS1 (clr,%A0));
3338 if (AVR_HAVE_MOVW)
3339 return *len = 3, (AS2 (movw,%C0,%A1) CR_TAB
3340 AS1 (clr,%B0) CR_TAB
3341 AS1 (clr,%A0));
3342 else
3343 return *len = 4, (AS2 (mov,%C0,%A1) CR_TAB
3344 AS2 (mov,%D0,%B1) CR_TAB
3345 AS1 (clr,%B0) CR_TAB
3346 AS1 (clr,%A0));
3349 case 24:
3350 *len = 4;
3351 return (AS2 (mov,%D0,%A1) CR_TAB
3352 AS1 (clr,%C0) CR_TAB
3353 AS1 (clr,%B0) CR_TAB
3354 AS1 (clr,%A0));
3356 case 31:
3357 *len = 6;
3358 return (AS1 (clr,%D0) CR_TAB
3359 AS1 (lsr,%A0) CR_TAB
3360 AS1 (ror,%D0) CR_TAB
3361 AS1 (clr,%C0) CR_TAB
3362 AS1 (clr,%B0) CR_TAB
3363 AS1 (clr,%A0));
3365 len = t;
3367 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3368 AS1 (rol,%B0) CR_TAB
3369 AS1 (rol,%C0) CR_TAB
3370 AS1 (rol,%D0)),
3371 insn, operands, len, 4);
3372 return "";
3375 /* 8bit arithmetic shift right ((signed char)x >> i) */
3377 const char *
3378 ashrqi3_out (rtx insn, rtx operands[], int *len)
3380 if (GET_CODE (operands[2]) == CONST_INT)
3382 int k;
3384 if (!len)
3385 len = &k;
3387 switch (INTVAL (operands[2]))
3389 case 1:
3390 *len = 1;
3391 return AS1 (asr,%0);
3393 case 2:
3394 *len = 2;
3395 return (AS1 (asr,%0) CR_TAB
3396 AS1 (asr,%0));
3398 case 3:
3399 *len = 3;
3400 return (AS1 (asr,%0) CR_TAB
3401 AS1 (asr,%0) CR_TAB
3402 AS1 (asr,%0));
3404 case 4:
3405 *len = 4;
3406 return (AS1 (asr,%0) CR_TAB
3407 AS1 (asr,%0) CR_TAB
3408 AS1 (asr,%0) CR_TAB
3409 AS1 (asr,%0));
3411 case 5:
3412 *len = 5;
3413 return (AS1 (asr,%0) CR_TAB
3414 AS1 (asr,%0) CR_TAB
3415 AS1 (asr,%0) CR_TAB
3416 AS1 (asr,%0) CR_TAB
3417 AS1 (asr,%0));
3419 case 6:
3420 *len = 4;
3421 return (AS2 (bst,%0,6) CR_TAB
3422 AS1 (lsl,%0) CR_TAB
3423 AS2 (sbc,%0,%0) CR_TAB
3424 AS2 (bld,%0,0));
3426 default:
3427 if (INTVAL (operands[2]) < 8)
3428 break;
3430 /* fall through */
3432 case 7:
3433 *len = 2;
3434 return (AS1 (lsl,%0) CR_TAB
3435 AS2 (sbc,%0,%0));
3438 else if (CONSTANT_P (operands[2]))
3439 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3441 out_shift_with_cnt (AS1 (asr,%0),
3442 insn, operands, len, 1);
3443 return "";
3447 /* 16bit arithmetic shift right ((signed short)x >> i) */
3449 const char *
3450 ashrhi3_out (rtx insn, rtx operands[], int *len)
3452 if (GET_CODE (operands[2]) == CONST_INT)
3454 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3455 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3456 int k;
3457 int *t = len;
3459 if (!len)
3460 len = &k;
3462 switch (INTVAL (operands[2]))
3464 case 4:
3465 case 5:
3466 /* XXX try to optimize this too? */
3467 break;
3469 case 6:
3470 if (optimize_size)
3471 break; /* scratch ? 5 : 6 */
3472 *len = 8;
3473 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3474 AS2 (mov,%A0,%B0) CR_TAB
3475 AS1 (lsl,__tmp_reg__) CR_TAB
3476 AS1 (rol,%A0) CR_TAB
3477 AS2 (sbc,%B0,%B0) CR_TAB
3478 AS1 (lsl,__tmp_reg__) CR_TAB
3479 AS1 (rol,%A0) CR_TAB
3480 AS1 (rol,%B0));
3482 case 7:
3483 *len = 4;
3484 return (AS1 (lsl,%A0) CR_TAB
3485 AS2 (mov,%A0,%B0) CR_TAB
3486 AS1 (rol,%A0) CR_TAB
3487 AS2 (sbc,%B0,%B0));
3489 case 8:
3491 int reg0 = true_regnum (operands[0]);
3492 int reg1 = true_regnum (operands[1]);
3494 if (reg0 == reg1)
3495 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3496 AS1 (lsl,%B0) CR_TAB
3497 AS2 (sbc,%B0,%B0));
3498 else
3499 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3500 AS1 (clr,%B0) CR_TAB
3501 AS2 (sbrc,%A0,7) CR_TAB
3502 AS1 (dec,%B0));
3505 case 9:
3506 *len = 4;
3507 return (AS2 (mov,%A0,%B0) CR_TAB
3508 AS1 (lsl,%B0) CR_TAB
3509 AS2 (sbc,%B0,%B0) CR_TAB
3510 AS1 (asr,%A0));
3512 case 10:
3513 *len = 5;
3514 return (AS2 (mov,%A0,%B0) CR_TAB
3515 AS1 (lsl,%B0) CR_TAB
3516 AS2 (sbc,%B0,%B0) CR_TAB
3517 AS1 (asr,%A0) CR_TAB
3518 AS1 (asr,%A0));
3520 case 11:
3521 if (AVR_HAVE_MUL && ldi_ok)
3523 *len = 5;
3524 return (AS2 (ldi,%A0,0x20) CR_TAB
3525 AS2 (muls,%B0,%A0) CR_TAB
3526 AS2 (mov,%A0,r1) CR_TAB
3527 AS2 (sbc,%B0,%B0) CR_TAB
3528 AS1 (clr,__zero_reg__));
3530 if (optimize_size && scratch)
3531 break; /* 5 */
3532 *len = 6;
3533 return (AS2 (mov,%A0,%B0) CR_TAB
3534 AS1 (lsl,%B0) CR_TAB
3535 AS2 (sbc,%B0,%B0) CR_TAB
3536 AS1 (asr,%A0) CR_TAB
3537 AS1 (asr,%A0) CR_TAB
3538 AS1 (asr,%A0));
3540 case 12:
3541 if (AVR_HAVE_MUL && ldi_ok)
3543 *len = 5;
3544 return (AS2 (ldi,%A0,0x10) CR_TAB
3545 AS2 (muls,%B0,%A0) CR_TAB
3546 AS2 (mov,%A0,r1) CR_TAB
3547 AS2 (sbc,%B0,%B0) CR_TAB
3548 AS1 (clr,__zero_reg__));
3550 if (optimize_size && scratch)
3551 break; /* 5 */
3552 *len = 7;
3553 return (AS2 (mov,%A0,%B0) CR_TAB
3554 AS1 (lsl,%B0) CR_TAB
3555 AS2 (sbc,%B0,%B0) CR_TAB
3556 AS1 (asr,%A0) CR_TAB
3557 AS1 (asr,%A0) CR_TAB
3558 AS1 (asr,%A0) CR_TAB
3559 AS1 (asr,%A0));
3561 case 13:
3562 if (AVR_HAVE_MUL && ldi_ok)
3564 *len = 5;
3565 return (AS2 (ldi,%A0,0x08) CR_TAB
3566 AS2 (muls,%B0,%A0) CR_TAB
3567 AS2 (mov,%A0,r1) CR_TAB
3568 AS2 (sbc,%B0,%B0) CR_TAB
3569 AS1 (clr,__zero_reg__));
3571 if (optimize_size)
3572 break; /* scratch ? 5 : 7 */
3573 *len = 8;
3574 return (AS2 (mov,%A0,%B0) CR_TAB
3575 AS1 (lsl,%B0) CR_TAB
3576 AS2 (sbc,%B0,%B0) CR_TAB
3577 AS1 (asr,%A0) CR_TAB
3578 AS1 (asr,%A0) CR_TAB
3579 AS1 (asr,%A0) CR_TAB
3580 AS1 (asr,%A0) CR_TAB
3581 AS1 (asr,%A0));
3583 case 14:
3584 *len = 5;
3585 return (AS1 (lsl,%B0) CR_TAB
3586 AS2 (sbc,%A0,%A0) CR_TAB
3587 AS1 (lsl,%B0) CR_TAB
3588 AS2 (mov,%B0,%A0) CR_TAB
3589 AS1 (rol,%A0));
3591 default:
3592 if (INTVAL (operands[2]) < 16)
3593 break;
3595 /* fall through */
3597 case 15:
3598 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3599 AS2 (sbc,%A0,%A0) CR_TAB
3600 AS2 (mov,%B0,%A0));
3602 len = t;
3604 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3605 AS1 (ror,%A0)),
3606 insn, operands, len, 2);
3607 return "";
3611 /* 32bit arithmetic shift right ((signed long)x >> i) */
3613 const char *
3614 ashrsi3_out (rtx insn, rtx operands[], int *len)
3616 if (GET_CODE (operands[2]) == CONST_INT)
3618 int k;
3619 int *t = len;
3621 if (!len)
3622 len = &k;
3624 switch (INTVAL (operands[2]))
3626 case 8:
3628 int reg0 = true_regnum (operands[0]);
3629 int reg1 = true_regnum (operands[1]);
3630 *len=6;
3631 if (reg0 <= reg1)
3632 return (AS2 (mov,%A0,%B1) CR_TAB
3633 AS2 (mov,%B0,%C1) CR_TAB
3634 AS2 (mov,%C0,%D1) CR_TAB
3635 AS1 (clr,%D0) CR_TAB
3636 AS2 (sbrc,%C0,7) CR_TAB
3637 AS1 (dec,%D0));
3638 else
3639 return (AS1 (clr,%D0) CR_TAB
3640 AS2 (sbrc,%D1,7) CR_TAB
3641 AS1 (dec,%D0) CR_TAB
3642 AS2 (mov,%C0,%D1) CR_TAB
3643 AS2 (mov,%B0,%C1) CR_TAB
3644 AS2 (mov,%A0,%B1));
3647 case 16:
3649 int reg0 = true_regnum (operands[0]);
3650 int reg1 = true_regnum (operands[1]);
3652 if (reg0 == reg1 + 2)
3653 return *len = 4, (AS1 (clr,%D0) CR_TAB
3654 AS2 (sbrc,%B0,7) CR_TAB
3655 AS1 (com,%D0) CR_TAB
3656 AS2 (mov,%C0,%D0));
3657 if (AVR_HAVE_MOVW)
3658 return *len = 5, (AS2 (movw,%A0,%C1) CR_TAB
3659 AS1 (clr,%D0) CR_TAB
3660 AS2 (sbrc,%B0,7) CR_TAB
3661 AS1 (com,%D0) CR_TAB
3662 AS2 (mov,%C0,%D0));
3663 else
3664 return *len = 6, (AS2 (mov,%B0,%D1) CR_TAB
3665 AS2 (mov,%A0,%C1) CR_TAB
3666 AS1 (clr,%D0) CR_TAB
3667 AS2 (sbrc,%B0,7) CR_TAB
3668 AS1 (com,%D0) CR_TAB
3669 AS2 (mov,%C0,%D0));
3672 case 24:
3673 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3674 AS1 (clr,%D0) CR_TAB
3675 AS2 (sbrc,%A0,7) CR_TAB
3676 AS1 (com,%D0) CR_TAB
3677 AS2 (mov,%B0,%D0) CR_TAB
3678 AS2 (mov,%C0,%D0));
3680 default:
3681 if (INTVAL (operands[2]) < 32)
3682 break;
3684 /* fall through */
3686 case 31:
3687 if (AVR_HAVE_MOVW)
3688 return *len = 4, (AS1 (lsl,%D0) CR_TAB
3689 AS2 (sbc,%A0,%A0) CR_TAB
3690 AS2 (mov,%B0,%A0) CR_TAB
3691 AS2 (movw,%C0,%A0));
3692 else
3693 return *len = 5, (AS1 (lsl,%D0) CR_TAB
3694 AS2 (sbc,%A0,%A0) CR_TAB
3695 AS2 (mov,%B0,%A0) CR_TAB
3696 AS2 (mov,%C0,%A0) CR_TAB
3697 AS2 (mov,%D0,%A0));
3699 len = t;
3701 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3702 AS1 (ror,%C0) CR_TAB
3703 AS1 (ror,%B0) CR_TAB
3704 AS1 (ror,%A0)),
3705 insn, operands, len, 4);
3706 return "";
3709 /* 8bit logic shift right ((unsigned char)x >> i) */
3711 const char *
3712 lshrqi3_out (rtx insn, rtx operands[], int *len)
3714 if (GET_CODE (operands[2]) == CONST_INT)
3716 int k;
3718 if (!len)
3719 len = &k;
3721 switch (INTVAL (operands[2]))
3723 default:
3724 if (INTVAL (operands[2]) < 8)
3725 break;
3727 *len = 1;
3728 return AS1 (clr,%0);
3730 case 1:
3731 *len = 1;
3732 return AS1 (lsr,%0);
3734 case 2:
3735 *len = 2;
3736 return (AS1 (lsr,%0) CR_TAB
3737 AS1 (lsr,%0));
3738 case 3:
3739 *len = 3;
3740 return (AS1 (lsr,%0) CR_TAB
3741 AS1 (lsr,%0) CR_TAB
3742 AS1 (lsr,%0));
3744 case 4:
3745 if (test_hard_reg_class (LD_REGS, operands[0]))
3747 *len=2;
3748 return (AS1 (swap,%0) CR_TAB
3749 AS2 (andi,%0,0x0f));
3751 *len = 4;
3752 return (AS1 (lsr,%0) CR_TAB
3753 AS1 (lsr,%0) CR_TAB
3754 AS1 (lsr,%0) CR_TAB
3755 AS1 (lsr,%0));
3757 case 5:
3758 if (test_hard_reg_class (LD_REGS, operands[0]))
3760 *len = 3;
3761 return (AS1 (swap,%0) CR_TAB
3762 AS1 (lsr,%0) CR_TAB
3763 AS2 (andi,%0,0x7));
3765 *len = 5;
3766 return (AS1 (lsr,%0) CR_TAB
3767 AS1 (lsr,%0) CR_TAB
3768 AS1 (lsr,%0) CR_TAB
3769 AS1 (lsr,%0) CR_TAB
3770 AS1 (lsr,%0));
3772 case 6:
3773 if (test_hard_reg_class (LD_REGS, operands[0]))
3775 *len = 4;
3776 return (AS1 (swap,%0) CR_TAB
3777 AS1 (lsr,%0) CR_TAB
3778 AS1 (lsr,%0) CR_TAB
3779 AS2 (andi,%0,0x3));
3781 *len = 6;
3782 return (AS1 (lsr,%0) CR_TAB
3783 AS1 (lsr,%0) CR_TAB
3784 AS1 (lsr,%0) CR_TAB
3785 AS1 (lsr,%0) CR_TAB
3786 AS1 (lsr,%0) CR_TAB
3787 AS1 (lsr,%0));
3789 case 7:
3790 *len = 3;
3791 return (AS1 (rol,%0) CR_TAB
3792 AS1 (clr,%0) CR_TAB
3793 AS1 (rol,%0));
3796 else if (CONSTANT_P (operands[2]))
3797 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3799 out_shift_with_cnt (AS1 (lsr,%0),
3800 insn, operands, len, 1);
3801 return "";
3804 /* 16bit logic shift right ((unsigned short)x >> i) */
3806 const char *
3807 lshrhi3_out (rtx insn, rtx operands[], int *len)
3809 if (GET_CODE (operands[2]) == CONST_INT)
3811 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3812 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3813 int k;
3814 int *t = len;
3816 if (!len)
3817 len = &k;
3819 switch (INTVAL (operands[2]))
3821 default:
3822 if (INTVAL (operands[2]) < 16)
3823 break;
3825 *len = 2;
3826 return (AS1 (clr,%B0) CR_TAB
3827 AS1 (clr,%A0));
3829 case 4:
3830 if (optimize_size && scratch)
3831 break; /* 5 */
3832 if (ldi_ok)
3834 *len = 6;
3835 return (AS1 (swap,%B0) CR_TAB
3836 AS1 (swap,%A0) CR_TAB
3837 AS2 (andi,%A0,0x0f) CR_TAB
3838 AS2 (eor,%A0,%B0) CR_TAB
3839 AS2 (andi,%B0,0x0f) CR_TAB
3840 AS2 (eor,%A0,%B0));
3842 if (scratch)
3844 *len = 7;
3845 return (AS1 (swap,%B0) CR_TAB
3846 AS1 (swap,%A0) CR_TAB
3847 AS2 (ldi,%3,0x0f) CR_TAB
3848 "and %A0,%3" CR_TAB
3849 AS2 (eor,%A0,%B0) CR_TAB
3850 "and %B0,%3" CR_TAB
3851 AS2 (eor,%A0,%B0));
3853 break; /* optimize_size ? 6 : 8 */
3855 case 5:
3856 if (optimize_size)
3857 break; /* scratch ? 5 : 6 */
3858 if (ldi_ok)
3860 *len = 8;
3861 return (AS1 (lsr,%B0) CR_TAB
3862 AS1 (ror,%A0) CR_TAB
3863 AS1 (swap,%B0) CR_TAB
3864 AS1 (swap,%A0) CR_TAB
3865 AS2 (andi,%A0,0x0f) CR_TAB
3866 AS2 (eor,%A0,%B0) CR_TAB
3867 AS2 (andi,%B0,0x0f) CR_TAB
3868 AS2 (eor,%A0,%B0));
3870 if (scratch)
3872 *len = 9;
3873 return (AS1 (lsr,%B0) CR_TAB
3874 AS1 (ror,%A0) CR_TAB
3875 AS1 (swap,%B0) CR_TAB
3876 AS1 (swap,%A0) CR_TAB
3877 AS2 (ldi,%3,0x0f) CR_TAB
3878 "and %A0,%3" CR_TAB
3879 AS2 (eor,%A0,%B0) CR_TAB
3880 "and %B0,%3" CR_TAB
3881 AS2 (eor,%A0,%B0));
3883 break; /* 10 */
3885 case 6:
3886 if (optimize_size)
3887 break; /* scratch ? 5 : 6 */
3888 *len = 9;
3889 return (AS1 (clr,__tmp_reg__) CR_TAB
3890 AS1 (lsl,%A0) CR_TAB
3891 AS1 (rol,%B0) CR_TAB
3892 AS1 (rol,__tmp_reg__) CR_TAB
3893 AS1 (lsl,%A0) CR_TAB
3894 AS1 (rol,%B0) CR_TAB
3895 AS1 (rol,__tmp_reg__) CR_TAB
3896 AS2 (mov,%A0,%B0) CR_TAB
3897 AS2 (mov,%B0,__tmp_reg__));
3899 case 7:
3900 *len = 5;
3901 return (AS1 (lsl,%A0) CR_TAB
3902 AS2 (mov,%A0,%B0) CR_TAB
3903 AS1 (rol,%A0) CR_TAB
3904 AS2 (sbc,%B0,%B0) CR_TAB
3905 AS1 (neg,%B0));
3907 case 8:
3908 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
3909 AS1 (clr,%B0));
3911 case 9:
3912 *len = 3;
3913 return (AS2 (mov,%A0,%B0) CR_TAB
3914 AS1 (clr,%B0) CR_TAB
3915 AS1 (lsr,%A0));
3917 case 10:
3918 *len = 4;
3919 return (AS2 (mov,%A0,%B0) CR_TAB
3920 AS1 (clr,%B0) CR_TAB
3921 AS1 (lsr,%A0) CR_TAB
3922 AS1 (lsr,%A0));
3924 case 11:
3925 *len = 5;
3926 return (AS2 (mov,%A0,%B0) CR_TAB
3927 AS1 (clr,%B0) CR_TAB
3928 AS1 (lsr,%A0) CR_TAB
3929 AS1 (lsr,%A0) CR_TAB
3930 AS1 (lsr,%A0));
3932 case 12:
3933 if (ldi_ok)
3935 *len = 4;
3936 return (AS2 (mov,%A0,%B0) CR_TAB
3937 AS1 (clr,%B0) CR_TAB
3938 AS1 (swap,%A0) CR_TAB
3939 AS2 (andi,%A0,0x0f));
3941 if (scratch)
3943 *len = 5;
3944 return (AS2 (mov,%A0,%B0) CR_TAB
3945 AS1 (clr,%B0) CR_TAB
3946 AS1 (swap,%A0) CR_TAB
3947 AS2 (ldi,%3,0x0f) CR_TAB
3948 "and %A0,%3");
3950 *len = 6;
3951 return (AS2 (mov,%A0,%B0) CR_TAB
3952 AS1 (clr,%B0) CR_TAB
3953 AS1 (lsr,%A0) CR_TAB
3954 AS1 (lsr,%A0) CR_TAB
3955 AS1 (lsr,%A0) CR_TAB
3956 AS1 (lsr,%A0));
3958 case 13:
3959 if (ldi_ok)
3961 *len = 5;
3962 return (AS2 (mov,%A0,%B0) CR_TAB
3963 AS1 (clr,%B0) CR_TAB
3964 AS1 (swap,%A0) CR_TAB
3965 AS1 (lsr,%A0) CR_TAB
3966 AS2 (andi,%A0,0x07));
3968 if (AVR_HAVE_MUL && scratch)
3970 *len = 5;
3971 return (AS2 (ldi,%3,0x08) CR_TAB
3972 AS2 (mul,%B0,%3) CR_TAB
3973 AS2 (mov,%A0,r1) CR_TAB
3974 AS1 (clr,%B0) CR_TAB
3975 AS1 (clr,__zero_reg__));
3977 if (optimize_size && scratch)
3978 break; /* 5 */
3979 if (scratch)
3981 *len = 6;
3982 return (AS2 (mov,%A0,%B0) CR_TAB
3983 AS1 (clr,%B0) CR_TAB
3984 AS1 (swap,%A0) CR_TAB
3985 AS1 (lsr,%A0) CR_TAB
3986 AS2 (ldi,%3,0x07) CR_TAB
3987 "and %A0,%3");
3989 if (AVR_HAVE_MUL)
3991 *len = 6;
3992 return ("set" CR_TAB
3993 AS2 (bld,r1,3) CR_TAB
3994 AS2 (mul,%B0,r1) CR_TAB
3995 AS2 (mov,%A0,r1) CR_TAB
3996 AS1 (clr,%B0) CR_TAB
3997 AS1 (clr,__zero_reg__));
3999 *len = 7;
4000 return (AS2 (mov,%A0,%B0) CR_TAB
4001 AS1 (clr,%B0) CR_TAB
4002 AS1 (lsr,%A0) CR_TAB
4003 AS1 (lsr,%A0) CR_TAB
4004 AS1 (lsr,%A0) CR_TAB
4005 AS1 (lsr,%A0) CR_TAB
4006 AS1 (lsr,%A0));
4008 case 14:
4009 if (AVR_HAVE_MUL && ldi_ok)
4011 *len = 5;
4012 return (AS2 (ldi,%A0,0x04) CR_TAB
4013 AS2 (mul,%B0,%A0) CR_TAB
4014 AS2 (mov,%A0,r1) CR_TAB
4015 AS1 (clr,%B0) CR_TAB
4016 AS1 (clr,__zero_reg__));
4018 if (AVR_HAVE_MUL && scratch)
4020 *len = 5;
4021 return (AS2 (ldi,%3,0x04) CR_TAB
4022 AS2 (mul,%B0,%3) CR_TAB
4023 AS2 (mov,%A0,r1) CR_TAB
4024 AS1 (clr,%B0) CR_TAB
4025 AS1 (clr,__zero_reg__));
4027 if (optimize_size && ldi_ok)
4029 *len = 5;
4030 return (AS2 (mov,%A0,%B0) CR_TAB
4031 AS2 (ldi,%B0,6) "\n1:\t"
4032 AS1 (lsr,%A0) CR_TAB
4033 AS1 (dec,%B0) CR_TAB
4034 AS1 (brne,1b));
4036 if (optimize_size && scratch)
4037 break; /* 5 */
4038 *len = 6;
4039 return (AS1 (clr,%A0) CR_TAB
4040 AS1 (lsl,%B0) CR_TAB
4041 AS1 (rol,%A0) CR_TAB
4042 AS1 (lsl,%B0) CR_TAB
4043 AS1 (rol,%A0) CR_TAB
4044 AS1 (clr,%B0));
4046 case 15:
4047 *len = 4;
4048 return (AS1 (clr,%A0) CR_TAB
4049 AS1 (lsl,%B0) CR_TAB
4050 AS1 (rol,%A0) CR_TAB
4051 AS1 (clr,%B0));
4053 len = t;
4055 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
4056 AS1 (ror,%A0)),
4057 insn, operands, len, 2);
4058 return "";
4061 /* 32bit logic shift right ((unsigned int)x >> i) */
4063 const char *
4064 lshrsi3_out (rtx insn, rtx operands[], int *len)
4066 if (GET_CODE (operands[2]) == CONST_INT)
4068 int k;
4069 int *t = len;
4071 if (!len)
4072 len = &k;
4074 switch (INTVAL (operands[2]))
4076 default:
4077 if (INTVAL (operands[2]) < 32)
4078 break;
4080 if (AVR_HAVE_MOVW)
4081 return *len = 3, (AS1 (clr,%D0) CR_TAB
4082 AS1 (clr,%C0) CR_TAB
4083 AS2 (movw,%A0,%C0));
4084 *len = 4;
4085 return (AS1 (clr,%D0) CR_TAB
4086 AS1 (clr,%C0) CR_TAB
4087 AS1 (clr,%B0) CR_TAB
4088 AS1 (clr,%A0));
4090 case 8:
4092 int reg0 = true_regnum (operands[0]);
4093 int reg1 = true_regnum (operands[1]);
4094 *len = 4;
4095 if (reg0 <= reg1)
4096 return (AS2 (mov,%A0,%B1) CR_TAB
4097 AS2 (mov,%B0,%C1) CR_TAB
4098 AS2 (mov,%C0,%D1) CR_TAB
4099 AS1 (clr,%D0));
4100 else
4101 return (AS1 (clr,%D0) CR_TAB
4102 AS2 (mov,%C0,%D1) CR_TAB
4103 AS2 (mov,%B0,%C1) CR_TAB
4104 AS2 (mov,%A0,%B1));
4107 case 16:
4109 int reg0 = true_regnum (operands[0]);
4110 int reg1 = true_regnum (operands[1]);
4112 if (reg0 == reg1 + 2)
4113 return *len = 2, (AS1 (clr,%C0) CR_TAB
4114 AS1 (clr,%D0));
4115 if (AVR_HAVE_MOVW)
4116 return *len = 3, (AS2 (movw,%A0,%C1) CR_TAB
4117 AS1 (clr,%C0) CR_TAB
4118 AS1 (clr,%D0));
4119 else
4120 return *len = 4, (AS2 (mov,%B0,%D1) CR_TAB
4121 AS2 (mov,%A0,%C1) CR_TAB
4122 AS1 (clr,%C0) CR_TAB
4123 AS1 (clr,%D0));
4126 case 24:
4127 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4128 AS1 (clr,%B0) CR_TAB
4129 AS1 (clr,%C0) CR_TAB
4130 AS1 (clr,%D0));
4132 case 31:
4133 *len = 6;
4134 return (AS1 (clr,%A0) CR_TAB
4135 AS2 (sbrc,%D0,7) CR_TAB
4136 AS1 (inc,%A0) CR_TAB
4137 AS1 (clr,%B0) CR_TAB
4138 AS1 (clr,%C0) CR_TAB
4139 AS1 (clr,%D0));
4141 len = t;
4143 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4144 AS1 (ror,%C0) CR_TAB
4145 AS1 (ror,%B0) CR_TAB
4146 AS1 (ror,%A0)),
4147 insn, operands, len, 4);
4148 return "";
4151 /* Modifies the length assigned to instruction INSN
4152 LEN is the initially computed length of the insn. */
4155 adjust_insn_length (rtx insn, int len)
4157 rtx patt = PATTERN (insn);
4158 rtx set;
4160 if (GET_CODE (patt) == SET)
4162 rtx op[10];
4163 op[1] = SET_SRC (patt);
4164 op[0] = SET_DEST (patt);
4165 if (general_operand (op[1], VOIDmode)
4166 && general_operand (op[0], VOIDmode))
4168 switch (GET_MODE (op[0]))
4170 case QImode:
4171 output_movqi (insn, op, &len);
4172 break;
4173 case HImode:
4174 output_movhi (insn, op, &len);
4175 break;
4176 case SImode:
4177 case SFmode:
4178 output_movsisf (insn, op, &len);
4179 break;
4180 default:
4181 break;
4184 else if (op[0] == cc0_rtx && REG_P (op[1]))
4186 switch (GET_MODE (op[1]))
4188 case HImode: out_tsthi (insn, op[1], &len); break;
4189 case SImode: out_tstsi (insn, op[1], &len); break;
4190 default: break;
4193 else if (GET_CODE (op[1]) == AND)
4195 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4197 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4198 if (GET_MODE (op[1]) == SImode)
4199 len = (((mask & 0xff) != 0xff)
4200 + ((mask & 0xff00) != 0xff00)
4201 + ((mask & 0xff0000L) != 0xff0000L)
4202 + ((mask & 0xff000000L) != 0xff000000L));
4203 else if (GET_MODE (op[1]) == HImode)
4204 len = (((mask & 0xff) != 0xff)
4205 + ((mask & 0xff00) != 0xff00));
4208 else if (GET_CODE (op[1]) == IOR)
4210 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4212 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4213 if (GET_MODE (op[1]) == SImode)
4214 len = (((mask & 0xff) != 0)
4215 + ((mask & 0xff00) != 0)
4216 + ((mask & 0xff0000L) != 0)
4217 + ((mask & 0xff000000L) != 0));
4218 else if (GET_MODE (op[1]) == HImode)
4219 len = (((mask & 0xff) != 0)
4220 + ((mask & 0xff00) != 0));
4224 set = single_set (insn);
4225 if (set)
4227 rtx op[10];
4229 op[1] = SET_SRC (set);
4230 op[0] = SET_DEST (set);
4232 if (GET_CODE (patt) == PARALLEL
4233 && general_operand (op[1], VOIDmode)
4234 && general_operand (op[0], VOIDmode))
4236 if (XVECLEN (patt, 0) == 2)
4237 op[2] = XVECEXP (patt, 0, 1);
4239 switch (GET_MODE (op[0]))
4241 case QImode:
4242 len = 2;
4243 break;
4244 case HImode:
4245 output_reload_inhi (insn, op, &len);
4246 break;
4247 case SImode:
4248 case SFmode:
4249 output_reload_insisf (insn, op, &len);
4250 break;
4251 default:
4252 break;
4255 else if (GET_CODE (op[1]) == ASHIFT
4256 || GET_CODE (op[1]) == ASHIFTRT
4257 || GET_CODE (op[1]) == LSHIFTRT)
4259 rtx ops[10];
4260 ops[0] = op[0];
4261 ops[1] = XEXP (op[1],0);
4262 ops[2] = XEXP (op[1],1);
4263 switch (GET_CODE (op[1]))
4265 case ASHIFT:
4266 switch (GET_MODE (op[0]))
4268 case QImode: ashlqi3_out (insn,ops,&len); break;
4269 case HImode: ashlhi3_out (insn,ops,&len); break;
4270 case SImode: ashlsi3_out (insn,ops,&len); break;
4271 default: break;
4273 break;
4274 case ASHIFTRT:
4275 switch (GET_MODE (op[0]))
4277 case QImode: ashrqi3_out (insn,ops,&len); break;
4278 case HImode: ashrhi3_out (insn,ops,&len); break;
4279 case SImode: ashrsi3_out (insn,ops,&len); break;
4280 default: break;
4282 break;
4283 case LSHIFTRT:
4284 switch (GET_MODE (op[0]))
4286 case QImode: lshrqi3_out (insn,ops,&len); break;
4287 case HImode: lshrhi3_out (insn,ops,&len); break;
4288 case SImode: lshrsi3_out (insn,ops,&len); break;
4289 default: break;
4291 break;
4292 default:
4293 break;
4297 return len;
4300 /* Return nonzero if register REG dead after INSN. */
4303 reg_unused_after (rtx insn, rtx reg)
4305 return (dead_or_set_p (insn, reg)
4306 || (REG_P(reg) && _reg_unused_after (insn, reg)));
4309 /* Return nonzero if REG is not used after INSN.
4310 We assume REG is a reload reg, and therefore does
4311 not live past labels. It may live past calls or jumps though. */
4314 _reg_unused_after (rtx insn, rtx reg)
4316 enum rtx_code code;
4317 rtx set;
4319 /* If the reg is set by this instruction, then it is safe for our
4320 case. Disregard the case where this is a store to memory, since
4321 we are checking a register used in the store address. */
4322 set = single_set (insn);
4323 if (set && GET_CODE (SET_DEST (set)) != MEM
4324 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4325 return 1;
4327 while ((insn = NEXT_INSN (insn)))
4329 rtx set;
4330 code = GET_CODE (insn);
4332 #if 0
4333 /* If this is a label that existed before reload, then the register
4334 if dead here. However, if this is a label added by reorg, then
4335 the register may still be live here. We can't tell the difference,
4336 so we just ignore labels completely. */
4337 if (code == CODE_LABEL)
4338 return 1;
4339 /* else */
4340 #endif
4342 if (!INSN_P (insn))
4343 continue;
4345 if (code == JUMP_INSN)
4346 return 0;
4348 /* If this is a sequence, we must handle them all at once.
4349 We could have for instance a call that sets the target register,
4350 and an insn in a delay slot that uses the register. In this case,
4351 we must return 0. */
4352 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4354 int i;
4355 int retval = 0;
4357 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4359 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4360 rtx set = single_set (this_insn);
4362 if (GET_CODE (this_insn) == CALL_INSN)
4363 code = CALL_INSN;
4364 else if (GET_CODE (this_insn) == JUMP_INSN)
4366 if (INSN_ANNULLED_BRANCH_P (this_insn))
4367 return 0;
4368 code = JUMP_INSN;
4371 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4372 return 0;
4373 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4375 if (GET_CODE (SET_DEST (set)) != MEM)
4376 retval = 1;
4377 else
4378 return 0;
4380 if (set == 0
4381 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4382 return 0;
4384 if (retval == 1)
4385 return 1;
4386 else if (code == JUMP_INSN)
4387 return 0;
4390 if (code == CALL_INSN)
4392 rtx tem;
4393 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4394 if (GET_CODE (XEXP (tem, 0)) == USE
4395 && REG_P (XEXP (XEXP (tem, 0), 0))
4396 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4397 return 0;
4398 if (call_used_regs[REGNO (reg)])
4399 return 1;
4402 set = single_set (insn);
4404 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4405 return 0;
4406 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4407 return GET_CODE (SET_DEST (set)) != MEM;
4408 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4409 return 0;
4411 return 1;
4414 /* Target hook for assembling integer objects. The AVR version needs
4415 special handling for references to certain labels. */
4417 static bool
4418 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
4420 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
4421 && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
4422 || GET_CODE (x) == LABEL_REF))
4424 fputs ("\t.word\tgs(", asm_out_file);
4425 output_addr_const (asm_out_file, x);
4426 fputs (")\n", asm_out_file);
4427 return true;
4429 return default_assemble_integer (x, size, aligned_p);
4432 /* Worker function for ASM_DECLARE_FUNCTION_NAME. */
4434 void
4435 avr_asm_declare_function_name (FILE *file, const char *name, tree decl)
4438 /* If the function has the 'signal' or 'interrupt' attribute, test to
4439 make sure that the name of the function is "__vector_NN" so as to
4440 catch when the user misspells the interrupt vector name. */
4442 if (cfun->machine->is_interrupt)
4444 if (strncmp (name, "__vector", strlen ("__vector")) != 0)
4446 warning_at (DECL_SOURCE_LOCATION (decl), 0,
4447 "%qs appears to be a misspelled interrupt handler",
4448 name);
4451 else if (cfun->machine->is_signal)
4453 if (strncmp (name, "__vector", strlen ("__vector")) != 0)
4455 warning_at (DECL_SOURCE_LOCATION (decl), 0,
4456 "%qs appears to be a misspelled signal handler",
4457 name);
4461 ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
4462 ASM_OUTPUT_LABEL (file, name);
4465 /* The routine used to output NUL terminated strings. We use a special
4466 version of this for most svr4 targets because doing so makes the
4467 generated assembly code more compact (and thus faster to assemble)
4468 as well as more readable, especially for targets like the i386
4469 (where the only alternative is to output character sequences as
4470 comma separated lists of numbers). */
4472 void
4473 gas_output_limited_string(FILE *file, const char *str)
4475 const unsigned char *_limited_str = (const unsigned char *) str;
4476 unsigned ch;
4477 fprintf (file, "%s\"", STRING_ASM_OP);
4478 for (; (ch = *_limited_str); _limited_str++)
4480 int escape;
4481 switch (escape = ESCAPES[ch])
4483 case 0:
4484 putc (ch, file);
4485 break;
4486 case 1:
4487 fprintf (file, "\\%03o", ch);
4488 break;
4489 default:
4490 putc ('\\', file);
4491 putc (escape, file);
4492 break;
4495 fprintf (file, "\"\n");
4498 /* The routine used to output sequences of byte values. We use a special
4499 version of this for most svr4 targets because doing so makes the
4500 generated assembly code more compact (and thus faster to assemble)
4501 as well as more readable. Note that if we find subparts of the
4502 character sequence which end with NUL (and which are shorter than
4503 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4505 void
4506 gas_output_ascii(FILE *file, const char *str, size_t length)
4508 const unsigned char *_ascii_bytes = (const unsigned char *) str;
4509 const unsigned char *limit = _ascii_bytes + length;
4510 unsigned bytes_in_chunk = 0;
4511 for (; _ascii_bytes < limit; _ascii_bytes++)
4513 const unsigned char *p;
4514 if (bytes_in_chunk >= 60)
4516 fprintf (file, "\"\n");
4517 bytes_in_chunk = 0;
4519 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4520 continue;
4521 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4523 if (bytes_in_chunk > 0)
4525 fprintf (file, "\"\n");
4526 bytes_in_chunk = 0;
4528 gas_output_limited_string (file, (const char*)_ascii_bytes);
4529 _ascii_bytes = p;
4531 else
4533 int escape;
4534 unsigned ch;
4535 if (bytes_in_chunk == 0)
4536 fprintf (file, "\t.ascii\t\"");
4537 switch (escape = ESCAPES[ch = *_ascii_bytes])
4539 case 0:
4540 putc (ch, file);
4541 bytes_in_chunk++;
4542 break;
4543 case 1:
4544 fprintf (file, "\\%03o", ch);
4545 bytes_in_chunk += 4;
4546 break;
4547 default:
4548 putc ('\\', file);
4549 putc (escape, file);
4550 bytes_in_chunk += 2;
4551 break;
4555 if (bytes_in_chunk > 0)
4556 fprintf (file, "\"\n");
4559 /* Return value is nonzero if pseudos that have been
4560 assigned to registers of class CLASS would likely be spilled
4561 because registers of CLASS are needed for spill registers. */
4563 bool
4564 class_likely_spilled_p (int c)
4566 return (c != ALL_REGS && c != ADDW_REGS);
4569 /* Valid attributes:
4570 progmem - put data to program memory;
4571 signal - make a function to be hardware interrupt. After function
4572 prologue interrupts are disabled;
4573 interrupt - make a function to be hardware interrupt. After function
4574 prologue interrupts are enabled;
4575 naked - don't generate function prologue/epilogue and `ret' command.
4577 Only `progmem' attribute valid for type. */
4579 /* Handle a "progmem" attribute; arguments as in
4580 struct attribute_spec.handler. */
4581 static tree
4582 avr_handle_progmem_attribute (tree *node, tree name,
4583 tree args ATTRIBUTE_UNUSED,
4584 int flags ATTRIBUTE_UNUSED,
4585 bool *no_add_attrs)
4587 if (DECL_P (*node))
4589 if (TREE_CODE (*node) == TYPE_DECL)
4591 /* This is really a decl attribute, not a type attribute,
4592 but try to handle it for GCC 3.0 backwards compatibility. */
4594 tree type = TREE_TYPE (*node);
4595 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
4596 tree newtype = build_type_attribute_variant (type, attr);
4598 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
4599 TREE_TYPE (*node) = newtype;
4600 *no_add_attrs = true;
4602 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
4604 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
4606 warning (0, "only initialized variables can be placed into "
4607 "program memory area");
4608 *no_add_attrs = true;
4611 else
4613 warning (OPT_Wattributes, "%qE attribute ignored",
4614 name);
4615 *no_add_attrs = true;
4619 return NULL_TREE;
4622 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4623 struct attribute_spec.handler. */
4625 static tree
4626 avr_handle_fndecl_attribute (tree *node, tree name,
4627 tree args ATTRIBUTE_UNUSED,
4628 int flags ATTRIBUTE_UNUSED,
4629 bool *no_add_attrs)
4631 if (TREE_CODE (*node) != FUNCTION_DECL)
4633 warning (OPT_Wattributes, "%qE attribute only applies to functions",
4634 name);
4635 *no_add_attrs = true;
4638 return NULL_TREE;
4641 static tree
4642 avr_handle_fntype_attribute (tree *node, tree name,
4643 tree args ATTRIBUTE_UNUSED,
4644 int flags ATTRIBUTE_UNUSED,
4645 bool *no_add_attrs)
4647 if (TREE_CODE (*node) != FUNCTION_TYPE)
4649 warning (OPT_Wattributes, "%qE attribute only applies to functions",
4650 name);
4651 *no_add_attrs = true;
4654 return NULL_TREE;
4657 /* Look for attribute `progmem' in DECL
4658 if found return 1, otherwise 0. */
4661 avr_progmem_p (tree decl, tree attributes)
4663 tree a;
4665 if (TREE_CODE (decl) != VAR_DECL)
4666 return 0;
4668 if (NULL_TREE
4669 != lookup_attribute ("progmem", attributes))
4670 return 1;
4672 a=decl;
4674 a = TREE_TYPE(a);
4675 while (TREE_CODE (a) == ARRAY_TYPE);
4677 if (a == error_mark_node)
4678 return 0;
4680 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4681 return 1;
4683 return 0;
4686 /* Add the section attribute if the variable is in progmem. */
4688 static void
4689 avr_insert_attributes (tree node, tree *attributes)
4691 if (TREE_CODE (node) == VAR_DECL
4692 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
4693 && avr_progmem_p (node, *attributes))
4695 static const char dsec[] = ".progmem.data";
4696 *attributes = tree_cons (get_identifier ("section"),
4697 build_tree_list (NULL, build_string (strlen (dsec), dsec)),
4698 *attributes);
4700 /* ??? This seems sketchy. Why can't the user declare the
4701 thing const in the first place? */
4702 TREE_READONLY (node) = 1;
4706 /* A get_unnamed_section callback for switching to progmem_section. */
4708 static void
4709 avr_output_progmem_section_asm_op (const void *arg ATTRIBUTE_UNUSED)
4711 fprintf (asm_out_file,
4712 "\t.section .progmem.gcc_sw_table, \"%s\", @progbits\n",
4713 AVR_HAVE_JMP_CALL ? "a" : "ax");
4714 /* Should already be aligned, this is just to be safe if it isn't. */
4715 fprintf (asm_out_file, "\t.p2align 1\n");
4718 /* Implement TARGET_ASM_INIT_SECTIONS. */
4720 static void
4721 avr_asm_init_sections (void)
4723 progmem_section = get_unnamed_section (AVR_HAVE_JMP_CALL ? 0 : SECTION_CODE,
4724 avr_output_progmem_section_asm_op,
4725 NULL);
4726 readonly_data_section = data_section;
4729 static unsigned int
4730 avr_section_type_flags (tree decl, const char *name, int reloc)
4732 unsigned int flags = default_section_type_flags (decl, name, reloc);
4734 if (strncmp (name, ".noinit", 7) == 0)
4736 if (decl && TREE_CODE (decl) == VAR_DECL
4737 && DECL_INITIAL (decl) == NULL_TREE)
4738 flags |= SECTION_BSS; /* @nobits */
4739 else
4740 warning (0, "only uninitialized variables can be placed in the "
4741 ".noinit section");
4744 return flags;
4747 /* Outputs some appropriate text to go at the start of an assembler
4748 file. */
4750 static void
4751 avr_file_start (void)
4753 if (avr_current_arch->asm_only)
4754 error ("MCU %qs supported for assembler only", avr_mcu_name);
4756 default_file_start ();
4758 /* fprintf (asm_out_file, "\t.arch %s\n", avr_mcu_name);*/
4759 fputs ("__SREG__ = 0x3f\n"
4760 "__SP_H__ = 0x3e\n"
4761 "__SP_L__ = 0x3d\n", asm_out_file);
4763 fputs ("__tmp_reg__ = 0\n"
4764 "__zero_reg__ = 1\n", asm_out_file);
4766 /* FIXME: output these only if there is anything in the .data / .bss
4767 sections - some code size could be saved by not linking in the
4768 initialization code from libgcc if one or both sections are empty. */
4769 fputs ("\t.global __do_copy_data\n", asm_out_file);
4770 fputs ("\t.global __do_clear_bss\n", asm_out_file);
4773 /* Outputs to the stdio stream FILE some
4774 appropriate text to go at the end of an assembler file. */
4776 static void
4777 avr_file_end (void)
4781 /* Choose the order in which to allocate hard registers for
4782 pseudo-registers local to a basic block.
4784 Store the desired register order in the array `reg_alloc_order'.
4785 Element 0 should be the register to allocate first; element 1, the
4786 next register; and so on. */
4788 void
4789 order_regs_for_local_alloc (void)
4791 unsigned int i;
4792 static const int order_0[] = {
4793 24,25,
4794 18,19,
4795 20,21,
4796 22,23,
4797 30,31,
4798 26,27,
4799 28,29,
4800 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4801 0,1,
4802 32,33,34,35
4804 static const int order_1[] = {
4805 18,19,
4806 20,21,
4807 22,23,
4808 24,25,
4809 30,31,
4810 26,27,
4811 28,29,
4812 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4813 0,1,
4814 32,33,34,35
4816 static const int order_2[] = {
4817 25,24,
4818 23,22,
4819 21,20,
4820 19,18,
4821 30,31,
4822 26,27,
4823 28,29,
4824 17,16,
4825 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4826 1,0,
4827 32,33,34,35
4830 const int *order = (TARGET_ORDER_1 ? order_1 :
4831 TARGET_ORDER_2 ? order_2 :
4832 order_0);
4833 for (i=0; i < ARRAY_SIZE (order_0); ++i)
4834 reg_alloc_order[i] = order[i];
4838 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
4839 cost of an RTX operand given its context. X is the rtx of the
4840 operand, MODE is its mode, and OUTER is the rtx_code of this
4841 operand's parent operator. */
4843 static int
4844 avr_operand_rtx_cost (rtx x, enum machine_mode mode, enum rtx_code outer,
4845 bool speed)
4847 enum rtx_code code = GET_CODE (x);
4848 int total;
4850 switch (code)
4852 case REG:
4853 case SUBREG:
4854 return 0;
4856 case CONST_INT:
4857 case CONST_DOUBLE:
4858 return COSTS_N_INSNS (GET_MODE_SIZE (mode));
4860 default:
4861 break;
4864 total = 0;
4865 avr_rtx_costs (x, code, outer, &total, speed);
4866 return total;
4869 /* The AVR backend's rtx_cost function. X is rtx expression whose cost
4870 is to be calculated. Return true if the complete cost has been
4871 computed, and false if subexpressions should be scanned. In either
4872 case, *TOTAL contains the cost result. */
4874 static bool
4875 avr_rtx_costs (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED, int *total,
4876 bool speed)
4878 enum rtx_code code = (enum rtx_code) codearg;
4879 enum machine_mode mode = GET_MODE (x);
4880 HOST_WIDE_INT val;
4882 switch (code)
4884 case CONST_INT:
4885 case CONST_DOUBLE:
4886 /* Immediate constants are as cheap as registers. */
4887 *total = 0;
4888 return true;
4890 case MEM:
4891 case CONST:
4892 case LABEL_REF:
4893 case SYMBOL_REF:
4894 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
4895 return true;
4897 case NEG:
4898 switch (mode)
4900 case QImode:
4901 case SFmode:
4902 *total = COSTS_N_INSNS (1);
4903 break;
4905 case HImode:
4906 *total = COSTS_N_INSNS (3);
4907 break;
4909 case SImode:
4910 *total = COSTS_N_INSNS (7);
4911 break;
4913 default:
4914 return false;
4916 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
4917 return true;
4919 case ABS:
4920 switch (mode)
4922 case QImode:
4923 case SFmode:
4924 *total = COSTS_N_INSNS (1);
4925 break;
4927 default:
4928 return false;
4930 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
4931 return true;
4933 case NOT:
4934 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
4935 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
4936 return true;
4938 case ZERO_EXTEND:
4939 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
4940 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
4941 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
4942 return true;
4944 case SIGN_EXTEND:
4945 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
4946 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
4947 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
4948 return true;
4950 case PLUS:
4951 switch (mode)
4953 case QImode:
4954 *total = COSTS_N_INSNS (1);
4955 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
4956 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
4957 break;
4959 case HImode:
4960 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
4962 *total = COSTS_N_INSNS (2);
4963 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
4965 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
4966 *total = COSTS_N_INSNS (1);
4967 else
4968 *total = COSTS_N_INSNS (2);
4969 break;
4971 case SImode:
4972 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
4974 *total = COSTS_N_INSNS (4);
4975 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
4977 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
4978 *total = COSTS_N_INSNS (1);
4979 else
4980 *total = COSTS_N_INSNS (4);
4981 break;
4983 default:
4984 return false;
4986 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
4987 return true;
4989 case MINUS:
4990 case AND:
4991 case IOR:
4992 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
4993 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
4994 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
4995 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
4996 return true;
4998 case XOR:
4999 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
5000 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5001 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5002 return true;
5004 case MULT:
5005 switch (mode)
5007 case QImode:
5008 if (AVR_HAVE_MUL)
5009 *total = COSTS_N_INSNS (!speed ? 3 : 4);
5010 else if (!speed)
5011 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
5012 else
5013 return false;
5014 break;
5016 case HImode:
5017 if (AVR_HAVE_MUL)
5018 *total = COSTS_N_INSNS (!speed ? 7 : 10);
5019 else if (!speed)
5020 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
5021 else
5022 return false;
5023 break;
5025 default:
5026 return false;
5028 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5029 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5030 return true;
5032 case DIV:
5033 case MOD:
5034 case UDIV:
5035 case UMOD:
5036 if (!speed)
5037 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
5038 else
5039 return false;
5040 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5041 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5042 return true;
5044 case ROTATE:
5045 switch (mode)
5047 case QImode:
5048 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
5049 *total = COSTS_N_INSNS (1);
5051 break;
5053 case HImode:
5054 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
5055 *total = COSTS_N_INSNS (3);
5057 break;
5059 case SImode:
5060 if (CONST_INT_P (XEXP (x, 1)))
5061 switch (INTVAL (XEXP (x, 1)))
5063 case 8:
5064 case 24:
5065 *total = COSTS_N_INSNS (5);
5066 break;
5067 case 16:
5068 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 6);
5069 break;
5071 break;
5073 default:
5074 return false;
5076 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5077 return true;
5079 case ASHIFT:
5080 switch (mode)
5082 case QImode:
5083 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5085 *total = COSTS_N_INSNS (!speed ? 4 : 17);
5086 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5088 else
5090 val = INTVAL (XEXP (x, 1));
5091 if (val == 7)
5092 *total = COSTS_N_INSNS (3);
5093 else if (val >= 0 && val <= 7)
5094 *total = COSTS_N_INSNS (val);
5095 else
5096 *total = COSTS_N_INSNS (1);
5098 break;
5100 case HImode:
5101 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5103 *total = COSTS_N_INSNS (!speed ? 5 : 41);
5104 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5106 else
5107 switch (INTVAL (XEXP (x, 1)))
5109 case 0:
5110 *total = 0;
5111 break;
5112 case 1:
5113 case 8:
5114 *total = COSTS_N_INSNS (2);
5115 break;
5116 case 9:
5117 *total = COSTS_N_INSNS (3);
5118 break;
5119 case 2:
5120 case 3:
5121 case 10:
5122 case 15:
5123 *total = COSTS_N_INSNS (4);
5124 break;
5125 case 7:
5126 case 11:
5127 case 12:
5128 *total = COSTS_N_INSNS (5);
5129 break;
5130 case 4:
5131 *total = COSTS_N_INSNS (!speed ? 5 : 8);
5132 break;
5133 case 6:
5134 *total = COSTS_N_INSNS (!speed ? 5 : 9);
5135 break;
5136 case 5:
5137 *total = COSTS_N_INSNS (!speed ? 5 : 10);
5138 break;
5139 default:
5140 *total = COSTS_N_INSNS (!speed ? 5 : 41);
5141 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5143 break;
5145 case SImode:
5146 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5148 *total = COSTS_N_INSNS (!speed ? 7 : 113);
5149 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5151 else
5152 switch (INTVAL (XEXP (x, 1)))
5154 case 0:
5155 *total = 0;
5156 break;
5157 case 24:
5158 *total = COSTS_N_INSNS (3);
5159 break;
5160 case 1:
5161 case 8:
5162 case 16:
5163 *total = COSTS_N_INSNS (4);
5164 break;
5165 case 31:
5166 *total = COSTS_N_INSNS (6);
5167 break;
5168 case 2:
5169 *total = COSTS_N_INSNS (!speed ? 7 : 8);
5170 break;
5171 default:
5172 *total = COSTS_N_INSNS (!speed ? 7 : 113);
5173 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5175 break;
5177 default:
5178 return false;
5180 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5181 return true;
5183 case ASHIFTRT:
5184 switch (mode)
5186 case QImode:
5187 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5189 *total = COSTS_N_INSNS (!speed ? 4 : 17);
5190 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5192 else
5194 val = INTVAL (XEXP (x, 1));
5195 if (val == 6)
5196 *total = COSTS_N_INSNS (4);
5197 else if (val == 7)
5198 *total = COSTS_N_INSNS (2);
5199 else if (val >= 0 && val <= 7)
5200 *total = COSTS_N_INSNS (val);
5201 else
5202 *total = COSTS_N_INSNS (1);
5204 break;
5206 case HImode:
5207 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5209 *total = COSTS_N_INSNS (!speed ? 5 : 41);
5210 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5212 else
5213 switch (INTVAL (XEXP (x, 1)))
5215 case 0:
5216 *total = 0;
5217 break;
5218 case 1:
5219 *total = COSTS_N_INSNS (2);
5220 break;
5221 case 15:
5222 *total = COSTS_N_INSNS (3);
5223 break;
5224 case 2:
5225 case 7:
5226 case 8:
5227 case 9:
5228 *total = COSTS_N_INSNS (4);
5229 break;
5230 case 10:
5231 case 14:
5232 *total = COSTS_N_INSNS (5);
5233 break;
5234 case 11:
5235 *total = COSTS_N_INSNS (!speed ? 5 : 6);
5236 break;
5237 case 12:
5238 *total = COSTS_N_INSNS (!speed ? 5 : 7);
5239 break;
5240 case 6:
5241 case 13:
5242 *total = COSTS_N_INSNS (!speed ? 5 : 8);
5243 break;
5244 default:
5245 *total = COSTS_N_INSNS (!speed ? 5 : 41);
5246 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5248 break;
5250 case SImode:
5251 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5253 *total = COSTS_N_INSNS (!speed ? 7 : 113);
5254 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5256 else
5257 switch (INTVAL (XEXP (x, 1)))
5259 case 0:
5260 *total = 0;
5261 break;
5262 case 1:
5263 *total = COSTS_N_INSNS (4);
5264 break;
5265 case 8:
5266 case 16:
5267 case 24:
5268 *total = COSTS_N_INSNS (6);
5269 break;
5270 case 2:
5271 *total = COSTS_N_INSNS (!speed ? 7 : 8);
5272 break;
5273 case 31:
5274 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
5275 break;
5276 default:
5277 *total = COSTS_N_INSNS (!speed ? 7 : 113);
5278 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5280 break;
5282 default:
5283 return false;
5285 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5286 return true;
5288 case LSHIFTRT:
5289 switch (mode)
5291 case QImode:
5292 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5294 *total = COSTS_N_INSNS (!speed ? 4 : 17);
5295 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5297 else
5299 val = INTVAL (XEXP (x, 1));
5300 if (val == 7)
5301 *total = COSTS_N_INSNS (3);
5302 else if (val >= 0 && val <= 7)
5303 *total = COSTS_N_INSNS (val);
5304 else
5305 *total = COSTS_N_INSNS (1);
5307 break;
5309 case HImode:
5310 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5312 *total = COSTS_N_INSNS (!speed ? 5 : 41);
5313 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5315 else
5316 switch (INTVAL (XEXP (x, 1)))
5318 case 0:
5319 *total = 0;
5320 break;
5321 case 1:
5322 case 8:
5323 *total = COSTS_N_INSNS (2);
5324 break;
5325 case 9:
5326 *total = COSTS_N_INSNS (3);
5327 break;
5328 case 2:
5329 case 10:
5330 case 15:
5331 *total = COSTS_N_INSNS (4);
5332 break;
5333 case 7:
5334 case 11:
5335 *total = COSTS_N_INSNS (5);
5336 break;
5337 case 3:
5338 case 12:
5339 case 13:
5340 case 14:
5341 *total = COSTS_N_INSNS (!speed ? 5 : 6);
5342 break;
5343 case 4:
5344 *total = COSTS_N_INSNS (!speed ? 5 : 7);
5345 break;
5346 case 5:
5347 case 6:
5348 *total = COSTS_N_INSNS (!speed ? 5 : 9);
5349 break;
5350 default:
5351 *total = COSTS_N_INSNS (!speed ? 5 : 41);
5352 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5354 break;
5356 case SImode:
5357 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5359 *total = COSTS_N_INSNS (!speed ? 7 : 113);
5360 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5362 else
5363 switch (INTVAL (XEXP (x, 1)))
5365 case 0:
5366 *total = 0;
5367 break;
5368 case 1:
5369 *total = COSTS_N_INSNS (4);
5370 break;
5371 case 2:
5372 *total = COSTS_N_INSNS (!speed ? 7 : 8);
5373 break;
5374 case 8:
5375 case 16:
5376 case 24:
5377 *total = COSTS_N_INSNS (4);
5378 break;
5379 case 31:
5380 *total = COSTS_N_INSNS (6);
5381 break;
5382 default:
5383 *total = COSTS_N_INSNS (!speed ? 7 : 113);
5384 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5386 break;
5388 default:
5389 return false;
5391 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5392 return true;
5394 case COMPARE:
5395 switch (GET_MODE (XEXP (x, 0)))
5397 case QImode:
5398 *total = COSTS_N_INSNS (1);
5399 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5400 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5401 break;
5403 case HImode:
5404 *total = COSTS_N_INSNS (2);
5405 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5406 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5407 else if (INTVAL (XEXP (x, 1)) != 0)
5408 *total += COSTS_N_INSNS (1);
5409 break;
5411 case SImode:
5412 *total = COSTS_N_INSNS (4);
5413 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5414 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5415 else if (INTVAL (XEXP (x, 1)) != 0)
5416 *total += COSTS_N_INSNS (3);
5417 break;
5419 default:
5420 return false;
5422 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5423 return true;
5425 default:
5426 break;
5428 return false;
5431 /* Calculate the cost of a memory address. */
5433 static int
5434 avr_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED)
5436 if (GET_CODE (x) == PLUS
5437 && GET_CODE (XEXP (x,1)) == CONST_INT
5438 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
5439 && INTVAL (XEXP (x,1)) >= 61)
5440 return 18;
5441 if (CONSTANT_ADDRESS_P (x))
5443 if (optimize > 0 && io_address_operand (x, QImode))
5444 return 2;
5445 return 4;
5447 return 4;
5450 /* Test for extra memory constraint 'Q'.
5451 It's a memory address based on Y or Z pointer with valid displacement. */
5454 extra_constraint_Q (rtx x)
5456 if (GET_CODE (XEXP (x,0)) == PLUS
5457 && REG_P (XEXP (XEXP (x,0), 0))
5458 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
5459 && (INTVAL (XEXP (XEXP (x,0), 1))
5460 <= MAX_LD_OFFSET (GET_MODE (x))))
5462 rtx xx = XEXP (XEXP (x,0), 0);
5463 int regno = REGNO (xx);
5464 if (TARGET_ALL_DEBUG)
5466 fprintf (stderr, ("extra_constraint:\n"
5467 "reload_completed: %d\n"
5468 "reload_in_progress: %d\n"),
5469 reload_completed, reload_in_progress);
5470 debug_rtx (x);
5472 if (regno >= FIRST_PSEUDO_REGISTER)
5473 return 1; /* allocate pseudos */
5474 else if (regno == REG_Z || regno == REG_Y)
5475 return 1; /* strictly check */
5476 else if (xx == frame_pointer_rtx
5477 || xx == arg_pointer_rtx)
5478 return 1; /* XXX frame & arg pointer checks */
5480 return 0;
5483 /* Convert condition code CONDITION to the valid AVR condition code. */
5485 RTX_CODE
5486 avr_normalize_condition (RTX_CODE condition)
5488 switch (condition)
5490 case GT:
5491 return GE;
5492 case GTU:
5493 return GEU;
5494 case LE:
5495 return LT;
5496 case LEU:
5497 return LTU;
5498 default:
5499 gcc_unreachable ();
5503 /* This function optimizes conditional jumps. */
5505 static void
5506 avr_reorg (void)
5508 rtx insn, pattern;
5510 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5512 if (! (GET_CODE (insn) == INSN
5513 || GET_CODE (insn) == CALL_INSN
5514 || GET_CODE (insn) == JUMP_INSN)
5515 || !single_set (insn))
5516 continue;
5518 pattern = PATTERN (insn);
5520 if (GET_CODE (pattern) == PARALLEL)
5521 pattern = XVECEXP (pattern, 0, 0);
5522 if (GET_CODE (pattern) == SET
5523 && SET_DEST (pattern) == cc0_rtx
5524 && compare_diff_p (insn))
5526 if (GET_CODE (SET_SRC (pattern)) == COMPARE)
5528 /* Now we work under compare insn. */
5530 pattern = SET_SRC (pattern);
5531 if (true_regnum (XEXP (pattern,0)) >= 0
5532 && true_regnum (XEXP (pattern,1)) >= 0 )
5534 rtx x = XEXP (pattern,0);
5535 rtx next = next_real_insn (insn);
5536 rtx pat = PATTERN (next);
5537 rtx src = SET_SRC (pat);
5538 rtx t = XEXP (src,0);
5539 PUT_CODE (t, swap_condition (GET_CODE (t)));
5540 XEXP (pattern,0) = XEXP (pattern,1);
5541 XEXP (pattern,1) = x;
5542 INSN_CODE (next) = -1;
5544 else if (true_regnum (XEXP (pattern, 0)) >= 0
5545 && XEXP (pattern, 1) == const0_rtx)
5547 /* This is a tst insn, we can reverse it. */
5548 rtx next = next_real_insn (insn);
5549 rtx pat = PATTERN (next);
5550 rtx src = SET_SRC (pat);
5551 rtx t = XEXP (src,0);
5553 PUT_CODE (t, swap_condition (GET_CODE (t)));
5554 XEXP (pattern, 1) = XEXP (pattern, 0);
5555 XEXP (pattern, 0) = const0_rtx;
5556 INSN_CODE (next) = -1;
5557 INSN_CODE (insn) = -1;
5559 else if (true_regnum (XEXP (pattern,0)) >= 0
5560 && GET_CODE (XEXP (pattern,1)) == CONST_INT)
5562 rtx x = XEXP (pattern,1);
5563 rtx next = next_real_insn (insn);
5564 rtx pat = PATTERN (next);
5565 rtx src = SET_SRC (pat);
5566 rtx t = XEXP (src,0);
5567 enum machine_mode mode = GET_MODE (XEXP (pattern, 0));
5569 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
5571 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
5572 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
5573 INSN_CODE (next) = -1;
5574 INSN_CODE (insn) = -1;
5582 /* Returns register number for function return value.*/
5585 avr_ret_register (void)
5587 return 24;
5590 /* Create an RTX representing the place where a
5591 library function returns a value of mode MODE. */
5594 avr_libcall_value (enum machine_mode mode)
5596 int offs = GET_MODE_SIZE (mode);
5597 if (offs < 2)
5598 offs = 2;
5599 return gen_rtx_REG (mode, RET_REGISTER + 2 - offs);
5602 /* Create an RTX representing the place where a
5603 function returns a value of data type VALTYPE. */
5606 avr_function_value (const_tree type,
5607 const_tree func ATTRIBUTE_UNUSED,
5608 bool outgoing ATTRIBUTE_UNUSED)
5610 unsigned int offs;
5612 if (TYPE_MODE (type) != BLKmode)
5613 return avr_libcall_value (TYPE_MODE (type));
5615 offs = int_size_in_bytes (type);
5616 if (offs < 2)
5617 offs = 2;
5618 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
5619 offs = GET_MODE_SIZE (SImode);
5620 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
5621 offs = GET_MODE_SIZE (DImode);
5623 return gen_rtx_REG (BLKmode, RET_REGISTER + 2 - offs);
5626 /* Places additional restrictions on the register class to
5627 use when it is necessary to copy value X into a register
5628 in class CLASS. */
5630 enum reg_class
5631 preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class rclass)
5633 return rclass;
5637 test_hard_reg_class (enum reg_class rclass, rtx x)
5639 int regno = true_regnum (x);
5640 if (regno < 0)
5641 return 0;
5643 if (TEST_HARD_REG_CLASS (rclass, regno))
5644 return 1;
5646 return 0;
5651 jump_over_one_insn_p (rtx insn, rtx dest)
5653 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5654 ? XEXP (dest, 0)
5655 : dest);
5656 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
5657 int dest_addr = INSN_ADDRESSES (uid);
5658 return dest_addr - jump_addr == get_attr_length (insn) + 1;
5661 /* Returns 1 if a value of mode MODE can be stored starting with hard
5662 register number REGNO. On the enhanced core, anything larger than
5663 1 byte must start in even numbered register for "movw" to work
5664 (this way we don't have to check for odd registers everywhere). */
5667 avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
5669 /* Disallow QImode in stack pointer regs. */
5670 if ((regno == REG_SP || regno == (REG_SP + 1)) && mode == QImode)
5671 return 0;
5673 /* The only thing that can go into registers r28:r29 is a Pmode. */
5674 if (regno == REG_Y && mode == Pmode)
5675 return 1;
5677 /* Otherwise disallow all regno/mode combinations that span r28:r29. */
5678 if (regno <= (REG_Y + 1) && (regno + GET_MODE_SIZE (mode)) >= (REG_Y + 1))
5679 return 0;
5681 if (mode == QImode)
5682 return 1;
5684 /* Modes larger than QImode occupy consecutive registers. */
5685 if (regno + GET_MODE_SIZE (mode) > FIRST_PSEUDO_REGISTER)
5686 return 0;
5688 /* All modes larger than QImode should start in an even register. */
5689 return !(regno & 1);
5692 const char *
5693 output_reload_inhi (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
5695 int tmp;
5696 if (!len)
5697 len = &tmp;
5699 if (GET_CODE (operands[1]) == CONST_INT)
5701 int val = INTVAL (operands[1]);
5702 if ((val & 0xff) == 0)
5704 *len = 3;
5705 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
5706 AS2 (ldi,%2,hi8(%1)) CR_TAB
5707 AS2 (mov,%B0,%2));
5709 else if ((val & 0xff00) == 0)
5711 *len = 3;
5712 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5713 AS2 (mov,%A0,%2) CR_TAB
5714 AS2 (mov,%B0,__zero_reg__));
5716 else if ((val & 0xff) == ((val & 0xff00) >> 8))
5718 *len = 3;
5719 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5720 AS2 (mov,%A0,%2) CR_TAB
5721 AS2 (mov,%B0,%2));
5724 *len = 4;
5725 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5726 AS2 (mov,%A0,%2) CR_TAB
5727 AS2 (ldi,%2,hi8(%1)) CR_TAB
5728 AS2 (mov,%B0,%2));
5732 const char *
5733 output_reload_insisf (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
5735 rtx src = operands[1];
5736 int cnst = (GET_CODE (src) == CONST_INT);
5738 if (len)
5740 if (cnst)
5741 *len = 4 + ((INTVAL (src) & 0xff) != 0)
5742 + ((INTVAL (src) & 0xff00) != 0)
5743 + ((INTVAL (src) & 0xff0000) != 0)
5744 + ((INTVAL (src) & 0xff000000) != 0);
5745 else
5746 *len = 8;
5748 return "";
5751 if (cnst && ((INTVAL (src) & 0xff) == 0))
5752 output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
5753 else
5755 output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
5756 output_asm_insn (AS2 (mov, %A0, %2), operands);
5758 if (cnst && ((INTVAL (src) & 0xff00) == 0))
5759 output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
5760 else
5762 output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
5763 output_asm_insn (AS2 (mov, %B0, %2), operands);
5765 if (cnst && ((INTVAL (src) & 0xff0000) == 0))
5766 output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
5767 else
5769 output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
5770 output_asm_insn (AS2 (mov, %C0, %2), operands);
5772 if (cnst && ((INTVAL (src) & 0xff000000) == 0))
5773 output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
5774 else
5776 output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
5777 output_asm_insn (AS2 (mov, %D0, %2), operands);
5779 return "";
5782 void
5783 avr_output_bld (rtx operands[], int bit_nr)
5785 static char s[] = "bld %A0,0";
5787 s[5] = 'A' + (bit_nr >> 3);
5788 s[8] = '0' + (bit_nr & 7);
5789 output_asm_insn (s, operands);
5792 void
5793 avr_output_addr_vec_elt (FILE *stream, int value)
5795 switch_to_section (progmem_section);
5796 if (AVR_HAVE_JMP_CALL)
5797 fprintf (stream, "\t.word gs(.L%d)\n", value);
5798 else
5799 fprintf (stream, "\trjmp .L%d\n", value);
5802 /* Returns true if SCRATCH are safe to be allocated as a scratch
5803 registers (for a define_peephole2) in the current function. */
5805 bool
5806 avr_hard_regno_scratch_ok (unsigned int regno)
5808 /* Interrupt functions can only use registers that have already been saved
5809 by the prologue, even if they would normally be call-clobbered. */
5811 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
5812 && !df_regs_ever_live_p (regno))
5813 return false;
5815 return true;
5818 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
5821 avr_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
5822 unsigned int new_reg)
5824 /* Interrupt functions can only use registers that have already been
5825 saved by the prologue, even if they would normally be
5826 call-clobbered. */
5828 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
5829 && !df_regs_ever_live_p (new_reg))
5830 return 0;
5832 return 1;
5835 /* Output a branch that tests a single bit of a register (QI, HI or SImode)
5836 or memory location in the I/O space (QImode only).
5838 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5839 Operand 1: register operand to test, or CONST_INT memory address.
5840 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5841 Operand 3: label to jump to if the test is true. */
5843 const char *
5844 avr_out_sbxx_branch (rtx insn, rtx operands[])
5846 enum rtx_code comp = GET_CODE (operands[0]);
5847 int long_jump = (get_attr_length (insn) >= 4);
5848 int reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
5850 if (comp == GE)
5851 comp = EQ;
5852 else if (comp == LT)
5853 comp = NE;
5855 if (reverse)
5856 comp = reverse_condition (comp);
5858 if (GET_CODE (operands[1]) == CONST_INT)
5860 if (INTVAL (operands[1]) < 0x40)
5862 if (comp == EQ)
5863 output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
5864 else
5865 output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
5867 else
5869 output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
5870 if (comp == EQ)
5871 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
5872 else
5873 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
5876 else /* GET_CODE (operands[1]) == REG */
5878 if (GET_MODE (operands[1]) == QImode)
5880 if (comp == EQ)
5881 output_asm_insn (AS2 (sbrs,%1,%2), operands);
5882 else
5883 output_asm_insn (AS2 (sbrc,%1,%2), operands);
5885 else /* HImode or SImode */
5887 static char buf[] = "sbrc %A1,0";
5888 int bit_nr = exact_log2 (INTVAL (operands[2])
5889 & GET_MODE_MASK (GET_MODE (operands[1])));
5891 buf[3] = (comp == EQ) ? 's' : 'c';
5892 buf[6] = 'A' + (bit_nr >> 3);
5893 buf[9] = '0' + (bit_nr & 7);
5894 output_asm_insn (buf, operands);
5898 if (long_jump)
5899 return (AS1 (rjmp,.+4) CR_TAB
5900 AS1 (jmp,%3));
5901 if (!reverse)
5902 return AS1 (rjmp,%3);
5903 return "";
5906 /* Worker function for TARGET_ASM_CONSTRUCTOR. */
5908 static void
5909 avr_asm_out_ctor (rtx symbol, int priority)
5911 fputs ("\t.global __do_global_ctors\n", asm_out_file);
5912 default_ctor_section_asm_out_constructor (symbol, priority);
5915 /* Worker function for TARGET_ASM_DESTRUCTOR. */
5917 static void
5918 avr_asm_out_dtor (rtx symbol, int priority)
5920 fputs ("\t.global __do_global_dtors\n", asm_out_file);
5921 default_dtor_section_asm_out_destructor (symbol, priority);
5924 /* Worker function for TARGET_RETURN_IN_MEMORY. */
5926 static bool
5927 avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
5929 if (TYPE_MODE (type) == BLKmode)
5931 HOST_WIDE_INT size = int_size_in_bytes (type);
5932 return (size == -1 || size > 8);
5934 else
5935 return false;
5938 /* Worker function for CASE_VALUES_THRESHOLD. */
5940 unsigned int avr_case_values_threshold (void)
5942 return (!AVR_HAVE_JMP_CALL || TARGET_CALL_PROLOGUES) ? 8 : 17;
5945 #include "gt-avr.h"